Merge c73ccd28f28d4507a085e24bb24bbfa7f4b8ca46 into 0b3452719992f855b64fa21c9d7fbd6158a8d23a

This commit is contained in:
Aetf 2018-09-06 02:19:59 +00:00 committed by GitHub
commit 9279ddf609
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 285 additions and 64 deletions

1
.gitignore vendored
View File

@ -10,6 +10,7 @@ Makefile.in
aclocal.m4
autom4te.cache/
build-aux/
build/
config.h
config.h.in
config.h.in~

View File

@ -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 \

View File

@ -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

View File

@ -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
View 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 "$@"

View File

@ -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)

View File

@ -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);

View File

@ -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)

View File

@ -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;

View File

@ -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,

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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,

View File

@ -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,

View File

@ -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 {

View File

@ -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 {

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -55,6 +55,7 @@ struct fbdev_display {
unsigned int stride;
bool xrgb32;
bool rgb24;
bool rgb16;
unsigned int Bpp;
unsigned int off_r;

View File

@ -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)

View File

@ -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;

View File

@ -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 {

View File

@ -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>