Brand new DirectFB engine.

ProFUSION funded the rework of DirectFB engine, it works quite well,
please report problems with it and be sure to try to uncomment the
following lines to see if it helps:

evas_engine.c: (uncomment if you notice problems)
    //#define DFB_USE_EVAS_IMAGE_DRAW 1
    //#define DFB_USE_EVAS_RECT_DRAW 1
    //#define DFB_USE_EVAS_POLYGON_DRAW 1
    //#define DFB_UPDATE_INDIVIDUAL_RECTS 1

polygon.c: (comment if you notice slowdowns, but may lead to visual problems)
    #define USE_SPAN_RECTS 1

You can also turn on debug by uncommenting in evas_engine.c:
    //#define DFB_DEBUG_IMAGE 1
    //#define DFB_DEBUG_FLAGS 1
    //#define DFB_DEBUG_ACCELERATION 1

Thanks to Denis Oliver Kropp (dok) for review and patches!



SVN revision: 35904
This commit is contained in:
Gustavo Sverzut Barbieri 2008-09-09 20:27:58 +00:00
parent d06c5e9efb
commit c1c8a18b54
8 changed files with 2037 additions and 27 deletions

View File

@ -88,9 +88,9 @@ if BUILD_ENGINE_SOFTWARE_XCB
psoftwarexcb = evas-software-xcb.pc
endif
#if BUILD_ENGINE_DIRECTFB
#pdirectfb = evas-directfb.pc
#endif
if BUILD_ENGINE_DIRECTFB
pdirectfb = evas-directfb.pc
endif
if BUILD_ENGINE_FB
pfb = evas-fb.pc

View File

