From 9a9ea4b6788fe160fc3d3823d3a16f557983a4b2 Mon Sep 17 00:00:00 2001 From: Jocelyn Falempe Date: Mon, 24 Nov 2025 15:28:45 +0100 Subject: [PATCH 1/2] Remove pixman text renderer Pixman renderer is still experimental, and doesn't provide advantage over bbulk. It also requires a specific API of the video backend, so removing it will allow to simplify drm2d and fbdev backend. It also slowed down feature development like rotation or mouse support. Signed-off-by: Jocelyn Falempe --- README.md | 1 - docs/man/kmscon.1.xml.in | 2 +- meson.build | 2 - meson.options | 2 - scripts/etc/kmscon.conf | 2 +- src/kmscon_mod_pixman.c | 57 ---- src/meson.build | 12 - src/text.h | 1 - src/text_pixman.c | 639 --------------------------------------- 9 files changed, 2 insertions(+), 716 deletions(-) delete mode 100644 src/kmscon_mod_pixman.c delete mode 100644 src/text_pixman.c diff --git a/README.md b/README.md index aa72615e..4403091a 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,6 @@ explicitly enable it via command line: |`font_pango`| `auto` | Pango based scalable font renderer | |`renderer_bbulk`| `auto` | Simple 2D software-renderer (bulk-mode) | |`renderer_gltex`| `auto` | OpenGLESv2 accelerated renderer | -|`renderer_pixman`| `auto` | pixman based renderer | |`session_dummy`| `auto` | Dummy fallback session | |`session_terminal`| `auto` | Terminal-emulator sessions | diff --git a/docs/man/kmscon.1.xml.in b/docs/man/kmscon.1.xml.in index 950ab73c..42da262a 100644 --- a/docs/man/kmscon.1.xml.in +++ b/docs/man/kmscon.1.xml.in @@ -511,7 +511,7 @@ Specify console the rendering engine. Available engines are - `bblit', `bbulk', `gltex', and `pixman'. + `bblit', `bbulk', and `gltex'. (default: detect by GPU type) diff --git a/meson.build b/meson.build index 2b5266ee..4fbe7c74 100644 --- a/meson.build +++ b/meson.build @@ -76,7 +76,6 @@ gbm_deps = dependency('gbm', disabler: true, required: get_option('video_drm3d') egl_deps = dependency('egl', disabler: true, required: get_option('video_drm3d')) glesv2_deps = dependency('glesv2', disabler: true, required: require_glesv2) pango_deps = dependency('pangoft2', disabler: true, required: get_option('font_pango')) -pixman_deps = dependency('pixman-1', disabler: true, required: get_option('renderer_pixman')) xsltproc = find_program('xsltproc', native: true, disabler: true, required: get_option('docs')) check_deps = dependency('check', disabler: true, required: get_option('tests')) @@ -101,7 +100,6 @@ foreach name, reqs : { 'video_drm3d': [libdrm_deps, gbm_deps, egl_deps, glesv2_deps], 'renderer_bbulk': [], 'renderer_gltex': [glesv2_deps], - 'renderer_pixman': [pixman_deps], 'font_unifont': [], 'font_pango': [pango_deps], 'session_dummy': [], diff --git a/meson.options b/meson.options index ec9a4bcc..c043dd7f 100644 --- a/meson.options +++ b/meson.options @@ -24,8 +24,6 @@ option('renderer_bbulk', type: 'feature', value: 'auto', description: 'bbulk renderer') option('renderer_gltex', type: 'feature', value: 'auto', description: 'gltex renderer') -option('renderer_pixman', type: 'feature', value: 'auto', - description: 'pixman renderer') # font backends option('font_unifont', type: 'feature', value: 'auto', diff --git a/scripts/etc/kmscon.conf b/scripts/etc/kmscon.conf index 2da34239..0272bb99 100644 --- a/scripts/etc/kmscon.conf +++ b/scripts/etc/kmscon.conf @@ -26,7 +26,7 @@ ## Enable 3d rendering (only useful with gltex) #hwaccel -## Text renderer, can be [gltex, pixman, bblit, bbluk] +## Text renderer, can be [gltex, bblit, bbluk] ## gltex only works with hwaccel enabled, and others work with hwaccel disabled #render-engine=gltex diff --git a/src/kmscon_mod_pixman.c b/src/kmscon_mod_pixman.c deleted file mode 100644 index 9bf4c74b..00000000 --- a/src/kmscon_mod_pixman.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * kmscon - Pixman based rendering backend module - * - * Copyright (c) 2012-2013 David Herrmann - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -/* - * Pixman based rendering backend - */ - -#include -#include -#include "text.h" -#include "shl_module_interface.h" -#include "shl_log.h" - -#define LOG_SUBSYSTEM "mod_pixman" - -static int kmscon_pixman_load(void) -{ - int ret; - - kmscon_text_pixman_ops.owner = SHL_THIS_MODULE; - ret = kmscon_text_register(&kmscon_text_pixman_ops); - if (ret) { - log_error("cannot register pixman renderer"); - return ret; - } - - return 0; -} - -static void kmscon_pixman_unload(void) -{ - kmscon_text_unregister(kmscon_text_pixman_ops.name); -} - -SHL_MODULE(NULL, kmscon_pixman_load, kmscon_pixman_unload, NULL); diff --git a/src/meson.build b/src/meson.build index 3f6db43f..eb96a5bf 100644 --- a/src/meson.build +++ b/src/meson.build @@ -226,18 +226,6 @@ if enable_renderer_gltex ) endif -if enable_renderer_pixman - mod_pixman = shared_module('mod-pixman', [ - 'text_pixman.c', - 'kmscon_mod_pixman.c', - ], - name_prefix: '', - dependencies: [libtsm_deps, pixman_deps, shl_deps], - install: true, - install_dir: moduledir, - ) -endif - # # Binaries # These are the sources for the main binaries and test programs. They mostly diff --git a/src/text.h b/src/text.h index 4fde896b..cc08c1f2 100644 --- a/src/text.h +++ b/src/text.h @@ -135,6 +135,5 @@ int kmscon_text_draw_cb(struct tsm_screen *con, extern struct kmscon_text_ops kmscon_text_bblit_ops; extern struct kmscon_text_ops kmscon_text_bbulk_ops; extern struct kmscon_text_ops kmscon_text_gltex_ops; -extern struct kmscon_text_ops kmscon_text_pixman_ops; #endif /* KMSCON_TEXT_H */ diff --git a/src/text_pixman.c b/src/text_pixman.c deleted file mode 100644 index 5c29e11a..00000000 --- a/src/text_pixman.c +++ /dev/null @@ -1,639 +0,0 @@ -/* - * kmscon - Pixman Text Renderer Backend - * - * Copyright (c) 2012-2013 David Herrmann - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -/* - * Pixman based text renderer - */ - -#include -#include -#include -#include -#include -#include "font.h" -#include "font_rotate.h" -#include "shl_hashtable.h" -#include "shl_log.h" -#include "shl_misc.h" -#include "text.h" -#include "uterm_video.h" - -#define LOG_SUBSYSTEM "text_pixman" - -struct tp_glyph { - struct uterm_video_buffer vb; - pixman_image_t *surf; -}; - -struct tp_pixman { - pixman_image_t *white; - struct shl_hashtable *glyphs; - struct shl_hashtable *bold_glyphs; - - struct uterm_video_buffer buf[2]; - pixman_image_t *surf[2]; - unsigned int format[2]; - - bool use_indirect; - uint8_t *data[2]; - struct uterm_video_buffer vbuf; - - /* cache */ - unsigned int cur; - unsigned int c_bpp; - uint32_t *c_data; - unsigned int c_stride; -}; - -static int tp_init(struct kmscon_text *txt) -{ - struct tp_pixman *tp; - - tp = malloc(sizeof(*tp)); - if (!tp) - return -ENOMEM; - - txt->data = tp; - return 0; -} - -static void tp_destroy(struct kmscon_text *txt) -{ - struct tp_pixman *tp = txt->data; - - free(tp); -} - -static void free_glyph(void *data) -{ - struct tp_glyph *glyph = data; - - pixman_image_unref(glyph->surf); - free(glyph->vb.data); - free(glyph); -} - -static unsigned int format_u2p(unsigned int f) -{ - switch (f) { - case UTERM_FORMAT_XRGB32: - return PIXMAN_x8r8g8b8; - case UTERM_FORMAT_RGB16: - return PIXMAN_r5g6b5; - case UTERM_FORMAT_GREY: - return PIXMAN_a8; - default: - return 0; - } -} - -static int alloc_indirect(struct kmscon_text *txt, - unsigned int w, unsigned int h) -{ - struct tp_pixman *tp = txt->data; - unsigned int s, i, format; - - log_info("using blitting engine"); - - format = format_u2p(UTERM_FORMAT_XRGB32); - s = w * 4; - - tp->data[0] = malloc(s * h); - tp->data[1] = malloc(s * h); - if (!tp->data[0] || !tp->data[1]) { - log_error("cannot allocate memory for render-buffer"); - goto err_free; - } - - for (i = 0; i < 2; ++i) { - tp->format[i] = format; - tp->surf[i] = pixman_image_create_bits(format, w, h, - (void*)tp->data[i], s); - if (!tp->surf[i]) { - log_error("cannot create pixman surfaces"); - goto err_pixman; - } - } - - tp->vbuf.width = w; - tp->vbuf.height = h; - tp->vbuf.stride = s; - tp->vbuf.format = UTERM_FORMAT_XRGB32; - tp->use_indirect = true; - return 0; - -err_pixman: - if (tp->surf[1]) - pixman_image_unref(tp->surf[1]); - tp->surf[1] = NULL; - if (tp->surf[0]) - pixman_image_unref(tp->surf[0]); - tp->surf[0] = NULL; -err_free: - free(tp->data[1]); - free(tp->data[0]); - tp->data[1] = NULL; - tp->data[0] = NULL; - return -ENOMEM; -} - -static int tp_set(struct kmscon_text *txt) -{ - struct tp_pixman *tp = txt->data; - int ret; - unsigned int w, h; - struct uterm_mode *m; - pixman_color_t white; - - memset(tp, 0, sizeof(*tp)); - m = uterm_display_get_current(txt->disp); - w = uterm_mode_get_width(m); - h = uterm_mode_get_height(m); - - white.red = 0xffff; - white.green = 0xffff; - white.blue = 0xffff; - white.red = 0xffff; - - tp->white = pixman_image_create_solid_fill(&white); - if (!tp->white) { - log_error("cannot create pixman solid color buffer"); - return -ENOMEM; - } - ret = kmscon_rotate_create_tables(&tp->glyphs, &tp->bold_glyphs, free_glyph); - if (ret) - goto err_white; - - /* - * TODO: It is actually faster to use a local shadow buffer and then - * blit all data to the framebuffer afterwards. Reads seem to be - * horribly slow on some mmap'ed framebuffers. However, that's not true - * for all so we actually don't know which to use here. - */ - ret = uterm_display_get_buffers(txt->disp, tp->buf, - UTERM_FORMAT_XRGB32); - if (ret) { - log_warning("cannot get buffers for display %p", - txt->disp); - ret = alloc_indirect(txt, w, h); - if (ret) - goto err_glyph_table; - } else { - tp->format[0] = format_u2p(tp->buf[0].format); - tp->surf[0] = pixman_image_create_bits_no_clear(tp->format[0], - tp->buf[0].width, tp->buf[0].height, - (void*)tp->buf[0].data, - tp->buf[0].stride); - tp->format[1] = format_u2p(tp->buf[1].format); - tp->surf[1] = pixman_image_create_bits_no_clear(tp->format[1], - tp->buf[1].width, tp->buf[1].height, - (void*)tp->buf[1].data, - tp->buf[1].stride); - if (!tp->surf[0] || !tp->surf[1]) { - log_error("cannot create pixman surfaces"); - goto err_ctx; - } - } - if (txt->orientation == OR_NORMAL || txt->orientation == OR_UPSIDE_DOWN) { - txt->cols = w / txt->font->attr.width; - txt->rows = h / txt->font->attr.height; - } else { - txt->cols = h / txt->font->attr.width; - txt->rows = w / txt->font->attr.height; - } - - return 0; - -err_ctx: - if (tp->surf[1]) - pixman_image_unref(tp->surf[1]); - if (tp->surf[0]) - pixman_image_unref(tp->surf[0]); - free(tp->data[1]); - free(tp->data[0]); -err_glyph_table: - kmscon_rotate_free_tables(tp->glyphs, tp->bold_glyphs); -err_white: - pixman_image_unref(tp->white); - return ret; -} - -static void tp_unset(struct kmscon_text *txt) -{ - struct tp_pixman *tp = txt->data; - - pixman_image_unref(tp->surf[1]); - pixman_image_unref(tp->surf[0]); - free(tp->data[1]); - free(tp->data[0]); - kmscon_rotate_free_tables(tp->glyphs, tp->bold_glyphs); - pixman_image_unref(tp->white); -} - -static int find_glyph(struct kmscon_text *txt, struct tp_glyph **out, - uint64_t id, const uint32_t *ch, size_t len, const struct tsm_screen_attr *attr) -{ - struct tp_pixman *tp = txt->data; - const struct kmscon_glyph *glyph; - struct tp_glyph *tp_glyph; - struct shl_hashtable *gtable; - struct kmscon_font *font; - int ret; - bool res; - - if (attr->bold) { - gtable = tp->bold_glyphs; - font = txt->bold_font; - } else { - gtable = tp->glyphs; - font = txt->font; - } - - if (attr->underline) - font->attr.underline = true; - else - font->attr.underline = false; - - if (attr->italic) - font->attr.italic = true; - else - font->attr.italic = false; - - res = shl_hashtable_find(gtable, (void**)&tp_glyph, id); - if (res) { - *out = tp_glyph; - return 0; - } - - tp_glyph = malloc(sizeof(*tp_glyph)); - if (!tp_glyph) - return -ENOMEM; - memset(tp_glyph, 0, sizeof(*tp_glyph)); - - if (!len) - ret = kmscon_font_render_empty(font, &glyph); - else - ret = kmscon_font_render(font, id, ch, len, &glyph); - - if (ret) { - ret = kmscon_font_render_inval(font, &glyph); - if (ret) - goto err_free; - } - - ret = kmscon_rotate_glyph(&tp_glyph->vb, glyph, txt->orientation, 4); - if (ret) - goto err_free; - - - tp_glyph->surf = pixman_image_create_bits_no_clear(PIXMAN_a8, - tp_glyph->vb.width, - tp_glyph->vb.height, - (void*) tp_glyph->vb.data, - tp_glyph->vb.stride); - - if (!tp_glyph->surf) { - log_error("cannot create pixman-glyph: %d %p %d %d %d", - ret, tp_glyph->vb.data, tp_glyph->vb.width, tp_glyph->vb.height, tp_glyph->vb.stride); - ret = -EFAULT; - goto err_free_vb; - } - - ret = shl_hashtable_insert(gtable, id, tp_glyph); - if (ret) - goto err_pixman; - - *out = tp_glyph; - return 0; - -err_pixman: - pixman_image_unref(tp_glyph->surf); - -err_free_vb: - free(tp_glyph->vb.data); -err_free: - free(tp_glyph); - return ret; -} - -static int tp_rotate(struct kmscon_text *txt, enum Orientation orientation) -{ - struct tp_pixman *tp = txt->data; - unsigned int w, h; - struct uterm_mode *m; - - m = uterm_display_get_current(txt->disp); - w = uterm_mode_get_width(m); - h = uterm_mode_get_height(m); - - txt->orientation = orientation; - - if (txt->orientation == OR_NORMAL || txt->orientation == OR_UPSIDE_DOWN) { - txt->cols = w / txt->font->attr.width; - txt->rows = h / txt->font->attr.height; - } else { - txt->cols = h / txt->font->attr.width; - txt->rows = w / txt->font->attr.height; - } - - // Free glyph cache, as the glyph are rotated in the cache. - kmscon_rotate_free_tables(tp->glyphs, tp->bold_glyphs); - - return kmscon_rotate_create_tables(&tp->glyphs, &tp->bold_glyphs, free_glyph); -} - -static int tp_prepare(struct kmscon_text *txt) -{ - struct tp_pixman *tp = txt->data; - int ret; - pixman_image_t *img; - - ret = uterm_display_use(txt->disp, NULL); - if (ret < 0) { - log_error("cannot use display %p", txt->disp); - return ret; - } - - tp->cur = ret; - img = tp->surf[tp->cur]; - tp->c_bpp = PIXMAN_FORMAT_BPP(tp->format[tp->cur]); - tp->c_data = pixman_image_get_data(img); - tp->c_stride = pixman_image_get_stride(img); - - return 0; -} - -static int tp_draw(struct kmscon_text *txt, - uint64_t id, const uint32_t *ch, size_t len, - unsigned int width, - unsigned int posx, unsigned int posy, - const struct tsm_screen_attr *attr) -{ - struct tp_pixman *tp = txt->data; - struct uterm_mode *mode; - struct tp_glyph *glyph; - int ret; - unsigned int x, y, w, h, sw, sh, cwidth; - uint32_t bc; - pixman_color_t fc; - pixman_image_t *col; - - if (!width) - return 0; - - mode = uterm_display_get_current(txt->disp); - if (!mode) - return -EINVAL; - sw = uterm_mode_get_width(mode); - sh = uterm_mode_get_height(mode); - - ret = find_glyph(txt, &glyph, id, ch, len, attr); - if (ret) - return ret; - - if (attr->inverse) { - bc = (attr->fr << 16) | (attr->fg << 8) | (attr->fb); - fc.red = attr->br << 8; - fc.green = attr->bg << 8; - fc.blue = attr->bb << 8; - fc.alpha = 0xffff; - } else { - bc = (attr->br << 16) | (attr->bg << 8) | (attr->bb); - fc.red = attr->fr << 8; - fc.green = attr->fg << 8; - fc.blue = attr->fb << 8; - fc.alpha = 0xffff; - } - - /* TODO: We _really_ should fix pixman to allow something like - * pixman_image_set_solid_fill(img, &fc) to avoid allocating a pixman - * image for each glyph here. - * libc malloc() is pretty fast, but this still costs us a lot of - * rendering performance. */ - if (fc.red == 0xff00 && fc.green == 0xff00 && fc.blue == 0xff00) { - col = tp->white; - pixman_image_ref(col); - } else { - col = pixman_image_create_solid_fill(&fc); - if (!col) { - log_error("cannot create pixman color image"); - return -ENOMEM; - } - } - - w = glyph->vb.width; - h = glyph->vb.height; - - switch (txt->orientation) { - default: - case OR_NORMAL: - x = posx * FONT_WIDTH(txt); - y = posy * FONT_HEIGHT(txt); - break; - case OR_UPSIDE_DOWN: - cwidth = w / FONT_WIDTH(txt); - x = sw - (posx + cwidth) * FONT_WIDTH(txt); - y = sh - (posy + 1) * FONT_HEIGHT(txt); - break; - case OR_RIGHT: - x = sw - (posy + 1) * FONT_HEIGHT(txt); - y = posx * FONT_WIDTH(txt); - break; - case OR_LEFT: - cwidth = h / FONT_WIDTH(txt); - x = posy * FONT_HEIGHT(txt); - y = sh - (posx + cwidth) * FONT_WIDTH(txt); - break; - } - - if (!bc) { - pixman_image_composite(PIXMAN_OP_SRC, - col, - glyph->surf, - tp->surf[tp->cur], - 0, 0, 0, 0, - x, y, w, h); - } else { - pixman_fill(tp->c_data, tp->c_stride / 4, tp->c_bpp, - x, y, w, h, bc); - - pixman_image_composite(PIXMAN_OP_OVER, - col, - glyph->surf, - tp->surf[tp->cur], - 0, 0, 0, 0, - x, y, w, h); - } - - pixman_image_unref(col); - - return 0; -} - -static int tp_draw_pointer(struct kmscon_text *txt, - unsigned int pointer_x, unsigned int pointer_y, - const struct tsm_screen_attr *attr) -{ - struct tp_pixman *tp = txt->data; - struct uterm_mode *mode; - struct tp_glyph *glyph; - uint32_t ch = 'I'; - uint64_t id = ch; - int ret; - unsigned int x, y, w, h, sw, sh; - unsigned int m_x, m_y; - uint32_t bc; - pixman_color_t fc; - pixman_image_t *col; - - mode = uterm_display_get_current(txt->disp); - if (!mode) - return -EINVAL; - sw = uterm_mode_get_width(mode); - sh = uterm_mode_get_height(mode); - - ret = find_glyph(txt, &glyph, id, &ch, 1, attr); - if (ret) - return ret; - - bc = (attr->br << 16) | (attr->bg << 8) | (attr->bb); - fc.red = attr->fr << 8; - fc.green = attr->fg << 8; - fc.blue = attr->fb << 8; - fc.alpha = 0xffff; - - /* TODO: We _really_ should fix pixman to allow something like - * pixman_image_set_solid_fill(img, &fc) to avoid allocating a pixman - * image for each glyph here. - * libc malloc() is pretty fast, but this still costs us a lot of - * rendering performance. */ - if (attr->fr == 0xff && attr->fg == 0xff && attr->fb == 0xff) { - col = tp->white; - pixman_image_ref(col); - } else { - col = pixman_image_create_solid_fill(&fc); - if (!col) { - log_error("cannot create pixman color image"); - return -ENOMEM; - } - } - - if (txt->orientation == OR_NORMAL || txt->orientation == OR_UPSIDE_DOWN) { - w = FONT_WIDTH(txt); - h = FONT_HEIGHT(txt); - } else { - w = FONT_HEIGHT(txt); - h = FONT_WIDTH(txt); - } - - m_x = SHL_DIV_ROUND_UP(w, 2); - m_y = SHL_DIV_ROUND_UP(h, 2); - - switch (txt->orientation) { - default: - case OR_NORMAL: - x = pointer_x; - y = pointer_y; - break; - case OR_UPSIDE_DOWN: - x = sw - pointer_x; - y = sh - pointer_y; - break; - case OR_RIGHT: - x = sw - pointer_y; - y = pointer_x; - break; - case OR_LEFT: - x = pointer_y; - y = sh - pointer_x; - break; - } - if (x < m_x) - x = m_x; - if (x + m_x > sw) - x = sw - m_x; - if (y < m_y) - y = m_y; - if (y + m_y > sh) - y = sh - m_y; - x -= m_x; - y -= m_y; - - if (!bc) { - pixman_image_composite(PIXMAN_OP_SRC, - col, - glyph->surf, - tp->surf[tp->cur], - 0, 0, 0, 0, - x, y, w, h); - } else { - pixman_fill(tp->c_data, tp->c_stride / 4, tp->c_bpp, - x, y, w, h, bc); - - pixman_image_composite(PIXMAN_OP_OVER, - col, - glyph->surf, - tp->surf[tp->cur], - 0, 0, 0, 0, - x, y, w, h); - } - - pixman_image_unref(col); - - return 0; -} - -static int tp_render(struct kmscon_text *txt) -{ - struct tp_pixman *tp = txt->data; - int ret; - - if (!tp->use_indirect) - return 0; - - tp->vbuf.data = tp->data[tp->cur]; - ret = uterm_display_blit(txt->disp, &tp->vbuf, 0, 0); - if (ret) { - log_error("cannot blit back-buffer to display: %d", ret); - return ret; - } - - return 0; -} - -struct kmscon_text_ops kmscon_text_pixman_ops = { - .name = "pixman", - .owner = NULL, - .init = tp_init, - .destroy = tp_destroy, - .set = tp_set, - .unset = tp_unset, - .rotate = tp_rotate, - .prepare = tp_prepare, - .draw = tp_draw, - .draw_pointer = tp_draw_pointer, - .render = tp_render, - .abort = NULL, -}; From 3f5ff7aa45853a7860ed69c1bef4826588b3d295 Mon Sep 17 00:00:00 2001 From: Jocelyn Falempe Date: Mon, 24 Nov 2025 15:43:45 +0100 Subject: [PATCH 2/2] Remove the blit callback, as it was only used by pixman Now that pixman has been removed, the blit callback has no user, so it can be removed to. This simplifies the video backends, and will allow better optimizations later. Signed-off-by: Jocelyn Falempe --- src/meson.build | 2 - src/uterm_drm2d_internal.h | 3 - src/uterm_drm2d_render.c | 47 ------------ src/uterm_drm2d_video.c | 1 - src/uterm_drm3d_blit.frag | 40 ---------- src/uterm_drm3d_blit.vert | 42 ----------- src/uterm_drm3d_internal.h | 7 -- src/uterm_drm3d_render.c | 149 +------------------------------------ src/uterm_drm3d_video.c | 1 - src/uterm_fbdev_internal.h | 3 - src/uterm_fbdev_render.c | 77 ------------------- src/uterm_fbdev_video.c | 1 - src/uterm_video.c | 11 --- src/uterm_video.h | 3 - src/uterm_video_internal.h | 3 - 15 files changed, 1 insertion(+), 389 deletions(-) delete mode 100644 src/uterm_drm3d_blit.frag delete mode 100644 src/uterm_drm3d_blit.vert diff --git a/src/meson.build b/src/meson.build index eb96a5bf..12cefbd6 100644 --- a/src/meson.build +++ b/src/meson.build @@ -148,8 +148,6 @@ if enable_video_drm3d 'uterm_mod_drm3d.c', embed_gen.process('uterm_drm3d_blend.vert', extra_args: shader_regex), embed_gen.process('uterm_drm3d_blend.frag', extra_args: shader_regex), - embed_gen.process('uterm_drm3d_blit.vert', extra_args: shader_regex), - embed_gen.process('uterm_drm3d_blit.frag', extra_args: shader_regex), embed_gen.process('uterm_drm3d_fill.vert', extra_args: shader_regex), embed_gen.process('uterm_drm3d_fill.frag', extra_args: shader_regex), ], diff --git a/src/uterm_drm2d_internal.h b/src/uterm_drm2d_internal.h index e2bcabea..e3c8aa91 100644 --- a/src/uterm_drm2d_internal.h +++ b/src/uterm_drm2d_internal.h @@ -52,9 +52,6 @@ struct uterm_drm2d_video { struct ev_fd *efd; }; -int uterm_drm2d_display_blit(struct uterm_display *disp, - const struct uterm_video_buffer *buf, - unsigned int x, unsigned int y); int uterm_drm2d_display_fake_blendv(struct uterm_display *disp, const struct uterm_video_blend_req *req, size_t num); diff --git a/src/uterm_drm2d_render.c b/src/uterm_drm2d_render.c index cfe4d755..fbb9019a 100644 --- a/src/uterm_drm2d_render.c +++ b/src/uterm_drm2d_render.c @@ -46,53 +46,6 @@ #define LOG_SUBSYSTEM "uterm_drm2d_render" -int uterm_drm2d_display_blit(struct uterm_display *disp, - const struct uterm_video_buffer *buf, - unsigned int x, unsigned int y) -{ - unsigned int tmp; - uint8_t *dst, *src; - unsigned int width, height; - unsigned int sw, sh; - struct uterm_drm2d_rb *rb; - struct uterm_drm2d_display *d2d = uterm_drm_display_get_data(disp); - - if (!buf || buf->format != UTERM_FORMAT_XRGB32) - return -EINVAL; - - rb = &d2d->rb[d2d->current_rb ^ 1]; - sw = uterm_drm_mode_get_width(disp->current_mode); - sh = uterm_drm_mode_get_height(disp->current_mode); - - tmp = x + buf->width; - if (tmp < x || x >= sw) - return -EINVAL; - if (tmp > sw) - width = sw - x; - else - width = buf->width; - - tmp = y + buf->height; - if (tmp < y || y >= sh) - return -EINVAL; - if (tmp > sh) - height = sh - y; - else - height = buf->height; - - dst = rb->map; - dst = &dst[y * rb->stride + x * 4]; - src = buf->data; - - while (height--) { - memcpy(dst, src, 4 * width); - dst += rb->stride; - src += buf->stride; - } - - return 0; -} - int uterm_drm2d_display_fake_blendv(struct uterm_display *disp, const struct uterm_video_blend_req *req, size_t num) diff --git a/src/uterm_drm2d_video.c b/src/uterm_drm2d_video.c index f2a84b6b..0284b008 100644 --- a/src/uterm_drm2d_video.c +++ b/src/uterm_drm2d_video.c @@ -285,7 +285,6 @@ static const struct display_ops drm2d_display_ops = { .use = display_use, .get_buffers = display_get_buffers, .swap = display_swap, - .blit = uterm_drm2d_display_blit, .fake_blendv = uterm_drm2d_display_fake_blendv, .fill = uterm_drm2d_display_fill, }; diff --git a/src/uterm_drm3d_blit.frag b/src/uterm_drm3d_blit.frag deleted file mode 100644 index 8b36d9e4..00000000 --- a/src/uterm_drm3d_blit.frag +++ /dev/null @@ -1,40 +0,0 @@ -/* - * kmscon - Fragment Shader - * - * Copyright (c) 2011-2012 David Herrmann - * Copyright (c) 2011 University of Tuebingen - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -/* - * Fragment Shader - * A basic fragment shader which applies a 2D texture. - */ - -precision mediump float; - -uniform sampler2D texture; -varying vec2 texpos; - -void main() -{ - gl_FragColor = texture2D(texture, texpos); -} diff --git a/src/uterm_drm3d_blit.vert b/src/uterm_drm3d_blit.vert deleted file mode 100644 index 82b598df..00000000 --- a/src/uterm_drm3d_blit.vert +++ /dev/null @@ -1,42 +0,0 @@ -/* - * kmscon - Vertex Shader - * - * Copyright (c) 2011-2012 David Herrmann - * Copyright (c) 2011 University of Tuebingen - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -/* - * Vertex Shader - * This shader is a very basic vertex shader which forwards all data and - * performs basic matrix multiplications. - */ - -uniform mat4 projection; -attribute vec2 position; -attribute vec2 texture_position; -varying vec2 texpos; - -void main() -{ - gl_Position = projection * vec4(position, 0.0, 1.0); - texpos = texture_position; -} diff --git a/src/uterm_drm3d_internal.h b/src/uterm_drm3d_internal.h index 9a0e4ca9..6ddd80e5 100644 --- a/src/uterm_drm3d_internal.h +++ b/src/uterm_drm3d_internal.h @@ -83,17 +83,10 @@ struct uterm_drm3d_video { GLuint uni_blend_tex; GLuint uni_blend_fgcol; GLuint uni_blend_bgcol; - - struct gl_shader *blit_shader; - GLuint uni_blit_proj; - GLuint uni_blit_tex; }; int uterm_drm3d_display_use(struct uterm_display *disp, bool *opengl); void uterm_drm3d_deinit_shaders(struct uterm_video *video); -int uterm_drm3d_display_blit(struct uterm_display *disp, - const struct uterm_video_buffer *buf, - unsigned int x, unsigned int y); int uterm_drm3d_display_fake_blendv(struct uterm_display *disp, const struct uterm_video_blend_req *req, size_t num); diff --git a/src/uterm_drm3d_render.c b/src/uterm_drm3d_render.c index f113d700..bfaf1d08 100644 --- a/src/uterm_drm3d_render.c +++ b/src/uterm_drm3d_render.c @@ -53,8 +53,6 @@ #include "uterm_video_internal.h" #include "uterm_drm3d_blend.vert.bin.h" #include "uterm_drm3d_blend.frag.bin.h" -#include "uterm_drm3d_blit.vert.bin.h" -#include "uterm_drm3d_blit.frag.bin.h" #include "uterm_drm3d_fill.vert.bin.h" #include "uterm_drm3d_fill.frag.bin.h" @@ -66,10 +64,8 @@ static int init_shaders(struct uterm_video *video) int ret; char *fill_attr[] = { "position", "color" }; char *blend_attr[] = { "position", "texture_position" }; - char *blit_attr[] = { "position", "texture_position" }; - int blend_vlen, blend_flen, blit_vlen, blit_flen, fill_vlen, fill_flen; + int blend_vlen, blend_flen, fill_vlen, fill_flen; const char *blend_vert, *blend_frag; - const char *blit_vert, *blit_frag; const char *fill_vert, *fill_frag; if (v3d->sinit == 1) @@ -83,10 +79,6 @@ static int init_shaders(struct uterm_video *video) blend_vlen = _binary_uterm_drm3d_blend_vert_size; blend_frag = _binary_uterm_drm3d_blend_frag_start; blend_flen = _binary_uterm_drm3d_blend_frag_size; - blit_vert = _binary_uterm_drm3d_blit_vert_start; - blit_vlen = _binary_uterm_drm3d_blit_vert_size; - blit_frag = _binary_uterm_drm3d_blit_frag_start; - blit_flen = _binary_uterm_drm3d_blit_frag_size; fill_vert = _binary_uterm_drm3d_fill_vert_start; fill_vlen = _binary_uterm_drm3d_fill_vert_size; fill_frag = _binary_uterm_drm3d_fill_frag_start; @@ -116,17 +108,6 @@ static int init_shaders(struct uterm_video *video) v3d->uni_blend_bgcol = gl_shader_get_uniform(v3d->blend_shader, "bgcolor"); - ret = gl_shader_new(&v3d->blit_shader, blit_vert, blit_vlen, - blit_frag, blit_flen, blit_attr, 2, log_llog, - NULL); - if (ret) - return ret; - - v3d->uni_blit_proj = gl_shader_get_uniform(v3d->blit_shader, - "projection"); - v3d->uni_blit_tex = gl_shader_get_uniform(v3d->blit_shader, - "texture"); - gl_tex_new(&v3d->tex, 1); v3d->sinit = 2; @@ -142,138 +123,10 @@ void uterm_drm3d_deinit_shaders(struct uterm_video *video) v3d->sinit = 0; gl_tex_free(&v3d->tex, 1); - gl_shader_unref(v3d->blit_shader); gl_shader_unref(v3d->blend_shader); gl_shader_unref(v3d->fill_shader); } -int uterm_drm3d_display_blit(struct uterm_display *disp, - const struct uterm_video_buffer *buf, - unsigned int x, unsigned int y) -{ - struct uterm_drm3d_video *v3d; - unsigned int sw, sh, tmp, width, height, i; - float mat[16]; - float vertices[6 * 2], texpos[6 * 2]; - int ret; - uint8_t *packed, *src, *dst; - - if (!buf || buf->format != UTERM_FORMAT_XRGB32) - return -EINVAL; - - v3d = uterm_drm_video_get_data(disp->video); - ret = uterm_drm3d_display_use(disp, NULL); - if (ret) - return ret; - ret = init_shaders(disp->video); - if (ret) - return ret; - - sw = uterm_drm_mode_get_width(disp->current_mode); - sh = uterm_drm_mode_get_height(disp->current_mode); - - vertices[0] = -1.0; - vertices[1] = -1.0; - vertices[2] = -1.0; - vertices[3] = +1.0; - vertices[4] = +1.0; - vertices[5] = +1.0; - - vertices[6] = -1.0; - vertices[7] = -1.0; - vertices[8] = +1.0; - vertices[9] = +1.0; - vertices[10] = +1.0; - vertices[11] = -1.0; - - texpos[0] = 0.0; - texpos[1] = 1.0; - texpos[2] = 0.0; - texpos[3] = 0.0; - texpos[4] = 1.0; - texpos[5] = 0.0; - - texpos[6] = 0.0; - texpos[7] = 1.0; - texpos[8] = 1.0; - texpos[9] = 0.0; - texpos[10] = 1.0; - texpos[11] = 1.0; - - tmp = x + buf->width; - if (tmp < x || x >= sw) - return -EINVAL; - if (tmp > sw) - width = sw - x; - else - width = buf->width; - - tmp = y + buf->height; - if (tmp < y || y >= sh) - return -EINVAL; - if (tmp > sh) - height = sh - y; - else - height = buf->height; - - glViewport(x, sh - y - height, width, height); - glDisable(GL_BLEND); - - gl_shader_use(v3d->blit_shader); - - gl_m4_identity(mat); - glUniformMatrix4fv(v3d->uni_blit_proj, 1, GL_FALSE, mat); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, v3d->tex); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - - if (v3d->supports_rowlen) { - glPixelStorei(GL_UNPACK_ROW_LENGTH, buf->stride / 4); - glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, width, height, 0, - GL_BGRA_EXT, GL_UNSIGNED_BYTE, buf->data); - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); - } else if (buf->stride == width) { - glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, width, height, 0, - GL_BGRA_EXT, GL_UNSIGNED_BYTE, buf->data); - } else { - packed = malloc(width * height); - if (!packed) - return -ENOMEM; - - src = buf->data; - dst = packed; - for (i = 0; i < height; ++i) { - memcpy(dst, src, width * 4); - dst += width * 4; - src += buf->stride; - } - - glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, width, height, 0, - GL_BGRA_EXT, GL_UNSIGNED_BYTE, packed); - - free(packed); - } - - glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - glUniform1i(v3d->uni_blit_tex, 0); - - glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, vertices); - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, texpos); - glEnableVertexAttribArray(0); - glEnableVertexAttribArray(1); - glDrawArrays(GL_TRIANGLES, 0, 6); - glDisableVertexAttribArray(0); - glDisableVertexAttribArray(1); - - if (gl_has_error(v3d->blit_shader)) { - log_warning("GL error"); - return -EFAULT; - } - - return 0; -} - static int display_blend(struct uterm_display *disp, const struct uterm_video_buffer *buf, unsigned int x, unsigned int y, diff --git a/src/uterm_drm3d_video.c b/src/uterm_drm3d_video.c index dd4f1446..ec397b51 100644 --- a/src/uterm_drm3d_video.c +++ b/src/uterm_drm3d_video.c @@ -353,7 +353,6 @@ static const struct display_ops drm_display_ops = { .use = uterm_drm3d_display_use, .get_buffers = NULL, .swap = display_swap, - .blit = uterm_drm3d_display_blit, .fake_blendv = uterm_drm3d_display_fake_blendv, .fill = uterm_drm3d_display_fill, }; diff --git a/src/uterm_fbdev_internal.h b/src/uterm_fbdev_internal.h index e263e4a8..6b79e546 100644 --- a/src/uterm_fbdev_internal.h +++ b/src/uterm_fbdev_internal.h @@ -74,9 +74,6 @@ struct fbdev_video { bool pending_intro; }; -int uterm_fbdev_display_blit(struct uterm_display *disp, - const struct uterm_video_buffer *buf, - unsigned int x, unsigned int y); int uterm_fbdev_display_fake_blendv(struct uterm_display *disp, const struct uterm_video_blend_req *req, size_t num); diff --git a/src/uterm_fbdev_render.c b/src/uterm_fbdev_render.c index 2dda19a2..8bb02136 100644 --- a/src/uterm_fbdev_render.c +++ b/src/uterm_fbdev_render.c @@ -115,83 +115,6 @@ static void write_24bit(uint8_t *dst, uint_fast32_t value) #endif } -int uterm_fbdev_display_blit(struct uterm_display *disp, - const struct uterm_video_buffer *buf, - unsigned int x, unsigned int y) -{ - unsigned int tmp; - uint8_t *dst, *src; - unsigned int width, height, i; - uint32_t val; - struct fbdev_display *fbdev = disp->data; - - if (!buf || buf->format != UTERM_FORMAT_XRGB32) - return -EINVAL; - - tmp = x + buf->width; - if (tmp < x || x >= fbdev->xres) - return -EINVAL; - if (tmp > fbdev->xres) - width = fbdev->xres - x; - else - width = buf->width; - - tmp = y + buf->height; - if (tmp < y || y >= fbdev->yres) - return -EINVAL; - if (tmp > fbdev->yres) - height = fbdev->yres - y; - else - height = buf->height; - - if (!(disp->flags & DISPLAY_DBUF) || fbdev->bufid) - dst = fbdev->map; - else - dst = &fbdev->map[fbdev->yres * fbdev->stride]; - dst = &dst[y * fbdev->stride + x * fbdev->Bpp]; - src = buf->data; - - if (fbdev->xrgb32) { - while (height--) { - memcpy(dst, src, 4 * width); - dst += fbdev->stride; - src += buf->stride; - } - } else if (fbdev->Bpp == 2) { - while (height--) { - for (i = 0; i < width; ++i) { - val = ((uint32_t*)src)[i]; - ((uint16_t*)dst)[i] = xrgb32_to_device(disp, val); - } - dst += fbdev->stride; - src += buf->stride; - } - } else if (fbdev->Bpp == 3) { - while (height--) { - for (i = 0; i < width; ++i) { - val = ((uint32_t*)src)[i]; - uint_fast32_t full = xrgb32_to_device(disp, val); - write_24bit(&dst[i * 3], full); - } - dst += fbdev->stride; - src += buf->stride; - } - } else if (fbdev->Bpp == 4) { - while (height--) { - for (i = 0; i < width; ++i) { - val = ((uint32_t*)src)[i]; - ((uint32_t*)dst)[i] = xrgb32_to_device(disp, val); - } - dst += fbdev->stride; - src += buf->stride; - } - } else { - log_debug("invalid Bpp"); - } - - return 0; -} - int uterm_fbdev_display_fake_blendv(struct uterm_display *disp, const struct uterm_video_blend_req *req, size_t num) diff --git a/src/uterm_fbdev_video.c b/src/uterm_fbdev_video.c index 73bb5907..de2c6b63 100644 --- a/src/uterm_fbdev_video.c +++ b/src/uterm_fbdev_video.c @@ -526,7 +526,6 @@ static const struct display_ops fbdev_display_ops = { .use = display_use, .get_buffers = display_get_buffers, .swap = display_swap, - .blit = uterm_fbdev_display_blit, .fake_blendv = uterm_fbdev_display_fake_blendv, .fill = uterm_fbdev_display_fill, }; diff --git a/src/uterm_video.c b/src/uterm_video.c index e68e9b05..258eaf7a 100644 --- a/src/uterm_video.c +++ b/src/uterm_video.c @@ -509,17 +509,6 @@ int uterm_display_fill(struct uterm_display *disp, width, height); } -SHL_EXPORT -int uterm_display_blit(struct uterm_display *disp, - const struct uterm_video_buffer *buf, - unsigned int x, unsigned int y) -{ - if (!disp || !display_is_online(disp) || !video_is_awake(disp->video)) - return -EINVAL; - - return VIDEO_CALL(disp->ops->blit, -EOPNOTSUPP, disp, buf, x, y); -} - SHL_EXPORT int uterm_display_fake_blend(struct uterm_display *disp, const struct uterm_video_buffer *buf, diff --git a/src/uterm_video.h b/src/uterm_video.h index fea62c38..d58bb648 100644 --- a/src/uterm_video.h +++ b/src/uterm_video.h @@ -178,9 +178,6 @@ int uterm_display_fill(struct uterm_display *disp, uint8_t r, uint8_t g, uint8_t b, unsigned int x, unsigned int y, unsigned int width, unsigned int height); -int uterm_display_blit(struct uterm_display *disp, - const struct uterm_video_buffer *buf, - unsigned int x, unsigned int y); int uterm_display_fake_blend(struct uterm_display *disp, const struct uterm_video_buffer *buf, unsigned int x, unsigned int y, diff --git a/src/uterm_video_internal.h b/src/uterm_video_internal.h index 949eaf26..020b7bbd 100644 --- a/src/uterm_video_internal.h +++ b/src/uterm_video_internal.h @@ -58,9 +58,6 @@ struct display_ops { struct uterm_video_buffer *buffer, unsigned int formats); int (*swap) (struct uterm_display *disp, bool immediate); - int (*blit) (struct uterm_display *disp, - const struct uterm_video_buffer *buf, - unsigned int x, unsigned int y); int (*fake_blendv) (struct uterm_display *disp, const struct uterm_video_blend_req *req, size_t num);