Remove cairo text-renderer
The cairo text-renderer is _way_ too slow. There's no reason to keep it around, anymore. Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
This commit is contained in:
parent
9f2f11d2a5
commit
1e94fc361e
19
Makefile.am
19
Makefile.am
@ -473,25 +473,6 @@ mod_gltex_la_LDFLAGS = \
|
||||
-module \
|
||||
-avoid-version
|
||||
|
||||
if BUILD_ENABLE_RENDERER_CAIRO
|
||||
module_LTLIBRARIES += mod-cairo.la
|
||||
endif
|
||||
|
||||
mod_cairo_la_SOURCES = \
|
||||
src/kmscon_module_interface.h \
|
||||
src/text_cairo.c \
|
||||
src/kmscon_mod_cairo.c
|
||||
mod_cairo_la_CPPFLAGS = \
|
||||
$(AM_CPPFLAGS) \
|
||||
$(CAIRO_CFLAGS)
|
||||
mod_cairo_la_LIBADD = \
|
||||
$(CAIRO_LIBS) \
|
||||
libshl.la
|
||||
mod_cairo_la_LDFLAGS = \
|
||||
$(AM_LDFLAGS) \
|
||||
-module \
|
||||
-avoid-version
|
||||
|
||||
if BUILD_ENABLE_RENDERER_PIXMAN
|
||||
module_LTLIBRARIES += mod-pixman.la
|
||||
endif
|
||||
|
1
README
1
README
@ -80,7 +80,6 @@ Released tarballs can be found at:
|
||||
--with-renderers: Console rendering backends. Available are:
|
||||
- bbulk: Simple 2D software-renderer (bulk-mode)
|
||||
- gltex: OpenGLESv2 accelerated renderer
|
||||
- cairo: cairo based renderer
|
||||
- pixman: pixman based renderer
|
||||
Default is: bbulk,gltex
|
||||
The bblit backend is always built-in.
|
||||
|
49
configure.ac
49
configure.ac
@ -100,11 +100,6 @@ PKG_CHECK_MODULES([PANGO], [pango pangoft2],
|
||||
AC_SUBST(PANGO_CFLAGS)
|
||||
AC_SUBST(PANGO_LIBS)
|
||||
|
||||
PKG_CHECK_MODULES([CAIRO], [cairo],
|
||||
[have_cairo=yes], [have_cairo=no])
|
||||
AC_SUBST(CAIRO_CFLAGS)
|
||||
AC_SUBST(CAIRO_LIBS)
|
||||
|
||||
PKG_CHECK_MODULES([PIXMAN], [pixman-1],
|
||||
[have_pixman=yes], [have_pixman=no])
|
||||
AC_SUBST(PIXMAN_CFLAGS)
|
||||
@ -276,18 +271,15 @@ AC_ARG_WITH([renderers],
|
||||
[with_renderers="default"])
|
||||
enable_renderer_bbulk="no"
|
||||
enable_renderer_gltex="no"
|
||||
enable_renderer_cairo="no"
|
||||
enable_renderer_pixman="no"
|
||||
if test "x$enable_all" = "xyes" ; then
|
||||
enable_renderer_bbulk="yes"
|
||||
enable_renderer_gltex="yes"
|
||||
enable_renderer_cairo="yes"
|
||||
enable_renderer_pixman="yes"
|
||||
with_renderers="bbulk,gltex,cairo,pixman (all)"
|
||||
with_renderers="bbulk,gltex,pixman (all)"
|
||||
elif test "x$with_renderers" = "xdefault" ; then
|
||||
enable_renderer_bbulk="yes (default)"
|
||||
enable_renderer_gltex="yes (default)"
|
||||
enable_renderer_cairo="no (default)"
|
||||
enable_renderer_pixman="no (default)"
|
||||
with_renderers="bbulk,gltex (default)"
|
||||
elif test ! "x$with_renderers" = "x" ; then
|
||||
@ -298,8 +290,6 @@ elif test ! "x$with_renderers" = "x" ; then
|
||||
enable_renderer_bbulk="yes"
|
||||
elif test "x$i" = "xgltex" ; then
|
||||
enable_renderer_gltex="yes"
|
||||
elif test "x$i" = "xcairo" ; then
|
||||
enable_renderer_cairo="yes"
|
||||
elif test "x$i" = "xpixman" ; then
|
||||
enable_renderer_pixman="yes"
|
||||
else
|
||||
@ -566,25 +556,6 @@ else
|
||||
renderer_gltex_missing="enable-renderer-gltex"
|
||||
fi
|
||||
|
||||
# renderer cairo
|
||||
renderer_cairo_avail=no
|
||||
renderer_cairo_missing=""
|
||||
if test ! "x$enable_renderer_cairo" = "xno" ; then
|
||||
renderer_cairo_avail=yes
|
||||
if test "x$have_cairo" = "xno" ; then
|
||||
renderer_cairo_avail=no
|
||||
renderer_cairo_missing="cairo"
|
||||
fi
|
||||
|
||||
if test "x$renderer_cairo_avail" = "xno" ; then
|
||||
if test "x$enable_renderer_cairo" = "xyes" ; then
|
||||
AC_ERROR([missing for renderer-cairo: $renderer_cairo_missing])
|
||||
fi
|
||||
fi
|
||||
else
|
||||
renderer_cairo_missing="enable-renderer-cairo"
|
||||
fi
|
||||
|
||||
# renderer pixman
|
||||
renderer_pixman_avail=no
|
||||
renderer_pixman_missing=""
|
||||
@ -747,14 +718,6 @@ if test "x$renderer_gltex_avail" = "xyes" ; then
|
||||
fi
|
||||
fi
|
||||
|
||||
# renderer cairo
|
||||
renderer_cairo_enabled=no
|
||||
if test "x$renderer_cairo_avail" = "xyes" ; then
|
||||
if test "x${enable_renderer_cairo% *}" = "xyes" ; then
|
||||
renderer_cairo_enabled=yes
|
||||
fi
|
||||
fi
|
||||
|
||||
# renderer pixman
|
||||
renderer_pixman_enabled=no
|
||||
if test "x$renderer_pixman_avail" = "xyes" ; then
|
||||
@ -948,15 +911,6 @@ fi
|
||||
AM_CONDITIONAL([BUILD_ENABLE_RENDERER_GLTEX],
|
||||
[test "x$renderer_gltex_enabled" = "xyes"])
|
||||
|
||||
# renderer cairo
|
||||
if test "x$renderer_cairo_enabled" = "xyes" ; then
|
||||
AC_DEFINE([BUILD_ENABLE_RENDERER_CAIRO], [1],
|
||||
[Build cairo rendering backend])
|
||||
fi
|
||||
|
||||
AM_CONDITIONAL([BUILD_ENABLE_RENDERER_CAIRO],
|
||||
[test "x$renderer_cairo_enabled" = "xyes"])
|
||||
|
||||
# renderer pixman
|
||||
if test "x$renderer_pixman_enabled" = "xyes" ; then
|
||||
AC_DEFINE([BUILD_ENABLE_RENDERER_PIXMAN], [1],
|
||||
@ -1109,7 +1063,6 @@ AC_MSG_NOTICE([Build configuration:
|
||||
Renderers:
|
||||
bbulk: $renderer_bbulk_enabled ($renderer_bbulk_avail: $renderer_bbulk_missing)
|
||||
gltex: $renderer_gltex_enabled ($renderer_gltex_avail: $renderer_gltex_missing)
|
||||
cairo: $renderer_cairo_enabled ($renderer_cairo_avail: $renderer_cairo_missing)
|
||||
pixman: $renderer_pixman_enabled ($renderer_pixman_avail: $renderer_pixman_missing)
|
||||
|
||||
Session Types:
|
||||
|
@ -1,57 +0,0 @@
|
||||
/*
|
||||
* kmscon - Cairo based rendering backend module
|
||||
*
|
||||
* Copyright (c) 2012-2013 David Herrmann <dh.herrmann@googlemail.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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Cairo based rendering backend
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include "text.h"
|
||||
#include "kmscon_module_interface.h"
|
||||
#include "shl_log.h"
|
||||
|
||||
#define LOG_SUBSYSTEM "mod_cairo"
|
||||
|
||||
static int kmscon_cairo_load(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
kmscon_text_cairo_ops.owner = KMSCON_THIS_MODULE;
|
||||
ret = kmscon_text_register(&kmscon_text_cairo_ops);
|
||||
if (ret) {
|
||||
log_error("cannot register cairo renderer");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void kmscon_cairo_unload(void)
|
||||
{
|
||||
kmscon_text_unregister(kmscon_text_cairo_ops.name);
|
||||
}
|
||||
|
||||
KMSCON_MODULE(NULL, kmscon_cairo_load, kmscon_cairo_unload, NULL);
|
@ -112,7 +112,6 @@ 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_cairo_ops;
|
||||
extern struct kmscon_text_ops kmscon_text_pixman_ops;
|
||||
|
||||
#endif /* KMSCON_TEXT_H */
|
||||
|
467
src/text_cairo.c
467
src/text_cairo.c
@ -1,467 +0,0 @@
|
||||
/*
|
||||
* kmscon - Cairo Text Renderer Backend
|
||||
*
|
||||
* Copyright (c) 2012-2013 David Herrmann <dh.herrmann@googlemail.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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Cairo based text renderer
|
||||
*/
|
||||
|
||||
#include <cairo.h>
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "shl_hashtable.h"
|
||||
#include "shl_log.h"
|
||||
#include "text.h"
|
||||
#include "uterm_video.h"
|
||||
|
||||
#define LOG_SUBSYSTEM "text_cairo"
|
||||
|
||||
struct tc_glyph {
|
||||
const struct kmscon_glyph *glyph;
|
||||
cairo_surface_t *surf;
|
||||
uint8_t *data;
|
||||
};
|
||||
|
||||
struct tc_cairo {
|
||||
struct shl_hashtable *glyphs;
|
||||
struct shl_hashtable *bold_glyphs;
|
||||
|
||||
bool new_stride;
|
||||
unsigned int cur;
|
||||
struct uterm_video_buffer buf[2];
|
||||
cairo_surface_t *surf[2];
|
||||
cairo_t *ctx[2];
|
||||
|
||||
bool use_indirect;
|
||||
uint8_t *data[2];
|
||||
struct uterm_video_buffer vbuf;
|
||||
};
|
||||
|
||||
static int tc_init(struct kmscon_text *txt)
|
||||
{
|
||||
struct tc_cairo *tc;
|
||||
|
||||
tc = malloc(sizeof(*tc));
|
||||
if (!tc)
|
||||
return -ENOMEM;
|
||||
|
||||
txt->data = tc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void tc_destroy(struct kmscon_text *txt)
|
||||
{
|
||||
struct tc_cairo *tc = txt->data;
|
||||
|
||||
free(tc);
|
||||
}
|
||||
|
||||
static void free_glyph(void *data)
|
||||
{
|
||||
struct tc_glyph *glyph = data;
|
||||
|
||||
cairo_surface_destroy(glyph->surf);
|
||||
free(glyph->data);
|
||||
free(glyph);
|
||||
}
|
||||
|
||||
static unsigned int format_u2c(unsigned int f)
|
||||
{
|
||||
switch (f) {
|
||||
case UTERM_FORMAT_XRGB32:
|
||||
return CAIRO_FORMAT_ARGB32;
|
||||
case UTERM_FORMAT_RGB16:
|
||||
return CAIRO_FORMAT_RGB16_565;
|
||||
case UTERM_FORMAT_GREY:
|
||||
return CAIRO_FORMAT_A8;
|
||||
default:
|
||||
return CAIRO_FORMAT_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
static int alloc_indirect(struct kmscon_text *txt,
|
||||
unsigned int w, unsigned int h)
|
||||
{
|
||||
struct tc_cairo *tc = txt->data;
|
||||
unsigned int s, i, format;
|
||||
int ret;
|
||||
|
||||
log_info("using blitting engine");
|
||||
|
||||
format = format_u2c(UTERM_FORMAT_XRGB32);
|
||||
s = cairo_format_stride_for_width(format, w);
|
||||
|
||||
tc->data[0] = malloc(s * h);
|
||||
tc->data[1] = malloc(s * h);
|
||||
if (!tc->data[0] || !tc->data[1]) {
|
||||
log_error("cannot allocate memory for render-buffer");
|
||||
ret = -ENOMEM;
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
for (i = 0; i < 2; ++i) {
|
||||
tc->surf[i] = cairo_image_surface_create_for_data(tc->data[i],
|
||||
format,
|
||||
w, h, s);
|
||||
|
||||
ret = cairo_surface_status(tc->surf[i]);
|
||||
if (ret != CAIRO_STATUS_SUCCESS) {
|
||||
log_error("cannot create cairo surface: %d", ret);
|
||||
goto err_cairo;
|
||||
}
|
||||
}
|
||||
|
||||
tc->vbuf.width = w;
|
||||
tc->vbuf.height = h;
|
||||
tc->vbuf.stride = s;
|
||||
tc->vbuf.format = UTERM_FORMAT_XRGB32;
|
||||
tc->use_indirect = true;
|
||||
return 0;
|
||||
|
||||
err_cairo:
|
||||
cairo_surface_destroy(tc->surf[1]);
|
||||
cairo_surface_destroy(tc->surf[0]);
|
||||
err_free:
|
||||
free(tc->data[1]);
|
||||
free(tc->data[0]);
|
||||
tc->data[1] = NULL;
|
||||
tc->data[0] = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tc_set(struct kmscon_text *txt)
|
||||
{
|
||||
struct tc_cairo *tc = txt->data;
|
||||
int ret, ret2;
|
||||
unsigned int format, w, h;
|
||||
struct uterm_mode *m;
|
||||
|
||||
memset(tc, 0, sizeof(*tc));
|
||||
m = uterm_display_get_current(txt->disp);
|
||||
w = uterm_mode_get_width(m);
|
||||
h = uterm_mode_get_height(m);
|
||||
|
||||
ret = shl_hashtable_new(&tc->glyphs, shl_direct_hash,
|
||||
shl_direct_equal, NULL,
|
||||
free_glyph);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = shl_hashtable_new(&tc->bold_glyphs, shl_direct_hash,
|
||||
shl_direct_equal, NULL,
|
||||
free_glyph);
|
||||
if (ret)
|
||||
goto err_htable;
|
||||
|
||||
/*
|
||||
* 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, tc->buf,
|
||||
UTERM_FORMAT_XRGB32 |
|
||||
UTERM_FORMAT_RGB16);
|
||||
if (ret) {
|
||||
log_warning("cannot get buffers for display %p",
|
||||
txt->disp);
|
||||
ret = alloc_indirect(txt, w, h);
|
||||
if (ret)
|
||||
goto err_htable_bold;
|
||||
} else {
|
||||
format = format_u2c(tc->buf[0].format);
|
||||
tc->surf[0] = cairo_image_surface_create_for_data(
|
||||
tc->buf[0].data,
|
||||
format,
|
||||
tc->buf[0].width,
|
||||
tc->buf[0].height,
|
||||
tc->buf[0].stride);
|
||||
format = format_u2c(tc->buf[1].format);
|
||||
tc->surf[1] = cairo_image_surface_create_for_data(
|
||||
tc->buf[1].data,
|
||||
format,
|
||||
tc->buf[1].width,
|
||||
tc->buf[1].height,
|
||||
tc->buf[1].stride);
|
||||
|
||||
ret = cairo_surface_status(tc->surf[0]);
|
||||
ret2 = cairo_surface_status(tc->surf[1]);
|
||||
if (ret != CAIRO_STATUS_SUCCESS ||
|
||||
ret2 != CAIRO_STATUS_SUCCESS) {
|
||||
log_error("cannot create cairo surface: %d %d",
|
||||
ret, ret2);
|
||||
cairo_surface_destroy(tc->surf[1]);
|
||||
cairo_surface_destroy(tc->surf[0]);
|
||||
ret = alloc_indirect(txt, w, h);
|
||||
if (ret)
|
||||
goto err_htable_bold;
|
||||
}
|
||||
}
|
||||
|
||||
tc->ctx[0] = cairo_create(tc->surf[0]);
|
||||
tc->ctx[1] = cairo_create(tc->surf[1]);
|
||||
ret = cairo_status(tc->ctx[0]);
|
||||
ret2 = cairo_status(tc->ctx[1]);
|
||||
if (ret != CAIRO_STATUS_SUCCESS || ret2 != CAIRO_STATUS_SUCCESS) {
|
||||
log_error("cannot create cairo contexts: %d %d", ret, ret2);
|
||||
goto err_ctx;
|
||||
}
|
||||
|
||||
txt->cols = w / txt->font->attr.width;
|
||||
txt->rows = h / txt->font->attr.height;
|
||||
|
||||
return 0;
|
||||
|
||||
err_ctx:
|
||||
cairo_destroy(tc->ctx[1]);
|
||||
cairo_destroy(tc->ctx[0]);
|
||||
cairo_surface_destroy(tc->surf[1]);
|
||||
cairo_surface_destroy(tc->surf[0]);
|
||||
free(tc->data[1]);
|
||||
free(tc->data[0]);
|
||||
err_htable_bold:
|
||||
shl_hashtable_free(tc->bold_glyphs);
|
||||
err_htable:
|
||||
shl_hashtable_free(tc->glyphs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void tc_unset(struct kmscon_text *txt)
|
||||
{
|
||||
struct tc_cairo *tc = txt->data;
|
||||
|
||||
cairo_destroy(tc->ctx[1]);
|
||||
cairo_destroy(tc->ctx[0]);
|
||||
cairo_surface_destroy(tc->surf[1]);
|
||||
cairo_surface_destroy(tc->surf[0]);
|
||||
free(tc->data[1]);
|
||||
free(tc->data[0]);
|
||||
shl_hashtable_free(tc->bold_glyphs);
|
||||
shl_hashtable_free(tc->glyphs);
|
||||
}
|
||||
|
||||
static int find_glyph(struct kmscon_text *txt, struct tc_glyph **out,
|
||||
uint32_t id, const uint32_t *ch, size_t len, bool bold)
|
||||
{
|
||||
struct tc_cairo *tc = txt->data;
|
||||
struct tc_glyph *glyph;
|
||||
struct shl_hashtable *gtable;
|
||||
struct kmscon_font *font;
|
||||
const struct uterm_video_buffer *buf;
|
||||
uint8_t *dst, *src;
|
||||
unsigned int format, i;
|
||||
int ret, stride;
|
||||
bool res;
|
||||
|
||||
if (bold) {
|
||||
gtable = tc->bold_glyphs;
|
||||
font = txt->bold_font;
|
||||
} else {
|
||||
gtable = tc->glyphs;
|
||||
font = txt->font;
|
||||
}
|
||||
|
||||
res = shl_hashtable_find(gtable, (void**)&glyph,
|
||||
(void*)(unsigned long)id);
|
||||
if (res) {
|
||||
*out = glyph;
|
||||
return 0;
|
||||
}
|
||||
|
||||
glyph = malloc(sizeof(*glyph));
|
||||
if (!glyph)
|
||||
return -ENOMEM;
|
||||
memset(glyph, 0, sizeof(*glyph));
|
||||
|
||||
if (!len)
|
||||
ret = kmscon_font_render_empty(font, &glyph->glyph);
|
||||
else
|
||||
ret = kmscon_font_render(font, id, ch, len, &glyph->glyph);
|
||||
|
||||
if (ret) {
|
||||
ret = kmscon_font_render_inval(font, &glyph->glyph);
|
||||
if (ret)
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
buf = &glyph->glyph->buf;
|
||||
stride = buf->stride;
|
||||
format = format_u2c(buf->format);
|
||||
glyph->surf = cairo_image_surface_create_for_data(buf->data,
|
||||
format,
|
||||
buf->width,
|
||||
buf->height,
|
||||
buf->stride);
|
||||
ret = cairo_surface_status(glyph->surf);
|
||||
if (ret == CAIRO_STATUS_INVALID_STRIDE) {
|
||||
stride = cairo_format_stride_for_width(format, buf->width);
|
||||
if (!tc->new_stride) {
|
||||
tc->new_stride = true;
|
||||
log_debug("wrong stride, copy buffer (%d => %d)",
|
||||
buf->stride, stride);
|
||||
}
|
||||
|
||||
glyph->data = malloc(stride * buf->height);
|
||||
if (!glyph->data) {
|
||||
log_error("cannot allocate memory for glyph storage");
|
||||
ret = -ENOMEM;
|
||||
goto err_cairo;
|
||||
}
|
||||
|
||||
src = buf->data;
|
||||
dst = glyph->data;
|
||||
for (i = 0; i < buf->height; ++i) {
|
||||
memcpy(dst, src, buf->width);
|
||||
dst += stride;
|
||||
src += buf->stride;
|
||||
}
|
||||
|
||||
cairo_surface_destroy(glyph->surf);
|
||||
glyph->surf = cairo_image_surface_create_for_data(glyph->data,
|
||||
format,
|
||||
buf->width,
|
||||
buf->height,
|
||||
stride);
|
||||
ret = cairo_surface_status(glyph->surf);
|
||||
}
|
||||
if (ret != CAIRO_STATUS_SUCCESS) {
|
||||
log_error("cannot create cairo-glyph: %d %p %d %d %d %d",
|
||||
ret, glyph->data ? glyph->data : buf->data, format,
|
||||
buf->width, buf->height, stride);
|
||||
ret = -EFAULT;
|
||||
goto err_cairo;
|
||||
}
|
||||
|
||||
ret = shl_hashtable_insert(gtable, (void*)(long)id, glyph);
|
||||
if (ret)
|
||||
goto err_cairo;
|
||||
|
||||
*out = glyph;
|
||||
return 0;
|
||||
|
||||
err_cairo:
|
||||
cairo_surface_destroy(glyph->surf);
|
||||
free(glyph->data);
|
||||
err_free:
|
||||
free(glyph);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tc_prepare(struct kmscon_text *txt)
|
||||
{
|
||||
struct tc_cairo *tc = txt->data;
|
||||
int ret;
|
||||
|
||||
ret = uterm_display_use(txt->disp, NULL);
|
||||
if (ret < 0) {
|
||||
log_error("cannot use display %p", txt->disp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
tc->cur = ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tc_draw(struct kmscon_text *txt,
|
||||
uint32_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 tc_cairo *tc = txt->data;
|
||||
cairo_t *cr = tc->ctx[tc->cur];
|
||||
struct tc_glyph *glyph;
|
||||
int ret;
|
||||
|
||||
if (!width)
|
||||
return 0;
|
||||
|
||||
ret = find_glyph(txt, &glyph, id, ch, len, attr->bold);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
cairo_rectangle(cr,
|
||||
posx * txt->font->attr.width,
|
||||
posy * txt->font->attr.height,
|
||||
txt->font->attr.width,
|
||||
txt->font->attr.height);
|
||||
|
||||
if (attr->inverse)
|
||||
cairo_set_source_rgb(cr, attr->fr / 255.0, attr->fg / 255.0,
|
||||
attr->fb / 255.0);
|
||||
else
|
||||
cairo_set_source_rgb(cr, attr->br / 255.0, attr->bg / 255.0,
|
||||
attr->bb / 255.0);
|
||||
|
||||
cairo_fill(cr);
|
||||
|
||||
if (attr->inverse)
|
||||
cairo_set_source_rgb(cr, attr->br / 255.0, attr->bg / 255.0,
|
||||
attr->bb / 255.0);
|
||||
else
|
||||
cairo_set_source_rgb(cr, attr->fr / 255.0, attr->fg / 255.0,
|
||||
attr->fb / 255.0);
|
||||
|
||||
cairo_mask_surface(cr, glyph->surf,
|
||||
posx * txt->font->attr.width,
|
||||
posy * txt->font->attr.height);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tc_render(struct kmscon_text *txt)
|
||||
{
|
||||
struct tc_cairo *tc = txt->data;
|
||||
int ret;
|
||||
|
||||
cairo_surface_flush(tc->surf[tc->cur]);
|
||||
|
||||
if (!tc->use_indirect)
|
||||
return 0;
|
||||
|
||||
tc->vbuf.data = tc->data[tc->cur];
|
||||
ret = uterm_display_blit(txt->disp, &tc->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_cairo_ops = {
|
||||
.name = "cairo",
|
||||
.owner = NULL,
|
||||
.init = tc_init,
|
||||
.destroy = tc_destroy,
|
||||
.set = tc_set,
|
||||
.unset = tc_unset,
|
||||
.prepare = tc_prepare,
|
||||
.draw = tc_draw,
|
||||
.render = tc_render,
|
||||
.abort = NULL,
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user