xrender xcb engine

SVN revision: 21172
This commit is contained in:
doursse 2006-03-10 19:10:07 +00:00 committed by doursse
parent 6e63a2d07b
commit 1f3549a60b
19 changed files with 3476 additions and 26 deletions

View File

@ -1,5 +1,7 @@
## Process this file with automake to produce Makefile.in
ACLOCAL_AMFLAGS = -I m4
SUBDIRS = data src proj
MAINTAINERCLEANFILES = Makefile.in aclocal.m4 config.guess \
@ -29,6 +31,6 @@ EXTRA_DIST = AUTHORS COPYING COPYING-PLAIN evas.c.in gendoc \
debian/libevas0-dev.files \
debian/libevas0.files \
debian/rules
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = evas.pc

View File

@ -5,6 +5,7 @@ AC_INIT(configure.in)
AC_CANONICAL_BUILD
AC_CANONICAL_HOST
AC_ISC_POSIX
AC_CONFIG_MACRO_DIR([m4])
AM_INIT_AUTOMAKE(evas, 0.9.9.023)
AM_CONFIG_HEADER(config.h)
@ -169,7 +170,6 @@ if test "x$have_evas_software_x11" = "xyes"; then
AC_PATH_XTRA
AC_CHECK_HEADER(X11/X.h,
[
AM_CONDITIONAL(BUILD_ENGINE_SOFTWARE_X11, true)
AC_DEFINE(BUILD_ENGINE_SOFTWARE_X11, 1, [Software X11 Rendering Backend])
x_dir=${x_dir:-/usr/X11R6}
x_cflags=${x_cflags:--I${x_includes:-$x_dir/include}}
@ -177,14 +177,12 @@ if test "x$have_evas_software_x11" = "xyes"; then
ENGINE_SOFTWARE_X11_PRG="evas_software_x11_test evas_software_x11_perf_test evas_software_x11_perf_load"
],
[
AM_CONDITIONAL(BUILD_ENGINE_SOFTWARE_X11, false)
AC_MSG_RESULT(disabling software X11 engine)
have_evas_software_x11="no"
]
)
else
AM_CONDITIONAL(BUILD_ENGINE_SOFTWARE_X11, false)
fi
AM_CONDITIONAL(BUILD_ENGINE_SOFTWARE_X11, test "x$have_evas_software_x11" = "yes")
#######################################
## Check if we should build the software_xcb engine
@ -223,17 +221,14 @@ if test "x$have_evas_software_xcb" = "xyes"; then
PKG_CHECK_MODULES(
XCB,
xcb xcb-image xcb-icccm,
[AM_CONDITIONAL(BUILD_ENGINE_SOFTWARE_XCB, true)
AC_DEFINE(BUILD_ENGINE_SOFTWARE_XCB, 1, [Software XCB Rendering Backend])
[AC_DEFINE(BUILD_ENGINE_SOFTWARE_XCB, 1, [Software XCB Rendering Backend])
xcb_cflags=$XCB_CFLAGS
xcb_libs=$XCB_LIBS
ENGINE_SOFTWARE_XCB_PRG="evas_software_xcb_test evas_software_xcb_perf_test evas_software_xcb_perf_load"],
[AM_CONDITIONAL(BUILD_ENGINE_SOFTWARE_XCB, false)
AC_MSG_RESULT(disabling software XCB engine)
[AC_MSG_RESULT(disabling software XCB engine)
have_evas_software_xcb="no"])
else
AM_CONDITIONAL(BUILD_ENGINE_SOFTWARE_XCB, false)
fi
AM_CONDITIONAL(BUILD_ENGINE_SOFTWARE_XCB, test "x$have_evas_software_xcb" = "xyes")
#######################################
## Check if we should build the directfb engine
@ -263,18 +258,15 @@ AC_ARG_ENABLE(directfb, [ --enable-directfb enable the DirectFB r
if test "x$have_evas_directfb" = "xyes"; then
PKG_CHECK_MODULES(DIRECTFB, directfb >= 0.9.16,
[
AM_CONDITIONAL(BUILD_ENGINE_DIRECTFB, true)
AC_DEFINE(BUILD_ENGINE_DIRECTFB, 1, [DirectFB Rendering Backend])
ENGINE_DIRECTFB_PRG="evas_directfb_test evas_directfb_window"
], [
AM_CONDITIONAL(BUILD_ENGINE_DIRECTFB, false)
AC_MSG_RESULT(disabling directfb engine)
have_evas_directfb="no"
]
)
else
AM_CONDITIONAL(BUILD_ENGINE_DIRECTFB, false)
fi
AM_CONDITIONAL(BUILD_ENGINE_DIRECTFB, test "x$have_evas_directfb" = "xyes")
#######################################
## Check if we should build the fb engine
@ -552,7 +544,6 @@ if test "x$have_evas_xrender_x11" = "xyes"; then
[
AC_CHECK_HEADER(X11/extensions/Xrender.h,
[
AM_CONDITIONAL(BUILD_ENGINE_XRENDER_X11, true)
AC_DEFINE(BUILD_ENGINE_XRENDER_X11, 1, [XRender X11 Rendering Backend])
x_dir=${x_dir:-/usr/X11R6}
x_cflags=${x_cflags:--I${x_includes:-$x_dir/include}}
@ -560,21 +551,64 @@ if test "x$have_evas_xrender_x11" = "xyes"; then
ENGINE_XRENDER_X11_PRG="evas_xrender_x11_test"
],
[
AM_CONDITIONAL(BUILD_ENGINE_XRENDER_X11, false)
AC_MSG_RESULT(disabling xrender X11 engine)
have_evas_xrender_x11="no"
]
)
],
[
AM_CONDITIONAL(BUILD_ENGINE_XRENDER_X11, false)
AC_MSG_RESULT(disabling xrender X11 engine)
have_evas_xrender_x11="no"
]
)
else
AM_CONDITIONAL(BUILD_ENGINE_XRENDER_X11, false)
fi
AM_CONDITIONAL(BUILD_ENGINE_XRENDER_X11, test "x$have_evas_xrender_x11" = "xyes")
#######################################
## Check if we should build the xrender_xcb engine
have_evas_xrender_xcb="no";
ENGINE_XRENDER_XCB_PRG="";
## Automatic check...
PKG_CHECK_MODULES(
XCB,
xcb xcb-image xcb-icccm,
[AC_CHECK_HEADER(
X11/X.h,
[have_evas_xrender_xcb="yes"],
[have_evas_xrender_xcb="no"])],
[ have_evas_xrender_xcb="no" ])
## manually disable xcb engine by default - not auto detected.
have_evas_xrender_xcb="no"
## Manual override
AC_MSG_CHECKING(whether xrender xcb backend is to be built)
AC_ARG_ENABLE(xrender-xcb, [ --enable-xrender-xcb enable the Xrender XCB rendering backend], [
if test x"$enableval" = x"yes" ; then
AC_MSG_RESULT(yes)
have_evas_xrender_xcb="yes"
else
AC_MSG_RESULT(no)
have_evas_xrender_xcb="no"
fi
], [
AC_MSG_RESULT($have_evas_xrender_xcb)
]
)
if test "x$have_evas_xrender_xcb" = "xyes"; then
AC_PATH_XTRA
PKG_CHECK_MODULES(
XCB,
xcb xcb-image xcb-icccm,
[AC_DEFINE(BUILD_ENGINE_XRENDER_XCB, 1, [Xrender XCB Rendering Backend])
xcb_cflags=$XCB_CFLAGS
xcb_libs=$XCB_LIBS
ENGINE_XRENDER_XCB_PRG="evas_xrender_xcb_test"],
[AC_MSG_RESULT(disabling xrender XCB engine)
have_evas_xrender_xcb="no"])
fi
AM_CONDITIONAL(BUILD_ENGINE_XRENDER_XCB, test "x$have_evas_xrender_xcb" = "xyes")
#####################################################################
@ -1616,6 +1650,7 @@ AC_SUBST(ENGINE_SOFTWARE_QTOPIA_PRG)
AC_SUBST(ENGINE_GL_X11_PRG)
AC_SUBST(ENGINE_CAIRO_X11_PRG)
AC_SUBST(ENGINE_XRENDER_X11_PRG)
AC_SUBST(ENGINE_XRENDER_XCB_PRG)
AC_SUBST(altivec_cflags)
@ -1651,6 +1686,7 @@ src/modules/engines/gl_x11/Makefile
src/modules/engines/cairo_common/Makefile
src/modules/engines/cairo_x11/Makefile
src/modules/engines/xrender_x11/Makefile
src/modules/engines/xrender_xcb/Makefile
src/modules/loaders/Makefile
src/modules/loaders/edb/Makefile
src/modules/loaders/eet/Makefile
@ -1698,6 +1734,7 @@ echo " DirectFB................: $have_evas_directfb"
echo " OpenGL X11..............: $have_evas_gl_x11"
echo " Cairo X11...............: $have_evas_cairo_x11"
echo " XRender X11.............: $have_evas_xrender_x11"
echo " XRender Xcb.............: $have_evas_xrender_xcb"
# FIXME: opengl engine needs to be fixed and tested lots for all drivers
# FIXME: xrender engine to be written
echo

View File

@ -23,7 +23,8 @@ bin_PROGRAMS = \
@ENGINE_SOFTWARE_QTOPIA_PRG@ \
@ENGINE_GL_X11_PRG@ \
@ENGINE_CAIRO_X11_PRG@ \
@ENGINE_XRENDER_X11_PRG@
@ENGINE_XRENDER_X11_PRG@ \
@ENGINE_XRENDER_XCB_PRG@
EXTRA_PROGRAMS = \
evas_software_x11_test \
@ -39,7 +40,8 @@ evas_buffer_test \
evas_software_qtopia_test \
evas_gl_x11_test \
evas_cairo_x11_test \
evas_xrender_x11_test
evas_xrender_x11_test \
evas_xrender_xcb_test
SUBDIRS = evas_software_win32
@ -119,6 +121,11 @@ evas_xrender_x11_test_LDADD = $(top_builddir)/src/lib/libevas.la -lm @x_libs@
evas_xrender_x11_test_CFLAGS = $(CFLAGS) @x_cflags@
evas_xrender_x11_test_DEPENDENCIES = $(top_builddir)/src/lib/libevas.la
evas_xrender_xcb_test_SOURCES = evas_test_main.h evas_test_main.c evas_xrender_xcb_main.c
evas_xrender_xcb_test_LDADD = $(top_builddir)/src/lib/libevas.la -lm @XCB_LIBS@
evas_xrender_xcb_test_CFLAGS = $(CFLAGS) @XCB_CFLAGS@
evas_xrender_xcb_test_DEPENDENCIES = $(top_builddir)/src/lib/libevas.la
EXTRA_DIST = evas_software_qtopia_main.h evas_software_qtopia_main.cpp
# moc_evas_software_qtopia_main.cpp

View File

@ -69,8 +69,8 @@ main(int argc, char **argv)
{
int pause_me = 0;
XCBConnection *conn;
XCBDRAWABLE win;
XCBSCREEN *screen;
XCBDRAWABLE win;
XCBGenericEvent *e;
CARD32 mask;
CARD32 value[6];

View File

@ -0,0 +1,238 @@
#include "evas_test_main.h"
#include <unistd.h>
#include <X11/XCB/xcb.h>
#include "Evas.h"
#include "Evas_Engine_XRender_Xcb.h"
XCBSCREEN *
get_screen (XCBConnection *c,
int screen)
{
XCBSCREENIter iter;
iter = XCBConnSetupSuccessRepRootsIter (XCBGetSetup (c));
for (; iter.rem; --screen, XCBSCREENNext (&iter))
if (screen == 0)
return iter.data;
return NULL;
}
int
get_depth(XCBConnection *conn,
XCBSCREEN *root)
{
XCBDRAWABLE drawable;
XCBGetGeometryRep *geom;
int depth;
drawable.window = root->root;
geom = XCBGetGeometryReply (conn, XCBGetGeometry(conn, drawable), 0);
if(!geom)
{
perror ("GetGeometry(root) failed");
exit (0);
}
depth = geom->depth;
free (geom);
return depth;
}
static void title_set (XCBConnection *conn, XCBWINDOW window, const char *title)
{
XCBInternAtomRep *rep;
XCBATOM encoding;
char *atom_name;
/* encoding */
atom_name = "UTF8_STRING";
rep = XCBInternAtomReply (conn,
XCBInternAtom (conn,
0,
strlen (atom_name),
atom_name),
NULL);
encoding = rep->atom;
free (rep);
/* ICCCM */
/* SetWMName (f->xcb.c, f->xcb.draw.window, encoding, strlen (title), title); */
/* NETWM */
atom_name = "_NET_WM_NAME";
rep = XCBInternAtomReply (conn,
XCBInternAtom (conn,
0,
strlen (atom_name),
atom_name),
NULL);
XCBChangeProperty(conn, PropModeReplace,
window,
rep->atom, encoding, 8, strlen (title), title);
free (rep);
}
int
main(int argc, char **argv)
{
int pause_me = 0;
XCBConnection *conn;
XCBSCREEN *screen;
XCBDRAWABLE win;
XCBGenericEvent *e;
CARD32 mask;
CARD32 value[6];
int screen_nbr;
conn = XCBConnect (NULL, &screen_nbr);
if (!conn)
{
printf("Error: cannot open a connection.\n");
exit(-1);
}
screen = get_screen (conn, screen_nbr);
mask =
XCBCWBackingStore | XCBCWColormap |
XCBCWBackPixmap | XCBCWBorderPixel |
XCBCWBitGravity | XCBCWEventMask;
value[0] = None;
value[1] = 0;
value[2] = ForgetGravity;
value[3] = NotUseful;
value[4] = ExposureMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask;
value[5] = screen->default_colormap.xid;
win.window = XCBWINDOWNew(conn);
XCBCreateWindow (conn,
get_depth(conn, screen),
win.window, screen->root,
0, 0,
win_w, win_h,
0,
InputOutput,
screen->root_visual,
mask, value);
title_set (conn, win.window, "Evas XRender Xcb Test");
#if 0
szhints.flags = PMinSize | PMaxSize | PSize | USSize;
szhints.min_width = szhints.max_width = win_w;
szhints.min_height = szhints.max_height = win_h;
XSetWMNormalHints(disp, win, &szhints);
#endif
XCBMapWindow (conn, win.window);
XCBSync(conn, 0);
/* test evas_free.... :) */
evas_init();
evas = evas_new();
evas_output_method_set(evas, evas_render_method_lookup("xrender_xcb"));
evas_output_size_set(evas, win_w, win_h);
evas_output_viewport_set(evas, 0, 0, win_w, win_h);
{
Evas_Engine_Info_XRender_Xcb *einfo;
einfo = (Evas_Engine_Info_XRender_Xcb *) evas_engine_info_get(evas);
/* the following is specific to the engine */
einfo->info.conn = conn;
einfo->info.visual = screen->root_visual;
einfo->info.drawable = win;
evas_engine_info_set(evas, (Evas_Engine_Info *) einfo);
}
setup();
orig_start_time = start_time = get_time();
while (1)
{
e = XCBPollForEvent(conn, NULL);
if (e) {
switch (e->response_type)
{
case XCBButtonPress: {
XCBButtonPressEvent *ev = (XCBButtonPressEvent *)e;
if (ev->detail.id == 3)
{
setdown();
evas_free(evas);
free(e);
XCBDisconnect(conn);
evas_shutdown();
exit(0);
}
#if 0
if (!pause_me)
pause_me = 1;
else if (pause_me == 1)
pause_me = 2;
else
pause_me = 1;
#endif
evas_event_feed_mouse_move(evas, ev->event_x, ev->event_y, 0, NULL);
evas_event_feed_mouse_down(evas, ev->state, EVAS_BUTTON_NONE, 0, NULL);
break;
}
case XCBButtonRelease: {
XCBButtonReleaseEvent *ev = (XCBButtonReleaseEvent *)e;
evas_event_feed_mouse_move(evas, ev->event_x, ev->event_y, 0, NULL);
evas_event_feed_mouse_up(evas, ev->state, EVAS_BUTTON_NONE, 0, NULL);
break;
}
case XCBMotionNotify: {
XCBMotionNotifyEvent *ev = (XCBMotionNotifyEvent *)e;
evas_event_feed_mouse_move(evas, ev->event_x, ev->event_y, 0, NULL);
break;
}
case Expose: {
XCBExposeEvent *ev = (XCBExposeEvent *)e;
evas_damage_rectangle_add(evas,
ev->x,
ev->y,
ev->width,
ev->height);
break;
}
case ConfigureNotify: {
XCBConfigureNotifyEvent *ev = (XCBConfigureNotifyEvent *)e;
evas_output_size_set(evas,
ev->width,
ev->height);
break;
default:
break;
}
}
free (e);
}
if (!(pause_me == 1))
{
loop();
evas_render(evas);
XCBFlush(conn);
}
if (pause_me == 2)
usleep(100000);
}
setdown();
evas_free(evas);
XCBDisconnect(conn);
evas_shutdown();
return 0;
}

View File

@ -690,6 +690,9 @@ evas_render_method_list(void)
#ifdef BUILD_ENGINE_SOFTWARE_XCB
methods = evas_list_append(methods, strdup("software_xcb"));
#endif
#ifdef BUILD_ENGINE_XRENDER_XCB
methods = evas_list_append(methods, strdup("xrender_xcb"));
#endif
#ifdef BUILD_ENGINE_GL_X11
methods = evas_list_append(methods, strdup("gl_x11"));
#endif

View File

@ -13,6 +13,7 @@ evas_engine_api_software_win32_gdi.h \
evas_engine_api_software_x11.h \
evas_engine_api_software_xcb.h \
evas_engine_api_xrender_x11.h \
evas_engine_api_xrender_xcb.h \
evas_gl_common.h \
evas_macros.h \
evas_mmx.h \

View File

@ -0,0 +1,7 @@
#ifndef EVAS_ENGINE_XRENDER_XCB_H
#define EVAS_ENGINE_XRENDER_XCB_H
#include <X11/XCB/xcb.h>
extern Evas_Func evas_engine_xrender_xcb_func;
#endif

View File

@ -13,7 +13,8 @@ software_qtopia \
software_win32_gdi \
software_x11 \
software_xcb \
xrender_x11
xrender_x11 \
xrender_xcb
# FIXME: these should go into engine subdirs so engines are much more fully
# self-contained.
@ -41,7 +42,17 @@ else
ENGINE_CAIRO_X11_INC =
endif
if BUILD_ENGINE_XRENDER_XCB
ENGINE_XRENDER_XCB = engines/xrender_xcb/libevas_engine_xrender_xcb.la
ENGINE_XRENDER_XCB_INC = Evas_Engine_XRender_Xcb.h
else
ENGINE_XRENDER_XCB =
ENGINE_XRENDER_XCB_INC =
endif
include_HEADERS = \
$(ENGINE_DIRECTFB_INC) \
$(ENGINE_GL_X11_INC) \
$(ENGINE_XRENDER_XCB_INC)
$(ENGINE_CAIRO_X11_INC)

View File

@ -83,7 +83,7 @@ X_Output_Buffer *
evas_software_x11_x_output_buffer_new(Display *d, Visual *v, int depth, int w, int h, int try_shm, void *data)
{
X_Output_Buffer *xob;
char *tmp = (char *)malloc (2);
xob = calloc(1, sizeof(X_Output_Buffer));
if (!xob) return NULL;

View File

@ -766,7 +766,7 @@ Evas_Module_Api evas_modapi =
{
EVAS_MODULE_API_VERSION,
EVAS_MODULE_TYPE_ENGINE,
"xrender",
"xrender_x11",
"none"
};

View File

@ -0,0 +1,45 @@
## Process this file with automake to produce Makefile.in
AUTOMAKE_OPTIONS = 1.4 foreign
# A list of all the files in the current directory which can be regenerated
MAINTAINERCLEANFILES = Makefile.in
INCLUDES = -I. \
-I$(top_srcdir)/src/lib \
-I$(top_srcdir)/src/lib/include \
-I$(top_srcdir)/src/modules/engines \
@FREETYPE_CFLAGS@ @XCB_CFLAGS@
if BUILD_ENGINE_XRENDER_XCB
pkgdir = $(libdir)/evas/modules/engines/xrender_xcb/$(MODULE_ARCH)
pkg_LTLIBRARIES = module.la
module_la_SOURCES = \
evas_engine.h \
evas_engine.c \
evas_engine_xrender.c \
evas_engine_image.c \
evas_engine_font.c \
evas_engine_gradient.c \
evas_engine_ximage.c
module_la_LIBADD = $(top_builddir)/src/lib/libevas.la @XCB_LIBS@
module_la_LDFLAGS = -module -avoid-version \
-L$(top_builddir)/src/lib -L$(top_builddir)/src/lib/.libs
module_la_DEPENDENCIES = \
$(top_builddir)/config.h
endif
EXTRA_DIST = \
evas_engine.h \
evas_engine.c \
evas_engine_ximage.c \
evas_engine_xrender.c \
evas_engine_image.c \
evas_engine_font.c \
evas_engine_gradient.c

View File

@ -0,0 +1,779 @@
#include "evas_common.h"
#include "evas_private.h"
#include "evas_engine.h"
#include "Evas_Engine_XRender_Xcb.h"
/* function tables - filled in later (func and parent func) */
static Evas_Func func, pfunc;
/* engine struct data */
typedef struct _Render_Engine Render_Engine;
typedef struct _Render_Engine_Update Render_Engine_Update;
struct _Render_Engine_Update
{
int x;
int y;
int w;
int h;
XCBrender_Surface *surface;
};
struct _Render_Engine
{
XCBConnection *conn;
XCBVISUALID vis;
XCBDRAWABLE win;
XCBPIXMAP mask;
unsigned char destination_alpha : 1;
XCBimage_Info *xcbinf;
XCBrender_Surface *output;
XCBrender_Surface *mask_output;
Tilebuf *tb;
Tilebuf_Rect *rects;
Evas_Object_List *cur_rect;
int end : 1;
Evas_List *updates;
};
/* prototypes we will use here */
static void *eng_info(Evas *e);
static void eng_info_free(Evas *e, void *info);
static void eng_setup(Evas *e, void *info);
static void eng_output_free(void *data);
static void eng_output_resize(void *data, int w, int h);
static void eng_output_tile_size_set(void *data, int w, int h);
static void eng_output_redraws_rect_add(void *data, int x, int y, int w, int h);
static void eng_output_redraws_rect_del(void *data, int x, int y, int w, int h);
static void eng_output_redraws_clear(void *data);
static void *eng_output_redraws_next_update_get(void *data, int *x, int *y, int *w, int *h, int *cx, int *cy, int *cw, int *ch);
static void eng_output_redraws_next_update_push(void *data, void *surface, int x, int y, int w, int h);
static void eng_output_flush(void *data);
static void eng_rectangle_draw(void *data, void *context, void *surface, int x, int y, int w, int h);
static void eng_line_draw(void *data, void *context, void *surface, int x1, int y1, int x2, int y2);
static void eng_polygon_draw(void *data, void *context, void *surface, void *polygon);
static void *eng_gradient_color_add(void *data, void *context, void *gradient, int r, int g, int b, int a, int distance);
static void *eng_gradient_colors_clear(void *data, void *context, void *gradient);
static void eng_gradient_free(void *data, void *gradient);
static void eng_gradient_fill_set(void *data, void *gradient, int x, int y, int w, int h);
static void eng_gradient_type_set(void *data, void *gradient, char *name);
static void eng_gradient_type_params_set(void *data, void *gradient, char *params);
static void *eng_gradient_geometry_init(void *data, void *gradient, int spread);
static int eng_gradient_alpha_get(void *data, void *gradient, int spread);
static void eng_gradient_map(void *data, void *context, void *gradient, int spread);
static void eng_gradient_draw(void *data, void *context, void *surface, void *gradient, int x, int y, int w, int h, double angle, int spread);
static void *eng_image_load(void *data, char *file, char *key, int *error);
static void *eng_image_new_from_data(void *data, int w, int h, DATA32 *image_data);
static void *eng_image_new_from_copied_data(void *data, int w, int h, DATA32 *image_data);
static void eng_image_free(void *data, void *image);
static void eng_image_size_get(void *data, void *image, int *w, int *h);
static void *eng_image_size_set(void *data, void *image, int w, int h);
static void *eng_image_dirty_region(void *data, void *image, int x, int y, int w, int h);
static void *eng_image_data_get(void *data, void *image, int to_write, DATA32 **image_data);
static void *eng_image_data_put(void *data, void *image, DATA32 *image_data);
static void *eng_image_alpha_set(void *data, void *image, int has_alpha);
static int eng_image_alpha_get(void *data, void *image);
static void eng_image_draw(void *data, void *context, void *surface, void *image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int dst_w, int dst_h, int smooth);
static char *eng_image_comment_get(void *data, void *image, char *key);
static char *eng_image_format_get(void *data, void *image);
static void eng_image_cache_flush(void *data);
static void eng_image_cache_set(void *data, int bytes);
static int eng_image_cache_get(void *data);
static void eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w, int h, int ow, int oh, char *text);
/* internal engine routines */
/* engine api this module provides */
static void *
eng_info(Evas *e)
{
Evas_Engine_Info_XRender_Xcb *info;
info = calloc(1, sizeof(Evas_Engine_Info_XRender_Xcb));
if (!info) return NULL;
info->magic.magic = rand();
return info;
e = NULL;
}
static void
eng_info_free(Evas *e, void *info)
{
Evas_Engine_Info_XRender_Xcb *in;
in = (Evas_Engine_Info_XRender_Xcb *)info;
free(in);
}
static void
eng_setup(Evas *e, void *in)
{
Render_Engine *re;
Evas_Engine_Info_XRender_Xcb *info;
info = (Evas_Engine_Info_XRender_Xcb *)in;
if (!e->engine.data.output)
{
re = calloc(1, sizeof(Render_Engine));
evas_common_cpu_init();
evas_common_blend_init();
evas_common_image_init();
evas_common_convert_init();
evas_common_scale_init();
evas_common_rectangle_init();
evas_common_gradient_init();
evas_common_polygon_init();
evas_common_line_init();
evas_common_font_init();
evas_common_draw_init();
evas_common_tilebuf_init();
re->tb = evas_common_tilebuf_new(e->output.w, e->output.h);
if (re->tb)
evas_common_tilebuf_set_tile_size(re->tb, TILESIZE, TILESIZE);
e->engine.data.output = re;
}
re = e->engine.data.output;
if (!re) return;
if (!e->engine.data.context) e->engine.data.context = e->engine.func->context_new(e->engine.data.output);
re->conn = info->info.conn;
re->vis = info->info.visual;
re->win = info->info.drawable;
re->mask = info->info.mask;
re->destination_alpha = info->info.destination_alpha;
if (re->xcbinf) _xr_image_info_free(re->xcbinf);
re->xcbinf = _xr_image_info_get(re->conn, re->win, re->vis);
if (re->output) _xr_render_surface_free(re->output);
re->output = _xr_render_surface_adopt(re->xcbinf, re->win, e->output.w, e->output.h, 0);
if (re->mask.xid)
{
XCBDRAWABLE draw;
if (re->mask_output) _xr_render_surface_free(re->mask_output);
draw.pixmap = re->mask;
re->mask_output = _xr_render_surface_format_adopt(re->xcbinf, draw,
e->output.w, e->output.h,
re->xcbinf->fmt1, 1);
}
else
re->mask_output = NULL;
}
static void
eng_output_free(void *data)
{
Render_Engine *re;
re = (Render_Engine *)data;
evas_common_font_shutdown();
evas_common_image_shutdown();
while (re->updates)
{
Render_Engine_Update *reu;
reu = re->updates->data;
re->updates = evas_list_remove_list(re->updates, re->updates);
_xr_render_surface_free(reu->surface);
free(reu);
}
if (re->tb) evas_common_tilebuf_free(re->tb);
if (re->output) _xr_render_surface_free(re->output);
if (re->mask_output) _xr_render_surface_free(re->mask_output);
if (re->rects) evas_common_tilebuf_free_render_rects(re->rects);
if (re->xcbinf) _xr_image_info_free(re->xcbinf);
free(re);
}
static void
eng_output_resize(void *data, int w, int h)
{
Render_Engine *re;
re = (Render_Engine *)data;
if (re->output)
{
if ((re->output->w == w) && (re->output->h ==h)) return;
if (re->output) _xr_render_surface_free(re->output);
}
re->output = _xr_render_surface_adopt(re->xcbinf, re->win, w, h, 0);
if (re->mask_output)
{
XCBDRAWABLE draw;
if (re->mask_output) _xr_render_surface_free(re->mask_output);
draw.pixmap = re->mask;
re->mask_output = _xr_render_surface_format_adopt(re->xcbinf, draw,
w, h,
re->xcbinf->fmt1, 1);
}
evas_common_tilebuf_free(re->tb);
re->tb = evas_common_tilebuf_new(w, h);
if (re->tb) evas_common_tilebuf_set_tile_size(re->tb, TILESIZE, TILESIZE);
}
static void
eng_output_tile_size_set(void *data, int w, int h)
{
Render_Engine *re;
re = (Render_Engine *)data;
evas_common_tilebuf_set_tile_size(re->tb, w, h);
}
static void
eng_output_redraws_rect_add(void *data, int x, int y, int w, int h)
{
Render_Engine *re;
re = (Render_Engine *)data;
evas_common_tilebuf_add_redraw(re->tb, x, y, w, h);
}
static void
eng_output_redraws_rect_del(void *data, int x, int y, int w, int h)
{
Render_Engine *re;
re = (Render_Engine *)data;
evas_common_tilebuf_del_redraw(re->tb, x, y, w, h);
}
static void
eng_output_redraws_clear(void *data)
{
Render_Engine *re;
re = (Render_Engine *)data;
evas_common_tilebuf_clear(re->tb);
}
static void *
eng_output_redraws_next_update_get(void *data, int *x, int *y, int *w, int *h, int *cx, int *cy, int *cw, int *ch)
{
Render_Engine *re;
Tilebuf_Rect *rect;
int ux, uy, uw, uh;
re = (Render_Engine *)data;
if (re->end)
{
re->end = 0;
return NULL;
}
if (!re->rects)
{
re->rects = evas_common_tilebuf_get_render_rects(re->tb);
re->cur_rect = (Evas_Object_List *)re->rects;
}
if (!re->cur_rect) return NULL;
rect = (Tilebuf_Rect *)re->cur_rect;
ux = rect->x; uy = rect->y; uw = rect->w; uh = rect->h;
re->cur_rect = re->cur_rect->next;
if (!re->cur_rect)
{
evas_common_tilebuf_free_render_rects(re->rects);
re->rects = NULL;
re->end = 1;
}
*x = ux; *y = uy; *w = uw; *h = uh;
*cx = 0; *cy = 0; *cw = uw; *ch = uh;
if ((re->destination_alpha) || (re->mask.xid))
{
XCBrender_Surface *surface;
surface = _xr_render_surface_new(re->xcbinf, uw, uh, re->xcbinf->fmt32, 1);
_xr_render_surface_solid_rectangle_set(surface, 0, 0, 0, 0, 0, 0, uw, uh);
return surface;
}
return _xr_render_surface_new(re->xcbinf, uw, uh, re->xcbinf->fmt24, 0);
}
static void
eng_output_redraws_next_update_push(void *data, void *surface, int x, int y, int w, int h)
{
Render_Engine *re;
Render_Engine_Update *reu;
re = (Render_Engine *)data;
reu = malloc(sizeof(Render_Engine_Update));
if (!reu) return;
reu->x = x;
reu->y = y;
reu->w = w;
reu->h = h;
reu->surface = (XCBrender_Surface *)surface;
re->updates = evas_list_append(re->updates, reu);
}
static void
eng_output_flush(void *data)
{
Render_Engine *re;
re = (Render_Engine *)data;
while (re->updates)
{
Render_Engine_Update *reu;
reu = re->updates->data;
re->updates = evas_list_remove_list(re->updates, re->updates);
if (re->mask_output)
{
XCBrender_Surface *tsurf;
_xr_render_surface_copy(reu->surface, re->output, 0, 0,
reu->x, reu->y, reu->w, reu->h);
tsurf = _xr_render_surface_new(re->xcbinf, reu->w, reu->h, re->xcbinf->fmt1, 1);
if (tsurf)
{
_xr_render_surface_copy(reu->surface, tsurf, 0, 0,
0, 0, reu->w, reu->h);
_xr_render_surface_copy(tsurf, re->mask_output, 0, 0,
reu->x, reu->y, reu->w, reu->h);
_xr_render_surface_free(tsurf);
}
}
else
{
_xr_render_surface_copy(reu->surface, re->output, 0, 0,
reu->x, reu->y, reu->w, reu->h);
}
_xr_render_surface_free(reu->surface);
free(reu);
}
XCBSync(re->conn, 0);
_xr_image_info_pool_flush(re->xcbinf, 0, 0);
}
static void
eng_rectangle_draw(void *data, void *context, void *surface, int x, int y, int w, int h)
{
_xr_render_surface_rectangle_draw((XCBrender_Surface *)surface,
(RGBA_Draw_Context *)context,
x, y, w, h);
}
static void
eng_line_draw(void *data, void *context, void *surface, int x1, int y1, int x2, int y2)
{
_xr_render_surface_line_draw((XCBrender_Surface *)surface, (RGBA_Draw_Context *)context, x1, y1, x2, y2);
}
static void
eng_polygon_draw(void *data, void *context, void *surface, void *polygon)
{
_xre_poly_draw((XCBrender_Surface *)surface, (RGBA_Draw_Context *)context, (RGBA_Polygon_Point *)polygon);
}
static void *
eng_gradient_color_add(void *data, void *context, void *gradient, int r, int g, int b, int a, int distance)
{
Render_Engine *re;
re = (Render_Engine *)data;
return _xre_gradient_color_add(re->xcbinf, (XR_Gradient *)gradient, r, g, b, a, distance);
}
static void *
eng_gradient_colors_clear(void *data, void *context, void *gradient)
{
return _xre_gradient_colors_clear((XR_Gradient *)gradient);
}
static void
eng_gradient_free(void *data, void *gradient)
{
_xre_gradient_free((XR_Gradient *)gradient);
}
static void
eng_gradient_fill_set(void *data, void *gradient, int x, int y, int w, int h)
{
_xre_gradient_fill_set((XR_Gradient *)gradient, x, y, w, h);
}
static void
eng_gradient_type_set(void *data, void *gradient, char *name)
{
_xre_gradient_type_set((XR_Gradient *)gradient, name);
}
static void
eng_gradient_type_params_set(void *data, void *gradient, char *params)
{
_xre_gradient_type_params_set((XR_Gradient *)gradient, params);
}
static void *
eng_gradient_geometry_init(void *data, void *gradient, int spread)
{
return _xre_gradient_geometry_init((XR_Gradient *)gradient, spread);
}
static int
eng_gradient_alpha_get(void *data, void *gradient, int spread)
{
return _xre_gradient_alpha_get((XR_Gradient *)gradient, spread);
}
static void
eng_gradient_map(void *data, void *context, void *gradient, int spread)
{
_xre_gradient_map((RGBA_Draw_Context *)context, (XR_Gradient *)gradient, spread);
}
static void
eng_gradient_draw(void *data, void *context, void *surface, void *gradient, int x, int y, int w, int h, double angle, int spread)
{
_xre_gradient_draw((XCBrender_Surface *)surface,
(RGBA_Draw_Context *)context,
(XR_Gradient *)gradient, x, y, w, h, angle, spread);
}
static void *
eng_image_load(void *data, char *file, char *key, int *error)
{
Render_Engine *re;
XR_Image *im;
re = (Render_Engine *)data;
*error = 0;
im = _xre_image_load(re->xcbinf, file, key);
return im;
}
static void *
eng_image_new_from_data(void *data, int w, int h, DATA32 *image_data)
{
Render_Engine *re;
XR_Image *im;
re = (Render_Engine *)data;
im = _xre_image_new_from_data(re->xcbinf, w, h, image_data);
return im;
}
static void *
eng_image_new_from_copied_data(void *data, int w, int h, DATA32 *image_data)
{
Render_Engine *re;
XR_Image *im;
re = (Render_Engine *)data;
im = _xre_image_new_from_copied_data(re->xcbinf, w, h, image_data);
return im;
}
static void
eng_image_free(void *data, void *image)
{
if (!image) return;
_xre_image_free((XR_Image *)image);
}
static void
eng_image_size_get(void *data, void *image, int *w, int *h)
{
if (!image) return;
if (w) *w = ((XR_Image *)image)->w;
if (h) *h = ((XR_Image *)image)->h;
}
static void *
eng_image_size_set(void *data, void *image, int w, int h)
{
if (!image) return image;
if ((w <= 0) || (h <= 0))
{
_xre_image_free((XR_Image *)image);
return NULL;
}
if (((XR_Image *)image)->references > 1)
{
XR_Image *old_image;
old_image = (XR_Image *)image;
image = _xre_image_copy((XR_Image *)old_image);
if (image)
{
((XR_Image *)image)->alpha = old_image->alpha;
_xre_image_free(old_image);
}
else
image = old_image;
}
else
_xre_image_dirty((XR_Image *)image);
_xre_image_resize((XR_Image *)image, w, h);
return image;
}
static void *
eng_image_dirty_region(void *data, void *image, int x, int y, int w, int h)
{
if (!image) return image;
_xre_image_dirty((XR_Image *)image);
_xre_image_region_dirty((XR_Image *)image, x, y, w, h);
return image;
}
static void *
eng_image_data_get(void *data, void *image, int to_write, DATA32 **image_data)
{
if (!image) return image;
if (to_write)
{
if (((XR_Image *)image)->references > 1)
{
XR_Image *old_image;
old_image = (XR_Image *)image;
image = _xre_image_copy((XR_Image *)old_image);
if (image)
{
((XR_Image *)image)->alpha = old_image->alpha;
_xre_image_free(old_image);
}
else
image = old_image;
}
else
_xre_image_dirty((XR_Image *)image);
}
if (image_data) *image_data = _xre_image_data_get((XR_Image *)image);
return image;
}
static void *
eng_image_data_put(void *data, void *image, DATA32 *image_data)
{
if (!image) return image;
if (_xre_image_data_get((XR_Image *)image) != image_data)
{
XR_Image *old_image;
old_image = (XR_Image *)image;
image = _xre_image_data_find(image_data);
if (image != old_image)
{
if (!image)
{
image = _xre_image_new_from_data(old_image->xcbinf, old_image->w, old_image->h, image_data);
if (image)
{
((XR_Image *)image)->alpha = old_image->alpha;
_xre_image_free(old_image);
}
else
image = old_image;
}
else
{
_xre_image_free(old_image);
}
}
else
{
_xre_image_free(image);
}
}
return image;
}
static void *
eng_image_alpha_set(void *data, void *image, int has_alpha)
{
if (!image) return image;
if (((((XR_Image *)image)->alpha) && (has_alpha)) ||
((!((XR_Image *)image)->alpha) && (!has_alpha)))
return image;
if (((XR_Image *)image)->references > 1)
{
XR_Image *old_image;
old_image = (XR_Image *)image;
image = _xre_image_copy((XR_Image *)old_image);
if (image)
{
((XR_Image *)image)->alpha = old_image->alpha;
_xre_image_free(old_image);
}
else
image = old_image;
}
else
_xre_image_dirty((XR_Image *)image);
_xre_image_alpha_set((XR_Image *)image, has_alpha);
return image;
}
static int
eng_image_alpha_get(void *data, void *image)
{
if (!image) return 0;
return _xre_image_alpha_get((XR_Image *)image);
}
static void
eng_image_draw(void *data, void *context, void *surface, void *image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int dst_w, int dst_h, int smooth)
{
if ((!image) || (!surface)) return;
_xre_image_surface_gen((XR_Image *)image);
if (((XR_Image *)image)->surface)
_xr_render_surface_composite(((XR_Image *)image)->surface,
(XCBrender_Surface *)surface,
(RGBA_Draw_Context *)context,
src_x, src_y, src_w, src_h,
dst_x, dst_y, dst_w, dst_h,
smooth);
}
static char *
eng_image_comment_get(void *data, void *image, char *key)
{
if (!image) return NULL;
return ((XR_Image *)image)->comment;
}
static char *
eng_image_format_get(void *data, void *image)
{
if (!image) return NULL;
return ((XR_Image *)image)->format;
}
static void
eng_image_cache_flush(void *data)
{
int tmp_size;
pfunc.image_cache_flush(data);
_xre_image_cache_set(0);
_xre_image_cache_set(tmp_size);
}
static void
eng_image_cache_set(void *data, int bytes)
{
pfunc.image_cache_set(data, bytes);
_xre_image_cache_set(bytes);
}
static int
eng_image_cache_get(void *data)
{
return pfunc.image_cache_get(data);
}
static void
eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w, int h, int ow, int oh, char *text)
{
Render_Engine *re;
re = (Render_Engine *)data;
{
static RGBA_Image *im = NULL;
if (!im)
{
im = evas_common_image_new();
im->image = evas_common_image_surface_new(im);
im->image->no_free = 1;
}
im->image->w = ((XCBrender_Surface *)surface)->w;
im->image->h = ((XCBrender_Surface *)surface)->h;
_xr_render_surface_clips_set((XCBrender_Surface *)surface, (RGBA_Draw_Context *)context, x, y, w, h);
im->image->data = surface;
evas_common_draw_context_font_ext_set(context,
re->xcbinf,
_xre_font_surface_new,
_xre_font_surface_free,
_xre_font_surface_draw);
evas_common_font_draw(im, context, font, x, y, text);
evas_common_draw_context_font_ext_set(context,
NULL,
NULL,
NULL,
NULL);
evas_common_cpu_end_opt();
}
}
/* module advertising code */
int
module_open(Evas_Module *em)
{
if (!em) return 0;
/* get whatever engine module we inherit from */
if (!_evas_module_engine_inherit(&pfunc, "software_generic")) return 0;
/* store it for later use */
func = pfunc;
/* now to override methods */
#define ORD(f) EVAS_API_OVERRIDE(f, &func, eng_)
ORD(info);
ORD(info_free);
ORD(setup);
ORD(output_free);
ORD(output_resize);
ORD(output_tile_size_set);
ORD(output_redraws_rect_add);
ORD(output_redraws_rect_del);
ORD(output_redraws_clear);
ORD(output_redraws_next_update_get);
ORD(output_redraws_next_update_push);
ORD(output_flush);
ORD(rectangle_draw);
ORD(line_draw);
ORD(polygon_draw);
ORD(gradient_color_add);
ORD(gradient_colors_clear);
ORD(gradient_free);
ORD(gradient_fill_set);
ORD(gradient_type_set);
ORD(gradient_type_params_set);
ORD(gradient_geometry_init);
ORD(gradient_alpha_get);
ORD(gradient_map);
ORD(gradient_draw);
ORD(image_load);
ORD(image_new_from_data);
ORD(image_new_from_copied_data);
ORD(image_free);
ORD(image_size_get);
ORD(image_size_set);
ORD(image_dirty_region);
ORD(image_data_get);
ORD(image_data_put);
ORD(image_alpha_set);
ORD(image_alpha_get);
ORD(image_draw);
ORD(image_comment_get);
ORD(image_format_get);
ORD(image_cache_flush);
ORD(image_cache_set);
ORD(image_cache_get);
ORD(font_draw);
/* now advertise out own api */
em->functions = (void *)(&func);
return 1;
}
void
module_close(void)
{
}
Evas_Module_Api evas_modapi =
{
EVAS_MODULE_API_VERSION,
EVAS_MODULE_TYPE_ENGINE,
"xrender_xcb",
"none"
};

View File

@ -0,0 +1,210 @@
#ifndef EVAS_ENGINE_H
#define EVAS_ENGINE_H
#include <sys/ipc.h>
#include <sys/shm.h>
#include <X11/XCB/xcb.h>
#include <X11/XCB/shm.h>
#include <X11/XCB/render.h>
#include <X11/XCB/xcb_image.h>
typedef struct _XCBimage_Info XCBimage_Info;
typedef struct _XCBimage_Image XCBimage_Image;
typedef struct _XCBrender_Surface XCBrender_Surface;
struct _XCBimage_Info
{
XCBConnection *conn;
XCBDRAWABLE root;
XCBDRAWABLE draw;
int depth;
XCBVISUALID vis;
int pool_mem;
Evas_List *pool;
unsigned char can_do_shm;
XCBRenderPICTFORMINFO *fmt32;
XCBRenderPICTFORMINFO *fmt24;
XCBRenderPICTFORMINFO *fmt8;
XCBRenderPICTFORMINFO *fmt4;
XCBRenderPICTFORMINFO *fmt1;
unsigned char mul_r;
unsigned char mul_g;
unsigned char mul_b;
unsigned char mul_a;
XCBrender_Surface *mul;
int references;
};
struct _XCBimage_Image
{
XCBimage_Info *xcbinf;
XCBImage *xcbim;
XCBShmSegmentInfo *shm_info;
int w;
int h;
int depth;
int line_bytes;
unsigned char *data;
unsigned char available : 1;
};
struct _XCBrender_Surface
{
XCBimage_Info *xcbinf;
int w;
int h;
int depth;
XCBRenderPICTFORMINFO *fmt;
XCBDRAWABLE draw;
XCBRenderPICTURE pic;
unsigned char alpha : 1;
unsigned char allocated : 1;
};
/* ximage support calls (ximage vs xshmimage, cache etc.) */
XCBimage_Info *_xr_image_info_get(XCBConnection *conn, XCBDRAWABLE draw, XCBVISUALID vis);
void _xr_image_info_free(XCBimage_Info *xcbinf);
void _xr_image_info_pool_flush(XCBimage_Info *xcbinf, int max_num, int max_mem);
XCBimage_Image *_xr_image_new(XCBimage_Info *xcbinf, int w, int h, int depth);
void _xr_image_free(XCBimage_Image *xim);
void _xr_image_put(XCBimage_Image *xim, XCBDRAWABLE draw, int x, int y, int w, int h);
/* xrender support calls */
XCBrender_Surface *_xr_render_surface_new(XCBimage_Info *xcbinf, int w, int h, XCBRenderPICTFORMINFO *fmt, int alpha);
XCBrender_Surface *_xr_render_surface_adopt(XCBimage_Info *xcbinf, XCBDRAWABLE draw, int w, int h, int alpha);
XCBrender_Surface *_xr_render_surface_format_adopt(XCBimage_Info *xcbinf, XCBDRAWABLE draw, int w, int h, XCBRenderPICTFORMINFO *fmt, int alpha);
void _xr_render_surface_free(XCBrender_Surface *rs);
void _xr_render_surface_repeat_set(XCBrender_Surface *rs, int repeat);
void _xr_render_surface_solid_rectangle_set(XCBrender_Surface *rs, int r, int g, int b, int a, int x, int y, int w, int h);
void _xr_render_surface_argb_pixels_fill(XCBrender_Surface *rs, int sw, int sh, void *pixels, int x, int y, int w, int h);
void _xr_render_surface_rgb_pixels_fill(XCBrender_Surface *rs, int sw, int sh, void *pixels, int x, int y, int w, int h);
void _xr_render_surface_clips_set(XCBrender_Surface *rs, RGBA_Draw_Context *dc, int rx, int ry, int rw, int rh);
void _xr_render_surface_composite(XCBrender_Surface *srs, XCBrender_Surface *drs, RGBA_Draw_Context *dc, int sx, int sy, int sw, int sh, int x, int y, int w, int h, int smooth);
void _xr_render_surface_copy(XCBrender_Surface *srs, XCBrender_Surface *drs, int sx, int sy, int x, int y, int w, int h);
void _xr_render_surface_rectangle_draw(XCBrender_Surface *rs, RGBA_Draw_Context *dc, int x, int y, int w, int h);
void _xr_render_surface_line_draw(XCBrender_Surface *rs, RGBA_Draw_Context *dc, int x1, int y1, int x2, int y2);
void _xre_poly_draw(XCBrender_Surface *rs, RGBA_Draw_Context *dc, RGBA_Polygon_Point *points);
typedef struct _XR_Image XR_Image;
struct _XR_Image
{
XCBimage_Info *xcbinf;
char *file;
char *key;
char *fkey;
RGBA_Image *im;
void *data;
int w, h;
XCBrender_Surface *surface;
int references;
char *format;
char *comment;
Tilebuf *updates;
unsigned char alpha : 1;
unsigned char dirty : 1;
unsigned char free_data : 1;
};
XR_Image *_xre_image_load(XCBimage_Info *xcbinf, char *file, char *key);
XR_Image *_xre_image_new_from_data(XCBimage_Info *xcbinf, int w, int h, void *data);
XR_Image *_xre_image_new_from_copied_data(XCBimage_Info *xcbinf, int w, int h, void *data);
XR_Image *_xre_image_new(XCBimage_Info *xcbinf, int w, int h);
void _xre_image_resize(XR_Image *im, int w, int h);
void _xre_image_free(XR_Image *im);
void _xre_image_region_dirty(XR_Image *im, int x, int y, int w, int h);
void _xre_image_dirty(XR_Image *im);
XR_Image *_xre_image_copy(XR_Image *im);
void *_xre_image_data_get(XR_Image *im);
XR_Image *_xre_image_data_find(void *data);
void _xre_image_data_put(XR_Image *im, void *data);
void _xre_image_alpha_set(XR_Image *im, int alpha);
int _xre_image_alpha_get(XR_Image *im);
void _xre_image_surface_gen(XR_Image *im);
void _xre_image_cache_set(int size);
int _xre_image_cache_get(void);
typedef struct _XR_Font_Surface XR_Font_Surface;
struct _XR_Font_Surface
{
XCBimage_Info *xcbinf;
RGBA_Font_Glyph *fg;
int w;
int h;
XCBDRAWABLE draw;
XCBRenderPICTURE pic;
};
XR_Font_Surface *_xre_font_surface_new (XCBimage_Info *xcbinf,
RGBA_Font_Glyph *fg);
void _xre_font_surface_free (XR_Font_Surface *fs);
void _xre_font_surface_draw (XCBimage_Info *xcbinf,
RGBA_Image *surface,
RGBA_Draw_Context *dc,
RGBA_Font_Glyph *fg,
int x,
int y);
typedef struct _XR_Gradient XR_Gradient;
struct _XR_Gradient
{
XCBimage_Info *xcbinf;
XCBrender_Surface *surface;
RGBA_Gradient *grad;
double angle;
int spread;
unsigned char changed;
};
/* gradient */
XR_Gradient *_xre_gradient_color_add (XCBimage_Info *xcbinf,
XR_Gradient *gr,
int r,
int g,
int b,
int a,
int distance);
XR_Gradient *_xre_gradient_colors_clear (XR_Gradient *gr);
void _xre_gradient_free (XR_Gradient *gr);
void _xre_gradient_fill_set (XR_Gradient *gr,
int x,
int y,
int w,
int h);
void _xre_gradient_type_set (XR_Gradient *gr,
char *name);
void _xre_gradient_type_params_set (XR_Gradient *gr,
char *params);
void *_xre_gradient_geometry_init (XR_Gradient *gr,
int spread);
int _xre_gradient_alpha_get (XR_Gradient *gr,
int spread);
void _xre_gradient_map (RGBA_Draw_Context *dc,
XR_Gradient *gr,
int spread);
void _xre_gradient_draw (XCBrender_Surface *rs,
RGBA_Draw_Context *dc,
XR_Gradient *gr,
int x,
int y,
int w,
int h,
double angle,
int spread);
#endif

View File

@ -0,0 +1,203 @@
#include "evas_common.h"
#include "evas_private.h"
#include "evas_engine.h"
#include "Evas_Engine_XRender_Xcb.h"
static Evas_Hash *_xr_fg_pool = NULL;
XR_Font_Surface *
_xre_font_surface_new(XCBimage_Info *xcbinf, RGBA_Font_Glyph *fg)
{
char buf[256];
char buf2[256];
XR_Font_Surface *fs;
DATA8 *data;
int w, h, j;
XCBimage_Image *xcim;
Evas_Hash *pool;
CARD32 mask;
CARD32 values[3];
data = fg->glyph_out->bitmap.buffer;
w = fg->glyph_out->bitmap.width;
h = fg->glyph_out->bitmap.rows;
j = fg->glyph_out->bitmap.pitch;
if (j < w) j = w;
if ((w <= 0) || (h <= 0)) return NULL;
if (fg->ext_dat)
{
fs = fg->ext_dat;
if ((fs->xcbinf->conn == xcbinf->conn) &&
(fs->xcbinf->root.window.xid == xcbinf->root.window.xid))
return fs;
snprintf(buf, sizeof(buf), "@%p@/@%lx@", fs->xcbinf->conn, fs->xcbinf->root.window.xid);
pool = evas_hash_find(_xr_fg_pool, buf);
if (pool)
{
snprintf(buf, sizeof(buf), "%p", fg);
fs = evas_hash_find(pool, buf);
if (fs) return fs;
}
}
fs = calloc(1, sizeof(XR_Font_Surface));
if (!fs) return NULL;
fs->xcbinf = xcbinf;
fs->fg = fg;
fs->xcbinf->references++;
fs->w = w;
fs->h = h;
snprintf(buf, sizeof(buf), "@%p@/@%lx@", fs->xcbinf->conn, fs->xcbinf->root.window.xid);
pool = evas_hash_find(_xr_fg_pool, buf);
snprintf(buf2, sizeof(buf2), "%p", fg);
pool = evas_hash_add(pool, buf2, fs);
_xr_fg_pool = evas_hash_add(_xr_fg_pool, buf, pool);
fs->draw.pixmap = XCBPIXMAPNew(xcbinf->conn);
XCBCreatePixmap(xcbinf->conn, xcbinf->fmt8->depth, fs->draw.pixmap, xcbinf->root, w, h);
mask = XCBRenderCPRepeat | XCBRenderCPDither | XCBRenderCPComponentAlpha;
values[0] = 0;
values[1] = 0;
values[2] = 0;
fs->pic = XCBRenderPICTURENew(xcbinf->conn);
XCBRenderCreatePicture(xcbinf->conn, fs->pic, fs->draw, xcbinf->fmt8->id, mask, values);
xcim = _xr_image_new(fs->xcbinf, w, h, xcbinf->fmt8->depth);
if ((fg->glyph_out->bitmap.num_grays == 256) &&
(fg->glyph_out->bitmap.pixel_mode == ft_pixel_mode_grays))
{
int x, y;
DATA8 *p1, *p2;
for (y = 0; y < h; y++)
{
p1 = data + (j * y);
p2 = ((DATA8 *)xcim->data) + (xcim->line_bytes * y);
for (x = 0; x < w; x++)
{
*p2 = *p1;
p1++;
p2++;
}
}
}
else
{
DATA8 *tmpbuf = NULL, *dp, *tp, bits;
int bi, bj, end;
const DATA8 bitrepl[2] = {0x0, 0xff};
tmpbuf = alloca(w);
{
int x, y;
DATA8 *p1, *p2;
for (y = 0; y < h; y++)
{
p1 = tmpbuf;
p2 = ((DATA8 *)xcim->data) + (xcim->line_bytes * y);
tp = tmpbuf;
dp = data + (y * fg->glyph_out->bitmap.pitch);
for (bi = 0; bi < w; bi += 8)
{
bits = *dp;
if ((w - bi) < 8) end = w - bi;
else end = 8;
for (bj = 0; bj < end; bj++)
{
*tp = bitrepl[(bits >> (7 - bj)) & 0x1];
tp++;
}
dp++;
}
for (x = 0; x < w; x++)
{
*p2 = *p1;
p1++;
p2++;
}
}
}
}
_xr_image_put(xcim, fs->draw, 0, 0, w, h);
return fs;
}
static Evas_Bool
_xre_font_pool_cb(Evas_Hash *hash, const char *key, void *data, void *fdata)
{
Evas_Hash *pool;
XR_Font_Surface *fs;
char buf[256];
fs = fdata;
pool = data;
snprintf(buf, sizeof(buf), "@%p@/@%lx@", fs->xcbinf->conn, fs->xcbinf->root.window.xid);
pool = evas_hash_del(pool, buf, fs);
hash = evas_hash_modify(hash, key, pool);
return 1;
}
void
_xre_font_surface_free(XR_Font_Surface *fs)
{
if (!fs) return;
evas_hash_foreach(_xr_fg_pool, _xre_font_pool_cb, fs);
XCBFreePixmap(fs->xcbinf->conn, fs->draw.pixmap);
XCBRenderFreePicture(fs->xcbinf->conn, fs->pic);
_xr_image_info_free(fs->xcbinf);
free(fs);
}
void
_xre_font_surface_draw(XCBimage_Info *xcbinf, RGBA_Image *surface, RGBA_Draw_Context *dc, RGBA_Font_Glyph *fg, int x, int y)
{
XR_Font_Surface *fs;
XCBrender_Surface *target_surface;
XCBRECTANGLE rect;
int r;
int g;
int b;
int a;
fs = fg->ext_dat;
if (!fs) return;
target_surface = (XCBrender_Surface *)(surface->image->data);
a = (dc->col.col >> 24) & 0xff;
r = (dc->col.col >> 16) & 0xff;
g = (dc->col.col >> 8 ) & 0xff;
b = (dc->col.col ) & 0xff;
if ((fs->xcbinf->mul_r != r) || (fs->xcbinf->mul_g != g) ||
(fs->xcbinf->mul_b != b) || (fs->xcbinf->mul_a != a))
{
fs->xcbinf->mul_r = r;
fs->xcbinf->mul_g = g;
fs->xcbinf->mul_b = b;
fs->xcbinf->mul_a = a;
_xr_render_surface_solid_rectangle_set(fs->xcbinf->mul, r, g, b, a, 0, 0, 1, 1);
}
rect.x = x;
rect.y = y;
rect.width = fs->w;
rect.height = fs->h;
if ((dc) && (dc->clip.use))
{
RECTS_CLIP_TO_RECT(rect.x, rect.y, rect.width, rect.height,
dc->clip.x, dc->clip.y, dc->clip.w, dc->clip.h);
}
XCBRenderSetPictureClipRectangles(target_surface->xcbinf->conn,
target_surface->pic, 0, 0, 1, &rect);
XCBRenderComposite(fs->xcbinf->conn, XCBRenderPictOpOver,
fs->xcbinf->mul->pic,
fs->pic,
target_surface->pic,
0, 0,
0, 0,
x, y,
fs->w, fs->h);
}

View File

@ -0,0 +1,157 @@
#include "evas_common.h"
#include "evas_private.h"
#include "evas_engine.h"
#include "Evas_Engine_XRender_Xcb.h"
#include <math.h>
XR_Gradient *
_xre_gradient_color_add(XCBimage_Info *xcbinf, XR_Gradient *gr, int r, int g, int b, int a, int distance)
{
if (!gr)
{
gr = calloc(1, sizeof(XR_Gradient));
if (!gr) return NULL;
gr->xcbinf = xcbinf;
gr->xcbinf->references++;
gr->grad = evas_common_gradient_new();
if (!gr->grad)
{
gr->xcbinf->references--;
free(gr);
return NULL;
}
}
evas_common_gradient_color_add(gr->grad, r, g, b, a, distance);
if (gr->surface)
{
_xr_render_surface_free(gr->surface);
gr->surface = NULL;
}
gr->changed = 1;
return gr;
}
XR_Gradient *
_xre_gradient_colors_clear(XR_Gradient *gr)
{
if (!gr) return NULL;
evas_common_gradient_colors_clear(gr->grad);
if (gr->surface)
{
_xr_render_surface_free(gr->surface);
gr->surface = NULL;
}
gr->changed = 1;
return gr;
}
void
_xre_gradient_free(XR_Gradient *gr)
{
if (!gr) return;
if (gr->grad)
{
evas_common_gradient_free(gr->grad);
gr->grad = NULL;
}
if (gr->surface)
{
_xr_render_surface_free(gr->surface);
gr->surface = NULL;
}
_xr_image_info_free(gr->xcbinf);
free(gr);
}
void
_xre_gradient_fill_set(XR_Gradient *gr, int x, int y, int w, int h)
{
if (!gr) return;
evas_common_gradient_fill_set(gr->grad, x, y, w, h);
gr->changed = 1;
}
void
_xre_gradient_type_set(XR_Gradient *gr, char *name)
{
if (!gr) return;
evas_common_gradient_type_set(gr->grad, name);
gr->changed = 1;
}
void
_xre_gradient_type_params_set(XR_Gradient *gr, char *params)
{
if (!gr) return;
evas_common_gradient_type_params_set(gr->grad, params);
gr->changed = 1;
}
void *
_xre_gradient_geometry_init(XR_Gradient *gr, int spread)
{
if (!gr) return NULL;
gr->grad = evas_common_gradient_geometry_init(gr->grad, spread);
return gr;
}
int
_xre_gradient_alpha_get(XR_Gradient *gr, int spread)
{
if (!gr) return 0;
return evas_common_gradient_has_alpha(gr->grad, spread);
}
void
_xre_gradient_map(RGBA_Draw_Context *dc, XR_Gradient *gr, int spread)
{
if (!gr) return;
evas_common_gradient_map(dc, gr->grad, spread);
evas_common_cpu_end_opt();
gr->changed = 1;
}
void
_xre_gradient_draw(XCBrender_Surface *rs, RGBA_Draw_Context *dc, XR_Gradient *gr, int x, int y, int w, int h, double angle, int spread)
{
RGBA_Image *im;
if ((w <= 0) || (h <= 0)) return;
if ((angle != gr->angle) || (spread != gr->spread) || (gr->changed))
{
if (gr->surface)
{
_xr_render_surface_free(gr->surface);
gr->surface = NULL;
}
}
if (!gr->surface)
{
im = evas_common_image_create(w, h);
if (im)
{
RGBA_Draw_Context *dc2;
dc2 = evas_common_draw_context_new();
if (dc2)
{
im->flags |= RGBA_IMAGE_HAS_ALPHA;
memset(im->image->data, 0, im->image->w * im->image->h * sizeof(DATA32));
dc2->anti_alias = dc->anti_alias;
dc2->interpolation.color_space = dc->interpolation.color_space;
evas_common_gradient_draw(im, dc2, 0, 0, w, h, gr->grad, angle, spread);
gr->surface = _xr_render_surface_new(gr->xcbinf, w, h, gr->xcbinf->fmt32, 1);
if (gr->surface)
_xr_render_surface_argb_pixels_fill(gr->surface, w, h, im->image->data, 0, 0, w, h);
evas_common_draw_context_free(dc2);
gr->angle = angle;
gr->spread = spread;
}
evas_common_image_free(im);
}
}
if (gr->surface)
_xr_render_surface_composite(gr->surface, rs, dc, 0, 0, gr->surface->w, gr->surface->h, x, y, w, h, 1);
gr->changed = 0;
}

View File

@ -0,0 +1,560 @@
#include "evas_common.h"
#include "evas_private.h"
#include "evas_engine.h"
#include "Evas_Engine_XRender_Xcb.h"
static Evas_Hash *_xr_image_hash = NULL;
static int _xr_image_cache_size = 0;
static int _xr_image_cache_usage = 0;
static Evas_List *_xr_image_cache = NULL;
static Evas_Hash *_xr_image_dirty_hash = NULL;
static void
__xre_image_dirty_hash_add(XR_Image *im)
{
char buf[64];
if (!im->data) return;
snprintf(buf, sizeof(buf), "%p", im->data);
_xr_image_dirty_hash = evas_hash_add(_xr_image_dirty_hash, buf, im);
}
static void
__xre_image_dirty_hash_del(XR_Image *im)
{
char buf[64];
if (!im->data) return;
snprintf(buf, sizeof(buf), "%p", im->data);
_xr_image_dirty_hash = evas_hash_del(_xr_image_dirty_hash, buf, im);
}
static XR_Image *
__xre_image_dirty_hash_find(void *data)
{
char buf[64];
snprintf(buf, sizeof(buf), "%p", data);
return evas_hash_find(_xr_image_dirty_hash, buf);
}
static XR_Image *
__xre_image_find(char *fkey)
{
XR_Image *im;
im = evas_hash_find(_xr_image_hash, fkey);
if (!im)
{
Evas_List *l;
for (l = _xr_image_cache; l; l = l->next)
{
im = l->data;
if (!strcmp(im->fkey, fkey))
{
_xr_image_cache = evas_list_remove_list(_xr_image_cache, l);
_xr_image_hash = evas_hash_add(_xr_image_hash, im->fkey, im);
_xr_image_cache_usage -= (im->w * im->h * 4);
break;
}
im = NULL;
}
}
if (im) im->references++;
return im;
}
XR_Image *
_xre_image_load(XCBimage_Info *xcbinf, char *file, char *key)
{
XR_Image *im;
char buf[4096];
if (!file) return NULL;
if (key)
snprintf(buf, sizeof(buf), "/@%p@%lx@/%s//://%s", xcbinf->conn, xcbinf->root.window.xid, file, key);
else
snprintf(buf, sizeof(buf), "/@%p@%lx@/%s", xcbinf->conn, xcbinf->root.window.xid, file);
im = __xre_image_find(buf);
if (im)
{
return im;
}
im = calloc(1, sizeof(XR_Image));
if (!im) return NULL;
im->im = evas_common_load_image_from_file(file, key);
if (!im->im)
{
free(im);
return NULL;
}
im->xcbinf = xcbinf;
im->xcbinf->references++;
im->fkey = strdup(buf);
im->file = (char *)evas_stringshare_add(file);
if (key) im->key = (char *)evas_stringshare_add(key);
im->w = im->im->image->w;
im->h = im->im->image->h;
im->references = 1;
if (im->im->info.comment) im->comment = (char *)evas_stringshare_add(im->im->info.comment);
/* if (im->im->info.format == 1) im->format = evas_stringshare_add("png"); */
if (im->im->flags & RGBA_IMAGE_HAS_ALPHA) im->alpha = 1;
_xr_image_hash = evas_hash_direct_add(_xr_image_hash, im->fkey, im);
return im;
}
XR_Image *
_xre_image_new_from_data(XCBimage_Info *xcbinf, int w, int h, void *data)
{
XR_Image *im;
im = calloc(1, sizeof(XR_Image));
if (!im) return NULL;
im->xcbinf = xcbinf;
im->xcbinf->references++;
im->w = w;
im->h = h;
im->references = 1;
im->data = data;
im->alpha = 1;
im->dirty = 1;
__xre_image_dirty_hash_add(im);
return im;
}
XR_Image *
_xre_image_new_from_copied_data(XCBimage_Info *xcbinf, int w, int h, void *data)
{
XR_Image *im;
im = calloc(1, sizeof(XR_Image));
if (!im) return NULL;
im->data = malloc(w * h * 4);
if (!im->data)
{
free(im);
return NULL;
}
if (data)
{
Gfx_Func_Blend_Src_Dst func;
func = evas_common_draw_func_copy_get(w * h, 0);
if (func) func(data, im->data, w * h);
evas_common_cpu_end_opt();
}
im->w = w;
im->h = h;
im->references = 1;
im->xcbinf = xcbinf;
im->xcbinf->references++;
im->free_data = 1;
im->alpha = 1;
im->dirty = 1;
__xre_image_dirty_hash_add(im);
return im;
}
XR_Image *
_xre_image_new(XCBimage_Info *xcbinf, int w, int h)
{
XR_Image *im;
im = calloc(1, sizeof(XR_Image));
if (!im) return NULL;
im->data = malloc(w * h * 4);
if (!im->data)
{
free(im);
return NULL;
}
im->w = w;
im->h = h;
im->references = 1;
im->xcbinf = xcbinf;
im->xcbinf->references++;
im->free_data = 1;
im->alpha = 1;
im->dirty = 1;
__xre_image_dirty_hash_add(im);
return im;
}
static void
__xre_image_real_free(XR_Image *im)
{
if (im->file) evas_stringshare_del(im->file);
if (im->key) evas_stringshare_del(im->key);
if (im->fkey) free(im->fkey);
if (im->im) evas_common_image_unref(im->im);
if ((im->data) && (im->dirty)) __xre_image_dirty_hash_del(im);
if ((im->free_data) && (im->data)) free(im->data);
if (im->surface) _xr_render_surface_free(im->surface);
if (im->format) evas_stringshare_del(im->format);
if (im->comment) evas_stringshare_del(im->comment);
if (im->updates) evas_common_tilebuf_free(im->updates);
_xr_image_info_free(im->xcbinf);
free(im);
}
void
_xre_image_free(XR_Image *im)
{
im->references--;
if (im->references != 0) return;
if (!im->dirty)
{
if (im->fkey)
_xr_image_hash = evas_hash_del(_xr_image_hash, im->fkey, im);
_xr_image_cache = evas_list_prepend(_xr_image_cache, im);
_xr_image_cache_usage += (im->w * im->h * 4);
_xre_image_cache_set(_xr_image_cache_size);
}
else
{
__xre_image_real_free(im);
}
}
void
_xre_image_region_dirty(XR_Image *im, int x, int y, int w, int h)
{
if (!im->updates)
{
im->updates = evas_common_tilebuf_new(im->w, im->h);
if (im->updates) evas_common_tilebuf_set_tile_size(im->updates, 8, 8);
}
if (im->updates)
evas_common_tilebuf_add_redraw(im->updates, x, y, w, h);
}
void
_xre_image_dirty(XR_Image *im)
{
if (im->dirty) return;
if (im->fkey)
_xr_image_hash = evas_hash_del(_xr_image_hash, im->fkey, im);
im->dirty = 1;
__xre_image_dirty_hash_add(im);
}
XR_Image *
_xre_image_copy(XR_Image *im)
{
XR_Image *im2;
void *data = NULL;
if (im->data) data = im->data;
else
{
if (!im->im) im->im = evas_common_load_image_from_file(im->file, im->key);
if (im->im)
{
evas_common_load_image_data_from_file(im->im);
data = im->im->image->data;
}
}
if (!data) return NULL;
im2 = _xre_image_new_from_copied_data(im->xcbinf, im->w, im->h, data);
if (im2) im2->alpha = im->alpha;
if ((im->im) && (!im->dirty))
{
evas_common_image_unref(im->im);
im->im = NULL;
}
return im2;
}
void
_xre_image_resize(XR_Image *im, int w, int h)
{
if ((w == im->w) && (h == im->h)) return;
if (im->surface)
{
XCBrender_Surface *old_surface;
int x = 0, y = 0, ww, hh;
ww = w; hh = h;
RECTS_CLIP_TO_RECT(x, y, ww, hh, 0, 0, im->w, im->h);
old_surface = im->surface;
im->surface = _xr_render_surface_new(old_surface->xcbinf, w, h, old_surface->fmt, old_surface->alpha);
if (im->surface)
_xr_render_surface_copy(old_surface, im->surface, 0, 0, 0, 0, ww, hh);
_xr_render_surface_free(old_surface);
}
if (im->data)
{
Gfx_Func_Blend_Src_Dst func;
int x = 0, y = 0, ww, hh;
unsigned int *sp, *dp;
void *data;
data = malloc(w * h * 4);
if (!data)
{
if (im->surface)
{
_xr_render_surface_free(im->surface);
im->surface = NULL;
}
return;
}
ww = w; hh = h;
RECTS_CLIP_TO_RECT(x, y, ww, hh, 0, 0, im->w, im->h);
func = evas_common_draw_func_copy_get(w * h, 0);
if (func)
{
for (y = 0; y < hh; y++)
{
sp = ((unsigned int *)im->data) + (y * im->w);
dp = ((unsigned int *)data) + (y * w);
func(sp, dp, ww);
}
evas_common_cpu_end_opt();
}
__xre_image_dirty_hash_del(im);
free(im->data);
im->data = data;
__xre_image_dirty_hash_add(im);
}
else if (im->im)
{
RGBA_Image *im_old;
im_old = im->im;
im->im = evas_common_image_create(w, h);
if (!im->im)
{
im->im = im_old;
if (im->surface)
{
_xr_render_surface_free(im->surface);
im->surface = NULL;
}
return;
}
evas_common_load_image_data_from_file(im_old);
if (im_old->image->data)
{
int x = 0, y = 0, ww, hh;
ww = w; hh = h;
RECTS_CLIP_TO_RECT(x, y, ww, hh, 0, 0, im->w, im->h);
evas_common_blit_rectangle(im_old, im->im, 0, 0, ww, hh, 0, 0);
evas_common_cpu_end_opt();
}
im->free_data = 1;
im->data = im->im->image->data;
im->im->image->data = NULL;
evas_common_image_unref(im->im);
im->im = NULL;
evas_common_image_unref(im_old);
__xre_image_dirty_hash_add(im);
}
else
{
im->data = malloc(w * h * 4);
im->free_data = 1;
__xre_image_dirty_hash_add(im);
}
im->w = w;
im->h = h;
}
void *
_xre_image_data_get(XR_Image *im)
{
void *data = NULL;
if (im->data) data = im->data;
else
{
if (!im->im) im->im = evas_common_load_image_from_file(im->file, im->key);
if (im->im)
{
evas_common_load_image_data_from_file(im->im);
data = im->im->image->data;
}
}
return data;
}
XR_Image *
_xre_image_data_find(void *data)
{
XR_Image *im;
im = __xre_image_dirty_hash_find(data);
if (im)
{
im->references++;
}
return im;
}
void
_xre_image_data_put(XR_Image *im, void *data)
{
void *imdata = NULL;
if (!data) return;
if (im->data)
{
imdata = im->data;
if (data == imdata) return;
__xre_image_dirty_hash_del(im);
if (im->free_data) free(im->data);
}
else
{
if (im->im) imdata = im->im->image->data;
if (data == imdata) return;
if (im->im)
{
evas_common_image_unref(im->im);
im->im = NULL;
}
}
im->data = data;
__xre_image_dirty_hash_add(im);
im->free_data = 0;
if (im->surface)
{
_xr_render_surface_free(im->surface);
im->surface = NULL;
}
if (!im->dirty)
{
if (im->fkey)
_xr_image_hash = evas_hash_del(_xr_image_hash, im->fkey, im);
im->dirty = 1;
}
if (im->updates)
{
evas_common_tilebuf_free(im->updates);
im->updates = NULL;
}
}
void
_xre_image_alpha_set(XR_Image *im, int alpha)
{
if (im->alpha == alpha) return;
im->alpha = alpha;
if (im->surface)
{
XCBrender_Surface *old_surface;
old_surface = im->surface;
im->surface = NULL;
if (im->alpha)
im->surface = _xr_render_surface_new(im->xcbinf, im->w, im->h, im->xcbinf->fmt32, 1);
else
im->surface = _xr_render_surface_new(im->xcbinf, im->w, im->h, im->xcbinf->fmt24, 0);
if (im->surface)
_xr_render_surface_copy(old_surface, im->surface, 0, 0, 0, 0, im->w, im->h);
_xr_render_surface_free(old_surface);
}
if (im->updates)
{
evas_common_tilebuf_free(im->updates);
im->updates = NULL;
}
}
int
_xre_image_alpha_get(XR_Image *im)
{
return im->alpha;
}
void
_xre_image_surface_gen(XR_Image *im)
{
void *data = NULL;
if ((im->surface) && (!im->updates)) return;
if (im->data) data = im->data;
else
{
if (!im->im) im->im = evas_common_load_image_from_file(im->file, im->key);
if (im->im)
{
evas_common_load_image_data_from_file(im->im);
data = im->im->image->data;
}
}
if (!data) return;
if (im->surface)
{
if (im->updates)
{
Tilebuf_Rect *rects, *r;
rects = evas_common_tilebuf_get_render_rects(im->updates);
if (rects)
{
for (r = rects; r; r = (Tilebuf_Rect *)((Evas_Object_List *)r)->next)
{
int rx, ry, rw, rh;
rx = r->x; ry = r->y; rw = r->w, rh = r->h;
RECTS_CLIP_TO_RECT(rx, ry, rw, rh, 0, 0, im->w, im->h);
if (im->alpha)
_xr_render_surface_argb_pixels_fill(im->surface, im->w, im->h, data, rx, ry, rw, rh);
else
_xr_render_surface_rgb_pixels_fill(im->surface, im->w, im->h, data, rx, ry, rw, rh);
}
evas_common_tilebuf_free_render_rects(rects);
}
evas_common_tilebuf_free(im->updates);
im->updates = NULL;
}
return;
}
if (im->alpha)
{
im->surface = _xr_render_surface_new(im->xcbinf, im->w, im->h, im->xcbinf->fmt32, 1);
_xr_render_surface_argb_pixels_fill(im->surface, im->w, im->h, data, 0, 0, im->w, im->h);
}
else
{
im->surface = _xr_render_surface_new(im->xcbinf, im->w, im->h, im->xcbinf->fmt24, 0);
_xr_render_surface_rgb_pixels_fill(im->surface, im->w, im->h, data, 0, 0, im->w, im->h);
}
if ((im->im) && (!im->dirty))
{
evas_common_image_unref(im->im);
im->im = NULL;
}
}
void
_xre_image_cache_set(int size)
{
_xr_image_cache_size = size;
while (_xr_image_cache_usage > _xr_image_cache_size)
{
Evas_List *l;
l = evas_list_last(_xr_image_cache);
if (l)
{
XR_Image *im;
im = l->data;
_xr_image_cache = evas_list_remove_list(_xr_image_cache, l);
_xr_image_cache_usage -= (im->w * im->h * 4);
__xre_image_real_free(im);
}
}
}
int
_xre_image_cache_get(void)
{
return _xr_image_cache_size;
}

View File

@ -0,0 +1,545 @@
#include "evas_common.h"
#include "evas_private.h"
#include "evas_engine.h"
#include "Evas_Engine_XRender_Xcb.h"
static Evas_List *_image_info_list = NULL;
static int _xcb_err = 0;
enum
{
XCBRenderPICTFORMINFOId = 1 << 0,
XCBRenderPICTFORMINFOType = 1 << 1,
XCBRenderPICTFORMINFODepth = 1 << 2,
XCBRenderPICTFORMINFORedShift = 1 << 3,
XCBRenderPICTFORMINFORedMask = 1 << 4,
XCBRenderPICTFORMINFOGreenShift = 1 << 5,
XCBRenderPICTFORMINFOGreenMask = 1 << 6,
XCBRenderPICTFORMINFOBlueShift = 1 << 7,
XCBRenderPICTFORMINFOBlueMask = 1 << 8,
XCBRenderPICTFORMINFOAlphaShift = 1 << 9,
XCBRenderPICTFORMINFOAlphaMask = 1 << 10,
XCBRenderPICTFORMINFOColormap = 1 << 11,
};
enum
{
XCBRenderStandardPICTFORMINFOARGB32,
XCBRenderStandardPICTFORMINFORGB24,
XCBRenderStandardPICTFORMINFOA8,
XCBRenderStandardPICTFORMINFOA4,
XCBRenderStandardPICTFORMINFOA1,
XCBRenderStandardPICTFORMINFOCount
};
static XCBRenderPICTFORMINFO *
XCBRenderFindPICTFORMINFO (XCBConnection *conn, CARD32 mask, const XCBRenderPICTFORMINFO *template, int count)
{
XCBRenderQueryPictFormatsCookie cookie;
XCBRenderQueryPictFormatsRep *rep;
XCBRenderPICTFORMINFOIter iter_forminfo;
cookie = XCBRenderQueryPictFormats (conn);
rep = XCBRenderQueryPictFormatsReply (conn, cookie, NULL);
iter_forminfo = XCBRenderQueryPictFormatsFormatsIter (rep);
for (; iter_forminfo.rem; XCBRenderPICTFORMINFONext (&iter_forminfo)) {
if (mask & XCBRenderPICTFORMINFOId)
if (template->id.xid != iter_forminfo.data->id.xid)
continue;
if (mask & XCBRenderPICTFORMINFOType)
if (template->type != iter_forminfo.data->type)
continue;
if (mask & XCBRenderPICTFORMINFODepth)
if (template->depth != iter_forminfo.data->depth)
continue;
if (mask & XCBRenderPICTFORMINFORedShift)
if (template->direct.red_shift != iter_forminfo.data->direct.red_shift)
continue;
if (mask & XCBRenderPICTFORMINFORedMask)
if (template->direct.red_mask != iter_forminfo.data->direct.red_mask)
continue;
if (mask & XCBRenderPICTFORMINFOGreenShift)
if (template->direct.green_shift != iter_forminfo.data->direct.green_shift)
continue;
if (mask & XCBRenderPICTFORMINFOGreenMask)
if (template->direct.green_mask != iter_forminfo.data->direct.green_mask)
continue;
if (mask & XCBRenderPICTFORMINFOBlueShift)
if (template->direct.blue_shift != iter_forminfo.data->direct.blue_shift)
continue;
if (mask & XCBRenderPICTFORMINFOBlueMask)
if (template->direct.blue_mask != iter_forminfo.data->direct.blue_mask)
continue;
if (mask & XCBRenderPICTFORMINFOAlphaShift)
if (template->direct.alpha_shift != iter_forminfo.data->direct.alpha_shift)
continue;
if (mask & XCBRenderPICTFORMINFOAlphaMask)
if (template->direct.alpha_mask != iter_forminfo.data->direct.alpha_mask)
continue;
if (mask & XCBRenderPICTFORMINFOColormap)
if (template->colormap.xid != iter_forminfo.data->colormap.xid)
continue;
if (count-- == 0) {
XCBRenderPICTFORMINFO *forminfo;
forminfo = (XCBRenderPICTFORMINFO *)malloc (sizeof (XCBRenderPICTFORMINFO));
memcpy (forminfo, iter_forminfo.data, sizeof (XCBRenderPICTFORMINFO));
free (rep);
return forminfo;
}
}
free (rep);
return NULL;
}
static XCBRenderPICTFORMINFO *
XCBRenderFindStandardPICTFORMINFO (XCBConnection *conn, int format)
{
XCBRenderPICTFORMINFO *forminfo = NULL;
struct {
XCBRenderPICTFORMINFO template;
CARD32 mask;
} standardFormats[XCBRenderStandardPICTFORMINFOCount] = {
/* StandardPICTFORMINFOARGB32 */
{
{
{ 0, }, /* id */
XCBRenderPictTypeDirect, /* type */
32, /* depth */
{ 0, 0 }, /* pad */
{ /* direct */
16, /* direct.red_shift */
0xff, /* direct.red_mask */
8, /* direct.green_shift */
0xff, /* direct.green_mask */
0, /* direct.blue_shift */
0xff, /* direct.blue_mask */
24, /* direct.alpha_shift */
0xff /* direct.alpha_mask */
},
{ 0, } /* colormap */
},
XCBRenderPICTFORMINFOType |
XCBRenderPICTFORMINFODepth |
XCBRenderPICTFORMINFORedShift |
XCBRenderPICTFORMINFORedMask |
XCBRenderPICTFORMINFOGreenShift |
XCBRenderPICTFORMINFOGreenMask |
XCBRenderPICTFORMINFOBlueShift |
XCBRenderPICTFORMINFOBlueMask |
XCBRenderPICTFORMINFOAlphaShift |
XCBRenderPICTFORMINFOAlphaMask
},
/* StandardPICTFORMINFORGB24 */
{
{
{ 0, }, /* id */
XCBRenderPictTypeDirect, /* type */
24, /* depth */
{ 0, 0 }, /* pad */
{ /* direct */
16, /* direct.red_shift */
0xff, /* direct.red_mask */
8, /* direct.green_shift */
0xff, /* direct.green_mask */
0, /* direct.blue_shift */
0xff, /* direct.blue_mask */
0, /* direct.alpha_shift */
0x00 /* direct.alpha_mask */
},
{ 0, } /* colormap */
},
XCBRenderPICTFORMINFOType |
XCBRenderPICTFORMINFODepth |
XCBRenderPICTFORMINFORedShift |
XCBRenderPICTFORMINFORedMask |
XCBRenderPICTFORMINFOGreenShift |
XCBRenderPICTFORMINFOGreenMask |
XCBRenderPICTFORMINFOBlueShift |
XCBRenderPICTFORMINFOBlueMask |
XCBRenderPICTFORMINFOAlphaMask
},
/* StandardPICTFORMINFOA8 */
{
{
{ 0, }, /* id */
XCBRenderPictTypeDirect, /* type */
8, /* depth */
{ 0, 0 }, /* pad */
{ /* direct */
0, /* direct.red_shift */
0x00, /* direct.red_mask */
0, /* direct.green_shift */
0x00, /* direct.green_mask */
0, /* direct.blue_shift */
0x00, /* direct.blue_mask */
0, /* direct.alpha_shift */
0xff /* direct.alpha_mask */
},
{ 0, } /* colormap */
},
XCBRenderPICTFORMINFOType |
XCBRenderPICTFORMINFODepth |
XCBRenderPICTFORMINFORedMask |
XCBRenderPICTFORMINFOGreenMask |
XCBRenderPICTFORMINFOBlueMask |
XCBRenderPICTFORMINFOAlphaShift |
XCBRenderPICTFORMINFOAlphaMask
},
/* StandardPICTFORMINFOA4 */
{
{
{ 0, }, /* id */
XCBRenderPictTypeDirect, /* type */
4, /* depth */
{ 0, 0 }, /* pad */
{ /* direct */
0, /* direct.red_shift */
0x00, /* direct.red_mask */
0, /* direct.green_shift */
0x00, /* direct.green_mask */
0, /* direct.blue_shift */
0x00, /* direct.blue_mask */
0, /* direct.alpha_shift */
0x0f /* direct.alpha_mask */
},
{ 0, } /* colormap */
},
XCBRenderPICTFORMINFOType |
XCBRenderPICTFORMINFODepth |
XCBRenderPICTFORMINFORedMask |
XCBRenderPICTFORMINFOGreenMask |
XCBRenderPICTFORMINFOBlueMask |
XCBRenderPICTFORMINFOAlphaShift |
XCBRenderPICTFORMINFOAlphaMask
},
/* StandardPICTFORMINFOA1 */
{
{
{ 0, }, /* id */
XCBRenderPictTypeDirect, /* type */
1, /* depth */
{ 0, 0 }, /* pad */
{ /* direct */
0, /* direct.red_shift */
0x00, /* direct.red_mask */
0, /* direct.green_shift */
0x00, /* direct.green_mask */
0, /* direct.blue_shift */
0x00, /* direct.blue_mask */
0, /* direct.alpha_shift */
0x01 /* direct.alpha_mask */
},
{ 0, } /* colormap */
},
XCBRenderPICTFORMINFOType |
XCBRenderPICTFORMINFODepth |
XCBRenderPICTFORMINFORedMask |
XCBRenderPICTFORMINFOGreenMask |
XCBRenderPICTFORMINFOBlueMask |
XCBRenderPICTFORMINFOAlphaShift |
XCBRenderPICTFORMINFOAlphaMask
},
};
if ((format >= 0) && (format < XCBRenderStandardPICTFORMINFOCount))
forminfo = XCBRenderFindPICTFORMINFO (conn,
standardFormats[format].mask,
&standardFormats[format].template,
0);
return forminfo;
}
static void
_tmp_xcb_err(XCBConnection *conn/* , XErrorEvent *ev */)
{
_xcb_err = 1;
return;
}
XCBimage_Info *
_xr_image_info_get(XCBConnection *conn, XCBDRAWABLE draw, XCBVISUALID vis)
{
XCBGetGeometryCookie cookie;
XCBGetGeometryRep *rep;
XCBimage_Info *xcbinf;
XCBimage_Info *xcbinf2;
Evas_List *l;
xcbinf2 = NULL;
for (l = _image_info_list; l; l = l->next)
{
xcbinf = l->data;
if (xcbinf->conn == conn)
{
xcbinf2 = xcbinf;
break;
}
}
xcbinf = calloc(1, sizeof(XCBimage_Info));
if (!xcbinf) return NULL;
xcbinf->references = 1;
xcbinf->conn = conn;
xcbinf->draw = draw;
cookie = XCBGetGeometry(xcbinf->conn, xcbinf->draw);
rep = XCBGetGeometryReply(xcbinf->conn, cookie, NULL);
xcbinf->root.window = rep->root;
free(rep);
xcbinf->vis = vis;
xcbinf->fmt32 = XCBRenderFindStandardPICTFORMINFO(xcbinf->conn, XCBRenderStandardPICTFORMINFOARGB32);
xcbinf->fmt24 = XCBRenderFindStandardPICTFORMINFO(xcbinf->conn, XCBRenderStandardPICTFORMINFORGB24);
xcbinf->fmt8 = XCBRenderFindStandardPICTFORMINFO(xcbinf->conn, XCBRenderStandardPICTFORMINFOA8);
xcbinf->fmt4 = XCBRenderFindStandardPICTFORMINFO(xcbinf->conn, XCBRenderStandardPICTFORMINFOA4);
xcbinf->fmt1 = XCBRenderFindStandardPICTFORMINFO(xcbinf->conn, XCBRenderStandardPICTFORMINFOA1);
xcbinf->mul = _xr_render_surface_new(xcbinf, 1, 1, xcbinf->fmt32, 1);
_xr_render_surface_repeat_set(xcbinf->mul, 1);
xcbinf->mul_r = xcbinf->mul_g = xcbinf->mul_b = xcbinf->mul_a = 0xff;
_xr_render_surface_solid_rectangle_set(xcbinf->mul, xcbinf->mul_r, xcbinf->mul_g, xcbinf->mul_b, xcbinf->mul_a, 0, 0, 1, 1);
if (xcbinf2)
{
xcbinf->can_do_shm = xcbinf2->can_do_shm;
xcbinf->depth = xcbinf2->depth;
}
else
{
const XCBQueryExtensionRep *rep_shm;
const XCBQueryExtensionRep *rep_xrender;
xcbinf->depth = 32;
{
XCBConnSetupSuccessRep *rep;
XCBSCREENIter iter_screen;
rep = XCBGetSetup(xcbinf->conn);
iter_screen = XCBConnSetupSuccessRepRootsIter(rep);
for (; iter_screen.rem ; XCBSCREENNext (&iter_screen)) {
XCBDEPTHIter iter_depth;
iter_depth = XCBSCREENAllowedDepthsIter (iter_screen.data);
for (; iter_depth.rem ; XCBDEPTHNext (&iter_depth)) {
XCBVISUALTYPEIter iter_visual;
iter_visual = XCBDEPTHVisualsIter (iter_depth.data);
for (; iter_visual.rem ; XCBVISUALTYPENext (&iter_visual)) {
if (iter_visual.data->visual_id.id == vis.id)
xcbinf->depth = iter_depth.data->depth;
}
}
}
}
xcbinf->can_do_shm = 0;
XCBPrefetchExtensionData (xcbinf->conn, &XCBShmId);
XCBPrefetchExtensionData (xcbinf->conn, &XCBRenderId);
rep_shm = XCBGetExtensionData(xcbinf->conn, &XCBShmId);
rep_xrender = XCBGetExtensionData(xcbinf->conn, &XCBRenderId);
if (rep_shm && rep_xrender && rep_shm->present && rep_xrender->present) {
XCBShmSegmentInfo shm_info;
XCBImage *xcbim;
shm_info.shmseg = XCBShmSEGNew(xcbinf->conn);
xcbim = XCBImageSHMCreate(xcbinf->conn, xcbinf->depth, ZPixmap, NULL, 1, 1);
if (xcbim) {
shm_info.shmid = shmget(IPC_PRIVATE, xcbim->bytes_per_line * xcbim->height, IPC_CREAT | 0777);
if (shm_info.shmid >= 0) {
shm_info.shmaddr = xcbim->data = shmat(shm_info.shmid, 0, 0);
if ((shm_info.shmaddr != NULL) && (shm_info.shmaddr != (void *) -1)) {
/*
* FIXME: no error mechanism
*/
/* XErrorHandler ph; */
XCBSync(xcbinf->conn, 0);
_xcb_err = 0;
/* ph = XSetErrorHandler((XErrorHandler)_tmp_xcb_err); */
XCBShmAttach(xcbinf->conn, shm_info.shmseg, shm_info.shmid, 0);
XCBSync(xcbinf->conn, 0);
/* XSetErrorHandler((XErrorHandler)ph); */
if (!_xcb_err) xcbinf->can_do_shm = 1;
shmdt(shm_info.shmaddr);
}
shmctl(shm_info.shmid, IPC_RMID, 0);
}
XCBImageSHMDestroy(xcbim);
}
}
}
_image_info_list = evas_list_prepend(_image_info_list, xcbinf);
return xcbinf;
}
void
_xr_image_info_free(XCBimage_Info *xcbinf)
{
if (xcbinf->pool) XCBSync(xcbinf->conn, 0);
_xr_image_info_pool_flush(xcbinf, 0, 0);
xcbinf->references--;
if (xcbinf->references != 0) return;
_xr_render_surface_free(xcbinf->mul);
free(xcbinf);
_image_info_list = evas_list_remove(_image_info_list, xcbinf);
}
void
_xr_image_info_pool_flush(XCBimage_Info *xcbinf, int max_num, int max_mem)
{
if ((xcbinf->pool_mem <= max_mem) && (evas_list_count(xcbinf->pool) <= max_num)) return;
while ((xcbinf->pool_mem > max_mem) || (evas_list_count(xcbinf->pool) > max_num))
{
XCBimage_Image *xcbim;
if (!xcbinf->pool) break;
xcbim = xcbinf->pool->data;
_xr_image_free(xcbim);
}
}
XCBimage_Image *
_xr_image_new(XCBimage_Info *xcbinf, int w, int h, int depth)
{
XCBimage_Image *xcbim, *xcbim2;
Evas_List *l;
xcbim2 = NULL;
for (l = xcbinf->pool; l; l = l->next)
{
xcbim = l->data;
if ((xcbim->w >= w) && (xcbim->h >= h) && (xcbim->depth == depth) && (xcbim->available))
{
if (!xcbim2) xcbim2 = xcbim;
else if ((xcbim->w * xcbim->h) < (xcbim2->w * xcbim2->h)) xcbim2 = xcbim;
}
}
if (xcbim2)
{
xcbim2->available = 0;
return xcbim2;
}
xcbim = calloc(1, sizeof(XCBimage_Image));
if (xcbim)
{
xcbim->xcbinf = xcbinf;
xcbim->w = w;
xcbim->h = h;
xcbim->depth = depth;
xcbim->available = 0;
if (xcbim->xcbinf->can_do_shm)
{
xcbim->shm_info = calloc(1, sizeof(XCBShmSegmentInfo));
if (xcbim->shm_info)
{
xcbim->shm_info->shmseg = XCBShmSEGNew(xcbinf->conn);
xcbim->xcbim = XCBImageSHMCreate(xcbim->xcbinf->conn, xcbim->depth, ZPixmap, NULL, xcbim->w, xcbim->h);
if (xcbim->xcbim)
{
xcbim->shm_info->shmid = shmget(IPC_PRIVATE, xcbim->xcbim->bytes_per_line * xcbim->xcbim->height, IPC_CREAT | 0777);
if (xcbim->shm_info->shmid >= 0)
{
xcbim->shm_info->shmaddr = xcbim->xcbim->data = shmat(xcbim->shm_info->shmid, 0, 0);
if ((xcbim->shm_info->shmaddr) && (xcbim->shm_info->shmaddr != (void *) -1))
{
/*
* FIXME: no error mechanism
*/
/* XErrorHandler ph; */
XCBSync(xcbim->xcbinf->conn, 0);
_xcb_err = 0;
/* ph = XSetErrorHandler((XErrorHandler)_tmp_xcb_err); */
XCBShmAttach(xcbim->xcbinf->conn, xcbim->shm_info->shmseg, xcbim->shm_info->shmid, 0);
XCBSync(xcbim->xcbinf->conn, 0);
/* XSetErrorHandler((XErrorHandler)ph); */
if (!_xcb_err) goto xcbim_ok;
shmdt(xcbim->shm_info->shmaddr);
}
shmctl(xcbim->shm_info->shmid, IPC_RMID, 0);
}
XCBImageSHMDestroy(xcbim->xcbim);
}
free(xcbim->shm_info);
xcbim->shm_info = NULL;
}
}
xcbim->xcbim = XCBImageCreate(xcbim->xcbinf->conn, xcbim->depth, ZPixmap, 0, NULL, xcbim->w, xcbim->h, 32, 0);
if (!xcbim->xcbim)
{
free(xcbim);
return NULL;
}
xcbim->xcbim->data = malloc(xcbim->xcbim->bytes_per_line * xcbim->xcbim->height);
if (!xcbim->xcbim->data)
{
XCBImageDestroy(xcbim->xcbim);
free(xcbim);
return NULL;
}
}
xcbim_ok:
_xr_image_info_pool_flush(xcbinf, 32, (1600 * 1200 * 32 * 2));
xcbim->line_bytes = xcbim->xcbim->bytes_per_line;
xcbim->data = (void *)(xcbim->xcbim->data);
xcbinf->pool_mem += (xcbim->w * xcbim->h * xcbim->depth);
xcbinf->pool = evas_list_append(xcbinf->pool, xcbim);
return xcbim;
}
void
_xr_image_free(XCBimage_Image *xcbim)
{
if (xcbim->shm_info)
{
if (!xcbim->available) XCBSync(xcbim->xcbinf->conn, 0);
XCBShmDetach(xcbim->xcbinf->conn, xcbim->shm_info->shmseg);
XCBImageSHMDestroy(xcbim->xcbim);
shmdt(xcbim->shm_info->shmaddr);
shmctl(xcbim->shm_info->shmid, IPC_RMID, 0);
free(xcbim->shm_info);
}
else
{
free(xcbim->xcbim->data);
xcbim->xcbim->data = NULL;
XCBImageDestroy(xcbim->xcbim);
}
xcbim->xcbinf->pool_mem -= (xcbim->w * xcbim->h * xcbim->depth);
xcbim->xcbinf->pool = evas_list_remove(xcbim->xcbinf->pool, xcbim);
free(xcbim);
}
void
_xr_image_put(XCBimage_Image *xcbim, XCBDRAWABLE draw, int x, int y, int w, int h)
{
XCBGCONTEXT gc;
gc = XCBGCONTEXTNew(xcbim->xcbinf->conn);
XCBCreateGC(xcbim->xcbinf->conn, gc, draw, 0, NULL);
if (xcbim->shm_info)
{
XCBImageSHMPut (xcbim->xcbinf->conn, draw, gc,
xcbim->xcbim, *xcbim->shm_info,
0, 0,
x, y,
xcbim->xcbim->width, xcbim->xcbim->height,
0);
/* XCBShmPutImage(xcbim->xcbinf->conn, draw, gc, */
/* xcbim->xcbim->width, xcbim->xcbim->height, */
/* 0, 0, */
/* w, h, */
/* x, y, */
/* xcbim->xcbim->depth, xcbim->xcbim->format, */
/* 0, */
/* xcbim->shm_info->shmseg, */
/* xcbim->xcbim->data - xcbim->shm_info->shmaddr); */
XCBSync(xcbim->xcbinf->conn, 0);
}
else
XCBImagePut(xcbim->xcbinf->conn, draw, gc, xcbim->xcbim, 0, 0, x, y, w, h);
xcbim->available = 1;
XCBFreeGC(xcbim->xcbinf->conn, gc);
}

View File

@ -0,0 +1,645 @@
#include "evas_common.h"
#include "evas_macros.h"
#include "evas_private.h"
#include "evas_engine.h"
#include "Evas_Engine_XRender_Xcb.h"
#include <math.h>
XCBRenderPICTFORMINFO *
XCBRenderFindVisualFormat (XCBConnection *c, XCBVISUALID visual)
{
XCBRenderQueryPictFormatsCookie cookie;
XCBRenderQueryPictFormatsRep *rep;
XCBRenderPICTSCREENIter screen_iter;
XCBRenderPICTFORMAT format = { 0 };
cookie = XCBRenderQueryPictFormats (c);
rep = XCBRenderQueryPictFormatsReply (c, cookie, NULL);
if (!rep)
return NULL;
screen_iter = XCBRenderQueryPictFormatsScreensIter (rep);
for (; screen_iter.rem; XCBRenderPICTSCREENNext (&screen_iter)) {
XCBRenderPICTDEPTHIter depth_iter;
depth_iter = XCBRenderPICTSCREENDepthsIter (screen_iter.data);
for (; depth_iter.rem; XCBRenderPICTDEPTHNext (&depth_iter)) {
XCBRenderPICTVISUALIter visual_iter;
visual_iter = XCBRenderPICTDEPTHVisualsIter (depth_iter.data);
for (; visual_iter.rem; XCBRenderPICTVISUALNext (&visual_iter)) {
if (visual.id == visual_iter.data->visual.id) {
format = visual_iter.data->format;
}
}
}
}
if (format.xid != 0) {
XCBRenderPICTFORMINFOIter forminfo_iter;
forminfo_iter = XCBRenderQueryPictFormatsFormatsIter (rep);
for (; forminfo_iter.rem; XCBRenderPICTFORMINFONext (&forminfo_iter)) {
if (forminfo_iter.data->id.xid == format.xid) {
XCBRenderPICTFORMINFO *forminfo;
forminfo = (XCBRenderPICTFORMINFO *)malloc (sizeof (XCBRenderPICTFORMINFO));
memcpy (forminfo, forminfo_iter.data, sizeof (XCBRenderPICTFORMINFO));
free (rep);
return forminfo;
}
}
}
free (rep);
return NULL;
}
XCBrender_Surface *
_xr_render_surface_new(XCBimage_Info *xcbinf, int w, int h, XCBRenderPICTFORMINFO *fmt, int alpha)
{
XCBrender_Surface *rs;
CARD32 mask;
CARD32 values[3];
rs = calloc(1, sizeof(XCBrender_Surface));
if (!rs) return NULL;
rs->xcbinf = xcbinf;
rs->w = w;
rs->h = h;
rs->fmt = fmt;
rs->alpha = alpha;
rs->depth = fmt->depth;
rs->allocated = 1;
rs->draw.pixmap = XCBPIXMAPNew(xcbinf->conn);
XCBCreatePixmap(xcbinf->conn, fmt->depth, rs->draw.pixmap, xcbinf->root, w, h);
rs->xcbinf->references++;
mask = XCBRenderCPRepeat | XCBRenderCPDither | XCBRenderCPComponentAlpha;
values[0] = 0;
values[1] = 0;
values[2] = 0;
rs->pic = XCBRenderPICTURENew(xcbinf->conn);
XCBRenderCreatePicture(xcbinf->conn, rs->pic, rs->draw, fmt->id, mask, values);
return rs;
}
XCBrender_Surface *
_xr_render_surface_adopt(XCBimage_Info *xcbinf, XCBDRAWABLE draw, int w, int h, int alpha)
{
XCBrender_Surface *rs;
XCBRenderPICTFORMINFO *fmt;
CARD32 mask;
CARD32 values[3];
rs = calloc(1, sizeof(XCBrender_Surface));
fmt = XCBRenderFindVisualFormat(xcbinf->conn, xcbinf->vis);
rs->xcbinf = xcbinf;
rs->w = w;
rs->h = h;
/* if (fmt->depth == xcbinf->fmt32->depth) */
/* rs->fmt = xcbinf->fmt32; */
/* else if (fmt->depth == xcbinf->fmt24->depth) */
/* rs->fmt = xcbinf->fmt24; */
/* else if (fmt->depth == xcbinf->fmt8->depth) */
/* rs->fmt = xcbinf->fmt8; */
/* else if (fmt->depth == xcbinf->fmt4->depth) */
/* rs->fmt = xcbinf->fmt4; */
/* else */
/* rs->fmt = xcbinf->fmt1; */
/* free(fmt); */
rs->fmt = fmt;
rs->alpha = alpha;
rs->depth = fmt->depth;
if (fmt->depth == 32) rs->alpha = 1;
rs->allocated = 0;
rs->draw = draw;
rs->xcbinf->references++;
mask = XCBRenderCPRepeat | XCBRenderCPDither | XCBRenderCPComponentAlpha;
values[0] = 0;
values[1] = 0;
values[2] = 0;
rs->pic = XCBRenderPICTURENew(xcbinf->conn);
XCBRenderCreatePicture(xcbinf->conn, rs->pic, rs->draw, fmt->id, mask, values);
return rs;
}
XCBrender_Surface *
_xr_render_surface_format_adopt(XCBimage_Info *xcbinf, XCBDRAWABLE draw, int w, int h, XCBRenderPICTFORMINFO *fmt, int alpha)
{
XCBrender_Surface *rs;
CARD32 mask;
CARD32 values[3];
rs = calloc(1, sizeof(XCBrender_Surface));
rs->xcbinf = xcbinf;
rs->w = w;
rs->h = h;
rs->fmt = fmt;
rs->alpha = alpha;
rs->depth = fmt->depth;
if (fmt->depth == 32) rs->alpha = 1;
rs->xcbinf->references++;
rs->allocated = 0;
rs->draw = draw;
mask = XCBRenderCPRepeat | XCBRenderCPDither | XCBRenderCPComponentAlpha;
values[0] = 0;
values[1] = 0;
values[2] = 0;
rs->pic = XCBRenderPICTURENew(xcbinf->conn);
XCBRenderCreatePicture(xcbinf->conn, rs->pic, rs->draw, fmt->id, mask, values);
return rs;
}
void
_xr_render_surface_free(XCBrender_Surface *rs)
{
if (rs->allocated) XCBFreePixmap(rs->xcbinf->conn, rs->draw.pixmap);
XCBRenderFreePicture(rs->xcbinf->conn, rs->pic);
_xr_image_info_free(rs->xcbinf);
rs->xcbinf = NULL;
free(rs);
}
void
_xr_render_surface_repeat_set(XCBrender_Surface *rs, int repeat)
{
CARD32 mask;
CARD32 value[1];
mask = XCBRenderCPRepeat;
value[0] = repeat;
XCBRenderChangePicture(rs->xcbinf->conn, rs->pic, mask, value);
}
void
_xr_render_surface_solid_rectangle_set(XCBrender_Surface *rs, int r, int g, int b, int a, int x, int y, int w, int h)
{
XCBRenderCOLOR col;
XCBRECTANGLE rect;
int aa;
aa = a +1;
r = (r * aa) >> 8;
g = (g * aa) >> 8;
b = (b * aa) >> 8;
col.red = (r << 8) | r;
col.green = (g << 8) | g;
col.blue = (b << 8) | b;
col.alpha = (a << 8) | a;
rect.x = x;
rect.y = y;
rect.width = w;
rect.height = h;
XCBRenderFillRectangles(rs->xcbinf->conn, XCBRenderPictOpSrc, rs->pic, col, 1, &rect);
}
void
_xr_render_surface_argb_pixels_fill(XCBrender_Surface *rs, int sw, int sh, void *pixels, int x, int y, int w, int h)
{
XCBimage_Image *xcbim;
unsigned int *p, *sp, *sple, *spe;
unsigned int jump, sjump;
unsigned int a, r, g, b, aa;
xcbim = _xr_image_new(rs->xcbinf, w, h, rs->depth);
if (!xcbim) return;
p = (unsigned int *)xcbim->data;
sp = ((unsigned int *)pixels) + (y * sw) + x;
jump = ((xcbim->line_bytes / 4) - w);
sjump = sw - w;
spe = sp + ((h - 1) * sw) + w;
if
#ifdef WORDS_BIGENDIAN
(xcbim->xcbim->image_byte_order == LSBFirst)
#else
(xcbim->xcbim->image_byte_order == MSBFirst)
#endif
{
while (sp < spe)
{
sple = sp + w;
while (sp < sple)
{
switch (a = A_VAL(sp))
{
case 0:
*p = 0;
break;
case 255:
*p = (B_VAL(sp) << 24) | (G_VAL(sp) << 16) | (R_VAL(sp) << 8) | 0xff;
break;
default:
aa = a + 1;
r = ((R_VAL(sp)) * aa) >> 8;
g = ((G_VAL(sp)) * aa) >> 8;
b = ((B_VAL(sp)) * aa) >> 8;
*p = (b << 24) | (g << 16) | (r << 8) | a;
break;
}
p++;
sp++;
}
p += jump;
sp += sjump;
}
}
else
{
while (sp < spe)
{
sple = sp + w;
while (sp < sple)
{
switch (a = A_VAL(sp))
{
case 0:
*p = 0;
break;
case 255:
*p = *sp;
break;
default:
aa = a + 1;
r = ((R_VAL(sp)) * aa) >> 8;
g = ((G_VAL(sp)) * aa) >> 8;
b = ((B_VAL(sp)) * aa) >> 8;
*p = (a << 24) | (r << 16) | (g << 8) | b;
break;
}
p++;
sp++;
}
p += jump;
sp += sjump;
}
}
_xr_image_put(xcbim, rs->draw, x, y, w, h);
}
void
_xr_render_surface_rgb_pixels_fill(XCBrender_Surface *rs, int sw, int sh, void *pixels, int x, int y, int w, int h)
{
XCBimage_Image *xcbim;
unsigned int *p, *sp, *sple, *spe;
unsigned int jump, sjump;
xcbim = _xr_image_new(rs->xcbinf, w, h, rs->depth);
if (!xcbim) return;
p = (unsigned int *)xcbim->data;
sp = ((unsigned int *)pixels) + (y * sw) + x;
jump = ((xcbim->line_bytes / 4) - w);
sjump = sw - w;
spe = sp + ((h - 1) * sw) + w;
if
#ifdef WORDS_BIGENDIAN
(xcbim->xcbim->image_byte_order == LSBFirst)
#else
(xcbim->xcbim->image_byte_order == MSBFirst)
#endif
{
while (sp < spe)
{
sple = sp + w;
while (sp < sple)
{
*p = ((B_VAL(sp)) << 24) | ((G_VAL(sp)) << 16) | ((R_VAL(sp)) << 8) | 0x000000ff;
p++;
sp++;
}
p += jump;
sp += sjump;
}
}
else
{
while (sp < spe)
{
sple = sp + w;
while (sp < sple)
{
*p = 0xff000000 | ((R_VAL(sp)) << 16) | ((G_VAL(sp)) << 8) | (B_VAL(sp));
p++;
sp++;
}
p += jump;
sp += sjump;
}
}
_xr_image_put(xcbim, rs->draw, x, y, w, h);
}
void
_xr_render_surface_clips_set(XCBrender_Surface *rs, RGBA_Draw_Context *dc, int rx, int ry, int rw, int rh)
{
int num = 0;
XCBRECTANGLE *rect = NULL;
if ((dc) && (dc->clip.use))
{
RECTS_CLIP_TO_RECT(rx, ry, rw, rh,
dc->clip.x, dc->clip.y, dc->clip.w, dc->clip.h);
}
if ((!dc) || (!dc->cutout.rects))
{
rect = malloc(sizeof(XCBRECTANGLE));
if (!rect) return;
rect->x = rx;
rect->y = ry;
rect->width = rw;
rect->height = rh;
num = 1;
}
else
{
int i;
Cutout_Rect *rects, *r;
Evas_Object_List *l;
rects = evas_common_draw_context_apply_cutouts(dc);
for (num = 0, l = (Evas_Object_List *)rects; l; l = l->next) num++;
rect = malloc(num * sizeof(XCBRECTANGLE));
if (!rect) return;
for (i = 0, l = (Evas_Object_List *)rects; l; l = l->next, i++)
{
r = (Cutout_Rect *)l;
rect[i].x = r->x;
rect[i].y = r->y;
rect[i].width = r->w;
rect[i].height = r->h;
}
evas_common_draw_context_apply_free_cutouts(rects);
}
if (!rect) return;
XCBRenderSetPictureClipRectangles(rs->xcbinf->conn, rs->pic, 0, 0, num, rect);
free(rect);
}
// when color multiplier is used want: instead
// CA src IN mask SRC temp; non-CA temp OVER dst. - i think. need to check.
void
_xr_render_surface_composite(XCBrender_Surface *srs, XCBrender_Surface *drs, RGBA_Draw_Context *dc, int sx, int sy, int sw, int sh, int x, int y, int w, int h, int smooth)
{
XCBRenderTRANSFORM xf;
XCBRenderPICTURE mask;
CARD32 value_mask;
CARD32 value_list[1];
int r, g, b, a;
int sf;
int op;
if ((sw <= 0) || (sh <= 0) || (w <= 0) || (h <= 0)) return;
sf = MAX(sw, sh);
#define BMAX 26
if (sf <= 8 ) sf = 1 << (BMAX - 3);
else if (sf <= 16 ) sf = 1 << (BMAX - 4);
else if (sf <= 32 ) sf = 1 << (BMAX - 5);
else if (sf <= 64 ) sf = 1 << (BMAX - 6);
else if (sf <= 128 ) sf = 1 << (BMAX - 7);
else if (sf <= 256 ) sf = 1 << (BMAX - 8);
else if (sf <= 512 ) sf = 1 << (BMAX - 9);
else if (sf <= 1024 ) sf = 1 << (BMAX - 10);
else if (sf <= 2048 ) sf = 1 << (BMAX - 11);
else if (sf <= 4096 ) sf = 1 << (BMAX - 12);
else if (sf <= 8192 ) sf = 1 << (BMAX - 13);
else if (sf <= 16384) sf = 1 << (BMAX - 14);
else sf = 1 << (BMAX - 15);
xf.matrix11 = (sf * sw) / w;
xf.matrix12 = 0;
xf.matrix13 = 0;
xf.matrix21 = 0;
xf.matrix22 = (sf * sh) / h;
xf.matrix23 = 0;
xf.matrix31 = 0;
xf.matrix32 = 0;
xf.matrix33 = sf;
op = XCBRenderPictOpSrc;
if (srs->alpha) op = XCBRenderPictOpOver;
mask.xid = 0;
if ((dc) && (dc->mul.use))
{
r = (int)(R_VAL(&dc->mul.col));
g = (int)(G_VAL(&dc->mul.col));
b = (int)(B_VAL(&dc->mul.col));
a = (int)(A_VAL(&dc->mul.col));
if ((r != 0xff) || (g != 0xff) || (b != 0xff) || (a != 0xff))
{
if ((srs->xcbinf->mul_r != r) || (srs->xcbinf->mul_g != g) ||
(srs->xcbinf->mul_b != b) || (srs->xcbinf->mul_a != a))
{
srs->xcbinf->mul_r = r;
srs->xcbinf->mul_g = g;
srs->xcbinf->mul_b = b;
srs->xcbinf->mul_a = a;
_xr_render_surface_solid_rectangle_set(srs->xcbinf->mul, r, g, b, a, 0, 0, 1, 1);
}
op = XCBRenderPictOpOver;
mask = srs->xcbinf->mul->pic;
}
}
XCBRenderSetPictureTransform(srs->xcbinf->conn, srs->pic, xf);
value_mask = XCBRenderCPClipMask;
value_list[0] = 0;
XCBRenderChangePicture(srs->xcbinf->conn, srs->pic, value_mask, value_list);
XCBRenderChangePicture(srs->xcbinf->conn, drs->pic, value_mask, value_list);
if (smooth) XCBRenderSetPictureFilter(srs->xcbinf->conn, srs->pic, strlen("best"), "best", 0, NULL);
else XCBRenderSetPictureFilter(srs->xcbinf->conn, srs->pic, strlen("nearest"), "nearest", 0, NULL);
_xr_render_surface_clips_set(drs, dc, x, y, w, h);
XCBRenderComposite(srs->xcbinf->conn, op, srs->pic, mask, drs->pic,
((sx * w) + (sw / 2)) / sw,
((sy * h) + (sh / 2)) / sh,
0, 0, x, y, w, h);
}
void
_xr_render_surface_copy(XCBrender_Surface *srs, XCBrender_Surface *drs, int sx, int sy, int x, int y, int w, int h)
{
XCBRenderTRANSFORM xf;
XCBRenderPICTURE mask = { 0 };
CARD32 value_mask;
CARD32 value_list[1];
if ((w <= 0) || (h <= 0)) return;
xf.matrix11 = 1;
xf.matrix12 = 0;
xf.matrix13 = 0;
xf.matrix21 = 0;
xf.matrix22 = 1;
xf.matrix23 = 0;
xf.matrix31 = 0;
xf.matrix32 = 0;
xf.matrix33 = 1;
XCBRenderSetPictureTransform(srs->xcbinf->conn, srs->pic, xf);
value_mask = XCBRenderCPClipMask;
value_list[0] = 0;
XCBRenderChangePicture(srs->xcbinf->conn, srs->pic, value_mask, value_list);
XCBRenderChangePicture(srs->xcbinf->conn, drs->pic, value_mask, value_list);
XCBRenderSetPictureFilter(srs->xcbinf->conn, srs->pic, strlen("nearest"), "nearest", 0, NULL);
XCBRenderComposite(srs->xcbinf->conn, XCBRenderPictOpSrc, srs->pic, mask, drs->pic,
sx, sy, 0, 0, x, y, w, h);
}
void
_xr_render_surface_rectangle_draw(XCBrender_Surface *rs, RGBA_Draw_Context *dc, int x, int y, int w, int h)
{
XCBRenderCOLOR col;
XCBRECTANGLE rect;
CARD32 value_mask;
CARD32 value_list[1];
int r, g, b, a, aa, op;
if ((w <= 0) || (h <= 0)) return;
a = (dc->col.col >> 24) & 0xff;
if (a == 0) return;
r = (dc->col.col >> 16) & 0xff;
g = (dc->col.col >> 8 ) & 0xff;
b = (dc->col.col ) & 0xff;
aa = a +1;
r = (r * aa) >> 8;
g = (g * aa) >> 8;
b = (b * aa) >> 8;
col.red = (r << 8) | r;
col.green = (g << 8) | g;
col.blue = (b << 8) | b;
col.alpha = (a << 8) | a;
op = XCBRenderPictOpSrc;
if (a < 0xff) op = XCBRenderPictOpOver;
value_mask = XCBRenderCPClipMask;
value_list[0] = 0;
XCBRenderChangePicture(rs->xcbinf->conn, rs->pic, value_mask, value_list);
_xr_render_surface_clips_set(rs, dc, x, y, w, h);
rect.x = x;
rect.y = y;
rect.width = w;
rect.height = h;
XCBRenderFillRectangles(rs->xcbinf->conn, op, rs->pic, col, 1, &rect);
}
void
_xr_render_surface_line_draw(XCBrender_Surface *rs, RGBA_Draw_Context *dc, int x1, int y1, int x2, int y2)
{
/* CARD32 value_mask; */
/* CARD32 value_list[1]; */
/* int op; */
/* op = XCBRenderPictOpSrc; */
/* value_mask = XCBRenderCPClipMask; */
/* value_list[0] = 0; */
/* XCBRenderChangePicture(rs->xcbinf->conn, rs->pic, value_mask, value_list); */
/* _xr_render_surface_clips_set(rs, dc, 0, 0, rs->w, rs->h); */
/* { */
/* int r, g, b, a; */
/* XPointDouble poly[4]; */
/* int dx, dy; */
/* double len, ddx, ddy; */
/* dx = x2 - x1; */
/* dy = y2 - y1; */
/* len = sqrt((double)(dx * dx) + (double)(dy * dy)); */
/* ddx = (0.5 * dx) / len; */
/* ddy = (0.5 * dy) / len; */
/* poly[0].x = (x1 + ddx); */
/* poly[0].y = (y1 - ddy); */
/* poly[1].x = (x2 + ddx); */
/* poly[1].y = (y2 - ddy); */
/* poly[2].x = (x2 - ddx); */
/* poly[2].y = (y2 + ddy); */
/* poly[3].x = (x1 - ddx); */
/* poly[3].y = (y1 + ddy); */
/* a = (dc->col.col >> 24) & 0xff; */
/* if (a == 0) return; */
/* if (a < 0xff) op = XCBRenderPictOpOver; */
/* r = (dc->col.col >> 16) & 0xff; */
/* g = (dc->col.col >> 8 ) & 0xff; */
/* b = (dc->col.col ) & 0xff; */
/* if ((rs->xcbinf->mul_r != r) || (rs->xcbinf->mul_g != g) || */
/* (rs->xcbinf->mul_b != b) || (rs->xcbinf->mul_a != a)) */
/* { */
/* rs->xcbinf->mul_r = r; */
/* rs->xcbinf->mul_g = g; */
/* rs->xcbinf->mul_b = b; */
/* rs->xcbinf->mul_a = a; */
/* _xr_render_surface_solid_rectangle_set(rs->xcbinf->mul, r, g, b, a, 0, 0, 1, 1); */
/* } */
/* XRenderCompositeDoublePoly(rs->xcbinf->conn, op, */
/* rs->xcbinf->mul->pic, rs->pic, */
/* rs->xcbinf->fmt8, 0, 0, 0, 0, */
/* poly, 4, EvenOddRule); */
/* } */
}
void
_xre_poly_draw(XCBrender_Surface *rs, RGBA_Draw_Context *dc, RGBA_Polygon_Point *points)
{
/* RGBA_Polygon_Point *pt; */
/* int i, num; */
/* XPointDouble *pts; */
/* int r, g, b, a; */
/* CARD32 value_mask; */
/* CARD32 value_list[1]; */
/* int op; */
/* op = XCBRenderPictOpSrc; */
/* num = 0; */
/* for (pt = points; pt; pt = (RGBA_Polygon_Point *)(((Evas_Object_List *)pt)->next)) num++; */
/* if (num < 3) return; */
/* a = (dc->col.col >> 24) & 0xff; */
/* if (a == 0) return; */
/* if (a < 0xff) op = XCBRenderPictOpOver; */
/* r = (dc->col.col >> 16) & 0xff; */
/* g = (dc->col.col >> 8 ) & 0xff; */
/* b = (dc->col.col ) & 0xff; */
/* if ((rs->xcbinf->mul_r != r) || (rs->xcbinf->mul_g != g) || */
/* (rs->xcbinf->mul_b != b) || (rs->xcbinf->mul_a != a)) */
/* { */
/* rs->xcbinf->mul_r = r; */
/* rs->xcbinf->mul_g = g; */
/* rs->xcbinf->mul_b = b; */
/* rs->xcbinf->mul_a = a; */
/* _xr_render_surface_solid_rectangle_set(rs->xcbinf->mul, r, g, b, a, 0, 0, 1, 1); */
/* } */
/* pts = malloc(num * sizeof(XPointDouble)); */
/* if (!pts) return; */
/* i = 0; */
/* for (pt = points; pt; pt = (RGBA_Polygon_Point *)(((Evas_Object_List *)pt)->next)) */
/* { */
/* if (i < num) */
/* { */
/* pts[i].x = pt->x; */
/* pts[i].y = pt->y; */
/* i++; */
/* } */
/* } */
/* value_mask = XCBRenderCPClipMask; */
/* value_list[0] = 0; */
/* XCBRenderChangePicture(rs->xcbinf->conn, rs->pic, value_mask, value_list); */
/* _xr_render_surface_clips_set(rs, dc, 0, 0, rs->w, rs->h); */
/* XRenderCompositeDoublePoly(rs->xcbinf->conn, op, */
/* rs->xcbinf->mul->pic, rs->pic, */
/* rs->xcbinf->fmt8, 0, 0, 0, 0, */
/* pts, num, Complex); */
/* free(pts); */
}