diff options
author | Michael Emmel <mike.emmel@gmail.com> | 2005-12-29 07:17:01 +0000 |
---|---|---|
committer | Michael Emmel <mike.emmel@gmail.com> | 2005-12-29 07:17:01 +0000 |
commit | 23e5e558414cbbb5e20a6b8b5e68f21c6a3ed15d (patch) | |
tree | 6295142921376468016b15fcd236bd49047d56bd | |
parent | f7236b84603c45d9c67cc5dfed6305a8a1241f6c (diff) |
New directfb backend for cairo includes test suite and example to run the test is in the comment at the top of cairo-test-directfb.c enable with
--enable-directfb
-rw-r--r-- | configure.in | 25 | ||||
-rw-r--r-- | src/Makefile.am | 9 | ||||
-rw-r--r-- | src/cairo-directfb-surface.c | 804 | ||||
-rw-r--r-- | src/cairo-directfb.h | 60 | ||||
-rw-r--r-- | src/cairo-features.h.in | 2 | ||||
-rw-r--r-- | test/Makefile.am | 4 | ||||
-rw-r--r-- | test/cairo-test-directfb.c | 127 | ||||
-rw-r--r-- | test/cairo-test-directfb.h | 23 | ||||
-rw-r--r-- | test/cairo-test.c | 11 |
9 files changed, 1064 insertions, 1 deletions
diff --git a/configure.in b/configure.in index ed560a904..a5e55fbce 100644 --- a/configure.in +++ b/configure.in @@ -322,6 +322,26 @@ AC_SUBST(GLITZ_REQUIRES) dnl =========================================================================== +AC_ARG_ENABLE(directfb, + [ --enable-directfb Enable cairo's directfb backend], + [use_directfb=$enableval], [use_directfb=no]) + +if test "x$use_directfb" = "xyes"; then + PKG_CHECK_MODULES(DIRECTFB, directfb, [use_directfb=yes], [ + use_directfb="no (requires directfb http://www.directfb.org)"]) +fi + +AM_CONDITIONAL(CAIRO_HAS_DIRECTFB_SURFACE, test "x$use_directfb" = "xyes") +if test "x$use_directfb" = "xyes"; then + DIRECTFB_SURFACE_FEATURE="#define CAIRO_HAS_DIRECTFB_SURFACE 1" +fi +AC_SUBST(DIRECTFB_SURFACE_FEATURE) + +CAIRO_CFLAGS="$CAIRO_CFLAGS $DIRECTFB_CFLAGS" +CAIRO_LIBS="$CAIRO_LIBS $DIRECTFB_LIBS" + +dnl =========================================================================== + AC_ARG_ENABLE(freetype, [ --disable-freetype Disable cairo's freetype font backend], [use_freetype=$enableval], [use_freetype=yes]) @@ -733,6 +753,7 @@ echo " PDF: $use_pdf" echo " SVG: $use_svg" echo " glitz: $use_glitz" echo " BeOS: $use_beos" +echo " DirectFB: $use_directfb" echo "" echo "the following font backends:" echo " FreeType: $use_freetype" @@ -786,3 +807,7 @@ fi if test x"$use_beos" = "xyes" ; then echo "$WARNING_MESSAGE" | sed 's/@BACKEND@/BeOS/' fi + +if test x"$use_directfb" == "xyes" ; then + echo "$WARNING_MESSAGE" | sed 's/@BACKEND@/DirectFB/' +fi diff --git a/src/Makefile.am b/src/Makefile.am index 4a4a139fc..4d31f349e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -73,6 +73,11 @@ libcairo_ft_headers = cairo-ft.h libcairo_ft_sources = cairo-ft-font.c cairo-ft-private.h endif +if CAIRO_HAS_DIRECTFB_SURFACE +libcairo_directfb_headers = cairo-directfb.h +libcairo_directfb_sources = cairo-directfb-surface.c +endif + # Headers that declare the functions in the cairo DLL API on Windows cairo_win32_api_headers = \ $(srcdir)/cairo.h \ @@ -112,7 +117,8 @@ cairoinclude_HEADERS = \ $(libcairo_win32_headers) \ $(libcairo_beos_headers) \ $(libcairo_xcb_headers) \ - $(libcairo_xlib_headers) + $(libcairo_xlib_headers) \ + $(libcairo_directfb_headers) lib_LTLIBRARIES = libcairo.la @@ -181,6 +187,7 @@ libcairo_la_SOURCES = \ $(libcairo_glitz_sources) \ $(libcairo_win32_sources) \ $(libcairo_beos_sources) \ + $(libcairo_directfb_sources) \ cairoint.h libcairo_la_LDFLAGS = -version-info @VERSION_INFO@ -no-undefined $(export_symbols) diff --git a/src/cairo-directfb-surface.c b/src/cairo-directfb-surface.c new file mode 100644 index 000000000..be1791584 --- /dev/null +++ b/src/cairo-directfb-surface.c @@ -0,0 +1,804 @@ +/* cairo - a vector graphics library with display and print output + * + * Copyright © 2003 University of Southern California + * + * This library is free software; you can redistribute it and/or + * modify it either under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation + * (the "LGPL") or, at your option, under the terms of the Mozilla + * Public License Version 1.1 (the "MPL"). If you do not alter this + * notice, a recipient may use your version of this file under either + * the MPL or the LGPL. + * + * You should have received a copy of the LGPL along with this library + * in the file COPYING-LGPL-2.1; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the MPL along with this library + * in the file COPYING-MPL-1.1 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY + * OF ANY KIND, either express or implied. See the LGPL or the MPL for + * the specific language governing rights and limitations. + * + * The Original Code is the cairo graphics library. + * + * The Initial Developer of the Original Code is University of Southern + * California. + * + * Contributor(s): + * Michael Emmel <mike.emmel@gmail.com> + */ +#include <stdio.h> +#include <directfb.h> +#include "cairo-directfb.h" +#include "cairoint.h" + +#define DFB_UNSUPPORTED -1 +#define DFB_SUPPORTED 1 + +/* +Glyph support not working +*/ +#define DFB_SHOW_GLYPHS 0 +/* +Composite support not working +*/ +#define DFB_COMPOSITE 0 + + +#if DFB_SHOW_GLYPHS +static cairo_int_status_t +_cairo_directfb_surface_show_glyphs (cairo_scaled_font_t *scaled_font, + cairo_operator_t operator, + cairo_pattern_t *pattern, + void *abstract_surface, + int source_x, + int source_y, + int dest_x, + int dest_y, + unsigned int width, + unsigned int height, + const cairo_glyph_t *glyphs, + int num_glyphs); +#endif + +typedef struct _cairo_directfb_surface { + cairo_surface_t base; + cairo_format_t format; + IDirectFB *dfb; + IDirectFBSurface *main_surface; + IDirectFBSurface *buffer; + pixman_region16_t *clip; + cairo_surface_t *buffer_image; + void *buffer_data; + int width; + int height; +} cairo_directfb_surface_t; + + +static int +_dfb_set_operator (cairo_operator_t operator,IDirectFBSurface *dest) +{ + dest->SetDrawingFlags(dest,DSDRAW_BLEND); + dest->SetPorterDuff(dest,DSPD_NONE); + switch (operator) { + case CAIRO_OPERATOR_CLEAR: + dest->SetPorterDuff(dest,DSPD_CLEAR); + break; + case CAIRO_OPERATOR_SOURCE: + dest->SetPorterDuff(dest,DSPD_SRC); + break; + case CAIRO_OPERATOR_OVER: + dest->SetPorterDuff(dest,DSPD_SRC_OVER); + break; + case CAIRO_OPERATOR_IN: + dest->SetPorterDuff(dest,DSPD_SRC_IN); + break; + case CAIRO_OPERATOR_OUT: + dest->SetPorterDuff(dest,DSPD_SRC_OUT); + break; + case CAIRO_OPERATOR_DEST_OVER: + dest->SetPorterDuff(dest,DSPD_DST_OVER); + break; + case CAIRO_OPERATOR_DEST_IN: + dest->SetPorterDuff(dest,DSPD_DST_IN); + break; + case CAIRO_OPERATOR_DEST_OUT: + dest->SetPorterDuff(dest,DSPD_DST_OUT); + break; + + /*not sure about these yet */ + case CAIRO_OPERATOR_ATOP: + return DFB_UNSUPPORTED; + break; + case CAIRO_OPERATOR_DEST: + return DFB_UNSUPPORTED; + break; + case CAIRO_OPERATOR_DEST_ATOP: + return DFB_UNSUPPORTED; + break; + case CAIRO_OPERATOR_XOR: + dest->SetDrawingFlags(dest,DSDRAW_XOR); + break; + case CAIRO_OPERATOR_ADD: + return DFB_UNSUPPORTED; + break; + case CAIRO_OPERATOR_SATURATE: + return DFB_UNSUPPORTED; + break; + default: + return DFB_UNSUPPORTED; + } + return DFB_SUPPORTED; +} + + +static inline int cairo_to_directfb_format(cairo_format_t format ) { + switch( format ) { + case CAIRO_FORMAT_RGB24: + return DSPF_RGB24; + case CAIRO_FORMAT_ARGB32: + return DSPF_ARGB; + case CAIRO_FORMAT_A8: + return DSPF_A8; + case CAIRO_FORMAT_A1: + return DSPF_A1; + default: + { + //assert(0); + return DSPF_UNKNOWN; + } + } +} + +static inline int directfb_to_cairo_format(DFBSurfacePixelFormat dfbformat ) { + switch( dfbformat ) { + case DSPF_RGB24 : + case DSPF_RGB32 : + return CAIRO_FORMAT_RGB24; + break; + case DSPF_AiRGB : + case DSPF_ARGB : + return CAIRO_FORMAT_ARGB32; + break; + case DSPF_A8 : + return CAIRO_FORMAT_A8; + break; + case DSPF_A1 : + return CAIRO_FORMAT_A1; + break; + case DSPF_UNKNOWN : + case DSPF_ARGB1555 : + case DSPF_RGB16 : + case DSPF_YUY2 : + case DSPF_RGB332 : + case DSPF_UYVY : + case DSPF_I420 : + case DSPF_ALUT44 : + case DSPF_NV12 : + case DSPF_NV16 : + default : + return DFB_UNSUPPORTED; + } +} + + +static IDirectFBSurface *cairo_directfb_buffer_surface_create(IDirectFB *dfb,void *data,int pitch, int format, + int width, int height) { + + DFBResult ret; + IDirectFBSurface *buffer; + DFBSurfaceDescription dsc; + + dsc.flags = DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT; + dsc.caps = DSCAPS_NONE; + dsc.width = width; + dsc.height = height; + dsc.pixelformat = format; + if( data ) { + dsc.flags |= DSDESC_CAPS; + dsc.flags |= DSDESC_PREALLOCATED; + dsc.caps = DSCAPS_NONE; + dsc.preallocated[0].data = data; + dsc.preallocated[0].pitch = pitch; + dsc.preallocated[1].data = NULL; + dsc.preallocated[1].pitch = 0; + } + + ret =dfb->CreateSurface (dfb, &dsc, &buffer); + if (ret) { + DirectFBError ("cairo_directfb_buffer_surface_create failed ", ret); + assert(0); + return NULL; + } +#if 0 + { + DFBSurfacePixelFormat dfbformat; + int nwidth=0; + int nheight=0; + int npitch; + void *ndata; + buffer->GetSize(buffer,&nwidth,&nheight); + buffer->GetPixelFormat(buffer,&dfbformat); + buffer->Lock(buffer,DSLF_READ,&ndata,&npitch); + buffer->Unlock(buffer); + assert( ( nwidth == width) && (nheight == height)); + } +#endif + return buffer; +} + +static cairo_status_t +_cairo_directfb_surface_get_image (cairo_directfb_surface_t *surface, + cairo_rectangle_t *interest, + cairo_image_surface_t **image_out, + cairo_rectangle_t *rect_out, + DFBSurfaceLockFlags flags) +{ + int pitch; + void *data; + + (void)interest; + if( surface->buffer->Lock(surface->buffer,flags,&data,&pitch) != DFB_OK ) + return CAIRO_STATUS_NO_MEMORY; + + /*lock the dest agianst other changes*/ + if( surface->buffer_image ) { + if( surface->buffer_data == data ) { + cairo_surface_reference(surface->buffer_image); + } + } + + if( surface->buffer_data != data ){ + /* new off screen buffer */ + int width; + int height; + DFBSurfacePixelFormat dfbformat; + /*surface moved free image if allocated */ + if( surface->buffer_image ) { + cairo_surface_destroy (surface->buffer_image); + surface->buffer_image=NULL; + surface->buffer_data=NULL; + } + surface->buffer->Unlock(surface->buffer); + + + surface->main_surface->GetSize(surface->main_surface,&width,&height); + surface->main_surface->GetPixelFormat(surface->main_surface,&dfbformat); + surface->format = directfb_to_cairo_format(dfbformat); + + if( surface->format == DFB_UNSUPPORTED ) { + surface->format = CAIRO_FORMAT_ARGB32; + surface->buffer = cairo_directfb_buffer_surface_create(surface->dfb,NULL, + 0,DSPF_ARGB,width,height); + if( !surface->buffer ) + return CAIRO_STATUS_NO_MEMORY; + /*Have to flip the main surface if its double buffered to blit the buffer*/ + surface->main_surface->Flip(surface->main_surface,NULL,0); + surface->buffer->Blit(surface->buffer,surface->main_surface,NULL,0,0); + }else { + surface->buffer = surface->main_surface; + } + + surface->width=width; + surface->height=height; + + if( surface->buffer->Lock(surface->buffer,flags,&data,&pitch) != DFB_OK ) + return CAIRO_STATUS_NO_MEMORY; + + surface->buffer_data = data; + surface->buffer_image = cairo_image_surface_create_for_data ( + (unsigned char *)data,surface->format,width, height, pitch); + if( surface->buffer_image == NULL ) { + surface->buffer->Release(surface->buffer); + surface->buffer = NULL; + surface->buffer_data = NULL; + return CAIRO_STATUS_NO_MEMORY; + } + #if 0 + if( surface->clip) + _cairo_image_surface_set_clip_region ( + (cairo_image_surface_t *)surface->buffer_image,surface->clip); + #endif + } + + if (rect_out) { + rect_out->x = 0; + rect_out->y = 0; + rect_out->width = surface->width; + rect_out->height = surface->height; + } + if( image_out ) + *image_out=(cairo_image_surface_t *)surface->buffer_image; + return CAIRO_STATUS_SUCCESS; +} + + +static cairo_surface_t * +_cairo_directfb_surface_create_similar (void *abstract_src, + cairo_content_t content, + int width, + int height) +{ + cairo_format_t format = _cairo_format_from_content (content); + int dfbformat; + switch( content ) { + case CAIRO_CONTENT_COLOR: + dfbformat=DSPF_ARGB; + break; + case CAIRO_CONTENT_ALPHA: + dfbformat=DSPF_A8; + break; + case CAIRO_CONTENT_COLOR_ALPHA: + dfbformat= DSPF_ARGB; + break; + default: + { + return cairo_image_surface_create (format, width, height); + } + } + cairo_directfb_surface_t *src = abstract_src; + IDirectFBSurface *buffer =cairo_directfb_buffer_surface_create(src->dfb, + NULL,0,dfbformat,width,height); + cairo_surface_t *sur =cairo_directfb_surface_create (src->dfb,buffer); + ((cairo_directfb_surface_t *)sur)->format = format; + return sur; +} + + +static cairo_status_t +_cairo_directfb_surface_finish (void *data ) { + cairo_directfb_surface_t *surface=(cairo_directfb_surface_t *)data; + if( surface->buffer_image ) + cairo_surface_destroy (surface->buffer_image); + if (surface->clip) + pixman_region_destroy (surface->clip); + + if( surface->main_surface != surface->buffer ) { + surface->main_surface->SetClip (surface->main_surface,NULL); + surface->main_surface->Blit(surface->main_surface,surface->buffer,NULL,0,0); + surface->buffer->Release (surface->buffer); + surface->buffer=NULL; + } +#if 0 /* No don't do this */ + surface->main_surface->Flip(surface->main_surface,NULL,0); +#endif + surface->main_surface->Release (surface->main_surface); + surface->main_surface=NULL; + surface->dfb->Release(surface->dfb); + surface->dfb=NULL; + return CAIRO_STATUS_SUCCESS; +} + +static cairo_status_t +_cairo_directfb_surface_acquire_source_image (void *abstract_surface, + cairo_image_surface_t **image_out, + void **image_extra) +{ + cairo_directfb_surface_t *surface = abstract_surface; + *image_extra = surface; + return _cairo_directfb_surface_get_image (surface, NULL,image_out,NULL,DSLF_READ); +} + + static void +_cairo_directfb_surface_release_source_image (void *abstract_surface, + cairo_image_surface_t *image, + void *image_extra) +{ + cairo_directfb_surface_t *surface = abstract_surface; + surface->buffer->Unlock(surface->buffer); +} + + static cairo_status_t +_cairo_directfb_surface_acquire_dest_image (void *abstract_surface, + cairo_rectangle_t *interest_rect, + cairo_image_surface_t **image_out, + cairo_rectangle_t *image_rect_out, + void **image_extra) +{ + cairo_directfb_surface_t *surface = abstract_surface; + *image_extra = interest_rect; + return _cairo_directfb_surface_get_image (surface, interest_rect,image_out, + image_rect_out,DSLF_READ|DSLF_WRITE); +} + +static void +_cairo_directfb_surface_release_dest_image (void *abstract_surface, + cairo_rectangle_t *interest_rect, + cairo_image_surface_t *image, + cairo_rectangle_t *image_rect, + void *image_extra) +{ + cairo_directfb_surface_t *surface = abstract_surface; + IDirectFBSurface *buffer=surface->buffer; + buffer->Unlock(buffer); +} + +static cairo_status_t +_cairo_directfb_surface_clone_similar (void *abstract_surface, + cairo_surface_t *src, + cairo_surface_t **clone_out) +{ + cairo_directfb_surface_t *surface = abstract_surface; + cairo_directfb_surface_t *clone; + + if (src->backend == surface->base.backend) { + *clone_out = src; + cairo_surface_reference (src); + return CAIRO_STATUS_SUCCESS; + } else if (_cairo_surface_is_image (src)) { + cairo_image_surface_t *image_src = (cairo_image_surface_t *) src; + clone = (cairo_directfb_surface_t *) + _cairo_directfb_surface_create_similar (surface, image_src->format, + image_src->width, + image_src->height); + if (!clone) + return CAIRO_STATUS_NO_MEMORY; + IDirectFBSurface *tmpbuffer; + int format = cairo_to_directfb_format(image_src->format); + tmpbuffer =cairo_directfb_buffer_surface_create(surface->dfb, + (void *)image_src->data,image_src->stride,format, + image_src->width,image_src->height); + + if (!tmpbuffer){ + cairo_surface_destroy((cairo_surface_t *)surface); + return CAIRO_STATUS_NO_MEMORY; + } + clone->buffer->Blit(clone->buffer,tmpbuffer,NULL,0,0); + tmpbuffer->Release(tmpbuffer); + *clone_out = &clone->base; + return CAIRO_STATUS_SUCCESS; + } + return CAIRO_INT_STATUS_UNSUPPORTED; +} + +#if DFB_COMPOSITE +static cairo_int_status_t +_cairo_directfb_surface_composite (cairo_operator_t op, + cairo_pattern_t *src_pattern, + cairo_pattern_t *mask_pattern, + void *abstract_dst, + int src_x, + int src_y, + int mask_x, + int mask_y, + int dst_x, + int dst_y, + unsigned int width, + unsigned int height) +{ + cairo_directfb_surface_t *dst = abstract_dst; + cairo_directfb_surface_t *src; + cairo_surface_pattern_t *src_surface_pattern; + int alpha; + int integer_transform; + int itx, ity; + + cairo_directfb_surface_t *surface = abstract_dst; + if( _dfb_set_operator(op,surface->buffer) == DFB_UNSUPPORTED ) + return CAIRO_INT_STATUS_UNSUPPORTED; + + if (src_pattern->type == CAIRO_PATTERN_SOLID ) { + + } else if (src_pattern->type != CAIRO_PATTERN_SURFACE || + src_pattern->extend != CAIRO_EXTEND_NONE) { + return CAIRO_INT_STATUS_UNSUPPORTED; + } + + if (mask_pattern) { + /* FIXME: When we fully support RENDER style 4-channel + * masks we need to check r/g/b != 1.0. + */ + if (mask_pattern->type != CAIRO_PATTERN_SOLID) + return CAIRO_INT_STATUS_UNSUPPORTED; + + alpha = ((cairo_solid_pattern_t *)mask_pattern)->color.alpha_short >> 8; + } else { + alpha = 255; + } + + src_surface_pattern = (cairo_surface_pattern_t *)src_pattern; + src = (cairo_directfb_surface_t *)src_surface_pattern->surface; + + if (src->base.backend != dst->base.backend){ + return CAIRO_INT_STATUS_UNSUPPORTED; + } + + integer_transform = _cairo_matrix_is_integer_translation (&src_pattern->matrix, &itx, &ity); + if (!integer_transform) { + return CAIRO_INT_STATUS_UNSUPPORTED; + } + surface->buffer->SetPorterDuff(surface->buffer,DSPD_NONE); + return CAIRO_INT_STATUS_UNSUPPORTED; +} +#endif + +static cairo_int_status_t +_cairo_directfb_surface_fill_rectangles (void *abstract_surface, + cairo_operator_t op, + const cairo_color_t *color, + cairo_rectangle_t *rects, + int n_rects) +{ + int i,k; + cairo_directfb_surface_t *surface = abstract_surface; + IDirectFBSurface *buffer = surface->buffer; + + if( _dfb_set_operator(op,buffer) == DFB_UNSUPPORTED ) { + return CAIRO_INT_STATUS_UNSUPPORTED; + } + + buffer->SetColor(buffer,color->red_short >> 8, + color->green_short >> 8, + color->blue_short >> 8, + color->alpha_short >> 8 ); + /*Not optimized not sure of the sorting on region*/ + if( surface->clip ) { + DFBRegion region; + int n_boxes = pixman_region_num_rects (surface->clip); + pixman_box16_t *boxes = pixman_region_rects (surface->clip); + for( k = 0; k < n_boxes; k++ ) { + region.x1 = boxes[k].x1; + region.y1 = boxes[k].y1; + region.x2 = boxes[k].x2; + region.y2 = boxes[k].y2; + buffer->SetClip (buffer,®ion); + for (i = 0; i < n_rects; i++) { + buffer->FillRectangle(buffer,rects[i].x,rects[i].y, + rects[i].width,rects[i].height); + } + } + buffer->SetClip (buffer, NULL); + }else { + buffer->SetClip (buffer, NULL); + for (i = 0; i < n_rects; i++) { + buffer->FillRectangle(buffer,rects[i].x,rects[i].y, + rects[i].width,rects[i].height); + } + } + return CAIRO_STATUS_SUCCESS; +} + +static cairo_int_status_t +_cairo_directfb_surface_set_clip_region (void *abstract_surface, + pixman_region16_t *region) +{ + cairo_directfb_surface_t *surface = abstract_surface; + if( region == NULL ) { + pixman_region_destroy (surface->clip); + surface->clip = NULL; + }else { + if (!surface->clip) { + surface->clip = pixman_region_create (); + if (!surface->clip) + return CAIRO_STATUS_NO_MEMORY; + } + pixman_region_copy (surface->clip, region); + } +#if 0 + if( surface->buffer_image ) + _cairo_image_surface_set_clip_region ( + (cairo_image_surface_t *)surface->buffer_image,region); +#endif + + return CAIRO_STATUS_SUCCESS; +} + +static cairo_int_status_t +_cairo_directfb_abstract_surface_get_extents (void *abstract_surface, + cairo_rectangle_t *rectangle) +{ + if( rectangle ) { + cairo_directfb_surface_t *surface = abstract_surface; + rectangle->x = 0; + rectangle->y = 0; + rectangle->width = surface->width; + rectangle->height = surface->height; + } + return CAIRO_STATUS_SUCCESS; +} +static cairo_status_t +_cairo_directfb_surface_mark_dirty_rectangle (void * abstract_surface, + int x, + int y, + int width, + int height) +{ + cairo_directfb_surface_t *surface = abstract_surface; + if( surface->main_surface != surface->buffer) { + DFBRegion region; + region.x1=x; + region.y1=y; + region.x2=x+width; + region.y2=y+height; + surface->buffer->SetClip (surface->buffer,®ion); + surface->buffer->Blit(surface->buffer,surface->main_surface,NULL,0,0); + surface->buffer->SetClip (surface->buffer,NULL); + } + return CAIRO_STATUS_SUCCESS; +} +static cairo_status_t +_cairo_directfb_surface_flush (void *abstract_surface) +{ + cairo_directfb_surface_t *surface = abstract_surface; + if( surface->main_surface != surface->buffer) + surface->main_surface->Blit(surface->main_surface,surface->buffer,NULL,0,0); + return CAIRO_STATUS_SUCCESS; +} + +#if DFB_SHOW_GLYPHS +static void +_cairo_directfb_surface_scaled_font_fini (cairo_scaled_font_t *scaled_font) +{ + cairo_directfb_surface_font_private_t *font_private; + + font_private = scaled_font->surface_private; + if (font_private) + { + xxx_destroy (font_private); + } +} +#endif + +#if DFB_SHOW_GLYPHS +static void +_cairo_directfb_surface_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph, + cairo_scaled_font_t *scaled_font) +{ + cairo_directfb_surface_glyph_private_t *glyph_private; + + glyph_private = scaled_glyph->surface_private; + if (glyph_private) + { + xxx_release(glyph_private); + } +} +#endif + + +static const cairo_surface_backend_t cairo_directfb_surface_backend = { + _cairo_directfb_surface_create_similar, + _cairo_directfb_surface_finish, + _cairo_directfb_surface_acquire_source_image, + _cairo_directfb_surface_release_source_image, + _cairo_directfb_surface_acquire_dest_image, + _cairo_directfb_surface_release_dest_image, + _cairo_directfb_surface_clone_similar, +#if DFB_COMPOSITE + _cairo_directfb_surface_composite, +#else + NULL, +#endif + _cairo_directfb_surface_fill_rectangles, + NULL,/*composite_trapezoids*/ + NULL, /* copy_page */ + NULL, /* show_page */ + _cairo_directfb_surface_set_clip_region, + NULL, /* intersect_clip_path */ + _cairo_directfb_abstract_surface_get_extents, +#if DFB_SHOW_GLYPHS + _cairo_directfb_surface_show_glyphs, +#else + NULL, +#endif + NULL, /* get_font_options */ + _cairo_directfb_surface_flush, + _cairo_directfb_surface_mark_dirty_rectangle, +#if DFB_SHOW_GLYPHS + _cairo_directfb_surface_scaled_font_fini, + _cairo_directfb_surface_scaled_glyph_fini +#else + NULL, + NULL +#endif +}; + +#if DFB_SHOW_GLYPHS +static cairo_int_status_t +_cairo_directfb_surface_show_glyphs (cairo_scaled_font_t *scaled_font, + cairo_operator_t operator, + cairo_pattern_t *pattern, + void *abstract_surface, + int source_x, + int source_y, + int dest_x, + int dest_y, + unsigned int width, + unsigned int height, + const cairo_glyph_t *glyphs, + int num_glyphs) +{ + int i; + cairo_int_status_t status; + cairo_directfb_surface_t *surface = abstract_surface; + cairo_scaled_glyph_t *scaled_glyph; + + if ((scaled_font->surface_backend != NULL && + scaled_font->surface_backend != &cairo_directfb_surface_backend) ) + return CAIRO_INT_STATUS_UNSUPPORTED; + + if (scaled_font->surface_backend == NULL) { + scaled_font->surface_backend = &cairo_directfb_surface_backend; + } + /* Send all unsent glyphs to the server */ + for (i = 0; i < num_glyphs; i++) { + IDirectFBSurface *tmpbuffer; + int x; + int y; + cairo_image_surface_t *glyph_img; + status = _cairo_scaled_glyph_lookup (scaled_font, + glyphs[i].index, + CAIRO_SCALED_GLYPH_INFO_SURFACE, + &scaled_glyph); + glyph_img = scaled_glyph->surface; + if (status != CAIRO_STATUS_SUCCESS) + return status; + /* its a space or something*/ + if( !glyph_img->data ) { + continue; + } + if (scaled_glyph->surface_private == NULL ) { + int dfbformat = cairo_to_directfb_format(glyph_img->format); + if( dfbformat == DSPF_UNKNOWN ) { + printf(" BAD IMAGE FORMAT[%d] cf=%d dfbf=%d data=%p \n",i,glyph_img->format,dfbformat,glyph_img->data); + continue; + } + tmpbuffer = cairo_directfb_buffer_surface_create(surface->dfb, + (void *)glyph_img->data,glyph_img->stride,dfbformat,glyph_img->width,glyph_img->height); + /*scaled_glyph->surface_private = tmpbuffer;*/ + }else { + tmpbuffer = (IDirectFBSurface *)scaled_glyph->surface_private; + } + if( !tmpbuffer ) { + assert(0); /*something really bad happend*/ + return CAIRO_INT_STATUS_UNSUPPORTED; + } + /* round glyph locations to the nearest pixel */ + x = (int) floor (glyphs[i].x + + glyph_img->base.device_x_offset + + 0.5); + y = (int) floor (glyphs[i].y + + glyph_img->base.device_y_offset + + 0.5); + x +=dest_x; + y +=dest_y; + + printf(" IMAGE FORMAT[%d] src_x=%d src_y=%d cf=%d data=%p x=%d y=%d w=%d h=%d\n",i,source_x,source_y,glyph_img->format,glyph_img->data,x,y,glyph_img->width,glyph_img->height); +#if 0 + surface->buffer->SetColor(surface->buffer,0,0xff,0,0xff); + surface->buffer->FillRectangle(surface->buffer,x,y,glyph_img->width,glyph_img->height); + surface->buffer->SetColor(surface->buffer,0,0xff,0xff,0xff); +#endif + surface->buffer->Blit(surface->buffer,tmpbuffer,NULL,x,y); + + } + return CAIRO_INT_STATUS_UNSUPPORTED; +} +#endif + + + +cairo_surface_t * +cairo_directfb_surface_create (IDirectFB *dfb,IDirectFBSurface *dfbsurface) +{ + cairo_directfb_surface_t *surface = calloc(1,sizeof(cairo_directfb_surface_t)); + if( surface == NULL ) + return NULL; + _cairo_surface_init (&surface->base, &cairo_directfb_surface_backend); + /*Reference the surface */ + dfb->AddRef(dfb); + dfbsurface->AddRef(dfbsurface); + surface->dfb=dfb; + surface->main_surface = dfbsurface; + dfbsurface->GetSize(dfbsurface,&surface->width,&surface->height); + surface->buffer = surface->main_surface; + surface->format = DFB_UNSUPPORTED; + surface->clip=NULL; + return ((cairo_surface_t *)surface); +} + diff --git a/src/cairo-directfb.h b/src/cairo-directfb.h new file mode 100644 index 000000000..ff3041643 --- /dev/null +++ b/src/cairo-directfb.h @@ -0,0 +1,60 @@ +/* cairo - a vector graphics library with display and print output + * + * Copyright © 2003 University of Southern California + * + * This library is free software; you can redistribute it and/or + * modify it either under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation + * (the "LGPL") or, at your option, under the terms of the Mozilla + * Public License Version 1.1 (the "MPL"). If you do not alter this + * notice, a recipient may use your version of this file under either + * the MPL or the LGPL. + * + * You should have received a copy of the LGPL along with this library + * in the file COPYING-LGPL-2.1; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the MPL along with this library + * in the file COPYING-MPL-1.1 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY + * OF ANY KIND, either express or implied. See the LGPL or the MPL for + * the specific language governing rights and limitations. + * + * The Original Code is the cairo graphics library. + * + * The Initial Developer of the Original Code is University of Southern + * California. + * + * Contributor(s): + * Carl D. Worth <cworth@isi.edu> + */ + +#ifndef CAIRO_DIRECTFB_H +#define CAIRO_DIRECTFB_H + +#include <cairo.h> + +#ifdef CAIRO_HAS_DIRECTFB_SURFACE + +CAIRO_BEGIN_DECLS + +cairo_surface_t * cairo_directfb_surface_create (IDirectFB *dfb,IDirectFBSurface *surface); + +CAIRO_END_DECLS + + + +#endif /*CAIRO_HAS_DIRECTFB_SURFACE*/ +#endif /*CAIRO_DIRECTFB_H*/ + + + + + + + diff --git a/src/cairo-features.h.in b/src/cairo-features.h.in index 4af0501f7..4b845bf95 100644 --- a/src/cairo-features.h.in +++ b/src/cairo-features.h.in @@ -73,6 +73,8 @@ @GLITZ_SURFACE_FEATURE@ +@DIRECTFB_SURFACE_FEATURE@ + @FT_FONT_FEATURE@ @WIN32_FONT_FEATURE@ diff --git a/test/Makefile.am b/test/Makefile.am index 23ea570e6..fc8f0c506 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -258,6 +258,10 @@ libcairotest_la_SOURCES += cairo-test-beos.cpp cairo-test-beos.h libcairotest_la_CXXFLAGS = -Wno-multichar endif +if CAIRO_HAS_DIRECTFB_SURFACE +libcairotest_la_SOURCES += cairo-test-directfb.c cairo-test-directfb.h +endif + LDADDS = libcairotest.la $(top_builddir)/src/libcairo.la if CAIRO_CAN_TEST_GLITZ_AGL_SURFACE diff --git a/test/cairo-test-directfb.c b/test/cairo-test-directfb.c new file mode 100644 index 000000000..13049c5e6 --- /dev/null +++ b/test/cairo-test-directfb.c @@ -0,0 +1,127 @@ + +/* +Test were run with the following script +target can be directfb_bitmap or directfb + +export CAIRO_TEST_TARGET=directfb_bitmap +export DFBARGS=quiet,no-banner,no-debug,log-file=dfblog,system=x11 +cd cairo/test +make check + + +*/ + +#include <stdio.h> +#include <stdlib.h> +#include "cairo-test.h" +#include "cairo-test-directfb.h" +#include <directfb.h> +#include "cairo-directfb.h" + +/* macro for a safe call to DirectFB functions */ +#define DFBCHECK(x...) \ +{ \ + err = x; \ + if (err != DFB_OK) { \ + fprintf( stderr, "%s <%d>:\n\t", __FILE__, __LINE__ ); \ + DirectFBErrorFatal( #x, err ); \ + } \ +} + +typedef struct _DFBInfo { + IDirectFB *dfb; + IDirectFBDisplayLayer *layer; + IDirectFBWindow *window; + IDirectFBSurface *surface; +} DFBInfo ; + +static DFBInfo *init(void) { + DFBDisplayLayerConfig layer_config; + DFBGraphicsDeviceDescription desc; + int err; + DFBInfo *info = malloc(sizeof(DFBInfo)); + if( !info ) + return NULL; + + + DFBCHECK(DirectFBInit( NULL,NULL)); + DFBCHECK(DirectFBCreate( &info->dfb )); + info->dfb->GetDeviceDescription(info->dfb, &desc ); + + DFBCHECK(info->dfb->GetDisplayLayer( info->dfb, DLID_PRIMARY, &info->layer )); + info->layer->SetCooperativeLevel( info->layer, DLSCL_ADMINISTRATIVE ); + + if (!((desc.blitting_flags & DSBLIT_BLEND_ALPHACHANNEL) && + (desc.blitting_flags & DSBLIT_BLEND_COLORALPHA ))) + { + layer_config.flags = DLCONF_BUFFERMODE; + layer_config.buffermode = DLBM_BACKSYSTEM; + info->layer->SetConfiguration( info->layer, &layer_config ); + } + return info; +} + + +cairo_surface_t * +create_directfb_surface (cairo_test_t* test, cairo_format_t format, + void **closure) { + DFBWindowDescription desc; + int err; + DFBInfo *info = init(); + if( !info ) + return NULL; + *closure = info; + + desc.flags = ( DWDESC_POSX | DWDESC_POSY | + DWDESC_WIDTH | DWDESC_HEIGHT | DWDESC_CAPS|DSDESC_PIXELFORMAT ); + desc.posx = 0; + desc.posy = 0; + desc.width = test->width; + desc.height = test->height; + desc.caps = DWCAPS_DOUBLEBUFFER; + desc.caps |= DWCAPS_ALPHACHANNEL; + desc.pixelformat = DSPF_ARGB; + + DFBCHECK(info->layer->CreateWindow( info->layer, &desc, &info->window ) ); + info->window->SetOpacity( info->window, 0xFF ); + info->window->GetSurface( info->window, &info->surface ); + info->surface->SetColor( info->surface, 0xFF, 0xFF, 0xFF, 0xFF ); + info->surface->FillRectangle( info->surface,0, 0, desc.width, desc.height ); + info->surface->Flip( info->surface, NULL, 0 ); + cairo_surface_t *csurface=cairo_directfb_surface_create(info->dfb,info->surface); + return csurface; +} + +cairo_surface_t * +create_directfb_bitmap_surface (cairo_test_t* test, cairo_format_t format, + void **closure) { + int err; + DFBInfo *info = init(); + if( !info ) return NULL; + *closure = info; + info->window= NULL; /* make sure window is null*/ + DFBSurfaceDescription desc; + + desc.flags = DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT; + desc.caps = DSCAPS_NONE; + desc.width = test->width; + desc.height = test->height; + desc.pixelformat = DSPF_ARGB; + DFBCHECK(info->dfb->CreateSurface (info->dfb, &desc,&info->surface)); + cairo_surface_t *csurface=cairo_directfb_surface_create(info->dfb, + info->surface); + return csurface; +} + +void +cleanup_directfb (void* closure) { + DFBInfo *info = (DFBInfo *)closure; + if( info->surface ) + info->surface->Release( info->surface ); + if( info->window ) + info->window->Release( info->window ); + if( info->layer ) + info->layer->Release( info->layer ); + if( info->dfb ) + info->dfb->Release( info->dfb ); +} diff --git a/test/cairo-test-directfb.h b/test/cairo-test-directfb.h new file mode 100644 index 000000000..29f5d20e8 --- /dev/null +++ b/test/cairo-test-directfb.h @@ -0,0 +1,23 @@ +#ifndef CAIRO_TEST_DIRECTFB_H_ +#define CAIRO_TEST_DIRECTFB_H_ + +/* Two functions: One for a real window, one for a bitmap */ + +#include <cairo.h> + +CAIRO_BEGIN_DECLS + +extern cairo_surface_t * +create_directfb_surface (cairo_test_t* test, cairo_format_t format, + void **closure); + +extern void +cleanup_directfb (void* closure); + +extern cairo_surface_t * +create_directfb_bitmap_surface (cairo_test_t* test, cairo_format_t format, + void **closure); + +CAIRO_END_DECLS + +#endif diff --git a/test/cairo-test.c b/test/cairo-test.c index e6c67e1bb..202b765fd 100644 --- a/test/cairo-test.c +++ b/test/cairo-test.c @@ -1059,6 +1059,10 @@ cleanup_xlib (void *closure) #include "cairo-test-beos.h" #endif +#if CAIRO_HAS_DIRECTFB_SURFACE +#include "cairo-test-directfb.h" +#endif + #if CAIRO_HAS_PS_SURFACE #include "cairo-ps.h" @@ -1450,6 +1454,13 @@ cairo_test_expecting (cairo_test_t *test, cairo_test_draw_function_t draw, { "beos_bitmap", CAIRO_FORMAT_ARGB32, create_beos_bitmap_surface, cairo_surface_write_to_png, cleanup_beos_bitmap}, #endif + +#if CAIRO_HAS_DIRECTFB_SURFACE + { "directfb", CAIRO_FORMAT_RGB24, + create_directfb_surface, cairo_surface_write_to_png, cleanup_directfb}, + { "directfb_bitmap", CAIRO_FORMAT_ARGB32, + create_directfb_bitmap_surface, cairo_surface_write_to_png,cleanup_directfb}, +#endif }; if ((tname = getenv ("CAIRO_TEST_TARGET")) != NULL) { |