@ -405,30 +405,30 @@ AM_CONDITIONAL(BUILD_ENGINE_SOFTWARE_XCB, test "x$have_evas_software_xcb" = "xye
#######################################
## Check if we should build the directfb engine
#want_evas_directfb="no";
#have_evas_directfb="no";
#
#AC_MSG_CHECKING(whether directfb backend is to be built)
#AC_ARG_ENABLE(directfb,
# AC_HELP_STRING([--enable-directfb], [enable the DirectFB rendering backend]),
# [ want_evas_directfb=$enableval ]
#)
#AC_MSG_RESULT($want_evas_directfb)
#
#if test "x$want_evas_directfb" = "xyes"; then
# PKG_CHECK_MODULES(DIRECTFB, directfb >= 0.9.16,
# [
# AC_DEFINE(BUILD_ENGINE_DIRECTFB, 1, [DirectFB Rendering Backend])
# have_evas_directfb="yes"
# ],
# [
# if test "x$want_evas_directfb" = "xyes" -a "x$use_strict" = "xyes" ; then
# AC_MSG_ERROR([DirectFB not found (strict dependencies checking)])
# fi
# ]
# )
#fi
#AM_CONDITIONAL(BUILD_ENGINE_DIRECTFB, test "x$have_evas_directfb" = "xyes")
want_evas_directfb="no";
have_evas_directfb="no";
AC_MSG_CHECKING(whether directfb backend is to be built)
AC_ARG_ENABLE(directfb,
AC_HELP_STRING([--enable-directfb], [enable the DirectFB rendering backend]),
[ want_evas_directfb=$enableval ]
)
AC_MSG_RESULT($want_evas_directfb)
if test "x$want_evas_directfb" = "xyes"; then
PKG_CHECK_MODULES(DIRECTFB, directfb >= 0.9.16,
[
AC_DEFINE(BUILD_ENGINE_DIRECTFB, 1, [DirectFB Rendering Backend])
have_evas_directfb="yes"
],
[
if test "x$want_evas_directfb" = "xyes" -a "x$use_strict" = "xyes" ; then
AC_MSG_ERROR([DirectFB not found (strict dependencies checking)])
fi
]
)
fi
AM_CONDITIONAL(BUILD_ENGINE_DIRECTFB, test "x$have_evas_directfb" = "xyes")
#######################################
## Check if we should build the sdl engine
@ -1653,6 +1653,7 @@ AC_SUBST(pthread_libs)
AC_OUTPUT([
Makefile
evas-cairo-x11.pc
evas-directfb.pc
evas-fb.pc
evas-glitz-x11.pc
evas-opengl-glew.pc
@ -1698,6 +1699,7 @@ src/modules/engines/fb/Makefile
src/modules/engines/buffer/Makefile
src/modules/engines/software_win32_gdi/Makefile
src/modules/engines/software_qtopia/Makefile
src/modules/engines/directfb/Makefile
src/modules/engines/gl_common/Makefile
src/modules/engines/gl_glew/Makefile
src/modules/engines/gl_x11/Makefile
@ -1764,6 +1766,7 @@ echo " Software 16bit X11.........: $have_evas_software_16_x11"
echo " Software 16bit Directdraw..: $have_evas_software_16_ddraw"
echo " Software 16bit WinCE.......: $have_evas_software_16_wince"
echo " Software 16bit SDL.........: $have_evas_sdl (primitive: $sdl_primitive)"
echo " DirectFB...................: $have_evas_directfb"
# FIXME: opengl engine needs to be fixed and tested lots for all drivers
# FIXME: xrender engine to be written
echo

View File

@ -5,6 +5,7 @@ software_generic \
buffer \
cairo_common \
cairo_x11 \
directfb \
fb \
gl_common \
gl_x11 \

View File

@ -0,0 +1,22 @@
#ifndef _EVAS_ENGINE_DIRECTFB_H
#define _EVAS_ENGINE_DIRECTFB_H
#include <Evas.h>
#include <directfb/directfb.h>
typedef struct _Evas_Engine_Info_DirectFB Evas_Engine_Info_DirectFB;
struct _Evas_Engine_Info_DirectFB
{
/* PRIVATE - don't mess with this baby or evas will poke its tongue out */
/* at you and make nasty noises */
Evas_Engine_Info magic;
struct Evas_Engine_DirectFB_Spec {
IDirectFB *dfb;
IDirectFBSurface *surface;
} info;
};
#endif

View File

@ -0,0 +1,31 @@
MAINTAINERCLEANFILES = Makefile.in
AM_CPPFLAGS = \
-I. \
-I$(top_srcdir)/src/lib \
-I$(top_srcdir)/src/lib/include \
-I$(top_srcdir)/src/modules/engines \
@FREETYPE_CFLAGS@ \
@DIRECTFB_CFLAGS@
AM_CFLAGS = @WIN32_CFLAGS@
if BUILD_ENGINE_DIRECTFB
pkgdir = $(libdir)/evas/modules/engines/directfb/$(MODULE_ARCH)
pkg_LTLIBRARIES = module.la
module_la_SOURCES = evas_engine.c polygon.c
module_la_LIBADD = @DIRECTFB_LIBS@ $(top_builddir)/src/lib/libevas.la
module_la_LDFLAGS = @lt_no_undefined@ -module -avoid-version
module_la_LIBTOOLFLAGS = --tag=disable-static
module_la_DEPENDENCIES = $(top_builddir)/config.h
include_HEADERS = Evas_Engine_DirectFB.h
endif
EXTRA_DIST = evas_engine.h

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,44 @@
#ifndef EVAS_ENGINE_DIRECTFB_H
#define EVAS_ENGINE_DIRECTFB_H
#include "evas_common.h"
#include "evas_private.h"
#include "Evas_Engine_DirectFB.h"
typedef struct _DirectFB_Engine_Image_Entry DirectFB_Engine_Image_Entry;
struct _DirectFB_Engine_Image_Entry
{
Engine_Image_Entry cache_entry;
IDirectFBSurface *surface;
struct
{
Evas_Bool engine_surface : 1;
Evas_Bool is_locked : 1;
} flags;
};
typedef struct _Render_Engine Render_Engine;
struct _Render_Engine
{
DirectFB_Engine_Image_Entry *screen_image;
const struct Evas_Engine_DirectFB_Spec *spec;
IDirectFB *dfb;
Evas_Cache_Engine_Image *cache;
Tilebuf *tb;
Tilebuf_Rect *rects;
Evas_Object_List *cur_rect;
DFBRegion *update_regions;
unsigned int update_regions_count;
unsigned int update_regions_limit;
Evas_Bool end : 1;
};
int _dfb_surface_set_color_from_context(IDirectFBSurface *surface, RGBA_Draw_Context *dc);
void _dfb_polygon_draw(IDirectFBSurface *surface, RGBA_Draw_Context *dc, Evas_Object_List *points);
#endif

View File

@ -0,0 +1,270 @@
#include <math.h>
#include "evas_engine.h"
/* Work around bug in DirectFB FillSpans(), but uses twice as much memory */
#define USE_SPAN_RECTS 1
#define MAX_SPANS 512
typedef struct _RGBA_Edge RGBA_Edge;
typedef struct _RGBA_Vertex RGBA_Vertex;
struct _RGBA_Edge
{
double x, dx;
int i;
};
struct _RGBA_Vertex
{
double x, y;
int i;
};
#define POLY_EDGE_DEL(_i) \
{ \
int _j; \
\
for (_j = 0; (_j < num_active_edges) && (edges[_j].i != _i); _j++); \
if (_j < num_active_edges) \
{ \
num_active_edges--; \
memmove(&(edges[_j]), &(edges[_j + 1]), \
(num_active_edges - _j) * sizeof(RGBA_Edge)); \
} \
}
#define POLY_EDGE_ADD(_i, _y) \
{ \
int _j; \
float _dx; \
RGBA_Vertex *_p, *_q; \
if (_i < (n - 1)) _j = _i + 1; \
else _j = 0; \
if (point[_i].y < point[_j].y) \
{ \
_p = &(point[_i]); \
_q = &(point[_j]); \
} \
else \
{ \
_p = &(point[_j]); \
_q = &(point[_i]); \
} \
edges[num_active_edges].dx = _dx = (_q->x - _p->x) / (_q->y - _p->y); \
edges[num_active_edges].x = (_dx * ((float)_y + 0.5 - _p->y)) + _p->x; \
edges[num_active_edges].i = _i; \
num_active_edges++; \
}
static int
polygon_point_sorter(const void *a, const void *b)
{
RGBA_Vertex *p, *q;
p = (RGBA_Vertex *)a;
q = (RGBA_Vertex *)b;
if (p->y <= q->y) return -1;
return 1;
}
static int
polygon_edge_sorter(const void *a, const void *b)
{
RGBA_Edge *p, *q;
p = (RGBA_Edge *)a;
q = (RGBA_Edge *)b;
if (p->x <= q->x) return -1;
return 1;
}
#ifndef USE_SPAN_RECTS
typedef DFBSpan span_t;
static void
polygon_span_add(span_t *span, int y, int x, int w)
{
span->x = x;
span->w = w;
}
static void
polygon_spans_fill(IDirectFBSurface *surface, int y, const span_t *spans, int n_spans)
{
surface->FillSpans(surface, y, spans, n_spans);
}
#else /* USE_SPAN_RECTS */
typedef DFBRectangle span_t;
static void
polygon_span_add(span_t *span, int y, int x, int w)
{
span->x = x;
span->y = y;
span->w = w;
span->h = 1;
}
static void
polygon_spans_fill(IDirectFBSurface *surface, int y, const span_t *spans, int n_spans)
{
surface->FillRectangles(surface, spans, n_spans);
}
#endif /* USE_SPAN_RECTS */
void
_dfb_polygon_draw(IDirectFBSurface *surface, RGBA_Draw_Context *dc, Evas_Object_List *points)
{
RGBA_Polygon_Point *pt;
RGBA_Vertex *point;
RGBA_Edge *edges;
Evas_Object_List *l;
int num_active_edges;
int n;
int i, j, k;
int y0, y1, y;
int ext_x, ext_y, ext_w, ext_h;
int *sorted_index;
ext_x = 0;
ext_y = 0;
surface->GetSize(surface, &ext_w, &ext_h);
if (dc->clip.use)
{
if (dc->clip.x > ext_x)
{
ext_w += ext_x - dc->clip.x;
ext_x = dc->clip.x;
}
if ((ext_x + ext_w) > (dc->clip.x + dc->clip.w))
{
ext_w = (dc->clip.x + dc->clip.w) - ext_x;
}
if (dc->clip.y > ext_y)
{
ext_h += ext_y - dc->clip.y;
ext_y = dc->clip.y;
}
if ((ext_y + ext_h) > (dc->clip.y + dc->clip.h))
{
ext_h = (dc->clip.y + dc->clip.h) - ext_y;
}
}
if ((ext_w <= 0) || (ext_h <= 0)) return;
evas_common_cpu_end_opt();
if (!_dfb_surface_set_color_from_context(surface, dc))
return;
n = 0; for (l = (Evas_Object_List *)points; l; l = l->next) n++;
if (n < 3) return;
edges = malloc(sizeof(RGBA_Edge) * n);
if (!edges) return;
point = malloc(sizeof(RGBA_Vertex) * n);
if (!point)
{
free(edges);
return;
}
sorted_index = malloc(sizeof(int) * n);
if (!sorted_index)
{
free(edges);
free(point);
return;
}
k = 0;
for (l = (Evas_Object_List *)points; l; l = l->next)
{
pt = (RGBA_Polygon_Point *)l;
point[k].x = pt->x;
point[k].y = pt->y;
point[k].i = k;
k++;
}
qsort(point, n, sizeof(RGBA_Vertex), polygon_point_sorter);
for (k = 0; k < n; k++) sorted_index[k] = point[k].i;
k = 0;
for (l = (Evas_Object_List *)points; l; l = l->next)
{
pt = (RGBA_Polygon_Point *)l;
point[k].x = pt->x;
point[k].y = pt->y;
point[k].i = k;
k++;
}
y0 = MAX(ext_y, ceil(point[sorted_index[0]].y - 0.5));
y1 = MIN(ext_y + ext_h - 1, floor(point[sorted_index[n - 1]].y - 0.5));
k = 0;
num_active_edges = 0;
for (y = y0; y <= y1; y++)
{
span_t spans[MAX_SPANS];
unsigned int n_spans = 0;
for (; (k < n) && (point[sorted_index[k]].y <= ((double)y + 0.5)); k++)
{
i = sorted_index[k];
if (i > 0) j = i - 1;
else j = n - 1;
if (point[j].y <= ((double)y - 0.5))
{
POLY_EDGE_DEL(j)
}
else if (point[j].y > ((double)y + 0.5))
{
POLY_EDGE_ADD(j, y)
}
if (i < (n - 1)) j = i + 1;
else j = 0;
if (point[j].y <= ((double)y - 0.5))
{
POLY_EDGE_DEL(i)
}
else if (point[j].y > ((double)y + 0.5))
{
POLY_EDGE_ADD(i, y)
}
}
qsort(edges, num_active_edges, sizeof(RGBA_Edge), polygon_edge_sorter);
for (j = 0; j < num_active_edges; j += 2)
{
int x0, x1;
x0 = ceil(edges[j].x - 0.5);
if (j < (num_active_edges - 1))
x1 = floor(edges[j + 1].x - 0.5);
else
x1 = x0;
if ((x1 >= ext_x) && (x0 < (ext_x + ext_w)) && (x0 <= x1))
{
if (n_spans == MAX_SPANS)
{
polygon_spans_fill(surface, y, spans, n_spans);
n_spans = 0;
}
polygon_span_add(spans + n_spans, y, x0, (x1 - x0) + 1);
n_spans++;
}
edges[j].x += edges[j].dx;
edges[j + 1].x += edges[j + 1].dx;
}
if (n_spans)
polygon_spans_fill(surface, y, spans, n_spans);
}
free(edges);
free(point);
free(sorted_index);
}