Merge c73ccd28f28d4507a085e24bb24bbfa7f4b8ca46 into 0b3452719992f855b64fa21c9d7fbd6158a8d23a
This commit is contained in:
commit
9279ddf609
1
.gitignore
vendored
1
.gitignore
vendored
@ -10,6 +10,7 @@ Makefile.in
|
||||
aclocal.m4
|
||||
autom4te.cache/
|
||||
build-aux/
|
||||
build/
|
||||
config.h
|
||||
config.h.in
|
||||
config.h.in~
|
||||
|
@ -30,15 +30,18 @@ MANPAGES =
|
||||
MANPAGES_ALIASES =
|
||||
TPHONY =
|
||||
|
||||
bin_PROGRAMS =
|
||||
check_PROGRAMS =
|
||||
noinst_PROGRAMS =
|
||||
lib_LTLIBRARIES =
|
||||
noinst_LTLIBRARIES =
|
||||
bin_SCRIPTS =
|
||||
|
||||
moduledir = $(libdir)/kmscon
|
||||
module_LTLIBRARIES =
|
||||
|
||||
helperdir = $(libexecdir)/kmscon
|
||||
helper_PROGRAMS =
|
||||
|
||||
#
|
||||
# Default CFlags
|
||||
# Make all files include "config.h" by default. This shouldn't cause any
|
||||
@ -475,7 +478,8 @@ mod_pixman_la_LDFLAGS = \
|
||||
# built as part of kmscon.
|
||||
#
|
||||
|
||||
bin_PROGRAMS += kmscon
|
||||
bin_SCRIPTS += scripts/kmscon
|
||||
helper_PROGRAMS += kmscon
|
||||
check_PROGRAMS += \
|
||||
test_output \
|
||||
test_vt \
|
||||
|
17
autogen.sh
17
autogen.sh
@ -1,8 +1,17 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
mkdir -p m4
|
||||
autoreconf -i
|
||||
|
||||
if test ! "x$NOCONFIGURE" = "x1" ; then
|
||||
exec ./configure "$@"
|
||||
srcdir=`dirname $0`
|
||||
test -z "$srcdir" && srcdir=.
|
||||
|
||||
origdir=`pwd`
|
||||
cd $srcdir
|
||||
|
||||
mkdir -p m4
|
||||
autoreconf -is --force
|
||||
|
||||
cd $origdir
|
||||
|
||||
if test -z "$NOCONFIGURE" ; then
|
||||
exec $srcdir/configure "$@"
|
||||
fi
|
||||
|
@ -51,7 +51,7 @@ PKG_CHECK_MODULES([XKBCOMMON], [xkbcommon])
|
||||
AC_SUBST(XKBCOMMON_CFLAGS)
|
||||
AC_SUBST(XKBCOMMON_LIBS)
|
||||
|
||||
PKG_CHECK_MODULES([TSM], [libtsm])
|
||||
PKG_CHECK_MODULES([TSM], [libtsm >= 4.0.0])
|
||||
AC_SUBST(TSM_CFLAGS)
|
||||
AC_SUBST(TSM_LIBS)
|
||||
|
||||
@ -791,7 +791,7 @@ fi
|
||||
# makefiles.
|
||||
#
|
||||
|
||||
AC_CONFIG_FILES([Makefile])
|
||||
AC_CONFIG_FILES([Makefile scripts/kmscon])
|
||||
AC_OUTPUT
|
||||
|
||||
#
|
||||
|
59
scripts/kmscon.in
Executable file
59
scripts/kmscon.in
Executable file
@ -0,0 +1,59 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2018 Aetf <aetf@unlimitedcodeworks.xyz>
|
||||
# Copyright (c) 2018 Fabian Vogt <fvogt@suse.com>
|
||||
#
|
||||
# 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.
|
||||
|
||||
# configuration path
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libexecdir=@libexecdir@
|
||||
helperdir=${libexecdir}/kmscon
|
||||
|
||||
# Get a property from org.freedesktop.locale1
|
||||
queryLocale1() {
|
||||
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}'
|
||||
}
|
||||
|
||||
# Query and setup system locale settings before start kmscon
|
||||
setupLocale() {
|
||||
# Fallback to do nothing if we don't have the command
|
||||
if ! command -v dbus-send >/dev/null 2>/dev/null; then
|
||||
return
|
||||
fi
|
||||
|
||||
# Don't override existing values. Also there is no point in setting only some of them
|
||||
# as then they would not match anymore.
|
||||
if test -n "${XKB_DEFAULT_MODEL}" -o -n "${XKB_DEFAULT_LAYOUT}" -o -n "${XKB_DEFAULT_VARIANT}" -o -n "${XKB_DEFAULT_OPTIONS}"; then
|
||||
return
|
||||
fi
|
||||
|
||||
X11MODEL="$(queryLocale1 X11Model)"
|
||||
X11LAYOUT="$(queryLocale1 X11Layout)"
|
||||
X11VARIANT="$(queryLocale1 X11Variant)"
|
||||
X11OPTIONS="$(queryLocale1 X11Options)"
|
||||
[ -n "${X11MODEL}" ] && export XKB_DEFAULT_MODEL="${X11MODEL}"
|
||||
[ -n "${X11LAYOUT}" ] && export XKB_DEFAULT_LAYOUT="${X11LAYOUT}"
|
||||
[ -n "${X11VARIANT}" ] && export XKB_DEFAULT_VARIANT="${X11VARIANT}"
|
||||
[ -n "${X11OPTIONS}" ] && export XKB_DEFAULT_OPTIONS="${X11OPTIONS}"
|
||||
}
|
||||
|
||||
setupLocale
|
||||
exec ${helperdir}/kmscon "$@"
|
@ -130,6 +130,8 @@ bool kmscon_font_attr_match(const struct kmscon_font_attr *a1,
|
||||
return false;
|
||||
if (a1->italic != a2->italic)
|
||||
return false;
|
||||
if (a1->underline != a2->underline)
|
||||
return false;
|
||||
if (*a1->name && *a2->name && strcmp(a1->name, a2->name))
|
||||
return false;
|
||||
|
||||
@ -396,7 +398,7 @@ void kmscon_font_unref(struct kmscon_font *font)
|
||||
*/
|
||||
SHL_EXPORT
|
||||
int kmscon_font_render(struct kmscon_font *font,
|
||||
uint32_t id, const uint32_t *ch, size_t len,
|
||||
uint64_t id, const uint32_t *ch, size_t len,
|
||||
const struct kmscon_glyph **out)
|
||||
{
|
||||
if (!font || !out || !ch || !len)
|
||||
|
@ -52,6 +52,7 @@ struct kmscon_font_attr {
|
||||
unsigned int points;
|
||||
bool bold;
|
||||
bool italic;
|
||||
bool underline;
|
||||
unsigned int height;
|
||||
unsigned int width;
|
||||
};
|
||||
@ -82,7 +83,7 @@ struct kmscon_font_ops {
|
||||
const struct kmscon_font_attr *attr);
|
||||
void (*destroy) (struct kmscon_font *font);
|
||||
int (*render) (struct kmscon_font *font,
|
||||
uint32_t id, const uint32_t *ch, size_t len,
|
||||
uint64_t id, const uint32_t *ch, size_t len,
|
||||
const struct kmscon_glyph **out);
|
||||
int (*render_empty) (struct kmscon_font *font,
|
||||
const struct kmscon_glyph **out);
|
||||
@ -100,7 +101,7 @@ void kmscon_font_ref(struct kmscon_font *font);
|
||||
void kmscon_font_unref(struct kmscon_font *font);
|
||||
|
||||
int kmscon_font_render(struct kmscon_font *font,
|
||||
uint32_t id, const uint32_t *ch, size_t len,
|
||||
uint64_t id, const uint32_t *ch, size_t len,
|
||||
const struct kmscon_glyph **out);
|
||||
int kmscon_font_render_empty(struct kmscon_font *font,
|
||||
const struct kmscon_glyph **out);
|
||||
|
@ -81,7 +81,7 @@ static void kmscon_font_8x16_destroy(struct kmscon_font *font)
|
||||
}
|
||||
|
||||
static int kmscon_font_8x16_render(struct kmscon_font *font,
|
||||
uint32_t id, const uint32_t *ch, size_t len,
|
||||
uint64_t id, const uint32_t *ch, size_t len,
|
||||
const struct kmscon_glyph **out)
|
||||
{
|
||||
if (len > 1 || *ch >= 256)
|
||||
|
@ -110,10 +110,11 @@ static void manager__unref()
|
||||
}
|
||||
|
||||
static int get_glyph(struct face *face, struct kmscon_glyph **out,
|
||||
uint32_t id, const uint32_t *ch, size_t len)
|
||||
uint64_t id, const uint32_t *ch, size_t len, const struct kmscon_font_attr *attr)
|
||||
{
|
||||
struct kmscon_glyph *glyph;
|
||||
PangoLayout *layout;
|
||||
PangoAttrList *attrlist;
|
||||
PangoRectangle rec;
|
||||
PangoLayoutLine *line;
|
||||
FT_Bitmap bitmap;
|
||||
@ -131,7 +132,7 @@ static int get_glyph(struct face *face, struct kmscon_glyph **out,
|
||||
|
||||
pthread_mutex_lock(&face->glyph_lock);
|
||||
res = shl_hashtable_find(face->glyphs, (void**)&glyph,
|
||||
(void*)(long)id);
|
||||
(void*)(uint64_t)id);
|
||||
pthread_mutex_unlock(&face->glyph_lock);
|
||||
if (res) {
|
||||
*out = glyph;
|
||||
@ -150,6 +151,12 @@ static int get_glyph(struct face *face, struct kmscon_glyph **out,
|
||||
glyph->width = cwidth;
|
||||
|
||||
layout = pango_layout_new(face->ctx);
|
||||
attrlist = pango_layout_get_attributes(layout);
|
||||
if (attrlist == NULL) {
|
||||
attrlist = pango_attr_list_new();
|
||||
pango_layout_set_attributes(layout, attrlist);
|
||||
pango_attr_list_unref(attrlist);
|
||||
}
|
||||
|
||||
/* render one line only */
|
||||
pango_layout_set_height(layout, 0);
|
||||
@ -157,6 +164,24 @@ static int get_glyph(struct face *face, struct kmscon_glyph **out,
|
||||
/* no line spacing */
|
||||
pango_layout_set_spacing(layout, 0);
|
||||
|
||||
/* underline if requested */
|
||||
if (attr->underline) {
|
||||
pango_attr_list_change(attrlist,
|
||||
pango_attr_underline_new(PANGO_UNDERLINE_SINGLE));
|
||||
} else {
|
||||
pango_attr_list_change(attrlist,
|
||||
pango_attr_underline_new(PANGO_UNDERLINE_NONE));
|
||||
}
|
||||
|
||||
/* italic if requested */
|
||||
if (attr->italic) {
|
||||
pango_attr_list_change(attrlist,
|
||||
pango_attr_style_new(PANGO_STYLE_ITALIC));
|
||||
} else {
|
||||
pango_attr_list_change(attrlist,
|
||||
pango_attr_style_new(PANGO_STYLE_NORMAL));
|
||||
}
|
||||
|
||||
val = tsm_ucs4_to_utf8_alloc(ch, len, &ulen);
|
||||
if (!val) {
|
||||
ret = -ERANGE;
|
||||
@ -202,7 +227,7 @@ static int get_glyph(struct face *face, struct kmscon_glyph **out,
|
||||
pango_ft2_render_layout_line(&bitmap, line, -rec.x, face->baseline);
|
||||
|
||||
pthread_mutex_lock(&face->glyph_lock);
|
||||
ret = shl_hashtable_insert(face->glyphs, (void*)(long)id, glyph);
|
||||
ret = shl_hashtable_insert(face->glyphs, (void*)(uint64_t)id, glyph);
|
||||
pthread_mutex_unlock(&face->glyph_lock);
|
||||
if (ret) {
|
||||
log_error("cannot add glyph to hashtable");
|
||||
@ -398,14 +423,14 @@ static void kmscon_font_pango_destroy(struct kmscon_font *font)
|
||||
manager_put_face(face);
|
||||
}
|
||||
|
||||
static int kmscon_font_pango_render(struct kmscon_font *font, uint32_t id,
|
||||
static int kmscon_font_pango_render(struct kmscon_font *font, uint64_t id,
|
||||
const uint32_t *ch, size_t len,
|
||||
const struct kmscon_glyph **out)
|
||||
{
|
||||
struct kmscon_glyph *glyph;
|
||||
int ret;
|
||||
|
||||
ret = get_glyph(font->data, &glyph, id, ch, len);
|
||||
ret = get_glyph(font->data, &glyph, id, ch, len, &font->attr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include <pthread.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <libtsm.h>
|
||||
#include "font.h"
|
||||
#include "shl_hashtable.h"
|
||||
#include "shl_log.h"
|
||||
@ -105,7 +106,7 @@ static void unfold(uint8_t *dst, uint8_t val)
|
||||
*dst = 0xff * !!val;
|
||||
}
|
||||
|
||||
static int find_glyph(uint32_t id, const struct kmscon_glyph **out)
|
||||
static int find_glyph(uint32_t ch, const struct kmscon_glyph **out)
|
||||
{
|
||||
struct kmscon_glyph *g;
|
||||
int ret;
|
||||
@ -124,21 +125,21 @@ static int find_glyph(uint32_t id, const struct kmscon_glyph **out)
|
||||
}
|
||||
} else {
|
||||
res = shl_hashtable_find(cache, (void**)out,
|
||||
(void*)(long)id);
|
||||
(void*)(uint64_t)ch);
|
||||
if (res) {
|
||||
ret = 0;
|
||||
goto out_unlock;
|
||||
}
|
||||
}
|
||||
|
||||
if (id > 0xffff) {
|
||||
if (ch > 0xffff) {
|
||||
ret = -ERANGE;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
start = _binary_src_font_unifont_data_bin_start;
|
||||
end = _binary_src_font_unifont_data_bin_end;
|
||||
d = &start[id];
|
||||
d = &start[ch];
|
||||
|
||||
if (d >= end) {
|
||||
ret = -ERANGE;
|
||||
@ -186,7 +187,7 @@ static int find_glyph(uint32_t id, const struct kmscon_glyph **out)
|
||||
unfold(&g->buf.data[i * 8 + 7], d->data[i] & 0x01);
|
||||
}
|
||||
|
||||
ret = shl_hashtable_insert(cache, (void*)(long)id, g);
|
||||
ret = shl_hashtable_insert(cache, (void*)(uint64_t)ch, g);
|
||||
if (ret) {
|
||||
log_error("cannot insert glyph into glyph-cache: %d", ret);
|
||||
goto err_data;
|
||||
@ -240,14 +241,14 @@ static void kmscon_font_unifont_destroy(struct kmscon_font *font)
|
||||
cache_unref();
|
||||
}
|
||||
|
||||
static int kmscon_font_unifont_render(struct kmscon_font *font, uint32_t id,
|
||||
static int kmscon_font_unifont_render(struct kmscon_font *font, uint64_t id,
|
||||
const uint32_t *ch, size_t len,
|
||||
const struct kmscon_glyph **out)
|
||||
{
|
||||
if (len > 1)
|
||||
return -ERANGE;
|
||||
|
||||
return find_glyph(id, out);
|
||||
return find_glyph(id & TSM_UCS4_MAX, out);
|
||||
}
|
||||
|
||||
static int kmscon_font_unifont_render_inval(struct kmscon_font *font,
|
||||
|
@ -181,7 +181,7 @@ void kmscon_load_modules(void)
|
||||
{
|
||||
int ret;
|
||||
DIR *ent;
|
||||
struct dirent *buf, *de;
|
||||
struct dirent *de;
|
||||
char *file;
|
||||
struct kmscon_module *mod;
|
||||
|
||||
@ -203,18 +203,13 @@ void kmscon_load_modules(void)
|
||||
return;
|
||||
}
|
||||
|
||||
ret = shl_dirent(BUILD_MODULE_DIR, &buf);
|
||||
if (ret) {
|
||||
log_error("cannot allocate dirent object");
|
||||
closedir(ent);
|
||||
return;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
ret = readdir_r(ent, buf, &de);
|
||||
if (ret != 0) {
|
||||
errno = 0;
|
||||
de = readdir(ent);
|
||||
if (!de && errno != 0) {
|
||||
int errsv = errno;
|
||||
log_error("cannot read directory %s: %d",
|
||||
BUILD_MODULE_DIR, ret);
|
||||
BUILD_MODULE_DIR, errsv);
|
||||
break;
|
||||
} else if (!de) {
|
||||
break;
|
||||
@ -255,7 +250,6 @@ void kmscon_load_modules(void)
|
||||
shl_dlist_link(&module_list, &mod->list);
|
||||
}
|
||||
|
||||
free(buf);
|
||||
closedir(ent);
|
||||
}
|
||||
|
||||
|
@ -88,6 +88,7 @@ static void do_clear_margins(struct screen *scr)
|
||||
{
|
||||
unsigned int w, h, sw, sh;
|
||||
struct uterm_mode *mode;
|
||||
struct tsm_screen_attr attr;
|
||||
int dw, dh;
|
||||
|
||||
mode = uterm_display_get_current(scr->disp);
|
||||
@ -101,12 +102,14 @@ static void do_clear_margins(struct screen *scr)
|
||||
dw = sw - w;
|
||||
dh = sh - h;
|
||||
|
||||
tsm_vte_get_def_attr(scr->term->vte, &attr);
|
||||
|
||||
if (dw > 0)
|
||||
uterm_display_fill(scr->disp, 0, 0, 0,
|
||||
uterm_display_fill(scr->disp, attr.br, attr.bg, attr.bb,
|
||||
w, 0,
|
||||
dw, h);
|
||||
if (dh > 0)
|
||||
uterm_display_fill(scr->disp, 0, 0, 0,
|
||||
uterm_display_fill(scr->disp, attr.br, attr.bg, attr.bb,
|
||||
0, h,
|
||||
sw, dh);
|
||||
}
|
||||
|
@ -299,7 +299,7 @@ static void setup_child(int master, struct winsize *ws)
|
||||
if (ret)
|
||||
log_warn("cannot reset blocked signals: %m");
|
||||
|
||||
for (i = 1; i < SIGUNUSED; ++i)
|
||||
for (i = 1; i < SIGSYS; ++i)
|
||||
signal(i, SIG_DFL);
|
||||
|
||||
ret = grantpt(master);
|
||||
|
@ -381,7 +381,7 @@ int kmscon_text_prepare(struct kmscon_text *txt)
|
||||
* Returns: 0 on success or negative error code if this glyph couldn't be drawn.
|
||||
*/
|
||||
int kmscon_text_draw(struct kmscon_text *txt,
|
||||
uint32_t id, const uint32_t *ch, size_t len,
|
||||
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)
|
||||
@ -438,7 +438,7 @@ void kmscon_text_abort(struct kmscon_text *txt)
|
||||
}
|
||||
|
||||
int kmscon_text_draw_cb(struct tsm_screen *con,
|
||||
uint32_t id, const uint32_t *ch, size_t len,
|
||||
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,
|
||||
|
@ -68,7 +68,7 @@ struct kmscon_text_ops {
|
||||
void (*unset) (struct kmscon_text *txt);
|
||||
int (*prepare) (struct kmscon_text *txt);
|
||||
int (*draw) (struct kmscon_text *txt,
|
||||
uint32_t id, const uint32_t *ch, size_t len,
|
||||
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);
|
||||
@ -93,7 +93,7 @@ unsigned int kmscon_text_get_rows(struct kmscon_text *txt);
|
||||
|
||||
int kmscon_text_prepare(struct kmscon_text *txt);
|
||||
int kmscon_text_draw(struct kmscon_text *txt,
|
||||
uint32_t id, const uint32_t *ch, size_t len,
|
||||
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);
|
||||
@ -101,7 +101,7 @@ int kmscon_text_render(struct kmscon_text *txt);
|
||||
void kmscon_text_abort(struct kmscon_text *txt);
|
||||
|
||||
int kmscon_text_draw_cb(struct tsm_screen *con,
|
||||
uint32_t id, const uint32_t *ch, size_t len,
|
||||
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,
|
||||
|
@ -62,7 +62,7 @@ static int bblit_set(struct kmscon_text *txt)
|
||||
}
|
||||
|
||||
static int bblit_draw(struct kmscon_text *txt,
|
||||
uint32_t id, const uint32_t *ch, size_t len,
|
||||
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)
|
||||
@ -79,6 +79,16 @@ static int bblit_draw(struct kmscon_text *txt,
|
||||
else
|
||||
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;
|
||||
|
||||
if (!len) {
|
||||
ret = kmscon_font_render_empty(font, &glyph);
|
||||
} else {
|
||||
|
@ -111,7 +111,7 @@ static void bbulk_unset(struct kmscon_text *txt)
|
||||
}
|
||||
|
||||
static int bbulk_draw(struct kmscon_text *txt,
|
||||
uint32_t id, const uint32_t *ch, size_t len,
|
||||
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)
|
||||
@ -132,6 +132,16 @@ static int bbulk_draw(struct kmscon_text *txt,
|
||||
else
|
||||
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;
|
||||
|
||||
if (!len) {
|
||||
ret = kmscon_font_render_empty(font, &glyph);
|
||||
} else {
|
||||
|
@ -381,7 +381,7 @@ err_free:
|
||||
}
|
||||
|
||||
static int find_glyph(struct kmscon_text *txt, struct glyph **out,
|
||||
uint32_t id, const uint32_t *ch, size_t len, bool bold)
|
||||
uint64_t id, const uint32_t *ch, size_t len, const struct tsm_screen_attr *attr)
|
||||
{
|
||||
struct gltex *gt = txt->data;
|
||||
struct atlas *atlas;
|
||||
@ -393,7 +393,7 @@ static int find_glyph(struct kmscon_text *txt, struct glyph **out,
|
||||
struct shl_hashtable *gtable;
|
||||
struct kmscon_font *font;
|
||||
|
||||
if (bold) {
|
||||
if (attr->bold) {
|
||||
gtable = gt->bold_glyphs;
|
||||
font = txt->bold_font;
|
||||
} else {
|
||||
@ -401,8 +401,18 @@ static int find_glyph(struct kmscon_text *txt, struct glyph **out,
|
||||
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**)&glyph,
|
||||
(void*)(unsigned long)id);
|
||||
(void*)(uint64_t)id);
|
||||
if (res) {
|
||||
*out = glyph;
|
||||
return 0;
|
||||
@ -505,7 +515,7 @@ static int find_glyph(struct kmscon_text *txt, struct glyph **out,
|
||||
glyph->atlas = atlas;
|
||||
glyph->texoff = atlas->fill;
|
||||
|
||||
ret = shl_hashtable_insert(gtable, (void*)(long)id, glyph);
|
||||
ret = shl_hashtable_insert(gtable, (void*)(uint64_t)id, glyph);
|
||||
if (ret)
|
||||
goto err_free;
|
||||
|
||||
@ -543,7 +553,7 @@ static int gltex_prepare(struct kmscon_text *txt)
|
||||
}
|
||||
|
||||
static int gltex_draw(struct kmscon_text *txt,
|
||||
uint32_t id, const uint32_t *ch, size_t len,
|
||||
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)
|
||||
@ -556,7 +566,7 @@ static int gltex_draw(struct kmscon_text *txt,
|
||||
if (!width)
|
||||
return 0;
|
||||
|
||||
ret = find_glyph(txt, &glyph, id, ch, len, attr->bold);
|
||||
ret = find_glyph(txt, &glyph, id, ch, len, attr);
|
||||
if (ret)
|
||||
return ret;
|
||||
atlas = glyph->atlas;
|
||||
|
@ -262,7 +262,7 @@ static void tp_unset(struct kmscon_text *txt)
|
||||
}
|
||||
|
||||
static int find_glyph(struct kmscon_text *txt, struct tp_glyph **out,
|
||||
uint32_t id, const uint32_t *ch, size_t len, bool bold)
|
||||
uint64_t id, const uint32_t *ch, size_t len, const struct tsm_screen_attr *attr)
|
||||
{
|
||||
struct tp_pixman *tp = txt->data;
|
||||
struct tp_glyph *glyph;
|
||||
@ -274,7 +274,7 @@ static int find_glyph(struct kmscon_text *txt, struct tp_glyph **out,
|
||||
int ret, stride;
|
||||
bool res;
|
||||
|
||||
if (bold) {
|
||||
if (attr->bold) {
|
||||
gtable = tp->bold_glyphs;
|
||||
font = txt->bold_font;
|
||||
} else {
|
||||
@ -282,8 +282,18 @@ static int find_glyph(struct kmscon_text *txt, struct tp_glyph **out,
|
||||
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**)&glyph,
|
||||
(void*)(unsigned long)id);
|
||||
(void*)(uint64_t)id);
|
||||
if (res) {
|
||||
*out = glyph;
|
||||
return 0;
|
||||
@ -351,7 +361,7 @@ static int find_glyph(struct kmscon_text *txt, struct tp_glyph **out,
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
ret = shl_hashtable_insert(gtable, (void*)(long)id, glyph);
|
||||
ret = shl_hashtable_insert(gtable, (void*)(uint64_t)id, glyph);
|
||||
if (ret)
|
||||
goto err_pixman;
|
||||
|
||||
@ -387,7 +397,7 @@ static int tp_prepare(struct kmscon_text *txt)
|
||||
}
|
||||
|
||||
static int tp_draw(struct kmscon_text *txt,
|
||||
uint32_t id, const uint32_t *ch, size_t len,
|
||||
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)
|
||||
@ -402,7 +412,7 @@ static int tp_draw(struct kmscon_text *txt,
|
||||
if (!width)
|
||||
return 0;
|
||||
|
||||
ret = find_glyph(txt, &glyph, id, ch, len, attr->bold);
|
||||
ret = find_glyph(txt, &glyph, id, ch, len, attr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -498,6 +498,14 @@ int uterm_drm3d_display_fill(struct uterm_display *disp,
|
||||
if (tmp > sh)
|
||||
height = sh - y;
|
||||
|
||||
/* Caution:
|
||||
* opengl uses a coordinate system with the origin at _lower-left_ corner
|
||||
* and positive y-axis up, while other parts uses a coordinate system
|
||||
* with the origin at _upper-left_ corner and positive y-axis down.
|
||||
*/
|
||||
y = sh - y; // invert y-axis
|
||||
y -= height; // move origin to lower left corner
|
||||
|
||||
glViewport(x, y, width, height);
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
|
@ -55,6 +55,7 @@ struct fbdev_display {
|
||||
unsigned int stride;
|
||||
|
||||
bool xrgb32;
|
||||
bool rgb24;
|
||||
bool rgb16;
|
||||
unsigned int Bpp;
|
||||
unsigned int off_r;
|
||||
|
@ -100,6 +100,21 @@ static uint_fast32_t xrgb32_to_device(struct uterm_display *disp,
|
||||
return res;
|
||||
}
|
||||
|
||||
static void write_24bit(uint8_t *dst, uint_fast32_t value)
|
||||
{
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
dst[0] = value;
|
||||
dst[1] = value >> 8;
|
||||
dst[2] = value >> 16;
|
||||
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
dst[0] = value >> 16;
|
||||
dst[1] = value >> 8;
|
||||
dst[2] = value;
|
||||
#else
|
||||
#error "Unknown endianness"
|
||||
#endif
|
||||
}
|
||||
|
||||
int uterm_fbdev_display_blit(struct uterm_display *disp,
|
||||
const struct uterm_video_buffer *buf,
|
||||
unsigned int x, unsigned int y)
|
||||
@ -151,6 +166,16 @@ int uterm_fbdev_display_blit(struct uterm_display *disp,
|
||||
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) {
|
||||
@ -272,6 +297,35 @@ int uterm_fbdev_display_fake_blendv(struct uterm_display *disp,
|
||||
dst += fbdev->stride;
|
||||
src += req->buf->stride;
|
||||
}
|
||||
} else if (fbdev->Bpp == 3) {
|
||||
while (height--) {
|
||||
for (i = 0; i < width; ++i) {
|
||||
if (src[i] == 0) {
|
||||
r = req->br;
|
||||
g = req->bg;
|
||||
b = req->bb;
|
||||
} else if (src[i] == 255) {
|
||||
r = req->fr;
|
||||
g = req->fg;
|
||||
b = req->fb;
|
||||
} else {
|
||||
r = req->fr * src[i] +
|
||||
req->br * (255 - src[i]);
|
||||
r /= 256;
|
||||
g = req->fg * src[i] +
|
||||
req->bg * (255 - src[i]);
|
||||
g /= 256;
|
||||
b = req->fb * src[i] +
|
||||
req->bb * (255 - src[i]);
|
||||
b /= 256;
|
||||
}
|
||||
val = (r << 16) | (g << 8) | b;
|
||||
uint_fast32_t full = xrgb32_to_device(disp, val);
|
||||
write_24bit(&dst[i * 3], full);
|
||||
}
|
||||
dst += fbdev->stride;
|
||||
src += req->buf->stride;
|
||||
}
|
||||
} else if (fbdev->Bpp == 4) {
|
||||
while (height--) {
|
||||
for (i = 0; i < width; ++i) {
|
||||
@ -358,6 +412,13 @@ int uterm_fbdev_display_fill(struct uterm_display *disp,
|
||||
dst += fbdev->stride;
|
||||
}
|
||||
}
|
||||
} else if (fbdev->Bpp == 3) {
|
||||
while (height--) {
|
||||
for (i = 0; i < width * 3; i += 3) {
|
||||
write_24bit(&dst[i], full_val);
|
||||
}
|
||||
dst += fbdev->stride;
|
||||
}
|
||||
} else if (fbdev->Bpp == 4) {
|
||||
while (height--) {
|
||||
for (i = 0; i < width; ++i)
|
||||
|
@ -132,9 +132,7 @@ static int display_activate_force(struct uterm_display *disp,
|
||||
struct uterm_mode *mode,
|
||||
bool force)
|
||||
{
|
||||
/* TODO: Add support for 24-bpp. However, we need to check how 3-bytes
|
||||
* integers are assembled in big/little/mixed endian systems. */
|
||||
static const char depths[] = { 32, 16, 0 };
|
||||
static const char depths[] = { 32, 24, 16, 0 };
|
||||
struct fbdev_display *dfb = disp->data;
|
||||
struct uterm_mode *m;
|
||||
struct fbdev_mode *mfb;
|
||||
@ -217,14 +215,19 @@ static int display_activate_force(struct uterm_display *disp,
|
||||
if (finfo->visual != FB_VISUAL_TRUECOLOR ||
|
||||
vinfo->bits_per_pixel != 32) {
|
||||
for (i = 0; depths[i]; ++i) {
|
||||
vinfo->bits_per_pixel = depths[i];
|
||||
vinfo->activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE;
|
||||
/* Try to set a new mode and if it's successful... */
|
||||
struct fb_var_screeninfo vinfo_new = *vinfo;
|
||||
vinfo_new.bits_per_pixel = depths[i];
|
||||
vinfo_new.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE;
|
||||
|
||||
ret = ioctl(dfb->fd, FBIOPUT_VSCREENINFO,
|
||||
vinfo);
|
||||
&vinfo_new);
|
||||
if (ret < 0)
|
||||
continue;
|
||||
|
||||
/* ... keep it. */
|
||||
*vinfo = vinfo_new;
|
||||
|
||||
ret = refresh_info(disp);
|
||||
if (ret)
|
||||
goto err_close;
|
||||
@ -235,6 +238,7 @@ static int display_activate_force(struct uterm_display *disp,
|
||||
}
|
||||
|
||||
if (vinfo->bits_per_pixel != 32 &&
|
||||
vinfo->bits_per_pixel != 24 &&
|
||||
vinfo->bits_per_pixel != 16) {
|
||||
log_error("device %s does not support 16/32 bpp but: %u",
|
||||
dfb->node, vinfo->bits_per_pixel);
|
||||
@ -333,6 +337,10 @@ static int display_activate_force(struct uterm_display *disp,
|
||||
dfb->off_r == 11 && dfb->off_g == 5 && dfb->off_b == 0 &&
|
||||
dfb->Bpp == 2)
|
||||
dfb->rgb16 = true;
|
||||
else if (dfb->len_r == 8 && dfb->len_g == 8 && dfb->len_b == 8 &&
|
||||
dfb->off_r == 16 && dfb->off_g == 8 && dfb->off_b == 0 &&
|
||||
dfb->Bpp == 3)
|
||||
dfb->rgb24 = true;
|
||||
|
||||
/* TODO: make dithering configurable */
|
||||
disp->flags |= DISPLAY_DITHERING;
|
||||
@ -455,6 +463,8 @@ static int display_get_buffers(struct uterm_display *disp,
|
||||
f = UTERM_FORMAT_XRGB32;
|
||||
else if (dfb->rgb16)
|
||||
f = UTERM_FORMAT_RGB16;
|
||||
else if (dfb->rgb24)
|
||||
f = UTERM_FORMAT_RGB24;
|
||||
|
||||
if (!(formats & f))
|
||||
return -EOPNOTSUPP;
|
||||
|
@ -100,6 +100,7 @@ enum uterm_video_format {
|
||||
UTERM_FORMAT_GREY = 0x01,
|
||||
UTERM_FORMAT_XRGB32 = 0x02,
|
||||
UTERM_FORMAT_RGB16 = 0x04,
|
||||
UTERM_FORMAT_RGB24 = 0x08,
|
||||
};
|
||||
|
||||
struct uterm_video_buffer {
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/signalfd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/sysmacros.h>
|
||||
#include <termios.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
Loading…
x
Reference in New Issue
Block a user