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

View File

@ -5,6 +5,7 @@ software_generic \
buffer \ buffer \
cairo_common \ cairo_common \
cairo_x11 \ cairo_x11 \
directfb \
fb \ fb \
gl_common \ gl_common \
gl_x11 \ 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);
}