From 7fe60435bce6595a9c58a9bfd8244d74b5320e96 Mon Sep 17 00:00:00 2001 From: Benjamin Franzke Date: Tue, 15 Jan 2013 08:46:13 +0100 Subject: Import DirectFB141_2k11R3_beta5 --- Source/DirectFB/src/Makefile.am | 73 + Source/DirectFB/src/Makefile.in | 745 ++ Source/DirectFB/src/core/Makefile.am | 84 + Source/DirectFB/src/core/Makefile.in | 648 ++ Source/DirectFB/src/core/clipboard.c | 298 + Source/DirectFB/src/core/clipboard.h | 53 + Source/DirectFB/src/core/colorhash.c | 366 + Source/DirectFB/src/core/colorhash.h | 54 + Source/DirectFB/src/core/core.c | 1160 +++ Source/DirectFB/src/core/core.h | 162 + Source/DirectFB/src/core/core_parts.c | 202 + Source/DirectFB/src/core/core_parts.h | 131 + Source/DirectFB/src/core/core_system.h | 141 + Source/DirectFB/src/core/coredefs.h | 48 + Source/DirectFB/src/core/coretypes.h | 89 + Source/DirectFB/src/core/fonts.c | 660 ++ Source/DirectFB/src/core/fonts.h | 250 + Source/DirectFB/src/core/gfxcard.c | 2921 +++++++ Source/DirectFB/src/core/gfxcard.h | 470 + Source/DirectFB/src/core/graphics_driver.h | 86 + Source/DirectFB/src/core/input.c | 2668 ++++++ Source/DirectFB/src/core/input.h | 203 + Source/DirectFB/src/core/input_driver.h | 103 + Source/DirectFB/src/core/layer_context.c | 1947 +++++ Source/DirectFB/src/core/layer_context.h | 149 + Source/DirectFB/src/core/layer_control.c | 589 ++ Source/DirectFB/src/core/layer_control.h | 72 + Source/DirectFB/src/core/layer_region.c | 1129 +++ Source/DirectFB/src/core/layer_region.h | 100 + Source/DirectFB/src/core/layers.c | 640 ++ Source/DirectFB/src/core/layers.h | 359 + Source/DirectFB/src/core/layers_internal.h | 196 + Source/DirectFB/src/core/local_surface_pool.c | 313 + Source/DirectFB/src/core/palette.c | 317 + Source/DirectFB/src/core/palette.h | 106 + Source/DirectFB/src/core/prealloc_surface_pool.c | 192 + Source/DirectFB/src/core/screen.c | 540 ++ Source/DirectFB/src/core/screen.h | 122 + Source/DirectFB/src/core/screens.c | 591 ++ Source/DirectFB/src/core/screens.h | 263 + Source/DirectFB/src/core/screens_internal.h | 81 + Source/DirectFB/src/core/shared_surface_pool.c | 227 + Source/DirectFB/src/core/state.c | 416 + Source/DirectFB/src/core/state.h | 362 + Source/DirectFB/src/core/surface.c | 768 ++ Source/DirectFB/src/core/surface.h | 446 + Source/DirectFB/src/core/surface_buffer.c | 1206 +++ Source/DirectFB/src/core/surface_buffer.h | 257 + Source/DirectFB/src/core/surface_core.c | 214 + Source/DirectFB/src/core/surface_pool.c | 1263 +++ Source/DirectFB/src/core/surface_pool.h | 272 + Source/DirectFB/src/core/surface_pool_bridge.c | 531 ++ Source/DirectFB/src/core/surface_pool_bridge.h | 187 + Source/DirectFB/src/core/system.c | 464 + Source/DirectFB/src/core/system.h | 258 + Source/DirectFB/src/core/windows.c | 1908 ++++ Source/DirectFB/src/core/windows.h | 316 + Source/DirectFB/src/core/windows_internal.h | 211 + Source/DirectFB/src/core/windowstack.c | 998 +++ Source/DirectFB/src/core/windowstack.h | 105 + Source/DirectFB/src/core/wm.c | 1440 +++ Source/DirectFB/src/core/wm.h | 468 + Source/DirectFB/src/core/wm_module.h | 274 + Source/DirectFB/src/directfb.c | 311 + Source/DirectFB/src/display/Makefile.am | 30 + Source/DirectFB/src/display/Makefile.in | 570 ++ .../DirectFB/src/display/idirectfbdisplaylayer.c | 1076 +++ .../DirectFB/src/display/idirectfbdisplaylayer.h | 43 + Source/DirectFB/src/display/idirectfbpalette.c | 365 + Source/DirectFB/src/display/idirectfbpalette.h | 51 + Source/DirectFB/src/display/idirectfbscreen.c | 722 ++ Source/DirectFB/src/display/idirectfbscreen.h | 42 + Source/DirectFB/src/display/idirectfbsurface.c | 2841 ++++++ Source/DirectFB/src/display/idirectfbsurface.h | 123 + .../DirectFB/src/display/idirectfbsurface_layer.c | 244 + .../DirectFB/src/display/idirectfbsurface_layer.h | 57 + .../DirectFB/src/display/idirectfbsurface_window.c | 353 + .../DirectFB/src/display/idirectfbsurface_window.h | 48 + Source/DirectFB/src/gfx/Makefile.am | 29 + Source/DirectFB/src/gfx/Makefile.in | 676 ++ Source/DirectFB/src/gfx/clip.c | 379 + Source/DirectFB/src/gfx/clip.h | 125 + Source/DirectFB/src/gfx/convert.c | 1427 +++ Source/DirectFB/src/gfx/convert.h | 562 ++ Source/DirectFB/src/gfx/generic/Makefile.am | 62 + Source/DirectFB/src/gfx/generic/Makefile.in | 602 ++ Source/DirectFB/src/gfx/generic/duffs_device.h | 89 + Source/DirectFB/src/gfx/generic/generic.c | 9161 ++++++++++++++++++++ Source/DirectFB/src/gfx/generic/generic.h | 174 + Source/DirectFB/src/gfx/generic/generic_64.h | 207 + Source/DirectFB/src/gfx/generic/generic_dummy.c | 94 + Source/DirectFB/src/gfx/generic/generic_mmx.h | 659 ++ Source/DirectFB/src/gfx/generic/stretch_hvx_16.h | 469 + Source/DirectFB/src/gfx/generic/stretch_hvx_32.h | 174 + Source/DirectFB/src/gfx/generic/stretch_hvx_8.h | 149 + Source/DirectFB/src/gfx/generic/stretch_hvx_88.h | 152 + Source/DirectFB/src/gfx/generic/stretch_hvx_N.h | 121 + .../DirectFB/src/gfx/generic/stretch_up_down_16.h | 68 + .../DirectFB/src/gfx/generic/stretch_up_down_32.h | 68 + .../src/gfx/generic/stretch_up_down_32_indexed.h | 82 + .../DirectFB/src/gfx/generic/stretch_up_down_8.h | 72 + .../DirectFB/src/gfx/generic/stretch_up_down_88.h | 72 + .../src/gfx/generic/stretch_up_down_table.h | 59 + Source/DirectFB/src/gfx/generic/template_acc_16.h | 382 + Source/DirectFB/src/gfx/generic/template_acc_32.h | 261 + .../src/gfx/generic/template_colorkey_16.h | 369 + .../src/gfx/generic/template_colorkey_32.h | 206 + Source/DirectFB/src/gfx/generic/yuvtbl-gen.c | 199 + Source/DirectFB/src/gfx/generic/yuvtbl.h | 296 + Source/DirectFB/src/gfx/util.c | 270 + Source/DirectFB/src/gfx/util.h | 42 + Source/DirectFB/src/idirectfb.c | 1965 +++++ Source/DirectFB/src/idirectfb.h | 89 + Source/DirectFB/src/input/Makefile.am | 22 + Source/DirectFB/src/input/Makefile.in | 556 ++ Source/DirectFB/src/input/idirectfbinputbuffer.c | 1121 +++ Source/DirectFB/src/input/idirectfbinputbuffer.h | 56 + Source/DirectFB/src/input/idirectfbinputdevice.c | 446 + Source/DirectFB/src/input/idirectfbinputdevice.h | 40 + Source/DirectFB/src/media/Makefile.am | 29 + Source/DirectFB/src/media/Makefile.in | 570 ++ Source/DirectFB/src/media/idirectfbdatabuffer.c | 264 + Source/DirectFB/src/media/idirectfbdatabuffer.h | 104 + .../DirectFB/src/media/idirectfbdatabuffer_file.c | 297 + .../src/media/idirectfbdatabuffer_memory.c | 266 + .../src/media/idirectfbdatabuffer_streamed.c | 529 ++ Source/DirectFB/src/media/idirectfbfont.c | 965 +++ Source/DirectFB/src/media/idirectfbfont.h | 82 + Source/DirectFB/src/media/idirectfbimageprovider.c | 167 + Source/DirectFB/src/media/idirectfbimageprovider.h | 48 + Source/DirectFB/src/media/idirectfbvideoprovider.c | 387 + Source/DirectFB/src/media/idirectfbvideoprovider.h | 54 + Source/DirectFB/src/misc/Makefile.am | 29 + Source/DirectFB/src/misc/Makefile.in | 564 ++ Source/DirectFB/src/misc/conf.c | 1947 +++++ Source/DirectFB/src/misc/conf.h | 287 + Source/DirectFB/src/misc/dither565.h | 211 + Source/DirectFB/src/misc/gfx_util.c | 964 ++ Source/DirectFB/src/misc/gfx_util.h | 48 + Source/DirectFB/src/misc/util.c | 471 + Source/DirectFB/src/misc/util.h | 34 + Source/DirectFB/src/windows/Makefile.am | 20 + Source/DirectFB/src/windows/Makefile.in | 552 ++ Source/DirectFB/src/windows/idirectfbwindow.c | 1446 +++ Source/DirectFB/src/windows/idirectfbwindow.h | 44 + 145 files changed, 71219 insertions(+) create mode 100755 Source/DirectFB/src/Makefile.am create mode 100755 Source/DirectFB/src/Makefile.in create mode 100755 Source/DirectFB/src/core/Makefile.am create mode 100755 Source/DirectFB/src/core/Makefile.in create mode 100755 Source/DirectFB/src/core/clipboard.c create mode 100755 Source/DirectFB/src/core/clipboard.h create mode 100755 Source/DirectFB/src/core/colorhash.c create mode 100755 Source/DirectFB/src/core/colorhash.h create mode 100755 Source/DirectFB/src/core/core.c create mode 100755 Source/DirectFB/src/core/core.h create mode 100755 Source/DirectFB/src/core/core_parts.c create mode 100755 Source/DirectFB/src/core/core_parts.h create mode 100755 Source/DirectFB/src/core/core_system.h create mode 100755 Source/DirectFB/src/core/coredefs.h create mode 100755 Source/DirectFB/src/core/coretypes.h create mode 100755 Source/DirectFB/src/core/fonts.c create mode 100755 Source/DirectFB/src/core/fonts.h create mode 100755 Source/DirectFB/src/core/gfxcard.c create mode 100755 Source/DirectFB/src/core/gfxcard.h create mode 100755 Source/DirectFB/src/core/graphics_driver.h create mode 100755 Source/DirectFB/src/core/input.c create mode 100755 Source/DirectFB/src/core/input.h create mode 100755 Source/DirectFB/src/core/input_driver.h create mode 100755 Source/DirectFB/src/core/layer_context.c create mode 100755 Source/DirectFB/src/core/layer_context.h create mode 100755 Source/DirectFB/src/core/layer_control.c create mode 100755 Source/DirectFB/src/core/layer_control.h create mode 100755 Source/DirectFB/src/core/layer_region.c create mode 100755 Source/DirectFB/src/core/layer_region.h create mode 100755 Source/DirectFB/src/core/layers.c create mode 100755 Source/DirectFB/src/core/layers.h create mode 100755 Source/DirectFB/src/core/layers_internal.h create mode 100755 Source/DirectFB/src/core/local_surface_pool.c create mode 100755 Source/DirectFB/src/core/palette.c create mode 100755 Source/DirectFB/src/core/palette.h create mode 100755 Source/DirectFB/src/core/prealloc_surface_pool.c create mode 100755 Source/DirectFB/src/core/screen.c create mode 100755 Source/DirectFB/src/core/screen.h create mode 100755 Source/DirectFB/src/core/screens.c create mode 100755 Source/DirectFB/src/core/screens.h create mode 100755 Source/DirectFB/src/core/screens_internal.h create mode 100755 Source/DirectFB/src/core/shared_surface_pool.c create mode 100755 Source/DirectFB/src/core/state.c create mode 100755 Source/DirectFB/src/core/state.h create mode 100755 Source/DirectFB/src/core/surface.c create mode 100755 Source/DirectFB/src/core/surface.h create mode 100755 Source/DirectFB/src/core/surface_buffer.c create mode 100755 Source/DirectFB/src/core/surface_buffer.h create mode 100755 Source/DirectFB/src/core/surface_core.c create mode 100755 Source/DirectFB/src/core/surface_pool.c create mode 100755 Source/DirectFB/src/core/surface_pool.h create mode 100755 Source/DirectFB/src/core/surface_pool_bridge.c create mode 100755 Source/DirectFB/src/core/surface_pool_bridge.h create mode 100755 Source/DirectFB/src/core/system.c create mode 100755 Source/DirectFB/src/core/system.h create mode 100755 Source/DirectFB/src/core/windows.c create mode 100755 Source/DirectFB/src/core/windows.h create mode 100755 Source/DirectFB/src/core/windows_internal.h create mode 100755 Source/DirectFB/src/core/windowstack.c create mode 100755 Source/DirectFB/src/core/windowstack.h create mode 100755 Source/DirectFB/src/core/wm.c create mode 100755 Source/DirectFB/src/core/wm.h create mode 100755 Source/DirectFB/src/core/wm_module.h create mode 100755 Source/DirectFB/src/directfb.c create mode 100755 Source/DirectFB/src/display/Makefile.am create mode 100755 Source/DirectFB/src/display/Makefile.in create mode 100755 Source/DirectFB/src/display/idirectfbdisplaylayer.c create mode 100755 Source/DirectFB/src/display/idirectfbdisplaylayer.h create mode 100755 Source/DirectFB/src/display/idirectfbpalette.c create mode 100755 Source/DirectFB/src/display/idirectfbpalette.h create mode 100755 Source/DirectFB/src/display/idirectfbscreen.c create mode 100755 Source/DirectFB/src/display/idirectfbscreen.h create mode 100755 Source/DirectFB/src/display/idirectfbsurface.c create mode 100755 Source/DirectFB/src/display/idirectfbsurface.h create mode 100755 Source/DirectFB/src/display/idirectfbsurface_layer.c create mode 100755 Source/DirectFB/src/display/idirectfbsurface_layer.h create mode 100755 Source/DirectFB/src/display/idirectfbsurface_window.c create mode 100755 Source/DirectFB/src/display/idirectfbsurface_window.h create mode 100755 Source/DirectFB/src/gfx/Makefile.am create mode 100755 Source/DirectFB/src/gfx/Makefile.in create mode 100755 Source/DirectFB/src/gfx/clip.c create mode 100755 Source/DirectFB/src/gfx/clip.h create mode 100755 Source/DirectFB/src/gfx/convert.c create mode 100755 Source/DirectFB/src/gfx/convert.h create mode 100755 Source/DirectFB/src/gfx/generic/Makefile.am create mode 100755 Source/DirectFB/src/gfx/generic/Makefile.in create mode 100755 Source/DirectFB/src/gfx/generic/duffs_device.h create mode 100755 Source/DirectFB/src/gfx/generic/generic.c create mode 100755 Source/DirectFB/src/gfx/generic/generic.h create mode 100755 Source/DirectFB/src/gfx/generic/generic_64.h create mode 100755 Source/DirectFB/src/gfx/generic/generic_dummy.c create mode 100755 Source/DirectFB/src/gfx/generic/generic_mmx.h create mode 100755 Source/DirectFB/src/gfx/generic/stretch_hvx_16.h create mode 100755 Source/DirectFB/src/gfx/generic/stretch_hvx_32.h create mode 100755 Source/DirectFB/src/gfx/generic/stretch_hvx_8.h create mode 100755 Source/DirectFB/src/gfx/generic/stretch_hvx_88.h create mode 100755 Source/DirectFB/src/gfx/generic/stretch_hvx_N.h create mode 100755 Source/DirectFB/src/gfx/generic/stretch_up_down_16.h create mode 100755 Source/DirectFB/src/gfx/generic/stretch_up_down_32.h create mode 100755 Source/DirectFB/src/gfx/generic/stretch_up_down_32_indexed.h create mode 100755 Source/DirectFB/src/gfx/generic/stretch_up_down_8.h create mode 100755 Source/DirectFB/src/gfx/generic/stretch_up_down_88.h create mode 100755 Source/DirectFB/src/gfx/generic/stretch_up_down_table.h create mode 100755 Source/DirectFB/src/gfx/generic/template_acc_16.h create mode 100755 Source/DirectFB/src/gfx/generic/template_acc_32.h create mode 100755 Source/DirectFB/src/gfx/generic/template_colorkey_16.h create mode 100755 Source/DirectFB/src/gfx/generic/template_colorkey_32.h create mode 100755 Source/DirectFB/src/gfx/generic/yuvtbl-gen.c create mode 100755 Source/DirectFB/src/gfx/generic/yuvtbl.h create mode 100755 Source/DirectFB/src/gfx/util.c create mode 100755 Source/DirectFB/src/gfx/util.h create mode 100755 Source/DirectFB/src/idirectfb.c create mode 100755 Source/DirectFB/src/idirectfb.h create mode 100755 Source/DirectFB/src/input/Makefile.am create mode 100755 Source/DirectFB/src/input/Makefile.in create mode 100755 Source/DirectFB/src/input/idirectfbinputbuffer.c create mode 100755 Source/DirectFB/src/input/idirectfbinputbuffer.h create mode 100755 Source/DirectFB/src/input/idirectfbinputdevice.c create mode 100755 Source/DirectFB/src/input/idirectfbinputdevice.h create mode 100755 Source/DirectFB/src/media/Makefile.am create mode 100755 Source/DirectFB/src/media/Makefile.in create mode 100755 Source/DirectFB/src/media/idirectfbdatabuffer.c create mode 100755 Source/DirectFB/src/media/idirectfbdatabuffer.h create mode 100755 Source/DirectFB/src/media/idirectfbdatabuffer_file.c create mode 100755 Source/DirectFB/src/media/idirectfbdatabuffer_memory.c create mode 100755 Source/DirectFB/src/media/idirectfbdatabuffer_streamed.c create mode 100755 Source/DirectFB/src/media/idirectfbfont.c create mode 100755 Source/DirectFB/src/media/idirectfbfont.h create mode 100755 Source/DirectFB/src/media/idirectfbimageprovider.c create mode 100755 Source/DirectFB/src/media/idirectfbimageprovider.h create mode 100755 Source/DirectFB/src/media/idirectfbvideoprovider.c create mode 100755 Source/DirectFB/src/media/idirectfbvideoprovider.h create mode 100755 Source/DirectFB/src/misc/Makefile.am create mode 100755 Source/DirectFB/src/misc/Makefile.in create mode 100755 Source/DirectFB/src/misc/conf.c create mode 100755 Source/DirectFB/src/misc/conf.h create mode 100755 Source/DirectFB/src/misc/dither565.h create mode 100755 Source/DirectFB/src/misc/gfx_util.c create mode 100755 Source/DirectFB/src/misc/gfx_util.h create mode 100755 Source/DirectFB/src/misc/util.c create mode 100755 Source/DirectFB/src/misc/util.h create mode 100755 Source/DirectFB/src/windows/Makefile.am create mode 100755 Source/DirectFB/src/windows/Makefile.in create mode 100755 Source/DirectFB/src/windows/idirectfbwindow.c create mode 100755 Source/DirectFB/src/windows/idirectfbwindow.h (limited to 'Source/DirectFB/src') diff --git a/Source/DirectFB/src/Makefile.am b/Source/DirectFB/src/Makefile.am new file mode 100755 index 0000000..8f506e6 --- /dev/null +++ b/Source/DirectFB/src/Makefile.am @@ -0,0 +1,73 @@ +## Makefile.am for DirectFB/src + +SUBDIRS = core display gfx input media misc windows + +INCLUDES = \ + -I$(top_builddir)/include \ + -I$(top_builddir)/lib \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/lib \ + -I$(top_srcdir)/src + +AM_CPPFLAGS = \ + -DDATADIR=\"${RUNTIME_SYSROOT}@DATADIR@\" \ + -DMODULEDIR=\"${RUNTIME_SYSROOT}@MODULEDIR@\" + + +internalincludedir = $(INTERNALINCLUDEDIR) + +internalinclude_HEADERS = \ + idirectfb.h + + +lib_LTLIBRARIES = libdirectfb.la + +libdirectfb_la_SOURCES = \ + directfb.c \ + idirectfb.c + +libdirectfb_la_LDFLAGS = \ + -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ + -release $(LT_RELEASE) \ + $(DFB_LDFLAGS) + +libdirectfb_la_LIBADD = \ + display/libdirectfb_display.la \ + media/libdirectfb_media.la \ + windows/libdirectfb_windows.la \ + input/libdirectfb_input.la \ + misc/libdirectfb_misc.la \ + gfx/libdirectfb_gfx.la \ + core/libdirectfb_core.la \ + ../lib/direct/libdirect.la \ + ../lib/fusion/libfusion.la + + +# +## and now rebuild the static version with the *correct* object files +# +if BUILD_STATIC + +clean-local: + rm -f libdirectfb_fixed.a + +all-local: libdirectfb_fixed.a + +libdirectfb_fixed.a: .libs/libdirectfb.a + rm -f libdirectfb_fixed.a + ${AR} cru libdirectfb_fixed.a `find . -name "*.o" | grep -v '.libs'` + ${RANLIB} libdirectfb_fixed.a + cp -pf libdirectfb_fixed.a .libs/libdirectfb.a + +.libs/libdirectfb.a: libdirectfb.la + +else + +clean-local: + +all-local: + +endif + + +include $(top_srcdir)/rules/nmfile.make diff --git a/Source/DirectFB/src/Makefile.in b/Source/DirectFB/src/Makefile.in new file mode 100755 index 0000000..9fb3b04 --- /dev/null +++ b/Source/DirectFB/src/Makefile.in @@ -0,0 +1,745 @@ +# Makefile.in generated by automake 1.10.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +DIST_COMMON = $(internalinclude_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(top_srcdir)/rules/nmfile.make +subdir = src +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/as-ac-expand.m4 \ + $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(libdir)" \ + "$(DESTDIR)$(internalincludedir)" +libLTLIBRARIES_INSTALL = $(INSTALL) +LTLIBRARIES = $(lib_LTLIBRARIES) +libdirectfb_la_DEPENDENCIES = display/libdirectfb_display.la \ + media/libdirectfb_media.la windows/libdirectfb_windows.la \ + input/libdirectfb_input.la misc/libdirectfb_misc.la \ + gfx/libdirectfb_gfx.la core/libdirectfb_core.la \ + ../lib/direct/libdirect.la ../lib/fusion/libfusion.la +am_libdirectfb_la_OBJECTS = directfb.lo idirectfb.lo +libdirectfb_la_OBJECTS = $(am_libdirectfb_la_OBJECTS) +libdirectfb_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libdirectfb_la_LDFLAGS) $(LDFLAGS) -o $@ +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libdirectfb_la_SOURCES) +DIST_SOURCES = $(libdirectfb_la_SOURCES) +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +internalincludeHEADERS_INSTALL = $(INSTALL_HEADER) +HEADERS = $(internalinclude_HEADERS) +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AS = @AS@ +ASFLAGS = @ASFLAGS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIR = @DATADIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DFB_CFLAGS_OMIT_FRAME_POINTER = @DFB_CFLAGS_OMIT_FRAME_POINTER@ +DFB_INTERNAL_CFLAGS = @DFB_INTERNAL_CFLAGS@ +DFB_LDFLAGS = @DFB_LDFLAGS@ +DFB_SMOOTH_SCALING = @DFB_SMOOTH_SCALING@ +DIRECTFB_BINARY_AGE = @DIRECTFB_BINARY_AGE@ +DIRECTFB_CSOURCE = @DIRECTFB_CSOURCE@ +DIRECTFB_INTERFACE_AGE = @DIRECTFB_INTERFACE_AGE@ +DIRECTFB_MAJOR_VERSION = @DIRECTFB_MAJOR_VERSION@ +DIRECTFB_MICRO_VERSION = @DIRECTFB_MICRO_VERSION@ +DIRECTFB_MINOR_VERSION = @DIRECTFB_MINOR_VERSION@ +DIRECTFB_VERSION = @DIRECTFB_VERSION@ +DIRECT_BUILD_DEBUG = @DIRECT_BUILD_DEBUG@ +DIRECT_BUILD_DEBUGS = @DIRECT_BUILD_DEBUGS@ +DIRECT_BUILD_GETTID = @DIRECT_BUILD_GETTID@ +DIRECT_BUILD_NETWORK = @DIRECT_BUILD_NETWORK@ +DIRECT_BUILD_STDBOOL = @DIRECT_BUILD_STDBOOL@ +DIRECT_BUILD_TEXT = @DIRECT_BUILD_TEXT@ +DIRECT_BUILD_TRACE = @DIRECT_BUILD_TRACE@ +DSYMUTIL = @DSYMUTIL@ +DYNLIB = @DYNLIB@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +FREETYPE_CFLAGS = @FREETYPE_CFLAGS@ +FREETYPE_LIBS = @FREETYPE_LIBS@ +FREETYPE_PROVIDER = @FREETYPE_PROVIDER@ +FUSION_BUILD_KERNEL = @FUSION_BUILD_KERNEL@ +FUSION_BUILD_MULTI = @FUSION_BUILD_MULTI@ +FUSION_MESSAGE_SIZE = @FUSION_MESSAGE_SIZE@ +GIF_PROVIDER = @GIF_PROVIDER@ +GREP = @GREP@ +HAVE_LINUX = @HAVE_LINUX@ +INCLUDEDIR = @INCLUDEDIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTERNALINCLUDEDIR = @INTERNALINCLUDEDIR@ +JPEG_PROVIDER = @JPEG_PROVIDER@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBJPEG = @LIBJPEG@ +LIBOBJS = @LIBOBJS@ +LIBPNG = @LIBPNG@ +LIBPNG_CONFIG = @LIBPNG_CONFIG@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_AGE = @LT_AGE@ +LT_BINARY = @LT_BINARY@ +LT_CURRENT = @LT_CURRENT@ +LT_RELEASE = @LT_RELEASE@ +LT_REVISION = @LT_REVISION@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MAN2HTML = @MAN2HTML@ +MKDIR_P = @MKDIR_P@ +MODULEDIR = @MODULEDIR@ +MODULEDIRNAME = @MODULEDIRNAME@ +NMEDIT = @NMEDIT@ +OBJEXT = @OBJEXT@ +OSX_LIBS = @OSX_LIBS@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PNG_PROVIDER = @PNG_PROVIDER@ +RANLIB = @RANLIB@ +RUNTIME_SYSROOT = @RUNTIME_SYSROOT@ +SDL_CFLAGS = @SDL_CFLAGS@ +SDL_LIBS = @SDL_LIBS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOPATH = @SOPATH@ +STRIP = @STRIP@ +SYSCONFDIR = @SYSCONFDIR@ +SYSFS_LIBS = @SYSFS_LIBS@ +THREADFLAGS = @THREADFLAGS@ +THREADLIB = @THREADLIB@ +TSLIB_CFLAGS = @TSLIB_CFLAGS@ +TSLIB_LIBS = @TSLIB_LIBS@ +VERSION = @VERSION@ +VNC_CFLAGS = @VNC_CFLAGS@ +VNC_CONFIG = @VNC_CONFIG@ +VNC_LIBS = @VNC_LIBS@ +X11_CFLAGS = @X11_CFLAGS@ +X11_LIBS = @X11_LIBS@ +ZLIB_LIBS = @ZLIB_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = core display gfx input media misc windows +INCLUDES = \ + -I$(top_builddir)/include \ + -I$(top_builddir)/lib \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/lib \ + -I$(top_srcdir)/src + +AM_CPPFLAGS = \ + -DDATADIR=\"${RUNTIME_SYSROOT}@DATADIR@\" \ + -DMODULEDIR=\"${RUNTIME_SYSROOT}@MODULEDIR@\" + +internalincludedir = $(INTERNALINCLUDEDIR) +internalinclude_HEADERS = \ + idirectfb.h + +lib_LTLIBRARIES = libdirectfb.la +libdirectfb_la_SOURCES = \ + directfb.c \ + idirectfb.c + +libdirectfb_la_LDFLAGS = \ + -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ + -release $(LT_RELEASE) \ + $(DFB_LDFLAGS) + +libdirectfb_la_LIBADD = \ + display/libdirectfb_display.la \ + media/libdirectfb_media.la \ + windows/libdirectfb_windows.la \ + input/libdirectfb_input.la \ + misc/libdirectfb_misc.la \ + gfx/libdirectfb_gfx.la \ + core/libdirectfb_core.la \ + ../lib/direct/libdirect.la \ + ../lib/fusion/libfusion.la + +@BUILD_SHARED_TRUE@@ENABLE_TRACE_TRUE@LIBTONM = $(LTLIBRARIES:.la=-$(LT_RELEASE).so.$(LT_BINARY)) +all: all-recursive + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/rules/nmfile.make $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)" + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + if test -f $$p; then \ + f=$(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \ + else :; fi; \ + done + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + p=$(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libdirectfb.la: $(libdirectfb_la_OBJECTS) $(libdirectfb_la_DEPENDENCIES) + $(libdirectfb_la_LINK) -rpath $(libdir) $(libdirectfb_la_OBJECTS) $(libdirectfb_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/directfb.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/idirectfb.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-internalincludeHEADERS: $(internalinclude_HEADERS) + @$(NORMAL_INSTALL) + test -z "$(internalincludedir)" || $(MKDIR_P) "$(DESTDIR)$(internalincludedir)" + @list='$(internalinclude_HEADERS)'; for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + f=$(am__strip_dir) \ + echo " $(internalincludeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(internalincludedir)/$$f'"; \ + $(internalincludeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(internalincludedir)/$$f"; \ + done + +uninstall-internalincludeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(internalinclude_HEADERS)'; for p in $$list; do \ + f=$(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(internalincludedir)/$$f'"; \ + rm -f "$(DESTDIR)$(internalincludedir)/$$f"; \ + done + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +$(RECURSIVE_CLEAN_TARGETS): + @failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done + list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + distdir=`$(am__cd) $(distdir) && pwd`; \ + top_distdir=`$(am__cd) $(top_distdir) && pwd`; \ + (cd $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$top_distdir" \ + distdir="$$distdir/$$subdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile $(LTLIBRARIES) $(HEADERS) all-local +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(internalincludedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +@BUILD_SHARED_FALSE@install-data-local: +@ENABLE_TRACE_FALSE@install-data-local: +clean: clean-recursive + +clean-am: clean-generic clean-libLTLIBRARIES clean-libtool clean-local \ + mostlyclean-am + +distclean: distclean-recursive + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +info: info-recursive + +info-am: + +install-data-am: install-data-local install-internalincludeHEADERS + +install-dvi: install-dvi-recursive + +install-exec-am: install-libLTLIBRARIES + +install-html: install-html-recursive + +install-info: install-info-recursive + +install-man: + +install-pdf: install-pdf-recursive + +install-ps: install-ps-recursive + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-internalincludeHEADERS \ + uninstall-libLTLIBRARIES + +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) install-am \ + install-strip + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am all-local check check-am clean clean-generic \ + clean-libLTLIBRARIES clean-libtool clean-local ctags \ + ctags-recursive distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-data-local install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-internalincludeHEADERS \ + install-libLTLIBRARIES install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-recursive uninstall uninstall-am \ + uninstall-internalincludeHEADERS uninstall-libLTLIBRARIES + + +# +# + +@BUILD_STATIC_TRUE@clean-local: +@BUILD_STATIC_TRUE@ rm -f libdirectfb_fixed.a + +@BUILD_STATIC_TRUE@all-local: libdirectfb_fixed.a + +@BUILD_STATIC_TRUE@libdirectfb_fixed.a: .libs/libdirectfb.a +@BUILD_STATIC_TRUE@ rm -f libdirectfb_fixed.a +@BUILD_STATIC_TRUE@ ${AR} cru libdirectfb_fixed.a `find . -name "*.o" | grep -v '.libs'` +@BUILD_STATIC_TRUE@ ${RANLIB} libdirectfb_fixed.a +@BUILD_STATIC_TRUE@ cp -pf libdirectfb_fixed.a .libs/libdirectfb.a + +@BUILD_STATIC_TRUE@.libs/libdirectfb.a: libdirectfb.la + +@BUILD_STATIC_FALSE@clean-local: + +@BUILD_STATIC_FALSE@all-local: + +@BUILD_SHARED_TRUE@@ENABLE_TRACE_TRUE@install-data-local: +@BUILD_SHARED_TRUE@@ENABLE_TRACE_TRUE@ mkdir -p -- "$(DESTDIR)$(libdir)" +@BUILD_SHARED_TRUE@@ENABLE_TRACE_TRUE@ nm -n ".libs/$(LIBTONM)" > "$(DESTDIR)$(libdir)/nm-n.$(LIBTONM)" +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/Source/DirectFB/src/core/Makefile.am b/Source/DirectFB/src/core/Makefile.am new file mode 100755 index 0000000..e387345 --- /dev/null +++ b/Source/DirectFB/src/core/Makefile.am @@ -0,0 +1,84 @@ +## Makefile.am for DirectFB/src/core + +INCLUDES = \ + -I$(top_builddir)/include \ + -I$(top_builddir)/lib \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/lib \ + -I$(top_srcdir)/src + +AM_CPPFLAGS = \ + -DDATADIR=\"${RUNTIME_SYSROOT}@DATADIR@\" \ + -DSOPATH=\"@SOPATH@\" \ + -DMODULEDIR=\"${RUNTIME_SYSROOT}@MODULEDIR@\" \ + "-DBUILDTIME=\"`date -u "+%Y-%m-%d %H:%M"`\"" + + +internalincludedir = $(INTERNALINCLUDEDIR)/core + +internalinclude_HEADERS = \ + clipboard.h \ + colorhash.h \ + coredefs.h \ + coretypes.h \ + core_parts.h \ + core_system.h \ + core.h \ + fonts.h \ + gfxcard.h \ + graphics_driver.h \ + input.h \ + input_driver.h \ + layer_context.h \ + layer_control.h \ + layer_region.h \ + layers.h \ + layers_internal.h \ + palette.h \ + screen.h \ + screens.h \ + screens_internal.h \ + state.h \ + surface.h \ + surface_buffer.h \ + surface_pool.h \ + surface_pool_bridge.h \ + system.h \ + windows.h \ + windows_internal.h \ + windowstack.h \ + wm.h \ + wm_module.h + + +noinst_LTLIBRARIES = libdirectfb_core.la + + +libdirectfb_core_la_SOURCES = \ + clipboard.c \ + colorhash.c \ + core.c \ + core_parts.c \ + fonts.c \ + gfxcard.c \ + input.c \ + layer_context.c \ + layer_control.c \ + layer_region.c \ + layers.c \ + local_surface_pool.c \ + palette.c \ + prealloc_surface_pool.c \ + screen.c \ + screens.c \ + shared_surface_pool.c \ + state.c \ + surface.c \ + surface_buffer.c \ + surface_core.c \ + surface_pool.c \ + surface_pool_bridge.c \ + system.c \ + windows.c \ + windowstack.c \ + wm.c diff --git a/Source/DirectFB/src/core/Makefile.in b/Source/DirectFB/src/core/Makefile.in new file mode 100755 index 0000000..9955d0b --- /dev/null +++ b/Source/DirectFB/src/core/Makefile.in @@ -0,0 +1,648 @@ +# Makefile.in generated by automake 1.10.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = src/core +DIST_COMMON = $(internalinclude_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/as-ac-expand.m4 \ + $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libdirectfb_core_la_LIBADD = +am_libdirectfb_core_la_OBJECTS = clipboard.lo colorhash.lo core.lo \ + core_parts.lo fonts.lo gfxcard.lo input.lo layer_context.lo \ + layer_control.lo layer_region.lo layers.lo \ + local_surface_pool.lo palette.lo prealloc_surface_pool.lo \ + screen.lo screens.lo shared_surface_pool.lo state.lo \ + surface.lo surface_buffer.lo surface_core.lo surface_pool.lo \ + surface_pool_bridge.lo system.lo windows.lo windowstack.lo \ + wm.lo +libdirectfb_core_la_OBJECTS = $(am_libdirectfb_core_la_OBJECTS) +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libdirectfb_core_la_SOURCES) +DIST_SOURCES = $(libdirectfb_core_la_SOURCES) +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(internalincludedir)" +internalincludeHEADERS_INSTALL = $(INSTALL_HEADER) +HEADERS = $(internalinclude_HEADERS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AS = @AS@ +ASFLAGS = @ASFLAGS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIR = @DATADIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DFB_CFLAGS_OMIT_FRAME_POINTER = @DFB_CFLAGS_OMIT_FRAME_POINTER@ +DFB_INTERNAL_CFLAGS = @DFB_INTERNAL_CFLAGS@ +DFB_LDFLAGS = @DFB_LDFLAGS@ +DFB_SMOOTH_SCALING = @DFB_SMOOTH_SCALING@ +DIRECTFB_BINARY_AGE = @DIRECTFB_BINARY_AGE@ +DIRECTFB_CSOURCE = @DIRECTFB_CSOURCE@ +DIRECTFB_INTERFACE_AGE = @DIRECTFB_INTERFACE_AGE@ +DIRECTFB_MAJOR_VERSION = @DIRECTFB_MAJOR_VERSION@ +DIRECTFB_MICRO_VERSION = @DIRECTFB_MICRO_VERSION@ +DIRECTFB_MINOR_VERSION = @DIRECTFB_MINOR_VERSION@ +DIRECTFB_VERSION = @DIRECTFB_VERSION@ +DIRECT_BUILD_DEBUG = @DIRECT_BUILD_DEBUG@ +DIRECT_BUILD_DEBUGS = @DIRECT_BUILD_DEBUGS@ +DIRECT_BUILD_GETTID = @DIRECT_BUILD_GETTID@ +DIRECT_BUILD_NETWORK = @DIRECT_BUILD_NETWORK@ +DIRECT_BUILD_STDBOOL = @DIRECT_BUILD_STDBOOL@ +DIRECT_BUILD_TEXT = @DIRECT_BUILD_TEXT@ +DIRECT_BUILD_TRACE = @DIRECT_BUILD_TRACE@ +DSYMUTIL = @DSYMUTIL@ +DYNLIB = @DYNLIB@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +FREETYPE_CFLAGS = @FREETYPE_CFLAGS@ +FREETYPE_LIBS = @FREETYPE_LIBS@ +FREETYPE_PROVIDER = @FREETYPE_PROVIDER@ +FUSION_BUILD_KERNEL = @FUSION_BUILD_KERNEL@ +FUSION_BUILD_MULTI = @FUSION_BUILD_MULTI@ +FUSION_MESSAGE_SIZE = @FUSION_MESSAGE_SIZE@ +GIF_PROVIDER = @GIF_PROVIDER@ +GREP = @GREP@ +HAVE_LINUX = @HAVE_LINUX@ +INCLUDEDIR = @INCLUDEDIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTERNALINCLUDEDIR = @INTERNALINCLUDEDIR@ +JPEG_PROVIDER = @JPEG_PROVIDER@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBJPEG = @LIBJPEG@ +LIBOBJS = @LIBOBJS@ +LIBPNG = @LIBPNG@ +LIBPNG_CONFIG = @LIBPNG_CONFIG@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_AGE = @LT_AGE@ +LT_BINARY = @LT_BINARY@ +LT_CURRENT = @LT_CURRENT@ +LT_RELEASE = @LT_RELEASE@ +LT_REVISION = @LT_REVISION@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MAN2HTML = @MAN2HTML@ +MKDIR_P = @MKDIR_P@ +MODULEDIR = @MODULEDIR@ +MODULEDIRNAME = @MODULEDIRNAME@ +NMEDIT = @NMEDIT@ +OBJEXT = @OBJEXT@ +OSX_LIBS = @OSX_LIBS@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PNG_PROVIDER = @PNG_PROVIDER@ +RANLIB = @RANLIB@ +RUNTIME_SYSROOT = @RUNTIME_SYSROOT@ +SDL_CFLAGS = @SDL_CFLAGS@ +SDL_LIBS = @SDL_LIBS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOPATH = @SOPATH@ +STRIP = @STRIP@ +SYSCONFDIR = @SYSCONFDIR@ +SYSFS_LIBS = @SYSFS_LIBS@ +THREADFLAGS = @THREADFLAGS@ +THREADLIB = @THREADLIB@ +TSLIB_CFLAGS = @TSLIB_CFLAGS@ +TSLIB_LIBS = @TSLIB_LIBS@ +VERSION = @VERSION@ +VNC_CFLAGS = @VNC_CFLAGS@ +VNC_CONFIG = @VNC_CONFIG@ +VNC_LIBS = @VNC_LIBS@ +X11_CFLAGS = @X11_CFLAGS@ +X11_LIBS = @X11_LIBS@ +ZLIB_LIBS = @ZLIB_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +INCLUDES = \ + -I$(top_builddir)/include \ + -I$(top_builddir)/lib \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/lib \ + -I$(top_srcdir)/src + +AM_CPPFLAGS = \ + -DDATADIR=\"${RUNTIME_SYSROOT}@DATADIR@\" \ + -DSOPATH=\"@SOPATH@\" \ + -DMODULEDIR=\"${RUNTIME_SYSROOT}@MODULEDIR@\" \ + "-DBUILDTIME=\"`date -u "+%Y-%m-%d %H:%M"`\"" + +internalincludedir = $(INTERNALINCLUDEDIR)/core +internalinclude_HEADERS = \ + clipboard.h \ + colorhash.h \ + coredefs.h \ + coretypes.h \ + core_parts.h \ + core_system.h \ + core.h \ + fonts.h \ + gfxcard.h \ + graphics_driver.h \ + input.h \ + input_driver.h \ + layer_context.h \ + layer_control.h \ + layer_region.h \ + layers.h \ + layers_internal.h \ + palette.h \ + screen.h \ + screens.h \ + screens_internal.h \ + state.h \ + surface.h \ + surface_buffer.h \ + surface_pool.h \ + surface_pool_bridge.h \ + system.h \ + windows.h \ + windows_internal.h \ + windowstack.h \ + wm.h \ + wm_module.h + +noinst_LTLIBRARIES = libdirectfb_core.la +libdirectfb_core_la_SOURCES = \ + clipboard.c \ + colorhash.c \ + core.c \ + core_parts.c \ + fonts.c \ + gfxcard.c \ + input.c \ + layer_context.c \ + layer_control.c \ + layer_region.c \ + layers.c \ + local_surface_pool.c \ + palette.c \ + prealloc_surface_pool.c \ + screen.c \ + screens.c \ + shared_surface_pool.c \ + state.c \ + surface.c \ + surface_buffer.c \ + surface_core.c \ + surface_pool.c \ + surface_pool_bridge.c \ + system.c \ + windows.c \ + windowstack.c \ + wm.c + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/core/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/core/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libdirectfb_core.la: $(libdirectfb_core_la_OBJECTS) $(libdirectfb_core_la_DEPENDENCIES) + $(LINK) $(libdirectfb_core_la_OBJECTS) $(libdirectfb_core_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clipboard.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/colorhash.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/core.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/core_parts.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fonts.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gfxcard.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/input.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/layer_context.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/layer_control.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/layer_region.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/layers.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/local_surface_pool.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/palette.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/prealloc_surface_pool.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/screen.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/screens.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/shared_surface_pool.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/state.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/surface.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/surface_buffer.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/surface_core.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/surface_pool.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/surface_pool_bridge.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/system.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/windows.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/windowstack.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wm.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-internalincludeHEADERS: $(internalinclude_HEADERS) + @$(NORMAL_INSTALL) + test -z "$(internalincludedir)" || $(MKDIR_P) "$(DESTDIR)$(internalincludedir)" + @list='$(internalinclude_HEADERS)'; for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + f=$(am__strip_dir) \ + echo " $(internalincludeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(internalincludedir)/$$f'"; \ + $(internalincludeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(internalincludedir)/$$f"; \ + done + +uninstall-internalincludeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(internalinclude_HEADERS)'; for p in $$list; do \ + f=$(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(internalincludedir)/$$f'"; \ + rm -f "$(DESTDIR)$(internalincludedir)/$$f"; \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(internalincludedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: install-internalincludeHEADERS + +install-dvi: install-dvi-am + +install-exec-am: + +install-html: install-html-am + +install-info: install-info-am + +install-man: + +install-pdf: install-pdf-am + +install-ps: install-ps-am + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-internalincludeHEADERS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am \ + install-internalincludeHEADERS install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-internalincludeHEADERS + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/Source/DirectFB/src/core/clipboard.c b/Source/DirectFB/src/core/clipboard.c new file mode 100755 index 0000000..53fde34 --- /dev/null +++ b/Source/DirectFB/src/core/clipboard.c @@ -0,0 +1,298 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include + +#include +#include + +#include + +#include +#include +#include + + +D_DEBUG_DOMAIN( Core_Clipboard, "Core/Clipboard", "DirectFB Clipboard Core" ); + +/**********************************************************************************************************************/ + +typedef struct { + int magic; + + FusionSkirmish lock; + char *mime_type; + void *data; + unsigned int size; + struct timeval timestamp; + + FusionSHMPoolShared *shmpool; +} DFBClipboardCoreShared; + +struct __DFB_DFBClipboardCore { + int magic; + + CoreDFB *core; + + DFBClipboardCoreShared *shared; +}; + + +DFB_CORE_PART( clipboard_core, ClipboardCore ); + +/**********************************************************************************************************************/ + +static DFBResult +dfb_clipboard_core_initialize( CoreDFB *core, + DFBClipboardCore *data, + DFBClipboardCoreShared *shared ) +{ + D_DEBUG_AT( Core_Clipboard, "dfb_clipboard_core_initialize( %p, %p, %p )\n", core, data, shared ); + + D_ASSERT( data != NULL ); + D_ASSERT( shared != NULL ); + + data->core = core; + data->shared = shared; + + shared->shmpool = dfb_core_shmpool( core ); + + fusion_skirmish_init( &shared->lock, "Clipboard Core", dfb_core_world(core) ); + + D_MAGIC_SET( data, DFBClipboardCore ); + D_MAGIC_SET( shared, DFBClipboardCoreShared ); + + return DFB_OK; +} + +static DFBResult +dfb_clipboard_core_join( CoreDFB *core, + DFBClipboardCore *data, + DFBClipboardCoreShared *shared ) +{ + D_DEBUG_AT( Core_Clipboard, "dfb_clipboard_core_join( %p, %p, %p )\n", core, data, shared ); + + D_ASSERT( data != NULL ); + D_MAGIC_ASSERT( shared, DFBClipboardCoreShared ); + + data->core = core; + data->shared = shared; + + D_MAGIC_SET( data, DFBClipboardCore ); + + return DFB_OK; +} + +static DFBResult +dfb_clipboard_core_shutdown( DFBClipboardCore *data, + bool emergency ) +{ + DFBClipboardCoreShared *shared; + + D_DEBUG_AT( Core_Clipboard, "dfb_clipboard_core_shutdown( %p, %semergency )\n", data, emergency ? "" : "no " ); + + D_MAGIC_ASSERT( data, DFBClipboardCore ); + + shared = data->shared; + + D_MAGIC_ASSERT( shared, DFBClipboardCoreShared ); + + fusion_skirmish_destroy( &shared->lock ); + + if (shared->data) + SHFREE( shared->shmpool, shared->data ); + + if (shared->mime_type) + SHFREE( shared->shmpool, shared->mime_type ); + + D_MAGIC_CLEAR( data ); + D_MAGIC_CLEAR( shared ); + + return DFB_OK; +} + +static DFBResult +dfb_clipboard_core_leave( DFBClipboardCore *data, + bool emergency ) +{ + D_DEBUG_AT( Core_Clipboard, "dfb_clipboard_core_leave( %p, %semergency )\n", data, emergency ? "" : "no " ); + + D_MAGIC_ASSERT( data, DFBClipboardCore ); + D_MAGIC_ASSERT( data->shared, DFBClipboardCoreShared ); + + D_MAGIC_CLEAR( data ); + + return DFB_OK; +} + +static DFBResult +dfb_clipboard_core_suspend( DFBClipboardCore *data ) +{ + D_DEBUG_AT( Core_Clipboard, "dfb_clipboard_core_suspend( %p )\n", data ); + + D_MAGIC_ASSERT( data, DFBClipboardCore ); + D_MAGIC_ASSERT( data->shared, DFBClipboardCoreShared ); + + return DFB_OK; +} + +static DFBResult +dfb_clipboard_core_resume( DFBClipboardCore *data ) +{ + D_DEBUG_AT( Core_Clipboard, "dfb_clipboard_core_resume( %p )\n", data ); + + D_MAGIC_ASSERT( data, DFBClipboardCore ); + D_MAGIC_ASSERT( data->shared, DFBClipboardCoreShared ); + + return DFB_OK; +} + +/**********************************************************************************************************************/ + +DFBResult +dfb_clipboard_set( DFBClipboardCore *core, + const char *mime_type, + const void *data, + unsigned int size, + struct timeval *timestamp ) +{ + DFBClipboardCoreShared *shared; + + char *new_mime; + void *new_data; + + D_MAGIC_ASSERT( core, DFBClipboardCore ); + D_ASSERT( mime_type != NULL ); + D_ASSERT( data != NULL ); + D_ASSERT( size > 0 ); + + shared = core->shared; + + D_MAGIC_ASSERT( shared, DFBClipboardCoreShared ); + + new_mime = SHSTRDUP( shared->shmpool, mime_type ); + if (!new_mime) + return D_OOSHM(); + + new_data = SHMALLOC( shared->shmpool, size ); + if (!new_data) { + SHFREE( shared->shmpool, new_mime ); + return D_OOSHM(); + } + + direct_memcpy( new_data, data, size ); + + if (fusion_skirmish_prevail( &shared->lock )) { + SHFREE( shared->shmpool, new_data ); + SHFREE( shared->shmpool, new_mime ); + return DFB_FUSION; + } + + if (shared->data) + SHFREE( shared->shmpool, shared->data ); + + if (shared->mime_type) + SHFREE( shared->shmpool, shared->mime_type ); + + shared->mime_type = new_mime; + shared->data = new_data; + shared->size = size; + + gettimeofday( &shared->timestamp, NULL ); + + if (timestamp) + *timestamp = shared->timestamp; + + fusion_skirmish_dismiss( &shared->lock ); + + return DFB_OK; +} + +DFBResult +dfb_clipboard_get( DFBClipboardCore *core, + char **mime_type, + void **data, + unsigned int *size ) +{ + DFBClipboardCoreShared *shared; + + D_MAGIC_ASSERT( core, DFBClipboardCore ); + + shared = core->shared; + + D_MAGIC_ASSERT( shared, DFBClipboardCoreShared ); + + if (fusion_skirmish_prevail( &shared->lock )) + return DFB_FUSION; + + if (!shared->mime_type || !shared->data) { + fusion_skirmish_dismiss( &shared->lock ); + return DFB_BUFFEREMPTY; + } + + if (mime_type) + *mime_type = strdup( shared->mime_type ); + + if (data) { + *data = malloc( shared->size ); + direct_memcpy( *data, shared->data, shared->size ); + } + + if (size) + *size = shared->size; + + fusion_skirmish_dismiss( &shared->lock ); + + return DFB_OK; +} + +DFBResult +dfb_clipboard_get_timestamp( DFBClipboardCore *core, + struct timeval *timestamp ) +{ + DFBClipboardCoreShared *shared; + + D_MAGIC_ASSERT( core, DFBClipboardCore ); + D_ASSERT( timestamp != NULL ); + + shared = core->shared; + + D_MAGIC_ASSERT( shared, DFBClipboardCoreShared ); + + if (fusion_skirmish_prevail( &shared->lock )) + return DFB_FUSION; + + *timestamp = shared->timestamp; + + fusion_skirmish_dismiss( &shared->lock ); + + return DFB_OK; +} + diff --git a/Source/DirectFB/src/core/clipboard.h b/Source/DirectFB/src/core/clipboard.h new file mode 100755 index 0000000..ffb9c43 --- /dev/null +++ b/Source/DirectFB/src/core/clipboard.h @@ -0,0 +1,53 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __CORE__CLIPBOARD_H__ +#define __CORE__CLIPBOARD_H__ + +#include + +#include + + +DFBResult dfb_clipboard_set( DFBClipboardCore *core, + const char *mime_type, + const void *data, + unsigned int size, + struct timeval *timestamp ); + +DFBResult dfb_clipboard_get( DFBClipboardCore *core, + char **mime_type, + void **data, + unsigned int *size ); + + +DFBResult dfb_clipboard_get_timestamp( DFBClipboardCore *core, + struct timeval *timestamp ); + +#endif + diff --git a/Source/DirectFB/src/core/colorhash.c b/Source/DirectFB/src/core/colorhash.c new file mode 100755 index 0000000..370697d --- /dev/null +++ b/Source/DirectFB/src/core/colorhash.c @@ -0,0 +1,366 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include + + +D_DEBUG_DOMAIN( Core_ColorHash, "Core/ColorHash", "DirectFB ColorHash Core" ); + + +#define HASH_SIZE 823 + +typedef struct { + unsigned int pixel; + unsigned int index; + CorePalette *palette; +} Colorhash; + +/**********************************************************************************************************************/ + +typedef struct { + int magic; + + Colorhash *hash; + unsigned int hash_users; + FusionSkirmish hash_lock; + + FusionSHMPoolShared *shmpool; +} DFBColorHashCoreShared; + +struct __DFB_DFBColorHashCore { + int magic; + + CoreDFB *core; + + DFBColorHashCoreShared *shared; +}; + +DFB_CORE_PART( colorhash_core, ColorHashCore ); + +/**********************************************************************************************************************/ + +static DFBColorHashCore *core_colorhash; /* FIXME */ + + +static DFBResult +dfb_colorhash_core_initialize( CoreDFB *core, + DFBColorHashCore *data, + DFBColorHashCoreShared *shared ) +{ + D_DEBUG_AT( Core_ColorHash, "dfb_colorhash_core_initialize( %p, %p, %p )\n", core, data, shared ); + + D_ASSERT( data != NULL ); + D_ASSERT( shared != NULL ); + + core_colorhash = data; /* FIXME */ + + data->core = core; + data->shared = shared; + + shared->shmpool = dfb_core_shmpool( core ); + + fusion_skirmish_init( &shared->hash_lock, "Colorhash Core", dfb_core_world(core) ); + + D_MAGIC_SET( data, DFBColorHashCore ); + D_MAGIC_SET( shared, DFBColorHashCoreShared ); + + return DFB_OK; +} + +static DFBResult +dfb_colorhash_core_join( CoreDFB *core, + DFBColorHashCore *data, + DFBColorHashCoreShared *shared ) +{ + D_DEBUG_AT( Core_ColorHash, "dfb_colorhash_core_join( %p, %p, %p )\n", core, data, shared ); + + D_ASSERT( data != NULL ); + D_MAGIC_ASSERT( shared, DFBColorHashCoreShared ); + + core_colorhash = data; /* FIXME */ + + data->core = core; + data->shared = shared; + + D_MAGIC_SET( data, DFBColorHashCore ); + + return DFB_OK; +} + +static DFBResult +dfb_colorhash_core_shutdown( DFBColorHashCore *data, + bool emergency ) +{ + DFBColorHashCoreShared *shared; + + D_DEBUG_AT( Core_ColorHash, "dfb_colorhash_core_shutdown( %p, %semergency )\n", data, emergency ? "" : "no " ); + + D_MAGIC_ASSERT( data, DFBColorHashCore ); + D_MAGIC_ASSERT( data->shared, DFBColorHashCoreShared ); + + shared = data->shared; + + fusion_skirmish_destroy( &shared->hash_lock ); + + D_MAGIC_CLEAR( data ); + D_MAGIC_CLEAR( shared ); + + return DFB_OK; +} + +static DFBResult +dfb_colorhash_core_leave( DFBColorHashCore *data, + bool emergency ) +{ + DFBColorHashCoreShared *shared; + + D_DEBUG_AT( Core_ColorHash, "dfb_colorhash_core_leave( %p, %semergency )\n", data, emergency ? "" : "no " ); + + D_MAGIC_ASSERT( data, DFBColorHashCore ); + D_MAGIC_ASSERT( data->shared, DFBColorHashCoreShared ); + + shared = data->shared; + + D_MAGIC_CLEAR( data ); + + return DFB_OK; +} + +static DFBResult +dfb_colorhash_core_suspend( DFBColorHashCore *data ) +{ + DFBColorHashCoreShared *shared; + + D_DEBUG_AT( Core_ColorHash, "dfb_colorhash_core_suspend( %p )\n", data ); + + D_MAGIC_ASSERT( data, DFBColorHashCore ); + D_MAGIC_ASSERT( data->shared, DFBColorHashCoreShared ); + + shared = data->shared; + + return DFB_OK; +} + +static DFBResult +dfb_colorhash_core_resume( DFBColorHashCore *data ) +{ + DFBColorHashCoreShared *shared; + + D_DEBUG_AT( Core_ColorHash, "dfb_colorhash_core_resume( %p )\n", data ); + + D_MAGIC_ASSERT( data, DFBColorHashCore ); + D_MAGIC_ASSERT( data->shared, DFBColorHashCoreShared ); + + shared = data->shared; + + return DFB_OK; +} + +/**********************************************************************************************************************/ + +void +dfb_colorhash_attach( DFBColorHashCore *core, + CorePalette *palette ) +{ + DFBColorHashCoreShared *shared; + + D_ASSUME( core != NULL ); + + if (core) { + D_MAGIC_ASSERT( core, DFBColorHashCore ); + D_MAGIC_ASSERT( core->shared, DFBColorHashCoreShared ); + } + else + core = core_colorhash; + + shared = core->shared; + + fusion_skirmish_prevail( &shared->hash_lock ); + + if (!shared->hash) { + D_ASSERT( shared->hash_users == 0 ); + + shared->hash = SHCALLOC( shared->shmpool, HASH_SIZE, sizeof (Colorhash) ); + } + + shared->hash_users++; + + fusion_skirmish_dismiss( &shared->hash_lock ); +} + +void +dfb_colorhash_detach( DFBColorHashCore *core, + CorePalette *palette ) +{ + DFBColorHashCoreShared *shared; + + D_ASSUME( core != NULL ); + + if (core) { + D_MAGIC_ASSERT( core, DFBColorHashCore ); + D_MAGIC_ASSERT( core->shared, DFBColorHashCoreShared ); + } + else + core = core_colorhash; + + shared = core->shared; + + D_ASSERT( shared->hash_users > 0 ); + D_ASSERT( shared->hash != NULL ); + + fusion_skirmish_prevail( &shared->hash_lock ); + + shared->hash_users--; + + if (!shared->hash_users) { + /* no more users, free allocated resources */ + SHFREE( shared->shmpool, shared->hash ); + shared->hash = NULL; + } + + fusion_skirmish_dismiss( &shared->hash_lock ); +} + +unsigned int +dfb_colorhash_lookup( DFBColorHashCore *core, + CorePalette *palette, + u8 r, + u8 g, + u8 b, + u8 a ) +{ + unsigned int pixel = PIXEL_ARGB(a, r, g, b); + unsigned int index = (pixel ^ (unsigned long) palette) % HASH_SIZE; + DFBColorHashCoreShared *shared; + +// D_ASSUME( core != NULL ); + + if (core) { + D_MAGIC_ASSERT( core, DFBColorHashCore ); + D_MAGIC_ASSERT( core->shared, DFBColorHashCoreShared ); + } + else + core = core_colorhash; + + shared = core->shared; + + D_ASSERT( shared->hash != NULL ); + + fusion_skirmish_prevail( &shared->hash_lock ); + + /* try a lookup in the hash table */ + if (shared->hash[index].palette == palette && shared->hash[index].pixel == pixel) { + /* set the return value */ + index = shared->hash[index].index; + } else { /* look for the closest match */ + DFBColor *entries = palette->entries; + int min_diff = 0; + unsigned int i, min_index = 0; + + for (i = 0; i < palette->num_entries; i++) { + int diff; + + int r_diff = (int) entries[i].r - (int) r; + int g_diff = (int) entries[i].g - (int) g; + int b_diff = (int) entries[i].b - (int) b; + int a_diff = (int) entries[i].a - (int) a; + + if (a) + diff = (r_diff * r_diff + g_diff * g_diff + + b_diff * b_diff + ((a_diff * a_diff) >> 6)); + else + diff = (r_diff + g_diff + b_diff + (a_diff * a_diff)); + + if (i == 0 || diff < min_diff) { + min_diff = diff; + min_index = i; + } + + if (!diff) + break; + } + + /* store the matching entry in the hash table */ + shared->hash[index].pixel = pixel; + shared->hash[index].index = min_index; + shared->hash[index].palette = palette; + + /* set the return value */ + index = min_index; + } + + fusion_skirmish_dismiss( &shared->hash_lock ); + + return index; +} + +void +dfb_colorhash_invalidate( DFBColorHashCore *core, + CorePalette *palette ) +{ + unsigned int index = HASH_SIZE - 1; + DFBColorHashCoreShared *shared; + + D_ASSUME( core != NULL ); + + if (core) { + D_MAGIC_ASSERT( core, DFBColorHashCore ); + D_MAGIC_ASSERT( core->shared, DFBColorHashCoreShared ); + } + else + core = core_colorhash; + + shared = core->shared; + + D_ASSERT( shared->hash != NULL ); + + fusion_skirmish_prevail( &shared->hash_lock ); + + /* invalidate all entries owned by this palette */ + do { + if (shared->hash[index].palette == palette) + shared->hash[index].palette = NULL; + } while (index--); + + fusion_skirmish_dismiss( &shared->hash_lock ); +} + diff --git a/Source/DirectFB/src/core/colorhash.h b/Source/DirectFB/src/core/colorhash.h new file mode 100755 index 0000000..d321000 --- /dev/null +++ b/Source/DirectFB/src/core/colorhash.h @@ -0,0 +1,54 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __CORE__COLORHASH_H__ +#define __CORE__COLORHASH_H__ + +#include + +#include + + +void dfb_colorhash_attach ( DFBColorHashCore *core, + CorePalette *palette ); + +void dfb_colorhash_detach ( DFBColorHashCore *core, + CorePalette *palette ); + +unsigned int dfb_colorhash_lookup ( DFBColorHashCore *core, + CorePalette *palette, + u8 r, + u8 g, + u8 b, + u8 a); + +void dfb_colorhash_invalidate( DFBColorHashCore *core, + CorePalette *palette ); + +#endif + diff --git a/Source/DirectFB/src/core/core.c b/Source/DirectFB/src/core/core.c new file mode 100755 index 0000000..ca20152 --- /dev/null +++ b/Source/DirectFB/src/core/core.c @@ -0,0 +1,1160 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +D_DEBUG_DOMAIN( DirectFB_Core, "DirectFB/Core", "DirectFB Core" ); + +/******************************************************************************/ + +extern CorePart dfb_clipboard_core; +extern CorePart dfb_colorhash_core; +extern CorePart dfb_graphics_core; +extern CorePart dfb_input_core; +extern CorePart dfb_layer_core; +extern CorePart dfb_screen_core; +extern CorePart dfb_surface_core; +extern CorePart dfb_system_core; +extern CorePart dfb_wm_core; + +static CorePart *core_parts[] = { + &dfb_clipboard_core, + &dfb_colorhash_core, + &dfb_surface_core, + &dfb_system_core, + &dfb_input_core, + &dfb_graphics_core, + &dfb_screen_core, + &dfb_layer_core, + &dfb_wm_core +}; + +void * +dfb_core_get_part( CoreDFB *core, + DFBCorePartID part_id ) +{ + switch (part_id) { + case DFCP_CLIPBOARD: + return dfb_clipboard_core.data_local; + + case DFCP_COLORHASH: + return dfb_colorhash_core.data_local; + + case DFCP_GRAPHICS: + return dfb_graphics_core.data_local; + + case DFCP_INPUT: + return dfb_input_core.data_local; + + case DFCP_LAYER: + return dfb_layer_core.data_local; + + case DFCP_SCREEN: + return dfb_screen_core.data_local; + + case DFCP_SURFACE: + return dfb_surface_core.data_local; + + case DFCP_SYSTEM: + return dfb_system_core.data_local; + + case DFCP_WM: + return dfb_wm_core.data_local; + + default: + D_BUG( "unknown core part" ); + } + + return NULL; +} + +/******************************************************************************/ + +/* + * one entry in the cleanup stack + */ +struct _CoreCleanup { + DirectLink link; + + CoreCleanupFunc func; /* the cleanup function to be called */ + void *data; /* context of the cleanup function */ + bool emergency; /* if true, cleanup is also done during + emergency shutdown (from signal hadler) */ +}; + +/******************************************************************************/ + +struct __DFB_CoreDFBShared { + int magic; + + FusionSkirmish lock; + bool active; + + FusionObjectPool *layer_context_pool; + FusionObjectPool *layer_region_pool; + FusionObjectPool *palette_pool; + FusionObjectPool *surface_pool; + FusionObjectPool *window_pool; + + FusionSHMPoolShared *shmpool; + FusionSHMPoolShared *shmpool_data; /* for raw data, e.g. surface buffers */ +}; + +struct __DFB_CoreDFB { + int magic; + + int refs; + + int fusion_id; + + FusionWorld *world; + FusionArena *arena; + + CoreDFBShared *shared; + + bool master; + bool suspended; + + DirectLink *cleanups; + + DirectThreadInitHandler *init_handler; + + DirectSignalHandler *signal_handler; + + DirectCleanupHandler *cleanup_handler; +}; + +/******************************************************************************/ + +/* + * ckecks if stack is clean, otherwise prints warning, then calls core_deinit() + */ +static void dfb_core_deinit_check( void *ctx ); + +static void dfb_core_thread_init_handler( DirectThread *thread, void *arg ); + +static void dfb_core_process_cleanups( CoreDFB *core, bool emergency ); + +static DirectSignalHandlerResult dfb_core_signal_handler( int num, + void *addr, + void *ctx ); + +/******************************************************************************/ + +static int dfb_core_arena_initialize( FusionArena *arena, + void *ctx ); +static int dfb_core_arena_shutdown ( FusionArena *arena, + void *ctx, + bool emergency ); +static int dfb_core_arena_join ( FusionArena *arena, + void *ctx ); +static int dfb_core_arena_leave ( FusionArena *arena, + void *ctx, + bool emergency ); + +/******************************************************************************/ + +#if defined(DFB_DYNAMIC_LINKING) && defined(SOPATH) +/* + * the library handle for dlopen'ing ourselves + */ +static void* dfb_lib_handle = NULL; +#endif + +/******************************************************************************/ + +static CoreDFB *core_dfb = NULL; +static pthread_mutex_t core_dfb_lock = PTHREAD_MUTEX_INITIALIZER; + +/******************************************************************************/ + +DFBResult +dfb_core_create( CoreDFB **ret_core ) +{ + int ret; +#if FUSION_BUILD_MULTI + char buf[16]; +#endif + CoreDFB *core = NULL; + CoreDFBShared *shared = NULL; + + D_ASSERT( ret_core != NULL ); + D_ASSERT( dfb_config != NULL ); + + D_DEBUG_AT( DirectFB_Core, "%s...\n", __FUNCTION__ ); + + pthread_mutex_lock( &core_dfb_lock ); + + D_ASSERT( core_dfb == NULL || core_dfb->refs > 0 ); + + if (core_dfb) { + D_MAGIC_ASSERT( core_dfb, CoreDFB ); + + core_dfb->refs++; + + *ret_core = core_dfb; + + pthread_mutex_unlock( &core_dfb_lock ); + + return DFB_OK; + } + + direct_initialize(); + + + D_INFO( "DirectFB/Core: %s Application Core. ("BUILDTIME") %s%s\n", + FUSION_BUILD_MULTI ? "Multi" : "Single", + DIRECT_BUILD_DEBUG ? "[ DEBUG ]" : "", + DIRECT_BUILD_TRACE ? "[ TRACE ]" : "" ); + + +#if defined(DFB_DYNAMIC_LINKING) && defined(SOPATH) + if (!dfb_lib_handle) +#ifdef RTLD_GLOBAL + dfb_lib_handle = dlopen(SOPATH, RTLD_GLOBAL|RTLD_LAZY); +#else + /* RTLD_GLOBAL is not defined on OpenBSD */ + dfb_lib_handle = dlopen(SOPATH, RTLD_LAZY); +#endif +#endif + + ret = dfb_system_lookup(); + if (ret) + goto error; + + + /* Allocate local core structure. */ + core = D_CALLOC( 1, sizeof(CoreDFB) ); + if (!core) { + ret = D_OOM(); + goto error; + } + + core->refs = 1; + + core->init_handler = direct_thread_add_init_handler( dfb_core_thread_init_handler, core ); + +#if FUSION_BUILD_MULTI + dfb_system_thread_init(); +#endif + + direct_find_best_memcpy(); + + D_MAGIC_SET( core, CoreDFB ); + + core_dfb = core; + + ret = fusion_enter( dfb_config->session, DIRECTFB_CORE_ABI, FER_ANY, &core->world ); + if (ret) + goto error; + + core->fusion_id = fusion_id( core->world ); + +#if FUSION_BUILD_MULTI + D_DEBUG_AT( DirectFB_Core, "world %d, fusion id %d\n", fusion_world_index(core->world), core->fusion_id ); + + snprintf( buf, sizeof(buf), "%d", fusion_world_index(core->world) ); + + setenv( "DIRECTFB_SESSION", buf, true ); +#endif + + if (dfb_config->sync) { + D_INFO( "DirectFB/Core: calling sync()...\n" ); + sync(); + } + + direct_signal_handler_add( DIRECT_SIGNAL_ANY, dfb_core_signal_handler, core, &core->signal_handler ); + + if (fusion_arena_enter( core->world, "DirectFB/Core", + dfb_core_arena_initialize, dfb_core_arena_join, + core, &core->arena, &ret ) || ret) + { + ret = ret ? ret : DFB_FUSION; + goto error; + } + + shared = core->shared; + D_MAGIC_ASSERT( shared, CoreDFBShared ); + + if (dfb_config->block_all_signals) + direct_signals_block_all(); + + if (dfb_config->deinit_check) + direct_cleanup_handler_add( dfb_core_deinit_check, NULL, &core->cleanup_handler ); + + + fusion_skirmish_prevail( &shared->lock ); + + if (!core->master) { + while (!shared->active) + fusion_skirmish_wait( &shared->lock, 0 ); + } + + fusion_skirmish_dismiss( &shared->lock ); + + + *ret_core = core; + + pthread_mutex_unlock( &core_dfb_lock ); + + D_DEBUG_AT( DirectFB_Core, "Core successfully created.\n" ); + + return DFB_OK; + + +error: + if (core) { + if (core->world) + fusion_exit( core->world, false ); + + if (core->init_handler) + direct_thread_remove_init_handler( core->init_handler ); + + if (core->signal_handler) + direct_signal_handler_remove( core->signal_handler ); + + D_MAGIC_CLEAR( core ); + + D_FREE( core ); + core_dfb = NULL; + } + + pthread_mutex_unlock( &core_dfb_lock ); + + direct_shutdown(); + + return ret; +} + +DFBResult +dfb_core_destroy( CoreDFB *core, bool emergency ) +{ + D_MAGIC_ASSERT( core, CoreDFB ); + D_ASSERT( core->refs > 0 ); + D_ASSERT( core == core_dfb ); + + D_DEBUG_AT( DirectFB_Core, "%s...\n", __FUNCTION__ ); + + if (!emergency) { + pthread_mutex_lock( &core_dfb_lock ); + + if (--core->refs) { + pthread_mutex_unlock( &core_dfb_lock ); + return DFB_OK; + } + } + + direct_signal_handler_remove( core->signal_handler ); + + if (core->cleanup_handler) + direct_cleanup_handler_remove( core->cleanup_handler ); + + if (core->master) { + if (emergency) { + fusion_kill( core->world, 0, SIGKILL, 1000 ); + } + else { + fusion_kill( core->world, 0, SIGTERM, 5000 ); + fusion_kill( core->world, 0, SIGKILL, 2000 ); + } + } + + dfb_core_process_cleanups( core, emergency ); + + while (fusion_arena_exit( core->arena, dfb_core_arena_shutdown, + core->master ? NULL : dfb_core_arena_leave, + core, emergency, NULL ) == DFB_BUSY) + { + D_ONCE( "waiting for DirectFB slaves to terminate" ); + usleep( 100000 ); + } + + fusion_exit( core->world, emergency ); + + if (!emergency) + direct_thread_remove_init_handler( core->init_handler ); + + D_MAGIC_CLEAR( core ); + + D_FREE( core ); + core_dfb = NULL; + + if (!emergency) { + pthread_mutex_unlock( &core_dfb_lock ); + + direct_shutdown(); + } + + return DFB_OK; +} + +CoreLayerContext * +dfb_core_create_layer_context( CoreDFB *core ) +{ + CoreDFBShared *shared; + + D_ASSUME( core != NULL ); + + if (!core) + core = core_dfb; + + D_MAGIC_ASSERT( core, CoreDFB ); + + shared = core->shared; + + D_MAGIC_ASSERT( shared, CoreDFBShared ); + D_ASSERT( shared->layer_context_pool != NULL ); + + return (CoreLayerContext*) fusion_object_create( shared->layer_context_pool, core->world ); +} + +CoreLayerRegion * +dfb_core_create_layer_region( CoreDFB *core ) +{ + CoreDFBShared *shared; + + D_ASSUME( core != NULL ); + + if (!core) + core = core_dfb; + + D_MAGIC_ASSERT( core, CoreDFB ); + + shared = core->shared; + + D_MAGIC_ASSERT( shared, CoreDFBShared ); + D_ASSERT( core->shared->layer_region_pool != NULL ); + + return (CoreLayerRegion*) fusion_object_create( core->shared->layer_region_pool, core->world ); +} + +CorePalette * +dfb_core_create_palette( CoreDFB *core ) +{ + CoreDFBShared *shared; + + D_ASSUME( core != NULL ); + + if (!core) + core = core_dfb; + + D_MAGIC_ASSERT( core, CoreDFB ); + + shared = core->shared; + + D_MAGIC_ASSERT( shared, CoreDFBShared ); + D_ASSERT( core->shared->palette_pool != NULL ); + + return (CorePalette*) fusion_object_create( core->shared->palette_pool, core->world ); +} + +CoreSurface * +dfb_core_create_surface( CoreDFB *core ) +{ + CoreDFBShared *shared; + + D_ASSUME( core != NULL ); + + if (!core) + core = core_dfb; + + D_MAGIC_ASSERT( core, CoreDFB ); + + shared = core->shared; + + D_MAGIC_ASSERT( shared, CoreDFBShared ); + D_ASSERT( core->shared->surface_pool != NULL ); + + return (CoreSurface*) fusion_object_create( core->shared->surface_pool, core->world ); +} + +CoreWindow * +dfb_core_create_window( CoreDFB *core ) +{ + CoreDFBShared *shared; + + D_ASSUME( core != NULL ); + + if (!core) + core = core_dfb; + + D_MAGIC_ASSERT( core, CoreDFB ); + + shared = core->shared; + + D_MAGIC_ASSERT( shared, CoreDFBShared ); + D_ASSERT( core->shared->window_pool != NULL ); + + return (CoreWindow*) fusion_object_create( core->shared->window_pool, core->world ); +} + +DirectResult +dfb_core_enum_surfaces( CoreDFB *core, + FusionObjectCallback callback, + void *ctx ) +{ + CoreDFBShared *shared; + + D_ASSERT( core != NULL || core_dfb != NULL ); + + if (!core) + core = core_dfb; + + D_MAGIC_ASSERT( core, CoreDFB ); + + shared = core->shared; + + D_MAGIC_ASSERT( shared, CoreDFBShared ); + + return fusion_object_pool_enum( shared->surface_pool, callback, ctx ); +} + +DirectResult +dfb_core_enum_layer_contexts( CoreDFB *core, + FusionObjectCallback callback, + void *ctx ) +{ + CoreDFBShared *shared; + + D_ASSERT( core != NULL || core_dfb != NULL ); + + if (!core) + core = core_dfb; + + D_MAGIC_ASSERT( core, CoreDFB ); + + shared = core->shared; + + D_MAGIC_ASSERT( shared, CoreDFBShared ); + + return fusion_object_pool_enum( shared->layer_context_pool, callback, ctx ); +} + +DirectResult +dfb_core_enum_layer_regions( CoreDFB *core, + FusionObjectCallback callback, + void *ctx ) +{ + CoreDFBShared *shared; + + D_ASSERT( core != NULL || core_dfb != NULL ); + + if (!core) + core = core_dfb; + + D_MAGIC_ASSERT( core, CoreDFB ); + + shared = core->shared; + + D_MAGIC_ASSERT( shared, CoreDFBShared ); + + return fusion_object_pool_enum( shared->layer_region_pool, callback, ctx ); +} + +bool +dfb_core_is_master( CoreDFB *core ) +{ + D_MAGIC_ASSERT( core, CoreDFB ); + + return core->master; +} + +void +dfb_core_activate( CoreDFB *core ) +{ + CoreDFBShared *shared; + + D_MAGIC_ASSERT( core, CoreDFB ); + + shared = core->shared; + D_MAGIC_ASSERT( shared, CoreDFBShared ); + + fusion_skirmish_prevail( &shared->lock ); + + shared->active = true; + + fusion_skirmish_notify( &shared->lock ); + + fusion_skirmish_dismiss( &shared->lock ); +} + +FusionWorld * +dfb_core_world( CoreDFB *core ) +{ +// D_ASSUME( core != NULL ); + + if (!core) + core = core_dfb; + + D_MAGIC_ASSERT( core, CoreDFB ); + + return core->world; +} + +FusionArena * +dfb_core_arena( CoreDFB *core ) +{ + D_ASSUME( core != NULL ); + + if (!core) + core = core_dfb; + + D_MAGIC_ASSERT( core, CoreDFB ); + + return core->arena; +} + +FusionSHMPoolShared * +dfb_core_shmpool( CoreDFB *core ) +{ + CoreDFBShared *shared; + + D_ASSUME( core != NULL ); + + if (!core) + core = core_dfb; + + D_MAGIC_ASSERT( core, CoreDFB ); + + shared = core->shared; + + D_MAGIC_ASSERT( shared, CoreDFBShared ); + + return shared->shmpool; +} + +FusionSHMPoolShared * +dfb_core_shmpool_data( CoreDFB *core ) +{ + CoreDFBShared *shared; + + D_ASSUME( core != NULL ); + + if (!core) + core = core_dfb; + + D_MAGIC_ASSERT( core, CoreDFB ); + + shared = core->shared; + + D_MAGIC_ASSERT( shared, CoreDFBShared ); + + return shared->shmpool_data; +} + +DFBResult +dfb_core_suspend( CoreDFB *core ) +{ + DFBResult ret; + + D_ASSUME( core != NULL ); + + if (!core) + core = core_dfb; + + D_MAGIC_ASSERT( core, CoreDFB ); + + if (!core->master) + return DFB_ACCESSDENIED; + + if (core->suspended) + return DFB_BUSY; + + ret = dfb_input_core.Suspend( dfb_input_core.data_local ); + if (ret) + goto error_input; + + ret = dfb_layer_core.Suspend( dfb_layer_core.data_local ); + if (ret) + goto error_layers; + + ret = dfb_screen_core.Suspend( dfb_screen_core.data_local ); + if (ret) + goto error_screens; + + ret = dfb_graphics_core.Suspend( dfb_graphics_core.data_local ); + if (ret) + goto error_graphics; + + core->suspended = true; + + return DFB_OK; + +error_graphics: + dfb_screen_core.Resume( dfb_screen_core.data_local ); +error_screens: + dfb_layer_core.Resume( dfb_layer_core.data_local ); +error_layers: + dfb_input_core.Resume( dfb_input_core.data_local ); +error_input: + return ret; +} + +DFBResult +dfb_core_resume( CoreDFB *core ) +{ + DFBResult ret; + + D_ASSUME( core != NULL ); + + if (!core) + core = core_dfb; + + D_MAGIC_ASSERT( core, CoreDFB ); + + if (!core->master) + return DFB_ACCESSDENIED; + + if (!core->suspended) + return DFB_BUSY; + + ret = dfb_graphics_core.Resume( dfb_graphics_core.data_local ); + if (ret) + goto error_graphics; + + ret = dfb_screen_core.Resume( dfb_screen_core.data_local ); + if (ret) + goto error_screens; + + ret = dfb_layer_core.Resume( dfb_layer_core.data_local ); + if (ret) + goto error_layers; + + ret = dfb_input_core.Resume( dfb_input_core.data_local ); + if (ret) + goto error_input; + + core->suspended = false; + + return DFB_OK; + +error_input: + dfb_layer_core.Suspend( dfb_layer_core.data_local ); +error_layers: + dfb_screen_core.Suspend( dfb_screen_core.data_local ); +error_screens: + dfb_graphics_core.Suspend( dfb_graphics_core.data_local ); +error_graphics: + return ret; +} + +CoreCleanup * +dfb_core_cleanup_add( CoreDFB *core, + CoreCleanupFunc func, + void *data, + bool emergency ) +{ + CoreCleanup *cleanup; + + D_ASSUME( core != NULL ); + + if (!core) + core = core_dfb; + + D_MAGIC_ASSERT( core, CoreDFB ); + + cleanup = D_CALLOC( 1, sizeof(CoreCleanup) ); + + cleanup->func = func; + cleanup->data = data; + cleanup->emergency = emergency; + + direct_list_prepend( &core->cleanups, &cleanup->link ); + + return cleanup; +} + +void +dfb_core_cleanup_remove( CoreDFB *core, + CoreCleanup *cleanup ) +{ + D_ASSUME( core != NULL ); + + if (!core) + core = core_dfb; + + D_MAGIC_ASSERT( core, CoreDFB ); + + direct_list_remove( &core->cleanups, &cleanup->link ); + + D_FREE( cleanup ); +} + +/******************************************************************************/ + +static void +dfb_core_deinit_check( void *ctx ) +{ + if (core_dfb && core_dfb->refs) { + D_WARN( "Application exited without deinitialization of DirectFB!" ); + dfb_core_destroy( core_dfb, true ); + } +} + +static void +dfb_core_thread_init_handler( DirectThread *thread, void *arg ) +{ + dfb_system_thread_init(); +} + +static void +dfb_core_process_cleanups( CoreDFB *core, bool emergency ) +{ + D_MAGIC_ASSERT( core, CoreDFB ); + + while (core->cleanups) { + CoreCleanup *cleanup = (CoreCleanup*) core->cleanups; + + core->cleanups = core->cleanups->next; + + if (cleanup->emergency || !emergency) + cleanup->func( cleanup->data, emergency ); + + D_FREE( cleanup ); + } +} + +static DirectSignalHandlerResult +dfb_core_signal_handler( int num, + void *addr, + void *ctx ) +{ + CoreDFB *core = ctx; + + D_ASSERT( core == core_dfb ); + + dfb_core_destroy( core, true ); + + return DSHR_OK; +} + +/******************************************************************************/ + +static int +dfb_core_shutdown( CoreDFB *core, bool emergency ) +{ + CoreDFBShared *shared; + + D_MAGIC_ASSERT( core, CoreDFB ); + + shared = core->shared; + + D_MAGIC_ASSERT( shared, CoreDFBShared ); + + /* Suspend input core to stop all input threads before shutting down. */ + if (dfb_input_core.initialized) + dfb_input_core.Suspend( dfb_input_core.data_local ); + + fusion_stop_dispatcher( core->world, emergency ); + + /* Destroy window objects. */ + fusion_object_pool_destroy( shared->window_pool, core->world ); + + /* Close window stacks. */ + if (dfb_wm_core.initialized) + dfb_wm_close_all_stacks( dfb_wm_core.data_local ); + + /* Destroy layer context and region objects. */ + fusion_object_pool_destroy( shared->layer_region_pool, core->world ); + fusion_object_pool_destroy( shared->layer_context_pool, core->world ); + + /* Shutdown WM core. */ + dfb_core_part_shutdown( core, &dfb_wm_core, emergency ); + + /* Shutdown layer core. */ + dfb_core_part_shutdown( core, &dfb_layer_core, emergency ); + dfb_core_part_shutdown( core, &dfb_screen_core, emergency ); + + /* Destroy surface and palette objects. */ + fusion_object_pool_destroy( shared->surface_pool, core->world ); + fusion_object_pool_destroy( shared->palette_pool, core->world ); + + /* Destroy remaining core parts. */ + dfb_core_part_shutdown( core, &dfb_graphics_core, emergency ); + dfb_core_part_shutdown( core, &dfb_surface_core, emergency ); + dfb_core_part_shutdown( core, &dfb_input_core, emergency ); + dfb_core_part_shutdown( core, &dfb_system_core, emergency ); + dfb_core_part_shutdown( core, &dfb_colorhash_core, emergency ); + dfb_core_part_shutdown( core, &dfb_clipboard_core, emergency ); + + /* Destroy shared memory pool for surface data. */ + fusion_shm_pool_destroy( core->world, shared->shmpool_data ); + + return 0; +} + +static DFBResult +dfb_core_initialize( CoreDFB *core ) +{ + int i; + DFBResult ret; + CoreDFBShared *shared; + + D_MAGIC_ASSERT( core, CoreDFB ); + + shared = core->shared; + + D_MAGIC_ASSERT( shared, CoreDFBShared ); + + ret = fusion_shm_pool_create( core->world, "DirectFB Data Pool", 0x1000000, + fusion_config->debugshm, &shared->shmpool_data ); + if (ret) + return ret; + + shared->layer_context_pool = dfb_layer_context_pool_create( core->world ); + shared->layer_region_pool = dfb_layer_region_pool_create( core->world ); + shared->palette_pool = dfb_palette_pool_create( core->world ); + shared->surface_pool = dfb_surface_pool_create( core->world ); + shared->window_pool = dfb_window_pool_create( core->world ); + + for (i=0; i=0; i--) + dfb_core_part_leave( core, core_parts[i], emergency ); + + return DFB_OK; +} + +static int +dfb_core_join( CoreDFB *core ) +{ + int i; + + D_MAGIC_ASSERT( core, CoreDFB ); + + for (i=0; iworld, "DirectFB Main Pool", 0x400000, + fusion_config->debugshm, &pool ); + if (ret) + return ret; + + /* Allocate shared structure in the new pool. */ + shared = SHCALLOC( pool, 1, sizeof(CoreDFBShared) ); + if (!shared) { + fusion_shm_pool_destroy( core->world, pool ); + return D_OOSHM(); + } + + core->shared = shared; + core->master = true; + + shared->shmpool = pool; + + D_MAGIC_SET( shared, CoreDFBShared ); + + /* Initialize. */ + ret = dfb_core_initialize( core ); + if (ret) { + D_MAGIC_CLEAR( shared ); + SHFREE( pool, shared ); + fusion_shm_pool_destroy( core->world, pool ); + return ret; + } + + fusion_skirmish_init( &shared->lock, "DirectFB Core", core->world ); + + /* Register shared data. */ + fusion_arena_add_shared_field( arena, "Core/Shared", shared ); + + return DFB_OK; +} + +static int +dfb_core_arena_shutdown( FusionArena *arena, + void *ctx, + bool emergency) +{ + DFBResult ret; + CoreDFB *core = ctx; + CoreDFBShared *shared; + FusionSHMPoolShared *pool; + + D_MAGIC_ASSERT( core, CoreDFB ); + + shared = core->shared; + + D_MAGIC_ASSERT( shared, CoreDFBShared ); + + pool = shared->shmpool; + + D_DEBUG_AT( DirectFB_Core, "Shutting down...\n" ); + + if (!core->master) { + D_WARN( "refusing shutdown in slave" ); + return dfb_core_leave( core, emergency ); + } + + /* Shutdown. */ + ret = dfb_core_shutdown( core, emergency ); + + fusion_skirmish_destroy( &shared->lock ); + + D_MAGIC_CLEAR( shared ); + + SHFREE( pool, shared ); + + fusion_shm_pool_destroy( core->world, pool ); + + return ret; +} + +static int +dfb_core_arena_join( FusionArena *arena, + void *ctx ) +{ + DFBResult ret; + CoreDFB *core = ctx; + void *field; + + D_MAGIC_ASSERT( core, CoreDFB ); + + D_DEBUG_AT( DirectFB_Core, "Joining...\n" ); + + /* Get shared data. */ + if (fusion_arena_get_shared_field( arena, "Core/Shared", &field )) + return DFB_FUSION; + + core->shared = field; + + /* Join. */ + ret = dfb_core_join( core ); + if (ret) + return ret; + + return DFB_OK; +} + +static int +dfb_core_arena_leave( FusionArena *arena, + void *ctx, + bool emergency) +{ + DFBResult ret; + CoreDFB *core = ctx; + + D_MAGIC_ASSERT( core, CoreDFB ); + + D_DEBUG_AT( DirectFB_Core, "Leaving...\n" ); + + /* Leave. */ + ret = dfb_core_leave( core, emergency ); + if (ret) + return ret; + + return DFB_OK; +} + diff --git a/Source/DirectFB/src/core/core.h b/Source/DirectFB/src/core/core.h new file mode 100755 index 0000000..7116e8c --- /dev/null +++ b/Source/DirectFB/src/core/core.h @@ -0,0 +1,162 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __CORE_H__ +#define __CORE_H__ + +#include +#include +#include + +#include + +#include "coretypes.h" +#include "coredefs.h" + + +#define DIRECTFB_CORE_ABI 45 + + +typedef enum { + DFCP_CLIPBOARD, + DFCP_COLORHASH, + DFCP_GRAPHICS, + DFCP_INPUT, + DFCP_LAYER, + DFCP_SCREEN, + DFCP_SURFACE, + DFCP_SYSTEM, + DFCP_WM, + + _DFCP_NUM +} DFBCorePartID; + + +/* + * Cleanup function, callback of a cleanup stack entry. + */ +typedef void (*CoreCleanupFunc)(void *data, int emergency); + + + +/* + * Core initialization and deinitialization + */ +DFBResult dfb_core_create ( CoreDFB **ret_core ); + +DFBResult dfb_core_destroy ( CoreDFB *core, + bool emergency ); + +void *dfb_core_get_part( CoreDFB *core, + DFBCorePartID part_id ); + + +#define DFB_CORE(core,PART) dfb_core_get_part( core, DFCP_##PART ) + + +/* + * Object creation + */ +CoreLayerContext *dfb_core_create_layer_context( CoreDFB *core ); +CoreLayerRegion *dfb_core_create_layer_region ( CoreDFB *core ); +CorePalette *dfb_core_create_palette ( CoreDFB *core ); +CoreSurface *dfb_core_create_surface ( CoreDFB *core ); +CoreWindow *dfb_core_create_window ( CoreDFB *core ); + +/* + * Debug + */ +DirectResult dfb_core_enum_surfaces ( CoreDFB *core, + FusionObjectCallback callback, + void *ctx ); +DirectResult dfb_core_enum_layer_contexts( CoreDFB *core, + FusionObjectCallback callback, + void *ctx ); +DirectResult dfb_core_enum_layer_regions ( CoreDFB *core, + FusionObjectCallback callback, + void *ctx ); + + +/* + * Returns true if the calling process is the master fusionee, + * i.e. handles input drivers running their threads. + */ +bool dfb_core_is_master( CoreDFB *core ); + +/* + * Allows other (blocking) Fusionees to enter the DirectFB session. + */ +void dfb_core_activate( CoreDFB *core ); + +/* + * Returns the core's fusion world. + */ +FusionWorld *dfb_core_world( CoreDFB *core ); + +/* + * Returns the core arena. + */ +FusionArena *dfb_core_arena( CoreDFB *core ); + +/* + * Returns the shared memory pool of the core. + */ +FusionSHMPoolShared *dfb_core_shmpool( CoreDFB *core ); + +/* + * Returns the shared memory pool for raw data, e.g. surface buffers. + */ +FusionSHMPoolShared *dfb_core_shmpool_data( CoreDFB *core ); + +/* + * Suspends all core parts, stopping input threads, closing devices... + */ +DFBResult dfb_core_suspend( CoreDFB *core ); + +/* + * Resumes all core parts, reopening devices, starting input threads... + */ +DFBResult dfb_core_resume( CoreDFB *core ); + +/* + * Adds a function to the cleanup stack that is called during deinitialization. + * If emergency is true, the cleanup is even called by core_deinit_emergency(). + */ +CoreCleanup *dfb_core_cleanup_add( CoreDFB *core, + CoreCleanupFunc func, + void *data, + bool emergency ); + +/* + * Removes a function from the cleanup stack. + */ +void dfb_core_cleanup_remove( CoreDFB *core, + CoreCleanup *cleanup ); + +#endif + diff --git a/Source/DirectFB/src/core/core_parts.c b/Source/DirectFB/src/core/core_parts.c new file mode 100755 index 0000000..1b5f944 --- /dev/null +++ b/Source/DirectFB/src/core/core_parts.c @@ -0,0 +1,202 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include +#include + +#include + +#include +#include + +#include +#include + +#include +#include + + +D_DEBUG_DOMAIN( Core_Parts, "Core/Parts", "DirectFB Core Parts" ); + + +DFBResult +dfb_core_part_initialize( CoreDFB *core, + CorePart *core_part ) +{ + DFBResult ret; + void *local = NULL; + void *shared = NULL; + FusionSHMPoolShared *pool; + + pool = dfb_core_shmpool( core ); + + if (core_part->initialized) { + D_BUG( "%s already initialized", core_part->name ); + return DFB_BUG; + } + + D_DEBUG_AT( Core_Parts, "Going to initialize '%s' core...\n", core_part->name ); + + if (core_part->size_local) + local = D_CALLOC( 1, core_part->size_local ); + + if (core_part->size_shared) + shared = SHCALLOC( pool, 1, core_part->size_shared ); + + ret = core_part->Initialize( core, local, shared ); + if (ret) { + D_ERROR( "DirectFB/Core: Could not initialize '%s' core!\n" + " --> %s\n", core_part->name, + DirectFBErrorString( ret ) ); + + if (shared) + SHFREE( pool, shared ); + + if (local) + D_FREE( local ); + + return ret; + } + + if (shared) + fusion_arena_add_shared_field( dfb_core_arena( core ), + core_part->name, shared ); + + core_part->data_local = local; + core_part->data_shared = shared; + core_part->initialized = true; + + return DFB_OK; +} + +DFBResult +dfb_core_part_join( CoreDFB *core, + CorePart *core_part ) +{ + DFBResult ret; + void *local = NULL; + void *shared = NULL; + + if (core_part->initialized) { + D_BUG( "%s already joined", core_part->name ); + return DFB_BUG; + } + + D_DEBUG_AT( Core_Parts, "Going to join '%s' core...\n", core_part->name ); + + if (core_part->size_shared && + fusion_arena_get_shared_field( dfb_core_arena( core ), + core_part->name, &shared )) + return DFB_FUSION; + + if (core_part->size_local) + local = D_CALLOC( 1, core_part->size_local ); + + ret = core_part->Join( core, local, shared ); + if (ret) { + D_ERROR( "DirectFB/Core: Could not join '%s' core!\n" + " --> %s\n", core_part->name, + DirectFBErrorString( ret ) ); + + if (local) + D_FREE( local ); + + return ret; + } + + core_part->data_local = local; + core_part->data_shared = shared; + core_part->initialized = true; + + return DFB_OK; +} + +DFBResult +dfb_core_part_shutdown( CoreDFB *core, + CorePart *core_part, + bool emergency ) +{ + DFBResult ret; + FusionSHMPoolShared *pool; + + pool = dfb_core_shmpool( core ); + + if (!core_part->initialized) + return DFB_OK; + + D_DEBUG_AT( Core_Parts, "Going to shutdown '%s' core...\n", core_part->name ); + + ret = core_part->Shutdown( core_part->data_local, emergency ); + if (ret) + D_ERROR( "DirectFB/Core: Could not shutdown '%s' core!\n" + " --> %s\n", core_part->name, + DirectFBErrorString( ret ) ); + + if (core_part->data_shared) + SHFREE( pool, core_part->data_shared ); + + if (core_part->data_local) + D_FREE( core_part->data_local ); + + core_part->data_local = NULL; + core_part->data_shared = NULL; + core_part->initialized = false; + + return DFB_OK; +} + +DFBResult +dfb_core_part_leave( CoreDFB *core, + CorePart *core_part, + bool emergency ) +{ + DFBResult ret; + + if (!core_part->initialized) + return DFB_OK; + + D_DEBUG_AT( Core_Parts, "Going to leave '%s' core...\n", core_part->name ); + + ret = core_part->Leave( core_part->data_local, emergency ); + if (ret) + D_ERROR( "DirectFB/Core: Could not leave '%s' core!\n" + " --> %s\n", core_part->name, + DirectFBErrorString( ret ) ); + + if (core_part->data_local) + D_FREE( core_part->data_local ); + + core_part->data_local = NULL; + core_part->data_shared = NULL; + core_part->initialized = false; + + return DFB_OK; +} + diff --git a/Source/DirectFB/src/core/core_parts.h b/Source/DirectFB/src/core/core_parts.h new file mode 100755 index 0000000..31b7563 --- /dev/null +++ b/Source/DirectFB/src/core/core_parts.h @@ -0,0 +1,131 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __CORE_PARTS_H__ +#define __CORE_PARTS_H__ + +#include +#include + +#include + +#include +#include + + +typedef DFBResult (*CoreInitialize)( CoreDFB *core, + void *data_local, + void *data_shared ); + +typedef DFBResult (*CoreJoin) ( CoreDFB *core, + void *data_local, + void *data_shared ); + +typedef DFBResult (*CoreShutdown) ( void *data_local, + bool emergency ); + +typedef DFBResult (*CoreLeave) ( void *data_local, + bool emergency ); + +typedef DFBResult (*CoreSuspend) ( void *data_local ); + +typedef DFBResult (*CoreResume) ( void *data_local ); + + +typedef struct { + const char *name; + + int size_local; + int size_shared; + + CoreInitialize Initialize; + CoreJoin Join; + CoreShutdown Shutdown; + CoreLeave Leave; + CoreSuspend Suspend; + CoreResume Resume; + + void *data_local; + void *data_shared; + + bool initialized; +} CorePart; + + +DFBResult dfb_core_part_initialize( CoreDFB *core, + CorePart *core_part ); + +DFBResult dfb_core_part_join ( CoreDFB *core, + CorePart *core_part ); + +DFBResult dfb_core_part_shutdown ( CoreDFB *core, + CorePart *core_part, + bool emergency ); + +DFBResult dfb_core_part_leave ( CoreDFB *core, + CorePart *core_part, + bool emergency ); + + +#define DFB_CORE_PART(part,Type) \ + \ +static DFBResult dfb_##part##_initialize( CoreDFB *core, \ + DFB##Type *local, \ + DFB##Type##Shared *shared ); \ + \ +static DFBResult dfb_##part##_join ( CoreDFB *core, \ + DFB##Type *local, \ + DFB##Type##Shared *shared ); \ + \ +static DFBResult dfb_##part##_shutdown ( DFB##Type *local, \ + bool emergency ); \ + \ +static DFBResult dfb_##part##_leave ( DFB##Type *local, \ + bool emergency ); \ + \ +static DFBResult dfb_##part##_suspend ( DFB##Type *local ); \ + \ +static DFBResult dfb_##part##_resume ( DFB##Type *local ); \ + \ +CorePart dfb_##part = { \ + .name = #part, \ + \ + .size_local = sizeof(DFB##Type), \ + .size_shared = sizeof(DFB##Type##Shared), \ + \ + .Initialize = (void*)dfb_##part##_initialize, \ + .Join = (void*)dfb_##part##_join, \ + .Shutdown = (void*)dfb_##part##_shutdown, \ + .Leave = (void*)dfb_##part##_leave, \ + .Suspend = (void*)dfb_##part##_suspend, \ + .Resume = (void*)dfb_##part##_resume, \ +} + + +#endif + diff --git a/Source/DirectFB/src/core/core_system.h b/Source/DirectFB/src/core/core_system.h new file mode 100755 index 0000000..dfa2abc --- /dev/null +++ b/Source/DirectFB/src/core/core_system.h @@ -0,0 +1,141 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __DFB__CORE__CORE_SYSTEM_H__ +#define __DFB__CORE__CORE_SYSTEM_H__ + +#include + +static void +system_get_info( CoreSystemInfo *info ); + +static DFBResult +system_initialize( CoreDFB *core, void **data ); + +static DFBResult +system_join( CoreDFB *core, void **data ); + +static DFBResult +system_shutdown( bool emergency ); + +static DFBResult +system_leave( bool emergency ); + +static DFBResult +system_suspend( void ); + +static DFBResult +system_resume( void ); + +static VideoMode* +system_get_modes( void ); + +static VideoMode* +system_get_current_mode( void ); + +static DFBResult +system_thread_init( void ); + +static bool +system_input_filter( CoreInputDevice *device, + DFBInputEvent *event ); + +static volatile void* +system_map_mmio( unsigned int offset, + int length ); + +static void +system_unmap_mmio( volatile void *addr, + int length ); + +static int +system_get_accelerator( void ); + +static unsigned long +system_video_memory_physical( unsigned int offset ); + +static void* +system_video_memory_virtual( unsigned int offset ); + +static unsigned int +system_videoram_length( void ); + +static unsigned long +system_aux_memory_physical( unsigned int offset ); + +static void* +system_aux_memory_virtual( unsigned int offset ); + +static unsigned int +system_auxram_length( void ); + +static void +system_get_busid( int *ret_bus, int *ret_dev, int *ret_func ); + +static void +system_get_deviceid( unsigned int *ret_vendor_id, unsigned int *ret_device_id ); + + +static CoreSystemFuncs system_funcs = { + .GetSystemInfo = system_get_info, + .Initialize = system_initialize, + .Join = system_join, + .Shutdown = system_shutdown, + .Leave = system_leave, + .Suspend = system_suspend, + .Resume = system_resume, + .GetModes = system_get_modes, + .GetCurrentMode = system_get_current_mode, + .ThreadInit = system_thread_init, + .InputFilter = system_input_filter, + .MapMMIO = system_map_mmio, + .UnmapMMIO = system_unmap_mmio, + .GetAccelerator = system_get_accelerator, + .VideoMemoryPhysical = system_video_memory_physical, + .VideoMemoryVirtual = system_video_memory_virtual, + .VideoRamLength = system_videoram_length, + .AuxMemoryPhysical = system_aux_memory_physical, + .AuxMemoryVirtual = system_aux_memory_virtual, + .AuxRamLength = system_auxram_length, + .GetBusID = system_get_busid, + .GetDeviceID = system_get_deviceid +}; + +#define DFB_CORE_SYSTEM(shortname) \ +__attribute__((constructor)) void directfb_##shortname( void ); \ + \ +void \ +directfb_##shortname( void ) \ +{ \ + direct_modules_register( &dfb_core_systems, \ + DFB_CORE_SYSTEM_ABI_VERSION, \ + #shortname, &system_funcs ); \ +} + +#endif + diff --git a/Source/DirectFB/src/core/coredefs.h b/Source/DirectFB/src/core/coredefs.h new file mode 100755 index 0000000..3354cfa --- /dev/null +++ b/Source/DirectFB/src/core/coredefs.h @@ -0,0 +1,48 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __CORE__COREDEFS_H__ +#define __CORE__COREDEFS_H__ + + +#ifdef PIC +#define DFB_DYNAMIC_LINKING +#endif + +#define MAX_INPUTDEVICES 64 +#define MAX_LAYERS 16 +#define MAX_SCREENS 4 + +#define MAX_INPUT_GLOBALS 8 + +#define MAX_SURFACE_BUFFERS 6 +#define MAX_SURFACE_POOLS 8 +#define MAX_SURFACE_POOL_BRIDGES 4 + +#endif + diff --git a/Source/DirectFB/src/core/coretypes.h b/Source/DirectFB/src/core/coretypes.h new file mode 100755 index 0000000..a5df62d --- /dev/null +++ b/Source/DirectFB/src/core/coretypes.h @@ -0,0 +1,89 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __CORETYPES_H__ +#define __CORETYPES_H__ + +#include + +typedef struct __DFB_CoreDFB CoreDFB; +typedef struct __DFB_CoreDFBShared CoreDFBShared; + + +typedef struct __DFB_DFBClipboardCore DFBClipboardCore; +typedef struct __DFB_DFBColorHashCore DFBColorHashCore; +typedef struct __DFB_DFBGraphicsCore DFBGraphicsCore; +typedef struct __DFB_DFBInputCore DFBInputCore; +typedef struct __DFB_DFBLayerCore DFBLayerCore; +typedef struct __DFB_DFBScreenCore DFBScreenCore; +typedef struct __DFB_DFBSystemCore DFBSystemCore; +typedef struct __DFB_DFBWMCore DFBWMCore; + + +typedef struct __DFB_DFBGraphicsCore CoreGraphicsDevice; /* FIXME */ + + +typedef struct _CoreCleanup CoreCleanup; + +typedef struct _CoreFont CoreFont; +typedef struct _CoreGlyphData CoreGlyphData; +typedef struct _CorePalette CorePalette; + +typedef struct _CardState CardState; + + +typedef struct __DFB_CoreGraphicsSerial CoreGraphicsSerial; + +typedef struct __DFB_CoreScreen CoreScreen; + +typedef struct __DFB_CoreInputDevice CoreInputDevice; + +typedef struct __DFB_CoreLayer CoreLayer; +typedef struct __DFB_CoreLayerContext CoreLayerContext; +typedef struct __DFB_CoreLayerRegion CoreLayerRegion; +typedef struct __DFB_CoreLayerRegionConfig CoreLayerRegionConfig; + +typedef struct __DFB_CoreSurface CoreSurface; +typedef struct __DFB_CoreSurfaceAccessor CoreSurfaceAccessor; +typedef struct __DFB_CoreSurfaceAllocation CoreSurfaceAllocation; +typedef struct __DFB_CoreSurfaceBuffer CoreSurfaceBuffer; +typedef struct __DFB_CoreSurfaceBufferLock CoreSurfaceBufferLock; +typedef struct __DFB_CoreSurfacePool CoreSurfacePool; +typedef struct __DFB_CoreSurfacePoolBridge CoreSurfacePoolBridge; +typedef struct __DFB_CoreSurfacePoolTransfer CoreSurfacePoolTransfer; + +typedef struct __DFB_CoreWindow CoreWindow; +typedef struct __DFB_CoreWindowConfig CoreWindowConfig; +typedef struct __DFB_CoreWindowStack CoreWindowStack; + + +typedef unsigned int CoreSurfacePoolID; +typedef unsigned int CoreSurfacePoolBridgeID; + +#endif + diff --git a/Source/DirectFB/src/core/fonts.c b/Source/DirectFB/src/core/fonts.c new file mode 100755 index 0000000..2e6b599 --- /dev/null +++ b/Source/DirectFB/src/core/fonts.c @@ -0,0 +1,660 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include +#include + +#include + +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + + +D_DEBUG_DOMAIN( Core_Font, "Core/Font", "DirectFB Core Font" ); +D_DEBUG_DOMAIN( Core_FontSurfaces, "Core/Font/Surf", "DirectFB Core Font Surfaces" ); + +/**********************************************************************************************************************/ + +static bool free_glyphs( DirectHash *hash, + unsigned long key, + void *value, + void *ctx ); + +/**********************************************************************************************************************/ + +DFBResult +dfb_font_create( CoreDFB *core, + const DFBFontDescription *description, + const char *url, + CoreFont **ret_font ) +{ + DFBResult ret; + int i; + CoreFont *font; + + D_DEBUG_AT( Core_Font, "%s()\n", __FUNCTION__ ); + + D_ASSERT( core != NULL ); + D_ASSERT( ret_font != NULL ); + + font = D_CALLOC( 1, sizeof(CoreFont) ); + if (!font) + return D_OOM(); + + for (i=0; ilayers[i].glyph_hash ); + if (ret) { + while (i--) + direct_hash_destroy( font->layers[i].glyph_hash ); + + D_FREE( font ); + return ret; + } + } + + font->description = *description; + font->url = D_STRDUP( url ); + + font->core = core; + font->max_rows = 2; + + direct_util_recursive_pthread_mutex_init( &font->lock ); + + /* the proposed pixel_format, may be changed by the font provider */ + font->pixel_format = dfb_config->font_format ? : DSPF_A8; + + if ((font->pixel_format == DSPF_ARGB || font->pixel_format == DSPF_ARGB4444) && dfb_config->font_premult) + font->surface_caps = DSCAPS_PREMULTIPLIED; + + font->blittingflags = DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_COLORIZE; + + D_MAGIC_SET( font, CoreFont ); + + *ret_font = font; + + return DFB_OK; +} + +void +dfb_font_destroy( CoreFont *font ) +{ + int i; + + D_DEBUG_AT( Core_Font, "%s()\n", __FUNCTION__ ); + + D_MAGIC_ASSERT( font, CoreFont ); + + D_MAGIC_CLEAR( font ); + + D_FREE( font->url ); + + pthread_mutex_lock( &font->lock ); + + for (i=0; ilayers[i].glyph_hash, free_glyphs, NULL ); + + direct_hash_destroy( font->layers[i].glyph_hash ); + } + + if (font->rows) { + for (i = 0; i < font->num_rows; i++) { + CoreFontCacheRow *row = font->rows[i]; + + D_MAGIC_ASSERT( row, CoreFontCacheRow ); + + dfb_surface_unref( row->surface ); + + D_MAGIC_CLEAR( row ); + + D_FREE( row ); + } + + D_FREE( font->rows ); + } + + D_ASSERT( font->encodings != NULL || !font->last_encoding ); + + for (i=DTEID_OTHER; i<=font->last_encoding; i++) { + CoreFontEncoding *encoding = font->encodings[i]; + + D_ASSERT( encoding != NULL ); + D_ASSERT( encoding->name != NULL ); + + D_MAGIC_CLEAR( encoding ); + + D_FREE( encoding->name ); + D_FREE( encoding ); + } + + if (font->encodings) + D_FREE( font->encodings ); + + pthread_mutex_unlock( &font->lock ); + pthread_mutex_destroy( &font->lock ); + + D_FREE( font ); +} + +/**********************************************************************************************************************/ + +DFBResult +dfb_font_get_glyph_data( CoreFont *font, + unsigned int index, + unsigned int layer, + CoreGlyphData **ret_data ) +{ + DFBResult ret; + CoreGlyphData *data; + int i; + int align; + CoreFontCacheRow *row = NULL; + + D_DEBUG_AT( Core_Font, "%s()\n", __FUNCTION__ ); + + D_MAGIC_ASSERT( font, CoreFont ); + D_ASSERT( ret_data != NULL ); + + D_ASSERT( layer < D_ARRAY_SIZE(font->layers) ); + D_ASSERT( font->num_rows >= 0 ); + + if (font->num_rows) { + D_ASSERT( font->num_rows <= font->max_rows || font->max_rows < 0 ); + D_ASSERT( font->active_row >= 0 ); + D_ASSERT( font->active_row < font->num_rows ); + } + + if (index < 128 && font->layers[layer].glyph_data[index]) { + data = font->layers[layer].glyph_data[index]; + if (data->failed) + goto retry; + + *ret_data = font->layers[layer].glyph_data[index]; + return DFB_OK; + } + + data = direct_hash_lookup( font->layers[layer].glyph_hash, index ); + if (data) { + D_MAGIC_ASSERT( data, CoreGlyphData ); + + if (font->rows) { + D_ASSERT( data->row >= 0 ); + D_ASSERT( data->row < font->num_rows ); + + row = font->rows[data->row]; + + D_MAGIC_ASSERT( row, CoreFontCacheRow ); + + row->stamp = font->row_stamp++; + } + + if (data->failed) + goto retry; + + *ret_data = data; + return DFB_OK; + } + + if (!font->GetGlyphData) + return DFB_UNSUPPORTED; + + data = D_CALLOC( 1, sizeof(CoreGlyphData) ); + if (!data) + return D_OOM(); + + D_MAGIC_SET( data, CoreGlyphData ); + + data->index = index; + data->layer = layer; + +retry: + data->failed = false; + + ret = font->GetGlyphData( font, index, data ); + if (ret) { + D_DERROR( ret, "Core/Font: Could not get glyph info for index %d!\n", index ); + data->start = data->width = data->height = 0; + data->failed = true; + goto out; + } + + if (data->width < 1 || data->height < 1) { + data->start = data->width = data->height = 0; + goto out; + } + + if (font->rows) { + D_ASSERT( font->active_row >= 0 ); + D_ASSERT( font->active_row < font->num_rows ); + + row = font->rows[font->active_row]; + + D_MAGIC_ASSERT( row, CoreFontCacheRow ); + } + else { + /* Calculate row width? */ + if (font->row_width == 0) { + int width = 2048 * font->height / 64; + + if (width > 2048) + width = 2048; + + if (width < font->maxadvance) + width = font->maxadvance; + + font->row_width = (width + 7) & ~7; + } + } + + /* Need another font surface? */ + if (!row || (row->next_x + data->width > font->row_width)) { + D_ASSERT( font->max_rows != 0 ); + + /* Maximum number of rows reached? */ + if (font->num_rows == font->max_rows) { + int best_row = -1; + unsigned int best_val = 0; + + /* Check for trailing space first. */ + for (i=0; inum_rows; i++) { + row = font->rows[i]; + + D_MAGIC_ASSERT( row, CoreFontCacheRow ); + + if (row->next_x + data->width <= font->row_width) { + if (best_row == -1 || best_val < row->next_x) { + best_row = i; + best_val = row->next_x; + } + } + } + + /* Found a row with enough trailing space? */ + if (best_row != -1) { + font->active_row = best_row; + row = font->rows[best_row]; + + D_MAGIC_ASSERT( row, CoreFontCacheRow ); + + D_DEBUG_AT( Core_FontSurfaces, " -> using trailing space of row %d - %dx%d %s\n", + font->active_row, row->surface->config.size.w, row->surface->config.size.h, + dfb_pixelformat_name(row->surface->config.format) ); + } + else { + CoreGlyphData *d, *n; + + D_ASSERT( best_row == -1 ); + D_ASSERT( best_val == 0 ); + + /* Reuse the least recently used row. */ + for (i=0; inum_rows; i++) { + row = font->rows[i]; + + D_MAGIC_ASSERT( row, CoreFontCacheRow ); + + if (best_row == -1 || best_val > row->stamp) { + best_row = i; + best_val = row->stamp; + } + } + + D_ASSERT( best_row != -1 ); + + font->active_row = best_row; + row = font->rows[best_row]; + + D_MAGIC_ASSERT( row, CoreFontCacheRow ); + + D_DEBUG_AT( Core_FontSurfaces, " -> reusing row %d - %dx%d %s\n", + font->active_row, row->surface->config.size.w, row->surface->config.size.h, + dfb_pixelformat_name(row->surface->config.format) ); + + /* Kick out all glyphs. */ + direct_list_foreach_safe (d, n, row->glyphs) { + D_MAGIC_ASSERT( d, CoreGlyphData ); + D_ASSERT( d->layer < D_ARRAY_SIZE(font->layers) ); + + /*ret =*/ direct_hash_remove( font->layers[d->layer].glyph_hash, d->index ); + //FIXME: use D_ASSERT( ret == DFB_OK ); + + if (d->index < 128) + font->layers[d->layer].glyph_data[d->index] = NULL; + + D_MAGIC_CLEAR( d ); + D_FREE( d ); + } + + /* Reset row. */ + row->glyphs = NULL; + row->next_x = 0; + } + } + else { + /* Allocate new font cache row structure. */ + row = D_CALLOC( 1, sizeof(CoreFontCacheRow) ); + if (!row) { + ret = D_OOM(); + goto error; + } + + /* Create a new font surface. */ + ret = dfb_surface_create_simple( font->core, + font->row_width, + MAX( font->height + 1, 8 ), + font->pixel_format, + font->surface_caps, CSTF_FONT, + 0 /* FIXME: no shared fonts, no font id */, + NULL, &row->surface ); + if (ret) { + D_DERROR( ret, "Core/Font: Could not create font surface!\n" ); + D_FREE( row ); + goto error; + } + + D_DEBUG_AT( Core_FontSurfaces, " -> new row %d - %dx%d %s\n", font->num_rows, + row->surface->config.size.w, row->surface->config.size.h, + dfb_pixelformat_name(row->surface->config.format) ); + + D_MAGIC_SET( row, CoreFontCacheRow ); + + + /* Append to array. FIXME: Use vector to avoid realloc each time! */ + font->rows = D_REALLOC( font->rows, sizeof(void*) * (font->num_rows + 1) ); + D_ASSERT( font->rows != NULL ); + + font->rows[font->num_rows] = row; + + /* Set new row to use. */ + font->active_row = font->num_rows++; + } + } + + D_MAGIC_ASSERT( row, CoreFontCacheRow ); + D_ASSERT( font->num_rows > 0 ); + D_ASSERT( font->num_rows <= font->max_rows || font->max_rows < 0 ); + D_ASSERT( font->active_row >= 0 ); + D_ASSERT( font->active_row < font->num_rows ); + D_ASSERT( row == font->rows[font->active_row] ); + + D_DEBUG_AT( Core_FontSurfaces, " -> render %2d - %2dx%2d at %d:%03d font <%p>\n", + index, data->width, data->height, font->active_row, row->next_x, font ); + + data->row = font->active_row; + data->start = row->next_x; + data->surface = row->surface; + + align = (8 / (DFB_BYTES_PER_PIXEL( font->pixel_format ) ? : 1)) * + (DFB_PIXELFORMAT_ALIGNMENT( font->pixel_format ) + 1) - 1; + + row->next_x += (data->width + align) & ~align; + + row->stamp = font->row_stamp++; + + /* Render the glyph data into the surface. */ + ret = font->RenderGlyph( font, index, data ); + if (ret) { + data->start = data->width = data->height = 0; + data->failed = true; + goto out; + } + + dfb_gfxcard_flush_texture_cache(); + + +out: + if (!data->inserted) { + if (row) + direct_list_append( &row->glyphs, &data->link ); + + direct_hash_insert( font->layers[layer].glyph_hash, index, data ); + + if (index < 128) + font->layers[layer].glyph_data[index] = data; + + data->inserted = true; + } + + *ret_data = data; + + return DFB_OK; + + +error: + D_MAGIC_CLEAR( data ); + D_FREE( data ); + + return ret; +} + +/**********************************************************************************************************************/ + +DFBResult +dfb_font_register_encoding( CoreFont *font, + const char *name, + const CoreFontEncodingFuncs *funcs, + DFBTextEncodingID encoding_id ) +{ + CoreFontEncoding *encoding; + CoreFontEncoding **encodings; + + D_DEBUG_AT( Core_Font, "%s()\n", __FUNCTION__ ); + + D_MAGIC_ASSERT( font, CoreFont ); + D_ASSERT( encoding_id == DTEID_UTF8 || name != NULL ); + D_ASSERT( funcs != NULL ); + + if (!funcs->GetCharacterIndex) + return DFB_INVARG; + + /* Special case for default, native format. */ + if (encoding_id == DTEID_UTF8) { + font->utf8 = funcs; + + return DFB_OK; + } + + if (!funcs->DecodeText) + return DFB_INVARG; + + /* Setup new encoding information. */ + encoding = D_CALLOC( 1, sizeof(CoreFontEncoding) ); + if (!encoding) + return D_OOM(); + + encoding->encoding = font->last_encoding + 1; + encoding->funcs = funcs; + encoding->name = D_STRDUP( name ); + + if (!encoding->name) { + D_FREE( encoding ); + return D_OOM(); + } + + /* Add to array. */ + encodings = D_REALLOC( font->encodings, + (encoding->encoding + 1) * sizeof(CoreFontEncoding*) ); + if (!encodings) { + D_FREE( encoding->name ); + D_FREE( encoding ); + return D_OOM(); + } + + font->encodings = encodings; + + font->last_encoding++; + + D_ASSERT( font->last_encoding == encoding->encoding ); + + encodings[encoding->encoding] = encoding; + + D_MAGIC_SET( encoding, CoreFontEncoding ); + + return DFB_OK; +} + +DFBResult +dfb_font_decode_text( CoreFont *font, + DFBTextEncodingID encoding, + const void *text, + int length, + unsigned int *ret_indices, + int *ret_num ) +{ + int pos = 0, num = 0; + const u8 *bytes = text; + + D_DEBUG_AT( Core_Font, "%s()\n", __FUNCTION__ ); + + D_MAGIC_ASSERT( font, CoreFont ); + D_ASSERT( text != NULL ); + D_ASSERT( length >= 0 ); /* TODO: handle -1 here? */ + D_ASSERT( ret_indices != NULL ); + D_ASSERT( ret_num != NULL ); + + if (encoding != DTEID_UTF8) { + if (encoding > font->last_encoding) + return DFB_IDNOTFOUND; + + D_ASSERT( font->encodings[encoding] != NULL ); + D_ASSERT( font->encodings[encoding]->funcs != NULL ); + D_ASSERT( font->encodings[encoding]->funcs->DecodeText != NULL ); + + return font->encodings[encoding]->funcs->DecodeText( font, text, length, + ret_indices, ret_num ); + } + else if (font->utf8) { + const CoreFontEncodingFuncs *funcs = font->utf8; + + if (funcs->DecodeText) + return funcs->DecodeText( font, text, length, ret_indices, ret_num ); + + D_ASSERT( funcs->GetCharacterIndex != NULL ); + + while (pos < length) { + unsigned int c; + + if (bytes[pos] < 128) + c = bytes[pos++]; + else { + c = DIRECT_UTF8_GET_CHAR( &bytes[pos] ); + pos += DIRECT_UTF8_SKIP(bytes[pos]); + } + + if (funcs->GetCharacterIndex( font, c, &ret_indices[num] ) == DFB_OK) + num++; + } + + } + else { + while (pos < length) { + if (bytes[pos] < 128) + ret_indices[num++] = bytes[pos++]; + else { + ret_indices[num++] = DIRECT_UTF8_GET_CHAR( &bytes[pos] ); + pos += DIRECT_UTF8_SKIP(bytes[pos]); + } + } + } + + *ret_num = num; + + return DFB_OK; +} + +DFBResult +dfb_font_decode_character( CoreFont *font, + DFBTextEncodingID encoding, + u32 character, + unsigned int *ret_index ) +{ + D_DEBUG_AT( Core_Font, "%s()\n", __FUNCTION__ ); + + D_MAGIC_ASSERT( font, CoreFont ); + D_ASSERT( ret_index != NULL ); + + if (encoding > font->last_encoding) + return DFB_IDNOTFOUND; + + if (encoding != DTEID_UTF8) { + D_ASSERT( font->encodings[encoding] != NULL ); + D_ASSERT( font->encodings[encoding]->funcs != NULL ); + D_ASSERT( font->encodings[encoding]->funcs->GetCharacterIndex != NULL ); + + return font->encodings[encoding]->funcs->GetCharacterIndex( font, character, ret_index ); + } + else if (font->utf8) { + const CoreFontEncodingFuncs *funcs = font->utf8; + + D_ASSERT( funcs->GetCharacterIndex != NULL ); + + return funcs->GetCharacterIndex( font, character, ret_index ); + } + else + *ret_index = character; + + return DFB_OK; +} + +/**********************************************************************************************************************/ + +static bool +free_glyphs( DirectHash *hash, + unsigned long key, + void *value, + void *ctx ) +{ + CoreGlyphData *data = value; + + D_MAGIC_ASSERT( data, CoreGlyphData ); + + D_MAGIC_CLEAR( data ); + D_FREE( data ); + + return true; +} + diff --git a/Source/DirectFB/src/core/fonts.h b/Source/DirectFB/src/core/fonts.h new file mode 100755 index 0000000..4dc04fa --- /dev/null +++ b/Source/DirectFB/src/core/fonts.h @@ -0,0 +1,250 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __FONTS_H__ +#define __FONTS_H__ + +#include + +#include + +#include + +#include + +#include + +/* + * glyph struct + */ +struct _CoreGlyphData { + DirectLink link; + + unsigned int index; + unsigned int layer; + unsigned int row; + + CoreSurface *surface; /* contains bitmap of glyph */ + int start; /* x offset of glyph in surface */ + int width; /* width of the glyphs bitmap */ + int height; /* height of the glyphs bitmap */ + int left; /* x offset of the glyph */ + int top; /* y offset of the glyph */ + int xadvance; /* placement of next glyph */ + int yadvance; + + bool inserted; + bool failed; + + int magic; +}; + +typedef struct { + DFBResult (* GetCharacterIndex) ( CoreFont *thiz, + unsigned int character, + unsigned int *ret_index ); + + DFBResult (* DecodeText) ( CoreFont *thiz, + const void *text, + int length, + unsigned int *ret_indices, + int *ret_num ); +} CoreFontEncodingFuncs; + +typedef struct { + DirectLink link; + + DFBTextEncodingID encoding; + char *name; + const CoreFontEncodingFuncs *funcs; + + int magic; +} CoreFontEncoding; + +typedef struct { + unsigned int stamp; + + CoreSurface *surface; + int next_x; + + DirectLink *glyphs; + + int magic; +} CoreFontCacheRow; + + +#define DFB_FONT_MAX_LAYERS 2 + +/* + * font struct + */ + +struct _CoreFont { + CoreDFB *core; + + DFBFontDescription description; /* original description used to create the font */ + char *url; + + DFBSurfaceBlittingFlags blittingflags; + DFBSurfacePixelFormat pixel_format; + DFBSurfaceCapabilities surface_caps; + int row_width; + int max_rows; + + DFBFontAttributes attributes; + + CoreFontCacheRow **rows; /* contain bitmaps of loaded glyphs */ + int num_rows; + int active_row; + unsigned int row_stamp; + + struct { + DirectHash *glyph_hash; /* infos about loaded glyphs */ + CoreGlyphData *glyph_data[128]; + } layers[DFB_FONT_MAX_LAYERS]; + + int height; /* font height */ + + int ascender; /* a positive value, the distance + from the baseline to the top */ + int descender; /* a negative value, the distance + from the baseline to the bottom */ + int maxadvance; /* width of largest character */ + + float up_unit_x; /* unit vector pointing 'up' in for */ + float up_unit_y; /* this font's rotation */ + + pthread_mutex_t lock; /* lock during access to the font */ + + const CoreFontEncodingFuncs *utf8; /* for default encoding, DTEID_UTF8 */ + CoreFontEncoding **encodings; /* for other encodings */ + DFBTextEncodingID last_encoding; /* dynamic allocation impl. helper */ + + void *impl_data; /* a pointer used by the impl. */ + + DFBResult (* GetGlyphData) ( CoreFont *thiz, + unsigned int index, + CoreGlyphData *data ); + + DFBResult (* RenderGlyph) ( CoreFont *thiz, + unsigned int index, + CoreGlyphData *data ); + + DFBResult (* GetKerning) ( CoreFont *thiz, + unsigned int prev, + unsigned int current, + int *ret_x, + int *ret_y ); + + + int magic; +}; + +/* + * allocates and initializes a new font structure + */ +DFBResult dfb_font_create( CoreDFB *core, + const DFBFontDescription *description, + const char *url, + CoreFont **ret_font ); + +/* + * destroy all data in the CoreFont struct + */ +void dfb_font_destroy( CoreFont *font ); + +/* + * lock the font before accessing it + */ +static inline void +dfb_font_lock( CoreFont *font ) +{ + D_MAGIC_ASSERT( font, CoreFont ); + + pthread_mutex_lock( &font->lock ); +} + +/* + * unlock the font after access + */ +static inline void +dfb_font_unlock( CoreFont *font ) +{ + D_MAGIC_ASSERT( font, CoreFont ); + + pthread_mutex_unlock( &font->lock ); +} + +/* + * loads glyph data from font + */ +DFBResult dfb_font_get_glyph_data( CoreFont *font, + unsigned int index, + unsigned int layer, + CoreGlyphData **glyph_data ); + + +/* + * Called by font module to register encoding implementations. + * + * The encoding can be DTEID_UTF8 or DTEID_OTHER, where in the + * latter case the actual id will be allocated dynamically. + * + * In the case of DTEID_UTF8 it's allowed to only provide + * GetCharacterIndex() and let the core do the DecodeText(), + * but that would cause a GetCharacterIndex() call per decoded + * unicode character. So implementing both is advisable. + * + * If nothing is registered for DTEID_UTF8 at all, the core will + * pass the raw unicode characters to GetGlyphInfo(), RenderGlyph() etc. + * That's the old behaviour, fully compatible with old modules. It's + * also a good choice if you want to avoid the character translation, + * having an efficient font module which is based natively on unicode + * characters. + * + * For registering an encoding as DTEID_OTHER both GetCharacterIndex() + * and DecodeText() must be provided. + */ +DFBResult dfb_font_register_encoding( CoreFont *font, + const char *name, + const CoreFontEncodingFuncs *funcs, + DFBTextEncodingID encoding ); + +DFBResult dfb_font_decode_text( CoreFont *font, + DFBTextEncodingID encoding, + const void *text, + int length, + unsigned int *ret_indices, + int *ret_num ); + +DFBResult dfb_font_decode_character( CoreFont *font, + DFBTextEncodingID encoding, + u32 character, + unsigned int *ret_index ); + +#endif diff --git a/Source/DirectFB/src/core/gfxcard.c b/Source/DirectFB/src/core/gfxcard.c new file mode 100755 index 0000000..84e725c --- /dev/null +++ b/Source/DirectFB/src/core/gfxcard.c @@ -0,0 +1,2921 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + + +D_DEBUG_DOMAIN( Core_Graphics, "Core/Graphics", "DirectFB Graphics Core" ); +D_DEBUG_DOMAIN( Core_GraphicsOps, "Core/GraphicsOps", "DirectFB Graphics Core Operations" ); +D_DEBUG_DOMAIN( Core_GfxState, "Core/GfxState", "DirectFB Graphics Core State" ); + + +DEFINE_MODULE_DIRECTORY( dfb_graphics_drivers, "gfxdrivers", DFB_GRAPHICS_DRIVER_ABI_VERSION ); + +/**********************************************************************************************************************/ + +static void dfb_gfxcard_find_driver( CoreDFB *core ); +static void dfb_gfxcard_load_driver( void ); + +static void fill_tri( DFBTriangle *tri, CardState *state, bool accelerated ); + +/**********************************************************************************************************************/ + +typedef struct { + int magic; + + /* amount of usable memory */ + unsigned int videoram_length; + unsigned int auxram_length; + unsigned int auxram_offset; + + char *module_name; + + GraphicsDriverInfo driver_info; + GraphicsDeviceInfo device_info; + void *device_data; + + FusionProperty lock; + GraphicsDeviceLockFlags lock_flags; + + /* + * Points to the current state of the graphics card. + */ + CardState *state; + FusionID holder; /* Fusion ID of state owner. */ +} DFBGraphicsCoreShared; + +struct __DFB_DFBGraphicsCore { + int magic; + + CoreDFB *core; + + DFBGraphicsCoreShared *shared; + + DirectModuleEntry *module; + const GraphicsDriverFuncs *driver_funcs; + + void *driver_data; + void *device_data; /* copy of shared->device_data */ + + CardCapabilities caps; /* local caps */ + CardLimitations limits; /* local limits */ + + GraphicsDeviceFuncs funcs; +}; + + +DFB_CORE_PART( graphics_core, GraphicsCore ); + +/**********************************************************************************************************************/ + +static CoreGraphicsDevice *card; /* FIXME */ + +/* Hook for registering additional screen(s) and layer(s) in app or lib initializing DirectFB. */ +void (*__DFB_CoreRegisterHook)( CoreDFB *core, CoreGraphicsDevice *device, void *ctx ) = NULL; +void *__DFB_CoreRegisterHookCtx = NULL; + + +/** public **/ + +static DFBResult +dfb_graphics_core_initialize( CoreDFB *core, + DFBGraphicsCore *data, + DFBGraphicsCoreShared *shared ) +{ + DFBResult ret; + int videoram_length; + int auxram_length; + FusionSHMPoolShared *pool = dfb_core_shmpool( core ); + + D_DEBUG_AT( Core_Graphics, "dfb_graphics_core_initialize( %p, %p, %p )\n", core, data, shared ); + + D_ASSERT( data != NULL ); + D_ASSERT( shared != NULL ); + + + card = data; /* FIXME */ + + data->core = core; + data->shared = shared; + + + /* fill generic driver info */ + gGetDriverInfo( &shared->driver_info ); + + /* fill generic device info */ + gGetDeviceInfo( &shared->device_info ); + + if (!shared->device_info.limits.dst_max.w) + shared->device_info.limits.dst_max.w = INT_MAX; + + if (!shared->device_info.limits.dst_max.h) + shared->device_info.limits.dst_max.h = INT_MAX; + + /* Limit video ram length */ + videoram_length = dfb_system_videoram_length(); + if (videoram_length) { + if (dfb_config->videoram_limit > 0 && + dfb_config->videoram_limit < videoram_length) + shared->videoram_length = dfb_config->videoram_limit; + else + shared->videoram_length = videoram_length; + } + + /* Limit auxiliary memory length (currently only AGP) */ + auxram_length = dfb_system_auxram_length(); + if (auxram_length) { + if (dfb_config->agpmem_limit > 0 && + dfb_config->agpmem_limit < auxram_length) + shared->auxram_length = dfb_config->agpmem_limit; + else + shared->auxram_length = auxram_length; + } + + /* Build a list of available drivers. */ + direct_modules_explore_directory( &dfb_graphics_drivers ); + + /* Load driver */ + if (dfb_system_caps() & CSCAPS_ACCELERATION) + dfb_gfxcard_find_driver( core ); + + if (data->driver_funcs) { + const GraphicsDriverFuncs *funcs = data->driver_funcs; + + data->driver_data = D_CALLOC( 1, shared->driver_info.driver_data_size ); + + card->device_data = + shared->device_data = SHCALLOC( pool, 1, shared->driver_info.device_data_size ); + + ret = funcs->InitDriver( card, &card->funcs, + card->driver_data, card->device_data, core ); + if (ret) { + SHFREE( pool, shared->device_data ); + SHFREE( pool, shared->module_name ); + D_FREE( card->driver_data ); + card = NULL; + return ret; + } + + ret = funcs->InitDevice( data, &shared->device_info, + data->driver_data, data->device_data ); + if (ret) { + funcs->CloseDriver( card, card->driver_data ); + SHFREE( pool, shared->device_data ); + SHFREE( pool, shared->module_name ); + D_FREE( card->driver_data ); + card = NULL; + return ret; + } + + if (data->funcs.EngineReset) + data->funcs.EngineReset( data->driver_data, data->device_data ); + } + + D_INFO( "DirectFB/Graphics: %s %s %d.%d (%s)\n", + shared->device_info.vendor, shared->device_info.name, + shared->driver_info.version.major, + shared->driver_info.version.minor, shared->driver_info.vendor ); + + if (dfb_config->software_only) { + if (data->funcs.CheckState) { + data->funcs.CheckState = NULL; + + D_INFO( "DirectFB/Graphics: Acceleration disabled (by 'no-hardware')\n" ); + } + } + else { + data->caps = shared->device_info.caps; + data->limits = shared->device_info.limits; + } + + fusion_property_init( &shared->lock, dfb_core_world(core) ); + + if (__DFB_CoreRegisterHook) + __DFB_CoreRegisterHook( core, card, __DFB_CoreRegisterHookCtx ); + + D_MAGIC_SET( data, DFBGraphicsCore ); + D_MAGIC_SET( shared, DFBGraphicsCoreShared ); + + return DFB_OK; +} + +static DFBResult +dfb_graphics_core_join( CoreDFB *core, + DFBGraphicsCore *data, + DFBGraphicsCoreShared *shared ) +{ + DFBResult ret; + GraphicsDriverInfo driver_info; + + D_DEBUG_AT( Core_Graphics, "dfb_graphics_core_join( %p, %p, %p )\n", core, data, shared ); + + D_ASSERT( data != NULL ); + D_MAGIC_ASSERT( shared, DFBGraphicsCoreShared ); + + card = data; /* FIXME */ + + data->core = core; + data->shared = shared; + + /* Initialize software rasterizer. */ + gGetDriverInfo( &driver_info ); + + /* Build a list of available drivers. */ + direct_modules_explore_directory( &dfb_graphics_drivers ); + + /* Load driver. */ + if (dfb_system_caps() & CSCAPS_ACCELERATION) + dfb_gfxcard_load_driver(); + + if (data->driver_funcs) { + const GraphicsDriverFuncs *funcs = data->driver_funcs; + + data->driver_data = D_CALLOC( 1, shared->driver_info.driver_data_size ); + + data->device_data = shared->device_data; + + ret = funcs->InitDriver( card, &card->funcs, + card->driver_data, card->device_data, core ); + if (ret) { + D_FREE( data->driver_data ); + data = NULL; + return ret; + } + } + else if (shared->module_name) { + D_ERROR( "DirectFB/Graphics: Could not load driver used by the running session!\n" ); + data = NULL; + return DFB_UNSUPPORTED; + } + + + D_INFO( "DirectFB/Graphics: %s %s %d.%d (%s)\n", + shared->device_info.vendor, shared->device_info.name, + shared->driver_info.version.major, + shared->driver_info.version.minor, shared->driver_info.vendor ); + + if (dfb_config->software_only) { + if (data->funcs.CheckState) { + data->funcs.CheckState = NULL; + + D_INFO( "DirectFB/Graphics: Acceleration disabled (by 'no-hardware')\n" ); + } + } + else { + data->caps = shared->device_info.caps; + data->limits = shared->device_info.limits; + } + + D_MAGIC_SET( data, DFBGraphicsCore ); + + return DFB_OK; +} + +static DFBResult +dfb_graphics_core_shutdown( DFBGraphicsCore *data, + bool emergency ) +{ + DFBGraphicsCoreShared *shared; + FusionSHMPoolShared *pool = dfb_core_shmpool( data->core ); + + D_DEBUG_AT( Core_Graphics, "dfb_graphics_core_shutdown( %p, %semergency )\n", data, emergency ? "" : "no " ); + + D_MAGIC_ASSERT( data, DFBGraphicsCore ); + D_MAGIC_ASSERT( data->shared, DFBGraphicsCoreShared ); + + shared = data->shared; + + + dfb_gfxcard_lock( GDLF_SYNC ); + + if (data->driver_funcs) { + const GraphicsDriverFuncs *funcs = data->driver_funcs; + + funcs->CloseDevice( data, data->driver_data, data->device_data ); + funcs->CloseDriver( data, data->driver_data ); + + direct_module_unref( data->module ); + + SHFREE( pool, card->device_data ); + D_FREE( card->driver_data ); + } + + fusion_property_destroy( &shared->lock ); + + if (shared->module_name) + SHFREE( pool, shared->module_name ); + + + D_MAGIC_CLEAR( data ); + D_MAGIC_CLEAR( shared ); + + return DFB_OK; +} + +static DFBResult +dfb_graphics_core_leave( DFBGraphicsCore *data, + bool emergency ) +{ + DFBGraphicsCoreShared *shared; + + D_DEBUG_AT( Core_Graphics, "dfb_graphics_core_leave( %p, %semergency )\n", data, emergency ? "" : "no " ); + + D_MAGIC_ASSERT( data, DFBGraphicsCore ); + D_MAGIC_ASSERT( data->shared, DFBGraphicsCoreShared ); + + shared = data->shared; + + if (data->driver_funcs) { + data->driver_funcs->CloseDriver( data, data->driver_data ); + + direct_module_unref( data->module ); + + D_FREE( data->driver_data ); + } + + + D_MAGIC_CLEAR( data ); + + return DFB_OK; +} + +static DFBResult +dfb_graphics_core_suspend( DFBGraphicsCore *data ) +{ + DFBGraphicsCoreShared *shared; + + D_DEBUG_AT( Core_Graphics, "dfb_graphics_core_suspend( %p )\n", data ); + + D_MAGIC_ASSERT( data, DFBGraphicsCore ); + D_MAGIC_ASSERT( data->shared, DFBGraphicsCoreShared ); + + shared = data->shared; + + dfb_gfxcard_lock( GDLF_WAIT | GDLF_SYNC | GDLF_RESET | GDLF_INVALIDATE ); + + return DFB_OK; +} + +static DFBResult +dfb_graphics_core_resume( DFBGraphicsCore *data ) +{ + DFBGraphicsCoreShared *shared; + + D_DEBUG_AT( Core_Graphics, "dfb_graphics_core_resume( %p )\n", data ); + + D_MAGIC_ASSERT( data, DFBGraphicsCore ); + D_MAGIC_ASSERT( data->shared, DFBGraphicsCoreShared ); + + shared = data->shared; + + dfb_gfxcard_unlock(); + + return DFB_OK; +} + +/**********************************************************************************************************************/ + +DFBResult +dfb_gfxcard_lock( GraphicsDeviceLockFlags flags ) +{ + DFBResult ret; + DFBGraphicsCoreShared *shared; + GraphicsDeviceFuncs *funcs; + + D_ASSERT( card != NULL ); + D_ASSERT( card->shared != NULL ); + + shared = card->shared; + funcs = &card->funcs; + + if ( ((flags & GDLF_WAIT) ? + fusion_property_purchase( &shared->lock ) : + fusion_property_lease( &shared->lock )) ) + return DFB_FAILURE; + + if ((flags & GDLF_SYNC) && funcs->EngineSync) { + ret = funcs->EngineSync( card->driver_data, card->device_data ); + if (ret) { + if (funcs->EngineReset) + funcs->EngineReset( card->driver_data, card->device_data ); + + shared->state = NULL; + + fusion_property_cede( &shared->lock ); + + return ret; + } + } + + if ((shared->lock_flags & GDLF_RESET) && funcs->EngineReset) + funcs->EngineReset( card->driver_data, card->device_data ); + + if (shared->lock_flags & GDLF_INVALIDATE) { + if (funcs->InvalidateState) + funcs->InvalidateState( card->driver_data, card->device_data ); + shared->state = NULL; + } + + shared->lock_flags = flags; + + return DFB_OK; +} + +void +dfb_gfxcard_unlock( void ) +{ + D_ASSERT( card != NULL ); + D_ASSERT( card->shared != NULL ); + + fusion_property_cede( &card->shared->lock ); +} + +void +dfb_gfxcard_holdup( void ) +{ + D_ASSERT( card != NULL ); + D_ASSERT( card->shared != NULL ); + + fusion_property_holdup( &card->shared->lock ); +} + +/* + * Signal beginning of a sequence of operations using this state. + * Any number of states can be 'drawing'. + */ +void +dfb_gfxcard_start_drawing( CoreGraphicsDevice *device, CardState *state ) +{ + D_ASSERT( device != NULL ); + D_MAGIC_ASSERT( state, CardState ); + + if (device->funcs.StartDrawing) + device->funcs.StartDrawing( device->driver_data, device->device_data, state ); +} + +/* + * Signal end of sequence, i.e. destination surface is consistent again. + */ +void +dfb_gfxcard_stop_drawing( CoreGraphicsDevice *device, CardState *state ) +{ + D_ASSERT( device != NULL ); + D_MAGIC_ASSERT( state, CardState ); + + if (device->funcs.StopDrawing) + device->funcs.StopDrawing( device->driver_data, device->device_data, state ); +} + +/* + * This function returns non zero if acceleration is available + * for the specific function using the given state. + */ +bool +dfb_gfxcard_state_check( CardState *state, DFBAccelerationMask accel ) +{ + CoreSurface *dst; + CoreSurface *src; + CoreSurfaceBuffer *dst_buffer; + CoreSurfaceBuffer *src_buffer; + + int cx2, cy2; + + D_ASSERT( card != NULL ); + D_MAGIC_ASSERT( state, CardState ); + D_MAGIC_ASSERT_IF( state->destination, CoreSurface ); + D_MAGIC_ASSERT_IF( state->source, CoreSurface ); + + D_DEBUG_AT( Core_GraphicsOps, "%s( %p, 0x%08x ) [%d,%d - %d,%d]\n", + __FUNCTION__, state, accel, DFB_REGION_VALS( &state->clip ) ); + + D_ASSERT( state->clip.x2 >= state->clip.x1 ); + D_ASSERT( state->clip.y2 >= state->clip.y1 ); + D_ASSERT( state->clip.x1 >= 0 ); + D_ASSERT( state->clip.y1 >= 0 ); + + if (DFB_BLITTING_FUNCTION(accel)) { + D_DEBUG_AT( Core_GfxState, "%s( %p, 0x%08x ) blitting %p -> %p\n", __FUNCTION__, + state, accel, state->source, state->destination ); + } + else { + D_DEBUG_AT( Core_GfxState, "%s( %p, 0x%08x ) drawing -> %p\n", __FUNCTION__, + state, accel, state->destination ); + } + + if (state->clip.x1 < 0) { + state->clip.x1 = 0; + state->modified |= SMF_CLIP; + } + + if (state->clip.y1 < 0) { + state->clip.y1 = 0; + state->modified |= SMF_CLIP; + } + + D_DEBUG_AT( Core_GfxState, " <- checked 0x%08x, accel 0x%08x, modified 0x%08x, mod_hw 0x%08x\n", + state->checked, state->accel, state->modified, state->mod_hw ); + + dst = state->destination; + src = state->source; + + /* Destination may have been destroyed. */ + if (!dst) { + D_BUG( "no destination" ); + return false; + } + + /* Source may have been destroyed. */ + if (DFB_BLITTING_FUNCTION( accel )) { + if (!src) { + D_BUG( "no source" ); + return false; + } + + /* Mask may have been destroyed. */ + if (state->blittingflags & (DSBLIT_SRC_MASK_ALPHA | DSBLIT_SRC_MASK_COLOR) && !state->source_mask) { + D_BUG( "no mask" ); + return false; + } + } + + dst_buffer = dfb_surface_get_buffer( dst, state->to ); + D_MAGIC_ASSERT( dst_buffer, CoreSurfaceBuffer ); + + D_ASSUME( state->clip.x2 < dst->config.size.w ); + D_ASSUME( state->clip.y2 < dst->config.size.h ); + + cx2 = state->destination->config.size.w - 1; + cy2 = state->destination->config.size.h - 1; + + if (state->clip.x2 > cx2) { + state->clip.x2 = cx2; + + if (state->clip.x1 > cx2) + state->clip.x1 = cx2; + + state->modified |= SMF_CLIP; + } + + if (state->clip.y2 > cy2) { + state->clip.y2 = cy2; + + if (state->clip.y1 > cy2) + state->clip.y1 = cy2; + + state->modified |= SMF_CLIP; + } + + + /* + * If there's no CheckState function there's no acceleration at all. + */ + if (!card->funcs.CheckState) + return false; + + /* + * Check if this function has been disabled temporarily. + */ + if (state->disabled & accel) + return false; + + /* If destination or blend functions have been changed... */ + if (state->modified & (SMF_DESTINATION | SMF_SRC_BLEND | SMF_DST_BLEND | SMF_RENDER_OPTIONS)) { + /* ...force rechecking for all functions. */ + state->checked = DFXL_NONE; + } + else { + /* If source/mask or blitting flags have been changed... */ + if (state->modified & (SMF_SOURCE | SMF_BLITTING_FLAGS | SMF_SOURCE_MASK | SMF_SOURCE_MASK_VALS)) { + /* ...force rechecking for all blitting functions. */ + state->checked &= ~DFXL_ALL_BLIT; + } + + /* If drawing flags have been changed... */ + if (state->modified & SMF_DRAWING_FLAGS) { + /* ...force rechecking for all drawing functions. */ + state->checked &= ~DFXL_ALL_DRAW; + } + } + + D_DEBUG_AT( Core_GfxState, " -> checked 0x%08x, accel 0x%08x, modified 0x%08x, mod_hw 0x%08x\n", + state->checked, state->accel, state->modified, state->mod_hw ); + + /* If the function needs to be checked... */ + if (!(state->checked & accel)) { + /* Unset unchecked functions. */ + state->accel &= state->checked; + + /* Call driver to (re)set the bit if the function is supported. */ + card->funcs.CheckState( card->driver_data, card->device_data, state, accel ); + + /* Add the function to 'checked functions'. */ + state->checked |= accel; + + /* Add additional functions the driver might have checked, too. */ + state->checked |= state->accel; + } + + D_DEBUG_AT( Core_GfxState, " -> checked 0x%08x, accel 0x%08x, modified 0x%08x, mod_hw 0x%08x\n", + state->checked, state->accel, state->modified, state->mod_hw ); + + /* Move modification flags to the set for drivers. */ + state->mod_hw |= state->modified; + state->modified = 0; + + /* + * If back_buffer policy is 'system only' there's no acceleration + * available. + */ + if (dst_buffer->policy == CSP_SYSTEMONLY || /* Special check required if driver does not check itself. */ + ( !(card->caps.flags & CCF_RENDEROPTS) && + (state->render_options & DSRO_MATRIX) )) + { + /* Clear 'accelerated functions'. */ + state->accel = DFXL_NONE; + state->checked = DFXL_ALL; + } + else if (DFB_BLITTING_FUNCTION( accel )) { + /* + * If the front buffer policy of the source is 'system only' + * no accelerated blitting is available. + */ + src_buffer = dfb_surface_get_buffer( src, state->from ); + + D_MAGIC_ASSERT( src_buffer, CoreSurfaceBuffer ); + + if (src_buffer->policy == CSP_SYSTEMONLY && !(card->caps.flags & CCF_READSYSMEM)) { + /* Clear 'accelerated blitting functions'. */ + state->accel &= ~DFXL_ALL_BLIT; + state->checked |= DFXL_ALL_BLIT; + } + } + + D_DEBUG_AT( Core_GfxState, " => checked 0x%08x, accel 0x%08x, modified 0x%08x, mod_hw 0x%08x\n", + state->checked, state->accel, state->modified, state->mod_hw ); + + /* Return whether the function bit is set. */ + return !!(state->accel & accel); +} + +/* + * This function returns non zero after successful locking the surface(s) + * for access by hardware. Propagate state changes to driver. + */ +static bool +dfb_gfxcard_state_acquire( CardState *state, DFBAccelerationMask accel ) +{ + DFBResult ret; + CoreSurface *dst; + CoreSurface *src; + DFBGraphicsCoreShared *shared; + CoreSurfaceAccessFlags access = CSAF_WRITE; + + D_ASSERT( card != NULL ); + D_ASSERT( card->shared != NULL ); + + D_MAGIC_ASSERT( state, CardState ); + D_MAGIC_ASSERT_IF( state->destination, CoreSurface ); + D_MAGIC_ASSERT_IF( state->source, CoreSurface ); + + dst = state->destination; + src = state->source; + shared = card->shared; + + /* find locking flags */ + if (DFB_BLITTING_FUNCTION( accel )) { + if (state->blittingflags & (DSBLIT_BLEND_ALPHACHANNEL | + DSBLIT_BLEND_COLORALPHA | + DSBLIT_DST_COLORKEY)) + access |= CSAF_READ; + } + else if (state->drawingflags & (DSDRAW_BLEND | DSDRAW_DST_COLORKEY)) + access |= CSAF_READ; + + if (DFB_BLITTING_FUNCTION(accel)) { + D_DEBUG_AT( Core_GfxState, "%s( %p, 0x%08x ) blitting %p -> %p\n", __FUNCTION__, + state, accel, state->source, state->destination ); + } + else { + D_DEBUG_AT( Core_GfxState, "%s( %p, 0x%08x ) drawing -> %p\n", __FUNCTION__, + state, accel, state->destination ); + } + + /* lock destination */ + ret = dfb_surface_lock_buffer( dst, state->to, CSAID_GPU, access, &state->dst ); + if (ret) { + D_DEBUG_AT( Core_Graphics, "Could not lock destination for GPU access!\n" ); + return false; + } + + /* if blitting... */ + if (DFB_BLITTING_FUNCTION( accel )) { + /* ...lock source for reading */ + ret = dfb_surface_lock_buffer( src, state->from, CSAID_GPU, CSAF_READ, &state->src ); + if (ret) { + D_DEBUG_AT( Core_Graphics, "Could not lock source for GPU access!\n" ); + dfb_surface_unlock_buffer( dst, &state->dst ); + return false; + } + + state->flags |= CSF_SOURCE_LOCKED; + + /* if using a mask... */ + if (state->blittingflags & (DSBLIT_SRC_MASK_ALPHA | DSBLIT_SRC_MASK_COLOR)) { + /* ...lock source mask for reading */ + ret = dfb_surface_lock_buffer( state->source_mask, state->from, CSAID_GPU, CSAF_READ, &state->src_mask ); + if (ret) { + D_DEBUG_AT( Core_Graphics, "Could not lock source mask for GPU access!\n" ); + dfb_surface_unlock_buffer( src, &state->src ); + dfb_surface_unlock_buffer( dst, &state->dst ); + return false; + } + + state->flags |= CSF_SOURCE_MASK_LOCKED; + } + } + + /* + * Make sure that state setting with subsequent command execution + * isn't done by two processes simultaneously. + * + * This will timeout if the hardware is locked by another party with + * the first argument being true (e.g. DRI). + */ + if (dfb_gfxcard_lock( GDLF_NONE )) { + D_DERROR( ret, "Core/Graphics: Could not lock GPU!\n" ); + + dfb_surface_unlock_buffer( dst, &state->dst ); + + if (state->flags & CSF_SOURCE_LOCKED) { + dfb_surface_unlock_buffer( src, &state->src ); + state->flags &= ~CSF_SOURCE_LOCKED; + } + + /* if source mask got locked this value is true */ + if (state->flags & CSF_SOURCE_MASK_LOCKED) { + dfb_surface_unlock_buffer( state->source_mask, &state->src_mask ); + + state->flags &= ~CSF_SOURCE_MASK_LOCKED; + } + + return false; + } + + /* if we are switching to another state... */ + if (state != shared->state || state->fusion_id != shared->holder) { + D_DEBUG_AT( Core_GfxState, " -> switch from %p [%lu] to %p [%lu]\n", + shared->state, shared->holder, state, state->fusion_id ); + + /* ...set all modification bits and clear 'set functions' */ + state->mod_hw |= SMF_ALL; + state->set = 0; + + shared->state = state; + shared->holder = state->fusion_id; + } + + dfb_state_update( state, state->flags & (CSF_SOURCE_LOCKED | CSF_SOURCE_MASK_LOCKED) ); + + D_DEBUG_AT( Core_GfxState, " -> mod_hw 0x%08x, modified 0x%08x\n", state->mod_hw, state->modified ); + + /* Move modification flags to the set for drivers. */ + state->mod_hw |= state->modified; + state->modified = SMF_ALL; + + /* + * If function hasn't been set or state is modified, + * call the driver function to propagate the state changes. + */ + D_DEBUG_AT( Core_GfxState, " -> mod_hw 0x%08x, set 0x%08x\n", state->mod_hw, state->set ); + if (state->mod_hw || !(state->set & accel)) { + card->funcs.SetState( card->driver_data, card->device_data, + &card->funcs, state, accel ); + + D_DEBUG_AT( Core_GfxState, " => mod_hw 0x%08x, set 0x%08x\n", state->mod_hw, state->set ); + } + + if (state->modified != SMF_ALL) + D_ONCE( "USING OLD DRIVER! *** Use 'state->mod_hw' NOT 'modified'." ); + + state->modified = 0; + + return true; +} + +/* + * Unlock destination and possibly the source. + */ +static void +dfb_gfxcard_state_release( CardState *state ) +{ + D_ASSERT( card != NULL ); + D_ASSERT( card->shared != NULL ); + D_MAGIC_ASSERT( state, CardState ); + D_ASSERT( state->destination != NULL ); + + /* start command processing if not already running */ + if (card->funcs.EmitCommands) + card->funcs.EmitCommands( card->driver_data, card->device_data ); + + /* Store the serial of the operation. */ +#if FIXME_SC_2 + if (card->funcs.GetSerial) { + card->funcs.GetSerial( card->driver_data, card->device_data, &state->serial ); + + state->destination->back_buffer->video.serial = state->serial; + } +#endif + + /* allow others to use the hardware */ + dfb_gfxcard_unlock(); + + /* destination always gets locked during acquisition */ + dfb_surface_unlock_buffer( state->destination, &state->dst ); + + /* if source got locked this value is true */ + if (state->flags & CSF_SOURCE_LOCKED) { + dfb_surface_unlock_buffer( state->source, &state->src ); + + state->flags &= ~CSF_SOURCE_LOCKED; + } + + /* if source mask got locked this value is true */ + if (state->flags & CSF_SOURCE_MASK_LOCKED) { + dfb_surface_unlock_buffer( state->source_mask, &state->src_mask ); + + state->flags &= ~CSF_SOURCE_MASK_LOCKED; + } +} + +/** DRAWING FUNCTIONS **/ + +#define DFB_TRANSFORM(x, y, m, affine) \ +do { \ + s32 _x, _y, _w; \ + if (affine) { \ + _x = ((x) * (m)[0] + (y) * (m)[1] + (m)[2] + 0x8000) >> 16; \ + _y = ((x) * (m)[3] + (y) * (m)[4] + (m)[5] + 0x8000) >> 16; \ + } \ + else { \ + _x = ((x) * (m)[0] + (y) * (m)[1] + (m)[2]); \ + _y = ((x) * (m)[3] + (y) * (m)[4] + (m)[5]); \ + _w = ((x) * (m)[6] + (y) * (m)[7] + (m)[8]); \ + if (!_w) { \ + _x = (_x < 0) ? -0x7fffffff : 0x7fffffff; \ + _y = (_y < 0) ? -0x7fffffff : 0x7fffffff; \ + } \ + else { \ + _x /= _w; \ + _y /= _w; \ + } \ + } \ + (x) = _x; \ + (y) = _y; \ +} while (0) + +void +dfb_gfxcard_fillrectangles( const DFBRectangle *rects, int num, CardState *state ) +{ + D_DEBUG_AT( Core_GraphicsOps, "%s( %p [%d], %p )\n", __FUNCTION__, rects, num, state ); + + D_ASSERT( card != NULL ); + D_ASSERT( card->shared != NULL ); + D_MAGIC_ASSERT( state, CardState ); + D_ASSERT( rects != NULL ); + D_ASSERT( num > 0 ); + + /* The state is locked during graphics operations. */ + dfb_state_lock( state ); + + /* Signal beginning of sequence of operations if not already done. */ + dfb_state_start_drawing( state, card ); + + if (!(state->render_options & DSRO_MATRIX)) { + while (num > 0) { + if (dfb_rectangle_region_intersects( rects, &state->clip )) + break; + + rects++; + num--; + } + } + + if (num > 0) { + int i = 0; + DFBRectangle rect; + + /* Check for acceleration and setup execution. */ + if (dfb_gfxcard_state_check( state, DFXL_FILLRECTANGLE ) && + dfb_gfxcard_state_acquire( state, DFXL_FILLRECTANGLE )) + { + /* + * Now everything is prepared for execution of the + * FillRectangle driver function. + */ + for (; irender_options & DSRO_MATRIX) && + !dfb_rectangle_region_intersects( &rects[i], &state->clip )) + continue; + + rect = rects[i]; + + if (rect.w > card->limits.dst_max.w || rect.h > card->limits.dst_max.h) { + dfb_clip_rectangle( &state->clip, &rect ); + + if (rect.w > card->limits.dst_max.w || rect.h > card->limits.dst_max.h) + break; + } + else if (!D_FLAGS_IS_SET( card->caps.flags, CCF_CLIPPING ) && + !D_FLAGS_IS_SET( card->caps.clip, DFXL_FILLRECTANGLE )) + dfb_clip_rectangle( &state->clip, &rect ); + + if (!card->funcs.FillRectangle( card->driver_data, + card->device_data, &rect )) + break; + } + + /* Release after state acquisition. */ + dfb_gfxcard_state_release( state ); + } + + if (i < num) { + /* Use software fallback. */ + if (gAcquire( state, DFXL_FILLRECTANGLE )) { + if (!(state->render_options & DSRO_MATRIX)) { + for (; iclip, &rect )) + gFillRectangle( state, &rect ); + } + } + else if (state->matrix[1] == 0 && state->matrix[3] == 0) { + /* Scaled/Translated Rectangle. */ + for (; imatrix, state->affine_matrix); + DFB_TRANSFORM(x2, y2, state->matrix, state->affine_matrix); + + if (x1 < x2) { + rect.x = x1; + rect.w = x2-x1; + } else { + rect.x = x2; + rect.w = x1-x2; + } + if (y1 < y2) { + rect.y = y1; + rect.h = y2-y1; + } + else { + rect.y = y2; + rect.h = y1-y2; + } + + if (dfb_clip_rectangle( &state->clip, &rect )) + gFillRectangle( state, &rect ); + } + } + else { + /* Rotated rectangle. Split into triangles. */ + for (; imatrix, state->affine_matrix); + DFB_TRANSFORM(tri.x2, tri.y2, state->matrix, state->affine_matrix); + DFB_TRANSFORM(tri.x3, tri.y3, state->matrix, state->affine_matrix); + + dfb_sort_triangle( &tri ); + if (tri.y3 - tri.y1 > 0) + fill_tri( &tri, state, false ); + + tri.x1 = rects[i].x; tri.y1 = rects[i].y; + tri.x2 = rects[i].x+rects[i].w; tri.y2 = rects[i].y+rects[i].h; + tri.x3 = rects[i].x; tri.y3 = rects[i].y+rects[i].h; + DFB_TRANSFORM(tri.x1, tri.y1, state->matrix, state->affine_matrix); + DFB_TRANSFORM(tri.x2, tri.y2, state->matrix, state->affine_matrix); + DFB_TRANSFORM(tri.x3, tri.y3, state->matrix, state->affine_matrix); + + dfb_sort_triangle( &tri ); + if (tri.y3 - tri.y1 > 0) + fill_tri( &tri, state, false ); + } + } + + gRelease( state ); + } + } + } + + /* Unlock after execution. */ + dfb_state_unlock( state ); +} + +static void +build_clipped_rectangle_outlines( DFBRectangle *rect, + const DFBRegion *clip, + DFBRectangle *ret_outlines, + int *ret_num ) +{ + DFBEdgeFlags edges = dfb_clip_edges( clip, rect ); + int t = (edges & DFEF_TOP ? 1 : 0); + int tb = t + (edges & DFEF_BOTTOM ? 1 : 0); + int num = 0; + + DFB_RECTANGLE_ASSERT( rect ); + + D_ASSERT( ret_outlines != NULL ); + D_ASSERT( ret_num != NULL ); + + if (edges & DFEF_TOP) { + DFBRectangle *out = &ret_outlines[num++]; + + out->x = rect->x; + out->y = rect->y; + out->w = rect->w; + out->h = 1; + } + + if (rect->h > t) { + if (edges & DFEF_BOTTOM) { + DFBRectangle *out = &ret_outlines[num++]; + + out->x = rect->x; + out->y = rect->y + rect->h - 1; + out->w = rect->w; + out->h = 1; + } + + if (rect->h > tb) { + if (edges & DFEF_LEFT) { + DFBRectangle *out = &ret_outlines[num++]; + + out->x = rect->x; + out->y = rect->y + t; + out->w = 1; + out->h = rect->h - tb; + } + + if (rect->w > 1 || !(edges & DFEF_LEFT)) { + if (edges & DFEF_RIGHT) { + DFBRectangle *out = &ret_outlines[num++]; + + out->x = rect->x + rect->w - 1; + out->y = rect->y + t; + out->w = 1; + out->h = rect->h - tb; + } + } + } + } + + *ret_num = num; +} + +void dfb_gfxcard_drawrectangle( DFBRectangle *rect, CardState *state ) +{ + DFBRectangle rects[4]; + bool hw = false; + int i = 0, num = 0; + + D_ASSERT( card != NULL ); + D_ASSERT( card->shared != NULL ); + D_MAGIC_ASSERT( state, CardState ); + DFB_RECTANGLE_ASSERT( rect ); + + D_DEBUG_AT( Core_GraphicsOps, "%s( %d,%d - %dx%d, %p )\n", __FUNCTION__, DFB_RECTANGLE_VALS(rect), state ); + + /* The state is locked during graphics operations. */ + dfb_state_lock( state ); + + /* Signal beginning of sequence of operations if not already done. */ + dfb_state_start_drawing( state, card ); + + if (!dfb_rectangle_region_intersects( rect, &state->clip )) { + dfb_state_unlock( state ); + return; + } + + if (D_FLAGS_IS_SET( card->caps.flags, CCF_CLIPPING ) || + D_FLAGS_IS_SET( card->caps.clip, DFXL_DRAWRECTANGLE ) || + !dfb_clip_needed( &state->clip, rect )) + { + if (rect->w <= card->limits.dst_max.w && rect->h <= card->limits.dst_max.h && + dfb_gfxcard_state_check( state, DFXL_DRAWRECTANGLE ) && + dfb_gfxcard_state_acquire( state, DFXL_DRAWRECTANGLE )) + { + hw = card->funcs.DrawRectangle( card->driver_data, + card->device_data, rect ); + + dfb_gfxcard_state_release( state ); + } + } + + if (!hw && !(state->render_options & DSRO_MATRIX)) { + build_clipped_rectangle_outlines( rect, &state->clip, rects, &num ); + + if (!num) { + dfb_state_unlock( state ); + return; + } + + if (dfb_gfxcard_state_check( state, DFXL_FILLRECTANGLE ) && + dfb_gfxcard_state_acquire( state, DFXL_FILLRECTANGLE )) + { + for (; ilimits.dst_max.w && rects[i].h <= card->limits.dst_max.h + && card->funcs.FillRectangle( card->driver_data, + card->device_data, &rects[i] ); + if (!hw) + break; + } + + dfb_gfxcard_state_release( state ); + } + } + + if (!hw) { + if (!(state->render_options & DSRO_MATRIX)) { + if (gAcquire( state, DFXL_FILLRECTANGLE )) { + for (; ix; y1 = rect->y; + x2 = rect->x+rect->w; y2 = rect->y; + x3 = rect->x+rect->w; y3 = rect->y+rect->h; + x4 = rect->x; y4 = rect->y+rect->h; + DFB_TRANSFORM(x1, y1, state->matrix, state->affine_matrix); + DFB_TRANSFORM(x2, y2, state->matrix, state->affine_matrix); + DFB_TRANSFORM(x3, y3, state->matrix, state->affine_matrix); + DFB_TRANSFORM(x4, y4, state->matrix, state->affine_matrix); + + line = (DFBRegion) { x1, y1, x2, y2 }; + if (dfb_clip_line( &state->clip, &line )) + gDrawLine( state, &line ); + + line = (DFBRegion) { x2, y2, x3, y3 }; + if (dfb_clip_line( &state->clip, &line )) + gDrawLine( state, &line ); + + line = (DFBRegion) { x3, y3, x4, y4 }; + if (dfb_clip_line( &state->clip, &line )) + gDrawLine( state, &line ); + + line = (DFBRegion) { x4, y4, x1, y1 }; + if (dfb_clip_line( &state->clip, &line )) + gDrawLine( state, &line ); + + gRelease( state ); + } + } + } + + dfb_state_unlock( state ); +} + +void dfb_gfxcard_drawlines( DFBRegion *lines, int num_lines, CardState *state ) +{ + int i = 0; + + D_DEBUG_AT( Core_GraphicsOps, "%s( %p [%d], %p )\n", __FUNCTION__, lines, num_lines, state ); + + D_ASSERT( card != NULL ); + D_ASSERT( card->shared != NULL ); + D_MAGIC_ASSERT( state, CardState ); + D_ASSERT( lines != NULL ); + D_ASSERT( num_lines > 0 ); + + /* The state is locked during graphics operations. */ + dfb_state_lock( state ); + + /* Signal beginning of sequence of operations if not already done. */ + dfb_state_start_drawing( state, card ); + + if (dfb_gfxcard_state_check( state, DFXL_DRAWLINE ) && + dfb_gfxcard_state_acquire( state, DFXL_DRAWLINE )) + { + for (; icaps.flags, CCF_CLIPPING ) && + !D_FLAGS_IS_SET( card->caps.clip, DFXL_DRAWLINE ) && + !dfb_clip_line( &state->clip, &lines[i] )) + continue; + + if (!card->funcs.DrawLine( card->driver_data, + card->device_data, &lines[i] )) + break; + } + + dfb_gfxcard_state_release( state ); + } + + if (i < num_lines) { + if (gAcquire( state, DFXL_DRAWLINE )) { + for (; irender_options & DSRO_MATRIX) { + DFB_TRANSFORM(lines[i].x1, lines[i].y1, state->matrix, state->affine_matrix); + DFB_TRANSFORM(lines[i].x2, lines[i].y2, state->matrix, state->affine_matrix); + } + + if (dfb_clip_line( &state->clip, &lines[i] )) + gDrawLine( state, &lines[i] ); + } + + gRelease( state ); + } + } + + dfb_state_unlock( state ); +} + +void dfb_gfxcard_fillspans( int y, DFBSpan *spans, int num_spans, CardState *state ) +{ + int i = 0; + + D_DEBUG_AT( Core_GraphicsOps, "%s( %d, %p [%d], %p )\n", __FUNCTION__, y, spans, num_spans, state ); + + D_ASSERT( card != NULL ); + D_ASSERT( card->shared != NULL ); + D_MAGIC_ASSERT( state, CardState ); + D_ASSERT( spans != NULL ); + D_ASSERT( num_spans > 0 ); + + /* The state is locked during graphics operations. */ + dfb_state_lock( state ); + + /* Signal beginning of sequence of operations if not already done. */ + dfb_state_start_drawing( state, card ); + + if (dfb_gfxcard_state_check( state, DFXL_FILLRECTANGLE ) && + dfb_gfxcard_state_acquire( state, DFXL_FILLRECTANGLE )) + { + for (; i card->limits.dst_max.w || rect.h > card->limits.dst_max.h) { + if (!dfb_clip_rectangle( &state->clip, &rect )) + continue; + + if (rect.w > card->limits.dst_max.w || rect.h > card->limits.dst_max.h) + break; + } + else if (!D_FLAGS_IS_SET( card->caps.flags, CCF_CLIPPING ) && + !D_FLAGS_IS_SET( card->caps.clip, DFXL_FILLRECTANGLE ) && + !dfb_clip_rectangle( &state->clip, &rect )) + continue; + + if (!card->funcs.FillRectangle( card->driver_data, + card->device_data, &rect )) + break; + } + + dfb_gfxcard_state_release( state ); + } + + if (i < num_spans) { + if (gAcquire( state, DFXL_FILLRECTANGLE )) { + for (; irender_options & DSRO_MATRIX) { + if (state->matrix[1] == 0 && state->matrix[3] == 0) { + int x1, y1, x2, y2; + + x1 = rect.x; y1 = rect.y; + x2 = x1+rect.w; y2 = y1+rect.h; + DFB_TRANSFORM(x1, y1, state->matrix, state->affine_matrix); + DFB_TRANSFORM(x2, y2, state->matrix, state->affine_matrix); + + if (x1 < x2) { + rect.x = x1; + rect.w = x2-x1; + } else { + rect.x = x2; + rect.w = x1-x2; + } + if (y1 < y2) { + rect.y = y1; + rect.h = y2-y1; + } + else { + rect.y = y2; + rect.h = y1-y2; + } + + if (dfb_clip_rectangle( &state->clip, &rect )) + gFillRectangle( state, &rect ); + } + else { + DFBTriangle tri; + + tri.x1 = rect.x; tri.y1 = rect.y; + tri.x2 = rect.x+rect.w; tri.y2 = rect.y; + tri.x3 = rect.x+rect.w; tri.y3 = rect.y+rect.h; + DFB_TRANSFORM(tri.x1, tri.y1, state->matrix, state->affine_matrix); + DFB_TRANSFORM(tri.x2, tri.y2, state->matrix, state->affine_matrix); + DFB_TRANSFORM(tri.x3, tri.y3, state->matrix, state->affine_matrix); + + dfb_sort_triangle( &tri ); + if (tri.y3 - tri.y1 > 0) + fill_tri( &tri, state, false ); + + tri.x1 = rect.x; tri.y1 = rect.y; + tri.x2 = rect.x+rect.w; tri.y2 = rect.y+rect.h; + tri.x3 = rect.x; tri.y3 = rect.y+rect.h; + DFB_TRANSFORM(tri.x1, tri.y1, state->matrix, state->affine_matrix); + DFB_TRANSFORM(tri.x2, tri.y2, state->matrix, state->affine_matrix); + DFB_TRANSFORM(tri.x3, tri.y3, state->matrix, state->affine_matrix); + + dfb_sort_triangle( &tri ); + if (tri.y3 - tri.y1 > 0) + fill_tri( &tri, state, false ); + } + } + else { + if (dfb_clip_rectangle( &state->clip, &rect )) + gFillRectangle( state, &rect ); + } + } + + gRelease( state ); + } + } + + dfb_state_unlock( state ); +} + + +typedef struct { + int xi; + int xf; + int mi; + int mf; + int _2dy; +} DDA; + +#define SETUP_DDA(xs,ys,xe,ye,dda) \ + do { \ + int dx = xe - xs; \ + int dy = ye - ys; \ + dda.xi = xs; \ + if (dy != 0) { \ + dda.mi = dx / dy; \ + dda.mf = 2*(dx % dy); \ + dda.xf = -dy; \ + dda._2dy = 2 * dy; \ + if (dda.mf < 0) { \ + dda.mf += 2 * ABS(dy); \ + dda.mi--; \ + } \ + } \ + else { \ + dda.mi = 0; \ + dda.mf = 0; \ + dda.xf = 0; \ + dda._2dy = 0; \ + } \ + } while (0) + + +#define INC_DDA(dda) \ + do { \ + dda.xi += dda.mi; \ + dda.xf += dda.mf; \ + if (dda.xf > 0) { \ + dda.xi++; \ + dda.xf -= dda._2dy; \ + } \ + } while (0) + + +/** + * render a triangle using two parallel DDA's + */ +static void +fill_tri( DFBTriangle *tri, CardState *state, bool accelerated ) +{ + int y, yend; + DDA dda1 = { .xi = 0 }, dda2 = { .xi = 0 }; + int clip_x1 = state->clip.x1; + int clip_x2 = state->clip.x2; + + D_MAGIC_ASSERT( state, CardState ); + + y = tri->y1; + yend = tri->y3; + + if (yend > state->clip.y2) + yend = state->clip.y2; + + SETUP_DDA(tri->x1, tri->y1, tri->x3, tri->y3, dda1); + SETUP_DDA(tri->x1, tri->y1, tri->x2, tri->y2, dda2); + + while (y <= yend) { + DFBRectangle rect; + + if (y == tri->y2) { + if (tri->y2 == tri->y3) + return; + SETUP_DDA(tri->x2, tri->y2, tri->x3, tri->y3, dda2); + } + + rect.w = ABS(dda1.xi - dda2.xi); + rect.x = MIN(dda1.xi, dda2.xi); + + if (clip_x2 < rect.x + rect.w) + rect.w = clip_x2 - rect.x + 1; + + if (rect.w > 0) { + if (clip_x1 > rect.x) { + rect.w -= (clip_x1 - rect.x); + rect.x = clip_x1; + } + rect.y = y; + rect.h = 1; + + if (rect.w > 0 && rect.y >= state->clip.y1) { + if (accelerated) + card->funcs.FillRectangle( card->driver_data, + card->device_data, &rect ); + else + gFillRectangle( state, &rect ); + } + } + + INC_DDA(dda1); + INC_DDA(dda2); + + y++; + } +} + + +void dfb_gfxcard_filltriangles( const DFBTriangle *tris, int num, CardState *state ) +{ + bool hw = false; + int i = 0; + + D_ASSERT( card != NULL ); + D_ASSERT( card->shared != NULL ); + D_MAGIC_ASSERT( state, CardState ); + D_ASSERT( tris != NULL ); + D_ASSERT( num > 0 ); + + D_DEBUG_AT( Core_GraphicsOps, "%s( %p [%d], %p )\n", __FUNCTION__, tris, num, state ); + + /* The state is locked during graphics operations. */ + dfb_state_lock( state ); + + /* Signal beginning of sequence of operations if not already done. */ + dfb_state_start_drawing( state, card ); + + if (dfb_gfxcard_state_check( state, DFXL_FILLTRIANGLE ) && + dfb_gfxcard_state_acquire( state, DFXL_FILLTRIANGLE )) + { + if (!D_FLAGS_IS_SET( card->caps.flags, CCF_CLIPPING ) && + !D_FLAGS_IS_SET( card->caps.clip, DFXL_FILLTRIANGLE )) + { + DFBPoint p[6]; + int n; + + for (; i < num; i++) { + /* FIXME: DSRO_MATRIX. */ + if (dfb_clip_triangle( &state->clip, &tris[i], p, &n )) { + DFBTriangle tri; + int j; + + tri.x1 = p[0].x; tri.y1 = p[0].y; + tri.x2 = p[1].x; tri.y2 = p[1].y; + tri.x3 = p[2].x; tri.y3 = p[2].y; + hw = card->funcs.FillTriangle( card->driver_data, + card->device_data, &tri ); + if (!hw) + break; + + /* FIXME: return value. */ + for (j = 3; j < n; j++) { + tri.x1 = p[0].x; tri.y1 = p[0].y; + tri.x2 = p[j-1].x; tri.y2 = p[j-1].y; + tri.x3 = p[j].x; tri.y3 = p[j].y; + card->funcs.FillTriangle( card->driver_data, + card->device_data, &tri ); + } + } + } + } + else { + for (; i < num; i++) { + DFBTriangle tri = tris[i]; + + hw = card->funcs.FillTriangle( card->driver_data, + card->device_data, &tri ); + if (!hw) + break; + } + + } + + dfb_gfxcard_state_release( state ); + } + + if (!hw && i < num) { + /* otherwise use the spanline rasterizer (fill_tri) + and fill the triangle using a rectangle for each spanline */ + + /* try hardware accelerated rectangle filling */ + if (!(card->caps.flags & CCF_NOTRIEMU) && + dfb_gfxcard_state_check( state, DFXL_FILLRECTANGLE ) && + dfb_gfxcard_state_acquire( state, DFXL_FILLRECTANGLE )) + { + for (; i < num; i++) { + DFBTriangle tri = tris[i]; + + dfb_sort_triangle( &tri ); + + if (tri.y3 - tri.y1 > 0) + fill_tri( &tri, state, true ); + } + + dfb_gfxcard_state_release( state ); + } + else if (gAcquire( state, DFXL_FILLRECTANGLE )) { + for (; i < num; i++) { + DFBTriangle tri = tris[i]; + + if (state->render_options & DSRO_MATRIX) { + DFB_TRANSFORM(tri.x1, tri.y1, state->matrix, state->affine_matrix); + DFB_TRANSFORM(tri.x2, tri.y2, state->matrix, state->affine_matrix); + DFB_TRANSFORM(tri.x3, tri.y3, state->matrix, state->affine_matrix); + } + + dfb_sort_triangle( &tri ); + + if (tri.y3 - tri.y1 > 0) + fill_tri( &tri, state, false ); + } + + gRelease( state ); + } + } + + dfb_state_unlock( state ); +} + +static void +clip_blit_rotated( DFBRectangle *srect, DFBRectangle *drect, const DFBRegion *clip, DFBSurfaceBlittingFlags flags ) +{ + DFBRegion dest = DFB_REGION_INIT_FROM_RECTANGLE( drect ); + DFBRegion clipped = dest; + + if (flags & (DSBLIT_ROTATE90 | DSBLIT_ROTATE270)) { + D_ASSERT( srect->w == drect->h ); + D_ASSERT( srect->h == drect->w ); + } + else { + D_ASSERT( srect->w == drect->w ); + D_ASSERT( srect->h == drect->h ); + } + + dfb_region_region_intersect( &clipped, clip ); + dfb_rectangle_from_region( drect, &clipped ); + + if (flags & DSBLIT_ROTATE90) { + srect->x += dest.y2 - clipped.y2; + srect->y += clipped.x1 - dest.x1; + srect->w = drect->h; + srect->h = drect->w; + + D_DEBUG_AT( Core_GraphicsOps, " => %4d,%4d-%4dx%4d -> %4d,%4d-%4dx%4d (90°)\n", + DFB_RECTANGLE_VALS(srect), DFB_RECTANGLE_VALS(drect) ); + } + else if (flags & DSBLIT_ROTATE180) { + srect->x += dest.x2 - clipped.x2; + srect->y += dest.y2 - clipped.y2; + srect->w = drect->w; + srect->h = drect->h; + + D_DEBUG_AT( Core_GraphicsOps, " => %4d,%4d-%4dx%4d -> %4d,%4d-%4dx%4d (180°)\n", + DFB_RECTANGLE_VALS(srect), DFB_RECTANGLE_VALS(drect) ); + } + else if (flags & DSBLIT_ROTATE270) { + srect->x += clipped.y1 - dest.y1; + srect->y += dest.x2 - clipped.x2; + srect->w = drect->h; + srect->h = drect->w; + + D_DEBUG_AT( Core_GraphicsOps, " => %4d,%4d-%4dx%4d -> %4d,%4d-%4dx%4d (270°)\n", + DFB_RECTANGLE_VALS(srect), DFB_RECTANGLE_VALS(drect) ); + } + else { + srect->x += clipped.x1 - dest.x1; + srect->y += clipped.y1 - dest.y1; + srect->w = drect->w; + srect->h = drect->h; + + D_DEBUG_AT( Core_GraphicsOps, " => %4d,%4d-%4dx%4d -> %4d,%4d-%4dx%4d\n", + DFB_RECTANGLE_VALS(srect), DFB_RECTANGLE_VALS(drect) ); + } +} + +void dfb_gfxcard_blit( DFBRectangle *rect, int dx, int dy, CardState *state ) +{ + bool hw = false; + DFBRectangle drect = { dx, dy, rect->w, rect->h }; + + if (state->blittingflags & (DSBLIT_ROTATE90 | DSBLIT_ROTATE270)) + D_UTIL_SWAP( drect.w, drect.h ); + + D_DEBUG_AT( Core_GraphicsOps, "%s( %4d,%4d-%4dx%4d -> %4d,%4d-%4dx%4d, %p )\n", + __FUNCTION__, DFB_RECTANGLE_VALS(rect), DFB_RECTANGLE_VALS(&drect), state ); + + D_ASSERT( card != NULL ); + D_ASSERT( card->shared != NULL ); + D_MAGIC_ASSERT( state, CardState ); + D_ASSERT( state->source != NULL ); + D_ASSERT( rect != NULL ); + D_ASSERT( rect->x >= 0 ); + D_ASSERT( rect->y >= 0 ); + D_ASSERT( rect->x < state->source->config.size.w ); + D_ASSERT( rect->y < state->source->config.size.h ); + D_ASSERT( rect->x + rect->w - 1 < state->source->config.size.w ); + D_ASSERT( rect->y + rect->h - 1 < state->source->config.size.h ); + + /* The state is locked during graphics operations. */ + dfb_state_lock( state ); + + /* Signal beginning of sequence of operations if not already done. */ + dfb_state_start_drawing( state, card ); + + if (!(state->render_options & DSRO_MATRIX) && + !dfb_clip_blit_precheck( &state->clip, drect.w, drect.h, drect.x, drect.y )) + { + /* no work at all */ + dfb_state_unlock( state ); + return; + } + + if (dfb_gfxcard_state_check( state, DFXL_BLIT ) && + dfb_gfxcard_state_acquire( state, DFXL_BLIT )) + { + if (!D_FLAGS_IS_SET( card->caps.flags, CCF_CLIPPING ) && + !D_FLAGS_IS_SET( card->caps.clip, DFXL_BLIT )) + clip_blit_rotated( rect, &drect, &state->clip, state->blittingflags ); + + hw = card->funcs.Blit( card->driver_data, card->device_data, rect, drect.x, drect.y ); + + dfb_gfxcard_state_release( state ); + } + + if (!hw) { + if (state->render_options & DSRO_MATRIX) { + if (state->matrix[0] < 0 || state->matrix[1] != 0 || + state->matrix[3] != 0 || state->matrix[4] < 0 || + state->matrix[6] != 0 || state->matrix[7] != 0) { + D_WARN( "rotation not yet implemented" ); + dfb_state_unlock( state ); + return; + } + + if (gAcquire( state, DFXL_STRETCHBLIT )) { + DFBRectangle drect; + int x1, y1, x2, y2; + + x1 = dx; y1 = dy; + x2 = dx+rect->w; y2 = dy+rect->h; + DFB_TRANSFORM(x1, y1, state->matrix, state->affine_matrix); + DFB_TRANSFORM(x2, y2, state->matrix, state->affine_matrix); + + drect = (DFBRectangle) { x1, y1, x2-x1, y2-y1 }; + if (dfb_clip_blit_precheck( &state->clip, + drect.w, drect.h, drect.x, drect.y )) + gStretchBlit( state, rect, &drect ); + + gRelease( state ); + } + } + else { + if (gAcquire( state, DFXL_BLIT )) { + clip_blit_rotated( rect, &drect, &state->clip, state->blittingflags ); + + gBlit( state, rect, drect.x, drect.y ); + + gRelease( state ); + } + } + } + + dfb_state_unlock( state ); +} + +void dfb_gfxcard_batchblit( DFBRectangle *rects, DFBPoint *points, + int num, CardState *state ) +{ + int i = 0; + + D_DEBUG_AT( Core_GraphicsOps, "%s( %p, %p [%d], %p )\n", __FUNCTION__, rects, points, num, state ); + + D_ASSERT( card != NULL ); + D_ASSERT( card->shared != NULL ); + D_MAGIC_ASSERT( state, CardState ); + D_ASSERT( rects != NULL ); + D_ASSERT( points != NULL ); + D_ASSERT( num > 0 ); + + /* The state is locked during graphics operations. */ + dfb_state_lock( state ); + + /* Signal beginning of sequence of operations if not already done. */ + dfb_state_start_drawing( state, card ); + + if (dfb_gfxcard_state_check( state, DFXL_BLIT ) && + dfb_gfxcard_state_acquire( state, DFXL_BLIT )) + { + for (; irender_options & DSRO_MATRIX) || + dfb_clip_blit_precheck( &state->clip, + rects[i].w, rects[i].h, + points[i].x, points[i].y )) + { + if (!D_FLAGS_IS_SET( card->caps.flags, CCF_CLIPPING ) && + !D_FLAGS_IS_SET( card->caps.clip, DFXL_BLIT )) + dfb_clip_blit( &state->clip, &rects[i], + &points[i].x, &points[i].y ); + + if (!card->funcs.Blit( card->driver_data, card->device_data, + &rects[i], points[i].x, points[i].y )) + break; + } + } + + dfb_gfxcard_state_release( state ); + } + + if (i < num) { + if (state->render_options & DSRO_MATRIX) { + if (state->matrix[0] < 0 || state->matrix[1] != 0 || + state->matrix[3] != 0 || state->matrix[4] < 0 || + state->matrix[6] != 0 || state->matrix[7] != 0) { + D_WARN( "rotation not yet implemented" ); + dfb_state_unlock( state ); + return; + } + + if (gAcquire( state, DFXL_STRETCHBLIT )) { + for (; imatrix, state->affine_matrix); + DFB_TRANSFORM(x2, y2, state->matrix, state->affine_matrix); + + drect = (DFBRectangle) { x1, y1, x2-x1, y2-y1 }; + if (dfb_clip_blit_precheck( &state->clip, + drect.w, drect.h, drect.x, drect.y )) + gStretchBlit( state, &rects[i], &drect ); + } + + gRelease( state ); + } + } + else { + if (gAcquire( state, DFXL_BLIT )) { + for (; iclip, + rects[i].w, rects[i].h, + points[i].x, points[i].y )) + { + dfb_clip_blit( &state->clip, &rects[i], + &points[i].x, &points[i].y ); + + gBlit( state, &rects[i], points[i].x, points[i].y ); + } + } + + gRelease( state ); + } + } + } + + dfb_state_unlock( state ); +} + +void dfb_gfxcard_tileblit( DFBRectangle *rect, int dx1, int dy1, int dx2, int dy2, + CardState *state ) +{ + int x, y; + int odx; + DFBRectangle srect; + DFBRegion *clip; + + D_DEBUG_AT( Core_GraphicsOps, "%s( %d,%d - %d,%d, %p )\n", __FUNCTION__, dx1, dy1, dx2, dy2, state ); + + D_ASSERT( card != NULL ); + D_ASSERT( card->shared != NULL ); + D_MAGIC_ASSERT( state, CardState ); + D_ASSERT( rect != NULL ); + + /* If called with an invalid rectangle, the algorithm goes into an + infinite loop. This should never happen but it's safer to check. */ + D_ASSERT( rect->w >= 1 ); + D_ASSERT( rect->h >= 1 ); + + /* The state is locked during graphics operations. */ + dfb_state_lock( state ); + + /* Signal beginning of sequence of operations if not already done. */ + dfb_state_start_drawing( state, card ); + + clip = &state->clip; + + /* Check if anything is drawn at all. */ + if (!(state->render_options & DSRO_MATRIX) && + !dfb_clip_blit_precheck( clip, dx2-dx1+1, dy2-dy1+1, dx1, dy1 )) { + dfb_state_unlock( state ); + return; + } + + /* Remove clipped tiles. */ + if (dx1 < clip->x1) { + int outer = clip->x1 - dx1; + + dx1 += outer - (outer % rect->w); + } + + if (dy1 < clip->y1) { + int outer = clip->y1 - dy1; + + dy1 += outer - (outer % rect->h); + } + + if (dx2 > clip->x2) { + int outer = clip->x2 - dx2; + + dx2 -= outer - (outer % rect->w); + } + + if (dy2 > clip->y2) { + int outer = clip->y2 - dy2; + + dy2 -= outer - (outer % rect->h); + } + + odx = dx1; + + if (dfb_gfxcard_state_check( state, DFXL_BLIT ) && + dfb_gfxcard_state_acquire( state, DFXL_BLIT )) { + bool hw = true; + + for (; dy1 < dy2; dy1 += rect->h) { + for (; dx1 < dx2; dx1 += rect->w) { + + if (!dfb_clip_blit_precheck( clip, rect->w, rect->h, dx1, dy1 )) + continue; + + x = dx1; + y = dy1; + srect = *rect; + + if (!D_FLAGS_IS_SET( card->caps.flags, CCF_CLIPPING ) && + !D_FLAGS_IS_SET( card->caps.clip, DFXL_BLIT )) + dfb_clip_blit( clip, &srect, &x, &y ); + + hw = card->funcs.Blit( card->driver_data, + card->device_data, &srect, x, y ); + if (!hw) + break; + } + if (!hw) + break; + dx1 = odx; + } + + dfb_gfxcard_state_release( state ); + } + + if (dy1 < dy2) { + if (state->render_options & DSRO_MATRIX) { + if (state->matrix[0] < 0 || state->matrix[1] != 0 || + state->matrix[3] != 0 || state->matrix[4] < 0 || + state->matrix[6] != 0 || state->matrix[7] != 0) { + D_WARN( "rotation not yet implemented" ); + dfb_state_unlock( state ); + return; + } + + if (gAcquire( state, DFXL_STRETCHBLIT )) { + for (; dy1 < dy2; dy1 += rect->h) { + for (; dx1 < dx2; dx1 += rect->w) { + DFBRectangle drect; + int x1, y1, x2, y2; + + x1 = dx1; y1 = dy1; + x2 = dx1+rect->w; y2 = dy1+rect->h; + DFB_TRANSFORM(x1, y1, state->matrix, state->affine_matrix); + DFB_TRANSFORM(x2, y2, state->matrix, state->affine_matrix); + + drect = (DFBRectangle) { x1, y1, x2-x1, y2-y1 }; + if (dfb_clip_blit_precheck( &state->clip, + drect.w, drect.h, drect.x, drect.y )) + gStretchBlit( state, rect, &drect ); + } + dx1 = odx; + } + + gRelease( state ); + } + } + else { + if (gAcquire( state, DFXL_BLIT )) { + for (; dy1 < dy2; dy1 += rect->h) { + for (; dx1 < dx2; dx1 += rect->w) { + + if (!dfb_clip_blit_precheck( clip, rect->w, rect->h, dx1, dy1 )) + continue; + + x = dx1; + y = dy1; + srect = *rect; + + dfb_clip_blit( clip, &srect, &x, &y ); + + gBlit( state, &srect, x, y ); + } + dx1 = odx; + } + + gRelease( state ); + } + } + } + + dfb_state_unlock( state ); +} + +void dfb_gfxcard_stretchblit( DFBRectangle *srect, DFBRectangle *drect, + CardState *state ) +{ + bool hw = false; + + D_ASSERT( card != NULL ); + D_ASSERT( card->shared != NULL ); + D_MAGIC_ASSERT( state, CardState ); + D_ASSERT( srect != NULL ); + D_ASSERT( drect != NULL ); + + D_DEBUG_AT( Core_GraphicsOps, "%s( %d,%d - %dx%d -> %d,%d - %dx%d, %p )\n", + __FUNCTION__, DFB_RECTANGLE_VALS(srect), DFB_RECTANGLE_VALS(drect), state ); + + if (state->blittingflags & (DSBLIT_ROTATE90 | DSBLIT_ROTATE270)) { + if (srect->w == drect->h && srect->h == drect->w) { + dfb_gfxcard_blit( srect, drect->x, drect->y, state ); + return; + } + } + else { + if (srect->w == drect->w && srect->h == drect->h) { + dfb_gfxcard_blit( srect, drect->x, drect->y, state ); + return; + } + } + + /* The state is locked during graphics operations. */ + dfb_state_lock( state ); + + /* Signal beginning of sequence of operations if not already done. */ + dfb_state_start_drawing( state, card ); + + if (!(state->render_options & DSRO_MATRIX) && + !dfb_clip_blit_precheck( &state->clip, drect->w, drect->h, + drect->x, drect->y )) + { + dfb_state_unlock( state ); + return; + } + + if (dfb_gfxcard_state_check( state, DFXL_STRETCHBLIT ) && + dfb_gfxcard_state_acquire( state, DFXL_STRETCHBLIT )) + { + if (!D_FLAGS_IS_SET( card->caps.flags, CCF_CLIPPING ) && + !D_FLAGS_IS_SET( card->caps.clip, DFXL_STRETCHBLIT )) + dfb_clip_stretchblit( &state->clip, srect, drect ); + + hw = card->funcs.StretchBlit( card->driver_data, card->device_data, srect, drect ); + + dfb_gfxcard_state_release( state ); + } + + if (!hw) { + if (state->render_options & DSRO_MATRIX) { + int x1, y1, x2, y2; + + if (state->matrix[0] < 0 || state->matrix[1] != 0 || + state->matrix[3] != 0 || state->matrix[4] < 0 || + state->matrix[6] != 0 || state->matrix[7] != 0) { + D_WARN( "rotation not yet implemented" ); + dfb_state_unlock( state ); + return; + } + + x1 = drect->x; y1 = drect->y; + x2 = x1+drect->w; y2 = y1+drect->h; + DFB_TRANSFORM(x1, y1, state->matrix, state->affine_matrix); + DFB_TRANSFORM(x2, y2, state->matrix, state->affine_matrix); + drect->x = x1; drect->y = y1; + drect->w = x2-x1; drect->h = y2-y1; + + if (!dfb_clip_blit_precheck( &state->clip, + drect->w, drect->h, drect->x, drect->y )) { + dfb_state_unlock( state ); + return; + } + } + + if (gAcquire( state, DFXL_STRETCHBLIT )) { + /* Clipping is performed in the following function. */ + gStretchBlit( state, srect, drect ); + gRelease( state ); + } + } + + dfb_state_unlock( state ); +} + +void dfb_gfxcard_texture_triangles( DFBVertex *vertices, int num, + DFBTriangleFormation formation, + CardState *state ) +{ + bool hw = false; + + D_DEBUG_AT( Core_GraphicsOps, "%s( %p [%d], %s, %p )\n", __FUNCTION__, vertices, num, + (formation == DTTF_LIST) ? "LIST" : + (formation == DTTF_STRIP) ? "STRIP" : + (formation == DTTF_FAN) ? "FAN" : "unknown formation", state ); + + D_ASSERT( card != NULL ); + D_ASSERT( card->shared != NULL ); + D_ASSERT( vertices != NULL ); + D_ASSERT( num >= 3 ); + D_MAGIC_ASSERT( state, CardState ); + + /* The state is locked during graphics operations. */ + dfb_state_lock( state ); + + /* Signal beginning of sequence of operations if not already done. */ + dfb_state_start_drawing( state, card ); + + if ((D_FLAGS_IS_SET( card->caps.flags, CCF_CLIPPING ) || D_FLAGS_IS_SET( card->caps.clip, DFXL_TEXTRIANGLES )) && + dfb_gfxcard_state_check( state, DFXL_TEXTRIANGLES ) && + dfb_gfxcard_state_acquire( state, DFXL_TEXTRIANGLES )) + { + hw = card->funcs.TextureTriangles( card->driver_data, + card->device_data, + vertices, num, formation ); + + dfb_gfxcard_state_release( state ); + } + + if (!hw) { + if (gAcquire( state, DFXL_TEXTRIANGLES )) { + //dfb_clip_stretchblit( &state->clip, srect, drect ); + //gStretchBlit( state, srect, drect ); + gRelease( state ); + } + } + + dfb_state_unlock( state ); +} + +void +dfb_gfxcard_drawstring( const u8 *text, int bytes, + DFBTextEncodingID encoding, int x, int y, + CoreFont *font, unsigned int layers, CardState *state ) +{ + unsigned int prev = 0; + unsigned int indices[bytes]; + int i, l, num; + int kern_x; + int kern_y; + CoreSurface *surface; + DFBSurfaceBlittingFlags orig_flags; + DFBSurfaceBlendFunction orig_srcblend; + DFBSurfaceBlendFunction orig_dstblend; + DFBPoint points[50]; + DFBRectangle rects[50]; + int num_blits = 0; + int ox = x; + int oy = y; + + if (encoding == DTEID_UTF8) + D_DEBUG_AT( Core_GraphicsOps, "%s( '%s' [%d], %d,%d, %p, %p )\n", + __FUNCTION__, text, bytes, x, y, font, state ); + else + D_DEBUG_AT( Core_GraphicsOps, "%s( %p [%d], %d, %d,%d, %p, %p )\n", + __FUNCTION__, text, bytes, encoding, x, y, font, state ); + + D_ASSERT( card != NULL ); + D_ASSERT( card->shared != NULL ); + D_MAGIC_ASSERT( state, CardState ); + D_ASSERT( text != NULL ); + D_ASSERT( bytes > 0 ); + D_ASSERT( font != NULL ); + + surface = state->destination; + D_MAGIC_ASSERT( surface, CoreSurface ); + + /* simple prechecks */ + if (!(state->render_options & DSRO_MATRIX) && + (x > state->clip.x2 || y > state->clip.y2 || + y + font->ascender - font->descender <= state->clip.y1)) { + return; + } + + dfb_font_lock( font ); + + /* Decode string to character indices. */ + dfb_font_decode_text( font, encoding, text, bytes, indices, &num ); + + orig_flags = state->blittingflags; + orig_srcblend = state->src_blend; + orig_dstblend = state->dst_blend; + + if (orig_flags != DSBLIT_INDEX_TRANSLATION) { + DFBSurfaceBlittingFlags flags = font->blittingflags; + + /* additional blending? */ + if ((state->drawingflags & DSDRAW_BLEND) && (state->color.a != 0xff)) + flags |= DSBLIT_BLEND_COLORALPHA; + + if (state->drawingflags & DSDRAW_DST_COLORKEY) + flags |= DSBLIT_DST_COLORKEY; + + if (state->drawingflags & DSDRAW_XOR) + flags |= DSBLIT_XOR; + + if (flags & (DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_BLEND_COLORALPHA)) { + /* Porter/Duff SRC_OVER composition */ + if ((DFB_PIXELFORMAT_HAS_ALPHA( surface->config.format ) && (surface->config.caps & DSCAPS_PREMULTIPLIED)) + || + (font->surface_caps & DSCAPS_PREMULTIPLIED)) + { + if (font->surface_caps & DSCAPS_PREMULTIPLIED) { + if (flags & DSBLIT_BLEND_COLORALPHA) + flags |= DSBLIT_SRC_PREMULTCOLOR; + } + else + flags |= DSBLIT_SRC_PREMULTIPLY; + + dfb_state_set_src_blend( state, DSBF_ONE ); + } + else + dfb_state_set_src_blend( state, DSBF_SRCALPHA ); + + dfb_state_set_dst_blend( state, DSBF_INVSRCALPHA ); + } + + dfb_state_set_blitting_flags( state, flags ); + } + + for (l=layers-1; l>=0; l--) { + x = ox; + y = oy; + + if (layers > 1) { + if (num_blits) { + dfb_gfxcard_batchblit( rects, points, num_blits, state ); + num_blits = 0; + } + + dfb_state_set_color( state, &state->colors[l] ); + } + + /* blit glyphs */ + for (i=0; i dfb_font_get_glyph_data() failed! [%s]\n", DirectFBErrorString( ret ) ); + prev = current; + continue; + } + + if (prev && font->GetKerning && font->GetKerning( font, prev, current, &kern_x, &kern_y) == DFB_OK) { + x += kern_x; + y += kern_y; + } + + if (glyph->width) { + if (glyph->surface != state->source || num_blits == D_ARRAY_SIZE(rects)) { + if (num_blits) { + dfb_gfxcard_batchblit( rects, points, num_blits, state ); + num_blits = 0; + } + + if (glyph->surface != state->source) + dfb_state_set_source( state, glyph->surface ); + } + + points[num_blits] = (DFBPoint){ x + glyph->left, y + glyph->top }; + rects[num_blits] = (DFBRectangle){ glyph->start, 0, glyph->width, glyph->height }; + + num_blits++; + } + + x += glyph->xadvance; + y += glyph->yadvance; + prev = current; + } + } + + if (num_blits) { + dfb_gfxcard_batchblit( rects, points, num_blits, state ); + num_blits = 0; + } + + dfb_font_unlock( font ); + + + if (orig_flags != DSBLIT_INDEX_TRANSLATION) { + dfb_state_set_blitting_flags( state, orig_flags ); + dfb_state_set_src_blend( state, orig_srcblend ); + dfb_state_set_dst_blend( state, orig_dstblend ); + } +} + +void dfb_gfxcard_drawglyph( CoreGlyphData **glyph, int x, int y, + CoreFont *font, unsigned int layers, CardState *state ) +{ + int l; + CoreSurface *surface; + DFBSurfaceBlittingFlags orig_flags; + DFBSurfaceBlendFunction orig_srcblend; + DFBSurfaceBlendFunction orig_dstblend; + + D_DEBUG_AT( Core_GraphicsOps, "%s( %u, %d,%d, %p, %p )\n", + __FUNCTION__, index, x, y, font, state ); + + D_ASSERT( card != NULL ); + D_ASSERT( card->shared != NULL ); + D_MAGIC_ASSERT( state, CardState ); + D_ASSERT( font != NULL ); + + surface = state->destination; + D_MAGIC_ASSERT( surface, CoreSurface ); + + orig_flags = state->blittingflags; + orig_srcblend = state->src_blend; + orig_dstblend = state->dst_blend; + + if (orig_flags != DSBLIT_INDEX_TRANSLATION) { + DFBSurfaceBlittingFlags flags = font->blittingflags; + + /* additional blending? */ + if ((state->drawingflags & DSDRAW_BLEND) && (state->color.a != 0xff)) + flags |= DSBLIT_BLEND_COLORALPHA; + + if (state->drawingflags & DSDRAW_DST_COLORKEY) + flags |= DSBLIT_DST_COLORKEY; + + if (state->drawingflags & DSDRAW_XOR) + flags |= DSBLIT_XOR; + + if (flags & (DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_BLEND_COLORALPHA)) { + /* Porter/Duff SRC_OVER composition */ + if ((DFB_PIXELFORMAT_HAS_ALPHA( surface->config.format ) && (surface->config.caps & DSCAPS_PREMULTIPLIED)) + || + (font->surface_caps & DSCAPS_PREMULTIPLIED)) + { + if (font->surface_caps & DSCAPS_PREMULTIPLIED) { + if (flags & DSBLIT_BLEND_COLORALPHA) + flags |= DSBLIT_SRC_PREMULTCOLOR; + } + else + flags |= DSBLIT_SRC_PREMULTIPLY; + + dfb_state_set_src_blend( state, DSBF_ONE ); + } + else + dfb_state_set_src_blend( state, DSBF_SRCALPHA ); + + dfb_state_set_dst_blend( state, DSBF_INVSRCALPHA ); + } + + dfb_state_set_blitting_flags( state, flags ); + } + + for (l=layers-1; l>=0; l--) { + if (layers > 1) + dfb_state_set_color( state, &state->colors[l] ); + + /* blit glyph */ + if (glyph[l]->width) { + DFBRectangle rect = { glyph[l]->start, 0, glyph[l]->width, glyph[l]->height }; + + dfb_state_set_source( state, glyph[l]->surface ); + + dfb_gfxcard_blit( &rect, x + glyph[l]->left, y + glyph[l]->top, state ); + } + } + + if (orig_flags != DSBLIT_INDEX_TRANSLATION) { + dfb_state_set_blitting_flags( state, orig_flags ); + dfb_state_set_src_blend( state, orig_srcblend ); + dfb_state_set_dst_blend( state, orig_dstblend ); + } +} + +bool dfb_gfxcard_drawstring_check_state( CoreFont *font, CardState *state ) +{ + int i; + bool result; + CoreSurface *surface; + DFBSurfaceBlittingFlags orig_flags; + DFBSurfaceBlendFunction orig_srcblend; + DFBSurfaceBlendFunction orig_dstblend; + CoreGlyphData *data = NULL; + + D_ASSERT( card != NULL ); + D_ASSERT( card->shared != NULL ); + D_MAGIC_ASSERT( state, CardState ); + D_ASSERT( font != NULL ); + + D_DEBUG_AT( Core_GfxState, "%s( %p, %p )\n", __FUNCTION__, font, state ); + + surface = state->destination; + D_MAGIC_ASSERT( surface, CoreSurface ); + + dfb_font_lock( font ); + + for (i=0; i<128; i++) { + if (dfb_font_get_glyph_data (font, i, 0, &data) == DFB_OK) + break; + } + + if (!data) { + D_DEBUG_AT( Core_GfxState, " -> No font data!\n" ); + dfb_font_unlock( font ); + return; + } + + orig_flags = state->blittingflags; + orig_srcblend = state->src_blend; + orig_dstblend = state->dst_blend; + + if (orig_flags != DSBLIT_INDEX_TRANSLATION) { + DFBSurfaceBlittingFlags flags = font->blittingflags; + + /* additional blending? */ + if ((state->drawingflags & DSDRAW_BLEND) && (state->color.a != 0xff)) + flags |= DSBLIT_BLEND_COLORALPHA; + + if (state->drawingflags & DSDRAW_DST_COLORKEY) + flags |= DSBLIT_DST_COLORKEY; + + if (state->drawingflags & DSDRAW_XOR) + flags |= DSBLIT_XOR; + + if (flags & (DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_BLEND_COLORALPHA)) { + /* Porter/Duff SRC_OVER composition */ + if ((DFB_PIXELFORMAT_HAS_ALPHA( surface->config.format ) && (surface->config.caps & DSCAPS_PREMULTIPLIED)) + || + (font->surface_caps & DSCAPS_PREMULTIPLIED)) + { + if (font->surface_caps & DSCAPS_PREMULTIPLIED) { + if (flags & DSBLIT_BLEND_COLORALPHA) + flags |= DSBLIT_SRC_PREMULTCOLOR; + } + else + flags |= DSBLIT_SRC_PREMULTIPLY; + + dfb_state_set_src_blend( state, DSBF_ONE ); + } + else + dfb_state_set_src_blend( state, DSBF_SRCALPHA ); + + dfb_state_set_dst_blend( state, DSBF_INVSRCALPHA ); + } + + dfb_state_set_blitting_flags( state, flags ); + } + + /* set the source */ + dfb_state_set_source( state, data->surface ); + + dfb_state_lock( state ); + + /* check for blitting and report */ + result = dfb_gfxcard_state_check( state, DFXL_BLIT ); + + dfb_state_unlock( state ); + + dfb_font_unlock( font ); + + if (orig_flags != DSBLIT_INDEX_TRANSLATION) { + dfb_state_set_blitting_flags( state, orig_flags ); + dfb_state_set_src_blend( state, orig_srcblend ); + dfb_state_set_dst_blend( state, orig_dstblend ); + } + + return result; +} + +DFBResult dfb_gfxcard_sync( void ) +{ + DFBResult ret; + + D_ASSUME( card != NULL ); + + if (!card) + return DFB_OK; + + ret = dfb_gfxcard_lock( GDLF_SYNC ); + if (ret) + return ret; + + dfb_gfxcard_unlock(); + + return DFB_OK; +} + +void dfb_gfxcard_invalidate_state( void ) +{ + D_ASSERT( card != NULL ); + D_ASSERT( card->shared != NULL ); + + card->shared->state = NULL; +} + +DFBResult dfb_gfxcard_wait_serial( const CoreGraphicsSerial *serial ) +{ + DFBResult ret; + + D_ASSERT( serial != NULL ); + D_ASSUME( card != NULL ); + + if (!card) + return DFB_OK; + + D_ASSERT( card->shared != NULL ); + + ret = dfb_gfxcard_lock( GDLF_NONE ); + if (ret) + return ret; + +/* FIXME_SC_2 if (card->funcs.WaitSerial) + ret = card->funcs.WaitSerial( card->driver_data, card->device_data, serial ); + else*/ if (card->funcs.EngineSync) + ret = card->funcs.EngineSync( card->driver_data, card->device_data ); + + if (ret) { + if (card->funcs.EngineReset) + card->funcs.EngineReset( card->driver_data, card->device_data ); + + card->shared->state = NULL; + } + + dfb_gfxcard_unlock(); + + return ret; +} + +void dfb_gfxcard_flush_texture_cache( void ) +{ + D_ASSUME( card != NULL ); + + if (card && card->funcs.FlushTextureCache) + card->funcs.FlushTextureCache( card->driver_data, card->device_data ); +} + +void dfb_gfxcard_flush_read_cache( void ) +{ + D_ASSUME( card != NULL ); + + if (card && card->funcs.FlushReadCache) + card->funcs.FlushReadCache( card->driver_data, card->device_data ); +} + +void dfb_gfxcard_after_set_var( void ) +{ + D_ASSUME( card != NULL ); + + if (card && card->funcs.AfterSetVar) + card->funcs.AfterSetVar( card->driver_data, card->device_data ); +} + +void dfb_gfxcard_surface_enter( CoreSurfaceBuffer *buffer, DFBSurfaceLockFlags flags ) +{ + D_ASSUME( card != NULL ); + + if (card && card->funcs.SurfaceEnter) + card->funcs.SurfaceEnter( card->driver_data, card->device_data, buffer, flags ); +} + +void dfb_gfxcard_surface_leave( CoreSurfaceBuffer *buffer ) +{ + D_ASSUME( card != NULL ); + + if (card && card->funcs.SurfaceLeave) + card->funcs.SurfaceLeave( card->driver_data, card->device_data, buffer ); +} + +DFBResult +dfb_gfxcard_adjust_heap_offset( int offset ) +{ + D_ASSERT( card != NULL ); + D_ASSERT( card->shared != NULL ); + +//FIXME_SMAN return dfb_surfacemanager_adjust_heap_offset( card->shared->surface_manager, offset ); + return DFB_OK; +} + +void +dfb_gfxcard_get_capabilities( CardCapabilities *ret_caps ) +{ + D_ASSERT( card != NULL ); + + D_ASSERT( ret_caps != NULL ); + + *ret_caps = card->caps; +} + +void +dfb_gfxcard_get_device_info( GraphicsDeviceInfo *ret_info ) +{ + D_ASSERT( card != NULL ); + D_ASSERT( card->shared != NULL ); + + D_ASSERT( ret_info != NULL ); + + *ret_info = card->shared->device_info; +} + +void +dfb_gfxcard_get_driver_info( GraphicsDriverInfo *ret_info ) +{ + D_ASSERT( card != NULL ); + D_ASSERT( card->shared != NULL ); + + D_ASSERT( ret_info != NULL ); + + *ret_info = card->shared->driver_info; +} + + +int +dfb_gfxcard_reserve_memory( CoreGraphicsDevice *device, unsigned int size ) +{ + DFBGraphicsCoreShared *shared; + + D_ASSERT( device != NULL ); + D_ASSERT( device->shared != NULL ); + + shared = device->shared; + + if (shared->device_info.limits.surface_byteoffset_alignment) { + size += shared->device_info.limits.surface_byteoffset_alignment - 1; + size -= (size % shared->device_info.limits.surface_byteoffset_alignment); + } + else + D_WARN( "no alignment specified yet?" ); + + if (shared->videoram_length < size) { + D_WARN( "not enough video memory (%u < %u)", shared->videoram_length, size ); + return -1; + } + + shared->videoram_length -= size; + + return shared->videoram_length; +} + +int +dfb_gfxcard_reserve_auxmemory( CoreGraphicsDevice *device, unsigned int size ) +{ + DFBGraphicsCoreShared *shared; + int offset; + + D_ASSERT( device != NULL ); + D_ASSERT( device->shared != NULL ); + + shared = device->shared; + + /* Reserve memory at the beginning of the aperture + * to prevent overflows on DMA buffers. */ + + offset = shared->auxram_offset; + + if (shared->auxram_length < (offset + size)) + return -1; + + shared->auxram_offset += size; + + return offset; +} + +unsigned int +dfb_gfxcard_memory_length( void ) +{ + D_ASSERT( card != NULL ); + D_ASSERT( card->shared != NULL ); + + return card->shared->videoram_length; +} + +unsigned int +dfb_gfxcard_auxmemory_length( void ) +{ + D_ASSERT( card != NULL ); + D_ASSERT( card->shared != NULL ); + + return card->shared->auxram_length; +} + +volatile void * +dfb_gfxcard_map_mmio( CoreGraphicsDevice *device, + unsigned int offset, + int length ) +{ + return dfb_system_map_mmio( offset, length ); +} + +void +dfb_gfxcard_unmap_mmio( CoreGraphicsDevice *device, + volatile void *addr, + int length ) +{ + dfb_system_unmap_mmio( addr, length ); +} + +int +dfb_gfxcard_get_accelerator( CoreGraphicsDevice *device ) +{ + return dfb_system_get_accelerator(); +} + +void +dfb_gfxcard_get_limits( CoreGraphicsDevice *device, + CardLimitations *ret_limits ) +{ + D_ASSERT( device != NULL ); + D_ASSERT( ret_limits != NULL ); + + if (!device) + device = card; + + *ret_limits = device->limits; +} + +void +dfb_gfxcard_calc_buffer_size( CoreGraphicsDevice *device, + CoreSurfaceBuffer *buffer, + int *ret_pitch, + int *ret_length ) +{ + int pitch; + int length; + CoreSurface *surface; + + D_ASSERT( device != NULL ); + D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); + + surface = buffer->surface; + D_MAGIC_ASSERT( surface, CoreSurface ); + + /* calculate the required length depending on limitations */ + pitch = MAX( surface->config.size.w, surface->config.min_size.w ); + + if (pitch < device->limits.surface_max_power_of_two_pixelpitch && + surface->config.size.h < device->limits.surface_max_power_of_two_height) + pitch = 1 << direct_log2( pitch ); + + if (device->limits.surface_pixelpitch_alignment > 1) { + pitch += device->limits.surface_pixelpitch_alignment - 1; + pitch -= pitch % device->limits.surface_pixelpitch_alignment; + } + + pitch = DFB_BYTES_PER_LINE( buffer->format, pitch ); + + if (pitch < device->limits.surface_max_power_of_two_bytepitch && + surface->config.size.h < device->limits.surface_max_power_of_two_height) + pitch = 1 << direct_log2( pitch ); + + if (device->limits.surface_bytepitch_alignment > 1) { + pitch += device->limits.surface_bytepitch_alignment - 1; + pitch -= pitch % device->limits.surface_bytepitch_alignment; + } + + length = DFB_PLANE_MULTIPLY( buffer->format, + MAX( surface->config.size.h, surface->config.min_size.h ) * pitch ); + + /* Add extra space for optimized routines which are now allowed to overrun, e.g. prefetching. */ + length += 16; + + if (device->limits.surface_byteoffset_alignment > 1) { + length += device->limits.surface_byteoffset_alignment - 1; + length -= length % device->limits.surface_byteoffset_alignment; + } + + if (ret_pitch) + *ret_pitch = pitch; + + if (ret_length) + *ret_length = length; +} + +unsigned long +dfb_gfxcard_memory_physical( CoreGraphicsDevice *device, + unsigned int offset ) +{ + return dfb_system_video_memory_physical( offset ); +} + +void * +dfb_gfxcard_memory_virtual( CoreGraphicsDevice *device, + unsigned int offset ) +{ + return dfb_system_video_memory_virtual( offset ); +} + +unsigned long +dfb_gfxcard_auxmemory_physical( CoreGraphicsDevice *device, + unsigned int offset ) +{ + return dfb_system_aux_memory_physical( offset ); +} + +void * +dfb_gfxcard_auxmemory_virtual( CoreGraphicsDevice *device, + unsigned int offset ) +{ + return dfb_system_aux_memory_virtual( offset ); +} + +void * +dfb_gfxcard_get_device_data( void ) +{ + D_ASSERT( card != NULL ); + D_ASSERT( card->shared != NULL ); + + return card->shared->device_data; +} + +void * +dfb_gfxcard_get_driver_data( void ) +{ + D_ASSERT( card != NULL ); + + return card->driver_data; +} + +CoreGraphicsDevice * +dfb_gfxcard_get_primary( void ) +{ + return card; +} + + +/** internal **/ + +/* + * loads/probes/unloads one driver module after another until a suitable + * driver is found and returns its symlinked functions + */ +static void dfb_gfxcard_find_driver( CoreDFB *core ) +{ + DirectLink *link; + FusionSHMPoolShared *pool = dfb_core_shmpool( core ); + + direct_list_foreach (link, dfb_graphics_drivers.entries) { + DirectModuleEntry *module = (DirectModuleEntry*) link; + + const GraphicsDriverFuncs *funcs = direct_module_ref( module ); + + if (!funcs) + continue; + + if (!card->module && funcs->Probe( card )) { + funcs->GetDriverInfo( card, &card->shared->driver_info ); + + card->module = module; + card->driver_funcs = funcs; + + card->shared->module_name = SHSTRDUP( pool, module->name ); + } + else + direct_module_unref( module ); + } +} + +/* + * loads the driver module used by the session + */ +static void dfb_gfxcard_load_driver( void ) +{ + DirectLink *link; + + if (!card->shared->module_name) + return; + + direct_list_foreach (link, dfb_graphics_drivers.entries) { + DirectModuleEntry *module = (DirectModuleEntry*) link; + + const GraphicsDriverFuncs *funcs = direct_module_ref( module ); + + if (!funcs) + continue; + + if (!card->module && + !strcmp( module->name, card->shared->module_name )) + { + card->module = module; + card->driver_funcs = funcs; + } + else + direct_module_unref( module ); + } +} + diff --git a/Source/DirectFB/src/core/gfxcard.h b/Source/DirectFB/src/core/gfxcard.h new file mode 100755 index 0000000..6e723d0 --- /dev/null +++ b/Source/DirectFB/src/core/gfxcard.h @@ -0,0 +1,470 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __GFXCARD_H__ +#define __GFXCARD_H__ + +#include + +#include + +#include + +#include +#include + + +typedef enum { + CCF_CLIPPING = 0x00000001, + CCF_NOTRIEMU = 0x00000002, + CCF_READSYSMEM = 0x00000004, + /* CCF_WRITESYSMEM ?! */ + CCF_AUXMEMORY = 0x00000010, + CCF_RENDEROPTS = 0x00000020 +} CardCapabilitiesFlags; + +struct __DFB_CoreGraphicsSerial { + unsigned int serial; + unsigned int generation; +}; + +typedef struct { + CardCapabilitiesFlags flags; + + DFBAccelerationMask accel; + DFBSurfaceBlittingFlags blitting; + DFBSurfaceDrawingFlags drawing; + DFBAccelerationMask clip; +} CardCapabilities; + +typedef struct { + unsigned int surface_byteoffset_alignment; + unsigned int surface_pixelpitch_alignment; + unsigned int surface_bytepitch_alignment; + + unsigned int surface_max_power_of_two_pixelpitch; + unsigned int surface_max_power_of_two_bytepitch; + unsigned int surface_max_power_of_two_height; + + DFBDimension dst_min; + DFBDimension dst_max; + DFBDimension src_min; + DFBDimension src_max; +} CardLimitations; + +DECLARE_MODULE_DIRECTORY( dfb_graphics_drivers ); + +/* + * Increase this number when changes result in binary incompatibility! + */ +#define DFB_GRAPHICS_DRIVER_ABI_VERSION 34 + +#define DFB_GRAPHICS_DRIVER_INFO_NAME_LENGTH 40 +#define DFB_GRAPHICS_DRIVER_INFO_VENDOR_LENGTH 60 +#define DFB_GRAPHICS_DRIVER_INFO_URL_LENGTH 100 +#define DFB_GRAPHICS_DRIVER_INFO_LICENSE_LENGTH 40 + +#define DFB_GRAPHICS_DEVICE_INFO_NAME_LENGTH 48 +#define DFB_GRAPHICS_DEVICE_INFO_VENDOR_LENGTH 64 + + +typedef struct { + int major; /* major version */ + int minor; /* minor version */ +} GraphicsDriverVersion; /* major.minor, e.g. 0.1 */ + +typedef struct { + GraphicsDriverVersion version; + + char name[DFB_GRAPHICS_DRIVER_INFO_NAME_LENGTH]; + /* Name of driver, e.g. 'Matrox Driver' */ + + char vendor[DFB_GRAPHICS_DRIVER_INFO_VENDOR_LENGTH]; + /* Vendor (or author) of the driver, + e.g. 'directfb.org' or 'Denis Oliver Kropp' */ + + char url[DFB_GRAPHICS_DRIVER_INFO_URL_LENGTH]; + /* URL for driver updates, + e.g. 'http://www.directfb.org/' */ + + char license[DFB_GRAPHICS_DRIVER_INFO_LICENSE_LENGTH]; + /* License, e.g. 'LGPL' or 'proprietary' */ + + unsigned int driver_data_size; + unsigned int device_data_size; +} GraphicsDriverInfo; + +typedef struct { + char name[DFB_GRAPHICS_DEVICE_INFO_NAME_LENGTH]; + /* Device name, e.g. 'G400' */ + + char vendor[DFB_GRAPHICS_DEVICE_INFO_VENDOR_LENGTH]; + /* Vendor of the device, + e.g. 'Matrox' or 'ATI' */ + + /* hardware acceleration capabilities */ + CardCapabilities caps; + + /* hardware limitations */ + CardLimitations limits; +} GraphicsDeviceInfo; + +typedef struct _GraphicsDeviceFuncs { + /* + * function that is called after variable screeninfo is changed + * (used for buggy fbdev drivers, that reinitialize something when + * calling FBIO_PUT_VSCREENINFO) + */ + void (*AfterSetVar)( void *driver_data, void *device_data ); + + /* + * Called after driver->InitDevice() and during dfb_gfxcard_unlock( true ). + * The driver should do the one time initialization of the engine, + * e.g. writing some registers that are supposed to have a fixed value. + * + * This happens after mode switching or after returning from + * OpenGL state (e.g. DRI driver). + */ + void (*EngineReset)( void *driver_data, void *device_data ); + + /* + * Makes sure that graphics hardware has finished all operations. + * + * This method is called before the CPU accesses a surface' buffer + * that had been written to by the hardware after this method has been + * called the last time. + * + * It's also called before entering the OpenGL state (e.g. DRI driver). + */ + DFBResult (*EngineSync)( void *driver_data, void *device_data ); + + /* + * Called during dfb_gfxcard_lock() to notify the driver that + * the current rendering state is no longer valid. + */ + void (*InvalidateState)( void *driver_data, void *device_data ); + + /* + * after the video memory has been written to by the CPU (e.g. modification + * of a texture) make sure the accelerator won't use cached texture data + */ + void (*FlushTextureCache)( void *driver_data, void *device_data ); + + /* + * After the video memory has been written to by the accelerator + * make sure the CPU won't read back cached data. + */ + void (*FlushReadCache)( void *driver_data, void *device_data ); + + /* + * Called before a software access to a video surface buffer. + */ + void (*SurfaceEnter)( void *driver_data, void *device_data, + CoreSurfaceBuffer *buffer, DFBSurfaceLockFlags flags ); + + /* + * Called after a software access to a video surface buffer. + */ + void (*SurfaceLeave)( void *driver_data, void *device_data, CoreSurfaceBuffer *buffer ); + + /* + * Return the serial of the last (queued) operation. + * + * The serial is used to wait for finishing a specific graphics + * operation instead of the whole engine being idle. + */ + void (*GetSerial)( void *driver_data, void *device_data, CoreGraphicsSerial *serial ); + + /* + * Makes sure that graphics hardware has finished the specified operation. + */ + DFBResult (*WaitSerial)( void *driver_data, void *device_data, const CoreGraphicsSerial *serial ); + + /* + * emit any buffered commands, i.e. trigger processing + */ + void (*EmitCommands) ( void *driver_data, void *device_data ); + + /* + * Check if the function 'accel' can be accelerated with the 'state'. + * If that's true, the function sets the 'accel' bit in 'state->accel'. + * Otherwise the function just returns, no need to clear the bit. + */ + void (*CheckState)( void *driver_data, void *device_data, + CardState *state, DFBAccelerationMask accel ); + + /* + * Program card for execution of the function 'accel' with the 'state'. + * 'state->modified' contains information about changed entries. + * This function has to set at least 'accel' in 'state->set'. + * The driver should remember 'state->modified' and clear it. + * The driver may modify 'funcs' depending on 'state' settings. + */ + void (*SetState) ( void *driver_data, void *device_data, + struct _GraphicsDeviceFuncs *funcs, + CardState *state, DFBAccelerationMask accel ); + + /* + * drawing functions + */ + bool (*FillRectangle) ( void *driver_data, void *device_data, + DFBRectangle *rect ); + + bool (*DrawRectangle) ( void *driver_data, void *device_data, + DFBRectangle *rect ); + + bool (*DrawLine) ( void *driver_data, void *device_data, + DFBRegion *line ); + + bool (*FillTriangle) ( void *driver_data, void *device_data, + DFBTriangle *tri ); + + /* + * blitting functions + */ + bool (*Blit) ( void *driver_data, void *device_data, + DFBRectangle *rect, int dx, int dy ); + + bool (*StretchBlit) ( void *driver_data, void *device_data, + DFBRectangle *srect, DFBRectangle *drect ); + + bool (*TextureTriangles)( void *driver_data, void *device_data, + DFBVertex *vertices, int num, + DFBTriangleFormation formation ); + + /* + * Signal beginning of a sequence of operations using this state. + * Any number of states can be 'drawing'. + */ + void (*StartDrawing)( void *driver_data, void *device_data, CardState *state ); + + /* + * Signal end of sequence, i.e. destination surface is consistent again. + */ + void (*StopDrawing)( void *driver_data, void *device_data, CardState *state ); +} GraphicsDeviceFuncs; + +typedef struct { + int (*Probe) (CoreGraphicsDevice *device); + void (*GetDriverInfo) (CoreGraphicsDevice *device, + GraphicsDriverInfo *driver_info); + + DFBResult (*InitDriver) (CoreGraphicsDevice *device, + GraphicsDeviceFuncs *funcs, + void *driver_data, + void *device_data, + CoreDFB *core); + + DFBResult (*InitDevice) (CoreGraphicsDevice *device, + GraphicsDeviceInfo *device_info, + void *driver_data, + void *device_data); + + void (*CloseDevice) (CoreGraphicsDevice *device, + void *driver_data, + void *device_data); + void (*CloseDriver) (CoreGraphicsDevice *device, + void *driver_data); +} GraphicsDriverFuncs; + +typedef enum { + GDLF_NONE = 0x00000000, + + GDLF_WAIT = 0x00000001, + GDLF_SYNC = 0x00000002, + GDLF_INVALIDATE = 0x00000004, + GDLF_RESET = 0x00000008 +} GraphicsDeviceLockFlags; + +DFBResult dfb_gfxcard_lock( GraphicsDeviceLockFlags flags ); +void dfb_gfxcard_unlock( void ); +void dfb_gfxcard_holdup( void ); + +bool dfb_gfxcard_state_check( CardState *state, DFBAccelerationMask accel ); + +/* + * Signal beginning of a sequence of operations using this state. + * Any number of states can be 'drawing'. + */ +void dfb_gfxcard_start_drawing( CoreGraphicsDevice *device, + CardState *state ); + +/* + * Signal end of sequence, i.e. destination surface is consistent again. + */ +void dfb_gfxcard_stop_drawing ( CoreGraphicsDevice *device, + CardState *state ); + +/* + * drawing functions, lock source and destination surfaces, + * handle clipping and drawing method (hardware/software) + */ +void dfb_gfxcard_fillrectangles ( const DFBRectangle *rects, + int num, + CardState *state ); + +void dfb_gfxcard_drawrectangle ( DFBRectangle *rect, + CardState *state ); + +void dfb_gfxcard_drawlines ( DFBRegion *lines, + int num_lines, + CardState *state ); + +void dfb_gfxcard_fillspans ( int y, + DFBSpan *spans, + int num_spans, + CardState *state ); + +void dfb_gfxcard_filltriangles ( const DFBTriangle *tris, + int num, + CardState *state ); + +void dfb_gfxcard_blit ( DFBRectangle *rect, + int dx, + int dy, + CardState *state ); + +void dfb_gfxcard_batchblit ( DFBRectangle *rects, + DFBPoint *points, + int num, + CardState *state ); + +void dfb_gfxcard_tileblit ( DFBRectangle *rect, + int dx1, + int dy1, + int dx2, + int dy2, + CardState *state ); + +void dfb_gfxcard_stretchblit ( DFBRectangle *srect, + DFBRectangle *drect, + CardState *state ); + +void dfb_gfxcard_texture_triangles ( DFBVertex *vertices, + int num, + DFBTriangleFormation formation, + CardState *state ); + +void dfb_gfxcard_drawstring ( const u8 *text, + int bytes, + DFBTextEncodingID encoding, + int x, + int y, + CoreFont *font, + unsigned int layers, + CardState *state ); + +void dfb_gfxcard_drawglyph ( CoreGlyphData **glyph, + int x, + int y, + CoreFont *font, + unsigned int layers, + CardState *state ); + +bool dfb_gfxcard_drawstring_check_state ( CoreFont *font, + CardState *state ); + +DFBResult dfb_gfxcard_sync( void ); +void dfb_gfxcard_invalidate_state( void ); +DFBResult dfb_gfxcard_wait_serial( const CoreGraphicsSerial *serial ); +void dfb_gfxcard_flush_texture_cache( void ); +void dfb_gfxcard_flush_read_cache( void ); +void dfb_gfxcard_after_set_var( void ); +void dfb_gfxcard_surface_enter( CoreSurfaceBuffer *buffer, DFBSurfaceLockFlags flags ); +void dfb_gfxcard_surface_leave( CoreSurfaceBuffer *buffer ); + +DFBResult dfb_gfxcard_adjust_heap_offset( int offset ); + +void dfb_gfxcard_get_capabilities ( CardCapabilities *ret_caps ); +void dfb_gfxcard_get_device_info ( GraphicsDeviceInfo *ret_info ); +void dfb_gfxcard_get_driver_info ( GraphicsDriverInfo *ret_info ); + +int dfb_gfxcard_reserve_memory ( CoreGraphicsDevice *device, + unsigned int size ); +int dfb_gfxcard_reserve_auxmemory ( CoreGraphicsDevice *device, + unsigned int size ); + +unsigned int dfb_gfxcard_memory_length ( void ); +unsigned int dfb_gfxcard_auxmemory_length ( void ); + +void *dfb_gfxcard_get_device_data ( void ); +void *dfb_gfxcard_get_driver_data ( void ); + +CoreGraphicsDevice *dfb_gfxcard_get_primary ( void ); + +/* + * Graphics drivers call this function to get access to MMIO regions. + * + * device: Graphics device to map + * offset: Offset from MMIO base (default offset is 0) + * length: Length of mapped region (-1 uses default length) + * + * Returns the virtual address or NULL if mapping failed. + */ +volatile void *dfb_gfxcard_map_mmio( CoreGraphicsDevice *device, + unsigned int offset, + int length ); + +/* + * Graphics drivers call this function to unmap MMIO regions. + * + * addr: Virtual address returned by gfxcard_map_mmio + * length: Length of mapped region (-1 uses default length) + */ +void dfb_gfxcard_unmap_mmio( CoreGraphicsDevice *device, + volatile void *addr, + int length ); + +int dfb_gfxcard_get_accelerator( CoreGraphicsDevice *device ); + +void dfb_gfxcard_get_limits( CoreGraphicsDevice *device, + CardLimitations *ret_limits ); + +void dfb_gfxcard_calc_buffer_size( CoreGraphicsDevice *device, + CoreSurfaceBuffer *buffer, + int *ret_pitch, + int *ret_length ); + +unsigned long dfb_gfxcard_memory_physical ( CoreGraphicsDevice *device, + unsigned int offset ); +void *dfb_gfxcard_memory_virtual ( CoreGraphicsDevice *device, + unsigned int offset ); + +unsigned long dfb_gfxcard_auxmemory_physical( CoreGraphicsDevice *device, + unsigned int offset ); +void *dfb_gfxcard_auxmemory_virtual ( CoreGraphicsDevice *device, + unsigned int offset ); + + +/* Hook for registering additional screen(s) and layer(s) in app or lib initializing DirectFB. */ +extern void (*__DFB_CoreRegisterHook)( CoreDFB *core, CoreGraphicsDevice *device, void *ctx ); +extern void *__DFB_CoreRegisterHookCtx; + + +#endif + diff --git a/Source/DirectFB/src/core/graphics_driver.h b/Source/DirectFB/src/core/graphics_driver.h new file mode 100755 index 0000000..de03234 --- /dev/null +++ b/Source/DirectFB/src/core/graphics_driver.h @@ -0,0 +1,86 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __GRAPHICS_DRIVER_H__ +#define __GRAPHICS_DRIVER_H__ + +#include + +#include + + +static int +driver_probe( CoreGraphicsDevice *device ); + +static void +driver_get_info( CoreGraphicsDevice *device, + GraphicsDriverInfo *info ); + +static DFBResult +driver_init_driver( CoreGraphicsDevice *device, + GraphicsDeviceFuncs *funcs, + void *driver_data, + void *device_data, + CoreDFB *core ); + +static DFBResult +driver_init_device( CoreGraphicsDevice *device, + GraphicsDeviceInfo *device_info, + void *driver_data, + void *device_data ); + +static void +driver_close_device( CoreGraphicsDevice *device, + void *driver_data, + void *device_data ); + +static void +driver_close_driver( CoreGraphicsDevice *device, + void *driver_data ); + +static GraphicsDriverFuncs driver_funcs = { + .Probe = driver_probe, + .GetDriverInfo = driver_get_info, + .InitDriver = driver_init_driver, + .InitDevice = driver_init_device, + .CloseDevice = driver_close_device, + .CloseDriver = driver_close_driver +}; + +#define DFB_GRAPHICS_DRIVER(shortname) \ +__attribute__((constructor)) void directfb_##shortname( void ); \ + \ +void \ +directfb_##shortname( void ) \ +{ \ + direct_modules_register( &dfb_graphics_drivers, \ + DFB_GRAPHICS_DRIVER_ABI_VERSION, \ + #shortname, &driver_funcs ); \ +} + +#endif diff --git a/Source/DirectFB/src/core/input.c b/Source/DirectFB/src/core/input.c new file mode 100755 index 0000000..c8eee18 --- /dev/null +++ b/Source/DirectFB/src/core/input.c @@ -0,0 +1,2668 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + + +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include + + +D_DEBUG_DOMAIN( Core_Input, "Core/Input", "DirectFB Input Core" ); +D_DEBUG_DOMAIN( Core_InputEvt, "Core/Input/Evt", "DirectFB Input Core Events & Dispatch" ); + + +DEFINE_MODULE_DIRECTORY( dfb_input_modules, "inputdrivers", DFB_INPUT_DRIVER_ABI_VERSION ); + +/**********************************************************************************************************************/ + +typedef enum { + CICC_RESCAN_DEVICES +} CoreInputCoreCommand; + +typedef enum { + CIDC_RELOAD_KEYMAP, + CIDC_SET_SENSITIVITY +} CoreInputDeviceCommand; + + +typedef struct { + DirectLink link; + + int magic; + + DirectModuleEntry *module; + + const InputDriverFuncs *funcs; + + InputDriverInfo info; + + int nr_devices; +} InputDriver; + +typedef struct { + int min_keycode; + int max_keycode; + int num_entries; + DFBInputDeviceKeymapEntry *entries; +} InputDeviceKeymap; + +typedef struct { + int magic; + + DFBInputDeviceID id; /* unique device id */ + + int num; + + InputDeviceInfo device_info; + + InputDeviceKeymap keymap; + + DFBInputDeviceModifierMask modifiers_l; + DFBInputDeviceModifierMask modifiers_r; + DFBInputDeviceLockState locks; + DFBInputDeviceButtonMask buttons; + + DFBInputDeviceKeyIdentifier last_key; /* last key pressed */ + DFBInputDeviceKeySymbol last_symbol; /* last symbol pressed */ + bool first_press; /* first press of key */ + + FusionReactor *reactor; /* event dispatcher */ + FusionSkirmish lock; + + FusionCall call; /* driver call via master */ + + unsigned int axis_num; + DFBInputDeviceAxisInfo *axis_info; + + + DFBInputDeviceState state; +} InputDeviceShared; + +struct __DFB_CoreInputDevice { + int magic; + + InputDeviceShared *shared; + + InputDriver *driver; + void *driver_data; + + CoreDFB *core; +}; + +/**********************************************************************************************************************/ + +typedef struct { + int magic; + + int num; + InputDeviceShared *devices[MAX_INPUTDEVICES]; + + FusionCall call; + FusionReactor *reactor; +} DFBInputCoreShared; + +struct __DFB_DFBInputCore { + int magic; + + CoreDFB *core; + + DFBInputCoreShared *shared; + + DirectLink *drivers; + + int num; + CoreInputDevice *devices[MAX_INPUTDEVICES]; + + Reaction reaction; +}; + + +DFB_CORE_PART( input_core, InputCore ); + +/**********************************************************************************************************************/ + +typedef struct { + DFBInputDeviceKeySymbol target; + DFBInputDeviceKeySymbol result; +} DeadKeyCombo; + +typedef struct { + DFBInputDeviceKeySymbol deadkey; + const DeadKeyCombo *combos; +} DeadKeyMap; + +/**********************************************************************************************************************/ + +static const DeadKeyCombo combos_grave[] = { + { DIKS_SPACE, (unsigned char) '`' }, + { DIKS_SMALL_A, (unsigned char) 'à' }, + { DIKS_SMALL_E, (unsigned char) 'è' }, + { DIKS_SMALL_I, (unsigned char) 'ì' }, + { DIKS_SMALL_O, (unsigned char) 'ò' }, + { DIKS_SMALL_U, (unsigned char) 'ù' }, + { DIKS_CAPITAL_A, (unsigned char) 'À' }, + { DIKS_CAPITAL_E, (unsigned char) 'È' }, + { DIKS_CAPITAL_I, (unsigned char) 'Ì' }, + { DIKS_CAPITAL_O, (unsigned char) 'Ò' }, + { DIKS_CAPITAL_U, (unsigned char) 'Ù' }, + { 0, 0 } +}; + +static const DeadKeyCombo combos_acute[] = { + { DIKS_SPACE, (unsigned char) '\'' }, + { DIKS_SMALL_A, (unsigned char) 'á' }, + { DIKS_SMALL_E, (unsigned char) 'é' }, + { DIKS_SMALL_I, (unsigned char) 'í' }, + { DIKS_SMALL_O, (unsigned char) 'ó' }, + { DIKS_SMALL_U, (unsigned char) 'ú' }, + { DIKS_SMALL_Y, (unsigned char) 'ý' }, + { DIKS_CAPITAL_A, (unsigned char) 'Á' }, + { DIKS_CAPITAL_E, (unsigned char) 'É' }, + { DIKS_CAPITAL_I, (unsigned char) 'Í' }, + { DIKS_CAPITAL_O, (unsigned char) 'Ó' }, + { DIKS_CAPITAL_U, (unsigned char) 'Ú' }, + { DIKS_CAPITAL_Y, (unsigned char) 'Ý' }, + { 0, 0 } +}; + +static const DeadKeyCombo combos_circumflex[] = { + { DIKS_SPACE, (unsigned char) '^' }, + { DIKS_SMALL_A, (unsigned char) 'â' }, + { DIKS_SMALL_E, (unsigned char) 'ê' }, + { DIKS_SMALL_I, (unsigned char) 'î' }, + { DIKS_SMALL_O, (unsigned char) 'ô' }, + { DIKS_SMALL_U, (unsigned char) 'û' }, + { DIKS_CAPITAL_A, (unsigned char) 'Â' }, + { DIKS_CAPITAL_E, (unsigned char) 'Ê' }, + { DIKS_CAPITAL_I, (unsigned char) 'Î' }, + { DIKS_CAPITAL_O, (unsigned char) 'Ô' }, + { DIKS_CAPITAL_U, (unsigned char) 'Û' }, + { 0, 0 } +}; + +static const DeadKeyCombo combos_diaeresis[] = { + { DIKS_SPACE, (unsigned char) '¨' }, + { DIKS_SMALL_A, (unsigned char) 'ä' }, + { DIKS_SMALL_E, (unsigned char) 'ë' }, + { DIKS_SMALL_I, (unsigned char) 'ï' }, + { DIKS_SMALL_O, (unsigned char) 'ö' }, + { DIKS_SMALL_U, (unsigned char) 'ü' }, + { DIKS_CAPITAL_A, (unsigned char) 'Ä' }, + { DIKS_CAPITAL_E, (unsigned char) 'Ë' }, + { DIKS_CAPITAL_I, (unsigned char) 'Ï' }, + { DIKS_CAPITAL_O, (unsigned char) 'Ö' }, + { DIKS_CAPITAL_U, (unsigned char) 'Ü' }, + { 0, 0 } +}; + +static const DeadKeyCombo combos_tilde[] = { + { DIKS_SPACE, (unsigned char) '~' }, + { DIKS_SMALL_A, (unsigned char) 'ã' }, + { DIKS_SMALL_N, (unsigned char) 'ñ' }, + { DIKS_SMALL_O, (unsigned char) 'õ' }, + { DIKS_CAPITAL_A, (unsigned char) 'Ã' }, + { DIKS_CAPITAL_N, (unsigned char) 'Ñ' }, + { DIKS_CAPITAL_O, (unsigned char) 'Õ' }, + { 0, 0 } +}; + +static const DeadKeyMap deadkey_maps[] = { + { DIKS_DEAD_GRAVE, combos_grave }, + { DIKS_DEAD_ACUTE, combos_acute }, + { DIKS_DEAD_CIRCUMFLEX, combos_circumflex }, + { DIKS_DEAD_DIAERESIS, combos_diaeresis }, + { DIKS_DEAD_TILDE, combos_tilde } +}; + +/* define a lookup table to go from key IDs to names. + * This is used to look up the names provided in a loaded key table */ +/* this table is roughly 4Kb in size */ +DirectFBKeySymbolNames(KeySymbolNames); +DirectFBKeyIdentifierNames(KeyIdentifierNames); + +/**********************************************************************************************************************/ + +static void init_drivers ( CoreDFB *core ); +static DFBResult rescan_devices( CoreDFB *core ); + +static void allocate_device_keymap( CoreDFB *core, CoreInputDevice *device ); + +static DFBInputDeviceKeymapEntry *get_keymap_entry( CoreInputDevice *device, + int code ); + +static DFBResult set_keymap_entry( CoreInputDevice *device, + int code, + DFBInputDeviceKeymapEntry *entry ); + +static DFBResult load_keymap( CoreInputDevice *device, + char *filename ); + +static DFBInputDeviceKeySymbol lookup_keysymbol( char *symbolname ); +static DFBInputDeviceKeyIdentifier lookup_keyidentifier( char *identifiername ); + +/**********************************************************************************************************************/ + +static bool lookup_from_table( CoreInputDevice *device, + DFBInputEvent *event, + DFBInputEventFlags lookup ); + +static void fixup_key_event ( CoreInputDevice *device, + DFBInputEvent *event ); + +static void fixup_mouse_event( CoreInputDevice *device, + DFBInputEvent *event ); + +static void flush_keys ( CoreInputDevice *device ); + +static bool core_input_filter( CoreInputDevice *device, + DFBInputEvent *event ); + +/**********************************************************************************************************************/ + +static DFBInputDeviceKeyIdentifier symbol_to_id( DFBInputDeviceKeySymbol symbol ); + +static DFBInputDeviceKeySymbol id_to_symbol( DFBInputDeviceKeyIdentifier id, + DFBInputDeviceModifierMask modifiers, + DFBInputDeviceLockState locks ); + +/**********************************************************************************************************************/ + +static ReactionFunc dfb_input_globals[MAX_INPUT_GLOBALS+1] = { +/* 0 */ _dfb_windowstack_inputdevice_listener, + NULL +}; + +DFBResult +dfb_input_add_global( ReactionFunc func, + int *ret_index ) +{ + int i; + + D_DEBUG_AT( Core_Input, "%s( %p, %p )\n", __FUNCTION__, func, ret_index ); + + D_ASSERT( func != NULL ); + D_ASSERT( ret_index != NULL ); + + for (i=0; i index %d\n", i ); + + *ret_index = i; + + return DFB_OK; + } + } + + return DFB_LIMITEXCEEDED; +} + +DFBResult +dfb_input_set_global( ReactionFunc func, + int index ) +{ + D_DEBUG_AT( Core_Input, "%s( %p, %d )\n", __FUNCTION__, func, index ); + + D_ASSERT( func != NULL ); + D_ASSERT( index >= 0 ); + D_ASSERT( index < MAX_INPUT_GLOBALS ); + + D_ASSUME( dfb_input_globals[index] == NULL ); + + dfb_input_globals[index] = func; + + return DFB_OK; +} + +/**********************************************************************************************************************/ + +static DFBInputCore *core_local; /* FIXME */ +static DFBInputCoreShared *core_input; /* FIXME */ + +/**********************************************************************************************************************/ + +static FusionCallHandlerResult +core_input_call_handler( int caller, /* fusion id of the caller */ + int call_arg, /* optional call parameter */ + void *call_ptr, /* optional call parameter */ + void *ctx, /* optional handler context */ + unsigned int serial, + int *ret_val ) +{ + CoreDFB *core = ctx; + + D_DEBUG_AT( Core_Input, "%s( %p )\n", __FUNCTION__, core ); + + switch (call_arg) { + case CICC_RESCAN_DEVICES: + *ret_val = rescan_devices( core ); + break; + + default: + D_BUG( "unknown command %d", call_arg ); + *ret_val = DFB_BUG; + } + + return FCHR_RETURN; +} + +/**********************************************************************************************************************/ + +static DFBResult +dfb_input_core_initialize( CoreDFB *core, + DFBInputCore *data, + DFBInputCoreShared *shared ) +{ + D_DEBUG_AT( Core_Input, "dfb_input_core_initialize( %p, %p, %p )\n", core, data, shared ); + + D_ASSERT( data != NULL ); + D_ASSERT( shared != NULL ); + + core_local = data; /* FIXME */ + core_input = shared; /* FIXME */ + + data->core = core; + data->shared = shared; + + + fusion_call_init( &core_input->call, core_input_call_handler, core, dfb_core_world( core ) ); + + core_input->reactor = fusion_reactor_new( sizeof(CoreInputCoreNotification), "Input Core", dfb_core_world( core ) ); + + fusion_reactor_direct( core_input->reactor, false ); + + direct_modules_explore_directory( &dfb_input_modules ); + + init_drivers( core ); + rescan_devices( core ); + + D_MAGIC_SET( data, DFBInputCore ); + D_MAGIC_SET( shared, DFBInputCoreShared ); + + return DFB_OK; +} + +static DFBResult +rejoin_devices( CoreDFB *core ) +{ + int i; + + D_DEBUG_AT( Core_Input, "%s( %p )\n", __FUNCTION__, core ); + + D_ASSERT( core != NULL ); + D_MAGIC_ASSERT( core_local, DFBInputCore ); + D_ASSERT( core_input != NULL ); + + for (i=core_local->num; inum; i++) { + CoreInputDevice *device; + + D_DEBUG_AT( Core_Input, " -> adding %d (%s)\n", + core_input->devices[i]->id, + core_input->devices[i]->device_info.desc.name ); + + device = D_CALLOC( 1, sizeof(CoreInputDevice) ); + if (!device) { + D_OOM(); + continue; + } + + device->shared = core_input->devices[i]; + + D_MAGIC_SET( device, CoreInputDevice ); + + /* add it to the list */ + core_local->devices[core_local->num++] = device; + } + + return DFB_OK; +} + +static ReactionResult +core_input_core_reaction( const void *msg_data, + void *ctx ) +{ + const CoreInputCoreNotification *notification = msg_data; + CoreDFB *core = ctx; + + if (notification->flags & CICNF_NEW_DEVICE) + rejoin_devices( core ); + + return RS_OK; +} + +static DFBResult +dfb_input_core_join( CoreDFB *core, + DFBInputCore *data, + DFBInputCoreShared *shared ) +{ + D_DEBUG_AT( Core_Input, "dfb_input_core_join( %p, %p, %p )\n", core, data, shared ); + + D_ASSERT( data != NULL ); + D_MAGIC_ASSERT( shared, DFBInputCoreShared ); + + core_local = data; /* FIXME */ + core_input = shared; /* FIXME */ + + data->core = core; + data->shared = shared; + + D_MAGIC_SET( data, DFBInputCore ); + + + rejoin_devices( core ); + + fusion_reactor_attach( core_input->reactor, core_input_core_reaction, core, &core_local->reaction ); + + return DFB_OK; +} + +static DFBResult +dfb_input_core_shutdown( DFBInputCore *data, + bool emergency ) +{ + int i; + DFBInputCoreShared *shared; + FusionSHMPoolShared *pool = dfb_core_shmpool( data->core ); + + D_DEBUG_AT( Core_Input, "dfb_input_core_shutdown( %p, %semergency )\n", data, emergency ? "" : "no " ); + + D_MAGIC_ASSERT( data, DFBInputCore ); + D_MAGIC_ASSERT( data->shared, DFBInputCoreShared ); + + shared = data->shared; + + + for (i=0; inum; i++) { + CoreInputDevice *device = data->devices[i]; + InputDriver *driver; + InputDeviceShared *devshared; + + D_MAGIC_ASSERT( device, CoreInputDevice ); + + driver = device->driver; + D_ASSERT( driver != NULL ); + + devshared = device->shared; + D_ASSERT( devshared != NULL ); + + fusion_call_destroy( &devshared->call ); + fusion_skirmish_destroy( &devshared->lock ); + + if (device->driver_data != NULL) { + void *driver_data; + + D_ASSERT( driver->funcs != NULL ); + D_ASSERT( driver->funcs->CloseDevice != NULL ); + + D_DEBUG_AT( Core_Input, " -> closing '%s' (%d) %d.%d (%s)\n", + devshared->device_info.desc.name, devshared->num + 1, + driver->info.version.major, + driver->info.version.minor, driver->info.vendor ); + + driver_data = device->driver_data; + device->driver_data = NULL; + driver->funcs->CloseDevice( driver_data ); + } + + if (!--driver->nr_devices) { + direct_module_unref( driver->module ); + D_FREE( driver ); + } + + fusion_reactor_free( devshared->reactor ); + + if (devshared->keymap.entries) + SHFREE( pool, devshared->keymap.entries ); + + if (devshared->axis_info) + SHFREE( pool, devshared->axis_info ); + + SHFREE( pool, devshared ); + + D_MAGIC_CLEAR( device ); + + D_FREE( device ); + } + + D_MAGIC_CLEAR( data ); + D_MAGIC_CLEAR( shared ); + + return DFB_OK; +} + +static DFBResult +dfb_input_core_leave( DFBInputCore *data, + bool emergency ) +{ + int i; + DFBInputCoreShared *shared; + + D_DEBUG_AT( Core_Input, "dfb_input_core_leave( %p, %semergency )\n", data, emergency ? "" : "no " ); + + D_MAGIC_ASSERT( data, DFBInputCore ); + D_MAGIC_ASSERT( data->shared, DFBInputCoreShared ); + + shared = data->shared; + + + for (i=0; inum; i++) { + CoreInputDevice *device = data->devices[i]; + + D_MAGIC_ASSERT( device, CoreInputDevice ); + + D_FREE( device ); + } + + + D_MAGIC_CLEAR( data ); + + return DFB_OK; +} + +static DFBResult +dfb_input_core_suspend( DFBInputCore *data ) +{ + int i; + DFBInputCoreShared *shared; + + D_DEBUG_AT( Core_Input, "dfb_input_core_suspend( %p )\n", data ); + + D_MAGIC_ASSERT( data, DFBInputCore ); + D_MAGIC_ASSERT( data->shared, DFBInputCoreShared ); + + shared = data->shared; + + D_DEBUG_AT( Core_Input, " -> suspending...\n" ); + + for (i=0; inum; i++) { + CoreInputDevice *device = data->devices[i]; + InputDriver *driver; + InputDeviceShared *devshared; + + D_MAGIC_ASSERT( device, CoreInputDevice ); + + driver = device->driver; + D_ASSERT( driver != NULL ); + + devshared = device->shared; + D_ASSERT( devshared != NULL ); + + if (device->driver_data != NULL) { + void *driver_data; + + D_ASSERT( driver->funcs != NULL ); + D_ASSERT( driver->funcs->CloseDevice != NULL ); + + D_DEBUG_AT( Core_Input, " -> closing '%s' (%d) %d.%d (%s)\n", + devshared->device_info.desc.name, devshared->num + 1, + driver->info.version.major, + driver->info.version.minor, driver->info.vendor ); + + driver_data = device->driver_data; + device->driver_data = NULL; + driver->funcs->CloseDevice( driver_data ); + } + + flush_keys( device ); + } + + D_DEBUG_AT( Core_Input, " -> suspended.\n" ); + + return DFB_OK; +} + +static DFBResult +dfb_input_core_resume( DFBInputCore *data ) +{ + DFBInputCoreShared *shared; + DFBResult ret; + int i; + + D_DEBUG_AT( Core_Input, "dfb_input_core_resume( %p )\n", data ); + + D_MAGIC_ASSERT( data, DFBInputCore ); + D_MAGIC_ASSERT( data->shared, DFBInputCoreShared ); + + shared = data->shared; + + D_DEBUG_AT( Core_Input, " -> resuming...\n" ); + + for (i=0; inum; i++) { + CoreInputDevice *device = data->devices[i]; + + D_MAGIC_ASSERT( device, CoreInputDevice ); + + D_DEBUG_AT( Core_Input, " -> reopening '%s' (%d) %d.%d (%s)\n", + device->shared->device_info.desc.name, device->shared->num + 1, + device->driver->info.version.major, + device->driver->info.version.minor, + device->driver->info.vendor ); + + D_ASSERT( device->driver_data == NULL ); + + ret = device->driver->funcs->OpenDevice( device, device->shared->num, + &device->shared->device_info, + &device->driver_data ); + if (ret) { + D_DERROR( ret, "DirectFB/Input: Failed reopening device " + "during resume (%s)!\n", device->shared->device_info.desc.name ); + device->driver_data = NULL; + } + } + + D_DEBUG_AT( Core_Input, " -> resumed.\n" ); + + return DFB_OK; +} + +void +dfb_input_enumerate_devices( InputDeviceCallback callback, + void *ctx, + DFBInputDeviceCapabilities caps ) +{ + int i; + + D_ASSERT( core_input != NULL ); + + for (i=0; inum; i++) { + CoreInputDevice *device = core_local->devices[i]; + + DFBInputDeviceCapabilities dev_caps; + + D_MAGIC_ASSERT( device, CoreInputDevice ); + D_ASSERT( device->shared != NULL ); + + dev_caps = device->shared->device_info.desc.caps; + + /* Always match if unclassified */ + if (!dev_caps) + dev_caps = DICAPS_ALL; + + if ((dev_caps & caps) && callback( device, ctx ) == DFENUM_CANCEL) + break; + } +} + +DirectResult +dfb_input_attach( CoreInputDevice *device, + ReactionFunc func, + void *ctx, + Reaction *reaction ) +{ + D_DEBUG_AT( Core_Input, "%s( %p, %p, %p, %p )\n", __FUNCTION__, device, func, ctx, reaction ); + + D_MAGIC_ASSERT( device, CoreInputDevice ); + + D_ASSERT( core_input != NULL ); + D_ASSERT( device != NULL ); + D_ASSERT( device->shared != NULL ); + + return fusion_reactor_attach( device->shared->reactor, func, ctx, reaction ); +} + +DirectResult +dfb_input_detach( CoreInputDevice *device, + Reaction *reaction ) +{ + D_DEBUG_AT( Core_Input, "%s( %p, %p )\n", __FUNCTION__, device, reaction ); + + D_MAGIC_ASSERT( device, CoreInputDevice ); + + D_ASSERT( core_input != NULL ); + D_ASSERT( device != NULL ); + D_ASSERT( device->shared != NULL ); + + return fusion_reactor_detach( device->shared->reactor, reaction ); +} + +DirectResult +dfb_input_attach_global( CoreInputDevice *device, + int index, + void *ctx, + GlobalReaction *reaction ) +{ + D_DEBUG_AT( Core_Input, "%s( %p, %d, %p, %p )\n", __FUNCTION__, device, index, ctx, reaction ); + + D_MAGIC_ASSERT( device, CoreInputDevice ); + + D_ASSERT( core_input != NULL ); + D_ASSERT( device != NULL ); + D_ASSERT( device->shared != NULL ); + + return fusion_reactor_attach_global( device->shared->reactor, index, ctx, reaction ); +} + +DirectResult +dfb_input_detach_global( CoreInputDevice *device, + GlobalReaction *reaction ) +{ + D_DEBUG_AT( Core_Input, "%s( %p, %p )\n", __FUNCTION__, device, reaction ); + + D_MAGIC_ASSERT( device, CoreInputDevice ); + + D_ASSERT( core_input != NULL ); + D_ASSERT( device != NULL ); + D_ASSERT( device->shared != NULL ); + + return fusion_reactor_detach_global( device->shared->reactor, reaction ); +} + +const char * +dfb_input_event_type_name( DFBInputEventType type ) +{ + switch (type) { + case DIET_UNKNOWN: + return "UNKNOWN"; + + case DIET_KEYPRESS: + return "KEYPRESS"; + + case DIET_KEYRELEASE: + return "KEYRELEASE"; + + case DIET_BUTTONPRESS: + return "BUTTONPRESS"; + + case DIET_BUTTONRELEASE: + return "BUTTONRELEASE"; + + case DIET_AXISMOTION: + return "AXISMOTION"; + + default: + break; + } + + return ""; +} + +void +dfb_input_dispatch( CoreInputDevice *device, DFBInputEvent *event ) +{ + D_DEBUG_AT( Core_Input, "%s( %p, %p )\n", __FUNCTION__, device, event ); + + D_MAGIC_ASSERT( device, CoreInputDevice ); + + D_ASSERT( core_input != NULL ); + D_ASSERT( device != NULL ); + D_ASSERT( event != NULL ); + + D_ASSUME( device->shared != NULL ); + + /* + * 0. Sanity checks & debugging... + */ + if (!device->shared) { + D_DEBUG_AT( Core_Input, " -> No shared data!\n" ); + return; + } + + D_ASSUME( device->shared->reactor != NULL ); + + if (!device->shared->reactor) { + D_DEBUG_AT( Core_Input, " -> No reactor!\n" ); + return; + } + + D_DEBUG_AT( Core_InputEvt, " -> (%02x) %s%s%s\n", event->type, + dfb_input_event_type_name( event->type ), + (event->flags & DIEF_FOLLOW) ? " [FOLLOW]" : "", + (event->flags & DIEF_REPEAT) ? " [REPEAT]" : "" ); + +#if D_DEBUG_ENABLED + if (event->flags & DIEF_TIMESTAMP) + D_DEBUG_AT( Core_InputEvt, " -> TIMESTAMP %lu.%06lu\n", event->timestamp.tv_sec, event->timestamp.tv_usec ); + if (event->flags & DIEF_AXISABS) + D_DEBUG_AT( Core_InputEvt, " -> AXISABS %d at %d\n", event->axis, event->axisabs ); + if (event->flags & DIEF_AXISREL) + D_DEBUG_AT( Core_InputEvt, " -> AXISREL %d by %d\n", event->axis, event->axisrel ); + if (event->flags & DIEF_KEYCODE) + D_DEBUG_AT( Core_InputEvt, " -> KEYCODE %d\n", event->key_code ); + if (event->flags & DIEF_KEYID) + D_DEBUG_AT( Core_InputEvt, " -> KEYID 0x%04x\n", event->key_id ); + if (event->flags & DIEF_KEYSYMBOL) + D_DEBUG_AT( Core_InputEvt, " -> KEYSYMBOL 0x%04x\n", event->key_symbol ); + if (event->flags & DIEF_MODIFIERS) + D_DEBUG_AT( Core_InputEvt, " -> MODIFIERS 0x%04x\n", event->modifiers ); + if (event->flags & DIEF_LOCKS) + D_DEBUG_AT( Core_InputEvt, " -> LOCKS 0x%04x\n", event->locks ); + if (event->flags & DIEF_BUTTONS) + D_DEBUG_AT( Core_InputEvt, " -> BUTTONS 0x%04x\n", event->buttons ); + if (event->flags & DIEF_GLOBAL) + D_DEBUG_AT( Core_InputEvt, " -> GLOBAL\n" ); +#endif + + /* + * 1. Fixup event... + */ + event->clazz = DFEC_INPUT; + event->device_id = device->shared->id; + + if (!(event->flags & DIEF_TIMESTAMP)) { + gettimeofday( &event->timestamp, NULL ); + event->flags |= DIEF_TIMESTAMP; + } + + switch (event->type) { + case DIET_BUTTONPRESS: + case DIET_BUTTONRELEASE: + D_DEBUG_AT( Core_InputEvt, " -> BUTTON 0x%04x\n", event->button ); + + if (dfb_config->lefty) { + if (event->button == DIBI_LEFT) + event->button = DIBI_RIGHT; + else if (event->button == DIBI_RIGHT) + event->button = DIBI_LEFT; + + D_DEBUG_AT( Core_InputEvt, " -> lefty! => 0x%04x <=\n", event->button ); + } + /* fallthru */ + + case DIET_AXISMOTION: + fixup_mouse_event( device, event ); + break; + + case DIET_KEYPRESS: + case DIET_KEYRELEASE: + if (dfb_config->capslock_meta) { + if (device->shared->keymap.num_entries && (event->flags & DIEF_KEYCODE)) + lookup_from_table( device, event, (DIEF_KEYID | + DIEF_KEYSYMBOL) & ~event->flags ); + + if (event->key_id == DIKI_CAPS_LOCK || event->key_symbol == DIKS_CAPS_LOCK) { + event->flags |= DIEF_KEYID | DIEF_KEYSYMBOL; + event->key_code = -1; + event->key_id = DIKI_META_L; + event->key_symbol = DIKS_META; + } + } + + fixup_key_event( device, event ); + break; + + default: + ; + } + +#if D_DEBUG_ENABLED + if (event->flags & DIEF_TIMESTAMP) + D_DEBUG_AT( Core_InputEvt, " => TIMESTAMP %lu.%06lu\n", event->timestamp.tv_sec, event->timestamp.tv_usec ); + if (event->flags & DIEF_AXISABS) + D_DEBUG_AT( Core_InputEvt, " => AXISABS %d at %d\n", event->axis, event->axisabs ); + if (event->flags & DIEF_AXISREL) + D_DEBUG_AT( Core_InputEvt, " => AXISREL %d by %d\n", event->axis, event->axisrel ); + if (event->flags & DIEF_KEYCODE) + D_DEBUG_AT( Core_InputEvt, " => KEYCODE %d\n", event->key_code ); + if (event->flags & DIEF_KEYID) + D_DEBUG_AT( Core_InputEvt, " => KEYID 0x%04x\n", event->key_id ); + if (event->flags & DIEF_KEYSYMBOL) + D_DEBUG_AT( Core_InputEvt, " => KEYSYMBOL 0x%04x\n", event->key_symbol ); + if (event->flags & DIEF_MODIFIERS) + D_DEBUG_AT( Core_InputEvt, " => MODIFIERS 0x%04x\n", event->modifiers ); + if (event->flags & DIEF_LOCKS) + D_DEBUG_AT( Core_InputEvt, " => LOCKS 0x%04x\n", event->locks ); + if (event->flags & DIEF_BUTTONS) + D_DEBUG_AT( Core_InputEvt, " => BUTTONS 0x%04x\n", event->buttons ); + if (event->flags & DIEF_GLOBAL) + D_DEBUG_AT( Core_InputEvt, " => GLOBAL\n" ); +#endif + + if (core_input_filter( device, event )) + D_DEBUG_AT( Core_InputEvt, " ****>> FILTERED\n" ); + else + fusion_reactor_dispatch( device->shared->reactor, event, true, dfb_input_globals ); +} + +DFBInputDeviceID +dfb_input_device_id( const CoreInputDevice *device ) +{ + D_MAGIC_ASSERT( device, CoreInputDevice ); + + D_ASSERT( core_input != NULL ); + D_ASSERT( device != NULL ); + D_ASSERT( device->shared != NULL ); + + return device->shared->id; +} + +CoreInputDevice * +dfb_input_device_at( DFBInputDeviceID id ) +{ + int i; + + D_ASSERT( core_input != NULL ); + + for (i=0; inum; i++) { + CoreInputDevice *device = core_local->devices[i]; + + D_MAGIC_ASSERT( device, CoreInputDevice ); + + if (device->shared->id == id) + return device; + } + + return NULL; +} + +void +dfb_input_device_description( const CoreInputDevice *device, + DFBInputDeviceDescription *desc ) +{ + D_MAGIC_ASSERT( device, CoreInputDevice ); + + D_ASSERT( core_input != NULL ); + D_ASSERT( device != NULL ); + D_ASSERT( device->shared != NULL ); + + *desc = device->shared->device_info.desc; +} + +DFBResult +dfb_input_device_get_keymap_entry( CoreInputDevice *device, + int keycode, + DFBInputDeviceKeymapEntry *entry ) +{ + DFBInputDeviceKeymapEntry *keymap_entry; + + D_MAGIC_ASSERT( device, CoreInputDevice ); + + D_ASSERT( core_input != NULL ); + D_ASSERT( device != NULL ); + D_ASSERT( entry != NULL ); + + keymap_entry = get_keymap_entry( device, keycode ); + if (!keymap_entry) + return DFB_FAILURE; + + *entry = *keymap_entry; + + return DFB_OK; +} + +DFBResult +dfb_input_device_set_keymap_entry( CoreInputDevice *device, + int keycode, + DFBInputDeviceKeymapEntry *entry ) +{ + D_MAGIC_ASSERT( device, CoreInputDevice ); + + D_ASSERT( core_input != NULL ); + D_ASSERT( device != NULL ); + D_ASSERT( entry != NULL ); + + return set_keymap_entry( device, keycode, entry ); +} + +DFBResult +dfb_input_device_load_keymap ( CoreInputDevice *device, + char *filename ) +{ + D_MAGIC_ASSERT( device, CoreInputDevice ); + + D_ASSERT( core_input != NULL ); + D_ASSERT( device != NULL ); + D_ASSERT( filename != NULL ); + + return load_keymap( device, filename ); +} + +DFBResult +dfb_input_device_reload_keymap( CoreInputDevice *device ) +{ + int ret; + InputDeviceShared *shared; + + D_MAGIC_ASSERT( device, CoreInputDevice ); + + shared = device->shared; + + D_ASSERT( shared != NULL ); + + D_INFO( "DirectFB/Input: Reloading keymap for '%s' [0x%02x]...\n", + shared->device_info.desc.name, shared->id ); + + if (fusion_call_execute( &shared->call, FCEF_NONE, CIDC_RELOAD_KEYMAP, NULL, &ret )) + return DFB_FUSION; + + return ret; +} + +DFBResult +dfb_input_device_set_sensitivity( CoreInputDevice *device, + int sensitivity ) +{ + int ret; + InputDeviceShared *shared; + + D_MAGIC_ASSERT( device, CoreInputDevice ); + + shared = device->shared; + D_ASSERT( shared != NULL ); + + if (fusion_call_execute( &shared->call, FCEF_NONE, CIDC_SET_SENSITIVITY, (void*)(long)sensitivity, &ret )) + return DFB_FUSION; + + return ret; +} + +DFBResult +dfb_input_rescan_devices( CoreDFB *core ) +{ + int ret; + + D_DEBUG_AT( Core_Input, "%s( %p )\n", __FUNCTION__, core ); + + D_ASSERT( core_input != NULL ); + + if (fusion_call_execute( &core_input->call, FCEF_NODIRECT, CICC_RESCAN_DEVICES, NULL, &ret )) + return DFB_FUSION; + + return ret; +} + +DFBResult +dfb_input_device_disconnected( CoreInputDevice *device ) +{ + D_DEBUG_AT( Core_Input, "%s( %p )\n", __FUNCTION__, device ); + + D_MAGIC_ASSERT( device, CoreInputDevice ); + + D_ASSERT( device->shared != NULL ); + + D_ASSUME( !(device->shared->state.flags & DISTATE_DISCONNECTED) ); + + device->shared->state.flags |= DISTATE_DISCONNECTED; + + return DFB_OK; +} + +DFBResult +dfb_input_device_reconnected( CoreInputDevice *device ) +{ + D_DEBUG_AT( Core_Input, "%s( %p )\n", __FUNCTION__, device ); + + D_MAGIC_ASSERT( device, CoreInputDevice ); + + D_ASSERT( device->shared != NULL ); + + D_ASSUME( device->shared->state.flags & DISTATE_DISCONNECTED ); + + device->shared->state.flags &= ~DISTATE_DISCONNECTED; + + return DFB_OK; +} + +DFBResult +dfb_input_device_get_state( const CoreInputDevice *device, + DFBInputDeviceState *ret_state ) +{ + D_DEBUG_AT( Core_Input, "%s( %p )\n", __FUNCTION__, device ); + + D_MAGIC_ASSERT( device, CoreInputDevice ); + + D_ASSERT( device->shared != NULL ); + + *ret_state = device->shared->state; + + return DFB_OK; +} + +DFBResult +dfb_input_core_attach( CoreDFB *core, + ReactionFunc func, + void *ctx, + Reaction *reaction ) +{ + D_DEBUG_AT( Core_Input, "%s( %p )\n", __FUNCTION__, core ); + + D_ASSERT( core_input != NULL ); + + return fusion_reactor_attach( core_input->reactor, func, ctx, reaction ); +} + +DFBResult +dfb_input_core_detach( CoreDFB *core, + Reaction *reaction ) +{ + D_DEBUG_AT( Core_Input, "%s( %p )\n", __FUNCTION__, core ); + + D_ASSERT( core_input != NULL ); + + return fusion_reactor_detach( core_input->reactor, reaction ); +} + +/** internal **/ + +static void +input_add_device( CoreInputDevice *device ) +{ + CoreInputCoreNotification notification; + + D_DEBUG_AT( Core_Input, "%s( %p )\n", __FUNCTION__, device ); + + D_MAGIC_ASSERT( device, CoreInputDevice ); + + D_ASSERT( core_input != NULL ); + D_ASSERT( device != NULL ); + D_ASSERT( device->shared != NULL ); + + if (core_input->num == MAX_INPUTDEVICES) { + D_ERROR( "DirectFB/Input: Maximum number of devices reached!\n" ); + return; + } + + core_local->devices[ core_local->num++ ] = device; + + core_input->devices[ core_input->num++ ] = device->shared; + + notification.flags = CICNF_NEW_DEVICE; + notification.device_id = device->shared->id; + + fusion_reactor_dispatch( core_input->reactor, ¬ification, true, NULL ); +} + +static void +allocate_device_keymap( CoreDFB *core, CoreInputDevice *device ) +{ + int i; + DFBInputDeviceKeymapEntry *entries; + FusionSHMPoolShared *pool = dfb_core_shmpool( core ); + InputDeviceShared *shared = device->shared; + DFBInputDeviceDescription *desc = &shared->device_info.desc; + int num_entries = desc->max_keycode - + desc->min_keycode + 1; + + D_DEBUG_AT( Core_Input, "%s( %p, %p )\n", __FUNCTION__, core, device ); + + D_MAGIC_ASSERT( device, CoreInputDevice ); + + D_ASSERT( core_input != NULL ); + + entries = SHCALLOC( pool, num_entries, sizeof(DFBInputDeviceKeymapEntry) ); + if (!entries) { + D_OOSHM(); + return; + } + + /* write -1 indicating entry is not fetched yet from driver */ + for (i=0; ikeymap.min_keycode = desc->min_keycode; + shared->keymap.max_keycode = desc->max_keycode; + shared->keymap.num_entries = num_entries; + shared->keymap.entries = entries; + +#if FUSION_BUILD_MULTI + /* we need to fetch the whole map, otherwise a slave would try to */ + for (i=desc->min_keycode; i<=desc->max_keycode; i++) + get_keymap_entry( device, i ); +#endif +} + +static int +make_id( DFBInputDeviceID prefered ) +{ + int i; + + D_DEBUG_AT( Core_Input, "%s( 0x%02x )\n", __FUNCTION__, prefered ); + + D_ASSERT( core_input != NULL ); + + for (i=0; inum; i++) { + CoreInputDevice *device = core_local->devices[i]; + + D_MAGIC_ASSERT( device, CoreInputDevice ); + + if (device->shared->id == prefered) + return make_id( (prefered < DIDID_ANY) ? DIDID_ANY : (prefered + 1) ); + } + + return prefered; +} + +static DFBResult +reload_keymap( CoreInputDevice *device ) +{ + int i; + InputDeviceShared *shared; + + D_DEBUG_AT( Core_Input, "%s( %p )\n", __FUNCTION__, device ); + + D_MAGIC_ASSERT( device, CoreInputDevice ); + + shared = device->shared; + + D_ASSERT( shared != NULL ); + + if (shared->device_info.desc.min_keycode < 0 || + shared->device_info.desc.max_keycode < 0) + return DFB_UNSUPPORTED; + + /* write -1 indicating entry is not fetched yet from driver */ + for (i=0; ikeymap.num_entries; i++) + shared->keymap.entries[i].code = -1; + + /* fetch the whole map */ + for (i=shared->keymap.min_keycode; i<=shared->keymap.max_keycode; i++) + get_keymap_entry( device, i ); + + D_INFO( "DirectFB/Input: Reloaded keymap for '%s' [0x%02x]\n", + shared->device_info.desc.name, shared->id ); + + return DFB_OK; +} + +static DFBResult +set_sensitivity( CoreInputDevice *device, + int sensitivity ) +{ + InputDriver *driver; + + D_DEBUG_AT( Core_Input, "%s( %p, %d )\n", __FUNCTION__, device, sensitivity ); + + D_MAGIC_ASSERT( device, CoreInputDevice ); + + driver = device->driver; + D_ASSERT( driver != NULL ); + + if (!driver->funcs->SetSensitivity) + return DFB_UNSUPPORTED; + + return driver->funcs->SetSensitivity( device, device->driver_data, sensitivity ); +} + +static FusionCallHandlerResult +input_device_call_handler( int caller, /* fusion id of the caller */ + int call_arg, /* optional call parameter */ + void *call_ptr, /* optional call parameter */ + void *ctx, /* optional handler context */ + unsigned int serial, + int *ret_val ) +{ + CoreInputDeviceCommand command = call_arg; + CoreInputDevice *device = ctx; + + D_DEBUG_AT( Core_Input, "%s( %d, %d, %p, %p )\n", __FUNCTION__, caller, call_arg, call_ptr, ctx ); + + D_MAGIC_ASSERT( device, CoreInputDevice ); + + switch (command) { + case CIDC_RELOAD_KEYMAP: + *ret_val = reload_keymap( device ); + break; + + case CIDC_SET_SENSITIVITY: + *ret_val = set_sensitivity( device, (long) call_ptr ); + break; + + default: + D_BUG( "unknown Core Input Device Command '%d'", command ); + *ret_val = DFB_BUG; + } + + return FCHR_RETURN; +} + +static DFBResult +init_axes( CoreInputDevice *device ) +{ + int i, num; + DFBResult ret; + InputDeviceShared *shared; + const InputDriverFuncs *funcs; + + D_DEBUG_AT( Core_Input, "%s( %p )\n", __FUNCTION__, device ); + + D_MAGIC_ASSERT( device, CoreInputDevice ); + D_ASSERT( device->driver != NULL ); + + funcs = device->driver->funcs; + D_ASSERT( funcs != NULL ); + + shared = device->shared; + D_ASSERT( shared != NULL ); + + if (shared->device_info.desc.max_axis < 0) + return DFB_OK; + + num = shared->device_info.desc.max_axis + 1; + + shared->axis_info = SHCALLOC( dfb_core_shmpool(device->core), num, sizeof(DFBInputDeviceAxisInfo) ); + if (!shared->axis_info) + return D_OOSHM(); + + shared->axis_num = num; + + if (funcs->GetAxisInfo) { + for (i=0; iGetAxisInfo( device, device->driver_data, i, &shared->axis_info[i] ); + if (ret) + D_DERROR( ret, "Core/Input: GetAxisInfo() failed for '%s' [%d] on axis %d!\n", + shared->device_info.desc.name, shared->id, i ); + } + } + + return DFB_OK; +} + +static void +init_drivers( CoreDFB *core ) +{ + DirectLink *next; + DirectModuleEntry *module; + + D_DEBUG_AT( Core_Input, "%s( %p )\n", __FUNCTION__, core ); + + D_ASSERT( core_input != NULL ); + + direct_list_foreach_safe (module, next, dfb_input_modules.entries) { + InputDriver *driver; + const InputDriverFuncs *funcs; + + funcs = direct_module_ref( module ); + if (!funcs) + continue; + + driver = D_CALLOC( 1, sizeof(InputDriver) ); + if (!driver) { + D_OOM(); + direct_module_unref( module ); + continue; + } + + D_ASSERT( funcs->GetDriverInfo != NULL ); + + funcs->GetDriverInfo( &driver->info ); + + driver->module = module; + driver->funcs = funcs; + + direct_list_prepend( &core_local->drivers, &driver->link ); + } +} + +static DFBResult +rescan_devices( CoreDFB *core ) +{ + InputDriver *driver; + FusionSHMPoolShared *pool = dfb_core_shmpool( core ); + + D_DEBUG_AT( Core_Input, "%s( %p )\n", __FUNCTION__, core ); + + D_ASSERT( core_input != NULL ); + + direct_list_foreach (driver, core_local->drivers) { + int i, num; + const InputDriverFuncs *funcs = driver->funcs; + + D_DEBUG_AT( Core_Input, " -> probing '%s'...\n", driver->info.name ); + + num = funcs->GetAvailable(); + + D_DEBUG_AT( Core_Input, " -> %d available device(s) provided by '%s'.\n", num, driver->info.name ); + + + for (i=driver->nr_devices; icore = core; + + memset( &device_info, 0, sizeof(InputDeviceInfo) ); + + device_info.desc.min_keycode = -1; + device_info.desc.max_keycode = -1; + + D_MAGIC_SET( device, CoreInputDevice ); + + if (funcs->OpenDevice( device, i, &device_info, &driver_data )) { + SHFREE( pool, shared ); + D_MAGIC_CLEAR( device ); + D_FREE( device ); + continue; + } + + D_DEBUG_AT( Core_Input, " -> opened '%s' (%d) %d.%d (%s)\n", + device_info.desc.name, i + 1, driver->info.version.major, + driver->info.version.minor, driver->info.vendor ); + + if (num > 1) + snprintf( buf, sizeof(buf), "%s (%d)", device_info.desc.name, i+1 ); + else + snprintf( buf, sizeof(buf), "%s", device_info.desc.name ); + + /* init skirmish */ + fusion_skirmish_init( &shared->lock, buf, dfb_core_world(core) ); + + /* create reactor */ + shared->reactor = fusion_reactor_new( sizeof(DFBInputEvent), buf, dfb_core_world(core) ); + + fusion_reactor_set_lock( shared->reactor, &shared->lock ); + + /* init call */ + fusion_call_init( &shared->call, input_device_call_handler, device, dfb_core_world(core) ); + + /* initialize shared data */ + shared->id = make_id(device_info.prefered_id); + shared->num = i; + shared->device_info = device_info; + shared->last_key = DIKI_UNKNOWN; + shared->first_press = true; + + /* initialize local data */ + device->shared = shared; + device->driver = driver; + device->driver_data = driver_data; + + D_INFO( "DirectFB/Input: %s %d.%d (%s)\n", + buf, driver->info.version.major, + driver->info.version.minor, driver->info.vendor ); + + if (device_info.desc.min_keycode > device_info.desc.max_keycode) { + D_BUG("min_keycode > max_keycode"); + device_info.desc.min_keycode = -1; + device_info.desc.max_keycode = -1; + } + else if (device_info.desc.min_keycode >= 0 && + device_info.desc.max_keycode >= 0) + allocate_device_keymap( core, device ); + + init_axes( device ); + + /* add it to the list */ + input_add_device( device ); + } + + driver->nr_devices = num; + } + + return DFB_OK; +} + +static DFBInputDeviceKeymapEntry * +get_keymap_entry( CoreInputDevice *device, + int code ) +{ + InputDeviceKeymap *map; + DFBInputDeviceKeymapEntry *entry; + + D_MAGIC_ASSERT( device, CoreInputDevice ); + + D_ASSERT( core_input != NULL ); + D_ASSERT( device != NULL ); + D_ASSERT( device->shared != NULL ); + + map = &device->shared->keymap; + + /* safety check */ + if (code < map->min_keycode || code > map->max_keycode) + return NULL; + + /* point to right array index */ + entry = &map->entries[code - map->min_keycode]; + + /* need to initialize? */ + if (entry->code != code) { + DFBResult ret; + InputDriver *driver = device->driver; + + if (!driver) { + D_BUG("seem to be a slave with an empty keymap"); + return NULL; + } + + /* write keycode to entry */ + entry->code = code; + + /* fetch entry from driver */ + ret = driver->funcs->GetKeymapEntry( device, + device->driver_data, entry ); + if (ret) + return NULL; + + /* drivers may leave this blank */ + if (entry->identifier == DIKI_UNKNOWN) + entry->identifier = symbol_to_id( entry->symbols[DIKSI_BASE] ); + + if (entry->symbols[DIKSI_BASE_SHIFT] == DIKS_NULL) + entry->symbols[DIKSI_BASE_SHIFT] = entry->symbols[DIKSI_BASE]; + + if (entry->symbols[DIKSI_ALT] == DIKS_NULL) + entry->symbols[DIKSI_ALT] = entry->symbols[DIKSI_BASE]; + + if (entry->symbols[DIKSI_ALT_SHIFT] == DIKS_NULL) + entry->symbols[DIKSI_ALT_SHIFT] = entry->symbols[DIKSI_ALT]; + } + + return entry; +} + +/* replace a single keymap entry with the code-entry pair */ +static DFBResult +set_keymap_entry( CoreInputDevice *device, + int code, + DFBInputDeviceKeymapEntry *entry ) +{ + InputDeviceKeymap *map; + + D_ASSERT( device->shared != NULL ); + D_ASSERT( device->shared->keymap.entries != NULL ); + + map = &device->shared->keymap; + + /* sanity check */ + if (code < map->min_keycode || code > map->max_keycode) + return DFB_FAILURE; + + /* copy the entry to the map */ + map->entries[code - map->min_keycode] = *entry; + + return DFB_OK; +} + +/* replace the complete current keymap with a keymap from a file. + * the minimum-maximum keycodes of the driver are to be respected. + */ +static DFBResult +load_keymap( CoreInputDevice *device, + char *filename ) +{ + DFBResult ret = DFB_OK; + InputDeviceKeymap *map = 0; + FILE *file = 0; + DFBInputDeviceLockState lockstate = 0; + + D_ASSERT( device->shared != NULL ); + D_ASSERT( device->shared->keymap.entries != NULL ); + + map = &device->shared->keymap; + + /* open the file */ + file = fopen( filename, "r" ); + if( !file ) + { + return errno2result( errno ); + } + + /* read the file, line by line, and consume the mentioned scancodes */ + while(1) + { + int i; + int dummy; + char buffer[201]; + int keycode; + char diki[201]; + char diks[4][201]; + char *b; + + DFBInputDeviceKeymapEntry entry = { .code = 0 }; + + b = fgets( buffer, 200, file ); + if( !b ) { + if( feof(file) ) { + fclose(file); + return DFB_OK; + } + fclose(file); + return errno2result(errno); + } + + /* comment or empty line */ + if( buffer[0]=='#' || strcmp(buffer,"\n")==0 ) + continue; + + /* check for lock state change */ + if( !strncmp(buffer,"capslock:",9) ) { lockstate |= DILS_CAPS; continue; } + if( !strncmp(buffer,":capslock",9) ) { lockstate &= ~DILS_CAPS; continue; } + if( !strncmp(buffer,"numlock:",8) ) { lockstate |= DILS_NUM; continue; } + if( !strncmp(buffer,":numlock",8) ) { lockstate &= ~DILS_NUM; continue; } + + i = sscanf( buffer, " keycode %i = %s = %s %s %s %s %i\n", + &keycode, diki, diks[0], diks[1], diks[2], diks[3], &dummy ); + + if( i < 3 || i > 6 ) { + /* we want 1 to 4 key symbols */ + D_INFO( "DirectFB/Input: skipped erroneous input line %s\n", buffer ); + continue; + } + + if( keycode > map->max_keycode || keycode < map->min_keycode ) { + D_INFO( "DirectFB/Input: skipped keycode %d out of range\n", keycode ); + continue; + } + + entry.code = keycode; + entry.locks = lockstate; + entry.identifier = lookup_keyidentifier( diki ); + + switch( i ) { + case 6: entry.symbols[3] = lookup_keysymbol( diks[3] ); + case 5: entry.symbols[2] = lookup_keysymbol( diks[2] ); + case 4: entry.symbols[1] = lookup_keysymbol( diks[1] ); + case 3: entry.symbols[0] = lookup_keysymbol( diks[0] ); + + /* fall through */ + } + + switch( i ) { + case 3: entry.symbols[1] = entry.symbols[0]; + case 4: entry.symbols[2] = entry.symbols[0]; + case 5: entry.symbols[3] = entry.symbols[1]; + + /* fall through */ + } + + ret = set_keymap_entry( device, keycode, &entry ); + if( ret ) + return ret; + } +} + +static DFBInputDeviceKeySymbol lookup_keysymbol( char *symbolname ) +{ + int i; + + /* we want uppercase */ + for( i=0; i= 'a' && symbolname[i] <= 'z' ) + symbolname[i] = symbolname[i] - 'a' + 'A'; + + for( i=0; i < sizeof (KeySymbolNames) / sizeof (KeySymbolNames[0]); i++ ) { + if( strcmp( symbolname, KeySymbolNames[i].name ) == 0 ) + return KeySymbolNames[i].symbol; + } + + /* not found, maybe starting with 0x for raw conversion. + * We are already at uppercase. + */ + if( symbolname[0]=='0' && symbolname[1]=='X' ) { + int code=0; + symbolname+=2; + while(*symbolname) { + if( *symbolname >= '0' && *symbolname <= '9' ) { + code = code*16 + *symbolname - '0'; + } else if( *symbolname >= 'A' && *symbolname <= 'F' ) { + code = code*16 + *symbolname - 'A' + 10; + } else { + /* invalid character */ + return DIKS_NULL; + } + symbolname++; + } + return code; + } + + return DIKS_NULL; +} + +static DFBInputDeviceKeyIdentifier lookup_keyidentifier( char *identifiername ) +{ + int i; + + /* we want uppercase */ + for( i=0; i= 'a' && identifiername[i] <= 'z' ) + identifiername[i] = identifiername[i] - 'a' + 'A'; + + for( i=0; i < sizeof (KeyIdentifierNames) / sizeof (KeyIdentifierNames[0]); i++ ) { + if( strcmp( identifiername, KeyIdentifierNames[i].name ) == 0 ) + return KeyIdentifierNames[i].identifier; + } + + return DIKI_UNKNOWN; +} + +static bool +lookup_from_table( CoreInputDevice *device, + DFBInputEvent *event, + DFBInputEventFlags lookup ) +{ + DFBInputDeviceKeymapEntry *entry; + + D_MAGIC_ASSERT( device, CoreInputDevice ); + + D_ASSERT( core_input != NULL ); + D_ASSERT( device != NULL ); + D_ASSERT( device->shared != NULL ); + D_ASSERT( event != NULL ); + + /* fetch the entry from the keymap, possibly calling the driver */ + entry = get_keymap_entry( device, event->key_code ); + if (!entry) + return false; + + /* lookup identifier */ + if (lookup & DIEF_KEYID) + event->key_id = entry->identifier; + + /* lookup symbol */ + if (lookup & DIEF_KEYSYMBOL) { + DFBInputDeviceKeymapSymbolIndex index = + (event->modifiers & DIMM_ALTGR) ? DIKSI_ALT : DIKSI_BASE; + + if (!(event->modifiers & DIMM_SHIFT) ^ !(entry->locks & event->locks)) + index++; + + /* don't modify modifiers */ + if (DFB_KEY_TYPE( entry->symbols[DIKSI_BASE] ) == DIKT_MODIFIER) + event->key_symbol = entry->symbols[DIKSI_BASE]; + else + event->key_symbol = entry->symbols[index]; + } + + return true; +} + +static int +find_key_code_by_id( CoreInputDevice *device, + DFBInputDeviceKeyIdentifier id ) +{ + int i; + InputDeviceKeymap *map; + + D_MAGIC_ASSERT( device, CoreInputDevice ); + + D_ASSERT( core_input != NULL ); + D_ASSERT( device != NULL ); + D_ASSERT( device->shared != NULL ); + + map = &device->shared->keymap; + + for (i=0; inum_entries; i++) { + DFBInputDeviceKeymapEntry *entry = &map->entries[i]; + + if (entry->identifier == id) + return entry->code; + } + + return -1; +} + +static int +find_key_code_by_symbol( CoreInputDevice *device, + DFBInputDeviceKeySymbol symbol ) +{ + int i; + InputDeviceKeymap *map; + + D_MAGIC_ASSERT( device, CoreInputDevice ); + + D_ASSERT( core_input != NULL ); + D_ASSERT( device != NULL ); + D_ASSERT( device->shared != NULL ); + + map = &device->shared->keymap; + + for (i=0; inum_entries; i++) { + int n; + DFBInputDeviceKeymapEntry *entry = &map->entries[i]; + + for (n=0; n<=DIKSI_LAST; n++) + if (entry->symbols[n] == symbol) + return entry->code; + } + + return -1; +} + +#define FIXUP_KEY_FIELDS (DIEF_MODIFIERS | DIEF_LOCKS | \ + DIEF_KEYCODE | DIEF_KEYID | DIEF_KEYSYMBOL) + +/* + * Fill partially missing values for key_code, key_id and key_symbol by + * translating those that are set. Fix modifiers/locks before if not set. + * + * + * There are five valid constellations that give reasonable values. + * (not counting the constellation where everything is set) + * + * Device has no translation table + * 1. key_id is set, key_symbol not + * -> key_code defaults to -1, key_symbol from key_id (up-translation) + * 2. key_symbol is set, key_id not + * -> key_code defaults to -1, key_id from key_symbol (down-translation) + * + * Device has a translation table + * 3. key_code is set + * -> look up key_id and/or key_symbol (key_code being the index) + * 4. key_id is set + * -> look up key_code and possibly key_symbol (key_id being searched for) + * 5. key_symbol is set + * -> look up key_code and key_id (key_symbol being searched for) + * + * Fields remaining will be set to the default, e.g. key_code to -1. + */ +static void +fixup_key_event( CoreInputDevice *device, DFBInputEvent *event ) +{ + int i; + DFBInputEventFlags valid = event->flags & FIXUP_KEY_FIELDS; + DFBInputEventFlags missing = valid ^ FIXUP_KEY_FIELDS; + InputDeviceShared *shared = device->shared; + + D_MAGIC_ASSERT( device, CoreInputDevice ); + + /* Add missing flags */ + event->flags |= missing; + + /* + * Use cached values for modifiers/locks if they are missing. + */ + if (missing & DIEF_MODIFIERS) + event->modifiers = shared->modifiers_l | shared->modifiers_r; + + if (missing & DIEF_LOCKS) + event->locks = shared->locks; + + /* + * With translation table + */ + if (device->shared->keymap.num_entries) { + if (valid & DIEF_KEYCODE) { + lookup_from_table( device, event, missing ); + + missing &= ~(DIEF_KEYID | DIEF_KEYSYMBOL); + } + else if (valid & DIEF_KEYID) { + event->key_code = find_key_code_by_id( device, event->key_id ); + + if (event->key_code != -1) { + lookup_from_table( device, event, missing ); + + missing &= ~(DIEF_KEYCODE | DIEF_KEYSYMBOL); + } + else if (missing & DIEF_KEYSYMBOL) { + event->key_symbol = id_to_symbol( event->key_id, + event->modifiers, + event->locks ); + missing &= ~DIEF_KEYSYMBOL; + } + } + else if (valid & DIEF_KEYSYMBOL) { + event->key_code = find_key_code_by_symbol( device, + event->key_symbol ); + + if (event->key_code != -1) { + lookup_from_table( device, event, missing ); + + missing &= ~(DIEF_KEYCODE | DIEF_KEYID); + } + else { + event->key_symbol = symbol_to_id( event->key_symbol ); + missing &= ~DIEF_KEYSYMBOL; + } + } + } + else { + /* + * Without translation table + */ + if (valid & DIEF_KEYID) { + if (missing & DIEF_KEYSYMBOL) { + event->key_symbol = id_to_symbol( event->key_id, + event->modifiers, + event->locks ); + missing &= ~DIEF_KEYSYMBOL; + } + } + else if (valid & DIEF_KEYSYMBOL) { + event->key_id = symbol_to_id( event->key_symbol ); + missing &= ~DIEF_KEYID; + } + } + + /* + * Clear remaining fields. + */ + if (missing & DIEF_KEYCODE) + event->key_code = -1; + + if (missing & DIEF_KEYID) + event->key_id = DIKI_UNKNOWN; + + if (missing & DIEF_KEYSYMBOL) + event->key_symbol = DIKS_NULL; + + /* + * Update cached values for modifiers. + */ + if (DFB_KEY_TYPE(event->key_symbol) == DIKT_MODIFIER) { + if (event->type == DIET_KEYPRESS) { + switch (event->key_id) { + case DIKI_SHIFT_L: + shared->modifiers_l |= DIMM_SHIFT; + break; + case DIKI_SHIFT_R: + shared->modifiers_r |= DIMM_SHIFT; + break; + case DIKI_CONTROL_L: + shared->modifiers_l |= DIMM_CONTROL; + break; + case DIKI_CONTROL_R: + shared->modifiers_r |= DIMM_CONTROL; + break; + case DIKI_ALT_L: + shared->modifiers_l |= DIMM_ALT; + break; + case DIKI_ALT_R: + shared->modifiers_r |= (event->key_symbol == DIKS_ALTGR) ? DIMM_ALTGR : DIMM_ALT; + break; + case DIKI_META_L: + shared->modifiers_l |= DIMM_META; + break; + case DIKI_META_R: + shared->modifiers_r |= DIMM_META; + break; + case DIKI_SUPER_L: + shared->modifiers_l |= DIMM_SUPER; + break; + case DIKI_SUPER_R: + shared->modifiers_r |= DIMM_SUPER; + break; + case DIKI_HYPER_L: + shared->modifiers_l |= DIMM_HYPER; + break; + case DIKI_HYPER_R: + shared->modifiers_r |= DIMM_HYPER; + break; + default: + ; + } + } + else { + switch (event->key_id) { + case DIKI_SHIFT_L: + shared->modifiers_l &= ~DIMM_SHIFT; + break; + case DIKI_SHIFT_R: + shared->modifiers_r &= ~DIMM_SHIFT; + break; + case DIKI_CONTROL_L: + shared->modifiers_l &= ~DIMM_CONTROL; + break; + case DIKI_CONTROL_R: + shared->modifiers_r &= ~DIMM_CONTROL; + break; + case DIKI_ALT_L: + shared->modifiers_l &= ~DIMM_ALT; + break; + case DIKI_ALT_R: + shared->modifiers_r &= (event->key_symbol == DIKS_ALTGR) ? ~DIMM_ALTGR : ~DIMM_ALT; + break; + case DIKI_META_L: + shared->modifiers_l &= ~DIMM_META; + break; + case DIKI_META_R: + shared->modifiers_r &= ~DIMM_META; + break; + case DIKI_SUPER_L: + shared->modifiers_l &= ~DIMM_SUPER; + break; + case DIKI_SUPER_R: + shared->modifiers_r &= ~DIMM_SUPER; + break; + case DIKI_HYPER_L: + shared->modifiers_l &= ~DIMM_HYPER; + break; + case DIKI_HYPER_R: + shared->modifiers_r &= ~DIMM_HYPER; + break; + default: + ; + } + } + + /* write back to event */ + if (missing & DIEF_MODIFIERS) + event->modifiers = shared->modifiers_l | shared->modifiers_r; + } + + /* + * Update cached values for locks. + */ + if (event->type == DIET_KEYPRESS) { + + /* When we receive a new key press, toggle lock flags */ + if (shared->first_press || shared->last_key != event->key_id) { + switch (event->key_id) { + case DIKI_CAPS_LOCK: + shared->locks ^= DILS_CAPS; + break; + case DIKI_NUM_LOCK: + shared->locks ^= DILS_NUM; + break; + case DIKI_SCROLL_LOCK: + shared->locks ^= DILS_SCROLL; + break; + default: + ; + } + } + + /* write back to event */ + if (missing & DIEF_LOCKS) + event->locks = shared->locks; + + /* store last pressed key */ + shared->last_key = event->key_id; + shared->first_press = false; + } + else if (event->type == DIET_KEYRELEASE) { + + shared->first_press = true; + } + + /* Handle dead keys. */ + if (DFB_KEY_TYPE(shared->last_symbol) == DIKT_DEAD) { + for (i=0; ideadkey == shared->last_symbol) { + for (i=0; map->combos[i].target; i++) { + if (map->combos[i].target == event->key_symbol) { + event->key_symbol = map->combos[i].result; + break; + } + } + break; + } + } + + if (event->type == DIET_KEYRELEASE && + DFB_KEY_TYPE(event->key_symbol) != DIKT_MODIFIER) + shared->last_symbol = event->key_symbol; + } + else + shared->last_symbol = event->key_symbol; +} + +static void +fixup_mouse_event( CoreInputDevice *device, DFBInputEvent *event ) +{ + InputDeviceShared *shared = device->shared; + + D_MAGIC_ASSERT( device, CoreInputDevice ); + + if (event->flags & DIEF_BUTTONS) { + shared->buttons = event->buttons; + } + else { + switch (event->type) { + case DIET_BUTTONPRESS: + shared->buttons |= (1 << event->button); + break; + case DIET_BUTTONRELEASE: + shared->buttons &= ~(1 << event->button); + break; + default: + ; + } + + /* Add missing flag */ + event->flags |= DIEF_BUTTONS; + + event->buttons = shared->buttons; + } + + switch (event->type) { + case DIET_AXISMOTION: + if ((event->flags & DIEF_AXISABS) && event->axis >= 0 && event->axis < shared->axis_num) { + if (!(event->flags & DIEF_MIN) && (shared->axis_info[event->axis].flags & DIAIF_ABS_MIN)) { + event->min = shared->axis_info[event->axis].abs_min; + + event->flags |= DIEF_MIN; + } + + if (!(event->flags & DIEF_MAX) && (shared->axis_info[event->axis].flags & DIAIF_ABS_MAX)) { + event->max = shared->axis_info[event->axis].abs_max; + + event->flags |= DIEF_MAX; + } + } + break; + + default: + break; + } +} + +static DFBInputDeviceKeyIdentifier +symbol_to_id( DFBInputDeviceKeySymbol symbol ) +{ + if (symbol >= 'a' && symbol <= 'z') + return DIKI_A + symbol - 'a'; + + if (symbol >= 'A' && symbol <= 'Z') + return DIKI_A + symbol - 'A'; + + if (symbol >= '0' && symbol <= '9') + return DIKI_0 + symbol - '0'; + + if (symbol >= DIKS_F1 && symbol <= DIKS_F12) + return DIKI_F1 + symbol - DIKS_F1; + + switch (symbol) { + case DIKS_ESCAPE: + return DIKI_ESCAPE; + + case DIKS_CURSOR_LEFT: + return DIKI_LEFT; + + case DIKS_CURSOR_RIGHT: + return DIKI_RIGHT; + + case DIKS_CURSOR_UP: + return DIKI_UP; + + case DIKS_CURSOR_DOWN: + return DIKI_DOWN; + + case DIKS_ALTGR: + return DIKI_ALT_R; + + case DIKS_CONTROL: + return DIKI_CONTROL_L; + + case DIKS_SHIFT: + return DIKI_SHIFT_L; + + case DIKS_ALT: + return DIKI_ALT_L; + + case DIKS_META: + return DIKI_META_L; + + case DIKS_SUPER: + return DIKI_SUPER_L; + + case DIKS_HYPER: + return DIKI_HYPER_L; + + case DIKS_TAB: + return DIKI_TAB; + + case DIKS_ENTER: + return DIKI_ENTER; + + case DIKS_SPACE: + return DIKI_SPACE; + + case DIKS_BACKSPACE: + return DIKI_BACKSPACE; + + case DIKS_INSERT: + return DIKI_INSERT; + + case DIKS_DELETE: + return DIKI_DELETE; + + case DIKS_HOME: + return DIKI_HOME; + + case DIKS_END: + return DIKI_END; + + case DIKS_PAGE_UP: + return DIKI_PAGE_UP; + + case DIKS_PAGE_DOWN: + return DIKI_PAGE_DOWN; + + case DIKS_CAPS_LOCK: + return DIKI_CAPS_LOCK; + + case DIKS_NUM_LOCK: + return DIKI_NUM_LOCK; + + case DIKS_SCROLL_LOCK: + return DIKI_SCROLL_LOCK; + + case DIKS_PRINT: + return DIKI_PRINT; + + case DIKS_PAUSE: + return DIKI_PAUSE; + + case DIKS_BACKSLASH: + return DIKI_BACKSLASH; + + case DIKS_PERIOD: + return DIKI_PERIOD; + + case DIKS_COMMA: + return DIKI_COMMA; + + default: + ; + } + + return DIKI_UNKNOWN; +} + +static DFBInputDeviceKeySymbol +id_to_symbol( DFBInputDeviceKeyIdentifier id, + DFBInputDeviceModifierMask modifiers, + DFBInputDeviceLockState locks ) +{ + bool shift = !(modifiers & DIMM_SHIFT) ^ !(locks & DILS_CAPS); + + if (id >= DIKI_A && id <= DIKI_Z) + return (shift ? DIKS_CAPITAL_A : DIKS_SMALL_A) + id - DIKI_A; + + if (id >= DIKI_0 && id <= DIKI_9) + return DIKS_0 + id - DIKI_0; + + if (id >= DIKI_KP_0 && id <= DIKI_KP_9) + return DIKS_0 + id - DIKI_KP_0; + + if (id >= DIKI_F1 && id <= DIKI_F12) + return DIKS_F1 + id - DIKI_F1; + + switch (id) { + case DIKI_ESCAPE: + return DIKS_ESCAPE; + + case DIKI_LEFT: + return DIKS_CURSOR_LEFT; + + case DIKI_RIGHT: + return DIKS_CURSOR_RIGHT; + + case DIKI_UP: + return DIKS_CURSOR_UP; + + case DIKI_DOWN: + return DIKS_CURSOR_DOWN; + + case DIKI_CONTROL_L: + case DIKI_CONTROL_R: + return DIKS_CONTROL; + + case DIKI_SHIFT_L: + case DIKI_SHIFT_R: + return DIKS_SHIFT; + + case DIKI_ALT_L: + case DIKI_ALT_R: + return DIKS_ALT; + + case DIKI_META_L: + case DIKI_META_R: + return DIKS_META; + + case DIKI_SUPER_L: + case DIKI_SUPER_R: + return DIKS_SUPER; + + case DIKI_HYPER_L: + case DIKI_HYPER_R: + return DIKS_HYPER; + + case DIKI_TAB: + return DIKS_TAB; + + case DIKI_ENTER: + return DIKS_ENTER; + + case DIKI_SPACE: + return DIKS_SPACE; + + case DIKI_BACKSPACE: + return DIKS_BACKSPACE; + + case DIKI_INSERT: + return DIKS_INSERT; + + case DIKI_DELETE: + return DIKS_DELETE; + + case DIKI_HOME: + return DIKS_HOME; + + case DIKI_END: + return DIKS_END; + + case DIKI_PAGE_UP: + return DIKS_PAGE_UP; + + case DIKI_PAGE_DOWN: + return DIKS_PAGE_DOWN; + + case DIKI_CAPS_LOCK: + return DIKS_CAPS_LOCK; + + case DIKI_NUM_LOCK: + return DIKS_NUM_LOCK; + + case DIKI_SCROLL_LOCK: + return DIKS_SCROLL_LOCK; + + case DIKI_PRINT: + return DIKS_PRINT; + + case DIKI_PAUSE: + return DIKS_PAUSE; + + case DIKI_KP_DIV: + return DIKS_SLASH; + + case DIKI_KP_MULT: + return DIKS_ASTERISK; + + case DIKI_KP_MINUS: + return DIKS_MINUS_SIGN; + + case DIKI_KP_PLUS: + return DIKS_PLUS_SIGN; + + case DIKI_KP_ENTER: + return DIKS_ENTER; + + case DIKI_KP_SPACE: + return DIKS_SPACE; + + case DIKI_KP_TAB: + return DIKS_TAB; + + case DIKI_KP_EQUAL: + return DIKS_EQUALS_SIGN; + + case DIKI_KP_DECIMAL: + return DIKS_PERIOD; + + case DIKI_KP_SEPARATOR: + return DIKS_COMMA; + + case DIKI_BACKSLASH: + return DIKS_BACKSLASH; + + case DIKI_EQUALS_SIGN: + return DIKS_EQUALS_SIGN; + + case DIKI_LESS_SIGN: + return DIKS_LESS_THAN_SIGN; + + case DIKI_MINUS_SIGN: + return DIKS_MINUS_SIGN; + + case DIKI_PERIOD: + return DIKS_PERIOD; + + case DIKI_QUOTE_LEFT: + case DIKI_QUOTE_RIGHT: + return DIKS_QUOTATION; + + case DIKI_SEMICOLON: + return DIKS_SEMICOLON; + + case DIKI_SLASH: + return DIKS_SLASH; + + default: + ; + } + + return DIKS_NULL; +} + +static void +release_key( CoreInputDevice *device, DFBInputDeviceKeyIdentifier id ) +{ + DFBInputEvent evt; + + D_MAGIC_ASSERT( device, CoreInputDevice ); + + evt.type = DIET_KEYRELEASE; + + if (DFB_KEY_TYPE(id) == DIKT_IDENTIFIER) { + evt.flags = DIEF_KEYID; + evt.key_id = id; + } + else { + evt.flags = DIEF_KEYSYMBOL; + evt.key_symbol = id; + } + + dfb_input_dispatch( device, &evt ); +} + +static void +flush_keys( CoreInputDevice *device ) +{ + D_MAGIC_ASSERT( device, CoreInputDevice ); + + if (device->shared->modifiers_l) { + if (device->shared->modifiers_l & DIMM_ALT) + release_key( device, DIKI_ALT_L ); + + if (device->shared->modifiers_l & DIMM_CONTROL) + release_key( device, DIKI_CONTROL_L ); + + if (device->shared->modifiers_l & DIMM_HYPER) + release_key( device, DIKI_HYPER_L ); + + if (device->shared->modifiers_l & DIMM_META) + release_key( device, DIKI_META_L ); + + if (device->shared->modifiers_l & DIMM_SHIFT) + release_key( device, DIKI_SHIFT_L ); + + if (device->shared->modifiers_l & DIMM_SUPER) + release_key( device, DIKI_SUPER_L ); + } + + if (device->shared->modifiers_r) { + if (device->shared->modifiers_r & DIMM_ALTGR) + release_key( device, DIKS_ALTGR ); + + if (device->shared->modifiers_r & DIMM_ALT) + release_key( device, DIKI_ALT_R ); + + if (device->shared->modifiers_r & DIMM_CONTROL) + release_key( device, DIKI_CONTROL_R ); + + if (device->shared->modifiers_r & DIMM_HYPER) + release_key( device, DIKI_HYPER_R ); + + if (device->shared->modifiers_r & DIMM_META) + release_key( device, DIKI_META_R ); + + if (device->shared->modifiers_r & DIMM_SHIFT) + release_key( device, DIKI_SHIFT_R ); + + if (device->shared->modifiers_r & DIMM_SUPER) + release_key( device, DIKI_SUPER_R ); + } +} + +static void +dump_primary_layer_surface( CoreDFB *core ) +{ + CoreLayer *layer = dfb_layer_at( DLID_PRIMARY ); + CoreLayerContext *context; + + /* Get the currently active context. */ + if (dfb_layer_get_active_context( layer, &context ) == DFB_OK) { + CoreLayerRegion *region; + + /* Get the first region. */ + if (dfb_layer_context_get_primary_region( context, + false, ®ion ) == DFB_OK) + { + CoreSurface *surface; + + /* Lock the region to avoid tearing due to concurrent updates. */ + dfb_layer_region_lock( region ); + + /* Get the surface of the region. */ + if (dfb_layer_region_get_surface( region, &surface ) == DFB_OK) { + /* Dump the surface contents. */ + dfb_surface_dump_buffer( surface, CSBR_FRONT, dfb_config->screenshot_dir, "dfb" ); + + /* Release the surface. */ + dfb_surface_unref( surface ); + } + + /* Unlock the region. */ + dfb_layer_region_unlock( region ); + + /* Release the region. */ + dfb_layer_region_unref( region ); + } + + /* Release the context. */ + dfb_layer_context_unref( context ); + } +} + +static bool +core_input_filter( CoreInputDevice *device, DFBInputEvent *event ) +{ + D_MAGIC_ASSERT( device, CoreInputDevice ); + + if (dfb_system_input_filter( device, event )) + return true; + + if (event->type == DIET_KEYPRESS) { + switch (event->key_symbol) { + case DIKS_PRINT: + if (!event->modifiers && dfb_config->screenshot_dir) { + dump_primary_layer_surface( device->core ); + return true; + } + break; + + case DIKS_BACKSPACE: + if (event->modifiers == DIMM_META) + direct_trace_print_stacks(); + + break; + + case DIKS_ESCAPE: + if (event->modifiers == DIMM_META) { +#if FUSION_BUILD_MULTI + DFBResult ret; + CoreLayer *layer = dfb_layer_at( DLID_PRIMARY ); + CoreLayerContext *context; + + /* Get primary (shared) context. */ + ret = dfb_layer_get_primary_context( layer, + false, &context ); + if (ret) + return false; + + /* Activate the context. */ + dfb_layer_activate_context( layer, context ); + + /* Release the context. */ + dfb_layer_context_unref( context ); + +#else + kill( 0, SIGINT ); +#endif + + return true; + } + break; + + default: + break; + } + } + + return false; +} + diff --git a/Source/DirectFB/src/core/input.h b/Source/DirectFB/src/core/input.h new file mode 100755 index 0000000..0e21e2c --- /dev/null +++ b/Source/DirectFB/src/core/input.h @@ -0,0 +1,203 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __INPUT_H__ +#define __INPUT_H__ + +#include +#include + +#include + +#include + +#include + + + +DECLARE_MODULE_DIRECTORY( dfb_input_modules ); + + +/* + * Increase this number when changes result in binary incompatibility! + */ +#define DFB_INPUT_DRIVER_ABI_VERSION 7 + +#define DFB_INPUT_DRIVER_INFO_NAME_LENGTH 48 +#define DFB_INPUT_DRIVER_INFO_VENDOR_LENGTH 64 + + +typedef struct { + int major; /* major version */ + int minor; /* minor version */ +} InputDriverVersion; /* major.minor, e.g. 0.1 */ + +typedef struct { + InputDriverVersion version; + + char name[DFB_INPUT_DRIVER_INFO_NAME_LENGTH]; + /* Name of driver, + e.g. 'Serial Mouse Driver' */ + + char vendor[DFB_INPUT_DRIVER_INFO_VENDOR_LENGTH]; + /* Vendor (or author) of the driver, + e.g. 'directfb.org' or 'Sven Neumann' */ +} InputDriverInfo; + +typedef struct { + unsigned int prefered_id; /* Prefered predefined input device id, + e.g. DIDID_MOUSE */ + + DFBInputDeviceDescription desc; /* Capabilities, type, etc. */ + DFBInputDeviceState state; +} InputDeviceInfo; + +typedef struct { + int (*GetAvailable) (void); + void (*GetDriverInfo) (InputDriverInfo *driver_info); + DFBResult (*OpenDevice) (CoreInputDevice *device, + unsigned int number, + InputDeviceInfo *device_info, + void **driver_data); + DFBResult (*GetKeymapEntry) (CoreInputDevice *device, + void *driver_data, + DFBInputDeviceKeymapEntry *entry); + void (*CloseDevice) (void *driver_data); + + DFBResult (*GetAxisInfo) (CoreInputDevice *device, + void *driver_data, + DFBInputDeviceAxisIdentifier axis, + DFBInputDeviceAxisInfo *ret_info); + + DFBResult (*SetSensitivity) (CoreInputDevice *device, + void *driver_data, + int sensitivity ); +} InputDriverFuncs; + + +typedef DFBEnumerationResult (*InputDeviceCallback) (CoreInputDevice *device, + void *ctx); + +void dfb_input_enumerate_devices( InputDeviceCallback callback, + void *ctx, + DFBInputDeviceCapabilities caps ); + + +DirectResult dfb_input_attach ( CoreInputDevice *device, + ReactionFunc func, + void *ctx, + Reaction *reaction ); + +DirectResult dfb_input_detach ( CoreInputDevice *device, + Reaction *reaction ); + +DirectResult dfb_input_attach_global( CoreInputDevice *device, + int index, + void *ctx, + GlobalReaction *reaction ); + +DirectResult dfb_input_detach_global( CoreInputDevice *device, + GlobalReaction *reaction ); + + +DFBResult dfb_input_add_global ( ReactionFunc func, + int *ret_index ); + +DFBResult dfb_input_set_global ( ReactionFunc func, + int index ); + + +void dfb_input_dispatch ( CoreInputDevice *device, + DFBInputEvent *event ); + + + +void dfb_input_device_description( const CoreInputDevice *device, + DFBInputDeviceDescription *desc ); + +DFBInputDeviceID dfb_input_device_id ( const CoreInputDevice *device ); + +CoreInputDevice *dfb_input_device_at ( DFBInputDeviceID id ); + + + +DFBResult dfb_input_device_get_keymap_entry( CoreInputDevice *device, + int keycode, + DFBInputDeviceKeymapEntry *entry ); + +DFBResult dfb_input_device_set_keymap_entry( CoreInputDevice *device, + int keycode, + DFBInputDeviceKeymapEntry *entry ); + +DFBResult dfb_input_device_load_keymap ( CoreInputDevice *device, + char *filename ); + +DFBResult dfb_input_device_reload_keymap ( CoreInputDevice *device ); + +DFBResult dfb_input_device_set_sensitivity( CoreInputDevice *device, + int sensitivity ); + +DFBResult dfb_input_rescan_devices( CoreDFB *core ); + +DFBResult dfb_input_device_disconnected( CoreInputDevice *device ); +DFBResult dfb_input_device_reconnected ( CoreInputDevice *device ); + +DFBResult dfb_input_device_get_state( const CoreInputDevice *device, + DFBInputDeviceState *ret_state ); + + + +typedef enum { + CICNF_NONE = 0x00000000, + + CICNF_NEW_DEVICE = 0x00000001, + + CICNF_ALL = 0x00000001, +} CoreInputCoreNotificationFlags; + +typedef struct { + CoreInputCoreNotificationFlags flags; + + DFBInputDeviceID device_id; +} CoreInputCoreNotification; + + +DFBResult dfb_input_core_attach( CoreDFB *core, + ReactionFunc func, + void *ctx, + Reaction *reaction ); + +DFBResult dfb_input_core_detach( CoreDFB *core, + Reaction *reaction ); +/* global reactions */ + +typedef enum { + DFB_WINDOWSTACK_INPUTDEVICE_LISTENER +} DFB_INPUT_GLOBALS; + +#endif diff --git a/Source/DirectFB/src/core/input_driver.h b/Source/DirectFB/src/core/input_driver.h new file mode 100755 index 0000000..41c4e0e --- /dev/null +++ b/Source/DirectFB/src/core/input_driver.h @@ -0,0 +1,103 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __INPUT_DRIVER_H__ +#define __INPUT_DRIVER_H__ + +#include + + +static int +driver_get_available( void ); + +static void +driver_get_info( InputDriverInfo *info ); + +static DFBResult +driver_open_device( CoreInputDevice *device, + unsigned int number, + InputDeviceInfo *info, + void **driver_data ); + +static DFBResult +driver_get_keymap_entry( CoreInputDevice *device, + void *driver_data, + DFBInputDeviceKeymapEntry *entry ); + +#ifdef DFB_INPUTDRIVER_HAS_AXIS_INFO +static DFBResult +driver_get_axis_info( CoreInputDevice *device, + void *driver_data, + DFBInputDeviceAxisIdentifier axis, + DFBInputDeviceAxisInfo *ret_info ); +#endif + +static void +driver_close_device( void *driver_data ); + +#ifdef DFB_INPUTDRIVER_HAS_SENSITIVITY +static DFBResult +driver_set_sensitivity( CoreInputDevice *device, + void *driver_data, + int sensitivity ); +#endif + +static const InputDriverFuncs driver_funcs = { + .GetAvailable = driver_get_available, + .GetDriverInfo = driver_get_info, + .OpenDevice = driver_open_device, + .GetKeymapEntry = driver_get_keymap_entry, + .CloseDevice = driver_close_device, + +#ifdef DFB_INPUTDRIVER_HAS_AXIS_INFO + .GetAxisInfo = driver_get_axis_info, +#endif + +#ifdef DFB_INPUTDRIVER_HAS_SENSITIVITY + .SetSensitivity = driver_set_sensitivity, +#endif +}; + +#define DFB_INPUT_DRIVER(shortname) \ +__attribute__((constructor)) void directfb_##shortname##_ctor( void ); \ +__attribute__((destructor)) void directfb_##shortname##_dtor( void ); \ + \ +void \ +directfb_##shortname##_ctor( void ) \ +{ \ + direct_modules_register( &dfb_input_modules, DFB_INPUT_DRIVER_ABI_VERSION, \ + #shortname, &driver_funcs ); \ +} \ + \ +void \ +directfb_##shortname##_dtor( void ) \ +{ \ + direct_modules_unregister( &dfb_input_modules, #shortname ); \ +} + +#endif diff --git a/Source/DirectFB/src/core/layer_context.c b/Source/DirectFB/src/core/layer_context.c new file mode 100755 index 0000000..1dcccc8 --- /dev/null +++ b/Source/DirectFB/src/core/layer_context.c @@ -0,0 +1,1947 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include +#include + +#include + +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + + +D_DEBUG_DOMAIN( Core_LayerContext, "Core/LayerContext", "DirectFB Display Layer Context" ); + +/**********************************************************************************************************************/ + +static void init_region_config ( CoreLayerContext *context, + CoreLayerRegionConfig *config ); + +static void build_updated_config( CoreLayer *layer, + CoreLayerContext *context, + const DFBDisplayLayerConfig *update, + CoreLayerRegionConfig *ret_config, + CoreLayerRegionConfigFlags *ret_flags ); + +static DFBResult allocate_surface ( CoreLayer *layer, + CoreLayerRegion *region, + CoreLayerRegionConfig *config ); + +static DFBResult reallocate_surface ( CoreLayer *layer, + CoreLayerRegion *region, + CoreLayerRegionConfig *config ); + +static DFBResult deallocate_surface ( CoreLayer *layer, + CoreLayerRegion *region ); + +static void screen_rectangle ( CoreLayerContext *context, + const DFBLocation *location, + DFBRectangle *rect ); + +/**********************************************************************************************************************/ + +static void +context_destructor( FusionObject *object, bool zombie, void *ctx ) +{ + CoreLayerContext *context = (CoreLayerContext*) object; + CoreLayer *layer = dfb_layer_at( context->layer_id ); + CoreLayerShared *shared = layer->shared; + + (void) shared; + + D_DEBUG_AT( Core_LayerContext, "*~ destroying context %p (%s, %sactive%s)\n", + context, shared->description.name, context->active ? "" : "in", + zombie ? " - ZOMBIE" : ""); + + D_MAGIC_ASSERT( context, CoreLayerContext ); + + /* Remove the context from the layer's context stack. */ + dfb_layer_remove_context( layer, context ); + + /* + * Detach input devices before taking the context lock to prevent a + * deadlock between windowstack destruction and input event processing. + */ + if (context->stack) + dfb_windowstack_detach_devices( context->stack ); + + dfb_layer_context_lock( context ); + + /* Destroy the window stack. */ + if (context->stack) { + dfb_windowstack_destroy( context->stack ); + context->stack = NULL; + } + + /* Destroy the region vector. */ + fusion_vector_destroy( &context->regions ); + + /* Deinitialize the lock. */ + fusion_skirmish_destroy( &context->lock ); + + /* Free clip regions. */ + if (context->primary.config.clips) + SHFREE( context->shmpool, context->primary.config.clips ); + + D_MAGIC_CLEAR( context ); + + /* Destroy the object. */ + fusion_object_destroy( object ); +} + +/**********************************************************************************************************************/ + +FusionObjectPool * +dfb_layer_context_pool_create( const FusionWorld *world ) +{ + return fusion_object_pool_create( "Layer Context Pool", + sizeof(CoreLayerContext), + sizeof(CoreLayerContextNotification), + context_destructor, NULL, world ); +} + +/**********************************************************************************************************************/ + +static void +update_stack_geometry( CoreLayerContext *context ) +{ + DFBDimension size; + int rotation; + CoreLayerRegion *region; + CoreSurface *surface; + + D_MAGIC_ASSERT( context, CoreLayerContext ); + + rotation = context->rotation; + + switch (rotation) { + default: + D_BUG( "invalid rotation %d", rotation ); + case 0: + case 180: + size.w = context->config.width; + size.h = context->config.height; + break; + + case 90: + case 270: + size.w = context->config.height; + size.h = context->config.width; + break; + } + + region = context->primary.region; + if (region) { + surface = region->surface; + if (surface) { + D_MAGIC_ASSERT( surface, CoreSurface ); + + rotation -= surface->rotation; + if (rotation < 0) + rotation += 360; + } + } + + dfb_windowstack_resize( context->stack, size.w, size.h, rotation ); +} + +DFBResult +dfb_layer_context_init( CoreLayerContext *context, + CoreLayer *layer ) +{ + CoreLayerShared *shared; + + D_ASSERT( context != NULL ); + D_ASSERT( layer != NULL ); + D_ASSERT( layer->shared != NULL ); + + shared = layer->shared; + + D_DEBUG_AT( Core_LayerContext, "%s( %p, %p [%s] )\n", __FUNCTION__, context, layer, shared->description.name ); + + context->shmpool = shared->shmpool; + + /* Initialize the lock. */ + if (fusion_skirmish_init( &context->lock, "Layer Context", dfb_core_world(layer->core) )) { + fusion_object_destroy( &context->object ); + return DFB_FUSION; + } + + /* Initialize the region vector. */ + fusion_vector_init( &context->regions, 4, context->shmpool ); + + /* Store layer ID, default configuration and default color adjustment. */ + context->layer_id = shared->layer_id; + context->config = shared->default_config; + context->adjustment = shared->default_adjustment; + context->rotation = dfb_config->layers[dfb_layer_id_translated(layer)].rotate; + + /* Initialize screen location. */ + context->screen.location.x = 0.0f; + context->screen.location.y = 0.0f; + context->screen.location.w = 1.0f; + context->screen.location.h = 1.0f; + + if (D_FLAGS_IS_SET( shared->description.caps, DLCAPS_SCREEN_LOCATION )) + context->screen.mode = CLLM_LOCATION; + else if (D_FLAGS_IS_SET( shared->description.caps, DLCAPS_SCREEN_POSITION )) + context->screen.mode = CLLM_CENTER; + + /* Change global reaction lock. */ + fusion_object_set_lock( &context->object, &context->lock ); + + D_MAGIC_SET( context, CoreLayerContext ); + + /* Initialize the primary region's configuration. */ + init_region_config( context, &context->primary.config ); + + /* Activate the object. */ + fusion_object_activate( &context->object ); + + + dfb_layer_context_lock( context ); + + /* Create the window stack. */ + context->stack = dfb_windowstack_create( context ); + if (!context->stack) { + dfb_layer_context_unlock( context ); + dfb_layer_context_unref( context ); + return D_OOSHM(); + } + + /* Tell the window stack about its size. */ + update_stack_geometry( context ); + + dfb_layer_context_unlock( context ); + + return DFB_OK; +} + +DFBResult +dfb_layer_context_activate( CoreLayerContext *context ) +{ + DFBResult ret; + int index; + CoreLayer *layer; + CoreLayerRegion *region; + + D_DEBUG_AT( Core_LayerContext, "%s( %p )\n", __FUNCTION__, context ); + + D_MAGIC_ASSERT( context, CoreLayerContext ); + + layer = dfb_layer_at( context->layer_id ); + + D_ASSERT( layer != NULL ); + D_ASSERT( layer->funcs != NULL ); + + /* Lock the context. */ + if (dfb_layer_context_lock( context )) + return DFB_FUSION; + + D_ASSUME( !context->active ); + + if (context->active) { + dfb_layer_context_unlock( context ); + return DFB_OK; + } + + /* Iterate through all regions. */ + fusion_vector_foreach (region, index, context->regions) { + /* Activate each region. */ + if (dfb_layer_region_activate( region )) + D_WARN( "could not activate region!" ); + + if (region->surface && region->surface->num_buffers == 0) { + D_ASSERT( region->surface_lock.buffer == NULL ); + + ret = reallocate_surface( layer, region, ®ion->config ); + if (ret) + D_DERROR( ret, "Core/Layers: Reallocation of layer surface failed!\n" ); + } + } + + context->active = true; + + /* set new adjustment */ + if (layer->funcs->SetColorAdjustment) + layer->funcs->SetColorAdjustment( layer, layer->driver_data, + layer->layer_data, &context->adjustment ); + + /* Resume window stack. */ + if (context->stack) { + CoreWindowStack *stack = context->stack; + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + + if (stack->flags & CWSF_INITIALIZED) + dfb_wm_set_active( stack, true ); + } + + /* Unlock the context. */ + dfb_layer_context_unlock( context ); + + return DFB_OK; +} + +DFBResult +dfb_layer_context_deactivate( CoreLayerContext *context ) +{ + int index; + CoreLayerRegion *region; + + D_MAGIC_ASSERT( context, CoreLayerContext ); + + /* Lock the context. */ + if (dfb_layer_context_lock( context )) + return DFB_FUSION; + + D_DEBUG_AT( Core_LayerContext, "%s( %p )\n", __FUNCTION__, context ); + + D_ASSUME( context->active ); + + if (!context->active) { + dfb_layer_context_unlock( context ); + return DFB_OK; + } + + /* Iterate through all regions. */ + fusion_vector_foreach (region, index, context->regions) { + /* Deactivate each region. */ + dfb_layer_region_deactivate( region ); + } + + context->active = false; + + /* Suspend window stack. */ + if (context->stack) { + CoreWindowStack *stack = context->stack; + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + + if (stack->flags & CWSF_ACTIVATED) + dfb_wm_set_active( stack, false ); + } + + /* Unlock the context. */ + dfb_layer_context_unlock( context ); + + return DFB_OK; +} + +DFBResult +dfb_layer_context_add_region( CoreLayerContext *context, + CoreLayerRegion *region ) +{ + D_DEBUG_AT( Core_LayerContext, "%s( %p, %p )\n", __FUNCTION__, context, region ); + + D_MAGIC_ASSERT( context, CoreLayerContext ); + D_ASSERT( region != NULL ); + + /* Lock the context. */ + if (dfb_layer_context_lock( context )) + return DFB_FUSION; + + D_ASSUME( ! fusion_vector_contains( &context->regions, region ) ); + + if (fusion_vector_contains( &context->regions, region )) { + dfb_layer_context_unlock( context ); + return DFB_OK; + } + + /* Add region to vector. */ + if (fusion_vector_add( &context->regions, region )) { + dfb_layer_context_unlock( context ); + return DFB_FUSION; + } + + /* Inherit state from context. */ + if (context->active) + region->state |= CLRSF_ACTIVE; + + /* Unlock the context. */ + dfb_layer_context_unlock( context ); + + return DFB_OK; +} + +DFBResult +dfb_layer_context_remove_region( CoreLayerContext *context, + CoreLayerRegion *region ) +{ + int index; + + D_MAGIC_ASSERT( context, CoreLayerContext ); + D_ASSERT( region != NULL ); + + /* Lock the context. */ + if (dfb_layer_context_lock( context )) + return DFB_FUSION; + + D_ASSUME( fusion_vector_contains( &context->regions, region ) ); + + /* Lookup region. */ + index = fusion_vector_index_of( &context->regions, region ); + if (index < 0) { + dfb_layer_context_unlock( context ); + return DFB_OK; + } + + /* Remove region from vector. */ + fusion_vector_remove( &context->regions, index ); + + /* Check if the primary region is removed. */ + if (region == context->primary.region) + context->primary.region = NULL; + + /* Unlock the context. */ + dfb_layer_context_unlock( context ); + + return DFB_OK; +} + +DFBResult +dfb_layer_context_get_primary_region( CoreLayerContext *context, + bool create, + CoreLayerRegion **ret_region ) +{ + DFBResult ret = DFB_OK; + + D_DEBUG_AT( Core_LayerContext, "%s( %p, %screate )\n", __FUNCTION__, context, create ? "" : "DON'T " ); + + D_MAGIC_ASSERT( context, CoreLayerContext ); + D_ASSERT( ret_region != NULL ); + + /* Lock the context. */ + if (dfb_layer_context_lock( context )) + return DFB_FUSION; + +restart: + while (context->primary.region) { + /* Increase the primary region's reference counter. */ + ret = dfb_layer_region_ref( context->primary.region ); + if (ret == DFB_OK) + break; + + dfb_layer_context_unlock( context ); + + if (ret == DFB_LOCKED) { + //sched_yield(); + usleep( 10000 ); + + if (dfb_layer_context_lock( context )) + return DFB_FUSION; + } + else + return DFB_FUSION; + } + + if (!context->primary.region) { + if (create) { + CoreLayerRegion *region; + + /* Unlock the context. */ + dfb_layer_context_unlock( context ); + + /* Create the primary region. */ + ret = dfb_layer_region_create( context, ®ion ); + if (ret) { + D_ERROR( "DirectFB/core/layers: Could not create primary region!\n" ); + return ret; + } + + /* Lock the context again. */ + if (dfb_layer_context_lock( context )) { + dfb_layer_region_unref( region ); + return DFB_FUSION; + } + + /* Check for race. */ + if (context->primary.region) { + dfb_layer_region_unref( region ); + goto restart; + } + + /* Set the region configuration. */ + ret = dfb_layer_region_set_configuration( region, + &context->primary.config, + CLRCF_ALL ); + if (ret) { + D_DERROR( ret, "DirectFB/core/layers: " + "Could not set primary region config!\n" ); + dfb_layer_region_unref( region ); + dfb_layer_context_unlock( context ); + return ret; + } + + /* Remember the primary region. */ + context->primary.region = region; + + /* Allocate surface, enable region etc. */ + ret = dfb_layer_context_set_configuration( context, &context->config ); + if (ret) { + D_DERROR( ret, "DirectFB/core/layers: " + "Could not set layer context config!\n" ); + context->primary.region = NULL; + dfb_layer_region_unref( region ); + dfb_layer_context_unlock( context ); + return ret; + } + } + else { + dfb_layer_context_unlock( context ); + return DFB_TEMPUNAVAIL; + } + } + + /* Return region. */ + *ret_region = context->primary.region; + + /* Unlock the context. */ + dfb_layer_context_unlock( context ); + + return DFB_OK; +} + +/* + * configuration management + */ +DFBResult +dfb_layer_context_test_configuration( CoreLayerContext *context, + const DFBDisplayLayerConfig *config, + DFBDisplayLayerConfigFlags *ret_failed ) +{ + DFBResult ret = DFB_OK; + CoreLayer *layer; + CoreLayerRegionConfig region_config; + CoreLayerRegionConfigFlags failed; + const DisplayLayerFuncs *funcs; + + D_DEBUG_AT( Core_LayerContext, "%s( %p, %p, %p )\n", __FUNCTION__, context, config, ret_failed ); + + D_MAGIC_ASSERT( context, CoreLayerContext ); + D_ASSERT( config != NULL ); + + /* Lock the context. */ + if (dfb_layer_context_lock( context )) + return DFB_FUSION; + + layer = dfb_layer_at( context->layer_id ); + + D_ASSERT( layer != NULL ); + D_ASSERT( layer->shared != NULL ); + D_ASSERT( layer->funcs != NULL ); + D_ASSERT( layer->funcs->TestRegion != NULL ); + + funcs = layer->funcs; + + /* Build a new region configuration with the changes. */ + build_updated_config( layer, context, config, ®ion_config, NULL ); + + /* Unlock the context. */ + dfb_layer_context_unlock( context ); + + + /* Test the region configuration. */ + if (region_config.buffermode == DLBM_WINDOWS) { + if (! D_FLAGS_IS_SET( layer->shared->description.caps, DLCAPS_WINDOWS )) { + failed = CLRCF_BUFFERMODE; + ret = DFB_UNSUPPORTED; + } + } + else { + /* Let the driver examine the modified configuration. */ + ret = funcs->TestRegion( layer, layer->driver_data, layer->layer_data, + ®ion_config, &failed ); + } + + /* Return flags for failing entries. */ + if (ret_failed) { + DFBDisplayLayerConfigFlags flags = DLCONF_NONE; + + /* Translate flags. */ + if (ret != DFB_OK) { + if (failed & CLRCF_WIDTH) + flags |= DLCONF_WIDTH; + + if (failed & CLRCF_HEIGHT) + flags |= DLCONF_HEIGHT; + + if (failed & CLRCF_FORMAT) + flags |= DLCONF_PIXELFORMAT; + + if (failed & CLRCF_BUFFERMODE) + flags |= DLCONF_BUFFERMODE; + + if (failed & CLRCF_OPTIONS) + flags |= DLCONF_OPTIONS; + + if (failed & CLRCF_SOURCE_ID) + flags |= DLCONF_SOURCE; + + if (failed & CLRCF_SURFACE_CAPS) + flags |= DLCONF_SURFACE_CAPS; + } + + *ret_failed = flags; + } + + return ret; +} + +DFBResult +dfb_layer_context_set_configuration( CoreLayerContext *context, + const DFBDisplayLayerConfig *config ) +{ + int i; + DFBResult ret; + CoreLayer *layer; + CoreLayerShared *shared; + CoreLayerRegionConfig region_config; + CoreLayerRegionConfigFlags flags; + const DisplayLayerFuncs *funcs; + + D_DEBUG_AT( Core_LayerContext, "%s( %p, %p )\n", __FUNCTION__, context, config ); + + D_MAGIC_ASSERT( context, CoreLayerContext ); + D_ASSERT( config != NULL ); + + /* Lock the context. */ + if (dfb_layer_context_lock( context )) + return DFB_FUSION; + + layer = dfb_layer_at( context->layer_id ); + + D_ASSERT( layer != NULL ); + D_ASSERT( layer->shared != NULL ); + D_ASSERT( layer->funcs != NULL ); + D_ASSERT( layer->funcs->TestRegion != NULL ); + + shared = layer->shared; + funcs = layer->funcs; + + /* Build a new region configuration with the changes. */ + build_updated_config( layer, context, config, ®ion_config, &flags ); + + /* Test the region configuration first. */ + if (region_config.buffermode == DLBM_WINDOWS) { + if (! D_FLAGS_IS_SET( shared->description.caps, DLCAPS_WINDOWS )) { + dfb_layer_context_unlock( context ); + return DFB_UNSUPPORTED; + } + } + else { + ret = funcs->TestRegion( layer, layer->driver_data, layer->layer_data, + ®ion_config, NULL ); + if (ret) { + dfb_layer_context_unlock( context ); + return ret; + } + } + + /* Set the region configuration. */ + if (context->primary.region) { + CoreLayerRegion *region = context->primary.region; + + /* Add local reference. */ + if (dfb_layer_region_ref( region )) { + dfb_layer_context_unlock( context ); + return DFB_FUSION; + } + + /* Lock the region. */ + if (dfb_layer_region_lock( region )) { + dfb_layer_region_unref( region ); + dfb_layer_context_unlock( context ); + return DFB_FUSION; + } + + /* Normal buffer mode? */ + if (region_config.buffermode != DLBM_WINDOWS) { + bool surface = shared->description.caps & DLCAPS_SURFACE; + CoreLayerRegionStateFlags configured = region->state & CLRSF_CONFIGURED; + + if (shared->description.caps & DLCAPS_SOURCES) { + for (i=0; idescription.sources; i++) { + if (shared->sources[i].description.source_id == region_config.source_id) + break; + } + + D_ASSERT( i < shared->description.sources ); + + surface = shared->sources[i].description.caps & DDLSCAPS_SURFACE; + } + + D_FLAGS_CLEAR( region->state, CLRSF_CONFIGURED ); + + /* Unlock the region surface */ + if (region->surface) { + if (D_FLAGS_IS_SET( region->state, CLRSF_REALIZED )) { + if (!D_FLAGS_IS_SET( region->state, CLRSF_FROZEN )) + D_ASSUME( region->surface_lock.buffer != NULL ); + + if (region->surface_lock.buffer) + dfb_surface_unlock_buffer( region->surface, ®ion->surface_lock ); + } + } + + /* (Re)allocate the region's surface. */ + if (surface) { + flags |= CLRCF_SURFACE | CLRCF_PALETTE; + + if (region->surface) { + ret = reallocate_surface( layer, region, ®ion_config ); + if (ret) + D_DERROR( ret, "Core/Layers: Reallocation of layer surface failed!\n" ); + } + else { + ret = allocate_surface( layer, region, ®ion_config ); + if (ret) + D_DERROR( ret, "Core/Layers: Allocation of layer surface failed!\n" ); + } + + if (ret) { + dfb_layer_region_unlock( region ); + dfb_layer_region_unref( region ); + dfb_layer_context_unlock( context ); + return ret; + } + } + else if (region->surface) + deallocate_surface( layer, region ); + + region->state |= configured; + + /* Set the new region configuration. */ + dfb_layer_region_set_configuration( region, ®ion_config, flags ); + + /* Enable the primary region. */ + if (! D_FLAGS_IS_SET( region->state, CLRSF_ENABLED )) + dfb_layer_region_enable( region ); + } + else { + /* Disable and deallocate the primary region. */ + if (D_FLAGS_IS_SET( region->state, CLRSF_ENABLED )) { + dfb_layer_region_disable( region ); + + if (region->surface) + deallocate_surface( layer, region ); + } + } + + /* Unlock the region and give up the local reference. */ + dfb_layer_region_unlock( region ); + dfb_layer_region_unref( region ); + } + + /* Remember new region config. */ + context->primary.config = region_config; + + /* + * Write back modified entries. + */ + if (config->flags & DLCONF_WIDTH) + context->config.width = config->width; + + if (config->flags & DLCONF_HEIGHT) + context->config.height = config->height; + + if (config->flags & DLCONF_PIXELFORMAT) + context->config.pixelformat = config->pixelformat; + + if (config->flags & DLCONF_BUFFERMODE) + context->config.buffermode = config->buffermode; + + if (config->flags & DLCONF_OPTIONS) + context->config.options = config->options; + + if (config->flags & DLCONF_SOURCE) + context->config.source = config->source; + + if (config->flags & DLCONF_SURFACE_CAPS) + context->config.surface_caps = config->surface_caps; + + /* Update the window stack. */ + if (context->stack) { + CoreWindowStack *stack = context->stack; + + /* Update hardware flag. */ + stack->hw_mode = (region_config.buffermode == DLBM_WINDOWS); + + /* Tell the windowing core about the new size. */ + if (config->flags & (DLCONF_WIDTH | DLCONF_HEIGHT | + DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE | DLCONF_SURFACE_CAPS)) + { + update_stack_geometry( context ); + + /* FIXME: call only if really needed */ + dfb_windowstack_repaint_all( stack ); + } + } + + /* Unlock the context. */ + dfb_layer_context_unlock( context ); + + return DFB_OK; +} + +DFBResult +dfb_layer_context_get_configuration( CoreLayerContext *context, + DFBDisplayLayerConfig *config ) +{ + D_DEBUG_AT( Core_LayerContext, "%s( %p, %p )\n", __FUNCTION__, context, config ); + + D_MAGIC_ASSERT( context, CoreLayerContext ); + D_ASSERT( config != NULL ); + + *config = context->config; + + return DFB_OK; +} + +static DFBResult +update_primary_region_config( CoreLayerContext *context, + CoreLayerRegionConfig *config, + CoreLayerRegionConfigFlags flags ) +{ + DFBResult ret = DFB_OK; + + D_DEBUG_AT( Core_LayerContext, "%s( %p, %p, 0x%08x )\n", __FUNCTION__, context, config, flags ); + + D_MAGIC_ASSERT( context, CoreLayerContext ); + D_ASSERT( config != NULL ); + + if (context->primary.region) { + /* Set the new configuration. */ + ret = dfb_layer_region_set_configuration( context->primary.region, config, flags ); + } + else { + CoreLayer *layer = dfb_layer_at( context->layer_id ); + + D_ASSERT( layer->funcs != NULL ); + D_ASSERT( layer->funcs->TestRegion != NULL ); + + /* Just test the new configuration. */ + ret = layer->funcs->TestRegion( layer, layer->driver_data, + layer->layer_data, config, NULL ); + } + + if (ret) + return ret; + + /* Remember the configuration. */ + context->primary.config = *config; + + return DFB_OK; +} + +DFBResult +dfb_layer_context_set_src_colorkey( CoreLayerContext *context, + u8 r, u8 g, u8 b, int index ) +{ + DFBResult ret; + CoreLayerRegionConfig config; + + D_DEBUG_AT( Core_LayerContext, "%s( %p, %02x %02x %02x - %d )\n", __FUNCTION__, context, r, g, b, index ); + + D_MAGIC_ASSERT( context, CoreLayerContext ); + + /* Lock the context. */ + if (dfb_layer_context_lock( context )) + return DFB_FUSION; + + /* Take the current configuration. */ + config = context->primary.config; + + /* Change the color key. */ + config.src_key.r = r; + config.src_key.g = g; + config.src_key.b = b; + + if (index >= 0) + config.src_key.index = index & 0xff; + + /* Try to set the new configuration. */ + ret = update_primary_region_config( context, &config, CLRCF_SRCKEY ); + + /* Unlock the context. */ + dfb_layer_context_unlock( context ); + + return ret; +} + +DFBResult +dfb_layer_context_set_dst_colorkey( CoreLayerContext *context, + u8 r, u8 g, u8 b, int index ) +{ + DFBResult ret; + CoreLayerRegionConfig config; + + D_DEBUG_AT( Core_LayerContext, "%s( %p, %02x %02x %02x - %d )\n", __FUNCTION__, context, r, g, b, index ); + + D_MAGIC_ASSERT( context, CoreLayerContext ); + + /* Lock the context. */ + if (dfb_layer_context_lock( context )) + return DFB_FUSION; + + /* Take the current configuration. */ + config = context->primary.config; + + /* Change the color key. */ + config.dst_key.r = r; + config.dst_key.g = g; + config.dst_key.b = b; + + if (index >= 0) + config.dst_key.index = index & 0xff; + + /* Try to set the new configuration. */ + ret = update_primary_region_config( context, &config, CLRCF_DSTKEY ); + + /* Unlock the context. */ + dfb_layer_context_unlock( context ); + + return ret; +} + +DFBResult +dfb_layer_context_set_sourcerectangle( CoreLayerContext *context, + const DFBRectangle *source ) +{ + DFBResult ret; + CoreLayerRegionConfig config; + CoreLayerRegionConfigFlags flags; + CoreLayer *layer; + + D_DEBUG_AT( Core_LayerContext, "%s( %p, %p )\n", __FUNCTION__, context, source ); + + D_MAGIC_ASSERT( context, CoreLayerContext ); + D_ASSERT( source != NULL ); + + /* Lock the context. */ + if (dfb_layer_context_lock( context )) + return DFB_FUSION; + + /* Take the current configuration. */ + config = context->primary.config; + + /* Do nothing if the source rectangle didn't change. */ + if (DFB_RECTANGLE_EQUAL( config.source, *source )) { + dfb_layer_context_unlock( context ); + return DFB_OK; + } + + /* Check if the new source rectangle is valid. */ + if (source->x < 0 || source->y < 0 || + source->x + source->w > config.width || + source->y + source->h > config.height) { + dfb_layer_context_unlock( context ); + return DFB_INVAREA; + } + + /* Change the source rectangle. */ + config.source = *source; + + flags = CLRCF_SOURCE; + layer = dfb_layer_at( context->layer_id ); + + /* If the display layer does not support scaling and the destination + rectangle size is not the same as the source, change it to match. The + origin is left alone to allow the driver to handle it. */ + if ( !D_FLAGS_IS_SET( layer->shared->description.caps, DLCAPS_SCREEN_SIZE ) && + ( config.dest.w != config.source.w || + config.dest.h != config.source.h ) ) + { + config.dest.w = config.source.w; + config.dest.h = config.source.h; + + flags |= CLRCF_DEST; + } + + /* Try to set the new configuration. */ + ret = update_primary_region_config( context, &config, flags ); + + /* Unlock the context. */ + dfb_layer_context_unlock( context ); + + return ret; +} + +DFBResult +dfb_layer_context_set_screenlocation( CoreLayerContext *context, + const DFBLocation *location ) +{ + DFBResult ret; + CoreLayerRegionConfig config; + + D_DEBUG_AT( Core_LayerContext, "%s( %p, %p )\n", __FUNCTION__, context, location ); + + D_MAGIC_ASSERT( context, CoreLayerContext ); + D_ASSERT( location != NULL ); + + /* Lock the context. */ + if (dfb_layer_context_lock( context )) + return DFB_FUSION; + + /* Do nothing if the location didn't change. */ +/* if (context->screen.mode == CLLM_LOCATION && + DFB_LOCATION_EQUAL( context->screen.location, *location )) + { + dfb_layer_context_unlock( context ); + return DFB_OK; + }*/ + + /* Take the current configuration. */ + config = context->primary.config; + + /* Calculate new absolute screen coordinates. */ + screen_rectangle( context, location, &config.dest ); + + /* Try to set the new configuration. */ + ret = update_primary_region_config( context, &config, CLRCF_DEST ); + if (ret == DFB_OK) { + context->screen.location = *location; + context->screen.rectangle = config.dest; + context->screen.mode = CLLM_LOCATION; + } + + /* Unlock the context. */ + dfb_layer_context_unlock( context ); + + return ret; +} + +DFBResult +dfb_layer_context_set_screenrectangle( CoreLayerContext *context, + const DFBRectangle *rectangle ) +{ + DFBResult ret; + CoreLayerRegionConfig config; + + D_DEBUG_AT( Core_LayerContext, "%s( %p, %p )\n", __FUNCTION__, context, rectangle ); + + D_MAGIC_ASSERT( context, CoreLayerContext ); + + DFB_RECTANGLE_ASSERT( rectangle ); + + /* Lock the context. */ + if (dfb_layer_context_lock( context )) + return DFB_FUSION; + + /* Do nothing if the location didn't change. */ +/* if (context->screen.mode == CLLM_RECTANGLE && + DFB_RECTANGLE_EQUAL( context->screen.rectangle, *rectangle )) + { + dfb_layer_context_unlock( context ); + return DFB_OK; + }*/ + + /* Take the current configuration. */ + config = context->primary.config; + + /* Use supplied absolute screen coordinates. */ + config.dest = *rectangle; + + /* Try to set the new configuration. */ + ret = update_primary_region_config( context, &config, CLRCF_DEST ); + if (ret == DFB_OK) { + context->screen.rectangle = config.dest; + context->screen.mode = CLLM_RECTANGLE; + } + + /* Unlock the context. */ + dfb_layer_context_unlock( context ); + + return ret; +} + +DFBResult +dfb_layer_context_set_screenposition( CoreLayerContext *context, + int x, + int y ) +{ + DFBResult ret; + CoreLayerRegionConfig config; + + D_DEBUG_AT( Core_LayerContext, "%s( %p, %4d,%4d )\n", __FUNCTION__, context, x, y ); + + D_MAGIC_ASSERT( context, CoreLayerContext ); + + /* Lock the context. */ + if (dfb_layer_context_lock( context )) + return DFB_FUSION; + + /* Do nothing if the location didn't change. */ + if (context->primary.config.dest.x == x && context->primary.config.dest.y == y) { + dfb_layer_context_unlock( context ); + return DFB_OK; + } + + /* Take the current configuration. */ + config = context->primary.config; + + /* Set new absolute screen coordinates. */ + config.dest.x = x; + config.dest.y = y; + + /* Try to set the new configuration. */ + ret = update_primary_region_config( context, &config, CLRCF_DEST ); + if (ret == DFB_OK) { + context->screen.rectangle = config.dest; + context->screen.mode = CLLM_POSITION; + } + + /* Unlock the context. */ + dfb_layer_context_unlock( context ); + + return ret; +} + +DFBResult +dfb_layer_context_set_opacity( CoreLayerContext *context, + u8 opacity ) +{ + DFBResult ret; + CoreLayerRegionConfig config; + + D_DEBUG_AT( Core_LayerContext, "%s( %p, %u )\n", __FUNCTION__, context, opacity ); + + D_MAGIC_ASSERT( context, CoreLayerContext ); + + /* Lock the context. */ + if (dfb_layer_context_lock( context )) + return DFB_FUSION; + + /* Do nothing if the opacity didn't change. */ + if (context->primary.config.opacity == opacity) { + dfb_layer_context_unlock( context ); + return DFB_OK; + } + + /* Take the current configuration. */ + config = context->primary.config; + + /* Change the opacity. */ + config.opacity = opacity; + + /* Try to set the new configuration. */ + ret = update_primary_region_config( context, &config, CLRCF_OPACITY ); + if (ret == DFB_OK) + context->primary.config.opacity = opacity; + + /* Unlock the context. */ + dfb_layer_context_unlock( context ); + + return ret; +} + +DFBResult +dfb_layer_context_set_rotation( CoreLayerContext *context, + int rotation ) +{ + D_DEBUG_AT( Core_LayerContext, "%s( %p, %d )\n", __FUNCTION__, context, rotation ); + + D_MAGIC_ASSERT( context, CoreLayerContext ); + + /* Lock the context. */ + if (dfb_layer_context_lock( context )) + return DFB_FUSION; + + /* Do nothing if the rotation didn't change. */ + if (context->rotation != rotation) { + context->rotation = rotation; + + update_stack_geometry( context ); + + dfb_windowstack_repaint_all( context->stack ); + } + + /* Unlock the context. */ + dfb_layer_context_unlock( context ); + + return DFB_OK; +} + +DFBResult +dfb_layer_context_set_coloradjustment( CoreLayerContext *context, + const DFBColorAdjustment *adjustment ) +{ + DFBResult ret; + DFBColorAdjustment adj; + CoreLayer *layer; + + D_DEBUG_AT( Core_LayerContext, "%s( %p, %p )\n", __FUNCTION__, context, adjustment ); + + D_MAGIC_ASSERT( context, CoreLayerContext ); + D_ASSERT( adjustment != NULL ); + + layer = dfb_layer_at( context->layer_id ); + + D_ASSERT( layer != NULL ); + D_ASSERT( layer->funcs != NULL ); + + adj = context->adjustment; + + if (!layer->funcs->SetColorAdjustment) + return DFB_UNSUPPORTED; + + /* if flags are set that are not in the default adjustment */ + if (adjustment->flags & ~context->adjustment.flags) + return DFB_UNSUPPORTED; + + /* take over changed values */ + if (adjustment->flags & DCAF_BRIGHTNESS) adj.brightness = adjustment->brightness; + if (adjustment->flags & DCAF_CONTRAST) adj.contrast = adjustment->contrast; + if (adjustment->flags & DCAF_HUE) adj.hue = adjustment->hue; + if (adjustment->flags & DCAF_SATURATION) adj.saturation = adjustment->saturation; + + /* set new adjustment */ + ret = layer->funcs->SetColorAdjustment( layer, layer->driver_data, + layer->layer_data, &adj ); + if (ret) + return ret; + + /* keep new adjustment */ + context->adjustment = adj; + + return DFB_OK; +} + +DFBResult +dfb_layer_context_get_coloradjustment( CoreLayerContext *context, + DFBColorAdjustment *ret_adjustment ) +{ + D_DEBUG_AT( Core_LayerContext, "%s( %p, %p )\n", __FUNCTION__, context, ret_adjustment ); + + D_MAGIC_ASSERT( context, CoreLayerContext ); + D_ASSERT( ret_adjustment != NULL ); + + *ret_adjustment = context->adjustment; + + return DFB_OK; +} + +DFBResult +dfb_layer_context_set_field_parity( CoreLayerContext *context, + int field ) +{ + DFBResult ret; + CoreLayerRegionConfig config; + + D_DEBUG_AT( Core_LayerContext, "%s( %p, %d )\n", __FUNCTION__, context, field ); + + D_MAGIC_ASSERT( context, CoreLayerContext ); + + /* Lock the context. */ + if (dfb_layer_context_lock( context )) + return DFB_FUSION; + + /* Do nothing if the parity didn't change. */ + if (context->primary.config.parity == field) { + dfb_layer_context_unlock( context ); + return DFB_OK; + } + + /* Take the current configuration. */ + config = context->primary.config; + + /* Change the parity. */ + config.parity = field; + + /* Try to set the new configuration. */ + ret = update_primary_region_config( context, &config, CLRCF_PARITY ); + + /* Unlock the context. */ + dfb_layer_context_unlock( context ); + + return ret; +} + +DFBResult +dfb_layer_context_set_clip_regions( CoreLayerContext *context, + const DFBRegion *regions, + int num_regions, + DFBBoolean positive ) +{ + DFBResult ret; + CoreLayerRegionConfig config; + DFBRegion *clips; + DFBRegion *old_clips; + + D_DEBUG_AT( Core_LayerContext, "%s( %p, %p [%d], %s )\n", __FUNCTION__, + context, regions, num_regions, positive ? "positive" : "negative" ); + + D_MAGIC_ASSERT( context, CoreLayerContext ); + + clips = SHMALLOC( context->shmpool, sizeof(DFBRegion) * num_regions ); + if (!clips) + return D_OOSHM(); + + direct_memcpy( clips, regions, sizeof(DFBRegion) * num_regions ); + + /* Lock the context. */ + if (dfb_layer_context_lock( context )) { + SHFREE( context->shmpool, clips ); + return DFB_FUSION; + } + + /* Take the current configuration. */ + config = context->primary.config; + + /* Remember for freeing later on. */ + old_clips = config.clips; + + /* Change the clip regions. */ + config.clips = clips; + config.num_clips = num_regions; + config.positive = positive; + + /* Try to set the new configuration. */ + ret = update_primary_region_config( context, &config, CLRCF_CLIPS ); + + /* Unlock the context. */ + dfb_layer_context_unlock( context ); + + if (ret) + SHFREE( context->shmpool, clips ); + else if (old_clips) + SHFREE( context->shmpool, old_clips ); + + return ret; +} + +DFBResult +dfb_layer_context_create_window( CoreDFB *core, + CoreLayerContext *context, + const DFBWindowDescription *desc, + CoreWindow **ret_window ) +{ + DFBResult ret; + CoreWindow *window; + CoreWindowStack *stack; + CoreLayer *layer; + + D_DEBUG_AT( Core_LayerContext, "%s( %p, %p, %p, %p )\n", __FUNCTION__, core, context, desc, ret_window ); + + D_MAGIC_ASSERT( context, CoreLayerContext ); + D_ASSERT( context->stack != NULL ); + D_ASSERT( desc != NULL ); + D_ASSERT( ret_window != NULL ); + + layer = dfb_layer_at( context->layer_id ); + + D_ASSERT( layer != NULL ); + D_ASSERT( layer->funcs != NULL ); + + if (dfb_layer_context_lock( context )) + return DFB_FUSION; + + stack = context->stack; + + if (!stack->cursor.set) { + ret = dfb_windowstack_cursor_enable( core, stack, true ); + if (ret) { + dfb_layer_context_unlock( context ); + return ret; + } + } + + ret = dfb_window_create( stack, desc, &window ); + if (ret) { + dfb_layer_context_unlock( context ); + return ret; + } + + *ret_window = window; + + dfb_layer_context_unlock( context ); + + return DFB_OK; +} + +CoreWindow * +dfb_layer_context_find_window( CoreLayerContext *context, DFBWindowID id ) +{ + CoreWindowStack *stack; + CoreWindow *window; + + D_DEBUG_AT( Core_LayerContext, "%s( %p, %u )\n", __FUNCTION__, context, id ); + + D_MAGIC_ASSERT( context, CoreLayerContext ); + D_ASSERT( context->stack != NULL ); + + stack = context->stack; + + if (dfb_layer_context_lock( context )) + return NULL; + + if (dfb_wm_window_lookup( stack, id, &window ) || dfb_window_ref( window )) + window = NULL; + + dfb_layer_context_unlock( context ); + + return window; +} + +CoreWindowStack * +dfb_layer_context_windowstack( const CoreLayerContext *context ) +{ + D_MAGIC_ASSERT( context, CoreLayerContext ); + + return context->stack; +} + +bool +dfb_layer_context_active( const CoreLayerContext *context ) +{ + D_MAGIC_ASSERT( context, CoreLayerContext ); + + return context->active; +} + +DirectResult +dfb_layer_context_lock( CoreLayerContext *context ) +{ + DFBResult ret; + + D_DEBUG_AT( Core_LayerContext, "%s( %p )\n", __FUNCTION__, context ); + + D_MAGIC_ASSERT( context, CoreLayerContext ); + + ret = fusion_skirmish_prevail( &context->lock ); + if (ret == DFB_OK) { + int locked; + + ret = fusion_skirmish_lock_count( &context->lock, &locked ); + if (ret == DFB_OK) + D_DEBUG_AT( Core_LayerContext, " -> locked %dx now\n", locked ); + } + + return ret; +} + +DirectResult +dfb_layer_context_unlock( CoreLayerContext *context ) +{ + D_DEBUG_AT( Core_LayerContext, "%s( %p )\n", __FUNCTION__, context ); + + D_MAGIC_ASSERT( context, CoreLayerContext ); + + return fusion_skirmish_dismiss( &context->lock ); +} + +/**************************************************************************************************/ + +/* + * region config construction + */ +static void +init_region_config( CoreLayerContext *context, + CoreLayerRegionConfig *config ) +{ + D_DEBUG_AT( Core_LayerContext, "%s( %p, %p )\n", __FUNCTION__, context, config ); + + D_MAGIC_ASSERT( context, CoreLayerContext ); + D_ASSERT( config != NULL ); + + memset( config, 0, sizeof(CoreLayerRegionConfig) ); + + /* Initialize values from layer config. */ + config->width = context->config.width; + config->height = context->config.height; + config->format = context->config.pixelformat; + config->buffermode = context->config.buffermode; + config->options = context->config.options; + config->source_id = context->config.source; + config->surface_caps = context->config.surface_caps; + + /* Initialize source rectangle. */ + config->source.x = 0; + config->source.y = 0; + config->source.w = config->width; + config->source.h = config->height; + + /* Initialize screen rectangle. */ + screen_rectangle( context, &context->screen.location, &config->dest ); + + /* Set default opacity. */ + config->opacity = 0xff; + + /* Set default alpha ramp. */ + config->alpha_ramp[0] = 0x00; + config->alpha_ramp[1] = 0x55; + config->alpha_ramp[2] = 0xaa; + config->alpha_ramp[3] = 0xff; +} + +static void +build_updated_config( CoreLayer *layer, + CoreLayerContext *context, + const DFBDisplayLayerConfig *update, + CoreLayerRegionConfig *ret_config, + CoreLayerRegionConfigFlags *ret_flags ) +{ + CoreLayerRegionConfigFlags flags = CLRCF_NONE; + + D_DEBUG_AT( Core_LayerContext, "%s( %p, %p, %p, %p, %p )\n", + __FUNCTION__, layer, context, update, ret_config, ret_flags ); + + D_ASSERT( layer != NULL ); + D_MAGIC_ASSERT( context, CoreLayerContext ); + D_ASSERT( update != NULL ); + D_ASSERT( ret_config != NULL ); + + /* Get the current region configuration. */ + *ret_config = context->primary.config; + + /* Change width. */ + if (update->flags & DLCONF_WIDTH) { + flags |= CLRCF_WIDTH; + ret_config->width = update->width; + } + + /* Change height. */ + if (update->flags & DLCONF_HEIGHT) { + flags |= CLRCF_HEIGHT; + ret_config->height = update->height; + } + + /* Update source and destination rectangle. */ + if (update->flags & (DLCONF_WIDTH | DLCONF_HEIGHT)) { + int width, height; + DFBResult ret; + + flags |= CLRCF_SOURCE | CLRCF_DEST; + + ret_config->source.x = 0; + ret_config->source.y = 0; + ret_config->source.w = ret_config->width; + ret_config->source.h = ret_config->height; + + switch (context->screen.mode) { + case CLLM_CENTER: + ret = dfb_screen_get_layer_dimension( layer->screen, layer, &width, &height ); + if( ret == DFB_OK ) { + ret_config->dest.x = (width - ret_config->width) / 2; + ret_config->dest.y = (height - ret_config->height) / 2; + } + /* fall through */ + + case CLLM_POSITION: + ret_config->dest.w = ret_config->width; + ret_config->dest.h = ret_config->height; + break; + + case CLLM_LOCATION: + case CLLM_RECTANGLE: + D_ASSERT( layer->shared != NULL ); + + /* If the display layer does not support scaling and the + destination rectangle size is not the same as the + source rectangle, change it to match. The origin is + left alone to allow the driver to handle it. */ + if ( !D_FLAGS_IS_SET( layer->shared->description.caps, DLCAPS_SCREEN_SIZE ) + && ( ret_config->dest.w != ret_config->source.w || + ret_config->dest.h != ret_config->source.h ) ) + { + ret_config->dest.w = ret_config->width; + ret_config->dest.h = ret_config->height; + } + break; + + default: + D_BREAK( "invalid layout mode" ); + } + } + + /* Change pixel format. */ + if (update->flags & DLCONF_PIXELFORMAT) { + flags |= CLRCF_FORMAT; + ret_config->format = update->pixelformat; + } + + /* Change buffer mode. */ + if (update->flags & DLCONF_BUFFERMODE) { + flags |= CLRCF_BUFFERMODE; + ret_config->buffermode = update->buffermode; + } + + /* Change options. */ + if (update->flags & DLCONF_OPTIONS) { + flags |= CLRCF_OPTIONS; + ret_config->options = update->options; + } + + /* Change source id. */ + if (update->flags & DLCONF_SOURCE) { + flags |= CLRCF_SOURCE_ID; + ret_config->source_id = update->source; + } + + /* Change surface caps. */ + if (update->flags & DLCONF_SURFACE_CAPS) { + flags |= CLRCF_SURFACE_CAPS; + ret_config->surface_caps = update->surface_caps; + } + + /* Return translated flags. */ + if (ret_flags) + *ret_flags = flags; +} + +/* + * region surface (re/de)allocation + */ +static DFBResult +allocate_surface( CoreLayer *layer, + CoreLayerRegion *region, + CoreLayerRegionConfig *config ) +{ + DFBResult ret; + const DisplayLayerFuncs *funcs; + CoreLayerContext *context; + CoreSurface *surface = NULL; + DFBSurfaceCapabilities caps = DSCAPS_VIDEOONLY; + CoreSurfaceTypeFlags type = CSTF_LAYER; + CoreSurfaceConfig scon; + + D_DEBUG_AT( Core_LayerContext, "%s( %p, %p, %p )\n", __FUNCTION__, layer, region, config ); + + D_ASSERT( layer != NULL ); + D_ASSERT( layer->shared != NULL ); + D_ASSERT( layer->funcs != NULL ); + D_ASSERT( region != NULL ); + D_ASSERT( region->surface == NULL ); + D_ASSERT( config != NULL ); + D_ASSERT( config->buffermode != DLBM_WINDOWS ); + + context = region->context; + D_MAGIC_ASSERT( context, CoreLayerContext ); + + funcs = layer->funcs; + + /* + * Create a new surface for the region. + * Drivers may provide their own surface creation (unusual). + */ + if (funcs->AllocateSurface) { + /* Let the driver create the surface. */ + ret = funcs->AllocateSurface( layer, layer->driver_data, + layer->layer_data, region->region_data, + config, &surface ); + if (ret) { + D_ERROR( "DirectFB/core/layers: AllocateSurface() failed!\n" ); + return ret; + } + } + else { + CoreLayerShared *shared = layer->shared; + + /* Choose surface capabilities depending on the buffer mode. */ + switch (config->buffermode) { + case DLBM_FRONTONLY: + break; + + case DLBM_BACKVIDEO: + case DLBM_BACKSYSTEM: + caps |= DSCAPS_DOUBLE; + break; + + case DLBM_TRIPLE: + caps |= DSCAPS_TRIPLE; + break; + + default: + D_BUG("unknown buffermode"); + break; + } + + if (context->rotation == 90 || context->rotation == 270) + caps |= DSCAPS_ROTATED; + + /* FIXME: remove this? */ + if (config->options & DLOP_DEINTERLACING) + caps |= DSCAPS_INTERLACED; + + /* Add available surface capabilities. */ + caps |= config->surface_caps & (DSCAPS_INTERLACED | + DSCAPS_SEPARATED | + DSCAPS_PREMULTIPLIED); + + scon.flags = CSCONF_SIZE | CSCONF_FORMAT | CSCONF_CAPS; + scon.size.w = config->width; + scon.size.h = config->height; + scon.format = config->format; + scon.caps = caps; + + if (shared->contexts.primary == region->context) + type |= CSTF_SHARED; + + /* Use the default surface creation. */ + ret = dfb_surface_create( layer->core, &scon, type, shared->layer_id, NULL, &surface ); + if (ret) { + D_DERROR( ret, "Core/layers: Surface creation failed!\n" ); + return ret; + } + + if (config->buffermode == DLBM_BACKSYSTEM) + surface->buffers[1]->policy = CSP_SYSTEMONLY; + } + + if (surface->config.caps & DSCAPS_ROTATED) + surface->rotation = context->rotation; + else + surface->rotation = (context->rotation == 180) ? 180 : 0; + + /* Tell the region about its new surface (adds a global reference). */ + ret = dfb_layer_region_set_surface( region, surface ); + + /* Remove local reference of dfb_surface_create(). */ + dfb_surface_unref( surface ); + + return ret; +} + +static DFBResult +reallocate_surface( CoreLayer *layer, + CoreLayerRegion *region, + CoreLayerRegionConfig *config ) +{ + DFBResult ret; + const DisplayLayerFuncs *funcs; + CoreLayerContext *context; + CoreSurface *surface; + CoreSurfaceConfig sconfig; + + D_DEBUG_AT( Core_LayerContext, "%s( %p, %p, %p )\n", __FUNCTION__, layer, region, config ); + + D_ASSERT( layer != NULL ); + D_ASSERT( layer->funcs != NULL ); + D_ASSERT( region != NULL ); + D_ASSERT( region->surface != NULL ); + D_ASSERT( config != NULL ); + D_ASSERT( config->buffermode != DLBM_WINDOWS ); + + context = region->context; + D_MAGIC_ASSERT( context, CoreLayerContext ); + + funcs = layer->funcs; + surface = region->surface; + + if (funcs->ReallocateSurface) + return funcs->ReallocateSurface( layer, layer->driver_data, + layer->layer_data, + region->region_data, + config, surface ); + + sconfig.flags = CSCONF_SIZE | CSCONF_FORMAT | CSCONF_CAPS; + + sconfig.caps = surface->config.caps & ~(DSCAPS_FLIPPING | DSCAPS_INTERLACED | + DSCAPS_SEPARATED | DSCAPS_PREMULTIPLIED | DSCAPS_ROTATED); + + switch (config->buffermode) { + case DLBM_TRIPLE: + sconfig.caps |= DSCAPS_TRIPLE; + break; + + case DLBM_BACKVIDEO: + case DLBM_BACKSYSTEM: + sconfig.caps |= DSCAPS_DOUBLE; + break; + + case DLBM_FRONTONLY: + break; + + default: + D_BUG("unknown buffermode"); + return DFB_BUG; + } + + if (context->rotation == 90 || context->rotation == 270) + sconfig.caps |= DSCAPS_ROTATED; + + /* Add available surface capabilities. */ + sconfig.caps |= config->surface_caps & (DSCAPS_INTERLACED | + DSCAPS_SEPARATED | + DSCAPS_PREMULTIPLIED); + + if (config->options & DLOP_DEINTERLACING) + sconfig.caps |= DSCAPS_INTERLACED; + + sconfig.size.w = config->width; + sconfig.size.h = config->height; + sconfig.format = config->format; + + ret = dfb_surface_lock( surface ); + if (ret) + return ret; + + ret = dfb_surface_reconfig( surface, &sconfig ); + if (ret) { + dfb_surface_unlock( surface ); + return ret; + } + + if (DFB_PIXELFORMAT_IS_INDEXED(surface->config.format) && !surface->palette) { + ret = dfb_surface_init_palette( layer->core, surface ); + if (ret) + D_DERROR( ret, "Core/Layers: Could not initialize palette while switching to indexed mode!\n" ); + } + + switch (config->buffermode) { + case DLBM_TRIPLE: + case DLBM_BACKVIDEO: + surface->buffers[1]->policy = CSP_VIDEOONLY; + break; + + case DLBM_BACKSYSTEM: + surface->buffers[1]->policy = CSP_SYSTEMONLY; + break; + + case DLBM_FRONTONLY: + break; + + default: + D_BUG("unknown buffermode"); + return DFB_BUG; + } + + if (surface->config.caps & DSCAPS_ROTATED) + surface->rotation = context->rotation; + else + surface->rotation = (context->rotation == 180) ? 180 : 0; + + dfb_surface_unlock( surface ); + + return DFB_OK; +} + +static DFBResult +deallocate_surface( CoreLayer *layer, CoreLayerRegion *region ) +{ + DFBResult ret; + const DisplayLayerFuncs *funcs; + CoreSurface *surface; + + D_DEBUG_AT( Core_LayerContext, "%s( %p, %p )\n", __FUNCTION__, layer, region ); + + D_ASSERT( layer != NULL ); + D_ASSERT( layer->funcs != NULL ); + D_ASSERT( region != NULL ); + + D_ASSUME( region->surface != NULL ); + + funcs = layer->funcs; + surface = region->surface; + + if (surface) { + /* Special deallocation by the driver. */ + if (funcs->DeallocateSurface) { + ret = funcs->DeallocateSurface( layer, layer->driver_data, + layer->layer_data, + region->region_data, surface ); + if (ret) + return ret; + } + + /* Detach the global listener. */ + dfb_surface_detach_global( surface, ®ion->surface_reaction ); + + /* Unlink from structure. */ + dfb_surface_unlink( ®ion->surface ); + } + + return DFB_OK; +} + +static void +screen_rectangle( CoreLayerContext *context, + const DFBLocation *location, + DFBRectangle *rect ) +{ + DFBResult ret; + int width; + int height; + CoreLayer *layer; + + D_DEBUG_AT( Core_LayerContext, "%s( %p, %p, %p )\n", __FUNCTION__, context, location, rect ); + + D_MAGIC_ASSERT( context, CoreLayerContext ); + D_ASSERT( location != NULL ); + D_ASSERT( rect != NULL ); + + D_DEBUG_AT( Core_LayerContext, " <- %4.2f,%4.2f-%4.2f,%4.2f\n", + location->x, location->y, location->w, location->h ); + + layer = dfb_layer_at( context->layer_id ); + D_ASSERT( layer != NULL ); + D_ASSERT( layer->screen != NULL ); + + ret = dfb_screen_get_layer_dimension( layer->screen, layer, &width, &height ); + if (ret) { + D_WARN( "could not determine mixer/screen dimension of layer %d", context->layer_id ); + + rect->x = location->x * 720; + rect->y = location->y * 576; + rect->w = location->w * 720; + rect->h = location->h * 576; + } + else { + rect->x = location->x * width; + rect->y = location->y * height; + rect->w = location->w * width; + rect->h = location->h * height; + } + + D_DEBUG_AT( Core_LayerContext, " => %4d,%4d-%4d,%4d\n", DFB_RECTANGLE_VALS(rect) ); +} + diff --git a/Source/DirectFB/src/core/layer_context.h b/Source/DirectFB/src/core/layer_context.h new file mode 100755 index 0000000..ab9d2fb --- /dev/null +++ b/Source/DirectFB/src/core/layer_context.h @@ -0,0 +1,149 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __CORE__LAYER_CONTEXT_H__ +#define __CORE__LAYER_CONTEXT_H__ + +#include + +#include +#include + +typedef enum { + CLCNF_ACTIVATED = 0x00000001, + CLCNF_DEACTIVATED = 0x00000002 +} CoreLayerContextNotificationFlags; + +typedef struct { + CoreLayerContextNotificationFlags flags; + CoreLayerContext *context; +} CoreLayerContextNotification; + +/* + * Creates a pool of layer context objects. + */ +FusionObjectPool *dfb_layer_context_pool_create( const FusionWorld *world ); + +/* + * Generates dfb_layer_context_ref(), dfb_layer_context_attach() etc. + */ +FUSION_OBJECT_METHODS( CoreLayerContext, dfb_layer_context ) + + +DFBResult dfb_layer_context_init( CoreLayerContext *context, + CoreLayer *layer ); + +DFBResult dfb_layer_context_get_primary_region( CoreLayerContext *context, + bool create, + CoreLayerRegion **ret_region ); + +/* + * configuration testing/setting/getting + */ +DFBResult dfb_layer_context_test_configuration ( CoreLayerContext *context, + const DFBDisplayLayerConfig *config, + DFBDisplayLayerConfigFlags *ret_failed ); + +DFBResult dfb_layer_context_set_configuration ( CoreLayerContext *context, + const DFBDisplayLayerConfig *config ); + +DFBResult dfb_layer_context_get_configuration ( CoreLayerContext *context, + DFBDisplayLayerConfig *ret_config ); + + +/* + * configuration details + */ +DFBResult dfb_layer_context_set_src_colorkey ( CoreLayerContext *context, + u8 r, + u8 g, + u8 b, + int index ); + +DFBResult dfb_layer_context_set_dst_colorkey ( CoreLayerContext *context, + u8 r, + u8 g, + u8 b, + int index ); + +DFBResult dfb_layer_context_set_sourcerectangle( CoreLayerContext *context, + const DFBRectangle *source ); + +DFBResult dfb_layer_context_set_screenlocation ( CoreLayerContext *context, + const DFBLocation *location ); + +DFBResult dfb_layer_context_set_screenrectangle( CoreLayerContext *context, + const DFBRectangle *rectangle ); + +DFBResult dfb_layer_context_set_screenposition ( CoreLayerContext *context, + int x, + int y ); + +DFBResult dfb_layer_context_set_opacity ( CoreLayerContext *context, + u8 opacity ); + +DFBResult dfb_layer_context_set_rotation ( CoreLayerContext *context, + int rotation ); + +DFBResult dfb_layer_context_set_coloradjustment( CoreLayerContext *context, + const DFBColorAdjustment *adjustment ); + +DFBResult dfb_layer_context_get_coloradjustment( CoreLayerContext *context, + DFBColorAdjustment *ret_adjustment ); + +DFBResult dfb_layer_context_set_field_parity ( CoreLayerContext *context, + int field ); + +DFBResult dfb_layer_context_set_clip_regions ( CoreLayerContext *context, + const DFBRegion *regions, + int num_regions, + DFBBoolean positive ); + + +/* + * window control + */ +DFBResult dfb_layer_context_create_window( CoreDFB *core, + CoreLayerContext *context, + const DFBWindowDescription *desc, + CoreWindow **ret_window ); + +CoreWindow *dfb_layer_context_find_window( CoreLayerContext *context, + DFBWindowID id ); + +CoreWindowStack *dfb_layer_context_windowstack( const CoreLayerContext *context ); + +bool dfb_layer_context_active ( const CoreLayerContext *context ); + +/* + * Locking + */ +DirectResult dfb_layer_context_lock ( CoreLayerContext *context ); +DirectResult dfb_layer_context_unlock( CoreLayerContext *context ); + +#endif diff --git a/Source/DirectFB/src/core/layer_control.c b/Source/DirectFB/src/core/layer_control.c new file mode 100755 index 0000000..b190cc5 --- /dev/null +++ b/Source/DirectFB/src/core/layer_control.c @@ -0,0 +1,589 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include + +#include + + +D_DEBUG_DOMAIN( Core_Layers, "Core/Layers", "DirectFB Display Layer Core" ); + +/** public **/ + +DFBResult +dfb_layer_suspend( CoreLayer *layer ) +{ + CoreLayerShared *shared; + CoreLayerContexts *contexts; + + D_ASSERT( layer != NULL ); + D_ASSERT( layer->shared != NULL ); + + shared = layer->shared; + contexts = &shared->contexts; + + /* Lock the layer. */ + if (fusion_skirmish_prevail( &shared->lock )) + return DFB_FUSION; + + D_ASSUME( !shared->suspended ); + + if (shared->suspended) { + fusion_skirmish_dismiss( &shared->lock ); + return DFB_OK; + } + + /* Deactivate current context. */ + if (contexts->active >= 0) { + DFBResult ret; + CoreLayerContext *current = fusion_vector_at( &contexts->stack, + contexts->active ); + + ret = dfb_layer_context_deactivate( current ); + if (ret) { + D_ERROR("DirectFB/Core/layer: " + "Could not deactivate current context of '%s'! (%s)\n", + shared->description.name, DirectFBErrorString( ret )); + } + } + + shared->suspended = true; + + /* Unlock the layer. */ + fusion_skirmish_dismiss( &shared->lock ); + + return DFB_OK; +} + +DFBResult +dfb_layer_resume( CoreLayer *layer ) +{ + CoreLayerShared *shared; + CoreLayerContexts *contexts; + + D_ASSERT( layer != NULL ); + D_ASSERT( layer->shared != NULL ); + + shared = layer->shared; + contexts = &shared->contexts; + + /* Lock the layer. */ + if (fusion_skirmish_prevail( &shared->lock )) + return DFB_FUSION; + + D_ASSUME( shared->suspended ); + + if (!shared->suspended) { + fusion_skirmish_dismiss( &shared->lock ); + return DFB_OK; + } + + /* (Re)Activate current context. */ + if (contexts->active >= 0) { + DFBResult ret; + CoreLayerContext *current = fusion_vector_at( &contexts->stack, + contexts->active ); + + ret = dfb_layer_context_activate( current ); + if (ret) { + D_ERROR("DirectFB/Core/layer: " + "Could not activate current context of '%s'! (%s)\n", + shared->description.name, DirectFBErrorString( ret )); + } + } + + shared->suspended = false; + + /* Unlock the layer. */ + fusion_skirmish_dismiss( &shared->lock ); + + return DFB_OK; +} + +DFBResult +dfb_layer_create_context( CoreLayer *layer, + CoreLayerContext **ret_context ) +{ + DFBResult ret; + CoreLayerShared *shared; + CoreLayerContexts *contexts; + CoreLayerContext *context = NULL; + + D_ASSERT( layer != NULL ); + D_ASSERT( layer->shared != NULL ); + D_ASSERT( ret_context != NULL ); + + shared = layer->shared; + contexts = &shared->contexts; + + D_DEBUG_AT( Core_Layers, "%s (%s)\n", __FUNCTION__, shared->description.name ); + + /* Create the object. */ + context = dfb_core_create_layer_context( layer->core ); + if (!context) + return DFB_FUSION; + + /* Lock the layer. */ + if (fusion_skirmish_prevail( &shared->lock )) { + fusion_object_destroy( &context->object ); + return DFB_FUSION; + } + + /* Initialize the new context. */ + ret = dfb_layer_context_init( context, layer ); + if (ret) { + fusion_skirmish_dismiss( &shared->lock ); + return ret; + } + + /* Add it to the context stack. */ + if (fusion_vector_add( &contexts->stack, context )) { + dfb_layer_context_unref( context ); + fusion_skirmish_dismiss( &shared->lock ); + return DFB_FUSION; + } + + /* Unlock the layer. */ + fusion_skirmish_dismiss( &shared->lock ); + + /* Return the context. */ + *ret_context = context; + + return DFB_OK; +} + +DFBResult +dfb_layer_get_active_context( CoreLayer *layer, + CoreLayerContext **ret_context ) +{ + CoreLayerShared *shared; + CoreLayerContexts *contexts; + CoreLayerContext *context; + + D_ASSERT( layer != NULL ); + D_ASSERT( layer->shared != NULL ); + D_ASSERT( ret_context != NULL ); + + shared = layer->shared; + contexts = &shared->contexts; + + D_DEBUG_AT( Core_Layers, "%s (%s)\n", __FUNCTION__, shared->description.name ); + + /* Lock the layer. */ + if (fusion_skirmish_prevail( &shared->lock )) + return DFB_FUSION; + + /* Check for active context. */ + if (contexts->active < 0) { + fusion_skirmish_dismiss( &shared->lock ); + return DFB_NOCONTEXT; + } + + /* Fetch active context. */ + context = fusion_vector_at( &contexts->stack, contexts->active ); + + /* Increase the context's reference counter. */ + if (dfb_layer_context_ref( context )) { + fusion_skirmish_dismiss( &shared->lock ); + return DFB_FUSION; + } + + D_DEBUG_AT( Core_Layers, " => %p [%4dx%4d %8s]\n", context, + context->config.width, context->config.height, + dfb_pixelformat_name( context->config.pixelformat ) ); + + /* Return the context. */ + *ret_context = context; + + /* Unlock the layer. */ + fusion_skirmish_dismiss( &shared->lock ); + + return DFB_OK; +} + +DFBResult +dfb_layer_get_primary_context( CoreLayer *layer, + bool activate, + CoreLayerContext **ret_context ) +{ + DFBResult ret; + CoreLayerShared *shared; + CoreLayerContexts *contexts; + + D_ASSERT( layer != NULL ); + D_ASSERT( layer->shared != NULL ); + D_ASSERT( ret_context != NULL ); + + shared = layer->shared; + contexts = &shared->contexts; + + /* Lock the layer. */ + if (fusion_skirmish_prevail( &shared->lock )) + return DFB_FUSION; + + D_DEBUG_AT( Core_Layers, "%s (%s, %sactivate) <- active: %d\n", + __FUNCTION__, shared->description.name, + activate ? "" : "don't ", contexts->active ); + + /* Check for primary context. */ + if (contexts->primary) { + /* Increase the context's reference counter. */ + if (dfb_layer_context_ref( contexts->primary )) { + fusion_skirmish_dismiss( &shared->lock ); + return DFB_FUSION; + } + } + else { + CoreLayerContext *primary; + + /* Unlock the layer. */ + fusion_skirmish_dismiss( &shared->lock ); + + /* Create the primary (shared) context. */ + ret = dfb_layer_create_context( layer, &primary ); + if (ret) + return ret; + + /* Lock the layer again. */ + if (fusion_skirmish_prevail( &shared->lock )) { + dfb_layer_context_unref( primary ); + return DFB_FUSION; + } + + /* Check if there was a race. */ + if (contexts->primary) { + /* Throw away ours, the other was faster. */ + dfb_layer_context_unref( primary ); + + /* Increase the context's reference counter. */ + if (dfb_layer_context_ref( contexts->primary )) { + fusion_skirmish_dismiss( &shared->lock ); + return DFB_FUSION; + } + } + else + contexts->primary = primary; + } + + /* Activate if no context is active? */ + if (contexts->active < 0 && activate) { + ret = dfb_layer_activate_context( layer, contexts->primary ); + if (ret) { + dfb_layer_context_unref( contexts->primary ); + fusion_skirmish_dismiss( &shared->lock ); + return ret; + } + } + + /* Return the context. */ + *ret_context = contexts->primary; + + /* Unlock the layer. */ + fusion_skirmish_dismiss( &shared->lock ); + + return DFB_OK; +} + +DFBResult +dfb_layer_activate_context( CoreLayer *layer, + CoreLayerContext *context ) +{ + DFBResult ret = DFB_OK; + int index; + CoreLayerShared *shared; + CoreLayerContexts *ctxs; + + D_ASSERT( layer != NULL ); + D_ASSERT( layer->shared != NULL ); + D_ASSERT( context != NULL ); + + shared = layer->shared; + ctxs = &shared->contexts; + + /* Lock the layer. */ + if (fusion_skirmish_prevail( &shared->lock )) + return DFB_FUSION; + + D_DEBUG_AT( Core_Layers, "%s (%s, %p)\n", __FUNCTION__, shared->description.name, context ); + + D_ASSERT( fusion_vector_contains( &ctxs->stack, context ) ); + + /* Lookup the context in the context stack. */ + index = fusion_vector_index_of( &ctxs->stack, context ); + + /* Lock the context. */ + if (dfb_layer_context_lock( context )) { + fusion_skirmish_dismiss( &shared->lock ); + return DFB_FUSION; + } + + /* Need to activate? */ + if (ctxs->active != index) { + DFBResult ret; + + /* Another context currently active? */ + if (ctxs->active >= 0) { + CoreLayerContext *current = fusion_vector_at( &ctxs->stack, + ctxs->active ); + + /* Deactivate current context. */ + if (!shared->suspended) { + ret = dfb_layer_context_deactivate( current ); + if (ret) + goto error; + } + + /* No active context. */ + ctxs->active = -1; + } + + /* Activate context now. */ + if (!shared->suspended) { + ret = dfb_layer_context_activate( context ); + if (ret) + goto error; + } + + ctxs->active = index; + } + + /* Unlock the context. */ + dfb_layer_context_unlock( context ); + + /* Unlock the layer. */ + fusion_skirmish_dismiss( &shared->lock ); + + return DFB_OK; + +error: + dfb_layer_context_unlock( context ); + + fusion_skirmish_dismiss( &shared->lock ); + + return ret; +} + +DFBResult +dfb_layer_remove_context( CoreLayer *layer, + CoreLayerContext *context ) +{ + int index; + CoreLayerShared *shared; + CoreLayerContexts *ctxs; + + D_ASSERT( layer != NULL ); + D_ASSERT( layer->shared != NULL ); + D_ASSERT( context != NULL ); + + shared = layer->shared; + ctxs = &shared->contexts; + + /* Lock the layer. */ + if (fusion_skirmish_prevail( &shared->lock )) + return DFB_FUSION; + + D_DEBUG_AT( Core_Layers, "%s (%s, %p)\n", __FUNCTION__, shared->description.name, context ); + + D_ASSUME( fusion_vector_contains( &ctxs->stack, context ) ); + + /* Lookup the context in the context stack. */ + index = fusion_vector_index_of( &ctxs->stack, context ); + if (index < 0) { + fusion_skirmish_dismiss( &shared->lock ); + return DFB_OK; + } + + /* Lock the context. */ + if (dfb_layer_context_lock( context )) { + fusion_skirmish_dismiss( &shared->lock ); + return DFB_FUSION; + } + + /* Remove context from context stack. */ + fusion_vector_remove( &ctxs->stack, index ); + + /* Check if the primary context is removed. */ + if (context == ctxs->primary) + ctxs->primary = NULL; + + /* Need to deactivate? */ + if (ctxs->active == index) { + /* Deactivate the context. */ + if (!shared->suspended) + dfb_layer_context_deactivate( context ); + + /* There's no active context anymore. */ + ctxs->active = -1; + + if (ctxs->primary) + D_ASSERT( fusion_vector_contains( &ctxs->stack, ctxs->primary ) ); + + if (fusion_vector_has_elements( &ctxs->stack )) { + CoreLayerContext *ctx; + + /* Activate most recent context. */ + index = fusion_vector_size( &ctxs->stack ) - 1; + ctx = fusion_vector_at( &ctxs->stack, index ); + + if (shared->suspended || dfb_layer_context_activate( ctx ) == DFB_OK) + ctxs->active = index; + } + } + else if (ctxs->active > index) { + /* Adjust index of active context due to the removed context. */ + ctxs->active--; + } + + /* Unlock the context. */ + dfb_layer_context_unlock( context ); + + /* Unlock the layer. */ + fusion_skirmish_dismiss( &shared->lock ); + + return DFB_OK; +} + +DFBResult +dfb_layer_get_current_output_field( CoreLayer *layer, int *field ) +{ + DFBResult ret; + + D_ASSERT( layer != NULL ); + D_ASSERT( layer->funcs != NULL ); + D_ASSERT( field != NULL ); + + if (!layer->funcs->GetCurrentOutputField) + return DFB_UNSUPPORTED; + + ret = layer->funcs->GetCurrentOutputField( layer, layer->driver_data, + layer->layer_data, field ); + if (ret) + return ret; + + return DFB_OK; +} + +DFBResult +dfb_layer_get_level( CoreLayer *layer, int *ret_level ) +{ + const DisplayLayerFuncs *funcs; + + D_ASSERT( layer != NULL ); + D_ASSERT( layer->funcs != NULL ); + D_ASSERT( ret_level != NULL ); + + funcs = layer->funcs; + + if (!funcs->GetLevel) + return DFB_UNSUPPORTED; + + return funcs->GetLevel( layer, layer->driver_data, + layer->layer_data, ret_level ); +} + +DFBResult +dfb_layer_set_level( CoreLayer *layer, int level ) +{ + const DisplayLayerFuncs *funcs; + + D_ASSERT( layer != NULL ); + D_ASSERT( layer->funcs != NULL ); + + funcs = layer->funcs; + + if (!funcs->SetLevel) + return DFB_UNSUPPORTED; + + return funcs->SetLevel( layer, layer->driver_data, + layer->layer_data, level ); +} + +DFBResult +dfb_layer_wait_vsync( CoreLayer *layer ) +{ + D_ASSERT( layer != NULL ); + D_ASSERT( layer->screen != NULL ); + + return dfb_screen_wait_vsync( layer->screen ); +} + +DFBResult +dfb_layer_get_source_info( CoreLayer *layer, + int source, + DFBDisplayLayerSourceDescription *ret_desc ) +{ + D_ASSERT( layer != NULL ); + D_ASSERT( layer->shared != NULL ); + D_ASSERT( source >= 0 ); + D_ASSERT( source < layer->shared->description.sources ); + D_ASSERT( ret_desc != NULL ); + + *ret_desc = layer->shared->sources[source].description; + + return DFB_OK; +} + diff --git a/Source/DirectFB/src/core/layer_control.h b/Source/DirectFB/src/core/layer_control.h new file mode 100755 index 0000000..51b7ae2 --- /dev/null +++ b/Source/DirectFB/src/core/layer_control.h @@ -0,0 +1,72 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __CORE__LAYER_CONTROL_H__ +#define __CORE__LAYER_CONTROL_H__ + +#include + +#include + + +DFBResult dfb_layer_create_context ( CoreLayer *layer, + CoreLayerContext **ret_context ); + +DFBResult dfb_layer_get_active_context ( CoreLayer *layer, + CoreLayerContext **ret_context ); + +DFBResult dfb_layer_get_primary_context ( CoreLayer *layer, + bool activate, + CoreLayerContext **ret_context ); + +DFBResult dfb_layer_activate_context ( CoreLayer *layer, + CoreLayerContext *context ); + +DFBResult dfb_layer_remove_context ( CoreLayer *layer, + CoreLayerContext *context ); + +DFBResult dfb_layer_suspend ( CoreLayer *layer ); +DFBResult dfb_layer_resume ( CoreLayer *layer ); + + +DFBResult dfb_layer_get_current_output_field( CoreLayer *layer, + int *field ); + +DFBResult dfb_layer_get_level ( CoreLayer *layer, + int *ret_level ); + +DFBResult dfb_layer_set_level ( CoreLayer *layer, + int level ); + +DFBResult dfb_layer_wait_vsync ( CoreLayer *layer ); + +DFBResult dfb_layer_get_source_info ( CoreLayer *layer, + int source, + DFBDisplayLayerSourceDescription *ret_desc ); + +#endif diff --git a/Source/DirectFB/src/core/layer_region.c b/Source/DirectFB/src/core/layer_region.c new file mode 100755 index 0000000..b96e742 --- /dev/null +++ b/Source/DirectFB/src/core/layer_region.c @@ -0,0 +1,1129 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include + +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + + +D_DEBUG_DOMAIN( Core_Layers, "Core/Layers", "DirectFB Display Layer Core" ); + + +static DFBResult region_buffer_lock( CoreLayerRegion *region, + CoreSurface *surface, + CoreSurfaceBufferRole role ); + +static DFBResult set_region ( CoreLayerRegion *region, + CoreLayerRegionConfig *config, + CoreLayerRegionConfigFlags flags, + CoreSurface *surface ); + +static DFBResult realize_region ( CoreLayerRegion *region ); + +static DFBResult unrealize_region( CoreLayerRegion *region ); + +/******************************************************************************/ + +static void +region_destructor( FusionObject *object, bool zombie, void *ctx ) +{ + CoreLayerRegion *region = (CoreLayerRegion*) object; + CoreLayerContext *context = region->context; + CoreLayer *layer = dfb_layer_at( context->layer_id ); + CoreLayerShared *shared = layer->shared; + + D_DEBUG_AT( Core_Layers, "destroying region %p (%s, %dx%d, " + "%s, %s, %s, %s%s)\n", region, shared->description.name, + region->config.width, region->config.height, + D_FLAGS_IS_SET( region->state, + CLRSF_CONFIGURED ) ? "configured" : "unconfigured", + D_FLAGS_IS_SET( region->state, + CLRSF_ENABLED ) ? "enabled" : "disabled", + D_FLAGS_IS_SET( region->state, + CLRSF_ACTIVE ) ? "active" : "inactive", + D_FLAGS_IS_SET( region->state, + CLRSF_REALIZED ) ? "realized" : "not realized", + zombie ? " - ZOMBIE" : "" ); + + /* Hide region etc. */ + if (D_FLAGS_IS_SET( region->state, CLRSF_ENABLED )) + dfb_layer_region_disable( region ); + + /* Remove the region from the context. */ + dfb_layer_context_remove_region( region->context, region ); + + /* Throw away its surface. */ + if (region->surface) { + /* Detach the global listener. */ + dfb_surface_detach_global( region->surface, + ®ion->surface_reaction ); + + /* Unlink from structure. */ + dfb_surface_unlink( ®ion->surface ); + } + + /* Unlink the context from the structure. */ + dfb_layer_context_unlink( ®ion->context ); + + /* Free driver's region data. */ + if (region->region_data) + SHFREE( shared->shmpool, region->region_data ); + + /* Deinitialize the lock. */ + fusion_skirmish_destroy( ®ion->lock ); + + /* Destroy the object. */ + fusion_object_destroy( object ); +} + +/******************************************************************************/ + +FusionObjectPool * +dfb_layer_region_pool_create( const FusionWorld *world ) +{ + return fusion_object_pool_create( "Layer Region Pool", + sizeof(CoreLayerRegion), + sizeof(CoreLayerRegionNotification), + region_destructor, NULL, world ); +} + +/******************************************************************************/ + +DFBResult +dfb_layer_region_create( CoreLayerContext *context, + CoreLayerRegion **ret_region ) +{ + CoreLayer *layer; + CoreLayerRegion *region; + + D_ASSERT( context != NULL ); + D_ASSERT( ret_region != NULL ); + + layer = dfb_layer_at( context->layer_id ); + + /* Create the object. */ + region = dfb_core_create_layer_region( layer->core ); + if (!region) + return DFB_FUSION; + + /* Link the context into the structure. */ + if (dfb_layer_context_link( ®ion->context, context )) { + fusion_object_destroy( ®ion->object ); + return DFB_FUSION; + } + + /* Initialize the lock. */ + if (fusion_skirmish_init( ®ion->lock, "Layer Region", dfb_core_world(layer->core) )) { + dfb_layer_context_unlink( ®ion->context ); + fusion_object_destroy( ®ion->object ); + return DFB_FUSION; + } + + /* Change global reaction lock. */ + fusion_object_set_lock( ®ion->object, ®ion->lock ); + + region->state = CLRSF_FROZEN; + + /* Activate the object. */ + fusion_object_activate( ®ion->object ); + + /* Add the region to the context. */ + dfb_layer_context_add_region( context, region ); + + /* Return the new region. */ + *ret_region = region; + + return DFB_OK; +} + +DFBResult +dfb_layer_region_activate( CoreLayerRegion *region ) +{ + DFBResult ret; + + D_ASSERT( region != NULL ); + + /* Lock the region. */ + if (dfb_layer_region_lock( region )) + return DFB_FUSION; + + D_ASSUME( ! D_FLAGS_IS_SET( region->state, CLRSF_ACTIVE ) ); + + if (D_FLAGS_IS_SET( region->state, CLRSF_ACTIVE )) { + dfb_layer_region_unlock( region ); + return DFB_OK; + } + + /* Realize the region if it's enabled. */ + if (D_FLAGS_IS_SET( region->state, CLRSF_ENABLED )) { + ret = realize_region( region ); + if (ret) { + dfb_layer_region_unlock( region ); + return ret; + } + } + + /* Update the region's state. */ + D_FLAGS_SET( region->state, CLRSF_ACTIVE ); + + /* Unlock the region. */ + dfb_layer_region_unlock( region ); + + return DFB_OK; +} + +DFBResult +dfb_layer_region_deactivate( CoreLayerRegion *region ) +{ + DFBResult ret; + + D_ASSERT( region != NULL ); + + /* Lock the region. */ + if (dfb_layer_region_lock( region )) + return DFB_FUSION; + + D_ASSUME( D_FLAGS_IS_SET( region->state, CLRSF_ACTIVE ) ); + + if (! D_FLAGS_IS_SET( region->state, CLRSF_ACTIVE )) { + dfb_layer_region_unlock( region ); + return DFB_OK; + } + + /* Unrealize the region? */ + if (D_FLAGS_IS_SET( region->state, CLRSF_REALIZED )) { + ret = unrealize_region( region ); + if (ret) + return ret; + } + + /* Update the region's state. */ + D_FLAGS_CLEAR( region->state, CLRSF_ACTIVE ); + + /* Unlock the region. */ + dfb_layer_region_unlock( region ); + + return DFB_OK; +} + +DFBResult +dfb_layer_region_enable( CoreLayerRegion *region ) +{ + DFBResult ret; + + D_ASSERT( region != NULL ); + D_ASSERT( region->context != NULL ); + + /* Lock the region. */ + if (dfb_layer_region_lock( region )) + return DFB_FUSION; + + D_ASSUME( ! D_FLAGS_IS_SET( region->state, CLRSF_ENABLED ) ); + + if (D_FLAGS_IS_SET( region->state, CLRSF_ENABLED )) { + dfb_layer_region_unlock( region ); + return DFB_OK; + } + + /* Realize the region if it's active. */ + if (D_FLAGS_IS_SET( region->state, CLRSF_ACTIVE )) { + ret = realize_region( region ); + if (ret) { + dfb_layer_region_unlock( region ); + return ret; + } + } + + /* Update the region's state. */ + D_FLAGS_SET( region->state, CLRSF_ENABLED ); + + /* Unlock the region. */ + dfb_layer_region_unlock( region ); + + return DFB_OK; +} + +DFBResult +dfb_layer_region_disable( CoreLayerRegion *region ) +{ + DFBResult ret; + + D_ASSERT( region != NULL ); + + /* Lock the region. */ + if (dfb_layer_region_lock( region )) + return DFB_FUSION; + + D_ASSUME( D_FLAGS_IS_SET( region->state, CLRSF_ENABLED ) ); + + if (! D_FLAGS_IS_SET( region->state, CLRSF_ENABLED )) { + dfb_layer_region_unlock( region ); + return DFB_OK; + } + + /* Unrealize the region? */ + if (D_FLAGS_IS_SET( region->state, CLRSF_REALIZED )) { + ret = unrealize_region( region ); + if (ret) + return ret; + } + + /* Update the region's state. */ + D_FLAGS_CLEAR( region->state, CLRSF_ENABLED ); + + /* Unlock the region. */ + dfb_layer_region_unlock( region ); + + return DFB_OK; +} + +DFBResult +dfb_layer_region_set_surface( CoreLayerRegion *region, + CoreSurface *surface ) +{ + DFBResult ret; + + D_ASSERT( region != NULL ); + D_ASSERT( surface != NULL ); + + /* Lock the region. */ + if (dfb_layer_region_lock( region )) + return DFB_FUSION; + + if (region->surface != surface) { + /* Setup hardware for the new surface if the region is realized. */ + if (D_FLAGS_IS_SET( region->state, CLRSF_REALIZED )) { + ret = set_region( region, ®ion->config, CLRCF_SURFACE | CLRCF_PALETTE, surface ); + if (ret) { + dfb_layer_region_unlock( region ); + return ret; + } + } + + /* Throw away the old surface. */ + if (region->surface) { + /* Detach the global listener. */ + dfb_surface_detach_global( region->surface, + ®ion->surface_reaction ); + + /* Unlink surface from structure. */ + dfb_surface_unlink( ®ion->surface ); + } + + /* Take the new surface. */ + if (surface) { + /* Link surface into structure. */ + if (dfb_surface_link( ®ion->surface, surface )) { + D_WARN( "region lost it's surface" ); + dfb_layer_region_unlock( region ); + return DFB_FUSION; + } + + /* Attach the global listener. */ + dfb_surface_attach_global( region->surface, + DFB_LAYER_REGION_SURFACE_LISTENER, + region, ®ion->surface_reaction ); + } + } + + /* Unlock the region. */ + dfb_layer_region_unlock( region ); + + return DFB_OK; +} + +DFBResult +dfb_layer_region_get_surface( CoreLayerRegion *region, + CoreSurface **ret_surface ) +{ + D_ASSERT( region != NULL ); + D_ASSERT( ret_surface != NULL ); + + /* Lock the region. */ + if (dfb_layer_region_lock( region )) + return DFB_FUSION; + + D_ASSUME( region->surface != NULL ); + + /* Check for NULL surface. */ + if (!region->surface) { + dfb_layer_region_unlock( region ); + return DFB_UNSUPPORTED; + } + + /* Increase the surface's reference counter. */ + if (dfb_surface_ref( region->surface )) { + dfb_layer_region_unlock( region ); + return DFB_FUSION; + } + + /* Return the surface. */ + *ret_surface = region->surface; + + /* Unlock the region. */ + dfb_layer_region_unlock( region ); + + return DFB_OK; +} + +DFBResult +dfb_layer_region_flip_update( CoreLayerRegion *region, + const DFBRegion *update, + DFBSurfaceFlipFlags flags ) +{ + DFBResult ret = DFB_OK; + DFBRegion unrotated; + DFBRegion rotated; + CoreLayer *layer; + CoreLayerContext *context; + CoreSurface *surface; + const DisplayLayerFuncs *funcs; + + if (update) + D_DEBUG_AT( Core_Layers, + "dfb_layer_region_flip_update( %p, %p, 0x%08x ) <- [%d, %d - %dx%d]\n", + region, update, flags, DFB_RECTANGLE_VALS_FROM_REGION( update ) ); + else + D_DEBUG_AT( Core_Layers, + "dfb_layer_region_flip_update( %p, %p, 0x%08x )\n", region, update, flags ); + + + D_ASSERT( region != NULL ); + D_ASSERT( region->context != NULL ); + + /* Lock the region. */ + if (dfb_layer_region_lock( region )) + return DFB_FUSION; + + D_ASSUME( region->surface != NULL ); + + /* Check for NULL surface. */ + if (!region->surface) { + D_DEBUG_AT( Core_Layers, " -> No surface => no update!\n" ); + dfb_layer_region_unlock( region ); + return DFB_UNSUPPORTED; + } + + context = region->context; + surface = region->surface; + layer = dfb_layer_at( context->layer_id ); + + D_ASSERT( layer->funcs != NULL ); + + funcs = layer->funcs; + + /* Unfreeze region? */ + if (D_FLAGS_IS_SET( region->state, CLRSF_FROZEN )) { + D_FLAGS_CLEAR( region->state, CLRSF_FROZEN ); + + if (D_FLAGS_IS_SET( region->state, CLRSF_REALIZED )) { + ret = set_region( region, ®ion->config, CLRCF_ALL, surface ); + if (ret) + D_DERROR( ret, "Core/LayerRegion: set_region() in dfb_layer_region_flip_update() failed!\n" ); + } + else if (D_FLAGS_ARE_SET( region->state, CLRSF_ENABLED | CLRSF_ACTIVE )) { + ret = realize_region( region ); + if (ret) + D_DERROR( ret, "Core/LayerRegion: realize_region() in dfb_layer_region_flip_update() failed!\n" ); + } + + if (ret) { + dfb_layer_region_unlock( region ); + return ret; + } + } + + /* Depending on the buffer mode... */ + switch (region->config.buffermode) { + case DLBM_TRIPLE: + case DLBM_BACKVIDEO: + /* Check if simply swapping the buffers is possible... */ + if (!(flags & DSFLIP_BLIT) && !surface->rotation && + (!update || (update->x1 == 0 && + update->y1 == 0 && + update->x2 == surface->config.size.w - 1 && + update->y2 == surface->config.size.h - 1))) + { + D_DEBUG_AT( Core_Layers, " -> Going to swap buffers...\n" ); + + /* Use the driver's routine if the region is realized. */ + if (D_FLAGS_IS_SET( region->state, CLRSF_REALIZED )) { + D_ASSUME( funcs->FlipRegion != NULL ); + + ret = region_buffer_lock( region, surface, CSBR_BACK ); + if (ret) { + dfb_layer_region_unlock( region ); + return ret; + } + + D_DEBUG_AT( Core_Layers, " -> Flipping region using driver...\n" ); + + if (funcs->FlipRegion) + ret = funcs->FlipRegion( layer, + layer->driver_data, + layer->layer_data, + region->region_data, + surface, flags, ®ion->surface_lock ); + + dfb_surface_unlock( surface ); + } + else { + D_DEBUG_AT( Core_Layers, " -> Flipping region not using driver...\n" ); + + /* Just do the hardware independent work. */ + dfb_surface_lock( surface ); + dfb_surface_flip( surface, false ); + dfb_surface_unlock( surface ); + } + break; + } + + /* fall through */ + + case DLBM_BACKSYSTEM: + D_DEBUG_AT( Core_Layers, " -> Going to copy portion...\n" ); + + if ((flags & DSFLIP_WAITFORSYNC) == DSFLIP_WAITFORSYNC) { + D_DEBUG_AT( Core_Layers, " -> Waiting for VSync...\n" ); + + dfb_layer_wait_vsync( layer ); + } + + D_DEBUG_AT( Core_Layers, " -> Copying content from back to front buffer...\n" ); + + /* ...or copy updated contents from back to front buffer. */ + dfb_back_to_front_copy_rotation( surface, update, surface->rotation ); + + if ((flags & DSFLIP_WAITFORSYNC) == DSFLIP_WAIT) { + D_DEBUG_AT( Core_Layers, " -> Waiting for VSync...\n" ); + + dfb_layer_wait_vsync( layer ); + } + + /* fall through */ + + case DLBM_FRONTONLY: + /* Tell the driver about the update if the region is realized. */ + if (funcs->UpdateRegion && D_FLAGS_IS_SET( region->state, CLRSF_REALIZED )) { + if (surface) { + CoreSurfaceAllocation *allocation; + + allocation = region->surface_lock.allocation; + D_ASSERT( allocation != NULL ); + + /* If hardware has written or is writing... */ + if (allocation->accessed[CSAID_GPU] & CSAF_WRITE) { + D_DEBUG_AT( Core_Layers, " -> Waiting for pending writes...\n" ); + + /* ...wait for the operation to finish. */ + if (!(flags & DSFLIP_PIPELINE)) + dfb_gfxcard_sync(); /* TODO: wait for serial instead */ + + allocation->accessed[CSAID_GPU] &= ~CSAF_WRITE; + } + + dfb_surface_lock( surface ); + dfb_surface_allocation_update( allocation, CSAF_READ ); + dfb_surface_unlock( surface ); + } + + D_DEBUG_AT( Core_Layers, " -> Notifying driver about updated content...\n" ); + + if( !update ) { + unrotated = DFB_REGION_INIT_FROM_RECTANGLE_VALS( 0, 0, + region->config.width, region->config.height ); + update = &unrotated; + } + dfb_region_from_rotated( &rotated, update, &surface->config.size, surface->rotation ); + + ret = funcs->UpdateRegion( layer, + layer->driver_data, + layer->layer_data, + region->region_data, + surface, &rotated, ®ion->surface_lock ); + } + break; + + default: + D_BUG("unknown buffer mode"); + ret = DFB_BUG; + } + + D_DEBUG_AT( Core_Layers, " -> done.\n" ); + + /* Unlock the region. */ + dfb_layer_region_unlock( region ); + + return ret; +} + +DFBResult +dfb_layer_region_set_configuration( CoreLayerRegion *region, + CoreLayerRegionConfig *config, + CoreLayerRegionConfigFlags flags ) +{ + DFBResult ret; + CoreLayer *layer; + const DisplayLayerFuncs *funcs; + CoreLayerRegionConfig new_config; + + D_ASSERT( region != NULL ); + D_ASSERT( region->context != NULL ); + D_ASSERT( config != NULL ); + D_ASSERT( config->buffermode != DLBM_WINDOWS ); + D_ASSERT( (flags == CLRCF_ALL) || (region->state & CLRSF_CONFIGURED) ); + + D_ASSUME( flags != CLRCF_NONE ); + D_ASSUME( ! (flags & ~CLRCF_ALL) ); + + layer = dfb_layer_at( region->context->layer_id ); + + D_ASSERT( layer != NULL ); + D_ASSERT( layer->funcs != NULL ); + D_ASSERT( layer->funcs->TestRegion != NULL ); + + funcs = layer->funcs; + + /* Lock the region. */ + if (dfb_layer_region_lock( region )) + return DFB_FUSION; + + /* Full configuration supplied? */ + if (flags == CLRCF_ALL) { + new_config = *config; + } + else { + /* Use the current configuration. */ + new_config = region->config; + + /* Update each modified entry. */ + if (flags & CLRCF_WIDTH) + new_config.width = config->width; + + if (flags & CLRCF_HEIGHT) + new_config.height = config->height; + + if (flags & CLRCF_FORMAT) + new_config.format = config->format; + + if (flags & CLRCF_SURFACE_CAPS) + new_config.surface_caps = config->surface_caps; + + if (flags & CLRCF_BUFFERMODE) + new_config.buffermode = config->buffermode; + + if (flags & CLRCF_OPTIONS) + new_config.options = config->options; + + if (flags & CLRCF_SOURCE_ID) + new_config.source_id = config->source_id; + + if (flags & CLRCF_SOURCE) + new_config.source = config->source; + + if (flags & CLRCF_DEST) + new_config.dest = config->dest; + + if (flags & CLRCF_OPACITY) + new_config.opacity = config->opacity; + + if (flags & CLRCF_ALPHA_RAMP) { + new_config.alpha_ramp[0] = config->alpha_ramp[0]; + new_config.alpha_ramp[1] = config->alpha_ramp[1]; + new_config.alpha_ramp[2] = config->alpha_ramp[2]; + new_config.alpha_ramp[3] = config->alpha_ramp[3]; + } + + if (flags & CLRCF_SRCKEY) + new_config.src_key = config->src_key; + + if (flags & CLRCF_DSTKEY) + new_config.dst_key = config->dst_key; + + if (flags & CLRCF_PARITY) + new_config.parity = config->parity; + + if (flags & CLRCF_CLIPS) { + new_config.clips = config->clips; + new_config.num_clips = config->num_clips; + new_config.positive = config->positive; + } + } + + /* Check if the new configuration is supported. */ + ret = funcs->TestRegion( layer, layer->driver_data, layer->layer_data, + &new_config, NULL ); + if (ret) { + dfb_layer_region_unlock( region ); + return ret; + } + + /* Check if the region should be frozen, thus requiring to apply changes explicitly. */ + if (flags & CLRCF_FREEZE) + region->state |= CLRSF_FROZEN; + + /* Propagate new configuration to the driver if the region is realized. */ + if (D_FLAGS_IS_SET( region->state, CLRSF_REALIZED )) { + ret = set_region( region, &new_config, flags, region->surface ); + if (ret) { + dfb_layer_region_unlock( region ); + return ret; + } + } + + /* Update the region's current configuration. */ + region->config = new_config; + + /* Update the region's state. */ + D_FLAGS_SET( region->state, CLRSF_CONFIGURED ); + + /* Unlock the region. */ + dfb_layer_region_unlock( region ); + + return DFB_OK; +} + +DFBResult +dfb_layer_region_get_configuration( CoreLayerRegion *region, + CoreLayerRegionConfig *config ) +{ + D_ASSERT( region != NULL ); + D_ASSERT( config != NULL ); + + D_ASSERT( D_FLAGS_IS_SET( region->state, CLRSF_CONFIGURED ) ); + + /* Lock the region. */ + if (dfb_layer_region_lock( region )) + return DFB_FUSION; + + /* Return the current configuration. */ + *config = region->config; + + /* Unlock the region. */ + dfb_layer_region_unlock( region ); + + return DFB_OK; +} + +DirectResult +dfb_layer_region_lock( CoreLayerRegion *region ) +{ + D_ASSERT( region != NULL ); + + return fusion_skirmish_prevail( ®ion->lock ); +} + +DirectResult +dfb_layer_region_unlock( CoreLayerRegion *region ) +{ + D_ASSERT( region != NULL ); + + return fusion_skirmish_dismiss( ®ion->lock ); +} + +/******************************************************************************/ + +/* + * listen to the layer's surface + */ +ReactionResult +_dfb_layer_region_surface_listener( const void *msg_data, void *ctx ) +{ + CoreSurfaceNotificationFlags flags; + CoreSurface *surface; + CoreLayer *layer; + CoreLayerShared *shared; + const DisplayLayerFuncs *funcs; + const CoreSurfaceNotification *notification = msg_data; + CoreLayerRegion *region = ctx; + + D_ASSERT( notification != NULL ); + D_ASSERT( region != NULL ); + D_ASSERT( region->context != NULL ); + + D_DEBUG_AT( Core_Layers, "_dfb_layer_region_surface_listener( %p, %p ) <- 0x%08x\n", + notification, region, notification->flags ); + + D_ASSERT( notification->surface != NULL ); + + D_ASSUME( notification->surface == region->surface ); + + if (notification->surface != region->surface) + return RS_OK; + + layer = dfb_layer_at( region->context->layer_id ); + + D_ASSERT( layer != NULL ); + D_ASSERT( layer->funcs != NULL ); + D_ASSERT( layer->funcs->SetRegion != NULL ); + D_ASSERT( layer->shared != NULL ); + + funcs = layer->funcs; + shared = layer->shared; + + flags = notification->flags; + surface = notification->surface; + + if (flags & CSNF_DESTROY) { + D_WARN( "layer region surface destroyed" ); + region->surface = NULL; + return RS_REMOVE; + } + + if (dfb_layer_region_lock( region )) + return RS_OK; + + if (D_FLAGS_ARE_SET( region->state, CLRSF_REALIZED | CLRSF_CONFIGURED ) && + !D_FLAGS_IS_SET( region->state, CLRSF_FROZEN )) + { + if (D_FLAGS_IS_SET( flags, CSNF_PALETTE_CHANGE | CSNF_PALETTE_UPDATE )) { + if (surface->palette) + funcs->SetRegion( layer, + layer->driver_data, layer->layer_data, + region->region_data, ®ion->config, + CLRCF_PALETTE, surface, surface->palette, + ®ion->surface_lock ); + } + + if ((flags & CSNF_FIELD) && funcs->SetInputField) + funcs->SetInputField( layer, + layer->driver_data, layer->layer_data, + region->region_data, surface->field ); + + if ((flags & CSNF_ALPHA_RAMP) && (shared->description.caps & DLCAPS_ALPHA_RAMP)) { + region->config.alpha_ramp[0] = surface->alpha_ramp[0]; + region->config.alpha_ramp[1] = surface->alpha_ramp[1]; + region->config.alpha_ramp[2] = surface->alpha_ramp[2]; + region->config.alpha_ramp[3] = surface->alpha_ramp[3]; + + funcs->SetRegion( layer, + layer->driver_data, layer->layer_data, + region->region_data, ®ion->config, + CLRCF_ALPHA_RAMP, surface, surface->palette, + ®ion->surface_lock ); + } + } + + dfb_layer_region_unlock( region ); + + return RS_OK; +} + +/******************************************************************************/ + +static DFBResult +region_buffer_lock( CoreLayerRegion *region, + CoreSurface *surface, + CoreSurfaceBufferRole role ) +{ + DFBResult ret; + CoreSurfaceBuffer *buffer; + CoreSurfaceAllocation *allocation; + CoreLayerContext *context; + + D_ASSERT( region != NULL ); + D_MAGIC_ASSERT( surface, CoreSurface ); + + context = region->context; + D_MAGIC_ASSERT( context, CoreLayerContext ); + + /* First unlock any previously locked buffer. */ + if (region->surface_lock.buffer) { + D_MAGIC_ASSERT( region->surface_lock.buffer, CoreSurfaceBuffer ); + + dfb_surface_unlock_buffer( region->surface_lock.buffer->surface, ®ion->surface_lock ); + } + + if (dfb_surface_lock( surface )) + return DFB_FUSION; + + buffer = dfb_surface_get_buffer( surface, role ); + D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); + + /* Lock the surface buffer. */ + ret = dfb_surface_buffer_lock( buffer, CSAID_LAYER0 + context->layer_id, CSAF_READ, ®ion->surface_lock ); + if (ret) { + D_DERROR( ret, "Core/LayerRegion: Could not lock region surface for SetRegion()!\n" ); + dfb_surface_unlock( surface ); + return ret; + } + + allocation = region->surface_lock.allocation; + D_ASSERT( allocation != NULL ); + + /* If hardware has written or is writing... */ + if (allocation->accessed[CSAID_GPU] & CSAF_WRITE) { + D_DEBUG_AT( Core_Layers, " -> Waiting for pending writes...\n" ); + + /* ...wait for the operation to finish. */ + dfb_gfxcard_sync(); /* TODO: wait for serial instead */ + + allocation->accessed[CSAID_GPU] &= ~CSAF_WRITE; + } + + /* surface is unlocked by caller */ + + return DFB_OK; +} + +static DFBResult +set_region( CoreLayerRegion *region, + CoreLayerRegionConfig *config, + CoreLayerRegionConfigFlags flags, + CoreSurface *surface ) +{ + DFBResult ret; + CoreLayer *layer; + CoreLayerShared *shared; + const DisplayLayerFuncs *funcs; + + D_DEBUG_AT( Core_Layers, "%s( %p, %p, 0x%08x, %p )\n", __FUNCTION__, region, config, flags, surface ); + + DFB_CORE_LAYER_REGION_CONFIG_DEBUG_AT( Core_Layers, config ); + + D_DEBUG_AT( Core_Layers, " -> state 0x%08x\n", region->state ); + + D_ASSERT( region != NULL ); + D_ASSERT( region->context != NULL ); + D_ASSERT( config != NULL ); + D_ASSERT( config->buffermode != DLBM_WINDOWS ); + + D_ASSERT( D_FLAGS_IS_SET( region->state, CLRSF_REALIZED ) ); + + layer = dfb_layer_at( region->context->layer_id ); + + D_ASSERT( layer != NULL ); + D_ASSERT( layer->shared != NULL ); + D_ASSERT( layer->funcs != NULL ); + D_ASSERT( layer->funcs->SetRegion != NULL ); + + if (region->state & CLRSF_FROZEN) { + D_DEBUG_AT( Core_Layers, " -> FROZEN!\n" ); + return DFB_OK; + } + + shared = layer->shared; + funcs = layer->funcs; + + if (surface) { + if (flags & (CLRCF_SURFACE | CLRCF_WIDTH | CLRCF_HEIGHT | CLRCF_FORMAT)) { + ret = region_buffer_lock( region, surface, CSBR_FRONT ); + if (ret) + return ret; + + dfb_surface_unlock( surface ); + } + + D_ASSERT( region->surface_lock.buffer != NULL ); + } + else if (region->surface_lock.buffer) { + D_MAGIC_ASSERT( region->surface_lock.buffer, CoreSurfaceBuffer ); + + dfb_surface_unlock_buffer( region->surface_lock.buffer->surface, ®ion->surface_lock ); + } + + D_DEBUG_AT( Core_Layers, " => setting region of '%s'\n", shared->description.name ); + + /* Setup hardware. */ + return funcs->SetRegion( layer, layer->driver_data, layer->layer_data, + region->region_data, config, flags, + surface, surface ? surface->palette : NULL, ®ion->surface_lock ); +} + +static DFBResult +realize_region( CoreLayerRegion *region ) +{ + DFBResult ret; + CoreLayer *layer; + CoreLayerShared *shared; + const DisplayLayerFuncs *funcs; + + D_DEBUG_AT( Core_Layers, "%s( %p )\n", __FUNCTION__, region ); + + D_ASSERT( region != NULL ); + + DFB_CORE_LAYER_REGION_CONFIG_DEBUG_AT( Core_Layers, ®ion->config ); + + D_DEBUG_AT( Core_Layers, " -> state 0x%08x\n", region->state ); + + D_ASSERT( region->context != NULL ); + D_ASSERT( D_FLAGS_IS_SET( region->state, CLRSF_CONFIGURED ) ); + D_ASSERT( ! D_FLAGS_IS_SET( region->state, CLRSF_REALIZED ) ); + + layer = dfb_layer_at( region->context->layer_id ); + + D_ASSERT( layer != NULL ); + D_ASSERT( layer->shared != NULL ); + D_ASSERT( layer->funcs != NULL ); + + shared = layer->shared; + funcs = layer->funcs; + + D_ASSERT( ! fusion_vector_contains( &shared->added_regions, region ) ); + + if (region->state & CLRSF_FROZEN) { + D_DEBUG_AT( Core_Layers, " -> FROZEN!\n" ); + return DFB_OK; + } + + /* Allocate the driver's region data. */ + if (funcs->RegionDataSize) { + int size = funcs->RegionDataSize(); + + if (size > 0) { + region->region_data = SHCALLOC( shared->shmpool, 1, size ); + if (!region->region_data) + return D_OOSHM(); + } + } + + D_DEBUG_AT( Core_Layers, " => adding region to '%s'\n", shared->description.name ); + + /* Add the region to the driver. */ + if (funcs->AddRegion) { + ret = funcs->AddRegion( layer, + layer->driver_data, layer->layer_data, + region->region_data, ®ion->config ); + if (ret) { + D_DERROR( ret, "Core/Layers: Could not add region!\n" ); + + if (region->region_data) { + SHFREE( shared->shmpool, region->region_data ); + region->region_data = NULL; + } + + return ret; + } + } + + /* Add the region to the 'added' list. */ + fusion_vector_add( &shared->added_regions, region ); + + /* Update the region's state. */ + D_FLAGS_SET( region->state, CLRSF_REALIZED ); + + /* Initially setup hardware. */ + ret = set_region( region, ®ion->config, CLRCF_ALL, region->surface ); + if (ret) { + unrealize_region( region ); + return ret; + } + + return DFB_OK; +} + +static DFBResult +unrealize_region( CoreLayerRegion *region ) +{ + DFBResult ret; + int index; + CoreLayer *layer; + CoreLayerShared *shared; + const DisplayLayerFuncs *funcs; + + D_DEBUG_AT( Core_Layers, "%s( %p )\n", __FUNCTION__, region ); + + D_ASSERT( region != NULL ); + + DFB_CORE_LAYER_REGION_CONFIG_DEBUG_AT( Core_Layers, ®ion->config ); + + D_DEBUG_AT( Core_Layers, " -> state 0x%08x\n", region->state ); + + D_ASSERT( region->context != NULL ); + D_ASSERT( D_FLAGS_IS_SET( region->state, CLRSF_REALIZED ) ); + + layer = dfb_layer_at( region->context->layer_id ); + + D_ASSERT( layer != NULL ); + D_ASSERT( layer->shared != NULL ); + D_ASSERT( layer->funcs != NULL ); + + shared = layer->shared; + funcs = layer->funcs; + + D_ASSERT( fusion_vector_contains( &shared->added_regions, region ) ); + + index = fusion_vector_index_of( &shared->added_regions, region ); + + D_DEBUG_AT( Core_Layers, " => removing region from '%s'\n", shared->description.name ); + + /* Remove the region from hardware and driver. */ + if (funcs->RemoveRegion) { + ret = funcs->RemoveRegion( layer, layer->driver_data, + layer->layer_data, region->region_data ); + if (ret) { + D_DERROR( ret, "Core/Layers: Could not remove region!\n" ); + return ret; + } + } + + /* Remove the region from the 'added' list. */ + fusion_vector_remove( &shared->added_regions, index ); + + /* Deallocate the driver's region data. */ + if (region->region_data) { + SHFREE( shared->shmpool, region->region_data ); + region->region_data = NULL; + } + + /* Update the region's state. */ + D_FLAGS_CLEAR( region->state, CLRSF_REALIZED ); + D_FLAGS_SET( region->state, CLRSF_FROZEN ); + + if (region->surface && region->surface_lock.buffer) { + dfb_surface_unlock_buffer( region->surface, ®ion->surface_lock ); + // PR brg36mgr#147044: [550r3cr1][CRASH][UI]set crashes when going through settings assistant + // This is because the YUV layer buffer is allocated in memory recuperated from the video flow + // and is only valid in the JPEG usecase. + // When the application destroys its window (on leaving the usecase),the layer buffer must + // also be removed. + dfb_surface_destroy_buffers( region->surface ); + } + + return DFB_OK; +} + diff --git a/Source/DirectFB/src/core/layer_region.h b/Source/DirectFB/src/core/layer_region.h new file mode 100755 index 0000000..29221a9 --- /dev/null +++ b/Source/DirectFB/src/core/layer_region.h @@ -0,0 +1,100 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __CORE__LAYER_REGION_H__ +#define __CORE__LAYER_REGION_H__ + +#include + +#include +#include + +#include + + +typedef enum { + CLRNF_NONE = 0x00000000 +} CoreLayerRegionNotificationFlags; + +typedef struct { + CoreLayerRegionNotificationFlags flags; + CoreLayerRegion *region; +} CoreLayerRegionNotification; + +/* + * Creates a pool of layer region objects. + */ +FusionObjectPool *dfb_layer_region_pool_create( const FusionWorld *world ); + +/* + * Generates dfb_layer_region_ref(), dfb_layer_region_attach() etc. + */ +FUSION_OBJECT_METHODS( CoreLayerRegion, dfb_layer_region ) + + +DFBResult dfb_layer_region_create ( CoreLayerContext *context, + CoreLayerRegion **ret_region ); + +DFBResult dfb_layer_region_activate ( CoreLayerRegion *region ); + +DFBResult dfb_layer_region_deactivate ( CoreLayerRegion *region ); + +DFBResult dfb_layer_region_enable ( CoreLayerRegion *region ); + +DFBResult dfb_layer_region_disable ( CoreLayerRegion *region ); + +DFBResult dfb_layer_region_set_surface ( CoreLayerRegion *region, + CoreSurface *surface ); + +DFBResult dfb_layer_region_get_surface ( CoreLayerRegion *region, + CoreSurface **ret_surface ); + +DFBResult dfb_layer_region_flip_update ( CoreLayerRegion *region, + const DFBRegion *update, + DFBSurfaceFlipFlags flags ); + + +/* + * Configuration + */ +DFBResult dfb_layer_region_set_configuration( CoreLayerRegion *region, + CoreLayerRegionConfig *config, + CoreLayerRegionConfigFlags flags ); + +DFBResult dfb_layer_region_get_configuration( CoreLayerRegion *region, + CoreLayerRegionConfig *config ); + + +/* + * Locking + */ +DirectResult dfb_layer_region_lock ( CoreLayerRegion *region ); +DirectResult dfb_layer_region_unlock( CoreLayerRegion *region ); + +#endif + diff --git a/Source/DirectFB/src/core/layers.c b/Source/DirectFB/src/core/layers.c new file mode 100755 index 0000000..29c0de8 --- /dev/null +++ b/Source/DirectFB/src/core/layers.c @@ -0,0 +1,640 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include + + +D_DEBUG_DOMAIN( Core_Layer, "Core/Layer", "DirectFB Display Layer Core" ); + +/**********************************************************************************************************************/ + +typedef struct { + int magic; + + int num; + CoreLayerShared *layers[MAX_LAYERS]; +} DFBLayerCoreShared; + +struct __DFB_DFBLayerCore { + int magic; + + CoreDFB *core; + + DFBLayerCoreShared *shared; +}; + + +DFB_CORE_PART( layer_core, LayerCore ); + +/**********************************************************************************************************************/ + +static int dfb_num_layers; +static CoreLayer *dfb_layers[MAX_LAYERS]; + +/** FIXME: Add proper error paths! **/ + +static DFBResult +dfb_layer_core_initialize( CoreDFB *core, + DFBLayerCore *data, + DFBLayerCoreShared *shared ) +{ + int i; + DFBResult ret; + FusionSHMPoolShared *pool; + + D_DEBUG_AT( Core_Layer, "dfb_layer_core_initialize( %p, %p, %p )\n", core, data, shared ); + + D_ASSERT( data != NULL ); + D_ASSERT( shared != NULL ); + + data->core = core; + data->shared = shared; + + + pool = dfb_core_shmpool( core ); + + /* Initialize all registered layers. */ + for (i=0; ifuncs; + + /* Allocate shared data. */ + lshared = SHCALLOC( pool, 1, sizeof(CoreLayerShared) ); + + /* Assign ID (zero based index). */ + lshared->layer_id = i; + lshared->shmpool = pool; + + snprintf( buf, sizeof(buf), "Display Layer %d", i ); + + /* Initialize the lock. */ + ret = fusion_skirmish_init( &lshared->lock, buf, dfb_core_world(core) ); + if (ret) + return ret; + + /* Allocate driver's layer data. */ + if (funcs->LayerDataSize) { + int size = funcs->LayerDataSize(); + + if (size > 0) { + lshared->layer_data = SHCALLOC( pool, 1, size ); + if (!lshared->layer_data) + return D_OOSHM(); + } + } + + /* Initialize the layer, get the layer description, + the default configuration and default color adjustment. */ + ret = funcs->InitLayer( layer, + layer->driver_data, + lshared->layer_data, + &lshared->description, + &lshared->default_config, + &lshared->default_adjustment ); + if (ret) { + D_DERROR( ret, "DirectFB/Core/layers: " + "Failed to initialize layer %d!\n", lshared->layer_id ); + return ret; + } + + if (lshared->description.caps & DLCAPS_SOURCES) { + int n; + + lshared->sources = SHCALLOC( pool, lshared->description.sources, sizeof(CoreLayerSource) ); + if (!lshared->sources) + return D_OOSHM(); + + for (n=0; ndescription.sources; n++) { + CoreLayerSource *source = &lshared->sources[n]; + + source->index = n; + + ret = funcs->InitSource( layer, layer->driver_data, + lshared->layer_data, n, &source->description ); + if (ret) { + D_DERROR( ret, "DirectFB/Core/layers: Failed to initialize source %d " + "of layer %d!\n", n, lshared->layer_id ); + return ret; + } + } + } + + if (D_FLAGS_IS_SET( lshared->description.caps, DLCAPS_SCREEN_LOCATION )) + D_FLAGS_SET( lshared->description.caps, DLCAPS_SCREEN_POSITION | DLCAPS_SCREEN_SIZE ); + + if (D_FLAGS_ARE_SET( lshared->description.caps, + DLCAPS_SCREEN_POSITION | DLCAPS_SCREEN_SIZE )) + D_FLAGS_SET( lshared->description.caps, DLCAPS_SCREEN_LOCATION ); + + /* Initialize the vector for the contexts. */ + fusion_vector_init( &lshared->contexts.stack, 4, pool ); + + /* Initialize the vector for realized (added) regions. */ + fusion_vector_init( &lshared->added_regions, 4, pool ); + + /* No active context by default. */ + lshared->contexts.active = -1; + + /* Store layer data. */ + layer->layer_data = lshared->layer_data; + + /* Store pointer to shared data and core. */ + layer->shared = lshared; + layer->core = core; + + /* Add the layer to the shared list. */ + shared->layers[ shared->num++ ] = lshared; + } + + + D_MAGIC_SET( data, DFBLayerCore ); + D_MAGIC_SET( shared, DFBLayerCoreShared ); + + return DFB_OK; +} + +static DFBResult +dfb_layer_core_join( CoreDFB *core, + DFBLayerCore *data, + DFBLayerCoreShared *shared ) +{ + int i; + + D_DEBUG_AT( Core_Layer, "dfb_layer_core_join( %p, %p, %p )\n", core, data, shared ); + + D_ASSERT( data != NULL ); + D_MAGIC_ASSERT( shared, DFBLayerCoreShared ); + + data->core = core; + data->shared = shared; + + + if (dfb_num_layers != shared->num) { + D_ERROR("DirectFB/core/layers: Number of layers does not match!\n"); + return DFB_BUG; + } + + for (i=0; ilayers[i]; + + /* make a copy for faster access */ + layer->layer_data = lshared->layer_data; + + /* store pointer to shared data and core */ + layer->shared = lshared; + layer->core = core; + } + + + D_MAGIC_SET( data, DFBLayerCore ); + + return DFB_OK; +} + +static DFBResult +dfb_layer_core_shutdown( DFBLayerCore *data, + bool emergency ) +{ + int i; + DFBResult ret; + DFBLayerCoreShared *shared; + + D_DEBUG_AT( Core_Layer, "dfb_layer_core_shutdown( %p, %semergency )\n", data, emergency ? "" : "no " ); + + D_MAGIC_ASSERT( data, DFBLayerCore ); + D_MAGIC_ASSERT( data->shared, DFBLayerCoreShared ); + + shared = data->shared; + + + /* Begin with the most recently added layer. */ + for (i=dfb_num_layers-1; i>=0; i--) { + CoreLayer *layer = dfb_layers[i]; + CoreLayerShared *shared = layer->shared; + const DisplayLayerFuncs *funcs = layer->funcs; + + D_ASSUME( emergency || fusion_vector_is_empty( &shared->added_regions ) ); + + /* Remove all regions during emergency shutdown. */ + if (emergency && funcs->RemoveRegion) { + int n; + CoreLayerRegion *region; + + fusion_vector_foreach( region, n, shared->added_regions ) { + D_DEBUG_AT( Core_Layer, "Removing region (%d, %d - %dx%d) from '%s'.\n", + DFB_RECTANGLE_VALS( ®ion->config.dest ), + shared->description.name ); + + ret = funcs->RemoveRegion( layer, layer->driver_data, + layer->layer_data, region->region_data ); + if (ret) + D_DERROR( ret, "Core/Layers: Could not remove region!\n" ); + } + } + + /* Deinitialize the lock. */ + fusion_skirmish_destroy( &shared->lock ); + + /* Deinitialize the state for window stack repaints. */ + dfb_state_destroy( &layer->state ); + + /* Deinitialize the vector for the contexts. */ + fusion_vector_destroy( &shared->contexts.stack ); + + /* Deinitialize the vector for the realized (added) regions. */ + fusion_vector_destroy( &shared->added_regions ); + + /* Free the driver's layer data. */ + if (shared->layer_data) + SHFREE( shared->shmpool, shared->layer_data ); + + /* Free the shared layer data. */ + SHFREE( shared->shmpool, shared ); + + /* Free the local layer data. */ + D_FREE( layer ); + } + + dfb_num_layers = 0; + + + D_MAGIC_CLEAR( data ); + D_MAGIC_CLEAR( shared ); + + return DFB_OK; +} + +static DFBResult +dfb_layer_core_leave( DFBLayerCore *data, + bool emergency ) +{ + int i; + DFBLayerCoreShared *shared; + + D_DEBUG_AT( Core_Layer, "dfb_layer_core_leave( %p, %semergency )\n", data, emergency ? "" : "no " ); + + D_MAGIC_ASSERT( data, DFBLayerCore ); + D_MAGIC_ASSERT( data->shared, DFBLayerCoreShared ); + + shared = data->shared; + + + /* Deinitialize all local stuff. */ + for (i=0; istate ); + + /* Free local layer data. */ + D_FREE( layer ); + } + + dfb_num_layers = 0; + + + D_MAGIC_CLEAR( data ); + + return DFB_OK; +} + +static DFBResult +dfb_layer_core_suspend( DFBLayerCore *data ) +{ + int i; + DFBLayerCoreShared *shared; + + D_DEBUG_AT( Core_Layer, "dfb_layer_core_suspend( %p )\n", data ); + + D_MAGIC_ASSERT( data, DFBLayerCore ); + D_MAGIC_ASSERT( data->shared, DFBLayerCoreShared ); + + shared = data->shared; + + for (i=dfb_num_layers-1; i>=0; i--) + dfb_layer_suspend( dfb_layers[i] ); + + return DFB_OK; +} + +static DFBResult +dfb_layer_core_resume( DFBLayerCore *data ) +{ + int i; + DFBLayerCoreShared *shared; + + D_DEBUG_AT( Core_Layer, "dfb_layer_core_resume( %p )\n", data ); + + D_MAGIC_ASSERT( data, DFBLayerCore ); + D_MAGIC_ASSERT( data->shared, DFBLayerCoreShared ); + + shared = data->shared; + + for (i=0; idevice = screen->device; + layer->screen = screen; + layer->driver_data = driver_data; + layer->funcs = funcs; + + /* Initialize the state for window stack repaints */ + dfb_state_init( &layer->state, NULL ); + + /* add it to the local list */ + dfb_layers[dfb_num_layers++] = layer; + + return layer; +} + +typedef void (*AnyFunc)( void ); + +CoreLayer * +dfb_layers_hook_primary( CoreGraphicsDevice *device, + void *driver_data, + DisplayLayerFuncs *funcs, + DisplayLayerFuncs *primary_funcs, + void **primary_driver_data ) +{ + int i; + int entries; + CoreLayer *primary = dfb_layers[0]; + + D_ASSERT( primary != NULL ); + D_ASSERT( device != NULL ); + D_ASSERT( funcs != NULL ); + + /* copy content of original function table */ + if (primary_funcs) + direct_memcpy( primary_funcs, primary->funcs, sizeof(DisplayLayerFuncs) ); + + /* copy pointer to original driver data */ + if (primary_driver_data) + *primary_driver_data = primary->driver_data; + + /* replace all entries in the old table that aren't NULL in the new one */ + entries = sizeof(DisplayLayerFuncs) / sizeof(void(*)( void )); + for (i=0; ifuncs; + + if (newfuncs[i]) + oldfuncs[i] = newfuncs[i]; + } + + /* replace device and driver data pointer */ + primary->device = device; + primary->driver_data = driver_data; + + return primary; +} + +CoreLayer * +dfb_layers_replace_primary( CoreGraphicsDevice *device, + void *driver_data, + DisplayLayerFuncs *funcs ) +{ + CoreLayer *primary = dfb_layers[0]; + + D_ASSERT( primary != NULL ); + D_ASSERT( device != NULL ); + D_ASSERT( funcs != NULL ); + + /* replace device, function table and driver data pointer */ + primary->device = device; + primary->funcs = funcs; + primary->driver_data = driver_data; + + return primary; +} + +void +dfb_layers_enumerate( DisplayLayerCallback callback, + void *ctx ) +{ + int i; + + D_ASSERT( callback != NULL ); + + for (i=0; i= 0); + D_ASSERT( id < dfb_num_layers); + + return dfb_layers[id]; +} + +CoreLayer * +dfb_layer_at_translated( DFBDisplayLayerID id ) +{ + D_ASSERT( id >= 0); + D_ASSERT( id < dfb_num_layers); + D_ASSERT( dfb_config != NULL ); + + if (dfb_config->primary_layer > 0 && + dfb_config->primary_layer < dfb_num_layers) + { + if (id == DLID_PRIMARY) + return dfb_layer_at( dfb_config->primary_layer ); + + if (id == dfb_config->primary_layer) + return dfb_layer_at( DLID_PRIMARY ); + } + + return dfb_layer_at( id ); +} + +void +dfb_layer_get_description( const CoreLayer *layer, + DFBDisplayLayerDescription *desc ) +{ + D_ASSERT( layer != NULL ); + D_ASSERT( layer->shared != NULL ); + D_ASSERT( desc != NULL ); + + *desc = layer->shared->description; +} + +CoreScreen * +dfb_layer_screen( const CoreLayer *layer ) +{ + D_ASSERT( layer != NULL ); + + return layer->screen; +} + +CardState * +dfb_layer_state( CoreLayer *layer ) +{ + D_ASSERT( layer != NULL ); + + return &layer->state; +} + +DFBDisplayLayerID +dfb_layer_id( const CoreLayer *layer ) +{ + D_ASSERT( layer != NULL ); + D_ASSERT( layer->shared != NULL ); + + return layer->shared->layer_id; +} + +DFBDisplayLayerID +dfb_layer_id_translated( const CoreLayer *layer ) +{ + CoreLayerShared *shared; + + D_ASSERT( layer != NULL ); + D_ASSERT( layer->shared != NULL ); + D_ASSERT( dfb_config != NULL ); + + shared = layer->shared; + + if (dfb_config->primary_layer > 0 && + dfb_config->primary_layer < dfb_num_layers) + { + if (shared->layer_id == DLID_PRIMARY) + return dfb_config->primary_layer; + + if (shared->layer_id == dfb_config->primary_layer) + return DLID_PRIMARY; + } + + return shared->layer_id; +} + +DFBSurfacePixelFormat +dfb_primary_layer_pixelformat( void ) +{ + CoreLayerShared *shared; + CoreLayerContext *context; + CoreLayer *layer = dfb_layer_at_translated(DLID_PRIMARY); + DFBSurfacePixelFormat format = DSPF_UNKNOWN; + + D_ASSERT( layer != NULL ); + D_ASSERT( layer->shared != NULL ); + + shared = layer->shared; + + /* If no context is active, return the default format. */ + if (dfb_layer_get_active_context( layer, &context ) != DFB_OK) + return shared->default_config.pixelformat; + + /* Use the format from the current configuration. */ + format = context->config.pixelformat; + + /* Decrease the context's reference counter. */ + dfb_layer_context_unref( context ); + + return format; +} + diff --git a/Source/DirectFB/src/core/layers.h b/Source/DirectFB/src/core/layers.h new file mode 100755 index 0000000..68a1d9e --- /dev/null +++ b/Source/DirectFB/src/core/layers.h @@ -0,0 +1,359 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __CORE__LAYERS_H__ +#define __CORE__LAYERS_H__ + +#include + +#include + +#include +#include + + +struct __DFB_CoreLayerRegionConfig { + int width; /* width of the source in pixels */ + int height; /* height of the source in pixels */ + DFBSurfacePixelFormat format; /* pixel format of the source surface */ + DFBSurfaceCapabilities surface_caps; /* capabilities of the source surface */ + DFBDisplayLayerBufferMode buffermode; /* surface buffer configuration */ + + DFBDisplayLayerOptions options; /* various configuration options */ + + DFBDisplayLayerSourceID source_id; /* selected source */ + + DFBRectangle source; /* viewport within source (input) */ + DFBRectangle dest; /* viewport on screen (output) */ + + u8 opacity; /* global region alpha */ + + DFBColorKey src_key; /* source color key */ + DFBColorKey dst_key; /* destination color key */ + + int parity; /* field parity (for interlaced) */ + + u8 alpha_ramp[4]; /* alpha values for 1 or 2 bit lookup */ + + DFBRegion *clips; /* clip regions */ + int num_clips; /* number of clip regions */ + DFBBoolean positive; /* show or cut out regions */ +}; + +#if D_DEBUG_ENABLED +#define DFB_CORE_LAYER_REGION_CONFIG_DEBUG_AT( domain, config ) \ + do { \ + const CoreLayerRegionConfig *_config = config; \ + \ + D_DEBUG_AT( domain, " -> size %dx%d\n", _config->width, _config->height ); \ + D_DEBUG_AT( domain, " -> format %s\n", dfb_pixelformat_name( _config->format ) ); \ + D_DEBUG_AT( domain, " -> surf caps 0x%08x\n", _config->surface_caps ); \ + D_DEBUG_AT( domain, " -> buffermode %d\n", _config->buffermode ); \ + D_DEBUG_AT( domain, " -> options 0x%08x\n", _config->options ); \ + D_DEBUG_AT( domain, " -> source %d,%d-%dx%d\n", DFB_RECTANGLE_VALS(&_config->source) ); \ + D_DEBUG_AT( domain, " -> dest %d,%d-%dx%d\n", DFB_RECTANGLE_VALS(&_config->dest) ); \ + D_DEBUG_AT( domain, " -> opacity %d\n", _config->opacity ); \ + D_DEBUG_AT( domain, " -> src_key %02x%02x%02x (index %d)\n", DFB_COLORKEY_VALS(&_config->src_key) ); \ + D_DEBUG_AT( domain, " -> dst_key %02x%02x%02x (index %d)\n", DFB_COLORKEY_VALS(&_config->dst_key) ); \ + } while (0) +#else +#define DFB_CORE_LAYER_REGION_CONFIG_DEBUG_AT( domain, config ) \ + do { \ + } while (0) +#endif + +typedef enum { + CLRCF_NONE = 0x00000000, + + CLRCF_WIDTH = 0x00000001, + CLRCF_HEIGHT = 0x00000002, + CLRCF_FORMAT = 0x00000004, + CLRCF_SURFACE_CAPS = 0x00000008, + + CLRCF_BUFFERMODE = 0x00000010, + CLRCF_OPTIONS = 0x00000020, + CLRCF_SOURCE_ID = 0x00000040, + + CLRCF_SOURCE = 0x00000100, + CLRCF_DEST = 0x00000200, + CLRCF_CLIPS = 0x00000400, + + CLRCF_OPACITY = 0x00001000, + CLRCF_ALPHA_RAMP = 0x00002000, + + CLRCF_SRCKEY = 0x00010000, + CLRCF_DSTKEY = 0x00020000, + + CLRCF_PARITY = 0x00100000, + + CLRCF_SURFACE = 0x10000000, + CLRCF_PALETTE = 0x20000000, + + CLRCF_FREEZE = 0x80000000, + + CLRCF_ALL = 0xB013377F +} CoreLayerRegionConfigFlags; + +typedef struct { + /** Driver Control **/ + + /* + * Return size of layer data (shared memory). + */ + int (*LayerDataSize) ( void ); + + /* + * Return size of region data (shared memory). + */ + int (*RegionDataSize)( void ); + + /* + * Called once by the master to initialize layer data and reset hardware. + * Return layer description, default configuration and color adjustment. + */ + DFBResult (*InitLayer) ( CoreLayer *layer, + void *driver_data, + void *layer_data, + DFBDisplayLayerDescription *description, + DFBDisplayLayerConfig *config, + DFBColorAdjustment *adjustment ); + + /* + * Called once by the master for each source. + * Driver fills description. + */ + DFBResult (*InitSource) ( CoreLayer *layer, + void *driver_data, + void *layer_data, + int source, + DFBDisplayLayerSourceDescription *description ); + + + /** Layer Control **/ + + /* + * Return the currently displayed field (interlaced only). + */ + DFBResult (*GetCurrentOutputField)( CoreLayer *layer, + void *driver_data, + void *layer_data, + int *field ); + + /* + * Return the z position of the layer. + */ + DFBResult (*GetLevel) ( CoreLayer *layer, + void *driver_data, + void *layer_data, + int *level ); + + /* + * Move the layer below or on top of others (z position). + */ + DFBResult (*SetLevel) ( CoreLayer *layer, + void *driver_data, + void *layer_data, + int level ); + + + /** Configuration **/ + + /* + * Adjust brightness, contrast, saturation etc. + */ + DFBResult (*SetColorAdjustment) ( CoreLayer *layer, + void *driver_data, + void *layer_data, + DFBColorAdjustment *adjustment ); + + + /** Region Control **/ + + /* + * Check all parameters and return if this region is supported. + */ + DFBResult (*TestRegion) ( CoreLayer *layer, + void *driver_data, + void *layer_data, + CoreLayerRegionConfig *config, + CoreLayerRegionConfigFlags *failed ); + + /* + * Add a new region to the layer, but don't program hardware, yet. + */ + DFBResult (*AddRegion) ( CoreLayer *layer, + void *driver_data, + void *layer_data, + void *region_data, + CoreLayerRegionConfig *config ); + + /* + * Setup hardware, called once after AddRegion() or when parameters + * have changed. Surface and palette are only set if updated or new. + */ + DFBResult (*SetRegion) ( CoreLayer *layer, + void *driver_data, + void *layer_data, + void *region_data, + CoreLayerRegionConfig *config, + CoreLayerRegionConfigFlags updated, + CoreSurface *surface, + CorePalette *palette, + CoreSurfaceBufferLock *lock ); + + /* + * Remove a region from the layer. + */ + DFBResult (*RemoveRegion) ( CoreLayer *layer, + void *driver_data, + void *layer_data, + void *region_data ); + + /* + * Flip the surface of the region. + */ + DFBResult (*FlipRegion) ( CoreLayer *layer, + void *driver_data, + void *layer_data, + void *region_data, + CoreSurface *surface, + DFBSurfaceFlipFlags flags, + CoreSurfaceBufferLock *lock ); + + /* + * Indicate updates to the front buffer content. + */ + DFBResult (*UpdateRegion) ( CoreLayer *layer, + void *driver_data, + void *layer_data, + void *region_data, + CoreSurface *surface, + const DFBRegion *update, + CoreSurfaceBufferLock *lock ); + + /* + * Control hardware deinterlacing. + */ + DFBResult (*SetInputField)( CoreLayer *layer, + void *driver_data, + void *layer_data, + void *region_data, + int field ); + + + /** Override defaults. Subject to change. **/ + + /* + * Allocate the surface of the region. + */ + DFBResult (*AllocateSurface) ( CoreLayer *layer, + void *driver_data, + void *layer_data, + void *region_data, + CoreLayerRegionConfig *config, + CoreSurface **ret_surface ); + + /* + * Reallocate the surface of the region. + */ + DFBResult (*ReallocateSurface)( CoreLayer *layer, + void *driver_data, + void *layer_data, + void *region_data, + CoreLayerRegionConfig *config, + CoreSurface *surface ); + + /* + * Deallocate the surface of the region. + */ + DFBResult (*DeallocateSurface)( CoreLayer *layer, + void *driver_data, + void *layer_data, + void *region_data, + CoreSurface *surface ); +} DisplayLayerFuncs; + + +/* + * Add a layer to a graphics device by pointing to a table + * containing driver functions. The supplied driver data + * will be passed to these functions. + */ +CoreLayer *dfb_layers_register( CoreScreen *screen, + void *driver_data, + const DisplayLayerFuncs *funcs ); + +/* + * Replace functions of the primary layer implementation by passing + * an alternative driver function table. All non-NULL functions in the new + * table replace the functions in the original function table. + * The original function table is written to 'primary_funcs' before to allow + * drivers to use existing functionality from the original implementation. + */ +CoreLayer *dfb_layers_hook_primary( CoreGraphicsDevice *device, + void *driver_data, + DisplayLayerFuncs *funcs, + DisplayLayerFuncs *primary_funcs, + void **primary_driver_data ); + +/* + * Replace functions of the primary layer implementation completely by passing + * an alternative driver function table. + */ +CoreLayer *dfb_layers_replace_primary( CoreGraphicsDevice *device, + void *driver_data, + DisplayLayerFuncs *funcs ); + +typedef DFBEnumerationResult (*DisplayLayerCallback) (CoreLayer *layer, + void *ctx); + +void dfb_layers_enumerate( DisplayLayerCallback callback, + void *ctx ); + + +int dfb_layer_num( void ); + +CoreLayer *dfb_layer_at( DFBDisplayLayerID id ); + +CoreLayer *dfb_layer_at_translated( DFBDisplayLayerID id ); + + +void dfb_layer_get_description( const CoreLayer *layer, + DFBDisplayLayerDescription *desc ); + +CoreScreen *dfb_layer_screen( const CoreLayer *layer ); + +CardState *dfb_layer_state( CoreLayer *layer ); + +DFBDisplayLayerID dfb_layer_id( const CoreLayer *layer ); + +DFBDisplayLayerID dfb_layer_id_translated( const CoreLayer *layer ); + +DFBSurfacePixelFormat dfb_primary_layer_pixelformat( void ); + +#endif diff --git a/Source/DirectFB/src/core/layers_internal.h b/Source/DirectFB/src/core/layers_internal.h new file mode 100755 index 0000000..c546a33 --- /dev/null +++ b/Source/DirectFB/src/core/layers_internal.h @@ -0,0 +1,196 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __CORE__LAYERS_INTERNAL_H__ +#define __CORE__LAYERS_INTERNAL_H__ + +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include + +typedef struct { + FusionVector stack; + int active; + + CoreLayerContext *primary; +} CoreLayerContexts; + +typedef struct { + int index; + DFBDisplayLayerSourceDescription description; +} CoreLayerSource; + +typedef struct { + DFBDisplayLayerID layer_id; + + DFBDisplayLayerDescription description; + DFBDisplayLayerConfig default_config; + DFBColorAdjustment default_adjustment; + + CoreLayerSource *sources; + + void *layer_data; + + FusionSkirmish lock; + + CoreLayerContexts contexts; + + bool suspended; + + FusionVector added_regions; + + FusionSHMPoolShared *shmpool; +} CoreLayerShared; + +struct __DFB_CoreLayer { + CoreLayerShared *shared; + + CoreDFB *core; + + CoreGraphicsDevice *device; + + CoreScreen *screen; + + void *driver_data; + void *layer_data; /* copy of shared->layer_data */ + + const DisplayLayerFuncs *funcs; + + CardState state; +}; + +typedef enum { + CLLM_LOCATION, /* Keep normalized area. */ + CLLM_CENTER, /* Center layer after resizing destination area. */ + CLLM_POSITION, /* Keep pixel position, but resize area. */ + CLLM_RECTANGLE /* Keep pixel based area. */ +} CoreLayerLayoutMode; + +struct __DFB_CoreLayerContext { + FusionObject object; + + int magic; + + DFBDisplayLayerID layer_id; + + FusionSkirmish lock; + + bool active; /* Is this the active context? */ + + DFBDisplayLayerConfig config; /* Current layer configuration. */ + int rotation; + + FusionVector regions; /* All regions created within + this context. */ + + struct { + CoreLayerRegion *region; /* Region of layer config if buffer + mode is not DLBM_WINDOWS. */ + CoreLayerRegionConfig config; /* Region config used to implement + layer config and settings. */ + } primary; + + struct { + DFBLocation location; /* Normalized screen location. */ + DFBRectangle rectangle; /* Pixel based position and size. */ + + CoreLayerLayoutMode mode; /* ...and how resizing influences them. */ + } screen; + + DFBColorAdjustment adjustment; /* Color adjustment of the layer.*/ + + CoreWindowStack *stack; /* Every layer has its own + windowstack as every layer has + its own pixel buffer. */ + + FusionSHMPoolShared *shmpool; +}; + +typedef enum { + CLRSF_NONE = 0x00000000, + + CLRSF_CONFIGURED = 0x00000001, + CLRSF_ENABLED = 0x00000002, + CLRSF_ACTIVE = 0x00000004, + CLRSF_REALIZED = 0x00000008, + + CLRSF_FROZEN = 0x00000010, + + CLRSF_ALL = 0x0000001F +} CoreLayerRegionStateFlags; + +struct __DFB_CoreLayerRegion { + FusionObject object; + + CoreLayerContext *context; + + FusionSkirmish lock; + + CoreLayerRegionStateFlags state; + + CoreLayerRegionConfig config; + + CoreSurface *surface; + CoreSurfaceBufferLock surface_lock; + GlobalReaction surface_reaction; + + void *region_data; +}; + + +/* Called at the end of dfb_layer_region_create(). */ +DFBResult dfb_layer_context_add_region( CoreLayerContext *context, + CoreLayerRegion *region ); + +/* Called early in the region_destructor(). */ +DFBResult dfb_layer_context_remove_region( CoreLayerContext *context, + CoreLayerRegion *region ); + +/* Called by dfb_layer_activate_context(), + dfb_layer_remove_context() and dfb_layer_resume(). */ +DFBResult dfb_layer_context_activate ( CoreLayerContext *context ); + +/* Called by dfb_layer_deactivate_context(), + dfb_layer_remove_context() and dfb_layer_suspend(). */ +DFBResult dfb_layer_context_deactivate( CoreLayerContext *context ); + +/* global reactions */ +ReactionResult _dfb_layer_region_surface_listener( const void *msg_data, + void *ctx ); + +#endif + diff --git a/Source/DirectFB/src/core/local_surface_pool.c b/Source/DirectFB/src/core/local_surface_pool.c new file mode 100755 index 0000000..8da06de --- /dev/null +++ b/Source/DirectFB/src/core/local_surface_pool.c @@ -0,0 +1,313 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include +#include + +#include + +#include +#include + + +/**********************************************************************************************************************/ + +typedef struct { +} LocalPoolData; + +typedef struct { + FusionCall call; +} LocalPoolLocalData; + +typedef struct { + int magic; + + void *addr; + int pitch; + int size; + + FusionCall call; + FusionID fid; +} LocalAllocationData; + +/**********************************************************************************************************************/ + +static FusionCallHandlerResult +local_surface_pool_call_handler( int caller, + int call_arg, + void *call_ptr, + void *ctx, + unsigned int serial, + int *ret_val ) +{ + D_FREE( call_ptr ); + + *ret_val = 0; + + return FCHR_RETURN; +} + +/**********************************************************************************************************************/ + +static int +localPoolDataSize( void ) +{ + return sizeof(LocalPoolData); +} + +static int +localPoolLocalDataSize( void ) +{ + return sizeof(LocalPoolLocalData); +} + +static int +localAllocationDataSize( void ) +{ + return sizeof(LocalAllocationData); +} + +static DFBResult +localInitPool( CoreDFB *core, + CoreSurfacePool *pool, + void *pool_data, + void *pool_local, + void *system_data, + CoreSurfacePoolDescription *ret_desc ) +{ + LocalPoolLocalData *local = pool_local; + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + D_ASSERT( pool_local != NULL ); + D_ASSERT( ret_desc != NULL ); + + ret_desc->caps = CSPCAPS_NONE; + ret_desc->access[CSAID_CPU] = CSAF_READ | CSAF_WRITE; + ret_desc->types = CSTF_FONT | CSTF_INTERNAL; + ret_desc->priority = CSPP_PREFERED; + + snprintf( ret_desc->name, DFB_SURFACE_POOL_DESC_NAME_LENGTH, "System Memory" ); + + fusion_call_init( &local->call, local_surface_pool_call_handler, local, dfb_core_world(core) ); + + return DFB_OK; +} + +static DFBResult +localJoinPool( CoreDFB *core, + CoreSurfacePool *pool, + void *pool_data, + void *pool_local, + void *system_data ) +{ + LocalPoolLocalData *local = pool_local; + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + D_ASSERT( pool_local != NULL ); + + return fusion_call_init( &local->call, local_surface_pool_call_handler, local, dfb_core_world(core) ); +} + +static DFBResult +localDestroyPool( CoreSurfacePool *pool, + void *pool_data, + void *pool_local ) +{ + CoreSurfaceAllocation *allocation; + LocalPoolLocalData *local = pool_local; + LocalAllocationData *data; + FusionID fid; + + DFBResult res; + int i; + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + D_ASSERT( pool_local != NULL ); + + res = fusion_call_destroy( &local->call ); + fid = fusion_id( dfb_core_world(NULL) ); + + /* remove the local allocations */ + fusion_vector_foreach (allocation, i, pool->allocs) { + data = allocation->data; + if( data->fid == fid ) + D_FREE( data->addr ); + } + + return res; +} + +static DFBResult +localLeavePool( CoreSurfacePool *pool, + void *pool_data, + void *pool_local ) +{ + CoreSurfaceAllocation *allocation; + LocalPoolLocalData *local = pool_local; + LocalAllocationData *data; + FusionID fid; + + DFBResult res; + int i; + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + D_ASSERT( pool_local != NULL ); + + res = fusion_call_destroy( &local->call ); + fid = fusion_id( dfb_core_world(NULL) ); + + /* remove the local allocations */ + fusion_vector_foreach (allocation, i, pool->allocs) { + data = allocation->data; + if( data->fid == fid ) + D_FREE( data->addr ); + } + + return res; +} + +static DFBResult +localAllocateBuffer( CoreSurfacePool *pool, + void *pool_data, + void *pool_local, + CoreSurfaceBuffer *buffer, + CoreSurfaceAllocation *allocation, + void *alloc_data ) +{ + CoreSurface *surface; + LocalPoolLocalData *local = pool_local; + LocalAllocationData *alloc = alloc_data; + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); + D_ASSERT( alloc != NULL ); + + surface = buffer->surface; + D_MAGIC_ASSERT( surface, CoreSurface ); + + dfb_surface_calc_buffer_size( surface, 8, 0, &alloc->pitch, &alloc->size ); + + alloc->addr = D_MALLOC( alloc->size ); + if (!alloc->addr) + return D_OOM(); + + alloc->call = local->call; + alloc->fid = fusion_id( dfb_core_world(NULL) ); + + D_MAGIC_SET( alloc, LocalAllocationData ); + + allocation->flags = CSALF_VOLATILE; + allocation->size = alloc->size; + + return DFB_OK; +} + +static DFBResult +localDeallocateBuffer( CoreSurfacePool *pool, + void *pool_data, + void *pool_local, + CoreSurfaceBuffer *buffer, + CoreSurfaceAllocation *allocation, + void *alloc_data ) +{ + DFBResult ret; + LocalAllocationData *alloc = alloc_data; + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); + D_MAGIC_ASSERT( alloc, LocalAllocationData ); + + ret = fusion_call_execute( &alloc->call, FCEF_ONEWAY, 0, alloc->addr, NULL ); +// if (ret) +// D_DERROR( ret, "SurfPool/Local: Could not call buffer owner to free it there!\n" ); + + D_MAGIC_CLEAR( alloc ); + + return DFB_OK; +} + +static DFBResult +localLock( CoreSurfacePool *pool, + void *pool_data, + void *pool_local, + CoreSurfaceAllocation *allocation, + void *alloc_data, + CoreSurfaceBufferLock *lock ) +{ + LocalAllocationData *alloc = alloc_data; + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation ); + D_MAGIC_ASSERT( lock, CoreSurfaceBufferLock ); + D_MAGIC_ASSERT( alloc, LocalAllocationData ); + + lock->addr = alloc->addr; + lock->pitch = alloc->pitch; + + return DFB_OK; +} + +static DFBResult +localUnlock( CoreSurfacePool *pool, + void *pool_data, + void *pool_local, + CoreSurfaceAllocation *allocation, + void *alloc_data, + CoreSurfaceBufferLock *lock ) +{ + LocalAllocationData *alloc = alloc_data; + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation ); + D_MAGIC_ASSERT( lock, CoreSurfaceBufferLock ); + D_MAGIC_ASSERT( alloc, LocalAllocationData ); + + (void) alloc; + + return DFB_OK; +} + +const SurfacePoolFuncs localSurfacePoolFuncs = { + .PoolDataSize = localPoolDataSize, + .PoolLocalDataSize = localPoolLocalDataSize, + .AllocationDataSize = localAllocationDataSize, + + .InitPool = localInitPool, + .JoinPool = localJoinPool, + .DestroyPool = localDestroyPool, + .LeavePool = localLeavePool, + + .AllocateBuffer = localAllocateBuffer, + .DeallocateBuffer = localDeallocateBuffer, + + .Lock = localLock, + .Unlock = localUnlock, +}; + diff --git a/Source/DirectFB/src/core/palette.c b/Source/DirectFB/src/core/palette.c new file mode 100755 index 0000000..3d66a54 --- /dev/null +++ b/Source/DirectFB/src/core/palette.c @@ -0,0 +1,317 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include + +D_DEBUG_DOMAIN( Core_Palette, "Core/Palette", "DirectFB Palette Core" ); + +/**********************************************************************************************************************/ + +static const u8 lookup3to8[] = { 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff }; +static const u8 lookup2to8[] = { 0x00, 0x55, 0xaa, 0xff }; + +static const ReactionFunc dfb_palette_globals[] = { +/* 0 */ _dfb_surface_palette_listener, + NULL +}; + +/**********************************************************************************************************************/ + +static void palette_destructor( FusionObject *object, bool zombie, void *ctx ) +{ + CorePaletteNotification notification; + CorePalette *palette = (CorePalette*) object; + + D_MAGIC_ASSERT( palette, CorePalette ); + + D_DEBUG_AT( Core_Palette, "destroying %p (%d)%s\n", palette, + palette->num_entries, zombie ? " (ZOMBIE)" : ""); + + D_ASSERT( palette->entries != NULL ); + D_ASSERT( palette->entries_yuv != NULL ); + + notification.flags = CPNF_DESTROY; + notification.palette = palette; + + dfb_palette_dispatch( palette, ¬ification, dfb_palette_globals ); + + if (palette->hash_attached) { + dfb_colorhash_invalidate( NULL, palette ); + dfb_colorhash_detach( NULL, palette ); + } + + SHFREE( palette->shmpool, palette->entries_yuv ); + SHFREE( palette->shmpool, palette->entries ); + + D_MAGIC_CLEAR( palette ); + + fusion_object_destroy( object ); +} + +FusionObjectPool * +dfb_palette_pool_create( const FusionWorld *world ) +{ + FusionObjectPool *pool; + + pool = fusion_object_pool_create( "Palette Pool", + sizeof(CorePalette), + sizeof(CorePaletteNotification), + palette_destructor, NULL, world ); + + return pool; +} + +/**********************************************************************************************************************/ + +DFBResult +dfb_palette_create( CoreDFB *core, + unsigned int size, + CorePalette **ret_palette ) +{ + CorePalette *palette; + + D_DEBUG_AT( Core_Palette, "%s( %d )\n", __FUNCTION__, size ); + + D_ASSERT( ret_palette ); + + palette = dfb_core_create_palette( core ); + if (!palette) + return DFB_FUSION; + + palette->shmpool = dfb_core_shmpool( core ); + + if (size) { + palette->entries = SHCALLOC( palette->shmpool, size, sizeof(DFBColor) ); + if (!palette->entries) { + fusion_object_destroy( &palette->object ); + return D_OOSHM(); + } + + palette->entries_yuv = SHCALLOC( palette->shmpool, size, sizeof(DFBColorYUV) ); + if (!palette->entries_yuv) { + SHFREE( palette->shmpool, palette->entries ); + fusion_object_destroy( &palette->object ); + return D_OOSHM(); + } + } + + palette->num_entries = size; + + /* reset cache */ + palette->search_cache.index = -1; + + D_MAGIC_SET( palette, CorePalette ); + + /* activate object */ + fusion_object_activate( &palette->object ); + + /* return the new palette */ + *ret_palette = palette; + + D_DEBUG_AT( Core_Palette, " -> %p\n", palette ); + + return DFB_OK; +} + +void +dfb_palette_generate_rgb332_map( CorePalette *palette ) +{ + unsigned int i; + + D_DEBUG_AT( Core_Palette, "%s( %p )\n", __FUNCTION__, palette ); + + D_MAGIC_ASSERT( palette, CorePalette ); + + if (!palette->num_entries) + return; + + for (i=0; inum_entries; i++) { + palette->entries[i].a = i ? 0xff : 0x00; + palette->entries[i].r = lookup3to8[ (i & 0xE0) >> 5 ]; + palette->entries[i].g = lookup3to8[ (i & 0x1C) >> 2 ]; + palette->entries[i].b = lookup2to8[ (i & 0x03) ]; + + palette->entries_yuv[i].a = palette->entries[i].a; + + RGB_TO_YCBCR( palette->entries[i].r, palette->entries[i].g, palette->entries[i].b, + palette->entries_yuv[i].y, palette->entries_yuv[i].u, palette->entries_yuv[i].v ); + } + + dfb_palette_update( palette, 0, palette->num_entries - 1 ); +} + +void +dfb_palette_generate_rgb121_map( CorePalette *palette ) +{ + unsigned int i; + + D_DEBUG_AT( Core_Palette, "%s( %p )\n", __FUNCTION__, palette ); + + D_MAGIC_ASSERT( palette, CorePalette ); + + if (!palette->num_entries) + return; + + for (i=0; inum_entries; i++) { + palette->entries[i].a = i ? 0xff : 0x00; + palette->entries[i].r = (i & 0x8) ? 0xff : 0x00; + palette->entries[i].g = lookup2to8[ (i & 0x6) >> 1 ]; + palette->entries[i].b = (i & 0x1) ? 0xff : 0x00; + + palette->entries_yuv[i].a = palette->entries[i].a; + + RGB_TO_YCBCR( palette->entries[i].r, palette->entries[i].g, palette->entries[i].b, + palette->entries_yuv[i].y, palette->entries_yuv[i].u, palette->entries_yuv[i].v ); + } + + dfb_palette_update( palette, 0, palette->num_entries - 1 ); +} + +unsigned int +dfb_palette_search( CorePalette *palette, + u8 r, + u8 g, + u8 b, + u8 a ) +{ + unsigned int index; + + D_MAGIC_ASSERT( palette, CorePalette ); + + /* check local cache first */ + if (palette->search_cache.index != -1 && + palette->search_cache.color.a == a && + palette->search_cache.color.r == r && + palette->search_cache.color.g == g && + palette->search_cache.color.b == b) + return palette->search_cache.index; + + /* check the global color hash table, returns the closest match */ + if (!palette->hash_attached) { + dfb_colorhash_attach( NULL, palette ); + palette->hash_attached = true; + } + + index = dfb_colorhash_lookup( NULL, palette, r, g, b, a ); + + /* write into local cache */ + palette->search_cache.index = index; + palette->search_cache.color.a = a; + palette->search_cache.color.r = r; + palette->search_cache.color.g = g; + palette->search_cache.color.b = b; + + return index; +} + +void +dfb_palette_update( CorePalette *palette, int first, int last ) +{ + CorePaletteNotification notification; + + D_DEBUG_AT( Core_Palette, "%s( %p, %d, %d )\n", __FUNCTION__, palette, first, last ); + + D_MAGIC_ASSERT( palette, CorePalette ); + D_ASSERT( first >= 0 ); + D_ASSERT( first < palette->num_entries ); + D_ASSERT( last >= 0 ); + D_ASSERT( last < palette->num_entries ); + D_ASSERT( first <= last ); + + notification.flags = CPNF_ENTRIES; + notification.palette = palette; + notification.first = first; + notification.last = last; + + /* reset cache */ + if (palette->search_cache.index >= first && + palette->search_cache.index <= last) + palette->search_cache.index = -1; + + /* invalidate entries in colorhash */ + if (palette->hash_attached) + dfb_colorhash_invalidate( NULL, palette ); + + /* post message about palette update */ + dfb_palette_dispatch( palette, ¬ification, dfb_palette_globals ); +} + +bool +dfb_palette_equal( CorePalette *palette1, CorePalette *palette2 ) +{ + u32 *entries1; + u32 *entries2; + int i; + + D_DEBUG_AT( Core_Palette, "%s( %p, %p )\n", __FUNCTION__, palette1, palette2 ); + + D_ASSERT( palette1 != NULL ); + D_ASSERT( palette2 != NULL ); + + if (palette1 == palette2) { + D_DEBUG_AT( Core_Palette, " -> SAME\n" ); + return true; + } + + if (palette1->num_entries != palette2->num_entries) { + D_DEBUG_AT( Core_Palette, " -> NOT EQUAL (%d/%d)\n", palette1->num_entries, palette2->num_entries ); + return false; + } + + entries1 = (u32*)palette1->entries; + entries2 = (u32*)palette2->entries; + + for (i = 0; i < palette1->num_entries; i++) { + if (entries1[i] != entries2[i]) { + D_DEBUG_AT( Core_Palette, " -> NOT EQUAL (%d)\n", i ); + return false; + } + } + + D_DEBUG_AT( Core_Palette, " -> EQUAL\n" ); + + return true; +} + diff --git a/Source/DirectFB/src/core/palette.h b/Source/DirectFB/src/core/palette.h new file mode 100755 index 0000000..10886be --- /dev/null +++ b/Source/DirectFB/src/core/palette.h @@ -0,0 +1,106 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __PALETTE_H__ +#define __PALETTE_H__ + +#include +#include +#include + +struct _CorePalette { + FusionObject object; + int magic; + + unsigned int num_entries; + DFBColor *entries; + DFBColorYUV *entries_yuv; + + struct { + int index; + DFBColor color; + } search_cache; + + bool hash_attached; + + FusionSHMPoolShared *shmpool; +}; + +typedef enum { + CPNF_ENTRIES = 0x00000001, + CPNF_DESTROY = 0x00000002 +} CorePaletteNotificationFlags; + +typedef struct { + CorePaletteNotificationFlags flags; + CorePalette *palette; + int first; + int last; +} CorePaletteNotification; + + +DFBResult dfb_palette_create ( CoreDFB *core, + unsigned int size, + CorePalette **ret_palette ); + +void dfb_palette_generate_rgb332_map( CorePalette *palette ); +void dfb_palette_generate_rgb121_map( CorePalette *palette ); + +unsigned int dfb_palette_search ( CorePalette *palette, + u8 r, + u8 g, + u8 b, + u8 a ); + +void dfb_palette_update ( CorePalette *palette, + int first, + int last ); + +bool dfb_palette_equal ( CorePalette *palette1, + CorePalette *palette2 ); + + +/* + * Creates a pool of palette objects. + */ +FusionObjectPool *dfb_palette_pool_create( const FusionWorld *world ); + +/* + * Generates dfb_palette_ref(), dfb_palette_attach() etc. + */ +FUSION_OBJECT_METHODS( CorePalette, dfb_palette ) + + +/* global reactions */ + +typedef enum { + DFB_SURFACE_PALETTE_LISTENER +} DFB_PALETTE_GLOBALS; + +#endif + diff --git a/Source/DirectFB/src/core/prealloc_surface_pool.c b/Source/DirectFB/src/core/prealloc_surface_pool.c new file mode 100755 index 0000000..f7d9051 --- /dev/null +++ b/Source/DirectFB/src/core/prealloc_surface_pool.c @@ -0,0 +1,192 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include + +#include +#include +#include + +#include +#include + +typedef struct { + void *addr; + int pitch; +} PreallocAllocationData; + +/**********************************************************************************************************************/ + +static int +preallocAllocationDataSize( void ) +{ + return sizeof(PreallocAllocationData); +} + +static DFBResult +preallocInitPool( CoreDFB *core, + CoreSurfacePool *pool, + void *pool_data, + void *pool_local, + void *system_data, + CoreSurfacePoolDescription *ret_desc ) +{ + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + D_ASSERT( ret_desc != NULL ); + + ret_desc->caps = CSPCAPS_NONE; + ret_desc->access[CSAID_CPU] = CSAF_READ | CSAF_WRITE; + ret_desc->types = CSTF_PREALLOCATED | CSTF_INTERNAL; + ret_desc->priority = CSPP_DEFAULT; + + snprintf( ret_desc->name, DFB_SURFACE_POOL_DESC_NAME_LENGTH, "Preallocated Memory" ); + + return DFB_OK; +} + +static DFBResult +preallocTestConfig( CoreSurfacePool *pool, + void *pool_data, + void *pool_local, + CoreSurfaceBuffer *buffer, + const CoreSurfaceConfig *config ) +{ + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + D_ASSERT( config != NULL ); + + return (config->flags & CSCONF_PREALLOCATED) ? DFB_OK : DFB_UNSUPPORTED; +} + +static DFBResult +preallocAllocateBuffer( CoreSurfacePool *pool, + void *pool_data, + void *pool_local, + CoreSurfaceBuffer *buffer, + CoreSurfaceAllocation *allocation, + void *alloc_data ) +{ + int index; + CoreSurface *surface; + PreallocAllocationData *alloc = alloc_data; + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); + + surface = buffer->surface; + D_MAGIC_ASSERT( surface, CoreSurface ); + + for (index=0; indexbuffers[index] == buffer) + break; + } + + if (index == MAX_SURFACE_BUFFERS) + return DFB_BUG; + + if (!(surface->config.flags & CSCONF_PREALLOCATED)) + return DFB_BUG; + + if (!surface->config.preallocated[index].addr || + surface->config.preallocated[index].pitch < DFB_BYTES_PER_LINE(surface->config.format, + surface->config.size.w)) + return DFB_INVARG; + + alloc->addr = surface->config.preallocated[index].addr; + alloc->pitch = surface->config.preallocated[index].pitch; + + allocation->flags = CSALF_PREALLOCATED | CSALF_VOLATILE; + allocation->size = surface->config.preallocated[index].pitch * + DFB_PLANE_MULTIPLY( surface->config.format, surface->config.size.h ); + + return DFB_OK; +} + +static DFBResult +preallocDeallocateBuffer( CoreSurfacePool *pool, + void *pool_data, + void *pool_local, + CoreSurfaceBuffer *buffer, + CoreSurfaceAllocation *allocation, + void *alloc_data ) +{ + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation ); + + return DFB_OK; +} + +static DFBResult +preallocLock( CoreSurfacePool *pool, + void *pool_data, + void *pool_local, + CoreSurfaceAllocation *allocation, + void *alloc_data, + CoreSurfaceBufferLock *lock ) +{ + PreallocAllocationData *alloc = alloc_data; + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation ); + D_MAGIC_ASSERT( lock, CoreSurfaceBufferLock ); + + lock->addr = alloc->addr; + lock->pitch = alloc->pitch; + + return DFB_OK; +} + +static DFBResult +preallocUnlock( CoreSurfacePool *pool, + void *pool_data, + void *pool_local, + CoreSurfaceAllocation *allocation, + void *alloc_data, + CoreSurfaceBufferLock *lock ) +{ + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation ); + D_MAGIC_ASSERT( lock, CoreSurfaceBufferLock ); + + return DFB_OK; +} + +const SurfacePoolFuncs preallocSurfacePoolFuncs = { + .AllocationDataSize = preallocAllocationDataSize, + .InitPool = preallocInitPool, + + .TestConfig = preallocTestConfig, + + .AllocateBuffer = preallocAllocateBuffer, + .DeallocateBuffer = preallocDeallocateBuffer, + + .Lock = preallocLock, + .Unlock = preallocUnlock, +}; + diff --git a/Source/DirectFB/src/core/screen.c b/Source/DirectFB/src/core/screen.c new file mode 100755 index 0000000..4b233e0 --- /dev/null +++ b/Source/DirectFB/src/core/screen.c @@ -0,0 +1,540 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include + +#include + +#include +#include +#include + + +DFBResult +dfb_screen_get_info( CoreScreen *screen, + DFBScreenID *ret_id, + DFBScreenDescription *ret_desc ) +{ + CoreScreenShared *shared; + + D_ASSERT( screen != NULL ); + D_ASSERT( screen->shared != NULL ); + + shared = screen->shared; + + if (ret_id) + *ret_id = shared->screen_id; + + if (ret_desc) + *ret_desc = shared->description; + + return DFB_OK; +} + +DFBResult +dfb_screen_suspend( CoreScreen *screen ) +{ + D_ASSERT( screen != NULL ); + + return DFB_OK; +} + +DFBResult +dfb_screen_resume( CoreScreen *screen ) +{ + D_ASSERT( screen != NULL ); + + return DFB_OK; +} + +DFBResult +dfb_screen_set_powermode( CoreScreen *screen, + DFBScreenPowerMode mode ) +{ + ScreenFuncs *funcs; + + D_ASSERT( screen != NULL ); + D_ASSERT( screen->funcs != NULL ); + + funcs = screen->funcs; + + if (funcs->SetPowerMode) + return funcs->SetPowerMode( screen, + screen->driver_data, + screen->screen_data, + mode ); + + return DFB_UNSUPPORTED; +} + +DFBResult +dfb_screen_wait_vsync( CoreScreen *screen ) +{ + ScreenFuncs *funcs; + + D_ASSERT( screen != NULL ); + D_ASSERT( screen->funcs != NULL ); + + funcs = screen->funcs; + + if (funcs->WaitVSync) + return funcs->WaitVSync( screen, + screen->driver_data, screen->screen_data ); + + return DFB_UNSUPPORTED; +} + + +/*********************************** Mixers ***********************************/ + +DFBResult +dfb_screen_get_mixer_info( CoreScreen *screen, + int mixer, + DFBScreenMixerDescription *ret_desc ) +{ + D_ASSERT( screen != NULL ); + D_ASSERT( screen->shared != NULL ); + D_ASSERT( mixer >= 0 ); + D_ASSERT( mixer < screen->shared->description.mixers ); + D_ASSERT( ret_desc != NULL ); + + /* Return mixer description. */ + *ret_desc = screen->shared->mixers[mixer].description; + + return DFB_OK; +} + +DFBResult +dfb_screen_get_mixer_config( CoreScreen *screen, + int mixer, + DFBScreenMixerConfig *ret_config ) +{ + D_ASSERT( screen != NULL ); + D_ASSERT( screen->shared != NULL ); + D_ASSERT( mixer >= 0 ); + D_ASSERT( mixer < screen->shared->description.mixers ); + D_ASSERT( ret_config != NULL ); + + /* Return current mixer configuration. */ + *ret_config = screen->shared->mixers[mixer].configuration; + + return DFB_OK; +} + +DFBResult +dfb_screen_test_mixer_config( CoreScreen *screen, + int mixer, + const DFBScreenMixerConfig *config, + DFBScreenMixerConfigFlags *ret_failed ) +{ + DFBResult ret; + DFBScreenMixerConfigFlags failed = DSMCONF_NONE; + + D_ASSERT( screen != NULL ); + D_ASSERT( screen->shared != NULL ); + D_ASSERT( screen->funcs != NULL ); + D_ASSERT( screen->funcs->TestMixerConfig != NULL ); + D_ASSERT( mixer >= 0 ); + D_ASSERT( mixer < screen->shared->description.mixers ); + D_ASSERT( config != NULL ); + D_ASSERT( config->flags == screen->shared->mixers[mixer].configuration.flags ); + + /* Test the mixer configuration. */ + ret = screen->funcs->TestMixerConfig( screen, + screen->driver_data, + screen->screen_data, + mixer, config, &failed ); + + D_ASSUME( (ret == DFB_OK && !failed) || (ret != DFB_OK) ); + + if (ret_failed) + *ret_failed = failed; + + return ret; +} + +DFBResult +dfb_screen_set_mixer_config( CoreScreen *screen, + int mixer, + const DFBScreenMixerConfig *config ) +{ + DFBResult ret; + DFBScreenMixerConfigFlags failed = DSOCONF_NONE; + + D_ASSERT( screen != NULL ); + D_ASSERT( screen->shared != NULL ); + D_ASSERT( screen->funcs != NULL ); + D_ASSERT( screen->funcs->TestMixerConfig != NULL ); + D_ASSERT( screen->funcs->SetMixerConfig != NULL ); + D_ASSERT( mixer >= 0 ); + D_ASSERT( mixer < screen->shared->description.mixers ); + D_ASSERT( config != NULL ); + D_ASSERT( config->flags == screen->shared->mixers[mixer].configuration.flags ); + + /* Test configuration first. */ + ret = screen->funcs->TestMixerConfig( screen, + screen->driver_data, + screen->screen_data, + mixer, config, &failed ); + + D_ASSUME( (ret == DFB_OK && !failed) || (ret != DFB_OK && failed) ); + + if (ret) + return ret; + + /* Set configuration afterwards. */ + ret = screen->funcs->SetMixerConfig( screen, + screen->driver_data, + screen->screen_data, + mixer, config ); + if (ret) + return ret; + + /* Store current configuration. */ + screen->shared->mixers[mixer].configuration = *config; + + return DFB_OK; +} + + +/********************************** Encoders **********************************/ + +DFBResult +dfb_screen_get_encoder_info( CoreScreen *screen, + int encoder, + DFBScreenEncoderDescription *ret_desc ) +{ + D_ASSERT( screen != NULL ); + D_ASSERT( screen->shared != NULL ); + D_ASSERT( encoder >= 0 ); + D_ASSERT( encoder < screen->shared->description.encoders ); + D_ASSERT( ret_desc != NULL ); + + /* Return encoder description. */ + *ret_desc = screen->shared->encoders[encoder].description; + + return DFB_OK; +} + +DFBResult +dfb_screen_get_encoder_config( CoreScreen *screen, + int encoder, + DFBScreenEncoderConfig *ret_config ) +{ + D_ASSERT( screen != NULL ); + D_ASSERT( screen->shared != NULL ); + D_ASSERT( encoder >= 0 ); + D_ASSERT( encoder < screen->shared->description.encoders ); + D_ASSERT( ret_config != NULL ); + + /* Return current encoder configuration. */ + *ret_config = screen->shared->encoders[encoder].configuration; + + return DFB_OK; +} + +DFBResult +dfb_screen_test_encoder_config( CoreScreen *screen, + int encoder, + const DFBScreenEncoderConfig *config, + DFBScreenEncoderConfigFlags *ret_failed ) +{ + DFBResult ret; + DFBScreenEncoderConfigFlags failed = DSECONF_NONE; + + D_ASSERT( screen != NULL ); + D_ASSERT( screen->shared != NULL ); + D_ASSERT( screen->funcs != NULL ); + D_ASSERT( screen->funcs->TestEncoderConfig != NULL ); + D_ASSERT( encoder >= 0 ); + D_ASSERT( encoder < screen->shared->description.encoders ); + D_ASSERT( config != NULL ); + D_ASSERT( config->flags == screen->shared->encoders[encoder].configuration.flags ); + + /* Test the encoder configuration. */ + ret = screen->funcs->TestEncoderConfig( screen, + screen->driver_data, + screen->screen_data, + encoder, config, &failed ); + + D_ASSUME( (ret == DFB_OK && !failed) || (ret != DFB_OK && failed) ); + + if (ret_failed) + *ret_failed = failed; + + return ret; +} + +DFBResult +dfb_screen_set_encoder_config( CoreScreen *screen, + int encoder, + const DFBScreenEncoderConfig *config ) +{ + DFBResult ret; + DFBScreenEncoderConfigFlags failed = DSECONF_NONE; + + D_ASSERT( screen != NULL ); + D_ASSERT( screen->shared != NULL ); + D_ASSERT( screen->funcs != NULL ); + D_ASSERT( screen->funcs->TestEncoderConfig != NULL ); + D_ASSERT( screen->funcs->SetEncoderConfig != NULL ); + D_ASSERT( encoder >= 0 ); + D_ASSERT( encoder < screen->shared->description.encoders ); + D_ASSERT( config != NULL ); + D_ASSERT( config->flags == screen->shared->encoders[encoder].configuration.flags ); + + /* Test configuration first. */ + ret = screen->funcs->TestEncoderConfig( screen, + screen->driver_data, + screen->screen_data, + encoder, config, &failed ); + + D_ASSUME( (ret == DFB_OK && !failed) || (ret != DFB_OK && failed) ); + + if (ret) + return ret; + + /* Set configuration afterwards. */ + ret = screen->funcs->SetEncoderConfig( screen, + screen->driver_data, + screen->screen_data, + encoder, config ); + if (ret) + return ret; + + /* Store current configuration. */ + screen->shared->encoders[encoder].configuration = *config; + + return DFB_OK; +} + + +/********************************** Outputs ***********************************/ + +DFBResult +dfb_screen_get_output_info( CoreScreen *screen, + int output, + DFBScreenOutputDescription *ret_desc ) +{ + D_ASSERT( screen != NULL ); + D_ASSERT( screen->shared != NULL ); + D_ASSERT( output >= 0 ); + D_ASSERT( output < screen->shared->description.outputs ); + D_ASSERT( ret_desc != NULL ); + + /* Return output description. */ + *ret_desc = screen->shared->outputs[output].description; + + return DFB_OK; +} + +DFBResult +dfb_screen_get_output_config( CoreScreen *screen, + int output, + DFBScreenOutputConfig *ret_config ) +{ + D_ASSERT( screen != NULL ); + D_ASSERT( screen->shared != NULL ); + D_ASSERT( output >= 0 ); + D_ASSERT( output < screen->shared->description.outputs ); + D_ASSERT( ret_config != NULL ); + + /* Return current output configuration. */ + *ret_config = screen->shared->outputs[output].configuration; + + return DFB_OK; +} + +DFBResult +dfb_screen_test_output_config( CoreScreen *screen, + int output, + const DFBScreenOutputConfig *config, + DFBScreenOutputConfigFlags *ret_failed ) +{ + DFBResult ret; + DFBScreenOutputConfigFlags failed = DSOCONF_NONE; + + D_ASSERT( screen != NULL ); + D_ASSERT( screen->shared != NULL ); + D_ASSERT( screen->funcs != NULL ); + D_ASSERT( screen->funcs->TestOutputConfig != NULL ); + D_ASSERT( output >= 0 ); + D_ASSERT( output < screen->shared->description.outputs ); + D_ASSERT( config != NULL ); + D_ASSERT( config->flags == screen->shared->outputs[output].configuration.flags ); + + /* Test the output configuration. */ + ret = screen->funcs->TestOutputConfig( screen, + screen->driver_data, + screen->screen_data, + output, config, &failed ); + + D_ASSUME( (ret == DFB_OK && !failed) || (ret != DFB_OK && failed) ); + + if (ret_failed) + *ret_failed = failed; + + return ret; +} + +DFBResult +dfb_screen_set_output_config( CoreScreen *screen, + int output, + const DFBScreenOutputConfig *config ) +{ + DFBResult ret; + DFBScreenOutputConfigFlags failed = DSOCONF_NONE; + + D_ASSERT( screen != NULL ); + D_ASSERT( screen->shared != NULL ); + D_ASSERT( screen->funcs != NULL ); + D_ASSERT( screen->funcs->TestOutputConfig != NULL ); + D_ASSERT( screen->funcs->SetOutputConfig != NULL ); + D_ASSERT( output >= 0 ); + D_ASSERT( output < screen->shared->description.outputs ); + D_ASSERT( config != NULL ); + D_ASSERT( config->flags == screen->shared->outputs[output].configuration.flags ); + + /* Test configuration first. */ + ret = screen->funcs->TestOutputConfig( screen, + screen->driver_data, + screen->screen_data, + output, config, &failed ); + + D_ASSUME( (ret == DFB_OK && !failed) || (ret != DFB_OK && failed) ); + + if (ret) + return ret; + + /* Set configuration afterwards. */ + ret = screen->funcs->SetOutputConfig( screen, + screen->driver_data, + screen->screen_data, + output, config ); + if (ret) + return ret; + + /* Store current configuration. */ + screen->shared->outputs[output].configuration = *config; + + return DFB_OK; +} + +DFBResult +dfb_screen_get_screen_size( CoreScreen *screen, + int *ret_width, + int *ret_height ) +{ + D_ASSERT( screen != NULL ); + D_ASSERT( screen->funcs != NULL ); + D_ASSERT( screen->funcs->GetScreenSize != NULL ); + D_ASSERT( ret_width != NULL ); + D_ASSERT( ret_height != NULL ); + + return screen->funcs->GetScreenSize( screen, + screen->driver_data, screen->screen_data, + ret_width, ret_height ); +} + +DFBResult +dfb_screen_get_layer_dimension( CoreScreen *screen, + CoreLayer *layer, + int *ret_width, + int *ret_height ) +{ + int i; + DFBResult ret = DFB_UNSUPPORTED; + CoreScreenShared *shared; + ScreenFuncs *funcs; + + D_ASSERT( screen != NULL ); + D_ASSERT( screen->shared != NULL ); + D_ASSERT( screen->funcs != NULL ); + D_ASSERT( layer != NULL ); + D_ASSERT( ret_width != NULL ); + D_ASSERT( ret_height != NULL ); + + shared = screen->shared; + funcs = screen->funcs; + + if (funcs->GetMixerState) { + for (i=0; idescription.mixers; i++) { + const DFBScreenMixerConfig *config = &shared->mixers[i].configuration; + + if ((config->flags & DSMCONF_LAYERS) && + DFB_DISPLAYLAYER_IDS_HAVE( config->layers, dfb_layer_id(layer) )) + { + CoreMixerState state; + + ret = funcs->GetMixerState( screen, screen->driver_data, screen->screen_data, i, &state ); + if (ret == DFB_OK) { + if (state.flags & CMSF_DIMENSION) { + *ret_width = state.dimension.w; + *ret_height = state.dimension.h; + + return DFB_OK; + } + + ret = DFB_UNSUPPORTED; + } + } + } + + for (i=0; idescription.mixers; i++) { + const DFBScreenMixerDescription *desc = &shared->mixers[i].description; + + if ((desc->caps & DSMCAPS_SUB_LAYERS) && + DFB_DISPLAYLAYER_IDS_HAVE( desc->sub_layers, dfb_layer_id(layer) )) + { + CoreMixerState state; + + ret = funcs->GetMixerState( screen, screen->driver_data, screen->screen_data, i, &state ); + if (ret == DFB_OK) { + if (state.flags & CMSF_DIMENSION) { + *ret_width = state.dimension.w; + *ret_height = state.dimension.h; + + return DFB_OK; + } + + ret = DFB_UNSUPPORTED; + } + } + } + } + + if (funcs->GetScreenSize) + ret = funcs->GetScreenSize( screen, + screen->driver_data, screen->screen_data, + ret_width, ret_height ); + + return ret; +} + diff --git a/Source/DirectFB/src/core/screen.h b/Source/DirectFB/src/core/screen.h new file mode 100755 index 0000000..b5491f4 --- /dev/null +++ b/Source/DirectFB/src/core/screen.h @@ -0,0 +1,122 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __DFB__CORE__SCREEN_H__ +#define __DFB__CORE__SCREEN_H__ + +#include + +DFBResult dfb_screen_get_info ( CoreScreen *screen, + DFBScreenID *ret_id, + DFBScreenDescription *ret_desc ); + + +/* Misc */ + +DFBResult dfb_screen_suspend ( CoreScreen *screen ); +DFBResult dfb_screen_resume ( CoreScreen *screen ); + +DFBResult dfb_screen_set_powermode ( CoreScreen *screen, + DFBScreenPowerMode mode ); + +DFBResult dfb_screen_wait_vsync ( CoreScreen *screen ); + + +/* Mixers */ + +DFBResult dfb_screen_get_mixer_info ( CoreScreen *screen, + int mixer, + DFBScreenMixerDescription *ret_desc ); + +DFBResult dfb_screen_get_mixer_config ( CoreScreen *screen, + int mixer, + DFBScreenMixerConfig *ret_config ); + +DFBResult dfb_screen_test_mixer_config( CoreScreen *screen, + int mixer, + const DFBScreenMixerConfig *config, + DFBScreenMixerConfigFlags *ret_failed ); + +DFBResult dfb_screen_set_mixer_config ( CoreScreen *screen, + int mixer, + const DFBScreenMixerConfig *config ); + + +/* Encoders */ + +DFBResult dfb_screen_get_encoder_info ( CoreScreen *screen, + int encoder, + DFBScreenEncoderDescription *ret_desc ); + +DFBResult dfb_screen_get_encoder_config ( CoreScreen *screen, + int encoder, + DFBScreenEncoderConfig *ret_config ); + +DFBResult dfb_screen_test_encoder_config( CoreScreen *screen, + int encoder, + const DFBScreenEncoderConfig *config, + DFBScreenEncoderConfigFlags *ret_failed ); + +DFBResult dfb_screen_set_encoder_config ( CoreScreen *screen, + int encoder, + const DFBScreenEncoderConfig *config ); + + +/* Outputs */ + +DFBResult dfb_screen_get_output_info ( CoreScreen *screen, + int output, + DFBScreenOutputDescription *ret_desc ); + +DFBResult dfb_screen_get_output_config ( CoreScreen *screen, + int output, + DFBScreenOutputConfig *ret_config ); + +DFBResult dfb_screen_test_output_config( CoreScreen *screen, + int output, + const DFBScreenOutputConfig *config, + DFBScreenOutputConfigFlags *ret_failed ); + +DFBResult dfb_screen_set_output_config ( CoreScreen *screen, + int output, + const DFBScreenOutputConfig *config ); + + +/* Screen configuration */ + +DFBResult dfb_screen_get_screen_size ( CoreScreen *screen, + int *ret_width, + int *ret_height ); + +DFBResult dfb_screen_get_layer_dimension( CoreScreen *screen, + CoreLayer *layer, + int *ret_width, + int *ret_height ); + +#endif + diff --git a/Source/DirectFB/src/core/screens.c b/Source/DirectFB/src/core/screens.c new file mode 100755 index 0000000..708f5e8 --- /dev/null +++ b/Source/DirectFB/src/core/screens.c @@ -0,0 +1,591 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include + +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include + +#include + +#include + + +D_DEBUG_DOMAIN( Core_Screen, "Core/Screen", "DirectFB Screen Core" ); + +/**********************************************************************************************************************/ + +typedef struct { + int magic; + + + int num; + CoreScreenShared *screens[MAX_SCREENS]; +} DFBScreenCoreShared; + +struct __DFB_DFBScreenCore { + int magic; + + CoreDFB *core; + + DFBScreenCoreShared *shared; +}; + + +DFB_CORE_PART( screen_core, ScreenCore ); + +/**********************************************************************************************************************/ + +static DFBScreenCoreShared *core_screens = NULL; /* FIXME */ + +static int num_screens = 0; /* FIXME */ +static CoreScreen *screens[MAX_SCREENS] = { NULL }; /* FIXME */ + + +static DFBResult +dfb_screen_core_initialize( CoreDFB *core, + DFBScreenCore *data, + DFBScreenCoreShared *shared ) +{ + int i; + DFBResult ret; + FusionSHMPoolShared *pool; + + D_DEBUG_AT( Core_Screen, "dfb_screen_core_initialize( %p, %p, %p )\n", core, data, shared ); + + D_ASSERT( data != NULL ); + D_ASSERT( shared != NULL ); + + data->core = core; + data->shared = shared; + + core_screens = shared; /* FIXME */ + + pool = dfb_core_shmpool( core ); + + /* Initialize all registered screens. */ + for (i=0; ifuncs; + DFBScreenDescription desc = { .caps = DSCCAPS_NONE }; + + /* Allocate shared data. */ + sshared = SHCALLOC( pool, 1, sizeof(CoreScreenShared) ); + + /* Assign ID (zero based index). */ + sshared->screen_id = i; + + snprintf( buf, sizeof(buf), "Screen %d", i ); + + /* Initialize the lock. */ + if (fusion_skirmish_init( &sshared->lock, buf, dfb_core_world(core) )) { + SHFREE( pool, sshared ); + return DFB_FUSION; + } + + /* Allocate driver's screen data. */ + if (funcs->ScreenDataSize) { + int size = funcs->ScreenDataSize(); + + if (size > 0) { + sshared->screen_data = SHCALLOC( pool, 1, size ); + if (!sshared->screen_data) { + fusion_skirmish_destroy( &sshared->lock ); + SHFREE( pool, sshared ); + return D_OOSHM(); + } + } + } + + /* Initialize the screen and get the screen description. */ + ret = funcs->InitScreen( screen, + screen->device, + screen->driver_data, + sshared->screen_data, + &desc ); + if (ret) { + D_ERROR("DirectFB/Core/screens: " + "Failed to initialize screen %d!\n", sshared->screen_id); + + fusion_skirmish_destroy( &sshared->lock ); + + if (sshared->screen_data) + SHFREE( pool, sshared->screen_data ); + + SHFREE( pool, sshared ); + + return ret; + } + + D_ASSUME( desc.mixers > 0 || !(desc.caps & DSCCAPS_MIXERS) ); + D_ASSUME( desc.mixers == 0 || (desc.caps & DSCCAPS_MIXERS) ); + + D_ASSUME( desc.encoders > 0 || !(desc.caps & DSCCAPS_ENCODERS) ); + D_ASSUME( desc.encoders == 0 || (desc.caps & DSCCAPS_ENCODERS) ); + + D_ASSUME( desc.outputs > 0 || !(desc.caps & DSCCAPS_OUTPUTS) ); + D_ASSUME( desc.outputs == 0 || (desc.caps & DSCCAPS_OUTPUTS) ); + + D_ASSERT( desc.mixers >= 0 ); + D_ASSERT( desc.mixers <= 32 ); + D_ASSERT( desc.encoders >= 0 ); + D_ASSERT( desc.encoders <= 32 ); + D_ASSERT( desc.outputs >= 0 ); + D_ASSERT( desc.outputs <= 32 ); + + /* Store description in sshared memory. */ + sshared->description = desc; + + /* Initialize mixers. */ + if (sshared->description.mixers) { + int i; + + D_ASSERT( funcs->InitMixer != NULL ); + D_ASSERT( funcs->SetMixerConfig != NULL ); + + sshared->mixers = SHCALLOC( pool, sshared->description.mixers, + sizeof(CoreScreenMixer) ); + for (i=0; idescription.mixers; i++) { + funcs->InitMixer( screen, + screen->driver_data, + sshared->screen_data, i, + &sshared->mixers[i].description, + &sshared->mixers[i].configuration ); + funcs->SetMixerConfig( screen, + screen->driver_data, + sshared->screen_data, i, + &sshared->mixers[i].configuration ); + } + } + + /* Initialize encoders. */ + if (sshared->description.encoders) { + int i; + + D_ASSERT( funcs->InitEncoder != NULL ); + D_ASSERT( funcs->SetEncoderConfig != NULL ); + + sshared->encoders = SHCALLOC( pool, sshared->description.encoders, + sizeof(CoreScreenEncoder) ); + for (i=0; idescription.encoders; i++) { + funcs->InitEncoder( screen, + screen->driver_data, + sshared->screen_data, i, + &sshared->encoders[i].description, + &sshared->encoders[i].configuration ); + funcs->SetEncoderConfig( screen, + screen->driver_data, + sshared->screen_data, i, + &sshared->encoders[i].configuration ); + } + } + + /* Initialize outputs. */ + if (sshared->description.outputs) { + int i; + + D_ASSERT( funcs->InitOutput != NULL ); + D_ASSERT( funcs->SetOutputConfig != NULL ); + + sshared->outputs = SHCALLOC( pool, sshared->description.outputs, + sizeof(CoreScreenOutput) ); + for (i=0; idescription.outputs; i++) { + funcs->InitOutput( screen, + screen->driver_data, + sshared->screen_data, i, + &sshared->outputs[i].description, + &sshared->outputs[i].configuration ); + funcs->SetOutputConfig( screen, + screen->driver_data, + sshared->screen_data, i, + &sshared->outputs[i].configuration ); + } + } + + /* Make a copy for faster access. */ + screen->screen_data = sshared->screen_data; + + /* Store pointer to sshared data and core. */ + screen->shared = sshared; + screen->core = core; + + /* Add the screen to the sshared list. */ + core_screens->screens[ core_screens->num++ ] = sshared; + } + + + D_MAGIC_SET( data, DFBScreenCore ); + D_MAGIC_SET( shared, DFBScreenCoreShared ); + + return DFB_OK; +} + +static DFBResult +dfb_screen_core_join( CoreDFB *core, + DFBScreenCore *data, + DFBScreenCoreShared *shared ) +{ + int i; + + D_DEBUG_AT( Core_Screen, "dfb_screen_core_join( %p, %p, %p )\n", core, data, shared ); + + D_ASSERT( data != NULL ); + D_MAGIC_ASSERT( shared, DFBScreenCoreShared ); + + data->core = core; + data->shared = shared; + + core_screens = shared; /* FIXME */ + + if (num_screens != core_screens->num) { + D_ERROR("DirectFB/core/screens: Number of screens does not match!\n"); + return DFB_BUG; + } + + for (i=0; iscreens[i]; + + /* Make a copy for faster access. */ + screen->screen_data = shared->screen_data; + + /* Store pointer to shared data and core. */ + screen->shared = shared; + screen->core = core; + } + + + D_MAGIC_SET( data, DFBScreenCore ); + + return DFB_OK; +} + +static DFBResult +dfb_screen_core_shutdown( DFBScreenCore *data, + bool emergency ) +{ + int i; + FusionSHMPoolShared *pool; + DFBScreenCoreShared *shared; + + D_DEBUG_AT( Core_Screen, "dfb_screen_core_shutdown( %p, %semergency )\n", data, emergency ? "" : "no " ); + + D_MAGIC_ASSERT( data, DFBScreenCore ); + D_MAGIC_ASSERT( data->shared, DFBScreenCoreShared ); + + shared = data->shared; + + pool = dfb_core_shmpool( data->core ); + + /* Begin with the most recently added screen. */ + for (i=num_screens-1; i>=0; i--) { + CoreScreen *screen = screens[i]; + CoreScreenShared *shared = screen->shared; + + /* Deinitialize the lock. */ + fusion_skirmish_destroy( &shared->lock ); + + /* Free the driver's screen data. */ + if (shared->screen_data) + SHFREE( pool, shared->screen_data ); + + /* Free mixer data. */ + if (shared->mixers) + SHFREE( pool, shared->mixers ); + + /* Free encoder data. */ + if (shared->encoders) + SHFREE( pool, shared->encoders ); + + /* Free output data. */ + if (shared->outputs) + SHFREE( pool, shared->outputs ); + + /* Free the shared screen data. */ + SHFREE( pool, shared ); + + /* Free the local screen data. */ + D_FREE( screen ); + } + + core_screens = NULL; + num_screens = 0; + + + D_MAGIC_CLEAR( data ); + D_MAGIC_CLEAR( shared ); + + return DFB_OK; +} + +static DFBResult +dfb_screen_core_leave( DFBScreenCore *data, + bool emergency ) +{ + int i; + DFBScreenCoreShared *shared; + + D_DEBUG_AT( Core_Screen, "dfb_screen_core_leave( %p, %semergency )\n", data, emergency ? "" : "no " ); + + D_MAGIC_ASSERT( data, DFBScreenCore ); + D_MAGIC_ASSERT( data->shared, DFBScreenCoreShared ); + + shared = data->shared; + + + /* Deinitialize all local stuff only. */ + for (i=0; ishared, DFBScreenCoreShared ); + + shared = data->shared; + + for (i=num_screens-1; i>=0; i--) + dfb_screen_suspend( screens[i] ); + + return DFB_OK; +} + +static DFBResult +dfb_screen_core_resume( DFBScreenCore *data ) +{ + int i; + DFBScreenCoreShared *shared; + + D_DEBUG_AT( Core_Screen, "dfb_screen_core_resume( %p )\n", data ); + + D_MAGIC_ASSERT( data, DFBScreenCore ); + D_MAGIC_ASSERT( data->shared, DFBScreenCoreShared ); + + shared = data->shared; + + for (i=0; idevice = device; + screen->driver_data = driver_data; + screen->funcs = funcs; + + /* add it to the local list */ + screens[num_screens++] = screen; + + return screen; +} + +typedef void (*AnyFunc)( void ); + +CoreScreen * +dfb_screens_hook_primary( CoreGraphicsDevice *device, + void *driver_data, + ScreenFuncs *funcs, + ScreenFuncs *primary_funcs, + void **primary_driver_data ) +{ + int i; + int entries; + CoreScreen *primary = screens[0]; + + D_ASSERT( primary != NULL ); + D_ASSERT( device != NULL ); + D_ASSERT( funcs != NULL ); + + /* copy content of original function table */ + if (primary_funcs) + direct_memcpy( primary_funcs, primary->funcs, sizeof(ScreenFuncs) ); + + /* copy pointer to original driver data */ + if (primary_driver_data) + *primary_driver_data = primary->driver_data; + + /* replace all entries in the old table that aren't NULL in the new one */ + entries = sizeof(ScreenFuncs) / sizeof(void(*)( void )); + for (i=0; ifuncs; + + if (newfuncs[i]) + oldfuncs[i] = newfuncs[i]; + } + + /* replace device and driver data pointer */ + primary->device = device; + primary->driver_data = driver_data; + + return primary; +} + +CoreScreen * +dfb_screens_register_primary( CoreGraphicsDevice *device, + void *driver_data, + ScreenFuncs *funcs ) +{ + CoreScreen *primary = screens[0]; + + D_ASSERT( primary != NULL ); + D_ASSERT( funcs != NULL ); + D_ASSERT( num_screens > 0 ); + + /* replace device, function table and driver data pointer */ + primary->device = device; + primary->funcs = funcs; + primary->driver_data = driver_data; + + return primary; +} + +void +dfb_screens_enumerate( CoreScreenCallback callback, + void *ctx ) +{ + int i; + + D_ASSERT( core_screens != NULL ); + D_ASSERT( callback != NULL ); + + for (i=0; i= 0); + D_ASSERT( screen_id < num_screens); + + return screens[screen_id]; +} + +CoreScreen * +dfb_screens_at_translated( DFBScreenID screen_id ) +{ + CoreScreen *primary; + + D_ASSERT( screen_id >= 0); + D_ASSERT( screen_id < num_screens); + + if (dfb_config->primary_layer > 0) { + primary = dfb_layer_screen( dfb_layer_at_translated( DLID_PRIMARY ) ); + + if (screen_id == DSCID_PRIMARY) + return primary; + + if (screen_id == primary->shared->screen_id) + return dfb_screens_at( DSCID_PRIMARY ); + } + + return dfb_screens_at( screen_id ); +} + +DFBScreenID +dfb_screen_id_translated( CoreScreen *screen ) +{ + CoreScreenShared *shared; + CoreScreen *primary; + + D_ASSERT( screen != NULL ); + D_ASSERT( screen->shared != NULL ); + + shared = screen->shared; + + if (dfb_config->primary_layer > 0) { + primary = dfb_layer_screen( dfb_layer_at_translated( DLID_PRIMARY ) ); + + if (shared->screen_id == DSCID_PRIMARY) + return primary->shared->screen_id; + + if (shared->screen_id == primary->shared->screen_id) + return DSCID_PRIMARY; + } + + return shared->screen_id; +} + diff --git a/Source/DirectFB/src/core/screens.h b/Source/DirectFB/src/core/screens.h new file mode 100755 index 0000000..1ebaa4e --- /dev/null +++ b/Source/DirectFB/src/core/screens.h @@ -0,0 +1,263 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __DFB__CORE__SCREENS_H__ +#define __DFB__CORE__SCREENS_H__ + +#include + +#include + + +typedef DFBEnumerationResult (*CoreScreenCallback) (CoreScreen *screen, + void *ctx); + +typedef enum { + CMSF_NONE = 0x00000000, /* none of these */ + + CMSF_DIMENSION = 0x00000001, /* dimension is set */ + + CMSF_ALL = 0x00000001, /* all of these */ +} CoreMixerStateFlags; + +typedef struct { + CoreMixerStateFlags flags; + + DFBDimension dimension; +} CoreMixerState; + +typedef struct { + /** Driver Control **/ + + /* + * Return size of screen data (shared memory). + */ + int (*ScreenDataSize)(void); + + /* + * Called once by the master to initialize screen data and reset hardware. + * Driver has to fill the screen description. + */ + DFBResult (*InitScreen) ( CoreScreen *screen, + CoreGraphicsDevice *device, + void *driver_data, + void *screen_data, + DFBScreenDescription *description ); + + /* + * Called once by the master for each mixer. + * Driver fills description and default config. + */ + DFBResult (*InitMixer) ( CoreScreen *screen, + void *driver_data, + void *screen_data, + int mixer, + DFBScreenMixerDescription *description, + DFBScreenMixerConfig *config ); + + /* + * Called once by the master for each encoder. + * Driver fills description and default config. + */ + DFBResult (*InitEncoder) ( CoreScreen *screen, + void *driver_data, + void *screen_data, + int encoder, + DFBScreenEncoderDescription *description, + DFBScreenEncoderConfig *config ); + + /* + * Called once by the master for each output. + * Driver fills description and default config. + */ + DFBResult (*InitOutput) ( CoreScreen *screen, + void *driver_data, + void *screen_data, + int output, + DFBScreenOutputDescription *description, + DFBScreenOutputConfig *config ); + + + /** Power management **/ + + /* + * Switch between "on", "standby", "suspend" and "off". + */ + DFBResult (*SetPowerMode) ( CoreScreen *screen, + void *driver_data, + void *screen_data, + DFBScreenPowerMode mode ); + + + /** Synchronization **/ + + /* + * Wait for the vertical retrace. + */ + DFBResult (*WaitVSync) ( CoreScreen *screen, + void *driver_data, + void *screen_data ); + + + /** Mixer configuration **/ + + /* + * Test if configuration is supported. Store failing fields in 'failed'. + */ + DFBResult (*TestMixerConfig)( CoreScreen *screen, + void *driver_data, + void *screen_data, + int mixer, + const DFBScreenMixerConfig *config, + DFBScreenMixerConfigFlags *failed ); + + /* + * Set new configuration. + */ + DFBResult (*SetMixerConfig) ( CoreScreen *screen, + void *driver_data, + void *screen_data, + int mixer, + const DFBScreenMixerConfig *config ); + + + /** Encoder configuration **/ + + /* + * Test if configuration is supported. Store failing fields in 'failed'. + */ + DFBResult (*TestEncoderConfig)( CoreScreen *screen, + void *driver_data, + void *screen_data, + int encoder, + const DFBScreenEncoderConfig *config, + DFBScreenEncoderConfigFlags *failed ); + + /* + * Set new configuration. + */ + DFBResult (*SetEncoderConfig) ( CoreScreen *screen, + void *driver_data, + void *screen_data, + int encoder, + const DFBScreenEncoderConfig *config ); + + + /** Output configuration **/ + + /* + * Test if configuration is supported. Store failing fields in 'failed'. + */ + DFBResult (*TestOutputConfig)( CoreScreen *screen, + void *driver_data, + void *screen_data, + int output, + const DFBScreenOutputConfig *config, + DFBScreenOutputConfigFlags *failed ); + + /* + * Set new configuration. + */ + DFBResult (*SetOutputConfig) ( CoreScreen *screen, + void *driver_data, + void *screen_data, + int output, + const DFBScreenOutputConfig *config ); + + + /** Screen configuration **/ + + /* + * Return the screen size, e.g. as a basis for positioning a layer. + * + * This function might be replaced soon. + */ + DFBResult (*GetScreenSize) ( CoreScreen *screen, + void *driver_data, + void *screen_data, + int *ret_width, + int *ret_height ); + + + /** States **/ + + DFBResult (*GetMixerState) ( CoreScreen *screen, + void *driver_data, + void *screen_data, + int mixer, + CoreMixerState *ret_state ); +} ScreenFuncs; + + +/* + * Add a screen to a graphics device by pointing to a table containing + * driver functions. The driver data will be passed to these functions. + */ +CoreScreen *dfb_screens_register( CoreGraphicsDevice *device, + void *driver_data, + ScreenFuncs *funcs ); + +/* + * Replace functions of the primary screen implementation by passing + * an alternative driver function table. All non-NULL functions in the new + * table replace the functions in the original function table. + * The original function table is written to 'primary_funcs' before to allow + * drivers to use existing functionality from the original implementation. + */ +CoreScreen *dfb_screens_hook_primary( CoreGraphicsDevice *device, + void *driver_data, + ScreenFuncs *funcs, + ScreenFuncs *primary_funcs, + void **primary_driver_data ); + +/* + * Replace the default implementation for the primary screen. + */ +CoreScreen *dfb_screens_register_primary( CoreGraphicsDevice *device, + void *driver_data, + ScreenFuncs *funcs ); + +/* + * Enumerate all registered screens by invoking the callback for each screen. + */ +void dfb_screens_enumerate( CoreScreenCallback callback, + void *ctx ); + +/* + * Returns the screen with the specified ID. + */ +CoreScreen *dfb_screens_at( DFBScreenID screen_id ); + +CoreScreen *dfb_screens_at_translated( DFBScreenID screen_id ); + +/* + * Return the (translated) ID of the specified screen. + */ +DFBScreenID dfb_screen_id_translated( CoreScreen *screen ); + +#endif diff --git a/Source/DirectFB/src/core/screens_internal.h b/Source/DirectFB/src/core/screens_internal.h new file mode 100755 index 0000000..361b571 --- /dev/null +++ b/Source/DirectFB/src/core/screens_internal.h @@ -0,0 +1,81 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __DFB__CORE__SCREENS_INTERNAL_H__ +#define __DFB__CORE__SCREENS_INTERNAL_H__ + +#include + +#include + +#include +#include + +typedef struct { + DFBScreenMixerDescription description; + DFBScreenMixerConfig configuration; +} CoreScreenMixer; + +typedef struct { + DFBScreenEncoderDescription description; + DFBScreenEncoderConfig configuration; +} CoreScreenEncoder; + +typedef struct { + DFBScreenOutputDescription description; + DFBScreenOutputConfig configuration; +} CoreScreenOutput; + +typedef struct { + FusionSkirmish lock; + + DFBScreenID screen_id; + + DFBScreenDescription description; + + CoreScreenMixer *mixers; + CoreScreenEncoder *encoders; + CoreScreenOutput *outputs; + + void *screen_data; +} CoreScreenShared; + +struct __DFB_CoreScreen { + CoreScreenShared *shared; + + CoreDFB *core; + CoreGraphicsDevice *device; + + ScreenFuncs *funcs; + + void *driver_data; + void *screen_data; /* copy of shared->screen_data */ +}; + +#endif + diff --git a/Source/DirectFB/src/core/shared_surface_pool.c b/Source/DirectFB/src/core/shared_surface_pool.c new file mode 100755 index 0000000..5199a84 --- /dev/null +++ b/Source/DirectFB/src/core/shared_surface_pool.c @@ -0,0 +1,227 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include + +#include +#include +#include + +#include +#include + +#include + +/**********************************************************************************************************************/ + +typedef struct { + FusionSHMPoolShared *shmpool; +} SharedPoolData; + +typedef struct { + CoreDFB *core; + FusionWorld *world; +} SharedPoolLocalData; + +typedef struct { + void *addr; + int pitch; + int size; +} SharedAllocationData; + +/**********************************************************************************************************************/ + +static int +sharedPoolDataSize( void ) +{ + return sizeof(SharedPoolData); +} + +static int +sharedPoolLocalDataSize( void ) +{ + return sizeof(SharedPoolLocalData); +} + +static int +sharedAllocationDataSize( void ) +{ + return sizeof(SharedAllocationData); +} + +static DFBResult +sharedInitPool( CoreDFB *core, + CoreSurfacePool *pool, + void *pool_data, + void *pool_local, + void *system_data, + CoreSurfacePoolDescription *ret_desc ) +{ + DFBResult ret; + SharedPoolData *data = pool_data; + SharedPoolLocalData *local = pool_local; + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + D_ASSERT( ret_desc != NULL ); + + local->core = core; + local->world = dfb_core_world( core ); + + ret = fusion_shm_pool_create( local->world, "Surface Memory Pool", dfb_config->surface_shmpool_size, + fusion_config->debugshm, &data->shmpool ); + if (ret) + return ret; + + ret_desc->caps = CSPCAPS_NONE; + ret_desc->access[CSAID_CPU] = CSAF_READ | CSAF_WRITE | CSAF_SHARED; + ret_desc->access[CSAID_LAYER0] = CSAF_READ | CSAF_SHARED; + ret_desc->access[CSAID_LAYER1] = CSAF_READ | CSAF_SHARED; + ret_desc->types = CSTF_LAYER | CSTF_WINDOW | CSTF_CURSOR | CSTF_FONT | CSTF_SHARED | CSTF_INTERNAL; + ret_desc->priority = CSPP_DEFAULT; + + snprintf( ret_desc->name, DFB_SURFACE_POOL_DESC_NAME_LENGTH, "Shared Memory" ); + + return DFB_OK; +} + +static DFBResult +sharedDestroyPool( CoreSurfacePool *pool, + void *pool_data, + void *pool_local ) +{ + SharedPoolData *data = pool_data; + SharedPoolLocalData *local = pool_local; + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + + fusion_shm_pool_destroy( local->world, data->shmpool ); + + return DFB_OK; +} + +static DFBResult +sharedAllocateBuffer( CoreSurfacePool *pool, + void *pool_data, + void *pool_local, + CoreSurfaceBuffer *buffer, + CoreSurfaceAllocation *allocation, + void *alloc_data ) +{ + CoreSurface *surface; + SharedPoolData *data = pool_data; + SharedAllocationData *alloc = alloc_data; + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); + + surface = buffer->surface; + + D_MAGIC_ASSERT( surface, CoreSurface ); + + dfb_surface_calc_buffer_size( surface, 8, 0, &alloc->pitch, &alloc->size ); + + alloc->addr = SHMALLOC( data->shmpool, alloc->size ); + if (!alloc->addr) + return D_OOSHM(); + + allocation->flags = CSALF_VOLATILE; + allocation->size = alloc->size; + + return DFB_OK; +} + +static DFBResult +sharedDeallocateBuffer( CoreSurfacePool *pool, + void *pool_data, + void *pool_local, + CoreSurfaceBuffer *buffer, + CoreSurfaceAllocation *allocation, + void *alloc_data ) +{ + SharedPoolData *data = pool_data; + SharedAllocationData *alloc = alloc_data; + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); + + SHFREE( data->shmpool, alloc->addr ); + + return DFB_OK; +} + +static DFBResult +sharedLock( CoreSurfacePool *pool, + void *pool_data, + void *pool_local, + CoreSurfaceAllocation *allocation, + void *alloc_data, + CoreSurfaceBufferLock *lock ) +{ + SharedAllocationData *alloc = alloc_data; + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation ); + D_MAGIC_ASSERT( lock, CoreSurfaceBufferLock ); + + lock->addr = alloc->addr; + lock->pitch = alloc->pitch; + + return DFB_OK; +} + +static DFBResult +sharedUnlock( CoreSurfacePool *pool, + void *pool_data, + void *pool_local, + CoreSurfaceAllocation *allocation, + void *alloc_data, + CoreSurfaceBufferLock *lock ) +{ + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation ); + D_MAGIC_ASSERT( lock, CoreSurfaceBufferLock ); + + return DFB_OK; +} + +const SurfacePoolFuncs sharedSurfacePoolFuncs = { + .PoolDataSize = sharedPoolDataSize, + .PoolLocalDataSize = sharedPoolLocalDataSize, + .AllocationDataSize = sharedAllocationDataSize, + .InitPool = sharedInitPool, + .DestroyPool = sharedDestroyPool, + + .AllocateBuffer = sharedAllocateBuffer, + .DeallocateBuffer = sharedDeallocateBuffer, + + .Lock = sharedLock, + .Unlock = sharedUnlock, +}; + diff --git a/Source/DirectFB/src/core/state.c b/Source/DirectFB/src/core/state.c new file mode 100755 index 0000000..8ae97e0 --- /dev/null +++ b/Source/DirectFB/src/core/state.c @@ -0,0 +1,416 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include + +#include + +#include +#include + +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include + + +static inline void +validate_clip( CardState *state, + int xmax, + int ymax, + bool warn ) +{ + D_MAGIC_ASSERT( state, CardState ); + DFB_REGION_ASSERT( &state->clip ); + + D_ASSERT( xmax >= 0 ); + D_ASSERT( ymax >= 0 ); + D_ASSERT( state->clip.x1 <= state->clip.x2 ); + D_ASSERT( state->clip.y1 <= state->clip.y2 ); + + if (state->clip.x1 <= xmax && + state->clip.y1 <= ymax && + state->clip.x2 <= xmax && + state->clip.y2 <= ymax) + return; + + if (warn) + D_WARN( "Clip %d,%d-%dx%d invalid, adjusting to fit %dx%d", + DFB_RECTANGLE_VALS_FROM_REGION( &state->clip ), xmax+1, ymax+1 ); + + if (state->clip.x1 > xmax) + state->clip.x1 = xmax; + + if (state->clip.y1 > ymax) + state->clip.y1 = ymax; + + if (state->clip.x2 > xmax) + state->clip.x2 = xmax; + + if (state->clip.y2 > ymax) + state->clip.y2 = ymax; + + state->modified |= SMF_CLIP; +} + +int +dfb_state_init( CardState *state, CoreDFB *core ) +{ + D_ASSERT( state != NULL ); + + memset( state, 0, sizeof(CardState) ); + + state->core = core; + state->fusion_id = fusion_id( dfb_core_world(core) ); + state->modified = SMF_ALL; + state->src_blend = DSBF_SRCALPHA; + state->dst_blend = DSBF_INVSRCALPHA; + state->render_options = dfb_config->render_options; + + state->matrix[0] = 0x10000; + state->matrix[1] = 0x00000; + state->matrix[2] = 0x00000; + state->matrix[3] = 0x00000; + state->matrix[4] = 0x10000; + state->matrix[5] = 0x00000; + state->matrix[6] = 0x00000; + state->matrix[7] = 0x00000; + state->matrix[8] = 0x10000; + state->affine_matrix = DFB_TRUE; + + state->from = CSBR_FRONT; + state->to = CSBR_BACK; + + direct_util_recursive_pthread_mutex_init( &state->lock ); + + direct_serial_init( &state->dst_serial ); + direct_serial_init( &state->src_serial ); + direct_serial_init( &state->src_mask_serial ); + + D_MAGIC_SET( state, CardState ); + + return 0; +} + +void +dfb_state_destroy( CardState *state ) +{ + D_MAGIC_ASSERT( state, CardState ); + + D_ASSUME( !(state->flags & CSF_DRAWING) ); + + D_ASSERT( state->destination == NULL ); + D_ASSERT( state->source == NULL ); + D_ASSERT( state->source_mask == NULL ); + + D_MAGIC_CLEAR( state ); + + direct_serial_deinit( &state->dst_serial ); + direct_serial_deinit( &state->src_serial ); + direct_serial_deinit( &state->src_mask_serial ); + + if (state->gfxs) { + GenefxState *gfxs = state->gfxs; + + if (gfxs->ABstart) + D_FREE( gfxs->ABstart ); + + D_FREE( gfxs ); + } + + if (state->num_translation) { + D_ASSERT( state->index_translation != NULL ); + + D_FREE( state->index_translation ); + } + else + D_ASSERT( state->index_translation == NULL ); + + pthread_mutex_destroy( &state->lock ); +} + +DFBResult +dfb_state_set_destination( CardState *state, CoreSurface *destination ) +{ + D_MAGIC_ASSERT( state, CardState ); + + dfb_state_lock( state ); + + D_ASSUME( !(state->flags & CSF_DRAWING) ); + + if (state->destination != destination) { + if (destination) { + if (dfb_surface_ref( destination )) { + D_WARN( "could not ref() destination" ); + dfb_state_unlock( state ); + return DFB_DEAD; + } + + validate_clip( state, destination->config.size.w - 1, destination->config.size.h - 1, false ); + } + + if (state->destination) { + D_ASSERT( D_FLAGS_IS_SET( state->flags, CSF_DESTINATION ) ); + dfb_surface_unref( state->destination ); + } + + state->destination = destination; + state->modified |= SMF_DESTINATION; + + if (destination) { + direct_serial_copy( &state->dst_serial, &destination->serial ); + + D_FLAGS_SET( state->flags, CSF_DESTINATION ); + } + else + D_FLAGS_CLEAR( state->flags, CSF_DESTINATION ); + } + + dfb_state_unlock( state ); + + return DFB_OK; +} + +DFBResult +dfb_state_set_source( CardState *state, CoreSurface *source ) +{ + D_MAGIC_ASSERT( state, CardState ); + + dfb_state_lock( state ); + + if (state->source != source) { + if (source && dfb_surface_ref( source )) { + D_WARN( "could not ref() source" ); + dfb_state_unlock( state ); + return DFB_DEAD; + } + + if (state->source) { + D_ASSERT( D_FLAGS_IS_SET( state->flags, CSF_SOURCE ) ); + dfb_surface_unref( state->source ); + } + + state->source = source; + state->modified |= SMF_SOURCE; + + if (source) { + direct_serial_copy( &state->src_serial, &source->serial ); + + D_FLAGS_SET( state->flags, CSF_SOURCE ); + } + else + D_FLAGS_CLEAR( state->flags, CSF_SOURCE ); + } + + dfb_state_unlock( state ); + + return DFB_OK; +} + +DFBResult +dfb_state_set_source_mask( CardState *state, CoreSurface *source_mask ) +{ + D_MAGIC_ASSERT( state, CardState ); + + dfb_state_lock( state ); + + if (state->source_mask != source_mask) { + if (source_mask && dfb_surface_ref( source_mask )) { + D_WARN( "could not ref() source mask" ); + dfb_state_unlock( state ); + return DFB_DEAD; + } + + if (state->source_mask) { + D_ASSERT( D_FLAGS_IS_SET( state->flags, CSF_SOURCE_MASK ) ); + dfb_surface_unref( state->source_mask ); + } + + state->source_mask = source_mask; + state->modified |= SMF_SOURCE_MASK; + + if (source_mask) { + direct_serial_copy( &state->src_mask_serial, &source_mask->serial ); + + D_FLAGS_SET( state->flags, CSF_SOURCE_MASK ); + } + else + D_FLAGS_CLEAR( state->flags, CSF_SOURCE_MASK ); + } + + dfb_state_unlock( state ); + + return DFB_OK; +} + +void +dfb_state_update( CardState *state, bool update_sources ) +{ + CoreSurface *destination; + + D_MAGIC_ASSERT( state, CardState ); + DFB_REGION_ASSERT( &state->clip ); + + destination = state->destination; + + if (D_FLAGS_IS_SET( state->flags, CSF_DESTINATION )) { + + D_ASSERT( destination != NULL ); + + if (direct_serial_update( &state->dst_serial, &destination->serial )) { + validate_clip( state, destination->config.size.w - 1, destination->config.size.h - 1, true ); + + state->modified |= SMF_DESTINATION; + } + } + else if (destination) + validate_clip( state, destination->config.size.w - 1, destination->config.size.h - 1, true ); + + if (update_sources && D_FLAGS_IS_SET( state->flags, CSF_SOURCE )) { + CoreSurface *source = state->source; + + D_ASSERT( source != NULL ); + + if (direct_serial_update( &state->src_serial, &source->serial )) + state->modified |= SMF_SOURCE; + } + + if (update_sources && D_FLAGS_IS_SET( state->flags, CSF_SOURCE_MASK )) { + CoreSurface *source_mask = state->source_mask; + + D_ASSERT( source_mask != NULL ); + + if (direct_serial_update( &state->src_mask_serial, &source_mask->serial )) + state->modified |= SMF_SOURCE_MASK; + } +} + +DFBResult +dfb_state_set_index_translation( CardState *state, + const int *indices, + int num_indices ) +{ + D_MAGIC_ASSERT( state, CardState ); + + D_ASSERT( indices != NULL || num_indices == 0 ); + + dfb_state_lock( state ); + + if (state->num_translation != num_indices) { + int *new_trans = D_REALLOC( state->index_translation, + num_indices * sizeof(int) ); + + D_ASSERT( num_indices || new_trans == NULL ); + + if (num_indices && !new_trans) { + dfb_state_unlock( state ); + return D_OOM(); + } + + state->index_translation = new_trans; + state->num_translation = num_indices; + } + + if (num_indices) + direct_memcpy( state->index_translation, indices, num_indices * sizeof(int) ); + + state->modified |= SMF_INDEX_TRANSLATION; + + dfb_state_unlock( state ); + + return DFB_OK; +} + +void +dfb_state_set_matrix( CardState *state, + const s32 *matrix ) +{ + D_MAGIC_ASSERT( state, CardState ); + + D_ASSERT( matrix != NULL ); + + if (memcmp( state->matrix, matrix, sizeof(state->matrix) )) { + direct_memcpy( state->matrix, matrix, sizeof(state->matrix) ); + + state->affine_matrix = (matrix[6] == 0x00000 && + matrix[7] == 0x00000 && + matrix[8] == 0x10000); + + state->modified |= SMF_MATRIX; + } +} + +void +dfb_state_set_color_or_index( CardState *state, + const DFBColor *color, + int index ) +{ + CoreSurface *destination; + CorePalette *palette = NULL; + + D_MAGIC_ASSERT( state, CardState ); + D_ASSERT( color != NULL ); + + destination = state->destination; + if (destination) + palette = destination->palette; + + if (index < 0) { + D_ASSERT( color != NULL ); + + if (palette) + dfb_state_set_color_index( state, dfb_palette_search( palette, + color->r, color->g, + color->b, color->a ) ); + + dfb_state_set_color( state, color ); + } + else { + dfb_state_set_color_index( state, index ); + + if (palette) { + D_ASSERT( palette->num_entries > 0 ); + D_ASSUME( palette->num_entries > index ); + + dfb_state_set_color( state, &palette->entries[index % palette->num_entries] ); + } + } +} + diff --git a/Source/DirectFB/src/core/state.h b/Source/DirectFB/src/core/state.h new file mode 100755 index 0000000..7eb7667 --- /dev/null +++ b/Source/DirectFB/src/core/state.h @@ -0,0 +1,362 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __CORE__STATE_H__ +#define __CORE__STATE_H__ + +#include + +#include + +#include + +#include + +#include +#include +#include +#include + +#include + +#include +#include + + +typedef enum { + SMF_DRAWING_FLAGS = 0x00000001, + SMF_BLITTING_FLAGS = 0x00000002, + SMF_CLIP = 0x00000004, + SMF_COLOR = 0x00000008, + SMF_SRC_BLEND = 0x00000010, + SMF_DST_BLEND = 0x00000020, + SMF_SRC_COLORKEY = 0x00000040, + SMF_DST_COLORKEY = 0x00000080, + + SMF_DESTINATION = 0x00000100, + SMF_SOURCE = 0x00000200, + SMF_SOURCE_MASK = 0x00000400, + SMF_SOURCE_MASK_VALS = 0x00000800, + + SMF_INDEX_TRANSLATION = 0x00001000, + SMF_COLORKEY = 0x00002000, + + SMF_RENDER_OPTIONS = 0x00010000, + SMF_MATRIX = 0x00020000, + + SMF_ALL = 0x00033FFF +} StateModificationFlags; + +typedef enum { + CSF_NONE = 0x00000000, + + CSF_DESTINATION = 0x00000001, /* destination is set using dfb_state_set_destination() */ + CSF_SOURCE = 0x00000002, /* source is set using dfb_state_set_source() */ + CSF_SOURCE_MASK = 0x00000008, /* source mask is set using dfb_state_set_source_mask() */ + + CSF_SOURCE_LOCKED = 0x00000010, /* source surface is locked */ + CSF_SOURCE_MASK_LOCKED = 0x00000020, /* source mask surface is locked */ + + CSF_DRAWING = 0x00010000, /* something has been rendered with this state, + this is cleared by flushing the state, e.g. upon flip */ + + CSF_ALL = 0x0001003B +} CardStateFlags; + +struct _CardState { + int magic; + + CoreDFB *core; + CoreGraphicsDevice *device; + FusionID fusion_id; + + pthread_mutex_t lock; /* lock for state handling */ + + CardStateFlags flags; + + StateModificationFlags modified; /* indicate which fields have been + modified, these flags will be + cleared by the gfx drivers */ + StateModificationFlags mod_hw; + + /* values forming the state for graphics operations */ + + DFBSurfaceDrawingFlags drawingflags; /* drawing flags */ + DFBSurfaceBlittingFlags blittingflags; /* blitting flags */ + + DFBRegion clip; /* clipping rectangle */ + DFBColor color; /* color for drawing or modulation */ + unsigned int color_index; /* index to color in palette */ + DFBSurfaceBlendFunction src_blend; /* blend function for source */ + DFBSurfaceBlendFunction dst_blend; /* blend function for destination */ + u32 src_colorkey; /* colorkey for source */ + u32 dst_colorkey; /* colorkey for destination */ + + CoreSurface *destination; /* destination surface */ + CoreSurface *source; /* source surface */ + + DirectSerial dst_serial; /* last destination surface serial */ + DirectSerial src_serial; /* last source surface serial */ + + int *index_translation; + int num_translation; + + /* hardware abstraction and state handling helpers */ + + DFBAccelerationMask accel; /* remember checked commands if they are accelerated */ + DFBAccelerationMask checked; /* commands for which a state has been checked */ + DFBAccelerationMask set; /* commands for which a state is valid */ + DFBAccelerationMask disabled; /* commands which are disabled temporarily */ + + CoreGraphicsSerial serial; /* hardware serial of the last operation */ + + /* from/to buffers */ + + CoreSurfaceBufferRole from; /* usually CSBR_FRONT */ + CoreSurfaceBufferRole to; /* usually CSBR_BACK */ + + /* read/write locks during operation */ + + CoreSurfaceBufferLock dst; + CoreSurfaceBufferLock src; + + /* software driver */ + + GenefxState *gfxs; + + + /* extended state */ + + DFBSurfaceRenderOptions render_options; + + DFBColorKey colorkey; /* key for color key protection */ + + s32 matrix[9]; /* transformation matrix for DSRO_MATRIX (fixed 16.16) */ + DFBBoolean affine_matrix; + + CoreSurface *source_mask; /* source mask surface */ + CoreSurfaceBufferLock src_mask; /* source mask surface lock */ + DirectSerial src_mask_serial; /* last source mask surface serial */ + DFBPoint src_mask_offset; /* relative or absolute coordinates */ + DFBSurfaceMaskFlags src_mask_flags; /* controls coordinate mode and more */ + + DFBColor colors[DFB_COLOR_IDS_MAX]; /* colors for drawing or modulation */ + unsigned int color_indices[DFB_COLOR_IDS_MAX]; /* indices to colors in palette */ +}; + +int dfb_state_init( CardState *state, CoreDFB *core ); +void dfb_state_destroy( CardState *state ); + +DFBResult dfb_state_set_destination( CardState *state, CoreSurface *destination ); +DFBResult dfb_state_set_source( CardState *state, CoreSurface *source ); +DFBResult dfb_state_set_source_mask( CardState *state, CoreSurface *source_mask ); + +void dfb_state_update( CardState *state, bool update_source ); + +DFBResult dfb_state_set_index_translation( CardState *state, + const int *indices, + int num_indices ); + +void dfb_state_set_matrix( CardState *state, + const s32 *matrix ); + +static inline void +dfb_state_get_serial( const CardState *state, CoreGraphicsSerial *ret_serial ) +{ + D_ASSERT( state != NULL ); + D_ASSERT( ret_serial != NULL ); + + *ret_serial = state->serial; +} + +static inline void +dfb_state_lock( CardState *state ) +{ + D_MAGIC_ASSERT( state, CardState ); + + DFB_REGION_ASSERT( &state->clip ); + + pthread_mutex_lock( &state->lock ); +} + +static inline void +dfb_state_start_drawing( CardState *state, CoreGraphicsDevice *device ) +{ + D_MAGIC_ASSERT( state, CardState ); + D_ASSERT( device != NULL ); + D_ASSERT( state->destination != NULL ); + + if (dfb_config->startstop) { + if (state->flags & CSF_DRAWING) + D_ASSERT( state->device == device ); + else { + dfb_gfxcard_start_drawing( device, state ); + + state->flags = (CardStateFlags)(state->flags | CSF_DRAWING); + state->device = device; + } + } +} + +static inline void +dfb_state_stop_drawing( CardState *state ) +{ + D_MAGIC_ASSERT( state, CardState ); + D_ASSERT( state->destination != NULL ); + + if (dfb_config->startstop) { + if (state->flags & CSF_DRAWING) { + D_ASSERT( state->device != NULL ); + + dfb_gfxcard_stop_drawing( state->device, state ); + + state->flags = (CardStateFlags)(state->flags & ~CSF_DRAWING); + state->device = NULL; + } + else + D_ASSERT( state->device == NULL ); + } +} + +static inline void +dfb_state_unlock( CardState *state ) +{ + D_MAGIC_ASSERT( state, CardState ); + + DFB_REGION_ASSERT( &state->clip ); + + pthread_mutex_unlock( &state->lock ); +} + + +#define _dfb_state_set_checked(member,flag,state,value) \ +do { \ + D_MAGIC_ASSERT( state, CardState ); \ + \ + if ((value) != (state)->member) { \ + (state)->member = (value); \ + (state)->modified |= SMF_##flag; \ + } \ +} while (0) + + +#define dfb_state_set_blitting_flags(state,flags) _dfb_state_set_checked( blittingflags, \ + BLITTING_FLAGS, \ + state, flags ) + +#define dfb_state_set_drawing_flags(state,flags) _dfb_state_set_checked( drawingflags, \ + DRAWING_FLAGS, \ + state, flags ) + +#define dfb_state_set_color_index(state,index) _dfb_state_set_checked( color_index, \ + COLOR, \ + state, index ) + +#define dfb_state_set_src_blend(state,blend) _dfb_state_set_checked( src_blend, \ + SRC_BLEND, \ + state, blend ) + +#define dfb_state_set_dst_blend(state,blend) _dfb_state_set_checked( dst_blend, \ + DST_BLEND, \ + state, blend ) + +#define dfb_state_set_src_colorkey(state,key) _dfb_state_set_checked( src_colorkey, \ + SRC_COLORKEY, \ + state, key ) + +#define dfb_state_set_dst_colorkey(state,key) _dfb_state_set_checked( dst_colorkey, \ + DST_COLORKEY, \ + state, key ) + +#define dfb_state_set_render_options(state,opts) _dfb_state_set_checked( render_options, \ + RENDER_OPTIONS, \ + state, opts ) + +static inline void dfb_state_set_clip( CardState *state, const DFBRegion *clip ) +{ + D_MAGIC_ASSERT( state, CardState ); + DFB_REGION_ASSERT( clip ); + + if (! DFB_REGION_EQUAL( state->clip, *clip )) { + state->clip = *clip; + state->modified = (StateModificationFlags)( state->modified | SMF_CLIP ); + } +} + +static inline void dfb_state_set_color( CardState *state, const DFBColor *color ) +{ + D_MAGIC_ASSERT( state, CardState ); + D_ASSERT( color != NULL ); + + if (! DFB_COLOR_EQUAL( state->color, *color )) { + state->color = *color; + state->modified = (StateModificationFlags)( state->modified | SMF_COLOR ); + } +} + +static inline void dfb_state_set_colorkey( CardState *state, const DFBColorKey *key ) +{ + D_MAGIC_ASSERT( state, CardState ); + D_ASSERT( key != NULL ); + + if (! DFB_COLORKEY_EQUAL( state->colorkey, *key )) { + state->colorkey = *key; + state->modified = (StateModificationFlags)( state->modified | SMF_COLOR ); + } +} + +static inline void dfb_state_set_source_mask_vals( CardState *state, + const DFBPoint *offset, + DFBSurfaceMaskFlags flags ) +{ + D_MAGIC_ASSERT( state, CardState ); + D_ASSERT( offset != NULL ); + D_FLAGS_ASSERT( flags, DSMF_ALL ); + + if (! DFB_POINT_EQUAL( state->src_mask_offset, *offset ) || state->src_mask_flags != flags) { + state->src_mask_offset = *offset; + state->src_mask_flags = flags; + + state->modified = (StateModificationFlags)( state->modified | SMF_SOURCE_MASK_VALS ); + } +} + +/* + * Multifunctional color configuration function. + * + * Always tries to set both color and index. + * + * If color index is -1, color is used and searched in palette of destination surface if present. + * If color index is valid the color is looked up in palette if present. + */ +void dfb_state_set_color_or_index( CardState *state, + const DFBColor *color, + int index ); + +#endif + diff --git a/Source/DirectFB/src/core/surface.c b/Source/DirectFB/src/core/surface.c new file mode 100755 index 0000000..7b8e4fc --- /dev/null +++ b/Source/DirectFB/src/core/surface.c @@ -0,0 +1,768 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include + +#include +#include +#include + +#include +#include + +#include + + +D_DEBUG_DOMAIN( Core_Surface, "Core/Surface", "DirectFB Core Surface" ); + +/**********************************************************************************************************************/ + +static const ReactionFunc dfb_surface_globals[] = { +/* 0 */ _dfb_layer_region_surface_listener, +/* 1 */ _dfb_windowstack_background_image_listener, + NULL +}; + +static void +surface_destructor( FusionObject *object, bool zombie, void *ctx ) +{ + int i; + CoreSurface *surface = (CoreSurface*) object; + + D_MAGIC_ASSERT( surface, CoreSurface ); + + D_DEBUG_AT( Core_Surface, "destroying %p (%dx%d%s)\n", surface, + surface->config.size.w, surface->config.size.h, zombie ? " ZOMBIE" : ""); + + dfb_surface_lock( surface ); + + surface->state |= CSSF_DESTROYED; + + /* announce surface destruction */ + dfb_surface_notify( surface, CSNF_DESTROY ); + + /* unlink palette */ + if (surface->palette) { + dfb_palette_detach_global( surface->palette, &surface->palette_reaction ); + dfb_palette_unlink( &surface->palette ); + } + + /* destroy buffers */ + for (i=0; ibuffers[i]) + dfb_surface_buffer_destroy( surface->buffers[i] ); + } + + direct_serial_deinit( &surface->serial ); + + dfb_surface_unlock( surface ); + + fusion_skirmish_destroy( &surface->lock ); + + D_MAGIC_CLEAR( surface ); + + fusion_object_destroy( object ); +} + +FusionObjectPool * +dfb_surface_pool_create( const FusionWorld *world ) +{ + FusionObjectPool *pool; + + pool = fusion_object_pool_create( "Surface Pool", + sizeof(CoreSurface), + sizeof(CoreSurfaceNotification), + surface_destructor, NULL, world ); + + return pool; +} + +/**********************************************************************************************************************/ + +DFBResult +dfb_surface_create( CoreDFB *core, + const CoreSurfaceConfig *config, + CoreSurfaceTypeFlags type, + unsigned long resource_id, + CorePalette *palette, + CoreSurface **ret_surface ) +{ + DFBResult ret = DFB_BUG; + int i; + int buffers; + CoreSurface *surface; + char buf[64]; + + D_ASSERT( core != NULL ); + D_FLAGS_ASSERT( type, CSTF_ALL ); + D_MAGIC_ASSERT_IF( palette, CorePalette ); + D_ASSERT( ret_surface != NULL ); + + D_DEBUG_AT( Core_Surface, "dfb_surface_create( %p, %p, %p )\n", core, config, ret_surface ); + + surface = dfb_core_create_surface( core ); + if (!surface) + return DFB_FUSION; + + if (config) { + D_FLAGS_ASSERT( config->flags, CSCONF_ALL ); + + surface->config.flags = config->flags; + + if (config->flags & CSCONF_SIZE) { + D_DEBUG_AT( Core_Surface, " -> %dx%d\n", config->size.w, config->size.h ); + + surface->config.size = config->size; + } + + if (config->flags & CSCONF_FORMAT) { + D_DEBUG_AT( Core_Surface, " -> %s\n", dfb_pixelformat_name( config->format ) ); + + surface->config.format = config->format; + } + + if (config->flags & CSCONF_CAPS) { + D_DEBUG_AT( Core_Surface, " -> caps 0x%08x\n", config->caps ); + + if (config->caps & DSCAPS_ROTATED) + D_UNIMPLEMENTED(); + + surface->config.caps = config->caps & ~DSCAPS_ROTATED; + } + + if (config->flags & CSCONF_PREALLOCATED) { + D_DEBUG_AT( Core_Surface, " -> prealloc %p [%d]\n", + config->preallocated[0].addr, + config->preallocated[0].pitch ); + + direct_memcpy( surface->config.preallocated, config->preallocated, sizeof(config->preallocated) ); + + type |= CSTF_PREALLOCATED; + } + } + + if (surface->config.caps & DSCAPS_SYSTEMONLY) + surface->type = (type & ~CSTF_EXTERNAL) | CSTF_INTERNAL; + else if (surface->config.caps & DSCAPS_VIDEOONLY) + surface->type = (type & ~CSTF_INTERNAL) | CSTF_EXTERNAL; + else + surface->type = type & ~(CSTF_INTERNAL | CSTF_EXTERNAL); + + if (surface->config.caps & DSCAPS_SHARED) + surface->type |= CSTF_SHARED; + + surface->resource_id = resource_id; + + if (surface->config.caps & DSCAPS_TRIPLE) + buffers = 3; + else if (surface->config.caps & DSCAPS_DOUBLE) + buffers = 2; + else { + buffers = 1; + + surface->config.caps &= ~DSCAPS_ROTATED; + } + + surface->notifications = CSNF_ALL & ~CSNF_FLIP; + + surface->alpha_ramp[0] = 0x00; + surface->alpha_ramp[1] = 0x55; + surface->alpha_ramp[2] = 0xaa; + surface->alpha_ramp[3] = 0xff; + + + if (surface->config.caps & DSCAPS_STATIC_ALLOC) + surface->config.min_size = surface->config.size; + + surface->shmpool = dfb_core_shmpool( core ); + + direct_serial_init( &surface->serial ); + + snprintf( buf, sizeof(buf), "Surface %dx%d %s", surface->config.size.w, + surface->config.size.h, dfb_pixelformat_name(surface->config.format) ); + + fusion_ref_set_name( &surface->object.ref, buf ); + + fusion_skirmish_init( &surface->lock, buf, dfb_core_world(core) ); + + fusion_object_set_lock( &surface->object, &surface->lock ); + + D_MAGIC_SET( surface, CoreSurface ); + + + if (dfb_config->warn.flags & DCWF_CREATE_SURFACE && + dfb_config->warn.create_surface.min_size.w <= surface->config.size.w && + dfb_config->warn.create_surface.min_size.h <= surface->config.size.h) + D_WARN( "create-surface %4dx%4d %6s, buffers %d, caps 0x%08x, type 0x%08x", + surface->config.size.w, surface->config.size.h, dfb_pixelformat_name(surface->config.format), + buffers, surface->config.caps, surface->type ); + + + if (palette) { + dfb_surface_set_palette( surface, palette ); + } + else if (DFB_PIXELFORMAT_IS_INDEXED( surface->config.format )) { + ret = dfb_surface_init_palette( core, surface ); + if (ret) + goto error; + } + + /* Create the Surface Buffers. */ + for (i=0; ibuffers[surface->num_buffers++] = buffer; + + switch (i) { + case 0: + surface->buffer_indices[CSBR_FRONT] = i; + case 1: + surface->buffer_indices[CSBR_BACK] = i; + case 2: + surface->buffer_indices[CSBR_IDLE] = i; + } + } + + fusion_object_activate( &surface->object ); + + *ret_surface = surface; + + return DFB_OK; + +error: + D_MAGIC_CLEAR( surface ); + + for (i=0; ibuffers[i]) + dfb_surface_buffer_destroy( surface->buffers[i] ); + } + + fusion_skirmish_destroy( &surface->lock ); + + direct_serial_deinit( &surface->serial ); + + fusion_object_destroy( &surface->object ); + + return ret; +} + +DFBResult +dfb_surface_create_simple ( CoreDFB *core, + int width, + int height, + DFBSurfacePixelFormat format, + DFBSurfaceCapabilities caps, + CoreSurfaceTypeFlags type, + unsigned long resource_id, + CorePalette *palette, + CoreSurface **ret_surface ) +{ + CoreSurfaceConfig config; + + D_DEBUG_AT( Core_Surface, "%s( %p, %dx%d %s, %p )\n", __FUNCTION__, core, width, height, + dfb_pixelformat_name( format ), ret_surface ); + + D_ASSERT( core != NULL ); + D_ASSERT( ret_surface != NULL ); + + config.flags = CSCONF_SIZE | CSCONF_FORMAT | CSCONF_CAPS; + config.size.w = width; + config.size.h = height; + config.format = format; + config.caps = caps; + + return dfb_surface_create( core, &config, type, resource_id, palette, ret_surface ); +} + +DFBResult +dfb_surface_init_palette( CoreDFB *core, + CoreSurface *surface ) +{ + DFBResult ret; + CorePalette *palette; + + ret = dfb_palette_create( core, + 1 << DFB_COLOR_BITS_PER_PIXEL( surface->config.format ), + &palette ); + if (ret) { + D_DERROR( ret, "Core/Surface: Error creating palette!\n" ); + return ret; + } + + switch (surface->config.format) { + case DSPF_LUT8: + dfb_palette_generate_rgb332_map( palette ); + break; + + case DSPF_ALUT44: + dfb_palette_generate_rgb121_map( palette ); + break; + + default: + break; + } + + dfb_surface_set_palette( surface, palette ); + + dfb_palette_unref( palette ); + + return DFB_OK; +} + + +DFBResult +dfb_surface_notify( CoreSurface *surface, + CoreSurfaceNotificationFlags flags) +{ + CoreSurfaceNotification notification; + + D_MAGIC_ASSERT( surface, CoreSurface ); + FUSION_SKIRMISH_ASSERT( &surface->lock ); + D_FLAGS_ASSERT( flags, CSNF_ALL ); + + direct_serial_increase( &surface->serial ); + + if (!(surface->state & CSSF_DESTROYED)) { + if (!(surface->notifications & flags)) + return DFB_OK; + } + + notification.flags = flags; + notification.surface = surface; + + return dfb_surface_dispatch( surface, ¬ification, dfb_surface_globals ); +} + +DFBResult +dfb_surface_flip( CoreSurface *surface, bool swap ) +{ + unsigned int back, front; + + D_MAGIC_ASSERT( surface, CoreSurface ); + + FUSION_SKIRMISH_ASSERT( &surface->lock ); + + back = (surface->flips + CSBR_BACK) % surface->num_buffers; + front = (surface->flips + CSBR_FRONT) % surface->num_buffers; + + D_ASSERT( surface->buffer_indices[back] < surface->num_buffers ); + D_ASSERT( surface->buffer_indices[front] < surface->num_buffers ); + + if (surface->buffers[surface->buffer_indices[back]]->policy != + surface->buffers[surface->buffer_indices[front]]->policy || (surface->config.caps & DSCAPS_ROTATED)) + return DFB_UNSUPPORTED; + + if (swap) { + int tmp = surface->buffer_indices[back]; + surface->buffer_indices[back] = surface->buffer_indices[front]; + surface->buffer_indices[front] = tmp; + } + else + surface->flips++; + + dfb_surface_notify( surface, CSNF_FLIP ); + + return DFB_OK; +} + +DFBResult +dfb_surface_reconfig( CoreSurface *surface, + const CoreSurfaceConfig *config ) +{ + int i, buffers; + DFBResult ret; + + D_DEBUG_AT( Core_Surface, "%s( %p, %dx%d %s -> %dx%d %s )\n", __FUNCTION__, surface, + surface->config.size.w, surface->config.size.h, dfb_pixelformat_name( surface->config.format ), + (config->flags & CSCONF_SIZE) ? config->size.w : surface->config.size.w, + (config->flags & CSCONF_SIZE) ? config->size.h : surface->config.size.h, + (config->flags & CSCONF_FORMAT) ? dfb_pixelformat_name( config->format ) : + dfb_pixelformat_name( surface->config.format ) ); + + D_MAGIC_ASSERT( surface, CoreSurface ); + D_ASSERT( config != NULL ); + + if (surface->type & CSTF_PREALLOCATED) + return DFB_UNSUPPORTED; + + if (config->flags & CSCONF_PREALLOCATED) + return DFB_UNSUPPORTED; + + if (fusion_skirmish_prevail( &surface->lock )) + return DFB_FUSION; + + if ( (config->flags == CSCONF_SIZE || + ((config->flags == (CSCONF_SIZE | CSCONF_FORMAT)) && (config->format == surface->config.format))) && + config->size.w <= surface->config.min_size.w && + config->size.h <= surface->config.min_size.h) + { + surface->config.size = config->size; + + fusion_skirmish_dismiss( &surface->lock ); + return DFB_OK; + } + +#if 1 + /* Precheck the Surface Buffers. */ + for (i=0; inum_buffers; i++) { + if (surface->buffers[i]->locked) { + D_DEBUG_AT( Core_Surface, " -> surface is locked, cannot reconfigure!\n" ); + + fusion_skirmish_dismiss( &surface->lock ); + return DFB_LOCKED; + } + } +#endif + + /* Destroy the Surface Buffers. */ + for (i=0; inum_buffers; i++) { + dfb_surface_buffer_destroy( surface->buffers[i] ); + surface->buffers[i] = NULL; + } + + surface->num_buffers = 0; + + if (config->flags & CSCONF_SIZE) + surface->config.size = config->size; + + if (config->flags & CSCONF_FORMAT) + surface->config.format = config->format; + + if (config->flags & CSCONF_CAPS) { + if (config->caps & DSCAPS_ROTATED) + D_UNIMPLEMENTED(); + + surface->config.caps = config->caps & ~DSCAPS_ROTATED; + } + + if (surface->config.caps & DSCAPS_SYSTEMONLY) + surface->type = (surface->type & ~CSTF_EXTERNAL) | CSTF_INTERNAL; + else if (surface->config.caps & DSCAPS_VIDEOONLY) + surface->type = (surface->type & ~CSTF_INTERNAL) | CSTF_EXTERNAL; + else + surface->type = surface->type & ~(CSTF_INTERNAL | CSTF_EXTERNAL); + + if (surface->config.caps & DSCAPS_TRIPLE) + buffers = 3; + else if (surface->config.caps & DSCAPS_DOUBLE) + buffers = 2; + else { + buffers = 1; + + surface->config.caps &= ~DSCAPS_ROTATED; + } + + /* Recreate the Surface Buffers. */ + for (i=0; ibuffers[surface->num_buffers++] = buffer; + + switch (i) { + case 0: + surface->buffer_indices[CSBR_FRONT] = i; + case 1: + surface->buffer_indices[CSBR_BACK] = i; + case 2: + surface->buffer_indices[CSBR_IDLE] = i; + } + } + + dfb_surface_notify( surface, CSNF_SIZEFORMAT ); + + fusion_skirmish_dismiss( &surface->lock ); + + return DFB_OK; + +error: + D_UNIMPLEMENTED(); + + fusion_skirmish_dismiss( &surface->lock ); + + return ret; +} + +DFBResult +dfb_surface_destroy_buffers( CoreSurface *surface ) +{ + int i; + + D_MAGIC_ASSERT( surface, CoreSurface ); + + if (surface->type & CSTF_PREALLOCATED) + return DFB_UNSUPPORTED; + + if (fusion_skirmish_prevail( &surface->lock )) + return DFB_FUSION; + + /* Destroy the Surface Buffers. */ + for (i=0; inum_buffers; i++) { + dfb_surface_buffer_destroy( surface->buffers[i] ); + surface->buffers[i] = NULL; + } + + surface->num_buffers = 0; + + fusion_skirmish_dismiss( &surface->lock ); + + return DFB_OK; +} + +DFBResult +dfb_surface_lock_buffer( CoreSurface *surface, + CoreSurfaceBufferRole role, + CoreSurfaceAccessorID accessor, + CoreSurfaceAccessFlags access, + CoreSurfaceBufferLock *ret_lock ) +{ + DFBResult ret; + CoreSurfaceBuffer *buffer; + + D_MAGIC_ASSERT( surface, CoreSurface ); + + if (fusion_skirmish_prevail( &surface->lock )) + return DFB_FUSION; + + buffer = dfb_surface_get_buffer( surface, role ); + D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); + + ret = dfb_surface_buffer_lock( buffer, accessor, access, ret_lock ); + + fusion_skirmish_dismiss( &surface->lock ); + + return ret; +} + +DFBResult +dfb_surface_unlock_buffer( CoreSurface *surface, + CoreSurfaceBufferLock *lock ) +{ + DFBResult ret; + + D_MAGIC_ASSERT( surface, CoreSurface ); + + if (fusion_skirmish_prevail( &surface->lock )) + return DFB_FUSION; + + ret = dfb_surface_buffer_unlock( lock ); + + fusion_skirmish_dismiss( &surface->lock ); + + return ret; +} + +DFBResult +dfb_surface_read_buffer( CoreSurface *surface, + CoreSurfaceBufferRole role, + void *destination, + int pitch, + const DFBRectangle *rect ) +{ + DFBResult ret; + CoreSurfaceBuffer *buffer; + + D_MAGIC_ASSERT( surface, CoreSurface ); + D_ASSERT( destination != NULL ); + D_ASSERT( pitch > 0 ); + DFB_RECTANGLE_ASSERT_IF( rect ); + + if (fusion_skirmish_prevail( &surface->lock )) + return DFB_FUSION; + + buffer = dfb_surface_get_buffer( surface, role ); + D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); + + ret = dfb_surface_buffer_read( buffer, destination, pitch, rect ); + + fusion_skirmish_dismiss( &surface->lock ); + + return ret; +} + +DFBResult +dfb_surface_write_buffer( CoreSurface *surface, + CoreSurfaceBufferRole role, + const void *source, + int pitch, + const DFBRectangle *rect ) +{ + DFBResult ret; + CoreSurfaceBuffer *buffer; + + D_MAGIC_ASSERT( surface, CoreSurface ); + D_ASSERT( source != NULL ); + D_ASSERT( pitch > 0 ); + DFB_RECTANGLE_ASSERT_IF( rect ); + + if (fusion_skirmish_prevail( &surface->lock )) + return DFB_FUSION; + + buffer = dfb_surface_get_buffer( surface, role ); + D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); + + ret = dfb_surface_buffer_write( buffer, source, pitch, rect ); + + fusion_skirmish_dismiss( &surface->lock ); + + return ret; +} + +DFBResult +dfb_surface_dump_buffer( CoreSurface *surface, + CoreSurfaceBufferRole role, + const char *path, + const char *prefix ) +{ + DFBResult ret; + CoreSurfaceBuffer *buffer; + + D_MAGIC_ASSERT( surface, CoreSurface ); + D_ASSERT( path != NULL ); + D_ASSERT( prefix != NULL ); + + if (fusion_skirmish_prevail( &surface->lock )) + return DFB_FUSION; + + buffer = dfb_surface_get_buffer( surface, role ); + D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); + + ret = dfb_surface_buffer_dump( buffer, path, prefix ); + + fusion_skirmish_dismiss( &surface->lock ); + + return ret; +} + +DFBResult +dfb_surface_set_palette( CoreSurface *surface, + CorePalette *palette ) +{ + D_MAGIC_ASSERT( surface, CoreSurface ); + D_MAGIC_ASSERT_IF( palette, CorePalette ); + + if (fusion_skirmish_prevail( &surface->lock )) + return DFB_FUSION; + + if (surface->palette != palette) { + if (surface->palette) { + dfb_palette_detach_global( surface->palette, &surface->palette_reaction ); + dfb_palette_unlink( &surface->palette ); + } + + if (palette) { + dfb_palette_link( &surface->palette, palette ); + dfb_palette_attach_global( palette, DFB_SURFACE_PALETTE_LISTENER, + surface, &surface->palette_reaction ); + } + + dfb_surface_notify( surface, CSNF_PALETTE_CHANGE ); + } + + fusion_skirmish_dismiss( &surface->lock ); + + return DFB_OK; +} + +DFBResult +dfb_surface_set_field( CoreSurface *surface, + int field ) +{ + D_MAGIC_ASSERT( surface, CoreSurface ); + + if (fusion_skirmish_prevail( &surface->lock )) + return DFB_FUSION; + + surface->field = field; + + dfb_surface_notify( surface, CSNF_FIELD ); + + fusion_skirmish_dismiss( &surface->lock ); + + return DFB_OK; +} + +DFBResult +dfb_surface_set_alpha_ramp( CoreSurface *surface, + u8 a0, + u8 a1, + u8 a2, + u8 a3 ) +{ + D_MAGIC_ASSERT( surface, CoreSurface ); + + if (fusion_skirmish_prevail( &surface->lock )) + return DFB_FUSION; + + surface->alpha_ramp[0] = a0; + surface->alpha_ramp[1] = a1; + surface->alpha_ramp[2] = a2; + surface->alpha_ramp[3] = a3; + + dfb_surface_notify( surface, CSNF_ALPHA_RAMP ); + + fusion_skirmish_dismiss( &surface->lock ); + + return DFB_OK; +} + +ReactionResult +_dfb_surface_palette_listener( const void *msg_data, + void *ctx ) +{ + const CorePaletteNotification *notification = msg_data; + CoreSurface *surface = ctx; + + if (notification->flags & CPNF_DESTROY) + return RS_REMOVE; + + if (notification->flags & CPNF_ENTRIES) { + if (fusion_skirmish_prevail( &surface->lock )) + return RS_OK; + + dfb_surface_notify( surface, CSNF_PALETTE_UPDATE ); + + fusion_skirmish_dismiss( &surface->lock ); + } + + return RS_OK; +} + diff --git a/Source/DirectFB/src/core/surface.h b/Source/DirectFB/src/core/surface.h new file mode 100755 index 0000000..1d2d452 --- /dev/null +++ b/Source/DirectFB/src/core/surface.h @@ -0,0 +1,446 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __CORE__SURFACE_H__ +#define __CORE__SURFACE_H__ + +#include + +#include +#include +#include + +#include +#include + +#include +#include + + +typedef enum { + CSNF_NONE = 0x00000000, + + CSNF_SIZEFORMAT = 0x00000001, /* width, height, format */ + CSNF_SYSTEM = 0x00000002, /* system instance information */ + CSNF_VIDEO = 0x00000004, /* video instance information */ + CSNF_DESTROY = 0x00000008, /* surface is about to be destroyed */ + CSNF_FLIP = 0x00000010, /* surface buffer pointer swapped */ + CSNF_FIELD = 0x00000020, /* active (displayed) field switched */ + CSNF_PALETTE_CHANGE = 0x00000040, /* another palette has been set */ + CSNF_PALETTE_UPDATE = 0x00000080, /* current palette has been altered */ + CSNF_ALPHA_RAMP = 0x00000100, /* alpha ramp was modified */ + + CSNF_ALL = 0x000001FF +} CoreSurfaceNotificationFlags; + +typedef struct { + CoreSurfaceNotificationFlags flags; + CoreSurface *surface; +} CoreSurfaceNotification; + + +typedef enum { + CSCONF_NONE = 0x00000000, + + CSCONF_SIZE = 0x00000001, + CSCONF_FORMAT = 0x00000002, + CSCONF_CAPS = 0x00000004, + + CSCONF_PREALLOCATED = 0x00000010, + + CSCONF_ALL = 0x00000017 +} CoreSurfaceConfigFlags; + +typedef enum { + CSTF_NONE = 0x00000000, + + CSTF_LAYER = 0x00000001, /* surface for layer */ + CSTF_WINDOW = 0x00000002, /* surface for window */ + CSTF_CURSOR = 0x00000004, /* surface for cursor */ + CSTF_FONT = 0x00000008, /* surface for font */ + + CSTF_SHARED = 0x00000010, /* accessable by other processes */ + + CSTF_INTERNAL = 0x00000100, /* system memory */ + CSTF_EXTERNAL = 0x00000200, /* video memory */ + + CSTF_PREALLOCATED = 0x00000400, /* preallocated memory */ + + CSTF_ALL = 0x0000071F +} CoreSurfaceTypeFlags; + +typedef struct { + CoreSurfaceConfigFlags flags; + + DFBDimension size; + DFBSurfacePixelFormat format; + DFBSurfaceCapabilities caps; + + struct { + void *addr; + int pitch; + } preallocated[MAX_SURFACE_BUFFERS]; + + DFBDimension min_size; +} CoreSurfaceConfig; + +typedef enum { + CSP_SYSTEMONLY = 0x00000000, /* never try to swap + into video memory */ + CSP_VIDEOLOW = 0x00000001, /* try to store in video memory, + low priority */ + CSP_VIDEOHIGH = 0x00000002, /* try to store in video memory, + high priority */ + CSP_VIDEOONLY = 0x00000003 /* always and only + store in video memory */ +} CoreSurfacePolicy; + +typedef enum { + CSAF_NONE = 0x00000000, + + CSAF_READ = 0x00000001, /* accessor may read */ + CSAF_WRITE = 0x00000002, /* accessor may write */ + + CSAF_SHARED = 0x00000010, /* other processes can read/write at the same time (shared mapping) */ + + CSAF_ALL = 0x00000013 +} CoreSurfaceAccessFlags; + +typedef enum { + CSAID_NONE = 0x00000000, /* none or unknown accessor */ + + CSAID_CPU = 0x00000001, /* local processor, where DirectFB is running on, could be app or sw fallback */ + + CSAID_GPU = 0x00000002, /* primary accelerator, as in traditional 'gfxcard' core (ACCEL0) */ + + CSAID_ACCEL0 = 0x00000002, /* accelerators, decoders etc. (CSAID_ACCEL0 + accel_id<0-5>) */ + CSAID_ACCEL1 = 0x00000003, + CSAID_ACCEL2 = 0x00000004, + CSAID_ACCEL3 = 0x00000005, + CSAID_ACCEL4 = 0x00000006, + CSAID_ACCEL5 = 0x00000007, + + CSAID_LAYER0 = 0x00000008, /* display layers, registered by layer core (CSAID_LAYER0 + layer_id<0-7>) */ + CSAID_LAYER1 = 0x00000009, + CSAID_LAYER2 = 0x0000000a, + CSAID_LAYER3 = 0x0000000b, + CSAID_LAYER4 = 0x0000000c, + CSAID_LAYER5 = 0x0000000d, + CSAID_LAYER6 = 0x0000000e, + CSAID_LAYER7 = 0x0000000f, + + _CSAID_NUM = 0x00000010, /* number of statically assigned IDs for usage in static arrays */ + + CSAID_ANY = 0x00000100, /* any other accessor needs to be registered using IDs starting from here */ +} CoreSurfaceAccessorID; + +typedef enum { + CSBR_FRONT = 0, + CSBR_BACK = 1, + CSBR_IDLE = 2 +} CoreSurfaceBufferRole; + +typedef enum { + CSSF_NONE = 0x00000000, + + CSSF_DESTROYED = 0x00000001, /* surface is being or has been destroyed */ + + CSSF_ALL = 0x00000001 +} CoreSurfaceStateFlags; + +struct __DFB_CoreSurface +{ + FusionObject object; + int magic; + + FusionSkirmish lock; + + CoreSurfaceStateFlags state; + + CoreSurfaceConfig config; + CoreSurfaceTypeFlags type; + unsigned long resource_id; /* layer id, window id, or user specified */ + + int rotation; + + CoreSurfaceNotificationFlags notifications; + + DirectSerial serial; + + int field; + u8 alpha_ramp[4]; + + CoreSurfaceBuffer *buffers[MAX_SURFACE_BUFFERS]; + int num_buffers; + + int buffer_indices[MAX_SURFACE_BUFFERS]; + + unsigned int flips; + + CorePalette *palette; + GlobalReaction palette_reaction; + + FusionSHMPoolShared *shmpool; +}; + + +/* + * Creates a pool of surface objects. + */ +FusionObjectPool *dfb_surface_pool_create( const FusionWorld *world ); + +/* + * Generates dfb_surface_ref(), dfb_surface_attach() etc. + */ +FUSION_OBJECT_METHODS( CoreSurface, dfb_surface ) + + +DFBResult dfb_surface_create ( CoreDFB *core, + const CoreSurfaceConfig *config, + CoreSurfaceTypeFlags type, + unsigned long resource_id, + CorePalette *palette, + CoreSurface **ret_surface ); + +DFBResult dfb_surface_create_simple ( CoreDFB *core, + int width, + int height, + DFBSurfacePixelFormat format, + DFBSurfaceCapabilities caps, + CoreSurfaceTypeFlags type, + unsigned long resource_id, + CorePalette *palette, + CoreSurface **ret_surface ); + +DFBResult dfb_surface_init_palette ( CoreDFB *core, + CoreSurface *surface ); + +DFBResult dfb_surface_notify ( CoreSurface *surface, + CoreSurfaceNotificationFlags flags); + +DFBResult dfb_surface_flip ( CoreSurface *surface, + bool swap ); + +DFBResult dfb_surface_reconfig ( CoreSurface *surface, + const CoreSurfaceConfig *config ); + +DFBResult dfb_surface_destroy_buffers( CoreSurface *surface ); + +DFBResult dfb_surface_lock_buffer ( CoreSurface *surface, + CoreSurfaceBufferRole role, + CoreSurfaceAccessorID accessor, + CoreSurfaceAccessFlags access, + CoreSurfaceBufferLock *ret_lock ); + +DFBResult dfb_surface_unlock_buffer ( CoreSurface *surface, + CoreSurfaceBufferLock *lock ); + +DFBResult dfb_surface_read_buffer ( CoreSurface *surface, + CoreSurfaceBufferRole role, + void *destination, + int pitch, + const DFBRectangle *rect ); + +DFBResult dfb_surface_write_buffer ( CoreSurface *surface, + CoreSurfaceBufferRole role, + const void *source, + int pitch, + const DFBRectangle *rect ); + +DFBResult dfb_surface_dump_buffer ( CoreSurface *surface, + CoreSurfaceBufferRole role, + const char *path, + const char *prefix ); + +DFBResult dfb_surface_set_palette ( CoreSurface *surface, + CorePalette *palette ); + +DFBResult dfb_surface_set_field ( CoreSurface *surface, + int field ); + +DFBResult dfb_surface_set_alpha_ramp( CoreSurface *surface, + u8 a0, + u8 a1, + u8 a2, + u8 a3 ); + + +static inline DirectResult +dfb_surface_lock( CoreSurface *surface ) +{ + D_MAGIC_ASSERT( surface, CoreSurface ); + + return fusion_skirmish_prevail( &surface->lock ); +} + +static inline DirectResult +dfb_surface_trylock( CoreSurface *surface ) +{ + D_MAGIC_ASSERT( surface, CoreSurface ); + + return fusion_skirmish_swoop( &surface->lock ); +} + +static inline DirectResult +dfb_surface_unlock( CoreSurface *surface ) +{ + D_MAGIC_ASSERT( surface, CoreSurface ); + + return fusion_skirmish_dismiss( &surface->lock ); +} + +static inline CoreSurfaceBuffer * +dfb_surface_get_buffer( CoreSurface *surface, + CoreSurfaceBufferRole role ) +{ + D_MAGIC_ASSERT( surface, CoreSurface ); + D_ASSERT( role == CSBR_FRONT || role == CSBR_BACK || role == CSBR_IDLE ); + + D_ASSERT( surface->num_buffers > 0 ); + + return surface->buffers[ surface->buffer_indices[(surface->flips + role) % surface->num_buffers] ]; +} + +static inline void * +dfb_surface_data_offset( const CoreSurface *surface, + void *data, + int pitch, + int x, + int y ) +{ + D_ASSERT( surface != NULL ); + D_ASSERT( data != NULL ); + D_ASSERT( pitch > 0 ); + D_ASSERT( x >= 0 ); + D_ASSERT( x < surface->config.size.w ); + D_ASSERT( y >= 0 ); + D_ASSERT( y < surface->config.size.h ); + + if (surface->config.caps & DSCAPS_SEPARATED) { + if (y & 1) + y += surface->config.size.h; + + y >>= 1; + } + + return (u8*)data + pitch * y + DFB_BYTES_PER_LINE( surface->config.format, x ); +} + +static inline void +dfb_surface_calc_buffer_size( CoreSurface *surface, + int byte_align, + int pixel_align, + int *ret_pitch, + int *ret_size ) +{ + DFBSurfacePixelFormat format; + int width; + int pitch; + + D_MAGIC_ASSERT( surface, CoreSurface ); + + format = surface->config.format; + + width = direct_util_align( surface->config.size.w, pixel_align ); + pitch = direct_util_align( DFB_BYTES_PER_LINE( format, width ), byte_align ); + + if (ret_pitch) + *ret_pitch = pitch; + + if (ret_size) + *ret_size = pitch * DFB_PLANE_MULTIPLY( format, surface->config.size.h ); +} + +static inline void +dfb_surface_caps_apply_policy( CoreSurfacePolicy policy, + DFBSurfaceCapabilities *caps ) +{ + switch (policy) { + case CSP_SYSTEMONLY: + *caps = (DFBSurfaceCapabilities)((*caps & ~DSCAPS_VIDEOONLY) | DSCAPS_SYSTEMONLY); + break; + + case CSP_VIDEOONLY: + *caps = (DFBSurfaceCapabilities)((*caps & ~DSCAPS_SYSTEMONLY) | DSCAPS_VIDEOONLY); + break; + + default: + *caps = (DFBSurfaceCapabilities)(*caps & ~(DSCAPS_SYSTEMONLY | DSCAPS_VIDEOONLY)); + break; + } +} + +static inline DFBResult +dfb_surface_resize( CoreSurface *surface, + int width, + int height ) +{ + CoreSurfaceConfig config; + + D_MAGIC_ASSERT( surface, CoreSurface ); + D_ASSERT( width > 0 ); + D_ASSERT( height > 0 ); + + config.flags = CSCONF_SIZE; + config.size.w = width; + config.size.h = height; + + return dfb_surface_reconfig( surface, &config ); +} + +static inline DFBResult +dfb_surface_reformat( CoreSurface *surface, + int width, + int height, + DFBSurfacePixelFormat format ) +{ + CoreSurfaceConfig config; + + D_MAGIC_ASSERT( surface, CoreSurface ); + D_ASSERT( width > 0 ); + D_ASSERT( height > 0 ); + + config.flags = (CoreSurfaceConfigFlags)(CSCONF_SIZE | CSCONF_FORMAT); + config.size.w = width; + config.size.h = height; + config.format = format; + + return dfb_surface_reconfig( surface, &config ); +} + +/* global reactions */ +ReactionResult _dfb_surface_palette_listener( const void *msg_data, + void *ctx ); + +typedef enum { + DFB_LAYER_REGION_SURFACE_LISTENER, + DFB_WINDOWSTACK_BACKGROUND_IMAGE_LISTENER +} DFB_SURFACE_GLOBALS; + +#endif + diff --git a/Source/DirectFB/src/core/surface_buffer.c b/Source/DirectFB/src/core/surface_buffer.c new file mode 100755 index 0000000..da477df --- /dev/null +++ b/Source/DirectFB/src/core/surface_buffer.c @@ -0,0 +1,1206 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +//#define DIRECT_ENABLE_DEBUG + +#include + +#include + +#include +#include +#include +#include + +#ifdef USE_ZLIB +#include +#endif + +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include + +static const u8 lookup3to8[] = { 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff }; +static const u8 lookup2to8[] = { 0x00, 0x55, 0xaa, 0xff }; + + +D_DEBUG_DOMAIN( Core_SurfBuffer, "Core/SurfBuffer", "DirectFB Core Surface Buffer" ); + +/**********************************************************************************************************************/ + +DFBResult +dfb_surface_buffer_new( CoreSurface *surface, + CoreSurfaceBufferFlags flags, + CoreSurfaceBuffer **ret_buffer ) +{ + CoreSurfaceBuffer *buffer; + + D_MAGIC_ASSERT( surface, CoreSurface ); + D_FLAGS_ASSERT( flags, CSBF_ALL ); + D_ASSERT( ret_buffer != NULL ); + +#if DIRECT_BUILD_DEBUG + D_DEBUG_AT( Core_SurfBuffer, "dfb_surface_buffer_new( %s )\n", dfb_pixelformat_name( surface->config.format ) ); + + if (flags & CSBF_STICKED) + D_DEBUG_AT( Core_SurfBuffer, " -> STICKED\n" ); +#endif + + buffer = SHCALLOC( surface->shmpool, 1, sizeof(CoreSurfaceBuffer) ); + if (!buffer) + return D_OOSHM(); + + direct_serial_init( &buffer->serial ); + direct_serial_increase( &buffer->serial ); + + buffer->surface = surface; + buffer->flags = flags; + buffer->format = surface->config.format; + + if (surface->config.caps & DSCAPS_VIDEOONLY) + buffer->policy = CSP_VIDEOONLY; + else if (surface->config.caps & DSCAPS_SYSTEMONLY) + buffer->policy = CSP_SYSTEMONLY; + else + buffer->policy = CSP_VIDEOLOW; + + fusion_vector_init( &buffer->allocs, 2, surface->shmpool ); + + D_MAGIC_SET( buffer, CoreSurfaceBuffer ); + + *ret_buffer = buffer; + + return DFB_OK; +} + +DFBResult +dfb_surface_buffer_destroy( CoreSurfaceBuffer *buffer ) +{ + CoreSurface *surface; + CoreSurfaceAllocation *allocation; + int i; + + D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); + + surface = buffer->surface; + D_MAGIC_ASSERT( surface, CoreSurface ); + FUSION_SKIRMISH_ASSERT( &surface->lock ); + + D_DEBUG_AT( Core_SurfBuffer, "dfb_surface_buffer_destroy( %p [%dx%d] )\n", + buffer, surface->config.size.w, surface->config.size.h ); + + fusion_vector_foreach_reverse (allocation, i, buffer->allocs) + dfb_surface_pool_deallocate( allocation->pool, allocation ); + + fusion_vector_destroy( &buffer->allocs ); + + direct_serial_deinit( &buffer->serial ); + + D_MAGIC_CLEAR( buffer ); + + SHFREE( surface->shmpool, buffer ); + + return DFB_OK; +} + +static CoreSurfaceAllocation * +find_allocation( CoreSurfaceBuffer *buffer, + CoreSurfaceAccessorID accessor, + CoreSurfaceAccessFlags flags, + bool lock ) +{ + int i; + CoreSurfaceAllocation *alloc; + CoreSurfaceAllocation *uptodate = NULL; + CoreSurfaceAllocation *outdated = NULL; + + /* Prefer allocations which are up to date. */ + fusion_vector_foreach (alloc, i, buffer->allocs) { + if (direct_serial_check( &alloc->serial, &buffer->serial )) { + /* Return immediately if up to date allocation has required flags. */ + if (D_FLAGS_ARE_SET( alloc->access[accessor], flags )) + return alloc; + + /* Remember up to date allocation in case none has supported flags. */ + uptodate = alloc; + } + else if (D_FLAGS_ARE_SET( alloc->access[accessor], flags )) { + /* Remember outdated allocation which has supported flags though. */ + outdated = alloc; + } + } + + /* In case of a lock the flags are mandatory and the outdated allocation has to be used... */ + if (lock) + return outdated; + + /* ...otherwise we can still prefer the up to date allocation for Read/Write()! */ + return uptodate ?: outdated; +} + +DFBResult +dfb_surface_buffer_lock( CoreSurfaceBuffer *buffer, + CoreSurfaceAccessorID accessor, + CoreSurfaceAccessFlags access, + CoreSurfaceBufferLock *lock ) +{ + DFBResult ret; + CoreSurface *surface; + CoreSurfaceAllocation *allocation = NULL; + bool allocated = false; + + D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); + D_FLAGS_ASSERT( access, CSAF_ALL ); + D_ASSERT( lock != NULL ); + + surface = buffer->surface; + D_MAGIC_ASSERT( surface, CoreSurface ); + + FUSION_SKIRMISH_ASSERT( &surface->lock ); + + D_ASSERT( accessor >= CSAID_CPU ); + D_ASSUME( accessor < _CSAID_NUM ); + if (accessor >= CSAID_ANY) { + D_UNIMPLEMENTED(); + return DFB_UNIMPLEMENTED; + } + + if (accessor < 0 || accessor >= _CSAID_NUM) + return DFB_INVARG; + +#if DIRECT_BUILD_DEBUG + D_DEBUG_AT( Core_SurfBuffer, "dfb_surface_buffer_lock( %p, 0x%02x, %p ) <- %dx%d %s [%d]\n", buffer, access, lock, + surface->config.size.w, surface->config.size.h, dfb_pixelformat_name(buffer->format), + dfb_surface_buffer_index(buffer) ); + + switch (accessor) { + case CSAID_CPU: + D_DEBUG_AT( Core_SurfBuffer, " -> CPU %s%s\n", + (access & CSAF_READ) ? "READ" : "", (access & CSAF_WRITE) ? "WRITE" : "" ); + break; + + case CSAID_GPU: + D_DEBUG_AT( Core_SurfBuffer, " -> GPU %s%s\n", + (access & CSAF_READ) ? "READ" : "", (access & CSAF_WRITE) ? "WRITE" : "" ); + break; + + case CSAID_LAYER0: + case CSAID_LAYER1: + case CSAID_LAYER2: + case CSAID_LAYER3: + case CSAID_LAYER4: + case CSAID_LAYER5: + case CSAID_LAYER6: + case CSAID_LAYER7: + D_DEBUG_AT( Core_SurfBuffer, " -> LAYER %d %s%s\n", accessor - CSAID_LAYER0, + (access & CSAF_READ) ? "READ" : "", (access & CSAF_WRITE) ? "WRITE" : "" ); + break; + + default: + D_DEBUG_AT( Core_SurfBuffer, " -> other\n" ); + break; + } + + if (access & CSAF_SHARED) + D_DEBUG_AT( Core_SurfBuffer, " -> SHARED\n" ); +#endif + + /* Look for allocation with proper access. */ + allocation = find_allocation( buffer, accessor, access, true ); + if (!allocation) { + /* If no allocation exists, create one. */ + ret = dfb_surface_pools_allocate( buffer, accessor, access, &allocation ); + if (ret) { + D_DERROR( ret, "Core/SurfBuffer: Buffer allocation failed!\n" ); + return ret; + } + + allocated = true; + } + + CORE_SURFACE_ALLOCATION_ASSERT( allocation ); + + /* Synchronize with other allocations. */ + ret = dfb_surface_allocation_update( allocation, access ); + if (ret) { + /* Destroy if newly created. */ + if (allocated) + dfb_surface_pool_deallocate( allocation->pool, allocation ); + return ret; + } + + /* Lock the allocation. */ + dfb_surface_buffer_lock_init( lock, accessor, access ); + + ret = dfb_surface_pool_lock( allocation->pool, allocation, lock ); + if (ret) { + D_DERROR( ret, "Core/SurfBuffer: Locking allocation failed! [%s]\n", + allocation->pool->desc.name ); + dfb_surface_buffer_lock_deinit( lock ); + + /* Destroy if newly created. */ + if (allocated) + dfb_surface_pool_deallocate( allocation->pool, allocation ); + + return ret; + } + +#if 1 + /* + * Manage access interlocks. + * + * SOON FIXME: Clearing flags only when not locked yet. Otherwise nested GPU/CPU locks are a problem. + */ + /* Software read/write access... */ + if (accessor == CSAID_CPU) { + /* If hardware has written or is writing... */ + if (allocation->accessed[CSAID_GPU] & CSAF_WRITE) { + /* ...wait for the operation to finish. */ + dfb_gfxcard_sync(); /* TODO: wait for serial instead */ + + /* Software read access after hardware write requires flush of the (bus) read cache. */ + dfb_gfxcard_flush_read_cache(); + + if (!buffer->locked) { + /* ...clear hardware write access. */ + allocation->accessed[CSAID_GPU] &= ~CSAF_WRITE; + + /* ...clear hardware read access (to avoid syncing twice). */ + allocation->accessed[CSAID_GPU] &= ~CSAF_READ; + } + } + + /* Software write access... */ + if (access & CSAF_WRITE) { + /* ...if hardware has (to) read... */ + if (allocation->accessed[CSAID_GPU] & CSAF_READ) { + /* ...wait for the operation to finish. */ + dfb_gfxcard_sync(); /* TODO: wait for serial instead */ + + /* ...clear hardware read access. */ + if (!buffer->locked) + allocation->accessed[CSAID_GPU] &= ~CSAF_READ; + } + } + } + + /* Hardware read access... */ + if (accessor == CSAID_GPU && access & CSAF_READ) { + /* ...if software has written before... */ + if (allocation->accessed[CSAID_CPU] & CSAF_WRITE) { + /* ...flush texture cache. */ + dfb_gfxcard_flush_texture_cache(); + + /* ...clear software write access. */ + if (!buffer->locked) + allocation->accessed[CSAID_CPU] &= ~CSAF_WRITE; + } + } + + if (! D_FLAGS_ARE_SET( allocation->accessed[accessor], access )) { + /* FIXME: surface_enter */ + } +#endif + + /* Collect... */ + allocation->accessed[accessor] |= access; + +#if 1 + /* FIXME: don't use weak counter */ + buffer->locked++; + + D_DEBUG_AT( Core_SurfBuffer, " -> locked %dx now\n", buffer->locked ); +#endif + + return DFB_OK; +} + +DFBResult +dfb_surface_buffer_unlock( CoreSurfaceBufferLock *lock ) +{ + DFBResult ret; + CoreSurfacePool *pool; + CoreSurfaceBuffer *buffer; + CoreSurfaceAllocation *allocation; + + D_DEBUG_AT( Core_SurfBuffer, "dfb_surface_buffer_unlock( %p )\n", lock ); + + D_MAGIC_ASSERT( lock, CoreSurfaceBufferLock ); + + D_MAGIC_ASSERT( lock->buffer, CoreSurfaceBuffer ); + D_MAGIC_ASSERT( lock->buffer->surface, CoreSurface ); + + FUSION_SKIRMISH_ASSERT( &lock->buffer->surface->lock ); + + allocation = lock->allocation; + CORE_SURFACE_ALLOCATION_ASSERT( allocation ); + + buffer = lock->buffer; + D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); + + pool = allocation->pool; + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + + /* + * FIXME: This should fail with a nested GPU Lock during a CPU Lock and/or vice versa? + */ +// D_ASSUME( D_FLAGS_ARE_SET( allocation->accessed, lock->access ) ); + + ret = dfb_surface_pool_unlock( pool, lock->allocation, lock ); + if (ret) { + D_DERROR( ret, "Core/SurfBuffer: Unlocking allocation failed! [%s]\n", pool->desc.name ); + return ret; + } + +#if 1 + buffer->locked--; +#endif + + dfb_surface_buffer_lock_reset( lock ); + + dfb_surface_buffer_lock_deinit( lock ); + + return DFB_OK; +} + +DFBResult +dfb_surface_buffer_read( CoreSurfaceBuffer *buffer, + void *destination, + int pitch, + const DFBRectangle *prect ) +{ + DFBResult ret; + int y; + int bytes; + DFBRectangle rect; + CoreSurface *surface; + CoreSurfaceAllocation *allocation = NULL; + bool allocated = false; + DFBSurfacePixelFormat format; + + D_DEBUG_AT( Core_SurfBuffer, "%s( %p, %p [%d] )\n", __FUNCTION__, buffer, destination, pitch ); + + D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); + D_ASSERT( destination != NULL ); + D_ASSERT( pitch > 0 ); + DFB_RECTANGLE_ASSERT_IF( prect ); + + surface = buffer->surface; + D_MAGIC_ASSERT( surface, CoreSurface ); + + FUSION_SKIRMISH_ASSERT( &surface->lock ); + + /* Determine area. */ + rect.x = 0; + rect.y = 0; + rect.w = surface->config.size.w; + rect.h = surface->config.size.h; + + if (prect && (!dfb_rectangle_intersect( &rect, prect ) || !DFB_RECTANGLE_EQUAL( rect, *prect ))) + return DFB_INVAREA; + + /* Calculate bytes per read line. */ + format = surface->config.format; + bytes = DFB_BYTES_PER_LINE( format, rect.w ); + + D_DEBUG_AT( Core_SurfBuffer, " -> %d,%d - %dx%d (%s)\n", DFB_RECTANGLE_VALS(&rect), + dfb_pixelformat_name( format ) ); + + /* If no allocations exists, simply clear the destination. */ + if (fusion_vector_is_empty( &buffer->allocs )) { + for (y=0; ywritten && direct_serial_check( &buffer->written->serial, &buffer->serial )) + allocation = buffer->written; + else { + /* ...otherwise look for allocation with CPU access. */ + allocation = find_allocation( buffer, CSAID_CPU, CSAF_READ, false ); + if (!allocation) { + /* If no allocation exists, create one. */ + ret = dfb_surface_pools_allocate( buffer, CSAID_CPU, CSAF_READ, &allocation ); + if (ret) { + D_DERROR( ret, "Core/SurfBuffer: Buffer allocation failed!\n" ); + return ret; + } + + allocated = true; + } + } + + CORE_SURFACE_ALLOCATION_ASSERT( allocation ); + + /* Synchronize with other allocations. */ + ret = dfb_surface_allocation_update( allocation, CSAF_READ ); + if (ret) { + /* Destroy if newly created. */ + if (allocated) + dfb_surface_pool_deallocate( allocation->pool, allocation ); + return ret; + } + + /* Try reading from allocation directly... */ + ret = dfb_surface_pool_read( allocation->pool, allocation, destination, pitch, &rect ); + if (ret) { + /* ...otherwise use fallback method via locking if possible. */ + if (allocation->access[CSAID_CPU] & CSAF_READ) { + CoreSurfaceBufferLock lock; + + /* Lock the allocation. */ + dfb_surface_buffer_lock_init( &lock, CSAID_CPU, CSAF_READ ); + + ret = dfb_surface_pool_lock( allocation->pool, allocation, &lock ); + if (ret) { + D_DERROR( ret, "Core/SurfBuffer: Locking allocation failed! [%s]\n", + allocation->pool->desc.name ); + dfb_surface_buffer_lock_deinit( &lock ); + return ret; + } + + /* Move to start of read. */ + lock.addr += DFB_BYTES_PER_LINE( format, rect.x ) + rect.y * lock.pitch; + + /* Copy the data. */ + for (y=0; ypool, allocation, &lock ); + if (ret) + D_DERROR( ret, "Core/SurfBuffer: Unlocking allocation failed! [%s]\n", allocation->pool->desc.name ); + + dfb_surface_buffer_lock_deinit( &lock ); + } + } + + return ret; +} + +DFBResult +dfb_surface_buffer_write( CoreSurfaceBuffer *buffer, + const void *source, + int pitch, + const DFBRectangle *prect ) +{ + DFBResult ret; + DFBRectangle rect; + CoreSurface *surface; + CoreSurfaceAllocation *allocation = NULL; + bool allocated = false; + + D_DEBUG_AT( Core_SurfBuffer, "%s( %p, %p [%d] )\n", __FUNCTION__, buffer, source, pitch ); + + D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); + D_ASSERT( pitch > 0 || source == NULL ); + DFB_RECTANGLE_ASSERT_IF( prect ); + + surface = buffer->surface; + D_MAGIC_ASSERT( surface, CoreSurface ); + + FUSION_SKIRMISH_ASSERT( &surface->lock ); + + /* Determine area. */ + rect.x = 0; + rect.y = 0; + rect.w = surface->config.size.w; + rect.h = surface->config.size.h; + + if (prect && (!dfb_rectangle_intersect( &rect, prect ) || !DFB_RECTANGLE_EQUAL( rect, *prect ))) + return DFB_INVAREA; + + D_DEBUG_AT( Core_SurfBuffer, " -> %d,%d - %dx%d (%s)\n", DFB_RECTANGLE_VALS(&rect), + dfb_pixelformat_name( surface->config.format ) ); + + /* Use last read allocation if it's up to date... */ + if (buffer->read && direct_serial_check( &buffer->read->serial, &buffer->serial )) + allocation = buffer->read; + else { + /* ...otherwise look for allocation with CPU access. */ + allocation = find_allocation( buffer, CSAID_CPU, CSAF_WRITE, false ); + if (!allocation) { + /* If no allocation exists, create one. */ + ret = dfb_surface_pools_allocate( buffer, CSAID_CPU, CSAF_WRITE, &allocation ); + if (ret) { + D_DERROR( ret, "Core/SurfBuffer: Buffer allocation failed!\n" ); + return ret; + } + + allocated = true; + } + } + + CORE_SURFACE_ALLOCATION_ASSERT( allocation ); + + /* Synchronize with other allocations. */ + ret = dfb_surface_allocation_update( allocation, CSAF_WRITE ); + if (ret) { + /* Destroy if newly created. */ + if (allocated) + dfb_surface_pool_deallocate( allocation->pool, allocation ); + return ret; + } + + /* Try writing to allocation directly... */ + ret = source ? dfb_surface_pool_write( allocation->pool, allocation, source, pitch, &rect ) : DFB_UNSUPPORTED; + if (ret) { + /* ...otherwise use fallback method via locking if possible. */ + if (allocation->access[CSAID_CPU] & CSAF_WRITE) { + int y; + int bytes; + DFBSurfacePixelFormat format; + CoreSurfaceBufferLock lock; + + /* Calculate bytes per written line. */ + format = surface->config.format; + bytes = DFB_BYTES_PER_LINE( format, rect.w ); + + /* Lock the allocation. */ + dfb_surface_buffer_lock_init( &lock, CSAID_CPU, CSAF_WRITE ); + + ret = dfb_surface_pool_lock( allocation->pool, allocation, &lock ); + if (ret) { + D_DERROR( ret, "Core/SurfBuffer: Locking allocation failed! [%s]\n", + allocation->pool->desc.name ); + dfb_surface_buffer_lock_deinit( &lock ); + return ret; + } + + /* Move to start of write. */ + lock.addr += DFB_BYTES_PER_LINE( format, rect.x ) + rect.y * lock.pitch; + + /* Copy the data. */ + for (y=0; ypool, allocation, &lock ); + if (ret) + D_DERROR( ret, "Core/SurfBuffer: Unlocking allocation failed! [%s]\n", allocation->pool->desc.name ); + + dfb_surface_buffer_lock_deinit( &lock ); + } + } + + return ret; +} + +DFBResult +dfb_surface_buffer_dump( CoreSurfaceBuffer *buffer, + const char *directory, + const char *prefix ) +{ + DFBResult ret; + int num = -1; + int fd_p = -1; + int fd_g = -1; + int i, n; + int len = (directory ? strlen(directory) : 0) + (prefix ? strlen(prefix) : 0) + 40; + char filename[len]; + char head[30]; + bool rgb = false; + bool alpha = false; +#ifdef USE_ZLIB + gzFile gz_p = NULL, gz_g = NULL; + static const char *gz_ext = ".gz"; +#else + static const char *gz_ext = ""; +#endif + CoreSurface *surface; + CorePalette *palette = NULL; + CoreSurfaceBufferLock lock; + + D_DEBUG_AT( Core_SurfBuffer, "%s( %p, %p, %p )\n", __FUNCTION__, buffer, directory, prefix ); + + D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); + D_ASSERT( directory != NULL ); + + surface = buffer->surface; + D_MAGIC_ASSERT( surface, CoreSurface ); + + FUSION_SKIRMISH_ASSERT( &surface->lock ); + + /* Check pixel format. */ + switch (buffer->format) { + case DSPF_LUT8: + palette = surface->palette; + + if (!palette) { + D_BUG( "no palette" ); + return DFB_BUG; + } + + if (dfb_palette_ref( palette )) + return DFB_FUSION; + + rgb = true; + + /* fall through */ + + case DSPF_A8: + alpha = true; + break; + + case DSPF_ARGB: + case DSPF_ARGB1555: + case DSPF_ARGB2554: + case DSPF_ARGB4444: + case DSPF_AiRGB: + alpha = true; + + /* fall through */ + + case DSPF_RGB332: + case DSPF_RGB16: + case DSPF_RGB24: + case DSPF_RGB32: + case DSPF_YUY2: + case DSPF_UYVY: + case DSPF_NV16: + case DSPF_RGB444: + case DSPF_RGB555: + case DSPF_BGR555: + rgb = true; + break; + + + default: + D_ERROR( "DirectFB/core/surfaces: surface dump for format " + "'%s' is not implemented!\n", + dfb_pixelformat_name( buffer->format ) ); + return DFB_UNSUPPORTED; + } + + /* Lock the surface buffer, get the data pointer and pitch. */ + ret = dfb_surface_buffer_lock( buffer, CSAID_CPU, CSAF_READ, &lock ); + if (ret) { + if (palette) + dfb_palette_unref( palette ); + return ret; + } + + if (prefix) { + /* Find the lowest unused index. */ + while (++num < 10000) { + snprintf( filename, len, "%s/%s_%04d.ppm%s", + directory, prefix, num, gz_ext ); + + if (access( filename, F_OK ) != 0) { + snprintf( filename, len, "%s/%s_%04d.pgm%s", + directory, prefix, num, gz_ext ); + + if (access( filename, F_OK ) != 0) + break; + } + } + + if (num == 10000) { + D_ERROR( "DirectFB/core/surfaces: " + "couldn't find an unused index for surface dump!\n" ); + dfb_surface_buffer_unlock( &lock ); + if (palette) + dfb_palette_unref( palette ); + return DFB_FAILURE; + } + } + + /* Create a file with the found index. */ + if (rgb) { + if (prefix) + snprintf( filename, len, "%s/%s_%04d.ppm%s", directory, prefix, num, gz_ext ); + else + snprintf( filename, len, "%s.ppm%s", directory, gz_ext ); + + fd_p = open( filename, O_EXCL | O_CREAT | O_WRONLY, 0644 ); + if (fd_p < 0) { + D_PERROR("DirectFB/core/surfaces: " + "could not open %s!\n", filename); + dfb_surface_buffer_unlock( &lock ); + if (palette) + dfb_palette_unref( palette ); + return DFB_IO; + } + } + + /* Create a graymap for the alpha channel using the found index. */ + if (alpha) { + if (prefix) + snprintf( filename, len, "%s/%s_%04d.pgm%s", directory, prefix, num, gz_ext ); + else + snprintf( filename, len, "%s.pgm%s", directory, gz_ext ); + + fd_g = open( filename, O_EXCL | O_CREAT | O_WRONLY, 0644 ); + if (fd_g < 0) { + D_PERROR("DirectFB/core/surfaces: " + "could not open %s!\n", filename); + + dfb_surface_buffer_unlock( &lock ); + if (palette) + dfb_palette_unref( palette ); + + if (rgb) { + close( fd_p ); + snprintf( filename, len, "%s/%s_%04d.ppm%s", + directory, prefix, num, gz_ext ); + unlink( filename ); + } + + return DFB_IO; + } + } + +#ifdef USE_ZLIB + if (rgb) + gz_p = gzdopen( fd_p, "wb" ); + + if (alpha) + gz_g = gzdopen( fd_g, "wb" ); +#endif + + if (rgb) { + /* Write the pixmap header. */ + snprintf( head, 30, + "P6\n%d %d\n255\n", surface->config.size.w, surface->config.size.h ); +#ifdef USE_ZLIB + gzwrite( gz_p, head, strlen(head) ); +#else + write( fd_p, head, strlen(head) ); +#endif + } + + /* Write the graymap header. */ + if (alpha) { + snprintf( head, 30, + "P5\n%d %d\n255\n", surface->config.size.w, surface->config.size.h ); +#ifdef USE_ZLIB + gzwrite( gz_g, head, strlen(head) ); +#else + write( fd_g, head, strlen(head) ); +#endif + } + + /* Write the pixmap (and graymap) data. */ + for (i=0; iconfig.size.h; i++) { + int n3; + + /* Prepare one row. */ + u8 *src8 = dfb_surface_data_offset( surface, lock.addr, lock.pitch, 0, i ); + + /* Write color buffer to pixmap file. */ + if (rgb) { + u8 buf_p[surface->config.size.w * 3]; + + if (buffer->format == DSPF_LUT8) { + for (n=0, n3=0; nconfig.size.w; n++, n3+=3) { + buf_p[n3+0] = palette->entries[src8[n]].r; + buf_p[n3+1] = palette->entries[src8[n]].g; + buf_p[n3+2] = palette->entries[src8[n]].b; + } + } + else + dfb_convert_to_rgb24( buffer->format, src8, lock.pitch, surface->config.size.h, + buf_p, surface->config.size.w * 3, surface->config.size.w, 1 ); +#ifdef USE_ZLIB + gzwrite( gz_p, buf_p, surface->config.size.w * 3 ); +#else + write( fd_p, buf_p, surface->config.size.w * 3 ); +#endif + } + + /* Write alpha buffer to graymap file. */ + if (alpha) { + u8 buf_g[surface->config.size.w]; + + if (buffer->format == DSPF_LUT8) { + for (n=0; nconfig.size.w; n++) + buf_g[n] = palette->entries[src8[n]].a; + } + else + dfb_convert_to_a8( buffer->format, src8, lock.pitch, surface->config.size.h, + buf_g, surface->config.size.w, surface->config.size.w, 1 ); +#ifdef USE_ZLIB + gzwrite( gz_g, buf_g, surface->config.size.w ); +#else + write( fd_g, buf_g, surface->config.size.w ); +#endif + } + } + + /* Unlock the surface buffer. */ + dfb_surface_buffer_unlock( &lock ); + + /* Release the palette. */ + if (palette) + dfb_palette_unref( palette ); + +#ifdef USE_ZLIB + if (rgb) + gzclose( gz_p ); + + if (alpha) + gzclose( gz_g ); +#endif + + /* Close pixmap file. */ + if (rgb) + close( fd_p ); + + /* Close graymap file. */ + if (alpha) + close( fd_g ); + + return DFB_OK; +} + +/**********************************************************************************************************************/ + +static void +transfer_buffer( CoreSurfaceBuffer *buffer, + const void *src, + void *dst, + int srcpitch, + int dstpitch ) +{ + int i; + CoreSurface *surface; + + D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); + + surface = buffer->surface; + D_MAGIC_ASSERT( surface, CoreSurface ); + + D_DEBUG_AT( Core_SurfBuffer, "%s( %p, %p [%d] -> %p [%d] ) * %d\n", + __FUNCTION__, buffer, src, srcpitch, dst, dstpitch, surface->config.size.h ); + + D_ASSERT( src != NULL ); + D_ASSERT( dst != NULL ); + D_ASSERT( srcpitch > 0 ); + D_ASSERT( dstpitch > 0 ); + + D_ASSERT( srcpitch >= DFB_BYTES_PER_LINE( buffer->format, surface->config.size.w ) ); + D_ASSERT( dstpitch >= DFB_BYTES_PER_LINE( buffer->format, surface->config.size.w ) ); + + for (i=0; iconfig.size.h; i++) { + direct_memcpy( dst, src, DFB_BYTES_PER_LINE( buffer->format, surface->config.size.w ) ); + + src += srcpitch; + dst += dstpitch; + } + + switch (buffer->format) { + case DSPF_YV12: + case DSPF_I420: + for (i=0; iconfig.size.h; i++) { + direct_memcpy( dst, src, + DFB_BYTES_PER_LINE( buffer->format, surface->config.size.w / 2 ) ); + src += srcpitch / 2; + dst += dstpitch / 2; + } + break; + + case DSPF_NV12: + case DSPF_NV21: + for (i=0; iconfig.size.h/2; i++) { + direct_memcpy( dst, src, + DFB_BYTES_PER_LINE( buffer->format, surface->config.size.w ) ); + src += srcpitch; + dst += dstpitch; + } + break; + + case DSPF_NV16: + for (i=0; iconfig.size.h; i++) { + direct_memcpy( dst, src, + DFB_BYTES_PER_LINE( buffer->format, surface->config.size.w ) ); + src += srcpitch; + dst += dstpitch; + } + break; + + default: + break; + } +} + +static DFBResult +allocation_update_copy( CoreSurfaceAllocation *allocation, + CoreSurfaceAllocation *source ) +{ + DFBResult ret; + CoreSurfaceBufferLock src; + CoreSurfaceBufferLock dst; + CoreSurfaceBuffer *buffer; + + D_DEBUG_AT( Core_SurfBuffer, "%s()\n", __FUNCTION__ ); + + D_ASSERT( allocation != source ); + + D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation ); + D_MAGIC_ASSERT( source, CoreSurfaceAllocation ); + + D_ASSERT( source->buffer == allocation->buffer ); + + buffer = allocation->buffer; + D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); + + /* Lock the source allocation. */ + dfb_surface_buffer_lock_init( &src, CSAID_CPU, CSAF_READ ); + + ret = dfb_surface_pool_lock( source->pool, source, &src ); + if (ret) { + D_DERROR( ret, "Core/SurfBuffer: Could not lock source for transfer!\n" ); + dfb_surface_buffer_lock_deinit( &src ); + return ret; + } + + /* Lock the destination allocation. */ + dfb_surface_buffer_lock_init( &dst, CSAID_CPU, CSAF_WRITE ); + + ret = dfb_surface_pool_lock( allocation->pool, allocation, &dst ); + if (ret) { + D_DERROR( ret, "Core/SurfBuffer: Could not lock destination for transfer!\n" ); + dfb_surface_pool_unlock( source->pool, source, &src ); + return ret; + } + + transfer_buffer( buffer, src.addr, dst.addr, src.pitch, dst.pitch ); + + dfb_surface_pool_unlock( allocation->pool, allocation, &dst ); + dfb_surface_pool_unlock( source->pool, source, &src ); + + dfb_surface_buffer_lock_deinit( &dst ); + dfb_surface_buffer_lock_deinit( &src ); + + return DFB_OK; +} + +static DFBResult +allocation_update_write( CoreSurfaceAllocation *allocation, + CoreSurfaceAllocation *source ) +{ + DFBResult ret; + CoreSurfaceBufferLock src; + CoreSurfaceBuffer *buffer; + + D_DEBUG_AT( Core_SurfBuffer, "%s()\n", __FUNCTION__ ); + + D_ASSERT( allocation != source ); + + D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation ); + D_MAGIC_ASSERT( source, CoreSurfaceAllocation ); + + D_ASSERT( source->buffer == allocation->buffer ); + + buffer = allocation->buffer; + D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); + + /* Lock the source allocation. */ + dfb_surface_buffer_lock_init( &src, CSAID_CPU, CSAF_READ ); + + ret = dfb_surface_pool_lock( source->pool, source, &src ); + if (ret) { + D_DERROR( ret, "Core/SurfBuffer: Could not lock source for transfer!\n" ); + dfb_surface_buffer_lock_deinit( &src ); + return ret; + } + + /* Write to the destination allocation. */ + ret = dfb_surface_pool_write( allocation->pool, allocation, src.addr, src.pitch, NULL ); + if (ret) + D_DERROR( ret, "Core/SurfBuffer: Could not write from destination allocation!\n" ); + + dfb_surface_pool_unlock( source->pool, source, &src ); + + dfb_surface_buffer_lock_deinit( &src ); + + return ret; +} + +static DFBResult +allocation_update_read( CoreSurfaceAllocation *allocation, + CoreSurfaceAllocation *source ) +{ + DFBResult ret; + CoreSurfaceBufferLock dst; + CoreSurfaceBuffer *buffer; + + D_DEBUG_AT( Core_SurfBuffer, "%s()\n", __FUNCTION__ ); + + D_ASSERT( allocation != source ); + + D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation ); + D_MAGIC_ASSERT( source, CoreSurfaceAllocation ); + + D_ASSERT( source->buffer == allocation->buffer ); + + buffer = allocation->buffer; + D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); + + /* Lock the destination allocation. */ + dfb_surface_buffer_lock_init( &dst, CSAID_CPU, CSAF_WRITE ); + + ret = dfb_surface_pool_lock( allocation->pool, allocation, &dst ); + if (ret) { + D_DERROR( ret, "Core/SurfBuffer: Could not lock destination for transfer!\n" ); + dfb_surface_buffer_lock_deinit( &dst ); + return ret; + } + + /* Read from the source allocation. */ + ret = dfb_surface_pool_read( source->pool, source, dst.addr, dst.pitch, NULL ); + if (ret) + D_DERROR( ret, "Core/SurfBuffer: Could not read from source allocation!\n" ); + + dfb_surface_pool_unlock( allocation->pool, allocation, &dst ); + + dfb_surface_buffer_lock_deinit( &dst ); + + return ret; +} + +DFBResult +dfb_surface_allocation_update( CoreSurfaceAllocation *allocation, + CoreSurfaceAccessFlags access ) +{ + DFBResult ret; + int i; + CoreSurfaceAllocation *alloc; + CoreSurfaceBuffer *buffer; + + D_DEBUG_AT( Core_SurfBuffer, "%s()\n", __FUNCTION__ ); + + D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation ); + D_FLAGS_ASSERT( access, CSAF_ALL ); + + buffer = allocation->buffer; + D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); + + if (direct_serial_update( &allocation->serial, &buffer->serial ) && buffer->written) { + CoreSurfaceAllocation *source = buffer->written; + + D_ASSUME( allocation != source ); + + D_DEBUG_AT( Core_SurfBuffer, " -> updating allocation...\n" ); + + D_MAGIC_ASSERT( source, CoreSurfaceAllocation ); + D_ASSERT( source->buffer == allocation->buffer ); + + ret = dfb_surface_pool_bridges_transfer( buffer, source, allocation, NULL, 0 ); + if (ret) { + if ((source->access[CSAID_CPU] & CSAF_READ) && (allocation->access[CSAID_CPU] & CSAF_WRITE)) + ret = allocation_update_copy( allocation, source ); + else if (source->access[CSAID_CPU] & CSAF_READ) + ret = allocation_update_write( allocation, source ); + else if (allocation->access[CSAID_CPU] & CSAF_WRITE) + ret = allocation_update_read( allocation, source ); + else { + D_UNIMPLEMENTED(); + ret = DFB_UNSUPPORTED; + } + } + + if (ret) { + D_DERROR( ret, "Core/SurfaceBuffer: Updating allocation failed!\n" ); + return ret; + } + } + + if (access & CSAF_WRITE) { + D_DEBUG_AT( Core_SurfBuffer, " -> increasing serial...\n" ); + + direct_serial_increase( &buffer->serial ); + + direct_serial_copy( &allocation->serial, &buffer->serial ); + + buffer->written = allocation; + buffer->read = NULL; + + /* Zap volatile allocations (freed when no longer up to date). */ + fusion_vector_foreach (alloc, i, buffer->allocs) { + D_MAGIC_ASSERT( alloc, CoreSurfaceAllocation ); + + if (alloc != allocation && (alloc->flags & CSALF_VOLATILE)) { + dfb_surface_pool_deallocate( alloc->pool, alloc ); + i--; + } + } + } + else + buffer->read = allocation; + + /* Zap all other allocations? */ + if (dfb_config->thrifty_surface_buffers) { + buffer->written = buffer->read = allocation; + + fusion_vector_foreach (alloc, i, buffer->allocs) { + D_MAGIC_ASSERT( alloc, CoreSurfaceAllocation ); + + /* Don't zap preallocated which would not really free up memory, but just loose the handle. */ + if (alloc != allocation && !(alloc->flags & (CSALF_PREALLOCATED | CSALF_MUCKOUT))) { + dfb_surface_pool_deallocate( alloc->pool, alloc ); + i--; + } + } + } + + return DFB_OK; +} + diff --git a/Source/DirectFB/src/core/surface_buffer.h b/Source/DirectFB/src/core/surface_buffer.h new file mode 100755 index 0000000..4acf65a --- /dev/null +++ b/Source/DirectFB/src/core/surface_buffer.h @@ -0,0 +1,257 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __CORE__SURFACE_BUFFER_H__ +#define __CORE__SURFACE_BUFFER_H__ + +#include +#include + +#include + +#include + +#include + + +/* + * Configuration and State flags of a Surface Buffer + */ +typedef enum { + CSBF_NONE = 0x00000000, /* None of these. */ + + CSBF_STICKED = 0x00000001, /* Sticked to one Surface Pool, e.g. system only. */ + + CSBF_ALL = 0x00000001 /* All of these. */ +} CoreSurfaceBufferFlags; + +/* + * Configuration and State flags of a Surface Buffer Allocation + */ +typedef enum { + CSALF_NONE = 0x00000000, /* None of these. */ + + CSALF_ONEFORALL = 0x00000001, /* Only one allocation in pool for all buffers. */ + CSALF_VOLATILE = 0x00000002, /* Allocation should be freed when no longer up to date. */ + CSALF_PREALLOCATED = 0x00000004, /* Preallocated memory, don't zap when "thrifty-surface-buffers" is active. */ + + CSALF_MUCKOUT = 0x00001000, /* Indicates surface pool being in the progress of mucking out this and possibly + other allocations to have enough space for a new allocation to be made. */ + + CSALF_ALL = 0x00001007 /* All of these. */ +} CoreSurfaceAllocationFlags; + +/* + * An Allocation of a Surface Buffer + */ +struct __DFB_CoreSurfaceAllocation { + int magic; + + DirectSerial serial; /* Equals serial of buffer if content is up to date. */ + + CoreSurfaceBuffer *buffer; /* Surface Buffer owning this allocation. */ + CoreSurface *surface; /* Surface owning the Buffer of this allocation. */ + CoreSurfacePool *pool; /* Surface Pool providing the allocation. */ + void *data; /* Pool's private data for this allocation. */ + int size; /* Amount of data used by this allocation. */ + unsigned long offset; /* Offset within address range of pool if contiguous. */ + + CoreSurfaceAllocationFlags flags; /* Pool can return CSALF_ONEFORALL upon allocation of first buffer. */ + + const CoreSurfaceAccessFlags *access; /* Possible access flags (pointer to pool description). */ + CoreSurfaceAccessFlags accessed[_CSAID_NUM]; /* Access since last synchronization. */ +}; + +#define CORE_SURFACE_ALLOCATION_ASSERT(alloc) \ + do { \ + D_MAGIC_ASSERT( alloc, CoreSurfaceAllocation ); \ + D_ASSUME( (alloc)->size > 0 ); \ + D_ASSERT( (alloc)->size >= 0 ); \ + D_ASSERT( (alloc)->offset + (alloc)->size <= ((alloc)->pool->desc.size ?:~0UL) ); \ + D_FLAGS_ASSERT( (alloc)->access[CSAID_CPU], CSAF_ALL ); \ + D_FLAGS_ASSERT( (alloc)->access[CSAID_GPU], CSAF_ALL ); \ + D_FLAGS_ASSERT( (alloc)->flags, CSALF_ALL ); \ + D_FLAGS_ASSERT( (alloc)->accessed[CSAID_CPU], CSAF_ALL ); \ + D_FLAGS_ASSERT( (alloc)->accessed[CSAID_GPU], CSAF_ALL ); \ + } while (0) + +/* + * A Lock on a Surface Buffer + */ +struct __DFB_CoreSurfaceBufferLock { + int magic; /* Must be valid before calling dfb_surface_pool_lock() */ + + CoreSurfaceAccessorID accessor; /* " */ + CoreSurfaceAccessFlags access; /* " */ + + CoreSurfaceBuffer *buffer; /* Set by dfb_surface_pool_lock() */ + CoreSurfaceAllocation *allocation; /* " */ + + void *addr; /* " */ + unsigned long phys; /* " */ + unsigned long offset; /* " */ + unsigned int pitch; /* " */ + + void *handle; /* " */ +}; + +static inline void +dfb_surface_buffer_lock_reset( CoreSurfaceBufferLock *lock ) +{ + D_MAGIC_ASSERT( lock, CoreSurfaceBufferLock ); + + lock->buffer = NULL; + lock->allocation = NULL; + lock->addr = NULL; + lock->phys = 0; + lock->offset = ~0; + lock->pitch = 0; + lock->handle = NULL; +} + +static inline void +dfb_surface_buffer_lock_init( CoreSurfaceBufferLock *lock, CoreSurfaceAccessorID accessor, CoreSurfaceAccessFlags access ) +{ + D_MAGIC_SET( lock, CoreSurfaceBufferLock ); + + lock->accessor = accessor; + lock->access = access; + + dfb_surface_buffer_lock_reset( lock ); +} + +static inline void +dfb_surface_buffer_lock_deinit( CoreSurfaceBufferLock *lock ) +{ + D_MAGIC_ASSERT( lock, CoreSurfaceBufferLock ); + + lock->accessor = CSAID_NONE; + lock->access = CSAF_NONE; + + D_MAGIC_CLEAR( lock ); +} + +#define CORE_SURFACE_BUFFER_LOCK_ASSERT(lock) \ + do { \ + D_MAGIC_ASSERT( lock, CoreSurfaceBufferLock ); \ + D_FLAGS_ASSERT( (lock)->access, CSAF_ALL ); \ + if ((lock)->buffer) { \ + D_ASSERT( (lock)->allocation != NULL ); \ + D_ASSERT( (lock)->buffer == (lock)->allocation->buffer ); \ + D_ASSUME( (lock)->addr != NULL || (lock)->phys != 0 || (lock)->offset != ~0 || (lock)->handle != NULL );\ + D_ASSUME( (lock)->offset == (lock)->allocation->offset || (lock)->offset == ~0 ); \ + D_ASSERT( (lock)->pitch > 0 || ((lock)->addr == NULL && (lock)->phys == 0) ); \ + } \ + else { \ + D_ASSERT( (lock)->allocation == NULL ); \ + D_ASSERT( (lock)->addr == NULL ); \ + D_ASSERT( (lock)->phys == 0 ); \ + D_ASSERT( (lock)->offset == ~0 ); \ + D_ASSERT( (lock)->pitch == 0 ); \ + D_ASSERT( (lock)->handle == NULL ); \ + } \ + } while (0) + +/* + * A Surface Buffer of a Surface + */ +struct __DFB_CoreSurfaceBuffer { + int magic; + + DirectSerial serial; /* Increased when content is written. */ + CoreSurfaceAllocation *written; /* Allocation with the last write access. */ + CoreSurfaceAllocation *read; /* Allocation with the last read access. */ + + CoreSurface *surface; /* Surface owning this Surface Buffer. */ + CoreSurfacePolicy policy; + + CoreSurfaceBufferFlags flags; /* Configuration and State flags. */ + DFBSurfacePixelFormat format; /* Pixel format of buffer data. */ + + FusionVector allocs; /* Allocations within Surface Pools. */ + +#if 1 + unsigned int locked; /* Lock count. FIXME: Add fail safe cleanup! */ +#endif +}; + + +DFBResult dfb_surface_buffer_new ( CoreSurface *surface, + CoreSurfaceBufferFlags flags, + CoreSurfaceBuffer **ret_buffer ); + +DFBResult dfb_surface_buffer_destroy( CoreSurfaceBuffer *buffer ); + + +DFBResult dfb_surface_buffer_lock ( CoreSurfaceBuffer *buffer, + CoreSurfaceAccessorID accessor, + CoreSurfaceAccessFlags access, + CoreSurfaceBufferLock *ret_lock ); + +DFBResult dfb_surface_buffer_unlock ( CoreSurfaceBufferLock *lock ); + +DFBResult dfb_surface_buffer_read ( CoreSurfaceBuffer *buffer, + void *destination, + int pitch, + const DFBRectangle *rect ); + +DFBResult dfb_surface_buffer_write ( CoreSurfaceBuffer *buffer, + const void *source, + int pitch, + const DFBRectangle *rect ); + +DFBResult dfb_surface_buffer_dump ( CoreSurfaceBuffer *buffer, + const char *directory, + const char *prefix ); + +static inline int +dfb_surface_buffer_index( CoreSurfaceBuffer *buffer ) +{ + int index; + CoreSurface *surface; + + D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); + + surface = buffer->surface; + D_MAGIC_ASSERT( surface, CoreSurface ); + + for (index=0; indexbuffers[index] == buffer) + return index; + } + + D_ASSERT( index, + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include + + +extern SurfacePoolFuncs localSurfacePoolFuncs; +extern SurfacePoolFuncs sharedSurfacePoolFuncs; +extern SurfacePoolFuncs preallocSurfacePoolFuncs; + + + +D_DEBUG_DOMAIN( Core_Surface, "Core/SurfaceCore", "DirectFB Surface Core" ); + +/**********************************************************************************************************************/ + +typedef struct { + int magic; + + CoreSurfacePool *local_pool; + CoreSurfacePool *shared_pool; + CoreSurfacePool *prealloc_pool; +} DFBSurfaceCoreShared; + +typedef struct { + int magic; + + CoreDFB *core; + + DFBSurfaceCoreShared *shared; +} DFBSurfaceCore; + + +DFB_CORE_PART( surface_core, SurfaceCore ); + +/**********************************************************************************************************************/ + +static DFBResult +dfb_surface_core_initialize( CoreDFB *core, + DFBSurfaceCore *data, + DFBSurfaceCoreShared *shared ) +{ + DFBResult ret; + + D_DEBUG_AT( Core_Surface, "dfb_surface_core_initialize( %p, %p, %p )\n", core, data, shared ); + + D_ASSERT( data != NULL ); + D_ASSERT( shared != NULL ); + + data->core = core; + data->shared = shared; + + ret = dfb_surface_pool_initialize( core, &sharedSurfacePoolFuncs, &shared->shared_pool ); + if (ret) { + D_DERROR( ret, "Core/Surface: Could not register 'shared' surface pool!\n" ); + return ret; + } + + ret = dfb_surface_pool_initialize( core, &localSurfacePoolFuncs, &shared->local_pool ); + if (ret) { + D_DERROR( ret, "Core/Surface: Could not register 'local' surface pool!\n" ); + dfb_surface_pool_destroy( shared->shared_pool ); + return ret; + } + + ret = dfb_surface_pool_initialize( core, &preallocSurfacePoolFuncs, &shared->prealloc_pool ); + if (ret) { + D_DERROR( ret, "Core/Surface: Could not register 'prealloc' surface pool!\n" ); + dfb_surface_pool_destroy( shared->local_pool ); + dfb_surface_pool_destroy( shared->shared_pool ); + return ret; + } + + D_MAGIC_SET( data, DFBSurfaceCore ); + D_MAGIC_SET( shared, DFBSurfaceCoreShared ); + + return DFB_OK; +} + +static DFBResult +dfb_surface_core_join( CoreDFB *core, + DFBSurfaceCore *data, + DFBSurfaceCoreShared *shared ) +{ + D_DEBUG_AT( Core_Surface, "dfb_surface_core_join( %p, %p, %p )\n", core, data, shared ); + + D_ASSERT( data != NULL ); + D_MAGIC_ASSERT( shared, DFBSurfaceCoreShared ); + + data->core = core; + data->shared = shared; + + dfb_surface_pool_join( core, shared->shared_pool, &sharedSurfacePoolFuncs ); + dfb_surface_pool_join( core, shared->local_pool, &localSurfacePoolFuncs ); + dfb_surface_pool_join( core, shared->prealloc_pool, &preallocSurfacePoolFuncs ); + + D_MAGIC_SET( data, DFBSurfaceCore ); + + return DFB_OK; +} + +static DFBResult +dfb_surface_core_shutdown( DFBSurfaceCore *data, + bool emergency ) +{ + DFBSurfaceCoreShared *shared; + + D_DEBUG_AT( Core_Surface, "dfb_surface_core_shutdown( %p, %semergency )\n", data, emergency ? "" : "no " ); + + D_MAGIC_ASSERT( data, DFBSurfaceCore ); + D_MAGIC_ASSERT( data->shared, DFBSurfaceCoreShared ); + + shared = data->shared; + + dfb_surface_pool_destroy( shared->prealloc_pool ); + dfb_surface_pool_destroy( shared->local_pool ); + dfb_surface_pool_destroy( shared->shared_pool ); + + D_MAGIC_CLEAR( data ); + D_MAGIC_CLEAR( shared ); + + return DFB_OK; +} + +static DFBResult +dfb_surface_core_leave( DFBSurfaceCore *data, + bool emergency ) +{ + DFBSurfaceCoreShared *shared; + + D_DEBUG_AT( Core_Surface, "dfb_surface_core_leave( %p, %semergency )\n", data, emergency ? "" : "no " ); + + D_MAGIC_ASSERT( data, DFBSurfaceCore ); + D_MAGIC_ASSERT( data->shared, DFBSurfaceCoreShared ); + + shared = data->shared; + + dfb_surface_pool_leave( shared->shared_pool ); + dfb_surface_pool_leave( shared->local_pool ); + dfb_surface_pool_leave( shared->prealloc_pool ); + + D_MAGIC_CLEAR( data ); + + return DFB_OK; +} + +static DFBResult +dfb_surface_core_suspend( DFBSurfaceCore *data ) +{ + DFBSurfaceCoreShared *shared; + + D_DEBUG_AT( Core_Surface, "dfb_surface_core_suspend( %p )\n", data ); + + D_MAGIC_ASSERT( data, DFBSurfaceCore ); + D_MAGIC_ASSERT( data->shared, DFBSurfaceCoreShared ); + + shared = data->shared; + + return DFB_OK; +} + +static DFBResult +dfb_surface_core_resume( DFBSurfaceCore *data ) +{ + DFBSurfaceCoreShared *shared; + + D_DEBUG_AT( Core_Surface, "dfb_surface_core_resume( %p )\n", data ); + + D_MAGIC_ASSERT( data, DFBSurfaceCore ); + D_MAGIC_ASSERT( data->shared, DFBSurfaceCoreShared ); + + shared = data->shared; + + return DFB_OK; +} + diff --git a/Source/DirectFB/src/core/surface_pool.c b/Source/DirectFB/src/core/surface_pool.c new file mode 100755 index 0000000..0518df2 --- /dev/null +++ b/Source/DirectFB/src/core/surface_pool.c @@ -0,0 +1,1263 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include +#include + +#include +#include + +#include + +#include +#include + +#include +#include +#include + +#include + +#include + + +D_DEBUG_DOMAIN( Core_SurfacePool, "Core/SurfacePool", "DirectFB Core Surface Pool" ); +D_DEBUG_DOMAIN( Core_SurfPoolLock, "Core/SurfPoolLock", "DirectFB Core Surface Pool Lock" ); + +/**********************************************************************************************************************/ + +static const SurfacePoolFuncs *pool_funcs[MAX_SURFACE_POOLS]; +static void *pool_locals[MAX_SURFACE_POOLS]; +static int pool_count; +static CoreSurfacePool *pool_array[MAX_SURFACE_POOLS]; +static unsigned int pool_order[MAX_SURFACE_POOLS]; + +/**********************************************************************************************************************/ + +static inline const SurfacePoolFuncs * +get_funcs( const CoreSurfacePool *pool ) +{ + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + + D_ASSERT( pool->pool_id >= 0 ); + D_ASSERT( pool->pool_id < MAX_SURFACE_POOLS ); + D_ASSERT( pool_funcs[pool->pool_id] != NULL ); + + /* Return function table of the pool. */ + return pool_funcs[pool->pool_id]; +} + +static inline void * +get_local( const CoreSurfacePool *pool ) +{ + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + + D_ASSERT( pool->pool_id >= 0 ); + D_ASSERT( pool->pool_id < MAX_SURFACE_POOLS ); + + /* Return local data of the pool. */ + return pool_locals[pool->pool_id]; +} + +/**********************************************************************************************************************/ + +static DFBResult init_pool( CoreDFB *core, + CoreSurfacePool *pool, + const SurfacePoolFuncs *funcs ); + +/**********************************************************************************************************************/ + +static void insert_pool_local( CoreSurfacePool *pool ); +static void remove_pool_local( CoreSurfacePoolID pool_id ); + +/**********************************************************************************************************************/ + +static void remove_allocation( CoreSurfacePool *pool, + CoreSurfaceBuffer *buffer, + CoreSurfaceAllocation *allocation ); + +static DFBResult backup_allocation( CoreSurfacePool *pool, + CoreSurfaceBuffer *buffer, + CoreSurfaceAllocation *allocation ); + +/**********************************************************************************************************************/ + +DFBResult +dfb_surface_pool_initialize( CoreDFB *core, + const SurfacePoolFuncs *funcs, + CoreSurfacePool **ret_pool ) +{ + DFBResult ret; + CoreSurfacePool *pool; + FusionSHMPoolShared *shmpool; + + D_DEBUG_AT( Core_SurfacePool, "%s( %p )\n", __FUNCTION__, funcs ); + + D_ASSERT( core != NULL ); + D_ASSERT( funcs != NULL ); + D_ASSERT( ret_pool != NULL ); + + /* Check against pool limit. */ + if (pool_count == MAX_SURFACE_POOLS) { + D_ERROR( "Core/SurfacePool: Maximum number of pools (%d) reached!\n", MAX_SURFACE_POOLS ); + return DFB_LIMITEXCEEDED; + } + + D_ASSERT( pool_funcs[pool_count] == NULL ); + + shmpool = dfb_core_shmpool( core ); + + /* Allocate pool structure. */ + pool = SHCALLOC( shmpool, 1, sizeof(CoreSurfacePool) ); + if (!pool) + return D_OOSHM(); + + /* Assign a pool ID. */ + pool->pool_id = pool_count++; + + /* Remember shared memory pool. */ + pool->shmpool = shmpool; + + /* Set function table of the pool. */ + pool_funcs[pool->pool_id] = funcs; + + /* Add to global pool list. */ + pool_array[pool->pool_id] = pool; + + D_MAGIC_SET( pool, CoreSurfacePool ); + + ret = init_pool( core, pool, funcs ); + if (ret) { + pool_funcs[pool->pool_id] = NULL; + pool_array[pool->pool_id] = NULL; + pool_count--; + D_MAGIC_CLEAR( pool ); + SHFREE( shmpool, pool ); + return ret; + } + + /* Set default backup pool being the shared memory surface pool */ + if (!pool->backup && pool_count > 1) + pool->backup = pool_array[0]; + + /* Insert new pool into priority order */ + insert_pool_local( pool ); + + /* Return the new pool. */ + *ret_pool = pool; + + return DFB_OK; +} + +DFBResult +dfb_surface_pool_join( CoreDFB *core, + CoreSurfacePool *pool, + const SurfacePoolFuncs *funcs ) +{ + DFBResult ret; + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + + D_DEBUG_AT( Core_SurfacePool, "%s( %p [%d], %p )\n", __FUNCTION__, pool, pool->pool_id, funcs ); + + D_ASSERT( core != NULL ); + D_ASSERT( funcs != NULL ); + + D_ASSERT( pool->pool_id < MAX_SURFACE_POOLS ); + D_ASSERT( pool->pool_id == pool_count ); + D_ASSERT( pool_funcs[pool->pool_id] == NULL ); + + /* Enforce same order as initialization to be used during join. */ + if (pool->pool_id != pool_count) { + D_ERROR( "Core/SurfacePool: Wrong order of joining pools, got %d, should be %d!\n", + pool->pool_id, pool_count ); + return DFB_BUG; + } + + /* Allocate local pool data. */ + if (pool->pool_local_data_size && + !(pool_locals[pool->pool_id] = D_CALLOC( 1, pool->pool_local_data_size ))) + return D_OOM(); + + /* Set function table of the pool. */ + pool_funcs[pool->pool_id] = funcs; + + /* Add to global pool list. */ + pool_array[pool->pool_id] = pool; + + /* Adjust pool count. */ + if (pool_count < pool->pool_id + 1) + pool_count = pool->pool_id + 1; + + funcs = get_funcs( pool ); + + if (funcs->JoinPool) { + ret = funcs->JoinPool( core, pool, pool->data, get_local(pool), dfb_system_data() ); + if (ret) { + D_DERROR( ret, "Core/SurfacePool: Joining '%s' failed!\n", pool->desc.name ); + + if (pool_locals[pool->pool_id]) { + D_FREE( pool_locals[pool->pool_id] ); + pool_locals[pool->pool_id] = NULL; + } + + pool_count--; + + return ret; + } + } + + /* Insert new pool into priority order */ + insert_pool_local( pool ); + + return DFB_OK; +} + +DFBResult +dfb_surface_pool_destroy( CoreSurfacePool *pool ) +{ + CoreSurfacePoolID pool_id; + const SurfacePoolFuncs *funcs; + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + + pool_id = pool->pool_id; + + D_DEBUG_AT( Core_SurfacePool, "%s( %p, '%s' [%d] )\n", __FUNCTION__, pool, pool->desc.name, pool_id ); + + D_ASSERT( pool->pool_id >= 0 ); + D_ASSERT( pool_id < MAX_SURFACE_POOLS ); + D_ASSERT( pool_array[pool_id] == pool ); + + funcs = get_funcs( pool ); + + if (funcs->DestroyPool) + funcs->DestroyPool( pool, pool->data, get_local(pool) ); + + /* Free shared pool data. */ + if (pool->data) + SHFREE( pool->shmpool, pool->data ); + + /* Free local pool data and remove from lists */ + remove_pool_local( pool_id ); + + fusion_skirmish_destroy( &pool->lock ); + + fusion_vector_destroy( &pool->allocs ); + + D_MAGIC_CLEAR( pool ); + + SHFREE( pool->shmpool, pool ); + + return DFB_OK; +} + +DFBResult +dfb_surface_pool_leave( CoreSurfacePool *pool ) +{ + CoreSurfacePoolID pool_id; + const SurfacePoolFuncs *funcs; + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + + pool_id = pool->pool_id; + + D_DEBUG_AT( Core_SurfacePool, "%s( %p, '%s' [%d] )\n", __FUNCTION__, pool, pool->desc.name, pool_id ); + + D_ASSERT( pool->pool_id >= 0 ); + D_ASSERT( pool_id < MAX_SURFACE_POOLS ); + D_ASSERT( pool_array[pool_id] == pool ); + + funcs = get_funcs( pool ); + + if (funcs->LeavePool) + funcs->LeavePool( pool, pool->data, get_local(pool) ); + + /* Free local pool data and remove from lists */ + remove_pool_local( pool_id ); + + return DFB_OK; +} + +/**********************************************************************************************************************/ + +DFBResult +dfb_surface_pools_negotiate( CoreSurfaceBuffer *buffer, + CoreSurfaceAccessorID accessor, + CoreSurfaceAccessFlags access, + CoreSurfacePool **ret_pools, + unsigned int max_pools, + unsigned int *ret_num ) +{ + DFBResult ret; + int i; + unsigned int num = 0; + CoreSurface *surface; + CoreSurfaceTypeFlags type; + unsigned int free_count = 0; + CoreSurfacePool *free_pools[pool_count]; + unsigned int oom_count = 0; + CoreSurfacePool *oom_pools[pool_count]; + + D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); + + D_DEBUG_AT( Core_SurfacePool, "%s( %p [%s], 0x%02x, 0x%02x, max %d )\n", __FUNCTION__, + buffer, dfb_pixelformat_name( buffer->format ), accessor, access, max_pools ); + + D_ASSERT( ret_pools != NULL ); + D_ASSERT( max_pools > 0 ); + D_ASSERT( ret_num != NULL ); + + surface = buffer->surface; + D_MAGIC_ASSERT( surface, CoreSurface ); + FUSION_SKIRMISH_ASSERT( &surface->lock ); + + D_ASSERT( accessor >= CSAID_CPU ); + D_ASSUME( accessor < _CSAID_NUM ); + if (accessor >= CSAID_ANY) { + D_UNIMPLEMENTED(); + return DFB_UNIMPLEMENTED; + } + + if (accessor < 0 || accessor >= _CSAID_NUM) + return DFB_INVARG; + + type = surface->type & ~(CSTF_INTERNAL | CSTF_EXTERNAL); + + switch (buffer->policy) { + case CSP_SYSTEMONLY: + type |= CSTF_INTERNAL; + break; + + case CSP_VIDEOONLY: + type |= CSTF_EXTERNAL; + break; + + default: + break; + } + + D_DEBUG_AT( Core_SurfacePool, " -> 0x%02x 0x%03x required\n", access, type ); + + for (i=0; i= 0 ); + D_ASSERT( pool_order[i] < pool_count ); + + pool = pool_array[pool_order[i]]; + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + + if (D_FLAGS_ARE_SET( pool->desc.access[accessor], access ) && + D_FLAGS_ARE_SET( pool->desc.types, type )) + { + const SurfacePoolFuncs *funcs; + + D_DEBUG_AT( Core_SurfacePool, " -> [%d] 0x%02x 0x%03x (%d) [%s]\n", pool->pool_id, + pool->desc.caps, pool->desc.types, pool->desc.priority, pool->desc.name ); + + funcs = get_funcs( pool ); + + ret = funcs->TestConfig ? funcs->TestConfig( pool, pool->data, get_local(pool), + buffer, &surface->config ) : DFB_OK; + switch (ret) { + case DFB_OK: + D_DEBUG_AT( Core_SurfacePool, " => OK\n" ); + free_pools[free_count++] = pool; + break; + + case DFB_NOVIDEOMEMORY: + D_DEBUG_AT( Core_SurfacePool, " => OUT OF MEMORY\n" ); + oom_pools[oom_count++] = pool; + break; + + default: + continue; + } + } + } + + D_DEBUG_AT( Core_SurfacePool, " => %d pools available\n", free_count ); + D_DEBUG_AT( Core_SurfacePool, " => %d pools out of memory\n", oom_count ); + + for (i=0; isurface; + D_MAGIC_ASSERT( surface, CoreSurface ); + FUSION_SKIRMISH_ASSERT( &surface->lock ); + + D_DEBUG_AT( Core_SurfacePool, "%s( %p, 0x%x )\n", __FUNCTION__, buffer, access ); + + D_DEBUG_AT( Core_SurfacePool, " -> %dx%d %s - %s%s%s%s%s%s%s%s\n", + surface->config.size.w, surface->config.size.h, + dfb_pixelformat_name( surface->config.format ), + (surface->type & CSTF_SHARED) ? "SHARED" : "PRIVATE", + (surface->type & CSTF_LAYER) ? " LAYER" : "", + (surface->type & CSTF_WINDOW) ? " WINDOW" : "", + (surface->type & CSTF_CURSOR) ? " CURSOR" : "", + (surface->type & CSTF_FONT) ? " FONT" : "", + (surface->type & CSTF_INTERNAL) ? " INTERNAL" : "", + (surface->type & CSTF_EXTERNAL) ? " EXTERNAL" : "", + (surface->type & CSTF_PREALLOCATED) ? " PREALLOCATED" : "" ); + + D_ASSERT( accessor >= CSAID_CPU ); + D_ASSUME( accessor < _CSAID_NUM ); + if (accessor >= CSAID_ANY) { + D_UNIMPLEMENTED(); + return DFB_UNIMPLEMENTED; + } + + if (accessor < 0 || accessor >= _CSAID_NUM) + return DFB_INVARG; + + /* Build a list of possible pools being free or out of memory */ + ret = dfb_surface_pools_negotiate( buffer, accessor, access, pools, pool_count, &num_pools ); + if (ret && ret != DFB_NOVIDEOMEMORY) { + D_DEBUG_AT( Core_SurfacePool, " -> NEGOTIATION FAILED! (%s)\n", DirectFBErrorString( ret ) ); + return ret; + } + + /* Try to do the allocation in one of the pools */ + for (i=0; i Allocation in '%s' failed!\n", pool->desc.name ); + + /* ...forget about the pool for now */ + pools[i] = NULL; + } + } + + /* Check if none of the pools could do the allocation */ + if (!allocation) { + /* Try to find a pool with "older" allocations to muck out */ + for (i=0; i FAILED!\n" ); + return DFB_FAILURE; + } + + CORE_SURFACE_ALLOCATION_ASSERT( allocation ); + + D_DEBUG_AT( Core_SurfacePool, " -> %p\n", allocation ); + + *ret_allocation = allocation; + + return DFB_OK; +} + +/**********************************************************************************************************************/ + +DFBResult +dfb_surface_pool_allocate( CoreSurfacePool *pool, + CoreSurfaceBuffer *buffer, + CoreSurfaceAllocation **ret_allocation ) +{ + DFBResult ret; + int i; + CoreSurface *surface; + CoreSurfaceAllocation *allocation = NULL; + const SurfacePoolFuncs *funcs; + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); + + D_DEBUG_AT( Core_SurfacePool, "%s( %p [%d], %p )\n", __FUNCTION__, pool, pool->pool_id, buffer ); + + D_ASSERT( ret_allocation != NULL ); + + surface = buffer->surface; + D_MAGIC_ASSERT( surface, CoreSurface ); + FUSION_SKIRMISH_ASSERT( &surface->lock ); + + funcs = get_funcs( pool ); + + D_ASSERT( funcs->AllocateBuffer != NULL ); + + allocation = SHCALLOC( pool->shmpool, 1, sizeof(CoreSurfaceAllocation) ); + if (!allocation) + return D_OOSHM(); + + allocation->buffer = buffer; + allocation->surface = surface; + allocation->pool = pool; + allocation->access = pool->desc.access; + + if (pool->alloc_data_size) { + allocation->data = SHCALLOC( pool->shmpool, 1, pool->alloc_data_size ); + if (!allocation->data) { + ret = D_OOSHM(); + goto error; + } + } + + D_MAGIC_SET( allocation, CoreSurfaceAllocation ); + + if (fusion_skirmish_prevail( &pool->lock )) { + ret = DFB_FUSION; + goto error; + } + + if (dfb_config->warn.flags & DCWF_ALLOCATE_BUFFER && + dfb_config->warn.allocate_buffer.min_size.w <= surface->config.size.w && + dfb_config->warn.allocate_buffer.min_size.h <= surface->config.size.h) + D_WARN( "allocate-buffer %4dx%4d %6s, surface-caps 0x%08x", + surface->config.size.w, surface->config.size.h, dfb_pixelformat_name(buffer->format), + surface->config.caps ); + + ret = funcs->AllocateBuffer( pool, pool->data, get_local(pool), buffer, allocation, allocation->data ); + if (ret) { + D_DEBUG_AT( Core_SurfacePool, " -> %s\n", DirectFBErrorString( ret ) ); + D_MAGIC_CLEAR( allocation ); + fusion_skirmish_dismiss( &pool->lock ); + goto error; + } + + D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation ); + + if (allocation->flags & CSALF_ONEFORALL) { + for (i=0; inum_buffers; i++) { + buffer = surface->buffers[i]; + + D_ASSUME( fusion_vector_is_empty( &buffer->allocs ) ); + + D_DEBUG_AT( Core_SurfacePool, " -> %p (%d)\n", allocation, i ); + fusion_vector_add( &buffer->allocs, allocation ); + fusion_vector_add( &pool->allocs, allocation ); + } + } + else { + D_DEBUG_AT( Core_SurfacePool, " -> %p\n", allocation ); + fusion_vector_add( &buffer->allocs, allocation ); + fusion_vector_add( &pool->allocs, allocation ); + } + + direct_serial_init( &allocation->serial ); + + fusion_skirmish_dismiss( &pool->lock ); + + CORE_SURFACE_ALLOCATION_ASSERT( allocation ); + + *ret_allocation = allocation; + + return DFB_OK; + +error: + if (allocation->data) + SHFREE( pool->shmpool, allocation->data ); + + SHFREE( pool->shmpool, allocation ); + + return ret; +} + +DFBResult +dfb_surface_pool_deallocate( CoreSurfacePool *pool, + CoreSurfaceAllocation *allocation ) +{ + DFBResult ret; + int i; + const SurfacePoolFuncs *funcs; + CoreSurfaceBuffer *buffer; + CoreSurface *surface; + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + CORE_SURFACE_ALLOCATION_ASSERT( allocation ); + + D_DEBUG_AT( Core_SurfacePool, "%s( %p [%d], %p )\n", __FUNCTION__, pool, pool->pool_id, allocation ); + + D_ASSERT( pool == allocation->pool ); + + buffer = allocation->buffer; + D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); + + surface = buffer->surface; + D_MAGIC_ASSERT( surface, CoreSurface ); + FUSION_SKIRMISH_ASSERT( &surface->lock ); + + funcs = get_funcs( pool ); + + D_ASSERT( funcs->DeallocateBuffer != NULL ); + + if (fusion_skirmish_prevail( &pool->lock )) + return DFB_FUSION; + + ret = funcs->DeallocateBuffer( pool, pool->data, get_local(pool), allocation->buffer, allocation, allocation->data ); + if (ret) { + D_DERROR( ret, "Core/SurfacePool: Could not deallocate buffer!\n" ); + fusion_skirmish_dismiss( &pool->lock ); + return ret; + } + + if (allocation->flags & CSALF_ONEFORALL) { + for (i=0; inum_buffers; i++) + remove_allocation( pool, surface->buffers[i], allocation ); + } + else + remove_allocation( pool, buffer, allocation ); + + fusion_skirmish_dismiss( &pool->lock ); + + if (allocation->data) + SHFREE( pool->shmpool, allocation->data ); + + direct_serial_deinit( &allocation->serial ); + + D_MAGIC_CLEAR( allocation ); + + SHFREE( pool->shmpool, allocation ); + + return DFB_OK; +} + +DFBResult +dfb_surface_pool_displace( CoreSurfacePool *pool, + CoreSurfaceBuffer *buffer, + CoreSurfaceAllocation **ret_allocation ) +{ + DFBResult ret, ret_lock = DFB_OK; + int i, retries = 3; + CoreSurface *surface; + CoreSurfaceAllocation *allocation; + const SurfacePoolFuncs *funcs; + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); + + D_DEBUG_AT( Core_SurfacePool, "%s( %p [%d], %p )\n", __FUNCTION__, pool, pool->pool_id, buffer ); + + D_ASSERT( ret_allocation != NULL ); + + surface = buffer->surface; + D_MAGIC_ASSERT( surface, CoreSurface ); + FUSION_SKIRMISH_ASSERT( &surface->lock ); + + funcs = get_funcs( pool ); + + if (fusion_skirmish_prevail( &pool->lock )) + return DFB_FUSION; + + /* Check for integrated method to muck out "older" allocations for a new one */ + if (funcs->MuckOut) { + ret = funcs->MuckOut( pool, pool->data, get_local(pool), buffer ); + if (ret) { + fusion_skirmish_dismiss( &pool->lock ); + return ret; + } + } + else { + /* Or take the generic approach via allocation list */ + D_UNIMPLEMENTED(); + } + + /* FIXME: Solve potential dead lock, until then do a few retries... */ +fixme_retry: + fusion_vector_foreach (allocation, i, pool->allocs) { + CORE_SURFACE_ALLOCATION_ASSERT( allocation ); + + if (allocation->flags & CSALF_MUCKOUT) { + CoreSurface *alloc_surface; + CoreSurfaceBuffer *alloc_buffer; + + alloc_buffer = allocation->buffer; + D_MAGIC_ASSERT( alloc_buffer, CoreSurfaceBuffer ); + + alloc_surface = alloc_buffer->surface; + D_MAGIC_ASSERT( alloc_surface, CoreSurface ); + + D_DEBUG_AT( Core_SurfacePool, " <= %p %5dk, %lu\n", + allocation, allocation->size / 1024, allocation->offset ); + + /* FIXME: Solve potential dead lock, until then only try to lock... */ + ret = dfb_surface_trylock( alloc_surface ); + if (ret) { + D_WARN( "could not lock surface (%s)", DirectFBErrorString(ret) ); + ret_lock = ret; + continue; + } + + /* Ensure mucked out allocation is backed up in another pool */ + ret = backup_allocation( pool, buffer, allocation ); + if (ret) { + D_WARN( "could not backup allocation (%s)", DirectFBErrorString(ret) ); + dfb_surface_unlock( alloc_surface ); + goto error_cleanup; + } + + /* Deallocate mucked out allocation */ + dfb_surface_pool_deallocate( pool, allocation ); + i--; + + dfb_surface_unlock( alloc_surface ); + } + } + + /* FIXME: Solve potential dead lock, until then do a few retries... */ + if (ret_lock) { + if (retries--) + goto fixme_retry; + + ret = DFB_LOCKED; + + goto error_cleanup; + } + else + ret = dfb_surface_pool_allocate( pool, buffer, ret_allocation ); + + fusion_skirmish_dismiss( &pool->lock ); + + return ret; + + +error_cleanup: + fusion_vector_foreach (allocation, i, pool->allocs) { + CORE_SURFACE_ALLOCATION_ASSERT( allocation ); + + if (allocation->flags & CSALF_MUCKOUT) + allocation->flags &= ~CSALF_MUCKOUT; + } + + fusion_skirmish_dismiss( &pool->lock ); + + return ret; +} + +DFBResult +dfb_surface_pool_lock( CoreSurfacePool *pool, + CoreSurfaceAllocation *allocation, + CoreSurfaceBufferLock *lock ) +{ + DFBResult ret; + const SurfacePoolFuncs *funcs; + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + + D_DEBUG_AT( Core_SurfPoolLock, "%s( %p [%d], %p )\n", __FUNCTION__, pool, pool->pool_id, allocation ); + + CORE_SURFACE_ALLOCATION_ASSERT( allocation ); + CORE_SURFACE_BUFFER_LOCK_ASSERT( lock ); + D_ASSERT( lock->buffer == NULL ); + + D_ASSERT( pool == allocation->pool ); + + funcs = get_funcs( pool ); + + D_ASSERT( funcs->Lock != NULL ); + + lock->allocation = allocation; + lock->buffer = allocation->buffer; + + ret = funcs->Lock( pool, pool->data, get_local(pool), allocation, allocation->data, lock ); + if (ret) { + D_DERROR( ret, "Core/SurfacePool: Could not lock allocation!\n" ); + dfb_surface_buffer_lock_reset( lock ); + return ret; + } + + CORE_SURFACE_BUFFER_LOCK_ASSERT( lock ); + D_ASSERT( lock->buffer != NULL ); + + return DFB_OK; +} + +DFBResult +dfb_surface_pool_unlock( CoreSurfacePool *pool, + CoreSurfaceAllocation *allocation, + CoreSurfaceBufferLock *lock ) +{ + DFBResult ret; + const SurfacePoolFuncs *funcs; + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + + D_DEBUG_AT( Core_SurfPoolLock, "%s( %p [%d], %p )\n", __FUNCTION__, pool, pool->pool_id, allocation ); + + CORE_SURFACE_ALLOCATION_ASSERT( allocation ); + CORE_SURFACE_BUFFER_LOCK_ASSERT( lock ); + D_ASSERT( lock->buffer != NULL ); + + D_ASSERT( pool == allocation->pool ); + + funcs = get_funcs( pool ); + + D_ASSERT( funcs->Unlock != NULL ); + + ret = funcs->Unlock( pool, pool->data, get_local(pool), allocation, allocation->data, lock ); + if (ret) { + D_DERROR( ret, "Core/SurfacePool: Could not unlock allocation!\n" ); + return ret; + } + + CORE_SURFACE_BUFFER_LOCK_ASSERT( lock ); + D_ASSERT( lock->buffer != NULL ); + + dfb_surface_buffer_lock_reset( lock ); + + return DFB_OK; +} + +DFBResult +dfb_surface_pool_read( CoreSurfacePool *pool, + CoreSurfaceAllocation *allocation, + void *data, + int pitch, + const DFBRectangle *rect ) +{ + DFBResult ret; + const SurfacePoolFuncs *funcs; + CoreSurface *surface; + DFBRectangle area; + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + + D_DEBUG_AT( Core_SurfPoolLock, "%s( %p [%d], %p )\n", __FUNCTION__, pool, pool->pool_id, allocation ); + + CORE_SURFACE_ALLOCATION_ASSERT( allocation ); + D_ASSERT( data != NULL ); + D_ASSERT( pitch >= 0 ); + DFB_RECTANGLE_ASSERT_IF( rect ); + + D_ASSERT( pool == allocation->pool ); + + funcs = get_funcs( pool ); + D_ASSERT( funcs != NULL ); + + if (!funcs->Read) + return DFB_UNSUPPORTED; + + surface = allocation->surface; + D_MAGIC_ASSERT( surface, CoreSurface ); + + area.x = 0; + area.y = 0; + area.w = surface->config.size.w; + area.h = surface->config.size.h; + + if (rect && !dfb_rectangle_intersect( &area, rect )) + return DFB_INVAREA; + + ret = funcs->Read( pool, pool->data, get_local(pool), allocation, allocation->data, data, pitch, &area ); + if (ret) + D_DERROR( ret, "Core/SurfacePool: Could not read from allocation!\n" ); + + return ret; +} + +DFBResult +dfb_surface_pool_write( CoreSurfacePool *pool, + CoreSurfaceAllocation *allocation, + const void *data, + int pitch, + const DFBRectangle *rect ) +{ + DFBResult ret; + const SurfacePoolFuncs *funcs; + CoreSurface *surface; + DFBRectangle area; + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + + D_DEBUG_AT( Core_SurfPoolLock, "%s( %p [%d], %p )\n", __FUNCTION__, pool, pool->pool_id, allocation ); + + CORE_SURFACE_ALLOCATION_ASSERT( allocation ); + D_ASSERT( data != NULL ); + D_ASSERT( pitch >= 0 ); + DFB_RECTANGLE_ASSERT_IF( rect ); + + D_ASSERT( pool == allocation->pool ); + + funcs = get_funcs( pool ); + D_ASSERT( funcs != NULL ); + + if (!funcs->Write) + return DFB_UNSUPPORTED; + + surface = allocation->surface; + D_MAGIC_ASSERT( surface, CoreSurface ); + + area.x = 0; + area.y = 0; + area.w = surface->config.size.w; + area.h = surface->config.size.h; + + if (rect && !dfb_rectangle_intersect( &area, rect )) + return DFB_INVAREA; + + ret = funcs->Write( pool, pool->data, get_local(pool), allocation, allocation->data, data, pitch, &area ); + if (ret) + D_DERROR( ret, "Core/SurfacePool: Could not write to allocation!\n" ); + + return ret; +} + +DFBResult +dfb_surface_pool_enumerate ( CoreSurfacePool *pool, + CoreSurfaceAllocCallback callback, + void *ctx ) +{ + int i; + CoreSurfaceAllocation *allocation; + + D_DEBUG_AT( Core_SurfacePool, "%s( %p, %p, %p )\n", __FUNCTION__, pool, callback, ctx ); + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + D_ASSERT( callback != NULL ); + + fusion_vector_foreach (allocation, i, pool->allocs) { + if (callback( allocation, ctx ) == DFENUM_CANCEL) + break; + } + + return DFB_OK; +} + +/**********************************************************************************************************************/ + +static DFBResult +init_pool( CoreDFB *core, + CoreSurfacePool *pool, + const SurfacePoolFuncs *funcs ) +{ + DFBResult ret; + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + D_ASSERT( funcs != NULL ); + D_ASSERT( funcs->InitPool != NULL ); + + D_DEBUG_AT( Core_SurfacePool, "%s( %p, %p )\n", __FUNCTION__, pool, funcs ); + + if (funcs->PoolDataSize) + pool->pool_data_size = funcs->PoolDataSize(); + + if (funcs->PoolLocalDataSize) + pool->pool_local_data_size = funcs->PoolLocalDataSize(); + + if (funcs->AllocationDataSize) + pool->alloc_data_size = funcs->AllocationDataSize(); + + /* Allocate shared pool data. */ + if (pool->pool_data_size) { + pool->data = SHCALLOC( pool->shmpool, 1, pool->pool_data_size ); + if (!pool->data) + return D_OOSHM(); + } + + /* Allocate local pool data. */ + if (pool->pool_local_data_size && + !(pool_locals[pool->pool_id] = D_CALLOC( 1, pool->pool_local_data_size ))) + { + SHFREE( pool->shmpool, pool->data ); + return D_OOM(); + } + + fusion_vector_init( &pool->allocs, 4, pool->shmpool ); + + ret = funcs->InitPool( core, pool, pool->data, get_local(pool), dfb_system_data(), &pool->desc ); + if (ret) { + D_DERROR( ret, "Core/SurfacePool: Initializing '%s' failed!\n", pool->desc.name ); + + if (pool_locals[pool->pool_id]) { + D_FREE( pool_locals[pool->pool_id] ); + pool_locals[pool->pool_id] = NULL; + } + if (pool->data) { + SHFREE( pool->shmpool, pool->data ); + pool->data = NULL; + } + return ret; + } + + fusion_skirmish_init( &pool->lock, pool->desc.name, dfb_core_world(core) ); + + return DFB_OK; +} + +static void +insert_pool_local( CoreSurfacePool *pool ) +{ + int i, n; + + for (i=0; i= 0 ); + D_ASSERT( pool_order[i] < pool_count-1 ); + + D_MAGIC_ASSERT( pool_array[pool_order[i]], CoreSurfacePool ); + + if (pool_array[pool_order[i]]->desc.priority < pool->desc.priority) + break; + } + + for (n=pool_count-1; n>i; n--) { + D_ASSERT( pool_order[n-1] >= 0 ); + D_ASSERT( pool_order[n-1] < pool_count-1 ); + + D_MAGIC_ASSERT( pool_array[pool_order[n-1]], CoreSurfacePool ); + + pool_order[n] = pool_order[n-1]; + } + + pool_order[n] = pool_count - 1; + +#if D_DEBUG_ENABLED + for (i=0; i [%d] %p - '%s' [%d] (%d), %p\n", + (i == n) ? '=' : '-', i, pool_array[pool_order[i]], pool_array[pool_order[i]]->desc.name, + pool_array[pool_order[i]]->pool_id, pool_array[pool_order[i]]->desc.priority, + pool_funcs[pool_order[i]] ); + D_ASSERT( pool_order[i] == pool_array[pool_order[i]]->pool_id ); + } +#endif +} + +static void +remove_pool_local( CoreSurfacePoolID pool_id ) +{ + int i; + + /* Free local pool data. */ + if (pool_locals[pool_id]) { + D_FREE( pool_locals[pool_id] ); + pool_locals[pool_id] = NULL; + } + + /* Erase entries of the pool. */ + pool_array[pool_id] = NULL; + pool_funcs[pool_id] = NULL; + + while (pool_count > 0 && !pool_array[pool_count-1]) { + pool_count--; + + for (i=0; isurface, CoreSurface ); + FUSION_SKIRMISH_ASSERT( &buffer->surface->lock ); + FUSION_SKIRMISH_ASSERT( &pool->lock ); + D_ASSERT( pool == allocation->pool ); + + /* Lookup indices within vectors */ + index_buffer = fusion_vector_index_of( &buffer->allocs, allocation ); + index_pool = fusion_vector_index_of( &pool->allocs, allocation ); + + D_ASSERT( index_buffer >= 0 ); + D_ASSERT( index_pool >= 0 ); + + /* Remove allocation from buffer and pool */ + fusion_vector_remove( &buffer->allocs, index_buffer ); + fusion_vector_remove( &pool->allocs, index_pool ); + + /* Update 'written' allocation pointer of buffer */ + if (buffer->written == allocation) { + /* Reset pointer first */ + buffer->written = NULL; + + /* Iterate through remaining allocations */ + fusion_vector_foreach (allocation, index_buffer, buffer->allocs) { + CORE_SURFACE_ALLOCATION_ASSERT( allocation ); + + /* Check if allocation is up to date and set it as 'written' allocation */ + if (direct_serial_check( &allocation->serial, &buffer->serial )) { + buffer->written = allocation; + break; + } + } + } + + /* Reset 'read' allocation pointer of buffer */ + if (buffer->read == allocation) + buffer->read = NULL; +} + +static DFBResult +backup_allocation( CoreSurfacePool *pool, + CoreSurfaceBuffer *buffer, + CoreSurfaceAllocation *allocation ) +{ + DFBResult ret = DFB_OK; + int i; + CoreSurfaceAllocation *backup = NULL; + + D_DEBUG_AT( Core_SurfacePool, "%s( %p, %p )\n", __FUNCTION__, pool, allocation ); + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); + CORE_SURFACE_ALLOCATION_ASSERT( allocation ); + D_MAGIC_ASSERT( buffer->surface, CoreSurface ); + FUSION_SKIRMISH_ASSERT( &buffer->surface->lock ); + FUSION_SKIRMISH_ASSERT( &pool->lock ); + D_ASSERT( pool == allocation->pool ); + + /* Check if allocation is the only up to date (requiring a backup) */ + if (direct_serial_check( &allocation->serial, &buffer->serial )) { + CoreSurfacePool *backup_pool = pool->backup; + + /* First check if any of the existing allocations is up to date */ + fusion_vector_foreach (backup, i, buffer->allocs) { + D_MAGIC_ASSERT( backup, CoreSurfaceAllocation ); + D_MAGIC_ASSERT( backup->pool, CoreSurfacePool ); + + if (backup->pool != pool && direct_serial_check( &backup->serial, &buffer->serial )) { + D_DEBUG_AT( Core_SurfacePool, " -> up to date in '%s'\n", backup->pool->desc.name ); + return DFB_OK; + } + } + + /* Try to update one of the existing allocations */ + fusion_vector_foreach (backup, i, buffer->allocs) { + D_MAGIC_ASSERT( backup, CoreSurfaceAllocation ); + D_MAGIC_ASSERT( backup->pool, CoreSurfacePool ); + + if (backup->pool != pool && dfb_surface_allocation_update( backup, CSAF_NONE ) == DFB_OK) { + D_DEBUG_AT( Core_SurfacePool, " -> updated in '%s'\n", backup->pool->desc.name ); + return DFB_OK; + } + } + + /* Try the designated backup pool and theirs if failing */ + while (backup_pool) { + D_MAGIC_ASSERT( backup_pool, CoreSurfacePool ); + + D_DEBUG_AT( Core_SurfacePool, " -> allocating in '%s'\n", backup_pool->desc.name ); + + /* Allocate in backup pool */ + ret = dfb_surface_pool_allocate( backup_pool, buffer, &backup ); + if (ret == DFB_OK) { + /* Update new allocation */ + ret = dfb_surface_allocation_update( backup, CSAF_NONE ); + if (ret) { + D_DEBUG_AT( Core_SurfacePool, " -> update failed! (%s)\n", DirectFBErrorString(ret) ); + dfb_surface_pool_deallocate( backup_pool, backup ); + backup = NULL; + } + else + return DFB_OK; + } + else + D_DEBUG_AT( Core_SurfacePool, " -> allocation failed! (%s)\n", DirectFBErrorString(ret) ); + + backup_pool = backup_pool->backup; + } + } + else + D_DEBUG_AT( Core_SurfacePool, " -> not up to date anyhow\n" ); + + return ret; +} + diff --git a/Source/DirectFB/src/core/surface_pool.h b/Source/DirectFB/src/core/surface_pool.h new file mode 100755 index 0000000..fc049e0 --- /dev/null +++ b/Source/DirectFB/src/core/surface_pool.h @@ -0,0 +1,272 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __CORE__SURFACE_POOL_H__ +#define __CORE__SURFACE_POOL_H__ + +#include + +#include + +#include +#include + + +typedef enum { + CSPCAPS_NONE = 0x00000000, + + CSPCAPS_PHYSICAL = 0x00000001, /* pool provides physical address to buffer */ + CSPCAPS_VIRTUAL = 0x00000002, /* pool provides virtual address to buffer */ + + CSPCAPS_ALL = 0x00000003 +} CoreSurfacePoolCapabilities; + +typedef enum { + CSPP_DEFAULT, + CSPP_PREFERED, + CSPP_ULTIMATE +} CoreSurfacePoolPriority; + +/* + * Increase this number when changes result in binary incompatibility! + */ +#define DFB_SURFACE_POOL_ABI_VERSION 1 + +#define DFB_SURFACE_POOL_DESC_NAME_LENGTH 44 + + +typedef struct { + CoreSurfacePoolCapabilities caps; + CoreSurfaceAccessFlags access[_CSAID_NUM]; + CoreSurfaceTypeFlags types; + CoreSurfacePoolPriority priority; + char name[DFB_SURFACE_POOL_DESC_NAME_LENGTH]; + unsigned long size; +} CoreSurfacePoolDescription; + + +typedef struct { + int (*PoolDataSize)( void ); + int (*PoolLocalDataSize)( void ); + int (*AllocationDataSize)( void ); + + /* + * Pool init/destroy + */ + DFBResult (*InitPool) ( CoreDFB *core, + CoreSurfacePool *pool, + void *pool_data, + void *pool_local, + void *system_data, + CoreSurfacePoolDescription *ret_desc ); + + DFBResult (*JoinPool) ( CoreDFB *core, + CoreSurfacePool *pool, + void *pool_data, + void *pool_local, + void *system_data ); + + DFBResult (*DestroyPool)( CoreSurfacePool *pool, + void *pool_data, + void *pool_local ); + + DFBResult (*LeavePool) ( CoreSurfacePool *pool, + void *pool_data, + void *pool_local ); + + + + DFBResult (*TestConfig) ( CoreSurfacePool *pool, + void *pool_data, + void *pool_local, + CoreSurfaceBuffer *buffer, + const CoreSurfaceConfig *config ); + /* + * Buffer management + */ + DFBResult (*AllocateBuffer) ( CoreSurfacePool *pool, + void *pool_data, + void *pool_local, + CoreSurfaceBuffer *buffer, + CoreSurfaceAllocation *allocation, + void *alloc_data ); + + DFBResult (*DeallocateBuffer)( CoreSurfacePool *pool, + void *pool_data, + void *pool_local, + CoreSurfaceBuffer *buffer, + CoreSurfaceAllocation *allocation, + void *alloc_data ); + + /* + * Locking + */ + DFBResult (*Lock) ( CoreSurfacePool *pool, + void *pool_data, + void *pool_local, + CoreSurfaceAllocation *allocation, + void *alloc_data, + CoreSurfaceBufferLock *lock ); + + DFBResult (*Unlock)( CoreSurfacePool *pool, + void *pool_data, + void *pool_local, + CoreSurfaceAllocation *allocation, + void *alloc_data, + CoreSurfaceBufferLock *lock ); + + /* + * Read/write + */ + DFBResult (*Read) ( CoreSurfacePool *pool, + void *pool_data, + void *pool_local, + CoreSurfaceAllocation *allocation, + void *alloc_data, + void *destination, + int pitch, + const DFBRectangle *rect ); + + DFBResult (*Write) ( CoreSurfacePool *pool, + void *pool_data, + void *pool_local, + CoreSurfaceAllocation *allocation, + void *alloc_data, + const void *source, + int pitch, + const DFBRectangle *rect ); + + /* + * Muck out + */ + DFBResult (*MuckOut) ( CoreSurfacePool *pool, + void *pool_data, + void *pool_local, + CoreSurfaceBuffer *buffer ); +} SurfacePoolFuncs; + + +struct __DFB_CoreSurfacePool { + int magic; + + FusionSkirmish lock; + + CoreSurfacePoolID pool_id; + + CoreSurfacePoolDescription desc; + + int pool_data_size; + int pool_local_data_size; + int alloc_data_size; + + void *data; + + FusionVector allocs; + + FusionSHMPoolShared *shmpool; + + CoreSurfacePool *backup; +}; + + +typedef DFBEnumerationResult (*CoreSurfacePoolCallback)( CoreSurfacePool *pool, + void *ctx ); + +typedef DFBEnumerationResult (*CoreSurfaceAllocCallback)( CoreSurfaceAllocation *allocation, + void *ctx ); + + + +DFBResult dfb_surface_pools_negotiate( CoreSurfaceBuffer *buffer, + CoreSurfaceAccessorID accessor, + CoreSurfaceAccessFlags access, + CoreSurfacePool **ret_pools, + unsigned int max_pools, + unsigned int *ret_num ); + +DFBResult dfb_surface_pools_enumerate( CoreSurfacePoolCallback callback, + void *ctx ); + +DFBResult dfb_surface_pools_allocate ( CoreSurfaceBuffer *buffer, + CoreSurfaceAccessorID accessor, + CoreSurfaceAccessFlags access, + CoreSurfaceAllocation **ret_allocation ); + + +DFBResult dfb_surface_pool_initialize( CoreDFB *core, + const SurfacePoolFuncs *funcs, + CoreSurfacePool **ret_pool ); + +DFBResult dfb_surface_pool_join ( CoreDFB *core, + CoreSurfacePool *pool, + const SurfacePoolFuncs *funcs ); + +DFBResult dfb_surface_pool_destroy ( CoreSurfacePool *pool ); + +DFBResult dfb_surface_pool_leave ( CoreSurfacePool *pool ); + + + +DFBResult dfb_surface_pool_allocate ( CoreSurfacePool *pool, + CoreSurfaceBuffer *buffer, + CoreSurfaceAllocation **ret_allocation ); + +DFBResult dfb_surface_pool_deallocate( CoreSurfacePool *pool, + CoreSurfaceAllocation *allocation ); + +DFBResult dfb_surface_pool_displace ( CoreSurfacePool *pool, + CoreSurfaceBuffer *buffer, + CoreSurfaceAllocation **ret_allocation ); + +DFBResult dfb_surface_pool_lock ( CoreSurfacePool *pool, + CoreSurfaceAllocation *allocation, + CoreSurfaceBufferLock *lock ); + +DFBResult dfb_surface_pool_unlock ( CoreSurfacePool *pool, + CoreSurfaceAllocation *allocation, + CoreSurfaceBufferLock *lock ); + +DFBResult dfb_surface_pool_read ( CoreSurfacePool *pool, + CoreSurfaceAllocation *allocation, + void *data, + int pitch, + const DFBRectangle *rect ); + +DFBResult dfb_surface_pool_write ( CoreSurfacePool *pool, + CoreSurfaceAllocation *allocation, + const void *data, + int pitch, + const DFBRectangle *rect ); + +DFBResult dfb_surface_pool_enumerate ( CoreSurfacePool *pool, + CoreSurfaceAllocCallback callback, + void *ctx ); + + +#endif + diff --git a/Source/DirectFB/src/core/surface_pool_bridge.c b/Source/DirectFB/src/core/surface_pool_bridge.c new file mode 100755 index 0000000..244ca2d --- /dev/null +++ b/Source/DirectFB/src/core/surface_pool_bridge.c @@ -0,0 +1,531 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +//#define DIRECT_ENABLE_DEBUG + +#include + +#include +#include + +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include + +#include + +#include + + +D_DEBUG_DOMAIN( Core_SurfPoolBridge, "Core/SurfPoolBridge", "DirectFB Core Surface Pool Bridge" ); + +/**********************************************************************************************************************/ + +static const SurfacePoolBridgeFuncs *bridge_funcs[MAX_SURFACE_POOL_BRIDGES]; +static void *bridge_locals[MAX_SURFACE_POOL_BRIDGES]; +static int bridge_count; +static CoreSurfacePoolBridge *bridge_array[MAX_SURFACE_POOL_BRIDGES]; + +/**********************************************************************************************************************/ + +static inline const SurfacePoolBridgeFuncs * +get_funcs( const CoreSurfacePoolBridge *bridge ) +{ + D_MAGIC_ASSERT( bridge, CoreSurfacePoolBridge ); + + D_ASSERT( bridge->bridge_id >= 0 ); + D_ASSERT( bridge->bridge_id < MAX_SURFACE_POOL_BRIDGES ); + D_ASSERT( bridge_funcs[bridge->bridge_id] != NULL ); + + /* Return function table of the bridge. */ + return bridge_funcs[bridge->bridge_id]; +} + +static inline void * +get_local( const CoreSurfacePoolBridge *bridge ) +{ + D_MAGIC_ASSERT( bridge, CoreSurfacePoolBridge ); + + D_ASSERT( bridge->bridge_id >= 0 ); + D_ASSERT( bridge->bridge_id < MAX_SURFACE_POOL_BRIDGES ); + + /* Return local data of the bridge. */ + return bridge_locals[bridge->bridge_id]; +} + +/**********************************************************************************************************************/ + +static DFBResult init_bridge( CoreDFB *core, + CoreSurfacePoolBridge *bridge, + const SurfacePoolBridgeFuncs *funcs, + void *context ); + +/**********************************************************************************************************************/ + +DFBResult +dfb_surface_pool_bridge_initialize( CoreDFB *core, + const SurfacePoolBridgeFuncs *funcs, + void *context, + CoreSurfacePoolBridge **ret_bridge ) +{ + DFBResult ret; + CoreSurfacePoolBridge *bridge; + FusionSHMPoolShared *shmpool; + + D_DEBUG_AT( Core_SurfPoolBridge, "%s( %p, %p )\n", __FUNCTION__, funcs, context ); + + D_ASSERT( core != NULL ); + D_ASSERT( funcs != NULL ); + D_ASSERT( ret_bridge != NULL ); + + /* Check against bridge limit. */ + if (bridge_count == MAX_SURFACE_POOL_BRIDGES) { + D_ERROR( "Core/SurfacePoolBridge: Maximum number of bridges (%d) reached!\n", MAX_SURFACE_POOL_BRIDGES ); + return DFB_LIMITEXCEEDED; + } + + D_ASSERT( bridge_funcs[bridge_count] == NULL ); + + shmpool = dfb_core_shmpool( core ); + + /* Allocate bridge structure. */ + bridge = SHCALLOC( shmpool, 1, sizeof(CoreSurfacePoolBridge) ); + if (!bridge) + return D_OOSHM(); + + /* Assign a bridge ID. */ + bridge->bridge_id = bridge_count++; + + /* Remember shared memory pool. */ + bridge->shmpool = shmpool; + + /* Set function table of the bridge. */ + bridge_funcs[bridge->bridge_id] = funcs; + + /* Add to global bridge list. */ + bridge_array[bridge->bridge_id] = bridge; + + D_MAGIC_SET( bridge, CoreSurfacePoolBridge ); + + ret = init_bridge( core, bridge, funcs, context ); + if (ret) { + bridge_count--; + D_MAGIC_CLEAR( bridge ); + SHFREE( shmpool, bridge ); + return ret; + } + + /* Return the new bridge. */ + *ret_bridge = bridge; + + return DFB_OK; +} + +DFBResult +dfb_surface_pool_bridge_join( CoreDFB *core, + CoreSurfacePoolBridge *bridge, + const SurfacePoolBridgeFuncs *funcs, + void *context ) +{ + DFBResult ret; + + D_MAGIC_ASSERT( bridge, CoreSurfacePoolBridge ); + + D_DEBUG_AT( Core_SurfPoolBridge, "%s( %p [%d], %p, %p )\n", __FUNCTION__, bridge, bridge->bridge_id, funcs, context ); + + D_ASSERT( core != NULL ); + D_ASSERT( funcs != NULL ); + + D_ASSERT( bridge->bridge_id < MAX_SURFACE_POOL_BRIDGES ); + D_ASSERT( bridge->bridge_id == bridge_count ); + D_ASSERT( bridge_funcs[bridge->bridge_id] == NULL ); + + /* Enforce same order as initialization to be used during join. */ + if (bridge->bridge_id != bridge_count) { + D_ERROR( "Core/SurfacePoolBridge: Wrong order of joining bridges, got %d, should be %d!\n", + bridge->bridge_id, bridge_count ); + return DFB_BUG; + } + + /* Allocate local bridge data. */ + if (bridge->bridge_local_data_size && + !(bridge_locals[bridge->bridge_id] = D_CALLOC( 1, bridge->bridge_local_data_size ))) + return D_OOM(); + + /* Set function table of the bridge. */ + bridge_funcs[bridge->bridge_id] = funcs; + + /* Add to global bridge list. */ + bridge_array[bridge->bridge_id] = bridge; + + /* Adjust bridge count. */ + if (bridge_count < bridge->bridge_id + 1) + bridge_count = bridge->bridge_id + 1; + + funcs = get_funcs( bridge ); + + if (funcs->JoinPoolBridge) { + ret = funcs->JoinPoolBridge( core, bridge, bridge->data, get_local(bridge), context ); + if (ret) { + D_DERROR( ret, "Core/SurfacePoolBridge: Joining '%s' failed!\n", bridge->desc.name ); + + if (bridge_locals[bridge->bridge_id]) { + D_FREE( bridge_locals[bridge->bridge_id] ); + bridge_locals[bridge->bridge_id] = NULL; + } + + bridge_array[bridge->bridge_id] = NULL; + bridge_funcs[bridge->bridge_id] = NULL; + + bridge_count--; + + return ret; + } + } + + return DFB_OK; +} + +DFBResult +dfb_surface_pool_bridge_destroy( CoreSurfacePoolBridge *bridge ) +{ + CoreSurfacePoolBridgeID bridge_id; + const SurfacePoolBridgeFuncs *funcs; + + D_MAGIC_ASSERT( bridge, CoreSurfacePoolBridge ); + + bridge_id = bridge->bridge_id; + + D_DEBUG_AT( Core_SurfPoolBridge, "%s( %p, '%s' [%d] )\n", __FUNCTION__, bridge, bridge->desc.name, bridge_id ); + + D_ASSERT( bridge->bridge_id >= 0 ); + D_ASSERT( bridge_id < MAX_SURFACE_POOL_BRIDGES ); + D_ASSERT( bridge_array[bridge_id] == bridge ); + + funcs = get_funcs( bridge ); + + if (funcs->DestroyPoolBridge) + funcs->DestroyPoolBridge( bridge, bridge->data, get_local(bridge) ); + + /* Free shared bridge data. */ + if (bridge->data) + SHFREE( bridge->shmpool, bridge->data ); + + /* Free local bridge data. */ + if (bridge_locals[bridge_id]) + D_FREE( bridge_locals[bridge_id] ); + + /* Remove from arrays. */ + bridge_array[bridge_id] = NULL; + bridge_funcs[bridge_id] = NULL; + bridge_locals[bridge_id] = NULL; + + fusion_skirmish_destroy( &bridge->lock ); + + D_MAGIC_CLEAR( bridge ); + + SHFREE( bridge->shmpool, bridge ); + + return DFB_OK; +} + +DFBResult +dfb_surface_pool_bridge_leave( CoreSurfacePoolBridge *bridge ) +{ + CoreSurfacePoolBridgeID bridge_id; + const SurfacePoolBridgeFuncs *funcs; + + D_MAGIC_ASSERT( bridge, CoreSurfacePoolBridge ); + + bridge_id = bridge->bridge_id; + + D_DEBUG_AT( Core_SurfPoolBridge, "%s( %p, '%s' [%d] )\n", __FUNCTION__, bridge, bridge->desc.name, bridge_id ); + + D_ASSERT( bridge->bridge_id >= 0 ); + D_ASSERT( bridge_id < MAX_SURFACE_POOL_BRIDGES ); + D_ASSERT( bridge_array[bridge_id] == bridge ); + + funcs = get_funcs( bridge ); + + if (funcs->LeavePoolBridge) + funcs->LeavePoolBridge( bridge, bridge->data, get_local(bridge) ); + + /* Free local bridge data. */ + if (bridge_locals[bridge_id]) + D_FREE( bridge_locals[bridge_id] ); + + /* Remove from arrays. */ + bridge_array[bridge_id] = NULL; + bridge_funcs[bridge_id] = NULL; + bridge_locals[bridge_id] = NULL; + + return DFB_OK; +} + +/**********************************************************************************************************************/ + +DFBResult +dfb_surface_pool_bridges_enumerate( CoreSurfacePoolBridgeCallback callback, + void *ctx ) +{ + int i; + + D_ASSERT( callback != NULL ); + + D_DEBUG_AT( Core_SurfPoolBridge, "%s( %p, %p )\n", __FUNCTION__, callback, ctx ); + + for (i=0; i 0 ); + D_ASSERT( ret_transfer != NULL ); + + alloc_size = sizeof(CoreSurfacePoolTransfer) + num_rects * sizeof(DFBRectangle) + bridge->transfer_data_size; + + transfer = SHCALLOC( bridge->shmpool, 1, alloc_size ); + if (!transfer) + return D_OOSHM(); + + transfer->bridge = bridge; + transfer->buffer = buffer; + transfer->from = from; + transfer->to = to; + + transfer->rects = (DFBRectangle*)(transfer + 1); + + if (bridge->transfer_data_size) + transfer->data = transfer->rects + num_rects; + + transfer->num_rects = num_rects; + + direct_memcpy( transfer->rects, rects, num_rects * sizeof(DFBRectangle) ); + + D_MAGIC_SET( transfer, CoreSurfacePoolTransfer ); + + *ret_transfer = transfer; + + return DFB_OK; +} + +static void +deallocate_transfer( CoreSurfacePoolTransfer *transfer ) +{ + CoreSurfacePoolBridge *bridge; + + D_MAGIC_ASSERT( transfer, CoreSurfacePoolTransfer ); + + bridge = transfer->bridge; + D_MAGIC_ASSERT( bridge, CoreSurfacePoolBridge ); + + D_MAGIC_CLEAR( transfer ); + + SHFREE( bridge->shmpool, transfer ); +} + +DFBResult +dfb_surface_pool_bridges_transfer( CoreSurfaceBuffer *buffer, + CoreSurfaceAllocation *from, + CoreSurfaceAllocation *to, + const DFBRectangle *rects, + unsigned int num_rects ) +{ + DFBResult ret; + int i; + DFBRectangle rect; + CoreSurface *surface; + CoreSurfacePoolBridge *bridge = NULL; + const SurfacePoolBridgeFuncs *funcs; + CoreSurfacePoolTransfer *transfer; + + D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); + CORE_SURFACE_ALLOCATION_ASSERT( from ); + CORE_SURFACE_ALLOCATION_ASSERT( to ); + D_ASSERT( rects != NULL || num_rects == 0 ); + D_ASSERT( num_rects > 0 || rects == NULL ); + + D_DEBUG_AT( Core_SurfPoolBridge, "%s( %p [%s], %p -> %p, %d rects )\n", __FUNCTION__, + buffer, dfb_pixelformat_name( buffer->format ), from, to, num_rects ); + + surface = buffer->surface; + D_MAGIC_ASSERT( surface, CoreSurface ); + FUSION_SKIRMISH_ASSERT( &surface->lock ); + + if (!rects) { + rect.x = rect.y = 0; + rect.w = surface->config.size.w; + rect.h = surface->config.size.h; + + rects = ▭ + num_rects = 1; + } + + for (i=0; iCheckTransfer != NULL ); + + ret = funcs->CheckTransfer( bridge, bridge->data, get_local(bridge), buffer, from, to ); + if (ret) + bridge = NULL; + else + break; + } + + if (!bridge) + return DFB_UNSUPPORTED; + + D_DEBUG_AT( Core_SurfPoolBridge, " -> using '%s'\n", bridge->desc.name ); + + ret = allocate_transfer( bridge, buffer, from, to, rects, num_rects, &transfer ); + if (ret) + return ret; + + D_ASSERT( funcs->StartTransfer != NULL ); + + D_DEBUG_AT( Core_SurfPoolBridge, " -> start...\n" ); + + ret = funcs->StartTransfer( bridge, bridge->data, get_local(bridge), transfer, transfer->data ); + if (ret) + D_DERROR( ret, "Core/SurfacePoolBridge: Starting transfer via '%s' failed!\n", bridge->desc.name ); + else if (funcs->FinishTransfer) { + D_DEBUG_AT( Core_SurfPoolBridge, " -> finish...\n" ); + + ret = funcs->FinishTransfer( bridge, bridge->data, get_local(bridge), transfer, transfer->data ); + if (ret) + D_DERROR( ret, "Core/SurfacePoolBridge: Finishing transfer via '%s' failed!\n", bridge->desc.name ); + } + + D_DEBUG_AT( Core_SurfPoolBridge, " => %s\n", DirectResultString(ret) ); + + deallocate_transfer( transfer ); + + return ret; +} + +/**********************************************************************************************************************/ + +static DFBResult +init_bridge( CoreDFB *core, + CoreSurfacePoolBridge *bridge, + const SurfacePoolBridgeFuncs *funcs, + void *context ) +{ + DFBResult ret; + + D_MAGIC_ASSERT( bridge, CoreSurfacePoolBridge ); + D_ASSERT( funcs != NULL ); + D_ASSERT( funcs->InitPoolBridge != NULL ); + + D_DEBUG_AT( Core_SurfPoolBridge, "%s( %p, %p )\n", __FUNCTION__, bridge, funcs ); + + if (funcs->PoolBridgeDataSize) + bridge->bridge_data_size = funcs->PoolBridgeDataSize(); + + if (funcs->PoolBridgeLocalDataSize) + bridge->bridge_local_data_size = funcs->PoolBridgeLocalDataSize(); + + if (funcs->PoolTransferDataSize) + bridge->transfer_data_size = funcs->PoolTransferDataSize(); + + /* Allocate shared bridge data. */ + if (bridge->bridge_data_size) { + bridge->data = SHCALLOC( bridge->shmpool, 1, bridge->bridge_data_size ); + if (!bridge->data) + return D_OOSHM(); + } + + /* Allocate local bridge data. */ + if (bridge->bridge_local_data_size && + !(bridge_locals[bridge->bridge_id] = D_CALLOC( 1, bridge->bridge_local_data_size ))) + { + SHFREE( bridge->shmpool, bridge->data ); + return D_OOM(); + } + + ret = funcs->InitPoolBridge( core, bridge, bridge->data, get_local(bridge), context, &bridge->desc ); + if (ret) { + D_DERROR( ret, "Core/SurfacePoolBridge: Initializing '%s' failed!\n", bridge->desc.name ); + + if (bridge_locals[bridge->bridge_id]) { + D_FREE( bridge_locals[bridge->bridge_id] ); + bridge_locals[bridge->bridge_id] = NULL; + } + + if (bridge->data) { + SHFREE( bridge->shmpool, bridge->data ); + bridge->data = NULL; + } + + bridge_array[bridge->bridge_id] = NULL; + bridge_funcs[bridge->bridge_id] = NULL; + + return ret; + } + + fusion_skirmish_init( &bridge->lock, bridge->desc.name, dfb_core_world(core) ); + + return DFB_OK; +} + diff --git a/Source/DirectFB/src/core/surface_pool_bridge.h b/Source/DirectFB/src/core/surface_pool_bridge.h new file mode 100755 index 0000000..8fb6dda --- /dev/null +++ b/Source/DirectFB/src/core/surface_pool_bridge.h @@ -0,0 +1,187 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __CORE__SURFACE_POOL_BRIDGE_H__ +#define __CORE__SURFACE_POOL_BRIDGE_H__ + +#include + +#include + +#include +#include + + +typedef enum { + CSPBCAPS_NONE = 0x00000000, + + CSPBCAPS_ALL = 0x00000000 +} CoreSurfacePoolBridgeCapabilities; + +/* + * Increase this number when changes result in binary incompatibility! + */ +#define DFB_SURFACE_POOL_BRIDGE_ABI_VERSION 1 + +#define DFB_SURFACE_POOL_BRIDGE_DESC_NAME_LENGTH 44 + + +typedef struct { + CoreSurfacePoolBridgeCapabilities caps; + char name[DFB_SURFACE_POOL_BRIDGE_DESC_NAME_LENGTH]; +} CoreSurfacePoolBridgeDescription; + + +typedef struct { + int (*PoolBridgeDataSize)( void ); + int (*PoolBridgeLocalDataSize)( void ); + + int (*PoolTransferDataSize)( void ); + + /* + * Bridge init/destroy + */ + DFBResult (*InitPoolBridge) ( CoreDFB *core, + CoreSurfacePoolBridge *bridge, + void *bridge_data, + void *bridge_local, + void *context, + CoreSurfacePoolBridgeDescription *ret_desc ); + + DFBResult (*JoinPoolBridge) ( CoreDFB *core, + CoreSurfacePoolBridge *bridge, + void *bridge_data, + void *bridge_local, + void *context ); + + DFBResult (*DestroyPoolBridge)( CoreSurfacePoolBridge *bridge, + void *bridge_data, + void *bridge_local ); + + DFBResult (*LeavePoolBridge) ( CoreSurfacePoolBridge *bridge, + void *bridge_data, + void *bridge_local ); + + + /* + * Probe + */ + DFBResult (*CheckTransfer) ( CoreSurfacePoolBridge *bridge, + void *bridge_data, + void *bridge_local, + CoreSurfaceBuffer *buffer, + CoreSurfaceAllocation *from, + CoreSurfaceAllocation *to ); + + /* + * Transfer + */ + DFBResult (*StartTransfer) ( CoreSurfacePoolBridge *bridge, + void *bridge_data, + void *bridge_local, + CoreSurfacePoolTransfer *transfer, + void *transfer_data ); + + DFBResult (*FinishTransfer) ( CoreSurfacePoolBridge *bridge, + void *bridge_data, + void *bridge_local, + CoreSurfacePoolTransfer *transfer, + void *transfer_data ); +} SurfacePoolBridgeFuncs; + + +struct __DFB_CoreSurfacePoolBridge { + int magic; + + FusionSkirmish lock; + + CoreSurfacePoolBridgeID bridge_id; + + CoreSurfacePoolBridgeDescription desc; + + int bridge_data_size; + int bridge_local_data_size; + int transfer_data_size; + + void *data; + + FusionSHMPoolShared *shmpool; + + DirectLink *transfers; +}; + +struct __DFB_CoreSurfacePoolTransfer { + DirectLink link; + + int magic; + + CoreSurfacePoolBridge *bridge; + + CoreSurfaceBuffer *buffer; + CoreSurfaceAllocation *from; + CoreSurfaceAllocation *to; + + DFBRectangle *rects; + unsigned int num_rects; + + void *data; +}; + + +typedef DFBEnumerationResult (*CoreSurfacePoolBridgeCallback)( CoreSurfacePoolBridge *bridge, + void *ctx ); + + + +DFBResult dfb_surface_pool_bridges_enumerate( CoreSurfacePoolBridgeCallback callback, + void *ctx ); + +DFBResult dfb_surface_pool_bridges_transfer ( CoreSurfaceBuffer *buffer, + CoreSurfaceAllocation *from, + CoreSurfaceAllocation *to, + const DFBRectangle *rects, + unsigned int num_rects ); + + +DFBResult dfb_surface_pool_bridge_initialize( CoreDFB *core, + const SurfacePoolBridgeFuncs *funcs, + void *context, + CoreSurfacePoolBridge **ret_bridge ); + +DFBResult dfb_surface_pool_bridge_join ( CoreDFB *core, + CoreSurfacePoolBridge *pool, + const SurfacePoolBridgeFuncs *funcs, + void *context ); + +DFBResult dfb_surface_pool_bridge_destroy ( CoreSurfacePoolBridge *bridge ); + +DFBResult dfb_surface_pool_bridge_leave ( CoreSurfacePoolBridge *bridge ); + + +#endif + diff --git a/Source/DirectFB/src/core/system.c b/Source/DirectFB/src/core/system.c new file mode 100755 index 0000000..6a78eb0 --- /dev/null +++ b/Source/DirectFB/src/core/system.c @@ -0,0 +1,464 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include + +DEFINE_MODULE_DIRECTORY( dfb_core_systems, "systems", DFB_CORE_SYSTEM_ABI_VERSION ); + + +D_DEBUG_DOMAIN( Core_System, "Core/System", "DirectFB System Core" ); + +/**********************************************************************************************************************/ + +typedef struct { + int magic; + + CoreSystemInfo system_info; +} DFBSystemCoreShared; + +struct __DFB_DFBSystemCore { + int magic; + + CoreDFB *core; + + DFBSystemCoreShared *shared; +}; + + +DFB_CORE_PART( system_core, SystemCore ); + +/**********************************************************************************************************************/ + +static DFBSystemCoreShared *system_field = NULL; /* FIXME */ + +static DirectModuleEntry *system_module = NULL; /* FIXME */ +static const CoreSystemFuncs *system_funcs = NULL; /* FIXME */ +static CoreSystemInfo system_info; /* FIXME */ +static void *system_data = NULL; /* FIXME */ + +/**********************************************************************************************************************/ + +static DFBResult +dfb_system_core_initialize( CoreDFB *core, + DFBSystemCore *data, + DFBSystemCoreShared *shared ) +{ + DFBResult ret; + + D_DEBUG_AT( Core_System, "dfb_system_core_initialize( %p, %p, %p )\n", core, data, shared ); + + D_ASSERT( data != NULL ); + D_ASSERT( shared != NULL ); + + data->core = core; + data->shared = shared; + + + system_field = shared; /* FIXME */ + + system_field->system_info = system_info; + + ret = system_funcs->Initialize( core, &system_data ); + if (ret) + return ret; + + + D_MAGIC_SET( data, DFBSystemCore ); + D_MAGIC_SET( shared, DFBSystemCoreShared ); + + return DFB_OK; +} + +static DFBResult +dfb_system_core_join( CoreDFB *core, + DFBSystemCore *data, + DFBSystemCoreShared *shared ) +{ + DFBResult ret; + + D_DEBUG_AT( Core_System, "dfb_system_core_join( %p, %p, %p )\n", core, data, shared ); + + D_ASSERT( data != NULL ); + D_MAGIC_ASSERT( shared, DFBSystemCoreShared ); + + data->core = core; + data->shared = shared; + + + system_field = shared; /* FIXME */ + + if (system_field->system_info.type != system_info.type || + strcmp( system_field->system_info.name, system_info.name )) + { + D_ERROR( "DirectFB/core/system: " + "running system '%s' doesn't match system '%s'!\n", + system_field->system_info.name, system_info.name ); + + system_field = NULL; + + return DFB_UNSUPPORTED; + } + + if (system_field->system_info.version.major != system_info.version.major || + system_field->system_info.version.minor != system_info.version.minor) + { + D_ERROR( "DirectFB/core/system: running system version '%d.%d' " + "doesn't match version '%d.%d'!\n", + system_field->system_info.version.major, + system_field->system_info.version.minor, + system_info.version.major, + system_info.version.minor ); + + system_field = NULL; + + return DFB_UNSUPPORTED; + } + + ret = system_funcs->Join( core, &system_data ); + if (ret) + return ret; + + + D_MAGIC_SET( data, DFBSystemCore ); + + return DFB_OK; +} + +static DFBResult +dfb_system_core_shutdown( DFBSystemCore *data, + bool emergency ) +{ + DFBResult ret; + DFBSystemCoreShared *shared; + + D_DEBUG_AT( Core_System, "dfb_system_core_shutdown( %p, %semergency )\n", data, emergency ? "" : "no " ); + + D_MAGIC_ASSERT( data, DFBSystemCore ); + D_MAGIC_ASSERT( data->shared, DFBSystemCoreShared ); + + shared = data->shared; + + + ret = system_funcs->Shutdown( emergency ); + + direct_module_unref( system_module ); + + system_module = NULL; + system_funcs = NULL; + system_field = NULL; + system_data = NULL; + + + D_MAGIC_CLEAR( data ); + D_MAGIC_CLEAR( shared ); + + return ret; +} + +static DFBResult +dfb_system_core_leave( DFBSystemCore *data, + bool emergency ) +{ + DFBResult ret; + DFBSystemCoreShared *shared; + + D_DEBUG_AT( Core_System, "dfb_system_core_leave( %p, %semergency )\n", data, emergency ? "" : "no " ); + + D_MAGIC_ASSERT( data, DFBSystemCore ); + D_MAGIC_ASSERT( data->shared, DFBSystemCoreShared ); + + shared = data->shared; + + + ret = system_funcs->Leave( emergency ); + + direct_module_unref( system_module ); + + system_module = NULL; + system_funcs = NULL; + system_field = NULL; + system_data = NULL; + + + D_MAGIC_CLEAR( data ); + + return ret; +} + +static DFBResult +dfb_system_core_suspend( DFBSystemCore *data ) +{ + DFBSystemCoreShared *shared; + + D_DEBUG_AT( Core_System, "dfb_system_core_suspend( %p )\n", data ); + + D_MAGIC_ASSERT( data, DFBSystemCore ); + D_MAGIC_ASSERT( data->shared, DFBSystemCoreShared ); + + shared = data->shared; + + return system_funcs->Suspend(); +} + +static DFBResult +dfb_system_core_resume( DFBSystemCore *data ) +{ + DFBSystemCoreShared *shared; + + D_DEBUG_AT( Core_System, "dfb_system_core_resume( %p )\n", data ); + + D_MAGIC_ASSERT( data, DFBSystemCore ); + D_MAGIC_ASSERT( data->shared, DFBSystemCoreShared ); + + shared = data->shared; + + return system_funcs->Resume(); +} + +/**********************************************************************************************************************/ + +DFBResult +dfb_system_lookup( void ) +{ + DirectLink *l; + + direct_modules_explore_directory( &dfb_core_systems ); + + direct_list_foreach( l, dfb_core_systems.entries ) { + DirectModuleEntry *module = (DirectModuleEntry*) l; + const CoreSystemFuncs *funcs; + + funcs = direct_module_ref( module ); + if (!funcs) + continue; + + if (!system_module || (!dfb_config->system || + !strcasecmp( dfb_config->system, module->name ))) + { + if (system_module) + direct_module_unref( system_module ); + + system_module = module; + system_funcs = funcs; + + funcs->GetSystemInfo( &system_info ); + } + else + direct_module_unref( module ); + } + + if (!system_module) { + D_ERROR("DirectFB/core/system: No system found!\n"); + + return DFB_NOIMPL; + } + + return DFB_OK; +} + +CoreSystemType +dfb_system_type( void ) +{ + return system_info.type; +} + +CoreSystemCapabilities +dfb_system_caps( void ) +{ + return system_info.caps; +} + +void * +dfb_system_data( void ) +{ + return system_data; +} + +volatile void * +dfb_system_map_mmio( unsigned int offset, + int length ) +{ + D_ASSERT( system_funcs != NULL ); + + return system_funcs->MapMMIO( offset, length ); +} + +void +dfb_system_unmap_mmio( volatile void *addr, + int length ) +{ + D_ASSERT( system_funcs != NULL ); + + system_funcs->UnmapMMIO( addr, length ); +} + +int +dfb_system_get_accelerator( void ) +{ + D_ASSERT( system_funcs != NULL ); + + return system_funcs->GetAccelerator(); +} + +VideoMode * +dfb_system_modes( void ) +{ + D_ASSERT( system_funcs != NULL ); + + return system_funcs->GetModes(); +} + +VideoMode * +dfb_system_current_mode( void ) +{ + D_ASSERT( system_funcs != NULL ); + + return system_funcs->GetCurrentMode(); +} + +DFBResult +dfb_system_thread_init( void ) +{ + D_ASSERT( system_funcs != NULL ); + + return system_funcs->ThreadInit(); +} + +bool +dfb_system_input_filter( CoreInputDevice *device, + DFBInputEvent *event ) +{ + D_ASSERT( system_funcs != NULL ); + + return system_funcs->InputFilter( device, event ); +} + +unsigned long +dfb_system_video_memory_physical( unsigned int offset ) +{ + D_ASSERT( system_funcs != NULL ); + + return system_funcs->VideoMemoryPhysical( offset ); +} + +void * +dfb_system_video_memory_virtual( unsigned int offset ) +{ + D_ASSERT( system_funcs != NULL ); + + return system_funcs->VideoMemoryVirtual( offset ); +} + +unsigned int +dfb_system_videoram_length( void ) +{ + D_ASSERT( system_funcs != NULL ); + + return system_funcs->VideoRamLength(); +} + +unsigned long +dfb_system_aux_memory_physical( unsigned int offset ) +{ + D_ASSERT( system_funcs != NULL ); + + return system_funcs->AuxMemoryPhysical( offset ); +} + +void * +dfb_system_aux_memory_virtual( unsigned int offset ) +{ + D_ASSERT( system_funcs != NULL ); + + return system_funcs->AuxMemoryVirtual( offset ); +} + +unsigned int +dfb_system_auxram_length( void ) +{ + D_ASSERT( system_funcs != NULL ); + + return system_funcs->AuxRamLength(); +} + +void +dfb_system_get_busid( int *ret_bus, int *ret_dev, int *ret_func ) +{ + int bus = -1, dev = -1, func = -1; + + D_ASSERT( system_funcs != NULL ); + + system_funcs->GetBusID( &bus, &dev, &func ); + + if (ret_bus) + *ret_bus = bus; + if (ret_dev) + *ret_dev = dev; + if (ret_func) + *ret_func = func; +} + +void +dfb_system_get_deviceid( unsigned int *ret_vendor_id, + unsigned int *ret_device_id ) +{ + unsigned int vendor_id = 0, device_id = 0; + + D_ASSERT( system_funcs != NULL ); + + system_funcs->GetDeviceID( &vendor_id, &device_id ); + + if (ret_vendor_id) + *ret_vendor_id = vendor_id; + if (ret_device_id) + *ret_device_id = device_id; +} + diff --git a/Source/DirectFB/src/core/system.h b/Source/DirectFB/src/core/system.h new file mode 100755 index 0000000..f6d4df1 --- /dev/null +++ b/Source/DirectFB/src/core/system.h @@ -0,0 +1,258 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __DFB__CORE__SYSTEM_H__ +#define __DFB__CORE__SYSTEM_H__ + +#include + +#include + +#include + +#include + +typedef enum { + CORE_ANY, + CORE_FBDEV, + CORE_X11, + CORE_OSX, + CORE_SDL, + CORE_VNC, + CORE_DEVMEM, + CORE_TI_CMEM +} CoreSystemType; + +typedef enum { + CSCAPS_NONE = 0x00000000, /* None of these. */ + + CSCAPS_ACCELERATION = 0x00000001, /* HW acceleration supported, so probe graphics drivers. */ + + CSCAPS_ALL = 0x00000001 /* All of these. */ +} CoreSystemCapabilities; + +/* + * hold information of a Videomode read from /etc/fb.modes + * (to be replaced by DirectFB's own config system) + */ +typedef struct _VideoMode { + int xres; + int yres; + int bpp; + + int priority; + + int pixclock; + int left_margin; + int right_margin; + int upper_margin; + int lower_margin; + int hsync_len; + int vsync_len; + int hsync_high; + int vsync_high; + int csync_high; + + int laced; + int doubled; + + int sync_on_green; + int external_sync; + int broadcast; + + struct _VideoMode *next; +} VideoMode; + +DECLARE_MODULE_DIRECTORY( dfb_core_systems ); + +/* + * Increase this number when changes result in binary incompatibility! + */ +#define DFB_CORE_SYSTEM_ABI_VERSION 9 + +#define DFB_CORE_SYSTEM_INFO_NAME_LENGTH 60 +#define DFB_CORE_SYSTEM_INFO_VENDOR_LENGTH 80 +#define DFB_CORE_SYSTEM_INFO_URL_LENGTH 120 +#define DFB_CORE_SYSTEM_INFO_LICENSE_LENGTH 40 + + +typedef struct { + int major; /* major version */ + int minor; /* minor version */ +} CoreSystemVersion; /* major.minor, e.g. 0.1 */ + +typedef struct { + CoreSystemVersion version; + + CoreSystemType type; + CoreSystemCapabilities caps; + + char name[DFB_CORE_SYSTEM_INFO_NAME_LENGTH]; + /* Name of system, e.g. 'FBDev' */ + + char vendor[DFB_CORE_SYSTEM_INFO_VENDOR_LENGTH]; + /* Vendor (or author) of the driver, + e.g. 'directfb.org' or 'Denis Oliver Kropp' */ + + char url[DFB_CORE_SYSTEM_INFO_URL_LENGTH]; + /* URL for driver updates, + e.g. 'http://www.directfb.org/' */ + + char license[DFB_CORE_SYSTEM_INFO_LICENSE_LENGTH]; + /* License, e.g. 'LGPL' or 'proprietary' */ +} CoreSystemInfo; + +typedef struct { + void (*GetSystemInfo)( CoreSystemInfo *info ); + + DFBResult (*Initialize)( CoreDFB *core, void **data ); + DFBResult (*Join)( CoreDFB *core, void **data ); + + DFBResult (*Shutdown)( bool emergency ); + DFBResult (*Leave)( bool emergency ); + + DFBResult (*Suspend)( void ); + DFBResult (*Resume)( void ); + + VideoMode* (*GetModes)( void ); + VideoMode* (*GetCurrentMode)( void ); + + /* + * Called at the beginning of a new thread. + */ + DFBResult (*ThreadInit)( void ); + + /* + * Called upon incoming input events. + * Return true to drop the event, e.g. after doing special handling of it. + */ + bool (*InputFilter)( CoreInputDevice *device, DFBInputEvent *event ); + + /* + * Graphics drivers call this function to get access to MMIO regions. + * + * device: Graphics device to map + * offset: Offset from MMIO base (default offset is 0) + * length: Length of mapped region (-1 uses default length) + * + * Returns the virtual address or NULL if mapping failed. + */ + volatile void* (*MapMMIO)( unsigned int offset, + int length ); + + /* + * Graphics drivers call this function to unmap MMIO regions. + * + * addr: Virtual address returned by gfxcard_map_mmio + * length: Length of mapped region (-1 uses default length) + */ + void (*UnmapMMIO)( volatile void *addr, + int length ); + + int (*GetAccelerator)( void ); + + unsigned long (*VideoMemoryPhysical)( unsigned int offset ); + void* (*VideoMemoryVirtual)( unsigned int offset ); + + unsigned int (*VideoRamLength)( void ); + + unsigned long (*AuxMemoryPhysical)( unsigned int offset ); + void* (*AuxMemoryVirtual)( unsigned int offset ); + + unsigned int (*AuxRamLength)( void ); + + void (*GetBusID)( int *ret_bus, int *ret_dev, int *ret_func ); + void (*GetDeviceID)( unsigned int *ret_vendor_id, + unsigned int *ret_device_id ); +} CoreSystemFuncs; + + + +DFBResult +dfb_system_lookup( void ); + +CoreSystemType +dfb_system_type( void ); + +CoreSystemCapabilities +dfb_system_caps( void ); + +void * +dfb_system_data( void ); + +volatile void * +dfb_system_map_mmio( unsigned int offset, + int length ); + +void +dfb_system_unmap_mmio( volatile void *addr, + int length ); + +int +dfb_system_get_accelerator( void ); + +VideoMode * +dfb_system_modes( void ); + +VideoMode * +dfb_system_current_mode( void ); + +DFBResult +dfb_system_thread_init( void ); + +bool +dfb_system_input_filter( CoreInputDevice *device, + DFBInputEvent *event ); + +unsigned long +dfb_system_video_memory_physical( unsigned int offset ); + +void * +dfb_system_video_memory_virtual( unsigned int offset ); + +unsigned int +dfb_system_videoram_length( void ); + +unsigned long +dfb_system_aux_memory_physical( unsigned int offset ); + +void * +dfb_system_aux_memory_virtual( unsigned int offset ); + +unsigned int +dfb_system_auxram_length( void ); + +void +dfb_system_get_busid( int *ret_bus, int *ret_dev, int *ret_func ); + +void +dfb_system_get_deviceid( unsigned int *ret_vendor_id, + unsigned int *ret_device_id ); + +#endif + diff --git a/Source/DirectFB/src/core/windows.c b/Source/DirectFB/src/core/windows.c new file mode 100755 index 0000000..6d60925 --- /dev/null +++ b/Source/DirectFB/src/core/windows.c @@ -0,0 +1,1908 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include +#include +#include +#include + + +#include + +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + + +D_DEBUG_DOMAIN( Core_Windows, "Core/Windows", "DirectFB Window Core" ); + + +typedef struct { + DirectLink link; + + DFBInputDeviceID id; + GlobalReaction reaction; +} StackDevice; + +/**************************************************************************************************/ + +static bool +core_window_filter( CoreWindow *window, const DFBWindowEvent *event ); + +/**************************************************************************************************/ + +static const ReactionFunc dfb_window_globals[] = { + NULL +}; + +/**************************************************************************************************/ + +/* + * Window destructor. + */ +static void +window_destructor( FusionObject *object, bool zombie, void *ctx ) +{ + CoreWindow *window = (CoreWindow*) object; + CoreWindowStack *stack = window->stack; + + D_DEBUG_AT( Core_Windows, "destroying %p (%d,%d - %dx%d%s)\n", window, + DFB_RECTANGLE_VALS( &window->config.bounds ), zombie ? " ZOMBIE" : ""); + + D_ASSUME( window->stack != NULL ); + + if (!stack) { + fusion_object_destroy( object ); + return; + } + + dfb_windowstack_lock( stack ); + + dfb_window_destroy( window ); + + + if (window->cursor.surface) + dfb_surface_unlink( &window->cursor.surface ); + + if (window->caps & DWCAPS_SUBWINDOW) { + int index; + CoreWindow *toplevel; + + toplevel = window->toplevel; + D_ASSERT( toplevel != NULL ); + + index = fusion_vector_index_of( &toplevel->subwindows, window ); + D_ASSERT( index >= 0 ); + + fusion_vector_remove( &toplevel->subwindows, index ); + + dfb_window_unlink( &window->toplevel ); + } + else { + D_ASSERT( fusion_vector_size(&window->subwindows) == 0 ); + + fusion_vector_destroy( &window->subwindows ); + } + + dfb_windowstack_unlock( stack ); + + + /* Unlink the primary region of the context. */ + if (window->primary_region) + dfb_layer_region_unlink( &window->primary_region ); + + D_MAGIC_CLEAR( window ); + + fusion_object_destroy( object ); +} + +FusionObjectPool * +dfb_window_pool_create( const FusionWorld *world ) +{ + return fusion_object_pool_create( "Window Pool", + sizeof(CoreWindow), + sizeof(DFBWindowEvent), + window_destructor, NULL, world ); +} + +/**************************************************************************************************/ + +static DFBResult +create_region( CoreDFB *core, + CoreLayerContext *context, + CoreWindow *window, + DFBSurfacePixelFormat format, + DFBSurfaceCapabilities surface_caps, + CoreLayerRegion **ret_region, + CoreSurface **ret_surface ) +{ + DFBResult ret; + CoreLayerRegionConfig config; + CoreLayerRegion *region; + CoreSurface *surface; + CoreSurfaceConfig scon; + + D_ASSERT( core != NULL ); + D_ASSERT( context != NULL ); + D_ASSERT( window != NULL ); + D_ASSERT( ret_region != NULL ); + D_ASSERT( ret_surface != NULL ); + + memset( &config, 0, sizeof(CoreLayerRegionConfig) ); + + config.width = window->config.bounds.w; + config.height = window->config.bounds.h; + config.format = format; + config.options = context->config.options & DLOP_FLICKER_FILTERING; + config.source = (DFBRectangle) { 0, 0, config.width, config.height }; + config.dest = window->config.bounds; + config.opacity = 0; + config.alpha_ramp[0] = 0x00; + config.alpha_ramp[1] = 0x55; + config.alpha_ramp[2] = 0xaa; + config.alpha_ramp[3] = 0xff; + + if (surface_caps & DSCAPS_DOUBLE) + config.buffermode = DLBM_BACKVIDEO; + else if (surface_caps & DSCAPS_TRIPLE) + config.buffermode = DLBM_TRIPLE; + else + config.buffermode = DLBM_FRONTONLY; + + if (((context->config.options & DLOP_ALPHACHANNEL) || + (window->config.options & DWOP_ALPHACHANNEL)) && DFB_PIXELFORMAT_HAS_ALPHA(format)) + config.options |= DLOP_ALPHACHANNEL; + + config.options |= DLOP_OPACITY; + + config.surface_caps = surface_caps & (DSCAPS_INTERLACED | + DSCAPS_SEPARATED | + DSCAPS_PREMULTIPLIED); + + ret = dfb_layer_region_create( context, ®ion ); + if (ret) + return ret; + + + do { + ret = dfb_layer_region_set_configuration( region, &config, CLRCF_ALL ); + if (ret) { + if (config.options & DLOP_OPACITY) + config.options &= ~DLOP_OPACITY; + else if (config.options & DLOP_ALPHACHANNEL) + config.options = (config.options & ~DLOP_ALPHACHANNEL) | DLOP_OPACITY; + else { + D_DERROR( ret, "DirectFB/Core/Windows: Unable to set region configuration!\n" ); + dfb_layer_region_unref( region ); + return ret; + } + } + } while (ret); + + scon.flags = CSCONF_SIZE | CSCONF_FORMAT | CSCONF_CAPS; + scon.size.w = config.width; + scon.size.h = config.height; + scon.format = format; + scon.caps = surface_caps | DSCAPS_VIDEOONLY; + + ret = dfb_surface_create( core, &scon, CSTF_SHARED | CSTF_LAYER, context->layer_id, NULL, &surface ); + if (ret) { + dfb_layer_region_unref( region ); + return ret; + } + + ret = dfb_layer_region_set_surface( region, surface ); + if (ret) { + dfb_surface_unref( surface ); + dfb_layer_region_unref( region ); + return ret; + } + + ret = dfb_layer_region_enable( region ); + if (ret) { + dfb_surface_unref( surface ); + dfb_layer_region_unref( region ); + return ret; + } + + *ret_region = region; + *ret_surface = surface; + + return DFB_OK; +} + +static DFBResult +init_subwindow( CoreWindow *window, + CoreWindowStack *stack, + DFBWindowID toplevel_id ) +{ + DFBResult ret; + CoreWindow *toplevel; + + /* Lookup top level window */ + ret = dfb_wm_window_lookup( stack, toplevel_id, &toplevel ); + if (ret) + return ret; + + /* Make sure chosen top level window is not a sub window */ + if (toplevel->caps & DWCAPS_SUBWINDOW) { + D_ASSERT( toplevel->toplevel != NULL ); + D_ASSERT( toplevel->toplevel_id != 0 ); + + return DFB_INVARG; + } + else { + D_ASSERT( toplevel->toplevel == NULL ); + D_ASSERT( toplevel->toplevel_id == 0 ); + } + + /* Link top level window into sub window structure */ + ret = dfb_window_link( &window->toplevel, toplevel ); + if (ret) + return ret; + + /* Add window to sub window list of top level window */ + ret = fusion_vector_add( &toplevel->subwindows, window ); + if (ret) { + dfb_window_unlink( &window->toplevel ); + return ret; + } + + return DFB_OK; +} + +DFBResult +dfb_window_create( CoreWindowStack *stack, + const DFBWindowDescription *desc, + CoreWindow **ret_window ) +{ + DFBResult ret; + CoreSurface *surface; + CoreSurfacePolicy surface_policy = CSP_SYSTEMONLY; + CoreLayer *layer; + CoreLayerContext *context; + CoreWindow *window; + CardCapabilities card_caps; + CoreWindowConfig config; + DFBWindowCapabilities caps; + DFBSurfaceCapabilities surface_caps; + DFBSurfacePixelFormat pixelformat; + DFBWindowID toplevel_id; + + D_DEBUG_AT( Core_Windows, "%s( %p )\n", __FUNCTION__, stack ); + + D_ASSERT( stack != NULL ); + D_ASSERT( stack->context != NULL ); + D_ASSERT( desc != NULL ); + D_ASSERT( desc->width > 0 ); + D_ASSERT( desc->height > 0 ); + D_ASSERT( ret_window != NULL ); + + if (desc->width > 4096 || desc->height > 4096) + return DFB_LIMITEXCEEDED; + + /* Lock the window stack. */ + if (dfb_windowstack_lock( stack )) + return DFB_FUSION; + + context = stack->context; + layer = dfb_layer_at( context->layer_id ); + + + caps = desc->caps; + pixelformat = desc->pixelformat; + surface_caps = desc->surface_caps & (DSCAPS_INTERLACED | DSCAPS_SEPARATED | + DSCAPS_PREMULTIPLIED | DSCAPS_DEPTH | + DSCAPS_STATIC_ALLOC | DSCAPS_SYSTEMONLY | + DSCAPS_VIDEOONLY); + toplevel_id = (desc->flags & DWDESC_TOPLEVEL_ID) ? desc->toplevel_id : 0; + + if (toplevel_id != 0) + caps |= DWCAPS_SUBWINDOW; + else + caps &= ~DWCAPS_SUBWINDOW; + + + if (!dfb_config->translucent_windows) { + caps &= ~DWCAPS_ALPHACHANNEL; + + /*if (DFB_PIXELFORMAT_HAS_ALPHA(pixelformat)) + pixelformat = DSPF_UNKNOWN;*/ + } + + /* Choose pixel format. */ + if (caps & DWCAPS_ALPHACHANNEL) { + if (pixelformat == DSPF_UNKNOWN) { + if (context->config.flags & DLCONF_PIXELFORMAT) + pixelformat = context->config.pixelformat; + + if (! DFB_PIXELFORMAT_HAS_ALPHA(pixelformat)) + pixelformat = DSPF_ARGB; + } + else if (! DFB_PIXELFORMAT_HAS_ALPHA(pixelformat)) { + dfb_windowstack_unlock( stack ); + return DFB_INVARG; + } + } + else if (pixelformat == DSPF_UNKNOWN) { + if (context->config.flags & DLCONF_PIXELFORMAT) + pixelformat = context->config.pixelformat; + else { + D_WARN( "layer config has no pixel format, using RGB16" ); + + pixelformat = DSPF_RGB16; + } + } + + /* Choose window surface policy */ + if ((surface_caps & DSCAPS_VIDEOONLY) || + (context->config.buffermode == DLBM_WINDOWS)) + { + surface_policy = CSP_VIDEOONLY; + } + else if (!(surface_caps & DSCAPS_SYSTEMONLY) && + context->config.buffermode != DLBM_BACKSYSTEM) + { + if (dfb_config->window_policy != -1) { + /* Use the explicitly specified policy. */ + surface_policy = dfb_config->window_policy; + } + else { + /* Examine the hardware capabilities. */ + dfb_gfxcard_get_capabilities( &card_caps ); + + if (card_caps.accel & DFXL_BLIT) { + if ((card_caps.blitting & DSBLIT_BLEND_ALPHACHANNEL) || + !(caps & DWCAPS_ALPHACHANNEL)) + surface_policy = CSP_VIDEOHIGH; + } + } + } + + dfb_surface_caps_apply_policy( surface_policy, &surface_caps ); + + if (caps & DWCAPS_DOUBLEBUFFER) + surface_caps |= DSCAPS_DOUBLE; + + + memset( &config, 0, sizeof(CoreWindowConfig) ); + + config.bounds.x = desc->posx; + config.bounds.y = desc->posy; + config.bounds.w = desc->width; + config.bounds.h = desc->height; + config.stacking = (desc->flags & DWDESC_STACKING) ? desc->stacking : DWSC_MIDDLE; + + config.events = DWET_ALL; + + /* Auto enable blending for ARGB only, not indexed. */ + if ((caps & DWCAPS_ALPHACHANNEL) && + DFB_PIXELFORMAT_HAS_ALPHA (pixelformat) && + !DFB_PIXELFORMAT_IS_INDEXED(pixelformat)) + config.options |= DWOP_ALPHACHANNEL; + + /* Override automatic settings. */ + if (desc->flags & DWDESC_OPTIONS) + config.options = desc->options; + + /* Create the window object. */ + window = dfb_core_create_window( layer->core ); + + window->id = ++stack->id_pool; + window->caps = caps; + window->stack = stack; + window->config = config; + window->config.association = (desc->flags & DWDESC_PARENT) ? desc->parent_id : 0; + window->config.cursor_flags = dfb_config->default_cursor_flags; + + /* Set toplevel window ID (new sub window feature) */ + window->toplevel_id = toplevel_id; + + if (desc->flags & DWDESC_RESOURCE_ID) + window->resource_id = desc->resource_id; + + D_MAGIC_SET( window, CoreWindow ); + + ret = dfb_wm_preconfigure_window( stack, window ); + if(ret) { + D_MAGIC_CLEAR( window ); + fusion_object_destroy( &window->object ); + dfb_windowstack_unlock( stack ); + return ret; + } + + /* wm may have changed values */ + config = window->config; + caps = window->caps; + + /* Initialize sub window... */ + if (caps & DWCAPS_SUBWINDOW) { + ret = init_subwindow( window, stack, toplevel_id ); + if (ret) { + D_MAGIC_CLEAR( window ); + fusion_object_destroy( &window->object ); + dfb_windowstack_unlock( stack ); + return ret; + } + } + else { + /* ...or initialize top level window */ + fusion_vector_init( &window->subwindows, 3, stack->shmpool ); + + /* In case WM forbids sub window request, clear the toplevel window ID */ + window->toplevel_id = 0; + } + + if (dfb_config->warn.flags & DCWF_CREATE_WINDOW) + D_WARN( "create-window %4dx%4d %6s, caps 0x%08x, surface-caps 0x%08x, ID %u", + window->config.bounds.w, window->config.bounds.h, dfb_pixelformat_name(pixelformat), + window->caps, surface_caps, window->id ); + + /* Create the window's surface using the layer's palette if possible. */ + if (! (caps & (DWCAPS_INPUTONLY | DWCAPS_COLOR))) { + if (context->config.buffermode == DLBM_WINDOWS) { + CoreLayerRegion *region = NULL; + + /* Create a region for the window. */ + ret = create_region( layer->core, context, window, + pixelformat, surface_caps, ®ion, &surface ); + if (ret) { + D_MAGIC_CLEAR( window ); + fusion_object_destroy( &window->object ); + dfb_windowstack_unlock( stack ); + return ret; + } + + /* Link the region into the window structure. */ + dfb_layer_region_link( &window->region, region ); + dfb_layer_region_unref( region ); + + /* Link the surface into the window structure. */ + dfb_surface_link( &window->surface, surface ); + dfb_surface_unref( surface ); + } + else { + CoreLayerRegion *region; + + /* Get the primary region of the layer context. */ + ret = dfb_layer_context_get_primary_region( context, true, ®ion ); + if (ret) { + D_MAGIC_CLEAR( window ); + fusion_object_destroy( &window->object ); + dfb_windowstack_unlock( stack ); + return ret; + } + + /* Link the primary region into the window structure. */ + dfb_layer_region_link( &window->primary_region, region ); + dfb_layer_region_unref( region ); + + D_DEBUG_AT( Core_Windows, " -> %dx%d %s %s\n", + window->config.bounds.w, window->config.bounds.h, + dfb_pixelformat_name(pixelformat), + (surface_policy == CSP_VIDEOONLY) ? + "VIDEOONLY" : + ((surface_policy == CSP_SYSTEMONLY) ? + "SYSTEM ONLY" : + "AUTO VIDEO") ); + + /* Give the WM a chance to provide its own surface. */ + if (!window->surface) { + /* Create the surface for the window. */ + ret = dfb_surface_create_simple( layer->core, config.bounds.w, config.bounds.h, + pixelformat, surface_caps, CSTF_SHARED | CSTF_WINDOW, + (desc->flags & DWDESC_RESOURCE_ID) ? + desc->resource_id : window->id, + region->surface ? + region->surface->palette : NULL, &surface ); + if (ret) { + D_DERROR( ret, "Core/Windows: Failed to create window surface!\n" ); + D_MAGIC_CLEAR( window ); + dfb_layer_region_unlink( &window->primary_region ); + fusion_object_destroy( &window->object ); + dfb_windowstack_unlock( stack ); + return ret; + } + + /* Link the surface into the window structure. */ + dfb_surface_link( &window->surface, surface ); + dfb_surface_unref( surface ); + } + } + } + else + D_DEBUG_AT( Core_Windows, " -> %dx%d - INPUT ONLY!\n", + window->config.bounds.w, window->config.bounds.h ); + + D_DEBUG_AT( Core_Windows, " -> %p\n", window ); + + /* Pass the new window to the window manager. */ + ret = dfb_wm_add_window( stack, window ); + if (ret) { + D_DERROR( ret, "Core/Windows: Failed to add window to manager!\n" ); + + D_MAGIC_CLEAR( window ); + + if (window->surface) + dfb_surface_unlink( &window->surface ); + + if (window->primary_region) + dfb_layer_region_unlink( &window->primary_region ); + + if (window->region) + dfb_layer_region_unlink( &window->region ); + + fusion_object_destroy( &window->object ); + dfb_windowstack_unlock( stack ); + return ret; + } + + /* Indicate that initialization is complete. */ + D_FLAGS_SET( window->flags, CWF_INITIALIZED ); + + /* Increase number of windows. */ + stack->num++; + + /* Finally activate the object. */ + fusion_object_activate( &window->object ); + + fusion_reactor_direct( window->object.reactor, true ); + + /* Unlock the window stack. */ + dfb_windowstack_unlock( stack ); + + /* Return the new window. */ + *ret_window = window; + + return DFB_OK;; +} + +void +dfb_window_destroy( CoreWindow *window ) +{ + int i; + DFBWindowEvent evt; + CoreWindowStack *stack; + BoundWindow *bound, *next; + CoreWindow *subwindow; + + D_MAGIC_ASSERT( window, CoreWindow ); + D_ASSERT( DFB_WINDOW_INITIALIZED( window ) ); + + D_DEBUG_AT( Core_Windows, "dfb_window_destroy (%p) [%4d,%4d - %4dx%4d]\n", + window, DFB_RECTANGLE_VALS( &window->config.bounds ) ); + + D_ASSUME( window->stack != NULL ); + + stack = window->stack; + if (!stack) + return; + + /* Lock the window stack. */ + if (dfb_windowstack_lock( stack )) + return; + + /* Destroy sub windows first. */ + fusion_vector_foreach_reverse (subwindow, i, window->subwindows) { + D_ASSERT( subwindow != NULL ); + D_ASSERT( DFB_WINDOW_INITIALIZED( subwindow ) ); + + dfb_window_destroy( subwindow ); + } + + /* Avoid multiple destructions. */ + if (DFB_WINDOW_DESTROYED( window )) { + D_DEBUG_AT( Core_Windows, "%p already destroyed.\n", window ); + dfb_windowstack_unlock( stack ); + return; + } + + /* Unbind bound windows. */ + direct_list_foreach_safe (bound, next, window->bound_windows) { + direct_list_remove( &window->bound_windows, &bound->link ); + + bound->window->boundto = NULL; + + SHFREE( stack->shmpool, bound ); + } + + /* Unbind this window. */ + if (window->boundto) + dfb_window_unbind( window->boundto, window ); + + /* Make sure the window is no longer visible. */ + dfb_window_set_opacity( window, 0 ); + + /* Stop managing the window. */ + dfb_wm_remove_window( stack, window ); + + /* Indicate destruction. */ + D_FLAGS_SET( window->flags, CWF_DESTROYED ); + + /* Hardware allocated? */ + if (window->region) { + /* Disable region (removing it from hardware). */ + dfb_layer_region_disable( window->region ); + + /* Unlink from structure. */ + dfb_layer_region_unlink( &window->region ); + } + + /* Unlink the window's surface. */ + if (window->surface) { + dfb_surface_unlink( &window->surface ); + } + + /* Decrease number of windows. */ + stack->num--; + + /* Unlock the window stack. */ + dfb_windowstack_unlock( stack ); + + + /* Notify listeners. */ + evt.type = DWET_DESTROYED; + dfb_window_post_event( window, &evt ); +} + +DFBResult +dfb_window_change_stacking( CoreWindow *window, + DFBWindowStackingClass stacking ) +{ + DFBResult ret; + CoreWindowStack *stack; + CoreWindowConfig config; + + D_MAGIC_ASSERT( window, CoreWindow ); + D_ASSERT( window->stack != NULL ); + + stack = window->stack; + + /* Lock the window stack. */ + if (dfb_windowstack_lock( stack )) + return DFB_FUSION; + + /* Never call WM after destroying the window. */ + if (DFB_WINDOW_DESTROYED( window )) { + dfb_windowstack_unlock( stack ); + return DFB_DESTROYED; + } + + config.stacking = stacking; + + /* Let the window manager do its work. */ + ret = dfb_wm_set_window_config( window, &config, CWCF_STACKING ); + + /* Unlock the window stack. */ + dfb_windowstack_unlock( stack ); + + return ret; +} + +DFBResult +dfb_window_raise( CoreWindow *window ) +{ + DFBResult ret; + CoreWindowStack *stack; + + D_MAGIC_ASSERT( window, CoreWindow ); + D_ASSERT( window->stack != NULL ); + + stack = window->stack; + + /* Lock the window stack. */ + if (dfb_windowstack_lock( stack )) + return DFB_FUSION; + + /* Never call WM after destroying the window. */ + if (DFB_WINDOW_DESTROYED( window )) { + dfb_windowstack_unlock( stack ); + return DFB_DESTROYED; + } + + /* Let the window manager do its work. */ + ret = dfb_wm_restack_window( window, window, 1 ); + + /* Unlock the window stack. */ + dfb_windowstack_unlock( stack ); + + return ret; +} + +DFBResult +dfb_window_lower( CoreWindow *window ) +{ + DFBResult ret; + CoreWindowStack *stack; + + D_MAGIC_ASSERT( window, CoreWindow ); + D_ASSERT( window->stack != NULL ); + + stack = window->stack; + + /* Lock the window stack. */ + if (dfb_windowstack_lock( stack )) + return DFB_FUSION; + + /* Never call WM after destroying the window. */ + if (DFB_WINDOW_DESTROYED( window )) { + dfb_windowstack_unlock( stack ); + return DFB_DESTROYED; + } + + /* Let the window manager do its work. */ + ret = dfb_wm_restack_window( window, window, -1 ); + + /* Unlock the window stack. */ + dfb_windowstack_unlock( stack ); + + return ret; +} + +DFBResult +dfb_window_raisetotop( CoreWindow *window ) +{ + DFBResult ret; + CoreWindowStack *stack; + + D_MAGIC_ASSERT( window, CoreWindow ); + D_ASSERT( window->stack != NULL ); + + stack = window->stack; + + /* Lock the window stack. */ + if (dfb_windowstack_lock( stack )) + return DFB_FUSION; + + /* Never call WM after destroying the window. */ + if (DFB_WINDOW_DESTROYED( window )) { + dfb_windowstack_unlock( stack ); + return DFB_DESTROYED; + } + + /* Let the window manager do its work. */ + ret = dfb_wm_restack_window( window, NULL, 1 ); + + /* Unlock the window stack. */ + dfb_windowstack_unlock( stack ); + + return ret; +} + +DFBResult +dfb_window_lowertobottom( CoreWindow *window ) +{ + DFBResult ret; + CoreWindowStack *stack; + + D_MAGIC_ASSERT( window, CoreWindow ); + D_ASSERT( window->stack != NULL ); + + stack = window->stack; + + /* Lock the window stack. */ + if (dfb_windowstack_lock( stack )) + return DFB_FUSION; + + /* Never call WM after destroying the window. */ + if (DFB_WINDOW_DESTROYED( window )) { + dfb_windowstack_unlock( stack ); + return DFB_DESTROYED; + } + + /* Let the window manager do its work. */ + ret = dfb_wm_restack_window( window, NULL, 0 ); + + /* Unlock the window stack. */ + dfb_windowstack_unlock( stack ); + + return ret; +} + +DFBResult +dfb_window_putatop( CoreWindow *window, + CoreWindow *lower ) +{ + DFBResult ret; + CoreWindowStack *stack; + + D_MAGIC_ASSERT( window, CoreWindow ); + D_ASSERT( window->stack != NULL ); + + stack = window->stack; + + /* Lock the window stack. */ + if (dfb_windowstack_lock( stack )) + return DFB_FUSION; + + /* Never call WM after destroying the window. */ + if (DFB_WINDOW_DESTROYED( window )) { + dfb_windowstack_unlock( stack ); + return DFB_DESTROYED; + } + + /* Let the window manager do its work. */ + ret = dfb_wm_restack_window( window, lower, 1 ); + + /* Unlock the window stack. */ + dfb_windowstack_unlock( stack ); + + return ret; +} + +DFBResult +dfb_window_putbelow( CoreWindow *window, + CoreWindow *upper ) +{ + DFBResult ret; + CoreWindowStack *stack; + + D_MAGIC_ASSERT( window, CoreWindow ); + D_ASSERT( window->stack != NULL ); + + stack = window->stack; + + /* Lock the window stack. */ + if (dfb_windowstack_lock( stack )) + return DFB_FUSION; + + /* Never call WM after destroying the window. */ + if (DFB_WINDOW_DESTROYED( window )) { + dfb_windowstack_unlock( stack ); + return DFB_DESTROYED; + } + + /* Let the window manager do its work. */ + ret = dfb_wm_restack_window( window, upper, -1 ); + + /* Unlock the window stack. */ + dfb_windowstack_unlock( stack ); + + return ret; +} + +DFBResult +dfb_window_set_config( CoreWindow *window, + const CoreWindowConfig *config, + CoreWindowConfigFlags flags ) +{ + DFBResult ret; + CoreWindowStack *stack = window->stack; + + D_MAGIC_ASSERT( window, CoreWindow ); + + /* Lock the window stack. */ + if (dfb_windowstack_lock( stack )) + return DFB_FUSION; + + /* Never call WM after destroying the window. */ + if (DFB_WINDOW_DESTROYED( window )) { + dfb_windowstack_unlock( stack ); + return DFB_DESTROYED; + } + + ret = dfb_wm_set_window_config( window, config, flags ); + + /* Unlock the window stack. */ + dfb_windowstack_unlock( stack ); + + return ret; +} + +DFBResult +dfb_window_set_cursor_shape( CoreWindow *window, + CoreSurface *surface, + unsigned int hot_x, + unsigned int hot_y ) +{ + DFBResult ret = DFB_OK; + CoreWindowStack *stack = window->stack; + + D_MAGIC_ASSERT( window, CoreWindow ); + + /* Lock the window stack. */ + if (dfb_windowstack_lock( stack )) + return DFB_FUSION; + + /* Never call WM after destroying the window. */ + if (DFB_WINDOW_DESTROYED( window )) { + dfb_windowstack_unlock( stack ); + return DFB_DESTROYED; + } + + window->cursor.hot_x = hot_x; + window->cursor.hot_y = hot_y; + + if (window->cursor.surface) + dfb_surface_unlink( &window->cursor.surface ); + + if (surface) { + ret = dfb_surface_link( &window->cursor.surface, surface ); + if (ret == DFB_OK) { + if (window->flags & CWF_FOCUSED) + dfb_windowstack_cursor_set_shape( stack, surface, hot_x, hot_y ); + } + } + + /* Unlock the window stack. */ + dfb_windowstack_unlock( stack ); + + return ret; +} + +static DFBResult +move_window( CoreWindow *window, + int x, + int y ) +{ + DFBResult ret; + CoreWindowConfig config; + BoundWindow *bound; + + D_MAGIC_ASSERT( window, CoreWindow ); + + config.bounds.x = x; + config.bounds.y = y; + + ret = dfb_wm_set_window_config( window, &config, CWCF_POSITION ); + if (ret) + return ret; + + direct_list_foreach (bound, window->bound_windows) { + move_window( bound->window, + window->config.bounds.x + bound->x, + window->config.bounds.y + bound->y ); + } + + return DFB_OK; +} + +DFBResult +dfb_window_move( CoreWindow *window, + int x, + int y, + bool relative ) +{ + DFBResult ret; + CoreWindowStack *stack = window->stack; + + D_MAGIC_ASSERT( window, CoreWindow ); + + /* Lock the window stack. */ + if (dfb_windowstack_lock( stack )) + return DFB_FUSION; + + /* Never call WM after destroying the window. */ + if (DFB_WINDOW_DESTROYED( window )) { + dfb_windowstack_unlock( stack ); + return DFB_DESTROYED; + } + + if (window->boundto) { + dfb_windowstack_unlock( stack ); + return DFB_UNSUPPORTED; + } + + if (relative) { + x += window->config.bounds.x; + y += window->config.bounds.y; + } + + if (x == window->config.bounds.x && y == window->config.bounds.y) { + dfb_windowstack_unlock( stack ); + return DFB_OK; + } + + ret = move_window( window, x, y ); + + /* Unlock the window stack. */ + dfb_windowstack_unlock( stack ); + + return ret; +} + +DFBResult +dfb_window_set_bounds( CoreWindow *window, + int x, + int y, + int width, + int height ) +{ + DFBResult ret; + CoreWindowConfig config; + CoreWindowStack *stack = window->stack; + int old_x; + int old_y; + + D_MAGIC_ASSERT( window, CoreWindow ); + + /* Lock the window stack. */ + if (dfb_windowstack_lock( stack )) + return DFB_FUSION; + + /* Never call WM after destroying the window. */ + if (DFB_WINDOW_DESTROYED( window )) { + dfb_windowstack_unlock( stack ); + return DFB_DESTROYED; + } + + old_x = window->config.bounds.x; + old_y = window->config.bounds.y; + + if (window->boundto) { + if (old_x != x || old_y != y) { + dfb_windowstack_unlock( stack ); + return DFB_UNSUPPORTED; + } + } + + config.bounds.x = x; + config.bounds.y = y; + config.bounds.w = width; + config.bounds.h = height; + + if (window->config.bounds.x == x && + window->config.bounds.y == y && + window->config.bounds.w == width && + window->config.bounds.h == height) + { + dfb_windowstack_unlock( stack ); + return DFB_OK; + } + + ret = dfb_wm_set_window_config( window, &config, CWCF_POSITION | CWCF_SIZE ); + if (ret) { + dfb_windowstack_unlock( stack ); + return ret; + } + + if (old_x != x || old_y != y) { + BoundWindow *bound; + + direct_list_foreach (bound, window->bound_windows) { + move_window( bound->window, + window->config.bounds.x + bound->x, + window->config.bounds.y + bound->y ); + } + } + + /* Unlock the window stack. */ + dfb_windowstack_unlock( stack ); + + return DFB_OK; +} + +DFBResult +dfb_window_resize( CoreWindow *window, + int width, + int height ) +{ + DFBResult ret; + CoreWindowConfig config; + CoreWindowStack *stack = window->stack; + + D_MAGIC_ASSERT( window, CoreWindow ); + + D_DEBUG_AT( Core_Windows, "dfb_window_resize (%p) [%4d,%4d - %4dx%4d -> %dx%d]\n", + window, DFB_RECTANGLE_VALS( &window->config.bounds ), width, height ); + + D_ASSERT( width > 0 ); + D_ASSERT( height > 0 ); + + if (width > 4096 || height > 4096) + return DFB_LIMITEXCEEDED; + + /* Lock the window stack. */ + if (dfb_windowstack_lock( stack )) + return DFB_FUSION; + + /* Never call WM after destroying the window. */ + if (DFB_WINDOW_DESTROYED( window )) { + dfb_windowstack_unlock( stack ); + return DFB_DESTROYED; + } + + if (window->config.bounds.w == width && window->config.bounds.h == height) { + dfb_windowstack_unlock( stack ); + return DFB_OK; + } + + config.bounds.w = width; + config.bounds.h = height; + + ret = dfb_wm_set_window_config( window, &config, CWCF_SIZE ); + + /* Unlock the window stack. */ + dfb_windowstack_unlock( stack ); + + return ret; +} + +DFBResult +dfb_window_bind( CoreWindow *window, + CoreWindow *source, + int x, + int y ) +{ + DFBResult ret; + CoreWindowStack *stack = window->stack; + BoundWindow *bound; + + D_MAGIC_ASSERT( window, CoreWindow ); + + if (window == source) + return DFB_UNSUPPORTED; + + /* Lock the window stack. */ + if (dfb_windowstack_lock( stack )) + return DFB_FUSION; + + /* Never call WM after destroying the window. */ + if (DFB_WINDOW_DESTROYED( window )) { + dfb_windowstack_unlock( stack ); + return DFB_DESTROYED; + } + + if (DFB_WINDOW_DESTROYED( source )) { + dfb_windowstack_unlock( stack ); + return DFB_DESTROYED; + } + + bound = SHCALLOC( stack->shmpool, 1, sizeof(BoundWindow) ); + if (!bound) { + dfb_windowstack_unlock( stack ); + return DFB_NOSHAREDMEMORY; + } + + if (source->boundto) + dfb_window_unbind( source->boundto, source ); + + ret = move_window( source, + window->config.bounds.x + x, + window->config.bounds.y + y ); + if (ret) { + SHFREE( stack->shmpool, bound ); + dfb_windowstack_unlock( stack ); + return ret; + } + + bound->window = source; + bound->x = x; + bound->y = y; + + direct_list_append( &window->bound_windows, &bound->link ); + + source->boundto = window; + + dfb_windowstack_unlock( stack ); + + return DFB_OK; +} + +DFBResult +dfb_window_unbind( CoreWindow *window, + CoreWindow *source ) +{ + CoreWindowStack *stack = window->stack; + BoundWindow *bound; + + D_MAGIC_ASSERT( window, CoreWindow ); + + /* Lock the window stack. */ + if (dfb_windowstack_lock( stack )) + return DFB_FUSION; + + /* Never call WM after destroying the window. */ + if (DFB_WINDOW_DESTROYED( window )) { + dfb_windowstack_unlock( stack ); + return DFB_DESTROYED; + } + + if (DFB_WINDOW_DESTROYED( source )) { + dfb_windowstack_unlock( stack ); + return DFB_DESTROYED; + } + + if (source->boundto != window) { + dfb_windowstack_unlock( stack ); + return DFB_UNSUPPORTED; + } + + direct_list_foreach (bound, window->bound_windows) { + if (bound->window == source) { + direct_list_remove( &window->bound_windows, &bound->link ); + + bound->window->boundto = NULL; + + SHFREE( stack->shmpool, bound ); + + break; + } + } + + if (!bound) + D_BUG( "window not found" ); + + dfb_windowstack_unlock( stack ); + + return bound ? DFB_OK : DFB_ITEMNOTFOUND; +} + +/* + * sets the source color key + */ +DFBResult +dfb_window_set_color( CoreWindow *window, + DFBColor color ) +{ + DFBResult ret; + DFBColor cc; + CoreWindowConfig config; + CoreWindowStack *stack = window->stack; + + D_MAGIC_ASSERT( window, CoreWindow ); + + /* Lock the window stack. */ + if (dfb_windowstack_lock( stack )) + return DFB_FUSION; + + /* Never call WM after destroying the window. */ + if (DFB_WINDOW_DESTROYED( window )) { + dfb_windowstack_unlock( stack ); + return DFB_DESTROYED; + } + + cc = window->config.color; + if ( (cc.a==color.a) && (cc.r==color.r) && (cc.g==color.g) && (cc.b==color.b) ) { + dfb_windowstack_unlock( stack ); + return DFB_OK; + } + + config.color = color; + + ret = dfb_wm_set_window_config( window, &config, CWCF_COLOR ); + + /* Unlock the window stack. */ + dfb_windowstack_unlock( stack ); + + return ret; +} + +DFBResult +dfb_window_set_colorkey( CoreWindow *window, + u32 color_key ) +{ + DFBResult ret; + CoreWindowConfig config; + CoreWindowStack *stack = window->stack; + + D_MAGIC_ASSERT( window, CoreWindow ); + + /* Lock the window stack. */ + if (dfb_windowstack_lock( stack )) + return DFB_FUSION; + + /* Never call WM after destroying the window. */ + if (DFB_WINDOW_DESTROYED( window )) { + dfb_windowstack_unlock( stack ); + return DFB_DESTROYED; + } + + if (window->config.color_key == color_key) { + dfb_windowstack_unlock( stack ); + return DFB_OK; + } + + config.color_key = color_key; + + ret = dfb_wm_set_window_config( window, &config, CWCF_COLOR_KEY ); + + /* Unlock the window stack. */ + dfb_windowstack_unlock( stack ); + + return ret; +} + +DFBResult +dfb_window_set_opacity( CoreWindow *window, + u8 opacity ) +{ + DFBResult ret; + CoreWindowConfig config; + CoreWindowStack *stack = window->stack; + + D_MAGIC_ASSERT( window, CoreWindow ); + + /* Lock the window stack. */ + if (dfb_windowstack_lock( stack )) + return DFB_FUSION; + + /* Never call WM after destroying the window. */ + if (DFB_WINDOW_DESTROYED( window )) { + dfb_windowstack_unlock( stack ); + return DFB_DESTROYED; + } + + if (window->config.opacity == opacity) { + dfb_windowstack_unlock( stack ); + return DFB_OK; + } + + config.opacity = opacity; + + ret = dfb_wm_set_window_config( window, &config, CWCF_OPACITY ); + + /* Unlock the window stack. */ + dfb_windowstack_unlock( stack ); + + return ret; +} + +DFBResult +dfb_window_change_options( CoreWindow *window, + DFBWindowOptions disable, + DFBWindowOptions enable ) +{ + DFBResult ret; + CoreWindowConfig config; + CoreWindowStack *stack = window->stack; + + D_MAGIC_ASSERT( window, CoreWindow ); + + D_ASSUME( disable | enable ); + + if (!disable && !enable) + return DFB_OK; + + /* Lock the window stack. */ + if (dfb_windowstack_lock( stack )) + return DFB_FUSION; + + /* Never call WM after destroying the window. */ + if (DFB_WINDOW_DESTROYED( window )) { + dfb_windowstack_unlock( stack ); + return DFB_DESTROYED; + } + + config.options = (window->config.options & ~disable) | enable; + + ret = dfb_wm_set_window_config( window, &config, CWCF_OPTIONS ); + + /* Unlock the window stack. */ + dfb_windowstack_unlock( stack ); + + return ret; +} + +DFBResult +dfb_window_set_opaque( CoreWindow *window, + const DFBRegion *region ) +{ + DFBResult ret; + CoreWindowConfig config; + CoreWindowStack *stack = window->stack; + + D_MAGIC_ASSERT( window, CoreWindow ); + + DFB_REGION_ASSERT_IF( region ); + + /* Lock the window stack. */ + if (dfb_windowstack_lock( stack )) + return DFB_FUSION; + + /* Never call WM after destroying the window. */ + if (DFB_WINDOW_DESTROYED( window )) { + dfb_windowstack_unlock( stack ); + return DFB_DESTROYED; + } + + config.opaque.x1 = 0; + config.opaque.y1 = 0; + config.opaque.x2 = window->config.bounds.w - 1; + config.opaque.y2 = window->config.bounds.h - 1; + + if (region && !dfb_region_region_intersect( &config.opaque, region )) + ret = DFB_INVAREA; + else + ret = dfb_wm_set_window_config( window, &config, CWCF_OPAQUE ); + + /* Unlock the window stack. */ + dfb_windowstack_unlock( stack ); + + return ret; +} + +DFBResult +dfb_window_change_events( CoreWindow *window, + DFBWindowEventType disable, + DFBWindowEventType enable ) +{ + DFBResult ret; + CoreWindowConfig config; + CoreWindowStack *stack = window->stack; + + D_MAGIC_ASSERT( window, CoreWindow ); + + D_ASSUME( disable | enable ); + + if (!disable && !enable) + return DFB_OK; + + /* Lock the window stack. */ + if (dfb_windowstack_lock( stack )) + return DFB_FUSION; + + /* Never call WM after destroying the window. */ + if (DFB_WINDOW_DESTROYED( window )) { + dfb_windowstack_unlock( stack ); + return DFB_DESTROYED; + } + + config.events = (window->config.events & ~disable) | enable; + + ret = dfb_wm_set_window_config( window, &config, CWCF_EVENTS ); + + /* Unlock the window stack. */ + dfb_windowstack_unlock( stack ); + + return ret; +} + +DFBResult +dfb_window_set_key_selection( CoreWindow *window, + DFBWindowKeySelection selection, + const DFBInputDeviceKeySymbol *keys, + unsigned int num_keys ) +{ + DFBResult ret; + CoreWindowConfig config; + CoreWindowStack *stack = window->stack; + + D_MAGIC_ASSERT( window, CoreWindow ); + + D_ASSERT( selection == DWKS_ALL || selection == DWKS_NONE || selection == DWKS_LIST ); + D_ASSERT( keys != NULL || selection != DWKS_LIST ); + D_ASSERT( num_keys > 0 || selection != DWKS_LIST ); + + /* Lock the window stack. */ + if (dfb_windowstack_lock( stack )) + return DFB_FUSION; + + /* Never call WM after destroying the window. */ + if (DFB_WINDOW_DESTROYED( window )) { + dfb_windowstack_unlock( stack ); + return DFB_DESTROYED; + } + + config.key_selection = selection; + config.keys = (DFBInputDeviceKeySymbol*) keys; /* FIXME */ + config.num_keys = num_keys; + + ret = dfb_wm_set_window_config( window, &config, CWCF_KEY_SELECTION ); + + /* Unlock the window stack. */ + dfb_windowstack_unlock( stack ); + + return ret; +} + +DFBResult +dfb_window_change_grab( CoreWindow *window, + CoreWMGrabTarget target, + bool grab ) +{ + DFBResult ret; + CoreWMGrab wmgrab; + CoreWindowStack *stack; + + D_MAGIC_ASSERT( window, CoreWindow ); + + stack = window->stack; + + /* Lock the window stack. */ + if (dfb_windowstack_lock( stack )) + return DFB_FUSION; + + /* Never call WM after destroying the window. */ + if (DFB_WINDOW_DESTROYED( window )) { + dfb_windowstack_unlock( stack ); + return DFB_DESTROYED; + } + + wmgrab.target = target; + + if (grab) + ret = dfb_wm_grab( window, &wmgrab ); + else + ret = dfb_wm_ungrab( window, &wmgrab ); + + /* Unlock the window stack. */ + dfb_windowstack_unlock( stack ); + + return ret; +} + +DFBResult +dfb_window_grab_key( CoreWindow *window, + DFBInputDeviceKeySymbol symbol, + DFBInputDeviceModifierMask modifiers ) +{ + DFBResult ret; + CoreWMGrab grab; + CoreWindowStack *stack = window->stack; + + D_MAGIC_ASSERT( window, CoreWindow ); + + /* Lock the window stack. */ + if (dfb_windowstack_lock( stack )) + return DFB_FUSION; + + /* Never call WM after destroying the window. */ + if (DFB_WINDOW_DESTROYED( window )) { + dfb_windowstack_unlock( stack ); + return DFB_DESTROYED; + } + + grab.target = CWMGT_KEY; + grab.symbol = symbol; + grab.modifiers = modifiers; + + ret = dfb_wm_grab( window, &grab ); + + /* Unlock the window stack. */ + dfb_windowstack_unlock( stack ); + + return ret; +} + +DFBResult +dfb_window_ungrab_key( CoreWindow *window, + DFBInputDeviceKeySymbol symbol, + DFBInputDeviceModifierMask modifiers ) +{ + DFBResult ret; + CoreWMGrab grab; + CoreWindowStack *stack = window->stack; + + D_MAGIC_ASSERT( window, CoreWindow ); + + /* Lock the window stack. */ + if (dfb_windowstack_lock( stack )) + return DFB_FUSION; + + /* Never call WM after destroying the window. */ + if (DFB_WINDOW_DESTROYED( window )) { + dfb_windowstack_unlock( stack ); + return DFB_DESTROYED; + } + + grab.target = CWMGT_KEY; + grab.symbol = symbol; + grab.modifiers = modifiers; + + ret = dfb_wm_ungrab( window, &grab ); + + /* Unlock the window stack. */ + dfb_windowstack_unlock( stack ); + + return ret; +} + +DFBResult +dfb_window_repaint( CoreWindow *window, + const DFBRegion *region, + DFBSurfaceFlipFlags flags ) +{ + DFBResult ret; + CoreWindowStack *stack = window->stack; + + D_MAGIC_ASSERT( window, CoreWindow ); + D_ASSERT( window->stack != NULL ); + + DFB_REGION_ASSERT_IF( region ); + + /* Lock the window stack. */ + if (dfb_windowstack_lock( stack )) + return DFB_FUSION; + + /* Never call WM after destroying the window. */ + if (DFB_WINDOW_DESTROYED( window )) { + dfb_windowstack_unlock( stack ); + return DFB_DESTROYED; + } + + ret = dfb_wm_update_window( window, region, flags ); + + /* Unlock the window stack. */ + dfb_windowstack_unlock( stack ); + + return ret; +} + +const char * +dfb_window_event_type_name( DFBWindowEventType type ) +{ + switch (type) { + case DWET_POSITION: + return "POSITION"; + + case DWET_SIZE: + return "SIZE"; + + case DWET_CLOSE: + return "CLOSE"; + + case DWET_DESTROYED: + return "DESTROYED"; + + case DWET_GOTFOCUS: + return "GOTFOCUS"; + + case DWET_LOSTFOCUS: + return "LOSTFOCUS"; + + case DWET_KEYDOWN: + return "KEYDOWN"; + + case DWET_KEYUP: + return "KEYUP"; + + case DWET_BUTTONDOWN: + return "BUTTONDOWN"; + + case DWET_BUTTONUP: + return "BUTTONUP"; + + case DWET_MOTION: + return "MOTION"; + + case DWET_ENTER: + return "ENTER"; + + case DWET_LEAVE: + return "LEAVE"; + + case DWET_WHEEL: + return "WHEEL"; + + case DWET_POSITION_SIZE: + return "POSITION_SIZE"; + + default: + break; + } + + return ""; +} + +void +dfb_window_post_event( CoreWindow *window, + DFBWindowEvent *event ) +{ + D_MAGIC_ASSERT( window, CoreWindow ); + D_ASSERT( event != NULL ); + + D_ASSUME( !DFB_WINDOW_DESTROYED( window ) || event->type == DWET_DESTROYED ); + + if (! (event->type & window->config.events)) + return; + + gettimeofday( &event->timestamp, NULL ); + + event->clazz = DFEC_WINDOW; + event->window_id = window->id; + + D_ASSUME( window->stack != NULL ); +/* + if (window->stack) { + CoreWindowStack *stack = window->stack; + + event->cx = stack->cursor.x; + event->cy = stack->cursor.y; + } +*/ + if (!core_window_filter( window, event )) + dfb_window_dispatch( window, event, dfb_window_globals ); +} + +DFBResult +dfb_window_send_configuration( CoreWindow *window ) +{ + DFBWindowEvent event; + + D_MAGIC_ASSERT( window, CoreWindow ); + + D_ASSUME( !DFB_WINDOW_DESTROYED( window ) ); + + event.type = DWET_POSITION_SIZE; + event.x = window->config.bounds.x; + event.y = window->config.bounds.y; + event.w = window->config.bounds.w; + event.h = window->config.bounds.h; + + dfb_window_post_event( window, &event ); + + return DFB_OK; +} + +DFBResult +dfb_window_request_focus( CoreWindow *window ) +{ + DFBResult ret; + CoreWindowStack *stack = window->stack; + + D_MAGIC_ASSERT( window, CoreWindow ); + + /* Lock the window stack. */ + if (dfb_windowstack_lock( stack )) + return DFB_FUSION; + + /* Never call WM after destroying the window. */ + if (DFB_WINDOW_DESTROYED( window )) { + dfb_windowstack_unlock( stack ); + return DFB_DESTROYED; + } + + ret = dfb_wm_request_focus( window ); + + /* Unlock the window stack. */ + dfb_windowstack_unlock( stack ); + + return ret; +} + +DFBWindowID +dfb_window_id( const CoreWindow *window ) +{ + D_MAGIC_ASSERT( window, CoreWindow ); + + return window->id; +} + +/* + * Returns window surface. + * For windows with DWCAPS_COLOR this returns 0. + */ +CoreSurface * +dfb_window_surface( const CoreWindow *window ) +{ + D_MAGIC_ASSERT( window, CoreWindow ); + + return window->surface; +} + +/******************************************************************************/ + +static bool +core_window_filter( CoreWindow *window, const DFBWindowEvent *event ) +{ + D_MAGIC_ASSERT( window, CoreWindow ); + + switch (event->type) { + case DWET_GOTFOCUS: + D_FLAGS_SET( window->flags, CWF_FOCUSED ); + break; + + case DWET_LOSTFOCUS: + D_FLAGS_CLEAR( window->flags, CWF_FOCUSED ); + break; + + case DWET_ENTER: + D_FLAGS_SET( window->flags, CWF_ENTERED ); + break; + + case DWET_LEAVE: + D_FLAGS_CLEAR( window->flags, CWF_ENTERED ); + break; + + default: + break; + } + + return false; +} + +DFBResult +dfb_window_set_rotation( CoreWindow *window, + int rotation ) +{ + DFBResult ret = DFB_OK; + CoreWindowStack *stack = window->stack; + + D_MAGIC_ASSERT( window, CoreWindow ); + + stack = window->stack; + D_MAGIC_ASSERT( stack, CoreWindowStack ); + + /* Lock the window stack. */ + if (dfb_windowstack_lock( stack )) + return DFB_FUSION; + + /* Never call WM after destroying the window. */ + if (DFB_WINDOW_DESTROYED( window )) { + dfb_windowstack_unlock( stack ); + return DFB_DESTROYED; + } + + /* Do nothing if the rotation didn't change. */ + if (window->config.rotation != rotation) { + CoreWindowConfig config; + + switch (rotation) { + case 0: + case 90: + case 180: + case 270: + config.rotation = rotation; + + dfb_wm_set_window_config( window, &config, CWCF_ROTATION ); + break; + + default: + ret = DFB_UNSUPPORTED; + } + } + + /* Unlock the window stack. */ + dfb_windowstack_unlock( stack ); + + return ret; +} + diff --git a/Source/DirectFB/src/core/windows.h b/Source/DirectFB/src/core/windows.h new file mode 100755 index 0000000..4b9e2a4 --- /dev/null +++ b/Source/DirectFB/src/core/windows.h @@ -0,0 +1,316 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __WINDOWS_H__ +#define __WINDOWS_H__ + +#include +#include + +#include +#include + +#include + +typedef enum { + CWMGT_KEYBOARD, + CWMGT_POINTER, + CWMGT_KEY, + CWMGT_UNSELECTED_KEYS, +} CoreWMGrabTarget; + + +#define CoreWindowConfigFlags DFBWindowConfigFlags + +#define CWCF_NONE DWCONF_NONE +#define CWCF_POSITION DWCONF_POSITION +#define CWCF_SIZE DWCONF_SIZE +#define CWCF_OPACITY DWCONF_OPACITY +#define CWCF_STACKING DWCONF_STACKING +#define CWCF_OPTIONS DWCONF_OPTIONS +#define CWCF_EVENTS DWCONF_EVENTS +#define CWCF_ASSOCIATION DWCONF_ASSOCIATION +#define CWCF_COLOR_KEY DWCONF_COLOR_KEY +#define CWCF_OPAQUE DWCONF_OPAQUE +#define CWCF_COLOR DWCONF_COLOR +#define CWCF_KEY_SELECTION DWCONF_KEY_SELECTION +#define CWCF_CURSOR_FLAGS DWCONF_CURSOR_FLAGS +#define CWCF_CURSOR_RESOLUTION DWCONF_CURSOR_RESOLUTION +#define CWCF_SRC_GEOMETRY DWCONF_SRC_GEOMETRY +#define CWCF_DST_GEOMETRY DWCONF_DST_GEOMETRY +#define CWCF_ROTATION DWCONF_ROTATION +#define CWCF_ALL DWCONF_ALL + + + +struct __DFB_CoreWindowConfig { + DFBRectangle bounds; /* position and size */ + int opacity; /* global alpha factor */ + DFBWindowStackingClass stacking; /* level boundaries */ + DFBWindowOptions options; /* flags for appearance/behaviour */ + DFBWindowEventType events; /* mask of enabled events */ + DFBColor color; /* color for DWCAPS_COLOR */ + u32 color_key; /* transparent pixel */ + DFBRegion opaque; /* region of the window forced to be opaque */ + + DFBWindowKeySelection key_selection; /* how to filter keys in focus */ + DFBInputDeviceKeySymbol *keys; /* list of keys for DWKS_LIST */ + unsigned int num_keys; /* number of entries in key array */ + + DFBWindowGeometry src_geometry; /* advanced source geometry */ + DFBWindowGeometry dst_geometry; /* advanced destination geometry */ + + int rotation; + + DFBWindowID association; + + DFBWindowCursorFlags cursor_flags; + DFBDimension cursor_resolution; +}; + + +#define TRANSLUCENT_WINDOW(w) ((w)->config.opacity < 0xff || \ + (w)->config.options & (DWOP_ALPHACHANNEL | DWOP_COLORKEYING)) + +#define VISIBLE_WINDOW(w) (!((w)->caps & DWCAPS_INPUTONLY) && \ + (w)->config.opacity > 0 && !DFB_WINDOW_DESTROYED((w))) + + +/* + * Creates a pool of window objects. + */ +FusionObjectPool *dfb_window_pool_create( const FusionWorld *world ); + +/* + * Generates dfb_window_ref(), dfb_window_attach() etc. + */ +FUSION_OBJECT_METHODS( CoreWindow, dfb_window ) + +/* + * creates a window on a given stack + */ +DFBResult +dfb_window_create( CoreWindowStack *stack, + const DFBWindowDescription *desc, + CoreWindow **ret_window ); + +/* + * deinitializes a window and removes it from the window stack + */ +void +dfb_window_destroy( CoreWindow *window ); + +/* + * moves a window relative to its current position + */ +DFBResult +dfb_window_move( CoreWindow *window, + int x, + int y, + bool relative ); + +/* + * set position and size + */ +DFBResult +dfb_window_set_bounds( CoreWindow *window, + int x, + int y, + int width, + int height ); + +/* + * resizes a window + */ +DFBResult +dfb_window_resize( CoreWindow *window, + int width, + int height ); + +/* + * binds a window to this window + */ +DFBResult +dfb_window_bind( CoreWindow *window, + CoreWindow *source, + int x, + int y ); + +/* + * unbinds a window from this window + */ +DFBResult +dfb_window_unbind( CoreWindow *window, + CoreWindow *source ); + +/* + * changes stacking class + */ +DFBResult +dfb_window_change_stacking( CoreWindow *window, + DFBWindowStackingClass stacking ); + +/* + * move a window up one step in window stack + */ +DFBResult +dfb_window_raise( CoreWindow *window ); + +/* + * move a window down one step in window stack + */ +DFBResult +dfb_window_lower( CoreWindow *window ); + +/* + * makes a window the first (topmost) window in the window stack + */ +DFBResult +dfb_window_raisetotop( CoreWindow *window ); + +/* + * makes a window the last (downmost) window in the window stack + */ +DFBResult +dfb_window_lowertobottom( CoreWindow *window ); + +/* + * stacks the window on top of another one + */ +DFBResult +dfb_window_putatop( CoreWindow *window, + CoreWindow *lower ); + +/* + * stacks the window below another one + */ +DFBResult +dfb_window_putbelow( CoreWindow *window, + CoreWindow *upper ); + +/* + * sets the source color key + */ +DFBResult +dfb_window_set_color( CoreWindow *window, + DFBColor color ); + +/* + * sets the source color key + */ +DFBResult +dfb_window_set_colorkey( CoreWindow *window, + u32 color_key ); + +/* + * change window configuration + */ +DFBResult +dfb_window_set_config( CoreWindow *window, + const CoreWindowConfig *config, + CoreWindowConfigFlags flags ); + +/* + * change window cursor + */ +DFBResult +dfb_window_set_cursor_shape( CoreWindow *window, + CoreSurface *surface, + unsigned int hot_x, + unsigned int hot_y ); + +/* + * sets the global alpha factor + */ +DFBResult +dfb_window_set_opacity( CoreWindow *window, + u8 opacity ); + +/* + * sets the window options + */ +DFBResult +dfb_window_change_options( CoreWindow *window, + DFBWindowOptions disable, + DFBWindowOptions enable ); + +/* + * sets the window options + */ +DFBResult +dfb_window_set_opaque( CoreWindow *window, + const DFBRegion *region ); + +/* + * manipulates the event mask + */ +DFBResult +dfb_window_change_events( CoreWindow *window, + DFBWindowEventType disable, + DFBWindowEventType enable ); + +/* + * repaints part of a window, if region is NULL the whole window is repainted + */ +DFBResult +dfb_window_repaint( CoreWindow *window, + const DFBRegion *region, + DFBSurfaceFlipFlags flags ); + +/* + * request a window to gain focus + */ +DFBResult +dfb_window_request_focus( CoreWindow *window ); + +DFBResult dfb_window_set_key_selection( CoreWindow *window, + DFBWindowKeySelection selection, + const DFBInputDeviceKeySymbol *keys, + unsigned int num_keys ); + +DFBResult dfb_window_change_grab ( CoreWindow *window, + CoreWMGrabTarget target, + bool grab ); +DFBResult dfb_window_grab_key ( CoreWindow *window, + DFBInputDeviceKeySymbol symbol, + DFBInputDeviceModifierMask modifiers ); +DFBResult dfb_window_ungrab_key ( CoreWindow *window, + DFBInputDeviceKeySymbol symbol, + DFBInputDeviceModifierMask modifiers ); + +void dfb_window_post_event( CoreWindow *window, DFBWindowEvent *event ); + +DFBResult dfb_window_send_configuration( CoreWindow *window ); + +DFBWindowID dfb_window_id( const CoreWindow *window ); + +CoreSurface *dfb_window_surface( const CoreWindow *window ); + +DFBResult +dfb_window_set_rotation( CoreWindow *window, int rotation ); +#endif diff --git a/Source/DirectFB/src/core/windows_internal.h b/Source/DirectFB/src/core/windows_internal.h new file mode 100755 index 0000000..cededef --- /dev/null +++ b/Source/DirectFB/src/core/windows_internal.h @@ -0,0 +1,211 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __CORE__WINDOWS_INTERNAL_H__ +#define __CORE__WINDOWS_INTERNAL_H__ + +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + + +typedef enum { + CWF_NONE = 0x00000000, + + CWF_INITIALIZED = 0x00000001, + CWF_FOCUSED = 0x00000002, + CWF_ENTERED = 0x00000004, + CWF_DESTROYED = 0x00000008, + + CWF_INSERTED = 0x00000010, + + CWF_ALL = 0x0000001F +} CoreWindowFlags; + +#define DFB_WINDOW_INITIALIZED(w) ((w)->flags & CWF_INITIALIZED) +#define DFB_WINDOW_FOCUSED(w) ((w)->flags & CWF_FOCUSED) +#define DFB_WINDOW_ENTERED(w) ((w)->flags & CWF_ENTERED) +#define DFB_WINDOW_DESTROYED(w) ((w)->flags & CWF_DESTROYED) + +typedef struct { + DirectLink link; + + CoreWindow *window; + int x; + int y; +} BoundWindow; + +/* + * Core data of a window. + */ +struct __DFB_CoreWindow { + FusionObject object; + + int magic; + + DFBWindowID id; + + CoreWindowFlags flags; + + DFBWindowCapabilities caps; /* window capabilities, to enable blending etc. */ + + CoreWindowConfig config; + + CoreSurface *surface; /* backing store surface */ + GlobalReaction surface_reaction; + + CoreWindowStack *stack; /* window stack the window belongs */ + + CoreLayerRegion *primary_region; /* default region of context */ + + CoreLayerRegion *region; /* hardware allocated window */ + + void *window_data; /* private data of window manager */ + + CoreGraphicsSerial serial1; + CoreGraphicsSerial serial2; + + DirectLink *bound_windows; /* list of bound windows */ + CoreWindow *boundto; /* window to which this window is bound (window binding) */ + + DFBWindowID toplevel_id; /* in case of a sub window toplevel_id != 0 */ + CoreWindow *toplevel; /* for top level windows this will be NULL */ + FusionVector subwindows; /* list of sub windows (only valid for top level windows) */ + + CoreWindow *subfocus; /* which of the sub windows has the focus? */ + + unsigned long resource_id; + + struct { + unsigned int hot_x; + unsigned int hot_y; + CoreSurface *surface; + } cursor; +}; + +typedef enum { + CWSF_NONE = 0x00000000, + + CWSF_INITIALIZED = 0x00000001, + CWSF_ACTIVATED = 0x00000002, + + CWSF_ALL = 0x00000003 +} CoreWindowStackFlags; + +/* + * Core data of a window stack. + */ +struct __DFB_CoreWindowStack { + DirectLink link; + + int magic; + + CoreLayerContext *context; + + int width; + int height; + + int rotation; + + int rotated_width; + int rotated_height; + DFBSurfaceBlittingFlags rotated_blit; + + DFBWindowID id_pool; + + int num; + + struct { + int enabled; /* is cursor enabled ? */ + int x, y; /* cursor position */ + DFBDimension size; /* cursor shape size */ + DFBPoint hot; /* hot spot */ + CoreSurface *surface; /* shape */ + u8 opacity; /* cursor opacity */ + DFBRegion region; /* cursor is clipped by this region */ + + int numerator; /* cursor acceleration */ + int denominator; + int threshold; + + bool set; /* cursor enable/disable has + been called at least one time */ + + CoreSurfacePolicy policy; + } cursor; + + /* stores information on handling the background on exposure */ + struct { + DFBDisplayLayerBackgroundMode mode; + /* background handling mode: + don't care, solid color or image */ + + DFBColor color; /* color for solid background mode */ + int color_index; + + + CoreSurface *image; /* surface for background image mode */ + + GlobalReaction image_reaction; + } bg; + + DirectLink *devices; /* input devices attached to the stack */ + + bool hw_mode; /* recompositing is done by hardware */ + + void *stack_data; /* private data of window manager */ + + FusionSHMPoolShared *shmpool; + + CoreWindowStackFlags flags; + + Reaction input_core_reaction; +}; + + +DFBResult dfb_wm_close_all_stacks( void *data ); + + +/* global reactions */ +ReactionResult _dfb_windowstack_inputdevice_listener ( const void *msg_data, + void *ctx ); + +ReactionResult _dfb_windowstack_background_image_listener( const void *msg_data, + void *ctx ); + +#endif diff --git a/Source/DirectFB/src/core/windowstack.c b/Source/DirectFB/src/core/windowstack.c new file mode 100755 index 0000000..7a19f1c --- /dev/null +++ b/Source/DirectFB/src/core/windowstack.c @@ -0,0 +1,998 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include + +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + + +#define CURSORFILE DATADIR"/cursor.dat" + + +D_DEBUG_DOMAIN( Core_WindowStack, "Core/WindowStack", "DirectFB Core WindowStack" ); + +/**********************************************************************************************************************/ + +typedef struct { + DirectLink link; + + DFBInputDeviceID id; + Reaction reaction; +} StackDevice; + +typedef struct { + DirectLink link; + + DFBInputDeviceKeySymbol symbol; + DFBInputDeviceModifierMask modifiers; + + CoreWindow *owner; +} GrabbedKey; + +/**********************************************************************************************************************/ + +static DFBResult load_default_cursor ( CoreDFB *core, + CoreWindowStack *stack ); +static DFBResult create_cursor_surface( CoreWindowStack *stack, + int width, + int height ); + +/**********************************************************************************************************************/ + +static DFBEnumerationResult stack_attach_devices( CoreInputDevice *device, + void *ctx ); + +static ReactionResult stack_input_core_listener( const void *msg_data, + void *ctx ); + +/**********************************************************************************************************************/ + +/* + * Allocates and initializes a window stack. + */ +CoreWindowStack* +dfb_windowstack_create( CoreLayerContext *context ) +{ + DFBResult ret; + CoreWindowStack *stack; + CoreSurfacePolicy policy = CSP_SYSTEMONLY; + CoreLayer *layer; + + D_DEBUG_AT( Core_WindowStack, "%s( %p )\n", __FUNCTION__, context ); + + D_ASSERT( context != NULL ); + + layer = dfb_layer_at( context->layer_id ); + + /* Allocate window stack data (completely shared) */ + stack = (CoreWindowStack*) SHCALLOC( context->shmpool, 1, sizeof(CoreWindowStack) ); + if (!stack) { + D_OOSHM(); + return NULL; + } + + stack->shmpool = context->shmpool; + + /* Store context which we belong to. */ + stack->context = context; + + /* Set default acceleration */ + stack->cursor.numerator = 2; + stack->cursor.denominator = 1; + stack->cursor.threshold = 4; + + /* Choose cursor surface policy. */ + if (context->config.buffermode != DLBM_BACKSYSTEM) { + CardCapabilities card_caps; + + /* Use the explicitly specified policy? */ + if (dfb_config->window_policy != -1) + policy = dfb_config->window_policy; + else { + /* Examine the hardware capabilities. */ + dfb_gfxcard_get_capabilities( &card_caps ); + + if (card_caps.accel & DFXL_BLIT && card_caps.blitting & DSBLIT_BLEND_ALPHACHANNEL) + policy = CSP_VIDEOHIGH; + } + } + + stack->cursor.policy = policy; + stack->cursor.opacity = 0xFF; + + /* Set default background mode. */ + stack->bg.mode = DLBM_DONTCARE; + stack->bg.color_index = -1; + + D_MAGIC_SET( stack, CoreWindowStack ); + + /* Initialize window manager */ + ret = dfb_wm_init_stack( stack ); + if (ret) { + D_MAGIC_CLEAR( stack ); + SHFREE( context->shmpool, stack ); + return NULL; + } + + if (dfb_core_is_master( layer->core )) + dfb_input_core_attach( layer->core, stack_input_core_listener, stack, &stack->input_core_reaction ); + + /* Attach to all input devices */ + dfb_input_enumerate_devices( stack_attach_devices, stack, DICAPS_ALL ); + + D_DEBUG_AT( Core_WindowStack, " -> %p\n", stack ); + + return stack; +} + +void +dfb_windowstack_detach_devices( CoreWindowStack *stack ) +{ + DirectLink *l; + + D_DEBUG_AT( Core_WindowStack, "%s( %p )\n", __FUNCTION__, stack ); + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + + /* Detach all input devices. */ + l = stack->devices; + while (l) { + DirectLink *next = l->next; + StackDevice *device = (StackDevice*) l; + + dfb_input_detach( dfb_input_device_at( device->id ), + &device->reaction ); + + SHFREE( stack->shmpool, device ); + + l = next; + } +} + +void +dfb_windowstack_destroy( CoreWindowStack *stack ) +{ + D_DEBUG_AT( Core_WindowStack, "%s( %p )\n", __FUNCTION__, stack ); + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + + if (stack->input_core_reaction.func) + dfb_input_core_detach( NULL, &stack->input_core_reaction ); + + /* Unlink cursor surface. */ + if (stack->cursor.surface) + dfb_surface_unlink( &stack->cursor.surface ); + + /* Shutdown window manager? */ + if (stack->flags & CWSF_INITIALIZED) + dfb_wm_close_stack( stack ); + + /* detach listener from background surface and unlink it */ + if (stack->bg.image) { + dfb_surface_detach_global( stack->bg.image, + &stack->bg.image_reaction ); + + dfb_surface_unlink( &stack->bg.image ); + } + + /* Deallocate shared stack data. */ + if (stack->stack_data) { + SHFREE( stack->shmpool, stack->stack_data ); + stack->stack_data = NULL; + } + + D_MAGIC_CLEAR( stack ); + + /* Free stack data. */ + SHFREE( stack->shmpool, stack ); +} + +void +dfb_windowstack_resize( CoreWindowStack *stack, + int width, + int height, + int rotation ) +{ + D_DEBUG_AT( Core_WindowStack, "%s( %p, %dx%d, %d )\n", __FUNCTION__, stack, width, height, rotation ); + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + + /* Lock the window stack. */ + if (dfb_windowstack_lock( stack )) + return; + + /* Store the width and height of the stack */ + stack->width = width; + stack->height = height; + stack->rotation = rotation; + + switch (stack->rotation) { + default: + D_BUG( "invalid rotation %d", stack->rotation ); + case 0: + stack->rotated_blit = DSBLIT_NOFX; + stack->rotated_width = stack->width; + stack->rotated_height = stack->height; + break; + + case 90: + stack->rotated_blit = DSBLIT_ROTATE90; + stack->rotated_width = stack->height; + stack->rotated_height = stack->width; + break; + + case 180: + stack->rotated_blit = DSBLIT_ROTATE180; + stack->rotated_width = stack->width; + stack->rotated_height = stack->height; + break; + + case 270: + stack->rotated_blit = DSBLIT_ROTATE270; + stack->rotated_width = stack->height; + stack->rotated_height = stack->width; + break; + } + + /* Setup new cursor clipping region */ + stack->cursor.region.x1 = 0; + stack->cursor.region.y1 = 0; + stack->cursor.region.x2 = width - 1; + stack->cursor.region.y2 = height - 1; + + /* Notify the window manager. */ + dfb_wm_resize_stack( stack, width, height ); + + /* Unlock the window stack. */ + dfb_windowstack_unlock( stack ); +} + +/* + * Prohibit access to the window stack data. + * Waits until stack is accessible. + */ +DirectResult +dfb_windowstack_lock( CoreWindowStack *stack ) +{ + D_MAGIC_ASSERT( stack, CoreWindowStack ); + D_ASSERT( stack->context != NULL ); + + return dfb_layer_context_lock( stack->context ); +} + +/* + * Allow access to the window stack data. + */ +DirectResult +dfb_windowstack_unlock( CoreWindowStack *stack ) +{ + D_MAGIC_ASSERT( stack, CoreWindowStack ); + D_ASSERT( stack->context != NULL ); + + return dfb_layer_context_unlock( stack->context ); +} + +DFBResult +dfb_windowstack_repaint_all( CoreWindowStack *stack ) +{ + DFBResult ret; + DFBRegion region; + + D_DEBUG_AT( Core_WindowStack, "%s( %p )\n", __FUNCTION__, stack ); + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + + /* Lock the window stack. */ + if (dfb_windowstack_lock( stack )) + return DFB_FUSION; + + region.x1 = 0; + region.y1 = 0; + region.x2 = stack->rotated_width - 1; + region.y2 = stack->rotated_height - 1; + + ret = dfb_wm_update_stack( stack, ®ion, 0 ); + + /* Unlock the window stack. */ + dfb_windowstack_unlock( stack ); + + return ret; +} + +/**********************************************************************************************************************/ + +/* + * background handling + */ + +DFBResult +dfb_windowstack_set_background_mode ( CoreWindowStack *stack, + DFBDisplayLayerBackgroundMode mode ) +{ + D_DEBUG_AT( Core_WindowStack, "%s( %p, %d )\n", __FUNCTION__, stack, mode ); + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + + /* Lock the window stack. */ + if (dfb_windowstack_lock( stack )) + return DFB_FUSION; + + /* nothing to do if mode is the same */ + if (mode != stack->bg.mode) { + /* for these modes a surface is required */ + if ((mode == DLBM_IMAGE || mode == DLBM_TILE) && !stack->bg.image) { + dfb_windowstack_unlock( stack ); + return DFB_MISSINGIMAGE; + } + + /* set new mode */ + stack->bg.mode = mode; + + /* force an update of the window stack */ + if (mode != DLBM_DONTCARE) + dfb_windowstack_repaint_all( stack ); + } + + /* Unlock the window stack. */ + dfb_windowstack_unlock( stack ); + + return DFB_OK; +} + +DFBResult +dfb_windowstack_set_background_image( CoreWindowStack *stack, + CoreSurface *image ) +{ + D_DEBUG_AT( Core_WindowStack, "%s( %p, %p )\n", __FUNCTION__, stack, image ); + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + D_ASSERT( image != NULL ); + + if (!(image->type & CSTF_SHARED)) + return DFB_INVARG; + + /* Lock the window stack. */ + if (dfb_windowstack_lock( stack )) + return DFB_FUSION; + + /* if the surface is changed */ + if (stack->bg.image != image) { + /* detach listener from old surface and unlink it */ + if (stack->bg.image) { + dfb_surface_detach_global( stack->bg.image, + &stack->bg.image_reaction ); + + dfb_surface_unlink( &stack->bg.image ); + } + + /* link surface object */ + dfb_surface_link( &stack->bg.image, image ); + + /* attach listener to new surface */ + dfb_surface_attach_global( image, + DFB_WINDOWSTACK_BACKGROUND_IMAGE_LISTENER, + stack, &stack->bg.image_reaction ); + } + + /* force an update of the window stack */ + if (stack->bg.mode == DLBM_IMAGE || stack->bg.mode == DLBM_TILE) + dfb_windowstack_repaint_all( stack ); + + /* Unlock the window stack. */ + dfb_windowstack_unlock( stack ); + + return DFB_OK; +} + +DFBResult +dfb_windowstack_set_background_color( CoreWindowStack *stack, + const DFBColor *color ) +{ + D_ASSERT( color != NULL ); + + D_DEBUG_AT( Core_WindowStack, "%s( %p, 0x%08x )\n", __FUNCTION__, stack, + PIXEL_ARGB( color->a, color->r, color->g, color->b ) ); + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + + /* Lock the window stack. */ + if (dfb_windowstack_lock( stack )) + return DFB_FUSION; + + /* do nothing if color didn't change */ + if (!DFB_COLOR_EQUAL( stack->bg.color, *color )) { + /* set new color */ + stack->bg.color = *color; + + /* force an update of the window stack */ + if (stack->bg.mode == DLBM_COLOR) + dfb_windowstack_repaint_all( stack ); + } + + /* Unlock the window stack. */ + dfb_windowstack_unlock( stack ); + + return DFB_OK; +} + +DFBResult +dfb_windowstack_set_background_color_index( CoreWindowStack *stack, + int index ) +{ + D_DEBUG_AT( Core_WindowStack, "%s( %p, %d )\n", __FUNCTION__, stack, index ); + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + + /* Lock the window stack. */ + if (dfb_windowstack_lock( stack )) + return DFB_FUSION; + + /* do nothing if color didn't change */ + if (stack->bg.color_index != index) { + /* set new color index */ + stack->bg.color_index = index; + + /* force an update of the window stack */ + if (stack->bg.mode == DLBM_COLOR) + dfb_windowstack_repaint_all( stack ); + } + + /* Unlock the window stack. */ + dfb_windowstack_unlock( stack ); + + return DFB_OK; +} + +/**********************************************************************************************************************/ + +/* + * cursor control + */ + +DFBResult +dfb_windowstack_cursor_enable( CoreDFB *core, CoreWindowStack *stack, bool enable ) +{ + DFBResult ret; + + D_DEBUG_AT( Core_WindowStack, "%s( %p, %s )\n", __FUNCTION__, stack, enable ? "enable" : "disable" ); + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + + /* Lock the window stack. */ + if (dfb_windowstack_lock( stack )) + return DFB_FUSION; + + stack->cursor.set = true; + + if (dfb_config->no_cursor || stack->cursor.enabled == enable) { + dfb_windowstack_unlock( stack ); + return DFB_OK; + } + + if (enable && !stack->cursor.surface) { + ret = load_default_cursor( core, stack ); + if (ret) { + dfb_windowstack_unlock( stack ); + return ret; + } + } + + /* Keep state. */ + stack->cursor.enabled = enable; + + /* Notify WM. */ + dfb_wm_update_cursor( stack, enable ? CCUF_ENABLE : CCUF_DISABLE ); + + /* Unlock the window stack. */ + dfb_windowstack_unlock( stack ); + + return DFB_OK; +} + +DFBResult +dfb_windowstack_cursor_set_opacity( CoreWindowStack *stack, u8 opacity ) +{ + D_DEBUG_AT( Core_WindowStack, "%s( %p, 0x%02x )\n", __FUNCTION__, stack, opacity ); + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + + /* Lock the window stack. */ + if (dfb_windowstack_lock( stack )) + return DFB_FUSION; + + if (stack->cursor.opacity != opacity) { + /* Set new opacity. */ + stack->cursor.opacity = opacity; + + /* Notify WM. */ + if (stack->cursor.enabled) + dfb_wm_update_cursor( stack, CCUF_OPACITY ); + } + + /* Unlock the window stack. */ + dfb_windowstack_unlock( stack ); + + return DFB_OK; +} + +DFBResult +dfb_windowstack_cursor_set_shape( CoreWindowStack *stack, + CoreSurface *shape, + int hot_x, + int hot_y ) +{ + DFBResult ret; + CoreSurface *cursor; + CoreCursorUpdateFlags flags = CCUF_SHAPE; + + D_DEBUG_AT( Core_WindowStack, "%s( %p, %p, hot %d, %d ) <- size %dx%d\n", + __FUNCTION__, stack, shape, hot_x, hot_y, + shape->config.size.w, shape->config.size.h ); + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + D_ASSERT( shape != NULL ); + + if (dfb_config->no_cursor) + return DFB_OK; + + /* Lock the window stack. */ + if (dfb_windowstack_lock( stack )) + return DFB_FUSION; + + cursor = stack->cursor.surface; + if (!cursor) { + D_ASSUME( !stack->cursor.enabled ); + + /* Create the a surface for the shape. */ + ret = create_cursor_surface( stack, shape->config.size.w, shape->config.size.h ); + if (ret) { + dfb_windowstack_unlock( stack ); + return ret; + } + + cursor = stack->cursor.surface; + } + else if (stack->cursor.size.w != shape->config.size.w || stack->cursor.size.h != shape->config.size.h) { + dfb_surface_unlink( &stack->cursor.surface ); + + /* Recreate the surface for the shape. */ + ret = create_cursor_surface( stack, shape->config.size.w, shape->config.size.h ); + if (ret) { + dfb_windowstack_unlock( stack ); + return ret; + } + + cursor = stack->cursor.surface; + + + stack->cursor.size.w = shape->config.size.w; + stack->cursor.size.h = shape->config.size.h; + + /* Notify about new size/shape. */ + flags |= CCUF_SIZE | CCUF_SHAPE; + } + + if (stack->cursor.hot.x != hot_x || stack->cursor.hot.y != hot_y) { + stack->cursor.hot.x = hot_x; + stack->cursor.hot.y = hot_y; + + /* Notify about new position. */ + flags |= CCUF_POSITION; + } + + /* Copy the content of the new shape. */ + dfb_gfx_copy( shape, cursor, NULL ); + + cursor->config.caps = ((cursor->config.caps & ~DSCAPS_PREMULTIPLIED) | (shape->config.caps & DSCAPS_PREMULTIPLIED)); + + /* Notify the WM. */ + if (stack->cursor.enabled) + dfb_wm_update_cursor( stack, flags ); + + /* Unlock the window stack. */ + dfb_windowstack_unlock( stack ); + + return DFB_OK; +} + +DFBResult +dfb_windowstack_cursor_warp( CoreWindowStack *stack, int x, int y ) +{ + D_DEBUG_AT( Core_WindowStack, "%s( %p, %d, %d )\n", __FUNCTION__, stack, x, y ); + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + + /* Lock the window stack. */ + if (dfb_windowstack_lock( stack )) + return DFB_FUSION; + + if (x < 0) + x = 0; + else if (x > stack->width - 1) + x = stack->width - 1; + + if (y < 0) + y = 0; + else if (y > stack->height - 1) + y = stack->height - 1; + + if (stack->cursor.x != x || stack->cursor.y != y) { + stack->cursor.x = x; + stack->cursor.y = y; + + /* Notify the WM. */ + if (stack->cursor.enabled) + dfb_wm_update_cursor( stack, CCUF_POSITION ); + } + + /* Unlock the window stack. */ + dfb_windowstack_unlock( stack ); + + return DFB_OK; +} + +DFBResult +dfb_windowstack_cursor_set_acceleration( CoreWindowStack *stack, + int numerator, + int denominator, + int threshold ) +{ + D_DEBUG_AT( Core_WindowStack, "%s( %p, %d, %d, %d )\n", + __FUNCTION__, stack, numerator, denominator, threshold ); + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + + /* Lock the window stack. */ + if (dfb_windowstack_lock( stack )) + return DFB_FUSION; + + stack->cursor.numerator = numerator; + stack->cursor.denominator = denominator; + stack->cursor.threshold = threshold; + + /* Unlock the window stack. */ + dfb_windowstack_unlock( stack ); + + return DFB_OK; +} + +DFBResult +dfb_windowstack_get_cursor_position( CoreWindowStack *stack, int *ret_x, int *ret_y ) +{ + D_DEBUG_AT( Core_WindowStack, "%s( %p, %p, %p )\n", __FUNCTION__, stack, ret_x, ret_y ); + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + D_ASSUME( ret_x != NULL || ret_y != NULL ); + + /* Lock the window stack. */ + if (dfb_windowstack_lock( stack )) + return DFB_FUSION; + + if (ret_x) + *ret_x = stack->cursor.x; + + if (ret_y) + *ret_y = stack->cursor.y; + + /* Unlock the window stack. */ + dfb_windowstack_unlock( stack ); + + return DFB_OK; +} + +/**********************************************************************************************************************/ + +static ReactionResult +stack_input_core_listener( const void *msg_data, + void *ctx ) +{ + const CoreInputCoreNotification *notification = msg_data; + CoreWindowStack *stack = ctx; + + (void) notification; + + D_DEBUG_AT( Core_WindowStack, "%s( %p, %p, %d )\n", __FUNCTION__, msg_data, ctx, notification->device_id ); + + D_ASSERT( msg_data != NULL ); + D_MAGIC_ASSERT( stack, CoreWindowStack ); + + /* Lock the window stack. */ + if (dfb_windowstack_lock( stack )) + return RS_REMOVE; + + /* Attach to all input devices */ + dfb_input_enumerate_devices( stack_attach_devices, stack, DICAPS_ALL ); + + /* Unlock the window stack. */ + dfb_windowstack_unlock( stack ); + + return RS_OK; +} + +ReactionResult +_dfb_windowstack_inputdevice_listener( const void *msg_data, + void *ctx ) +{ + const DFBInputEvent *event = msg_data; + CoreWindowStack *stack = ctx; + + D_DEBUG_AT( Core_WindowStack, "%s( %p, %p )\n", __FUNCTION__, msg_data, ctx ); + + D_ASSERT( msg_data != NULL ); + D_MAGIC_ASSERT( stack, CoreWindowStack ); + + /* Lock the window stack. */ + if (dfb_windowstack_lock( stack )) + return RS_REMOVE; + + /* Call the window manager to dispatch the event. */ + if (dfb_layer_context_active( stack->context )) + dfb_wm_process_input( stack, event ); + + /* Unlock the window stack. */ + dfb_windowstack_unlock( stack ); + + return RS_OK; +} + +/* + * listen to the background image + */ +ReactionResult +_dfb_windowstack_background_image_listener( const void *msg_data, + void *ctx ) +{ + const CoreSurfaceNotification *notification = msg_data; + CoreWindowStack *stack = ctx; + + D_DEBUG_AT( Core_WindowStack, "%s( %p, %p )\n", __FUNCTION__, msg_data, ctx ); + + D_ASSERT( notification != NULL ); + D_MAGIC_ASSERT( stack, CoreWindowStack ); + + if (notification->flags & CSNF_DESTROY) { + if (stack->bg.image == notification->surface) { + D_ERROR( "Core/WindowStack: Surface for background vanished.\n" ); + + stack->bg.mode = DLBM_COLOR; + stack->bg.image = NULL; + + dfb_windowstack_repaint_all( stack ); + } + + return RS_REMOVE; + } + + if (notification->flags & (CSNF_FLIP | CSNF_SIZEFORMAT)) + dfb_windowstack_repaint_all( stack ); + + return RS_OK; +} + +/**********************************************************************************************************************/ + +/* + * internals + */ + +static DFBEnumerationResult +stack_attach_devices( CoreInputDevice *device, + void *ctx ) +{ + StackDevice *dev; + DFBInputDeviceID id = dfb_input_device_id( device ); + CoreWindowStack *stack = (CoreWindowStack*) ctx; + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + + direct_list_foreach (dev, stack->devices) { + if (dev->id == id) + return DFENUM_OK; + } + + dev = SHCALLOC( stack->shmpool, 1, sizeof(StackDevice) ); + if (!dev) { + D_ERROR( "Core/WindowStack: Could not allocate %zu bytes\n", sizeof(StackDevice) ); + return DFENUM_CANCEL; + } + + dev->id = id; + + direct_list_prepend( &stack->devices, &dev->link ); + + dfb_input_attach( device, _dfb_windowstack_inputdevice_listener, ctx, &dev->reaction ); + + return DFENUM_OK; +} + +/* + * internal function that installs the cursor window + * and fills it with data from 'cursor.dat' + */ +static DFBResult +load_default_cursor( CoreDFB *core, CoreWindowStack *stack ) +{ + DFBResult ret; + int i; + FILE *f; + CoreSurfaceBufferLock lock; + void *data; + + D_DEBUG_AT( Core_WindowStack, "%s( %p )\n", __FUNCTION__, stack ); + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + + if (!stack->cursor.surface) { + ret = create_cursor_surface( stack, 40, 40 ); + if (ret) + return ret; + } + else { + stack->cursor.hot.x = 0; + stack->cursor.hot.y = 0; + stack->cursor.size.w = 40; + stack->cursor.size.h = 40; + } + + /* lock the cursor surface */ + ret = dfb_surface_lock_buffer( stack->cursor.surface, CSBR_BACK, CSAID_CPU, CSAF_WRITE, &lock ); + if (ret) { + D_ERROR( "Core/WindowStack: cannot lock the cursor surface!\n" ); + return ret; + } + + data = lock.addr; + + /* initialize as empty cursor */ + memset( data, 0, 40 * lock.pitch ); + + /* open the file containing the cursors image data */ + f = fopen( CURSORFILE, "rb" ); + if (!f) { + ret = errno2result( errno ); + + /* ignore a missing cursor file */ + if (ret == DFB_FILENOTFOUND) + ret = DFB_OK; + else + D_PERROR( "Core/WindowStack: `" CURSORFILE "` could not be opened!\n" ); + + goto finish; + } + + /* read from file directly into the cursor window surface */ + for (i=0; i<40; i++) { + if (fread( data, MIN (40*4, lock.pitch), 1, f ) != 1) { + ret = errno2result( errno ); + + D_ERROR( "Core/WindowStack: unexpected end or read error of cursor data!\n" ); + + goto finish; + } +#ifdef WORDS_BIGENDIAN + { + int i = MIN (40, lock.pitch/4); + u32 *tmp_data = data; + + while (i--) { + *tmp_data = (*tmp_data & 0xFF000000) >> 24 | + (*tmp_data & 0x00FF0000) >> 8 | + (*tmp_data & 0x0000FF00) << 8 | + (*tmp_data & 0x000000FF) << 24; + ++tmp_data; + } + } +#endif + data += lock.pitch; + } + +finish: + if (f) + fclose( f ); + + dfb_surface_unlock_buffer( stack->cursor.surface, &lock ); + + return ret; +} + +static DFBResult +create_cursor_surface( CoreWindowStack *stack, + int width, + int height ) +{ + DFBResult ret; + CoreSurface *surface; + CoreLayer *layer; + CoreLayerContext *context; + DFBSurfaceCapabilities surface_caps = DSCAPS_NONE; + + D_DEBUG_AT( Core_WindowStack, "%s( %p, %dx%d )\n", __FUNCTION__, stack, width, height ); + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + D_ASSERT( stack->cursor.surface == NULL ); + + context = stack->context; + + D_ASSERT( context != NULL ); + + layer = dfb_layer_at( context->layer_id ); + + D_ASSERT( layer != NULL ); + + stack->cursor.x = stack->width / 2; + stack->cursor.y = stack->height / 2; + stack->cursor.hot.x = 0; + stack->cursor.hot.y = 0; + stack->cursor.size.w = width; + stack->cursor.size.h = height; + + if (context->config.buffermode == DLBM_WINDOWS) + D_WARN( "cursor not yet visible with DLBM_WINDOWS" ); + + dfb_surface_caps_apply_policy( stack->cursor.policy, &surface_caps ); + + /* Create the cursor surface. */ + ret = dfb_surface_create_simple( layer->core, width, height, DSPF_ARGB, + surface_caps, CSTF_SHARED | CSTF_CURSOR, + 0, /* FIXME: no shared cursor objects, no cursor id */ + NULL, &surface ); + if (ret) { + D_ERROR( "Core/WindowStack: Failed creating a surface for software cursor!\n" ); + return ret; + } + + dfb_surface_globalize( surface ); + + stack->cursor.surface = surface; + + return DFB_OK; +} + diff --git a/Source/DirectFB/src/core/windowstack.h b/Source/DirectFB/src/core/windowstack.h new file mode 100755 index 0000000..6d7bed5 --- /dev/null +++ b/Source/DirectFB/src/core/windowstack.h @@ -0,0 +1,105 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __CORE__WINDOWSTACK_H__ +#define __CORE__WINDOWSTACK_H__ + +#include +#include + +#include + +/* + * allocates a WindowStack, initializes it, registers it for input events + */ +CoreWindowStack *dfb_windowstack_create ( CoreLayerContext *context ); + +void dfb_windowstack_detach_devices( CoreWindowStack *stack ); + +void dfb_windowstack_destroy( CoreWindowStack *stack ); + +void dfb_windowstack_resize ( CoreWindowStack *stack, + int width, + int height, + int rotation ); + +DirectResult dfb_windowstack_lock ( CoreWindowStack *stack ); + +DirectResult dfb_windowstack_unlock ( CoreWindowStack *stack ); + +/* + * repaints all window on a window stack + */ +DFBResult dfb_windowstack_repaint_all( CoreWindowStack *stack ); + +/* + * background handling + */ +DFBResult dfb_windowstack_set_background_mode ( CoreWindowStack *stack, + DFBDisplayLayerBackgroundMode mode ); + +DFBResult dfb_windowstack_set_background_image( CoreWindowStack *stack, + CoreSurface *image ); + +DFBResult dfb_windowstack_set_background_color( CoreWindowStack *stack, + const DFBColor *color ); + +DFBResult dfb_windowstack_set_background_color_index( CoreWindowStack *stack, + int index ); + + +/* + * cursor control + */ +DFBResult dfb_windowstack_cursor_enable( CoreDFB *core, + CoreWindowStack *stack, + bool enable ); + +DFBResult dfb_windowstack_cursor_set_shape( CoreWindowStack *stack, + CoreSurface *shape, + int hot_x, + int hot_y ); + +DFBResult dfb_windowstack_cursor_set_opacity( CoreWindowStack *stack, + u8 opacity ); + +DFBResult dfb_windowstack_cursor_set_acceleration( CoreWindowStack *stack, + int numerator, + int denominator, + int threshold ); + +DFBResult dfb_windowstack_cursor_warp( CoreWindowStack *stack, + int x, + int y ); + + +DFBResult dfb_windowstack_get_cursor_position (CoreWindowStack *stack, + int *x, + int *y); + +#endif diff --git a/Source/DirectFB/src/core/wm.c b/Source/DirectFB/src/core/wm.c new file mode 100755 index 0000000..fb9148c --- /dev/null +++ b/Source/DirectFB/src/core/wm.c @@ -0,0 +1,1440 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +DEFINE_MODULE_DIRECTORY( dfb_core_wm_modules, "wm", DFB_CORE_WM_ABI_VERSION ); + + +D_DEBUG_DOMAIN( Core_WM, "Core/WM", "DirectFB WM Core" ); + +/**********************************************************************************************************************/ + +typedef struct { + int magic; + + DirectLink *stacks; + + int abi; + + char *name; + CoreWMInfo info; + void *data; + + FusionSHMPoolShared *shmpool; + + FusionReactor *reactor; +} DFBWMCoreShared; + +struct __DFB_DFBWMCore { + int magic; + + CoreDFB *core; + + DFBWMCoreShared *shared; + + + DirectModuleEntry *module; + const CoreWMFuncs *funcs; + void *data; +}; + + +DFB_CORE_PART( wm_core, WMCore ); + +/**********************************************************************************************************************/ + +static DFBResult load_module( const char *name ); + +/**********************************************************************************************************************/ + +static DFBWMCore *wm_local = NULL; /* FIXME */ +static DFBWMCoreShared *wm_shared = NULL; /* FIXME */ + + +static DFBResult +dfb_wm_core_initialize( CoreDFB *core, + DFBWMCore *data, + DFBWMCoreShared *shared ) +{ + DFBResult ret; + + D_DEBUG_AT( Core_WM, "dfb_wm_core_initialize( %p, %p, %p )\n", core, data, shared ); + + D_ASSERT( data != NULL ); + D_ASSERT( shared != NULL ); + + data->core = core; + data->shared = shared; + + + wm_local = data; /* FIXME */ + wm_shared = shared; /* FIXME */ + + wm_shared->shmpool = dfb_core_shmpool( core ); + + /* Set ABI version for the session. */ + wm_shared->abi = DFB_CORE_WM_ABI_VERSION; + + /* Load the module. */ + ret = load_module( dfb_config->wm ); + if (ret) + goto error; + + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->GetWMInfo != NULL ); + D_ASSERT( wm_local->funcs->Initialize != NULL ); + + /* Query module information. */ + wm_local->funcs->GetWMInfo( &wm_shared->info ); + + D_INFO( "DirectFB/Core/WM: %s %d.%d (%s)\n", + wm_shared->info.name, wm_shared->info.version.major, + wm_shared->info.version.minor, wm_shared->info.vendor ); + + ret = DFB_NOSHAREDMEMORY; + + /* Store module name in shared memory. */ + wm_shared->name = SHSTRDUP( wm_shared->shmpool, wm_local->module->name ); + if (!wm_shared->name) { + D_OOSHM(); + goto error; + } + + /* Allocate shared window manager data. */ + if (wm_shared->info.wm_shared_size) { + wm_shared->data = SHCALLOC( wm_shared->shmpool, 1, wm_shared->info.wm_shared_size ); + if (!wm_shared->data) { + D_OOSHM(); + goto error; + } + } + + ret = DFB_NOSYSTEMMEMORY; + + /* Allocate local window manager data. */ + if (wm_shared->info.wm_data_size) { + wm_local->data = D_CALLOC( 1, wm_shared->info.wm_data_size ); + if (!wm_local->data) { + D_OOM(); + goto error; + } + } + + wm_shared->reactor = fusion_reactor_new( 0, "WM", dfb_core_world(core) ); + + /* Initialize window manager. */ + ret = wm_local->funcs->Initialize( core, wm_local->data, wm_shared->data ); + if (ret) { + D_DERROR( ret, "DirectFB/Core/WM: Could not initialize window manager!\n" ); + goto error; + } + + D_MAGIC_SET( data, DFBWMCore ); + D_MAGIC_SET( shared, DFBWMCoreShared ); + + return DFB_OK; + +error: + if (wm_local->data) + D_FREE( wm_local->data ); + + if (wm_shared->data) + SHFREE( wm_shared->shmpool, wm_shared->data ); + + if (wm_shared->name) + SHFREE( wm_shared->shmpool, wm_shared->name ); + + wm_local = NULL; + wm_shared = NULL; + + return ret; +} + +static DFBResult +dfb_wm_core_join( CoreDFB *core, + DFBWMCore *data, + DFBWMCoreShared *shared ) +{ + DFBResult ret; + CoreWMInfo info; + + D_DEBUG_AT( Core_WM, "dfb_wm_core_join( %p, %p, %p )\n", core, data, shared ); + + D_ASSERT( data != NULL ); + D_MAGIC_ASSERT( shared, DFBWMCoreShared ); + + data->core = core; + data->shared = shared; + + + wm_local = data; /* FIXME */ + wm_shared = shared; /* FIXME */ + + /* Check binary version numbers. */ + if (wm_shared->abi != DFB_CORE_WM_ABI_VERSION) { + D_ERROR( "DirectFB/Core/WM: ABI version of running core instance (%d) doesn't match %d!\n", + wm_shared->abi, DFB_CORE_WM_ABI_VERSION ); + ret = DFB_VERSIONMISMATCH; + goto error; + } + + /* Load the module that is used by the running session. */ + ret = load_module( wm_shared->name ); + if (ret) + goto error; + + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->GetWMInfo != NULL ); + D_ASSERT( wm_local->funcs->Join != NULL ); + + /* Query module information. */ + wm_local->funcs->GetWMInfo( &info ); + + /* Check binary version numbers. */ + if (info.version.binary != wm_shared->info.version.binary) { + D_ERROR( "DirectFB/Core/WM: ABI version of running module instance (%d) doesn't match %d!\n", + wm_shared->info.version.binary, info.version.binary ); + ret = DFB_VERSIONMISMATCH; + goto error; + } + + /* Allocate window manager data. */ + if (wm_shared->info.wm_data_size) { + wm_local->data = D_CALLOC( 1, wm_shared->info.wm_data_size ); + if (!wm_local->data) { + D_WARN( "out of memory" ); + ret = DFB_NOSYSTEMMEMORY; + goto error; + } + } + + /* Join window manager. */ + ret = wm_local->funcs->Join( core, wm_local->data, wm_shared->data ); + if (ret) { + D_DERROR( ret, "DirectFB/Core/WM: Could not join window manager!\n" ); + goto error; + } + + D_MAGIC_SET( data, DFBWMCore ); + + return DFB_OK; + +error: + if (wm_local->data) + D_FREE( wm_local->data ); + + wm_local = NULL; + wm_shared = NULL; + + return ret; +} + +static DFBResult +dfb_wm_core_shutdown( DFBWMCore *data, + bool emergency ) +{ + DFBResult ret; + DFBWMCoreShared *shared; + + D_DEBUG_AT( Core_WM, "dfb_wm_core_shutdown( %p, %semergency )\n", data, emergency ? "" : "no " ); + + D_MAGIC_ASSERT( data, DFBWMCore ); + D_MAGIC_ASSERT( data->shared, DFBWMCoreShared ); + + shared = data->shared; + + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->Shutdown != NULL ); + D_ASSERT( wm_shared != NULL ); + + fusion_reactor_destroy( wm_shared->reactor ); + + /* Shutdown window manager. */ + ret = wm_local->funcs->Shutdown( emergency, wm_local->data, wm_shared->data ); + + /* Unload the module. */ + direct_module_unref( wm_local->module ); + + /* Deallocate local window manager data. */ + if (wm_local->data) + D_FREE( wm_local->data ); + + /* Deallocate shared window manager data. */ + if (wm_shared->data) + SHFREE( wm_shared->shmpool, wm_shared->data ); + + /* Free module name in shared memory. */ + SHFREE( wm_shared->shmpool, wm_shared->name ); + + wm_local = NULL; + wm_shared = NULL; + + + D_MAGIC_CLEAR( data ); + D_MAGIC_CLEAR( shared ); + + return ret; +} + +static DFBResult +dfb_wm_core_leave( DFBWMCore *data, + bool emergency ) +{ + DFBResult ret; + DFBWMCoreShared *shared; + + D_DEBUG_AT( Core_WM, "dfb_wm_core_leave( %p, %semergency )\n", data, emergency ? "" : "no " ); + + D_MAGIC_ASSERT( data, DFBWMCore ); + D_MAGIC_ASSERT( data->shared, DFBWMCoreShared ); + + shared = data->shared; + + + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->Leave != NULL ); + D_ASSERT( wm_shared != NULL ); + + /* Leave window manager. */ + ret = wm_local->funcs->Leave( emergency, wm_local->data, wm_shared->data ); + + /* Unload the module. */ + direct_module_unref( wm_local->module ); + + /* Deallocate local window manager data. */ + if (wm_local->data) + D_FREE( wm_local->data ); + + wm_local = NULL; + wm_shared = NULL; + + + D_MAGIC_CLEAR( data ); + + return ret; +} + +static DFBResult +dfb_wm_core_suspend( DFBWMCore *data ) +{ + DFBWMCoreShared *shared; + + D_DEBUG_AT( Core_WM, "%s( %p )\n", __FUNCTION__, data ); + + D_MAGIC_ASSERT( data, DFBWMCore ); + D_MAGIC_ASSERT( data->shared, DFBWMCoreShared ); + + shared = data->shared; + + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->Suspend != NULL ); + D_ASSERT( wm_shared != NULL ); + + return wm_local->funcs->Suspend( wm_local->data, wm_shared->data ); +} + +static DFBResult +dfb_wm_core_resume( DFBWMCore *data ) +{ + DFBWMCoreShared *shared; + + D_DEBUG_AT( Core_WM, "%s( %p )\n", __FUNCTION__, data ); + + D_MAGIC_ASSERT( data, DFBWMCore ); + D_MAGIC_ASSERT( data->shared, DFBWMCoreShared ); + + shared = data->shared; + + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->Resume != NULL ); + D_ASSERT( wm_shared != NULL ); + + return wm_local->funcs->Resume( wm_local->data, wm_shared->data ); +} + +DFBResult +dfb_wm_close_all_stacks( void *data ) +{ + CoreLayerContext *context; + CoreWindowStack *stack, *next; + DFBWMCore *local; + DFBWMCoreShared *shared; + + D_DEBUG_AT( Core_WM, "%s( %p )\n", __FUNCTION__, data ); + + local = data; + + D_MAGIC_ASSERT( local, DFBWMCore ); + D_ASSERT( local->funcs != NULL ); + D_ASSERT( local->funcs->CloseStack != NULL ); + + shared = local->shared; + + D_MAGIC_ASSERT( shared, DFBWMCoreShared ); + + D_DEBUG_AT( Core_WM, " -> checking %d stacks...\n", direct_list_count_elements_EXPENSIVE(shared->stacks) ); + + direct_list_foreach_safe (stack, next, shared->stacks) { + D_DEBUG_AT( Core_WM, " -> checking %p...\n", stack ); + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + + context = stack->context; + D_MAGIC_ASSERT( context, CoreLayerContext ); + + D_DEBUG_AT( Core_WM, " -> ref context %p...\n", context ); + + dfb_layer_context_ref( context ); + + dfb_layer_context_lock( context ); + + if (stack->flags & CWSF_INITIALIZED) { + D_DEBUG_AT( Core_WM, " => CLOSING %p\n", stack ); + dfb_wm_close_stack( stack ); + } + + dfb_layer_context_unlock( context ); + + D_DEBUG_AT( Core_WM, " -> unref context %p...\n", context ); + + dfb_layer_context_unref( context ); + } + + return DFB_OK; +} + +/**************************************************************************************************/ + +static DFBResult +load_module( const char *name ) +{ + DirectLink *l; + + D_ASSERT( wm_local != NULL ); + + direct_modules_explore_directory( &dfb_core_wm_modules ); + + direct_list_foreach( l, dfb_core_wm_modules.entries ) { + DirectModuleEntry *module = (DirectModuleEntry*) l; + const CoreWMFuncs *funcs; + + funcs = direct_module_ref( module ); + if (!funcs) + continue; + + if (!name || !strcasecmp( name, module->name )) { + if (wm_local->module) + direct_module_unref( wm_local->module ); + + wm_local->module = module; + wm_local->funcs = funcs; + } + else + direct_module_unref( module ); + } + + if (!wm_local->module) { + if (name) + D_ERROR( "DirectFB/WM: Window manager module '%s' not found!\n", name ); + else + D_ERROR( "DirectFB/WM: No window manager module found!\n" ); + + return DFB_NOIMPL; + } + + return DFB_OK; +} + +/**************************************************************************************************/ + +static void +convert_config( DFBWindowConfig *config, + const CoreWindowConfig *from ) +{ + config->bounds = from->bounds; + config->opacity = from->opacity; + config->stacking = from->stacking; + config->options = from->options; + config->events = from->events; + config->color = from->color; + config->color_key = from->color_key; + config->opaque = from->opaque; +// config->key_selection = DWKS_ALL; // FIXME: implement +// config->keys = NULL; // FIXME: implement +// config->num_keys = 0; // FIXME: implement + config->association = from->association; + config->src_geometry = from->src_geometry; + config->dst_geometry = from->dst_geometry; + config->cursor_flags = from->cursor_flags; + config->cursor_resolution = from->cursor_resolution; +} + +static void +convert_state( DFBWindowState *state, + const CoreWindowFlags flags ) +{ + state->flags = DWSTATE_NONE; + + if (flags & CWF_INSERTED) + state->flags |= DWSTATE_INSERTED; + + if (flags & CWF_FOCUSED) + state->flags |= DWSTATE_FOCUSED; + + if (flags & CWF_ENTERED) + state->flags |= DWSTATE_ENTERED; +} + +/**************************************************************************************************/ + +typedef struct { + ReactionFunc func; + void *ctx; +} AttachContext; + +static DFBEnumerationResult +wm_window_attach_callback( CoreWindow *window, + void *ctx ) +{ + AttachContext *context = ctx; + + CoreWM_WindowAdd add; + + add.info.window_id = window->id; + add.info.caps = window->caps; + add.info.resource_id = window->resource_id; + + convert_config( &add.info.config, &window->config ); + + convert_state( &add.info.state, window->flags ); + + context->func( &add, context->ctx ); + + return DFENUM_OK; +} + +DFBResult +dfb_wm_attach( CoreDFB *core, + int channel, + ReactionFunc func, + void *ctx, + Reaction *reaction ) +{ + D_ASSERT( wm_shared != NULL ); + + if (channel == CORE_WM_WINDOW_ADD) { + CoreWindowStack *stack = (CoreWindowStack *) wm_shared->stacks; + + if (stack) { + DFBResult ret; + AttachContext context = { func, ctx }; + + dfb_windowstack_lock( stack ); + + ret = dfb_wm_enum_windows( stack, wm_window_attach_callback, &context ); + if (ret) + D_WARN( "could not enumerate windows" ); + + ret = fusion_reactor_attach_channel( wm_shared->reactor, channel, func, ctx, reaction ); + + dfb_windowstack_unlock( stack ); + + return ret; + } + } + + return fusion_reactor_attach_channel( wm_shared->reactor, channel, func, ctx, reaction ); +} + +DFBResult +dfb_wm_detach( CoreDFB *core, + Reaction *reaction ) +{ + D_ASSERT( wm_shared != NULL ); + + return fusion_reactor_detach( wm_shared->reactor, reaction ); +} + +DFBResult +dfb_wm_dispatch( CoreDFB *core, + int channel, + const void *data, + int size ) +{ + D_ASSERT( wm_shared != NULL ); + + return fusion_reactor_dispatch_channel( wm_shared->reactor, channel, data, size, true, NULL ); +} + +DFBResult +dfb_wm_dispatch_WindowAdd( CoreDFB *core, + CoreWindow *window ) +{ + CoreWM_WindowAdd add; + + add.info.window_id = window->id; + add.info.caps = window->caps; + add.info.resource_id = window->resource_id; + + convert_config( &add.info.config, &window->config ); + + convert_state( &add.info.state, window->flags ); + + return dfb_wm_dispatch( core, CORE_WM_WINDOW_ADD, &add, sizeof(add) ); +} + +DFBResult +dfb_wm_dispatch_WindowRemove( CoreDFB *core, + CoreWindow *window ) +{ + CoreWM_WindowRemove remove; + + remove.window_id = window->id; + + return dfb_wm_dispatch( core, CORE_WM_WINDOW_REMOVE, &remove, sizeof(remove) ); +} + +DFBResult +dfb_wm_dispatch_WindowConfig( CoreDFB *core, + CoreWindow *window, + DFBWindowConfigFlags flags ) +{ + CoreWM_WindowConfig config; + + config.window_id = window->id; + config.flags = flags; + + convert_config( &config.config, &window->config ); + + return dfb_wm_dispatch( core, CORE_WM_WINDOW_CONFIG, &config, sizeof(config) ); +} + +DFBResult +dfb_wm_dispatch_WindowState( CoreDFB *core, + CoreWindow *window ) +{ + CoreWM_WindowState state; + + state.window_id = window->id; + + convert_state( &state.state, window->flags ); + + return dfb_wm_dispatch( core, CORE_WM_WINDOW_STATE, &state, sizeof(state) ); +} + +DFBResult +dfb_wm_dispatch_WindowRestack( CoreDFB *core, + CoreWindow *window, + unsigned int index ) +{ + CoreWM_WindowRestack restack; + + restack.window_id = window->id; + restack.index = index; + + return dfb_wm_dispatch( core, CORE_WM_WINDOW_RESTACK, &restack, sizeof(restack) ); +} + +DFBResult +dfb_wm_dispatch_WindowFocus( CoreDFB *core, + CoreWindow *window ) +{ + CoreWM_WindowFocus focus; + + focus.window_id = window->id; + + return dfb_wm_dispatch( core, CORE_WM_WINDOW_FOCUS, &focus, sizeof(focus) ); +} + +/**************************************************************************************************/ + +void +dfb_wm_get_info( CoreWMInfo *info ) +{ + D_ASSERT( wm_shared != NULL ); + + D_ASSERT( info != NULL ); + + *info = wm_shared->info; +} + +DFBResult +dfb_wm_post_init( CoreDFB *core ) +{ + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->Resume != NULL ); + D_ASSERT( wm_shared != NULL ); + + return wm_local->funcs->PostInit( wm_local->data, wm_shared->data ); +} + +/**************************************************************************************************/ + +DFBResult +dfb_wm_init_stack( CoreWindowStack *stack ) +{ + DFBResult ret; + + D_DEBUG_AT( Core_WM, "%s( %p )\n", __FUNCTION__, stack ); + + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->InitStack != NULL ); + D_ASSERT( wm_shared != NULL ); + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + D_ASSERT( !(stack->flags & CWSF_INITIALIZED) ); + + D_MAGIC_ASSERT( stack->context, CoreLayerContext ); + FUSION_SKIRMISH_ASSERT( &stack->context->lock ); + + /* Allocate shared stack data. */ + if (wm_shared->info.stack_data_size) { + if (stack->stack_data) + SHFREE( stack->shmpool, stack->stack_data ); + + stack->stack_data = SHCALLOC( stack->shmpool, 1, wm_shared->info.stack_data_size ); + if (!stack->stack_data) { + D_WARN( "out of (shared) memory" ); + return D_OOSHM(); + } + } + + /* Window manager specific initialization. */ + ret = wm_local->funcs->InitStack( stack, wm_local->data, stack->stack_data ); + if (ret) { + if (stack->stack_data) { + SHFREE( wm_shared->shmpool, stack->stack_data ); + stack->stack_data = NULL; + } + + return ret; + } + + stack->flags |= CWSF_INITIALIZED; + + /* Add window stack to list. */ + direct_list_append( &wm_shared->stacks, &stack->link ); + + return DFB_OK; +} + +DFBResult +dfb_wm_close_stack( CoreWindowStack *stack ) +{ + D_DEBUG_AT( Core_WM, "%s( %p )\n", __FUNCTION__, stack ); + + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->CloseStack != NULL ); + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + + D_ASSUME( stack->flags & CWSF_INITIALIZED ); + + if (!(stack->flags & CWSF_INITIALIZED)) { + D_ASSUME( !(stack->flags & CWSF_ACTIVATED) ); + return DFB_OK; + } + + D_MAGIC_ASSERT( stack->context, CoreLayerContext ); + FUSION_SKIRMISH_ASSERT( &stack->context->lock ); + + /* Deactivate before deinitialization. */ + if (stack->flags & CWSF_ACTIVATED) + dfb_wm_set_active( stack, false ); + + /* + * Clear flag and remove stack first, because + * CloseStack() may cause the stack to be destroyed! + */ + stack->flags &= ~CWSF_INITIALIZED; + + /* Remove window stack from list. */ + direct_list_remove( &wm_shared->stacks, &stack->link ); + + /* Window manager specific deinitialization. */ + return wm_local->funcs->CloseStack( stack, wm_local->data, stack->stack_data ); +} + +DFBResult +dfb_wm_set_active( CoreWindowStack *stack, + bool active ) +{ + DFBResult ret; + + D_DEBUG_AT( Core_WM, "%s( %p, %sactive )\n", __FUNCTION__, stack, active ? "" : "in" ); + + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->SetActive != NULL ); + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + D_ASSERT( stack->flags & CWSF_INITIALIZED ); + + D_MAGIC_ASSERT( stack->context, CoreLayerContext ); + FUSION_SKIRMISH_ASSERT( &stack->context->lock ); + + if (active) { + D_ASSUME( !(stack->flags & CWSF_ACTIVATED) ); + + if (stack->flags & CWSF_ACTIVATED) + return DFB_OK; + + ret = wm_local->funcs->SetActive( stack, wm_local->data, stack->stack_data, true ); + + stack->flags |= CWSF_ACTIVATED; + } + else { + D_ASSUME( stack->flags & CWSF_ACTIVATED ); + + if (!(stack->flags & CWSF_ACTIVATED)) + return DFB_OK; + + ret = wm_local->funcs->SetActive( stack, wm_local->data, stack->stack_data, false ); + + stack->flags &= ~CWSF_ACTIVATED; + } + + return ret; +} + +DFBResult +dfb_wm_resize_stack( CoreWindowStack *stack, + int width, + int height ) +{ + D_DEBUG_AT( Core_WM, "%s( %p, %dx%d )\n", __FUNCTION__, stack, width, height ); + + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->ResizeStack != NULL ); + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + D_ASSERT( stack->flags & CWSF_INITIALIZED ); + + D_MAGIC_ASSERT( stack->context, CoreLayerContext ); + FUSION_SKIRMISH_ASSERT( &stack->context->lock ); + + /* Notify window manager about the new size. */ + return wm_local->funcs->ResizeStack( stack, wm_local->data, stack->stack_data, width, height ); +} + +DFBResult +dfb_wm_process_input( CoreWindowStack *stack, + const DFBInputEvent *event ) +{ + D_DEBUG_AT( Core_WM, "%s( %p, %p )\n", __FUNCTION__, stack, event ); + + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->ProcessInput != NULL ); + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + D_ASSERT( stack->flags & CWSF_INITIALIZED ); + + D_MAGIC_ASSERT( stack->context, CoreLayerContext ); + FUSION_SKIRMISH_ASSERT( &stack->context->lock ); + + D_ASSERT( event != NULL ); + + /* Dispatch input event via window manager. */ + return wm_local->funcs->ProcessInput( stack, wm_local->data, stack->stack_data, event ); +} + +DFBResult +dfb_wm_flush_keys( CoreWindowStack *stack ) +{ + D_DEBUG_AT( Core_WM, "%s( %p )\n", __FUNCTION__, stack ); + + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->FlushKeys != NULL ); + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + D_ASSERT( stack->flags & CWSF_INITIALIZED ); + + D_MAGIC_ASSERT( stack->context, CoreLayerContext ); + FUSION_SKIRMISH_ASSERT( &stack->context->lock ); + + return wm_local->funcs->FlushKeys( stack, wm_local->data, stack->stack_data ); +} + +DFBResult +dfb_wm_window_at( CoreWindowStack *stack, + int x, + int y, + CoreWindow **ret_window ) +{ + D_DEBUG_AT( Core_WM, "%s( %p, %d,%d )\n", __FUNCTION__, stack, x, y ); + + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->WindowAt != NULL ); + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + D_ASSERT( stack->flags & CWSF_INITIALIZED ); + + D_MAGIC_ASSERT( stack->context, CoreLayerContext ); + FUSION_SKIRMISH_ASSERT( &stack->context->lock ); + + D_ASSERT( ret_window != NULL ); + + return wm_local->funcs->WindowAt( stack, wm_local->data, stack->stack_data, x, y, ret_window ); +} + +DFBResult +dfb_wm_window_lookup( CoreWindowStack *stack, + DFBWindowID window_id, + CoreWindow **ret_window ) +{ + D_DEBUG_AT( Core_WM, "%s( %p, %u )\n", __FUNCTION__, stack, window_id ); + + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->WindowLookup != NULL ); + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + D_ASSERT( stack->flags & CWSF_INITIALIZED ); + + D_MAGIC_ASSERT( stack->context, CoreLayerContext ); + FUSION_SKIRMISH_ASSERT( &stack->context->lock ); + + D_ASSERT( ret_window != NULL ); + + return wm_local->funcs->WindowLookup( stack, wm_local->data, + stack->stack_data, window_id, ret_window ); +} + +DFBResult +dfb_wm_enum_windows( CoreWindowStack *stack, + CoreWMWindowCallback callback, + void *callback_ctx ) +{ + D_DEBUG_AT( Core_WM, "%s( %p, %p, %p )\n", __FUNCTION__, stack, callback, callback_ctx ); + + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->EnumWindows != NULL ); + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + D_ASSERT( stack->flags & CWSF_INITIALIZED ); + + D_MAGIC_ASSERT( stack->context, CoreLayerContext ); + FUSION_SKIRMISH_ASSERT( &stack->context->lock ); + + D_ASSERT( callback != NULL ); + + return wm_local->funcs->EnumWindows( stack, wm_local->data, + stack->stack_data, callback, callback_ctx ); +} + +/** + * Give the wm a chance to specifiy a border + */ +DFBResult +dfb_wm_get_insets( CoreWindowStack *stack, + CoreWindow *window, + DFBInsets *insets) +{ + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->GetInsets != NULL ); + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + D_ASSERT( stack->flags & CWSF_INITIALIZED ); + + D_MAGIC_ASSERT( stack->context, CoreLayerContext ); + FUSION_SKIRMISH_ASSERT( &stack->context->lock ); + + D_ASSERT( window != NULL ); + D_ASSERT( insets != NULL ); + + return wm_local->funcs->GetInsets( stack, window, insets ); +} + +/** + * Give the wm a chance to override the windows configuration + */ +DFBResult +dfb_wm_preconfigure_window( CoreWindowStack *stack, + CoreWindow *window ) +{ + DFBResult ret; + void *window_data = NULL; + + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_shared != NULL ); + D_MAGIC_ASSERT( stack, CoreWindowStack ); + D_ASSERT( stack->flags & CWSF_INITIALIZED ); + D_ASSERT( window != NULL ); + D_ASSERT( wm_local->funcs->PreConfigureWindow != NULL ); + + D_MAGIC_ASSERT( stack->context, CoreLayerContext ); + FUSION_SKIRMISH_ASSERT( &stack->context->lock ); + + D_DEBUG_AT( Core_WM, "%s( %p, %p [%d,%d-%dx%d] )\n", __FUNCTION__, + stack, window, DFB_RECTANGLE_VALS(&window->config.bounds) ); + + /* Allocate shared window data. */ + if (wm_shared->info.window_data_size) { + window_data = SHCALLOC( wm_shared->shmpool, 1, wm_shared->info.window_data_size ); + if (!window_data) { + D_WARN( "out of (shared) memory" ); + return D_OOSHM(); + } + } + + /* Keep shared window data. */ + window->window_data = window_data; + + /* Tell window manager about the new window. */ + ret = wm_local->funcs->PreConfigureWindow( stack, wm_local->data, + stack->stack_data, window, window_data ); + if (ret) { + if (window_data) { + SHFREE( wm_shared->shmpool, window_data ); + window->window_data = NULL; + } + + return ret; + } + + return DFB_OK; +} + +DFBResult +dfb_wm_add_window( CoreWindowStack *stack, + CoreWindow *window ) +{ + DFBResult ret; + + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->AddWindow != NULL ); + D_ASSERT( wm_shared != NULL ); + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + D_ASSERT( stack->flags & CWSF_INITIALIZED ); + + D_MAGIC_ASSERT( stack->context, CoreLayerContext ); + FUSION_SKIRMISH_ASSERT( &stack->context->lock ); + + D_ASSERT( window != NULL ); + + D_DEBUG_AT( Core_WM, "%s( %p, %p [%d,%d-%dx%d] )\n", __FUNCTION__, + stack, window, DFB_RECTANGLE_VALS(&window->config.bounds) ); + + /* Tell window manager about the new window. */ + ret = wm_local->funcs->AddWindow( stack, wm_local->data, + stack->stack_data, window, window->window_data ); + if (ret) { + if (window->window_data) + SHFREE( wm_shared->shmpool, window->window_data ); + return ret; + } + return DFB_OK; +} + +DFBResult +dfb_wm_remove_window( CoreWindowStack *stack, + CoreWindow *window ) +{ + DFBResult ret; + + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->RemoveWindow != NULL ); + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + D_ASSERT( stack->flags & CWSF_INITIALIZED ); + + D_MAGIC_ASSERT( stack->context, CoreLayerContext ); + FUSION_SKIRMISH_ASSERT( &stack->context->lock ); + + D_ASSERT( window != NULL ); + + D_DEBUG_AT( Core_WM, "%s( %p, %p [%d,%d-%dx%d] )\n", __FUNCTION__, + stack, window, DFB_RECTANGLE_VALS(&window->config.bounds) ); + + /* Remove window from window manager. */ + ret = wm_local->funcs->RemoveWindow( stack, wm_local->data, + stack->stack_data, window, window->window_data ); + + /* Deallocate shared stack data. */ + if (window->window_data) + SHFREE( wm_shared->shmpool, window->window_data ); + + return ret; +} + +/** + * Let the wm set a property on a window + */ +DFBResult +dfb_wm_set_window_property( CoreWindowStack *stack, + CoreWindow *window, + const char *key, + void *value, + void **ret_old_value ) +{ + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->SetWindowProperty != NULL ); + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + D_ASSERT( stack->flags & CWSF_INITIALIZED ); + + D_MAGIC_ASSERT( stack->context, CoreLayerContext ); + FUSION_SKIRMISH_ASSERT( &stack->context->lock ); + + D_ASSERT( window != NULL ); + D_ASSERT( key != NULL ); + + D_DEBUG_AT( Core_WM, "%s( %p, %p [%d,%d-%dx%d], '%s' = %p )\n", __FUNCTION__, + stack, window, DFB_RECTANGLE_VALS(&window->config.bounds), key, value ); + + return wm_local->funcs->SetWindowProperty( stack, wm_local->data, stack->stack_data, + window, window->window_data, + key, value, ret_old_value ); +} + +/** + * get the wm property on a window + */ +DFBResult +dfb_wm_get_window_property( CoreWindowStack *stack, + CoreWindow *window, + const char *key, + void **ret_value ) +{ + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->GetWindowProperty != NULL ); + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + D_ASSERT( stack->flags & CWSF_INITIALIZED ); + + D_MAGIC_ASSERT( stack->context, CoreLayerContext ); + FUSION_SKIRMISH_ASSERT( &stack->context->lock ); + + D_ASSERT( window != NULL ); + D_ASSERT( key != NULL ); + + D_DEBUG_AT( Core_WM, "%s( %p, %p [%d,%d-%dx%d], '%s' )\n", __FUNCTION__, + stack, window, DFB_RECTANGLE_VALS(&window->config.bounds), key ); + + return wm_local->funcs->GetWindowProperty( stack, wm_local->data, stack->stack_data, + window, window->window_data, key, ret_value ); +} + +/** + * remove th wm property on a window + */ +DFBResult +dfb_wm_remove_window_property( CoreWindowStack *stack, + CoreWindow *window, + const char *key, + void **ret_value ) +{ + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->RemoveWindowProperty != NULL ); + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + D_ASSERT( stack->flags & CWSF_INITIALIZED ); + + D_MAGIC_ASSERT( stack->context, CoreLayerContext ); + FUSION_SKIRMISH_ASSERT( &stack->context->lock ); + + D_ASSERT( window != NULL ); + D_ASSERT( key != NULL ); + + D_DEBUG_AT( Core_WM, "%s( %p, %p [%d,%d-%dx%d], '%s' )\n", __FUNCTION__, + stack, window, DFB_RECTANGLE_VALS(&window->config.bounds), key ); + + return wm_local->funcs->RemoveWindowProperty( stack, wm_local->data, stack->stack_data, + window, window->window_data, key, ret_value ); +} + +DFBResult +dfb_wm_set_window_config( CoreWindow *window, + const CoreWindowConfig *config, + CoreWindowConfigFlags flags ) +{ + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->SetWindowConfig != NULL ); + + D_ASSERT( window != NULL ); + D_ASSERT( config != NULL ); + + D_MAGIC_ASSERT( window->stack, CoreWindowStack ); + D_MAGIC_ASSERT( window->stack->context, CoreLayerContext ); + FUSION_SKIRMISH_ASSERT( &window->stack->context->lock ); + + D_DEBUG_AT( Core_WM, "%s( %p [%d,%d-%dx%d], %p, 0x%x )\n", __FUNCTION__, + window, DFB_RECTANGLE_VALS(&window->config.bounds), config, flags ); + + return wm_local->funcs->SetWindowConfig( window, wm_local->data, + window->window_data, config, flags ); +} + +DFBResult +dfb_wm_restack_window( CoreWindow *window, + CoreWindow *relative, + int relation ) +{ + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->RestackWindow != NULL ); + + D_ASSERT( window != NULL ); + + D_MAGIC_ASSERT( window->stack, CoreWindowStack ); + D_MAGIC_ASSERT( window->stack->context, CoreLayerContext ); + FUSION_SKIRMISH_ASSERT( &window->stack->context->lock ); + + D_ASSERT( relative == NULL || relative == window || relation != 0); + + D_DEBUG_AT( Core_WM, "%s( %p [%d,%d-%dx%d], %p, %d )\n", __FUNCTION__, + window, DFB_RECTANGLE_VALS(&window->config.bounds), relative, relation ); + + return wm_local->funcs->RestackWindow( window, wm_local->data, window->window_data, relative, + relative ? relative->window_data : NULL, relation ); +} + +DFBResult +dfb_wm_grab( CoreWindow *window, + CoreWMGrab *grab ) +{ + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->Grab != NULL ); + + D_ASSERT( window != NULL ); + + D_MAGIC_ASSERT( window->stack, CoreWindowStack ); + D_MAGIC_ASSERT( window->stack->context, CoreLayerContext ); + FUSION_SKIRMISH_ASSERT( &window->stack->context->lock ); + + D_ASSERT( grab != NULL ); + + D_DEBUG_AT( Core_WM, "%s( %p [%d,%d-%dx%d], %d )\n", __FUNCTION__, + window, DFB_RECTANGLE_VALS(&window->config.bounds), grab->target ); + + return wm_local->funcs->Grab( window, wm_local->data, window->window_data, grab ); +} + +DFBResult +dfb_wm_ungrab( CoreWindow *window, + CoreWMGrab *grab ) +{ + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->Ungrab != NULL ); + + D_ASSERT( window != NULL ); + + D_MAGIC_ASSERT( window->stack, CoreWindowStack ); + D_MAGIC_ASSERT( window->stack->context, CoreLayerContext ); + FUSION_SKIRMISH_ASSERT( &window->stack->context->lock ); + + D_ASSERT( grab != NULL ); + + D_DEBUG_AT( Core_WM, "%s( %p [%d,%d-%dx%d], %d )\n", __FUNCTION__, + window, DFB_RECTANGLE_VALS(&window->config.bounds), grab->target ); + + return wm_local->funcs->Ungrab( window, wm_local->data, window->window_data, grab ); +} + +DFBResult +dfb_wm_request_focus( CoreWindow *window ) +{ + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->RequestFocus != NULL ); + + D_ASSERT( window != NULL ); + + D_MAGIC_ASSERT( window->stack, CoreWindowStack ); + D_MAGIC_ASSERT( window->stack->context, CoreLayerContext ); + FUSION_SKIRMISH_ASSERT( &window->stack->context->lock ); + + D_DEBUG_AT( Core_WM, "%s( %p [%d,%d-%dx%d] )\n", __FUNCTION__, + window, DFB_RECTANGLE_VALS(&window->config.bounds) ); + + return wm_local->funcs->RequestFocus( window, wm_local->data, window->window_data ); +} + +DFBResult +dfb_wm_begin_updates( CoreWindow *window, + const DFBRegion *update ) +{ + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->RequestFocus != NULL ); + + D_ASSERT( window != NULL ); + + D_MAGIC_ASSERT( window->stack, CoreWindowStack ); + D_MAGIC_ASSERT( window->stack->context, CoreLayerContext ); + FUSION_SKIRMISH_ASSERT( &window->stack->context->lock ); + + D_DEBUG_AT( Core_WM, "%s( %p [%d,%d-%dx%d] )\n", __FUNCTION__, + window, DFB_RECTANGLE_VALS(&window->config.bounds) ); + + return wm_local->funcs->BeginUpdates( window, wm_local->data, window->window_data, update ); +} + +DFBResult +dfb_wm_set_cursor_position( CoreWindow *window, + int x, + int y ) +{ + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->SetCursorPosition != NULL ); + + D_ASSERT( window != NULL ); + + D_MAGIC_ASSERT( window->stack, CoreWindowStack ); + D_MAGIC_ASSERT( window->stack->context, CoreLayerContext ); + FUSION_SKIRMISH_ASSERT( &window->stack->context->lock ); + + D_DEBUG_AT( Core_WM, "%s( %p [%d,%d] )\n", __FUNCTION__, window, x, y ); + + return wm_local->funcs->SetCursorPosition( window, wm_local->data, window->window_data, x, y ); +} + +DFBResult +dfb_wm_update_stack( CoreWindowStack *stack, + const DFBRegion *region, + DFBSurfaceFlipFlags flags ) +{ + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->UpdateStack != NULL ); + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + D_ASSERT( stack->flags & CWSF_INITIALIZED ); + + D_MAGIC_ASSERT( stack->context, CoreLayerContext ); + FUSION_SKIRMISH_ASSERT( &stack->context->lock ); + + DFB_REGION_ASSERT( region ); + + D_DEBUG_AT( Core_WM, "%s( %p, [%d,%d-%dx%d], 0x%x )\n", __FUNCTION__, + stack, DFB_RECTANGLE_VALS_FROM_REGION(region), flags ); + + return wm_local->funcs->UpdateStack( stack, wm_local->data, + stack->stack_data, region, flags ); +} + +DFBResult +dfb_wm_update_window( CoreWindow *window, + const DFBRegion *region, + DFBSurfaceFlipFlags flags ) +{ + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->UpdateWindow != NULL ); + + D_ASSERT( window != NULL ); + + D_MAGIC_ASSERT( window->stack, CoreWindowStack ); + D_MAGIC_ASSERT( window->stack->context, CoreLayerContext ); + FUSION_SKIRMISH_ASSERT( &window->stack->context->lock ); + + DFB_REGION_ASSERT_IF( region ); + + D_DEBUG_AT( Core_WM, "%s( %p [%d,%d-%dx%d], [%d,%d-%dx%d], 0x%x )\n", __FUNCTION__, + window, DFB_RECTANGLE_VALS(&window->config.bounds), + DFB_RECTANGLE_VALS_FROM_REGION(region), flags ); + + return wm_local->funcs->UpdateWindow( window, wm_local->data, + window->window_data, region, flags ); +} + +DFBResult +dfb_wm_update_cursor( CoreWindowStack *stack, + CoreCursorUpdateFlags flags ) +{ + D_ASSERT( wm_local != NULL ); + D_ASSERT( wm_local->funcs != NULL ); + D_ASSERT( wm_local->funcs->UpdateStack != NULL ); + + D_MAGIC_ASSERT( stack, CoreWindowStack ); + D_ASSERT( stack->flags & CWSF_INITIALIZED ); + + D_MAGIC_ASSERT( stack->context, CoreLayerContext ); + FUSION_SKIRMISH_ASSERT( &stack->context->lock ); + + D_FLAGS_ASSERT( flags, CCUF_ALL ); + + if (dfb_config->no_cursor_updates) + return DFB_OK; + + return wm_local->funcs->UpdateCursor( stack, wm_local->data, + stack->stack_data, flags ); +} + diff --git a/Source/DirectFB/src/core/wm.h b/Source/DirectFB/src/core/wm.h new file mode 100755 index 0000000..eea4fd9 --- /dev/null +++ b/Source/DirectFB/src/core/wm.h @@ -0,0 +1,468 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __DFB__CORE__WM_H__ +#define __DFB__CORE__WM_H__ + +#include +#include + +#include + +#include +#include + + +DECLARE_MODULE_DIRECTORY( dfb_core_wm_modules ); + + +/* + * Increase this number when changes result in binary incompatibility! + */ +#define DFB_CORE_WM_ABI_VERSION 9 + +#define DFB_CORE_WM_INFO_NAME_LENGTH 60 +#define DFB_CORE_WM_INFO_VENDOR_LENGTH 80 +#define DFB_CORE_WM_INFO_URL_LENGTH 120 +#define DFB_CORE_WM_INFO_LICENSE_LENGTH 40 + + +typedef struct { + int major; + int minor; + + int binary; +} CoreWMVersion; + +typedef struct { + CoreWMVersion version; + + char name [DFB_CORE_WM_INFO_NAME_LENGTH]; + char vendor [DFB_CORE_WM_INFO_VENDOR_LENGTH]; + char url [DFB_CORE_WM_INFO_URL_LENGTH]; + char license[DFB_CORE_WM_INFO_LICENSE_LENGTH]; + + unsigned int wm_data_size; + unsigned int wm_shared_size; + unsigned int stack_data_size; + unsigned int window_data_size; +} CoreWMInfo; + +typedef struct { + CoreWMGrabTarget target; + + /* Both for CWMGT_KEY only. */ + DFBInputDeviceKeySymbol symbol; + DFBInputDeviceModifierMask modifiers; +} CoreWMGrab; + +/* FIXME: move to cursor.h when it's there */ +typedef enum { + CCUF_NONE = 0x00000000, + + CCUF_ENABLE = 0x00000001, + CCUF_DISABLE = 0x00000002, + + CCUF_POSITION = 0x00000010, + CCUF_SIZE = 0x00000020, + CCUF_SHAPE = 0x00000040, + CCUF_OPACITY = 0x00000080, + + CCUF_ALL = 0x000000F3 +} CoreCursorUpdateFlags; + +typedef DFBEnumerationResult (*CoreWMWindowCallback) (CoreWindow *window, + void *ctx); + +typedef struct { + + /** Module **/ + + void (*GetWMInfo) ( CoreWMInfo *info ); + + DFBResult (*Initialize) ( CoreDFB *core, + void *wm_data, + void *shared_data ); + + DFBResult (*Join) ( CoreDFB *core, + void *wm_data, + void *shared_data ); + + DFBResult (*Shutdown) ( bool emergency, + void *wm_data, + void *shared_data ); + + DFBResult (*Leave) ( bool emergency, + void *wm_data, + void *shared_data ); + + DFBResult (*Suspend) ( void *wm_data, + void *shared_data ); + + DFBResult (*Resume) ( void *wm_data, + void *shared_data ); + + DFBResult (*PostInit) ( void *wm_data, + void *shared_data ); + + + /** Stack **/ + + DFBResult (*InitStack) ( CoreWindowStack *stack, + void *wm_data, + void *stack_data ); + + DFBResult (*CloseStack) ( CoreWindowStack *stack, + void *wm_data, + void *stack_data ); + + DFBResult (*SetActive) ( CoreWindowStack *stack, + void *wm_data, + void *stack_data, + bool active ); + + DFBResult (*ResizeStack) ( CoreWindowStack *stack, + void *wm_data, + void *stack_data, + int width, + int height ); + + DFBResult (*ProcessInput) ( CoreWindowStack *stack, + void *wm_data, + void *stack_data, + const DFBInputEvent *event ); + + DFBResult (*FlushKeys) ( CoreWindowStack *stack, + void *wm_data, + void *stack_data ); + + DFBResult (*WindowAt) ( CoreWindowStack *stack, + void *wm_data, + void *stack_data, + int x, + int y, + CoreWindow **ret_window ); + + DFBResult (*WindowLookup) ( CoreWindowStack *stack, + void *wm_data, + void *stack_data, + DFBWindowID window_id, + CoreWindow **ret_window ); + + DFBResult (*EnumWindows) ( CoreWindowStack *stack, + void *wm_data, + void *stack_data, + CoreWMWindowCallback callback, + void *callback_ctx ); + + + /** Window **/ + DFBResult (*SetWindowProperty)( CoreWindowStack *stack, + void *wm_data, + void *stack_data, + CoreWindow *window, + void *window_data, + const char *key, + void *value, + void **old_value ); + + DFBResult (*GetWindowProperty)( CoreWindowStack *stack, + void *wm_data, + void *stack_data, + CoreWindow *window, + void *window_data, + const char *key, + void **value); + + DFBResult (*RemoveWindowProperty)( CoreWindowStack *stack, + void *wm_data, + void *stack_data, + CoreWindow *window, + void *window_data, + const char *key, + void **value ); + + DFBResult (*GetInsets) ( CoreWindowStack *stack, + CoreWindow *window, + DFBInsets *insets ); + + DFBResult (*PreConfigureWindow)( CoreWindowStack *stack, + void *wm_data, + void *stack_data, + CoreWindow *window, + void *window_data ); + + DFBResult (*AddWindow) ( CoreWindowStack *stack, + void *wm_data, + void *stack_data, + CoreWindow *window, + void *window_data ); + + DFBResult (*RemoveWindow) ( CoreWindowStack *stack, + void *wm_data, + void *stack_data, + CoreWindow *window, + void *window_data ); + + DFBResult (*SetWindowConfig) ( CoreWindow *window, + void *wm_data, + void *window_data, + const CoreWindowConfig *config, + CoreWindowConfigFlags flags ); + + DFBResult (*RestackWindow) ( CoreWindow *window, + void *wm_data, + void *window_data, + CoreWindow *relative, + void *relative_data, + int relation ); + + DFBResult (*Grab) ( CoreWindow *window, + void *wm_data, + void *window_data, + CoreWMGrab *grab ); + + DFBResult (*Ungrab) ( CoreWindow *window, + void *wm_data, + void *window_data, + CoreWMGrab *grab ); + + DFBResult (*RequestFocus) ( CoreWindow *window, + void *wm_data, + void *window_data ); + + DFBResult (*BeginUpdates) ( CoreWindow *window, + void *wm_data, + void *window_data, + const DFBRegion *update ); + + DFBResult (*SetCursorPosition) ( CoreWindow *window, + void *wm_data, + void *window_data, + int x, + int y ); + + + /** Updates **/ + + DFBResult (*UpdateStack) ( CoreWindowStack *stack, + void *wm_data, + void *stack_data, + const DFBRegion *region, + DFBSurfaceFlipFlags flags ); + + DFBResult (*UpdateWindow) ( CoreWindow *window, + void *wm_data, + void *window_data, + const DFBRegion *region, + DFBSurfaceFlipFlags flags ); + + DFBResult (*UpdateCursor) ( CoreWindowStack *stack, + void *wm_data, + void *stack_data, + CoreCursorUpdateFlags flags ); +} CoreWMFuncs; + + + +typedef enum { + CORE_WM_WINDOW_ADD = 1, + CORE_WM_WINDOW_REMOVE = 2, + CORE_WM_WINDOW_CONFIG = 3, + CORE_WM_WINDOW_STATE = 4, + CORE_WM_WINDOW_RESTACK = 5, + CORE_WM_WINDOW_FOCUS = 6, + + _CORE_WM_NUM_CHANNELS +} CoreWMChannels; + +typedef struct { + DFBWindowInfo info; +} CoreWM_WindowAdd; + +typedef struct { + DFBWindowID window_id; +} CoreWM_WindowRemove; + +typedef struct { + DFBWindowID window_id; + DFBWindowConfig config; + DFBWindowConfigFlags flags; +} CoreWM_WindowConfig; + +typedef struct { + DFBWindowID window_id; + DFBWindowState state; +} CoreWM_WindowState; + +typedef struct { + DFBWindowID window_id; + unsigned int index; +} CoreWM_WindowRestack; + +typedef struct { + DFBWindowID window_id; +} CoreWM_WindowFocus; + + +DFBResult dfb_wm_attach ( CoreDFB *core, + int channel, + ReactionFunc func, + void *ctx, + Reaction *reaction ); + +DFBResult dfb_wm_detach ( CoreDFB *core, + Reaction *reaction ); + +DFBResult dfb_wm_dispatch( CoreDFB *core, + int channel, + const void *data, + int size ); + + +DFBResult dfb_wm_dispatch_WindowAdd ( CoreDFB *core, + CoreWindow *window ); + +DFBResult dfb_wm_dispatch_WindowRemove ( CoreDFB *core, + CoreWindow *window ); + +DFBResult dfb_wm_dispatch_WindowConfig ( CoreDFB *core, + CoreWindow *window, + DFBWindowConfigFlags flags ); + +DFBResult dfb_wm_dispatch_WindowState ( CoreDFB *core, + CoreWindow *window ); + +DFBResult dfb_wm_dispatch_WindowRestack( CoreDFB *core, + CoreWindow *window, + unsigned int index ); + +DFBResult dfb_wm_dispatch_WindowFocus ( CoreDFB *core, + CoreWindow *window ); + + + +void dfb_wm_get_info( CoreWMInfo *info ); + +DFBResult dfb_wm_post_init ( CoreDFB *core ); + +DFBResult dfb_wm_init_stack ( CoreWindowStack *stack ); + +DFBResult dfb_wm_close_stack ( CoreWindowStack *stack ); + +DFBResult dfb_wm_set_active ( CoreWindowStack *stack, + bool active ); + +DFBResult dfb_wm_resize_stack ( CoreWindowStack *stack, + int width, + int height ); + +DFBResult dfb_wm_process_input ( CoreWindowStack *stack, + const DFBInputEvent *event ); + +DFBResult dfb_wm_flush_keys ( CoreWindowStack *stack ); + +DFBResult dfb_wm_window_at ( CoreWindowStack *stack, + int x, + int y, + CoreWindow **ret_window ); + +DFBResult dfb_wm_window_lookup ( CoreWindowStack *stack, + DFBWindowID window_id, + CoreWindow **ret_window ); + +DFBResult dfb_wm_enum_windows ( CoreWindowStack *stack, + CoreWMWindowCallback callback, + void *callback_ctx ); + +DFBResult dfb_wm_get_insets ( CoreWindowStack *stack, + CoreWindow *window, + DFBInsets *insets ); + +DFBResult dfb_wm_set_window_property ( CoreWindowStack *stack, + CoreWindow *window, + const char *key, + void *value, + void **ret_old_value ); + +DFBResult dfb_wm_get_window_property ( CoreWindowStack *stack, + CoreWindow *window, + const char *key, + void **ret_value ); + +DFBResult dfb_wm_remove_window_property ( CoreWindowStack *stack, + CoreWindow *window, + const char *key, + void **ret_value ); + +DFBResult dfb_wm_preconfigure_window ( CoreWindowStack *stack, + CoreWindow *window ); + + +DFBResult dfb_wm_add_window ( CoreWindowStack *stack, + CoreWindow *window ); + +DFBResult dfb_wm_remove_window ( CoreWindowStack *stack, + CoreWindow *window ); + +DFBResult dfb_wm_set_window_config ( CoreWindow *window, + const CoreWindowConfig *config, + CoreWindowConfigFlags flags ); + +DFBResult dfb_wm_restack_window ( CoreWindow *window, + CoreWindow *relative, + int relation ); + +DFBResult dfb_wm_grab ( CoreWindow *window, + CoreWMGrab *grab ); + +DFBResult dfb_wm_ungrab ( CoreWindow *window, + CoreWMGrab *grab ); + +DFBResult dfb_wm_request_focus ( CoreWindow *window ); + +DFBResult dfb_wm_begin_updates ( CoreWindow *window, + const DFBRegion *update ); + +DFBResult dfb_wm_set_cursor_position( CoreWindow *window, + int x, + int y ); + + +DFBResult dfb_wm_update_stack ( CoreWindowStack *stack, + const DFBRegion *region, + DFBSurfaceFlipFlags flags ); + +DFBResult dfb_wm_update_window ( CoreWindow *window, + const DFBRegion *region, + DFBSurfaceFlipFlags flags ); + +DFBResult dfb_wm_update_cursor ( CoreWindowStack *stack, + CoreCursorUpdateFlags flags ); + +#endif diff --git a/Source/DirectFB/src/core/wm_module.h b/Source/DirectFB/src/core/wm_module.h new file mode 100755 index 0000000..b470ebd --- /dev/null +++ b/Source/DirectFB/src/core/wm_module.h @@ -0,0 +1,274 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __DFB__CORE__WM_MODULE_H__ +#define __DFB__CORE__WM_MODULE_H__ + +#include + + +/** Module **/ + +static void wm_get_info ( CoreWMInfo *info ); + +static DFBResult wm_initialize ( CoreDFB *core, + void *wm_data, + void *shared_data ); + +static DFBResult wm_join ( CoreDFB *core, + void *wm_data, + void *shared_data ); + +static DFBResult wm_shutdown ( bool emergency, + void *wm_data, + void *shared_data ); + +static DFBResult wm_leave ( bool emergency, + void *wm_data, + void *shared_data ); + +static DFBResult wm_suspend ( void *wm_data, + void *shared_data ); + +static DFBResult wm_resume ( void *wm_data, + void *shared_data ); + +static DFBResult wm_post_init ( void *wm_data, + void *shared_data ); + + +/** Stack **/ + +static DFBResult wm_init_stack ( CoreWindowStack *stack, + void *wm_data, + void *stack_data ); + +static DFBResult wm_close_stack ( CoreWindowStack *stack, + void *wm_data, + void *stack_data ); + +static DFBResult wm_set_active ( CoreWindowStack *stack, + void *wm_data, + void *stack_data, + bool active ); + +static DFBResult wm_resize_stack ( CoreWindowStack *stack, + void *wm_data, + void *stack_data, + int width, + int height ); + +static DFBResult wm_process_input ( CoreWindowStack *stack, + void *wm_data, + void *stack_data, + const DFBInputEvent *event ); + +static DFBResult wm_flush_keys ( CoreWindowStack *stack, + void *wm_data, + void *stack_data ); + +static DFBResult wm_window_at ( CoreWindowStack *stack, + void *wm_data, + void *stack_data, + int x, + int y, + CoreWindow **ret_window ); + +static DFBResult wm_window_lookup ( CoreWindowStack *stack, + void *wm_data, + void *stack_data, + DFBWindowID window_id, + CoreWindow **ret_window ); + +static DFBResult wm_enum_windows ( CoreWindowStack *stack, + void *wm_data, + void *stack_data, + CoreWMWindowCallback callback, + void *callback_ctx ); + +/** Window **/ +static DFBResult wm_get_insets ( CoreWindowStack *stack, + CoreWindow *window, + DFBInsets *insets ); + +static DFBResult wm_preconfigure_window ( CoreWindowStack *stack, + void *wm_data, + void *stack_data, + CoreWindow *window, + void *window_data ); + +static DFBResult wm_set_window_property( CoreWindowStack *stack, + void *wm_data, + void *stack_data, + CoreWindow *window, + void *window_data, + const char *key, + void *value, + void **ret_old_value ); + +static DFBResult wm_get_window_property( CoreWindowStack *stack, + void *wm_data, + void *stack_data, + CoreWindow *window, + void *window_data, + const char *key, + void **ret_value ); + +static DFBResult wm_remove_window_property( CoreWindowStack *stack, + void *wm_data, + void *stack_data, + CoreWindow *window, + void *window_data, + const char *key, + void **ret_value ); + +static DFBResult wm_add_window ( CoreWindowStack *stack, + void *wm_data, + void *stack_data, + CoreWindow *window, + void *window_data ); + +static DFBResult wm_remove_window ( CoreWindowStack *stack, + void *wm_data, + void *stack_data, + CoreWindow *window, + void *window_data ); + +static DFBResult wm_set_window_config( CoreWindow *window, + void *wm_data, + void *window_data, + const CoreWindowConfig *config, + CoreWindowConfigFlags flags ); + +static DFBResult wm_restack_window ( CoreWindow *window, + void *wm_data, + void *window_data, + CoreWindow *relative, + void *relative_data, + int relation ); + +static DFBResult wm_grab ( CoreWindow *window, + void *wm_data, + void *window_data, + CoreWMGrab *grab ); + +static DFBResult wm_ungrab ( CoreWindow *window, + void *wm_data, + void *window_data, + CoreWMGrab *grab ); + +static DFBResult wm_request_focus ( CoreWindow *window, + void *wm_data, + void *window_data ); + +static DFBResult wm_begin_updates ( CoreWindow *window, + void *wm_data, + void *window_data, + const DFBRegion *update ); + +static DFBResult wm_set_cursor_position( CoreWindow *window, + void *wm_data, + void *window_data, + int x, + int y ); + +/** Updates **/ + +static DFBResult wm_update_stack ( CoreWindowStack *stack, + void *wm_data, + void *stack_data, + const DFBRegion *region, + DFBSurfaceFlipFlags flags ); + +static DFBResult wm_update_window ( CoreWindow *window, + void *wm_data, + void *window_data, + const DFBRegion *region, + DFBSurfaceFlipFlags flags ); + +static DFBResult wm_update_cursor ( CoreWindowStack *stack, + void *wm_data, + void *stack_data, + CoreCursorUpdateFlags flags ); + + +static CoreWMFuncs wm_funcs = { + .GetWMInfo = wm_get_info, + + .Initialize = wm_initialize, + .Join = wm_join, + .Shutdown = wm_shutdown, + .Leave = wm_leave, + .Suspend = wm_suspend, + .Resume = wm_resume, + .PostInit = wm_post_init, + + .InitStack = wm_init_stack, + .CloseStack = wm_close_stack, + .SetActive = wm_set_active, + .ResizeStack = wm_resize_stack, + .ProcessInput = wm_process_input, + .FlushKeys = wm_flush_keys, + .WindowAt = wm_window_at, + .WindowLookup = wm_window_lookup, + .EnumWindows = wm_enum_windows, + + .GetInsets = wm_get_insets, + .PreConfigureWindow = wm_preconfigure_window, + .SetWindowProperty = wm_set_window_property, + .GetWindowProperty = wm_get_window_property, + .RemoveWindowProperty = wm_remove_window_property, + .AddWindow = wm_add_window, + .RemoveWindow = wm_remove_window, + .SetWindowConfig = wm_set_window_config, + .RestackWindow = wm_restack_window, + .Grab = wm_grab, + .Ungrab = wm_ungrab, + .RequestFocus = wm_request_focus, + .BeginUpdates = wm_begin_updates, + .SetCursorPosition = wm_set_cursor_position, + + .UpdateStack = wm_update_stack, + .UpdateWindow = wm_update_window, + .UpdateCursor = wm_update_cursor +}; + + +#define DFB_WINDOW_MANAGER(shortname) \ +__attribute__((constructor)) void directfbwm_##shortname( void ); \ + \ +void \ +directfbwm_##shortname( void ) \ +{ \ + direct_modules_register( &dfb_core_wm_modules, \ + DFB_CORE_WM_ABI_VERSION, \ + #shortname, &wm_funcs ); \ +} + +#endif + diff --git a/Source/DirectFB/src/directfb.c b/Source/DirectFB/src/directfb.c new file mode 100755 index 0000000..9562811 --- /dev/null +++ b/Source/DirectFB/src/directfb.c @@ -0,0 +1,311 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include +#include +#include + +#include + +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + + +IDirectFB *idirectfb_singleton = NULL; + +static DFBResult CreateRemote( const char *host, int session, IDirectFB **ret_interface ); + +/* + * Version checking + */ +const unsigned int directfb_major_version = DIRECTFB_MAJOR_VERSION; +const unsigned int directfb_minor_version = DIRECTFB_MINOR_VERSION; +const unsigned int directfb_micro_version = DIRECTFB_MICRO_VERSION; +const unsigned int directfb_binary_age = DIRECTFB_BINARY_AGE; +const unsigned int directfb_interface_age = DIRECTFB_INTERFACE_AGE; + +const char * +DirectFBCheckVersion( unsigned int required_major, + unsigned int required_minor, + unsigned int required_micro ) +{ + if (required_major > DIRECTFB_MAJOR_VERSION) + return "DirectFB version too old (major mismatch)"; + if (required_major < DIRECTFB_MAJOR_VERSION) + return "DirectFB version too new (major mismatch)"; + if (required_minor > DIRECTFB_MINOR_VERSION) + return "DirectFB version too old (minor mismatch)"; + if (required_minor < DIRECTFB_MINOR_VERSION) + return "DirectFB version too new (minor mismatch)"; + if (required_micro < DIRECTFB_MICRO_VERSION - DIRECTFB_BINARY_AGE) + return "DirectFB version too new (micro mismatch)"; + if (required_micro > DIRECTFB_MICRO_VERSION) + return "DirectFB version too old (micro mismatch)"; + + return NULL; +} + +const char * +DirectFBUsageString( void ) +{ + return dfb_config_usage(); +} + +DFBResult +DirectFBInit( int *argc, char *(*argv[]) ) +{ + DFBResult ret; + +#ifdef DSLINUX + IDirectFBEventBuffer_Dispatcher_ctor(); + IDirectFBDataBuffer_Dispatcher_ctor(); + IDirectFBWindow_Requestor_ctor(); + IDirectFBSurface_Requestor_ctor(); + IDirectFBScreen_Requestor_ctor(); + IDirectFBPalette_Requestor_ctor(); + IDirectFBInputDevice_Requestor_ctor(); + IDirectFBImageProvider_Requestor_ctor(); + IDirectFBFont_Requestor_ctor(); + IDirectFBDisplayLayer_Requestor_ctor(); + IDirectFB_Requestor_ctor(); +#endif + + ret = dfb_config_init( argc, argv ); + if (ret) + return ret; + + return DFB_OK; +} + +DFBResult +DirectFBSetOption( const char *name, const char *value ) +{ + DFBResult ret; + + if (dfb_config == NULL) { + D_ERROR( "DirectFBSetOption: DirectFBInit has to be " + "called before DirectFBSetOption!\n" ); + return DFB_INIT; + } + + if (idirectfb_singleton) { + D_ERROR( "DirectFBSetOption: DirectFBSetOption has to be " + "called before DirectFBCreate!\n" ); + return DFB_INIT; + } + + if (!name) + return DFB_INVARG; + + ret = dfb_config_set( name, value ); + if (ret) + return ret; + + return DFB_OK; +} + +/* + * Programs have to call this to get the super interface + * which is needed to access other functions + */ +DFBResult +DirectFBCreate( IDirectFB **interface ) +{ + DFBResult ret; + IDirectFB *dfb; + CoreDFB *core_dfb; + + if (!dfb_config) { + /* don't use D_ERROR() here, it uses dfb_config */ + direct_log_printf( NULL, "(!) DirectFBCreate: DirectFBInit " + "has to be called before DirectFBCreate!\n" ); + return DFB_INIT; + } + + if (!interface) + return DFB_INVARG; + + if (idirectfb_singleton) { + idirectfb_singleton->AddRef( idirectfb_singleton ); + *interface = idirectfb_singleton; + return DFB_OK; + } + + direct_initialize(); + + if ( !(direct_config->quiet & DMT_BANNER) && dfb_config->banner) { + direct_log_printf( NULL, + "\n" + " ~~~~~~~~~~~~~~~~~~~~~~~~~~| DirectFB " DIRECTFB_VERSION " |~~~~~~~~~~~~~~\n" + " (c) 2001-2009 The world wide DirectFB Open Source Community\n" + " (c) 2000-2004 Convergence (integrated media) GmbH\n" + " ----------------------------------------------------------------\n" + "\n" ); + } + +#ifndef DIRECTFB_PURE_VOODOO + if (dfb_config->remote.host) + return CreateRemote( dfb_config->remote.host, dfb_config->remote.session, interface ); + + ret = dfb_core_create( &core_dfb ); + if (ret) + return ret; + + DIRECT_ALLOCATE_INTERFACE( dfb, IDirectFB ); + + ret = IDirectFB_Construct( dfb, core_dfb ); + if (ret) { + dfb_core_destroy( core_dfb, false ); + return ret; + } + + if (dfb_core_is_master( core_dfb )) { + /* not fatal */ + ret = dfb_wm_post_init( core_dfb ); + if (ret) + D_DERROR( ret, "DirectFBCreate: Post initialization of WM failed!\n" ); + + dfb_core_activate( core_dfb ); + } + + *interface = idirectfb_singleton = dfb; + + return DFB_OK; +#else + return CreateRemote( dfb_config->remote.host ?: "", dfb_config->remote.session, interface ); +#endif +} + +DFBResult +DirectFBError( const char *msg, DFBResult error ) +{ + if (msg) + direct_log_printf( NULL, "(#) DirectFBError [%s]: %s\n", msg, + DirectFBErrorString( error ) ); + else + direct_log_printf( NULL, "(#) DirectFBError: %s\n", + DirectFBErrorString( error ) ); + + return error; +} + +const char * +DirectFBErrorString( DFBResult error ) +{ + if (D_RESULT_TYPE_IS( error, 'D','F','B' )) { + switch (error) { + case DFB_NOVIDEOMEMORY: + return "Out of video memory!"; + case DFB_MISSINGFONT: + return "No font has been set!"; + case DFB_MISSINGIMAGE: + return "No image has been set!"; + default: + return "UKNOWN DIRECTFB RESULT!"; + } + } + + return DirectResultString( error ); +} + +DFBResult +DirectFBErrorFatal( const char *msg, DFBResult error ) +{ + DirectFBError( msg, error ); + + //if (idirectfb_singleton) + //IDirectFB_Destruct( idirectfb_singleton ); + + exit( error ); +} + +/**************************************************************************************************/ + +static DFBResult +CreateRemote( const char *host, int session, IDirectFB **ret_interface ) +{ + DFBResult ret; + DirectInterfaceFuncs *funcs; + void *interface; + + D_ASSERT( host != NULL ); + D_ASSERT( ret_interface != NULL ); + + ret = DirectGetInterface( &funcs, "IDirectFB", "Requestor", NULL, NULL ); + if (ret) + return ret; + + ret = funcs->Allocate( &interface ); + if (ret) + return ret; + + ret = funcs->Construct( interface, host, session ); + if (ret) + return ret; + +#ifndef DIRECTFB_PURE_VOODOO + *ret_interface = idirectfb_singleton = interface; +#else + *ret_interface = interface; +#endif + return DFB_OK; +} + diff --git a/Source/DirectFB/src/display/Makefile.am b/Source/DirectFB/src/display/Makefile.am new file mode 100755 index 0000000..ddb1456 --- /dev/null +++ b/Source/DirectFB/src/display/Makefile.am @@ -0,0 +1,30 @@ +## Makefile.am for DirectFB/src/display + +INCLUDES = \ + -I$(top_builddir)/lib \ + -I$(top_builddir)/include \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/lib \ + -I$(top_srcdir)/src + + +internalincludedir = $(INTERNALINCLUDEDIR)/display + +internalinclude_HEADERS = \ + idirectfbpalette.h \ + idirectfbsurface.h \ + idirectfbsurface_layer.h \ + idirectfbsurface_window.h \ + idirectfbdisplaylayer.h \ + idirectfbscreen.h + + +noinst_LTLIBRARIES = libdirectfb_display.la + +libdirectfb_display_la_SOURCES = \ + idirectfbpalette.c \ + idirectfbsurface.c \ + idirectfbsurface_layer.c \ + idirectfbsurface_window.c \ + idirectfbdisplaylayer.c \ + idirectfbscreen.c diff --git a/Source/DirectFB/src/display/Makefile.in b/Source/DirectFB/src/display/Makefile.in new file mode 100755 index 0000000..312b297 --- /dev/null +++ b/Source/DirectFB/src/display/Makefile.in @@ -0,0 +1,570 @@ +# Makefile.in generated by automake 1.10.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = src/display +DIST_COMMON = $(internalinclude_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/as-ac-expand.m4 \ + $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libdirectfb_display_la_LIBADD = +am_libdirectfb_display_la_OBJECTS = idirectfbpalette.lo \ + idirectfbsurface.lo idirectfbsurface_layer.lo \ + idirectfbsurface_window.lo idirectfbdisplaylayer.lo \ + idirectfbscreen.lo +libdirectfb_display_la_OBJECTS = $(am_libdirectfb_display_la_OBJECTS) +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libdirectfb_display_la_SOURCES) +DIST_SOURCES = $(libdirectfb_display_la_SOURCES) +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(internalincludedir)" +internalincludeHEADERS_INSTALL = $(INSTALL_HEADER) +HEADERS = $(internalinclude_HEADERS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AS = @AS@ +ASFLAGS = @ASFLAGS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIR = @DATADIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DFB_CFLAGS_OMIT_FRAME_POINTER = @DFB_CFLAGS_OMIT_FRAME_POINTER@ +DFB_INTERNAL_CFLAGS = @DFB_INTERNAL_CFLAGS@ +DFB_LDFLAGS = @DFB_LDFLAGS@ +DFB_SMOOTH_SCALING = @DFB_SMOOTH_SCALING@ +DIRECTFB_BINARY_AGE = @DIRECTFB_BINARY_AGE@ +DIRECTFB_CSOURCE = @DIRECTFB_CSOURCE@ +DIRECTFB_INTERFACE_AGE = @DIRECTFB_INTERFACE_AGE@ +DIRECTFB_MAJOR_VERSION = @DIRECTFB_MAJOR_VERSION@ +DIRECTFB_MICRO_VERSION = @DIRECTFB_MICRO_VERSION@ +DIRECTFB_MINOR_VERSION = @DIRECTFB_MINOR_VERSION@ +DIRECTFB_VERSION = @DIRECTFB_VERSION@ +DIRECT_BUILD_DEBUG = @DIRECT_BUILD_DEBUG@ +DIRECT_BUILD_DEBUGS = @DIRECT_BUILD_DEBUGS@ +DIRECT_BUILD_GETTID = @DIRECT_BUILD_GETTID@ +DIRECT_BUILD_NETWORK = @DIRECT_BUILD_NETWORK@ +DIRECT_BUILD_STDBOOL = @DIRECT_BUILD_STDBOOL@ +DIRECT_BUILD_TEXT = @DIRECT_BUILD_TEXT@ +DIRECT_BUILD_TRACE = @DIRECT_BUILD_TRACE@ +DSYMUTIL = @DSYMUTIL@ +DYNLIB = @DYNLIB@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +FREETYPE_CFLAGS = @FREETYPE_CFLAGS@ +FREETYPE_LIBS = @FREETYPE_LIBS@ +FREETYPE_PROVIDER = @FREETYPE_PROVIDER@ +FUSION_BUILD_KERNEL = @FUSION_BUILD_KERNEL@ +FUSION_BUILD_MULTI = @FUSION_BUILD_MULTI@ +FUSION_MESSAGE_SIZE = @FUSION_MESSAGE_SIZE@ +GIF_PROVIDER = @GIF_PROVIDER@ +GREP = @GREP@ +HAVE_LINUX = @HAVE_LINUX@ +INCLUDEDIR = @INCLUDEDIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTERNALINCLUDEDIR = @INTERNALINCLUDEDIR@ +JPEG_PROVIDER = @JPEG_PROVIDER@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBJPEG = @LIBJPEG@ +LIBOBJS = @LIBOBJS@ +LIBPNG = @LIBPNG@ +LIBPNG_CONFIG = @LIBPNG_CONFIG@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_AGE = @LT_AGE@ +LT_BINARY = @LT_BINARY@ +LT_CURRENT = @LT_CURRENT@ +LT_RELEASE = @LT_RELEASE@ +LT_REVISION = @LT_REVISION@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MAN2HTML = @MAN2HTML@ +MKDIR_P = @MKDIR_P@ +MODULEDIR = @MODULEDIR@ +MODULEDIRNAME = @MODULEDIRNAME@ +NMEDIT = @NMEDIT@ +OBJEXT = @OBJEXT@ +OSX_LIBS = @OSX_LIBS@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PNG_PROVIDER = @PNG_PROVIDER@ +RANLIB = @RANLIB@ +RUNTIME_SYSROOT = @RUNTIME_SYSROOT@ +SDL_CFLAGS = @SDL_CFLAGS@ +SDL_LIBS = @SDL_LIBS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOPATH = @SOPATH@ +STRIP = @STRIP@ +SYSCONFDIR = @SYSCONFDIR@ +SYSFS_LIBS = @SYSFS_LIBS@ +THREADFLAGS = @THREADFLAGS@ +THREADLIB = @THREADLIB@ +TSLIB_CFLAGS = @TSLIB_CFLAGS@ +TSLIB_LIBS = @TSLIB_LIBS@ +VERSION = @VERSION@ +VNC_CFLAGS = @VNC_CFLAGS@ +VNC_CONFIG = @VNC_CONFIG@ +VNC_LIBS = @VNC_LIBS@ +X11_CFLAGS = @X11_CFLAGS@ +X11_LIBS = @X11_LIBS@ +ZLIB_LIBS = @ZLIB_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +INCLUDES = \ + -I$(top_builddir)/lib \ + -I$(top_builddir)/include \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/lib \ + -I$(top_srcdir)/src + +internalincludedir = $(INTERNALINCLUDEDIR)/display +internalinclude_HEADERS = \ + idirectfbpalette.h \ + idirectfbsurface.h \ + idirectfbsurface_layer.h \ + idirectfbsurface_window.h \ + idirectfbdisplaylayer.h \ + idirectfbscreen.h + +noinst_LTLIBRARIES = libdirectfb_display.la +libdirectfb_display_la_SOURCES = \ + idirectfbpalette.c \ + idirectfbsurface.c \ + idirectfbsurface_layer.c \ + idirectfbsurface_window.c \ + idirectfbdisplaylayer.c \ + idirectfbscreen.c + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/display/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/display/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libdirectfb_display.la: $(libdirectfb_display_la_OBJECTS) $(libdirectfb_display_la_DEPENDENCIES) + $(LINK) $(libdirectfb_display_la_OBJECTS) $(libdirectfb_display_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/idirectfbdisplaylayer.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/idirectfbpalette.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/idirectfbscreen.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/idirectfbsurface.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/idirectfbsurface_layer.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/idirectfbsurface_window.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-internalincludeHEADERS: $(internalinclude_HEADERS) + @$(NORMAL_INSTALL) + test -z "$(internalincludedir)" || $(MKDIR_P) "$(DESTDIR)$(internalincludedir)" + @list='$(internalinclude_HEADERS)'; for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + f=$(am__strip_dir) \ + echo " $(internalincludeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(internalincludedir)/$$f'"; \ + $(internalincludeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(internalincludedir)/$$f"; \ + done + +uninstall-internalincludeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(internalinclude_HEADERS)'; for p in $$list; do \ + f=$(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(internalincludedir)/$$f'"; \ + rm -f "$(DESTDIR)$(internalincludedir)/$$f"; \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(internalincludedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: install-internalincludeHEADERS + +install-dvi: install-dvi-am + +install-exec-am: + +install-html: install-html-am + +install-info: install-info-am + +install-man: + +install-pdf: install-pdf-am + +install-ps: install-ps-am + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-internalincludeHEADERS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am \ + install-internalincludeHEADERS install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-internalincludeHEADERS + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/Source/DirectFB/src/display/idirectfbdisplaylayer.c b/Source/DirectFB/src/display/idirectfbdisplaylayer.c new file mode 100755 index 0000000..014848a --- /dev/null +++ b/Source/DirectFB/src/display/idirectfbdisplaylayer.c @@ -0,0 +1,1076 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include +#include +#include + +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + + +D_DEBUG_DOMAIN( Layer, "IDirectFBDisplayLayer", "Display Layer Interface" ); + +/* + * private data struct of IDirectFB + */ +typedef struct { + int ref; /* reference counter */ + DFBDisplayLayerDescription desc; /* description of the layer's caps */ + DFBDisplayLayerCooperativeLevel level; /* current cooperative level */ + CoreScreen *screen; /* layer's screen */ + CoreLayer *layer; /* core layer data */ + CoreLayerContext *context; /* shared or exclusive context */ + CoreLayerRegion *region; /* primary region of the context */ + CoreWindowStack *stack; /* stack of shared context */ + DFBBoolean switch_exclusive; /* switch to exclusive context after creation? */ + CoreDFB *core; +} IDirectFBDisplayLayer_data; + + + +static void +IDirectFBDisplayLayer_Destruct( IDirectFBDisplayLayer *thiz ) +{ + IDirectFBDisplayLayer_data *data = (IDirectFBDisplayLayer_data*)thiz->priv; + + D_DEBUG_AT( Layer, "IDirectFBDisplayLayer_Destruct()\n" ); + + D_DEBUG_AT( Layer, " -> unref region...\n" ); + + dfb_layer_region_unref( data->region ); + + D_DEBUG_AT( Layer, " -> unref context...\n" ); + + dfb_layer_context_unref( data->context ); + + DIRECT_DEALLOCATE_INTERFACE( thiz ); + + D_DEBUG_AT( Layer, " -> done.\n" ); +} + +static DirectResult +IDirectFBDisplayLayer_AddRef( IDirectFBDisplayLayer *thiz ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBDisplayLayer) + + data->ref++; + + return DFB_OK; +} + +static DirectResult +IDirectFBDisplayLayer_Release( IDirectFBDisplayLayer *thiz ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBDisplayLayer) + + if (--data->ref == 0) + IDirectFBDisplayLayer_Destruct( thiz ); + + return DFB_OK; +} + +static DFBResult +IDirectFBDisplayLayer_GetID( IDirectFBDisplayLayer *thiz, + DFBDisplayLayerID *id ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBDisplayLayer) + + if (!id) + return DFB_INVARG; + + *id = dfb_layer_id_translated( data->layer ); + + return DFB_OK; +} + +static DFBResult +IDirectFBDisplayLayer_GetDescription( IDirectFBDisplayLayer *thiz, + DFBDisplayLayerDescription *desc ) +{ + + DIRECT_INTERFACE_GET_DATA(IDirectFBDisplayLayer) + + if (!desc) + return DFB_INVARG; + + *desc = data->desc; + + return DFB_OK; +} + +static DFBResult +IDirectFBDisplayLayer_GetSurface( IDirectFBDisplayLayer *thiz, + IDirectFBSurface **interface ) +{ + DFBResult ret; + CoreLayerRegion *region; + IDirectFBSurface *surface; + + DIRECT_INTERFACE_GET_DATA(IDirectFBDisplayLayer) + + if (!interface) + return DFB_INVARG; + + if (data->level == DLSCL_SHARED) { + D_WARN( "letting unprivileged IDirectFBDisplayLayer::GetSurface() " + "call pass until cooperative level handling is finished" ); + } + + ret = dfb_layer_context_get_primary_region( data->context, true, ®ion ); + if (ret) + return ret; + + DIRECT_ALLOCATE_INTERFACE( surface, IDirectFBSurface ); + + ret = IDirectFBSurface_Layer_Construct( surface, NULL, NULL, NULL, + region, DSCAPS_NONE, data->core ); + + if (region->config.buffermode == DLBM_FRONTONLY && data->level == DLSCL_EXCLUSIVE) { + surface->Clear( surface, 0, 0, 0, 0 ); + dfb_layer_region_flip_update( region, NULL, DSFLIP_NONE ); + } + + *interface = ret ? NULL : surface; + + dfb_layer_region_unref( region ); + + return ret; +} + +static DFBResult +IDirectFBDisplayLayer_GetScreen( IDirectFBDisplayLayer *thiz, + IDirectFBScreen **interface ) +{ + DFBResult ret; + IDirectFBScreen *screen; + + DIRECT_INTERFACE_GET_DATA(IDirectFBDisplayLayer) + + if (!interface) + return DFB_INVARG; + + DIRECT_ALLOCATE_INTERFACE( screen, IDirectFBScreen ); + + ret = IDirectFBScreen_Construct( screen, data->screen ); + + *interface = ret ? NULL : screen; + + return ret; +} + +static DFBResult +IDirectFBDisplayLayer_SetCooperativeLevel( IDirectFBDisplayLayer *thiz, + DFBDisplayLayerCooperativeLevel level ) +{ + DFBResult ret; + CoreLayerContext *context; + CoreLayerRegion *region; + + DIRECT_INTERFACE_GET_DATA(IDirectFBDisplayLayer) + + if (data->level == level) + return DFB_OK; + + switch (level) { + case DLSCL_SHARED: + case DLSCL_ADMINISTRATIVE: + if (data->level == DLSCL_EXCLUSIVE) { + ret = dfb_layer_get_primary_context( data->layer, false, &context ); + if (ret) + return ret; + + ret = dfb_layer_context_get_primary_region( context, true, ®ion ); + if (ret) { + dfb_layer_context_unref( context ); + return ret; + } + + dfb_layer_region_unref( data->region ); + dfb_layer_context_unref( data->context ); + + data->context = context; + data->region = region; + data->stack = dfb_layer_context_windowstack( data->context ); + } + + break; + + case DLSCL_EXCLUSIVE: + ret = dfb_layer_create_context( data->layer, &context ); + if (ret) + return ret; + + if (data->switch_exclusive) { + ret = dfb_layer_activate_context( data->layer, context ); + if (ret) { + dfb_layer_context_unref( context ); + return ret; + } + } + + ret = dfb_layer_context_get_primary_region( context, true, ®ion ); + if (ret) { + dfb_layer_context_unref( context ); + return ret; + } + + dfb_layer_region_unref( data->region ); + dfb_layer_context_unref( data->context ); + + data->context = context; + data->region = region; + data->stack = dfb_layer_context_windowstack( data->context ); + + break; + + default: + return DFB_INVARG; + } + + data->level = level; + + return DFB_OK; +} + +static DFBResult +IDirectFBDisplayLayer_SetOpacity( IDirectFBDisplayLayer *thiz, + u8 opacity ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBDisplayLayer) + + if (data->level == DLSCL_SHARED) + return DFB_ACCESSDENIED; + + return dfb_layer_context_set_opacity( data->context, opacity ); +} + +static DFBResult +IDirectFBDisplayLayer_GetCurrentOutputField( IDirectFBDisplayLayer *thiz, int *field ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBDisplayLayer) + + return dfb_layer_get_current_output_field( data->layer, field ); +} + +static DFBResult +IDirectFBDisplayLayer_SetFieldParity( IDirectFBDisplayLayer *thiz, int field ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBDisplayLayer) + + if (data->level != DLSCL_EXCLUSIVE) + return DFB_ACCESSDENIED; + + return dfb_layer_context_set_field_parity( data->context, field ); +} + +static DFBResult +IDirectFBDisplayLayer_SetClipRegions( IDirectFBDisplayLayer *thiz, + const DFBRegion *regions, + int num_regions, + DFBBoolean positive ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBDisplayLayer) + + if (!regions || num_regions < 1) + return DFB_INVARG; + + if (num_regions > data->desc.clip_regions) + return DFB_UNSUPPORTED; + + if (data->level != DLSCL_EXCLUSIVE) + return DFB_ACCESSDENIED; + + return dfb_layer_context_set_clip_regions( data->context, regions, num_regions, positive ); +} + +static DFBResult +IDirectFBDisplayLayer_SetSourceRectangle( IDirectFBDisplayLayer *thiz, + int x, + int y, + int width, + int height ) +{ + DFBRectangle source = { x, y, width, height }; + + DIRECT_INTERFACE_GET_DATA(IDirectFBDisplayLayer) + + if (x < 0 || y < 0 || width <= 0 || height <= 0) + return DFB_INVARG; + + if (data->level == DLSCL_SHARED) + return DFB_ACCESSDENIED; + + return dfb_layer_context_set_sourcerectangle( data->context, &source ); +} + +static DFBResult +IDirectFBDisplayLayer_SetScreenLocation( IDirectFBDisplayLayer *thiz, + float x, + float y, + float width, + float height ) +{ + DFBLocation location = { x, y, width, height }; + + DIRECT_INTERFACE_GET_DATA(IDirectFBDisplayLayer) + + if (! D_FLAGS_IS_SET( data->desc.caps, DLCAPS_SCREEN_LOCATION )) + return DFB_UNSUPPORTED; + + if (width <= 0 || height <= 0) + return DFB_INVARG; + + if (data->level == DLSCL_SHARED) + return DFB_ACCESSDENIED; + + return dfb_layer_context_set_screenlocation( data->context, &location ); +} + +static DFBResult +IDirectFBDisplayLayer_SetScreenPosition( IDirectFBDisplayLayer *thiz, + int x, + int y ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBDisplayLayer) + + if (! D_FLAGS_IS_SET( data->desc.caps, DLCAPS_SCREEN_POSITION )) + return DFB_UNSUPPORTED; + + if (data->level == DLSCL_SHARED) + return DFB_ACCESSDENIED; + + return dfb_layer_context_set_screenposition( data->context, x, y ); +} + +static DFBResult +IDirectFBDisplayLayer_SetScreenRectangle( IDirectFBDisplayLayer *thiz, + int x, + int y, + int width, + int height ) +{ + DFBRectangle rect = { x, y, width, height }; + + DIRECT_INTERFACE_GET_DATA(IDirectFBDisplayLayer) + + if (! D_FLAGS_IS_SET( data->desc.caps, DLCAPS_SCREEN_LOCATION )) + return DFB_UNSUPPORTED; + + if (width <= 0 || height <= 0) + return DFB_INVARG; + + if (data->level == DLSCL_SHARED) + return DFB_ACCESSDENIED; + + return dfb_layer_context_set_screenrectangle( data->context, &rect ); +} + +static DFBResult +IDirectFBDisplayLayer_SetSrcColorKey( IDirectFBDisplayLayer *thiz, + u8 r, + u8 g, + u8 b ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBDisplayLayer) + + if (data->level == DLSCL_SHARED) + return DFB_ACCESSDENIED; + + return dfb_layer_context_set_src_colorkey( data->context, r, g, b, -1 ); +} + +static DFBResult +IDirectFBDisplayLayer_SetDstColorKey( IDirectFBDisplayLayer *thiz, + u8 r, + u8 g, + u8 b ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBDisplayLayer) + + if (data->level == DLSCL_SHARED) + return DFB_ACCESSDENIED; + + return dfb_layer_context_set_dst_colorkey( data->context, r, g, b, -1 ); +} + +static DFBResult +IDirectFBDisplayLayer_GetLevel( IDirectFBDisplayLayer *thiz, + int *level ) +{ + DFBResult ret; + int lvl; + + DIRECT_INTERFACE_GET_DATA(IDirectFBDisplayLayer) + + if (!level) + return DFB_INVARG; + + ret = dfb_layer_get_level( data->layer, &lvl ); + if (ret) + return ret; + + *level = lvl; + + return DFB_OK; +} + +static DFBResult +IDirectFBDisplayLayer_SetLevel( IDirectFBDisplayLayer *thiz, + int level ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBDisplayLayer) + + if (! D_FLAGS_IS_SET( data->desc.caps, DLCAPS_LEVELS )) + return DFB_UNSUPPORTED; + + if (data->level == DLSCL_SHARED) + return DFB_ACCESSDENIED; + + return dfb_layer_set_level( data->layer, level ); +} + +static DFBResult +IDirectFBDisplayLayer_GetConfiguration( IDirectFBDisplayLayer *thiz, + DFBDisplayLayerConfig *config ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBDisplayLayer) + + if (!config) + return DFB_INVARG; + + return dfb_layer_context_get_configuration( data->context, config ); +} + +static DFBResult +IDirectFBDisplayLayer_TestConfiguration( IDirectFBDisplayLayer *thiz, + const DFBDisplayLayerConfig *config, + DFBDisplayLayerConfigFlags *failed ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBDisplayLayer) + + if (!config) + return DFB_INVARG; + + if (((config->flags & DLCONF_WIDTH) && (config->width < 0)) || + ((config->flags & DLCONF_HEIGHT) && (config->height < 0))) + return DFB_INVARG; + + return dfb_layer_context_test_configuration( data->context, config, failed ); +} + +static DFBResult +IDirectFBDisplayLayer_SetConfiguration( IDirectFBDisplayLayer *thiz, + const DFBDisplayLayerConfig *config ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBDisplayLayer) + + if (!config) + return DFB_INVARG; + + if (((config->flags & DLCONF_WIDTH) && (config->width < 0)) || + ((config->flags & DLCONF_HEIGHT) && (config->height < 0))) + return DFB_INVARG; + + switch (data->level) { + case DLSCL_EXCLUSIVE: + case DLSCL_ADMINISTRATIVE: + return dfb_layer_context_set_configuration( data->context, config ); + + default: + break; + } + + return DFB_ACCESSDENIED; +} + +static DFBResult +IDirectFBDisplayLayer_SetBackgroundMode( IDirectFBDisplayLayer *thiz, + DFBDisplayLayerBackgroundMode background_mode ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBDisplayLayer) + + if (data->level == DLSCL_SHARED) + return DFB_ACCESSDENIED; + + switch (background_mode) { + case DLBM_DONTCARE: + case DLBM_COLOR: + case DLBM_IMAGE: + case DLBM_TILE: + break; + + default: + return DFB_INVARG; + } + + return dfb_windowstack_set_background_mode( data->stack, background_mode ); +} + +static DFBResult +IDirectFBDisplayLayer_SetBackgroundImage( IDirectFBDisplayLayer *thiz, + IDirectFBSurface *surface ) +{ + IDirectFBSurface_data *surface_data; + + DIRECT_INTERFACE_GET_DATA(IDirectFBDisplayLayer) + + + if (!surface) + return DFB_INVARG; + + if (data->level == DLSCL_SHARED) + return DFB_ACCESSDENIED; + + surface_data = (IDirectFBSurface_data*)surface->priv; + if (!surface_data) + return DFB_DEAD; + + if (!surface_data->surface) + return DFB_DESTROYED; + + return dfb_windowstack_set_background_image( data->stack, + surface_data->surface ); +} + +static DFBResult +IDirectFBDisplayLayer_SetBackgroundColor( IDirectFBDisplayLayer *thiz, + u8 r, u8 g, u8 b, u8 a ) +{ + DFBColor color = { a: a, r: r, g: g, b: b }; + + DIRECT_INTERFACE_GET_DATA(IDirectFBDisplayLayer) + + if (data->level == DLSCL_SHARED) + return DFB_ACCESSDENIED; + + return dfb_windowstack_set_background_color( data->stack, &color ); +} + +static DFBResult +IDirectFBDisplayLayer_CreateWindow( IDirectFBDisplayLayer *thiz, + const DFBWindowDescription *desc, + IDirectFBWindow **window ) +{ + CoreWindow *w; + DFBResult ret; + DFBWindowDescription wd; + + DIRECT_INTERFACE_GET_DATA(IDirectFBDisplayLayer) + + memset( &wd, 0, sizeof(wd) ); + + wd.flags = DWDESC_WIDTH | DWDESC_HEIGHT | DWDESC_POSX | DWDESC_POSY | + DWDESC_PIXELFORMAT | DWDESC_SURFACE_CAPS | DWDESC_CAPS; + + wd.width = (desc->flags & DWDESC_WIDTH) ? desc->width : 480; + wd.height = (desc->flags & DWDESC_HEIGHT) ? desc->height : 300; + wd.posx = (desc->flags & DWDESC_POSX) ? desc->posx : 100; + wd.posy = (desc->flags & DWDESC_POSY) ? desc->posy : 100; + + D_DEBUG_AT( Layer, "CreateWindow() <- %d,%d - %dx%d )\n", wd.posx, wd.posy, wd.width, wd.height ); + + if (desc->flags & DWDESC_CAPS) + wd.caps = desc->caps; + + wd.caps |= DWCAPS_NOFOCUS; //no focus patch PR brg36mgr#118432 + + if (desc->flags & DWDESC_PIXELFORMAT) + wd.pixelformat = desc->pixelformat; + + if (desc->flags & DWDESC_SURFACE_CAPS) + wd.surface_caps = desc->surface_caps; + + if (desc->flags & DWDESC_PARENT) { + wd.flags |= DWDESC_PARENT; + wd.parent_id = desc->parent_id; + } + + if (desc->flags & DWDESC_OPTIONS) { + wd.flags |= DWDESC_OPTIONS; + wd.options = desc->options; + } + + if (desc->flags & DWDESC_STACKING) { + wd.flags |= DWDESC_STACKING; + wd.stacking = desc->stacking; + } + + if (desc->flags & DWDESC_RESOURCE_ID) { + wd.flags |= DWDESC_RESOURCE_ID; + wd.resource_id = desc->resource_id; + } + + if (desc->flags & DWDESC_TOPLEVEL_ID) { + wd.flags |= DWDESC_TOPLEVEL_ID; + wd.toplevel_id = desc->toplevel_id; + } + + + if ((wd.caps & ~DWCAPS_ALL) || !window) + return DFB_INVARG; + + if (wd.width < 1 || wd.width > 4096 || wd.height < 1 || wd.height > 4096) + return DFB_INVARG; + + ret = dfb_layer_context_create_window( data->core, data->context, &wd, &w ); + if (ret) + return ret; + + DIRECT_ALLOCATE_INTERFACE( *window, IDirectFBWindow ); + + return IDirectFBWindow_Construct( *window, w, data->layer, data->core ); +} + +static DFBResult +IDirectFBDisplayLayer_GetWindow( IDirectFBDisplayLayer *thiz, + DFBWindowID id, + IDirectFBWindow **window ) +{ + CoreWindow *w; + + DIRECT_INTERFACE_GET_DATA(IDirectFBDisplayLayer) + + if (!window) + return DFB_INVARG; + + //remove for now + //if (data->level == DLSCL_SHARED) + // return DFB_ACCESSDENIED; + + w = dfb_layer_context_find_window( data->context, id ); + if (!w) + return DFB_IDNOTFOUND; + + DIRECT_ALLOCATE_INTERFACE( *window, IDirectFBWindow ); + + return IDirectFBWindow_Construct( *window, w, data->layer, data->core ); +} + +static DFBResult +IDirectFBDisplayLayer_EnableCursor( IDirectFBDisplayLayer *thiz, int enable ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBDisplayLayer) + + if (data->level == DLSCL_SHARED) + return DFB_ACCESSDENIED; + + return dfb_windowstack_cursor_enable( data->core, data->stack, enable ); +} + +static DFBResult +IDirectFBDisplayLayer_GetCursorPosition( IDirectFBDisplayLayer *thiz, + int *x, int *y ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBDisplayLayer) + + if (!x && !y) + return DFB_INVARG; + + return dfb_windowstack_get_cursor_position( data->stack, x, y ); +} + +static DFBResult +IDirectFBDisplayLayer_WarpCursor( IDirectFBDisplayLayer *thiz, int x, int y ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBDisplayLayer) + + if (data->level == DLSCL_SHARED) + return DFB_ACCESSDENIED; + + return dfb_windowstack_cursor_warp( data->stack, x, y ); +} + +static DFBResult +IDirectFBDisplayLayer_SetCursorAcceleration( IDirectFBDisplayLayer *thiz, + int numerator, + int denominator, + int threshold ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBDisplayLayer) + + if (numerator < 0 || denominator < 1 || threshold < 0) + return DFB_INVARG; + + if (data->level == DLSCL_SHARED) + return DFB_ACCESSDENIED; + + return dfb_windowstack_cursor_set_acceleration( data->stack, numerator, + denominator, threshold ); +} + +static DFBResult +IDirectFBDisplayLayer_SetCursorShape( IDirectFBDisplayLayer *thiz, + IDirectFBSurface *shape, + int hot_x, + int hot_y ) +{ + IDirectFBSurface_data *shape_data; + + DIRECT_INTERFACE_GET_DATA(IDirectFBDisplayLayer) + + if (!shape) + return DFB_INVARG; + + if (data->level == DLSCL_SHARED) + return DFB_ACCESSDENIED; + + shape_data = (IDirectFBSurface_data*)shape->priv; + + if (hot_x < 0 || + hot_y < 0 || + hot_x >= shape_data->surface->config.size.w || + hot_y >= shape_data->surface->config.size.h) + return DFB_INVARG; + + return dfb_windowstack_cursor_set_shape( data->stack, + shape_data->surface, + hot_x, hot_y ); +} + +static DFBResult +IDirectFBDisplayLayer_SetCursorOpacity( IDirectFBDisplayLayer *thiz, + u8 opacity ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBDisplayLayer) + + if (data->level == DLSCL_SHARED) + return DFB_ACCESSDENIED; + + return dfb_windowstack_cursor_set_opacity( data->stack, opacity ); +} + +static DFBResult +IDirectFBDisplayLayer_GetColorAdjustment( IDirectFBDisplayLayer *thiz, + DFBColorAdjustment *adj ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBDisplayLayer) + + if (!adj) + return DFB_INVARG; + + return dfb_layer_context_get_coloradjustment( data->context, adj ); +} + +static DFBResult +IDirectFBDisplayLayer_SetColorAdjustment( IDirectFBDisplayLayer *thiz, + const DFBColorAdjustment *adj ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBDisplayLayer) + + if (!adj || (adj->flags & ~DCAF_ALL)) + return DFB_INVARG; + + if (data->level == DLSCL_SHARED) + return DFB_ACCESSDENIED; + + if (!adj->flags) + return DFB_OK; + + return dfb_layer_context_set_coloradjustment( data->context, adj ); +} + +static DFBResult +IDirectFBDisplayLayer_WaitForSync( IDirectFBDisplayLayer *thiz ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBDisplayLayer) + + return dfb_layer_wait_vsync( data->layer ); +} + +static DFBResult +IDirectFBDisplayLayer_GetSourceDescriptions( IDirectFBDisplayLayer *thiz, + DFBDisplayLayerSourceDescription *ret_descriptions ) +{ + int i; + + DIRECT_INTERFACE_GET_DATA(IDirectFBDisplayLayer) + + if (!ret_descriptions) + return DFB_INVARG; + + if (! D_FLAGS_IS_SET( data->desc.caps, DLCAPS_SOURCES )) + return DFB_UNSUPPORTED; + + for (i=0; idesc.sources; i++) + dfb_layer_get_source_info( data->layer, i, &ret_descriptions[i] ); + + return DFB_OK; +} + +static DFBResult +IDirectFBDisplayLayer_SwitchContext( IDirectFBDisplayLayer *thiz, + DFBBoolean exclusive ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBDisplayLayer) + + if (!exclusive && data->level == DLSCL_EXCLUSIVE) { + DFBResult ret; + CoreLayerContext *context; + + ret = dfb_layer_get_primary_context( data->layer, false, &context ); + if (ret) + return ret; + + dfb_layer_activate_context( data->layer, context ); + + dfb_layer_context_unref( context ); + } + else + dfb_layer_activate_context( data->layer, data->context ); + + data->switch_exclusive = exclusive; + + return DFB_OK; +} + +static DFBResult +IDirectFBDisplayLayer_SetRotation( IDirectFBDisplayLayer *thiz, + int rotation ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBDisplayLayer) + + if (data->level == DLSCL_SHARED) + return DFB_ACCESSDENIED; + + return dfb_layer_context_set_rotation( data->context, rotation ); +} + +static DFBResult +IDirectFBDisplayLayer_GetRotation( IDirectFBDisplayLayer *thiz, + int *ret_rotation ) +{ + CoreLayerContext *context; + + DIRECT_INTERFACE_GET_DATA(IDirectFBDisplayLayer) + + if (!ret_rotation) + return DFB_INVARG; + + context = data->context; + D_MAGIC_ASSERT( context, CoreLayerContext ); + + /* Lock the context. */ + if (dfb_layer_context_lock( context )) + return DFB_FUSION; + + *ret_rotation = context->rotation; + + /* Unlock the context. */ + dfb_layer_context_unlock( context ); + + return DFB_OK; +} + +typedef struct { + unsigned long resource_id; + CoreWindow *window; +} IDirectFBDisplayLayer_GetWindowByResourceID_Context; + +static DFBEnumerationResult +IDirectFBDisplayLayer_GetWindowByResourceID_WindowCallback( CoreWindow *window, + void *_ctx ) +{ + IDirectFBDisplayLayer_GetWindowByResourceID_Context *ctx = _ctx; + + if (window->surface) { + if (window->surface->resource_id == ctx->resource_id) { + ctx->window = window; + + return DFENUM_CANCEL; + } + } + + return DFENUM_OK; +} + +static DFBResult +IDirectFBDisplayLayer_GetWindowByResourceID( IDirectFBDisplayLayer *thiz, + unsigned long resource_id, + IDirectFBWindow **ret_window ) +{ + DFBResult ret; + CoreLayerContext *context; + CoreWindowStack *stack; + IDirectFBDisplayLayer_GetWindowByResourceID_Context ctx; + + DIRECT_INTERFACE_GET_DATA(IDirectFBDisplayLayer) + + if (!ret_window) + return DFB_INVARG; + + context = data->context; + D_MAGIC_ASSERT( context, CoreLayerContext ); + + stack = context->stack; + D_ASSERT( stack != NULL ); + + ctx.resource_id = resource_id; + ctx.window = NULL; + + ret = dfb_layer_context_lock( context ); + if (ret) + return ret; + + ret = dfb_wm_enum_windows( stack, IDirectFBDisplayLayer_GetWindowByResourceID_WindowCallback, &ctx ); + if (ret == DFB_OK) { + if (ctx.window) { + IDirectFBWindow *window; + + ret = dfb_window_ref( ctx.window ); + if (ret == DFB_OK) { + DIRECT_ALLOCATE_INTERFACE( window, IDirectFBWindow ); + + ret = IDirectFBWindow_Construct( window, ctx.window, data->layer, data->core ); + if (ret == DFB_OK) + *ret_window = window; + } + } + else + ret = DFB_IDNOTFOUND; + } + + dfb_layer_context_unlock( context ); + + return ret; +} + +DFBResult +IDirectFBDisplayLayer_Construct( IDirectFBDisplayLayer *thiz, + CoreLayer *layer, + CoreDFB *core ) +{ + DFBResult ret; + CoreLayerContext *context; + CoreLayerRegion *region; + + DIRECT_ALLOCATE_INTERFACE_DATA(thiz, IDirectFBDisplayLayer) + + ret = dfb_layer_get_primary_context( layer, true, &context ); + if (ret) { + DIRECT_DEALLOCATE_INTERFACE( thiz ) + return ret; + } + + ret = dfb_layer_context_get_primary_region( context, true, ®ion ); + if (ret) { + dfb_layer_context_unref( context ); + DIRECT_DEALLOCATE_INTERFACE( thiz ) + return ret; + } + + data->ref = 1; + data->core = core; + data->screen = dfb_layer_screen( layer ); + data->layer = layer; + data->context = context; + data->region = region; + data->stack = dfb_layer_context_windowstack( context ); + data->switch_exclusive = DFB_TRUE; + + dfb_layer_get_description( data->layer, &data->desc ); + + thiz->AddRef = IDirectFBDisplayLayer_AddRef; + thiz->Release = IDirectFBDisplayLayer_Release; + thiz->GetID = IDirectFBDisplayLayer_GetID; + thiz->GetDescription = IDirectFBDisplayLayer_GetDescription; + thiz->GetSurface = IDirectFBDisplayLayer_GetSurface; + thiz->GetScreen = IDirectFBDisplayLayer_GetScreen; + thiz->SetCooperativeLevel = IDirectFBDisplayLayer_SetCooperativeLevel; + thiz->SetOpacity = IDirectFBDisplayLayer_SetOpacity; + thiz->GetCurrentOutputField = IDirectFBDisplayLayer_GetCurrentOutputField; + thiz->SetSourceRectangle = IDirectFBDisplayLayer_SetSourceRectangle; + thiz->SetScreenLocation = IDirectFBDisplayLayer_SetScreenLocation; + thiz->SetSrcColorKey = IDirectFBDisplayLayer_SetSrcColorKey; + thiz->SetDstColorKey = IDirectFBDisplayLayer_SetDstColorKey; + thiz->GetLevel = IDirectFBDisplayLayer_GetLevel; + thiz->SetLevel = IDirectFBDisplayLayer_SetLevel; + thiz->GetConfiguration = IDirectFBDisplayLayer_GetConfiguration; + thiz->TestConfiguration = IDirectFBDisplayLayer_TestConfiguration; + thiz->SetConfiguration = IDirectFBDisplayLayer_SetConfiguration; + thiz->SetBackgroundMode = IDirectFBDisplayLayer_SetBackgroundMode; + thiz->SetBackgroundColor = IDirectFBDisplayLayer_SetBackgroundColor; + thiz->SetBackgroundImage = IDirectFBDisplayLayer_SetBackgroundImage; + thiz->GetColorAdjustment = IDirectFBDisplayLayer_GetColorAdjustment; + thiz->SetColorAdjustment = IDirectFBDisplayLayer_SetColorAdjustment; + thiz->CreateWindow = IDirectFBDisplayLayer_CreateWindow; + thiz->GetWindow = IDirectFBDisplayLayer_GetWindow; + thiz->WarpCursor = IDirectFBDisplayLayer_WarpCursor; + thiz->SetCursorAcceleration = IDirectFBDisplayLayer_SetCursorAcceleration; + thiz->EnableCursor = IDirectFBDisplayLayer_EnableCursor; + thiz->GetCursorPosition = IDirectFBDisplayLayer_GetCursorPosition; + thiz->SetCursorShape = IDirectFBDisplayLayer_SetCursorShape; + thiz->SetCursorOpacity = IDirectFBDisplayLayer_SetCursorOpacity; + thiz->SetFieldParity = IDirectFBDisplayLayer_SetFieldParity; + thiz->SetClipRegions = IDirectFBDisplayLayer_SetClipRegions; + thiz->WaitForSync = IDirectFBDisplayLayer_WaitForSync; + thiz->GetSourceDescriptions = IDirectFBDisplayLayer_GetSourceDescriptions; + thiz->SetScreenPosition = IDirectFBDisplayLayer_SetScreenPosition; + thiz->SetScreenRectangle = IDirectFBDisplayLayer_SetScreenRectangle; + thiz->SwitchContext = IDirectFBDisplayLayer_SwitchContext; + thiz->SetRotation = IDirectFBDisplayLayer_SetRotation; + thiz->GetRotation = IDirectFBDisplayLayer_GetRotation; + thiz->GetWindowByResourceID = IDirectFBDisplayLayer_GetWindowByResourceID; + + return DFB_OK; +} + diff --git a/Source/DirectFB/src/display/idirectfbdisplaylayer.h b/Source/DirectFB/src/display/idirectfbdisplaylayer.h new file mode 100755 index 0000000..9b39468 --- /dev/null +++ b/Source/DirectFB/src/display/idirectfbdisplaylayer.h @@ -0,0 +1,43 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __IDIRECTFBDISPLAYLAYER_H__ +#define __IDIRECTFBDISPLAYLAYER_H__ + +#include +#include + +/* + * initializes interface struct and private data + */ +DFBResult IDirectFBDisplayLayer_Construct( IDirectFBDisplayLayer *thiz, + CoreLayer *layer, + CoreDFB *core ); + + +#endif diff --git a/Source/DirectFB/src/display/idirectfbpalette.c b/Source/DirectFB/src/display/idirectfbpalette.c new file mode 100755 index 0000000..213af4d --- /dev/null +++ b/Source/DirectFB/src/display/idirectfbpalette.c @@ -0,0 +1,365 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include +#include +#include +#include + +#include + + +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "idirectfbpalette.h" + + + +static void +IDirectFBPalette_Destruct( IDirectFBPalette *thiz ) +{ + IDirectFBPalette_data *data = (IDirectFBPalette_data*)thiz->priv; + + if (data->palette) + dfb_palette_unref( data->palette ); + + DIRECT_DEALLOCATE_INTERFACE( thiz ); +} + +static DirectResult +IDirectFBPalette_AddRef( IDirectFBPalette *thiz ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBPalette) + + data->ref++; + + return DFB_OK; +} + +static DirectResult +IDirectFBPalette_Release( IDirectFBPalette *thiz ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBPalette) + + if (--data->ref == 0) + IDirectFBPalette_Destruct( thiz ); + + return DFB_OK; +} + +static DFBResult +IDirectFBPalette_GetCapabilities( IDirectFBPalette *thiz, + DFBPaletteCapabilities *caps ) +{ + CorePalette *palette; + + DIRECT_INTERFACE_GET_DATA(IDirectFBPalette) + + palette = data->palette; + if (!palette) + return DFB_DESTROYED; + + if (!caps) + return DFB_INVARG; + + /* FIXME: no caps yet */ + *caps = DPCAPS_NONE; + + return DFB_OK; +} + +static DFBResult +IDirectFBPalette_GetSize( IDirectFBPalette *thiz, + unsigned int *size ) +{ + CorePalette *palette; + + DIRECT_INTERFACE_GET_DATA(IDirectFBPalette) + + palette = data->palette; + if (!palette) + return DFB_DESTROYED; + + if (!size) + return DFB_INVARG; + + *size = palette->num_entries; + + return DFB_OK; +} + +static DFBResult +IDirectFBPalette_SetEntries( IDirectFBPalette *thiz, + const DFBColor *entries, + unsigned int num_entries, + unsigned int offset ) +{ + int i; + CorePalette *palette; + + DIRECT_INTERFACE_GET_DATA(IDirectFBPalette) + + palette = data->palette; + if (!palette) + return DFB_DESTROYED; + + if (!entries || offset + num_entries > palette->num_entries) + return DFB_INVARG; + + if (num_entries) { + direct_memcpy( palette->entries + offset, entries, num_entries * sizeof(DFBColor)); + + for (i=offset; ientries_yuv[i].a = palette->entries[i].a; + + RGB_TO_YCBCR( palette->entries[i].r, palette->entries[i].g, palette->entries[i].b, + palette->entries_yuv[i].y, palette->entries_yuv[i].u, palette->entries_yuv[i].v ); + } + + dfb_palette_update( palette, offset, offset + num_entries - 1 ); + } + + return DFB_OK; +} + +static DFBResult +IDirectFBPalette_GetEntries( IDirectFBPalette *thiz, + DFBColor *entries, + unsigned int num_entries, + unsigned int offset ) +{ + CorePalette *palette; + + DIRECT_INTERFACE_GET_DATA(IDirectFBPalette) + + palette = data->palette; + if (!palette) + return DFB_DESTROYED; + + if (!entries || offset + num_entries > palette->num_entries) + return DFB_INVARG; + + direct_memcpy( entries, palette->entries + offset, num_entries * sizeof(DFBColor)); + + return DFB_OK; +} + +static DFBResult +IDirectFBPalette_FindBestMatch( IDirectFBPalette *thiz, + u8 r, + u8 g, + u8 b, + u8 a, + unsigned int *index ) +{ + CorePalette *palette; + + DIRECT_INTERFACE_GET_DATA(IDirectFBPalette) + + if (!index) + return DFB_INVARG; + + palette = data->palette; + if (!palette) + return DFB_DESTROYED; + + *index = dfb_palette_search( palette, r, g, b, a ); + + return DFB_OK; +} + +static DFBResult +IDirectFBPalette_CreateCopy( IDirectFBPalette *thiz, + IDirectFBPalette **interface ) +{ + DFBResult ret; + IDirectFBPalette *iface; + CorePalette *palette = NULL; + + DIRECT_INTERFACE_GET_DATA(IDirectFBPalette) + + if (!data->palette) + return DFB_DESTROYED; + + if (!interface) + return DFB_INVARG; + + ret = dfb_palette_create( NULL, /* FIXME */ + data->palette->num_entries, &palette ); + if (ret) + return ret; + + direct_memcpy( palette->entries, data->palette->entries, + palette->num_entries * sizeof(DFBColor)); + + dfb_palette_update( palette, 0, palette->num_entries - 1 ); + + + DIRECT_ALLOCATE_INTERFACE( iface, IDirectFBPalette ); + + ret = IDirectFBPalette_Construct( iface, palette ); + + dfb_palette_unref( palette ); + + if (!ret) + *interface = iface; + + return ret; +} + +static DFBResult +IDirectFBPalette_SetEntriesYUV( IDirectFBPalette *thiz, + const DFBColorYUV *entries, + unsigned int num_entries, + unsigned int offset ) +{ + int i; + CorePalette *palette; + + DIRECT_INTERFACE_GET_DATA(IDirectFBPalette) + + palette = data->palette; + if (!palette) + return DFB_DESTROYED; + + if (!entries || offset + num_entries > palette->num_entries) + return DFB_INVARG; + + if (num_entries) { + direct_memcpy( palette->entries_yuv + offset, entries, num_entries * sizeof(DFBColorYUV)); + + for (i=offset; ientries[i].a = palette->entries_yuv[i].a; + + YCBCR_TO_RGB( palette->entries_yuv[i].y, palette->entries_yuv[i].u, palette->entries_yuv[i].v, + palette->entries[i].r, palette->entries[i].g, palette->entries[i].b ); + } + + dfb_palette_update( palette, offset, offset + num_entries - 1 ); + } + + return DFB_OK; +} + +static DFBResult +IDirectFBPalette_GetEntriesYUV( IDirectFBPalette *thiz, + DFBColorYUV *ret_entries, + unsigned int num_entries, + unsigned int offset ) +{ + CorePalette *palette; + + DIRECT_INTERFACE_GET_DATA(IDirectFBPalette) + + palette = data->palette; + if (!palette) + return DFB_DESTROYED; + + if (!ret_entries || offset + num_entries > palette->num_entries) + return DFB_INVARG; + + direct_memcpy( ret_entries, palette->entries_yuv + offset, num_entries * sizeof(DFBColorYUV)); + + return DFB_OK; +} + +static DFBResult +IDirectFBPalette_FindBestMatchYUV( IDirectFBPalette *thiz, + u8 y, + u8 u, + u8 v, + u8 a, + unsigned int *ret_index ) +{ + int r, g, b; + CorePalette *palette; + + DIRECT_INTERFACE_GET_DATA(IDirectFBPalette) + + if (!ret_index) + return DFB_INVARG; + + palette = data->palette; + if (!palette) + return DFB_DESTROYED; + + YCBCR_TO_RGB( y, u, v, r, g, b ); + + *ret_index = dfb_palette_search( palette, r, g, b, a ); + + return DFB_OK; +} + +/******/ + +DFBResult IDirectFBPalette_Construct( IDirectFBPalette *thiz, + CorePalette *palette ) +{ + DIRECT_ALLOCATE_INTERFACE_DATA(thiz, IDirectFBPalette) + + if (dfb_palette_ref( palette )) { + DIRECT_DEALLOCATE_INTERFACE(thiz); + return DFB_FAILURE; + } + + data->ref = 1; + data->palette = palette; + + + thiz->AddRef = IDirectFBPalette_AddRef; + thiz->Release = IDirectFBPalette_Release; + + thiz->GetCapabilities = IDirectFBPalette_GetCapabilities; + thiz->GetSize = IDirectFBPalette_GetSize; + + thiz->SetEntries = IDirectFBPalette_SetEntries; + thiz->GetEntries = IDirectFBPalette_GetEntries; + thiz->FindBestMatch = IDirectFBPalette_FindBestMatch; + + thiz->CreateCopy = IDirectFBPalette_CreateCopy; + + thiz->SetEntriesYUV = IDirectFBPalette_SetEntriesYUV; + thiz->GetEntriesYUV = IDirectFBPalette_GetEntriesYUV; + thiz->FindBestMatchYUV = IDirectFBPalette_FindBestMatchYUV; + + return DFB_OK; +} + diff --git a/Source/DirectFB/src/display/idirectfbpalette.h b/Source/DirectFB/src/display/idirectfbpalette.h new file mode 100755 index 0000000..2bedfa2 --- /dev/null +++ b/Source/DirectFB/src/display/idirectfbpalette.h @@ -0,0 +1,51 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __IDIRECTFBPALETTE_H__ +#define __IDIRECTFBPALETTE_H__ + +#include +#include + +/* + * private data struct of IDirectFBPalette + */ +typedef struct { + int ref; /* reference counter */ + + CorePalette *palette; /* the palette object */ +} IDirectFBPalette_data; + +/* + * initializes interface struct and private data + */ +DFBResult IDirectFBPalette_Construct( IDirectFBPalette *thiz, + CorePalette *palette ); + + +#endif diff --git a/Source/DirectFB/src/display/idirectfbscreen.c b/Source/DirectFB/src/display/idirectfbscreen.c new file mode 100755 index 0000000..9fcebdc --- /dev/null +++ b/Source/DirectFB/src/display/idirectfbscreen.c @@ -0,0 +1,722 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include +#include +#include + +#include + +#include + +#include +#include +#include + +#include + +#include + +#include "idirectfbscreen.h" + +/* + * private data struct of IDirectFBScreen + */ +typedef struct { + int ref; /* reference counter */ + + CoreScreen *screen; + + DFBScreenID id; + DFBScreenDescription description; +} IDirectFBScreen_data; + +/******************************************************************************/ + +static DFBResult PatchMixerConfig ( DFBScreenMixerConfig *patched, + const DFBScreenMixerConfig *patch ); +static DFBResult PatchEncoderConfig( DFBScreenEncoderConfig *patched, + const DFBScreenEncoderConfig *patch ); +static DFBResult PatchOutputConfig ( DFBScreenOutputConfig *patched, + const DFBScreenOutputConfig *patch ); + +/******************************************************************************/ + +typedef struct { + CoreScreen *screen; + + DFBDisplayLayerCallback callback; + void *callback_ctx; +} EnumDisplayLayers_Context; + +static DFBEnumerationResult EnumDisplayLayers_Callback( CoreLayer *layer, + void *ctx ); + +/******************************************************************************/ + +static void +IDirectFBScreen_Destruct( IDirectFBScreen *thiz ) +{ +// IDirectFBScreen_data *data = (IDirectFBScreen_data*)thiz->priv; + + DIRECT_DEALLOCATE_INTERFACE( thiz ); +} + +static DirectResult +IDirectFBScreen_AddRef( IDirectFBScreen *thiz ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBScreen) + + data->ref++; + + return DFB_OK; +} + +static DirectResult +IDirectFBScreen_Release( IDirectFBScreen *thiz ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBScreen) + + if (--data->ref == 0) + IDirectFBScreen_Destruct( thiz ); + + return DFB_OK; +} + +static DFBResult +IDirectFBScreen_GetID( IDirectFBScreen *thiz, + DFBScreenID *id ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBScreen) + + if (!id) + return DFB_INVARG; + + *id = data->id; + + return DFB_OK; +} + +static DFBResult +IDirectFBScreen_GetDescription( IDirectFBScreen *thiz, + DFBScreenDescription *desc ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBScreen) + + if (!desc) + return DFB_INVARG; + + *desc = data->description; + + return DFB_OK; +} + +static DFBResult +IDirectFBScreen_GetSize( IDirectFBScreen *thiz, + int *ret_width, + int *ret_height ) +{ + DFBResult ret; + int width = 0; + int height = 0; + + DIRECT_INTERFACE_GET_DATA(IDirectFBScreen) + + if (!ret_width && !ret_height) + return DFB_INVARG; + + ret = dfb_screen_get_screen_size( data->screen, &width, &height ); + + if (ret_width) + *ret_width = width; + + if (ret_height) + *ret_height = height; + + return ret; +} + +static DFBResult +IDirectFBScreen_EnumDisplayLayers( IDirectFBScreen *thiz, + DFBDisplayLayerCallback callbackfunc, + void *callbackdata ) +{ + EnumDisplayLayers_Context context; + + DIRECT_INTERFACE_GET_DATA(IDirectFBScreen) + + if (!callbackfunc) + return DFB_INVARG; + + context.screen = data->screen; + context.callback = callbackfunc; + context.callback_ctx = callbackdata; + + dfb_layers_enumerate( EnumDisplayLayers_Callback, &context ); + + return DFB_OK; +} + +static DFBResult +IDirectFBScreen_SetPowerMode( IDirectFBScreen *thiz, + DFBScreenPowerMode mode ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBScreen) + + switch (mode) { + case DSPM_ON: + case DSPM_STANDBY: + case DSPM_SUSPEND: + case DSPM_OFF: + break; + + default: + return DFB_INVARG; + } + + return dfb_screen_set_powermode( data->screen, mode ); +} + +static DFBResult +IDirectFBScreen_WaitForSync( IDirectFBScreen *thiz ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBScreen) + + return dfb_screen_wait_vsync( data->screen ); +} + +static DFBResult +IDirectFBScreen_GetMixerDescriptions( IDirectFBScreen *thiz, + DFBScreenMixerDescription *descriptions ) +{ + int i; + + DIRECT_INTERFACE_GET_DATA(IDirectFBScreen) + + if (!descriptions) + return DFB_INVARG; + + if (! (data->description.caps & DSCCAPS_MIXERS)) + return DFB_UNSUPPORTED; + + for (i=0; idescription.mixers; i++) + dfb_screen_get_mixer_info( data->screen, i, &descriptions[i] ); + + return DFB_OK; +} + +static DFBResult +IDirectFBScreen_GetMixerConfiguration( IDirectFBScreen *thiz, + int mixer, + DFBScreenMixerConfig *config ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBScreen) + + if (!config) + return DFB_INVARG; + + if (! (data->description.caps & DSCCAPS_MIXERS)) + return DFB_UNSUPPORTED; + + if (mixer < 0 || mixer >= data->description.mixers) + return DFB_INVARG; + + return dfb_screen_get_mixer_config( data->screen, mixer, config ); +} + +static DFBResult +IDirectFBScreen_TestMixerConfiguration( IDirectFBScreen *thiz, + int mixer, + const DFBScreenMixerConfig *config, + DFBScreenMixerConfigFlags *failed ) +{ + DFBResult ret; + DFBScreenMixerConfig patched; + + DIRECT_INTERFACE_GET_DATA(IDirectFBScreen) + + if (!config || (config->flags & ~DSMCONF_ALL)) + return DFB_INVARG; + + if (! (data->description.caps & DSCCAPS_MIXERS)) + return DFB_UNSUPPORTED; + + if (mixer < 0 || mixer >= data->description.mixers) + return DFB_INVARG; + + /* Get the current configuration. */ + ret = dfb_screen_get_mixer_config( data->screen, mixer, &patched ); + if (ret) + return ret; + + /* Patch the configuration. */ + ret = PatchMixerConfig( &patched, config ); + if (ret) + return ret; + + /* Test the patched configuration. */ + return dfb_screen_test_mixer_config( data->screen, + mixer, &patched, failed ); +} + +static DFBResult +IDirectFBScreen_SetMixerConfiguration( IDirectFBScreen *thiz, + int mixer, + const DFBScreenMixerConfig *config ) +{ + DFBResult ret; + DFBScreenMixerConfig patched; + + DIRECT_INTERFACE_GET_DATA(IDirectFBScreen) + + if (!config || (config->flags & ~DSMCONF_ALL)) + return DFB_INVARG; + + if (! (data->description.caps & DSCCAPS_MIXERS)) + return DFB_UNSUPPORTED; + + if (mixer < 0 || mixer >= data->description.mixers) + return DFB_INVARG; + + /* Get the current configuration. */ + ret = dfb_screen_get_mixer_config( data->screen, mixer, &patched ); + if (ret) + return ret; + + /* Patch the configuration. */ + ret = PatchMixerConfig( &patched, config ); + if (ret) + return ret; + + /* Set the patched configuration. */ + return dfb_screen_set_mixer_config( data->screen, mixer, &patched ); +} + +static DFBResult +IDirectFBScreen_GetEncoderDescriptions( IDirectFBScreen *thiz, + DFBScreenEncoderDescription *descriptions ) +{ + int i; + + DIRECT_INTERFACE_GET_DATA(IDirectFBScreen) + + if (!descriptions) + return DFB_INVARG; + + if (! (data->description.caps & DSCCAPS_ENCODERS)) + return DFB_UNSUPPORTED; + + for (i=0; idescription.encoders; i++) + dfb_screen_get_encoder_info( data->screen, i, &descriptions[i] ); + + return DFB_OK; +} + +static DFBResult +IDirectFBScreen_GetEncoderConfiguration( IDirectFBScreen *thiz, + int encoder, + DFBScreenEncoderConfig *config ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBScreen) + + if (!config) + return DFB_INVARG; + + if (! (data->description.caps & DSCCAPS_ENCODERS)) + return DFB_UNSUPPORTED; + + if (encoder < 0 || encoder >= data->description.encoders) + return DFB_INVARG; + + return dfb_screen_get_encoder_config( data->screen, encoder, config ); +} + +static DFBResult +IDirectFBScreen_TestEncoderConfiguration( IDirectFBScreen *thiz, + int encoder, + const DFBScreenEncoderConfig *config, + DFBScreenEncoderConfigFlags *failed ) +{ + DFBResult ret; + DFBScreenEncoderConfig patched; + + DIRECT_INTERFACE_GET_DATA(IDirectFBScreen) + + if (!config || (config->flags & ~DSECONF_ALL)) + return DFB_INVARG; + + if (! (data->description.caps & DSCCAPS_ENCODERS)) + return DFB_UNSUPPORTED; + + if (encoder < 0 || encoder >= data->description.encoders) + return DFB_INVARG; + + /* Get the current configuration. */ + ret = dfb_screen_get_encoder_config( data->screen, encoder, &patched ); + if (ret) + return ret; + + /* Patch the configuration. */ + ret = PatchEncoderConfig( &patched, config ); + if (ret) + return ret; + + /* Test the patched configuration. */ + return dfb_screen_test_encoder_config( data->screen, + encoder, &patched, failed ); +} + +static DFBResult +IDirectFBScreen_SetEncoderConfiguration( IDirectFBScreen *thiz, + int encoder, + const DFBScreenEncoderConfig *config ) +{ + DFBResult ret; + DFBScreenEncoderConfig patched; + + DIRECT_INTERFACE_GET_DATA(IDirectFBScreen) + + if (!config || (config->flags & ~DSECONF_ALL)) + return DFB_INVARG; + + if (! (data->description.caps & DSCCAPS_ENCODERS)) + return DFB_UNSUPPORTED; + + if (encoder < 0 || encoder >= data->description.encoders) + return DFB_INVARG; + + /* Get the current configuration. */ + ret = dfb_screen_get_encoder_config( data->screen, encoder, &patched ); + if (ret) + return ret; + + /* Patch the configuration. */ + ret = PatchEncoderConfig( &patched, config ); + if (ret) + return ret; + + /* Set the patched configuration. */ + return dfb_screen_set_encoder_config( data->screen, encoder, &patched ); +} + +static DFBResult +IDirectFBScreen_GetOutputDescriptions( IDirectFBScreen *thiz, + DFBScreenOutputDescription *descriptions ) +{ + int i; + + DIRECT_INTERFACE_GET_DATA(IDirectFBScreen) + + if (!descriptions) + return DFB_INVARG; + + if (!data->description.caps & DSCCAPS_OUTPUTS) + return DFB_UNSUPPORTED; + + for (i=0; idescription.outputs; i++) + dfb_screen_get_output_info( data->screen, i, &descriptions[i] ); + + return DFB_OK; +} + +static DFBResult +IDirectFBScreen_GetOutputConfiguration( IDirectFBScreen *thiz, + int output, + DFBScreenOutputConfig *config ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBScreen) + + if (!config) + return DFB_INVARG; + + if (! (data->description.caps & DSCCAPS_OUTPUTS)) + return DFB_UNSUPPORTED; + + if (output < 0 || output >= data->description.outputs) + return DFB_INVARG; + + return dfb_screen_get_output_config( data->screen, output, config ); +} + +static DFBResult +IDirectFBScreen_TestOutputConfiguration( IDirectFBScreen *thiz, + int output, + const DFBScreenOutputConfig *config, + DFBScreenOutputConfigFlags *failed ) +{ + DFBResult ret; + DFBScreenOutputConfig patched; + + DIRECT_INTERFACE_GET_DATA(IDirectFBScreen) + + if (!config || (config->flags & ~DSOCONF_ALL)) + return DFB_INVARG; + + if (! (data->description.caps & DSCCAPS_OUTPUTS)) + return DFB_UNSUPPORTED; + + if (output < 0 || output >= data->description.outputs) + return DFB_INVARG; + + /* Get the current configuration. */ + ret = dfb_screen_get_output_config( data->screen, output, &patched ); + if (ret) + return ret; + + /* Patch the configuration. */ + ret = PatchOutputConfig( &patched, config ); + if (ret) + return ret; + + /* Test the patched configuration. */ + return dfb_screen_test_output_config( data->screen, + output, &patched, failed ); +} + +static DFBResult +IDirectFBScreen_SetOutputConfiguration( IDirectFBScreen *thiz, + int output, + const DFBScreenOutputConfig *config ) +{ + DFBResult ret; + DFBScreenOutputConfig patched; + + DIRECT_INTERFACE_GET_DATA(IDirectFBScreen) + + if (!config || (config->flags & ~DSOCONF_ALL)) + return DFB_INVARG; + + if (! (data->description.caps & DSCCAPS_OUTPUTS)) + return DFB_UNSUPPORTED; + + if (output < 0 || output >= data->description.outputs) + return DFB_INVARG; + + /* Get the current configuration. */ + ret = dfb_screen_get_output_config( data->screen, output, &patched ); + if (ret) + return ret; + + /* Patch the configuration. */ + ret = PatchOutputConfig( &patched, config ); + if (ret) + return ret; + + /* Set the patched configuration. */ + return dfb_screen_set_output_config( data->screen, output, &patched ); +} + +/******************************************************************************/ + +DFBResult +IDirectFBScreen_Construct( IDirectFBScreen *thiz, + CoreScreen *screen ) +{ + DIRECT_ALLOCATE_INTERFACE_DATA(thiz, IDirectFBScreen) + + data->ref = 1; + data->screen = screen; + + dfb_screen_get_info( screen, NULL, &data->description ); + data->id = dfb_screen_id_translated( data->screen ); + + thiz->AddRef = IDirectFBScreen_AddRef; + thiz->Release = IDirectFBScreen_Release; + thiz->GetID = IDirectFBScreen_GetID; + thiz->GetDescription = IDirectFBScreen_GetDescription; + thiz->GetSize = IDirectFBScreen_GetSize; + thiz->EnumDisplayLayers = IDirectFBScreen_EnumDisplayLayers; + thiz->SetPowerMode = IDirectFBScreen_SetPowerMode; + thiz->WaitForSync = IDirectFBScreen_WaitForSync; + thiz->GetMixerDescriptions = IDirectFBScreen_GetMixerDescriptions; + thiz->GetMixerConfiguration = IDirectFBScreen_GetMixerConfiguration; + thiz->TestMixerConfiguration = IDirectFBScreen_TestMixerConfiguration; + thiz->SetMixerConfiguration = IDirectFBScreen_SetMixerConfiguration; + thiz->GetEncoderDescriptions = IDirectFBScreen_GetEncoderDescriptions; + thiz->GetEncoderConfiguration = IDirectFBScreen_GetEncoderConfiguration; + thiz->TestEncoderConfiguration = IDirectFBScreen_TestEncoderConfiguration; + thiz->SetEncoderConfiguration = IDirectFBScreen_SetEncoderConfiguration; + thiz->GetOutputDescriptions = IDirectFBScreen_GetOutputDescriptions; + thiz->GetOutputConfiguration = IDirectFBScreen_GetOutputConfiguration; + thiz->TestOutputConfiguration = IDirectFBScreen_TestOutputConfiguration; + thiz->SetOutputConfiguration = IDirectFBScreen_SetOutputConfiguration; + + return DFB_OK; +} + +/******************************************************************************/ + +static DFBResult +PatchMixerConfig( DFBScreenMixerConfig *patched, + const DFBScreenMixerConfig *patch ) +{ + /* Check for unsupported flags. */ + if (patch->flags & ~patched->flags) + return DFB_UNSUPPORTED; + + if (patch->flags & DSMCONF_TREE) + patched->tree = patch->tree; + + if (patch->flags & DSMCONF_LEVEL) + patched->level = patch->level; + + if (patch->flags & DSMCONF_LAYERS) + patched->layers = patch->layers; + + if (patch->flags & DSMCONF_BACKGROUND) + patched->background = patch->background; + + return DFB_OK; +} + +static DFBResult +PatchEncoderConfig( DFBScreenEncoderConfig *patched, + const DFBScreenEncoderConfig *patch ) +{ + /* Check for unsupported flags. */ + if (patch->flags & ~patched->flags) + return DFB_UNSUPPORTED; + + if (patch->flags & DSECONF_RESOLUTION) + patched->resolution = patch->resolution; + + if (patch->flags & DSECONF_FREQUENCY) + patched->frequency = patch->frequency; + + /** + * Need to be backwards compatible with these so that + * they specify resolution and frequency as well. + * If you have set a TV_STANDARD + * (and set the flag) it will override the resolution and + * frequency chosen above.*/ + if (patch->flags & DSECONF_TV_STANDARD) { + patched->tv_standard = patch->tv_standard; + switch (patched->tv_standard) { + case DSETV_PAL: + case DSETV_PAL_BG: + case DSETV_PAL_I: + case DSETV_PAL_N: + case DSETV_PAL_NC: + patched->resolution = DSOR_720_576; + patched->frequency = DSEF_50HZ; + break; + + case DSETV_PAL_60: + case DSETV_PAL_M: + patched->resolution = DSOR_720_480; + patched->frequency = DSEF_60HZ; + break; + + case DSETV_SECAM: + patched->resolution = DSOR_720_576; + patched->frequency = DSEF_50HZ; + break; + + case DSETV_NTSC: + case DSETV_NTSC_M_JPN: + case DSETV_NTSC_443: + patched->resolution = DSOR_720_480; + patched->frequency = DSEF_60HZ; + break; + + default: + break; + } + } + if (patch->flags & DSECONF_TEST_PICTURE) + patched->test_picture = patch->test_picture; + + if (patch->flags & DSECONF_MIXER) + patched->mixer = patch->mixer; + + if (patch->flags & DSECONF_OUT_SIGNALS) + patched->out_signals = patch->out_signals; + + if (patch->flags & DSECONF_SCANMODE) + patched->scanmode = patch->scanmode; + + if (patch->flags & DSECONF_ADJUSTMENT) + patched->adjustment = patch->adjustment; + + if (patch->flags & DSECONF_CONNECTORS) + patched->out_connectors = patch->out_connectors; + + if (patch->flags & DSECONF_SLOW_BLANKING) + patched->slow_blanking = patch->slow_blanking; + + return DFB_OK; +} + +static DFBResult +PatchOutputConfig( DFBScreenOutputConfig *patched, + const DFBScreenOutputConfig *patch ) +{ + /* Check for unsupported flags. */ + if (patch->flags & ~patched->flags) + return DFB_UNSUPPORTED; + + if (patch->flags & DSOCONF_RESOLUTION) + patched->resolution = patch->resolution; + + if (patch->flags & DSOCONF_ENCODER) + patched->encoder = patch->encoder; + + if (patch->flags & DSOCONF_SIGNALS) + patched->out_signals = patch->out_signals; + + if (patch->flags & DSOCONF_CONNECTORS) + patched->out_connectors = patch->out_connectors; + + if (patch->flags & DSOCONF_SLOW_BLANKING) + patched->slow_blanking = patch->slow_blanking; + + return DFB_OK; +} + +static DFBEnumerationResult +EnumDisplayLayers_Callback( CoreLayer *layer, void *ctx ) +{ + DFBDisplayLayerDescription desc; + DFBDisplayLayerID id; + EnumDisplayLayers_Context *context = (EnumDisplayLayers_Context*) ctx; + + if (dfb_layer_screen( layer ) != context->screen) + return DFENUM_OK; + + id = dfb_layer_id_translated( layer ); + + if (dfb_config->primary_only && id != DLID_PRIMARY) + return DFENUM_OK; + + dfb_layer_get_description( layer, &desc ); + + return context->callback( id, desc, context->callback_ctx ); +} + diff --git a/Source/DirectFB/src/display/idirectfbscreen.h b/Source/DirectFB/src/display/idirectfbscreen.h new file mode 100755 index 0000000..682ee8b --- /dev/null +++ b/Source/DirectFB/src/display/idirectfbscreen.h @@ -0,0 +1,42 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __IDIRECTFBSCREEN_H__ +#define __IDIRECTFBSCREEN_H__ + +#include +#include + +/* + * initializes interface struct and private data + */ +DFBResult IDirectFBScreen_Construct( IDirectFBScreen *thiz, + CoreScreen *screen ); + + +#endif diff --git a/Source/DirectFB/src/display/idirectfbsurface.c b/Source/DirectFB/src/display/idirectfbsurface.c new file mode 100755 index 0000000..bd23975 --- /dev/null +++ b/Source/DirectFB/src/display/idirectfbsurface.c @@ -0,0 +1,2841 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include +#include +#include +#include +#include + +#include + + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + + +D_DEBUG_DOMAIN( Surface, "IDirectFBSurface", "IDirectFBSurface Interface" ); + +/**********************************************************************************************************************/ + +static ReactionResult IDirectFBSurface_listener( const void *msg_data, void *ctx ); + +/**********************************************************************************************************************/ + +void +IDirectFBSurface_Destruct( IDirectFBSurface *thiz ) +{ + IDirectFBSurface_data *data; + IDirectFBSurface *parent; + + D_DEBUG_AT( Surface, "%s( %p )\n", __FUNCTION__, thiz ); + + D_ASSERT( thiz != NULL ); + + data = thiz->priv; + + D_ASSERT( data != NULL ); + D_ASSERT( data->children_data == NULL ); + + parent = data->parent; + if (parent) { + IDirectFBSurface_data *parent_data; + + D_MAGIC_ASSERT( (IAny*) parent, DirectInterface ); + + parent_data = parent->priv; + D_ASSERT( parent_data != NULL ); + + pthread_mutex_lock( &parent_data->children_lock ); + + direct_list_remove( &parent_data->children_data, &data->link ); + + pthread_mutex_unlock( &parent_data->children_lock ); + } + + if (data->surface) + dfb_surface_detach( data->surface, &data->reaction ); + + dfb_state_stop_drawing( &data->state ); + + dfb_state_set_destination( &data->state, NULL ); + dfb_state_set_source( &data->state, NULL ); + dfb_state_set_source_mask( &data->state, NULL ); + + dfb_state_destroy( &data->state ); + + if (data->font) + data->font->Release( data->font ); + + if (data->surface) { + if (data->locked) + dfb_surface_unlock_buffer( data->surface, &data->lock ); + + dfb_surface_unref( data->surface ); + } + + pthread_mutex_destroy( &data->children_lock ); + + DIRECT_DEALLOCATE_INTERFACE( thiz ); + + if (parent) + parent->Release( parent ); +} + +static DirectResult +IDirectFBSurface_AddRef( IDirectFBSurface *thiz ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p )\n", __FUNCTION__, thiz ); + + data->ref++; + + return DFB_OK; +} + +static DirectResult +IDirectFBSurface_Release( IDirectFBSurface *thiz ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p )\n", __FUNCTION__, thiz ); + + if (--data->ref == 0) + IDirectFBSurface_Destruct( thiz ); + + return DFB_OK; +} + + +static DFBResult +IDirectFBSurface_GetPixelFormat( IDirectFBSurface *thiz, + DFBSurfacePixelFormat *format ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p )\n", __FUNCTION__, thiz ); + + if (!data->surface) + return DFB_DESTROYED; + + if (!format) + return DFB_INVARG; + + *format = data->surface->config.format; + + return DFB_OK; +} + +static DFBResult +IDirectFBSurface_GetAccelerationMask( IDirectFBSurface *thiz, + IDirectFBSurface *source, + DFBAccelerationMask *ret_mask ) +{ + DFBAccelerationMask mask = DFXL_NONE; + + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p )\n", __FUNCTION__, thiz ); + + if (!data->surface) + return DFB_DESTROYED; + + if (!ret_mask) + return DFB_INVARG; + + dfb_state_lock( &data->state ); + + /* Check drawing functions */ + if (dfb_gfxcard_state_check( &data->state, DFXL_FILLRECTANGLE )) + mask |= DFXL_FILLRECTANGLE; + + if (dfb_gfxcard_state_check( &data->state, DFXL_DRAWRECTANGLE )) + mask |= DFXL_DRAWRECTANGLE; + + if (dfb_gfxcard_state_check( &data->state, DFXL_DRAWLINE )) + mask |= DFXL_DRAWLINE; + + if (dfb_gfxcard_state_check( &data->state, DFXL_FILLTRIANGLE )) + mask |= DFXL_FILLTRIANGLE; + + dfb_state_unlock( &data->state ); + + /* Check blitting functions */ + if (source) { + IDirectFBSurface_data *src_data = source->priv; + + dfb_state_set_source( &data->state, src_data->surface ); + + dfb_state_lock( &data->state ); + + if (dfb_gfxcard_state_check( &data->state, DFXL_BLIT )) + mask |= DFXL_BLIT; + + if (dfb_gfxcard_state_check( &data->state, DFXL_STRETCHBLIT )) + mask |= DFXL_STRETCHBLIT; + + if (dfb_gfxcard_state_check( &data->state, DFXL_TEXTRIANGLES )) + mask |= DFXL_TEXTRIANGLES; + + dfb_state_unlock( &data->state ); + } + + /* Check text rendering function */ + if (data->font) { + IDirectFBFont_data *font_data = data->font->priv; + + if (dfb_gfxcard_drawstring_check_state( font_data->font, &data->state )) + mask |= DFXL_DRAWSTRING; + } + + *ret_mask = mask; + + return DFB_OK; +} + +static DFBResult +IDirectFBSurface_GetPosition( IDirectFBSurface *thiz, + int *x, + int *y ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p )\n", __FUNCTION__, thiz ); + + if (!x && !y) + return DFB_INVARG; + + if (x) + *x = data->area.wanted.x; + + if (y) + *y = data->area.wanted.y; + + return DFB_OK; +} + +static DFBResult +IDirectFBSurface_GetSize( IDirectFBSurface *thiz, + int *width, + int *height ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p )\n", __FUNCTION__, thiz ); + + if (!width && !height) + return DFB_INVARG; + + if (width) + *width = data->area.wanted.w; + + if (height) + *height = data->area.wanted.h; + + return DFB_OK; +} + +static DFBResult +IDirectFBSurface_GetVisibleRectangle( IDirectFBSurface *thiz, + DFBRectangle *rect ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p )\n", __FUNCTION__, thiz ); + + if (!rect) + return DFB_INVARG; + + rect->x = data->area.current.x - data->area.wanted.x; + rect->y = data->area.current.y - data->area.wanted.y; + rect->w = data->area.current.w; + rect->h = data->area.current.h; + + return DFB_OK; +} + +static DFBResult +IDirectFBSurface_GetCapabilities( IDirectFBSurface *thiz, + DFBSurfaceCapabilities *caps ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p )\n", __FUNCTION__, thiz ); + + if (!caps) + return DFB_INVARG; + + *caps = data->caps; + + return DFB_OK; +} + +static DFBResult +IDirectFBSurface_GetPalette( IDirectFBSurface *thiz, + IDirectFBPalette **interface ) +{ + DFBResult ret; + CoreSurface *surface; + IDirectFBPalette *palette; + + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p )\n", __FUNCTION__, thiz ); + + surface = data->surface; + if (!surface) + return DFB_DESTROYED; + + if (!surface->palette) + return DFB_UNSUPPORTED; + + if (!interface) + return DFB_INVARG; + + DIRECT_ALLOCATE_INTERFACE( palette, IDirectFBPalette ); + + ret = IDirectFBPalette_Construct( palette, surface->palette ); + if (ret) + return ret; + + *interface = palette; + + return DFB_OK; +} + +static DFBResult +IDirectFBSurface_SetPalette( IDirectFBSurface *thiz, + IDirectFBPalette *palette ) +{ + CoreSurface *surface; + IDirectFBPalette_data *palette_data; + + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p )\n", __FUNCTION__, thiz ); + + surface = data->surface; + if (!surface) + return DFB_DESTROYED; + + if (!palette) + return DFB_INVARG; + + if (! DFB_PIXELFORMAT_IS_INDEXED( surface->config.format )) + return DFB_UNSUPPORTED; + + palette_data = (IDirectFBPalette_data*) palette->priv; + if (!palette_data) + return DFB_DEAD; + + if (!palette_data->palette) + return DFB_DESTROYED; + + dfb_surface_set_palette( surface, palette_data->palette ); + + return DFB_OK; +} + +static DFBResult +IDirectFBSurface_SetAlphaRamp( IDirectFBSurface *thiz, + u8 a0, + u8 a1, + u8 a2, + u8 a3 ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p )\n", __FUNCTION__, thiz ); + + if (!data->surface) + return DFB_DESTROYED; + + dfb_surface_set_alpha_ramp( data->surface, a0, a1, a2, a3 ); + + return DFB_OK; +} + +static DFBResult +IDirectFBSurface_Lock( IDirectFBSurface *thiz, + DFBSurfaceLockFlags flags, + void **ret_ptr, int *ret_pitch ) +{ + DFBResult ret; + CoreSurfaceBufferRole role = CSBR_FRONT; + CoreSurfaceAccessFlags access = CSAF_NONE; + + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p )\n", __FUNCTION__, thiz ); + + if (!data->surface) + return DFB_DESTROYED; + + if (data->locked) + return DFB_LOCKED; + + if (!flags || !ret_ptr || !ret_pitch) + return DFB_INVARG; + + if (!data->area.current.w || !data->area.current.h) + return DFB_INVAREA; + + if (flags & DSLF_READ) + access |= CSAF_READ; + + if (flags & DSLF_WRITE) { + access |= CSAF_WRITE; + role = CSBR_BACK; + } + + ret = dfb_surface_lock_buffer( data->surface, role, CSAID_CPU, access, &data->lock ); + if (ret) + return ret; + + data->locked = true; + + *ret_ptr = data->lock.addr + data->lock.pitch * data->area.current.y + + DFB_BYTES_PER_LINE( data->surface->config.format, data->area.current.x ); + *ret_pitch = data->lock.pitch; + + return DFB_OK; +} + +static DFBResult +IDirectFBSurface_GetFramebufferOffset( IDirectFBSurface *thiz, + int *offset ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + if (!data->surface) + return DFB_DESTROYED; + + if (!offset) + return DFB_INVARG; + + if (!data->locked) + return DFB_ACCESSDENIED; + + if (!data->lock.phys) { + /* The surface is probably in a system buffer if there's no physical address. */ + return DFB_UNSUPPORTED; + } + + *offset = data->lock.offset; + + return DFB_OK; +} + +static DFBResult +IDirectFBSurface_Unlock( IDirectFBSurface *thiz ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p )\n", __FUNCTION__, thiz ); + + if (!data->surface) + return DFB_DESTROYED; + + if (data->locked) { + dfb_surface_unlock_buffer( data->surface, &data->lock ); + + data->locked = false; + } + + return DFB_OK; +} + +static DFBResult +IDirectFBSurface_Write( IDirectFBSurface *thiz, + const DFBRectangle *rect, + const void *ptr, + int pitch ) +{ + CoreSurface *surface; + + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p, %p, %p [%d] )\n", __FUNCTION__, thiz, rect, ptr, pitch ); + + surface = data->surface; + if (!surface) + return DFB_DESTROYED; + + if (!rect || !ptr || pitch < DFB_BYTES_PER_LINE(surface->config.format,rect->w ) ) + return DFB_INVARG; + + if (data->locked) + return DFB_LOCKED; + + if (!data->area.current.w || !data->area.current.h) + return DFB_INVAREA; + + D_DEBUG_AT( Surface, " -> %4d,%4d-%4dx%4d\n", DFB_RECTANGLE_VALS( rect ) ); + + //FIXME: check rectangle + + return dfb_surface_write_buffer( data->surface, CSBR_BACK, ptr, pitch, rect ); +} + +static DFBResult +IDirectFBSurface_Read( IDirectFBSurface *thiz, + const DFBRectangle *rect, + void *ptr, + int pitch ) +{ + CoreSurface *surface; + + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p, %p, %p [%d] )\n", __FUNCTION__, thiz, rect, ptr, pitch ); + + surface = data->surface; + if (!surface) + return DFB_DESTROYED; + + if (!rect || !ptr || pitch < DFB_BYTES_PER_LINE(surface->config.format,rect->w ) ) + return DFB_INVARG; + + if (data->locked) + return DFB_LOCKED; + + if (!data->area.current.w || !data->area.current.h) + return DFB_INVAREA; + + D_DEBUG_AT( Surface, " -> %4d,%4d-%4dx%4d\n", DFB_RECTANGLE_VALS( rect ) ); + + //FIXME: check rectangle + + return dfb_surface_read_buffer( data->surface, CSBR_FRONT, ptr, pitch, rect ); +} + +static DFBResult +IDirectFBSurface_Flip( IDirectFBSurface *thiz, + const DFBRegion *region, + DFBSurfaceFlipFlags flags ) +{ + DFBResult ret; + DFBRegion reg; + CoreSurface *surface; + + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p, %p, 0x%08x )\n", __FUNCTION__, thiz, region, flags ); + + surface = data->surface; + if (!surface) + return DFB_DESTROYED; + + if (data->locked) + return DFB_LOCKED; + + if (!(surface->config.caps & DSCAPS_FLIPPING)) + return DFB_UNSUPPORTED; + + if (!data->area.current.w || !data->area.current.h || + (region && (region->x1 > region->x2 || region->y1 > region->y2))) + return DFB_INVAREA; + + IDirectFBSurface_StopAll( data ); + + /* FIXME: This is a temporary workaround for LiTE. */ + if (data->parent) { + IDirectFBSurface_data *parent_data; + + DIRECT_INTERFACE_GET_DATA_FROM( data->parent, parent_data, IDirectFBSurface ); + + /* Signal end of sequence of operations. */ + dfb_state_lock( &parent_data->state ); + dfb_state_stop_drawing( &parent_data->state ); + dfb_state_unlock( &parent_data->state ); + } + + dfb_region_from_rectangle( ®, &data->area.current ); + + if (region) { + DFBRegion clip = DFB_REGION_INIT_TRANSLATED( region, + data->area.wanted.x, + data->area.wanted.y ); + + if (!dfb_region_region_intersect( ®, &clip )) + return DFB_INVAREA; + } + + D_DEBUG_AT( Surface, " -> %4d,%4d-%4dx%4d\n", DFB_RECTANGLE_VALS_FROM_REGION( ® ) ); + + if (!(flags & DSFLIP_BLIT) && reg.x1 == 0 && reg.y1 == 0 && + reg.x2 == surface->config.size.w - 1 && reg.y2 == surface->config.size.h - 1) + { + ret = dfb_surface_lock( data->surface ); + if (ret) + return ret; + + dfb_surface_flip( data->surface, false ); + + dfb_surface_unlock( data->surface ); + } + else + dfb_back_to_front_copy( data->surface, ® ); + + return DFB_OK; +} + +static DFBResult +IDirectFBSurface_SetField( IDirectFBSurface *thiz, + int field ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p )\n", __FUNCTION__, thiz ); + + if (!data->surface) + return DFB_DESTROYED; + + if (!(data->surface->config.caps & DSCAPS_INTERLACED)) + return DFB_UNSUPPORTED; + + if (field < 0 || field > 1) + return DFB_INVARG; + + dfb_surface_set_field( data->surface, field ); + + return DFB_OK; +} + +static DFBResult +IDirectFBSurface_Clear( IDirectFBSurface *thiz, + u8 r, u8 g, u8 b, u8 a ) +{ + DFBColor old_color; + unsigned int old_index; + DFBSurfaceDrawingFlags old_flags; + DFBSurfaceRenderOptions old_options; + CoreSurface *surface; + DFBColor color = { a, r, g, b }; + + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p, 0x%08x )\n", __FUNCTION__, thiz, PIXEL_ARGB(a,r,g,b) ); + + surface = data->surface; + if (!surface) + return DFB_DESTROYED; + + if (!data->area.current.w || !data->area.current.h) + return DFB_INVAREA; + + if (data->locked) + return DFB_LOCKED; + + /* save current color and drawing flags */ + old_color = data->state.color; + old_index = data->state.color_index; + old_flags = data->state.drawingflags; + old_options = data->state.render_options; + + /* set drawing flags */ + dfb_state_set_drawing_flags( &data->state, DSDRAW_NOFX ); + + /* set render options */ + dfb_state_set_render_options( &data->state, DSRO_NONE ); + + /* set color */ + if (DFB_PIXELFORMAT_IS_INDEXED( surface->config.format )) + dfb_state_set_color_index( &data->state, + dfb_palette_search( surface->palette, r, g, b, a ) ); + + dfb_state_set_color( &data->state, &color ); + + /* fill the visible rectangle */ + dfb_gfxcard_fillrectangles( &data->area.current, 1, &data->state ); + + /* clear the depth buffer */ + if (data->caps & DSCAPS_DEPTH) + dfb_clear_depth( data->surface, &data->state.clip ); + + /* restore drawing flags */ + dfb_state_set_drawing_flags( &data->state, old_flags ); + + /* restore render options */ + dfb_state_set_render_options( &data->state, old_options ); + + /* restore color */ + if (DFB_PIXELFORMAT_IS_INDEXED( surface->config.format )) + dfb_state_set_color_index( &data->state, old_index ); + + dfb_state_set_color( &data->state, &old_color ); + + return DFB_OK; +} + +static DFBResult +IDirectFBSurface_SetClip( IDirectFBSurface *thiz, const DFBRegion *clip ) +{ + DFBRegion newclip; + + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p, %p )\n", __FUNCTION__, thiz, clip ); + + + if (!data->area.current.w || !data->area.current.h) + return DFB_INVAREA; + + if (clip) { + newclip = DFB_REGION_INIT_TRANSLATED( clip, data->area.wanted.x, data->area.wanted.y ); + + D_DEBUG_AT( Surface, " <- %4d,%4d-%4dx%4d\n", DFB_RECTANGLE_VALS_FROM_REGION(&newclip) ); + + if (!dfb_unsafe_region_rectangle_intersect( &newclip, + &data->area.wanted )) + return DFB_INVARG; + + D_DEBUG_AT( Surface, " -> %4d,%4d-%4dx%4d\n", DFB_RECTANGLE_VALS_FROM_REGION(&newclip) ); + + data->clip_set = true; + data->clip_wanted = newclip; + + if (!dfb_region_rectangle_intersect( &newclip, &data->area.current )) + return DFB_INVAREA; + } + else { + dfb_region_from_rectangle( &newclip, &data->area.current ); + data->clip_set = false; + } + + D_DEBUG_AT( Surface, " => CLIP %4d,%4d-%4dx%4d\n", DFB_RECTANGLE_VALS_FROM_REGION(&newclip) ); + + dfb_state_set_clip( &data->state, &newclip ); + + return DFB_OK; +} + +static DFBResult +IDirectFBSurface_GetClip( IDirectFBSurface *thiz, DFBRegion *ret_clip ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p )\n", __FUNCTION__, thiz ); + + if (!ret_clip) + return DFB_INVARG; + + if (!data->area.current.w || !data->area.current.h) + return DFB_INVAREA; + + *ret_clip = DFB_REGION_INIT_TRANSLATED( &data->state.clip, -data->area.wanted.x, -data->area.wanted.y ); + + D_DEBUG_AT( Surface, " -> %4d,%4d-%4dx%4d\n", DFB_RECTANGLE_VALS_FROM_REGION(ret_clip) ); + + return DFB_OK; +} + +static DFBResult +IDirectFBSurface_SetColor( IDirectFBSurface *thiz, + u8 r, u8 g, u8 b, u8 a ) +{ + CoreSurface *surface; + DFBColor color = { a, r, g, b }; + + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p, COLOR 0x%08x )\n", __FUNCTION__, thiz, PIXEL_ARGB(a, r, g, b) ); + + surface = data->surface; + if (!surface) + return DFB_DESTROYED; + + dfb_state_set_color( &data->state, &color ); + + if (DFB_PIXELFORMAT_IS_INDEXED( surface->config.format )) + dfb_state_set_color_index( &data->state, + dfb_palette_search( surface->palette, r, g, b, a ) ); + + data->state.colors[0] = data->state.color; + data->state.color_indices[0] = data->state.color_index; + + return DFB_OK; +} + +static DFBResult +IDirectFBSurface_SetColors( IDirectFBSurface *thiz, + const DFBColorID *ids, + const DFBColor *colors, + unsigned int num ) +{ + unsigned int i; + CoreSurface *surface; + + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p, %p, %p, %u )\n", __FUNCTION__, thiz, ids, colors, num ); + + surface = data->surface; + if (!surface) + return DFB_DESTROYED; + + for (i=0; i [%d] id %d = %02x %02x %02x %02x\n", + i, ids[i], colors[i].a, colors[i].r, colors[i].g, colors[i].b ); + + if (ids[i] >= DFB_COLOR_IDS_MAX) + return DFB_INVARG; + + data->state.colors[ids[i]] = colors[i]; + + if (DFB_PIXELFORMAT_IS_INDEXED( surface->config.format )) + data->state.color_indices[ids[i]] = dfb_palette_search( surface->palette, + colors[i].r, colors[i].g, colors[i].b, colors[i].a ); + } + + dfb_state_set_color( &data->state, &data->state.colors[0] ); + dfb_state_set_color_index( &data->state, data->state.color_indices[0] ); + + return DFB_OK; +} + +static DFBResult +IDirectFBSurface_SetColorIndex( IDirectFBSurface *thiz, + unsigned int index ) +{ + CoreSurface *surface; + CorePalette *palette; + + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p, COLOR INDEX %3u )\n", __FUNCTION__, thiz, index ); + + surface = data->surface; + if (!surface) + return DFB_DESTROYED; + + if (! DFB_PIXELFORMAT_IS_INDEXED( surface->config.format )) + return DFB_UNSUPPORTED; + + palette = surface->palette; + if (!palette) + return DFB_UNSUPPORTED; + + if (index > palette->num_entries) + return DFB_INVARG; + + dfb_state_set_color( &data->state, &palette->entries[index] ); + + dfb_state_set_color_index( &data->state, index ); + + data->state.colors[0] = data->state.color; + data->state.color_indices[0] = data->state.color_index; + + return DFB_OK; +} + +static DFBResult +IDirectFBSurface_SetSrcBlendFunction( IDirectFBSurface *thiz, + DFBSurfaceBlendFunction src ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p, %d )\n", __FUNCTION__, thiz, src ); + + switch (src) { + case DSBF_ZERO: + case DSBF_ONE: + case DSBF_SRCCOLOR: + case DSBF_INVSRCCOLOR: + case DSBF_SRCALPHA: + case DSBF_INVSRCALPHA: + case DSBF_DESTALPHA: + case DSBF_INVDESTALPHA: + case DSBF_DESTCOLOR: + case DSBF_INVDESTCOLOR: + case DSBF_SRCALPHASAT: + dfb_state_set_src_blend( &data->state, src ); + return DFB_OK; + + default: + break; + } + + return DFB_INVARG; +} + +static DFBResult +IDirectFBSurface_SetDstBlendFunction( IDirectFBSurface *thiz, + DFBSurfaceBlendFunction dst ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p, %d )\n", __FUNCTION__, thiz, dst ); + + switch (dst) { + case DSBF_ZERO: + case DSBF_ONE: + case DSBF_SRCCOLOR: + case DSBF_INVSRCCOLOR: + case DSBF_SRCALPHA: + case DSBF_INVSRCALPHA: + case DSBF_DESTALPHA: + case DSBF_INVDESTALPHA: + case DSBF_DESTCOLOR: + case DSBF_INVDESTCOLOR: + case DSBF_SRCALPHASAT: + dfb_state_set_dst_blend( &data->state, dst ); + return DFB_OK; + + default: + break; + } + + return DFB_INVARG; +} + +static DFBResult +IDirectFBSurface_SetPorterDuff( IDirectFBSurface *thiz, + DFBSurfacePorterDuffRule rule ) +{ + DFBSurfaceBlendFunction src; + DFBSurfaceBlendFunction dst; + + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p, %d )\n", __FUNCTION__, thiz, rule ); + + + switch (rule) { + case DSPD_NONE: + src = DSBF_SRCALPHA; + dst = DSBF_INVSRCALPHA; + break; + case DSPD_CLEAR: + src = DSBF_ZERO; + dst = DSBF_ZERO; + break; + case DSPD_SRC: + src = DSBF_ONE; + dst = DSBF_ZERO; + break; + case DSPD_SRC_OVER: + src = DSBF_ONE; + dst = DSBF_INVSRCALPHA; + break; + case DSPD_DST_OVER: + src = DSBF_INVDESTALPHA; + dst = DSBF_ONE; + break; + case DSPD_SRC_IN: + src = DSBF_DESTALPHA; + dst = DSBF_ZERO; + break; + case DSPD_DST_IN: + src = DSBF_ZERO; + dst = DSBF_SRCALPHA; + break; + case DSPD_SRC_OUT: + src = DSBF_INVDESTALPHA; + dst = DSBF_ZERO; + break; + case DSPD_DST_OUT: + src = DSBF_ZERO; + dst = DSBF_INVSRCALPHA; + break; + case DSPD_SRC_ATOP: + src = DSBF_DESTALPHA; + dst = DSBF_INVSRCALPHA; + break; + case DSPD_DST_ATOP: + src = DSBF_INVDESTALPHA; + dst = DSBF_SRCALPHA; + break; + case DSPD_ADD: + src = DSBF_ONE; + dst = DSBF_ONE; + break; + case DSPD_XOR: + src = DSBF_INVDESTALPHA; + dst = DSBF_INVSRCALPHA; + break; + default: + return DFB_INVARG; + } + + dfb_state_set_src_blend( &data->state, src ); + dfb_state_set_dst_blend( &data->state, dst ); + + return DFB_OK; +} + +static DFBResult +IDirectFBSurface_SetSrcColorKey( IDirectFBSurface *thiz, + u8 r, + u8 g, + u8 b ) +{ + CoreSurface *surface; + + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p )\n", __FUNCTION__, thiz ); + + surface = data->surface; + if (!surface) + return DFB_DESTROYED; + + data->src_key.r = r; + data->src_key.g = g; + data->src_key.b = b; + + if (DFB_PIXELFORMAT_IS_INDEXED( surface->config.format )) + data->src_key.value = dfb_palette_search( surface->palette, + r, g, b, 0x80 ); + else + data->src_key.value = dfb_color_to_pixel( surface->config.format, r, g, b ); + + /* The new key won't be applied to this surface's state. + The key will be taken by the destination surface to apply it + to its state when source color keying is used. */ + + return DFB_OK; +} + +static DFBResult +IDirectFBSurface_SetSrcColorKeyIndex( IDirectFBSurface *thiz, + unsigned int index ) +{ + CoreSurface *surface; + CorePalette *palette; + + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p )\n", __FUNCTION__, thiz ); + + surface = data->surface; + if (!surface) + return DFB_DESTROYED; + + if (! DFB_PIXELFORMAT_IS_INDEXED( surface->config.format )) + return DFB_UNSUPPORTED; + + palette = surface->palette; + if (!palette) + return DFB_UNSUPPORTED; + + if (index > palette->num_entries) + return DFB_INVARG; + + data->src_key.r = palette->entries[index].r; + data->src_key.g = palette->entries[index].g; + data->src_key.b = palette->entries[index].b; + + data->src_key.value = index; + + /* The new key won't be applied to this surface's state. + The key will be taken by the destination surface to apply it + to its state when source color keying is used. */ + + return DFB_OK; +} + +static DFBResult +IDirectFBSurface_SetDstColorKey( IDirectFBSurface *thiz, + u8 r, + u8 g, + u8 b ) +{ + CoreSurface *surface; + + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p )\n", __FUNCTION__, thiz ); + + surface = data->surface; + if (!surface) + return DFB_DESTROYED; + + data->dst_key.r = r; + data->dst_key.g = g; + data->dst_key.b = b; + + if (DFB_PIXELFORMAT_IS_INDEXED( surface->config.format )) + data->dst_key.value = dfb_palette_search( surface->palette, + r, g, b, 0x80 ); + else + data->dst_key.value = dfb_color_to_pixel( surface->config.format, r, g, b ); + + dfb_state_set_dst_colorkey( &data->state, data->dst_key.value ); + + return DFB_OK; +} + +static DFBResult +IDirectFBSurface_SetDstColorKeyIndex( IDirectFBSurface *thiz, + unsigned int index ) +{ + CoreSurface *surface; + CorePalette *palette; + + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p )\n", __FUNCTION__, thiz ); + + surface = data->surface; + if (!surface) + return DFB_DESTROYED; + + if (! DFB_PIXELFORMAT_IS_INDEXED( surface->config.format )) + return DFB_UNSUPPORTED; + + palette = surface->palette; + if (!palette) + return DFB_UNSUPPORTED; + + if (index > palette->num_entries) + return DFB_INVARG; + + data->dst_key.r = palette->entries[index].r; + data->dst_key.g = palette->entries[index].g; + data->dst_key.b = palette->entries[index].b; + + data->dst_key.value = index; + + dfb_state_set_dst_colorkey( &data->state, data->dst_key.value ); + + return DFB_OK; +} + +static DFBResult +IDirectFBSurface_SetIndexTranslation( IDirectFBSurface *thiz, + const int *indices, + int num_indices ) +{ + CoreSurface *surface; + + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + surface = data->surface; + if (!surface) + return DFB_DESTROYED; + + if (! DFB_PIXELFORMAT_IS_INDEXED( surface->config.format )) + return DFB_UNSUPPORTED; + + if (!indices && num_indices > 0) + return DFB_INVAREA; + + if (num_indices < 0 || num_indices > 256) + return DFB_INVARG; + + return dfb_state_set_index_translation( &data->state, indices, num_indices ); +} + +static DFBResult +IDirectFBSurface_SetFont( IDirectFBSurface *thiz, + IDirectFBFont *font ) +{ + DFBResult ret; + + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p, %p )\n", __FUNCTION__, thiz, font ); + + if (data->font != font) { + if (font) { + IDirectFBFont_data *font_data; + + ret = font->AddRef( font ); + if (ret) + return ret; + + DIRECT_INTERFACE_GET_DATA_FROM( font, font_data, IDirectFBFont ); + + data->encoding = font_data->encoding; + } + + if (data->font) + data->font->Release( data->font ); + + data->font = font; + } + + return DFB_OK; +} + +static DFBResult +IDirectFBSurface_GetFont( IDirectFBSurface *thiz, + IDirectFBFont **ret_font ) +{ + DFBResult ret; + IDirectFBFont *font; + + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p )\n", __FUNCTION__, thiz ); + + if (!ret_font) + return DFB_INVARG; + + font = data->font; + if (!font) { + *ret_font = NULL; + return DFB_MISSINGFONT; + } + + ret = font->AddRef( font ); + if (ret) + return ret; + + *ret_font = font; + + return DFB_OK; +} + +static DFBResult +IDirectFBSurface_SetDrawingFlags( IDirectFBSurface *thiz, + DFBSurfaceDrawingFlags flags ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p, 0x%08x )\n", __FUNCTION__, thiz, flags ); + + dfb_state_set_drawing_flags( &data->state, flags ); + + return DFB_OK; +} + +static DFBResult +IDirectFBSurface_FillRectangle( IDirectFBSurface *thiz, + int x, int y, int w, int h ) +{ + DFBRectangle rect = { x, y, w, h }; + + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p )\n", __FUNCTION__, thiz ); + D_DEBUG_AT( Surface, " -> [%2d] %4d,%4d-%4dx%4d\n", 0, x, y, w, h ); + + if (!data->surface) + return DFB_DESTROYED; + + + if (!data->area.current.w || !data->area.current.h) + return DFB_INVAREA; + + if (data->locked) + return DFB_LOCKED; + + if (w<=0 || h<=0) + return DFB_INVARG; + + rect.x += data->area.wanted.x; + rect.y += data->area.wanted.y; + + dfb_gfxcard_fillrectangles( &rect, 1, &data->state ); + + return DFB_OK; +} + + +static DFBResult +IDirectFBSurface_DrawLine( IDirectFBSurface *thiz, + int x1, int y1, int x2, int y2 ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p )\n", __FUNCTION__, thiz ); + D_DEBUG_AT( Surface, " -> [%2d] %4d,%4d-%4d,%4d\n", 0, x1, y1, x2, y2 ); + + if (!data->surface) + return DFB_DESTROYED; + + + if (!data->area.current.w || !data->area.current.h) + return DFB_INVAREA; + + if (data->locked) + return DFB_LOCKED; + + if ((x1 == x2 || y1 == y2) && !(data->state.render_options & DSRO_MATRIX)) { + DFBRectangle rect; + + if (x1 <= x2) { + rect.x = x1; + rect.w = x2 - x1 + 1; + } + else { + rect.x = x2; + rect.w = x1 - x2 + 1; + } + + if (y1 <= y2) { + rect.y = y1; + rect.h = y2 - y1 + 1; + } + else { + rect.y = y2; + rect.h = y1 - y2 + 1; + } + + rect.x += data->area.wanted.x; + rect.y += data->area.wanted.y; + + dfb_gfxcard_fillrectangles( &rect, 1, &data->state ); + } + else { + DFBRegion line = { x1, y1, x2, y2 }; + + line.x1 += data->area.wanted.x; + line.x2 += data->area.wanted.x; + line.y1 += data->area.wanted.y; + line.y2 += data->area.wanted.y; + + dfb_gfxcard_drawlines( &line, 1, &data->state ); + } + + return DFB_OK; +} + +static DFBResult +IDirectFBSurface_DrawLines( IDirectFBSurface *thiz, + const DFBRegion *lines, + unsigned int num_lines ) +{ + unsigned int i; + + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p, %p [%d] )\n", __FUNCTION__, thiz, lines, num_lines ); + + if (!data->surface) + return DFB_DESTROYED; + + + if (!data->area.current.w || !data->area.current.h) + return DFB_INVAREA; + + if (data->locked) + return DFB_LOCKED; + + if (!lines || !num_lines) + return DFB_INVARG; + + /* Check if all lines are either horizontal or vertical */ + for (i=0; iarea.wanted.x || data->area.wanted.y) { + for (i=0; iarea.wanted.x; + local_lines[i].x2 = lines[i].x2 + data->area.wanted.x; + local_lines[i].y1 = lines[i].y1 + data->area.wanted.y; + local_lines[i].y2 = lines[i].y2 + data->area.wanted.y; + } + } + else + /* clipping may modify lines, so we copy them */ + direct_memcpy( local_lines, lines, sizeof(DFBRegion) * num_lines ); + + dfb_gfxcard_drawlines( local_lines, num_lines, &data->state ); + } + /* Optimized rectangle drawing */ + else { + DFBRectangle *local_rects = alloca(sizeof(DFBRectangle) * num_lines); + + for (i=0; iarea.wanted.x + lines[i].x1; + local_rects[i].y = data->area.wanted.y + MIN( lines[i].y1, lines[i].y2 ); + local_rects[i].w = 1; + local_rects[i].h = ABS( lines[i].y2 - lines[i].y1 ) + 1; + } + /* Horizontal line */ + else { + local_rects[i].x = data->area.wanted.x + MIN( lines[i].x1, lines[i].x2 ); + local_rects[i].y = data->area.wanted.y + lines[i].y1; + local_rects[i].w = ABS( lines[i].x2 - lines[i].x1 ) + 1; + local_rects[i].h = 1; + } + } + + dfb_gfxcard_fillrectangles( local_rects, num_lines, &data->state ); + } + + return DFB_OK; +} + +static DFBResult +IDirectFBSurface_DrawRectangle( IDirectFBSurface *thiz, + int x, int y, int w, int h ) +{ + DFBRectangle rect = { x, y, w, h }; + + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p )\n", __FUNCTION__, thiz ); + D_DEBUG_AT( Surface, " -> [%2d] %4d,%4d-%4dx%4d\n", 0, x, y, w, h ); + + if (!data->surface) + return DFB_DESTROYED; + + + if (!data->area.current.w || !data->area.current.h) + return DFB_INVAREA; + + if (data->locked) + return DFB_LOCKED; + + if (w<=0 || h<=0) + return DFB_INVARG; + + rect.x += data->area.wanted.x; + rect.y += data->area.wanted.y; + + dfb_gfxcard_drawrectangle( &rect, &data->state ); + + return DFB_OK; +} + +static DFBResult +IDirectFBSurface_FillTriangle( IDirectFBSurface *thiz, + int x1, int y1, + int x2, int y2, + int x3, int y3 ) +{ + DFBTriangle tri = { x1, y1, x2, y2, x3, y3 }; + + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p )\n", __FUNCTION__, thiz ); + D_DEBUG_AT( Surface, " -> [%2d] %4d,%4d-%4d,%4d-%4d,%4d\n", 0, x1, y1, x2, y2, x3, y3 ); + + if (!data->surface) + return DFB_DESTROYED; + + + if (!data->area.current.w || !data->area.current.h) + return DFB_INVAREA; + + if (data->locked) + return DFB_LOCKED; + + tri.x1 += data->area.wanted.x; + tri.y1 += data->area.wanted.y; + tri.x2 += data->area.wanted.x; + tri.y2 += data->area.wanted.y; + tri.x3 += data->area.wanted.x; + tri.y3 += data->area.wanted.y; + + dfb_gfxcard_filltriangles( &tri, 1, &data->state ); + + return DFB_OK; +} + +static DFBResult +IDirectFBSurface_FillRectangles( IDirectFBSurface *thiz, + const DFBRectangle *rects, + unsigned int num_rects ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p, %p [%d] )\n", __FUNCTION__, thiz, rects, num_rects ); + + DFB_RECTANGLES_DEBUG_AT( Surface, rects, num_rects ); + + + if (!data->surface) + return DFB_DESTROYED; + + + if (!data->area.current.w || !data->area.current.h) + return DFB_INVAREA; + + if (data->locked) + return DFB_LOCKED; + + if (!rects || !num_rects) + return DFB_INVARG; + + if (data->area.wanted.x || data->area.wanted.y) { + unsigned int i; + DFBRectangle *local_rects; + bool malloced = (num_rects > 256); + + if (malloced) + local_rects = D_MALLOC( sizeof(DFBRectangle) * num_rects ); + else + local_rects = alloca( sizeof(DFBRectangle) * num_rects ); + + for (i=0; iarea.wanted.x; + local_rects[i].y = rects[i].y + data->area.wanted.y; + local_rects[i].w = rects[i].w; + local_rects[i].h = rects[i].h; + } + + dfb_gfxcard_fillrectangles( local_rects, num_rects, &data->state ); + + if (malloced) + D_FREE( local_rects ); + } + else + dfb_gfxcard_fillrectangles( rects, num_rects, &data->state ); + + return DFB_OK; +} + +static DFBResult +IDirectFBSurface_FillSpans( IDirectFBSurface *thiz, + int y, + const DFBSpan *spans, + unsigned int num_spans ) +{ + DFBSpan *local_spans = alloca(sizeof(DFBSpan) * num_spans); + + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p )\n", __FUNCTION__, thiz ); + + if (!data->surface) + return DFB_DESTROYED; + + + if (!data->area.current.w || !data->area.current.h) + return DFB_INVAREA; + + if (data->locked) + return DFB_LOCKED; + + if (!spans || !num_spans) + return DFB_INVARG; + + if (data->area.wanted.x || data->area.wanted.y) { + unsigned int i; + + for (i=0; iarea.wanted.x; + local_spans[i].w = spans[i].w; + } + } + else + /* clipping may modify spans, so we copy them */ + direct_memcpy( local_spans, spans, sizeof(DFBSpan) * num_spans ); + + dfb_gfxcard_fillspans( y + data->area.wanted.y, local_spans, num_spans, &data->state ); + + return DFB_OK; +} + +static DFBResult +IDirectFBSurface_FillTriangles( IDirectFBSurface *thiz, + const DFBTriangle *tris, + unsigned int num_tris ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p )\n", __FUNCTION__, thiz ); + + if (!data->surface) + return DFB_DESTROYED; + + + if (!data->area.current.w || !data->area.current.h) + return DFB_INVAREA; + + if (data->locked) + return DFB_LOCKED; + + if (!tris || !num_tris) + return DFB_INVARG; + + if (data->area.wanted.x || data->area.wanted.y) { + unsigned int i; + DFBTriangle *local_tris; + bool malloced = (num_tris > 170); + + if (malloced) + local_tris = D_MALLOC( sizeof(DFBTriangle) * num_tris ); + else + local_tris = alloca( sizeof(DFBTriangle) * num_tris ); + + for (i=0; iarea.wanted.x; + local_tris[i].y1 = tris[i].y1 + data->area.wanted.y; + local_tris[i].x2 = tris[i].x2 + data->area.wanted.x; + local_tris[i].y2 = tris[i].y2 + data->area.wanted.y; + local_tris[i].x3 = tris[i].x3 + data->area.wanted.x; + local_tris[i].y3 = tris[i].y3 + data->area.wanted.y; + } + + dfb_gfxcard_filltriangles( local_tris, num_tris, &data->state ); + + if (malloced) + D_FREE( local_tris ); + } + else + dfb_gfxcard_filltriangles( tris, num_tris, &data->state ); + + return DFB_OK; +} + +static DFBResult +IDirectFBSurface_SetBlittingFlags( IDirectFBSurface *thiz, + DFBSurfaceBlittingFlags flags ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p )\n", __FUNCTION__, thiz ); + + dfb_state_set_blitting_flags( &data->state, flags ); + + return DFB_OK; +} + +static DFBResult +IDirectFBSurface_Blit( IDirectFBSurface *thiz, + IDirectFBSurface *source, + const DFBRectangle *sr, + int dx, int dy ) +{ + DFBRectangle srect; + IDirectFBSurface_data *src_data; + + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p )\n", __FUNCTION__, thiz ); + + if (sr) + D_DEBUG_AT( Surface, " -> [%2d] %4d,%4d-%4dx%4d <- %4d,%4d\n", 0, dx, dy, sr->w, sr->h, sr->x, sr->y ); + + if (!data->surface) + return DFB_DESTROYED; + + if (!source) + return DFB_INVARG; + + if (!data->area.current.w || !data->area.current.h) + return DFB_INVAREA; + + if (data->locked) + return DFB_LOCKED; + + + src_data = (IDirectFBSurface_data*)source->priv; + + if (!src_data->area.current.w || !src_data->area.current.h) + return DFB_INVAREA; + + if (sr) { + if (sr->w < 1 || sr->h < 1) + return DFB_OK; + + srect = *sr; + + srect.x += src_data->area.wanted.x; + srect.y += src_data->area.wanted.y; + + if (!dfb_rectangle_intersect( &srect, &src_data->area.current )) + return DFB_INVAREA; + + dx += srect.x - (sr->x + src_data->area.wanted.x); + dy += srect.y - (sr->y + src_data->area.wanted.y); + } + else { + srect = src_data->area.current; + + dx += srect.x - src_data->area.wanted.x; + dy += srect.y - src_data->area.wanted.y; + } + + dfb_state_set_source( &data->state, src_data->surface ); + + /* fetch the source color key from the source if necessary */ + if (data->state.blittingflags & DSBLIT_SRC_COLORKEY) + dfb_state_set_src_colorkey( &data->state, src_data->src_key.value ); + + dfb_gfxcard_blit( &srect, + data->area.wanted.x + dx, + data->area.wanted.y + dy, &data->state ); + + return DFB_OK; +} + +static DFBResult +IDirectFBSurface_TileBlit( IDirectFBSurface *thiz, + IDirectFBSurface *source, + const DFBRectangle *sr, + int dx, int dy ) +{ + DFBRectangle srect; + IDirectFBSurface_data *src_data; + + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p )\n", __FUNCTION__, thiz ); + + if (sr) + D_DEBUG_AT( Surface, " -> [%2d] %4d,%4d-%4dx%4d <- %4d,%4d\n", 0, dx, dy, sr->w, sr->h, sr->x, sr->y ); + + if (!data->surface) + return DFB_DESTROYED; + + + if (!data->area.current.w || !data->area.current.h) + return DFB_INVAREA; + + if (data->locked) + return DFB_LOCKED; + + if (!source) + return DFB_INVARG; + + + src_data = (IDirectFBSurface_data*)source->priv; + + if (!src_data->area.current.w || !src_data->area.current.h) + return DFB_INVAREA; + + + if (sr) { + if (sr->w < 1 || sr->h < 1) + return DFB_OK; + + srect = *sr; + + srect.x += src_data->area.wanted.x; + srect.y += src_data->area.wanted.y; + + if (!dfb_rectangle_intersect( &srect, &src_data->area.current )) + return DFB_INVAREA; + + dx += srect.x - (sr->x + src_data->area.wanted.x); + dy += srect.y - (sr->y + src_data->area.wanted.y); + } + else { + srect = src_data->area.current; + + dx += srect.x - src_data->area.wanted.x; + dy += srect.y - src_data->area.wanted.y; + } + + dfb_state_set_source( &data->state, src_data->surface ); + + /* fetch the source color key from the source if necessary */ + if (data->state.blittingflags & DSBLIT_SRC_COLORKEY) + dfb_state_set_src_colorkey( &data->state, src_data->src_key.value ); + + dx %= srect.w; + if (dx > 0) + dx -= srect.w; + + dy %= srect.h; + if (dy > 0) + dy -= srect.h; + + dx += data->area.wanted.x; + dy += data->area.wanted.y; + + dfb_gfxcard_tileblit( &srect, dx, dy, + dx + data->area.wanted.w + srect.w - 1, + dy + data->area.wanted.h + srect.h - 1, &data->state ); + + return DFB_OK; +} + +static DFBResult +IDirectFBSurface_BatchBlit( IDirectFBSurface *thiz, + IDirectFBSurface *source, + const DFBRectangle *source_rects, + const DFBPoint *dest_points, + int num ) +{ + int i, dx, dy, sx, sy; + DFBRectangle *rects; + DFBPoint *points; + IDirectFBSurface_data *src_data; + + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p )\n", __FUNCTION__, thiz ); + + if (!data->surface) + return DFB_DESTROYED; + + if (!source || !source_rects || !dest_points || num < 1) + return DFB_INVARG; + + if (!data->area.current.w || !data->area.current.h) + return DFB_INVAREA; + + if (data->locked) + return DFB_LOCKED; + + + src_data = (IDirectFBSurface_data*)source->priv; + + if (!src_data->area.current.w || !src_data->area.current.h) + return DFB_INVAREA; + + dx = data->area.wanted.x; + dy = data->area.wanted.y; + + sx = src_data->area.wanted.x; + sy = src_data->area.wanted.y; + + rects = alloca( sizeof(DFBRectangle) * num ); + points = alloca( sizeof(DFBPoint) * num ); + + direct_memcpy( rects, source_rects, sizeof(DFBRectangle) * num ); + direct_memcpy( points, dest_points, sizeof(DFBPoint) * num ); + + for (i=0; iarea.current )) + rects[i].w = rects[i].h = 0; + + points[i].x += rects[i].x - (source_rects[i].x + sx); + points[i].y += rects[i].y - (source_rects[i].y + sy); + } + + dfb_state_set_source( &data->state, src_data->surface ); + + /* fetch the source color key from the source if necessary */ + if (data->state.blittingflags & DSBLIT_SRC_COLORKEY) + dfb_state_set_src_colorkey( &data->state, src_data->src_key.value ); + + dfb_gfxcard_batchblit( rects, points, num, &data->state ); + + return DFB_OK; +} + +static DFBResult +IDirectFBSurface_StretchBlit( IDirectFBSurface *thiz, + IDirectFBSurface *source, + const DFBRectangle *source_rect, + const DFBRectangle *destination_rect ) +{ + DFBRectangle srect, drect; + IDirectFBSurface_data *src_data; + + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p )\n", __FUNCTION__, thiz ); + + if (!data->surface) + return DFB_DESTROYED; + + + if (!data->area.current.w || !data->area.current.h) + return DFB_INVAREA; + + if (data->locked) + return DFB_LOCKED; + + if (!source) + return DFB_INVARG; + + + src_data = (IDirectFBSurface_data*)source->priv; + + if (!src_data->area.current.w || !src_data->area.current.h) + return DFB_INVAREA; + + + /* do destination rectangle */ + if (destination_rect) { + if (destination_rect->w < 1 || destination_rect->h < 1) + return DFB_INVARG; + + drect = *destination_rect; + + drect.x += data->area.wanted.x; + drect.y += data->area.wanted.y; + } + else + drect = data->area.wanted; + + /* do source rectangle */ + if (source_rect) { + if (source_rect->w < 1 || source_rect->h < 1) + return DFB_INVARG; + + srect = *source_rect; + + srect.x += src_data->area.wanted.x; + srect.y += src_data->area.wanted.y; + } + else + srect = src_data->area.wanted; + + + /* clipping of the source rectangle must be applied to the destination */ + { + DFBRectangle orig_src = srect; + + if (!dfb_rectangle_intersect( &srect, &src_data->area.current )) + return DFB_INVAREA; + + if (srect.x != orig_src.x) + drect.x += (int)( (srect.x - orig_src.x) * + (drect.w / (float)orig_src.w) + 0.5f); + + if (srect.y != orig_src.y) + drect.y += (int)( (srect.y - orig_src.y) * + (drect.h / (float)orig_src.h) + 0.5f); + + if (srect.w != orig_src.w) + drect.w = D_ICEIL(drect.w * (srect.w / (float)orig_src.w)); + if (srect.h != orig_src.h) + drect.h = D_ICEIL(drect.h * (srect.h / (float)orig_src.h)); + } + + dfb_state_set_source( &data->state, src_data->surface ); + + /* fetch the source color key from the source if necessary */ + if (data->state.blittingflags & DSBLIT_SRC_COLORKEY) + dfb_state_set_src_colorkey( &data->state, src_data->src_key.value ); + + dfb_gfxcard_stretchblit( &srect, &drect, &data->state ); + + return DFB_OK; +} + +#define SET_VERTEX(v,X,Y,Z,W,S,T) \ + do { \ + (v)->x = X; \ + (v)->y = Y; \ + (v)->z = Z; \ + (v)->w = W; \ + (v)->s = S; \ + (v)->t = T; \ + } while (0) + +static DFBResult +IDirectFBSurface_TextureTriangles( IDirectFBSurface *thiz, + IDirectFBSurface *source, + const DFBVertex *vertices, + const int *indices, + int num, + DFBTriangleFormation formation ) +{ + int i; + DFBVertex *translated; + IDirectFBSurface_data *src_data; + bool src_sub; + float x0 = 0; + float y0 = 0; + + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p )\n", __FUNCTION__, thiz ); + + if (!data->surface) + return DFB_DESTROYED; + + + if (!data->area.current.w || !data->area.current.h) + return DFB_INVAREA; + + if (data->locked) + return DFB_LOCKED; + + if (!source || !vertices || num < 3) + return DFB_INVARG; + + src_data = (IDirectFBSurface_data*)source->priv; + + if ((src_sub = (src_data->caps & DSCAPS_SUBSURFACE))) { + D_ONCE( "sub surface texture not fully working with 'repeated' mapping" ); + + x0 = data->area.wanted.x; + y0 = data->area.wanted.y; + } + + switch (formation) { + case DTTF_LIST: + if (num % 3) + return DFB_INVARG; + break; + + case DTTF_STRIP: + case DTTF_FAN: + break; + + default: + return DFB_INVARG; + } + + translated = alloca( num * sizeof(DFBVertex) ); + if (!translated) + return DFB_NOSYSTEMMEMORY; + + /* TODO: pass indices through to driver */ + if (src_sub) { + float oowidth = 1.0f / src_data->surface->config.size.w; + float ooheight = 1.0f / src_data->surface->config.size.h; + + float s0 = src_data->area.wanted.x * oowidth; + float t0 = src_data->area.wanted.y * ooheight; + + float fs = src_data->area.wanted.w * oowidth; + float ft = src_data->area.wanted.h * ooheight; + + for (i=0; ix, y0 + in->y, in->z, in->w, + s0 + fs * in->s, t0 + ft * in->t ); + } + } + else { + if (indices) { + for (i=0; ix, y0 + in->y, in->z, in->w, in->s, in->t ); + } + } + else { + direct_memcpy( translated, vertices, num * sizeof(DFBVertex) ); + + for (i=0; istate, src_data->surface ); + + /* fetch the source color key from the source if necessary */ + if (data->state.blittingflags & DSBLIT_SRC_COLORKEY) + dfb_state_set_src_colorkey( &data->state, src_data->src_key.value ); + + dfb_gfxcard_texture_triangles( translated, num, formation, &data->state ); + + return DFB_OK; +} + +static DFBResult +IDirectFBSurface_DrawString( IDirectFBSurface *thiz, + const char *text, int bytes, + int x, int y, + DFBSurfaceTextFlags flags ) +{ + DFBResult ret; + IDirectFBFont *font; + IDirectFBFont_data *font_data; + CoreFont *core_font; + unsigned int layers = 1; + + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p )\n", __FUNCTION__, thiz ); + + if (!data->surface) + return DFB_DESTROYED; + + if (!text) + return DFB_INVARG; + + if (!data->area.current.w || !data->area.current.h) + return DFB_INVAREA; + + if (data->locked) + return DFB_LOCKED; + + if (!data->font) + return DFB_MISSINGFONT; + + if (bytes < 0) + bytes = strlen (text); + + if (bytes == 0) + return DFB_OK; + + font = data->font; + + DIRECT_INTERFACE_GET_DATA_FROM( font, font_data, IDirectFBFont ); + + core_font = font_data->font; + + if (flags & DSTF_OUTLINE) { + if (!(core_font->attributes & DFFA_OUTLINED)) + return DFB_UNSUPPORTED; + + layers = 2; + } + + if (!(flags & DSTF_TOP)) { + x += core_font->ascender * core_font->up_unit_x; + y += core_font->ascender * core_font->up_unit_y; + + if (flags & DSTF_BOTTOM) { + x -= core_font->descender * core_font->up_unit_x; + y -= core_font->descender * core_font->up_unit_y; + } + } + + if (flags & (DSTF_RIGHT | DSTF_CENTER)) { + int i, num, kx, ky; + int xsize = 0; + int ysize = 0; + unsigned int prev = 0; + unsigned int indices[bytes]; + + /* FIXME: Avoid double locking and decoding. */ + dfb_font_lock( core_font ); + + /* Decode string to character indices. */ + ret = dfb_font_decode_text( core_font, data->encoding, text, bytes, indices, &num ); + if (ret) { + dfb_font_unlock( core_font ); + return ret; + } + + /* Calculate string width. */ + for (i=0; ixadvance; + ysize += glyph->yadvance; + + if (prev && core_font->GetKerning && + core_font->GetKerning( core_font, prev, current, &kx, &ky ) == DFB_OK) { + xsize += kx; + ysize += ky; + } + } + + prev = current; + } + + dfb_font_unlock( core_font ); + + /* Justify. */ + if (flags & DSTF_RIGHT) { + x -= xsize; + y -= ysize; + } + else if (flags & DSTF_CENTER) { + x -= xsize >> 1; + y -= ysize >> 1; + } + } + + dfb_gfxcard_drawstring( (const unsigned char*) text, bytes, data->encoding, + data->area.wanted.x + x, data->area.wanted.y + y, + core_font, layers, &data->state ); + + return DFB_OK; +} + +static DFBResult +IDirectFBSurface_DrawGlyph( IDirectFBSurface *thiz, + unsigned int character, int x, int y, + DFBSurfaceTextFlags flags ) +{ + DFBResult ret; + int l; + IDirectFBFont *font; + IDirectFBFont_data *font_data; + CoreFont *core_font; + CoreGlyphData *glyph[DFB_FONT_MAX_LAYERS]; + unsigned int index; + unsigned int layers = 1; + + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p, 0x%x, %d,%d, 0x%x )\n", + __FUNCTION__, thiz, character, x, y, flags ); + + if (!data->surface) + return DFB_DESTROYED; + + if (!character) + return DFB_INVARG; + + if (!data->area.current.w || !data->area.current.h) + return DFB_INVAREA; + + if (data->locked) + return DFB_LOCKED; + + if (!data->font) + return DFB_MISSINGFONT; + + font = data->font; + + DIRECT_INTERFACE_GET_DATA_FROM( font, font_data, IDirectFBFont ); + + core_font = font_data->font; + + if (flags & DSTF_OUTLINE) { + if (!(core_font->attributes & DFFA_OUTLINED)) + return DFB_UNSUPPORTED; + + layers = 2; + } + + dfb_font_lock( core_font ); + + ret = dfb_font_decode_character( core_font, data->encoding, character, &index ); + if (ret) { + dfb_font_unlock( core_font ); + return ret; + } + + for (l=0; lascender * core_font->up_unit_x; + y += core_font->ascender * core_font->up_unit_y; + + if (flags & DSTF_BOTTOM) { + x -= core_font->descender * core_font->up_unit_x; + y -= core_font->descender * core_font->up_unit_y; + } + } + + if (flags & (DSTF_RIGHT | DSTF_CENTER)) { + if (flags & DSTF_RIGHT) { + x -= glyph[0]->xadvance; + y -= glyph[0]->yadvance; + } + else if (flags & DSTF_CENTER) { + x -= glyph[0]->xadvance >> 1; + y -= glyph[0]->yadvance >> 1; + } + } + + dfb_gfxcard_drawglyph( glyph, + data->area.wanted.x + x, data->area.wanted.y + y, + core_font, layers, &data->state ); + + dfb_font_unlock( core_font ); + + return DFB_OK; +} + +static DFBResult +IDirectFBSurface_SetEncoding( IDirectFBSurface *thiz, + DFBTextEncodingID encoding ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p, %d )\n", __FUNCTION__, thiz, encoding ); + + /* TODO: check for support or fail later? */ + data->encoding = encoding; + + return DFB_OK; +} + +static DFBResult +IDirectFBSurface_GetSubSurface( IDirectFBSurface *thiz, + const DFBRectangle *rect, + IDirectFBSurface **surface ) +{ + DFBResult ret; + + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p )\n", __FUNCTION__, thiz ); + + /* Check arguments */ + if (!data->surface) + return DFB_DESTROYED; + + if (!surface) + return DFB_INVARG; + + /* Allocate interface */ + DIRECT_ALLOCATE_INTERFACE( *surface, IDirectFBSurface ); + + if (rect || data->limit_set) { + DFBRectangle wanted, granted; + + /* Compute wanted rectangle */ + if (rect) { + wanted = *rect; + + wanted.x += data->area.wanted.x; + wanted.y += data->area.wanted.y; + + if (wanted.w <= 0 || wanted.h <= 0) { + wanted.w = 0; + wanted.h = 0; + } + } + else { + wanted = data->area.wanted; + } + + /* Compute granted rectangle */ + granted = wanted; + + dfb_rectangle_intersect( &granted, &data->area.granted ); + + /* Construct */ + ret = IDirectFBSurface_Construct( *surface, thiz, + &wanted, &granted, &data->area.insets, + data->surface, + data->caps | DSCAPS_SUBSURFACE, data->core ); + } + else { + /* Construct */ + ret = IDirectFBSurface_Construct( *surface, thiz, + NULL, NULL, &data->area.insets, + data->surface, + data->caps | DSCAPS_SUBSURFACE, data->core ); + } + + return ret; +} + +static DFBResult +IDirectFBSurface_MakeSubSurface( IDirectFBSurface *thiz, + IDirectFBSurface *from, + const DFBRectangle *rect ) +{ + CoreSurface *surface; + DFBRectangle wanted, granted; + DFBRectangle full_rect; + IDirectFBSurface_data *from_data; + + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p )\n", __FUNCTION__, thiz ); + + /* Check arguments */ + if (!from) + return DFB_INVARG; + + surface = data->surface; + if (!surface) + return DFB_DESTROYED; + + DIRECT_INTERFACE_GET_DATA_FROM(from, from_data, IDirectFBSurface); + + /* Check if CoreSurface is the same */ + if (from_data->surface != surface) + return DFB_UNSUPPORTED; + + + full_rect.x = 0; + full_rect.y = 0; + full_rect.w = surface->config.size.w; + full_rect.h = surface->config.size.h; + + if (rect || from_data->limit_set) { + /* Compute wanted rectangle */ + if (rect) { + wanted = *rect; + + wanted.x += from_data->area.wanted.x; + wanted.y += from_data->area.wanted.y; + + if (wanted.w <= 0 || wanted.h <= 0) { + wanted.w = 0; + wanted.h = 0; + } + } + else { + wanted = from_data->area.wanted; + } + + /* Compute granted rectangle */ + granted = wanted; + + dfb_rectangle_intersect( &granted, &from_data->area.granted ); + } + else { + wanted = full_rect; + granted = full_rect; + } + + + data->caps |= DSCAPS_SUBSURFACE; + + + data->area.wanted = wanted; + data->area.granted = granted; + + data->area.current = data->area.granted; + dfb_rectangle_intersect( &data->area.current, &full_rect ); + + + data->state.clip.x1 = data->area.current.x; + data->state.clip.y1 = data->area.current.y; + data->state.clip.x2 = data->area.current.x + (data->area.current.w ? : 1) - 1; + data->state.clip.y2 = data->area.current.y + (data->area.current.h ? : 1) - 1; + + data->state.modified |= SMF_CLIP; + + + return DFB_OK; +} + +static DFBResult +IDirectFBSurface_GetGL( IDirectFBSurface *thiz, + IDirectFBGL **interface ) +{ + DFBResult ret; + DirectInterfaceFuncs *funcs = NULL; + + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p )\n", __FUNCTION__, thiz ); + + if (!data->surface) + return DFB_DESTROYED; + + if (!interface) + return DFB_INVARG; + + if (!data->area.current.w || !data->area.current.h) + return DFB_INVAREA; + + + ret = DirectGetInterface( &funcs, "IDirectFBGL", NULL, DirectProbeInterface, thiz ); + if (ret) + return ret; + + ret = funcs->Allocate( (void**)interface ); + if (ret) + return ret; + + ret = funcs->Construct( *interface, thiz ); + if (ret) + *interface = NULL; + + return ret; +} + +static DFBResult +IDirectFBSurface_Dump( IDirectFBSurface *thiz, + const char *directory, + const char *prefix ) +{ + CoreSurface *surface; + + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p )\n", __FUNCTION__, thiz ); + + if (!directory) + return DFB_INVARG; + + if (!data->area.current.w || !data->area.current.h) + return DFB_INVAREA; + + if (data->caps & DSCAPS_SUBSURFACE) { + D_ONCE( "sub surface dumping not supported yet" ); + return DFB_UNSUPPORTED; + } + + surface = data->surface; + if (!surface) + return DFB_DESTROYED; + + return dfb_surface_dump_buffer( surface, CSBR_FRONT, directory, prefix ); +} + +static DFBResult +IDirectFBSurface_DisableAcceleration( IDirectFBSurface *thiz, + DFBAccelerationMask mask ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p )\n", __FUNCTION__, thiz ); + + if (D_FLAGS_INVALID( mask, DFXL_ALL )) + return DFB_INVARG; + + data->state.disabled = mask; + + return DFB_OK; +} + +static DFBResult +IDirectFBSurface_ReleaseSource( IDirectFBSurface *thiz ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p )\n", __FUNCTION__, thiz ); + + dfb_state_set_source( &data->state, NULL ); + dfb_state_set_source_mask( &data->state, NULL ); + + return DFB_OK; +} + +static DFBResult +IDirectFBSurface_SetRenderOptions( IDirectFBSurface *thiz, + DFBSurfaceRenderOptions options ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p )\n", __FUNCTION__, thiz ); + + dfb_state_set_render_options( &data->state, options ); + + return DFB_OK; +} + +static DFBResult +IDirectFBSurface_SetMatrix( IDirectFBSurface *thiz, + const s32 *matrix ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p, %p )\n", __FUNCTION__, thiz, matrix ); + + if (!matrix) + return DFB_INVARG; + + dfb_state_set_matrix( &data->state, matrix ); + + return DFB_OK; +} + +static DFBResult +IDirectFBSurface_SetSourceMask( IDirectFBSurface *thiz, + IDirectFBSurface *mask, + int x, + int y, + DFBSurfaceMaskFlags flags ) +{ + DFBResult ret; + DFBPoint offset = { x, y }; + IDirectFBSurface_data *mask_data; + + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p, %p, %d,%d, 0x%04x )\n", __FUNCTION__, thiz, mask, x, y, flags ); + + if (!mask || flags & ~DSMF_ALL) + return DFB_INVARG; + + DIRECT_INTERFACE_GET_DATA_FROM(mask, mask_data, IDirectFBSurface); + + if (!mask_data->surface) + return DFB_DESTROYED; + + ret = dfb_state_set_source_mask( &data->state, mask_data->surface ); + if (ret) + return ret; + + dfb_state_set_source_mask_vals( &data->state, &offset, flags ); + + return DFB_OK; +} + +/******/ + +DFBResult IDirectFBSurface_Construct( IDirectFBSurface *thiz, + IDirectFBSurface *parent, + DFBRectangle *wanted, + DFBRectangle *granted, + DFBInsets *insets, + CoreSurface *surface, + DFBSurfaceCapabilities caps, + CoreDFB *core ) +{ + DFBRectangle rect = { 0, 0, surface->config.size.w, surface->config.size.h }; + + DIRECT_ALLOCATE_INTERFACE_DATA(thiz, IDirectFBSurface) + + D_DEBUG_AT( Surface, "%s( %p )\n", __FUNCTION__, thiz ); + + data->ref = 1; + data->caps = caps | surface->config.caps; + data->core = core; + + if (dfb_surface_ref( surface )) { + DIRECT_DEALLOCATE_INTERFACE(thiz); + return DFB_FAILURE; + } + + if (parent && dfb_config->startstop) { + IDirectFBSurface_data *parent_data; + + if (parent->AddRef( parent )) { + dfb_surface_unref( surface ); + DIRECT_DEALLOCATE_INTERFACE(thiz); + return DFB_FAILURE; + } + + DIRECT_INTERFACE_GET_DATA_FROM( parent, parent_data, IDirectFBSurface ); + + pthread_mutex_lock( &parent_data->children_lock ); + + direct_list_append( &parent_data->children_data, &data->link ); + + pthread_mutex_unlock( &parent_data->children_lock ); + + data->parent = parent; + } + + pthread_mutex_init( &data->children_lock, NULL ); + + /* The area insets */ + if (insets) { + data->area.insets = *insets; + dfb_rectangle_subtract( &rect, insets ); + } + + /* The area that was requested */ + if (wanted) + data->area.wanted = *wanted; + else + data->area.wanted = rect; + + /* The area that will never be exceeded */ + if (granted) + data->area.granted = *granted; + else + data->area.granted = data->area.wanted; + + /* The currently accessible rectangle */ + data->area.current = data->area.granted; + dfb_rectangle_intersect( &data->area.current, &rect ); + + /* Whether granted rectangle is meaningful */ + data->limit_set = (granted != NULL); + + data->surface = surface; + + dfb_state_init( &data->state, NULL ); + dfb_state_set_destination( &data->state, surface ); + + data->state.clip.x1 = data->area.current.x; + data->state.clip.y1 = data->area.current.y; + data->state.clip.x2 = data->area.current.x + (data->area.current.w ? : 1) - 1; + data->state.clip.y2 = data->area.current.y + (data->area.current.h ? : 1) - 1; + + data->state.modified = SMF_ALL; + + thiz->AddRef = IDirectFBSurface_AddRef; + thiz->Release = IDirectFBSurface_Release; + + thiz->GetCapabilities = IDirectFBSurface_GetCapabilities; + thiz->GetPosition = IDirectFBSurface_GetPosition; + thiz->GetSize = IDirectFBSurface_GetSize; + thiz->GetVisibleRectangle = IDirectFBSurface_GetVisibleRectangle; + thiz->GetPixelFormat = IDirectFBSurface_GetPixelFormat; + thiz->GetAccelerationMask = IDirectFBSurface_GetAccelerationMask; + + thiz->GetPalette = IDirectFBSurface_GetPalette; + thiz->SetPalette = IDirectFBSurface_SetPalette; + thiz->SetAlphaRamp = IDirectFBSurface_SetAlphaRamp; + + thiz->Lock = IDirectFBSurface_Lock; + thiz->GetFramebufferOffset = IDirectFBSurface_GetFramebufferOffset; + thiz->Unlock = IDirectFBSurface_Unlock; + thiz->Flip = IDirectFBSurface_Flip; + thiz->SetField = IDirectFBSurface_SetField; + thiz->Clear = IDirectFBSurface_Clear; + + thiz->SetClip = IDirectFBSurface_SetClip; + thiz->GetClip = IDirectFBSurface_GetClip; + thiz->SetColor = IDirectFBSurface_SetColor; + thiz->SetColorIndex = IDirectFBSurface_SetColorIndex; + thiz->SetSrcBlendFunction = IDirectFBSurface_SetSrcBlendFunction; + thiz->SetDstBlendFunction = IDirectFBSurface_SetDstBlendFunction; + thiz->SetPorterDuff = IDirectFBSurface_SetPorterDuff; + thiz->SetSrcColorKey = IDirectFBSurface_SetSrcColorKey; + thiz->SetSrcColorKeyIndex = IDirectFBSurface_SetSrcColorKeyIndex; + thiz->SetDstColorKey = IDirectFBSurface_SetDstColorKey; + thiz->SetDstColorKeyIndex = IDirectFBSurface_SetDstColorKeyIndex; + thiz->SetIndexTranslation = IDirectFBSurface_SetIndexTranslation; + + thiz->SetBlittingFlags = IDirectFBSurface_SetBlittingFlags; + thiz->Blit = IDirectFBSurface_Blit; + thiz->TileBlit = IDirectFBSurface_TileBlit; + thiz->BatchBlit = IDirectFBSurface_BatchBlit; + thiz->StretchBlit = IDirectFBSurface_StretchBlit; + thiz->TextureTriangles = IDirectFBSurface_TextureTriangles; + + thiz->SetDrawingFlags = IDirectFBSurface_SetDrawingFlags; + thiz->FillRectangle = IDirectFBSurface_FillRectangle; + thiz->DrawLine = IDirectFBSurface_DrawLine; + thiz->DrawLines = IDirectFBSurface_DrawLines; + thiz->DrawRectangle = IDirectFBSurface_DrawRectangle; + thiz->FillTriangle = IDirectFBSurface_FillTriangle; + thiz->FillRectangles = IDirectFBSurface_FillRectangles; + thiz->FillSpans = IDirectFBSurface_FillSpans; + thiz->FillTriangles = IDirectFBSurface_FillTriangles; + + thiz->SetFont = IDirectFBSurface_SetFont; + thiz->GetFont = IDirectFBSurface_GetFont; + thiz->DrawString = IDirectFBSurface_DrawString; + thiz->DrawGlyph = IDirectFBSurface_DrawGlyph; + thiz->SetEncoding = IDirectFBSurface_SetEncoding; + + thiz->GetSubSurface = IDirectFBSurface_GetSubSurface; + + thiz->GetGL = IDirectFBSurface_GetGL; + + thiz->Dump = IDirectFBSurface_Dump; + thiz->DisableAcceleration = IDirectFBSurface_DisableAcceleration; + thiz->ReleaseSource = IDirectFBSurface_ReleaseSource; + + thiz->SetRenderOptions = IDirectFBSurface_SetRenderOptions; + thiz->SetMatrix = IDirectFBSurface_SetMatrix; + thiz->SetSourceMask = IDirectFBSurface_SetSourceMask; + + thiz->MakeSubSurface = IDirectFBSurface_MakeSubSurface; + + thiz->Write = IDirectFBSurface_Write; + thiz->Read = IDirectFBSurface_Read; + + thiz->SetColors = IDirectFBSurface_SetColors; + + dfb_surface_attach( surface, + IDirectFBSurface_listener, thiz, &data->reaction ); + + return DFB_OK; +} + + +/* internal */ + +static ReactionResult +IDirectFBSurface_listener( const void *msg_data, void *ctx ) +{ + const CoreSurfaceNotification *notification = msg_data; + IDirectFBSurface *thiz = ctx; + IDirectFBSurface_data *data = thiz->priv; + CoreSurface *surface = data->surface; + + D_DEBUG_AT( Surface, "%s( %p, %p )\n", __FUNCTION__, msg_data, ctx ); + + if (notification->flags & CSNF_DESTROY) { + if (data->surface) { + data->surface = NULL; + dfb_surface_unref( surface ); + } + return RS_REMOVE; + } + + if (notification->flags & CSNF_SIZEFORMAT) { + DFBRectangle rect = { 0, 0, surface->config.size.w, surface->config.size.h }; + + dfb_rectangle_subtract( &rect, &data->area.insets ); + + if (data->limit_set) { + data->area.current = data->area.granted; + + dfb_rectangle_intersect( &data->area.current, &rect ); + } + else + data->area.wanted = data->area.granted = data->area.current = rect; + + /* Reset clip to avoid crashes caused by drawing out of bounds. */ + if (data->clip_set) + thiz->SetClip( thiz, &data->clip_wanted ); + else + thiz->SetClip( thiz, NULL ); + } + + return RS_OK; +} + +void +IDirectFBSurface_StopAll( IDirectFBSurface_data *data ) +{ + if (!dfb_config->startstop) + return; + + if (data->children_data) { + IDirectFBSurface_data *child; + + pthread_mutex_lock( &data->children_lock ); + + direct_list_foreach (child, data->children_data) + IDirectFBSurface_StopAll( child ); + + pthread_mutex_unlock( &data->children_lock ); + } + + /* Signal end of sequence of operations. */ + dfb_state_lock( &data->state ); + dfb_state_stop_drawing( &data->state ); + dfb_state_unlock( &data->state ); +} + diff --git a/Source/DirectFB/src/display/idirectfbsurface.h b/Source/DirectFB/src/display/idirectfbsurface.h new file mode 100755 index 0000000..a350054 --- /dev/null +++ b/Source/DirectFB/src/display/idirectfbsurface.h @@ -0,0 +1,123 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __IDIRECTFBSURFACE_H__ +#define __IDIRECTFBSURFACE_H__ + +#include + +#include + +#include + +#include +#include + + +/* + * private data struct of IDirectFBSurface + */ +typedef struct { + DirectLink link; + + int ref; /* reference counter */ + + DFBSurfaceCapabilities caps; /* capabilities */ + + struct { + DFBRectangle wanted; /* passed to GetSubSurface */ + DFBRectangle granted; /* clipped by parent on creation */ + DFBRectangle current; /* currently available area */ + DFBInsets insets; /* actually set by the window manager */ + } area; + + bool limit_set; /* greanted rectangle set? + (GetSubSurface called with rect != NULL) */ + + bool clip_set; /* fixed clip set? (SetClip called + with clip != NULL) */ + DFBRegion clip_wanted; /* last region passed to SetClip + intersected by wanted area, + only valid if clip_set != 0 */ + + CoreSurface *surface; /* buffer to show */ + bool locked; /* which buffer is locked? */ + CoreSurfaceBufferLock lock; + + IDirectFBFont *font; /* font to use */ + CardState state; /* render state to use */ + DFBTextEncodingID encoding; /* text encoding */ + + struct { + u8 r; /* red component */ + u8 g; /* green component */ + u8 b; /* blue component */ + u32 value; /* r/g/b in surface's format */ + } src_key; /* src key for blitting from + this surface */ + + struct { + u8 r; /* red component */ + u8 g; /* green component */ + u8 b; /* blue component */ + u32 value; /* r/g/b in surface's format */ + } dst_key; /* dst key for blitting to + this surface */ + + Reaction reaction; + + CoreDFB *core; + + IDirectFBSurface *parent; + DirectLink *children_data; + pthread_mutex_t children_lock; +} IDirectFBSurface_data; + +/* + * initializes interface struct and private data + */ +DFBResult IDirectFBSurface_Construct( IDirectFBSurface *thiz, + IDirectFBSurface *parent, + DFBRectangle *req_rect, + DFBRectangle *clip_rect, + DFBInsets *insets, + CoreSurface *surface, + DFBSurfaceCapabilities caps, + CoreDFB *core ); + +/* + * destroys surface(s) and frees private data + */ +void IDirectFBSurface_Destruct( IDirectFBSurface *thiz ); + +/* + * internal + */ +void IDirectFBSurface_StopAll( IDirectFBSurface_data *data ); + +#endif diff --git a/Source/DirectFB/src/display/idirectfbsurface_layer.c b/Source/DirectFB/src/display/idirectfbsurface_layer.c new file mode 100755 index 0000000..4507a56 --- /dev/null +++ b/Source/DirectFB/src/display/idirectfbsurface_layer.c @@ -0,0 +1,244 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include +#include +#include + +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "idirectfbsurface.h" +#include "idirectfbsurface_layer.h" + +#include + +#include +#include + +#include + + +D_DEBUG_DOMAIN( Surface, "IDirectFBSurfaceL", "IDirectFBSurface_Layer Interface" ); + +/**********************************************************************************************************************/ + +static void +IDirectFBSurface_Layer_Destruct( IDirectFBSurface *thiz ) +{ + IDirectFBSurface_Layer_data *data = (IDirectFBSurface_Layer_data*) thiz->priv; + + D_DEBUG_AT( Surface, "%s( %p )\n", __FUNCTION__, thiz ); + + dfb_layer_region_unref( data->region ); + IDirectFBSurface_Destruct( thiz ); +} + +static DirectResult +IDirectFBSurface_Layer_Release( IDirectFBSurface *thiz ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Layer) + + D_DEBUG_AT( Surface, "%s( %p )\n", __FUNCTION__, thiz ); + + if (--data->base.ref == 0) + IDirectFBSurface_Layer_Destruct( thiz ); + + return DFB_OK; +} + +static DFBResult +IDirectFBSurface_Layer_Flip( IDirectFBSurface *thiz, + const DFBRegion *region, + DFBSurfaceFlipFlags flags ) +{ + DFBRegion reg; + + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Layer) + + D_DEBUG_AT( Surface, "%s( %p, %p, 0x%08x )\n", __FUNCTION__, thiz, region, flags ); + + if (!data->base.surface) + return DFB_DESTROYED; + + if (data->base.locked) + return DFB_LOCKED; + + if (!data->base.area.current.w || !data->base.area.current.h || + (region && (region->x1 > region->x2 || region->y1 > region->y2))) + return DFB_INVAREA; + + + IDirectFBSurface_StopAll( &data->base ); + + if (data->base.parent) { + IDirectFBSurface_data *parent_data; + + DIRECT_INTERFACE_GET_DATA_FROM( data->base.parent, parent_data, IDirectFBSurface ); + + /* Signal end of sequence of operations. */ + dfb_state_lock( &parent_data->state ); + dfb_state_stop_drawing( &parent_data->state ); + dfb_state_unlock( &parent_data->state ); + } + + + dfb_region_from_rectangle( ®, &data->base.area.current ); + + if (region) { + DFBRegion clip = DFB_REGION_INIT_TRANSLATED( region, + data->base.area.wanted.x, + data->base.area.wanted.y ); + + if (!dfb_region_region_intersect( ®, &clip )) + return DFB_INVAREA; + } + + D_DEBUG_AT( Surface, " -> FLIP %4d,%4d-%4dx%4d\n", DFB_RECTANGLE_VALS_FROM_REGION( ® ) ); + + return dfb_layer_region_flip_update( data->region, ®, flags ); +} + +static DFBResult +IDirectFBSurface_Layer_GetSubSurface( IDirectFBSurface *thiz, + const DFBRectangle *rect, + IDirectFBSurface **surface ) +{ + DFBResult ret; + + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Layer) + + D_DEBUG_AT( Surface, "%s( %p )\n", __FUNCTION__, thiz ); + + /* Check arguments */ + if (!data->base.surface) + return DFB_DESTROYED; + + if (!surface) + return DFB_INVARG; + + /* Allocate interface */ + DIRECT_ALLOCATE_INTERFACE( *surface, IDirectFBSurface ); + + if (rect || data->base.limit_set) { + DFBRectangle wanted, granted; + + /* Compute wanted rectangle */ + if (rect) { + wanted = *rect; + + wanted.x += data->base.area.wanted.x; + wanted.y += data->base.area.wanted.y; + + if (wanted.w <= 0 || wanted.h <= 0) { + wanted.w = 0; + wanted.h = 0; + } + } + else { + wanted = data->base.area.wanted; + } + + /* Compute granted rectangle */ + granted = wanted; + + dfb_rectangle_intersect( &granted, &data->base.area.granted ); + + /* Construct */ + ret = IDirectFBSurface_Layer_Construct( *surface, thiz, &wanted, &granted, + data->region, data->base.caps | + DSCAPS_SUBSURFACE, data->base.core ); + } + else { + /* Construct */ + ret = IDirectFBSurface_Layer_Construct( *surface, thiz, NULL, NULL, + data->region, data->base.caps | + DSCAPS_SUBSURFACE, data->base.core ); + } + + return ret; +} + +DFBResult +IDirectFBSurface_Layer_Construct( IDirectFBSurface *thiz, + IDirectFBSurface *parent, + DFBRectangle *wanted, + DFBRectangle *granted, + CoreLayerRegion *region, + DFBSurfaceCapabilities caps, + CoreDFB *core ) +{ + DFBResult ret; + CoreSurface *surface; + + DIRECT_ALLOCATE_INTERFACE_DATA(thiz, IDirectFBSurface_Layer); + + D_DEBUG_AT( Surface, "%s( %p )\n", __FUNCTION__, thiz ); + + if (dfb_layer_region_ref( region )) + return DFB_FUSION; + + ret = dfb_layer_region_get_surface( region, &surface ); + if (ret) { + dfb_layer_region_unref( region ); + DIRECT_DEALLOCATE_INTERFACE(thiz); + return ret; + } + + ret = IDirectFBSurface_Construct( thiz, parent, wanted, granted, NULL, + surface, surface->config.caps | caps, core ); + if (ret) { + dfb_surface_unref( surface ); + dfb_layer_region_unref( region ); + return ret; + } + + dfb_surface_unref( surface ); + + data->region = region; + + thiz->Release = IDirectFBSurface_Layer_Release; + thiz->Flip = IDirectFBSurface_Layer_Flip; + thiz->GetSubSurface = IDirectFBSurface_Layer_GetSubSurface; + + return DFB_OK; +} + diff --git a/Source/DirectFB/src/display/idirectfbsurface_layer.h b/Source/DirectFB/src/display/idirectfbsurface_layer.h new file mode 100755 index 0000000..c2ddb8c --- /dev/null +++ b/Source/DirectFB/src/display/idirectfbsurface_layer.h @@ -0,0 +1,57 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __DIRECTFBSURFACE_LAYER_H__ +#define __DIRECTFBSURFACE_LAYER_H__ + +#include +#include + +/* + * private data struct of IDirectFBSurface_Layer + */ +typedef struct { + IDirectFBSurface_data base; /* base Surface implementation */ + + CoreLayerRegion *region; /* the region this surface belongs to */ +} IDirectFBSurface_Layer_data; + +/* + * sets buffer mode according to capabilities, calls base classes + * IDirectFBSurface_Construct, reallocates private data and + * overloads functions of the interface + */ +DFBResult IDirectFBSurface_Layer_Construct( IDirectFBSurface *thiz, + IDirectFBSurface *parent, + DFBRectangle *req_rect, + DFBRectangle *clip_rect, + CoreLayerRegion *region, + DFBSurfaceCapabilities caps, + CoreDFB *core ); + +#endif diff --git a/Source/DirectFB/src/display/idirectfbsurface_window.c b/Source/DirectFB/src/display/idirectfbsurface_window.c new file mode 100755 index 0000000..c76eb3d --- /dev/null +++ b/Source/DirectFB/src/display/idirectfbsurface_window.c @@ -0,0 +1,353 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include +#include +#include + +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include /* FIXME */ +#include + +#include +#include + +#include +#include +#include + +#include + + +D_DEBUG_DOMAIN( Surface, "IDirectFBSurfaceW", "IDirectFBSurface_Window Interface" ); + +/**********************************************************************************************************************/ + +/* + * private data struct of IDirectFBSurface_Window + */ +typedef struct { + IDirectFBSurface_data base; /* base Surface implementation */ + + CoreWindow *window; /* pointer to core data */ + + pthread_t flip_thread; /* thread for non-flipping primary + surfaces, to make changes visible */ + +// CoreGraphicsSerial serial; +} IDirectFBSurface_Window_data; + +/**********************************************************************************************************************/ + +static void *Flipping_Thread( void *arg ); + +/**********************************************************************************************************************/ + +static void +IDirectFBSurface_Window_Destruct( IDirectFBSurface *thiz ) +{ + IDirectFBSurface_Window_data *data; + + D_DEBUG_AT( Surface, "%s( %p )\n", __FUNCTION__, thiz ); + + D_ASSERT( thiz != NULL ); + + data = thiz->priv; + + if ((int) data->flip_thread != -1) { + pthread_cancel( data->flip_thread ); + pthread_join( data->flip_thread, NULL ); + } + + dfb_window_unref( data->window ); + + IDirectFBSurface_Destruct( thiz ); +} + +static DirectResult +IDirectFBSurface_Window_Release( IDirectFBSurface *thiz ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Window) + + D_DEBUG_AT( Surface, "%s( %p )\n", __FUNCTION__, thiz ); + + if (--data->base.ref == 0) + IDirectFBSurface_Window_Destruct( thiz ); + + return DFB_OK; +} + +static DFBResult +IDirectFBSurface_Window_Flip( IDirectFBSurface *thiz, + const DFBRegion *region, + DFBSurfaceFlipFlags flags ) +{ + DFBResult ret; + DFBRegion reg; + + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Window) + + D_DEBUG_AT( Surface, "%s( %p, %p, 0x%08x )\n", __FUNCTION__, thiz, region, flags ); + + if (!data->base.surface) + return DFB_DESTROYED; + + if (data->base.locked) + return DFB_LOCKED; + + if (!data->base.area.current.w || !data->base.area.current.h || + (region && (region->x1 > region->x2 || region->y1 > region->y2))) + return DFB_INVAREA; + + + IDirectFBSurface_StopAll( &data->base ); + + if (data->base.parent) { + IDirectFBSurface_data *parent_data; + + DIRECT_INTERFACE_GET_DATA_FROM( data->base.parent, parent_data, IDirectFBSurface ); + + /* Signal end of sequence of operations. */ + dfb_state_lock( &parent_data->state ); + dfb_state_stop_drawing( &parent_data->state ); + dfb_state_unlock( &parent_data->state ); + } + + + + dfb_region_from_rectangle( ®, &data->base.area.current ); + + if (region) { + DFBRegion clip = DFB_REGION_INIT_TRANSLATED( region, + data->base.area.wanted.x, + data->base.area.wanted.y ); + + if (!dfb_region_region_intersect( ®, &clip )) + return DFB_INVAREA; + } + + D_DEBUG_AT( Surface, " -> FLIP %4d,%4d-%4dx%4d\n", DFB_RECTANGLE_VALS_FROM_REGION( ® ) ); + + + if (flags & DSFLIP_PIPELINE) { + dfb_gfxcard_wait_serial( &data->window->serial2 ); + + data->window->serial2 = data->window->serial1; + + dfb_state_get_serial( &data->base.state, &data->window->serial1 ); + } + + + if (data->window->region) { + dfb_layer_region_flip_update( data->window->region, ®, flags ); + } + else { + if (data->base.surface->config.caps & DSCAPS_FLIPPING) { + if (!(flags & DSFLIP_BLIT) && reg.x1 == 0 && reg.y1 == 0 && + reg.x2 == data->base.surface->config.size.w - 1 && + reg.y2 == data->base.surface->config.size.h - 1) + { + ret = dfb_surface_lock( data->base.surface ); + if (ret) + return ret; + + dfb_surface_flip( data->base.surface, false ); + + dfb_surface_unlock( data->base.surface ); + } + else + dfb_back_to_front_copy( data->base.surface, ® ); + } + + dfb_window_repaint( data->window, ®, flags ); + } + + if (!data->window->config.opacity && data->base.caps & DSCAPS_PRIMARY) + dfb_window_set_opacity( data->window, 0xff ); + + return DFB_OK; +} + +static DFBResult +IDirectFBSurface_Window_GetSubSurface( IDirectFBSurface *thiz, + const DFBRectangle *rect, + IDirectFBSurface **surface ) +{ + DFBResult ret; + + DIRECT_INTERFACE_GET_DATA(IDirectFBSurface_Window) + + D_DEBUG_AT( Surface, "%s( %p )\n", __FUNCTION__, thiz ); + + /* Check arguments */ + if (!data->base.surface || !data->window || !data->window->surface) + return DFB_DESTROYED; + + if (!surface) + return DFB_INVARG; + + /* Allocate interface */ + DIRECT_ALLOCATE_INTERFACE( *surface, IDirectFBSurface ); + + if (rect || data->base.limit_set) { + DFBRectangle wanted, granted; + + /* Compute wanted rectangle */ + if (rect) { + wanted = *rect; + + wanted.x += data->base.area.wanted.x; + wanted.y += data->base.area.wanted.y; + + if (wanted.w <= 0 || wanted.h <= 0) { + wanted.w = 0; + wanted.h = 0; + } + } + else { + wanted = data->base.area.wanted; + } + + /* Compute granted rectangle */ + granted = wanted; + + dfb_rectangle_intersect( &granted, &data->base.area.granted ); + + /* Construct */ + ret = IDirectFBSurface_Window_Construct( *surface, thiz, &wanted, &granted, + data->window, data->base.caps | + DSCAPS_SUBSURFACE, data->base.core ); + } + else { + /* Construct */ + ret = IDirectFBSurface_Window_Construct( *surface, thiz, NULL, NULL, + data->window, data->base.caps | + DSCAPS_SUBSURFACE, data->base.core ); + } + + return ret; +} + +DFBResult +IDirectFBSurface_Window_Construct( IDirectFBSurface *thiz, + IDirectFBSurface *parent, + DFBRectangle *wanted, + DFBRectangle *granted, + CoreWindow *window, + DFBSurfaceCapabilities caps, + CoreDFB *core ) +{ + DFBResult ret; + DFBInsets insets; + CoreWindowStack *stack; + + DIRECT_ALLOCATE_INTERFACE_DATA(thiz, IDirectFBSurface_Window) + + D_DEBUG_AT( Surface, "%s( %p )\n", __FUNCTION__, thiz ); + + stack = window->stack; + D_MAGIC_ASSERT( stack, CoreWindowStack ); + + dfb_layer_context_lock( stack->context ); + + dfb_wm_get_insets( stack, window, &insets ); + + dfb_layer_context_unlock( stack->context ); + + ret = IDirectFBSurface_Construct( thiz, parent, wanted, granted, &insets, + window->surface, caps, core ); + if (ret) + return ret; + + if (dfb_window_ref( window )) { + IDirectFBSurface_Destruct( thiz ); + return DFB_FAILURE; + } + + data->window = window; + data->flip_thread = (pthread_t) -1; + + /* + * Create an auto flipping thread if the application + * requested a (primary) surface that doesn't need to be flipped. + * Window surfaces even need to be flipped when they are single buffered. + */ + if (!(caps & DSCAPS_FLIPPING) && !(caps & DSCAPS_SUBSURFACE)) { + if (dfb_config->autoflip_window) + pthread_create( &data->flip_thread, NULL, Flipping_Thread, thiz ); + else + D_WARN( "Non-flipping window surface and no 'autoflip-window' option used" ); + } + + thiz->Release = IDirectFBSurface_Window_Release; + thiz->Flip = IDirectFBSurface_Window_Flip; + thiz->GetSubSurface = IDirectFBSurface_Window_GetSubSurface; + + return DFB_OK; +} + + +/* file internal */ + +static void * +Flipping_Thread( void *arg ) +{ + IDirectFBSurface *thiz = (IDirectFBSurface*) arg; + IDirectFBSurface_Window_data *data = (IDirectFBSurface_Window_data*) thiz->priv; + + D_DEBUG_AT( Surface, "%s( %p )\n", __FUNCTION__, thiz ); + + while (data->base.surface && data->window->surface) { + pthread_testcancel(); + + /* + * OPTIMIZE: only call if surface has been touched in the meantime + */ + thiz->Flip( thiz, NULL, 0 ); + + usleep(40000); + } + + return NULL; +} + diff --git a/Source/DirectFB/src/display/idirectfbsurface_window.h b/Source/DirectFB/src/display/idirectfbsurface_window.h new file mode 100755 index 0000000..92ca56e --- /dev/null +++ b/Source/DirectFB/src/display/idirectfbsurface_window.h @@ -0,0 +1,48 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __DIRECTFBSURFACE_WINDOW_H__ +#define __DIRECTFBSURFACE_WINDOW_H__ + +#include + +#include + +/* + * calls base classes IDirectFBSurface_Construct, + * reallocates private data and overloads functions of the interface + */ +DFBResult IDirectFBSurface_Window_Construct( IDirectFBSurface *thiz, + IDirectFBSurface *parent, + DFBRectangle *req_rect, + DFBRectangle *clip_rect, + CoreWindow *window, + DFBSurfaceCapabilities caps, + CoreDFB *core ); + +#endif diff --git a/Source/DirectFB/src/gfx/Makefile.am b/Source/DirectFB/src/gfx/Makefile.am new file mode 100755 index 0000000..8cbd6b9 --- /dev/null +++ b/Source/DirectFB/src/gfx/Makefile.am @@ -0,0 +1,29 @@ +## Makefile.am for DirectFB/src/misc + +SUBDIRS = generic + +INCLUDES = \ + -I$(top_builddir)/lib \ + -I$(top_builddir)/include \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/lib \ + -I$(top_srcdir)/src + + +internalincludedir = $(INTERNALINCLUDEDIR)/gfx + +internalinclude_HEADERS = \ + clip.h \ + convert.h \ + util.h + + +noinst_LTLIBRARIES = libdirectfb_gfx.la + +libdirectfb_gfx_la_SOURCES = \ + clip.c \ + convert.c \ + util.c + +libdirectfb_gfx_la_LIBADD = \ + generic/libdirectfb_generic.la diff --git a/Source/DirectFB/src/gfx/Makefile.in b/Source/DirectFB/src/gfx/Makefile.in new file mode 100755 index 0000000..db7dfa4 --- /dev/null +++ b/Source/DirectFB/src/gfx/Makefile.in @@ -0,0 +1,676 @@ +# Makefile.in generated by automake 1.10.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = src/gfx +DIST_COMMON = $(internalinclude_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/as-ac-expand.m4 \ + $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libdirectfb_gfx_la_DEPENDENCIES = generic/libdirectfb_generic.la +am_libdirectfb_gfx_la_OBJECTS = clip.lo convert.lo util.lo +libdirectfb_gfx_la_OBJECTS = $(am_libdirectfb_gfx_la_OBJECTS) +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libdirectfb_gfx_la_SOURCES) +DIST_SOURCES = $(libdirectfb_gfx_la_SOURCES) +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(internalincludedir)" +internalincludeHEADERS_INSTALL = $(INSTALL_HEADER) +HEADERS = $(internalinclude_HEADERS) +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AS = @AS@ +ASFLAGS = @ASFLAGS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIR = @DATADIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DFB_CFLAGS_OMIT_FRAME_POINTER = @DFB_CFLAGS_OMIT_FRAME_POINTER@ +DFB_INTERNAL_CFLAGS = @DFB_INTERNAL_CFLAGS@ +DFB_LDFLAGS = @DFB_LDFLAGS@ +DFB_SMOOTH_SCALING = @DFB_SMOOTH_SCALING@ +DIRECTFB_BINARY_AGE = @DIRECTFB_BINARY_AGE@ +DIRECTFB_CSOURCE = @DIRECTFB_CSOURCE@ +DIRECTFB_INTERFACE_AGE = @DIRECTFB_INTERFACE_AGE@ +DIRECTFB_MAJOR_VERSION = @DIRECTFB_MAJOR_VERSION@ +DIRECTFB_MICRO_VERSION = @DIRECTFB_MICRO_VERSION@ +DIRECTFB_MINOR_VERSION = @DIRECTFB_MINOR_VERSION@ +DIRECTFB_VERSION = @DIRECTFB_VERSION@ +DIRECT_BUILD_DEBUG = @DIRECT_BUILD_DEBUG@ +DIRECT_BUILD_DEBUGS = @DIRECT_BUILD_DEBUGS@ +DIRECT_BUILD_GETTID = @DIRECT_BUILD_GETTID@ +DIRECT_BUILD_NETWORK = @DIRECT_BUILD_NETWORK@ +DIRECT_BUILD_STDBOOL = @DIRECT_BUILD_STDBOOL@ +DIRECT_BUILD_TEXT = @DIRECT_BUILD_TEXT@ +DIRECT_BUILD_TRACE = @DIRECT_BUILD_TRACE@ +DSYMUTIL = @DSYMUTIL@ +DYNLIB = @DYNLIB@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +FREETYPE_CFLAGS = @FREETYPE_CFLAGS@ +FREETYPE_LIBS = @FREETYPE_LIBS@ +FREETYPE_PROVIDER = @FREETYPE_PROVIDER@ +FUSION_BUILD_KERNEL = @FUSION_BUILD_KERNEL@ +FUSION_BUILD_MULTI = @FUSION_BUILD_MULTI@ +FUSION_MESSAGE_SIZE = @FUSION_MESSAGE_SIZE@ +GIF_PROVIDER = @GIF_PROVIDER@ +GREP = @GREP@ +HAVE_LINUX = @HAVE_LINUX@ +INCLUDEDIR = @INCLUDEDIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTERNALINCLUDEDIR = @INTERNALINCLUDEDIR@ +JPEG_PROVIDER = @JPEG_PROVIDER@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBJPEG = @LIBJPEG@ +LIBOBJS = @LIBOBJS@ +LIBPNG = @LIBPNG@ +LIBPNG_CONFIG = @LIBPNG_CONFIG@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_AGE = @LT_AGE@ +LT_BINARY = @LT_BINARY@ +LT_CURRENT = @LT_CURRENT@ +LT_RELEASE = @LT_RELEASE@ +LT_REVISION = @LT_REVISION@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MAN2HTML = @MAN2HTML@ +MKDIR_P = @MKDIR_P@ +MODULEDIR = @MODULEDIR@ +MODULEDIRNAME = @MODULEDIRNAME@ +NMEDIT = @NMEDIT@ +OBJEXT = @OBJEXT@ +OSX_LIBS = @OSX_LIBS@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PNG_PROVIDER = @PNG_PROVIDER@ +RANLIB = @RANLIB@ +RUNTIME_SYSROOT = @RUNTIME_SYSROOT@ +SDL_CFLAGS = @SDL_CFLAGS@ +SDL_LIBS = @SDL_LIBS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOPATH = @SOPATH@ +STRIP = @STRIP@ +SYSCONFDIR = @SYSCONFDIR@ +SYSFS_LIBS = @SYSFS_LIBS@ +THREADFLAGS = @THREADFLAGS@ +THREADLIB = @THREADLIB@ +TSLIB_CFLAGS = @TSLIB_CFLAGS@ +TSLIB_LIBS = @TSLIB_LIBS@ +VERSION = @VERSION@ +VNC_CFLAGS = @VNC_CFLAGS@ +VNC_CONFIG = @VNC_CONFIG@ +VNC_LIBS = @VNC_LIBS@ +X11_CFLAGS = @X11_CFLAGS@ +X11_LIBS = @X11_LIBS@ +ZLIB_LIBS = @ZLIB_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = generic +INCLUDES = \ + -I$(top_builddir)/lib \ + -I$(top_builddir)/include \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/lib \ + -I$(top_srcdir)/src + +internalincludedir = $(INTERNALINCLUDEDIR)/gfx +internalinclude_HEADERS = \ + clip.h \ + convert.h \ + util.h + +noinst_LTLIBRARIES = libdirectfb_gfx.la +libdirectfb_gfx_la_SOURCES = \ + clip.c \ + convert.c \ + util.c + +libdirectfb_gfx_la_LIBADD = \ + generic/libdirectfb_generic.la + +all: all-recursive + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/gfx/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/gfx/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libdirectfb_gfx.la: $(libdirectfb_gfx_la_OBJECTS) $(libdirectfb_gfx_la_DEPENDENCIES) + $(LINK) $(libdirectfb_gfx_la_OBJECTS) $(libdirectfb_gfx_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clip.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/convert.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/util.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-internalincludeHEADERS: $(internalinclude_HEADERS) + @$(NORMAL_INSTALL) + test -z "$(internalincludedir)" || $(MKDIR_P) "$(DESTDIR)$(internalincludedir)" + @list='$(internalinclude_HEADERS)'; for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + f=$(am__strip_dir) \ + echo " $(internalincludeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(internalincludedir)/$$f'"; \ + $(internalincludeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(internalincludedir)/$$f"; \ + done + +uninstall-internalincludeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(internalinclude_HEADERS)'; for p in $$list; do \ + f=$(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(internalincludedir)/$$f'"; \ + rm -f "$(DESTDIR)$(internalincludedir)/$$f"; \ + done + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +$(RECURSIVE_CLEAN_TARGETS): + @failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done + list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + distdir=`$(am__cd) $(distdir) && pwd`; \ + top_distdir=`$(am__cd) $(top_distdir) && pwd`; \ + (cd $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$top_distdir" \ + distdir="$$distdir/$$subdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(internalincludedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-recursive + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +info: info-recursive + +info-am: + +install-data-am: install-internalincludeHEADERS + +install-dvi: install-dvi-recursive + +install-exec-am: + +install-html: install-html-recursive + +install-info: install-info-recursive + +install-man: + +install-pdf: install-pdf-recursive + +install-ps: install-ps-recursive + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-internalincludeHEADERS + +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) install-am \ + install-strip + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am check check-am clean clean-generic clean-libtool \ + clean-noinstLTLIBRARIES ctags ctags-recursive distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am \ + install-internalincludeHEADERS install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs installdirs-am \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags tags-recursive uninstall uninstall-am \ + uninstall-internalincludeHEADERS + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/Source/DirectFB/src/gfx/clip.c b/Source/DirectFB/src/gfx/clip.c new file mode 100755 index 0000000..195dc73 --- /dev/null +++ b/Source/DirectFB/src/gfx/clip.c @@ -0,0 +1,379 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include + +#include + +#include + +#include + +#include + +#define REGION_CODE(x,y,cx1,cx2,cy1,cy2) ( ( (y) > (cy2) ? 8 : 0) | \ + ( (y) < (cy1) ? 4 : 0) | \ + ( (x) > (cx2) ? 2 : 0) | \ + ( (x) < (cx1) ? 1 : 0) ) + + +DFBBoolean +dfb_clip_line( const DFBRegion *clip, DFBRegion *line ) +{ + unsigned char region_code1 = REGION_CODE( line->x1, line->y1, + clip->x1, + clip->x2, + clip->y1, + clip->y2 ); + + unsigned char region_code2 = REGION_CODE( line->x2, line->y2, + clip->x1, + clip->x2, + clip->y1, + clip->y2 ); + + while (region_code1 | region_code2) { + /* line completely outside the clipping rectangle */ + if (region_code1 & region_code2) + return DFB_FALSE; + + + if (region_code1) { + if (region_code1 & 8) { /* divide line at bottom*/ + line->x1 = line->x1 +(line->x2-line->x1) * (clip->y2 - line->y1) / (line->y2-line->y1); + line->y1 = clip->y2; + } + else + if (region_code1 & 4) { /* divide line at top*/ + line->x1 = line->x1 +(line->x2-line->x1) * (clip->y1 - line->y1) / (line->y2-line->y1); + line->y1 = clip->y1; + } + else + if (region_code1 & 2) { /* divide line at right*/ + line->y1 = line->y1 +(line->y2-line->y1) * (clip->x2 - line->x1) / (line->x2-line->x1); + line->x1 = clip->x2; + } + else + if (region_code1 & 1) { /* divide line at right*/ + line->y1 = line->y1 +(line->y2-line->y1) * (clip->x1 - line->x1) / (line->x2-line->x1); + line->x1 = clip->x1; + } + region_code1 = REGION_CODE( line->x1, line->y1, + clip->x1, + clip->x2, + clip->y1, + clip->y2 ); + } + else { + if (region_code2 & 8) { /* divide line at bottom*/ + line->x2 = line->x1 +(line->x2-line->x1) * (clip->y2 - line->y1) / (line->y2-line->y1); + line->y2 = clip->y2; + } + else + if (region_code2 & 4) { /* divide line at top*/ + line->x2 = line->x1 +(line->x2-line->x1) * (clip->y1 - line->y1) / (line->y2-line->y1); + line->y2 = clip->y1; + } + else + if (region_code2 & 2) { /* divide line at right*/ + line->y2 = line->y1 +(line->y2-line->y1) * (clip->x2 - line->x1) / (line->x2-line->x1); + line->x2 = clip->x2; + } + else + if (region_code2 & 1) { /* divide line at right*/ + line->y2 = line->y1 +(line->y2-line->y1) * (clip->x1 - line->x1) / (line->x2-line->x1); + line->x2 = clip->x1; + } + region_code2 = REGION_CODE( line->x2, line->y2, clip->x1, + clip->x2, + clip->y1, + clip->y2 ); + } + } + + /* successfully clipped or clipping not neccessary */ + return DFB_TRUE; +} + +DFBEdgeFlags +dfb_clip_edges( const DFBRegion *clip, DFBRectangle *rect ) +{ + DFBEdgeFlags flags = DFEF_ALL; + + if ((clip->x1 >= rect->x + rect->w) || + (clip->x2 < rect->x) || + (clip->y1 >= rect->y + rect->h) || + (clip->y2 < rect->y)) + return DFEF_NONE; + + if (clip->x1 > rect->x) { + rect->w += rect->x - clip->x1; + rect->x = clip->x1; + + flags &= ~DFEF_LEFT; + } + + if (clip->y1 > rect->y) { + rect->h += rect->y - clip->y1; + rect->y = clip->y1; + + flags &= ~DFEF_TOP; + } + + if (clip->x2 < rect->x + rect->w - 1) { + rect->w = clip->x2 - rect->x + 1; + + flags &= ~DFEF_RIGHT; + } + + if (clip->y2 < rect->y + rect->h - 1) { + rect->h = clip->y2 - rect->y + 1; + + flags &= ~DFEF_BOTTOM; + } + + return flags; +} + +DFBBoolean +dfb_clip_rectangle( const DFBRegion *clip, DFBRectangle *rect ) +{ + if ((clip->x1 >= rect->x + rect->w) || + (clip->x2 < rect->x) || + (clip->y1 >= rect->y + rect->h) || + (clip->y2 < rect->y)) + return DFB_FALSE; + + if (clip->x1 > rect->x) { + rect->w += rect->x - clip->x1; + rect->x = clip->x1; + } + + if (clip->y1 > rect->y) { + rect->h += rect->y - clip->y1; + rect->y = clip->y1; + } + + if (clip->x2 < rect->x + rect->w - 1) + rect->w = clip->x2 - rect->x + 1; + + if (clip->y2 < rect->y + rect->h - 1) + rect->h = clip->y2 - rect->y + 1; + + return DFB_TRUE; +} + +DFBBoolean +dfb_clip_triangle_precheck( const DFBRegion *clip, const DFBTriangle *tri ) +{ + int x, y, w, h; + + x = MIN (MIN (tri->x1, tri->x2), tri->x3); + y = MIN (MIN (tri->y1, tri->y2), tri->y3); + w = MAX (MAX (tri->x1, tri->x2), tri->x3) - x; + h = MAX (MAX (tri->y1, tri->y2), tri->y3) - y; + + if (clip->x1 > x || + clip->x2 < x + w || + clip->y1 > y || + clip->y2 < y + h) + return DFB_FALSE; + + return DFB_TRUE; +} + +DFBBoolean +dfb_clip_triangle( const DFBRegion *clip, const DFBTriangle *tri, DFBPoint p[6], int *num ) +{ + DFBRegion edges[3]; + int num_edges; + int i, n; + DFBPoint p1 = {0, 0}, p2 = {0, 0}; + + /* Initialize edges. */ + edges[0].x1 = tri->x1; edges[0].y1 = tri->y1; + edges[0].x2 = tri->x2; edges[0].y2 = tri->y2; + edges[1].x1 = tri->x2; edges[1].y1 = tri->y2; + edges[1].x2 = tri->x3; edges[1].y2 = tri->y3; + edges[2].x1 = tri->x3; edges[2].y1 = tri->y3; + edges[2].x2 = tri->x1; edges[2].y2 = tri->y1; + num_edges = 3; + + for (i = 0; i < num_edges; i++) { + DFBRegion *reg = &edges[i]; + DFBRegion line; + bool i1, i2; + + /* Clip the edge to the clipping region. */ + line = *reg; + if (dfb_clip_line( clip, &line )) { + *reg = line; + continue; + } + + /* If the edge doesn't intersect clipping region, then + * intersect the edge with the diagonals of the clipping + * rectangle. If intersection point exits, add the nearest + * corner of the clipping region to the list of vertices. + */ + + /* Diagonal (x1,y1) (x2,y2). */ + line = (DFBRegion) { clip->x1, clip->y1, clip->x2, clip->y2 }; + i1 = dfb_line_segment_intersect( &line, reg, &p1.x, &p1.y ); + if (i1) { + /* Get nearest corner. */ + if (p1.x <= clip->x1 || p1.y <= clip->y1) { + p1.x = clip->x1; + p1.y = clip->y1; + } else { + p1.x = clip->x2; + p1.y = clip->y2; + } + } + + /* Diagonal (x2,y1) (x1,y2). */ + line = (DFBRegion) { clip->x2, clip->y1, clip->x1, clip->y2 }; + i2 = dfb_line_segment_intersect( &line, reg, &p2.x, &p2.y ); + if (i2) { + /* Get nearest corner. */ + if (p2.x >= clip->x2 || p2.y <= clip->y1) { + p2.x = clip->x2; + p2.y = clip->y1; + } else { + p2.x = clip->x1; + p2.y = clip->y2; + } + } + + if (i1 && i2) { + reg->x1 = p1.x; + reg->y1 = p1.y; + reg->x2 = p2.x; + reg->y2 = p2.y; + } + else if (i1) { + reg->x1 = reg->x2 = p1.x; + reg->y1 = reg->y2 = p1.y; + } + else if (i2) { + reg->x1 = reg->x2 = p2.x; + reg->y1 = reg->y2 = p2.y; + } + else { + /* Redudant edge. Remote it. */ + memmove( reg, &edges[i+1], (num_edges-i-1) * sizeof(DFBRegion) ); + num_edges--; + i--; + } + } + + if (num_edges < 1) { + *num = 0; + return DFB_FALSE; + } + + /* Get vertices from edges. */ + p[0].x = edges[0].x1; p[0].y = edges[0].y1; + n = 1; + if (edges[0].x2 != edges[0].x1 || edges[0].y2 != edges[0].y1) { + p[1].x = edges[0].x2; p[1].y = edges[0].y2; + n++; + } + + for (i = 1; i < num_edges; i++) { + if (edges[i].x1 != p[n-1].x || edges[i].y1 != p[n-1].y) { + p[n].x = edges[i].x1; p[n].y = edges[i].y1; + n++; + } + if (edges[i].x2 != p[n-1].x || edges[i].y2 != p[n-1].y) { + p[n].x = edges[i].x2; p[n].y = edges[i].y2; + n++; + } + } + + if (p[n-1].x == p[0].x && p[n-1].y == p[0].y) + n--; + + *num = n; + + /* Actually fail if the number of vertices is below 3. */ + return (n >= 3); +} + + +void +dfb_clip_blit( const DFBRegion *clip, + DFBRectangle *srect, int *dx, int *dy ) +{ + if (clip->x1 > *dx ) { + srect->w = MIN( (clip->x2 - clip->x1) + 1, + (*dx + srect->w) - clip->x1); + + srect->x+= clip->x1 - *dx; + *dx = clip->x1; + } + else if (clip->x2 < *dx + srect->w - 1) { + srect->w = clip->x2 - *dx + 1; + } + + if (clip->y1 > *dy ) { + srect->h = MIN( (clip->y2 - clip->y1) + 1, + (*dy + srect->h) - clip->y1); + srect->y+= clip->y1 - *dy; + *dy = clip->y1; + } + else if (clip->y2 < *dy + srect->h - 1) { + srect->h = clip->y2 - *dy + 1; + } +} + +void +dfb_clip_stretchblit( const DFBRegion *clip, + DFBRectangle *srect, DFBRectangle *drect ) +{ + DFBRectangle orig_dst = *drect; + + dfb_clip_rectangle( clip, drect ); + + if (drect->x != orig_dst.x) + srect->x += (int)( (drect->x - orig_dst.x) * + (srect->w / (float)orig_dst.w) ); + + if (drect->y != orig_dst.y) + srect->y += (int)( (drect->y - orig_dst.y) * + (srect->h / (float)orig_dst.h) ); + + if (drect->w != orig_dst.w) + srect->w = (int)( srect->w * (drect->w / (float)orig_dst.w) ); + + if (drect->h != orig_dst.h) + srect->h = (int)( srect->h * (drect->h / (float)orig_dst.h) ); +} + diff --git a/Source/DirectFB/src/gfx/clip.h b/Source/DirectFB/src/gfx/clip.h new file mode 100755 index 0000000..e1ea261 --- /dev/null +++ b/Source/DirectFB/src/gfx/clip.h @@ -0,0 +1,125 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __GFX__CLIP_H__ +#define __GFX__CLIP_H__ + +#include + +typedef enum { + DFEF_NONE = 0x00000000, + + DFEF_LEFT = 0x00000001, + DFEF_RIGHT = 0x00000002, + DFEF_TOP = 0x00000004, + DFEF_BOTTOM = 0x00000008, + + DFEF_ALL = 0x0000000F +} DFBEdgeFlags; + +/* + * Clips the line to the clipping region. + * Returns DFB_TRUE if at least one pixel of the line resides in the region. + */ +DFBBoolean dfb_clip_line( const DFBRegion *clip, DFBRegion *line ); + +/* + * Clips the rectangle to the clipping region. + * Returns true if there was an intersection with the clipping region. + */ +DFBBoolean dfb_clip_rectangle( const DFBRegion *clip, DFBRectangle *rect ); + +/* + * Clips the rectangle to the clipping region. + * Returns a flag for each edge that wasn't cut off. + */ +DFBEdgeFlags dfb_clip_edges( const DFBRegion *clip, DFBRectangle *rect ); + +static inline DFBBoolean +dfb_clip_needed( const DFBRegion *clip, DFBRectangle *rect ) +{ + return ((clip->x1 > rect->x) || + (clip->y1 > rect->y) || + (clip->x2 < rect->x + rect->w - 1) || + (clip->y2 < rect->y + rect->h - 1)); +} + +/* + * Simple check if triangle lies outside the clipping region. + * Returns true if the triangle may be visible within the region. + */ +DFBBoolean dfb_clip_triangle_precheck( const DFBRegion *clip, + const DFBTriangle *tri ); + +/* + * Clips the triangle to the clipping region. + * Returns true if the triangle if visible within the region. + * The vertices of the polygon resulting from intersection are returned in buf. + * The number of vertices is at least 3. + */ +DFBBoolean dfb_clip_triangle( const DFBRegion *clip, + const DFBTriangle *tri, + DFBPoint buf[6], + int *num ); + +/* + * Simple check if requested blitting lies outside of the clipping region. + * Returns true if blitting may need to be performed. + */ +static inline DFBBoolean +dfb_clip_blit_precheck( const DFBRegion *clip, + int w, int h, int dx, int dy ) +{ + if (w < 1 || h < 1 || + (clip->x1 >= dx + w) || + (clip->x2 < dx) || + (clip->y1 >= dy + h) || + (clip->y2 < dy)) + return DFB_FALSE; + + return DFB_TRUE; +} + +/* + * Clips the blitting request to the clipping region. + * This includes adjustment of source AND destination coordinates. + */ +void dfb_clip_blit( const DFBRegion *clip, + DFBRectangle *srect, int *dx, int *dy ); + +/* + * Clips the stretch blit request to the clipping region. + * This includes adjustment of source AND destination coordinates + * based on the scaling factor. + */ +void dfb_clip_stretchblit( const DFBRegion *clip, + DFBRectangle *srect, + DFBRectangle *drect ); + +#endif + diff --git a/Source/DirectFB/src/gfx/convert.c b/Source/DirectFB/src/gfx/convert.c new file mode 100755 index 0000000..484f5a6 --- /dev/null +++ b/Source/DirectFB/src/gfx/convert.c @@ -0,0 +1,1427 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include +#include + +#include "convert.h" + +/* lookup tables for 2/3bit to 8bit color conversion */ +static const u8 lookup3to8[] = { 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff}; +static const u8 lookup2to8[] = { 0x00, 0x55, 0xaa, 0xff}; + +#define EXPAND_1to8(v) ((v) ? 0xff : 0x00) +#define EXPAND_2to8(v) (lookup2to8[v]) +#define EXPAND_3to8(v) (lookup3to8[v]) +#define EXPAND_4to8(v) (((v) << 4) | ((v) )) +#define EXPAND_5to8(v) (((v) << 3) | ((v) >> 2)) +#define EXPAND_6to8(v) (((v) << 2) | ((v) >> 4)) +#define EXPAND_7to8(v) (((v) << 1) | ((v) >> 6)) + + +DFBSurfacePixelFormat +dfb_pixelformat_for_depth( int depth ) +{ + switch (depth) { + case 2: + return DSPF_LUT2; + case 8: + return DSPF_LUT8; + case 12: + return DSPF_ARGB4444; + case 14: + return DSPF_ARGB2554; + case 15: + return DSPF_ARGB1555; + case 16: + return DSPF_RGB16; + case 18: + return DSPF_RGB18; + case 24: + return DSPF_RGB24; + case 32: + return DSPF_RGB32; + } + + return DSPF_UNKNOWN; +} + +void +dfb_pixel_to_color( DFBSurfacePixelFormat format, + unsigned long pixel, + DFBColor *ret_color ) +{ + ret_color->a = 0xff; + + switch (format) { + case DSPF_RGB332: + ret_color->r = EXPAND_3to8( (pixel & 0xe0) >> 5 ); + ret_color->g = EXPAND_3to8( (pixel & 0x1c) >> 2 ); + ret_color->b = EXPAND_2to8( (pixel & 0x03) ); + break; + + case DSPF_ARGB1555: + ret_color->a = EXPAND_1to8( pixel >> 15 ); + case DSPF_RGB555: + ret_color->r = EXPAND_5to8( (pixel & 0x7c00) >> 10 ); + ret_color->g = EXPAND_5to8( (pixel & 0x03e0) >> 5 ); + ret_color->b = EXPAND_5to8( (pixel & 0x001f) ); + break; + + case DSPF_BGR555: + ret_color->r = EXPAND_5to8( (pixel & 0x001f) ); + ret_color->g = EXPAND_5to8( (pixel & 0x03e0) >> 5 ); + ret_color->b = EXPAND_5to8( (pixel & 0x7c00) >> 10 ); + break; + + case DSPF_ARGB2554: + ret_color->a = EXPAND_2to8( pixel >> 14 ); + ret_color->r = EXPAND_5to8( (pixel & 0x3e00) >> 9 ); + ret_color->g = EXPAND_5to8( (pixel & 0x01f0) >> 4 ); + ret_color->b = EXPAND_4to8( (pixel & 0x000f) ); + break; + + case DSPF_ARGB4444: + ret_color->a = EXPAND_4to8( pixel >> 12 ); + case DSPF_RGB444: + ret_color->r = EXPAND_4to8( (pixel & 0x0f00) >> 8 ); + ret_color->g = EXPAND_4to8( (pixel & 0x00f0) >> 4 ); + ret_color->b = EXPAND_4to8( (pixel & 0x000f) ); + break; + + case DSPF_RGBA4444: + ret_color->r = EXPAND_4to8( (pixel ) >> 12 ); + ret_color->g = EXPAND_4to8( (pixel & 0x0f00) >> 8 ); + ret_color->b = EXPAND_4to8( (pixel & 0x00f0) >> 4 ); + ret_color->a = EXPAND_4to8( (pixel & 0x000f) ); + break; + + case DSPF_RGB16: + ret_color->r = EXPAND_5to8( (pixel & 0xf800) >> 11 ); + ret_color->g = EXPAND_6to8( (pixel & 0x07e0) >> 5 ); + ret_color->b = EXPAND_5to8( (pixel & 0x001f) ); + break; + + case DSPF_ARGB: + ret_color->a = pixel >> 24; + case DSPF_RGB24: + case DSPF_RGB32: + ret_color->r = (pixel & 0xff0000) >> 16; + ret_color->g = (pixel & 0x00ff00) >> 8; + ret_color->b = (pixel & 0x0000ff); + break; + + case DSPF_AiRGB: + ret_color->a = (pixel >> 24) ^ 0xff; + ret_color->r = (pixel & 0xff0000) >> 16; + ret_color->g = (pixel & 0x00ff00) >> 8; + ret_color->b = (pixel & 0x0000ff); + break; + + default: + ret_color->r = 0; + ret_color->g = 0; + ret_color->b = 0; + } +} + +unsigned long +dfb_pixel_from_color( DFBSurfacePixelFormat format, + const DFBColor *color ) +{ + u32 y, cb, cr; + + switch (format) { + case DSPF_RGB332: + return PIXEL_RGB332( color->r, color->g, color->b ); + + case DSPF_ARGB1555: + return PIXEL_ARGB1555( color->a, color->r, color->g, color->b ); + + case DSPF_RGB555: + return PIXEL_RGB555( color->r, color->g, color->b ); + + case DSPF_BGR555: + return PIXEL_BGR555( color->r, color->g, color->b ); + + case DSPF_ARGB2554: + return PIXEL_ARGB2554( color->a, color->r, color->g, color->b ); + + case DSPF_ARGB4444: + return PIXEL_ARGB4444( color->a, color->r, color->g, color->b ); + + case DSPF_RGBA4444: + return PIXEL_RGBA4444( color->a, color->r, color->g, color->b ); + + case DSPF_RGB444: + return PIXEL_RGB444( color->r, color->g, color->b ); + + case DSPF_RGB16: + return PIXEL_RGB16( color->r, color->g, color->b ); + + case DSPF_RGB18: + return PIXEL_RGB18( color->r, color->g, color->b ); + + case DSPF_ARGB1666: + return PIXEL_ARGB1666( color->a, color->r, color->g, color->b ); + + case DSPF_ARGB6666: + return PIXEL_ARGB6666( color->a, color->r, color->g, color->b ); + + case DSPF_RGB24: + return PIXEL_RGB32( color->r, color->g, color->b ); + + case DSPF_RGB32: + return PIXEL_RGB32( color->r, color->g, color->b ); + + case DSPF_ARGB: + return PIXEL_ARGB( color->a, color->r, color->g, color->b ); + + case DSPF_AiRGB: + return PIXEL_AiRGB( color->a, color->r, color->g, color->b ); + + case DSPF_AYUV: + RGB_TO_YCBCR( color->r, color->g, color->b, y, cb, cr ); + return PIXEL_AYUV( color->a, y, cb, cr ); + + case DSPF_YUY2: + RGB_TO_YCBCR( color->r, color->g, color->b, y, cb, cr ); + return PIXEL_YUY2( y, cb, cr ); + + case DSPF_UYVY: + RGB_TO_YCBCR( color->r, color->g, color->b, y, cb, cr ); + return PIXEL_UYVY( y, cb, cr ); + + case DSPF_I420: + case DSPF_YV12: + RGB_TO_YCBCR( color->r, color->g, color->b, y, cb, cr ); + return y | (cb << 8) | (cr << 16); + + default: + D_WARN( "unknown format 0x%08x", format ); + } + + return 0x55555555; +} + +const char * +dfb_pixelformat_name( DFBSurfacePixelFormat format ) +{ + int i = 0; + + do { + if (format == dfb_pixelformat_names[i].format) + return dfb_pixelformat_names[i].name; + } while (dfb_pixelformat_names[i++].format != DSPF_UNKNOWN); + + return ""; +} + +void +dfb_convert_to_rgb16( DFBSurfacePixelFormat format, + const void *src, + int spitch, + int surface_height, + u16 *dst, + int dpitch, + int width, + int height ) +{ + const int dp2 = dpitch / 2; + int x; + + switch (format) { + case DSPF_RGB16: + while (height--) { + direct_memcpy( dst, src, width * 2 ); + + src += spitch; + dst += dp2; + } + break; + + case DSPF_NV16: + while (height--) { + const u8 *src8 = src; + const u16 *src16 = src + surface_height * spitch; + + for (x=0; x>1] >> 8, src16[x>>1] & 0xff, r, g, b ); +#else + YCBCR_TO_RGB( src8[x], src16[x>>1] & 0xff, src16[x>>1] >> 8, r, g, b ); +#endif + + dst[x] = PIXEL_RGB16( r, g, b ); + } + + src += spitch; + dst += dp2; + } + break; + + case DSPF_RGB444: + case DSPF_ARGB4444: + while (height--) { + const u16 *src16 = src; + + for (x=0; x> 8 ), + EXPAND_4to8( (src16[x] & 0x00f0) >> 4 ), + EXPAND_4to8( (src16[x] & 0x000f) ) ); + + src += spitch; + dst += dp2; + } + break; + + case DSPF_RGBA4444: + while (height--) { + const u16 *src16 = src; + + for (x=0; x> 12 ), + EXPAND_4to8( (src16[x] & 0x0f00) >> 8 ), + EXPAND_4to8( (src16[x] & 0x00f0) >> 4 ) ); + + src += spitch; + dst += dp2; + } + break; + + case DSPF_RGB555: + case DSPF_ARGB1555: + while (height--) { + const u16 *src16 = src; + + for (x=0; x> 10) | ((src16[x] & 0x03e0) << 1) | ((src16[x] & 0x001f) << 11 ); + + src += spitch; + dst += dp2; + } + break; + + case DSPF_RGB32: + case DSPF_ARGB: + while (height--) { + const u32 *src32 = src; + + for (x=0; x> 16, + (src32[x] & 0x00ff00) >> 8, + (src32[x] & 0x0000ff) ); + + src += spitch; + dst += dp2; + } + break; + + case DSPF_AYUV: + while (height--) { + const u32 *src32 = src; + + for (x=0; x> 16) & 0xff, (src32[x] >> 8) & 0xff, src32[x] & 0xff, r, g, b ); + + dst[x] = PIXEL_RGB16( r, g, b ); + } + + src += spitch; + dst += dp2; + } + break; + + default: + D_ONCE( "unsupported format" ); + } +} + +void +dfb_convert_to_rgb555( DFBSurfacePixelFormat format, + const void *src, + int spitch, + int surface_height, + u16 *dst, + int dpitch, + int width, + int height ) +{ + const int dp2 = dpitch / 2; + int x; + + switch (format) { + case DSPF_RGB555: + case DSPF_ARGB1555: + while (height--) { + direct_memcpy( dst, src, width * 2 ); + + src += spitch; + dst += dp2; + } + break; + + case DSPF_NV16: + while (height--) { + const u8 *src8 = src; + const u16 *src16 = src + surface_height * spitch; + + for (x=0; x>1] >> 8, src16[x>>1] & 0xff, r, g, b ); +#else + YCBCR_TO_RGB( src8[x], src16[x>>1] & 0xff, src16[x>>1] >> 8, r, g, b ); +#endif + + dst[x] = PIXEL_RGB555( r, g, b ); + } + + src += spitch; + dst += dp2; + } + break; + + case DSPF_RGB444: + case DSPF_ARGB4444: + while (height--) { + const u16 *src16 = src; + + for (x=0; x> 8 ), + EXPAND_4to8( (src16[x] & 0x00f0) >> 4 ), + EXPAND_4to8( (src16[x] & 0x000f) ) ); + + src += spitch; + dst += dp2; + } + break; + + case DSPF_RGBA4444: + while (height--) { + const u16 *src16 = src; + + for (x=0; x> 12 ), + EXPAND_4to8( (src16[x] & 0x0f00) >> 8 ), + EXPAND_4to8( (src16[x] & 0x00f0) >> 4 ) ); + + src += spitch; + dst += dp2; + } + break; + + case DSPF_RGB16: + while (height--) { + const u16 *src16 = src; + + for (x=0; x> 1) | (src16[x] & 0x001f); + + src += spitch; + dst += dp2; + } + break; + + case DSPF_BGR555: + while (height--) { + const u16 *src16 = src; + + for (x=0; x> 10) | (src16[x] & 0x03e0) | ((src16[x] & 0x001f) << 10 ); + + src += spitch; + dst += dp2; + } + break; + + case DSPF_RGB32: + case DSPF_ARGB: + while (height--) { + const u32 *src32 = src; + + for (x=0; x> 16, + (src32[x] & 0x00ff00) >> 8, + (src32[x] & 0x0000ff) ); + + src += spitch; + dst += dp2; + } + break; + + case DSPF_AYUV: + while (height--) { + const u32 *src32 = src; + + for (x=0; x> 16) & 0xff, (src32[x] >> 8) & 0xff, src32[x] & 0xff, r, g, b ); + + dst[x] = PIXEL_RGB555( r, g, b ); + } + + src += spitch; + dst += dp2; + } + break; + + default: + D_ONCE( "unsupported format" ); + } +} + +void +dfb_convert_to_rgb32( DFBSurfacePixelFormat format, + const void *src, + int spitch, + int surface_height, + u32 *dst, + int dpitch, + int width, + int height ) +{ + const int dp4 = dpitch / 4; + int x; + + switch (format) { + case DSPF_RGB32: + case DSPF_ARGB: + while (height--) { + direct_memcpy( dst, src, width * 4 ); + + src += spitch; + dst += dp4; + } + break; + + case DSPF_RGB24: + while (height--) { + const u8 *src8 = src; + + for (x=0; x> 16) & 0xff, (src32[x] >> 8) & 0xff, src32[x] & 0xff, r, g, b ); + + dst[x] = PIXEL_RGB32( r, g, b ); + } + + src += spitch; + dst += dp4; + } + break; + + case DSPF_NV16: + while (height--) { + const u8 *src8 = src; + const u16 *src16 = src + surface_height * spitch; + + for (x=0; x>1] >> 8, src16[x>>1] & 0xff, r, g, b ); +#else + YCBCR_TO_RGB( src8[x], src16[x>>1] & 0xff, src16[x>>1] >> 8, r, g, b ); +#endif + + dst[x] = PIXEL_RGB32( r, g, b ); + } + + src += spitch; + dst += dp4; + } + break; + + case DSPF_RGB444: + case DSPF_ARGB4444: + while (height--) { + const u16 *src16 = src; + + for (x=0; x> 7) | ((src16[x] & 0x7000) >> 12), + ((src16[x] & 0x03e0) >> 2) | ((src16[x] & 0x0380) >> 7), + ((src16[x] & 0x001f) << 3) | ((src16[x] & 0x001c) >> 2) ); + + src += spitch; + dst += dp4; + } + break; + + case DSPF_BGR555: + while (height--) { + const u16 *src16 = src; + + for (x=0; x> 2), + ((src16[x] & 0x03e0) >> 2) | ((src16[x] & 0x0380) >> 7), + ((src16[x] & 0x7c00) >> 7) | ((src16[x] & 0x7000) >> 12) ); + + src += spitch; + dst += dp4; + } + break; + + case DSPF_RGB16: + while (height--) { + const u16 *src16 = src; + + for (x=0; x> 8) | ((src16[x] & 0xe000) >> 13), + ((src16[x] & 0x07e0) >> 3) | ((src16[x] & 0x0300) >> 8), + ((src16[x] & 0x001f) << 3) | ((src16[x] & 0x001c) >> 2) ); + + src += spitch; + dst += dp4; + } + break; + + default: + D_ONCE( "unsupported format" ); + } +} + +void +dfb_convert_to_argb( DFBSurfacePixelFormat format, + const void *src, + int spitch, + int surface_height, + u32 *dst, + int dpitch, + int width, + int height ) +{ + const int dp4 = dpitch / 4; + int x; + + switch (format) { + case DSPF_ARGB: + while (height--) { + direct_memcpy( dst, src, width * 4 ); + + src += spitch; + dst += dp4; + } + break; + + case DSPF_RGB32: + while (height--) { + const u32 *src32 = src; + + for (x=0; x> 16) & 0xff, (src32[x] >> 8) & 0xff, src32[x] & 0xff, r, g, b ); + + dst[x] = PIXEL_ARGB( src32[x] >> 24, r, g, b ); + } + + src += spitch; + dst += dp4; + } + break; + + case DSPF_NV16: + while (height--) { + const u8 *src8 = src; + const u16 *src16 = src + surface_height * spitch; + + for (x=0; x>1] >> 8, src16[x>>1] & 0xff, r, g, b ); +#else + YCBCR_TO_RGB( src8[x], src16[x>>1] & 0xff, src16[x>>1] >> 8, r, g, b ); +#endif + + dst[x] = PIXEL_ARGB( 0xff, r, g, b ); + } + + src += spitch; + dst += dp4; + } + break; + + case DSPF_ARGB4444: + while (height--) { + const u16 *src16 = src; + + for (x=0; x> 4) | ((src16[x] & 0x0f00) >> 8), + ((src16[x] & 0x00f0) ) | ((src16[x] & 0x00f0) >> 4), + ((src16[x] & 0x000f) << 4) | ((src16[x] & 0x000f) ) ); + + src += spitch; + dst += dp4; + } + break; + + case DSPF_ARGB1555: + while (height--) { + const u16 *src16 = src; + + for (x=0; x> 7) | ((src16[x] & 0x7000) >> 12), + ((src16[x] & 0x03e0) >> 2) | ((src16[x] & 0x0380) >> 7), + ((src16[x] & 0x001f) << 3) | ((src16[x] & 0x001c) >> 2) ); + + src += spitch; + dst += dp4; + } + break; + + case DSPF_RGB555: + while (height--) { + const u16 *src16 = src; + + for (x=0; x> 7) | ((src16[x] & 0x7000) >> 12), + ((src16[x] & 0x03e0) >> 2) | ((src16[x] & 0x0380) >> 7), + ((src16[x] & 0x001f) << 3) | ((src16[x] & 0x001c) >> 2) ); + + src += spitch; + dst += dp4; + } + break; + + case DSPF_BGR555: + while (height--) { + const u16 *src16 = src; + + for (x=0; x> 2), + ((src16[x] & 0x03e0) >> 2) | ((src16[x] & 0x0380) >> 7), + ((src16[x] & 0x7c00) >> 7) | ((src16[x] & 0x7000) >> 12) ); + + src += spitch; + dst += dp4; + } + break; + + case DSPF_RGB16: + while (height--) { + const u16 *src16 = src; + + for (x=0; x> 8) | ((src16[x] & 0xe000) >> 13), + ((src16[x] & 0x07e0) >> 3) | ((src16[x] & 0x0300) >> 8), + ((src16[x] & 0x001f) << 3) | ((src16[x] & 0x001c) >> 2) ); + + src += spitch; + dst += dp4; + } + break; + + default: + D_ONCE( "unsupported format" ); + } +} + +void +dfb_convert_to_rgb24( DFBSurfacePixelFormat format, + const void *src, + int spitch, + int surface_height, + u8 *dst, + int dpitch, + int width, + int height ) +{ + int n, n3; + + switch (format) { + case DSPF_A8: + while (height--) { + const u8 *src8 = src; + + for (n=0, n3=0; n> 16; + dst[n3+1] = (src32[n] & 0x00FF00) >> 8; + dst[n3+2] = (src32[n] & 0x0000FF); + } + + src += spitch; + dst += dpitch; + } + break; + case DSPF_ARGB: + while (height--) { + const u32 *src32 = src; + + for (n=0, n3=0; n> 16; + dst[n3+1] = (src32[n] & 0x00FF00) >> 8; + dst[n3+2] = (src32[n] & 0x0000FF); + } + + src += spitch; + dst += dpitch; + } + break; + case DSPF_ARGB1555: + while (height--) { + const u16 *src16 = src; + + for (n=0, n3=0; n> 7; + dst[n3+1] = (src16[n] & 0x03E0) >> 2; + dst[n3+2] = (src16[n] & 0x001F) << 3; + } + + src += spitch; + dst += dpitch; + } + break; + case DSPF_RGB555: + while (height--) { + const u16 *src16 = src; + + for (n=0, n3=0; n> 7; + dst[n3+1] = (src16[n] & 0x03E0) >> 2; + dst[n3+2] = (src16[n] & 0x001F) << 3; + } + + src += spitch; + dst += dpitch; + } + break; + + case DSPF_BGR555: + while (height--) { + const u16 *src16 = src; + + for (n=0, n3=0; n> 7; + dst[n3+1] = (src16[n] & 0x03E0) >> 2; + dst[n3+0] = (src16[n] & 0x001F) << 3; + } + + src += spitch; + dst += dpitch; + } + break; + + case DSPF_ARGB2554: + while (height--) { + const u16 *src16 = src; + + for (n=0, n3=0; n> 6; + dst[n3+1] = (src16[n] & 0x01F0) >> 1; + dst[n3+2] = (src16[n] & 0x000F) << 4; + } + + src += spitch; + dst += dpitch; + } + break; + case DSPF_ARGB4444: + while (height--) { + const u16 *src16 = src; + + for (n=0, n3=0; n> 4; + dst[n3+1] = (src16[n] & 0x00F0); + dst[n3+2] = (src16[n] & 0x000F) << 4; + } + + src += spitch; + dst += dpitch; + } + break; + case DSPF_RGBA4444: + while (height--) { + const u16 *src16 = src; + + for (n=0, n3=0; n> 8; + dst[n3+1] = (src16[n] & 0x0F00) >> 4; + dst[n3+2] = (src16[n] & 0x00F0); + } + + src += spitch; + dst += dpitch; + } + break; + case DSPF_RGB444: + while (height--) { + const u16 *src16 = src; + + for (n=0, n3=0; n> 4; + dst[n3+1] = (src16[n] & 0x00F0); + dst[n3+2] = (src16[n] & 0x000F) << 4; + } + + src += spitch; + dst += dpitch; + } + break; + case DSPF_RGB332: + while (height--) { + const u8 *src8 = src; + + for (n=0, n3=0; n> 5) ]; + dst[n3+1] = lookup3to8[ (src8[n] >> 2) & 0x07 ]; + dst[n3+2] = lookup2to8[ (src8[n] ) & 0x03 ]; + } + + src += spitch; + dst += dpitch; + } + break; + case DSPF_RGB16: + while (height--) { + const u16 *src16 = src; + + for (n=0, n3=0; n> 8; + dst[n3+1] = (src16[n] & 0x07E0) >> 3; + dst[n3+2] = (src16[n] & 0x001F) << 3; + } + + src += spitch; + dst += dpitch; + } + break; + case DSPF_RGB24: + while (height--) { + const u8 *src8 = src; + + for (n=0, n3=0; n> 16; + dst[n3+1] = (src32[n] & 0x00FF00) >> 8; + dst[n3+2] = (src32[n] & 0x0000FF); + } + + src += spitch; + dst += dpitch; + } + break; + case DSPF_YUY2: + while (height--) { + const u32 *src32 = src; + + for (n=0, n3=0; n> 8; + y1 = (src32[n] & 0x00FF0000) >> 16; + cr = (src32[n] & 0xFF000000) >> 24; + YCBCR_TO_RGB( y0, cb, cr, + dst[n3+0], dst[n3+1], dst[n3+2] ); + YCBCR_TO_RGB( y1, cb, cr, + dst[n3+3], dst[n3+4], dst[n3+5] ); + } + + src += spitch; + dst += dpitch; + } + break; + case DSPF_UYVY: + while (height--) { + const u32 *src32 = src; + + for (n=0, n3=0; n> 8; + cr = (src32[n] & 0x00FF0000) >> 16; + y1 = (src32[n] & 0xFF000000) >> 24; + YCBCR_TO_RGB( y0, cb, cr, + dst[n3+0], dst[n3+1], dst[n3+2] ); + YCBCR_TO_RGB( y1, cb, cr, + dst[n3+3], dst[n3+4], dst[n3+5] ); + } + + src += spitch; + dst += dpitch; + } + break; + case DSPF_NV16: { + while (height--) { + const u16 *cbcr = src + surface_height * spitch; + const u8 *src8 = src; + + for (n=0, n3=0; n> 8, cbcr[n] & 0xff, + dst[n3+0], dst[n3+1], dst[n3+2] ); + + YCBCR_TO_RGB( src8[n*2+1], cbcr[n] >> 8, cbcr[n] & 0xff, + dst[n3+3], dst[n3+4], dst[n3+5] ); +#else + YCBCR_TO_RGB( src8[n*2+0], cbcr[n] & 0xff, cbcr[n] >> 8, + dst[n3+0], dst[n3+1], dst[n3+2] ); + + YCBCR_TO_RGB( src8[n*2+1], cbcr[n] & 0xff, cbcr[n] >> 8, + dst[n3+3], dst[n3+4], dst[n3+5] ); +#endif + } + + src += spitch; + dst += dpitch; + } + break; + } + default: + D_ONCE( "unsupported format" ); + } +} + +void +dfb_convert_to_a8( DFBSurfacePixelFormat format, + const void *src, + int spitch, + int surface_height, + u8 *dst, + int dpitch, + int width, + int height ) +{ + int n; + + switch (format) { + case DSPF_A8: + while (height--) { + const u8 *src8 = src; + + direct_memcpy( dst, src8, width ); + + src += spitch; + dst += dpitch; + } + break; + case DSPF_AiRGB: + while (height--) { + const u32 *src32 = src; + + for (n=0; n> 24); + } + + src += spitch; + dst += dpitch; + } + break; + case DSPF_ARGB: + while (height--) { + const u32 *src32 = src; + + for (n=0; n> 24; + } + + src += spitch; + dst += dpitch; + } + break; + case DSPF_ARGB1555: + while (height--) { + const u16 *src16 = src; + + for (n=0; n> 14) { + case 0: + dst[n] = 0x00; + break; + case 1: + dst[n] = 0x55; + break; + case 2: + dst[n] = 0xAA; + break; + case 3: + dst[n] = 0xFF; + break; + } + } + + src += spitch; + dst += dpitch; + } + break; + case DSPF_ARGB4444: + while (height--) { + const u16 *src16 = src; + + for (n=0; n> 12); + dst[n] |= dst[n] << 4; + } + + src += spitch; + dst += dpitch; + } + break; + case DSPF_RGBA4444: + while (height--) { + const u16 *src16 = src; + + for (n=0; n> 4); + + src += spitch; + dst += dpitch; + } + break; + + case DSPF_ARGB4444: + while (height--) { + const u16 *src16 = src; + + for (x=0, n=0; x> 8) | (src16[n+1] >> 12); + + src += spitch; + dst += dpitch; + } + break; + + case DSPF_RGBA4444: + while (height--) { + const u16 *src16 = src; + + for (x=0, n=0; x> 24) | ((src32[n+1] & 0xf0000000) >> 28); + + src += spitch; + dst += dpitch; + } + break; + + default: + if (DFB_PIXELFORMAT_HAS_ALPHA( format )) + D_ONCE( "unsupported format" ); + } +} + +void +dfb_convert_to_yuy2( DFBSurfacePixelFormat format, + const void *src, + int spitch, + int surface_height, + u32 *dst, + int dpitch, + int width, + int height ) +{ + const int dp4 = dpitch / 4; + + switch (format) { + case DSPF_YUY2: + while (height--) { + direct_memcpy( dst, src, width * 2 ); + + src += spitch; + dst += dp4; + } + break; + + default: + D_ONCE( "unsupported format" ); + } +} + +void +dfb_convert_to_uyvy( DFBSurfacePixelFormat format, + const void *src, + int spitch, + int surface_height, + u32 *dst, + int dpitch, + int width, + int height ) +{ + const int dp4 = dpitch / 4; + + switch (format) { + case DSPF_UYVY: + while (height--) { + direct_memcpy( dst, src, width * 2 ); + + src += spitch; + dst += dp4; + } + break; + + default: + D_ONCE( "unsupported format" ); + } +} + diff --git a/Source/DirectFB/src/gfx/convert.h b/Source/DirectFB/src/gfx/convert.h new file mode 100755 index 0000000..a831d8c --- /dev/null +++ b/Source/DirectFB/src/gfx/convert.h @@ -0,0 +1,562 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __GFX__CONVERT_H__ +#define __GFX__CONVERT_H__ + +#include + +#include +#include + + +/* pixel packing */ + +#define PIXEL_RGB332(r,g,b) ( (((r)&0xE0) ) | \ + (((g)&0xE0) >> 3) | \ + (((b)&0xC0) >> 6) ) + +#define PIXEL_ARGB1555(a,r,g,b)( (((a)&0x80) << 8) | \ + (((r)&0xF8) << 7) | \ + (((g)&0xF8) << 2) | \ + (((b)&0xF8) >> 3) ) + +#define PIXEL_RGB555(r,g,b) ( (((r)&0xF8) << 7) | \ + (((g)&0xF8) << 2) | \ + (((b)&0xF8) >> 3) ) + +#define PIXEL_BGR555(r,g,b) ( (((b)&0xF8) << 7) | \ + (((g)&0xF8) << 2) | \ + (((r)&0xF8) >> 3) ) + +#define PIXEL_ARGB2554(a,r,g,b)( (((a)&0xC0) << 8) | \ + (((r)&0xF8) << 6) | \ + (((g)&0xF8) << 1) | \ + (((b)&0xF0) >> 4) ) + +#define PIXEL_ARGB4444(a,r,g,b)( (((a)&0xF0) << 8) | \ + (((r)&0xF0) << 4) | \ + (((g)&0xF0) ) | \ + (((b)&0xF0) >> 4) ) + +#define PIXEL_RGBA4444(a,r,g,b)( (((r)&0xF0) << 8) | \ + (((g)&0xF0) << 4) | \ + (((b)&0xF0) ) | \ + (((a)&0xF0) >> 4) ) + +#define PIXEL_RGB444(r,g,b) ( (((r)&0xF0) << 4) | \ + (((g)&0xF0) ) | \ + (((b)&0xF0) >> 4) ) + +#define PIXEL_RGB16(r,g,b) ( (((r)&0xF8) << 8) | \ + (((g)&0xFC) << 3) | \ + (((b)&0xF8) >> 3) ) + +#define PIXEL_RGB18(r,g,b) ( (((r)&0xFC) << 10) | \ + (((g)&0xFC) << 4) | \ + (((b)&0xFC) >> 2) ) + +#define PIXEL_RGB32(r,g,b) ( ((r) << 16) | \ + ((g) << 8) | \ + (b) ) + +#define PIXEL_ARGB(a,r,g,b) ( ((a) << 24) | \ + ((r) << 16) | \ + ((g) << 8) | \ + (b) ) + +#define PIXEL_ARGB1666(a,r,g,b) ( (((a)&0x80) << 11) | \ + (((r)&0xFC) << 10) | \ + (((g)&0xFC) << 4) | \ + (((b)&0xFC) >> 2) ) + +#define PIXEL_ARGB6666(a,r,g,b) ( (((a)&0xFC) << 16) | \ + (((r)&0xFC) << 10) | \ + (((g)&0xFC) << 4) | \ + (((b)&0xFC) >> 2) ) + +#define PIXEL_AYUV(a,y,u,v) ( ((a) << 24) | \ + ((y) << 16) | \ + ((u) << 8) | \ + (v) ) + +#define PIXEL_AiRGB(a,r,g,b) ( (((a) ^ 0xff) << 24) | \ + ((r) << 16) | \ + ((g) << 8) | \ + (b) ) + +#ifdef WORDS_BIGENDIAN + +#define PIXEL_YUY2(y,u,v) ( ((u) << 24) | \ + ((y) << 16) | \ + ((v) << 8) | \ + (y) ) + +#define PIXEL_UYVY(y,u,v) ( ((y) << 24) | \ + ((u) << 16) | \ + ((y) << 8) | \ + (v) ) +#else /* little endian */ + +#define PIXEL_YUY2(y,u,v) ( ((v) << 24) | \ + ((y) << 16) | \ + ((u) << 8) | \ + (y) ) + +#define PIXEL_UYVY(y,u,v) ( ((y) << 24) | \ + ((v) << 16) | \ + ((y) << 8) | \ + (u) ) + +#endif + + +/* packed pixel conversions */ + +#define ARGB1555_TO_RGB332(pixel) ( (((pixel) & 0x7000) >> 7) | \ + (((pixel) & 0x0380) >> 5) | \ + (((pixel) & 0x0018) >> 3) ) + +#define ARGB1555_TO_ARGB2554(pixel) ( (((pixel) & 0x8000) ) | \ + (((pixel) & 0x7FFF) >> 1) ) + +#define ARGB1555_TO_ARGB4444(pixel) ( (((pixel) & 0x8000) ? 0xf000 : 0 ) | \ + (((pixel) & 0x7800) >> 3) | \ + (((pixel) & 0x03C0) >> 2) | \ + (((pixel) & 0x0018) >> 1) ) + +#define ARGB1555_TO_RGBA4444(pixel) ( (((pixel) & 0x8000) ? 0x000f : 0 ) | \ + (((pixel) & 0x7800) << 1) | \ + (((pixel) & 0x03C0) << 2) | \ + (((pixel) & 0x0018) << 3) ) + +#define ARGB1555_TO_RGB16(pixel) ( (((pixel) & 0x7C00) << 1) | \ + (((pixel) & 0x03E0) << 1) | \ + (((pixel) & 0x001F)) ) + +#define ARGB1555_TO_RGB32(pixel) ( (((pixel) & 0x7C00) << 9) | \ + (((pixel) & 0x03E0) << 6) | \ + (((pixel) & 0x001F) << 3) ) + +#define ARGB1555_TO_ARGB(pixel) ( (((pixel) & 0x8000) ? 0xFF000000 : 0) | \ + (((pixel) & 0x7C00) << 9) | \ + (((pixel) & 0x03E0) << 6) | \ + (((pixel) & 0x001F) << 3) ) + +#define ARGB1555_TO_RGB555(pixel) ( (((pixel) & 0x7C00) << 9) | \ + (((pixel) & 0x03E0) << 6) | \ + (((pixel) & 0x001F) << 3) ) + +#define ARGB1555_TO_RGB444(pixel) ( (((pixel) & 0x7800) >> 3) | \ + (((pixel) & 0x03C0) >> 2) | \ + (((pixel) & 0x001E) >> 1) ) + +/* xRGB to xxRRGGBB, so xRxx left 3, xRGx left 2, xxGB left 1, xxxB */ +#define ARGB4444_TO_RGB32(pixel) ( (((pixel) & 0x0F00) << 12) | \ + (((pixel) & 0x0FF0) << 8) | \ + (((pixel) & 0x00FF) << 4) | \ + (((pixel) & 0x000F) ) ) + +/* RGBx to xxRRGGBB, so Rxxx left 2, RGxx left 1, xGBx, xxBx right 1 */ +#define RGBA4444_TO_RGB32(pixel) ( (((pixel) & 0xF000) << 8) | \ + (((pixel) & 0xFF00) << 4) | \ + (((pixel) & 0x0FF0) ) | \ + (((pixel) & 0x00F0) >> 4) ) + +/* ARGB to AARRGGBB, so Axxx left 4, ARxx left 3, xRGx left 2, xxGB left 1, xxxB */ +#define ARGB4444_TO_ARGB(pixel) ( (((pixel) & 0xF000) << 16) | \ + (((pixel) & 0xFF00) << 12) | \ + (((pixel) & 0x0FF0) << 8) | \ + (((pixel) & 0x00FF) << 4) | \ + (((pixel) & 0x000F) ) ) + +/* RGBA to AARRGGBB, so Rxxx left 2, RGxx left 1, xGBx, xxBx right 1, A to the left */ +#define RGBA4444_TO_ARGB(pixel) ( (((pixel) & 0x000F) << 28) | \ + (((pixel) & 0x000F) << 24) | \ + (((pixel) & 0xF000) << 8) | \ + (((pixel) & 0xFF00) << 4) | \ + (((pixel) & 0x0FF0) ) | \ + (((pixel) & 0x00F0) >> 4) ) + +#define RGB16_TO_RGB332(pixel) ( (((pixel) & 0xE000) >> 8) | \ + (((pixel) & 0x0700) >> 6) | \ + (((pixel) & 0x0018) >> 3) ) + +#define RGB16_TO_ARGB1555(pixel) ( 0x8000 | \ + (((pixel) & 0xF800) >> 1) | \ + (((pixel) & 0x07C0) >> 1) | \ + (((pixel) & 0x001F)) ) + +#define RGB16_TO_ARGB2554(pixel) ( 0xC000 | \ + (((pixel) & 0xF800) >> 2) | \ + (((pixel) & 0x07C0) >> 2) | \ + (((pixel) & 0x001F) >> 1) ) + +#define RGB16_TO_ARGB4444(pixel) ( 0xF000 | \ + (((pixel) & 0xF000) >> 4) | \ + (((pixel) & 0x0780) >> 3) | \ + (((pixel) & 0x001E) >> 1) ) + +#define RGB16_TO_RGBA4444(pixel) ( 0x000F | \ + (((pixel) & 0xF000) ) | \ + (((pixel) & 0x0780) << 1) | \ + (((pixel) & 0x001E) << 3) ) + + +#define RGB16_TO_RGB32(pixel) ( (((pixel) & 0xF800) << 8) | \ + (((pixel) & 0x07E0) << 5) | \ + (((pixel) & 0x001F) << 3) ) + +#define RGB16_TO_ARGB(pixel) ( 0xFF000000 | \ + (((pixel) & 0xF800) << 8) | \ + (((pixel) & 0x07E0) << 5) | \ + (((pixel) & 0x001F) << 3) ) + +#define RGB16_TO_RGB555(pixel) ( (((pixel) & 0xF800) >> 1) | \ + (((pixel) & 0x07C0) >> 1) | \ + (((pixel) & 0x001F)) ) + +#define RGB16_TO_BGR555(pixel) ( (((pixel) & 0xF800) >> 12) | \ + (((pixel) & 0x07C0) >> 1) | \ + (((pixel) & 0x001F) << 10 ) ) + +#define RGB16_TO_RGB444(pixel) ( (((pixel) & 0xF000) >> 4) | \ + (((pixel) & 0x0780) >> 3) | \ + (((pixel) & 0x001F) >> 1) ) + +#define RGB18_TO_ARGB(pixel) ( 0xFF000000 | \ + (((pixel) & 0xFC00) << 10) | \ + (((pixel) & 0x3F00) << 4) | \ + (((pixel) & 0x00FC) << 2) ) + +#define RGB32_TO_RGB332(pixel) ( (((pixel) & 0xE00000) >> 16) | \ + (((pixel) & 0x00E000) >> 11) | \ + (((pixel) & 0x0000C0) >> 6) ) + +#define RGB32_TO_ARGB1555(pixel) ( 0x8000 | \ + (((pixel) & 0xF80000) >> 9) | \ + (((pixel) & 0x00F800) >> 6) | \ + (((pixel) & 0x0000F8) >> 3) ) + +#define RGB32_TO_ARGB2554(pixel) ( 0xC000 | \ + (((pixel) & 0xF80000) >> 10) | \ + (((pixel) & 0x00F800) >> 7) | \ + (((pixel) & 0x0000F0) >> 4) ) + +#define RGB32_TO_ARGB4444(pixel) ( 0xF000 | \ + (((pixel) & 0xF00000) >> 12) | \ + (((pixel) & 0x00F000) >> 8) | \ + (((pixel) & 0x0000F0) >> 4) ) + +#define RGB32_TO_RGBA4444(pixel) ( 0x000F | \ + (((pixel) & 0xF00000) >> 8) | \ + (((pixel) & 0x00F000) >> 4) | \ + (((pixel) & 0x0000F0) ) ) + +#define RGB32_TO_RGB16(pixel) ( (((pixel) & 0xF80000) >> 8) | \ + (((pixel) & 0x00FC00) >> 5) | \ + (((pixel) & 0x0000F8) >> 3) ) + +#define RGB32_TO_ARGB1555(pixel) ( 0x8000 | \ + (((pixel) & 0xF80000) >> 9) | \ + (((pixel) & 0x00F800) >> 6) | \ + (((pixel) & 0x0000F8) >> 3) ) + +#define RGB32_TO_ARGB(pixel) ( 0xFF000000 | (pixel) ) + + +#define RGB32_TO_RGB555(pixel) ( (((pixel) & 0xF80000) >> 9) | \ + (((pixel) & 0x00F800) >> 6) | \ + (((pixel) & 0x0000F8) >> 3) ) + +#define RGB32_TO_BGR555(pixel) ( (((pixel) & 0xF80000) >> 19) | \ + (((pixel) & 0x00F800) >> 6) | \ + (((pixel) & 0x0000F8) << 7) ) + +#define RGB32_TO_RGB444(pixel) ( (((pixel) & 0xF00000) >> 12) | \ + (((pixel) & 0x00F000) >> 8) | \ + (((pixel) & 0x0000F0) >> 4) ) + +#define ARGB_TO_ARGB1555(pixel) ( (((pixel) & 0x80000000) >> 16) | \ + (((pixel) & 0x00F80000) >> 9) | \ + (((pixel) & 0x0000F800) >> 6) | \ + (((pixel) & 0x000000F8) >> 3) ) + +#define ARGB_TO_ARGB2554(pixel) ( (((pixel) & 0xC0000000) >> 16) | \ + (((pixel) & 0x00F80000) >> 10) | \ + (((pixel) & 0x0000F800) >> 7) | \ + (((pixel) & 0x000000F0) >> 4) ) + +#define ARGB_TO_ARGB4444(pixel) ( (((pixel) & 0xF0000000) >> 16) | \ + (((pixel) & 0x00F00000) >> 12) | \ + (((pixel) & 0x0000F000) >> 8) | \ + (((pixel) & 0x000000F0) >> 4) ) + +#define ARGB_TO_RGBA4444(pixel) ( (((pixel) & 0xF0000000) >> 28) | \ + (((pixel) & 0x00F00000) >> 8) | \ + (((pixel) & 0x0000F000) >> 4) | \ + (((pixel) & 0x000000F0) ) ) + +#define ARGB_TO_RGB444(pixel) ( (((pixel) & 0x00F00000) >> 12) | \ + (((pixel) & 0x0000F000) >> 8) | \ + (((pixel) & 0x000000F0) >> 4) ) + +#define ARGB_TO_RGB555(pixel) ( (((pixel) & 0x00F80000) >> 9) | \ + (((pixel) & 0x0000F800) >> 6) | \ + (((pixel) & 0x000000F8) >> 3) ) + +#define ARGB_TO_BGR555(pixel) ( (((pixel) & 0x00F80000) >> 19) | \ + (((pixel) & 0x0000F800) >> 6) | \ + (((pixel) & 0x000000F8) << 7) ) + +/* RGB <-> YCbCr conversion */ + +#define YCBCR_TO_RGB( y, cb, cr, r, g, b ) \ +do { \ + int _y = (y) - 16; \ + int _cb = (cb) - 128; \ + int _cr = (cr) - 128; \ + \ + int _r = (298 * _y + 409 * _cr + 128) >> 8; \ + int _g = (298 * _y - 100 * _cb - 208 * _cr + 128) >> 8; \ + int _b = (298 * _y + 516 * _cb + 128) >> 8; \ + \ + (r) = CLAMP( _r, 0, 255 ); \ + (g) = CLAMP( _g, 0, 255 ); \ + (b) = CLAMP( _b, 0, 255 ); \ +} while (0) + +#define RGB_TO_YCBCR( r, g, b, y, cb, cr ) \ +do { \ + int _r = (r), _g = (g), _b = (b); \ + \ + (y) = ( 66 * _r + 129 * _g + 25 * _b + 16*256 + 128) >> 8; \ + (cb) = ( - 38 * _r - 74 * _g + 112 * _b + 128*256 + 128) >> 8; \ + (cr) = ( 112 * _r - 94 * _g - 18 * _b + 128*256 + 128) >> 8; \ +} while (0) + + +DFBSurfacePixelFormat dfb_pixelformat_for_depth( int depth ); + + +void dfb_pixel_to_color ( DFBSurfacePixelFormat format, + unsigned long pixel, + DFBColor *ret_color ); + +unsigned long dfb_pixel_from_color( DFBSurfacePixelFormat format, + const DFBColor *color ); + + +static inline u32 +dfb_color_to_pixel( DFBSurfacePixelFormat format, + u8 r, u8 g, u8 b ) +{ + const DFBColor color = { 0, r, g, b }; + + return dfb_pixel_from_color( format, &color ); +} + +static inline u32 +dfb_color_to_argb( const DFBColor *color ) +{ + return (color->a << 24) | (color->r << 16) | (color->g << 8) | color->b; +} + +static inline u32 +dfb_color_to_aycbcr( const DFBColor *color ) +{ + u32 y = ( 66 * color->r + 129 * color->g + 25 * color->b + 16*256 + 128) >> 8; + u32 cb = ( - 38 * color->r - 74 * color->g + 112 * color->b + 128*256 + 128) >> 8; + u32 cr = ( 112 * color->r - 94 * color->g - 18 * color->b + 128*256 + 128) >> 8; + + return (color->a << 24) | (y << 16) | (cb << 8) | cr; +} + +static inline void +dfb_argb_to_rgb332( const u32 *src, u8 *dst, int len ) +{ + int i; + + for (i=0; i> 24; +} + +void dfb_convert_to_rgb16( DFBSurfacePixelFormat format, + const void *src, + int spitch, + int surface_height, + u16 *dst, + int dpitch, + int width, + int height ); + +void dfb_convert_to_rgb555( DFBSurfacePixelFormat format, + const void *src, + int spitch, + int surface_height, + u16 *dst, + int dpitch, + int width, + int height ); + +void dfb_convert_to_argb( DFBSurfacePixelFormat format, + const void *src, + int spitch, + int surface_height, + u32 *dst, + int dpitch, + int width, + int height ); + +void dfb_convert_to_rgb32( DFBSurfacePixelFormat format, + const void *src, + int spitch, + int surface_height, + u32 *dst, + int dpitch, + int width, + int height ); + +void dfb_convert_to_rgb24( DFBSurfacePixelFormat format, + const void *src, + int spitch, + int surface_height, + u8 *dst, + int dpitch, + int width, + int height ); + +void dfb_convert_to_a8( DFBSurfacePixelFormat format, + const void *src, + int spitch, + int surface_height, + u8 *dst, + int dpitch, + int width, + int height ); + +void dfb_convert_to_a4( DFBSurfacePixelFormat format, + const void *src, + int spitch, + int surface_height, + u8 *dst, + int dpitch, + int width, + int height ); + +void dfb_convert_to_yuy2( DFBSurfacePixelFormat format, + const void *src, + int spitch, + int surface_height, + u32 *dst, + int dpitch, + int width, + int height ); + +void dfb_convert_to_uyvy( DFBSurfacePixelFormat format, + const void *src, + int spitch, + int surface_height, + u32 *dst, + int dpitch, + int width, + int height ); + +#endif diff --git a/Source/DirectFB/src/gfx/generic/Makefile.am b/Source/DirectFB/src/gfx/generic/Makefile.am new file mode 100755 index 0000000..6d80484 --- /dev/null +++ b/Source/DirectFB/src/gfx/generic/Makefile.am @@ -0,0 +1,62 @@ +## Makefile.am for DirectFB/src/gfx/generic + +INCLUDES = \ + -I$(top_builddir)/lib \ + -I$(top_builddir)/include \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/lib \ + -I$(top_srcdir)/src + +AM_CFLAGS = $(DFB_CFLAGS_OMIT_FRAME_POINTER) + +EXTRA_DIST = \ + yuvtbl-gen.c + +internalincludedir = $(INTERNALINCLUDEDIR)/gfx/generic + +internalinclude_HEADERS = \ + generic.h + +noinst_LTLIBRARIES = libdirectfb_generic.la + +if SOFTWARE_RENDERING +GENERIC_C = generic.c +else +GENERIC_C = generic_dummy.c +endif + +libdirectfb_generic_la_SOURCES = \ + duffs_device.h \ + $(GENERIC_C) \ + generic.h \ + generic_mmx.h \ + generic_64.h \ + stretch_hvx_N.h \ + stretch_hvx_16.h \ + stretch_hvx_32.h \ + stretch_hvx_8.h \ + stretch_hvx_88.h \ + stretch_up_down_16.h \ + stretch_up_down_32.h \ + stretch_up_down_32_indexed.h \ + stretch_up_down_8.h \ + stretch_up_down_88.h \ + stretch_up_down_table.h \ + template_acc_16.h \ + template_acc_32.h \ + template_colorkey_16.h \ + template_colorkey_32.h \ + yuvtbl.h + +generic.c: yuvtbl.h +generic_dummy.c: yuvtbl.h + +yuvtbl-gen: yuvtbl-gen.c + $(CC) -O2 yuvtbl-gen.c -o yuvtbl-gen + +#yuvtbl.h: yuvtbl-gen +# ./yuvtbl-gen > $(srcdir)/yuvtbl.h + +clean-local: + rm -f yuvtbl-gen + diff --git a/Source/DirectFB/src/gfx/generic/Makefile.in b/Source/DirectFB/src/gfx/generic/Makefile.in new file mode 100755 index 0000000..94695ac --- /dev/null +++ b/Source/DirectFB/src/gfx/generic/Makefile.in @@ -0,0 +1,602 @@ +# Makefile.in generated by automake 1.10.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = src/gfx/generic +DIST_COMMON = $(internalinclude_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/as-ac-expand.m4 \ + $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libdirectfb_generic_la_LIBADD = +am__libdirectfb_generic_la_SOURCES_DIST = duffs_device.h \ + generic_dummy.c generic.c generic.h generic_mmx.h generic_64.h \ + stretch_hvx_N.h stretch_hvx_16.h stretch_hvx_32.h \ + stretch_hvx_8.h stretch_hvx_88.h stretch_up_down_16.h \ + stretch_up_down_32.h stretch_up_down_32_indexed.h \ + stretch_up_down_8.h stretch_up_down_88.h \ + stretch_up_down_table.h template_acc_16.h template_acc_32.h \ + template_colorkey_16.h template_colorkey_32.h yuvtbl.h +@SOFTWARE_RENDERING_FALSE@am__objects_1 = generic_dummy.lo +@SOFTWARE_RENDERING_TRUE@am__objects_1 = generic.lo +am_libdirectfb_generic_la_OBJECTS = $(am__objects_1) +libdirectfb_generic_la_OBJECTS = $(am_libdirectfb_generic_la_OBJECTS) +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libdirectfb_generic_la_SOURCES) +DIST_SOURCES = $(am__libdirectfb_generic_la_SOURCES_DIST) +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(internalincludedir)" +internalincludeHEADERS_INSTALL = $(INSTALL_HEADER) +HEADERS = $(internalinclude_HEADERS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AS = @AS@ +ASFLAGS = @ASFLAGS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIR = @DATADIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DFB_CFLAGS_OMIT_FRAME_POINTER = @DFB_CFLAGS_OMIT_FRAME_POINTER@ +DFB_INTERNAL_CFLAGS = @DFB_INTERNAL_CFLAGS@ +DFB_LDFLAGS = @DFB_LDFLAGS@ +DFB_SMOOTH_SCALING = @DFB_SMOOTH_SCALING@ +DIRECTFB_BINARY_AGE = @DIRECTFB_BINARY_AGE@ +DIRECTFB_CSOURCE = @DIRECTFB_CSOURCE@ +DIRECTFB_INTERFACE_AGE = @DIRECTFB_INTERFACE_AGE@ +DIRECTFB_MAJOR_VERSION = @DIRECTFB_MAJOR_VERSION@ +DIRECTFB_MICRO_VERSION = @DIRECTFB_MICRO_VERSION@ +DIRECTFB_MINOR_VERSION = @DIRECTFB_MINOR_VERSION@ +DIRECTFB_VERSION = @DIRECTFB_VERSION@ +DIRECT_BUILD_DEBUG = @DIRECT_BUILD_DEBUG@ +DIRECT_BUILD_DEBUGS = @DIRECT_BUILD_DEBUGS@ +DIRECT_BUILD_GETTID = @DIRECT_BUILD_GETTID@ +DIRECT_BUILD_NETWORK = @DIRECT_BUILD_NETWORK@ +DIRECT_BUILD_STDBOOL = @DIRECT_BUILD_STDBOOL@ +DIRECT_BUILD_TEXT = @DIRECT_BUILD_TEXT@ +DIRECT_BUILD_TRACE = @DIRECT_BUILD_TRACE@ +DSYMUTIL = @DSYMUTIL@ +DYNLIB = @DYNLIB@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +FREETYPE_CFLAGS = @FREETYPE_CFLAGS@ +FREETYPE_LIBS = @FREETYPE_LIBS@ +FREETYPE_PROVIDER = @FREETYPE_PROVIDER@ +FUSION_BUILD_KERNEL = @FUSION_BUILD_KERNEL@ +FUSION_BUILD_MULTI = @FUSION_BUILD_MULTI@ +FUSION_MESSAGE_SIZE = @FUSION_MESSAGE_SIZE@ +GIF_PROVIDER = @GIF_PROVIDER@ +GREP = @GREP@ +HAVE_LINUX = @HAVE_LINUX@ +INCLUDEDIR = @INCLUDEDIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTERNALINCLUDEDIR = @INTERNALINCLUDEDIR@ +JPEG_PROVIDER = @JPEG_PROVIDER@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBJPEG = @LIBJPEG@ +LIBOBJS = @LIBOBJS@ +LIBPNG = @LIBPNG@ +LIBPNG_CONFIG = @LIBPNG_CONFIG@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_AGE = @LT_AGE@ +LT_BINARY = @LT_BINARY@ +LT_CURRENT = @LT_CURRENT@ +LT_RELEASE = @LT_RELEASE@ +LT_REVISION = @LT_REVISION@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MAN2HTML = @MAN2HTML@ +MKDIR_P = @MKDIR_P@ +MODULEDIR = @MODULEDIR@ +MODULEDIRNAME = @MODULEDIRNAME@ +NMEDIT = @NMEDIT@ +OBJEXT = @OBJEXT@ +OSX_LIBS = @OSX_LIBS@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PNG_PROVIDER = @PNG_PROVIDER@ +RANLIB = @RANLIB@ +RUNTIME_SYSROOT = @RUNTIME_SYSROOT@ +SDL_CFLAGS = @SDL_CFLAGS@ +SDL_LIBS = @SDL_LIBS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOPATH = @SOPATH@ +STRIP = @STRIP@ +SYSCONFDIR = @SYSCONFDIR@ +SYSFS_LIBS = @SYSFS_LIBS@ +THREADFLAGS = @THREADFLAGS@ +THREADLIB = @THREADLIB@ +TSLIB_CFLAGS = @TSLIB_CFLAGS@ +TSLIB_LIBS = @TSLIB_LIBS@ +VERSION = @VERSION@ +VNC_CFLAGS = @VNC_CFLAGS@ +VNC_CONFIG = @VNC_CONFIG@ +VNC_LIBS = @VNC_LIBS@ +X11_CFLAGS = @X11_CFLAGS@ +X11_LIBS = @X11_LIBS@ +ZLIB_LIBS = @ZLIB_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +INCLUDES = \ + -I$(top_builddir)/lib \ + -I$(top_builddir)/include \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/lib \ + -I$(top_srcdir)/src + +AM_CFLAGS = $(DFB_CFLAGS_OMIT_FRAME_POINTER) +EXTRA_DIST = \ + yuvtbl-gen.c + +internalincludedir = $(INTERNALINCLUDEDIR)/gfx/generic +internalinclude_HEADERS = \ + generic.h + +noinst_LTLIBRARIES = libdirectfb_generic.la +@SOFTWARE_RENDERING_FALSE@GENERIC_C = generic_dummy.c +@SOFTWARE_RENDERING_TRUE@GENERIC_C = generic.c +libdirectfb_generic_la_SOURCES = \ + duffs_device.h \ + $(GENERIC_C) \ + generic.h \ + generic_mmx.h \ + generic_64.h \ + stretch_hvx_N.h \ + stretch_hvx_16.h \ + stretch_hvx_32.h \ + stretch_hvx_8.h \ + stretch_hvx_88.h \ + stretch_up_down_16.h \ + stretch_up_down_32.h \ + stretch_up_down_32_indexed.h \ + stretch_up_down_8.h \ + stretch_up_down_88.h \ + stretch_up_down_table.h \ + template_acc_16.h \ + template_acc_32.h \ + template_colorkey_16.h \ + template_colorkey_32.h \ + yuvtbl.h + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/gfx/generic/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/gfx/generic/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libdirectfb_generic.la: $(libdirectfb_generic_la_OBJECTS) $(libdirectfb_generic_la_DEPENDENCIES) + $(LINK) $(libdirectfb_generic_la_OBJECTS) $(libdirectfb_generic_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/generic.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/generic_dummy.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-internalincludeHEADERS: $(internalinclude_HEADERS) + @$(NORMAL_INSTALL) + test -z "$(internalincludedir)" || $(MKDIR_P) "$(DESTDIR)$(internalincludedir)" + @list='$(internalinclude_HEADERS)'; for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + f=$(am__strip_dir) \ + echo " $(internalincludeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(internalincludedir)/$$f'"; \ + $(internalincludeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(internalincludedir)/$$f"; \ + done + +uninstall-internalincludeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(internalinclude_HEADERS)'; for p in $$list; do \ + f=$(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(internalincludedir)/$$f'"; \ + rm -f "$(DESTDIR)$(internalincludedir)/$$f"; \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(internalincludedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-local \ + clean-noinstLTLIBRARIES mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: install-internalincludeHEADERS + +install-dvi: install-dvi-am + +install-exec-am: + +install-html: install-html-am + +install-info: install-info-am + +install-man: + +install-pdf: install-pdf-am + +install-ps: install-ps-am + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-internalincludeHEADERS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-local clean-noinstLTLIBRARIES ctags \ + distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-internalincludeHEADERS install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags uninstall uninstall-am \ + uninstall-internalincludeHEADERS + + +generic.c: yuvtbl.h +generic_dummy.c: yuvtbl.h + +yuvtbl-gen: yuvtbl-gen.c + $(CC) -O2 yuvtbl-gen.c -o yuvtbl-gen + +#yuvtbl.h: yuvtbl-gen +# ./yuvtbl-gen > $(srcdir)/yuvtbl.h + +clean-local: + rm -f yuvtbl-gen +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/Source/DirectFB/src/gfx/generic/duffs_device.h b/Source/DirectFB/src/gfx/generic/duffs_device.h new file mode 100755 index 0000000..4e31089 --- /dev/null +++ b/Source/DirectFB/src/gfx/generic/duffs_device.h @@ -0,0 +1,89 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __DUFFS_DEVICE_H__ +#define __DUFFS_DEVICE_H__ + +#define DUFF_1() \ + case 1:\ + SET_PIXEL( D[0], S[0] ); + +#define DUFF_2() \ + case 3:\ + SET_PIXEL( D[2], S[2] );\ + case 2:\ + SET_PIXEL( D[1], S[1] );\ + DUFF_1() + +#define DUFF_3() \ + case 7:\ + SET_PIXEL( D[6], S[6] );\ + case 6:\ + SET_PIXEL( D[5], S[5] );\ + case 5:\ + SET_PIXEL( D[4], S[4] );\ + case 4:\ + SET_PIXEL( D[3], S[3] );\ + DUFF_2() + +#define DUFF_4() \ + case 15:\ + SET_PIXEL( D[14], S[14] );\ + case 14:\ + SET_PIXEL( D[13], S[13] );\ + case 13:\ + SET_PIXEL( D[12], S[12] );\ + case 12:\ + SET_PIXEL( D[11], S[11] );\ + case 11:\ + SET_PIXEL( D[10], S[10] );\ + case 10:\ + SET_PIXEL( D[9], S[9] );\ + case 9:\ + SET_PIXEL( D[8], S[8] );\ + case 8:\ + SET_PIXEL( D[7], S[7] );\ + DUFF_3() + +#define SET_PIXEL_DUFFS_DEVICE_N( D, S, w, n ) \ +do {\ + while (w) {\ + register int l = w & ((1 << n) - 1);\ + switch (l) {\ + default:\ + l = (1 << n);\ + SET_PIXEL( D[(1 << n)-1], S[(1 << n)-1] );\ + DUFF_##n()\ + }\ + D += l;\ + S += l;\ + w -= l;\ + }\ +} while(0) + +#endif diff --git a/Source/DirectFB/src/gfx/generic/generic.c b/Source/DirectFB/src/gfx/generic/generic.c new file mode 100755 index 0000000..9b7cdeb --- /dev/null +++ b/Source/DirectFB/src/gfx/generic/generic.c @@ -0,0 +1,9161 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "generic.h" +#include "duffs_device.h" + + +/* lookup tables for 2/3bit to 8bit color conversion */ +static const u8 lookup3to8[] = { 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff}; +static const u8 lookup2to8[] = { 0x00, 0x55, 0xaa, 0xff}; + +#define EXPAND_1to8(v) ((v) ? 0xff : 0x00) +#define EXPAND_2to8(v) (lookup2to8[v]) +#define EXPAND_3to8(v) (lookup3to8[v]) +#define EXPAND_4to8(v) (((v) << 4) | ((v) )) +#define EXPAND_5to8(v) (((v) << 3) | ((v) >> 2)) +#define EXPAND_6to8(v) (((v) << 2) | ((v) >> 4)) +#define EXPAND_7to8(v) (((v) << 1) | ((v) >> 6)) + + +static int use_mmx = 0; + +#ifdef USE_MMX +static void gInit_MMX( void ); +#endif + +#if SIZEOF_LONG == 8 +static void gInit_64bit( void ); +#endif + +/* RGB16 */ +#define RGB_MASK 0xffff +#define Cop_OP_Aop_PFI( op ) Cop_##op##_Aop_16 +#define Bop_PFI_OP_Aop_PFI( op ) Bop_16_##op##_Aop +#include "template_colorkey_16.h" + +/* ARGB1555 / RGB555 / BGR555 */ +#define RGB_MASK 0x7fff +#define Cop_OP_Aop_PFI( op ) Cop_##op##_Aop_15 +#define Bop_PFI_OP_Aop_PFI( op ) Bop_15_##op##_Aop +#include "template_colorkey_16.h" + +/* ARGB2554 */ +#define RGB_MASK 0x3fff +#define Cop_OP_Aop_PFI( op ) Cop_##op##_Aop_14 +#define Bop_PFI_OP_Aop_PFI( op ) Bop_14_##op##_Aop +#include "template_colorkey_16.h" + +/* ARGB4444 / RGB444*/ +#define RGB_MASK 0x0fff +#define Cop_OP_Aop_PFI( op ) Cop_##op##_Aop_12 +#define Bop_PFI_OP_Aop_PFI( op ) Bop_12_##op##_Aop +#include "template_colorkey_16.h" + +/* RGBA4444 */ +#define RGB_MASK 0xfff0 +#define Cop_OP_Aop_PFI( op ) Cop_##op##_Aop_12vv +#define Bop_PFI_OP_Aop_PFI( op ) Bop_12vv_##op##_Aop +#include "template_colorkey_16.h" + +/* ARGB/RGB32/AiRGB */ +#define RGB_MASK 0x00ffffff +#define Cop_OP_Aop_PFI( op ) Cop_##op##_Aop_32 +#define Bop_PFI_OP_Aop_PFI( op ) Bop_32_##op##_Aop +#include "template_colorkey_32.h" + +/* RGB16 */ +#define EXPAND_Ato8( a ) 0xFF +#define EXPAND_Rto8( r ) EXPAND_5to8( r ) +#define EXPAND_Gto8( g ) EXPAND_6to8( g ) +#define EXPAND_Bto8( b ) EXPAND_5to8( b ) +#define PIXEL_OUT( a, r, g, b ) PIXEL_RGB16( r, g, b ) +#define Sop_PFI_OP_Dacc( op ) Sop_rgb16_##op##_Dacc +#define Sacc_OP_Aop_PFI( op ) Sacc_##op##_Aop_rgb16 +#define A_SHIFT 0 +#define R_SHIFT 11 +#define G_SHIFT 5 +#define B_SHIFT 0 +#define A_MASK 0 +#define R_MASK 0xf800 +#define G_MASK 0x07e0 +#define B_MASK 0x001f +#include "template_acc_16.h" + +/* ARGB1555 */ +#define EXPAND_Ato8( a ) EXPAND_1to8( a ) +#define EXPAND_Rto8( r ) EXPAND_5to8( r ) +#define EXPAND_Gto8( g ) EXPAND_5to8( g ) +#define EXPAND_Bto8( b ) EXPAND_5to8( b ) +#define PIXEL_OUT( a, r, g, b ) PIXEL_ARGB1555( a, r, g, b ) +#define Sop_PFI_OP_Dacc( op ) Sop_argb1555_##op##_Dacc +#define Sacc_OP_Aop_PFI( op ) Sacc_##op##_Aop_argb1555 +#define A_SHIFT 15 +#define R_SHIFT 10 +#define G_SHIFT 5 +#define B_SHIFT 0 +#define A_MASK 0x8000 +#define R_MASK 0x7c00 +#define G_MASK 0x03e0 +#define B_MASK 0x001f +#include "template_acc_16.h" + +/* RGB555 */ +#define EXPAND_Ato8( a ) 0xFF +#define EXPAND_Rto8( r ) EXPAND_5to8( r ) +#define EXPAND_Gto8( g ) EXPAND_5to8( g ) +#define EXPAND_Bto8( b ) EXPAND_5to8( b ) +#define PIXEL_OUT( a, r, g, b ) PIXEL_RGB555( r, g, b ) +#define Sop_PFI_OP_Dacc( op ) Sop_xrgb1555_##op##_Dacc +#define Sacc_OP_Aop_PFI( op ) Sacc_##op##_Aop_xrgb1555 +#define A_SHIFT 0 +#define R_SHIFT 10 +#define G_SHIFT 5 +#define B_SHIFT 0 +#define A_MASK 0 +#define R_MASK 0x7c00 +#define G_MASK 0x03e0 +#define B_MASK 0x001f +#include "template_acc_16.h" + +/* BGR555 */ +#define EXPAND_Ato8( a ) 0xFF +#define EXPAND_Rto8( r ) EXPAND_5to8( r ) +#define EXPAND_Gto8( g ) EXPAND_5to8( g ) +#define EXPAND_Bto8( b ) EXPAND_5to8( b ) +#define PIXEL_OUT( a, r, g, b ) PIXEL_BGR555( r, g, b ) +#define Sop_PFI_OP_Dacc( op ) Sop_xbgr1555_##op##_Dacc +#define Sacc_OP_Aop_PFI( op ) Sacc_##op##_Aop_xbgr1555 +#define A_SHIFT 0 +#define B_SHIFT 10 +#define G_SHIFT 5 +#define R_SHIFT 0 +#define A_MASK 0 +#define B_MASK 0x7c00 +#define G_MASK 0x03e0 +#define R_MASK 0x001f +#include "template_acc_16.h" + +/* ARGB2554 */ +#define EXPAND_Ato8( a ) EXPAND_2to8( a ) +#define EXPAND_Rto8( r ) EXPAND_5to8( r ) +#define EXPAND_Gto8( g ) EXPAND_5to8( g ) +#define EXPAND_Bto8( b ) EXPAND_4to8( b ) +#define PIXEL_OUT( a, r, g, b ) PIXEL_ARGB2554( a, r, g, b ) +#define Sop_PFI_OP_Dacc( op ) Sop_argb2554_##op##_Dacc +#define Sacc_OP_Aop_PFI( op ) Sacc_##op##_Aop_argb2554 +#define A_SHIFT 14 +#define R_SHIFT 9 +#define G_SHIFT 4 +#define B_SHIFT 0 +#define A_MASK 0xc000 +#define R_MASK 0x3e00 +#define G_MASK 0x01f0 +#define B_MASK 0x000f +#include "template_acc_16.h" + +/* ARGB4444 */ +#define EXPAND_Ato8( a ) EXPAND_4to8( a ) +#define EXPAND_Rto8( r ) EXPAND_4to8( r ) +#define EXPAND_Gto8( g ) EXPAND_4to8( g ) +#define EXPAND_Bto8( b ) EXPAND_4to8( b ) +#define PIXEL_OUT( a, r, g, b ) PIXEL_ARGB4444( a, r, g, b ) +#define Sop_PFI_OP_Dacc( op ) Sop_argb4444_##op##_Dacc +#define Sacc_OP_Aop_PFI( op ) Sacc_##op##_Aop_argb4444 +#define A_SHIFT 12 +#define R_SHIFT 8 +#define G_SHIFT 4 +#define B_SHIFT 0 +#define A_MASK 0xf000 +#define R_MASK 0x0f00 +#define G_MASK 0x00f0 +#define B_MASK 0x000f +#include "template_acc_16.h" + +/* ARGB4444 */ +#define EXPAND_Ato8( a ) EXPAND_4to8( a ) +#define EXPAND_Rto8( r ) EXPAND_4to8( r ) +#define EXPAND_Gto8( g ) EXPAND_4to8( g ) +#define EXPAND_Bto8( b ) EXPAND_4to8( b ) +#define PIXEL_OUT( a, r, g, b ) PIXEL_RGBA4444( a, r, g, b ) +#define Sop_PFI_OP_Dacc( op ) Sop_rgba4444_##op##_Dacc +#define Sacc_OP_Aop_PFI( op ) Sacc_##op##_Aop_rgba4444 +#define A_SHIFT 0 +#define R_SHIFT 12 +#define G_SHIFT 8 +#define B_SHIFT 4 +#define A_MASK 0x000f +#define R_MASK 0xf000 +#define G_MASK 0x0f00 +#define B_MASK 0x00f0 +#include "template_acc_16.h" + +/* RGB444 */ +#define EXPAND_Ato8( a ) 0xFF +#define EXPAND_Rto8( r ) EXPAND_4to8( r ) +#define EXPAND_Gto8( g ) EXPAND_4to8( g ) +#define EXPAND_Bto8( b ) EXPAND_4to8( b ) +#define PIXEL_OUT( a, r, g, b ) PIXEL_RGB444( r, g, b ) +#define Sop_PFI_OP_Dacc( op ) Sop_xrgb4444_##op##_Dacc +#define Sacc_OP_Aop_PFI( op ) Sacc_##op##_Aop_xrgb4444 +#define A_SHIFT 0 +#define R_SHIFT 8 +#define G_SHIFT 4 +#define B_SHIFT 0 +#define A_MASK 0 +#define R_MASK 0x0f00 +#define G_MASK 0x00f0 +#define B_MASK 0x000f +#include "template_acc_16.h" + +/* ARGB */ +#define EXPAND_Ato8( a ) (a) +#define EXPAND_Rto8( r ) (r) +#define EXPAND_Gto8( g ) (g) +#define EXPAND_Bto8( b ) (b) +#define PIXEL_OUT( a, r, g, b ) PIXEL_ARGB( a, r, g, b ) +#define Sop_PFI_OP_Dacc( op ) Sop_argb_##op##_Dacc +#define Sacc_OP_Aop_PFI( op ) Sacc_##op##_Aop_argb +#define A_SHIFT 24 +#define R_SHIFT 16 +#define G_SHIFT 8 +#define B_SHIFT 0 +#define A_MASK 0xff000000 +#define R_MASK 0x00ff0000 +#define G_MASK 0x0000ff00 +#define B_MASK 0x000000ff +#include "template_acc_32.h" + +/* RGB32 */ +#define EXPAND_Ato8( a ) 0xFF +#define EXPAND_Rto8( r ) (r) +#define EXPAND_Gto8( g ) (g) +#define EXPAND_Bto8( b ) (b) +#define PIXEL_OUT( a, r, g, b ) PIXEL_RGB32( r, g, b ) +#define Sop_PFI_OP_Dacc( op ) Sop_rgb32_##op##_Dacc +#define Sacc_OP_Aop_PFI( op ) Sacc_##op##_Aop_rgb32 +#define A_SHIFT 0 +#define R_SHIFT 16 +#define G_SHIFT 8 +#define B_SHIFT 0 +#define A_MASK 0 +#define R_MASK 0x00ff0000 +#define G_MASK 0x0000ff00 +#define B_MASK 0x000000ff +#include "template_acc_32.h" + +/* AiRGB */ +#define EXPAND_Ato8( a ) ((a) ^ 0xff) +#define EXPAND_Rto8( r ) (r) +#define EXPAND_Gto8( g ) (g) +#define EXPAND_Bto8( b ) (b) +#define PIXEL_OUT( a, r, g, b ) PIXEL_AiRGB( a, r, g, b ) +#define Sop_PFI_OP_Dacc( op ) Sop_airgb_##op##_Dacc +#define Sacc_OP_Aop_PFI( op ) Sacc_##op##_Aop_airgb +#define A_SHIFT 24 +#define R_SHIFT 16 +#define G_SHIFT 8 +#define B_SHIFT 0 +#define A_MASK 0xff000000 +#define R_MASK 0x00ff0000 +#define G_MASK 0x0000ff00 +#define B_MASK 0x000000ff +#include "template_acc_32.h" + +/********************************* Cop_to_Aop_PFI *****************************/ + +static void Cop_to_Aop_8( GenefxState *gfxs ) +{ + memset( gfxs->Aop[0], gfxs->Cop, gfxs->length ); +} + +static void Cop_to_Aop_16( GenefxState *gfxs ) +{ + int w; + int l = gfxs->length; + u32 *D = gfxs->Aop[0]; + u32 Cop = gfxs->Cop; + + u32 DCop = ((Cop << 16) | Cop); + + if (((long)D)&2) { /* align */ + u16* tmp = (u16*) D; + --l; + *tmp = Cop; + D = (u32*)(tmp+1); + } + + w = (l >> 1); + while (w) { + *D = DCop; + --w; + ++D; + } + + if (l & 1) /* do the last ential pixel */ + *((u16*)D) = (u16)Cop; +} + +static void Cop_to_Aop_18( GenefxState *gfxs ) +{ + int w = gfxs->length; + u8 *D = gfxs->Aop[0]; + u32 Cop = gfxs->Cop; + + while (w) { + D[0] = Cop; + D[1] = Cop >> 8; + D[2] = Cop >> 16; + D += 3; + --w; + } +} + +static void Cop_to_Aop_24( GenefxState *gfxs ) +{ + int w = gfxs->length; + u8 *D = gfxs->Aop[0]; + + while (w) { + D[0] = gfxs->color.b; + D[1] = gfxs->color.g; + D[2] = gfxs->color.r; + + D += 3; + --w; + } +} + +static void Cop_to_Aop_32( GenefxState *gfxs ) +{ + int w = gfxs->length; + u32 *D = gfxs->Aop[0]; + u32 Cop = gfxs->Cop; + + while (w--) + *D++ = Cop; +} + +static void Cop_to_Aop_yuv422( GenefxState *gfxs ) +{ + int l; + int w = gfxs->length; + u16 *D = gfxs->Aop[0]; + u32 Cop = gfxs->Cop; + + if ((long)D & 2) { +#ifdef WORDS_BIGENDIAN + *D++ = Cop & 0xffff; +#else + *D++ = Cop >> 16; +#endif + w--; + } + + for (l = w>>1; l--;) { + *((u32*)D) = Cop; + D += 2; + } + + if (w & 1) { +#ifdef WORDS_BIGENDIAN + *D = Cop >> 16; +#else + *D = Cop & 0xffff; +#endif + } +} + +static void Cop_to_Aop_i420( GenefxState *gfxs ) +{ + memset( gfxs->Aop[0], gfxs->YCop, gfxs->length ); + if (gfxs->AopY & 1) { + memset( gfxs->Aop[1], gfxs->CbCop, gfxs->length>>1 ); + memset( gfxs->Aop[2], gfxs->CrCop, gfxs->length>>1 ); + } +} + +static void Cop_to_Aop_nv12( GenefxState *gfxs ) +{ + memset( gfxs->Aop[0], gfxs->YCop, gfxs->length ); + + if (gfxs->dst_format == DSPF_NV16 || gfxs->AopY & 1) { + u16 *D = gfxs->Aop[1]; + int w = gfxs->length>>1; + u16 Cop = gfxs->CbCop | (gfxs->CrCop << 8); + + while (w--) + *D++ = Cop; + } +} + +static void Cop_to_Aop_nv21( GenefxState *gfxs ) +{ + memset( gfxs->Aop[0], gfxs->YCop, gfxs->length ); + + if (gfxs->AopY & 1) { + u16 *D = gfxs->Aop[1]; + int w = gfxs->length>>1; + u16 Cop = gfxs->CrCop | (gfxs->CbCop << 8); + + while (w--) + *D++ = Cop; + } +} + +static GenefxFunc Cop_to_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + Cop_to_Aop_16, /* DSPF_ARGB1555 */ + Cop_to_Aop_16, /* DSPF_RGB16 */ + Cop_to_Aop_24, /* DSPF_RGB24 */ + Cop_to_Aop_32, /* DSPF_RGB32 */ + Cop_to_Aop_32, /* DSPF_ARGB */ + Cop_to_Aop_8, /* DSPF_A8 */ + Cop_to_Aop_yuv422, /* DSPF_YUY2 */ + Cop_to_Aop_8, /* DSPF_RGB332 */ + Cop_to_Aop_yuv422, /* DSPF_UYVY */ + Cop_to_Aop_i420, /* DSPF_I420 */ + Cop_to_Aop_i420, /* DSPF_YV12 */ + Cop_to_Aop_8, /* DSPF_LUT8 */ + Cop_to_Aop_8, /* DSPF_ALUT44 */ + Cop_to_Aop_32, /* DSPF_AiRGB */ + NULL, /* DSPF_A1 */ + Cop_to_Aop_nv12, /* DSPF_NV12 */ + Cop_to_Aop_nv12, /* DSPF_NV16 */ + Cop_to_Aop_16, /* DSPF_ARGB2554 */ + Cop_to_Aop_16, /* DSPF_ARGB4444 */ + Cop_to_Aop_16, /* DSPF_RGBA4444 */ + Cop_to_Aop_nv21, /* DSPF_NV21 */ + Cop_to_Aop_32, /* DSPF_AYUV */ + NULL, /* DSPF_A4 */ + Cop_to_Aop_18, /* DSPF_ARGB1666 */ + Cop_to_Aop_18, /* DSPF_ARGB6666 */ + Cop_to_Aop_18, /* DSPF_RGB18 */ + NULL, /* DSPF_LUT2 */ + Cop_to_Aop_16, /* DSPF_RGB444 */ + Cop_to_Aop_16, /* DSPF_RGB555 */ + Cop_to_Aop_16 /* DSPF_BGR555 */ +}; + +/********************************* Cop_toK_Aop_PFI ****************************/ + +static void Cop_toK_Aop_8( GenefxState *gfxs ) +{ + int w = gfxs->length; + u8 *D = gfxs->Aop[0]; + u32 Cop = gfxs->Cop; + u32 Dkey = gfxs->Dkey; + + while (w--) { + if (Dkey == *D) + *D = Cop; + + D++; + } +} + +static void Cop_toK_Aop_18( GenefxState *gfxs ) +{ + int w = gfxs->length; + u8 *D = gfxs->Aop[0]; + u32 Dkey = gfxs->Dkey; + u32 Cop = gfxs->Cop; + + while (w) { + if (Dkey == ((u32)(D[2]<<16 | D[1]<<8 | D[0]) & 0x3FFFF)) { + D[0] = Cop; + D[1] = Cop >> 8; + D[2] = Cop >> 16; + } + D += 3; + --w; + } + +} + +static void Cop_toK_Aop_24( GenefxState *gfxs ) +{ + int w = gfxs->length; + u8 *D = gfxs->Aop[0]; + u8 Dkr = (gfxs->Dkey & 0xff0000) >> 16; + u8 Dkg = (gfxs->Dkey & 0x00ff00) >> 8; + u8 Dkb = (gfxs->Dkey & 0x0000ff); + + while (w--) { + if (D[0] == Dkb && D[1] == Dkg && D[2] == Dkr) { + D[0] = gfxs->color.b; + D[1] = gfxs->color.g; + D[2] = gfxs->color.r; + } + + D += 3; + } +} + +static void Cop_toK_Aop_yuv422( GenefxState *gfxs ) +{ + int l; + int w = gfxs->length; + u16 *D = gfxs->Aop[0]; + u32 Cop = gfxs->Cop; + u32 Dkey = gfxs->Dkey; + + if ((long)D & 2) { +#ifdef WORDS_BIGENDIAN + if (*D == (Dkey & 0xffff)) + *D = Cop & 0xffff; +#else + if (*D == (Dkey >> 16)) + *D = Cop >> 16; +#endif + D++; + w--; + } + + for (l = w>>1; l--;) { + if (*((u32*)D) == Dkey) + *((u32*)D) = Cop; + D += 2; + } + + if (w & 1) { +#ifdef WORDS_BIGENDIAN + if (*D == (Dkey >> 16)) + *D = Cop >> 16; +#else + if (*D == (Dkey & 0xffff)) + *D = Cop & 0xffff; +#endif + } +} + +static void Cop_toK_Aop_alut44( GenefxState *gfxs ) +{ + int w = gfxs->length; + u8 *D = gfxs->Aop[0]; + u32 Cop = gfxs->Cop; + u32 Dkey = gfxs->Dkey; + + while (w--) { + if (Dkey == (*D & 0x0F)) + *D = Cop; + + D++; + } +} + +static GenefxFunc Cop_toK_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + Cop_toK_Aop_15, /* DSPF_ARGB1555 */ + Cop_toK_Aop_16, /* DSPF_RGB16 */ + Cop_toK_Aop_24, /* DSPF_RGB24 */ + Cop_toK_Aop_32, /* DSPF_RGB32 */ + Cop_toK_Aop_32, /* DSPF_ARGB */ + Cop_toK_Aop_8, /* DSPF_A8 */ + Cop_toK_Aop_yuv422, /* DSPF_YUY2 */ + Cop_toK_Aop_8, /* DSPF_RGB332 */ + Cop_toK_Aop_yuv422, /* DSPF_UYVY */ + NULL, /* DSPF_I420 */ + NULL, /* DSPF_YV12 */ + Cop_toK_Aop_8, /* DSPF_LUT8 */ + Cop_toK_Aop_alut44, /* DSPF_ALUT44 */ + Cop_toK_Aop_32, /* DSPF_AiRGB */ + NULL, /* DSPF_A1 */ + NULL, /* DSPF_NV12 */ + NULL, /* DSPF_NV16 */ + Cop_toK_Aop_14, /* DSPF_ARGB2554 */ + Cop_toK_Aop_12, /* DSPF_ARGB4444 */ + Cop_toK_Aop_12vv, /* DSPF_RGBA4444 */ + NULL, /* DSPF_NV21 */ + Cop_toK_Aop_32, /* DSPF_AYUV */ + NULL, /* DSPF_A4 */ + Cop_toK_Aop_18, /* DSPF_ARGB1666 */ + Cop_toK_Aop_18, /* DSPF_ARGB6666 */ + Cop_toK_Aop_18, /* DSPF_RGB18 */ + NULL, /* DSPF_LUT2 */ + Cop_toK_Aop_12, /* DSPF_RGB444 */ + Cop_toK_Aop_15, /* DSPF_RGB555 */ + Cop_toK_Aop_15 /* DSPF_BGR555 */ +}; + +/********************************* Bop_PFI_to_Aop_PFI *************************/ + +static void Bop_4_to_Aop( GenefxState *gfxs ) +{ + direct_memmove( gfxs->Aop[0], gfxs->Bop[0], gfxs->length>>1 ); +} + +static void Bop_8_to_Aop( GenefxState *gfxs ) +{ + direct_memmove( gfxs->Aop[0], gfxs->Bop[0], gfxs->length ); +} + +static void Bop_16_to_Aop( GenefxState *gfxs ) +{ + direct_memmove( gfxs->Aop[0], gfxs->Bop[0], gfxs->length*2 ); +} + +static void Bop_24_to_Aop( GenefxState *gfxs ) +{ + direct_memmove( gfxs->Aop[0], gfxs->Bop[0], gfxs->length*3 ); +} + +static void Bop_32_to_Aop( GenefxState *gfxs ) +{ + direct_memmove( gfxs->Aop[0], gfxs->Bop[0], gfxs->length*4 ); +} + +static void Bop_i420_to_Aop( GenefxState *gfxs ) +{ + direct_memmove( gfxs->Aop[0], gfxs->Bop[0], gfxs->length ); + if (gfxs->AopY & 1) { + direct_memmove( gfxs->Aop[1], gfxs->Bop[1], gfxs->length>>1 ); + direct_memmove( gfxs->Aop[2], gfxs->Bop[2], gfxs->length>>1 ); + } +} + +static void Bop_NV_to_Aop( GenefxState *gfxs ) +{ + direct_memmove( gfxs->Aop[0], gfxs->Bop[0], gfxs->length ); + if (gfxs->dst_format == DSPF_NV16 || gfxs->AopY & 1) + direct_memmove( gfxs->Aop[1], gfxs->Bop[1], gfxs->length&~1 ); +} + +static GenefxFunc Bop_PFI_to_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + Bop_16_to_Aop, /* DSPF_ARGB1555 */ + Bop_16_to_Aop, /* DSPF_RGB16 */ + Bop_24_to_Aop, /* DSPF_RGB24 */ + Bop_32_to_Aop, /* DSPF_RGB32 */ + Bop_32_to_Aop, /* DSPF_ARGB */ + Bop_8_to_Aop, /* DSPF_A8 */ + Bop_16_to_Aop, /* DSPF_YUY2 */ + Bop_8_to_Aop, /* DSPF_RGB332 */ + Bop_16_to_Aop, /* DSPF_UYVY */ + Bop_i420_to_Aop, /* DSPF_I420 */ + Bop_i420_to_Aop, /* DSPF_YV12 */ + Bop_8_to_Aop, /* DSPF_LUT8 */ + Bop_8_to_Aop, /* DSPF_ALUT44 */ + Bop_32_to_Aop, /* DSPF_AiRGB */ + NULL, /* DSPF_A1 */ + Bop_NV_to_Aop, /* DSPF_NV12 */ + Bop_NV_to_Aop, /* DSPF_NV16 */ + Bop_16_to_Aop, /* DSPF_ARGB2554 */ + Bop_16_to_Aop, /* DSPF_ARGB4444 */ + Bop_16_to_Aop, /* DSPF_RGBA4444 */ + Bop_NV_to_Aop, /* DSPF_NV21 */ + Bop_32_to_Aop, /* DSPF_AYUV */ + Bop_4_to_Aop, /* DSPF_A4 */ + Bop_24_to_Aop, /* DSPF_ARGB1666 */ + Bop_24_to_Aop, /* DSPF_ARGB6666 */ + Bop_24_to_Aop, /* DSPF_RGB18 */ + NULL, /* DSPF_LUT2 */ + Bop_16_to_Aop, /* DSPF_RGB444 */ + Bop_16_to_Aop, /* DSPF_RGB555 */ + Bop_16_to_Aop /* DSPF_BGR555 */ +}; + +/********************************* Bop_PFI_toR_Aop_PFI *************************/ + +static void Bop_4_toR_Aop( GenefxState *gfxs ) +{ + int w = gfxs->length>>1; + int Dstep = gfxs->Astep; + u8 * S = gfxs->Bop[0]; + u8 * D = gfxs->Aop[0]; + while(w--) + { + *D = *S; + D += Dstep; + S++; + } +} + +static void Bop_8_toR_Aop( GenefxState *gfxs ) +{ + int w = gfxs->length; + int Dstep = gfxs->Astep; + u8 * S = gfxs->Bop[0]; + u8 * D = gfxs->Aop[0]; + while(w--) + { + *D = *S; + D += Dstep; + S++; + } +} + +static void Bop_16_toR_Aop( GenefxState *gfxs ) +{ + int w = gfxs->length; + int Dstep = gfxs->Astep; + u16 * S = gfxs->Bop[0]; + u16 * D = gfxs->Aop[0]; + while(w--) + { + *D = *S; + D += Dstep; + S++; + } +} + +static void Bop_24_toR_Aop( GenefxState *gfxs ) +{ + int w = gfxs->length; + int Dstep = gfxs->Astep; + u8 * S = gfxs->Bop[0]; + u8 * D = gfxs->Aop[0]; + while(w--) + { + D[0] = S[0]; + D[1] = S[1]; + D[2] = S[2]; + + D += Dstep * 3; + S += 3; + } +} + +static void Bop_32_toR_Aop( GenefxState *gfxs ) +{ + int w = gfxs->length; + int Dstep = gfxs->Astep; + u32 * S = gfxs->Bop[0]; + u32 * D = gfxs->Aop[0]; + while(w--) + { + *D = *S; + D += Dstep; + S++; + } +} + +static void Bop_i420_toR_Aop( GenefxState *gfxs ) +{ + Bop_8_toR_Aop( gfxs ); + if (gfxs->AopY & 1) { + int w = gfxs->length>>1; + int Dstep = gfxs->Astep>>1; + u8 * S1 = gfxs->Bop[1]; + u8 * D1 = gfxs->Aop[1]; + u8 * S2 = gfxs->Bop[2]; + u8 * D2 = gfxs->Aop[2]; + while(w--) + { + *D1 = *S1++; + *D2 = *S2++; + D1 += Dstep; + D2 += Dstep; + } + } +} + +static void Bop_NV_toR_Aop( GenefxState *gfxs ) +{ + Bop_8_toR_Aop( gfxs ); + if (gfxs->dst_format == DSPF_NV16 || gfxs->AopY & 1) { + int w = gfxs->length&~1; + int Dstep = gfxs->Astep; + u8 * S = gfxs->Bop[1]; + u8 * D = gfxs->Aop[1]; + while(w--) + { + *D = *S++; + D += Dstep; + } + } +} + +static GenefxFunc Bop_PFI_toR_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + Bop_16_toR_Aop, /* DSPF_ARGB1555 */ + Bop_16_toR_Aop, /* DSPF_RGB16 */ + Bop_24_toR_Aop, /* DSPF_RGB24 */ + Bop_32_toR_Aop, /* DSPF_RGB32 */ + Bop_32_toR_Aop, /* DSPF_ARGB */ + Bop_8_toR_Aop, /* DSPF_A8 */ + Bop_16_toR_Aop, /* DSPF_YUY2 */ + Bop_8_toR_Aop, /* DSPF_RGB332 */ + Bop_16_toR_Aop, /* DSPF_UYVY */ + Bop_i420_toR_Aop, /* DSPF_I420 */ + Bop_i420_toR_Aop, /* DSPF_YV12 */ + Bop_8_toR_Aop, /* DSPF_LUT8 */ + Bop_8_toR_Aop, /* DSPF_ALUT44 */ + Bop_32_toR_Aop, /* DSPF_AiRGB */ + NULL, /* DSPF_A1 */ + Bop_NV_toR_Aop, /* DSPF_NV12 */ + Bop_NV_toR_Aop, /* DSPF_NV16 */ + Bop_16_toR_Aop, /* DSPF_ARGB2554 */ + Bop_16_toR_Aop, /* DSPF_ARGB4444 */ + Bop_16_toR_Aop, /* DSPF_RGBA4444 */ + Bop_NV_toR_Aop, /* DSPF_NV21 */ + Bop_32_toR_Aop, /* DSPF_AYUV */ + Bop_4_toR_Aop, /* DSPF_A4 */ + Bop_24_toR_Aop, /* DSPF_ARGB1666 */ + Bop_24_toR_Aop, /* DSPF_ARGB6666 */ + Bop_24_toR_Aop, /* DSPF_RGB18 */ + NULL, /* DSPF_LUT2 */ + Bop_16_toR_Aop, /* DSPF_RGB444 */ + Bop_16_toR_Aop, /* DSPF_RGB555 */ + Bop_16_toR_Aop /* DSPF_BGR555 */ +}; + +/********************************* Bop_PFI_Kto_Aop_PFI ************************/ + +static void Bop_rgb18_Kto_Aop( GenefxState *gfxs ) +{ + + int w = gfxs->length; + u8 *D = gfxs->Aop[0]; + u8 *S = gfxs->Bop[0]; + u32 Skey = gfxs->Skey; + int Ostep = gfxs->Ostep; + + if (Ostep < 0) { + D += (gfxs->length - 1) * 3; + S += (gfxs->length - 1) * 3; + } + + while (w--) { + u8 s0 = S[0]; + u8 s1 = S[1]; + u8 s2 = S[2]; + + if (Skey != ((u32)(s2<<16 | s1<<8 | s0) & 0x3FFFF)) { + D[0] = s0; + D[1] = s1; + D[2] = s2; + } + + S += Ostep * 3; + D += Ostep * 3; + } +} + +static void Bop_rgb24_Kto_Aop( GenefxState *gfxs ) +{ + int w = gfxs->length; + u8 *D = gfxs->Aop[0]; + u8 *S = gfxs->Bop[0]; + u32 Skey = gfxs->Skey; + int Ostep = gfxs->Ostep; + + if (Ostep < 0) { + D += (gfxs->length - 1) * 3; + S += (gfxs->length - 1) * 3; + } + + while (w--) { + u8 b = *S; + u8 g = *(S+1); + u8 r = *(S+2); + + if (Skey != (u32)(r<<16 | g<<8 | b)) { + *D = b; + *(D+1) = g; + *(D+2) = r; + } + + S += Ostep * 3; + D += Ostep * 3; + } +} + +static void Bop_a8_Kto_Aop( GenefxState *gfxs ) +{ + /* no color to key */ + direct_memmove( gfxs->Aop[0], gfxs->Bop[0], gfxs->length ); +} + +static void Bop_yuv422_Kto_Aop( GenefxState *gfxs ) +{ + int l; + int w = gfxs->length; + u16 *D = gfxs->Aop[0]; + u16 *S = gfxs->Bop[0]; + u32 Skey = gfxs->Skey; + int Ostep = gfxs->Ostep; + + if (Ostep < 0) { + D += gfxs->length - 1; + S += gfxs->length - 1; + } + + if ((long)D & 2) { + u16 s = *S; +#ifdef WORDS_BIGENDIAN + if (s != (Skey >> 16)) + *D = s; +#else + if (s != (Skey & 0xffff)) + *D = s; +#endif + S += Ostep; + D += Ostep; + w--; + } + + if (Ostep < 0) { + S--; + D--; + } + + for (l = w>>1; l--;) { + u32 s = *((u32*)S); + + if (s != Skey) + *((u32*)D) = s; + + S += Ostep << 1; + D += Ostep << 1; + } + + if (w & 1) { + u16 s = *S; +#ifdef WORDS_BIGENDIAN + if (s != (Skey & 0xffff)) + *D = s; +#else + if (s != (Skey >> 16)) + *D = s; +#endif + } +} + + +/* change the last value to adjust the size of the device (1-4) */ +#define SET_PIXEL_DUFFS_DEVICE( D, S, w ) \ + SET_PIXEL_DUFFS_DEVICE_N( D, S, w, 4 ) + +#define SET_PIXEL( D, S ) \ + do { \ + register u32 s = S; \ + \ + if (s != Skey) \ + D = s; \ + } while (0) + +static void Bop_8_Kto_Aop( GenefxState *gfxs ) +{ + int i; + int w = gfxs->length; + u8 *D = gfxs->Aop[0]; + u8 *S = gfxs->Bop[0]; + u32 Skey = gfxs->Skey; + + if (gfxs->Ostep > 0) { + SET_PIXEL_DUFFS_DEVICE( D, S, w ); + } + else { + for (i=w-1; i>=0; i--) + if (S[i] != Skey) + D[i] = S[i]; + } +} + +#undef SET_PIXEL_DUFFS_DEVICE +#undef SET_PIXEL + +static void Bop_alut44_Kto_Aop( GenefxState *gfxs ) +{ + int w = gfxs->length; + u8 *D = gfxs->Aop[0]; + u8 *S = gfxs->Bop[0]; + u32 Skey = gfxs->Skey; + int Ostep = gfxs->Ostep; + + if (Ostep < 0) { + D += gfxs->length - 1; + S += gfxs->length - 1; + } + + while (w--) { + u8 spixel = *S; + + if ((spixel & 0x0F) != Skey) + *D = spixel; + + S += Ostep; + D += Ostep; + } +} + +static GenefxFunc Bop_PFI_Kto_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + Bop_15_Kto_Aop, /* DSPF_ARGB1555 */ + Bop_16_Kto_Aop, /* DSPF_RGB16 */ + Bop_rgb24_Kto_Aop, /* DSPF_RGB24 */ + Bop_32_Kto_Aop, /* DSPF_RGB32 */ + Bop_32_Kto_Aop, /* DSPF_ARGB */ + Bop_a8_Kto_Aop, /* DSPF_A8 */ + Bop_yuv422_Kto_Aop, /* DSPF_YUY2 */ + Bop_8_Kto_Aop, /* DSPF_RGB332 */ + Bop_yuv422_Kto_Aop, /* DSPF_UYVY */ + NULL, /* DSPF_I420 */ + NULL, /* DSPF_YV12 */ + Bop_8_Kto_Aop, /* DSPF_LUT8 */ + Bop_alut44_Kto_Aop, /* DSPF_ALUT44 */ + Bop_32_Kto_Aop, /* DSPF_AiRGB */ + NULL, /* DSPF_A1 */ + NULL, /* DSPF_NV12 */ + NULL, /* DSPF_NV16 */ + Bop_14_Kto_Aop, /* DSPF_ARGB2554 */ + Bop_12_Kto_Aop, /* DSPF_ARGB4444 */ + Bop_12vv_Kto_Aop, /* DSPF_RGBA4444 */ + NULL, /* DSPF_NV21 */ + Bop_32_Kto_Aop, /* DSPF_AYUV */ + NULL, /* DSPF_A4 */ + Bop_rgb18_Kto_Aop, /* DSPF_ARGB1666 */ + Bop_rgb18_Kto_Aop, /* DSPF_ARGB6666 */ + Bop_rgb18_Kto_Aop, /* DSPF_RGB18 */ + NULL, /* DSPF_LUT2 */ + Bop_12_Kto_Aop, /* DSPF_RGB444 */ + Bop_15_Kto_Aop, /* DSPF_RGB555 */ + Bop_15_Kto_Aop /* DSPF_BGR555 */ +}; + +/********************************* Bop_PFI_toK_Aop_PFI ************************/ + +static void Bop_rgb18_toK_Aop( GenefxState *gfxs ) +{ + int w = gfxs->length; + u8 *D = gfxs->Aop[0]; + u8 *S = gfxs->Bop[0]; + u32 Dkey = gfxs->Dkey; + + while (w--) { + if (Dkey == ((u32)(D[2]<<16 | D[1]<<8 | D[0]) & 0x3FFFF)) { + D[0] = S[0]; + D[1] = S[1]; + D[2] = S[2]; + } + S += 3; + D += 3; + } +} + +static void Bop_rgb24_toK_Aop( GenefxState *gfxs ) +{ + int w = gfxs->length; + u8 *S = gfxs->Bop[0]; + u8 *D = gfxs->Aop[0]; + u8 Dkr = (gfxs->Dkey & 0xff0000) >> 16; + u8 Dkg = (gfxs->Dkey & 0x00ff00) >> 8; + u8 Dkb = (gfxs->Dkey & 0x0000ff); + + while (w--) { + if (D[0] == Dkb && D[1] == Dkg && D[2] == Dkr) { + D[0] = S[0]; + D[1] = S[1]; + D[2] = S[2]; + } + S += 3; + D += 3; + } +} + +static void Bop_yuv422_toK_Aop( GenefxState *gfxs ) +{ + int l; + int w = gfxs->length; + u16 *S = gfxs->Bop[0]; + u16 *D = gfxs->Aop[0]; + u32 Dkey = gfxs->Dkey; + int Ostep = gfxs->Ostep; + + if (Ostep < 0) { + D += gfxs->length - 1; + S += gfxs->length - 1; + } + + if ((long)D & 2) { +#ifdef WORDS_BIGENDIAN + if (*D == (Dkey & 0xffff)) + *D = *S; +#else + if (*D == (Dkey >> 16)) + *D = *S; +#endif + D += Ostep; + S += Ostep; + w--; + } + + if (Ostep < 0) { + S--; + D--; + } + + for (l = w>>1; l--;) { + if (*D == Dkey) + *D = *S; + D += Ostep << 1; + S += Ostep << 1; + } + + if (w & 1) { +#ifdef WORDS_BIGENDIAN + if (*D == (Dkey >> 16)) + *D = *S; +#else + if (*D == (Dkey & 0xffff)) + *D = *S; +#endif + } +} + +static void Bop_rgb332_toK_Aop( GenefxState *gfxs ) +{ + int w = gfxs->length; + u8 *S = gfxs->Bop[0]; + u8 *D = gfxs->Aop[0]; + u8 Dkey = gfxs->Dkey; + + while (w--) { + if (*D == Dkey) { + *D = *S; + } + D++; + S++; + } +} + +static GenefxFunc Bop_PFI_toK_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + Bop_15_toK_Aop, /* DSPF_ARGB1555 */ + Bop_16_toK_Aop, /* DSPF_RGB16 */ + Bop_rgb24_toK_Aop, /* DSPF_RGB24 */ + Bop_32_toK_Aop, /* DSPF_RGB32 */ + Bop_32_toK_Aop, /* DSPF_ARGB */ + NULL, /* DSPF_A8 */ + Bop_yuv422_toK_Aop, /* DSPF_YUY2 */ + Bop_rgb332_toK_Aop, /* DSPF_RGB332 */ + Bop_yuv422_toK_Aop, /* DSPF_UYVY */ + NULL, /* DSPF_I420 */ + NULL, /* DSPF_YV12 */ + NULL, /* DSPF_LUT8 */ + NULL, /* DSPF_ALUT44 */ + Bop_32_toK_Aop, /* DSPF_AiRGB */ + NULL, /* DSPF_A1 */ + NULL, /* DSPF_NV12 */ + NULL, /* DSPF_NV16 */ + Bop_14_toK_Aop, /* DSPF_ARGB2554 */ + Bop_12_toK_Aop, /* DSPF_ARGB4444 */ + Bop_12vv_toK_Aop, /* DSPF_RGBA4444 */ + NULL, /* DSPF_NV21 */ + Bop_32_toK_Aop, /* DSPF_AYUV */ + NULL, /* DSPF_A4 */ + Bop_rgb18_toK_Aop, /* DSPF_ARGB1666 */ + Bop_rgb18_toK_Aop, /* DSPF_ARGB6666 */ + Bop_rgb18_toK_Aop, /* DSPF_RGB18 */ + NULL, /* DSPF_LUT2 */ + Bop_12_toK_Aop, /* DSPF_RGB444 */ + Bop_15_toK_Aop, /* DSPF_RGB555 */ + Bop_15_toK_Aop /* DSPF_BGR555 */ +}; + +/********************************* Bop_PFI_KtoK_Aop_PFI ***********************/ + +static GenefxFunc Bop_PFI_KtoK_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + Bop_15_KtoK_Aop, /* DSPF_ARGB1555 */ + Bop_16_KtoK_Aop, /* DSPF_RGB16 */ + NULL, /* DSPF_RGB24 */ + Bop_32_KtoK_Aop, /* DSPF_RGB32 */ + Bop_32_KtoK_Aop, /* DSPF_ARGB */ + NULL, /* DSPF_A8 */ + NULL, /* DSPF_YUY2 */ + NULL, /* DSPF_RGB332 */ + NULL, /* DSPF_UYVY */ + NULL, /* DSPF_I420 */ + NULL, /* DSPF_YV12 */ + NULL, /* DSPF_LUT8 */ + NULL, /* DSPF_ALUT44 */ + Bop_32_KtoK_Aop, /* DSPF_AiRGB */ + NULL, /* DSPF_A1 */ + NULL, /* DSPF_NV12 */ + NULL, /* DSPF_NV16 */ + Bop_14_KtoK_Aop, /* DSPF_ARGB2554 */ + Bop_12_KtoK_Aop, /* DSPF_ARGB4444 */ + Bop_12vv_KtoK_Aop, /* DSPF_RGBA4444 */ + NULL, /* DSPF_NV21 */ + NULL, /* DSPF_AYUV */ + NULL, /* DSPF_A4 */ + NULL, /* DSPF_ARGB1666 */ + NULL, /* DSPF_ARGB6666 */ + NULL, /* DSPF_RGB18 */ + NULL, /* DSPF_LUT2 */ + Bop_12_KtoK_Aop, /* DSPF_RGB444 */ + Bop_15_KtoK_Aop, /* DSPF_RGB555 */ + Bop_15_KtoK_Aop /* DSPF_BGR555 */ +}; + +/********************************* Bop_PFI_Sto_Aop_PFI ************************/ + +static void Bop_16_Sto_Aop( GenefxState *gfxs ) +{ + int w2; + int w = gfxs->length; + int i = gfxs->Xphase; + u32 *D = gfxs->Aop[0]; + u16 *S = gfxs->Bop[0]; + int SperD = gfxs->SperD; + int SperD2 = SperD << 1; + + if (((long)D)&2) { + *(u16*)D = *S; + i += SperD; + w--; + D = gfxs->Aop[0] + 2; + } + + w2 = (w >> 1); + while (w2--) { +#ifdef WORDS_BIGENDIAN + *D++ = S[i>>16] << 16 | S[(i+SperD)>>16]; +#else + *D++ = (S[(i+SperD)>>16] << 16) | S[i>>16]; +#endif + i += SperD2; + } + if (w&1) { + *(u16*)D = S[i>>16]; + } +} + +static void Bop_24_Sto_Aop( GenefxState *gfxs ) +{ + int w = gfxs->length; + int i = gfxs->Xphase; + u8 *D = gfxs->Aop[0]; + u8 *S = gfxs->Bop[0]; + int SperD = gfxs->SperD; + + while (w--) { + int pixelstart = (i>>16)*3; + + *D++ = S[pixelstart+0]; + *D++ = S[pixelstart+1]; + *D++ = S[pixelstart+2]; + + i += SperD; + } +} + +static void Bop_32_Sto_Aop( GenefxState *gfxs ) +{ + int w = gfxs->length; + int i = gfxs->Xphase; + u32 *D = gfxs->Aop[0]; + u32 *S = gfxs->Bop[0]; + int SperD = gfxs->SperD; + + while (w--) { + *D++ = S[i>>16]; + + i += SperD; + } +} + +static void Bop_yuy2_Sto_Aop( GenefxState *gfxs ) +{ + int l; + int w = gfxs->length; + int i = gfxs->Xphase; + u16 *D = gfxs->Aop[0]; + u16 *S = gfxs->Bop[0]; + int SperD = gfxs->SperD; + + if ((long)D & 2) { + *D++ = *S; + i = SperD; + w--; + } + + for (l = w>>1; l--;) { + register u32 d; + + d = ((u32*)S)[i>>17] & 0xff00ff00; +#ifdef WORDS_BIGENDIAN + d |= (S[i>>16] & 0x00ff) << 16; + d |= (S[(i+SperD)>>16] & 0x00ff); +#else + d |= (S[i>>16] & 0x00ff); + d |= (S[(i+SperD)>>16] & 0x00ff) << 16; +#endif + *((u32*)D) = d; + D += 2; + + i += SperD << 1; + } + + if (w & 1) + *D = S[i>>16]; +} + +static void Bop_8_Sto_Aop( GenefxState *gfxs ) +{ + int w = gfxs->length; + int i = gfxs->Xphase; + u8 *D = gfxs->Aop[0]; + u8 *S = gfxs->Bop[0]; + int SperD = gfxs->SperD; + + while (w--) { + *D++ = S[i>>16]; + + i += SperD; + } +} + +static void Bop_uyvy_Sto_Aop( GenefxState *gfxs ) +{ + int l; + int w = gfxs->length; + int i = gfxs->Xphase; + u16 *D = gfxs->Aop[0]; + u16 *S = gfxs->Bop[0]; + int SperD = gfxs->SperD; + + if ((long)D & 2) { + *D++ = *S; + i = SperD; + w--; + } + + for (l = w>>1; l--;) { + register u32 d; + + d = ((u32*)S)[i>>17] & 0x00ff00ff; +#ifdef WORDS_BIGENDIAN + d |= (S[i>>16] & 0xff00) << 16; + d |= (S[(i+SperD)>>16] & 0xff00); +#else + d |= (S[i>>16] & 0xff00); + d |= (S[(i+SperD)>>16] & 0xff00) << 16; +#endif + *((u32*)D) = d; + D += 2; + + i += SperD << 1; + } + + if (w & 1) + *D = S[i>>16]; +} + +static void Bop_i420_Sto_Aop( GenefxState *gfxs ) +{ + int w = gfxs->length; + int i = gfxs->Xphase; + u8 *Dy = gfxs->Aop[0]; + u8 *Sy = gfxs->Bop[0]; + int SperD = gfxs->SperD; + + while (w--) { + *Dy++ = Sy[i>>16]; + + i += SperD; + } + + if (gfxs->AopY & 1) { + u8 *Du = gfxs->Aop[1]; + u8 *Dv = gfxs->Aop[2]; + u8 *Su = gfxs->Bop[1]; + u8 *Sv = gfxs->Bop[2]; + + for (w = gfxs->length>>1, i = 0; w--;) { + *Du++ = Su[i>>16]; + + i += SperD; + } + + for (w = gfxs->length>>1, i = 0; w--;) { + *Dv++ = Sv[i>>16]; + + i += SperD; + } + } +} + +static void Bop_NV_Sto_Aop( GenefxState *gfxs ) +{ + int w = gfxs->length; + int i = gfxs->Xphase; + u8 *Dy = gfxs->Aop[0]; + u8 *Sy = gfxs->Bop[0]; + int SperD = gfxs->SperD; + + while (w--) { + *Dy++ = Sy[i>>16]; + + i += SperD; + } + + if (gfxs->dst_format == DSPF_NV16 || gfxs->AopY & 1) { + u16 *Duv = gfxs->Aop[1]; + u16 *Suv = gfxs->Bop[1]; + + for (w = gfxs->length>>1, i = 0; w--;) { + *Duv++ = Suv[i>>16]; + + i += SperD; + } + } +} + +static GenefxFunc Bop_PFI_Sto_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + Bop_16_Sto_Aop, /* DSPF_ARGB1555 */ + Bop_16_Sto_Aop, /* DSPF_RGB16 */ + Bop_24_Sto_Aop, /* DSPF_RGB24 */ + Bop_32_Sto_Aop, /* DSPF_RGB32 */ + Bop_32_Sto_Aop, /* DSPF_ARGB */ + Bop_8_Sto_Aop, /* DSPF_A8 */ + Bop_yuy2_Sto_Aop, /* DSPF_YUY2 */ + Bop_8_Sto_Aop, /* DSPF_RGB332 */ + Bop_uyvy_Sto_Aop, /* DSPF_UYVY */ + Bop_i420_Sto_Aop, /* DSPF_I420 */ + Bop_i420_Sto_Aop, /* DSPF_YV12 */ + Bop_8_Sto_Aop, /* DSPF_LUT8 */ + Bop_8_Sto_Aop, /* DSPF_ALUT44 */ + Bop_32_Sto_Aop, /* DSPF_AiRGB */ + NULL, /* DSPF_A1 */ + Bop_NV_Sto_Aop, /* DSPF_NV12 */ + Bop_NV_Sto_Aop, /* DSPF_NV16 */ + Bop_16_Sto_Aop, /* DSPF_ARGB2554 */ + Bop_16_Sto_Aop, /* DSPF_ARGB4444 */ + Bop_16_Sto_Aop, /* DSPF_RGBA4444 */ + Bop_NV_Sto_Aop, /* DSPF_NV21 */ + Bop_32_Sto_Aop, /* DSPF_AYUV */ + NULL, /* DSPF_A4 */ + Bop_24_Sto_Aop, /* DSPF_ARGB1666 */ + Bop_24_Sto_Aop, /* DSPF_ARGB6666 */ + Bop_24_Sto_Aop, /* DSPF_RGB18 */ + NULL, /* DSPF_LUT2 */ + Bop_16_Sto_Aop, /* DSPF_ARGB4444 */ + Bop_16_Sto_Aop, /* DSPF_ARGB1555 */ + Bop_16_Sto_Aop /* DSPF_ARGB1555 */ +}; + +/********************************* Bop_PFI_SKto_Aop_PFI ***********************/ + +static void Bop_rgb18_SKto_Aop( GenefxState *gfxs ) +{ + int w = gfxs->length; + int i = gfxs->Xphase; + u8 *D = gfxs->Aop[0]; + u8 *S = gfxs->Bop[0]; + u32 Skey = gfxs->Skey; + int SperD = gfxs->SperD; + + while (w--) { + int pixelstart = (i>>16)*3; + + u8 s0 = S[pixelstart+0]; + u8 s1 = S[pixelstart+1]; + u8 s2 = S[pixelstart+2]; + + if (Skey != ((u32)(s2<<16 | s1<<8 | s0) & 0x3FFFF)) { + D[0] = s0; + D[1] = s1; + D[2] = s2; + } + i += SperD; + D += 3; + } +} + +static void Bop_rgb24_SKto_Aop( GenefxState *gfxs ) +{ + int w = gfxs->length; + int i = gfxs->Xphase; + u8 *D = gfxs->Aop[0]; + u8 *S = gfxs->Bop[0]; + u32 Skey = gfxs->Skey; + int SperD = gfxs->SperD; + + while (w--) { + int pixelstart = (i>>16)*3; + + u8 b = S[pixelstart+0]; + u8 g = S[pixelstart+1]; + u8 r = S[pixelstart+2]; + + if (Skey != (u32)(r<<16 | g<<8 | b)) { + *D = b; + *(D+1) = g; + *(D+2) = r; + } + + D += 3; + i += SperD; + } +} + +static void Bop_a8_SKto_Aop( GenefxState *gfxs ) +{ + int w = gfxs->length; + int i = gfxs->Xphase; + u8 *D = gfxs->Aop[0]; + u8 *S = gfxs->Bop[0]; + int SperD = gfxs->SperD; + + /* no color to key */ + while (w--) { + *D++ = S[i>>16]; + + i += SperD; + } +} + +static void Bop_yuy2_SKto_Aop( GenefxState *gfxs ) +{ + int l; + int w = gfxs->length; + int i = gfxs->Xphase; + u16 *D = gfxs->Aop[0]; + u16 *S = gfxs->Bop[0]; + u32 Skey = gfxs->Skey; +#ifdef WORDS_BIGENDIAN + u16 Skey0 = gfxs->Skey >> 16; + u16 Skey1 = gfxs->Skey & 0xffff; +#else + u16 Skey0 = gfxs->Skey & 0xffff; + u16 Skey1 = gfxs->Skey >> 16; +#endif + int SperD = gfxs->SperD; + + if ((long)D & 2) { + u16 s = *S; + if (s != Skey0) + *D = s; + D++; + i = SperD; + w--; + } + + for (l = w>>1; l--;) { + register u32 s; + + s = ((u32*)S)[i>>17] & 0xff00ff00; +#ifdef WORDS_BIGENDIAN + s |= (S[i>>16] & 0x00ff) << 16; + s |= (S[(i+SperD)>>16] & 0x00ff); +#else + s |= (S[i>>16] & 0x00ff); + s |= (S[(i+SperD)>>16] & 0x00ff) << 16; +#endif + if (s != Skey) + *((u32*)D) = s; + D += 2; + + i += SperD << 1; + } + + if (w & 1) { + u16 s = S[i>>16]; + if (i & 0x20000) { + if (s != Skey1) + *D = s; + } else { + if (s != Skey0) + *D = s; + } + } +} + +static void Bop_8_SKto_Aop( GenefxState *gfxs ) +{ + int w = gfxs->length; + int i = gfxs->Xphase; + u8 *D = gfxs->Aop[0]; + u8 *S = gfxs->Bop[0]; + u32 Skey = gfxs->Skey; + int SperD = gfxs->SperD; + + while (w--) { + u8 s = S[i>>16]; + + if (s != Skey) + *D = s; + + D++; + i += SperD; + } +} + +static void Bop_uyvy_SKto_Aop( GenefxState *gfxs ) +{ + int l; + int w = gfxs->length; + int i = gfxs->Xphase; + u16 *D = gfxs->Aop[0]; + u16 *S = gfxs->Bop[0]; + u32 Skey = gfxs->Skey; +#ifdef WORDS_BIGENDIAN + u16 Skey0 = gfxs->Skey >> 16; + u16 Skey1 = gfxs->Skey & 0xffff; +#else + u16 Skey0 = gfxs->Skey & 0xffff; + u16 Skey1 = gfxs->Skey >> 16; +#endif + int SperD = gfxs->SperD; + + if ((long)D & 2) { + u16 s = *S; + if (s != Skey0) + *D = s; + D++; + i = SperD; + w--; + } + + for (l = w>>1; l--;) { + register u32 s; + + s = ((u32*)S)[i>>17] & 0x00ff00ff; +#ifdef WORDS_BIGENDIAN + s |= (S[i>>16] & 0xff00) << 16; + s |= (S[(i+SperD)>>16] & 0xff00); +#else + s |= (S[i>>16] & 0xff00); + s |= (S[(i+SperD)>>16] & 0xff00) << 16; +#endif + if (s != Skey) + *((u32*)D) = s; + D += 2; + + i += SperD << 1; + } + + if (w & 1) { + u16 s = S[i>>16]; + if (i & 0x20000) { + if (s != Skey1) + *D = s; + } else { + if (s != Skey0) + *D = s; + } + } +} + +static void Bop_alut44_SKto_Aop( GenefxState *gfxs ) +{ + int w = gfxs->length; + int i = gfxs->Xphase; + u8 *D = gfxs->Aop[0]; + u8 *S = gfxs->Bop[0]; + u32 Skey = gfxs->Skey; + int SperD = gfxs->SperD; + + while (w--) { + u8 s = S[i>>16]; + + if ((s & 0x0f) != Skey) + *D = s; + + D++; + i += SperD; + } +} + +static GenefxFunc Bop_PFI_SKto_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + Bop_15_SKto_Aop, /* DSPF_ARGB1555 */ + Bop_16_SKto_Aop, /* DSPF_RGB16 */ + Bop_rgb24_SKto_Aop, /* DSPF_RGB24 */ + Bop_32_SKto_Aop, /* DSPF_RGB32 */ + Bop_32_SKto_Aop, /* DSPF_ARGB */ + Bop_a8_SKto_Aop, /* DSPF_A8 */ + Bop_yuy2_SKto_Aop, /* DSPF_YUY2 */ + Bop_8_SKto_Aop, /* DSPF_RGB332 */ + Bop_uyvy_SKto_Aop, /* DSPF_UYVY */ + NULL, /* DSPF_I420 */ + NULL, /* DSPF_YV12 */ + Bop_8_SKto_Aop, /* DSPF_LUT8 */ + Bop_alut44_SKto_Aop, /* DSPF_ALUT44 */ + Bop_32_SKto_Aop, /* DSPF_AiRGB */ + NULL, /* DSPF_A1 */ + NULL, /* DSPF_NV12 */ + NULL, /* DSPF_NV16 */ + Bop_14_SKto_Aop, /* DSPF_ARGB2554 */ + Bop_12_SKto_Aop, /* DSPF_ARGB4444 */ + Bop_12vv_SKto_Aop, /* DSPF_RGBA4444 */ + NULL, /* DSPF_NV21 */ + Bop_32_SKto_Aop, /* DSPF_AYUV */ + NULL, /* DSPF_A4 */ + Bop_rgb18_SKto_Aop, /* DSPF_ARGB1666 */ + Bop_rgb18_SKto_Aop, /* DSPF_ARGB6666 */ + Bop_rgb18_SKto_Aop, /* DSPF_RGB18 */ + NULL, /* DSPF_LUT2 */ + Bop_12_SKto_Aop, /* DSPF_RGB444 */ + Bop_15_SKto_Aop, /* DSPF_RGB555 */ + Bop_15_SKto_Aop /* DSPF_BGR555 */ +}; + +/********************************* Bop_PFI_StoK_Aop_PFI ***********************/ + +static GenefxFunc Bop_PFI_StoK_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + Bop_15_StoK_Aop, /* DSPF_ARGB1555 */ + Bop_16_StoK_Aop, /* DSPF_RGB16 */ + NULL, /* DSPF_RGB24 */ + Bop_32_StoK_Aop, /* DSPF_RGB32 */ + Bop_32_StoK_Aop, /* DSPF_ARGB */ + NULL, /* DSPF_A8 */ + NULL, /* DSPF_YUY2 */ + NULL, /* DSPF_RGB332 */ + NULL, /* DSPF_UYVY */ + NULL, /* DSPF_I420 */ + NULL, /* DSPF_YV12 */ + NULL, /* DSPF_LUT8 */ + NULL, /* DSPF_ALUT44 */ + Bop_32_StoK_Aop, /* DSPF_AiRGB */ + NULL, /* DSPF_A1 */ + NULL, /* DSPF_NV12 */ + NULL, /* DSPF_NV16 */ + Bop_14_StoK_Aop, /* DSPF_ARGB2554 */ + Bop_12_StoK_Aop, /* DSPF_ARGB4444 */ + Bop_12vv_StoK_Aop, /* DSPF_RGBA4444 */ + NULL, /* DSPF_NV21 */ + NULL, /* DSPF_AYUV */ + NULL, /* DSPF_A4 */ + NULL, /* DSPF_ARGB1666 */ + NULL, /* DSPF_ARGB6666 */ + NULL, /* DSPF_RGB18 */ + NULL, /* DSPF_LUT2 */ + Bop_12_StoK_Aop, /* DSPF_RGB444 */ + Bop_15_StoK_Aop, /* DSPF_RGB555 */ + Bop_15_StoK_Aop /* DSPF_BGR555 */ +}; + +/********************************* Bop_PFI_SKtoK_Aop_PFI **********************/ + +static GenefxFunc Bop_PFI_SKtoK_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + Bop_15_SKtoK_Aop, /* DSPF_ARGB1555 */ + Bop_16_SKtoK_Aop, /* DSPF_RGB16 */ + NULL, /* DSPF_RGB24 */ + Bop_32_SKtoK_Aop, /* DSPF_RGB32 */ + Bop_32_SKtoK_Aop, /* DSPF_ARGB */ + NULL, /* DSPF_A8 */ + NULL, /* DSPF_YUY2 */ + NULL, /* DSPF_RGB332 */ + NULL, /* DSPF_UYVY */ + NULL, /* DSPF_I420 */ + NULL, /* DSPF_YV12 */ + NULL, /* DSPF_LUT8 */ + NULL, /* DSPF_ALUT44 */ + Bop_32_SKtoK_Aop, /* DSPF_AiRGB */ + NULL, /* DSPF_A1 */ + NULL, /* DSPF_NV12 */ + NULL, /* DSPF_NV16 */ + Bop_14_SKtoK_Aop, /* DSPF_ARGB2554 */ + Bop_12_SKtoK_Aop, /* DSPF_ARGB4444 */ + Bop_12vv_SKtoK_Aop, /* DSPF_RGBA4444 */ + NULL, /* DSPF_NV21 */ + NULL, /* DSPF_AYUV */ + NULL, /* DSPF_A4 */ + NULL, /* DSPF_ARGB1666 */ + NULL, /* DSPF_ARGB6666 */ + NULL, /* DSPF_RGB18 */ + NULL, /* DSPF_LUT2 */ + Bop_12_SKtoK_Aop, /* DSPF_RGB444 */ + Bop_15_SKtoK_Aop, /* DSPF_RGB555 */ + Bop_15_SKtoK_Aop /* DSPF_BGR555 */ +}; + +/********************************* Sop_PFI_Sto_Dacc ***************************/ + +static void Sop_argb6666_Sto_Dacc( GenefxState *gfxs ) +{ + int w = gfxs->length; + int i = gfxs->Xphase; + int SperD = gfxs->SperD; + + GenefxAccumulator *D = gfxs->Dacc; + u8 *S = gfxs->Sop[0]; + + while (w--) { + int pixelstart = (i>>16)*3; + + u8 b = S[pixelstart+0] & 0x3F; + u8 g = ((S[pixelstart+0] & 0xC0) >> 6) | ((S[pixelstart+1] & 0x0F) << 2); + u8 r = ((S[pixelstart+1] & 0xF0) >> 4) | ((S[pixelstart+2] & 0x03) << 4); + u8 a = (S[pixelstart+2] & 0xFC) >> 2; + + D->RGB.a = EXPAND_6to8( a ); + D->RGB.r = EXPAND_6to8( r ); + D->RGB.g = EXPAND_6to8( g ); + D->RGB.b = EXPAND_6to8( b ); + i += SperD; + D++; + } +} + +static void Sop_argb1666_Sto_Dacc( GenefxState *gfxs ) +{ + int w = gfxs->length; + int i = gfxs->Xphase; + int SperD = gfxs->SperD; + + GenefxAccumulator *D = gfxs->Dacc; + u8 *S = gfxs->Sop[0]; + + while (w--) { + int pixelstart = (i>>16)*3; + + u8 b = S[pixelstart+0] & 0x3F; + u8 g = ((S[pixelstart+0] & 0xC0) >> 6) | ((S[pixelstart+1] & 0x0F) << 2); + u8 r = ((S[pixelstart+1] & 0xF0) >> 4) | ((S[pixelstart+2] & 0x03) << 4); + u8 a = (S[pixelstart+2] & 0x04) >> 2; + + D->RGB.a = EXPAND_1to8( a ); + D->RGB.r = EXPAND_6to8( r ); + D->RGB.g = EXPAND_6to8( g ); + D->RGB.b = EXPAND_6to8( b ); + i += SperD; + D++; + } +} + +static void Sop_rgb18_Sto_Dacc( GenefxState *gfxs ) +{ + int w = gfxs->length; + int i = gfxs->Xphase; + int SperD = gfxs->SperD; + + GenefxAccumulator *D = gfxs->Dacc; + u8 *S = gfxs->Sop[0]; + + while (w--) { + int pixelstart = (i>>16)*3; + + u8 b = S[pixelstart+0] & 0x3F; + u8 g = ((S[pixelstart+0] & 0xC0) >> 6) | ((S[pixelstart+1] & 0x0F) << 2); + u8 r = ((S[pixelstart+1] & 0xF0) >> 4) | ((S[pixelstart+2] & 0x03) << 4); + + D->RGB.a = 0xFF; + D->RGB.r = EXPAND_6to8( r ); + D->RGB.g = EXPAND_6to8( g ); + D->RGB.b = EXPAND_6to8( b ); + i += SperD; + D++; + } +} + +static void Sop_rgb24_Sto_Dacc( GenefxState *gfxs ) +{ + int w = gfxs->length; + int i = gfxs->Xphase; + int SperD = gfxs->SperD; + + GenefxAccumulator *D = gfxs->Dacc; + u8 *S = gfxs->Sop[0]; + + while (w--) { + int pixelstart = (i>>16)*3; + + D->RGB.a = 0xFF; + D->RGB.r = S[pixelstart+2]; + D->RGB.g = S[pixelstart+1]; + D->RGB.b = S[pixelstart+0]; + + i += SperD; + + D++; + } +} + +static void Sop_a8_Sto_Dacc( GenefxState *gfxs ) +{ + int w = gfxs->length; + int i = gfxs->Xphase; + int SperD = gfxs->SperD; + + GenefxAccumulator *D = gfxs->Dacc; + u8 *S = gfxs->Sop[0]; + + while (w--) { + u8 s = S[i>>16]; + + D->RGB.a = s; + D->RGB.r = 0xFF; + D->RGB.g = 0xFF; + D->RGB.b = 0xFF; + + i += SperD; + + D++; + } +} + +static void Sop_yuy2_Sto_Dacc( GenefxState *gfxs ) +{ + int w = gfxs->length>>1; + int i = gfxs->Xphase; + int SperD = gfxs->SperD; + + GenefxAccumulator *D = gfxs->Dacc; + u32 *S = gfxs->Sop[0]; + + while (w--) { + u32 s = S[i>>17]; + + D[0].YUV.a = D[1].YUV.a = 0xFF; +#ifdef WORDS_BIGENDIAN + D[0].YUV.u = D[1].YUV.u = (s & 0xFF000000) >> 24; + D[0].YUV.v = D[1].YUV.v = (s & 0x0000FF00) >> 8; +#else + D[0].YUV.u = D[1].YUV.u = (s & 0x0000FF00) >> 8; + D[0].YUV.v = D[1].YUV.v = (s & 0xFF000000) >> 24; +#endif + D[0].YUV.y = ((u16*)S)[i>>16] & 0x00FF; + D[1].YUV.y = ((u16*)S)[(i+SperD)>>16] & 0x00FF; + + D += 2; + i += SperD << 1; + } + + if (gfxs->length & 1) { + u16 s = ((u16*)S)[i>>17]; + + D->YUV.a = 0xFF; + D->YUV.y = s & 0xFF; + D->YUV.u = s >> 8; + D->YUV.v = 0x00; + } +} + +static void Sop_rgb332_Sto_Dacc( GenefxState *gfxs ) +{ + int w = gfxs->length; + int i = gfxs->Xphase; + int SperD = gfxs->SperD; + + GenefxAccumulator *D = gfxs->Dacc; + u8 *S = gfxs->Sop[0]; + + while (w--) { + u8 s = S[i>>16]; + + D->RGB.a = 0xFF; + D->RGB.r = EXPAND_3to8(s >> 5); + D->RGB.g = EXPAND_3to8((s & 0x1C) >> 2); + D->RGB.b = EXPAND_2to8(s & 0x03); + + i += SperD; + + D++; + } +} + +static void Sop_uyvy_Sto_Dacc( GenefxState *gfxs ) +{ + int w = gfxs->length>>1; + int i = gfxs->Xphase; + int SperD = gfxs->SperD; + + GenefxAccumulator *D = gfxs->Dacc; + u32 *S = gfxs->Sop[0]; + + while (w--) { + u32 s = S[i>>17]; + + D[0].YUV.a = D[1].YUV.a = 0xFF; +#ifdef WORDS_BIGENDIAN + D[0].YUV.u = D[1].YUV.u = (s & 0x00FF0000) >> 16; + D[0].YUV.v = D[1].YUV.v = (s & 0x000000FF); +#else + D[0].YUV.u = D[1].YUV.u = (s & 0x000000FF); + D[0].YUV.v = D[1].YUV.v = (s & 0x00FF0000) >> 16; +#endif + D[0].YUV.y = (((u16*)S)[i>>16] & 0xFF00) >> 8; + D[1].YUV.y = (((u16*)S)[(i+SperD)>>16] & 0xFF00) >> 8; + + D += 2; + i += SperD << 1; + } + + if (gfxs->length & 1) { + u16 s = ((u16*)S)[i>>16]; + + D->YUV.a = 0xFF; + D->YUV.y = s >> 8; + D->YUV.u = s & 0xFF; + D->YUV.v = 0x00; + } +} + +static void Sop_lut8_Sto_Dacc( GenefxState *gfxs ) +{ + int w = gfxs->length; + int i = gfxs->Xphase; + int SperD = gfxs->SperD; + + GenefxAccumulator *D = gfxs->Dacc; + u8 *S = gfxs->Sop[0]; + + DFBColor *entries = gfxs->Slut->entries; + + while (w--) { + u8 s = S[i>>16]; + + D->RGB.a = entries[s].a; + D->RGB.r = entries[s].r; + D->RGB.g = entries[s].g; + D->RGB.b = entries[s].b; + + i += SperD; + + D++; + } +} + +static void Sop_alut44_Sto_Dacc( GenefxState *gfxs ) +{ + int w = gfxs->length; + int i = gfxs->Xphase; + int SperD = gfxs->SperD; + + GenefxAccumulator *D = gfxs->Dacc; + u8 *S = gfxs->Sop[0]; + + DFBColor *entries = gfxs->Slut->entries; + + while (w--) { + u8 s = S[i>>16]; + + D->RGB.a = s & 0xF0; + s &= 0x0F; + D->RGB.r = entries[s].r; + D->RGB.g = entries[s].g; + D->RGB.b = entries[s].b; + + i += SperD; + + D++; + } +} + +static void Sop_i420_Sto_Dacc( GenefxState *gfxs ) +{ + int w = gfxs->length; + int i = gfxs->Xphase; + int SperD = gfxs->SperD; + + GenefxAccumulator *D = gfxs->Dacc; + u8 *Sy = gfxs->Sop[0]; + u8 *Su = gfxs->Sop[1]; + u8 *Sv = gfxs->Sop[2]; + + while (w--) { + D->YUV.a = 0xFF; + D->YUV.y = Sy[i>>16]; + D->YUV.u = Su[i>>17]; + D->YUV.v = Sv[i>>17]; + + i += SperD; + + D++; + } +} + +static void Sop_nv12_Sto_Dacc( GenefxState *gfxs ) +{ + int w = gfxs->length; + int i = gfxs->Xphase; + int SperD = gfxs->SperD; + + GenefxAccumulator *D = gfxs->Dacc; + u8 *Sy = gfxs->Sop[0]; + u16 *Suv = gfxs->Sop[1]; + + while (w--) { + D->YUV.a = 0xFF; + D->YUV.y = Sy[i>>16]; + D->YUV.u = Suv[i>>17] & 0xFF; + D->YUV.v = Suv[i>>17] >> 8; + + i += SperD; + + D++; + } +} + +static void Sop_nv21_Sto_Dacc( GenefxState *gfxs ) +{ + int w = gfxs->length; + int i = gfxs->Xphase; + int SperD = gfxs->SperD; + + GenefxAccumulator *D = gfxs->Dacc; + u8 *Sy = gfxs->Sop[0]; + u16 *Svu = gfxs->Sop[1]; + + while (w--) { + D->YUV.a = 0xFF; + D->YUV.y = Sy[i>>16]; + D->YUV.u = Svu[i>>17] >> 8; + D->YUV.v = Svu[i>>17] & 0xFF; + + i += SperD; + + D++; + } +} + +static void Sop_ayuv_Sto_Dacc( GenefxState *gfxs ) +{ + int w = gfxs->length; + int i = gfxs->Xphase; + int SperD = gfxs->SperD; + + GenefxAccumulator *D = gfxs->Dacc; + u32 *S = gfxs->Sop[0]; + + while (w--) { + u32 s = S[i>>16]; + + D->YUV.a = (s >> 24); + D->YUV.y = (s >> 16) & 0xff; + D->YUV.u = (s >> 8) & 0xff; + D->YUV.v = (s ) & 0xff; + + i += SperD; + + D++; + } +} + +static GenefxFunc Sop_PFI_Sto_Dacc[DFB_NUM_PIXELFORMATS] = { + Sop_argb1555_Sto_Dacc, /* DSPF_ARGB1555 */ + Sop_rgb16_Sto_Dacc, /* DSPF_RGB16 */ + Sop_rgb24_Sto_Dacc, /* DSPF_RGB24 */ + Sop_rgb32_Sto_Dacc, /* DSPF_RGB32 */ + Sop_argb_Sto_Dacc, /* DSPF_ARGB */ + Sop_a8_Sto_Dacc, /* DSPF_A8 */ + Sop_yuy2_Sto_Dacc, /* DSPF_YUY2 */ + Sop_rgb332_Sto_Dacc, /* DSPF_RGB332 */ + Sop_uyvy_Sto_Dacc, /* DSPF_UYVY */ + Sop_i420_Sto_Dacc, /* DSPF_I420 */ + Sop_i420_Sto_Dacc, /* DSPF_YV12 */ + Sop_lut8_Sto_Dacc, /* DSPF_LUT8 */ + Sop_alut44_Sto_Dacc, /* DSPF_ALUT44 */ + Sop_airgb_Sto_Dacc, /* DSPF_AiRGB */ + NULL, /* DSPF_A1 */ + Sop_nv12_Sto_Dacc, /* DSPF_NV12 */ + Sop_nv12_Sto_Dacc, /* DSPF_NV16 */ + Sop_argb2554_Sto_Dacc, /* DSPF_ARGB2554 */ + Sop_argb4444_Sto_Dacc, /* DSPF_ARGB4444 */ + Sop_rgba4444_Sto_Dacc, /* DSPF_RGBA4444 */ + Sop_nv21_Sto_Dacc, /* DSPF_NV21 */ + Sop_ayuv_Sto_Dacc, /* DSPF_AYUV */ + NULL, /* DSPF_A4 */ + Sop_argb1666_Sto_Dacc, /* DSPF_ARGB1666 */ + Sop_argb6666_Sto_Dacc, /* DSPF_ARGB6666 */ + Sop_rgb18_Sto_Dacc, /* DSPF_RGB18 */ + NULL, /* DSPF_LUT2 */ + Sop_xrgb4444_Sto_Dacc, /* DSPF_RGB444 */ + Sop_xrgb1555_Sto_Dacc, /* DSPF_RGB555 */ + Sop_xbgr1555_Sto_Dacc /* DSPF_BGR555 */ +}; + +/********************************* Sop_PFI_SKto_Dacc **************************/ + +static void Sop_argb6666_SKto_Dacc( GenefxState *gfxs ) +{ + int w = gfxs->length; + int i = gfxs->Xphase; + int SperD = gfxs->SperD; + u32 Skey = gfxs->Skey; + + GenefxAccumulator *D = gfxs->Dacc; + u8 *S = gfxs->Sop[0]; + + while (w--) { + int pixelstart = (i>>16)*3; + + u8 s0 = S[pixelstart+0]; + u8 s1 = S[pixelstart+1]; + u8 s2 = S[pixelstart+2]; + + if (Skey != ((u32)(s2<<16 | s1<<8 | s0) & 0x3FFFF)) { + u8 b = s0 & 0x3F; + u8 g = ((s0 & 0xC0) >> 6) | ((s1 & 0x0F) << 2); + u8 r = ((s1 & 0xF0) >> 4) | ((s2 & 0x03) << 4); + u8 a = (s2 & 0xFC) >> 2; + + D->RGB.a = EXPAND_6to8( a ); + D->RGB.r = EXPAND_6to8( r ); + D->RGB.g = EXPAND_6to8( g ); + D->RGB.b = EXPAND_6to8( b ); + } + else + D->RGB.a = 0xFF00; + + i += SperD; + D++; + } +} + +static void Sop_argb1666_SKto_Dacc( GenefxState *gfxs ) +{ + int w = gfxs->length; + int i = gfxs->Xphase; + int SperD = gfxs->SperD; + + GenefxAccumulator *D = gfxs->Dacc; + u8 *S = gfxs->Sop[0]; + u32 Skey = gfxs->Skey; + + while (w--) { + int pixelstart = (i>>16)*3; + + u8 s0 = S[pixelstart+0]; + u8 s1 = S[pixelstart+1]; + u8 s2 = S[pixelstart+2]; + + if (Skey != ((u32)(s2<<16 | s1<<8 | s0) & 0x3FFFF)) { + u8 b = s0 & 0x3F; + u8 g = ((s0 & 0xC0) >> 6) | ((s1 & 0x0F) << 2); + u8 r = ((s1 & 0xF0) >> 4) | ((s2 & 0x03) << 4); + u8 a = (s2 & 0x04) >> 2; + + D->RGB.a = EXPAND_1to8( a ); + D->RGB.r = EXPAND_6to8( r ); + D->RGB.g = EXPAND_6to8( g ); + D->RGB.b = EXPAND_6to8( b ); + } + else + D->RGB.a = 0xFF00; + i += SperD; + D++; + } +} + +static void Sop_rgb18_SKto_Dacc( GenefxState *gfxs ) +{ + int w = gfxs->length; + int i = gfxs->Xphase; + int SperD = gfxs->SperD; + u32 Skey = gfxs->Skey; + + GenefxAccumulator *D = gfxs->Dacc; + u8 *S = gfxs->Sop[0]; + + while (w--) { + int pixelstart = (i>>16)*3; + + u8 s0 = S[pixelstart+0]; + u8 s1 = S[pixelstart+1]; + u8 s2 = S[pixelstart+2]; + + if (Skey != ((u32)(s2<<16 | s1<<8 | s0) & 0x3FFFF)) { + u8 b = s0 & 0x3F; + u8 g = ((s0 & 0xC0) >> 6) | ((s1 & 0x0F) << 2); + u8 r = ((s1 & 0xF0) >> 4) | ((s2 & 0x03) << 4); + + D->RGB.a = 0xFF; + D->RGB.r = EXPAND_6to8( r ); + D->RGB.g = EXPAND_6to8( g ); + D->RGB.b = EXPAND_6to8( b ); + } + else + D->RGB.a = 0xFF00; + + i += SperD; + D++; + } +} + +static void Sop_rgb24_SKto_Dacc( GenefxState *gfxs ) +{ + int w = gfxs->length; + int i = gfxs->Xphase; + int SperD = gfxs->SperD; + + GenefxAccumulator *D = gfxs->Dacc; + u8 *S = gfxs->Sop[0]; + u32 Skey = gfxs->Skey; + + while (w--) { + int pixelstart = (i>>16)*3; + + u8 b = S[pixelstart+0]; + u8 g = S[pixelstart+1]; + u8 r = S[pixelstart+2]; + + if (Skey != (u32)(r<<16 | g<<8 | b)) { + D->RGB.a = 0xFF; + D->RGB.r = r; + D->RGB.g = g; + D->RGB.b = b; + } + else + D->RGB.a = 0xFF00; + + i += SperD; + + D++; + } +} + +static void Sop_a8_SKto_Dacc( GenefxState *gfxs ) +{ + int w = gfxs->length; + int i = gfxs->Xphase; + int SperD = gfxs->SperD; + + GenefxAccumulator *D = gfxs->Dacc; + u8 *S = gfxs->Sop[0]; + + /* no color to key */ + while (w--) { + u8 s = S[i>>16]; + + D->RGB.a = s; + D->RGB.r = 0xFF; + D->RGB.g = 0xFF; + D->RGB.b = 0xFF; + + i += SperD; + + D++; + } +} + +static void Sop_lut8_SKto_Dacc( GenefxState *gfxs ) +{ + int w = gfxs->length; + int i = gfxs->Xphase; + int SperD = gfxs->SperD; + + GenefxAccumulator *D = gfxs->Dacc; + u8 *S = gfxs->Sop[0]; + u32 Skey = gfxs->Skey; + + DFBColor *entries = gfxs->Slut->entries; + + while (w--) { + u8 s = S[i>>16]; + + if (s != Skey) { + D->RGB.a = entries[s].a; + D->RGB.r = entries[s].r; + D->RGB.g = entries[s].g; + D->RGB.b = entries[s].b; + } + else + D->RGB.a = 0xF000; + + i += SperD; + + D++; + } +} + +static void Sop_alut44_SKto_Dacc( GenefxState *gfxs ) +{ + int w = gfxs->length; + int i = gfxs->Xphase; + int SperD = gfxs->SperD; + + GenefxAccumulator *D = gfxs->Dacc; + u8 *S = gfxs->Sop[0]; + u32 Skey = gfxs->Skey; + + DFBColor *entries = gfxs->Slut->entries; + + while (w--) { + u8 s = S[i>>16]; + + if ((s & 0x0F) != Skey) { + D->RGB.a = ((s & 0xF0) >> 4) | (s & 0xF0); + s &= 0x0F; + D->RGB.r = entries[s].r; + D->RGB.g = entries[s].g; + D->RGB.b = entries[s].b; + } + else + D->RGB.a = 0xF000; + + i += SperD; + + D++; + } +} + +static void Sop_yuy2_SKto_Dacc( GenefxState *gfxs ) +{ + int w = gfxs->length>>1; + int i = gfxs->Xphase; + int SperD = gfxs->SperD; + u32 Ky = (gfxs->Skey & 0x000000FF); +#ifdef WORDS_BIGENDIAN + u32 Kcb = (gfxs->Skey & 0xFF000000) >> 24; + u32 Kcr = (gfxs->Skey & 0x0000FF00) >> 8; +#else + u32 Kcb = (gfxs->Skey & 0x0000FF00) >> 8; + u32 Kcr = (gfxs->Skey & 0xFF000000) >> 24; +#endif + + GenefxAccumulator *D = gfxs->Dacc; + u32 *S = gfxs->Sop[0]; + + while (w--) { + u32 s = S[i>>17]; + u32 y0, cb, y1, cr; + +#ifdef WORDS_BIGENDIAN + cb = (s & 0xFF000000) >> 24; + cr = (s & 0x0000FF00) >> 8; +#else + cb = (s & 0x0000FF00) >> 8; + cr = (s & 0xFF000000) >> 24; +#endif + y0 = ((u16*)S)[i>>16] & 0x00FF; + y1 = ((u16*)S)[(i+SperD)>>16] & 0x00FF; + + if (y0 != Ky || cb != Kcb || cr != Kcr) { + D[0].YUV.a = 0xFF; + D[0].YUV.y = y0; + D[0].YUV.u = cb; + D[0].YUV.v = cr; + } + else + D[0].YUV.a = 0xF000; + + if (y0 != Ky || cb != Kcb || cr != Kcr) { + D[1].YUV.a = 0xFF; + D[1].YUV.y = y1; + D[1].YUV.u = cb; + D[1].YUV.v = cr; + } + else + D[1].YUV.a = 0xF000; + + D += 2; + i += SperD << 1; + } + + if (gfxs->length & 1) { + u16 s = ((u16*)S)[i>>16]; + + if (s != (Ky | (Kcb << 8))) { + D->YUV.a = 0xFF; + D->YUV.y = s & 0xFF; + D->YUV.u = s >> 8; + D->YUV.v = 0x00; + } + else + D->YUV.a = 0xF000; + } +} + +static void Sop_rgb332_SKto_Dacc( GenefxState *gfxs ) +{ + int w = gfxs->length; + int i = gfxs->Xphase; + int SperD = gfxs->SperD; + + GenefxAccumulator *D = gfxs->Dacc; + u8 *S = gfxs->Sop[0]; + u8 Skey = gfxs->Skey; + + while (w--) { + u8 s = S[i>>16]; + + if (s != Skey) { + D->RGB.a = 0xFF; + D->RGB.r = EXPAND_3to8(s >> 5); + D->RGB.g = EXPAND_3to8((s & 0x1C) >> 2); + D->RGB.b = EXPAND_2to8(s & 0x03); + } + else + D->RGB.a = 0xF000; + + i += SperD; + + D++; + } +} + +static void Sop_uyvy_SKto_Dacc( GenefxState *gfxs ) +{ + int w = gfxs->length>>1; + int i = gfxs->Xphase; + int SperD = gfxs->SperD; + u32 Ky = (gfxs->Skey & 0x0000FF00) >> 8; +#ifdef WORDS_BIGENDIAN + u32 Kcb = (gfxs->Skey & 0x00FF0000) >> 16; + u32 Kcr = (gfxs->Skey & 0x000000FF); +#else + u32 Kcb = (gfxs->Skey & 0x000000FF); + u32 Kcr = (gfxs->Skey & 0x00FF0000) >> 16; +#endif + + GenefxAccumulator *D = gfxs->Dacc; + u32 *S = gfxs->Sop[0]; + + while (w--) { + u32 s = S[i>>17]; + u32 cb, y0, cr, y1; + +#ifdef WORDS_BIGENDIAN + cb = (s & 0x00FF0000) >> 16; + cr = (s & 0x000000FF); +#else + cb = (s & 0x000000FF); + cr = (s & 0x00FF0000) >> 16; +#endif + y0 = (((u16*)S)[i>>16] & 0xFF00) >> 8; + y1 = (((u16*)S)[(i+SperD)>>16] & 0xFF00) >> 8; + + if (y0 != Ky || cb != Kcb || cr != Kcr) { + D[0].YUV.a = 0xFF; + D[0].YUV.y = y0; + D[0].YUV.u = cb; + D[0].YUV.v = cr; + } + else + D[0].YUV.a = 0xF000; + + if (y0 != Ky || cb != Kcb || cr != Kcr) { + D[1].YUV.a = 0xFF; + D[1].YUV.y = y1; + D[1].YUV.u = cb; + D[1].YUV.v = cr; + } + else + D[1].YUV.a = 0xF000; + + D += 2; + i += SperD << 1; + } + + if (gfxs->length & 1) { + u16 s = ((u16*)S)[i>>16]; + + if (s != (Kcb | (Ky << 8))) { + D->YUV.a = 0xFF; + D->YUV.y = s >> 8; + D->YUV.u = s & 0xFF; + D->YUV.v = 0x00; + } + else + D->YUV.a = 0xF000; + } +} + +static GenefxFunc Sop_PFI_SKto_Dacc[DFB_NUM_PIXELFORMATS] = { + Sop_argb1555_SKto_Dacc, /* DSPF_ARGB1555 */ + Sop_rgb16_SKto_Dacc, /* DSPF_RGB16 */ + Sop_rgb24_SKto_Dacc, /* DSPF_RGB24 */ + Sop_rgb32_SKto_Dacc, /* DSPF_RGB32 */ + Sop_argb_SKto_Dacc, /* DSPF_ARGB */ + Sop_a8_SKto_Dacc, /* DSPF_A8 */ + Sop_yuy2_SKto_Dacc, /* DSPF_YUY2 */ + Sop_rgb332_SKto_Dacc, /* DSPF_RGB332 */ + Sop_uyvy_SKto_Dacc, /* DSPF_UYVY */ + NULL, /* DSPF_I420 */ + NULL, /* DSPF_YV12 */ + Sop_lut8_SKto_Dacc, /* DSPF_LUT8 */ + Sop_alut44_SKto_Dacc, /* DSPF_ALUT44 */ + Sop_airgb_SKto_Dacc, /* DSPF_AiRGB */ + NULL, /* DSPF_A1 */ + NULL, /* DSPF_NV12 */ + NULL, /* DSPF_NV16 */ + Sop_argb2554_SKto_Dacc, /* DSPF_ARGB2554 */ + Sop_argb4444_SKto_Dacc, /* DSPF_ARGB4444 */ + Sop_rgba4444_SKto_Dacc, /* DSPF_RGBA4444 */ + NULL, /* DSPF_NV21 */ + NULL, /* DSPF_AYUV */ + NULL, /* DSPF_A4 */ + Sop_argb1666_SKto_Dacc, /* DSPF_ARGB1666 */ + Sop_argb6666_SKto_Dacc, /* DSPF_ARGB6666 */ + Sop_rgb18_SKto_Dacc, /* DSPF_RGB18 */ + NULL, /* DSPF_LUT2 */ + Sop_xrgb4444_SKto_Dacc, /* DSPF_RGB444 */ + Sop_xrgb1555_SKto_Dacc, /* DSPF_RGB555 */ + Sop_xbgr1555_SKto_Dacc /* DSPF_BGR555 */ +}; + +/********************************* Sop_PFI_to_Dacc ****************************/ + +static void Sop_argb6666_to_Dacc( GenefxState *gfxs ) +{ + int w = gfxs->length; + + GenefxAccumulator *D = gfxs->Dacc; + u8 *S = gfxs->Sop[0]; + + while (w--) { + u8 b = S[0] & 0x3F; + u8 g = ((S[0] & 0xC0) >> 6) | ((S[1] & 0x0F) << 2); + u8 r = ((S[1] & 0xF0) >> 4) | ((S[2] & 0x03) << 4); + u8 a = (S[2] & 0xFC) >> 2; + + D->RGB.a = EXPAND_6to8( a ); + D->RGB.r = EXPAND_6to8( r ); + D->RGB.g = EXPAND_6to8( g ); + D->RGB.b = EXPAND_6to8( b ); + + S +=3; + D++; + } +} + +static void Sop_argb1666_to_Dacc( GenefxState *gfxs ) +{ + int w = gfxs->length; + + GenefxAccumulator *D = gfxs->Dacc; + u8 *S = gfxs->Sop[0]; + + while (w--) { + u8 b = S[0] & 0x3F; + u8 g = ((S[0] & 0xC0) >> 6) | ((S[1] & 0x0F) << 2); + u8 r = ((S[1] & 0xF0) >> 4) | ((S[2] & 0x03) << 4); + u8 a = (S[2] & 0x04) >> 2; + + D->RGB.a = EXPAND_1to8( a ); + D->RGB.r = EXPAND_6to8( r ); + D->RGB.g = EXPAND_6to8( g ); + D->RGB.b = EXPAND_6to8( b ); + + S +=3; + D++; + } +} + +static void Sop_rgb18_to_Dacc( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *D = gfxs->Dacc; + u8 *S = gfxs->Sop[0]; + + while (w--) { + u8 b = S[0] & 0x3F; + u8 g = ((S[0] & 0xC0) >> 6) | ((S[1] & 0x0F) << 2); + u8 r = ((S[1] & 0xF0) >> 4) | ((S[2] & 0x03) << 4); + + D->RGB.a = 0xFF; + D->RGB.r = EXPAND_6to8( r ); + D->RGB.g = EXPAND_6to8( g ); + D->RGB.b = EXPAND_6to8( b ); + + S +=3; + D++; + } +} + +static void Sop_rgb24_to_Dacc( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *D = gfxs->Dacc; + u8 *S = gfxs->Sop[0]; + + while (w--) { + D->RGB.a = 0xFF; + D->RGB.b = *S++; + D->RGB.g = *S++; + D->RGB.r = *S++; + + D++; + } +} + +static void Sop_a8_to_Dacc( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *D = gfxs->Dacc; + u8 *S = gfxs->Sop[0]; + + while (w--) { + D->RGB.a = *S++; + D->RGB.r = 0xFF; + D->RGB.g = 0xFF; + D->RGB.b = 0xFF; + + D++; + } +} + +static void Sop_a4_to_Dacc( GenefxState *gfxs ) +{ + int i, n; + GenefxAccumulator *D = gfxs->Dacc; + u8 *S = gfxs->Sop[0]; + + for (i=0, n=0; ilength; i+=2, n++) { + register int left = S[n] & 0xF0; + register int right = S[n] & 0x0F; + + D[i].RGB.a = left | (left >> 4); + D[i].RGB.r = 0xFF; + D[i].RGB.g = 0xFF; + D[i].RGB.b = 0xFF; + + D[i+1].RGB.a = right | (right << 4); + D[i+1].RGB.r = 0xFF; + D[i+1].RGB.g = 0xFF; + D[i+1].RGB.b = 0xFF; + } +} + +static void Sop_yuy2_to_Dacc( GenefxState *gfxs ) +{ + int w = gfxs->length>>1; + GenefxAccumulator *D = gfxs->Dacc; + u32 *S = gfxs->Sop[0]; + + while (w--) { + u32 s = *S++; + + D[0].YUV.a = D[1].YUV.a = 0xFF; +#ifdef WORDS_BIGENDIAN + D[0].YUV.y = (s & 0x00FF0000) >> 16; + D[1].YUV.y = (s & 0x000000FF); + D[0].YUV.u = D[1].YUV.u = (s & 0xFF000000) >> 24; + D[0].YUV.v = D[1].YUV.v = (s & 0x0000FF00) >> 8; +#else + D[0].YUV.y = (s & 0x000000FF); + D[1].YUV.y = (s & 0x00FF0000) >> 16; + D[0].YUV.u = D[1].YUV.u = (s & 0x0000FF00) >> 8; + D[0].YUV.v = D[1].YUV.v = (s & 0xFF000000) >> 24; +#endif + + D += 2; + } + + if (gfxs->length & 1) { + u16 s = *((u16*)S); + + D->YUV.a = 0xFF; + D->YUV.y = s & 0xFF; + D->YUV.u = s >> 8; + D->YUV.v = 0x00; + } +} + +static void Sop_rgb332_to_Dacc( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *D = gfxs->Dacc; + u8 *S = gfxs->Sop[0]; + + while (w--) { + u8 s = *S++; + + D->RGB.a = 0xFF; + D->RGB.r = EXPAND_3to8(s >> 5); + D->RGB.g = EXPAND_3to8((s & 0x1C) >> 2); + D->RGB.b = EXPAND_2to8(s & 0x03); + + D++; + } +} + +static void Sop_uyvy_to_Dacc( GenefxState *gfxs ) +{ + int w = gfxs->length>>1; + GenefxAccumulator *D = gfxs->Dacc; + u32 *S = gfxs->Sop[0]; + + while (w--) { + u32 s = *S++; + + D[0].YUV.a = D[1].YUV.a = 0xFF; +#ifdef WORDS_BIGENDIAN + D[0].YUV.y = (s & 0xFF000000) >> 24; + D[1].YUV.y = (s & 0x0000FF00) >> 8; + D[0].YUV.u = D[1].YUV.u = (s & 0x00FF0000) >> 16; + D[0].YUV.v = D[1].YUV.v = (s & 0x000000FF); +#else + D[0].YUV.y = (s & 0x0000FF00) >> 8; + D[1].YUV.y = (s & 0xFF000000) >> 24; + D[0].YUV.u = D[1].YUV.u = (s & 0x000000FF); + D[0].YUV.v = D[1].YUV.v = (s & 0x00FF0000) >> 16; +#endif + + D += 2; + } + + if (gfxs->length & 1) { + u16 s = *((u16*)S); + + D->YUV.a = 0xFF; + D->YUV.y = s >> 8; + D->YUV.u = s & 0xFF; + D->YUV.v = 0x00; + } +} + +static void Sop_lut8_to_Dacc( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *D = gfxs->Dacc; + u8 *S = gfxs->Sop[0]; + + DFBColor *entries = gfxs->Slut->entries; + + while (w--) { + u8 s = *S++; + + D->RGB.a = entries[s].a; + D->RGB.r = entries[s].r; + D->RGB.g = entries[s].g; + D->RGB.b = entries[s].b; + + D++; + } +} + +static void Sop_alut44_to_Dacc( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *D = gfxs->Dacc; + u8 *S = gfxs->Sop[0]; + + DFBColor *entries = gfxs->Slut->entries; + + while (w--) { + u8 s = *S++; + + D->RGB.a = s & 0xF0; + s &= 0x0F; + D->RGB.r = entries[s].r; + D->RGB.g = entries[s].g; + D->RGB.b = entries[s].b; + + D++; + } +} + +static void Sop_i420_to_Dacc( GenefxState *gfxs ) +{ + int w = gfxs->length>>1; + GenefxAccumulator *D = gfxs->Dacc; + u8 *Sy = gfxs->Sop[0]; + u8 *Su = gfxs->Sop[1]; + u8 *Sv = gfxs->Sop[2]; + + while (w--) { + D[1].YUV.a = D[0].YUV.a = 0xFF; + D[0].YUV.y = Sy[0]; + D[1].YUV.y = Sy[1]; + D[1].YUV.u = D[0].YUV.u = Su[0]; + D[1].YUV.v = D[0].YUV.v = Sv[0]; + + Sy += 2; + Su++; + Sv++; + + D += 2; + } +} + +static void Sop_nv12_to_Dacc( GenefxState *gfxs ) +{ + int w = gfxs->length>>1; + GenefxAccumulator *D = gfxs->Dacc; + u8 *Sy = gfxs->Sop[0]; + u16 *Suv = gfxs->Sop[1]; + + while (w--) { + D[1].YUV.a = D[0].YUV.a = 0xFF; + D[0].YUV.y = Sy[0]; + D[1].YUV.y = Sy[1]; + D[1].YUV.u = D[0].YUV.u = Suv[0] & 0xFF; + D[1].YUV.v = D[0].YUV.v = Suv[0] >> 8; + + Sy += 2; + Suv++; + + D += 2; + } +} + +static void Sop_nv21_to_Dacc( GenefxState *gfxs ) +{ + int w = gfxs->length>>1; + GenefxAccumulator *D = gfxs->Dacc; + u8 *Sy = gfxs->Sop[0]; + u16 *Svu = gfxs->Sop[1]; + + while (w--) { + D[1].YUV.a = D[0].YUV.a = 0xFF; + D[0].YUV.y = Sy[0]; + D[1].YUV.y = Sy[1]; + D[1].YUV.u = D[0].YUV.u = Svu[0] >> 8; + D[1].YUV.v = D[0].YUV.v = Svu[0] & 0xFF; + + Sy += 2; + Svu++; + + D += 2; + } +} + +static void Sop_ayuv_to_Dacc( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *D = gfxs->Dacc; + u32 *S = gfxs->Sop[0]; + + while (w--) { + u32 s = *S++; + + D->YUV.a = (s >> 24); + D->YUV.y = (s >> 16) & 0xff; + D->YUV.u = (s >> 8) & 0xff; + D->YUV.v = (s ) & 0xff; + + D++; + } +} + +static GenefxFunc Sop_PFI_to_Dacc[DFB_NUM_PIXELFORMATS] = { + Sop_argb1555_to_Dacc, /* DSPF_ARGB1555 */ + Sop_rgb16_to_Dacc, /* DSPF_RGB16 */ + Sop_rgb24_to_Dacc, /* DSPF_RGB24 */ + Sop_rgb32_to_Dacc, /* DSPF_RGB32 */ + Sop_argb_to_Dacc, /* DSPF_ARGB */ + Sop_a8_to_Dacc, /* DSPF_A8 */ + Sop_yuy2_to_Dacc, /* DSPF_YUY2 */ + Sop_rgb332_to_Dacc, /* DSPF_RGB332 */ + Sop_uyvy_to_Dacc, /* DSPF_UYVY */ + Sop_i420_to_Dacc, /* DSPF_I420 */ + Sop_i420_to_Dacc, /* DSPF_YV12 */ + Sop_lut8_to_Dacc, /* DSPF_LUT8 */ + Sop_alut44_to_Dacc, /* DSPF_ALUT44 */ + Sop_airgb_to_Dacc, /* DSPF_AiRGB */ + NULL, /* DSPF_A1 */ + Sop_nv12_to_Dacc, /* DSPF_NV12 */ + Sop_nv12_to_Dacc, /* DSPF_NV16 */ + Sop_argb2554_to_Dacc, /* DSPF_ARGB2554 */ + Sop_argb4444_to_Dacc, /* DSPF_ARGB4444 */ + Sop_rgba4444_to_Dacc, /* DSPF_RGBA4444 */ + Sop_nv21_to_Dacc, /* DSPF_NV21 */ + Sop_ayuv_to_Dacc, /* DSPF_AYUV */ + Sop_a4_to_Dacc, /* DSPF_A4 */ + Sop_argb1666_to_Dacc, /* DSPF_ARGB1666 */ + Sop_argb6666_to_Dacc, /* DSPF_ARGB6666 */ + Sop_rgb18_to_Dacc, /* DSPF_RGB18 */ + NULL, /* DSPF_LUT2 */ + Sop_xrgb4444_to_Dacc, /* DSPF_RGB444 */ + Sop_xrgb1555_to_Dacc, /* DSPF_RGB555 */ + Sop_xbgr1555_to_Dacc, /* DSPF_BGR555 */ +}; + +/********************************* Sop_PFI_Kto_Dacc ***************************/ + +static void Sop_argb6666_Kto_Dacc( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *D = gfxs->Dacc; + u8 *S = gfxs->Sop[0]; + u32 Skey = gfxs->Skey; + + while (w--) { + u8 s0 = S[0]; + u8 s1 = S[1]; + u8 s2 = S[2]; + + if (Skey != ((u32)(s2<<16 | s1<<8 | s0) & 0x3FFFF)) { + u8 b = s0 & 0x3F; + u8 g = ((s0 & 0xC0) >> 6) | ((s1 & 0x0F) << 2); + u8 r = ((s1 & 0xF0) >> 4) | ((s2 & 0x03) << 4); + u8 a = (s2 & 0xFC) >> 2; + + D->RGB.a = EXPAND_6to8( a ); + D->RGB.r = EXPAND_6to8( r ); + D->RGB.g = EXPAND_6to8( g ); + D->RGB.b = EXPAND_6to8( b ); + } + else + D->RGB.a = 0xF000; + + S += 3; + D++; + } +} + +static void Sop_argb1666_Kto_Dacc( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *D = gfxs->Dacc; + u8 *S = gfxs->Sop[0]; + u32 Skey = gfxs->Skey; + + while (w--) { + u8 s0 = S[0]; + u8 s1 = S[1]; + u8 s2 = S[2]; + + if (Skey != ((u32)(s2<<16 | s1<<8 | s0) & 0x3FFFF)) { + u8 b = s0 & 0x3F; + u8 g = ((s0 & 0xC0) >> 6) | ((s1 & 0x0F) << 2); + u8 r = ((s1 & 0xF0) >> 4) | ((s2 & 0x03) << 4); + u8 a = (s2 & 0x04) >> 2; + + D->RGB.a = EXPAND_1to8( a ); + D->RGB.r = EXPAND_6to8( r ); + D->RGB.g = EXPAND_6to8( g ); + D->RGB.b = EXPAND_6to8( b ); + } + else + D->RGB.a = 0xF000; + + S += 3; + D++; + } +} + +static void Sop_rgb18_Kto_Dacc( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *D = gfxs->Dacc; + u8 *S = gfxs->Sop[0]; + u32 Skey = gfxs->Skey; + + while (w--) { + u8 s0 = S[0]; + u8 s1 = S[1]; + u8 s2 = S[2]; + + if (Skey != ((u32)(s2<<16 | s1<<8 | s0) & 0x3ffff)) { + u8 b = s0 & 0x3F; + u8 g = ((s0 & 0xC0) >> 6) | ((s1 & 0x0F) << 2); + u8 r = ((s1 & 0xF0) >> 4) | ((s2 & 0x03) << 4); + + D->RGB.a = 0xFF; + D->RGB.r = EXPAND_6to8( r ); + D->RGB.g = EXPAND_6to8( g ); + D->RGB.b = EXPAND_6to8( b ); + } + else + D->RGB.a = 0xF000; + + S += 3; + D++; + } +} + +static void Sop_rgb24_Kto_Dacc( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *D = gfxs->Dacc; + u8 *S = gfxs->Sop[0]; + u32 Skey = gfxs->Skey; + + while (w--) { + u8 b = *S++; + u8 g = *S++; + u8 r = *S++; + + if (Skey != (u32)(r<<16 | g<<8 | b)) { + D->RGB.a = 0xFF; + D->RGB.r = r; + D->RGB.g = g; + D->RGB.b = b; + } + else + D->RGB.a = 0xF000; + + D++; + } +} + +static void Sop_a8_Kto_Dacc( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *D = gfxs->Dacc; + u8 *S = gfxs->Sop[0]; + + /* no color to key */ + while (w--) { + D->RGB.a = *S++; + D->RGB.r = 0xFF; + D->RGB.g = 0xFF; + D->RGB.b = 0xFF; + + D++; + } +} + +static void Sop_yuy2_Kto_Dacc( GenefxState *gfxs ) +{ + int w = gfxs->length>>1; + GenefxAccumulator *D = gfxs->Dacc; + u32 *S = gfxs->Sop[0]; + u32 Skey = gfxs->Skey; + u32 Skey0 = gfxs->Skey & 0xFF00FFFF; + u32 Skey1 = gfxs->Skey & 0xFFFFFF00; + +#ifdef WORDS_BIGENDIAN +#define S0_MASK 0xFFFFFF00 +#define S1_MASK 0xFF00FFFF +#else +#define S0_MASK 0xFF00FFFF +#define S1_MASK 0xFFFFFF00 +#endif + + while (w--) { + u32 s = *S++; + + if (s != Skey) { + u32 cb, cr; + +#ifdef WORDS_BIGENDIAN + cb = (s & 0xFF000000) >> 24; + cr = (s & 0x0000FF00) >> 8; +#else + cb = (s & 0x0000FF00) >> 8; + cr = (s & 0xFF000000) >> 24; +#endif + + if ((s & S0_MASK) != Skey0) { + D[0].YUV.a = 0xFF; +#ifdef WORDS_BIGENDIAN + D[0].YUV.y = (s & 0x00FF0000) >> 16; +#else + D[0].YUV.y = (s & 0x000000FF); +#endif + D[0].YUV.u = cb; + D[0].YUV.v = cr; + } + else + D[0].YUV.a = 0xF000; + + if ((s & S1_MASK) != Skey1) { + D[1].YUV.a = 0xFF; +#ifdef WORDS_BIGENDIAN + D[1].YUV.y = (s & 0x000000FF); +#else + D[1].YUV.y = (s & 0x00FF0000) >> 16; +#endif + D[1].YUV.u = cb; + D[1].YUV.v = cr; + } + else + D[1].YUV.a = 0xF000; + } + + D += 2; + } + + if (gfxs->length & 1) { + u16 s = *((u16*)S); + + if (s != Skey0) { + D->YUV.a = 0xFF; + D->YUV.y = s & 0xFF; + D->YUV.u = s >> 8; + D->YUV.v = 0x00; + } + else + D->YUV.a = 0xF000; + } +#undef S0_MASK +#undef S1_MASK +} + +static void Sop_rgb332_Kto_Dacc( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *D = gfxs->Dacc; + u8 *S = gfxs->Sop[0]; + u32 Skey = gfxs->Skey; + + while (w--) { + u8 s = *S++; + + if (s != Skey) { + D->RGB.a = 0xFF; + D->RGB.r = EXPAND_3to8(s >> 5); + D->RGB.g = EXPAND_3to8((s & 0x1C) >> 2); + D->RGB.b = EXPAND_2to8(s & 0x03); + } + else + D->RGB.a = 0xF000; + + D++; + } +} + +static void Sop_uyvy_Kto_Dacc( GenefxState *gfxs ) +{ + int w = gfxs->length>>1; + GenefxAccumulator *D = gfxs->Dacc; + u32 *S = gfxs->Sop[0]; + u32 Skey = gfxs->Skey; + u32 Skey0 = gfxs->Skey & 0x00FFFFFF; + u32 Skey1 = gfxs->Skey & 0xFFFF00FF; + +#ifdef WORDS_BIGENDIAN +#define S0_MASK 0xFFFF00FF +#define S1_MASK 0x00FFFFFF +#else +#define S0_MASK 0x00FFFFFF +#define S1_MASK 0xFFFF00FF +#endif + + while (w--) { + u32 s = *S++; + + if (s != Skey) { + u32 cb, cr; + +#ifdef WORDS_BIGENDIAN + cb = (s & 0x00FF0000) >> 16; + cr = (s & 0x000000FF); +#else + cb = (s & 0x000000FF); + cr = (s & 0x00FF0000) >> 16; +#endif + + if ((s & S0_MASK) != Skey0) { + D[0].YUV.a = 0xFF; +#ifdef WORDS_BIGENDIAN + D[0].YUV.y = (s & 0xFF000000) >> 24; +#else + D[0].YUV.y = (s & 0x0000FF00) >> 8; +#endif + D[0].YUV.u = cb; + D[0].YUV.v = cr; + } + else + D[0].YUV.a = 0xF000; + + if ((s & S1_MASK) != Skey1) { + D[1].YUV.a = 0xFF; +#ifdef WORDS_BIGENDIAN + D[1].YUV.y = (s & 0x0000FF00) >> 8; +#else + D[1].YUV.y = (s & 0xFF000000) >>24; +#endif + D[1].YUV.u = cb; + D[1].YUV.v = cr; + } + else + D[1].YUV.a = 0xF000; + } + + D += 2; + } + + if (gfxs->length & 1) { + u16 s = *((u16*)S); + + if (s != Skey0) { + D->YUV.a = 0xFF; + D->YUV.y = s >> 8; + D->YUV.u = s & 0xFF; + D->YUV.v = 0x00; + } + else + D->YUV.a = 0xF000; + } +#undef S0_MASK +#undef S1_MASK +} + +static void Sop_lut8_Kto_Dacc( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *D = gfxs->Dacc; + u8 *S = gfxs->Sop[0]; + u32 Skey = gfxs->Skey; + + DFBColor *entries = gfxs->Slut->entries; + + while (w--) { + u8 s = *S++; + + if (s != Skey) { + D->RGB.a = entries[s].a; + D->RGB.r = entries[s].r; + D->RGB.g = entries[s].g; + D->RGB.b = entries[s].b; + } + else + D->RGB.a = 0xF000; + + D++; + } +} + +static void Sop_alut44_Kto_Dacc( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *D = gfxs->Dacc; + u8 *S = gfxs->Sop[0]; + u32 Skey = gfxs->Skey; + + DFBColor *entries = gfxs->Slut->entries; + + while (w--) { + u8 s = *S++; + + if ((s & 0x0F) != Skey) { + D->RGB.a = ((s & 0xF0) >> 4) | (s & 0xF0); + s &= 0x0F; + D->RGB.r = entries[s].r; + D->RGB.g = entries[s].g; + D->RGB.b = entries[s].b; + } + else + D->RGB.a = 0xF000; + + D++; + } +} + +static GenefxFunc Sop_PFI_Kto_Dacc[DFB_NUM_PIXELFORMATS] = { + Sop_argb1555_Kto_Dacc, /* DSPF_ARGB1555 */ + Sop_rgb16_Kto_Dacc, /* DSPF_RGB16 */ + Sop_rgb24_Kto_Dacc, /* DSPF_RGB24 */ + Sop_rgb32_Kto_Dacc, /* DSPF_RGB32 */ + Sop_argb_Kto_Dacc, /* DSPF_ARGB */ + Sop_a8_Kto_Dacc, /* DSPF_A8 */ + Sop_yuy2_Kto_Dacc, /* DSPF_YUY2 */ + Sop_rgb332_Kto_Dacc, /* DSPF_RGB332 */ + Sop_uyvy_Kto_Dacc, /* DSPF_UYVY */ + NULL, /* DSPF_I420 */ + NULL, /* DSPF_YV12 */ + Sop_lut8_Kto_Dacc, /* DSPF_LUT8 */ + Sop_alut44_Kto_Dacc, /* DSPF_ALUT44 */ + Sop_airgb_Kto_Dacc, /* DSPF_AiRGB */ + NULL, /* DSPF_A1 */ + NULL, /* DSPF_NV12 */ + NULL, /* DSPF_NV16 */ + Sop_argb2554_Kto_Dacc, /* DSPF_ARGB2554 */ + Sop_argb4444_Kto_Dacc, /* DSPF_ARGB4444 */ + Sop_rgba4444_Kto_Dacc, /* DSPF_RGBA4444 */ + NULL, /* DSPF_NV21 */ + NULL, /* DSPF_AYUV */ + NULL, /* DSPF_A4 */ + Sop_argb6666_Kto_Dacc, /* DSPF_ARGB1666 */ + Sop_argb1666_Kto_Dacc, /* DSPF_ARGB6666 */ + Sop_rgb18_Kto_Dacc, /* DSPF_RGB18 */ + NULL, /* DSPF_LUT2 */ + Sop_xrgb4444_Kto_Dacc, /* DSPF_RGB444 */ + Sop_xrgb1555_Kto_Dacc, /* DSPF_RGB555 */ + Sop_xbgr1555_Kto_Dacc, /* DSPF_BGR555 */ +}; + +/********************************* Sacc_to_Aop_PFI ****************************/ + +static void Sacc_to_Aop_argb6666( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *S = gfxs->Sacc; + u8 *D = gfxs->Aop[0]; + + while (w--) { + if (!(S->RGB.a & 0xF000)) { + u32 pixel = PIXEL_ARGB6666( (S->RGB.a & 0xFF00) ? 0xFF : S->RGB.a, + (S->RGB.r & 0xFF00) ? 0xFF : S->RGB.r, + (S->RGB.g & 0xFF00) ? 0xFF : S->RGB.g, + (S->RGB.b & 0xFF00) ? 0xFF : S->RGB.b ); + + D[0] = pixel; + D[1] = pixel >> 8; + D[2] = pixel >> 16; + } + D +=3; + S++; + } +} + +static void Sacc_to_Aop_argb1666( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *S = gfxs->Sacc; + u8 *D = gfxs->Aop[0]; + + while (w--) { + if (!(S->RGB.a & 0xF000)) { + u32 pixel = PIXEL_ARGB1666( (S->RGB.a & 0xFF00) ? 0xFF : S->RGB.a, + (S->RGB.r & 0xFF00) ? 0xFF : S->RGB.r, + (S->RGB.g & 0xFF00) ? 0xFF : S->RGB.g, + (S->RGB.b & 0xFF00) ? 0xFF : S->RGB.b ); + + D[0] = pixel; + D[1] = pixel >> 8; + D[2] = pixel >> 16; + } + D +=3; + S++; + } +} + +static void Sacc_to_Aop_rgb18( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *S = gfxs->Sacc; + u8 *D = gfxs->Aop[0]; + + while (w--) { + if (!(S->RGB.a & 0xF000)) { + u32 pixel = PIXEL_RGB18( (S->RGB.r & 0xFF00) ? 0xFF : S->RGB.r, + (S->RGB.g & 0xFF00) ? 0xFF : S->RGB.g, + (S->RGB.b & 0xFF00) ? 0xFF : S->RGB.b ); + + D[0] = pixel; + D[1] = pixel >> 8; + D[2] = pixel >> 16; + } + D +=3; + S++; + } +} + +static void Sacc_to_Aop_rgb24( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *S = gfxs->Sacc; + u8 *D = gfxs->Aop[0]; + + while (w--) { + if (!(S->RGB.a & 0xF000)) { + *D++ = (S->RGB.b & 0xFF00) ? 0xFF : S->RGB.b; + *D++ = (S->RGB.g & 0xFF00) ? 0xFF : S->RGB.g; + *D++ = (S->RGB.r & 0xFF00) ? 0xFF : S->RGB.r; + } + else + D += 3; + + S++; + } +} + +static void Sacc_to_Aop_a8( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *S = gfxs->Sacc; + u8 *D = gfxs->Aop[0]; + + while (w--) { + if (!(S->RGB.a & 0xF000)) + *D = (S->RGB.a & 0xFF00) ? 0xFF : S->RGB.a; + + D++; + S++; + } +} + +static void Sacc_to_Aop_yuy2( GenefxState *gfxs ) +{ + int l; + int w = gfxs->length; + GenefxAccumulator *S = gfxs->Sacc; + u16 *D = gfxs->Aop[0]; + + if ((long)D & 2) { + if (!(S->YUV.a & 0xF00)) { + *D = ((S->YUV.y & 0xFF00) ? 0x00FF : S->YUV.y) | + ((S->YUV.v & 0xFF00) ? 0XFF00 : (S->YUV.v<<8)); + } + S++; + D++; + w--; + } + + for (l = w>>1; l--;) { + if (!(S[0].YUV.a & 0xF000) && !(S[1].YUV.a & 0xF000)) { + u32 y0, cb, y1, cr; + + y0 = (S[0].YUV.y & 0xFF00) ? 0xFF : S[0].YUV.y; + y1 = (S[1].YUV.y & 0xFF00) ? 0xFF : S[1].YUV.y; + + cb = (S[0].YUV.u + S[1].YUV.u) >> 1; + if (cb & 0xFF00) + cb = 0xFF; + + cr = (S[0].YUV.v + S[1].YUV.v) >> 1; + if (cr & 0xFF00) + cr = 0xFF; + +#ifdef WORDS_BIGENDIAN + *((u32*)D) = y1 | (cr << 8) | (y0 << 16) | (cb << 24); +#else + *((u32*)D) = y0 | (cb << 8) | (y1 << 16) | (cr << 24); +#endif + } + else if (!(S[0].YUV.a & 0xF000)) { + D[0] = ((S[0].YUV.y & 0xFF00) ? 0x00FF : S[0].YUV.y) | + ((S[0].YUV.u & 0xFF00) ? 0xFF00 : (S[0].YUV.u<<8)); + } + else if (!(S[1].YUV.a & 0xF000)) { + D[1] = ((S[1].YUV.y & 0xFF00) ? 0x00FF : S[1].YUV.y) | + ((S[1].YUV.v & 0xFF00) ? 0xFF00 : (S[1].YUV.v<<8)); + } + + D += 2; + S += 2; + } + + if (w & 1) { + if (!(S->YUV.a & 0xF00)) { + *D = ((S->YUV.y & 0xFF00) ? 0x00FF : S->YUV.y) | + ((S->YUV.u & 0xFF00) ? 0xFF00 : (S->YUV.u<<8)); + } + } +} + +static void Sacc_to_Aop_rgb332( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *S = gfxs->Sacc; + u8 *D = gfxs->Aop[0]; + + while (w--) { + if (!(S->RGB.a & 0xF000)) { + *D = PIXEL_RGB332( (S->RGB.r & 0xFF00) ? 0xFF : S->RGB.r, + (S->RGB.g & 0xFF00) ? 0xFF : S->RGB.g, + (S->RGB.b & 0xFF00) ? 0xFF : S->RGB.b ); + } + + D++; + S++; + } +} + +static void Sacc_to_Aop_uyvy( GenefxState *gfxs ) +{ + int l; + int w = gfxs->length; + GenefxAccumulator *S = gfxs->Sacc; + u16 *D = gfxs->Aop[0]; + + if ((long)D & 2) { + if (!(S->YUV.a & 0xF00)) { + *D = ((S->YUV.v & 0xFF00) ? 0x00FF : S->YUV.v) | + ((S->YUV.y & 0xFF00) ? 0xFF00 : (S->YUV.y<<8)); + } + S++; + D++; + w--; + } + + for (l = w>>1; l--;) { + if (!(S[0].YUV.a & 0xF000) && !(S[1].YUV.a & 0xF000)) { + u32 cb, y0, cr, y1; + + y0 = (S[0].YUV.y & 0xFF00) ? 0xFF : S[0].YUV.y; + y1 = (S[1].YUV.y & 0xFF00) ? 0xFF : S[1].YUV.y; + + cb = (S[0].YUV.u + S[1].YUV.u) >> 1; + if (cb & 0xFF00) + cb = 0xFF; + + cr = (S[0].YUV.v + S[1].YUV.v) >> 1; + if (cr & 0xFF00) + cr = 0xFF; + +#ifdef WORDS_BIGENDIAN + *((u32*)D) = cr | (y1 << 8) | (cb << 16) | (y0 << 24); +#else + *((u32*)D) = cb | (y0 << 8) | (cr << 16) | (y1 << 24); +#endif + } + else if (!(S[0].YUV.a & 0xF000)) { + D[0] = ((S[0].YUV.u & 0xFF00) ? 0x00FF : S[0].YUV.u) | + ((S[0].YUV.y & 0xFF00) ? 0xFF00 : (S[0].YUV.y<<8)); + } + else if (!(S[1].YUV.a & 0xF000)) { + D[1] = ((S[1].YUV.v & 0xFF00) ? 0x00FF : S[1].YUV.v) | + ((S[1].YUV.y & 0xFF00) ? 0xFF00 : (S[1].YUV.y<<8)); + } + + D += 2; + S += 2; + } + + if (w & 1) { + if (!(S->YUV.a & 0xF00)) { + *D = ((S->YUV.u & 0xFF00) ? 0x00FF : S->YUV.u) | + ((S->YUV.y & 0xFF00) ? 0xFF00 : (S->YUV.y<<8)); + } + } +} + +static void Sacc_to_Aop_lut8( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *S = gfxs->Sacc; + u8 *D = gfxs->Aop[0]; + + while (w--) { + if (!(S->RGB.a & 0xF000)) { + *D = dfb_palette_search( gfxs->Alut, + (S->RGB.r & 0xFF00) ? 0xFF : S->RGB.r, + (S->RGB.g & 0xFF00) ? 0xFF : S->RGB.g, + (S->RGB.b & 0xFF00) ? 0xFF : S->RGB.b, + (S->RGB.a & 0xFF00) ? 0xFF : S->RGB.a ); + } + + D++; + S++; + } +} + +static void Sacc_to_Aop_alut44( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *S = gfxs->Sacc; + u8 *D = gfxs->Aop[0]; + + while (w--) { + if (!(S->RGB.a & 0xF000)) { + *D = (S->RGB.a & 0xFF00) ? 0xF0 : (S->RGB.a & 0xF0) + + dfb_palette_search( gfxs->Alut, + (S->RGB.r & 0xFF00) ? 0xFF : S->RGB.r, + (S->RGB.g & 0xFF00) ? 0xFF : S->RGB.g, + (S->RGB.b & 0xFF00) ? 0xFF : S->RGB.b, + 0x80 ); + } + + D++; + S++; + } +} + +static void Sacc_to_Aop_i420( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *S = gfxs->Sacc; + u8 *Dy = gfxs->Aop[0]; + + while (w--) { + if (!(S->YUV.a & 0xF000)) + *Dy = (S->YUV.y & 0xFF00) ? 0xFF : S->YUV.y; + + S++; + Dy++; + } + + if (gfxs->AopY & 1) { + u8 *Du = gfxs->Aop[1]; + u8 *Dv = gfxs->Aop[2]; + + w = gfxs->length>>1; + S = gfxs->Sacc; + + while (w--) { + if (!(S[0].YUV.a & 0xF000) && !(S[1].YUV.a & 0xF000)) { + u32 tmp; + + tmp = (S[0].YUV.u + S[1].YUV.u) >> 1; + if (tmp & 0xFF00) + tmp = 0xFF; + *Du = tmp; + + tmp = (S[0].YUV.v + S[1].YUV.v) >> 1; + if (tmp & 0xFF00) + tmp = 0xFF; + *Dv = tmp; + + } + else if (!(S[0].YUV.a & 0xF000)) { + *Du = (*Du + ((S[0].YUV.u & 0xFF00) ? 0xFF : S[0].YUV.u)) >> 1; + *Dv = (*Dv + ((S[0].YUV.v & 0xFF00) ? 0xFF : S[0].YUV.v)) >> 1; + } + else if (!(S[1].YUV.a & 0xF000)) { + *Du = (*Du + ((S[1].YUV.u & 0xFF00) ? 0xFF : S[1].YUV.u)) >> 1; + *Dv = (*Dv + ((S[1].YUV.v & 0xFF00) ? 0xFF : S[1].YUV.v)) >> 1; + } + + S += 2; + Du++; + Dv++; + } + } +} + +static void Sacc_to_Aop_nv12( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *S = gfxs->Sacc; + u8 *Dy = gfxs->Aop[0]; + + while (w--) { + if (!(S->YUV.a & 0xF000)) + *Dy = (S->YUV.y & 0xFF00) ? 0xFF : S->YUV.y; + + S++; + Dy++; + } + + if (gfxs->dst_format == DSPF_NV16 || gfxs->AopY & 1) { + u16 *Duv = gfxs->Aop[1]; + + w = gfxs->length>>1; + S = gfxs->Sacc; + + while (w--) { + u32 cb, cr; + + if (!(S[0].YUV.a & 0xF000) && !(S[1].YUV.a & 0xF000)) { + cb = (S[0].YUV.u + S[1].YUV.u) >> 1; + if (cb & 0xFF00) + cb = 0xFF; + + cr = (S[0].YUV.v + S[1].YUV.v) >> 1; + if (cr & 0xFF00) + cr = 0xFF; + +#ifdef WORDS_BIGENDIAN + *Duv = cr | (cb << 8); + } + else if (!(S[0].YUV.a & 0xF000)) { + cb = ((*Duv >> 8) + ((S[0].YUV.u & 0xFF00) ? 0xFF : S[0].YUV.u)) >> 1; + cr = ((*Duv & 0xFF) + ((S[0].YUV.v & 0xFF00) ? 0xFF : S[0].YUV.v)) >> 1; + *Duv = cr | (cb << 8); + } + else if (!(S[1].YUV.a & 0xF000)) { + cb = ((*Duv >> 8) + ((S[1].YUV.u & 0xFF00) ? 0xFF : S[1].YUV.u)) >> 1; + cr = ((*Duv & 0xFF) + ((S[1].YUV.v & 0xFF00) ? 0xFF : S[1].YUV.v)) >> 1; + *Duv = cr | (cb << 8); + } +#else + *Duv = cb | (cr << 8); + } + else if (!(S[0].YUV.a & 0xF000)) { + cb = ((*Duv & 0xFF) + ((S[0].YUV.u & 0xFF00) ? 0xFF : S[0].YUV.u)) >> 1; + cr = ((*Duv >> 8) + ((S[0].YUV.v & 0xFF00) ? 0xFF : S[0].YUV.v)) >> 1; + *Duv = cb | (cr << 8); + } + else if (!(S[1].YUV.a & 0xF000)) { + cb = ((*Duv & 0xFF) + ((S[1].YUV.u & 0xFF00) ? 0xFF : S[1].YUV.u)) >> 1; + cr = ((*Duv >> 8) + ((S[1].YUV.v & 0xFF00) ? 0xFF : S[1].YUV.v)) >> 1; + *Duv = cb | (cr << 8); + } +#endif + + S += 2; + Duv++; + } + } +} + +static void Sacc_to_Aop_nv21( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *S = gfxs->Sacc; + u8 *Dy = gfxs->Aop[0]; + + while (w--) { + if (!(S->YUV.a & 0xF000)) + *Dy = (S->YUV.y & 0xFF00) ? 0xFF : S->YUV.y; + + S++; + Dy++; + } + + if (gfxs->AopY & 1) { + u16 *Dvu = gfxs->Aop[1]; + + w = gfxs->length>>1; + S = gfxs->Sacc; + + while (w--) { + u32 cb, cr; + + if (!(S[0].YUV.a & 0xF000) && !(S[1].YUV.a & 0xF000)) { + cb = (S[0].YUV.u + S[1].YUV.u) >> 1; + if (cb & 0xFF00) + cb = 0xFF; + + cr = (S[0].YUV.v + S[1].YUV.v) >> 1; + if (cr & 0xFF00) + cr = 0xFF; + + *Dvu = cr | (cb << 8); + } + else if (!(S[0].YUV.a & 0xF000)) { + cb = ((*Dvu >> 8) + ((S[0].YUV.u & 0xFF00) ? 0xFF : S[0].YUV.u)) >> 1; + cr = ((*Dvu & 0xFF) + ((S[0].YUV.v & 0xFF00) ? 0xFF : S[0].YUV.v)) >> 1; + *Dvu = cr | (cb << 8); + } + else if (!(S[1].YUV.a & 0xF000)) { + cb = ((*Dvu >> 8) + ((S[1].YUV.u & 0xFF00) ? 0xFF : S[1].YUV.u)) >> 1; + cr = ((*Dvu & 0xFF) + ((S[1].YUV.v & 0xFF00) ? 0xFF : S[1].YUV.v)) >> 1; + *Dvu = cr | (cb << 8); + } + + S += 2; + Dvu++; + } + } +} + +static void Sacc_to_Aop_ayuv( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *S = gfxs->Sacc; + u32 *D = gfxs->Aop[0]; + + while (w--) { + if (!(S->YUV.a & 0xF000)) { + *D = PIXEL_AYUV( (S->YUV.a & 0xFF00) ? 0xFF : S->YUV.a, + (S->YUV.y & 0xFF00) ? 0xFF : S->YUV.y, + (S->YUV.u & 0xFF00) ? 0xFF : S->YUV.u, + (S->YUV.v & 0xFF00) ? 0xFF : S->YUV.v ); + } + + D++; + S++; + } +} + +static void Sacc_to_Aop_a4( GenefxState *gfxs ) +{ + int w = gfxs->length>>1; + GenefxAccumulator *S = gfxs->Sacc; + u8 *D = gfxs->Aop[0]; + + while (w--) { + if (!(S[0].RGB.a & 0xF000) && !(S[1].RGB.a & 0xF000)) { + *D = ((S[0].RGB.a & 0xFF00) ? 0xF0 : (S[0].RGB.a & 0xF0)) | + ((S[1].RGB.a & 0XFF00) ? 0x0F : (S[1].RGB.a >> 4)); + } + else if (!(S[0].RGB.a & 0xF000)) { + *D = (*D & 0x0F) | ((S[0].RGB.a & 0xFF00) ? 0xF0 : (S[0].RGB.a & 0xF0)); + } + else if (!(S[1].RGB.a & 0xF000)) { + *D = (*D & 0xF0) | ((S[1].RGB.a & 0XFF00) ? 0x0F : (S[1].RGB.a >> 4)); + } + + D++; + S += 2; + } + + if (gfxs->length & 1) { + if (!(S->RGB.a & 0xF000)) + *D = (*D & 0x0F) | ((S->RGB.a & 0xFF00) ? 0xF0 : (S->RGB.a & 0xF0)); + } +} + +static GenefxFunc Sacc_to_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + Sacc_to_Aop_argb1555, /* DSPF_ARGB1555 */ + Sacc_to_Aop_rgb16, /* DSPF_RGB16 */ + Sacc_to_Aop_rgb24, /* DSPF_RGB24 */ + Sacc_to_Aop_rgb32, /* DSPF_RGB32 */ + Sacc_to_Aop_argb, /* DSPF_ARGB */ + Sacc_to_Aop_a8, /* DSPF_A8 */ + Sacc_to_Aop_yuy2, /* DSPF_YUY2 */ + Sacc_to_Aop_rgb332, /* DSPF_RGB332 */ + Sacc_to_Aop_uyvy, /* DSPF_UYVY */ + Sacc_to_Aop_i420, /* DSPF_I420 */ + Sacc_to_Aop_i420, /* DSPF_YV12 */ + Sacc_to_Aop_lut8, /* DSPF_LUT8 */ + Sacc_to_Aop_alut44, /* DSPF_ALUT44 */ + Sacc_to_Aop_airgb, /* DSPF_AiRGB */ + NULL, /* DSPF_A1 */ + Sacc_to_Aop_nv12, /* DSPF_NV12 */ + Sacc_to_Aop_nv12, /* DSPF_NV16 */ + Sacc_to_Aop_argb2554, /* DSPF_ARGB2554 */ + Sacc_to_Aop_argb4444, /* DSPF_ARGB4444 */ + Sacc_to_Aop_rgba4444, /* DSPF_RGBA4444 */ + Sacc_to_Aop_nv21, /* DSPF_NV21 */ + Sacc_to_Aop_ayuv, /* DSPF_AYUV */ + Sacc_to_Aop_a4, /* DSPF_A4 */ + Sacc_to_Aop_argb1666, /* DSPF_ARGB1666 */ + Sacc_to_Aop_argb6666, /* DSPF_ARGB6666 */ + Sacc_to_Aop_rgb18, /* DSPF_RGB18 */ + NULL, /* DSPF_LUT2 */ + Sacc_to_Aop_xrgb4444, /* DSPF_RGB444 */ + Sacc_to_Aop_xrgb1555, /* DSPF_RGB555 */ + Sacc_to_Aop_xbgr1555, /* DSPF_BGR555 */ +}; + +/********************************* Sacc_Sto_Aop_PFI ***************************/ + +static void Sacc_Sto_Aop_argb6666( GenefxState *gfxs ) +{ + int w = gfxs->length; + int i = gfxs->Xphase; + GenefxAccumulator *Sacc = gfxs->Sacc; + u8 *D = gfxs->Aop[0]; + int SperD = gfxs->SperD; + + while (w--) { + GenefxAccumulator *S = &Sacc[i>>16]; + + if (!(S->RGB.a & 0xF000)) { + u32 pixel = PIXEL_ARGB6666( (S->RGB.a & 0xFF00) ? 0xFF : S->RGB.a, + (S->RGB.r & 0xFF00) ? 0xFF : S->RGB.r, + (S->RGB.g & 0xFF00) ? 0xFF : S->RGB.g, + (S->RGB.b & 0xFF00) ? 0xFF : S->RGB.b ); + + D[0] = pixel; + D[1] = pixel >> 8; + D[2] = pixel >> 16; + } + D +=3; + i += SperD; + } +} + +static void Sacc_Sto_Aop_argb1666( GenefxState *gfxs ) +{ + int w = gfxs->length; + int i = gfxs->Xphase; + GenefxAccumulator *Sacc = gfxs->Sacc; + u8 *D = gfxs->Aop[0]; + int SperD = gfxs->SperD; + + while (w--) { + GenefxAccumulator *S = &Sacc[i>>16]; + + if (!(S->RGB.a & 0xF000)) { + u32 pixel = PIXEL_ARGB1666( (S->RGB.a & 0xFF00) ? 0xFF : S->RGB.a, + (S->RGB.r & 0xFF00) ? 0xFF : S->RGB.r, + (S->RGB.g & 0xFF00) ? 0xFF : S->RGB.g, + (S->RGB.b & 0xFF00) ? 0xFF : S->RGB.b ); + + D[0] = pixel; + D[1] = pixel >> 8; + D[2] = pixel >> 16; + } + D +=3; + i += SperD; + } +} + +static void Sacc_Sto_Aop_rgb18( GenefxState *gfxs ) +{ + int w = gfxs->length; + int i = gfxs->Xphase; + GenefxAccumulator *Sacc = gfxs->Sacc; + u8 *D = gfxs->Aop[0]; + int SperD = gfxs->SperD; + + while (w--) { + GenefxAccumulator *S = &Sacc[i>>16]; + + if (!(S->RGB.a & 0xF000)) { + u32 pixel = PIXEL_RGB18( (S->RGB.r & 0xFF00) ? 0xFF : S->RGB.r, + (S->RGB.g & 0xFF00) ? 0xFF : S->RGB.g, + (S->RGB.b & 0xFF00) ? 0xFF : S->RGB.b ); + + D[0] = pixel; + D[1] = pixel >> 8; + D[2] = pixel >> 16; + } + D +=3; + i += SperD; + } +} + +static void Sacc_Sto_Aop_rgb24( GenefxState *gfxs ) +{ + int w = gfxs->length; + int i = gfxs->Xphase; + GenefxAccumulator *Sacc = gfxs->Sacc; + u8 *D = gfxs->Aop[0]; + int SperD = gfxs->SperD; + + while (w--) { + GenefxAccumulator *S = &Sacc[i>>16]; + + if (!(S->RGB.a & 0xF000)) { + *D++ = (S->RGB.b & 0xFF00) ? 0xFF : S->RGB.b; + *D++ = (S->RGB.g & 0xFF00) ? 0xFF : S->RGB.g; + *D++ = (S->RGB.r & 0xFF00) ? 0xFF : S->RGB.r; + } + else + D += 3; + + i += SperD; + } +} + +static void Sacc_Sto_Aop_a8( GenefxState *gfxs ) +{ + int w = gfxs->length; + int i = gfxs->Xphase; + GenefxAccumulator *Sacc = gfxs->Sacc; + u8 *D = gfxs->Aop[0]; + int SperD = gfxs->SperD; + + while (w--) { + GenefxAccumulator *S = &Sacc[i>>16]; + + if (!(S->RGB.a & 0xF000)) + *D = (S->RGB.a & 0xFF00) ? 0xFF : S->RGB.a; + + D++; + i += SperD; + } +} + +static void Sacc_Sto_Aop_yuy2( GenefxState *gfxs ) +{ + int l; + int w = gfxs->length; + int i = gfxs->Xphase; + GenefxAccumulator *Sacc = gfxs->Sacc; + u16 *D = gfxs->Aop[0]; + int SperD = gfxs->SperD; + int SperD2 = gfxs->SperD << 1; + + if ((long)D & 2) { + GenefxAccumulator *S = Sacc; + if (!(S->YUV.a & 0xF00)) { + *D = ((S->YUV.y & 0xFF00) ? 0x00FF : S->YUV.y) | + ((S->YUV.v & 0xFF00) ? 0XFF00 : (S->YUV.v<<8)); + } + D++; + w--; + i = SperD; + } + + for (l = w>>1; l--;) { + GenefxAccumulator *S0 = &Sacc[i>>16]; + GenefxAccumulator *S1 = &Sacc[(i+SperD)>>16]; + + if (!(S0->YUV.a & 0xF000) && !(S1->YUV.a & 0xF000)) { + u32 y0, cb, y1, cr; + + y0 = (S0->YUV.y & 0xFF00) ? 0xFF : S0->YUV.y; + y1 = (S1->YUV.y & 0xFF00) ? 0xFF : S1->YUV.y; + + cb = (S0->YUV.u + S1->YUV.u) >> 1; + if (cb & 0xFF00) + cb = 0xFF; + + cr = (S0->YUV.v + S1->YUV.v) >> 1; + if (cr & 0xFF00) + cr = 0xFF; + +#ifdef WORDS_BIGENDIAN + *((u32*)D) = y1 | (cr << 8) | (y0 << 16) | (cb << 24); +#else + *((u32*)D) = y0 | (cb << 8) | (y1 << 16) | (cr << 24); +#endif + } + else if (!(S0->YUV.a & 0xF000)) { + D[0] = ((S0->YUV.y & 0xFF00) ? 0x00FF : S0->YUV.y) | + ((S0->YUV.u & 0xFF00) ? 0xFF00 : (S0->YUV.u<<8)); + } + else if (!(S1->YUV.a & 0xF000)) { + D[1] = ((S1->YUV.y & 0xFF00) ? 0x00FF : S1->YUV.y) | + ((S1->YUV.v & 0xFF00) ? 0xFF00 : (S1->YUV.v<<8)); + } + + D += 2; + i += SperD2; + } + + if (w & 1) { + GenefxAccumulator *S = &Sacc[i>>16]; + if (!(S->YUV.a & 0xF00)) { + *D = ((S->YUV.y & 0xFF00) ? 0x00FF : S->YUV.y) | + ((S->YUV.u & 0xFF00) ? 0xFF00 : (S->YUV.u<<8)); + } + } +} + +static void Sacc_Sto_Aop_rgb332( GenefxState *gfxs ) +{ + int w = gfxs->length; + int i = gfxs->Xphase; + GenefxAccumulator *Sacc = gfxs->Sacc; + u8 *D = gfxs->Aop[0]; + int SperD = gfxs->SperD; + + while (w--) { + GenefxAccumulator *S = &Sacc[i>>16]; + + if (!(S->RGB.a & 0xF000)) { + *D = PIXEL_RGB332( (S->RGB.r & 0xFF00) ? 0xFF : S->RGB.r, + (S->RGB.g & 0xFF00) ? 0xFF : S->RGB.g, + (S->RGB.b & 0xFF00) ? 0xFF : S->RGB.b ); + } + + D++; + i += SperD; + } +} + +static void Sacc_Sto_Aop_uyvy( GenefxState *gfxs ) +{ + int l; + int w = gfxs->length; + int i = gfxs->Xphase; + GenefxAccumulator *Sacc = gfxs->Sacc; + u16 *D = gfxs->Aop[0]; + int SperD = gfxs->SperD; + int SperD2 = gfxs->SperD << 1; + + if ((long)D & 2) { + GenefxAccumulator *S = Sacc; + if (!(S->YUV.a & 0xF00)) { + *D = ((S->YUV.v & 0xFF00) ? 0x00FF : S->YUV.v) | + ((S->YUV.y & 0xFF00) ? 0xFF00 : (S->YUV.y<<8)); + } + D++; + w--; + i = SperD; + } + + for (l = w>>1; l--;) { + GenefxAccumulator *S0 = &Sacc[i>>16]; + GenefxAccumulator *S1 = &Sacc[(i+SperD)>>16]; + + if (!(S0->YUV.a & 0xF000) && !(S1->YUV.a & 0xF000)) { + u32 cb, y0, cr, y1; + + y0 = (S0->YUV.y & 0xFF00) ? 0xFF : S0->YUV.y; + y1 = (S1->YUV.y & 0xFF00) ? 0xFF : S1->YUV.y; + + cb = (S0->YUV.u + S1->YUV.u) >> 1; + if (cb & 0xFF00) + cb = 0xFF; + + cr = (S0->YUV.v + S1->YUV.v) >> 1; + if (cr & 0xFF00) + cr = 0xFF; + +#ifdef WORDS_BIGENDIAN + *((u32*)D) = cr | (y1 << 8) | (cb << 16) | (y0 << 24); +#else + *((u32*)D) = cb | (y0 << 8) | (cr << 16) | (y1 << 24); +#endif + } + else if (!(S0->YUV.a & 0xF000)) { + D[0] = ((S0->YUV.u & 0xFF00) ? 0x00FF : S0->YUV.u) | + ((S0->YUV.y & 0xFF00) ? 0xFF00 : (S0->YUV.y<<8)); + } + else if (!(S1->YUV.a & 0xF000)) { + D[1] = ((S1->YUV.v & 0xFF00) ? 0x00FF : S1->YUV.v) | + ((S1->YUV.y & 0xFF00) ? 0xFF00 : (S1->YUV.y<<8)); + } + + D += 2; + i += SperD2; + } + + if (w & 1) { + GenefxAccumulator *S = &Sacc[i>>16]; + if (!(S->YUV.a & 0xF00)) { + *D = ((S->YUV.u & 0xFF00) ? 0x00FF : S->YUV.u) | + ((S->YUV.y & 0xFF00) ? 0xFF00 : (S->YUV.y<<8)); + } + } +} + +static void Sacc_Sto_Aop_lut8( GenefxState *gfxs ) +{ + int w = gfxs->length; + int i = gfxs->Xphase; + GenefxAccumulator *Sacc = gfxs->Sacc; + u8 *D = gfxs->Aop[0]; + int SperD = gfxs->SperD; + + while (w--) { + GenefxAccumulator *S = &Sacc[i>>16]; + + if (!(S->RGB.a & 0xF000)) { + *D = dfb_palette_search( gfxs->Alut, + (S->RGB.r & 0xFF00) ? 0xFF : S->RGB.r, + (S->RGB.g & 0xFF00) ? 0xFF : S->RGB.g, + (S->RGB.b & 0xFF00) ? 0xFF : S->RGB.b, + (S->RGB.a & 0xFF00) ? 0xFF : S->RGB.a ); + } + + D++; + i += SperD; + } +} + +static void Sacc_Sto_Aop_alut44( GenefxState *gfxs ) +{ + int w = gfxs->length; + int i = gfxs->Xphase; + GenefxAccumulator *Sacc = gfxs->Sacc; + u8 *D = gfxs->Aop[0]; + int SperD = gfxs->SperD; + + while (w--) { + GenefxAccumulator *S = &Sacc[i>>16]; + + if (!(S->RGB.a & 0xF000)) { + *D = (S->RGB.a & 0xFF00) ? 0xF0 : (S->RGB.a & 0xF0) + + dfb_palette_search( gfxs->Alut, + (S->RGB.r & 0xFF00) ? 0xFF : S->RGB.r, + (S->RGB.g & 0xFF00) ? 0xFF : S->RGB.g, + (S->RGB.b & 0xFF00) ? 0xFF : S->RGB.b, + 0x80 ); + } + + D++; + i += SperD; + } +} + +static void Sacc_Sto_Aop_i420( GenefxState *gfxs ) +{ + int i = gfxs->Xphase; + int w = gfxs->length; + GenefxAccumulator *Sacc = gfxs->Sacc; + u8 *Dy = gfxs->Aop[0]; + int SperD = gfxs->SperD; + + while (w--) { + GenefxAccumulator *S = &Sacc[i>>16]; + + if (!(S->YUV.a & 0xF000)) + *Dy = (S->YUV.y & 0xFF00) ? 0xFF : S->YUV.y; + + Dy++; + i += SperD; + } + + if (gfxs->AopY & 1) { + u8 *Du = gfxs->Aop[1]; + u8 *Dv = gfxs->Aop[2]; + + w = gfxs->length>>1; + i = gfxs->Xphase>>1; + + while (w--) { + GenefxAccumulator *S0 = &Sacc[i>>16]; + GenefxAccumulator *S1 = &Sacc[(i+SperD)>>16]; + + if (!(S0->YUV.a & 0xF000) && !(S1->YUV.a & 0xF000)) { + u32 tmp; + + tmp = (S0->YUV.u + S1->YUV.u) >> 1; + if (tmp & 0xFF00) + tmp = 0xFF; + *Du = tmp; + + tmp = (S0->YUV.v + S1->YUV.v) >> 1; + if (tmp & 0xFF00) + tmp = 0xFF; + *Dv = tmp; + + } + else if (!(S0->YUV.a & 0xF000)) { + *Du = (*Du + ((S0->YUV.u & 0xFF00) ? 0xFF : S0->YUV.u)) >> 1; + *Dv = (*Dv + ((S0->YUV.v & 0xFF00) ? 0xFF : S0->YUV.v)) >> 1; + } + else if (!(S1->YUV.a & 0xF000)) { + *Du = (*Du + ((S1->YUV.u & 0xFF00) ? 0xFF : S1->YUV.u)) >> 1; + *Dv = (*Dv + ((S1->YUV.v & 0xFF00) ? 0xFF : S1->YUV.v)) >> 1; + } + + Du++; + Dv++; + i += SperD << 1; + } + } +} + +static void Sacc_Sto_Aop_nv12( GenefxState *gfxs ) +{ + int i = gfxs->Xphase; + int w = gfxs->length; + GenefxAccumulator *Sacc = gfxs->Sacc; + u8 *Dy = gfxs->Aop[0]; + int SperD = gfxs->SperD; + + while (w--) { + GenefxAccumulator *S = &Sacc[i>>16]; + + if (!(S->YUV.a & 0xF000)) + *Dy = (S->YUV.y & 0xFF00) ? 0xFF : S->YUV.y; + + Dy++; + i += SperD; + } + + if (gfxs->dst_format == DSPF_NV16 || gfxs->AopY & 1) { + u16 *Duv = gfxs->Aop[1]; + + w = gfxs->length>>1; + i = gfxs->Xphase>>1; + + while (w--) { + GenefxAccumulator *S0 = &Sacc[i>>16]; + GenefxAccumulator *S1 = &Sacc[(i+SperD)>>16]; + u32 cb, cr; + + if (!(S0->YUV.a & 0xF000) && !(S1->YUV.a & 0xF000)) { + cb = (S0->YUV.u + S1->YUV.u) >> 1; + if (cb & 0xFF00) + cb = 0xFF; + + cr = (S0->YUV.v + S1->YUV.v) >> 1; + if (cr & 0xFF00) + cr = 0xFF; + +#ifdef WORDS_BIGENDIAN + *Duv = cr | (cb << 8); + } + else if (!(S0->YUV.a & 0xF000)) { + cb = ((*Duv >> 8) + ((S0->YUV.u & 0xFF00) ? 0xFF : S0->YUV.u)) >> 1; + cr = ((*Duv & 0xFF) + ((S0->YUV.v & 0xFF00) ? 0xFF : S0->YUV.v)) >> 1; + *Duv = cr | (cb << 8); + } + else if (!(S1->YUV.a & 0xF000)) { + cb = ((*Duv >> 8) + ((S1->YUV.u & 0xFF00) ? 0xFF : S1->YUV.u)) >> 1; + cr = ((*Duv & 0xFF) + ((S1->YUV.v & 0xFF00) ? 0xFF : S1->YUV.v)) >> 1; + *Duv = cr | (cb << 8); + } +#else + *Duv = cb | (cr << 8); + } + else if (!(S0->YUV.a & 0xF000)) { + cb = ((*Duv & 0xFF) + ((S0->YUV.u & 0xFF00) ? 0xFF : S0->YUV.u)) >> 1; + cr = ((*Duv >> 8) + ((S0->YUV.v & 0xFF00) ? 0xFF : S0->YUV.v)) >> 1; + *Duv = cb | (cr << 8); + } + else if (!(S1->YUV.a & 0xF000)) { + cb = ((*Duv & 0xFF) + ((S1->YUV.u & 0xFF00) ? 0xFF : S1->YUV.u)) >> 1; + cr = ((*Duv >> 8) + ((S1->YUV.v & 0xFF00) ? 0xFF : S1->YUV.v)) >> 1; + *Duv = cb | (cr << 8); + } +#endif + + Duv++; + + i += SperD << 1; + } + } +} + +static void Sacc_Sto_Aop_nv21( GenefxState *gfxs ) +{ + int i = gfxs->Xphase; + int w = gfxs->length; + GenefxAccumulator *Sacc = gfxs->Sacc; + u8 *Dy = gfxs->Aop[0]; + int SperD = gfxs->SperD; + + while (w--) { + GenefxAccumulator *S = &Sacc[i>>16]; + + if (!(S->YUV.a & 0xF000)) + *Dy = (S->YUV.y & 0xFF00) ? 0xFF : S->YUV.y; + + Dy++; + i += SperD; + } + + if (gfxs->dst_format == DSPF_NV16 || gfxs->AopY & 1) { + u16 *Dvu = gfxs->Aop[1]; + + w = gfxs->length>>1; + i = gfxs->Xphase>>1; + + while (w--) { + GenefxAccumulator *S0 = &Sacc[i>>16]; + GenefxAccumulator *S1 = &Sacc[(i+SperD)>>16]; + u32 cb, cr; + + if (!(S0->YUV.a & 0xF000) && !(S1->YUV.a & 0xF000)) { + cb = (S0->YUV.u + S1->YUV.u) >> 1; + if (cb & 0xFF00) + cb = 0xFF; + + cr = (S0->YUV.v + S1->YUV.v) >> 1; + if (cr & 0xFF00) + cr = 0xFF; + +#ifdef WORDS_BIGENDIAN + *Dvu = cb | (cr << 8); + } + else if (!(S0->YUV.a & 0xF000)) { + cb = ((*Dvu & 0xFF) + ((S0->YUV.u & 0xFF00) ? 0xFF : S0->YUV.u)) >> 1; + cr = ((*Dvu >> 8) + ((S0->YUV.v & 0xFF00) ? 0xFF : S0->YUV.v)) >> 1; + *Dvu = cb | (cr << 8); + } + else if (!(S1->YUV.a & 0xF000)) { + cb = ((*Dvu & 0xFF) + ((S1->YUV.u & 0xFF00) ? 0xFF : S1->YUV.u)) >> 1; + cr = ((*Dvu >> 8) + ((S1->YUV.v & 0xFF00) ? 0xFF : S1->YUV.v)) >> 1; + *Dvu = cb | (cr << 8); + } +#else + *Dvu = cr | (cb << 8); + } + else if (!(S0->YUV.a & 0xF000)) { + cb = ((*Dvu >> 8) + ((S0->YUV.u & 0xFF00) ? 0xFF : S0->YUV.u)) >> 1; + cr = ((*Dvu & 0xFF) + ((S0->YUV.v & 0xFF00) ? 0xFF : S0->YUV.v)) >> 1; + *Dvu = cr | (cb << 8); + } + else if (!(S1->YUV.a & 0xF000)) { + cb = ((*Dvu >> 8) + ((S1->YUV.u & 0xFF00) ? 0xFF : S1->YUV.u)) >> 1; + cr = ((*Dvu & 0xFF) + ((S1->YUV.v & 0xFF00) ? 0xFF : S1->YUV.v)) >> 1; + *Dvu = cr | (cb << 8); + } +#endif + + Dvu++; + + i += SperD << 1; + } + } +} + +static void Sacc_Sto_Aop_ayuv( GenefxState *gfxs ) +{ + int w = gfxs->length; + int i = gfxs->Xphase; + GenefxAccumulator *Sacc = gfxs->Sacc; + u32 *D = gfxs->Aop[0]; + int SperD = gfxs->SperD; + + while (w--) { + GenefxAccumulator *S = &Sacc[i>>16]; + + if (!(S->YUV.a & 0xF000)) { + *D = PIXEL_AYUV( (S->YUV.a & 0xFF00) ? 0xFF : S->YUV.a, + (S->YUV.y & 0xFF00) ? 0xFF : S->YUV.y, + (S->YUV.u & 0xFF00) ? 0xFF : S->YUV.u, + (S->YUV.v & 0xFF00) ? 0xFF : S->YUV.v ); + } + + D++; + i += SperD; + } +} + + +static GenefxFunc Sacc_Sto_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + Sacc_Sto_Aop_argb1555, /* DSPF_ARGB1555 */ + Sacc_Sto_Aop_rgb16, /* DSPF_RGB16 */ + Sacc_Sto_Aop_rgb24, /* DSPF_RGB24 */ + Sacc_Sto_Aop_rgb32, /* DSPF_RGB32 */ + Sacc_Sto_Aop_argb, /* DSPF_ARGB */ + Sacc_Sto_Aop_a8, /* DSPF_A8 */ + Sacc_Sto_Aop_yuy2, /* DSPF_YUY2 */ + Sacc_Sto_Aop_rgb332, /* DSPF_RGB332 */ + Sacc_Sto_Aop_uyvy, /* DSPF_UYVY */ + Sacc_Sto_Aop_i420, /* DSPF_I420 */ + Sacc_Sto_Aop_i420, /* DSPF_YV12 */ + Sacc_Sto_Aop_lut8, /* DSPF_LUT8 */ + Sacc_Sto_Aop_alut44, /* DSPF_ALUT44 */ + Sacc_Sto_Aop_airgb, /* DSPF_AiRGB */ + NULL, /* DSPF_A1 */ + Sacc_Sto_Aop_nv12, /* DSPF_NV12 */ + Sacc_Sto_Aop_nv12, /* DSPF_NV16 */ + Sacc_Sto_Aop_argb2554, /* DSPF_ARGB2554 */ + Sacc_Sto_Aop_argb4444, /* DSPF_ARGB4444 */ + Sacc_Sto_Aop_rgba4444, /* DSPF_RGBA4444 */ + Sacc_Sto_Aop_nv21, /* DSPF_NV21 */ + Sacc_Sto_Aop_ayuv, /* DSPF_AYUV */ + NULL, /* DSPF_A4 */ + Sacc_Sto_Aop_argb1666, /* DSPF_ARGB1666 */ + Sacc_Sto_Aop_argb6666, /* DSPF_ARGB6666 */ + Sacc_Sto_Aop_rgb18, /* DSPF_RGB18 */ + NULL, /* DSPF_LUT2 */ + Sacc_Sto_Aop_xrgb4444, /* DSPF_RGB444 */ + Sacc_Sto_Aop_xrgb1555, /* DSPF_RGB555 */ + Sacc_Sto_Aop_xbgr1555, /* DSPF_BGR555 */ +}; + +/********************************* Sacc_toK_Aop_PFI ***************************/ + +static void Sacc_toK_Aop_argb6666( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *S = gfxs->Sacc; + u8 *D = gfxs->Aop[0]; + u32 Dkey = gfxs->Dkey; + + while (w--) { + if (!(S->RGB.a & 0xF000) && Dkey == ((u32)(D[2]<<16 | D[1]<<8 | D[0]) & 0x3FFFF)) { + u32 pixel = PIXEL_ARGB6666( (S->RGB.a & 0xFF00) ? 0xFF : S->RGB.a, + (S->RGB.r & 0xFF00) ? 0xFF : S->RGB.r, + (S->RGB.g & 0xFF00) ? 0xFF : S->RGB.g, + (S->RGB.b & 0xFF00) ? 0xFF : S->RGB.b ); + + D[0] = pixel; + D[1] = pixel >> 8; + D[2] = pixel >> 16; + } + D +=3; + S++; + } +} + +static void Sacc_toK_Aop_argb1666( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *S = gfxs->Sacc; + u8 *D = gfxs->Aop[0]; + u32 Dkey = gfxs->Dkey; + + while (w--) { + if (!(S->RGB.a & 0xF000) && Dkey == ((u32)(D[2]<<16 | D[1]<<8 | D[0]) & 0x3FFFF)) { + u32 pixel = PIXEL_ARGB1666( (S->RGB.a & 0xFF00) ? 0xFF : S->RGB.a, + (S->RGB.r & 0xFF00) ? 0xFF : S->RGB.r, + (S->RGB.g & 0xFF00) ? 0xFF : S->RGB.g, + (S->RGB.b & 0xFF00) ? 0xFF : S->RGB.b ); + + D[0] = pixel; + D[1] = pixel >> 8; + D[2] = pixel >> 16; + } + D +=3; + S++; + } +} + +static void Sacc_toK_Aop_rgb18( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *S = gfxs->Sacc; + u8 *D = gfxs->Aop[0]; + u32 Dkey = gfxs->Dkey; + + while (w--) { + if (!(S->RGB.a & 0xF000) && Dkey == ((u32)(D[2]<<16 | D[1]<<8 | D[0]) & 0x3FFFF)) { + u32 pixel = PIXEL_RGB18( (S->RGB.r & 0xFF00) ? 0xFF : S->RGB.r, + (S->RGB.g & 0xFF00) ? 0xFF : S->RGB.g, + (S->RGB.b & 0xFF00) ? 0xFF : S->RGB.b ); + + D[0] = pixel; + D[1] = pixel >> 8; + D[2] = pixel >> 16; + } + D +=3; + S++; + } +} + +static void Sacc_toK_Aop_rgb24( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *S = gfxs->Sacc; + u8 *D = gfxs->Aop[0]; + u8 r = (gfxs->Dkey >> 16); + u8 g = (gfxs->Dkey >> 8) & 0xff; + u8 b = (gfxs->Dkey ) & 0xff; + + while (w--) { + if (!(S->RGB.a & 0xF000) && D[0] == b && D[1] == g && D[2] == r) { + *D++ = (S->RGB.b & 0xFF00) ? 0xFF : S->RGB.b; + *D++ = (S->RGB.g & 0xFF00) ? 0xFF : S->RGB.g; + *D++ = (S->RGB.r & 0xFF00) ? 0xFF : S->RGB.r; + } + else + D += 3; + + S++; + } +} + +static void Sacc_toK_Aop_a8( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *S = gfxs->Sacc; + u8 *D = gfxs->Aop[0]; + + /* FIXME: do all or do none? */ + while (w--) { + if (!(S->RGB.a & 0xF000)) + *D = (S->RGB.a & 0xFF00) ? 0xFF : S->RGB.a; + + D++; + S++; + } +} + +static void Sacc_toK_Aop_yuy2( GenefxState *gfxs ) +{ + int l; + int w = gfxs->length; + GenefxAccumulator *S = gfxs->Sacc; + u16 *D = gfxs->Aop[0]; + u32 Dkey = gfxs->Dkey; +#ifdef WORDS_BIGENDIAN + u16 Dkey0 = gfxs->Dkey >> 16; + u16 Dkey1 = gfxs->Dkey & 0xFFFF; +#else + u16 Dkey0 = gfxs->Dkey & 0xFFFF; + u16 Dkey1 = gfxs->Dkey >> 16; +#endif + + if ((long)D & 2) { + if (!(S->YUV.a & 0xF000) && (*D == Dkey1)) { + *D = ((S->YUV.y & 0xFF00) ? 0x00FF : S->YUV.y) | + ((S->YUV.v & 0xFF00) ? 0xFF00 : (S->YUV.v<<8)); + } + S++; + D++; + w--; + } + + for (l = w>>1; l--;) { + if (*D == Dkey) { + if (!(S[0].YUV.a & 0xF000) && !(S[1].YUV.a & 0xF000)) { + u32 y0, cb, y1, cr; + + y0 = (S[0].YUV.y & 0xFF00) ? 0xFF : S[0].YUV.y; + y1 = (S[1].YUV.y & 0xFF00) ? 0xFF : S[1].YUV.y; + + cb = (S[0].YUV.u + S[1].YUV.u) >> 1; + if (cb & 0xFF00) + cb = 0xFF; + + cr = (S[0].YUV.v + S[1].YUV.v) >> 1; + if (cr & 0xFF00) + cr = 0xFF; + +#ifdef WORDS_BIGENDIAN + *((u32*)D) = y1 | (cr << 8) | (y0 << 16) | (cb << 24); +#else + *((u32*)D) = y0 | (cb << 8) | (y1 << 16) | (cr << 24); +#endif + } + else if (!(S[0].YUV.a & 0xF000)) { + D[0] = ((S[0].YUV.y & 0xFF00) ? 0x00FF : S[0].YUV.y) | + ((S[0].YUV.u & 0xFF00) ? 0xFF00 : (S[0].YUV.u<<8)); + } + else if (!(S[1].YUV.a & 0xF000)) { + D[1] = ((S[1].YUV.y & 0xFF00) ? 0x00FF : S[1].YUV.y) | + ((S[1].YUV.v & 0xFF00) ? 0xFF00 : (S[1].YUV.v<<8)); + } + } + + D += 2; + S += 2; + } + + if (w & 1) { + if (!(S->YUV.a & 0xF000) && (*D == Dkey0)) { + *D = ((S->YUV.y & 0xFF00) ? 0x00FF : S->YUV.y) | + ((S->YUV.u & 0xFF00) ? 0xFF00 : (S->YUV.u<<8)); + } + } +} + +static void Sacc_toK_Aop_rgb332( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *S = gfxs->Sacc; + u8 *D = gfxs->Aop[0]; + u32 Dkey = gfxs->Dkey; + + while (w--) { + if (!(S->RGB.a & 0xF000) && (*D == Dkey)) { + *D = PIXEL_RGB332( (S->RGB.r & 0xFF00) ? 0xFF : S->RGB.r, + (S->RGB.g & 0xFF00) ? 0xFF : S->RGB.g, + (S->RGB.b & 0xFF00) ? 0xFF : S->RGB.b ); + } + + D++; + S++; + } +} + +static void Sacc_toK_Aop_uyvy( GenefxState *gfxs ) +{ + int l; + int w = gfxs->length; + GenefxAccumulator *S = gfxs->Sacc; + u16 *D = gfxs->Aop[0]; + u32 Dkey = gfxs->Dkey; +#ifdef WORDS_BIGENDIAN + u16 Dkey0 = gfxs->Dkey >> 16; + u16 Dkey1 = gfxs->Dkey & 0xFFFF; +#else + u16 Dkey0 = gfxs->Dkey & 0xFFFF; + u16 Dkey1 = gfxs->Dkey >> 16; +#endif + + if ((long)D & 2) { + if (!(S->YUV.a & 0xF000) && (*D == Dkey1)) { + *D = ((S->YUV.v & 0xFF00) ? 0x00FF : S->YUV.v) | + ((S->YUV.y & 0xFF00) ? 0xFF00 : (S->YUV.y<<8)); + } + S++; + D++; + w--; + } + + for (l = w>>1; l--;) { + if (*D == Dkey) { + if (!(S[0].YUV.a & 0xF000) && !(S[1].YUV.a & 0xF000)) { + u32 cb, y0, cr, y1; + + y0 = (S[0].YUV.y & 0xFF00) ? 0xFF : S[0].YUV.y; + y1 = (S[1].YUV.y & 0xFF00) ? 0xFF : S[1].YUV.y; + + cb = (S[0].YUV.u + S[1].YUV.u) >> 1; + if (cb & 0xFF00) + cb = 0xFF; + + cr = (S[0].YUV.v + S[1].YUV.v) >> 1; + if (cr & 0xFF00) + cr = 0xFF; + +#ifdef WORDS_BIGENDIAN + *((u32*)D) = cr | (y1 << 8) | (cb << 16) | (y0 << 24); +#else + *((u32*)D) = cb | (y0 << 8) | (cr << 16) | (y1 << 24); +#endif + } + else if (!(S[0].YUV.a & 0xF000)) { + D[0] = ((S[0].YUV.u & 0xFF00) ? 0x00FF : S[0].YUV.u) | + ((S[0].YUV.y & 0xFF00) ? 0xFF00 : (S[0].YUV.y<<8)); + } + else if (!(S[1].YUV.a & 0xF000)) { + D[1] = ((S[1].YUV.v & 0xFF00) ? 0x00FF : S[1].YUV.v) | + ((S[1].YUV.y & 0xFF00) ? 0xFF00 : (S[1].YUV.y<<8)); + } + } + + D += 2; + S += 2; + } + + if (w & 1) { + if (!(S->YUV.a & 0xF000) && (*D == Dkey0)) { + *D = ((S->YUV.u & 0xFF00) ? 0x00FF : S->YUV.u) | + ((S->YUV.y & 0xFF00) ? 0xFF00 : (S->YUV.y<<8)); + } + } +} + +static void Sacc_toK_Aop_lut8( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *S = gfxs->Sacc; + u8 *D = gfxs->Aop[0]; + u32 Dkey = gfxs->Dkey; + + while (w--) { + if (!(S->RGB.a & 0xF000) && (*D == Dkey)) { + *D = dfb_palette_search( gfxs->Alut, + (S->RGB.r & 0xFF00) ? 0xFF : S->RGB.r, + (S->RGB.g & 0xFF00) ? 0xFF : S->RGB.g, + (S->RGB.b & 0xFF00) ? 0xFF : S->RGB.b, + (S->RGB.a & 0xFF00) ? 0xFF : S->RGB.a ); + } + + D++; + S++; + } +} + +static void Sacc_toK_Aop_alut44( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *S = gfxs->Sacc; + u8 *D = gfxs->Aop[0]; + u32 Dkey = gfxs->Dkey; + + while (w--) { + if (!(S->RGB.a & 0xF000) && ((*D & 0x0F) == Dkey)) { + *D = (S->RGB.a & 0xFF00) ? 0xF0 : (S->RGB.a & 0xF0) + + dfb_palette_search( gfxs->Alut, + (S->RGB.r & 0xFF00) ? 0xFF : S->RGB.r, + (S->RGB.g & 0xFF00) ? 0xFF : S->RGB.g, + (S->RGB.b & 0xFF00) ? 0xFF : S->RGB.b, + 0x80 ); + } + + D++; + S++; + } +} + +static GenefxFunc Sacc_toK_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + Sacc_toK_Aop_argb1555, /* DSPF_ARGB1555 */ + Sacc_toK_Aop_rgb16, /* DSPF_RGB16 */ + Sacc_toK_Aop_rgb24, /* DSPF_RGB24 */ + Sacc_toK_Aop_rgb32, /* DSPF_RGB32 */ + Sacc_toK_Aop_argb, /* DSPF_ARGB */ + Sacc_toK_Aop_a8, /* DSPF_A8 */ + Sacc_toK_Aop_yuy2, /* DSPF_YUY2 */ + Sacc_toK_Aop_rgb332, /* DSPF_RGB332 */ + Sacc_toK_Aop_uyvy, /* DSPF_UYVY */ + NULL, /* DSPF_I420 */ + NULL, /* DSPF_YV12 */ + Sacc_toK_Aop_lut8, /* DSPF_LUT8 */ + Sacc_toK_Aop_alut44, /* DSPF_ALUT44 */ + Sacc_toK_Aop_airgb, /* DSPF_AiRGB */ + NULL, /* DSPF_A1 */ + NULL, /* DSPF_NV12 */ + NULL, /* DSPF_NV16 */ + Sacc_toK_Aop_argb2554, /* DSPF_ARGB2554 */ + Sacc_toK_Aop_argb4444, /* DSPF_ARGB4444 */ + Sacc_toK_Aop_rgba4444, /* DSPF_RGBA4444 */ + NULL, /* DSPF_NV21 */ + NULL, /* DSPF_AYUV */ + NULL, /* DSPF_A4 */ + Sacc_toK_Aop_argb1666, /* DSPF_ARGB1666 */ + Sacc_toK_Aop_argb6666, /* DSPF_ARGB6666 */ + Sacc_toK_Aop_rgb18, /* DSPF_RGB18 */ + NULL, /* DSPF_LUT2 */ + Sacc_toK_Aop_xrgb4444, /* DSPF_RGB444 */ + Sacc_toK_Aop_xrgb1555, /* DSPF_RGB555 */ + Sacc_toK_Aop_xbgr1555, /* DSPF_BGR555 */ +}; + +/********************************* Sacc_StoK_Aop_PFI **************************/ + +static GenefxFunc Sacc_StoK_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + Sacc_StoK_Aop_argb1555, /* DSPF_ARGB1555 */ + Sacc_StoK_Aop_rgb16, /* DSPF_RGB16 */ + NULL, /* DSPF_RGB24 */ + Sacc_StoK_Aop_rgb32, /* DSPF_RGB32 */ + Sacc_StoK_Aop_argb, /* DSPF_ARGB */ + NULL, /* DSPF_A8 */ + NULL, /* DSPF_YUY2 */ + NULL, /* DSPF_RGB332 */ + NULL, /* DSPF_UYVY */ + NULL, /* DSPF_I420 */ + NULL, /* DSPF_YV12 */ + NULL, /* DSPF_LUT8 */ + NULL, /* DSPF_ALUT44 */ + Sacc_StoK_Aop_airgb, /* DSPF_AiRGB */ + NULL, /* DSPF_A1 */ + NULL, /* DSPF_NV12 */ + NULL, /* DSPF_NV16 */ + Sacc_StoK_Aop_argb2554, /* DSPF_ARGB2554 */ + Sacc_StoK_Aop_argb4444, /* DSPF_ARGB4444 */ + Sacc_StoK_Aop_rgba4444, /* DSPF_RGBA4444 */ + NULL, /* DSPF_NV21 */ + NULL, /* DSPF_AYUV */ + NULL, /* DSPF_A4 */ + NULL, /* DSPF_ARGB1666 */ + NULL, /* DSPF_ARGB6666 */ + NULL, /* DSPF_RGB18 */ + NULL, /* DSPF_LUT2 */ + Sacc_StoK_Aop_xrgb4444, /* DSPF_RGB444 */ + Sacc_StoK_Aop_xrgb1555, /* DSPF_RGB555 */ + Sacc_StoK_Aop_xbgr1555, /* DSPF_BGR555 */ +}; + +/************** Bop_a8_set_alphapixel_Aop_PFI *********************************/ + +/* change the last value to adjust the size of the device (1-4) */ +#define SET_PIXEL_DUFFS_DEVICE( D, S, w ) \ + SET_PIXEL_DUFFS_DEVICE_N( D, S, w, 3 ) + + +static void Bop_a8_set_alphapixel_Aop_argb1555( GenefxState *gfxs ) +{ + int w = gfxs->length; + u8 *S = gfxs->Bop[0]; + u16 *D = gfxs->Aop[0]; + u32 Cop = gfxs->Cop; + u32 rb = Cop & 0x7c1f; + u32 g = Cop & 0x03e0; + +#define SET_PIXEL(d,a) \ + switch (a) {\ + case 0xff: d = Cop;\ + case 0: break;\ + default: {\ + register u32 s = (a>>3)+1;\ + register u32 t1 = (d & 0x7c1f);\ + register u32 t2 = (d & 0x03e0);\ + d = ((d) & 0x8000) | ((a & 0x80) << 8) | \ + ((((rb-t1)*s+(t1<<5)) & 0x000f83e0) + \ + ((( g-t2)*s+(t2<<5)) & 0x00007c00)) >> 5;\ + }\ + } + + SET_PIXEL_DUFFS_DEVICE( D, S, w ); + +#undef SET_PIXEL +} + + +static void Bop_a8_set_alphapixel_Aop_rgb16( GenefxState *gfxs ) +{ + int w = gfxs->length; + u8 *S = gfxs->Bop[0]; + u16 *D = gfxs->Aop[0]; + u32 Cop = gfxs->Cop; + u32 rb = Cop & 0xf81f; + u32 g = Cop & 0x07e0; + +#define SET_PIXEL(d,a)\ + switch (a) {\ + case 0xff: d = Cop;\ + case 0: break;\ + default: {\ + register u32 s = (a>>2)+1;\ + register u32 t1 = (d & 0xf81f);\ + register u32 t2 = (d & 0x07e0);\ + d = ((((rb-t1)*s+(t1<<6)) & 0x003e07c0) + \ + ((( g-t2)*s+(t2<<6)) & 0x0001f800)) >> 6;\ + }\ + } + + SET_PIXEL_DUFFS_DEVICE( D, S, w ); + +#undef SET_PIXEL +} + +static void Bop_a8_set_alphapixel_Aop_argb6666( GenefxState *gfxs ) +{ + + int w = gfxs->length; + u8 *S = gfxs->Bop[0]; + u8 *D = gfxs->Aop[0]; + + u32 Cop = gfxs->Cop; + u32 rb = Cop & 0x3f03f; + u32 g = Cop & 0xfc0; + + +#define SET_PIXEL(d,a)\ + switch (a) {\ + case 0xff: d = Cop;\ + case 0: break;\ + default: {\ + register u32 s = (a>>2)+1;\ + register u32 t1 = (d & 0x3f03f);\ + register u32 t2 = (d & 0xfc0);\ + d = ((((rb-t1)*s+(t1<<6)) & 0xfc0fc0) + \ + ((( g-t2)*s+(t2<<6)) & 0xfc000)) >> 6;\ + }\ + } + SET_PIXEL_DUFFS_DEVICE( D, S, w ); + +#undef SET_PIXEL + +} + +static void Bop_a8_set_alphapixel_Aop_argb1666( GenefxState *gfxs ) +{ + int w = gfxs->length; + u8 *S = gfxs->Bop[0]; + u8 *D = gfxs->Aop[0]; + + u32 Cop = gfxs->Cop; + u32 rb = Cop & 0x3f03f; + u32 g = Cop & 0xfc0; + + +#define SET_PIXEL(d,a)\ + switch (a) {\ + case 0xff: d = Cop;\ + case 0: break;\ + default: {\ + register u32 s = (a>>2)+1;\ + register u32 t1 = (d & 0x3f03f);\ + register u32 t2 = (d & 0xfc0);\ + d = ((((rb-t1)*s+(t1<<6)) & 0xfc0fc0) + \ + ((( g-t2)*s+(t2<<6)) & 0xfc000)) >> 6;\ + }\ + } + SET_PIXEL_DUFFS_DEVICE( D, S, w ); + +#undef SET_PIXEL +} + +static void Bop_a8_set_alphapixel_Aop_rgb18( GenefxState *gfxs ) +{ + int w = gfxs->length; + u8 *S = gfxs->Bop[0]; + u8 *D = gfxs->Aop[0]; + + u32 Cop = gfxs->Cop; + u32 rb = Cop & 0x3f03f; + u32 g = Cop & 0xfc0; + + +#define SET_PIXEL(d,a)\ + switch (a) {\ + case 0xff: d = Cop;\ + case 0: break;\ + default: {\ + register u32 s = (a>>2)+1;\ + register u32 t1 = (d & 0x3f03f);\ + register u32 t2 = (d & 0xfc0);\ + d = ((((rb-t1)*s+(t1<<6)) & 0xfc0fc0) + \ + ((( g-t2)*s+(t2<<6)) & 0xfc000)) >> 6;\ + }\ + } + SET_PIXEL_DUFFS_DEVICE( D, S, w ); + +#undef SET_PIXEL + +} + +static void Bop_a8_set_alphapixel_Aop_rgb24( GenefxState *gfxs ) +{ + int w = gfxs->length; + u8 *S = gfxs->Bop[0]; + u8 *D = gfxs->Aop[0]; + DFBColor color = gfxs->color; + +#define SET_PIXEL(d,r,g,b,a)\ + switch (a) {\ + case 0xff:\ + d[0] = b;\ + d[1] = g;\ + d[2] = r;\ + case 0: break;\ + default: {\ + register u16 s = a+1;\ + d[0] = ((b-d[0]) * s + (d[0] << 8)) >> 8;\ + d[1] = ((g-d[1]) * s + (d[1] << 8)) >> 8;\ + d[2] = ((r-d[2]) * s + (d[2] << 8)) >> 8;\ + }\ + } + + while (w>4) { + SET_PIXEL( D, color.r, color.g, color.b, *S ); D+=3; S++; + SET_PIXEL( D, color.r, color.g, color.b, *S ); D+=3; S++; + SET_PIXEL( D, color.r, color.g, color.b, *S ); D+=3; S++; + SET_PIXEL( D, color.r, color.g, color.b, *S ); D+=3; S++; + w-=4; + } + while (w--) { + SET_PIXEL( D, color.r, color.g, color.b, *S ); D+=3, S++; + } + +#undef SET_PIXEL +} + +static void Bop_a8_set_alphapixel_Aop_rgb32( GenefxState *gfxs ) +{ + int w = gfxs->length; + u8 *S = gfxs->Bop[0]; + u32 *D = gfxs->Aop[0]; + u32 Cop = gfxs->Cop; + u32 rb = Cop & 0xff00ff; + u32 g = Cop & 0x00ff00; + +#define SET_PIXEL(d,a)\ + switch (a) {\ + case 0xff: d = Cop;\ + case 0: break;\ + default: {\ + register u32 s = a+1;\ + register u32 t1 = (d & 0x00ff00ff);\ + register u32 t2 = (d & 0x0000ff00);\ + d = ((((rb-t1)*s+(t1<<8)) & 0xff00ff00) + \ + ((( g-t2)*s+(t2<<8)) & 0x00ff0000)) >> 8;\ + }\ + } + + SET_PIXEL_DUFFS_DEVICE( D, S, w ); + +#undef SET_PIXEL +} + + +/* saturating alpha blend */ + +static void Bop_a8_set_alphapixel_Aop_argb( GenefxState *gfxs ) +{ + int w = gfxs->length; + u8 *S = gfxs->Bop[0]; + u32 *D = gfxs->Aop[0]; + u32 Cop = gfxs->Cop | 0xff000000; + u32 rb = Cop & 0x00ff00ff; + u32 g = gfxs->color.g; + +#define SET_PIXEL(d,a)\ + switch (a) {\ + case 0xff: d = Cop;\ + case 0: break;\ + default: {\ + register u32 s = a+1;\ + register u32 s1 = 256-a;\ + register u32 sa = (((d >> 24) * s1) >> 8) + a;\ + d = (sa << 24) + \ + (((((d & 0x00ff00ff) * s1) + (rb * s)) >> 8) & 0x00ff00ff) + \ + (((((d & 0x0000ff00) >> 8) * s1) + ((g) * s)) & 0x0000ff00); \ + }\ + } + + SET_PIXEL_DUFFS_DEVICE( D, S, w ); + +#undef SET_PIXEL +} + +static void Bop_a8_set_alphapixel_Aop_airgb( GenefxState *gfxs ) +{ + int w = gfxs->length; + u8 *S = gfxs->Bop[0]; + u32 *D = gfxs->Aop[0]; + u32 Cop = gfxs->Cop; + u32 rb = Cop & 0x00ff00ff; + u32 g = gfxs->color.g; + +#define SET_PIXEL(d,a)\ + switch (a) {\ + case 0xff: d = Cop;\ + case 0: break;\ + default: {\ + register u32 s = a+1;\ + register u32 s1 = 256-s;\ + register s32 sa = (d >> 24) - a;\ + if (sa < 0) sa = 0;\ + d = (sa << 24) + \ + (((((d & 0x00ff00ff) * s1) + (rb * s)) >> 8) & 0x00ff00ff) + \ + (((((d & 0x0000ff00) >> 8) * s1) + ((g) * s)) & 0x0000ff00); \ + }\ + } + + SET_PIXEL_DUFFS_DEVICE( D, S, w ); + +#undef SET_PIXEL +} + +static void Bop_a8_set_alphapixel_Aop_a8( GenefxState *gfxs ) +{ + int w = gfxs->length; + u8 *S = gfxs->Bop[0]; + u8 *D = gfxs->Aop[0]; + +#define SET_PIXEL(d,a)\ + switch (a) {\ + case 0xff: d = 0xff;\ + case 0: break; \ + default: {\ + register u16 s1 = 255-a;\ + d = ((d * s1) >> 8) + a;\ + }\ + } + + SET_PIXEL_DUFFS_DEVICE( D, S, w ); + +#undef SET_PIXEL +} + +static void Bop_a8_set_alphapixel_Aop_yuy2( GenefxState *gfxs ) +{ + int w = gfxs->length; + u8 *S = gfxs->Bop[0]; + u16 *D = gfxs->Aop[0]; + u32 y = gfxs->YCop; + u32 u = gfxs->CbCop; + u32 v = gfxs->CrCop; + +#ifdef WORDS_BIGENDIAN + u16 Cop0 = u | (y << 8); + u16 Cop1 = v | (y << 8); + +#define SET_PIXEL(d,a)\ + switch (a) {\ + case 0xff:\ + d = ((long)&(d) & 2) ? Cop1 : Cop0;\ + case 0x00: break;\ + default: {\ + register u32 s = a+1;\ + register u32 t1 = d & 0xff;\ + register u32 t2 = d >> 8;\ + if ((long)&(d) & 2)\ + d = (((v-t1)*s+(t1<<8)) >> 8) |\ + (((y-t2)*s+(t2<<8)) & 0xff00);\ + else\ + d = (((u-t1)*s+(t1<<8)) >> 8) |\ + (((y-t2)*s+(t2<<8)) & 0xff00);\ + } break;\ + } +#else + u16 Cop0 = y | (u << 8); + u16 Cop1 = y | (v << 8); + +#define SET_PIXEL(d,a)\ + switch (a) {\ + case 0xff:\ + d = ((long)&(d) & 2) ? Cop1 : Cop0;\ + case 0x00: break;\ + default: {\ + register u32 s = a+1;\ + register u32 t1 = d & 0xff;\ + register u32 t2 = d >> 8;\ + if ((long)&(d) & 2)\ + d = (((y-t1)*s+(t1<<8)) >> 8) |\ + (((v-t2)*s+(t2<<8)) & 0xff00);\ + else\ + d = (((y-t1)*s+(t1<<8)) >> 8) |\ + (((u-t2)*s+(t2<<8)) & 0xff00);\ + } break;\ + } +#endif + + SET_PIXEL_DUFFS_DEVICE( D, S, w ); + +#undef SET_PIXEL +} + +static void Bop_a8_set_alphapixel_Aop_rgb332( GenefxState *gfxs ) +{ + int w = gfxs->length; + u8 *S = gfxs->Bop[0]; + u8 *D = gfxs->Aop[0]; + u32 Cop = gfxs->Cop; + u32 rgb = ((Cop & 0xe0) << 16) | ((Cop & 0x1c) << 8) | (Cop & 0x03); + +#define SET_PIXEL(d,a) \ + switch (a) {\ + case 0xff: d = Cop;\ + case 0: break;\ + default: {\ + register u32 s = a + 1;\ + register u32 t = ((d & 0xe0) << 16) | ((d & 0x1c) << 8) | (d & 0x03);\ + register u32 c = ((rgb-t)*s + (t<<8)) & 0xe01c0300;\ + d = (c >> 24) | ((c >> 16) & 0xff) | ((c >> 8) & 0xff);\ + }\ + } + + SET_PIXEL_DUFFS_DEVICE( D, S, w ); + +#undef SET_PIXEL +} + +static void Bop_a8_set_alphapixel_Aop_uyvy( GenefxState *gfxs ) +{ + int w = gfxs->length; + u8 *S = gfxs->Bop[0]; + u16 *D = gfxs->Aop[0]; + u32 y = gfxs->YCop; + u32 u = gfxs->CbCop; + u32 v = gfxs->CrCop; + u16 Cop0 = u | (y << 8); + u16 Cop1 = v | (y << 8); + +#define SET_PIXEL(d,a)\ + switch (a) {\ + case 0xff: d = ((long)&(d) & 2) ? Cop1 : Cop0;\ + case 0x00: break;\ + default: {\ + register u32 s = a+1;\ + register u32 t1 = d & 0xff;\ + register u32 t2 = d >> 8;\ + if ((long)&(d) & 2)\ + d = (((v-t1)*s+(t1<<8)) >> 8) |\ + (((y-t2)*s+(t2<<8)) & 0xff00);\ + else\ + d = (((u-t1)*s+(t1<<8)) >> 8) |\ + (((y-t2)*s+(t2<<8)) & 0xff00);\ + } break;\ + } + + SET_PIXEL_DUFFS_DEVICE( D, S, w ); + +#undef SET_PIXEL +} + +static void Bop_a8_set_alphapixel_Aop_lut8( GenefxState *gfxs ) +{ + int w = gfxs->length; + u8 *S = gfxs->Bop[0]; + u8 *D = gfxs->Aop[0]; + u32 Cop = gfxs->Cop; + +#if 0 + DFBColor color = gfxs->color; + DFBColor *entries = gfxs->Alut->entries; + +# define SET_PIXEL(d,alpha) \ + switch (alpha) {\ + case 0xff: d = Cop;\ + case 0: break; \ + default: {\ + register u16 s = alpha+1;\ + DFBColor dc = entries[d];\ + u16 sa = alpha + dc.a;\ + dc.r = ((color.r - dc.r) * s + (dc.r << 8)) >> 8;\ + dc.g = ((color.g - dc.g) * s + (dc.g << 8)) >> 8;\ + dc.b = ((color.b - dc.b) * s + (dc.b << 8)) >> 8;\ + d = dfb_palette_search( gfxs->Alut, dc.r, dc.g, dc.b,\ + sa & 0xff00 ? 0xff : sa );\ + }\ + } +#else +# define SET_PIXEL(d,a) \ + if (a & 0x80) \ + d = Cop; +#endif + + SET_PIXEL_DUFFS_DEVICE( D, S, w ); + +#undef SET_PIXEL +} + +static void Bop_a8_set_alphapixel_Aop_alut44( GenefxState *gfxs ) +{ + int w = gfxs->length; + u8 *S = gfxs->Bop[0]; + u8 *D = gfxs->Aop[0]; + u32 Cop = gfxs->Cop; + + DFBColor color = gfxs->color; + DFBColor *entries = gfxs->Alut->entries; + +#define SET_PIXEL(d,alpha) \ + switch (alpha) {\ + case 0xff: d = Cop;\ + case 0: break; \ + default: {\ + register u16 s = alpha+1;\ + DFBColor dc = entries[d & 0x0f];\ + u16 sa = (d & 0xf0) + alpha;\ + dc.r = ((color.r - dc.r) * s + (dc.r << 8)) >> 8;\ + dc.g = ((color.g - dc.g) * s + (dc.g << 8)) >> 8;\ + dc.b = ((color.b - dc.b) * s + (dc.b << 8)) >> 8;\ + if (sa & 0xff00) sa = 0xf0;\ + d = (sa & 0xf0) + \ + dfb_palette_search( gfxs->Alut, dc.r, dc.g, dc.b, 0x80 );\ + }\ + } + + while (w--) { + SET_PIXEL( *D, *S ); + D++, S++; + } + +#undef SET_PIXEL +} + +#undef SET_PIXEL_DUFFS_DEVICE + +static GenefxFunc Bop_a8_set_alphapixel_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + Bop_a8_set_alphapixel_Aop_argb1555, /* DSPF_ARGB1555 */ + Bop_a8_set_alphapixel_Aop_rgb16, /* DSPF_RGB16 */ + Bop_a8_set_alphapixel_Aop_rgb24, /* DSPF_RGB24 */ + Bop_a8_set_alphapixel_Aop_rgb32, /* DSPF_RGB32 */ + Bop_a8_set_alphapixel_Aop_argb, /* DSPF_ARGB */ + Bop_a8_set_alphapixel_Aop_a8, /* DSPF_A8 */ + Bop_a8_set_alphapixel_Aop_yuy2, /* DSPF_YUY2 */ + Bop_a8_set_alphapixel_Aop_rgb332, /* DSPF_RGB332 */ + Bop_a8_set_alphapixel_Aop_uyvy, /* DSPF_UYVY */ + NULL, /* DSPF_I420 */ + NULL, /* DSPF_YV12 */ + Bop_a8_set_alphapixel_Aop_lut8, /* DSPF_LUT8 */ + Bop_a8_set_alphapixel_Aop_alut44, /* DSPF_ALUT44 */ + Bop_a8_set_alphapixel_Aop_airgb, /* DSPF_AiRGB */ + NULL, /* DSPF_A1 */ + NULL, /* DSPF_NV12 */ + NULL, /* DSPF_NV16 */ + NULL, /* DSPF_ARGB2554 */ + NULL, /* DSPF_ARGB4444 */ + NULL, /* DSPF_RGBA4444 */ + NULL, /* DSPF_NV21 */ + Bop_a8_set_alphapixel_Aop_argb, /* DSPF_AYUV */ + NULL, /* DSPF_A4 */ + Bop_a8_set_alphapixel_Aop_argb1666, /* DSPF_ARGB1666 */ + Bop_a8_set_alphapixel_Aop_argb6666, /* DSPF_ARGB6666 */ + Bop_a8_set_alphapixel_Aop_rgb18, /* DSPF_RGB18 */ + NULL, /* DSPF_LUT2 */ + NULL, /* DSPF_ARGB4444 */ + NULL, /* DSPF_ARGB1555 */ + NULL /* DSPF_ARGB1555 */ +}; + +/************** Bop_a1_set_alphapixel_Aop_PFI *********************************/ + +static void Bop_a1_set_alphapixel_Aop_argb1555( GenefxState *gfxs ) +{ + int i; + int w = gfxs->length; + u8 *S = gfxs->Bop[0]; + u16 *D = gfxs->Aop[0]; + u16 Cop = gfxs->Cop | 0x8000; + + for (i=0; i>3] & (0x80 >> (i&7))) + D[i] = Cop; + } +} + +static void Bop_a1_set_alphapixel_Aop_rgb16( GenefxState *gfxs ) +{ + int i; + int w = gfxs->length; + u8 *S = gfxs->Bop[0]; + u16 *D = gfxs->Aop[0]; + u16 Cop = gfxs->Cop; + + for (i=0; i>3] & (0x80 >> (i&7))) + D[i] = Cop; + } +} + +static void Bop_a1_set_alphapixel_Aop_argb6666( GenefxState *gfxs ) +{ + int i; + int w = gfxs->length; + u8 *S = gfxs->Bop[0]; + u8 *D = gfxs->Aop[0]; + DFBColor color = gfxs->color; + + for (i=0; i>3] & (0x80 >> (i&7))) { + u32 pixel = PIXEL_ARGB6666( color.a, color.r, color.g, color.b ); + + D[0] = pixel; + D[1] = pixel >> 8; + D[2] = pixel >> 16; + } + D += 3; + } + +} + +static void Bop_a1_set_alphapixel_Aop_argb1666( GenefxState *gfxs ) +{ + int i; + int w = gfxs->length; + u8 *S = gfxs->Bop[0]; + u8 *D = gfxs->Aop[0]; + DFBColor color = gfxs->color; + + for (i=0; i>3] & (0x80 >> (i&7))) { + u32 pixel = PIXEL_ARGB1666( color.a, color.r, color.g, color.b ); + + D[0] = pixel; + D[1] = pixel >> 8; + D[2] = pixel >> 16; + } + D += 3; + } + +} + +static void Bop_a1_set_alphapixel_Aop_rgb18( GenefxState *gfxs ) +{ + int i; + int w = gfxs->length; + u8 *S = gfxs->Bop[0]; + u8 *D = gfxs->Aop[0]; + DFBColor color = gfxs->color; + + for (i=0; i>3] & (0x80 >> (i&7))) { + u32 pixel = PIXEL_RGB18( color.r, color.g, color.b ); + + D[0] = pixel; + D[1] = pixel >> 8; + D[2] = pixel >> 16; + } + D += 3; + } + +} + +static void Bop_a1_set_alphapixel_Aop_rgb24( GenefxState *gfxs ) +{ + int i; + int w = gfxs->length; + u8 *S = gfxs->Bop[0]; + u8 *D = gfxs->Aop[0]; + DFBColor color = gfxs->color; + + for (i=0; i>3] & (0x80 >> (i&7))) { + D[0] = color.b; + D[1] = color.g; + D[2] = color.r; + } + + D += 3; + } +} + +static void Bop_a1_set_alphapixel_Aop_rgb32( GenefxState *gfxs ) +{ + int i; + int w = gfxs->length; + u8 *S = gfxs->Bop[0]; + u32 *D = gfxs->Aop[0]; + u32 Cop = gfxs->Cop; + + for (i=0; i>3] & (0x80 >> (i&7))) + D[i] = Cop; + } +} + +static void Bop_a1_set_alphapixel_Aop_argb( GenefxState *gfxs ) +{ + int i; + int w = gfxs->length; + u8 *S = gfxs->Bop[0]; + u32 *D = gfxs->Aop[0]; + u32 Cop = gfxs->Cop | 0xFF000000; + + for (i=0; i>3] & (0x80 >> (i&7))) + D[i] = Cop; + } +} + +static void Bop_a1_set_alphapixel_Aop_airgb( GenefxState *gfxs ) +{ + int i; + int w = gfxs->length; + u8 *S = gfxs->Bop[0]; + u32 *D = gfxs->Aop[0]; + u32 Cop = gfxs->Cop & 0x00FFFFFF; + + for (i=0; i>3] & (0x80 >> (i&7))) + D[i] = Cop; + } +} + +static void Bop_a1_set_alphapixel_Aop_a8( GenefxState *gfxs ) +{ + int i; + int w = gfxs->length; + u8 *S = gfxs->Bop[0]; + u8 *D = gfxs->Aop[0]; + + for (i=0; i>3] & (0x80 >> (i&7))) + D[i] = 0xff; + } +} + +static void Bop_a1_set_alphapixel_Aop_yuy2( GenefxState *gfxs ) +{ + int i; + int w = gfxs->length; + u8 *S = gfxs->Bop[0]; + u16 *D = gfxs->Aop[0]; + u16 Cop0 = gfxs->YCop | (gfxs->CbCop << 8); + u16 Cop1 = gfxs->YCop | (gfxs->CrCop << 8); + + for (i=0; i>3] & (0x80 >> (i&7))) { + D[i] = ((long)&D[i] & 2) ? Cop1 : Cop0; + } + } +} + +static void Bop_a1_set_alphapixel_Aop_rgb332( GenefxState *gfxs ) +{ + int i; + int w = gfxs->length; + u8 *S = gfxs->Bop[0]; + u8 *D = gfxs->Aop[0]; + u8 Cop = gfxs->Cop; + + for (i=0; i>3] & (0x80 >> (i&7))) + D[i] = Cop; + } +} + +static void Bop_a1_set_alphapixel_Aop_uyvy( GenefxState *gfxs ) +{ + int i; + int w = gfxs->length; + u8 *S = gfxs->Bop[0]; + u16 *D = gfxs->Aop[0]; + u16 Cop0 = gfxs->CbCop | (gfxs->YCop << 8); + u16 Cop1 = gfxs->CrCop | (gfxs->YCop << 8); + + for (i=0; i>3] & (0x80 >> (i&7))) { + D[i] = ((long)&D[i] & 2) ? Cop1 : Cop0; + } + } +} + +static void Bop_a1_set_alphapixel_Aop_lut8( GenefxState *gfxs ) +{ + int i; + int w = gfxs->length; + u8 *S = gfxs->Bop[0]; + u8 *D = gfxs->Aop[0]; + u8 Cop = gfxs->Cop; + + for (i=0; i>3] & (0x80 >> (i&7))) + D[i] = Cop; + } +} + +static void Bop_a1_set_alphapixel_Aop_alut44( GenefxState *gfxs ) +{ + int i; + int w = gfxs->length; + u8 *S = gfxs->Bop[0]; + u8 *D = gfxs->Aop[0]; + u8 Cop = gfxs->Cop; + + for (i=0; i>3] & (0x80 >> (i&7))) + D[i] = Cop; + } +} + +static void Bop_a1_set_alphapixel_Aop_argb2554( GenefxState *gfxs ) +{ + int i; + int w = gfxs->length; + u8 *S = gfxs->Bop[0]; + u16 *D = gfxs->Aop[0]; + u16 Cop = gfxs->Cop | 0xC000; + + for (i=0; i>3] & (0x80 >> (i&7))) + D[i] = Cop; + } +} + +static void Bop_a1_set_alphapixel_Aop_argb4444( GenefxState *gfxs ) +{ + int i; + int w = gfxs->length; + u8 *S = gfxs->Bop[0]; + u16 *D = gfxs->Aop[0]; + u16 Cop = gfxs->Cop | 0xF000; + + for (i=0; i>3] & (0x80 >> (i&7))) + D[i] = Cop; + } +} + +static void Bop_a1_set_alphapixel_Aop_rgba4444( GenefxState *gfxs ) +{ + int i; + int w = gfxs->length; + u8 *S = gfxs->Bop[0]; + u16 *D = gfxs->Aop[0]; + u16 Cop = gfxs->Cop | 0x000F; + + for (i=0; i>3] & (0x80 >> (i&7))) + D[i] = Cop; + } +} + +static GenefxFunc Bop_a1_set_alphapixel_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + Bop_a1_set_alphapixel_Aop_argb1555, /* DSPF_ARGB1555 */ + Bop_a1_set_alphapixel_Aop_rgb16, /* DSPF_RGB16 */ + Bop_a1_set_alphapixel_Aop_rgb24, /* DSPF_RGB24 */ + Bop_a1_set_alphapixel_Aop_rgb32, /* DSPF_RGB32 */ + Bop_a1_set_alphapixel_Aop_argb, /* DSPF_ARGB */ + Bop_a1_set_alphapixel_Aop_a8, /* DSPF_A8 */ + Bop_a1_set_alphapixel_Aop_yuy2, /* DSPF_YUY2 */ + Bop_a1_set_alphapixel_Aop_rgb332, /* DSPF_RGB332 */ + Bop_a1_set_alphapixel_Aop_uyvy, /* DSPF_UYVY */ + NULL, /* DSPF_I420 */ + NULL, /* DSPF_YV12 */ + Bop_a1_set_alphapixel_Aop_lut8, /* DSPF_LUT8 */ + Bop_a1_set_alphapixel_Aop_alut44, /* DSPF_ALUT44 */ + Bop_a1_set_alphapixel_Aop_airgb, /* DSPF_AiRGB */ + NULL, /* DSPF_A1 */ + NULL, /* DSPF_NV12 */ + NULL, /* DSPF_NV16 */ + Bop_a1_set_alphapixel_Aop_argb2554, /* DSPF_ARGB2554 */ + Bop_a1_set_alphapixel_Aop_argb4444, /* DSPF_ARGB4444 */ + Bop_a1_set_alphapixel_Aop_rgba4444, /* DSPF_RGBA4444 */ + NULL, /* DSPF_NV21 */ + Bop_a1_set_alphapixel_Aop_argb, /* DSPF_AYUV */ + NULL, /* DSPF_A4 */ + Bop_a1_set_alphapixel_Aop_argb1666, /* DSPF_ARGB1666 */ + Bop_a1_set_alphapixel_Aop_argb6666, /* DSPF_ARGB6666 */ + Bop_a1_set_alphapixel_Aop_rgb18, /* DSPF_RGB18 */ + NULL, /* DSPF_LUT2 */ + NULL, /* DSPF_RGB444 */ + NULL, /* DSPF_RGB555 */ + NULL, /* DSPF_BGR555 */ +}; + + +/**************************** Bop_translate_to_Aop ****************************/ + +static void Bop_lut2_translate_to_Aop_lut8( GenefxState *gfxs ) +{ + int i; + int w = gfxs->length; + int W = (w + 3) / 4; + u8 *S = gfxs->Bop[0]; + u8 *D = gfxs->Aop[0]; + + for (i=0; inum_trans && gfxs->trans[index] >= 0) + D[3] = gfxs->trans[index]; + + case 3: + index = (pixels >> 2) & 3; + if (index < gfxs->num_trans && gfxs->trans[index] >= 0) + D[2] = gfxs->trans[index]; + + case 2: + index = (pixels >> 4) & 3; + if (index < gfxs->num_trans && gfxs->trans[index] >= 0) + D[1] = gfxs->trans[index]; + + case 1: + index = (pixels >> 6); + if (index < gfxs->num_trans && gfxs->trans[index] >= 0) + D[0] = gfxs->trans[index]; + } + } +} + +/********************************* Xacc_blend *********************************/ + +static void Xacc_blend_zero( GenefxState *gfxs ) +{ + int i; + int w = gfxs->length; + GenefxAccumulator *X = gfxs->Xacc; + GenefxAccumulator *Y = gfxs->Yacc; + + for (i=0; ilength; + GenefxAccumulator *X = gfxs->Xacc; + GenefxAccumulator *Y = gfxs->Yacc; + + for (i=0; ilength; + GenefxAccumulator *X = gfxs->Xacc; + GenefxAccumulator *Y = gfxs->Yacc; + + if (gfxs->Sacc) { + GenefxAccumulator *S = gfxs->Sacc; + + while (w--) { + if (!(Y->RGB.a & 0xF000)) { + X->RGB.r = ((S->RGB.r + 1) * Y->RGB.r) >> 8; + X->RGB.g = ((S->RGB.g + 1) * Y->RGB.g) >> 8; + X->RGB.b = ((S->RGB.b + 1) * Y->RGB.b) >> 8; + X->RGB.a = ((S->RGB.a + 1) * Y->RGB.a) >> 8; + } else + *X = *Y; + + X++; + Y++; + S++; + } + } + else { + GenefxAccumulator Cacc = gfxs->Cacc; + Cacc.RGB.r = Cacc.RGB.r + 1; + Cacc.RGB.g = Cacc.RGB.g + 1; + Cacc.RGB.b = Cacc.RGB.b + 1; + Cacc.RGB.a = Cacc.RGB.a + 1; + + while (w--) { + if (!(Y->RGB.a & 0xF000)) { + X->RGB.r = (Cacc.RGB.r * Y->RGB.r) >> 8; + X->RGB.g = (Cacc.RGB.g * Y->RGB.g) >> 8; + X->RGB.b = (Cacc.RGB.b * Y->RGB.b) >> 8; + X->RGB.a = (Cacc.RGB.a * Y->RGB.a) >> 8; + } else + *X = *Y; + + X++; + Y++; + } + } +} + +static void Xacc_blend_invsrccolor( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *X = gfxs->Xacc; + GenefxAccumulator *Y = gfxs->Yacc; + + if (gfxs->Sacc) { + GenefxAccumulator *S = gfxs->Sacc; + + while (w--) { + if (!(Y->RGB.a & 0xF000)) { + X->RGB.r = ((0x100 - S->RGB.r) * Y->RGB.r) >> 8; + X->RGB.g = ((0x100 - S->RGB.g) * Y->RGB.g) >> 8; + X->RGB.b = ((0x100 - S->RGB.b) * Y->RGB.b) >> 8; + X->RGB.a = ((0x100 - S->RGB.a) * Y->RGB.a) >> 8; + } else + *X = *Y; + + X++; + Y++; + S++; + } + } + else { + GenefxAccumulator Cacc = gfxs->Cacc; + Cacc.RGB.r = 0x100 - Cacc.RGB.r; + Cacc.RGB.g = 0x100 - Cacc.RGB.g; + Cacc.RGB.b = 0x100 - Cacc.RGB.b; + Cacc.RGB.a = 0x100 - Cacc.RGB.a; + + while (w--) { + if (!(Y->RGB.a & 0xF000)) { + X->RGB.r = (Cacc.RGB.r * Y->RGB.r) >> 8; + X->RGB.g = (Cacc.RGB.g * Y->RGB.g) >> 8; + X->RGB.b = (Cacc.RGB.b * Y->RGB.b) >> 8; + X->RGB.a = (Cacc.RGB.a * Y->RGB.a) >> 8; + } else + *X = *Y; + + X++; + Y++; + } + } +} + +static void Xacc_blend_srcalpha( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *X = gfxs->Xacc; + GenefxAccumulator *Y = gfxs->Yacc; + + if (gfxs->Sacc) { + GenefxAccumulator *S = gfxs->Sacc; + + while (w--) { + if (!(Y->RGB.a & 0xF000)) { + register u16 Sa = S->RGB.a + 1; + + X->RGB.r = (Sa * Y->RGB.r) >> 8; + X->RGB.g = (Sa * Y->RGB.g) >> 8; + X->RGB.b = (Sa * Y->RGB.b) >> 8; + X->RGB.a = (Sa * Y->RGB.a) >> 8; + } else + *X = *Y; + + X++; + Y++; + S++; + } + } + else { + register u16 Sa = gfxs->color.a + 1; + + while (w--) { + if (!(Y->RGB.a & 0xF000)) { + X->RGB.r = (Sa * Y->RGB.r) >> 8; + X->RGB.g = (Sa * Y->RGB.g) >> 8; + X->RGB.b = (Sa * Y->RGB.b) >> 8; + X->RGB.a = (Sa * Y->RGB.a) >> 8; + } else + *X = *Y; + + X++; + Y++; + } + } +} + +static void Xacc_blend_invsrcalpha( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *X = gfxs->Xacc; + GenefxAccumulator *Y = gfxs->Yacc; + + if (gfxs->Sacc) { + GenefxAccumulator *S = gfxs->Sacc; + + while (w--) { + if (!(Y->RGB.a & 0xF000)) { + register u16 Sa = 0x100 - S->RGB.a; + + X->RGB.r = (Sa * Y->RGB.r) >> 8; + X->RGB.g = (Sa * Y->RGB.g) >> 8; + X->RGB.b = (Sa * Y->RGB.b) >> 8; + X->RGB.a = (Sa * Y->RGB.a) >> 8; + } else + *X = *Y; + + X++; + Y++; + S++; + } + } + else { + register u16 Sa = 0x100 - gfxs->color.a; + + while (w--) { + if (!(Y->RGB.a & 0xF000)) { + X->RGB.a = (Sa * Y->RGB.a) >> 8; + X->RGB.r = (Sa * Y->RGB.r) >> 8; + X->RGB.g = (Sa * Y->RGB.g) >> 8; + X->RGB.b = (Sa * Y->RGB.b) >> 8; + } else + *X = *Y; + + X++; + Y++; + } + } +} + +static void Xacc_blend_dstalpha( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *X = gfxs->Xacc; + GenefxAccumulator *Y = gfxs->Yacc; + GenefxAccumulator *D = gfxs->Dacc; + + while (w--) { + if (!(Y->RGB.a & 0xF000)) { + register u16 Da = D->RGB.a + 1; + + X->RGB.r = (Da * Y->RGB.r) >> 8; + X->RGB.g = (Da * Y->RGB.g) >> 8; + X->RGB.b = (Da * Y->RGB.b) >> 8; + X->RGB.a = (Da * Y->RGB.a) >> 8; + } else + *X = *Y; + + X++; + Y++; + D++; + } +} + +static void Xacc_blend_invdstalpha( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *X = gfxs->Xacc; + GenefxAccumulator *Y = gfxs->Yacc; + GenefxAccumulator *D = gfxs->Dacc; + + while (w--) { + if (!(Y->RGB.a & 0xF000)) { + register u16 Da = 0x100 - D->RGB.a; + + X->RGB.r = (Da * Y->RGB.r) >> 8; + X->RGB.g = (Da * Y->RGB.g) >> 8; + X->RGB.b = (Da * Y->RGB.b) >> 8; + X->RGB.a = (Da * Y->RGB.a) >> 8; + } else + *X = *Y; + + X++; + Y++; + D++; + } +} + +static void Xacc_blend_destcolor( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *X = gfxs->Xacc; + GenefxAccumulator *Y = gfxs->Yacc; + GenefxAccumulator *D = gfxs->Dacc; + + while (w--) { + if (!(Y->RGB.a & 0xF000)) { + X->RGB.r = ((D->RGB.r + 1) * Y->RGB.r) >> 8; + X->RGB.g = ((D->RGB.g + 1) * Y->RGB.g) >> 8; + X->RGB.b = ((D->RGB.b + 1) * Y->RGB.b) >> 8; + X->RGB.a = ((D->RGB.a + 1) * Y->RGB.a) >> 8; + } else + *X = *Y; + + X++; + Y++; + D++; + } +} + +static void Xacc_blend_invdestcolor( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *X = gfxs->Xacc; + GenefxAccumulator *Y = gfxs->Yacc; + GenefxAccumulator *D = gfxs->Dacc; + + while (w--) { + if (!(Y->RGB.a & 0xF000)) { + X->RGB.r = ((0x100 - D->RGB.r) * Y->RGB.r) >> 8; + X->RGB.g = ((0x100 - D->RGB.g) * Y->RGB.g) >> 8; + X->RGB.b = ((0x100 - D->RGB.b) * Y->RGB.b) >> 8; + X->RGB.a = ((0x100 - D->RGB.a) * Y->RGB.a) >> 8; + } else + *X = *Y; + + X++; + Y++; + D++; + } +} + +static void Xacc_blend_srcalphasat( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *X = gfxs->Xacc; + GenefxAccumulator *Y = gfxs->Yacc; + GenefxAccumulator *D = gfxs->Dacc; + + if (gfxs->Sacc) { + GenefxAccumulator *S = gfxs->Sacc; + + while (w--) { + if (!(Y->RGB.a & 0xF000)) { + register u16 Sa = MIN( S->RGB.a + 1, 0x100 - D->RGB.a ); + + X->RGB.a = Y->RGB.a; + X->RGB.r = (Sa * Y->RGB.r) >> 8; + X->RGB.g = (Sa * Y->RGB.g) >> 8; + X->RGB.b = (Sa * Y->RGB.b) >> 8; + } else + *X = *Y; + + X++; + Y++; + D++; + S++; + } + } + else { + while (w--) { + if (!(Y->RGB.a & 0xF000)) { + register u16 Sa = MIN( gfxs->color.a + 1, 0x100 - D->RGB.a ); + + X->RGB.a = Y->RGB.a; + X->RGB.r = (Sa * Y->RGB.r) >> 8; + X->RGB.g = (Sa * Y->RGB.g) >> 8; + X->RGB.b = (Sa * Y->RGB.b) >> 8; + } else + *X = *Y; + + X++; + Y++; + D++; + } + } +} + +static GenefxFunc Xacc_blend[] = { + Xacc_blend_zero, /* DSBF_ZERO */ + Xacc_blend_one, /* DSBF_ONE */ + Xacc_blend_srccolor, /* DSBF_SRCCOLOR */ + Xacc_blend_invsrccolor, /* DSBF_INVSRCCOLOR */ + Xacc_blend_srcalpha, /* DSBF_SRCALPHA */ + Xacc_blend_invsrcalpha, /* DSBF_INVSRCALPHA */ + Xacc_blend_dstalpha, /* DSBF_DESTALPHA */ + Xacc_blend_invdstalpha, /* DSBF_INVDESTALPHA */ + Xacc_blend_destcolor, /* DSBF_DESTCOLOR */ + Xacc_blend_invdestcolor, /* DSBF_INVDESTCOLOR */ + Xacc_blend_srcalphasat /* DSBF_SRCALPHASAT */ +}; + +/********************************* Dacc_modulation ****************************/ + +static void Dacc_set_alpha( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *D = gfxs->Dacc; + int a = gfxs->color.a; + + while (w--) { + if (!(D->RGB.a & 0xF000)) { + D->RGB.a = a; + } + + D++; + } +} + +static void Dacc_modulate_alpha( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *D = gfxs->Dacc; + int a = gfxs->Cacc.RGB.a; + + while (w--) { + if (!(D->RGB.a & 0xF000)) { + D->RGB.a = (a * D->RGB.a) >> 8; + } + + D++; + } +} + +static void Dacc_modulate_rgb( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *D = gfxs->Dacc; + GenefxAccumulator Cacc = gfxs->Cacc; + + while (w--) { + if (!(D->RGB.a & 0xF000)) { + D->RGB.r = (Cacc.RGB.r * D->RGB.r) >> 8; + D->RGB.g = (Cacc.RGB.g * D->RGB.g) >> 8; + D->RGB.b = (Cacc.RGB.b * D->RGB.b) >> 8; + } + + D++; + } +} + +static void Dacc_modulate_rgb_set_alpha( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *D = gfxs->Dacc; + GenefxAccumulator Cacc = gfxs->Cacc; + int a = gfxs->color.a; + + while (w--) { + if (!(D->RGB.a & 0xF000)) { + D->RGB.a = a; + D->RGB.r = (Cacc.RGB.r * D->RGB.r) >> 8; + D->RGB.g = (Cacc.RGB.g * D->RGB.g) >> 8; + D->RGB.b = (Cacc.RGB.b * D->RGB.b) >> 8; + } + + D++; + } +} + +static void Dacc_modulate_argb( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *D = gfxs->Dacc; + GenefxAccumulator Cacc = gfxs->Cacc; + + while (w--) { + if (!(D->RGB.a & 0xF000)) { + D->RGB.a = (Cacc.RGB.a * D->RGB.a) >> 8; + D->RGB.r = (Cacc.RGB.r * D->RGB.r) >> 8; + D->RGB.g = (Cacc.RGB.g * D->RGB.g) >> 8; + D->RGB.b = (Cacc.RGB.b * D->RGB.b) >> 8; + } + + D++; + } +} + +static GenefxFunc Dacc_modulation[] = { + NULL, + NULL, + Dacc_set_alpha, + Dacc_modulate_alpha, + Dacc_modulate_rgb, + Dacc_modulate_rgb, + Dacc_modulate_rgb_set_alpha, + Dacc_modulate_argb +}; + +/********************************* misc accumulator operations ****************/ + +static void Dacc_premultiply( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *D = gfxs->Dacc; + + while (w--) { + if (!(D->RGB.a & 0xF000)) { + register u16 Da = D->RGB.a + 1; + + D->RGB.r = (Da * D->RGB.r) >> 8; + D->RGB.g = (Da * D->RGB.g) >> 8; + D->RGB.b = (Da * D->RGB.b) >> 8; + } + + D++; + } +} + +static void Dacc_premultiply_color_alpha( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *D = gfxs->Dacc; + register u16 Ca = gfxs->Cacc.RGB.a; + + while (w--) { + if (!(D->RGB.a & 0xF000)) { + D->RGB.r = (Ca * D->RGB.r) >> 8; + D->RGB.g = (Ca * D->RGB.g) >> 8; + D->RGB.b = (Ca * D->RGB.b) >> 8; + } + + D++; + } +} + +static void Dacc_demultiply( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *D = gfxs->Dacc; + + while (w--) { + if (!(D->RGB.a & 0xF000)) { + register u16 Da = D->RGB.a + 1; + + D->RGB.r = (D->RGB.r << 8) / Da; + D->RGB.g = (D->RGB.g << 8) / Da; + D->RGB.b = (D->RGB.b << 8) / Da; + } + + D++; + } +} + +static void Dacc_xor_C( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *D = gfxs->Dacc; + DFBColor color = gfxs->color; + + while (w--) { + if (!(D->RGB.a & 0xF000)) { + D->RGB.a ^= color.a; + D->RGB.r ^= color.r; + D->RGB.g ^= color.g; + D->RGB.b ^= color.b; + } + + D++; + } +} + +static GenefxFunc Dacc_xor = Dacc_xor_C; + +static void Sacc_xor_Dacc( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *S = gfxs->Sacc; + GenefxAccumulator *D = gfxs->Dacc; + + while (w--) { + if (!(D->RGB.a & 0xF000)) { + D->RGB.a ^= S->RGB.a; + D->RGB.r ^= S->RGB.r; + D->RGB.g ^= S->RGB.g; + D->RGB.b ^= S->RGB.b; + } + D++; + S++; + } +} + +static void Cacc_to_Dacc( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *D = gfxs->Dacc; + GenefxAccumulator Cacc = gfxs->Cacc; + + while (w--) + *D++ = Cacc; +} + +static void SCacc_add_to_Dacc_C( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *D = gfxs->Dacc; + GenefxAccumulator SCacc = gfxs->SCacc; + + while (w--) { + if (!(D->RGB.a & 0xF000)) { + D->RGB.a += SCacc.RGB.a; + D->RGB.r += SCacc.RGB.r; + D->RGB.g += SCacc.RGB.g; + D->RGB.b += SCacc.RGB.b; + } + D++; + } +} + +static GenefxFunc SCacc_add_to_Dacc = SCacc_add_to_Dacc_C; + +static void Sacc_add_to_Dacc_C( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *S = gfxs->Sacc; + GenefxAccumulator *D = gfxs->Dacc; + + while (w--) { + if (!(D->RGB.a & 0xF000)) { + D->RGB.a += S->RGB.a; + D->RGB.r += S->RGB.r; + D->RGB.g += S->RGB.g; + D->RGB.b += S->RGB.b; + } + D++; + S++; + } +} + +static GenefxFunc Sacc_add_to_Dacc = Sacc_add_to_Dacc_C; + +/**********************************************************************************************************************/ + +/* change the last value to adjust the size of the device (1-4) */ +#define SET_PIXEL_DUFFS_DEVICE( D, S, w ) \ + SET_PIXEL_DUFFS_DEVICE_N( D, S, w, 3 ) + +#define SET_PIXEL( D, S ) \ + if (!(S.RGB.a & 0xF000)) { \ + RGB_TO_YCBCR( S.RGB.r, S.RGB.g, S.RGB.b, \ + D.YUV.y, D.YUV.u, D.YUV.v ); \ + } + +static void Dacc_RGB_to_YCbCr_C( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *D = gfxs->Dacc; + GenefxAccumulator *S = gfxs->Dacc; + + SET_PIXEL_DUFFS_DEVICE( D, S, w ); +} + +#undef SET_PIXEL_DUFFS_DEVICE +#undef SET_PIXEL + +static GenefxFunc Dacc_RGB_to_YCbCr = Dacc_RGB_to_YCbCr_C; + +/**********************************************************************************************************************/ + +/* change the last value to adjust the size of the device (1-4) */ +#define SET_PIXEL_DUFFS_DEVICE( D, S, w ) \ + SET_PIXEL_DUFFS_DEVICE_N( D, S, w, 2 ) + +#define SET_PIXEL( D, S ) \ + if (!(S.YUV.a & 0xF000)) { \ + YCBCR_TO_RGB( S.YUV.y, S.YUV.u, S.YUV.v, \ + D.RGB.r, D.RGB.g, D.RGB.b ); \ + } + +static void Dacc_YCbCr_to_RGB_C( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *D = gfxs->Dacc; + GenefxAccumulator *S = gfxs->Dacc; + + SET_PIXEL_DUFFS_DEVICE( D, S, w ); +} + +#undef SET_PIXEL_DUFFS_DEVICE +#undef SET_PIXEL + +static GenefxFunc Dacc_YCbCr_to_RGB = Dacc_YCbCr_to_RGB_C; + +/**********************************************************************************************************************/ + +/* change the last value to adjust the size of the device (1-4) */ +#define SET_PIXEL_DUFFS_DEVICE( D, S, w ) \ + SET_PIXEL_DUFFS_DEVICE_N( D, S, w, 3 ) + +#define SET_PIXEL( D, S ) \ + switch (S >> 26) { \ + case 0: \ + break; \ + case 0x3f: \ + D = RGB32_TO_RGB16( S ); \ + break; \ + default: \ + D = (((( (((S>>8) & 0xf800) | ((S>>3) & 0x001f)) \ + - (D & 0xf81f)) * ((S>>26)+1) + ((D & 0xf81f)<<6)) & 0x003e07c0) \ + + \ + ((( ((S>>5) & 0x07e0) \ + - (D & 0x07e0)) * ((S>>26)+1) + ((D & 0x07e0)<<6)) & 0x0001f800)) >> 6; \ + } while (0) + +static void Bop_argb_blend_alphachannel_src_invsrc_Aop_rgb16( GenefxState *gfxs ) +{ + int w = gfxs->length; + u32 *S = gfxs->Bop[0]; + u16 *D = gfxs->Aop[0]; + + SET_PIXEL_DUFFS_DEVICE( D, S, w ); +} + +#undef SET_PIXEL_DUFFS_DEVICE +#undef SET_PIXEL + +static void Bop_argb_blend_alphachannel_src_invsrc_Aop_rgb32( GenefxState *gfxs ) +{ + int w = gfxs->length; + int Dstep = gfxs->Astep; + u32 *S = gfxs->Bop[0]; + u32 *D = gfxs->Aop[0]; + + while (w--) { + u32 dp32 = *D; + u32 sp32 = *S++; + int salpha = (sp32 >> 25) + 1; + +#define rb (sp32 & 0xff00ff) +#define g (sp32 & 0x00ff00) + + *D = ((((rb-(dp32 & 0xff00ff))*salpha+((dp32 & 0xff00ff)<<7)) & 0x7f807f80) + + ((( g-(dp32 & 0x00ff00))*salpha+((dp32 & 0x00ff00)<<7)) & 0x007f8000)) >> 7; + D += Dstep; + +#undef rb +#undef g + } +} + +static GenefxFunc Bop_argb_blend_alphachannel_src_invsrc_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + NULL, /* DSPF_ARGB1555 */ + Bop_argb_blend_alphachannel_src_invsrc_Aop_rgb16, /* DSPF_RGB16 */ + NULL, /* DSPF_RGB24 */ + Bop_argb_blend_alphachannel_src_invsrc_Aop_rgb32, /* DSPF_RGB32 */ + NULL, /* DSPF_ARGB */ + NULL, /* DSPF_A8 */ + NULL, /* DSPF_YUY2 */ + NULL, /* DSPF_RGB332 */ + NULL, /* DSPF_UYVY */ + NULL, /* DSPF_I420 */ + NULL, /* DSPF_YV12 */ + NULL, /* DSPF_LUT8 */ + NULL, /* DSPF_ALUT44 */ + NULL, /* DSPF_AiRGB */ + NULL, /* DSPF_A1 */ + NULL, /* DSPF_NV12 */ + NULL, /* DSPF_NV16 */ + NULL, /* DSPF_ARGB2554 */ + NULL, /* DSPF_ARGB4444 */ + NULL, /* DSPF_RGBA4444 */ + NULL, /* DSPF_NV21 */ + NULL, /* DSPF_AYUV */ + NULL, /* DSPF_A4 */ + NULL, /* DSPF_ARGB1666 */ + NULL, /* DSPF_ARGB6666 */ + NULL, /* DSPF_RGB18 */ + NULL, /* DSPF_LUT2 */ + NULL, /* DSPF_RGB444 */ + NULL, /* DSPF_RGB555 */ + NULL /* DSPF_BGR555 */ +}; + +/**********************************************************************************************************************/ + +/* change the last value to adjust the size of the device (1-4) */ +#define SET_PIXEL_DUFFS_DEVICE( D, S, w ) \ + SET_PIXEL_DUFFS_DEVICE_N( D, S, w, 3 ) + +#define SET_PIXEL( D, S ) \ +do { \ + int invsrc = 256 - (S >> 24); \ + \ + u32 Drb = ((D & 0x00ff00ff) * invsrc) >> 8; \ + u32 Dag = ((D & 0xff00ff00) >> 8) * invsrc; \ + \ + D = S + (Drb & 0x00ff00ff) + (Dag & 0xff00ff00); \ +} while (0) + +static void Bop_argb_blend_alphachannel_one_invsrc_Aop_argb( GenefxState *gfxs ) +{ + int w = gfxs->length; + u32 *S = gfxs->Bop[0]; + u32 *D = gfxs->Aop[0]; + + SET_PIXEL_DUFFS_DEVICE( D, S, w ); +} + +#undef SET_PIXEL_DUFFS_DEVICE +#undef SET_PIXEL + +static GenefxFunc Bop_argb_blend_alphachannel_one_invsrc_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + NULL, /* DSPF_ARGB1555 */ + NULL, /* DSPF_RGB16 */ + NULL, /* DSPF_RGB24 */ + Bop_argb_blend_alphachannel_one_invsrc_Aop_argb, /* DSPF_RGB32 */ + Bop_argb_blend_alphachannel_one_invsrc_Aop_argb, /* DSPF_ARGB */ + NULL, /* DSPF_A8 */ + NULL, /* DSPF_YUY2 */ + NULL, /* DSPF_RGB332 */ + NULL, /* DSPF_UYVY */ + NULL, /* DSPF_I420 */ + NULL, /* DSPF_YV12 */ + NULL, /* DSPF_LUT8 */ + NULL, /* DSPF_ALUT44 */ + NULL, /* DSPF_AiRGB */ + NULL, /* DSPF_A1 */ + NULL, /* DSPF_NV12 */ + NULL, /* DSPF_NV16 */ + NULL, /* DSPF_ARGB2554 */ + NULL, /* DSPF_ARGB4444 */ + NULL, /* DSPF_RGBA4444 */ + NULL, /* DSPF_NV21 */ + NULL, /* DSPF_AYUV */ + NULL, /* DSPF_A4 */ + NULL, /* DSPF_ARGB1666 */ + NULL, /* DSPF_ARGB6666 */ + NULL, /* DSPF_RGB18 */ + NULL, /* DSPF_LUT2 */ + NULL, /* DSPF_RGB444 */ + NULL, /* DSPF_RGB555 */ + NULL /* DSPF_BGR555 */ +}; + +/**********************************************************************************************************************/ + +/* A8/A1 to YCbCr */ +static void Dacc_Alpha_to_YCbCr( GenefxState *gfxs ) +{ + int w = gfxs->length; + GenefxAccumulator *D = gfxs->Dacc; + + while (w--) { + if (!(D->RGB.a & 0xF000)) { + D->YUV.y = 235; + D->YUV.u = 128; + D->YUV.v = 128; + } + + D++; + } +} + +/**********************************************************************************************************************/ + +static void Sop_is_Aop( GenefxState *gfxs ) { gfxs->Sop = gfxs->Aop; gfxs->Ostep = gfxs->Astep; } +static void Sop_is_Bop( GenefxState *gfxs ) { gfxs->Sop = gfxs->Bop; gfxs->Ostep = gfxs->Bstep; } + +static void Slut_is_Alut( GenefxState *gfxs ) { gfxs->Slut = gfxs->Alut;} +static void Slut_is_Blut( GenefxState *gfxs ) { gfxs->Slut = gfxs->Blut;} + +static void Sacc_is_NULL( GenefxState *gfxs ) { gfxs->Sacc = NULL;} +static void Sacc_is_Aacc( GenefxState *gfxs ) { gfxs->Sacc = gfxs->Aacc;} +static void Sacc_is_Bacc( GenefxState *gfxs ) { gfxs->Sacc = gfxs->Bacc;} +static void Sacc_is_Tacc( GenefxState *gfxs ) { gfxs->Sacc = gfxs->Tacc;} + +static void Dacc_is_Aacc( GenefxState *gfxs ) { gfxs->Dacc = gfxs->Aacc;} +static void Dacc_is_Bacc( GenefxState *gfxs ) { gfxs->Dacc = gfxs->Bacc;} + +static void Xacc_is_Aacc( GenefxState *gfxs ) { gfxs->Xacc = gfxs->Aacc;} +static void Xacc_is_Bacc( GenefxState *gfxs ) { gfxs->Xacc = gfxs->Bacc;} +static void Xacc_is_Tacc( GenefxState *gfxs ) { gfxs->Xacc = gfxs->Tacc;} + +static void Yacc_is_Aacc( GenefxState *gfxs ) { gfxs->Yacc = gfxs->Aacc;} +static void Yacc_is_Bacc( GenefxState *gfxs ) { gfxs->Yacc = gfxs->Bacc;} + +static void Len_is_Slen( GenefxState *gfxs ) { gfxs->length = gfxs->Slen;} +static void Len_is_Dlen( GenefxState *gfxs ) { gfxs->length = gfxs->Dlen;} + +/******************************************************************************/ + +#ifdef USE_MMX +static bool has_mmx( void ) +{ +#ifdef ARCH_X86_64 + return true; +#else + u32 a, b, c, d; + + asm( "pushfl \n" + "pushfl \n" + "popl %0 \n" + "movl %0, %1 \n" + "xorl $0x200000, %0 \n" + "pushl %0 \n" + "popfl \n" + "pushfl \n" + "popl %0 \n" + "popfl" + : "=a" (a), "=r" (b) + : + : "cc" ); + + if (a == b) + return false; + + asm( "pushl %%ebx \n" + "cpuid \n" + "movl %%ebx, %1 \n" + "popl %%ebx" + : "=a" (a), "=r" (b), "=c" (c), "=d" (d) + : "a" (0) + : "cc" ); + + if (!a) + return false; + + asm( "pushl %%ebx \n" + "cpuid \n" + "movl %%ebx, %1 \n" + "popl %%ebx" + : "=a" (a), "=r" (b), "=c" (c), "=d" (d) + : "a" (1) + : "cc" ); + + return (d & 0x800000) ? true : false; +#endif /* !ARCH_X86_64 */ +} +#endif + +void gGetDriverInfo( GraphicsDriverInfo *info ) +{ + snprintf( info->name, + DFB_GRAPHICS_DRIVER_INFO_NAME_LENGTH, "Software Driver" ); + +#if SIZEOF_LONG == 8 + gInit_64bit(); +#endif + +#ifdef USE_MMX + if (has_mmx()) { + if (!dfb_config->mmx) { + D_INFO( "DirectFB/Genefx: MMX detected, but disabled by option 'no-mmx'\n"); + } + else { + gInit_MMX(); + + snprintf( info->name, DFB_GRAPHICS_DRIVER_INFO_NAME_LENGTH, + "MMX Software Driver" ); + + D_INFO( "DirectFB/Genefx: MMX detected and enabled\n"); + } + } + else { + D_INFO( "DirectFB/Genefx: No MMX detected\n" ); + } +#endif + + snprintf( info->vendor, DFB_GRAPHICS_DRIVER_INFO_VENDOR_LENGTH, "directfb.org" ); + + info->version.major = 0; + info->version.minor = 6; +} + +void gGetDeviceInfo( GraphicsDeviceInfo *info ) +{ + snprintf( info->name, DFB_GRAPHICS_DEVICE_INFO_NAME_LENGTH, + "Software Rasterizer" ); + + snprintf( info->vendor, DFB_GRAPHICS_DEVICE_INFO_VENDOR_LENGTH, + use_mmx ? "MMX" : "Generic" ); + + info->caps.accel = DFXL_NONE; + info->caps.flags = 0; + info->caps.drawing = DSDRAW_NOFX; + info->caps.blitting = DSBLIT_NOFX; +} + +#define MODULATION_FLAGS (DSBLIT_BLEND_ALPHACHANNEL | \ + DSBLIT_BLEND_COLORALPHA | \ + DSBLIT_COLORIZE | \ + DSBLIT_DST_PREMULTIPLY | \ + DSBLIT_SRC_PREMULTIPLY | \ + DSBLIT_SRC_PREMULTCOLOR | \ + DSBLIT_DEMULTIPLY | \ + DSBLIT_XOR) + +#ifndef WORDS_BIGENDIAN +#define BGR_TO_RGB16(pixel) ( (((pixel) << 8) & 0xF800) | \ + (((pixel) >> 5) & 0x07E0) | \ + (((pixel) >> 19) & 0x001F) ) + +/* + * Fast RGB24 to RGB16 conversion. + */ +static void +Bop_rgb24_to_Aop_rgb16_LE( GenefxState *gfxs ) +{ + int w = gfxs->length; + u8 *S = gfxs->Bop[0]; + u16 *D = gfxs->Aop[0]; + + while ((unsigned long)S & 3) { + *D++ = PIXEL_RGB16( S[0], S[1], S[2] ); + + S += 3; + w -= 1; + } + + if ((unsigned long)D & 2) { + *D++ = PIXEL_RGB16( S[0], S[1], S[2] ); + + w -= 1; + S += 3; + + while (w > 1) { + *(u32*)D = PIXEL_RGB16( S[0], S[1], S[2] ) | (PIXEL_RGB16( S[3], S[4], S[5] ) << 16); + + w -= 2; + D += 2; + S += 6; + } + } + else { + u32 *S32 = (u32*)S; + u32 *D32 = (u32*)D; + + while (w > 3) { + D32[0] = BGR_TO_RGB16( S32[0] ) | (BGR_TO_RGB16( (S32[0] >> 24) | (S32[1] << 8) ) << 16); + D32[1] = BGR_TO_RGB16( (S32[1] >> 16) | (S32[2] << 16) ) | (BGR_TO_RGB16( S32[2] >> 8 ) << 16); + + D32 += 2; + S32 += 3; + w -= 4; + } + + S = (u8*) S32; + D = (u16*) D32; + } + + while (w > 0) { + *D++ = PIXEL_RGB16( S[0], S[1], S[2] ); + + w -= 1; + S += 3; + } +} + +/* + * Fast RGB32 to RGB16 conversion. + */ +static void +Bop_rgb32_to_Aop_rgb16_LE( GenefxState *gfxs ) +{ + int w = gfxs->length; + u32 *S = gfxs->Bop[0]; + u32 *D = gfxs->Aop[0]; + + if ((unsigned long)D & 2) { + u16 *d = (u16*)D; + + d[0] = RGB32_TO_RGB16( S[0] ); + + w--; + S++; + + D = (u32*)(d+1); + } + + while (w > 1) { + D[0] = RGB32_TO_RGB16( S[0] ) | (RGB32_TO_RGB16( S[1] ) << 16); + + w -= 2; + S += 2; + D += 1; + } + + if (w > 0) { + u16 *d = (u16*)D; + + d[0] = RGB32_TO_RGB16( S[0] ); + } +} +#endif /* #ifndef WORDS_BIGENDIAN */ + +bool gAcquire( CardState *state, DFBAccelerationMask accel ) +{ + DFBResult ret; + GenefxState *gfxs; + GenefxFunc *funcs; + int dst_pfi; + int src_pfi = 0; + CoreSurface *destination = state->destination; + CoreSurface *source = state->source; + DFBColor color = state->color; + bool src_ycbcr = false; + bool dst_ycbcr = false; + + CoreSurfaceAccessFlags access = CSAF_WRITE; + + if (dfb_config->hardware_only) { + if (dfb_config->software_warn) { + if (DFB_BLITTING_FUNCTION( accel )) + D_WARN( "Ignoring blit (%x) from %s to %s, flags 0x%08x, funcs %d %d", accel, + source ? dfb_pixelformat_name(source->config.format) : "NULL SOURCE", + destination ? dfb_pixelformat_name(destination->config.format) : "NULL DESTINATION", + state->blittingflags, state->src_blend, state->dst_blend ); + else + D_WARN( "Ignoring draw (%x) to %s, flags 0x%08x", accel, + destination ? dfb_pixelformat_name(destination->config.format) : "NULL DESTINATION", + state->drawingflags ); + } + + return false; + } + + if (!state->gfxs) { + gfxs = D_CALLOC( 1, sizeof(GenefxState) ); + if (!gfxs) { + D_ERROR( "DirectFB/Genefx: Couldn't allocate state struct!\n" ); + return false; + } + + state->gfxs = gfxs; + } + + gfxs = state->gfxs; + funcs = gfxs->funcs; + + /* Destination may have been destroyed. */ + if (!destination) + return false; + + /* Source may have been destroyed. */ + if (DFB_BLITTING_FUNCTION( accel ) && !source) + return false; + + /* + * Destination setup + */ + + if (DFB_BLITTING_FUNCTION( accel )) { + if (state->blittingflags & (DSBLIT_BLEND_ALPHACHANNEL | + DSBLIT_BLEND_COLORALPHA | + DSBLIT_DST_COLORKEY)) + access |= CSAF_READ; + } + else if (state->drawingflags & (DSDRAW_BLEND | DSDRAW_DST_COLORKEY)) + access |= CSAF_READ; + + /* Lock destination */ + ret = dfb_surface_lock_buffer( destination, state->to, CSAID_CPU, access, &state->dst ); + if (ret) { + D_DERROR( ret, "DirectFB/Genefx: Could not lock destination!\n" ); + return false; + } + + gfxs->dst_caps = destination->config.caps; + gfxs->dst_height = destination->config.size.h; + gfxs->dst_format = destination->config.format; + gfxs->dst_bpp = DFB_BYTES_PER_PIXEL( gfxs->dst_format ); + dst_pfi = DFB_PIXELFORMAT_INDEX( gfxs->dst_format ); + + gfxs->dst_org[0] = state->dst.addr; + gfxs->dst_pitch = state->dst.pitch; + + switch (gfxs->dst_format) { + case DSPF_I420: + gfxs->dst_org[1] = gfxs->dst_org[0] + gfxs->dst_height * gfxs->dst_pitch; + gfxs->dst_org[2] = gfxs->dst_org[1] + gfxs->dst_height/2 * gfxs->dst_pitch/2; + break; + case DSPF_YV12: + gfxs->dst_org[2] = gfxs->dst_org[0] + gfxs->dst_height * gfxs->dst_pitch; + gfxs->dst_org[1] = gfxs->dst_org[2] + gfxs->dst_height/2 * gfxs->dst_pitch/2; + break; + case DSPF_NV12: + case DSPF_NV21: + case DSPF_NV16: + gfxs->dst_org[1] = gfxs->dst_org[0] + gfxs->dst_height * gfxs->dst_pitch; + break; + default: + break; + } + + gfxs->dst_field_offset = gfxs->dst_height/2 * gfxs->dst_pitch; + + + /* + * Source setup + */ + + if (DFB_BLITTING_FUNCTION( accel )) { +#if FIXME_SC_3 + DFBSurfaceLockFlags flags = DSLF_READ; + + if (accel == DFXL_STRETCHBLIT) + flags |= CSLF_FORCE; +#endif + + /* Lock source */ + ret = dfb_surface_lock_buffer( source, state->from, CSAID_CPU, CSAF_READ, &state->src ); + if (ret) { + D_DERROR( ret, "DirectFB/Genefx: Could not lock source!\n" ); + dfb_surface_unlock_buffer( destination, &state->dst ); + return false; + } + + gfxs->src_caps = source->config.caps; + gfxs->src_height = source->config.size.h; + gfxs->src_format = source->config.format; + gfxs->src_bpp = DFB_BYTES_PER_PIXEL( gfxs->src_format ); + src_pfi = DFB_PIXELFORMAT_INDEX( gfxs->src_format ); + + gfxs->src_org[0] = state->src.addr; + gfxs->src_pitch = state->src.pitch; + + switch (gfxs->src_format) { + case DSPF_I420: + gfxs->src_org[1] = gfxs->src_org[0] + gfxs->src_height * gfxs->src_pitch; + gfxs->src_org[2] = gfxs->src_org[1] + gfxs->src_height/2 * gfxs->src_pitch/2; + break; + case DSPF_YV12: + gfxs->src_org[2] = gfxs->src_org[0] + gfxs->src_height * gfxs->src_pitch; + gfxs->src_org[1] = gfxs->src_org[2] + gfxs->src_height/2 * gfxs->src_pitch/2; + break; + case DSPF_NV12: + case DSPF_NV21: + case DSPF_NV16: + gfxs->src_org[1] = gfxs->src_org[0] + gfxs->src_height * gfxs->src_pitch; + break; + default: + break; + } + + gfxs->src_field_offset = gfxs->src_height/2 * gfxs->src_pitch; + + state->flags |= CSF_SOURCE_LOCKED; + } + + + /* premultiply source (color) */ + if (DFB_DRAWING_FUNCTION(accel) && (state->drawingflags & DSDRAW_SRC_PREMULTIPLY)) { + u16 ca = color.a + 1; + + color.r = (color.r * ca) >> 8; + color.g = (color.g * ca) >> 8; + color.b = (color.b * ca) >> 8; + } + + + gfxs->color = color; + + + switch (gfxs->dst_format) { + case DSPF_ARGB1555: + gfxs->Cop = PIXEL_ARGB1555( color.a, color.r, color.g, color.b ); + break; + case DSPF_RGB16: + gfxs->Cop = PIXEL_RGB16( color.r, color.g, color.b ); + break; + case DSPF_RGB18: + gfxs->Cop = PIXEL_RGB18( color.r, color.g, color.b ); + break; + case DSPF_RGB24: + gfxs->Cop = PIXEL_RGB32( color.r, color.g, color.b ); + break; + case DSPF_RGB32: + gfxs->Cop = PIXEL_RGB32( color.r, color.g, color.b ); + break; + case DSPF_ARGB: + gfxs->Cop = PIXEL_ARGB( color.a, color.r, color.g, color.b ); + break; + case DSPF_AiRGB: + gfxs->Cop = PIXEL_AiRGB( color.a, color.r, color.g, color.b ); + break; + case DSPF_ARGB6666: + gfxs->Cop = PIXEL_ARGB6666( color.a, color.r, color.g, color.b ); + break; + case DSPF_ARGB1666: + gfxs->Cop = PIXEL_ARGB1666( color.a, color.r, color.g, color.b ); + break; + case DSPF_A1: + gfxs->Cop = color.a >> 7; + break; + case DSPF_A4: + gfxs->Cop = color.a >> 4; + break; + case DSPF_A8: + gfxs->Cop = color.a; + break; + case DSPF_YUY2: + RGB_TO_YCBCR( color.r, color.g, color.b, + gfxs->YCop, gfxs->CbCop, gfxs->CrCop ); + gfxs->Cop = PIXEL_YUY2( gfxs->YCop, gfxs->CbCop, gfxs->CrCop ); + dst_ycbcr = true; + break; + case DSPF_RGB332: + gfxs->Cop = PIXEL_RGB332( color.r, color.g, color.b ); + break; + case DSPF_UYVY: + RGB_TO_YCBCR( color.r, color.g, color.b, + gfxs->YCop, gfxs->CbCop, gfxs->CrCop ); + gfxs->Cop = PIXEL_UYVY( gfxs->YCop, gfxs->CbCop, gfxs->CrCop ); + dst_ycbcr = true; + break; + case DSPF_I420: + case DSPF_YV12: + case DSPF_NV12: + case DSPF_NV16: + RGB_TO_YCBCR( color.r, color.g, color.b, + gfxs->YCop, gfxs->CbCop, gfxs->CrCop ); + gfxs->Cop = gfxs->YCop; + dst_ycbcr = true; + break; + case DSPF_NV21: + RGB_TO_YCBCR( color.r, color.g, color.b, + gfxs->YCop, gfxs->CrCop, gfxs->CbCop ); + gfxs->Cop = gfxs->YCop; + dst_ycbcr = true; + break; + case DSPF_LUT2: + case DSPF_LUT8: + gfxs->Cop = state->color_index; + gfxs->Alut = destination->palette; + break; + case DSPF_ALUT44: + gfxs->Cop = (color.a & 0xF0) + state->color_index; + gfxs->Alut = destination->palette; + break; + case DSPF_ARGB2554: + gfxs->Cop = PIXEL_ARGB2554( color.a, color.r, color.g, color.b ); + break; + case DSPF_ARGB4444: + gfxs->Cop = PIXEL_ARGB4444( color.a, color.r, color.g, color.b ); + break; + case DSPF_RGBA4444: + gfxs->Cop = PIXEL_RGBA4444( color.a, color.r, color.g, color.b ); + break; + case DSPF_AYUV: + RGB_TO_YCBCR( color.r, color.g, color.b, + gfxs->YCop, gfxs->CbCop, gfxs->CrCop ); + gfxs->Cop = PIXEL_AYUV( color.a, gfxs->YCop, gfxs->CbCop, gfxs->CrCop ); + dst_ycbcr = true; + break; + case DSPF_RGB444: + gfxs->Cop = PIXEL_RGB444( color.r, color.g, color.b ); + break; + case DSPF_RGB555: + gfxs->Cop = PIXEL_RGB555( color.r, color.g, color.b ); + break; + case DSPF_BGR555: + gfxs->Cop = PIXEL_BGR555( color.r, color.g, color.b ); + break; + default: + D_ONCE("unsupported destination format"); + return false; + } + + if (DFB_BLITTING_FUNCTION( accel )) { + switch (gfxs->src_format) { + case DSPF_LUT2: + case DSPF_LUT8: + case DSPF_ALUT44: + gfxs->Blut = source->palette; + case DSPF_ARGB1555: + case DSPF_ARGB2554: + case DSPF_ARGB4444: + case DSPF_RGBA4444: + case DSPF_ARGB1666: + case DSPF_ARGB6666: + case DSPF_RGB16: + case DSPF_RGB18: + case DSPF_RGB24: + case DSPF_RGB32: + case DSPF_ARGB: + case DSPF_AiRGB: + case DSPF_RGB332: + case DSPF_RGB444: + case DSPF_RGB555: + case DSPF_BGR555: + if (dst_ycbcr && + state->blittingflags & (DSBLIT_COLORIZE | + DSBLIT_SRC_PREMULTCOLOR)) + return false; + case DSPF_A1: + case DSPF_A4: + case DSPF_A8: + if (DFB_PLANAR_PIXELFORMAT(gfxs->dst_format) && + state->blittingflags & DSBLIT_DST_COLORKEY) + return false; + break; + case DSPF_I420: + case DSPF_YV12: + case DSPF_NV12: + case DSPF_NV21: + case DSPF_NV16: + if (state->blittingflags & DSBLIT_SRC_COLORKEY) + return false; + case DSPF_YUY2: + case DSPF_UYVY: + case DSPF_AYUV: + if (dst_ycbcr) { + if (state->blittingflags & (DSBLIT_COLORIZE | + DSBLIT_SRC_PREMULTCOLOR)) + return false; + + if (DFB_PLANAR_PIXELFORMAT(gfxs->dst_format) && + state->blittingflags & DSBLIT_DST_COLORKEY) + return false; + } + src_ycbcr = true; + break; + default: + D_ONCE("unsupported source format"); + return false; + } + } + + gfxs->need_accumulator = true; + + /* Initialization */ + gfxs->Astep = gfxs->Bstep = gfxs->Ostep = 1; + + switch (accel) { + case DFXL_FILLRECTANGLE: + case DFXL_DRAWRECTANGLE: + case DFXL_DRAWLINE: + case DFXL_FILLTRIANGLE: + if (state->drawingflags & ~(DSDRAW_DST_COLORKEY | DSDRAW_SRC_PREMULTIPLY)) { + GenefxAccumulator Cacc, SCacc; + + /* not yet completed optimizing checks */ + if (state->drawingflags & DSDRAW_BLEND) { + if (state->src_blend == DSBF_ZERO) { + if (state->dst_blend == DSBF_ZERO) { + gfxs->Cop = 0; + if (state->drawingflags & DSDRAW_DST_COLORKEY) { + gfxs->Dkey = state->dst_colorkey; + *funcs++ = Cop_toK_Aop_PFI[dst_pfi]; + } + else + *funcs++ = Cop_to_Aop_PFI[dst_pfi]; + break; + } + else if (state->dst_blend == DSBF_ONE) { + break; + } + } + else if (state->src_blend == DSBF_ONE && state->dst_blend == DSBF_ZERO) { + if (state->drawingflags & DSDRAW_DST_COLORKEY) { + gfxs->Dkey = state->dst_colorkey; + *funcs++ = Cop_toK_Aop_PFI[dst_pfi]; + } + else + *funcs++ = Cop_to_Aop_PFI[dst_pfi]; + break; + } + } + + /* load from destination */ + *funcs++ = Sop_is_Aop; + if (DFB_PIXELFORMAT_IS_INDEXED(gfxs->dst_format)) + *funcs++ = Slut_is_Alut; + *funcs++ = Dacc_is_Aacc; + *funcs++ = Sop_PFI_to_Dacc[dst_pfi]; + + /* premultiply destination */ + if (state->drawingflags & DSDRAW_DST_PREMULTIPLY) + *funcs++ = Dacc_premultiply; + + /* xor destination */ + if (state->drawingflags & DSDRAW_XOR) + *funcs++ = Dacc_xor; + + /* load source (color) */ + Cacc.RGB.a = color.a; + if (!dst_ycbcr) { + Cacc.RGB.r = color.r; + Cacc.RGB.g = color.g; + Cacc.RGB.b = color.b; + } else { + Cacc.YUV.y = gfxs->YCop; + Cacc.YUV.u = gfxs->CbCop; + Cacc.YUV.v = gfxs->CrCop; + } + + /* premultiply source (color) */ + /*if (state->drawingflags & DSDRAW_SRC_PREMULTIPLY) { + u16 ca = color.a + 1; + + Cacc.r = (Cacc.r * ca) >> 8; + Cacc.g = (Cacc.g * ca) >> 8; + Cacc.b = (Cacc.b * ca) >> 8; + }*/ + + if (state->drawingflags & DSDRAW_BLEND) { + /* source blending */ + switch (state->src_blend) { + case DSBF_ZERO: + break; + case DSBF_ONE: + SCacc = Cacc; + break; + case DSBF_SRCCOLOR: + SCacc.RGB.a = (Cacc.RGB.a * (Cacc.RGB.a + 1)) >> 8; + SCacc.RGB.r = (Cacc.RGB.r * (Cacc.RGB.r + 1)) >> 8; + SCacc.RGB.g = (Cacc.RGB.g * (Cacc.RGB.g + 1)) >> 8; + SCacc.RGB.b = (Cacc.RGB.b * (Cacc.RGB.b + 1)) >> 8; + break; + case DSBF_INVSRCCOLOR: + SCacc.RGB.a = (Cacc.RGB.a * (0x100 - Cacc.RGB.a)) >> 8; + SCacc.RGB.r = (Cacc.RGB.r * (0x100 - Cacc.RGB.r)) >> 8; + SCacc.RGB.g = (Cacc.RGB.g * (0x100 - Cacc.RGB.g)) >> 8; + SCacc.RGB.b = (Cacc.RGB.b * (0x100 - Cacc.RGB.b)) >> 8; + break; + case DSBF_SRCALPHA: { + u16 ca = color.a + 1; + + SCacc.RGB.a = (Cacc.RGB.a * ca) >> 8; + SCacc.RGB.r = (Cacc.RGB.r * ca) >> 8; + SCacc.RGB.g = (Cacc.RGB.g * ca) >> 8; + SCacc.RGB.b = (Cacc.RGB.b * ca) >> 8; + break; + } + case DSBF_INVSRCALPHA: { + u16 ca = 0x100 - color.a; + + SCacc.RGB.a = (Cacc.RGB.a * ca) >> 8; + SCacc.RGB.r = (Cacc.RGB.r * ca) >> 8; + SCacc.RGB.g = (Cacc.RGB.g * ca) >> 8; + SCacc.RGB.b = (Cacc.RGB.b * ca) >> 8; + break; + } + case DSBF_SRCALPHASAT: + *funcs++ = Sacc_is_NULL; + case DSBF_DESTALPHA: + case DSBF_INVDESTALPHA: + case DSBF_DESTCOLOR: + case DSBF_INVDESTCOLOR: + *funcs++ = Dacc_is_Bacc; + *funcs++ = Cacc_to_Dacc; + + *funcs++ = Dacc_is_Aacc; + *funcs++ = Xacc_is_Bacc; + *funcs++ = Yacc_is_Bacc; + *funcs++ = Xacc_blend[state->src_blend - 1]; + + break; + + default: + D_BUG( "unknown src_blend %d", state->src_blend ); + } + + + /* destination blending */ + *funcs++ = Sacc_is_NULL; + *funcs++ = Xacc_is_Aacc; + *funcs++ = Yacc_is_Aacc; + + if (state->dst_blend > D_ARRAY_SIZE(Xacc_blend) || state->dst_blend < 1) + D_BUG( "unknown dst_blend %d", state->dst_blend ); + else + *funcs++ = Xacc_blend[state->dst_blend - 1]; + + /* add source to destination accumulator */ + switch (state->src_blend) { + case DSBF_ZERO: + break; + case DSBF_ONE: + case DSBF_SRCCOLOR: + case DSBF_INVSRCCOLOR: + case DSBF_SRCALPHA: + case DSBF_INVSRCALPHA: + if (SCacc.RGB.a || SCacc.RGB.r || + SCacc.RGB.g || SCacc.RGB.b) + *funcs++ = SCacc_add_to_Dacc; + break; + case DSBF_DESTALPHA: + case DSBF_INVDESTALPHA: + case DSBF_DESTCOLOR: + case DSBF_INVDESTCOLOR: + case DSBF_SRCALPHASAT: + *funcs++ = Sacc_is_Bacc; + *funcs++ = Sacc_add_to_Dacc; + break; + + default: + D_BUG( "unknown src_blend %d", state->src_blend ); + } + } + + /* demultiply result */ + if (state->drawingflags & DSDRAW_DEMULTIPLY) + *funcs++ = Dacc_demultiply; + + /* write to destination */ + *funcs++ = Sacc_is_Aacc; + if (state->drawingflags & DSDRAW_DST_COLORKEY) { + gfxs->Dkey = state->dst_colorkey; + *funcs++ = Sacc_toK_Aop_PFI[dst_pfi]; + } + else + *funcs++ = Sacc_to_Aop_PFI[dst_pfi]; + + /* store computed Cacc */ + gfxs->Cacc = Cacc; + gfxs->SCacc = SCacc; + } + else { + gfxs->need_accumulator = false; + + if (state->drawingflags & DSDRAW_DST_COLORKEY) { + gfxs->Dkey = state->dst_colorkey; + *funcs++ = Cop_toK_Aop_PFI[dst_pfi]; + } + else + *funcs++ = Cop_to_Aop_PFI[dst_pfi]; + } + break; + case DFXL_BLIT: + if (state->blittingflags == DSBLIT_BLEND_ALPHACHANNEL && + state->src_blend == DSBF_SRCALPHA && + state->dst_blend == DSBF_INVSRCALPHA) + { + if (gfxs->src_format == DSPF_ARGB && + Bop_argb_blend_alphachannel_src_invsrc_Aop_PFI[dst_pfi]) + { + *funcs++ = Bop_argb_blend_alphachannel_src_invsrc_Aop_PFI[dst_pfi]; + break; + } + } + if (state->blittingflags == DSBLIT_BLEND_ALPHACHANNEL && + state->src_blend == DSBF_ONE && + state->dst_blend == DSBF_INVSRCALPHA) + { + if (gfxs->src_format == DSPF_ARGB && + Bop_argb_blend_alphachannel_one_invsrc_Aop_PFI[dst_pfi]) + { + *funcs++ = Bop_argb_blend_alphachannel_one_invsrc_Aop_PFI[dst_pfi]; + break; + } + } + if (((state->blittingflags == (DSBLIT_COLORIZE | DSBLIT_BLEND_ALPHACHANNEL | + DSBLIT_SRC_PREMULTIPLY) && + state->src_blend == DSBF_ONE) + || + (state->blittingflags == (DSBLIT_COLORIZE | DSBLIT_BLEND_ALPHACHANNEL) && + state->src_blend == DSBF_SRCALPHA)) + && + state->dst_blend == DSBF_INVSRCALPHA) + { + if (gfxs->src_format == DSPF_A8 && Bop_a8_set_alphapixel_Aop_PFI[dst_pfi]) { + *funcs++ = Bop_a8_set_alphapixel_Aop_PFI[dst_pfi]; + break; + } + if (gfxs->src_format == DSPF_A1 && Bop_a1_set_alphapixel_Aop_PFI[dst_pfi]) { + *funcs++ = Bop_a1_set_alphapixel_Aop_PFI[dst_pfi]; + break; + } + } +#ifndef WORDS_BIGENDIAN + if (state->blittingflags == DSBLIT_NOFX && + source->config.format == DSPF_RGB24 && + destination->config.format == DSPF_RGB16) + { + *funcs++ = Bop_rgb24_to_Aop_rgb16_LE; + break; + } + if (state->blittingflags == DSBLIT_NOFX && + (source->config.format == DSPF_RGB32 || source->config.format == DSPF_ARGB) && + destination->config.format == DSPF_RGB16) + { + *funcs++ = Bop_rgb32_to_Aop_rgb16_LE; + break; + } +#endif + /* fallthru */ + case DFXL_STRETCHBLIT: { + int modulation = state->blittingflags & MODULATION_FLAGS; + + if (modulation) { + bool read_destination = false; + bool source_needs_destination = false; + bool scale_from_accumulator; + + /* check if destination has to be read */ + if (state->blittingflags & (DSBLIT_BLEND_ALPHACHANNEL | + DSBLIT_BLEND_COLORALPHA)) { + switch (state->src_blend) { + case DSBF_DESTALPHA: + case DSBF_DESTCOLOR: + case DSBF_INVDESTALPHA: + case DSBF_INVDESTCOLOR: + case DSBF_SRCALPHASAT: + source_needs_destination = true; + default: + ; + } + + read_destination = source_needs_destination || + (state->dst_blend != DSBF_ZERO) || + (state->blittingflags & DSBLIT_XOR); + } + else if (state->blittingflags & DSBLIT_XOR) { + read_destination = true; + } + + scale_from_accumulator = !read_destination && + (accel == DFXL_STRETCHBLIT); + + /* read the destination if needed */ + if (read_destination) { + *funcs++ = Sop_is_Aop; + if (DFB_PIXELFORMAT_IS_INDEXED(gfxs->dst_format)) + *funcs++ = Slut_is_Alut; + *funcs++ = Dacc_is_Aacc; + *funcs++ = Sop_PFI_to_Dacc[dst_pfi]; + + if (state->blittingflags & DSBLIT_DST_PREMULTIPLY) + *funcs++ = Dacc_premultiply; + } + else if (scale_from_accumulator) { + *funcs++ = Len_is_Slen; + } + + /* read the source */ + *funcs++ = Sop_is_Bop; + if (DFB_PIXELFORMAT_IS_INDEXED(gfxs->src_format)) + *funcs++ = Slut_is_Blut; + *funcs++ = Dacc_is_Bacc; + if (state->blittingflags & DSBLIT_SRC_COLORKEY) { + gfxs->Skey = state->src_colorkey; + if (accel == DFXL_BLIT || scale_from_accumulator) + *funcs++ = Sop_PFI_Kto_Dacc[src_pfi]; + else + *funcs++ = Sop_PFI_SKto_Dacc[src_pfi]; + } + else { + if (accel == DFXL_BLIT || scale_from_accumulator) + *funcs++ = Sop_PFI_to_Dacc[src_pfi]; + else + *funcs++ = Sop_PFI_Sto_Dacc[src_pfi]; + } + + if (!src_ycbcr && dst_ycbcr) { + if (DFB_COLOR_BITS_PER_PIXEL(gfxs->src_format)) + *funcs++ = Dacc_RGB_to_YCbCr; + /*else + *funcs++ = Dacc_Alpha_to_YCbCr;*/ + } + else if (src_ycbcr && !dst_ycbcr) { + if (DFB_COLOR_BITS_PER_PIXEL(gfxs->dst_format)) + *funcs++ = Dacc_YCbCr_to_RGB; + } + + /* Premultiply color alpha? */ + if (state->blittingflags & DSBLIT_SRC_PREMULTCOLOR) { + gfxs->Cacc.RGB.a = color.a + 1; + *funcs++ = Dacc_premultiply_color_alpha; + } + + /* modulate the source if requested */ + if (Dacc_modulation[modulation & 0x7]) { + /* modulation source */ + gfxs->Cacc.RGB.a = color.a + 1; + if (!dst_ycbcr) { + gfxs->Cacc.RGB.r = color.r + 1; + gfxs->Cacc.RGB.g = color.g + 1; + gfxs->Cacc.RGB.b = color.b + 1; + } else { + gfxs->Cacc.YUV.y = gfxs->YCop + 1; + gfxs->Cacc.YUV.u = gfxs->CbCop + 1; + gfxs->Cacc.YUV.v = gfxs->CrCop + 1; + } + + *funcs++ = Dacc_modulation[modulation & 0x7]; + } + + /* Premultiply (modulated) source alpha? */ + if (state->blittingflags & DSBLIT_SRC_PREMULTIPLY) + *funcs++ = Dacc_premultiply; + + /* Xor source with destination */ + if (state->blittingflags & DSBLIT_XOR) { + *funcs++ = Sacc_is_Aacc; + *funcs++ = Dacc_is_Bacc; + *funcs++ = Sacc_xor_Dacc; + } + + /* do blend functions and combine both accumulators */ + if (state->blittingflags & (DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_BLEND_COLORALPHA)) { + /* Xacc will be blended and written to while + Sacc and Dacc point to the SRC and DST + as referenced by the blending functions */ + *funcs++ = Sacc_is_Bacc; + *funcs++ = Dacc_is_Aacc; + + if (source_needs_destination && + state->dst_blend != DSBF_ONE) { + /* blend the destination */ + *funcs++ = Yacc_is_Aacc; + *funcs++ = Xacc_is_Tacc; + *funcs++ = Xacc_blend[state->dst_blend - 1]; + + /* blend the source */ + *funcs++ = Xacc_is_Bacc; + *funcs++ = Yacc_is_Bacc; + *funcs++ = Xacc_blend[state->src_blend - 1]; + } + else { + /* blend the destination if needed */ + if (read_destination) { + *funcs++ = Yacc_is_Aacc; + *funcs++ = Xacc_is_Tacc; + *funcs++ = Xacc_blend[state->dst_blend - 1]; + } + + /* blend the source */ + *funcs++ = Xacc_is_Bacc; + *funcs++ = Yacc_is_Bacc; + *funcs++ = Xacc_blend[state->src_blend - 1]; + } + + /* add the destination to the source */ + if (read_destination) { + *funcs++ = Sacc_is_Tacc; + *funcs++ = Dacc_is_Bacc; + *funcs++ = Sacc_add_to_Dacc; + } + } + + if (state->blittingflags & DSBLIT_DEMULTIPLY) { + *funcs++ = Dacc_is_Bacc; + *funcs++ = Dacc_demultiply; + } + + /* write source to destination */ + *funcs++ = Sacc_is_Bacc; + if (scale_from_accumulator) { + *funcs++ = Len_is_Dlen; + if (state->blittingflags & DSBLIT_DST_COLORKEY ) { + gfxs->Dkey = state->dst_colorkey; + *funcs++ = Sacc_StoK_Aop_PFI[dst_pfi]; + } else + *funcs++ = Sacc_Sto_Aop_PFI[dst_pfi]; + } else { + if (state->blittingflags & DSBLIT_DST_COLORKEY ) { + gfxs->Dkey = state->dst_colorkey; + *funcs++ = Sacc_toK_Aop_PFI[dst_pfi]; + } else + *funcs++ = Sacc_to_Aop_PFI[dst_pfi]; + } + } + else if (state->blittingflags == DSBLIT_INDEX_TRANSLATION && + DFB_PIXELFORMAT_IS_INDEXED(gfxs->src_format) && + DFB_PIXELFORMAT_IS_INDEXED(gfxs->dst_format)) + { + gfxs->trans = state->index_translation; + gfxs->num_trans = state->num_translation; + + switch (gfxs->src_format) { + case DSPF_LUT2: + switch (gfxs->dst_format) { + case DSPF_LUT8: + *funcs++ = Bop_lut2_translate_to_Aop_lut8; + break; + + default: + D_ONCE( "no index translation to %s implemented", + dfb_pixelformat_name( gfxs->dst_format ) ); + break; + } + break; + + default: + D_ONCE( "no index translation from %s implemented", + dfb_pixelformat_name( gfxs->src_format ) ); + break; + } + } + else if ((gfxs->src_format == gfxs->dst_format && + (!DFB_PIXELFORMAT_IS_INDEXED(gfxs->src_format) || + dfb_palette_equal( gfxs->Alut, gfxs->Blut ))) || + ((gfxs->src_format == DSPF_I420 || gfxs->src_format == DSPF_YV12) && + (gfxs->dst_format == DSPF_I420 || gfxs->dst_format == DSPF_YV12))) + { + gfxs->need_accumulator = false; + + if (accel == DFXL_BLIT) { + if (state->blittingflags & DSBLIT_SRC_COLORKEY && + state->blittingflags & DSBLIT_DST_COLORKEY) { + gfxs->Skey = state->src_colorkey; + gfxs->Dkey = state->dst_colorkey; + *funcs++ = Bop_PFI_KtoK_Aop_PFI[dst_pfi]; + } else if (state->blittingflags & DSBLIT_SRC_COLORKEY) { + gfxs->Skey = state->src_colorkey; + *funcs++ = Bop_PFI_Kto_Aop_PFI[dst_pfi]; + } else if (state->blittingflags & DSBLIT_DST_COLORKEY) { + gfxs->Dkey = state->dst_colorkey; + *funcs++ = Bop_PFI_toK_Aop_PFI[dst_pfi]; + } else if (state->blittingflags & (DSBLIT_ROTATE90 | + DSBLIT_ROTATE180 | + DSBLIT_ROTATE270)) { + *funcs++ = Bop_PFI_toR_Aop_PFI[dst_pfi]; + } else + *funcs++ = Bop_PFI_to_Aop_PFI[dst_pfi]; + } + else { + if (state->blittingflags & DSBLIT_SRC_COLORKEY && + state->blittingflags & DSBLIT_DST_COLORKEY) { + gfxs->Skey = state->src_colorkey; + gfxs->Dkey = state->dst_colorkey; + *funcs++ = Bop_PFI_SKtoK_Aop_PFI[dst_pfi]; + } else if (state->blittingflags & DSBLIT_SRC_COLORKEY) { + gfxs->Skey = state->src_colorkey; + *funcs++ = Bop_PFI_SKto_Aop_PFI[dst_pfi]; + } else if (state->blittingflags & DSBLIT_DST_COLORKEY) { + gfxs->Dkey = state->dst_colorkey; + *funcs++ = Bop_PFI_StoK_Aop_PFI[dst_pfi]; + } else + *funcs++ = Bop_PFI_Sto_Aop_PFI[dst_pfi]; + } + } + else { + bool scale_from_accumulator = (src_ycbcr != dst_ycbcr) && + (accel == DFXL_STRETCHBLIT); + + if (scale_from_accumulator) + *funcs++ = Len_is_Slen; + + gfxs->Sop = gfxs->Bop; + + if (DFB_PIXELFORMAT_IS_INDEXED(gfxs->src_format)) + *funcs++ = Slut_is_Blut; + + if (accel == DFXL_BLIT || scale_from_accumulator) { + if (state->blittingflags & DSBLIT_SRC_COLORKEY ) { + gfxs->Skey = state->src_colorkey; + *funcs++ = Sop_PFI_Kto_Dacc[src_pfi]; + } + else + *funcs++ = Sop_PFI_to_Dacc[src_pfi]; + } + else { /* DFXL_STRETCHBLIT */ + + if (state->blittingflags & DSBLIT_SRC_COLORKEY ) { + gfxs->Skey = state->src_colorkey; + *funcs++ = Sop_PFI_SKto_Dacc[src_pfi]; + } + else + *funcs++ = Sop_PFI_Sto_Dacc[src_pfi]; + + } + + if (!src_ycbcr && dst_ycbcr) { + if (DFB_COLOR_BITS_PER_PIXEL(gfxs->src_format)) + *funcs++ = Dacc_RGB_to_YCbCr; + else + *funcs++ = Dacc_Alpha_to_YCbCr; + } + else if (src_ycbcr && !dst_ycbcr) { + if (DFB_COLOR_BITS_PER_PIXEL(gfxs->dst_format)) + *funcs++ = Dacc_YCbCr_to_RGB; + } + + if (scale_from_accumulator) { + *funcs++ = Len_is_Dlen; + if (state->blittingflags & DSBLIT_DST_COLORKEY ) { + gfxs->Dkey = state->dst_colorkey; + *funcs++ = Sacc_StoK_Aop_PFI[dst_pfi]; + } else + *funcs++ = Sacc_Sto_Aop_PFI[dst_pfi]; + } else { + if (state->blittingflags & DSBLIT_DST_COLORKEY ) { + gfxs->Dkey = state->dst_colorkey; + *funcs++ = Sacc_toK_Aop_PFI[dst_pfi]; + } else + *funcs++ = Sacc_to_Aop_PFI[dst_pfi]; + } + } + break; + } + default: + D_ONCE("unimplemented drawing/blitting function"); + gRelease( state ); + return false; + } + + *funcs = NULL; + + dfb_state_update( state, state->flags & CSF_SOURCE_LOCKED ); + + return true; +} + +void gRelease( CardState *state ) +{ + dfb_surface_unlock_buffer( state->destination, &state->dst ); + + if (state->flags & CSF_SOURCE_LOCKED) { + dfb_surface_unlock_buffer( state->source, &state->src ); + state->flags &= ~CSF_SOURCE_LOCKED; + } +} + +#define CHECK_PIPELINE() \ + { \ + if (!gfxs->funcs[0]) \ + return; \ + \ + if (dfb_config->software_trace) { \ + int i; \ + GenefxFunc *funcs = gfxs->funcs; \ + \ + direct_log_lock( NULL ); \ + direct_log_printf( NULL, " Software Fallback Pipeline:\n" ); \ + \ + for (i=0; funcs[i]; ++i) \ + direct_log_printf( NULL, " [%2d] %s\n", i, \ + direct_trace_lookup_symbol_at( funcs[i] ) ); \ + \ + direct_log_printf( NULL, "\n" ); \ + direct_log_unlock( NULL ); \ + } \ + } + +#define RUN_PIPELINE() \ + { \ + int i; \ + GenefxFunc *funcs = gfxs->funcs; \ + \ + for (i=0; funcs[i]; ++i) \ + funcs[i]( gfxs ); \ + } + + +static inline void Aop_xy( GenefxState *gfxs, int x, int y ) +{ + int pitch = gfxs->dst_pitch; + + gfxs->Aop[0] = gfxs->dst_org[0]; + gfxs->AopY = y; + + if (gfxs->dst_caps & DSCAPS_SEPARATED) { + gfxs->Aop_field = y & 1; + if (gfxs->Aop_field) + gfxs->Aop[0] += gfxs->dst_field_offset; + + y /= 2; + } + + D_ASSUME( !(x & DFB_PIXELFORMAT_ALIGNMENT(gfxs->dst_format)) ); + + gfxs->Aop[0] += y * pitch + DFB_BYTES_PER_LINE( gfxs->dst_format, x ); + + if (DFB_PLANAR_PIXELFORMAT(gfxs->dst_format)) { + int dst_field_offset = gfxs->dst_field_offset; + + switch (gfxs->dst_format) { + case DSPF_YV12: + case DSPF_I420: + dst_field_offset /= 4; + pitch /= 2; + y /= 2; + x /= 2; + break; + case DSPF_NV12: + case DSPF_NV21: + dst_field_offset /= 2; + y /= 2; + case DSPF_NV16: + x &= ~1; + break; + default: + break; + } + + gfxs->Aop[1] = gfxs->dst_org[1]; + gfxs->Aop[2] = gfxs->dst_org[2]; + + if (gfxs->dst_caps & DSCAPS_SEPARATED && gfxs->Aop_field) { + gfxs->Aop[1] += dst_field_offset; + gfxs->Aop[2] += dst_field_offset; + } + + gfxs->Aop[1] += y * pitch + x; + gfxs->Aop[2] += y * pitch + x; + } +} + +static inline void Aop_crab( GenefxState *gfxs ) +{ + gfxs->Aop[0] += gfxs->dst_bpp; + gfxs->AopY++; +} + +static inline void Aop_next( GenefxState *gfxs ) +{ + int pitch = gfxs->dst_pitch; + + if (gfxs->dst_caps & DSCAPS_SEPARATED) { + gfxs->Aop_field++; + + if (gfxs->Aop_field & 1) + gfxs->Aop[0] += gfxs->dst_field_offset; + else + gfxs->Aop[0] += pitch - gfxs->dst_field_offset; + } + else + gfxs->Aop[0] += pitch; + + if (DFB_PLANAR_PIXELFORMAT(gfxs->dst_format)) { + if (gfxs->dst_format == DSPF_YV12 || gfxs->dst_format == DSPF_I420) { + if (gfxs->AopY & 1) { + if (gfxs->dst_caps & DSCAPS_SEPARATED) { + if (gfxs->Aop_field & 2) { + gfxs->Aop[1] += gfxs->dst_field_offset/4; + gfxs->Aop[2] += gfxs->dst_field_offset/4; + } + else { + gfxs->Aop[1] += pitch/2 - gfxs->dst_field_offset/4; + gfxs->Aop[2] += pitch/2 - gfxs->dst_field_offset/4; + } + } + else { + gfxs->Aop[1] += pitch/2; + gfxs->Aop[2] += pitch/2; + } + } + } + else if (gfxs->dst_format == DSPF_NV12 || gfxs->dst_format == DSPF_NV21) { + if (gfxs->AopY & 1) { + if (gfxs->dst_caps & DSCAPS_SEPARATED) { + if (gfxs->Aop_field & 2) + gfxs->Aop[1] += gfxs->dst_field_offset/2; + else + gfxs->Aop[1] += pitch - gfxs->dst_field_offset/2; + } + else { + gfxs->Aop[1] += pitch; + } + } + } + else { /* NV16 */ + if (gfxs->dst_caps & DSCAPS_SEPARATED) { + if (gfxs->Aop_field & 1) + gfxs->Aop[1] += gfxs->dst_field_offset; + else + gfxs->Aop[1] += pitch - gfxs->dst_field_offset; + } + else { + gfxs->Aop[1] += pitch; + } + } + } + + gfxs->AopY++; +} + +static inline void Aop_prev( GenefxState *gfxs ) +{ + int pitch = gfxs->dst_pitch; + + if (gfxs->dst_caps & DSCAPS_SEPARATED) { + gfxs->Aop_field++; + + if (gfxs->Aop_field & 1) + gfxs->Aop[0] += gfxs->dst_field_offset - pitch; + else + gfxs->Aop[0] -= gfxs->dst_field_offset; + } + else + gfxs->Aop[0] -= pitch; + + if (DFB_PLANAR_PIXELFORMAT(gfxs->dst_format)) { + if (gfxs->dst_format == DSPF_YV12 || gfxs->dst_format == DSPF_I420) { + if (gfxs->AopY & 1) { + if (gfxs->dst_caps & DSCAPS_SEPARATED) { + if (gfxs->Aop_field & 2) { + gfxs->Aop[1] += gfxs->dst_field_offset/4 - pitch/2; + gfxs->Aop[2] += gfxs->dst_field_offset/4 - pitch/2; + } + else { + gfxs->Aop[1] -= gfxs->dst_field_offset/4; + gfxs->Aop[2] -= gfxs->dst_field_offset/4; + } + } + else { + gfxs->Aop[1] -= pitch/2; + gfxs->Aop[2] -= pitch/2; + } + } + } + else if (gfxs->dst_format == DSPF_NV12 || gfxs->dst_format == DSPF_NV21) { + if (gfxs->AopY & 1) { + if (gfxs->dst_caps & DSCAPS_SEPARATED) { + if (gfxs->Aop_field & 2) + gfxs->Aop[1] += gfxs->dst_field_offset/2 - pitch; + else + gfxs->Aop[1] -= gfxs->dst_field_offset/2; + } + else { + gfxs->Aop[1] -= pitch; + } + } + } + else { /* NV16 */ + if (gfxs->dst_caps & DSCAPS_SEPARATED) { + if (gfxs->Aop_field & 1) + gfxs->Aop[1] += gfxs->dst_field_offset - pitch; + else + gfxs->Aop[1] -= gfxs->dst_field_offset; + } + else { + gfxs->Aop[1] -= pitch; + } + } + } + + gfxs->AopY--; +} + + +static inline void Bop_xy( GenefxState *gfxs, int x, int y ) +{ + int pitch = gfxs->src_pitch; + + gfxs->Bop[0] = gfxs->src_org[0]; + gfxs->BopY = y; + + if (gfxs->src_caps & DSCAPS_SEPARATED) { + gfxs->Bop_field = y & 1; + if (gfxs->Bop_field) + gfxs->Bop[0] += gfxs->src_field_offset; + + y /= 2; + } + + D_ASSUME( !(x & DFB_PIXELFORMAT_ALIGNMENT(gfxs->src_format)) ); + + gfxs->Bop[0] += y * pitch + DFB_BYTES_PER_LINE( gfxs->src_format, x ); + + if (DFB_PLANAR_PIXELFORMAT(gfxs->src_format)) { + int src_field_offset = gfxs->src_field_offset; + + switch (gfxs->src_format) { + case DSPF_YV12: + case DSPF_I420: + src_field_offset /= 4; + pitch /= 2; + y /= 2; + x /= 2; + break; + case DSPF_NV12: + case DSPF_NV21: + src_field_offset /= 2; + y /= 2; + case DSPF_NV16: + x &= ~1; + break; + default: + break; + } + + gfxs->Bop[1] = gfxs->src_org[1]; + gfxs->Bop[2] = gfxs->src_org[2]; + + if (gfxs->src_caps & DSCAPS_SEPARATED && gfxs->Bop_field) { + gfxs->Bop[1] += src_field_offset; + gfxs->Bop[2] += src_field_offset; + } + + gfxs->Bop[1] += y * pitch + x; + gfxs->Bop[2] += y * pitch + x; + } +} + +static inline void Bop_next( GenefxState *gfxs ) +{ + int pitch = gfxs->src_pitch; + + if (gfxs->src_caps & DSCAPS_SEPARATED) { + gfxs->Bop_field++; + + if (gfxs->Bop_field & 1) + gfxs->Bop[0] += gfxs->src_field_offset; + else + gfxs->Bop[0] += pitch - gfxs->src_field_offset; + } + else + gfxs->Bop[0] += pitch; + + if (DFB_PLANAR_PIXELFORMAT(gfxs->src_format)) { + if (gfxs->src_format == DSPF_YV12 || gfxs->src_format == DSPF_I420) { + if (gfxs->BopY & 1) { + if (gfxs->src_caps & DSCAPS_SEPARATED) { + if (gfxs->Bop_field & 2) { + gfxs->Bop[1] += gfxs->src_field_offset/4; + gfxs->Bop[2] += gfxs->src_field_offset/4; + } + else { + gfxs->Bop[1] += pitch/2 - gfxs->src_field_offset/4; + gfxs->Bop[2] += pitch/2 - gfxs->src_field_offset/4; + } + } + else { + gfxs->Bop[1] += pitch/2; + gfxs->Bop[2] += pitch/2; + } + } + } + else if (gfxs->src_format == DSPF_NV12 || gfxs->src_format == DSPF_NV21) { + if (gfxs->BopY & 1) { + if (gfxs->src_caps & DSCAPS_SEPARATED) { + if (gfxs->Bop_field & 2) + gfxs->Bop[1] += gfxs->src_field_offset/2; + else + gfxs->Bop[1] += pitch - gfxs->src_field_offset/2; + } + else { + gfxs->Bop[1] += pitch; + } + } + } + else { /* NV16 */ + if (gfxs->src_caps & DSCAPS_SEPARATED) { + if (gfxs->Bop_field & 1) + gfxs->Bop[1] += gfxs->src_field_offset; + else + gfxs->Bop[1] += pitch - gfxs->src_field_offset; + } + else { + gfxs->Bop[1] += pitch; + } + } + } + + gfxs->BopY++; +} + +static inline void Bop_prev( GenefxState *gfxs ) +{ + int pitch = gfxs->src_pitch; + + if (gfxs->src_caps & DSCAPS_SEPARATED) { + gfxs->Bop_field++; + + if (gfxs->Bop_field & 1) + gfxs->Bop[0] += gfxs->src_field_offset - pitch; + else + gfxs->Bop[0] -= gfxs->src_field_offset; + } + else + gfxs->Bop[0] -= pitch; + + if (DFB_PLANAR_PIXELFORMAT(gfxs->src_format)) { + if (gfxs->src_format == DSPF_YV12 || gfxs->src_format == DSPF_I420) { + if (gfxs->BopY & 1) { + if (gfxs->src_caps & DSCAPS_SEPARATED) { + if (gfxs->Bop_field & 2) { + gfxs->Bop[1] += gfxs->src_field_offset/4 - pitch/2; + gfxs->Bop[2] += gfxs->src_field_offset/4 - pitch/2; + } + else { + gfxs->Bop[1] -= gfxs->src_field_offset/4; + gfxs->Bop[2] -= gfxs->src_field_offset/4; + } + } + else { + gfxs->Bop[1] -= pitch/2; + gfxs->Bop[2] -= pitch/2; + } + } + } + else if (gfxs->src_format == DSPF_NV12 || gfxs->src_format == DSPF_NV21) { + if (gfxs->BopY & 1) { + if (gfxs->src_caps & DSCAPS_SEPARATED) { + if (gfxs->Bop_field & 2) + gfxs->Bop[1] += gfxs->src_field_offset/2 - pitch; + else + gfxs->Bop[1] -= gfxs->src_field_offset/2; + } + else { + gfxs->Bop[1] -= pitch; + } + } + } + else { /* NV16 */ + if (gfxs->src_caps & DSCAPS_SEPARATED) { + if (gfxs->Bop_field & 1) + gfxs->Bop[1] += gfxs->src_field_offset - pitch; + else + gfxs->Bop[1] -= gfxs->src_field_offset; + } + else { + gfxs->Bop[1] -= pitch; + } + } + } + + gfxs->BopY--; +} + +static bool +ABacc_prepare( GenefxState *gfxs, int width ) +{ + int size; + + if (!gfxs->need_accumulator) + return true; + + size = (width + 31) & ~31; + + if (gfxs->ABsize < size) { + void *ABstart = D_MALLOC( size * sizeof(GenefxAccumulator) * 3 + 31 ); + + if (!ABstart) { + D_WARN( "out of memory" ); + return false; + } + + if (gfxs->ABstart) + D_FREE( gfxs->ABstart ); + + gfxs->ABstart = ABstart; + gfxs->ABsize = size; + gfxs->Aacc = (GenefxAccumulator*) (((unsigned long)ABstart+31) & ~31); + gfxs->Bacc = gfxs->Aacc + size; + gfxs->Tacc = gfxs->Aacc + size + size; + } + + gfxs->Sacc = gfxs->Dacc = gfxs->Aacc; + + return true; +} + +static void +ABacc_flush( GenefxState *gfxs ) +{ + if (dfb_config->keep_accumulators >= 0 && gfxs->ABsize > dfb_config->keep_accumulators) { + D_FREE( gfxs->ABstart ); + + gfxs->ABsize = 0; + gfxs->ABstart = NULL; + gfxs->Aacc = NULL; + gfxs->Bacc = NULL; + gfxs->Sacc = NULL; + gfxs->Dacc = NULL; + } +} + +void gFillRectangle( CardState *state, DFBRectangle *rect ) +{ + int h; + GenefxState *gfxs = state->gfxs; + + D_ASSERT( gfxs != NULL ); + + if (dfb_config->software_warn) { + D_WARN( "FillRectangle (%4d,%4d-%4dx%4d) %6s, flags 0x%08x, color 0x%02x%02x%02x%02x", + DFB_RECTANGLE_VALS(rect), dfb_pixelformat_name(gfxs->dst_format), state->drawingflags, + state->color.a, state->color.r, state->color.g, state->color.b ); + } + + D_ASSERT( state->clip.x1 <= rect->x ); + D_ASSERT( state->clip.y1 <= rect->y ); + D_ASSERT( state->clip.x2 >= (rect->x + rect->w - 1) ); + D_ASSERT( state->clip.y2 >= (rect->y + rect->h - 1) ); + + CHECK_PIPELINE(); + + if (!ABacc_prepare( gfxs, rect->w )) + return; + + gfxs->length = rect->w; + + Aop_xy( gfxs, rect->x, rect->y ); + + h = rect->h; + while (h--) { + RUN_PIPELINE(); + + Aop_next( gfxs ); + } + + ABacc_flush( gfxs ); +} + +void gDrawLine( CardState *state, DFBRegion *line ) +{ + GenefxState *gfxs = state->gfxs; + + int i,dx,dy,sdy,dxabs,dyabs,x,y,px,py; + + D_ASSERT( gfxs != NULL ); + + CHECK_PIPELINE(); + + /* the horizontal distance of the line */ + dx = line->x2 - line->x1; + dxabs = abs(dx); + + if (!ABacc_prepare( gfxs, dxabs )) + return; + + /* the vertical distance of the line */ + dy = line->y2 - line->y1; + dyabs = abs(dy); + + if (!dx || !dy) { /* draw horizontal/vertical line */ + DFBRectangle rect = { + MIN (line->x1, line->x2), + MIN (line->y1, line->y2), + dxabs + 1, dyabs + 1}; + + gFillRectangle( state, &rect ); + return; + } + + if (dfb_config->software_warn) { + D_WARN( "DrawLine (%4d,%4d-%4d,%4d) %6s, flags 0x%08x, color 0x%02x%02x%02x%02x", + DFB_RECTANGLE_VALS_FROM_REGION(line), dfb_pixelformat_name(gfxs->dst_format), state->drawingflags, + state->color.a, state->color.r, state->color.g, state->color.b ); + } + + sdy = SIGN(dy) * SIGN(dx); + x = dyabs >> 1; + y = dxabs >> 1; + + if (dx > 0) { + px = line->x1; + py = line->y1; + } + else { + px = line->x2; + py = line->y2; + } + + if (dxabs >= dyabs) { /* the line is more horizontal than vertical */ + + for (i=0, gfxs->length=1; ilength++) { + y += dyabs; + if (y >= dxabs) { + Aop_xy( gfxs, px, py ); + RUN_PIPELINE(); + px += gfxs->length; + gfxs->length = 0; + y -= dxabs; + py += sdy; + } + } + Aop_xy( gfxs, px, py ); + RUN_PIPELINE(); + } + else { /* the line is more vertical than horizontal */ + + gfxs->length = 1; + Aop_xy( gfxs, px, py ); + RUN_PIPELINE(); + + for (i=0; i= dyabs) { + x -= dyabs; + px++; + } + py += sdy; + + Aop_xy( gfxs, px, py ); + RUN_PIPELINE(); + } + } + + ABacc_flush( gfxs ); +} + +void gBlit( CardState *state, DFBRectangle *rect, int dx, int dy ) +{ + GenefxState *gfxs = state->gfxs; + int x, h; + + D_ASSERT( gfxs != NULL ); + + if (dfb_config->software_warn) { + D_WARN( "Blit (%4d,%4d-%4dx%4d) %6s, flags 0x%08x, funcs %d/%d, color 0x%02x%02x%02x%02x, source (%4d,%4d) %6s", + dx, dy, rect->w, rect->h, dfb_pixelformat_name(gfxs->dst_format), state->blittingflags, + state->src_blend, state->dst_blend, + state->color.a, state->color.r, state->color.g, state->color.b, rect->x, rect->y, + dfb_pixelformat_name(gfxs->src_format) ); + } + + D_ASSERT( state->clip.x1 <= dx ); + D_ASSERT( state->clip.y1 <= dy ); + D_ASSERT( (state->blittingflags & (DSBLIT_ROTATE90 | DSBLIT_ROTATE270)) || state->clip.x2 >= (dx + rect->w - 1) ); + D_ASSERT( (state->blittingflags & (DSBLIT_ROTATE90 | DSBLIT_ROTATE270)) || state->clip.y2 >= (dy + rect->h - 1) ); + D_ASSERT( !(state->blittingflags & (DSBLIT_ROTATE90 | DSBLIT_ROTATE270)) || state->clip.x2 >= (dx + rect->h - 1) ); + D_ASSERT( !(state->blittingflags & (DSBLIT_ROTATE90 | DSBLIT_ROTATE270)) || state->clip.y2 >= (dy + rect->w - 1) ); + + CHECK_PIPELINE(); + + if (!ABacc_prepare( gfxs, rect->w )) + return; + + if (gfxs->src_org[0] == gfxs->dst_org[0] && dy == rect->y && dx > rect->x) + /* we must blit from right to left */ + gfxs->Astep = gfxs->Bstep = -1; + else + /* we must blit from left to right*/ + gfxs->Astep = gfxs->Bstep = 1; + + if (state->blittingflags & DSBLIT_ROTATE90) + gfxs->Astep *= -gfxs->dst_pitch / gfxs->dst_bpp; + else if (state->blittingflags & DSBLIT_ROTATE180) + gfxs->Astep *= -1; + else if (state->blittingflags & DSBLIT_ROTATE270) + gfxs->Astep *= gfxs->dst_pitch / gfxs->dst_bpp; + + switch (gfxs->src_format) { + case DSPF_A4: + case DSPF_YUY2: + case DSPF_UYVY: + rect->x &= ~1; + break; + default: + break; + } + + switch (gfxs->dst_format) { + case DSPF_A4: + case DSPF_YUY2: + case DSPF_UYVY: + dx &= ~1; + break; + default: + break; + } + + gfxs->length = rect->w; + + if (state->blittingflags == DSBLIT_ROTATE180 && gfxs->src_format == gfxs->dst_format) { + Aop_xy( gfxs, dx, dy ); + Bop_xy( gfxs, rect->x + rect->w - 1, rect->y + rect->h - 1 ); + + switch (DFB_BYTES_PER_PIXEL(gfxs->dst_format)) { + case 4: { + for (h = rect->h; h; h--) { + u32 *src = gfxs->Bop[0]; + u32 *dst = gfxs->Aop[0]; + + for (x=0; xw; x++) + dst[x] = src[-x]; + + Aop_next( gfxs ); + Bop_prev( gfxs ); + } + return; + } + case 2: { + for (h = rect->h; h; h--) { + u16 *src = gfxs->Bop[0]; + u16 *dst = gfxs->Aop[0]; + + for (x=0; xw; x++) + dst[x] = src[-x]; + + Aop_next( gfxs ); + Bop_prev( gfxs ); + } + return; + } + case 1: { + for (h = rect->h; h; h--) { + u8 *src = gfxs->Bop[0]; + u8 *dst = gfxs->Aop[0]; + + for (x=0; xw; x++) + dst[x] = src[-x]; + + Aop_next( gfxs ); + Bop_prev( gfxs ); + } + return; + } + + default: + break; + } + } + + if (state->blittingflags & DSBLIT_ROTATE180) { + Aop_xy( gfxs, dx + rect->w - 1, dy ); + Bop_xy( gfxs, rect->x, rect->y + rect->h - 1 ); + + for (h = rect->h; h; h--) { + RUN_PIPELINE(); + + Aop_next( gfxs ); + Bop_prev( gfxs ); + } + return; + } + else if( state->blittingflags & DSBLIT_ROTATE270 ) + { + Aop_xy( gfxs, dx, dy ); + Bop_xy( gfxs, rect->x, rect->y + rect->h - 1 ); + + for( h = rect->h; h; h-- ) + { + RUN_PIPELINE(); + + Aop_crab( gfxs ); + Bop_prev( gfxs ); + } + return; + } + else if( state->blittingflags & DSBLIT_ROTATE90 ) + { + Aop_xy( gfxs, dx, dy + rect->w - 1 ); + Bop_xy( gfxs, rect->x, rect->y ); + + for( h = rect->h; h; h-- ) + { + RUN_PIPELINE(); + + Aop_crab( gfxs ); + Bop_next( gfxs ); + } + return; + } + + if (gfxs->src_org[0] == gfxs->dst_org[0] && dy > rect->y && + !(state->blittingflags & DSBLIT_DEINTERLACE)) { + /* we must blit from bottom to top */ + Aop_xy( gfxs, dx, dy + rect->h - 1 ); + Bop_xy( gfxs, rect->x, rect->y + rect->h - 1 ); + + for (h = rect->h; h; h--) { + RUN_PIPELINE(); + + Aop_prev( gfxs ); + Bop_prev( gfxs ); + } + } + else { + /* we must blit from top to bottom */ + Aop_xy( gfxs, dx, dy ); + Bop_xy( gfxs, rect->x, rect->y ); + + if (state->blittingflags & DSBLIT_DEINTERLACE) { + if (state->source->field) { + Aop_next( gfxs ); + Bop_next( gfxs ); + rect->h--; + } + + for (h = rect->h/2; h; h--) { + RUN_PIPELINE(); + + Aop_next( gfxs ); + + RUN_PIPELINE(); + + Aop_next( gfxs ); + + Bop_next( gfxs ); + Bop_next( gfxs ); + } + } /* ! DSBLIT_DEINTERLACE */ + else { + for (h = rect->h; h; h--) { + RUN_PIPELINE(); + + Aop_next( gfxs ); + Bop_next( gfxs ); + } + } + } + + ABacc_flush( gfxs ); +} + +/**********************************************************************************************************************/ +/********* **************************************************************************************************/ +/*** Smooth scaling routines ******************************************************************************************/ +/********* **************************************************************************************************/ +/**********************************************************************************************************************/ + +#if DFB_SMOOTH_SCALING + +typedef struct { + DFBRegion clip; + const void *colors; + ulong protect; + ulong key; +} StretchCtx; + +typedef void (*StretchHVx)( void *dst, + int dpitch, + const void *src, + int spitch, + int width, + int height, + int dst_width, + int dst_height, + const StretchCtx *ctx ); + +#define STRETCH_NONE 0 +#define STRETCH_SRCKEY 1 +#define STRETCH_PROTECT 2 +#define STRETCH_SRCKEY_PROTECT 3 +#define STRETCH_NUM 4 + +typedef struct { + struct { + StretchHVx up[STRETCH_NUM]; + StretchHVx down[STRETCH_NUM]; + } f[DFB_NUM_PIXELFORMATS]; +} StretchFunctionTable; + +/**********************************************************************************************************************/ +/*** 16 bit RGB 565 scalers *******************************************************************************************/ +/**********************************************************************************************************************/ + +#define DST_FORMAT DSPF_RGB16 +#define TABLE_NAME stretch_hvx_RGB16 +#define FUNC_NAME(UPDOWN,K,P,F) stretch_hvx_RGB16_ ## UPDOWN ## _ ## K ## P ## _ ## F +#define SHIFT_R5 5 +#define SHIFT_R6 6 +#define X_F81F 0xf81f +#define X_07E0 0x07e0 +#define MASK_RGB 0xffff + +#define FORMAT_RGB16 +#include "stretch_up_down_16.h" +#undef FORMAT_RGB16 + +#undef DST_FORMAT +#undef TABLE_NAME +#undef FUNC_NAME +#undef SHIFT_R5 +#undef SHIFT_R6 +#undef X_F81F +#undef X_07E0 +#undef MASK_RGB + +/**********************************************************************************************************************/ +/*** 16 bit ARGB 4444 scalers *****************************************************************************************/ +/**********************************************************************************************************************/ + +#define DST_FORMAT DSPF_ARGB4444 +#define TABLE_NAME stretch_hvx_ARGB4444 +#define FUNC_NAME(UPDOWN,K,P,F) stretch_hvx_ARGB4444_ ## UPDOWN ## _ ## K ## P ## _ ## F +#define SHIFT_R5 4 +#define SHIFT_R6 4 +#define X_F81F 0x0f0f +#define X_07E0 0xf0f0 +#define MASK_RGB 0x0fff +#define HAS_ALPHA + +#define FORMAT_ARGB4444 +#include "stretch_up_down_16.h" +#undef FORMAT_ARGB4444 + +#undef DST_FORMAT +#undef TABLE_NAME +#undef FUNC_NAME +#undef SHIFT_R5 +#undef SHIFT_R6 +#undef X_F81F +#undef X_07E0 +#undef MASK_RGB +#undef HAS_ALPHA + +/**********************************************************************************************************************/ +/*** 16 bit RGBA 4444 scalers *****************************************************************************************/ +/**********************************************************************************************************************/ + +#define DST_FORMAT DSPF_RGBA4444 +#define TABLE_NAME stretch_hvx_RGBA4444 +#define FUNC_NAME(UPDOWN,K,P,F) stretch_hvx_RGBA4444_ ## UPDOWN ## _ ## K ## P ## _ ## F +#define SHIFT_R5 4 +#define SHIFT_R6 4 +#define X_F81F 0x0f0f +#define X_07E0 0xf0f0 +#define MASK_RGB 0xfff0 +#define HAS_ALPHA + +#define FORMAT_RGBA4444 +#include "stretch_up_down_16.h" +#undef FORMAT_RGBA4444 + +#undef DST_FORMAT +#undef TABLE_NAME +#undef FUNC_NAME +#undef SHIFT_R5 +#undef SHIFT_R6 +#undef X_F81F +#undef X_07E0 +#undef MASK_RGB +#undef HAS_ALPHA + +/**********************************************************************************************************************/ +/*** 32 bit ARGB 8888 scalers *****************************************************************************************/ +/**********************************************************************************************************************/ + +#define DST_FORMAT DSPF_ARGB +#define TABLE_NAME stretch_hvx_ARGB +#define FUNC_NAME(UPDOWN,K,P,F) stretch_hvx_ARGB_ ## UPDOWN ## _ ## K ## P ## _ ## F +#define SHIFT_R8 8 +#define SHIFT_L8 8 +#define X_00FF00FF 0x00ff00ff +#define X_FF00FF00 0xff00ff00 +#define MASK_RGB 0x00ffffff +#define HAS_ALPHA + +#include "stretch_up_down_32.h" + +#undef DST_FORMAT +#undef TABLE_NAME +#undef FUNC_NAME +#undef SHIFT_R8 +#undef SHIFT_L8 +#undef X_00FF00FF +#undef X_FF00FF00 +#undef MASK_RGB +#undef HAS_ALPHA + +/**********************************************************************************************************************/ +/*** 32 bit RGB 888 scalers *******************************************************************************************/ +/**********************************************************************************************************************/ + +#define DST_FORMAT DSPF_RGB32 +#define TABLE_NAME stretch_hvx_RGB32 +#define FUNC_NAME(UPDOWN,K,P,F) stretch_hvx_RGB32_ ## UPDOWN ## _ ## K ## P ## _ ## F +#define SHIFT_R8 8 +#define SHIFT_L8 8 +#define X_00FF00FF 0x00ff00ff +#define X_FF00FF00 0x0000ff00 +#define MASK_RGB 0x00ffffff + +#include "stretch_up_down_32.h" + +#undef DST_FORMAT +#undef TABLE_NAME +#undef FUNC_NAME +#undef SHIFT_R8 +#undef SHIFT_L8 +#undef X_00FF00FF +#undef X_FF00FF00 +#undef MASK_RGB + +#if 0 +/**********************************************************************************************************************/ +/*** 16 bit YUV 422 scalers *******************************************************************************************/ +/**********************************************************************************************************************/ + +#define FUNC_NAME(UPDOWN) stretch_hvx_nv16_ ## UPDOWN + +#include "stretch_up_down_8.h" + +#undef FUNC_NAME + +/**********************************************************************************************************************/ + +#define FUNC_NAME(UPDOWN) stretch_hvx_nv16_uv_ ## UPDOWN + +#include "stretch_up_down_88.h" + +#undef FUNC_NAME + +#endif +/**********************************************************************************************************************/ +/**********************************************************************************************************************/ + +static const StretchFunctionTable *stretch_tables[DFB_NUM_PIXELFORMATS] = { + NULL, /* DSPF_ARGB1555 */ + &stretch_hvx_RGB16, /* DSPF_RGB16 */ + NULL, /* DSPF_RGB24 */ + &stretch_hvx_RGB32, /* DSPF_RGB32 */ + &stretch_hvx_ARGB, /* DSPF_ARGB */ + NULL, /* DSPF_A8 */ + NULL, /* DSPF_YUY2 */ + NULL, /* DSPF_RGB332 */ + NULL, /* DSPF_UYVY */ + NULL, /* DSPF_I420 */ + NULL, /* DSPF_YV12 */ + NULL, /* DSPF_LUT8 */ + NULL, /* DSPF_ALUT44 */ + NULL, /* DSPF_AiRGB */ + NULL, /* DSPF_A1 */ + NULL, /* DSPF_NV12 */ + NULL, /* DSPF_NV16 */ + NULL, /* DSPF_ARGB2554 */ + &stretch_hvx_ARGB4444, /* DSPF_ARGB4444 */ + &stretch_hvx_RGBA4444, /* DSPF_RGBA4444 */ + NULL, /* DSPF_NV21 */ + NULL, /* DSPF_AYUV */ + NULL, /* DSPF_A4 */ + NULL, /* DSPF_ARGB1666 */ + NULL, /* DSPF_ARGB6666 */ + NULL, /* DSPF_RGB18 */ + NULL, /* DSPF_LUT2 */ + NULL, /* DSPF_RGB444 */ + NULL, /* DSPF_RGB555 */ + NULL /* DSPF_BGR555 */ +}; + +/**********************************************************************************************************************/ + +__attribute__((noinline)) +static bool +stretch_hvx( CardState *state, DFBRectangle *srect, DFBRectangle *drect ) +{ + GenefxState *gfxs; + const StretchFunctionTable *table; + StretchHVx stretch; + bool down = false; + void *dst; + void *src; + StretchCtx ctx; + int idx = STRETCH_NONE; + u32 colors[256]; + + D_ASSERT( state != NULL ); + DFB_RECTANGLE_ASSERT( srect ); + DFB_RECTANGLE_ASSERT( drect ); + + gfxs = state->gfxs; + + if (state->blittingflags & ~(DSBLIT_COLORKEY_PROTECT | DSBLIT_SRC_COLORKEY | DSBLIT_SRC_PREMULTIPLY)) + return false; + + if (state->blittingflags & DSBLIT_SRC_PREMULTIPLY && !DFB_PIXELFORMAT_IS_INDEXED( gfxs->src_format )) + return false; + + if (DFB_PIXELFORMAT_INDEX(gfxs->dst_format) >= D_ARRAY_SIZE(stretch_tables)) + return false; + + if (DFB_PIXELFORMAT_INDEX(gfxs->src_format) >= D_ARRAY_SIZE((stretch_tables[0])->f)) + return false; + + table = stretch_tables[DFB_PIXELFORMAT_INDEX(gfxs->dst_format)]; + if (!table) + return false; + + if (srect->w > drect->w && srect->h > drect->h) + down = true; + + if (state->blittingflags & DSBLIT_SRC_COLORKEY) + idx |= STRETCH_SRCKEY; + + if (state->blittingflags & DSBLIT_COLORKEY_PROTECT) + idx |= STRETCH_PROTECT; + + if (down) { + if (!(state->render_options & DSRO_SMOOTH_DOWNSCALE)) + return false; + + stretch = table->f[DFB_PIXELFORMAT_INDEX(gfxs->src_format)].down[idx]; + } + else { + if (!(state->render_options & DSRO_SMOOTH_UPSCALE)) + return false; + + stretch = table->f[DFB_PIXELFORMAT_INDEX(gfxs->src_format)].up[idx]; + } + + if (!stretch) + return false; + + ctx.clip = state->clip; + + if (!dfb_region_rectangle_intersect( &ctx.clip, drect )) + return false; + + dfb_region_translate( &ctx.clip, - drect->x, - drect->y ); + + if (DFB_PIXELFORMAT_IS_INDEXED( gfxs->src_format )) { + int i; + const DFBColor *entries; + u16 *colors16 = (void*) colors; + + D_ASSERT( gfxs->Blut != NULL ); + + entries = gfxs->Blut->entries; + + switch (gfxs->dst_format) { + case DSPF_ARGB: + if (state->blittingflags & DSBLIT_SRC_PREMULTIPLY) { + for (i=0; iBlut->num_entries; i++) { + int alpha = entries[i].a + 1; + + switch (alpha) { + case 0: + colors[i] = 0; + break; + + case 255: + colors[i] = PIXEL_ARGB( entries[i].a, + entries[i].r, + entries[i].g, + entries[i].b ); + break; + + default: + colors[i] = PIXEL_ARGB( entries[i].a, + (alpha * entries[i].r) >> 8, + (alpha * entries[i].g) >> 8, + (alpha * entries[i].b) >> 8 ); + } + } + } + else { + for (i=0; iBlut->num_entries; i++) + colors[i] = PIXEL_ARGB( entries[i].a, entries[i].r, entries[i].g, entries[i].b ); + } + break; + + case DSPF_RGB32: + for (i=0; iBlut->num_entries; i++) + colors[i] = PIXEL_RGB32( entries[i].r, entries[i].g, entries[i].b ); + break; + + case DSPF_RGB16: + for (i=0; iBlut->num_entries; i++) + colors16[i] = PIXEL_RGB16( entries[i].r, entries[i].g, entries[i].b ); + break; + + case DSPF_ARGB4444: + if (state->blittingflags & DSBLIT_SRC_PREMULTIPLY) { + for (i=0; iBlut->num_entries; i++) { + int alpha = entries[i].a + 1; + + switch (alpha) { + case 0: + colors16[i] = 0; + break; + + case 255: + colors16[i] = PIXEL_ARGB4444( entries[i].a, + entries[i].r, + entries[i].g, + entries[i].b ); + break; + + default: + colors16[i] = PIXEL_ARGB4444( entries[i].a, + (alpha * entries[i].r) >> 8, + (alpha * entries[i].g) >> 8, + (alpha * entries[i].b) >> 8 ); + } + } + } + else { + for (i=0; iBlut->num_entries; i++) + colors16[i] = PIXEL_ARGB4444( entries[i].a, entries[i].r, entries[i].g, entries[i].b ); + } + break; + + case DSPF_RGBA4444: + if (state->blittingflags & DSBLIT_SRC_PREMULTIPLY) { + for (i=0; iBlut->num_entries; i++) { + int alpha = entries[i].a + 1; + + switch (alpha) { + case 0: + colors16[i] = 0; + break; + + case 255: + colors16[i] = PIXEL_RGBA4444( entries[i].a, + entries[i].r, + entries[i].g, + entries[i].b ); + break; + + default: + colors16[i] = PIXEL_RGBA4444( entries[i].a, + (alpha * entries[i].r) >> 8, + (alpha * entries[i].g) >> 8, + (alpha * entries[i].b) >> 8 ); + } + } + } + else { + for (i=0; iBlut->num_entries; i++) + colors16[i] = PIXEL_RGBA4444( entries[i].a, entries[i].r, entries[i].g, entries[i].b ); + } + break; + + case DSPF_RGB444: + for (i=0; iBlut->num_entries; i++) + colors16[i] = PIXEL_RGB444( entries[i].r, entries[i].g, entries[i].b ); + break; + + default: + D_UNIMPLEMENTED(); + } + + ctx.colors = colors; + + if (state->blittingflags & DSBLIT_SRC_COLORKEY) { + if (DFB_PIXELFORMAT_IS_INDEXED( gfxs->dst_format )) + ctx.key = state->src_colorkey; + else { + const DFBColor *color = &entries[state->src_colorkey % gfxs->Blut->num_entries]; + + ctx.key = dfb_color_to_pixel( gfxs->dst_format, color->r, color->g, color->b ); + } + } + } + else { + ctx.colors = NULL; + + if (state->blittingflags & DSBLIT_SRC_COLORKEY) { + DFBColor color; + + dfb_pixel_to_color( gfxs->src_format, state->src_colorkey, &color ); + + ctx.key = dfb_color_to_pixel( gfxs->dst_format, color.r, color.g, color.b ); + } + } + + if (state->blittingflags & DSBLIT_COLORKEY_PROTECT) { + if (DFB_PIXELFORMAT_IS_INDEXED( gfxs->dst_format )) + ctx.protect = state->colorkey.index; + else + ctx.protect = dfb_color_to_pixel( gfxs->dst_format, + state->colorkey.r, + state->colorkey.g, + state->colorkey.b ); + } + + dst = gfxs->dst_org[0] + drect->y * gfxs->dst_pitch + DFB_BYTES_PER_LINE( gfxs->dst_format, drect->x ); + src = gfxs->src_org[0] + srect->y * gfxs->src_pitch + DFB_BYTES_PER_LINE( gfxs->src_format, srect->x ); + + stretch( dst, gfxs->dst_pitch, src, gfxs->src_pitch, + srect->w, srect->h, drect->w, drect->h, &ctx ); + +#if 0 /* FIXME: repair */ + switch (gfxs->dst_format) { + case DSPF_NV16: + ctx.clip.x1 /= 2; + ctx.clip.x2 /= 2; + if (srect->w < drect->w || srect->h < drect->h) { + stretch_hvx_nv16_uv_up( dst, gfxs->dst_pitch, src, gfxs->src_pitch, + srect->w/2, srect->h, drect->w/2, drect->h, &ctx ); + } + else { + stretch_hvx_nv16_uv_down( dst, gfxs->dst_pitch, src, gfxs->src_pitch, + srect->w/2, srect->h, drect->w/2, drect->h, &ctx ); + } + break; + + default: + break; + } +#endif + + return true; +} +#endif /* DFB_SMOOTH_SCALING */ + +void gStretchBlit( CardState *state, DFBRectangle *srect, DFBRectangle *drect ) +{ + GenefxState *gfxs = state->gfxs; + DFBRectangle orect = *drect; + + int fx, fy; + int ix, iy; + int h; + + D_ASSERT( gfxs != NULL ); + + if (dfb_config->software_warn) { + D_WARN( "StretchBlit (%4d,%4d-%4dx%4d) %6s, flags 0x%08x, color 0x%02x%02x%02x%02x, source (%4d,%4d-%4dx%4d) %6s", + drect->x, drect->y, drect->w, drect->h, dfb_pixelformat_name(gfxs->dst_format), state->blittingflags, + state->color.a, state->color.r, state->color.g, state->color.b, srect->x, srect->y, srect->w, srect->h, + dfb_pixelformat_name(gfxs->src_format) ); + } + + CHECK_PIPELINE(); + +#if DFB_SMOOTH_SCALING + if (state->render_options & (DSRO_SMOOTH_UPSCALE | DSRO_SMOOTH_DOWNSCALE) && + stretch_hvx( state, srect, drect )) + return; +#endif + + /* Clip destination rectangle. */ + if (!dfb_rectangle_intersect_by_region( drect, &state->clip )) + return; + + /* Calculate fractions. */ + fx = (srect->w << 16) / orect.w; + fy = (srect->h << 16) / orect.h; + + /* Calculate horizontal phase and offset. */ + ix = fx * (drect->x - orect.x); + srect->x += ix >> 16; + ix &= 0xFFFF; + + /* Calculate vertical phase and offset. */ + iy = fy * (drect->y - orect.y); + srect->y += iy >> 16; + iy &= 0xFFFF; + + /* Adjust source size. */ + srect->w = ((drect->w * fx + ix) + 0xFFFF) >> 16; + srect->h = ((drect->h * fy + iy) + 0xFFFF) >> 16; + + D_ASSERT( srect->x + srect->w <= state->source->config.size.w ); + D_ASSERT( srect->y + srect->h <= state->source->config.size.h ); + D_ASSERT( drect->x + drect->w <= state->clip.x2 + 1 ); + D_ASSERT( drect->y + drect->h <= state->clip.y2 + 1 ); + + + if (!ABacc_prepare( gfxs, MAX( srect->w, drect->w ) )) + return; + + + switch (gfxs->src_format) { + case DSPF_A4: + case DSPF_YUY2: + case DSPF_UYVY: + srect->x &= ~1; + break; + default: + break; + } + + switch (gfxs->dst_format) { + case DSPF_A4: + case DSPF_YUY2: + case DSPF_UYVY: + drect->x &= ~1; + break; + default: + break; + } + + gfxs->Slen = srect->w; + gfxs->Dlen = drect->w; + gfxs->length = gfxs->Dlen; + gfxs->SperD = fx; + gfxs->Xphase = ix; + + h = drect->h; + + Aop_xy( gfxs, drect->x, drect->y ); + Bop_xy( gfxs, srect->x, srect->y ); + + while (h--) { + RUN_PIPELINE(); + + Aop_next( gfxs ); + + iy += fy; + + while (iy > 0xFFFF) { + iy -= 0x10000; + Bop_next( gfxs ); + } + } + + ABacc_flush( gfxs ); +} + + +#ifdef USE_MMX + +#include "generic_mmx.h" + +/* + * patches function pointers to MMX functions + */ +static void gInit_MMX( void ) +{ + use_mmx = 1; + +/********************************* Sop_PFI_Sto_Dacc ***************************/ +// Sop_PFI_Sto_Dacc[DFB_PIXELFORMAT_INDEX(DSPF_ARGB)] = Sop_argb_Sto_Dacc_MMX; +/********************************* Sop_PFI_to_Dacc ****************************/ +// Sop_PFI_to_Dacc[DFB_PIXELFORMAT_INDEX(DSPF_RGB16)] = Sop_rgb16_to_Dacc_MMX; +// Sop_PFI_to_Dacc[DFB_PIXELFORMAT_INDEX(DSPF_RGB32)] = Sop_rgb32_to_Dacc_MMX; +// Sop_PFI_to_Dacc[DFB_PIXELFORMAT_INDEX(DSPF_ARGB )] = Sop_argb_to_Dacc_MMX; +/********************************* Sacc_to_Aop_PFI ****************************/ +// Sacc_to_Aop_PFI[DFB_PIXELFORMAT_INDEX(DSPF_RGB16)] = Sacc_to_Aop_rgb16_MMX; +// Sacc_to_Aop_PFI[DFB_PIXELFORMAT_INDEX(DSPF_RGB32)] = Sacc_to_Aop_rgb32_MMX; +/********************************* Xacc_blend *********************************/ + Xacc_blend[DSBF_SRCALPHA-1] = Xacc_blend_srcalpha_MMX; + Xacc_blend[DSBF_INVSRCALPHA-1] = Xacc_blend_invsrcalpha_MMX; +/********************************* Dacc_modulation ****************************/ + Dacc_modulation[DSBLIT_BLEND_ALPHACHANNEL | + DSBLIT_BLEND_COLORALPHA | + DSBLIT_COLORIZE] = Dacc_modulate_argb_MMX; +/********************************* misc accumulator operations ****************/ + SCacc_add_to_Dacc = SCacc_add_to_Dacc_MMX; + Sacc_add_to_Dacc = Sacc_add_to_Dacc_MMX; + Dacc_YCbCr_to_RGB = Dacc_YCbCr_to_RGB_MMX; + Dacc_RGB_to_YCbCr = Dacc_RGB_to_YCbCr_MMX; +} + +#endif + + +#if SIZEOF_LONG == 8 + +#include "generic_64.h" + +/* + * patches function pointers to 64bit functions + */ +static void gInit_64bit( void ) +{ +/********************************* Cop_to_Aop_PFI ********************************/ + Cop_to_Aop_PFI[DFB_PIXELFORMAT_INDEX(DSPF_RGB32)] = Cop_to_Aop_32_64; + Cop_to_Aop_PFI[DFB_PIXELFORMAT_INDEX(DSPF_ARGB)] = Cop_to_Aop_32_64; + Cop_to_Aop_PFI[DFB_PIXELFORMAT_INDEX(DSPF_AiRGB)] = Cop_to_Aop_32_64; +/********************************* Bop_PFI_Kto_Aop_PFI ***************************/ + Bop_PFI_Kto_Aop_PFI[DFB_PIXELFORMAT_INDEX(DSPF_RGB32)] = Bop_rgb32_Kto_Aop_64; + Bop_PFI_Kto_Aop_PFI[DFB_PIXELFORMAT_INDEX(DSPF_ARGB)] = Bop_rgb32_Kto_Aop_64; + Bop_PFI_Kto_Aop_PFI[DFB_PIXELFORMAT_INDEX(DSPF_AiRGB)] = Bop_rgb32_Kto_Aop_64; +/********************************* Bop_PFI_tKo_Aop_PFI ***************************/ + Bop_PFI_toK_Aop_PFI[DFB_PIXELFORMAT_INDEX(DSPF_RGB32)] = Bop_rgb32_toK_Aop_64; + Bop_PFI_toK_Aop_PFI[DFB_PIXELFORMAT_INDEX(DSPF_ARGB)] = Bop_rgb32_toK_Aop_64; + Bop_PFI_toK_Aop_PFI[DFB_PIXELFORMAT_INDEX(DSPF_AiRGB)] = Bop_rgb32_toK_Aop_64; +/********************************* Bop_PFI_Sto_Aop_PFI ***************************/ + Bop_PFI_Sto_Aop_PFI[DFB_PIXELFORMAT_INDEX(DSPF_RGB32)] = Bop_32_Sto_Aop_64; + Bop_PFI_Sto_Aop_PFI[DFB_PIXELFORMAT_INDEX(DSPF_ARGB)] = Bop_32_Sto_Aop_64; + Bop_PFI_Sto_Aop_PFI[DFB_PIXELFORMAT_INDEX(DSPF_AiRGB)] = Bop_32_Sto_Aop_64; +/********************************* misc accumulator operations *******************/ + Dacc_xor = Dacc_xor_64; +} + +#endif diff --git a/Source/DirectFB/src/gfx/generic/generic.h b/Source/DirectFB/src/gfx/generic/generic.h new file mode 100755 index 0000000..7c73c40 --- /dev/null +++ b/Source/DirectFB/src/gfx/generic/generic.h @@ -0,0 +1,174 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __GENERIC_H__ +#define __GENERIC_H__ + +#include + +#include +#include +#include + +/* this order is required for Intel with MMX, how about bigendian? */ + +typedef union { + struct { + u16 b; + u16 g; + u16 r; + u16 a; + } RGB; + struct { + u16 u; + u16 v; + u16 y; + u16 a; + } YUV; +} GenefxAccumulator; + + +typedef struct _GenefxState GenefxState; + +typedef void (*GenefxFunc)(GenefxState *gfxs); + +/* + * State of the virtual graphics processing unit "Genefx" (pron. 'genie facts'). + */ +struct _GenefxState { + GenefxFunc funcs[32]; + + int length; /* span length */ + int Slen; /* span length (source) */ + int Dlen; /* span length (destination) */ + + /* + * state values + */ + void *dst_org[3]; + void *src_org[3]; + int dst_pitch; + int src_pitch; + + int dst_bpp; + int src_bpp; + + DFBSurfaceCapabilities dst_caps; + DFBSurfaceCapabilities src_caps; + + DFBSurfacePixelFormat src_format; + DFBSurfacePixelFormat dst_format; + + int dst_height; + int src_height; + + int dst_field_offset; + int src_field_offset; + + DFBColor color; + + /* + * operands + */ + void *Aop[3]; + void *Bop[3]; + u32 Cop; + + int Astep; + int Bstep; + + u8 YCop; + u8 CbCop; + u8 CrCop; + + int Aop_field; + int Bop_field; + + int AopY; + int BopY; + + /* + * color keys + */ + u32 Dkey; + u32 Skey; + + /* + * color lookup tables + */ + CorePalette *Alut; + CorePalette *Blut; + + /* + * accumulators + */ + void *ABstart; + int ABsize; + GenefxAccumulator *Aacc; + GenefxAccumulator *Bacc; + GenefxAccumulator *Tacc; /* for simultaneous S+D blending */ + GenefxAccumulator Cacc; + GenefxAccumulator SCacc; + + /* + * dataflow control + */ + GenefxAccumulator *Xacc; /* writing pointer for blending */ + GenefxAccumulator *Yacc; /* input pointer for blending */ + GenefxAccumulator *Dacc; + GenefxAccumulator *Sacc; + + void **Sop; + CorePalette *Slut; + + int Ostep; /* controls horizontal blitting direction */ + + int SperD; /* for scaled routines only */ + int Xphase; /* initial value for fractional steps (zero if not clipped) */ + + bool need_accumulator; + + int *trans; + int num_trans; +}; + + +void gGetDriverInfo( GraphicsDriverInfo *info ); +void gGetDeviceInfo( GraphicsDeviceInfo *info ); + +bool gAcquire ( CardState *state, DFBAccelerationMask accel ); +void gRelease ( CardState *state ); + +void gFillRectangle ( CardState *state, DFBRectangle *rect ); +void gDrawLine ( CardState *state, DFBRegion *line ); + +void gBlit ( CardState *state, DFBRectangle *rect, int dx, int dy ); +void gStretchBlit ( CardState *state, DFBRectangle *srect, DFBRectangle *drect ); + + +#endif diff --git a/Source/DirectFB/src/gfx/generic/generic_64.h b/Source/DirectFB/src/gfx/generic/generic_64.h new file mode 100755 index 0000000..b0079ce --- /dev/null +++ b/Source/DirectFB/src/gfx/generic/generic_64.h @@ -0,0 +1,207 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + + +static void Cop_to_Aop_32_64( GenefxState *gfxs ) +{ + int w, l = gfxs->length; + u32 *D = gfxs->Aop[0]; + u32 Cop = gfxs->Cop; + u64 DCop = ((u64)Cop << 32) | Cop; + + if ((long)D & 4) { + *D++ = Cop; + l--; + } + + for (w = l >> 1; w; w--) { + *((u64*)D) = DCop; + D += 2; + } + + if (l & 1) + *D = Cop; +} + +static void Bop_rgb32_Kto_Aop_64( GenefxState *gfxs ) +{ + int w, l = gfxs->length; + u32 *D = gfxs->Aop[0]; + u32 *S = gfxs->Bop[0]; + u32 Skey = gfxs->Skey; + u64 DSkey = ((u64)Skey << 32) | Skey; + + if ((long)D & 4) { + if ((*S & 0x00ffffff) != Skey) + *D = *S; + D++; + S++; + l--; + } + + for (w = l >> 1; w; w--) { + u64 s = *((u64*)S); + + if ((s & 0x00ffffff00ffffffull) != DSkey) { + if ((s & 0x00ffffff00000000ull) != + (DSkey & 0x00ffffff00000000ull)) { + if ((s & 0x0000000000ffffffull) != + (DSkey & 0x0000000000ffffffull)) { + *((u64*)D) = s; + } + else { +#ifdef WORDS_BIGENDIAN + D[0] = (u32)(s >> 32); +#else + D[1] = (u32)(s >> 32); +#endif + } + } + else { +#ifdef WORDS_BIGENDIAN + D[1] = (u32)s; +#else + D[0] = (u32)s; +#endif + } + } + S += 2; + D += 2; + } + + if (l & 1) { /* do the last potential pixel */ + if ((*S & 0x00ffffff) != Skey) + *D = *S; + } +} + +static void Bop_rgb32_toK_Aop_64( GenefxState *gfxs ) +{ + int w, l = gfxs->length; + u32 *D = gfxs->Aop[0]; + u32 *S = gfxs->Bop[0]; + u32 Dkey = gfxs->Dkey; + u64 DDkey = ((u64)Dkey << 32) | Dkey; + + if ((long)D & 4) { + if ((*D & 0x00ffffff) == Dkey) + *D = *S; + D++; + S++; + l--; + } + + for (w = l >> 1; w; w--) { + u64 d = *((u64*)D); + + if ((d & 0x00ffffff00ffffffull) != DDkey) { + if ((d & 0x00ffffff00000000ull) == + (DDkey & 0x00ffffff00000000ull)) { + if ((d & 0x0000000000ffffffull) == + (DDkey & 0x0000000000ffffffull)) { + *((u64*)D) = *((u64*)S); + } + else { +#ifdef WORDS_BIGENDIAN + D[0] = S[0]; +#else + D[1] = S[1]; +#endif + } + } + else { +#ifdef WORDS_BIGENDIAN + D[1] = S[1]; +#else + D[0] = S[0]; +#endif + } + } + S += 2; + D += 2; + } + + if (l & 1) { /* do the last potential pixel */ + if ((*D & 0x00ffffff) == Dkey) + *D = *S; + } +} + +static void Bop_32_Sto_Aop_64( GenefxState *gfxs ) +{ + int w, l = gfxs->length; + int i = 0; + u32 *D = gfxs->Aop[0]; + u32 *S = gfxs->Bop[0]; + int SperD = gfxs->SperD; + int SperD2 = SperD << 1; + + if ((long)D & 4) { + *D++ = *S; + i += SperD; + l--; + } + + for (w = l >> 1; w; w--) { +#ifdef WORDS_BIGENDIAN + *((u64*)D) = ((u64)S[i>>16] << 32) | S[(i+SperD)>>16]; +#else + *((u64*)D) = ((u64)S[(i+SperD)>>16] << 32) | S[i>>16]; +#endif + D += 2; + i += SperD2; + } + + if (l & 1) + *D = S[i>>16]; +} + +static void Dacc_xor_64( GenefxState *gfxs ) +{ + int w = gfxs->length; + u64 *D = (u64*)gfxs->Dacc; + u64 color; + +#ifdef WORDS_BIGENDIAN + color = ((u64)gfxs->color.b << 48) | + ((u64)gfxs->color.g << 32) | + ((u64)gfxs->color.r << 16) | + ((u64)gfxs->color.a); +#else + color = ((u64)gfxs->color.a << 48) | + ((u64)gfxs->color.r << 32) | + ((u64)gfxs->color.g << 16) | + ((u64)gfxs->color.b); +#endif + + for (; w; w--) { + *D ^= color; + D++; + } +} + diff --git a/Source/DirectFB/src/gfx/generic/generic_dummy.c b/Source/DirectFB/src/gfx/generic/generic_dummy.c new file mode 100755 index 0000000..00032a7 --- /dev/null +++ b/Source/DirectFB/src/gfx/generic/generic_dummy.c @@ -0,0 +1,94 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include + +#include + +#include + +#include + + +void +gGetDriverInfo( GraphicsDriverInfo *info ) +{ + D_INFO( "DirectFB/Genefx: No software fallbacks supported\n" ); + + snprintf( info->name, DFB_GRAPHICS_DRIVER_INFO_NAME_LENGTH, "Software Driver" ); + snprintf( info->vendor, DFB_GRAPHICS_DRIVER_INFO_VENDOR_LENGTH, "directfb.org" ); + + info->version.major = 0; + info->version.minor = 0; +} + +void +gGetDeviceInfo( GraphicsDeviceInfo *info ) +{ + snprintf( info->name, DFB_GRAPHICS_DEVICE_INFO_NAME_LENGTH, "Software Rasterizer" ); + snprintf( info->vendor, DFB_GRAPHICS_DEVICE_INFO_VENDOR_LENGTH, "Dummy" ); + + info->caps.accel = DFXL_NONE; + info->caps.flags = 0; + info->caps.drawing = DSDRAW_NOFX; + info->caps.blitting = DSBLIT_NOFX; +} + +bool +gAcquire( CardState *state, DFBAccelerationMask accel ) +{ + return false; +} + +void +gRelease( CardState *state ) +{ +} + +void +gFillRectangle( CardState *state, DFBRectangle *rect ) +{ +} + +void +gDrawLine( CardState *state, DFBRegion *line ) +{ +} + +void +gBlit( CardState *state, DFBRectangle *rect, int dx, int dy ) +{ +} + +void +gStretchBlit( CardState *state, DFBRectangle *srect, DFBRectangle *drect ) +{ +} + diff --git a/Source/DirectFB/src/gfx/generic/generic_mmx.h b/Source/DirectFB/src/gfx/generic/generic_mmx.h new file mode 100755 index 0000000..57757f3 --- /dev/null +++ b/Source/DirectFB/src/gfx/generic/generic_mmx.h @@ -0,0 +1,659 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + + +#define __aligned( n ) __attribute__ ((aligned((n)))) + + +static void SCacc_add_to_Dacc_MMX( GenefxState *gfxs ) +{ + __asm__ __volatile__ ( + " movq %2, %%mm0\n" + ".align 16\n" + "1:\n" + " movq (%0), %%mm1\n" + " paddw %%mm0, %%mm1\n" + " movq %%mm1, (%0)\n" + " add $8, %0\n" + " dec %1\n" + " jnz 1b\n" + " emms" + : /* no outputs */ + : "D" (gfxs->Dacc), "c" (gfxs->length), "m" (gfxs->SCacc) + : "%st", "memory"); +} + +static void Dacc_modulate_argb_MMX( GenefxState *gfxs ) +{ + __asm__ __volatile__ ( + "movq %2, %%mm0\n\t" + ".align 16\n" + "1:\n\t" + "testw $0xF000, 6(%0)\n\t" + "jnz 2f\n\t" + "movq (%0), %%mm1\n\t" + "pmullw %%mm0, %%mm1\n\t" + "psrlw $8, %%mm1\n\t" + "movq %%mm1, (%0)\n" + ".align 16\n" + "2:\n\t" + "add $8, %0\n\t" + "dec %1\n\t" + "jnz 1b\n\t" + "emms" + : /* no outputs */ + : "D" (gfxs->Dacc), "c" (gfxs->length), "m" (gfxs->Cacc) + : "%st", "memory"); +} + +static void Sacc_add_to_Dacc_MMX( GenefxState *gfxs ) +{ + __asm__ __volatile__ ( + ".align 16\n" + "1:\n\t" + "movq (%2), %%mm0\n\t" + "movq (%0), %%mm1\n\t" + "paddw %%mm1, %%mm0\n\t" + "movq %%mm0, (%0)\n\t" + "add $8, %0\n\t" + "add $8, %2\n\t" + "dec %1\n\t" + "jnz 1b\n\t" + "emms" + : /* no outputs */ + : "D" (gfxs->Dacc), "c" (gfxs->length), "S" (gfxs->Sacc) + : "%st", "memory"); +} + +static void Sacc_to_Aop_rgb16_MMX( GenefxState *gfxs ) +{ + static const u32 preload[] = { 0xFF00FF00, 0x0000FF00 }; + static const u32 mask[] = { 0x00FC00F8, 0x000000F8 }; + static const u32 pm[] = { 0x01000004, 0x00000004 }; + + __asm__ __volatile__ ( + "movq %3, %%mm7\n\t" + "movq %4, %%mm5\n\t" + "movq %5, %%mm4\n\t" + ".align 16\n" + "1:\n\t" + "testw $0xF000, 6(%2)\n\t" + "jnz 2f\n\t" + "movq (%2), %%mm0\n\t" + "paddusw %%mm7, %%mm0\n\t" + "pand %%mm5, %%mm0\n\t" + "pmaddwd %%mm4, %%mm0\n\t" + "psrlq $5, %%mm0\n\t" + "movq %%mm0, %%mm1\n\t" + "psrlq $21, %%mm0\n\t" + "por %%mm1, %%mm0\n\t" + "movd %%mm0, %%eax\n\t" + "movw %%ax, (%0)\n\t" + ".align 16\n" + "2:\n\t" + "add $8, %2\n\t" + "add $2, %0\n\t" + "dec %1\n\t" + "jnz 1b\n\t" + "emms" + : /* no outputs */ + : "D" (gfxs->Aop[0]), "c" (gfxs->length), "S" (gfxs->Sacc), + "m" (*preload), "m" (*mask), "m" (*pm) + : "%eax", "%st", "memory"); +} + +static void Sacc_to_Aop_rgb32_MMX( GenefxState *gfxs ) +{ + static const u32 preload[] = { 0xFF00FF00, 0x0000FF00 }; + static const u32 postload[] = { 0x00FF00FF, 0x000000FF }; + static const u32 pm[] = { 0x01000001, 0x00000001 }; + + __asm__ __volatile__ ( + "movq %3, %%mm1\n\t" + "movq %4, %%mm2\n\t" + "movq %5, %%mm3\n\t" + ".align 16\n" + "1:\n\t" + "testw $0xF000, 6(%2)\n\t" + "jnz 2f\n\t" + "movq (%2), %%mm0\n\t" + "paddusw %%mm1, %%mm0\n\t" + "pand %%mm2, %%mm0\n\t" + "pmaddwd %%mm3, %%mm0\n\t" + "movq %%mm0, %%mm4\n\t" + "psrlq $16, %%mm0\n\t" + "por %%mm0, %%mm4\n\t" + "movd %%mm4, (%0)\n\t" + ".align 16\n" + "2:\n\t" + "add $8, %2\n\t" + "add $4, %0\n\t" + "dec %1\n\t" + "jnz 1b\n\t" + "emms" + : /* no outputs */ + : "D" (gfxs->Aop[0]), "c" (gfxs->length), "S" (gfxs->Sacc), + "m" (*preload), "m" (*postload), "m" (*pm) + : "%st", "memory"); +} + +__attribute__((no_instrument_function)) +static void Sop_argb_Sto_Dacc_MMX( GenefxState *gfxs ) +{ + static const u32 zeros[] = { 0, 0 }; + int i = 0; + + __asm__ __volatile__ ( + "movq %5, %%mm0\n\t" + ".align 16\n" + "1:\n\t" + "movd (%3), %%mm1\n\t" + "punpcklbw %%mm0, %%mm1\n\t" + ".align 16\n" + "2:\n\t" + "movq %%mm1, (%1)\n\t" + "dec %2\n\t" + "jz 3f\n\t" + "add $8, %1\n\t" + "add %4, %0\n\t" + "testl $0xFFFF0000, %0\n\t" + "jz 2b\n\t" + "movl %0, %%edx\n\t" + "andl $0xFFFF0000, %%edx\n\t" + "shrl $14, %%edx\n\t" +#ifdef ARCH_X86_64 + "addq %%rdx, %3\n\t" +#else + "addl %%edx, %3\n\t" +#endif + "andl $0xFFFF, %0\n\t" + "jmp 1b\n" + "3:\n\t" + "emms" + : "=r" (i) + : "D" (gfxs->Dacc), "c" (gfxs->length), "S" (gfxs->Sop[0]), + "a" (gfxs->SperD), "m" (*zeros), "0" (i) + : "%edx", "%st", "memory"); +} + +static void Sop_argb_to_Dacc_MMX( GenefxState *gfxs ) +{ + static const u32 zeros[] = { 0, 0 }; + + __asm__ __volatile__ ( + "movq %3, %%mm0\n\t" + ".align 16\n" + "1:\n\t" + "movd (%2), %%mm1\n\t" + "punpcklbw %%mm0, %%mm1\n\t" + "movq %%mm1, (%0)\n\t" + "add $4, %2\n\t" + "add $8, %0\n\t" + "dec %1\n\t" + "jnz 1b\n\t" + "emms" + : /* no outputs */ + : "D" (gfxs->Dacc), "c" (gfxs->length), + "S" (gfxs->Sop[0]), "m" (*zeros) + : "%st", "memory"); +} + +static void Sop_rgb16_to_Dacc_MMX( GenefxState *gfxs ) +{ + static const u32 mask[] = { 0x07E0001F, 0x0000F800 }; + static const u32 smul[] = { 0x00200800, 0x00000001 }; + static const u32 alpha[] = { 0x00000000, 0x00FF0000 }; + + __asm__ __volatile__ ( + "movq %3, %%mm4\n\t" + "movq %4, %%mm5\n\t" + "movq %5, %%mm7\n\t" + ".align 16\n" + "1:\n\t" + "movq (%2), %%mm0\n\t" + /* 1. Konvertierung nach 24 bit interleaved */ + "movq %%mm0, %%mm3\n\t" + "punpcklwd %%mm3, %%mm3\n\t" + "punpckldq %%mm3, %%mm3\n\t" + "pand %%mm4, %%mm3\n\t" + "pmullw %%mm5, %%mm3\n\t" + "psrlw $8, %%mm3\n\t" + /* mm3 enthaelt jetzt: 0000 00rr 00gg 00bb des alten pixels */ + "por %%mm7, %%mm3\n\t" + "movq %%mm3, (%0)\n\t" + "dec %1\n\t" + "jz 2f\n\t" + "psrlq $16, %%mm0\n\t" + "add $8, %0\n\t" + /* 2. Konvertierung nach 24 bit interleaved */ + "movq %%mm0, %%mm3\n\t" + "punpcklwd %%mm3, %%mm3\n\t" + "punpckldq %%mm3, %%mm3\n\t" + "pand %%mm4, %%mm3\n\t" + "pmullw %%mm5, %%mm3\n\t" + "psrlw $8, %%mm3\n\t" + /* mm3 enthaelt jetzt: 0000 00rr 00gg 00bb des alten pixels */ + "por %%mm7, %%mm3\n\t" + "movq %%mm3, (%0)\n\t" + "dec %1\n\t" + "jz 2f\n\t" + "psrlq $16, %%mm0\n\t" + "add $8, %0\n\t" + /* 3. Konvertierung nach 24 bit interleaved */ + "movq %%mm0, %%mm3\n\t" + "punpcklwd %%mm3, %%mm3\n\t" + "punpckldq %%mm3, %%mm3\n\t" + "pand %%mm4, %%mm3\n\t" + "pmullw %%mm5, %%mm3\n\t" + "psrlw $8, %%mm3\n\t" + /* mm3 enthaelt jetzt: 0000 00rr 00gg 00bb des alten pixels */ + "por %%mm7, %%mm3\n\t" + "movq %%mm3, (%0)\n\t" + "dec %1\n\t" + "jz 2f\n\t" + "psrlq $16, %%mm0\n\t" + "add $8, %0\n\t" + /* 4. Konvertierung nach 24 bit interleaved */ + "movq %%mm0, %%mm3\n\t" + "punpcklwd %%mm3, %%mm3\n\t" + "punpckldq %%mm3, %%mm3\n\t" + "pand %%mm4, %%mm3\n\t" + "pmullw %%mm5, %%mm3\n\t" + "psrlw $8, %%mm3\n\t" + /* mm3 enthaelt jetzt: 0000 00rr 00gg 00bb des alten pixels */ + "por %%mm7, %%mm3\n\t" + "movq %%mm3, (%0)\n\t" + "dec %1\n\t" + "jz 2f\n\t" + "add $8, %0\n\t" + "add $8, %2\n\t" + "jmp 1b\n" + "2:\n\t" + "emms" + : /* no outputs */ + : "D" (gfxs->Dacc), "c" (gfxs->length), "S" (gfxs->Sop[0]), + "m" (*mask), "m" (*smul), "m" (*alpha) + : "%st", "memory"); +} + +static void Sop_rgb32_to_Dacc_MMX( GenefxState *gfxs ) +{ + static const u32 alpha[] = { 0, 0x00FF0000 }; + static const u32 zeros[] = { 0, 0 }; + + __asm__ __volatile__ ( + "movq %3, %%mm7\n\t" + "movq %4, %%mm6\n\t" + ".align 16\n" + "1:\n\t" + "movd (%2), %%mm0\n\t" + "punpcklbw %%mm6, %%mm0\n\t" + "por %%mm7, %%mm0\n\t" + "movq %%mm0, (%0)\n\t" + "add $4, %2\n\t" + "add $8, %0\n\t" + "dec %1\n\t" + "jnz 1b\n\t" + "emms" + : /* no outputs */ + : "D" (gfxs->Dacc), "c" (gfxs->length), "S" (gfxs->Sop[0]), + "m" (*alpha), "m" (*zeros) + : "%st", "memory"); +} + +static void Xacc_blend_invsrcalpha_MMX( GenefxState *gfxs ) +{ + static const u32 einser[] = { 0x01000100, 0x01000100 }; + static const u32 zeros[] = { 0, 0 }; + + __asm__ __volatile__ ( + "movq %3, %%mm7\n\t" + "cmp $0, %2\n\t" + "jne 1f\n\t" + "movq %4, %%mm6\n\t" + "movd %5, %%mm0\n\t" + "punpcklbw %%mm6, %%mm0\n\t" /* mm0 = 00aa 00rr 00gg 00bb */ + "punpcklwd %%mm0, %%mm0\n\t" /* mm0 = 00aa 00aa xxxx xxxx */ + "movq %%mm7, %%mm1\n\t" + "punpckldq %%mm0, %%mm0\n\t" /* mm0 = 00aa 00aa 00aa 00aa */ + "psubw %%mm0, %%mm1\n\t" + + ".align 16\n" + "2:\n\t" /* blend from color */ + "testw $0xF000, 6(%0)\n\t" + "jnz 3f\n\t" + "movq (%0), %%mm0\n\t" + "pmullw %%mm1, %%mm0\n\t" + "psrlw $8, %%mm0\n\t" + "movq %%mm0, (%6)\n\t" + "jmp 4f\n\t" + "3:\n\t" + "movq (%0), %%mm0\n\t" + "movq %%mm0, (%6)\n\t" + "4:\n\t" + "add $8, %0\n\t" + "add $8, %6\n\t" + "dec %1\n\t" + "jnz 2b\n\t" + "jmp 9f\n\t" + + ".align 16\n" + "1:\n\t" /* blend from Sacc */ + "testw $0xF000, 6(%0)\n\t" + "jnz 5f\n\t" + "movq (%2), %%mm2\n\t" + "movq (%0), %%mm0\n\t" + "punpckhwd %%mm2, %%mm2\n\t" /* mm2 = 00aa 00aa xxxx xxxx */ + "movq %%mm7, %%mm1\n\t" + "punpckhdq %%mm2, %%mm2\n\t" /* mm2 = 00aa 00aa 00aa 00aa */ + "psubw %%mm2, %%mm1\n\t" + "pmullw %%mm1, %%mm0\n\t" + "psrlw $8, %%mm0\n\t" + "movq %%mm0, (%6)\n\t" + "jmp 6f\n\t" + "5:\n\t" + "movq (%0), %%mm0\n\t" + "movq %%mm0, (%6)\n\t" + "6:\n\t" + "add $8, %2\n\t" + "add $8, %0\n\t" + "add $8, %6\n\t" + "dec %1\n\t" + "jnz 1b\n\t" + "9:\n\t" + "emms" + : /* no outputs */ + : "D" (gfxs->Yacc), "c" (gfxs->length), "S" (gfxs->Sacc), + "m" (*einser), "m" (*zeros), "m" (gfxs->color), "r" (gfxs->Xacc) + : "%st", "memory"); +} + +static void Xacc_blend_srcalpha_MMX( GenefxState *gfxs ) +{ + static const u32 ones[] = { 0x00010001, 0x00010001 }; + static const u32 zeros[] = { 0, 0 }; + + __asm__ __volatile__ ( + "movq %3, %%mm7\n\t" + "cmp $0, %2\n\t" + "jne 3f\n\t" + "movq %4, %%mm6\n\t" + "movd %5, %%mm0\n\t" + "punpcklbw %%mm6, %%mm0\n\t" /* mm0 = 00aa 00rr 00gg 00bb */ + "punpcklwd %%mm0, %%mm0\n\t" /* mm0 = 00aa 00aa xxxx xxxx */ + "punpckldq %%mm0, %%mm0\n\t" /* mm0 = 00aa 00aa 00aa 00aa */ + "paddw %%mm7, %%mm0\n\t" + + ".align 16\n\t" + "4:\n\t" /* blend from color */ + "testw $0xF000, 6(%0)\n\t" + "jnz 6f\n\t" + "movq (%0), %%mm1\n\t" + "pmullw %%mm0, %%mm1\n\t" + "psrlw $8, %%mm1\n\t" + "movq %%mm1, (%6)\n\t" + "jmp 1f\n\t" + "6:\n\t" + "movq (%0), %%mm1\n\t" + "movq %%mm1, (%6)\n\t" + "1:\n\t" + "add $8, %0\n\t" + "add $8, %6\n\t" + "dec %1\n\t" + "jnz 4b\n\t" + "jmp 2f\n\t" + + ".align 16\n\t" + "3:\n\t" /* blend from Sacc */ + "testw $0xF000, 6(%0)\n\t" + "jnz 5f\n\t" + "movq (%2), %%mm0\n\t" + "movq (%0), %%mm1\n\t" + "punpckhwd %%mm0, %%mm0\n\t" /* mm2 = 00aa 00aa xxxx xxxx */ + "punpckhdq %%mm0, %%mm0\n\t" /* mm2 = 00aa 00aa 00aa 00aa */ + "paddw %%mm7, %%mm0\n\t" + "pmullw %%mm0, %%mm1\n\t" + "psrlw $8, %%mm1\n\t" + "movq %%mm1, (%6)\n\t" + "jmp 7f\n\t" + "5:\n\t" + "movq (%0), %%mm1\n\t" + "movq %%mm1, (%6)\n\t" + "7:\n\t" + "add $8, %2\n\t" + "add $8, %0\n\t" + "add $8, %6\n\t" + "dec %1\n\t" + "jnz 3b\n\t" + "2:\n\t" + "emms" + : /* no outputs */ + : "D" (gfxs->Yacc), "c" (gfxs->length), "S" (gfxs->Sacc), + "m" (*ones), "m" (*zeros), "m" (gfxs->color), "r" (gfxs->Xacc) + : "%st", "memory"); +} + +static void Dacc_YCbCr_to_RGB_MMX( GenefxState *gfxs ) +{ + static const u16 __aligned(8) sub0[4] = { 16, 16, 16, 16 }; + static const u16 __aligned(8) sub1[4] = { 128, 128, 128, 128 }; + static const s16 __aligned(8) mul[20] = { + 0x253F, 0x253F, 0x253F, 0x253F, // Y Coeff. + 0x3312, 0x3312, 0x3312, 0x3312, // V Red Coeff. + 0x4093, 0x4093, 0x4093, 0x4093, // U Blue Coeff. + -0x1A04, -0x1A04, -0x1A04, -0x1A04, // V Green Coeff. + -0x0C83, -0x0C83, -0x0C83, -0x0C83 // U Green Coeff. + }; + + int w = gfxs->length & 3; + GenefxAccumulator *D = gfxs->Dacc; + + __asm__ __volatile__ ( + "shrl $2, %1\n\t" + "jz 2f\n\t" + "pxor %%mm7, %%mm7\n\t" + ".align 16\n" + "1:\n\t" + "movq (%0), %%mm0\n\t" // 00 a0 00 y0 00 v0 00 u0 + "movq 8(%0), %%mm1\n\t" // 00 a1 00 y1 00 v1 00 u1 + "movq 16(%0), %%mm2\n\t" // 00 a2 00 y2 00 v2 00 u2 + "movq 24(%0), %%mm3\n\t" // 00 a3 00 y3 00 v3 00 u3 + "movq %%mm0, %%mm4\n\t" // 00 a0 00 y0 00 v0 00 u0 + "movq %%mm2, %%mm5\n\t" // 00 a2 00 y2 00 v2 00 u2 + "punpcklwd %%mm1, %%mm0\n\t" // 00 v1 00 v0 00 u1 00 u0 + "punpcklwd %%mm3, %%mm2\n\t" // 00 v3 00 v2 00 u3 00 u2 + "punpckhwd %%mm1, %%mm4\n\t" // 00 a1 00 a0 00 y1 00 y0 + "punpckhwd %%mm3, %%mm5\n\t" // 00 a3 00 a2 00 y3 00 y2 + "movq %%mm0, %%mm1\n\t" // 00 v1 00 v1 00 u1 00 u0 + "movq %%mm4, %%mm3\n\t" // 00 a1 00 a0 00 y1 00 y0 + "punpckldq %%mm2, %%mm0\n\t" // 00 u3 00 u2 00 u1 00 u0 + "punpckldq %%mm5, %%mm3\n\t" // 00 y3 00 y2 00 y1 00 y0 + "punpckhdq %%mm2, %%mm1\n\t" // 00 v3 00 v2 00 v1 00 v0 + "punpckhdq %%mm5, %%mm4\n\t" // 00 a3 00 a2 00 a1 00 a0 + /* mm0 = u, mm1 = v, mm3 = y, mm4 = a */ + "psubw %2, %%mm3\n\t" // y -= 16 + "psllw $3, %%mm3\n\t" // precision + "pmulhw (%4), %%mm3\n\t" + "psubw %3, %%mm1\n\t" // v -= 128 + "psllw $3, %%mm1\n\t" // precision + "movq %%mm1, %%mm2\n\t" // 00 v3 00 v2 00 v1 00 v0 + "pmulhw 8(%4), %%mm2\n\t" // vr + "psubw %3, %%mm0\n\t" // u -= 128 + "psllw $3, %%mm0\n\t" // precision + "movq %%mm0, %%mm5\n\t" // 00 u3 00 u2 00 u1 00 u0 + "pmulhw 16(%4), %%mm5\n\t" // ub + "paddw %%mm3, %%mm2\n\t" // 00 r3 00 r2 00 r1 00 r0 + "paddw %%mm3, %%mm5\n\t" // 00 b3 00 b2 00 b1 00 b0 + "pmulhw 24(%4), %%mm1\n\t" // vg + "packuswb %%mm2, %%mm2\n\t" // r3 r2 r1 r0 r3 r2 r1 r0 + "packuswb %%mm5, %%mm5\n\t" // b3 b2 b1 b0 b3 b2 b1 b0 + "pmulhw 32(%4), %%mm0\n\t" // ug + "punpcklbw %%mm7, %%mm2\n\t" // 00 r3 00 r2 00 r1 00 r0 + "punpcklbw %%mm7, %%mm5\n\t" // 00 b3 00 b2 00 b1 00 b0 + "paddw %%mm1, %%mm3\n\t" // y + vg + "paddw %%mm0, %%mm3\n\t" // 00 g3 00 g2 00 g1 00 g0 + "packuswb %%mm3, %%mm3\n\t" // g3 g2 g1 g0 g3 g2 g1 g0 + "punpcklbw %%mm7, %%mm3\n\t" // 00 g3 00 g2 00 g1 00 g0 + /* mm5 = b, mm3 = g, mm2 = r, mm4 = a */ + "movq %%mm5, %%mm0\n\t" // 00 b3 00 b2 00 b1 00 b0 + "movq %%mm3, %%mm1\n\t" // 00 g3 00 g2 00 g1 00 g0 + "punpcklwd %%mm2, %%mm0\n\t" // 00 r1 00 b1 00 r0 00 b0 + "punpcklwd %%mm4, %%mm1\n\t" // 00 a1 00 g1 00 a0 00 g0 + "punpckhwd %%mm2, %%mm5\n\t" // 00 r3 00 b3 00 r2 00 b2 + "punpckhwd %%mm4, %%mm3\n\t" // 00 a3 00 g3 00 a2 00 g2 + "movq %%mm0, %%mm2\n\t" // 00 r1 00 b1 00 r0 00 b0 + "movq %%mm5, %%mm4\n\t" // 00 r3 00 b3 00 r2 00 b2 + "punpcklwd %%mm1, %%mm0\n\t" // 00 a0 00 r0 00 g0 00 b0 + "punpcklwd %%mm3, %%mm5\n\t" // 00 a2 00 r2 00 g2 00 b2 + "punpckhwd %%mm1, %%mm2\n\t" // 00 a1 00 r1 00 g1 00 b1 + "punpckhwd %%mm3, %%mm4\n\t" // 00 a3 00 r3 00 g3 00 b3 + "movq %%mm0, (%0)\n\t" + "movq %%mm2, 8(%0)\n\t" + "movq %%mm5,16(%0)\n\t" + "movq %%mm4,24(%0)\n\t" + "add $32, %0\n\t" + "decl %1\n\t" + "jnz 1b\n\t" + "emms\n\t" + "2:" + : "=&D" (D) + : "c" (gfxs->length), "m" (*sub0), "m" (*sub1), "r" (mul), "0" (D) + : "memory" ); + + while (w) { + if (!(D->YUV.a & 0xF000)) + YCBCR_TO_RGB( D->YUV.y, D->YUV.u, D->YUV.v, + D->RGB.r, D->RGB.g, D->RGB.b ); + + D++; + w--; + } +} + +static void Dacc_RGB_to_YCbCr_MMX( GenefxState *gfxs ) +{ + static const u16 __aligned(8) add0[4] = { 128, 128, 128, 128 }; + static const u16 __aligned(8) add1[4] = { 16, 16, 16, 16 }; + static const u16 __aligned(8) mul[24] = { + 0x03A5, 0x03A5, 0x03A5, 0x03A5, // Eb + 0x12C8, 0x12C8, 0x12C8, 0x12C8, // Eg + 0x0991, 0x0991, 0x0991, 0x0991, // Er + 0x0FE1, 0x0FE1, 0x0FE1, 0x0FE1, // Cb + 0x140A, 0x140A, 0x140A, 0x140A, // Cr + 0x1B7B, 0x1B7B, 0x1B7B, 0x1B7B // Y + }; + + int w = gfxs->length & 3; + GenefxAccumulator *D = gfxs->Dacc; + + __asm__ __volatile__( + "shrl $2, %1\n\t" + "jz 2f\n\t" + "pxor %%mm7, %%mm7\n\t" + ".align 16\n" + "1:\n\t" + "movq (%0), %%mm0\n\t" // 00 a0 00 r0 00 g0 00 b0 + "movq 8(%0), %%mm1\n\t" // 00 a1 00 r1 00 g1 00 b1 + "movq 16(%0), %%mm2\n\t" // 00 a2 00 r2 00 g2 00 b2 + "movq 24(%0), %%mm3\n\t" // 00 a3 00 r3 00 g3 00 b3 + "movq %%mm0, %%mm4\n\t" // 00 a0 00 r0 00 g0 00 b0 + "movq %%mm2, %%mm6\n\t" // 00 a2 00 r2 00 g2 00 b2 + "punpcklwd %%mm1, %%mm0\n\t" // 00 g1 00 g0 00 b1 00 b0 + "punpcklwd %%mm3, %%mm2\n\t" // 00 g3 00 g2 00 b3 00 b2 + "movq %%mm0, %%mm5\n\t" // 00 g1 00 g0 00 b1 00 b0 + "punpckldq %%mm2, %%mm0\n\t" // 00 b3 00 b2 00 b1 00 b0 + "punpckhdq %%mm2, %%mm5\n\t" // 00 g3 00 g2 00 g1 00 g0 + "punpckhwd %%mm1, %%mm4\n\t" // 00 a1 00 a0 00 r1 00 r0 + "punpckhwd %%mm3, %%mm6\n\t" // 00 a3 00 a2 00 r3 00 r2 + "movq %%mm4, %%mm3\n\t" // 00 a1 00 a0 00 r1 00 r0 + "punpckldq %%mm6, %%mm4\n\t" // 00 r3 00 r2 00 r1 00 r0 + "punpckhdq %%mm6, %%mm3\n\t" // 00 a3 00 a2 00 a1 00 a0 + /* mm0 = b, mm5 = g, mm4 = r, mm3 = a */ + "movq %%mm0, %%mm1\n\t" // save b + "psllw $3, %%mm0\n\t" + "pmulhw (%2), %%mm0\n\t" + "movq %%mm4, %%mm2\n\t" // save r + "psllw $3, %%mm5\n\t" + "pmulhw 8(%2), %%mm5\n\t" + "psllw $3, %%mm4\n\t" + "pmulhw 16(%2), %%mm4\n\t" + "paddw %%mm5, %%mm0\n\t" + "paddw %%mm4, %%mm0\n\t" // ey + "psubw %%mm0, %%mm1\n\t" // b - ey + "psllw $3, %%mm1\n\t" + "pmulhw 24(%2), %%mm1\n\t" // 00 u3 00 u2 00 u1 00 u0 + "psubw %%mm0, %%mm2\n\t" // r - ey + "psllw $3, %%mm2\n\t" + "pmulhw 32(%2), %%mm2\n\t" // 00 v3 00 v2 00 v1 00 v0 + "paddw %3, %%mm1\n\t" // Cb + 128 + "packuswb %%mm1, %%mm1\n\t" // u3 u2 u1 u0 u3 u2 u1 u0 + "psllw $3, %%mm0\n\t" + "pmulhw 40(%2), %%mm0\n\t" // 00 y3 00 y2 00 y1 00 y0 + "paddw %3, %%mm2\n\t" // Cr + 128 + "packuswb %%mm2, %%mm2\n\t" // v3 v2 v1 v0 v3 v2 v1 v0 + "paddw %4, %%mm0\n\t" // Y + 16 + "packuswb %%mm0, %%mm0\n\t" // y3 y2 y1 y0 y3 y2 y1 y0 + "punpcklbw %%mm7, %%mm2\n\t" // 00 v3 00 v2 00 v1 00 v0 + "punpcklbw %%mm7, %%mm1\n\t" // 00 u3 00 y2 00 u1 00 u0 + "punpcklbw %%mm7, %%mm0\n\t" // 00 y3 00 y2 00 y1 00 y0 + /* mm1 = u, mm2 = v, mm0 = y, mm3 = a */ + "movq %%mm2, %%mm4\n\t" // 00 v3 00 v2 00 v1 00 v0 + "movq %%mm1, %%mm5\n\t" // 00 u3 00 y2 00 u1 00 u0 + "punpcklwd %%mm3, %%mm2\n\t" // 00 a1 00 v1 00 a0 00 v0 + "punpcklwd %%mm0, %%mm1\n\t" // 00 y1 00 u1 00 y0 00 u0 + "punpckhwd %%mm3, %%mm4\n\t" // 00 a3 00 v3 00 a2 00 v2 + "punpckhwd %%mm0, %%mm5\n\t" // 00 y3 00 u3 00 y2 00 u2 + "movq %%mm1, %%mm3\n\t" // 00 y1 00 u1 00 y0 00 u0 + "movq %%mm5, %%mm6\n\t" // 00 y3 00 u3 00 y2 00 u2 + "punpcklwd %%mm2, %%mm1\n\t" // 00 a0 00 y0 00 v0 00 u0 + "punpcklwd %%mm4, %%mm5\n\t" // 00 a2 00 y2 00 v2 00 u2 + "punpckhwd %%mm2, %%mm3\n\t" // 00 a1 00 y1 00 v1 00 u1 + "punpckhwd %%mm4, %%mm6\n\t" // 00 a3 00 y3 00 v3 00 u3 + "movq %%mm1, (%0)\n\t" + "movq %%mm3, 8(%0)\n\t" + "movq %%mm5,16(%0)\n\t" + "movq %%mm6,24(%0)\n\t" + "add $32, %0\n\t" + "decl %1\n\t" + "jnz 1b\n\t" + "emms\n\t" + "2:" + : "=&D" (D) + : "c" (gfxs->length), "r" (mul), "m" (*add0), "m" (*add1), "0" (D) + : "memory" ); + + while (w) { + if (!(D->RGB.a & 0xF000)) + RGB_TO_YCBCR( D->RGB.r, D->RGB.g, D->RGB.b, + D->YUV.y, D->YUV.u, D->YUV.v ); + + D++; + w--; + } +} + diff --git a/Source/DirectFB/src/gfx/generic/stretch_hvx_16.h b/Source/DirectFB/src/gfx/generic/stretch_hvx_16.h new file mode 100755 index 0000000..01cf41f --- /dev/null +++ b/Source/DirectFB/src/gfx/generic/stretch_hvx_16.h @@ -0,0 +1,469 @@ +#ifndef SOURCE_LOOKUP +#define SOURCE_LOOKUP(x) (x) +#define SOURCE_LOOKUP_AUTO +#endif + +#ifndef SOURCE_TYPE +#define SOURCE_TYPE u16 +#define SOURCE_TYPE_AUTO +#endif + + +#define SHIFT_L5 SHIFT_R5 +#define SHIFT_L6 SHIFT_R6 +#define SHIFT_L10 (16-SHIFT_L6) + +#define X_003F (X_07E0>>SHIFT_R5) + +#define X_003E07C0 (X_F81F<>SHIFT_R5) + +#if 0 +#define HVX_DEBUG(x...) direct_log_printf( NULL, x ) +#else +#define HVX_DEBUG(x...) do {} while (0) +#endif + +/* stretch_hvx_up/down_16_KPI */( void *dst, + int dpitch, + const void *src, + int spitch, + int width, + int height, + int dst_width, + int dst_height, + const StretchCtx *ctx ) +{ + long x, y, r = 0; + long head = ((((ulong) dst) & 2) >> 1) ^ (ctx->clip.x1 & 1); + long cw = ctx->clip.x2 - ctx->clip.x1 + 1; + long ch = ctx->clip.y2 - ctx->clip.y1 + 1; + long tail = (cw - head) & 1; + long w2 = (cw - head) / 2; + long hfraq = ((long)(width - MINUS_1) << 18) / (long)(dst_width); + long vfraq = ((long)(height - MINUS_1) << 18) / (long)(dst_height); + long dp4 = dpitch / 4; + long point0 = POINT_0 + ctx->clip.x1 * hfraq; + long point = point0; + long line = LINE_0 + ctx->clip.y1 * vfraq; + long ratios[cw]; + u32 *dst32; + +#if defined (COLOR_KEY) || defined (KEY_PROTECT) + u32 dt; + u16 l_, h_; +#endif + + u32 _lbT[w2+8]; + u32 _lbB[w2+8]; + + u32 *lbX; + u32 *lbT = (u32*)((((ulong)(&_lbT[0])) + 31) & ~31); + u32 *lbB = (u32*)((((ulong)(&_lbB[0])) + 31) & ~31); + + long lineT = -2000; + + for (x=0; x %dx%d (0x%lx, 0x%lx) prot %lx, key %lx\n", + __FUNCTION__, width, height, dst_width, dst_height, hfraq, vfraq, ctx->protect, ctx->key ); + + dst += ctx->clip.x1 * 2 + ctx->clip.y1 * dpitch; + + dst32 = dst; + + if (head) { + u32 dpT, dpB, L, R; + + u16 *dst16 = dst; + + point = point0; + + for (y=0; y= 0 ); + D_ASSERT( pl < width-1 ); + L = SOURCE_LOOKUP(srcT[pl]); + R = SOURCE_LOOKUP(srcT[pl+1]); + + dpT = (((((R & X_F81F)-(L & X_F81F))*ratios[r] + ((L & X_F81F)<> SHIFT_R6; + + L = SOURCE_LOOKUP(srcB[pl]); + R = SOURCE_LOOKUP(srcB[pl+1]); + + dpB = (((((R & X_F81F)-(L & X_F81F))*ratios[r] + ((L & X_F81F)<> SHIFT_R6; + + /* + * Vertical interpolation + */ +#if defined (COLOR_KEY) || defined (KEY_PROTECT) + l_ = ((((((dpB & X_F81F) - (dpT & X_F81F))*X) >> SHIFT_R5) + (dpT & X_F81F)) & X_F81F) + + ((((((dpB>>SHIFT_R5) & X_003F) - ((dpT>>SHIFT_R5) & X_003F))*X) + (dpT & X_07E0)) & X_07E0); +#ifdef COLOR_KEY + if ((l_ & MASK_RGB) != (COLOR_KEY)) +#endif +#ifdef KEY_PROTECT + /* Write to destination with color key protection */ + dst16[0] = ((l_ & MASK_RGB) == KEY_PROTECT) ? l_^1 : l_; +#else + /* Write to destination without color key protection */ + dst16[0] = l_; +#endif +#else + /* Write to destination without color key protection */ + dst16[0] = ((((((dpB & X_F81F) - (dpT & X_F81F))*X) >> SHIFT_R5) + (dpT & X_F81F)) & X_F81F) + + ((((((dpB>>SHIFT_R5) & X_003F) - ((dpT>>SHIFT_R5) & X_003F))*X) + (dpT & X_07E0)) & X_07E0); +#endif + + dst16 += dpitch / 2; + line += vfraq; + } + + /* Adjust */ + point0 += hfraq; + dst32 = dst + 2; + + /* Reset */ + line = LINE_0 + ctx->clip.y1 * vfraq; + } + + /* + * Scale line by line. + */ + for (y=0; y= 0 ); + D_ASSERT( nlT < height-1 ); + + /* + * Fill line buffer(s) ? + */ + if (nlT != lineT) { + u32 L, R, dpT, dpB; + const SOURCE_TYPE *srcT = src + spitch * nlT; + const SOURCE_TYPE *srcB = src + spitch * (nlT + 1); + long diff = nlT - lineT; + + if (diff > 1) { + /* + * Two output pixels per step. + */ + for (x=0, r=head, point=point0; x= 0 ); + D_ASSERT( pl < width-1 ); + L = SOURCE_LOOKUP(srcT[pl]); + R = SOURCE_LOOKUP(srcT[pl+1]); + + dpT = (((((R & X_F81F)-(L & X_F81F))*ratios[r] + ((L & X_F81F)<> SHIFT_R6; +#endif + + L = SOURCE_LOOKUP(srcB[pl]); + R = SOURCE_LOOKUP(srcB[pl+1]); + + dpB = (((((R & X_F81F)-(L & X_F81F))*ratios[r] + ((L & X_F81F)<> SHIFT_R6; +#endif + + point += hfraq; + r++; + + + pl = POINT_L( point, hfraq ); + HVX_DEBUG("%ld,%ld %lu (%lu/%lu) 0x%x 0x%x\n", x, y, pl, + POINT_L( point, hfraq ), POINT_R( point, hfraq ), point, ratios[r] ); + D_ASSERT( pl >= 0 ); + D_ASSERT( pl < width-1 ); + + L = SOURCE_LOOKUP(srcT[pl]); + R = SOURCE_LOOKUP(srcT[pl+1]); + + dpT |= (((((R & X_F81F)-(L & X_F81F))*ratios[r] + ((L & X_F81F)<> SHIFT_R6; +#else + << SHIFT_L10; +#endif + + L = SOURCE_LOOKUP(srcB[pl]); + R = SOURCE_LOOKUP(srcB[pl+1]); + + dpB |= (((((R & X_F81F)-(L & X_F81F))*ratios[r] + ((L & X_F81F)<> SHIFT_R6; +#else + << SHIFT_L10; +#endif + + point += hfraq; + r++; + + /* Store */ + lbT[x] = dpT; + lbB[x] = dpB; + } + } + else { + /* Swap */ + lbX = lbT; + lbT = lbB; + lbB = lbX; + + /* + * Two output pixels per step. + */ + for (x=0, r=head, point=point0; x= 0 ); + D_ASSERT( pl < width-1 ); + L = SOURCE_LOOKUP(srcB[pl]); + R = SOURCE_LOOKUP(srcB[pl+1]); + + dpB = (((((R & X_F81F)-(L & X_F81F))*ratios[r] + ((L & X_F81F)<> SHIFT_R6; +#endif + + point += hfraq; + r++; + + + pl = POINT_L( point, hfraq ); + HVX_DEBUG("%ld,%ld %lu (%lu/%lu) 0x%x 0x%x\n", x, y, pl, + POINT_L( point, hfraq ), POINT_R( point, hfraq ), point, ratios[r] ); + D_ASSERT( pl >= 0 ); + D_ASSERT( pl < width-1 ); + + L = SOURCE_LOOKUP(srcB[pl]); + R = SOURCE_LOOKUP(srcB[pl+1]); + + dpB |= (((((R & X_F81F)-(L & X_F81F))*ratios[r] + ((L & X_F81F)<> SHIFT_R6; +#else + << SHIFT_L10; +#endif + + point += hfraq; + r++; + + /* Store */ + lbB[x] = dpB; + } + } + + lineT = nlT; + } + + /* + * Vertical interpolation + */ + X = LINE_TO_RATIO( line, vfraq ); + + for (x=0; x> SHIFT_R5) + (lbT[x] & X_F81FF81F)) & X_F81FF81F) + + ((((((lbB[x]>>SHIFT_R5) & X_F81FF81F) - ((lbT[x]>>SHIFT_R5) & X_F81FF81F))*X) + (lbT[x] & X_07E007E0)) & X_07E007E0); +#else + dt = ((((((lbB[x] & X_07E0F81F) - (lbT[x] & X_07E0F81F))*X) >> SHIFT_R5) + (lbT[x] & X_07E0F81F)) & X_07E0F81F) + + ((((((lbB[x]>>SHIFT_R5) & X_07C0F83F) - ((lbT[x]>>SHIFT_R5) & X_07C0F83F))*X) + (lbT[x] & X_F81F07E0)) & X_F81F07E0); +#endif + + /* Get two new pixels. */ + l_ = dt; + h_ = dt >> 16; + +#ifdef COLOR_KEY + if ((l_ & MASK_RGB) != (COLOR_KEY)) { + if ((h_ & MASK_RGB) != (COLOR_KEY)) { +#ifdef KEY_PROTECT + /* Write to destination with color key protection */ + dst32[x] = ((((h_ & MASK_RGB) == KEY_PROTECT) ? h_^1 : h_) << 16) | (((l_ & MASK_RGB) == KEY_PROTECT) ? l_^1 : l_); +#else + /* Write to destination without color key protection */ + dst32[x] = dt; +#endif + } + else { + u16 *_dst16 = (u16*) &dst32[x]; + +#ifdef KEY_PROTECT + /* Write to destination with color key protection */ + *_dst16 = (((l_ & MASK_RGB) == KEY_PROTECT) ? l_^1 : l_); +#else + /* Write to destination without color key protection */ + *_dst16 = l_; +#endif + } + } + else if ((h_ & MASK_RGB) != (COLOR_KEY)) { + u16 *_dst16 = ((u16*) &dst32[x]) + 1; + +#ifdef KEY_PROTECT + /* Write to destination with color key protection */ + *_dst16 = (((h_ & MASK_RGB) == KEY_PROTECT) ? h_^1 : h_); +#else + /* Write to destination without color key protection */ + *_dst16 = h_; +#endif + } +#else + /* Write to destination with color key protection */ + dst32[x] = ((((h_ & MASK_RGB) == KEY_PROTECT) ? h_^1 : h_) << 16) | (((l_ & MASK_RGB) == KEY_PROTECT) ? l_^1 : l_); +#endif +#else +#ifdef HAS_ALPHA + dst32[x] = ((((((lbB[x] & X_F81FF81F) - (lbT[x] & X_F81FF81F))*X) >> SHIFT_R5) + (lbT[x] & X_F81FF81F)) & X_F81FF81F) + + ((((((lbB[x]>>SHIFT_R5) & X_F81FF81F) - ((lbT[x]>>SHIFT_R5) & X_F81FF81F))*X) + (lbT[x] & X_07E007E0)) & X_07E007E0); +#else + dst32[x] = ((((((lbB[x] & X_07E0F81F) - (lbT[x] & X_07E0F81F))*X) >> SHIFT_R5) + (lbT[x] & X_07E0F81F)) & X_07E0F81F) + + ((((((lbB[x]>>SHIFT_R5) & X_07C0F83F) - ((lbT[x]>>SHIFT_R5) & X_07C0F83F))*X) + (lbT[x] & X_F81F07E0)) & X_F81F07E0); +#endif +#endif + } + + dst32 += dp4; + line += vfraq; + } + + if (tail) { + u32 dpT, dpB, L, R; + + u16 *dst16 = dst + cw * 2 - 2; + + /* Reset */ + line = LINE_0 + ctx->clip.y1 * vfraq; + + for (y=0; y= 0 ); + D_ASSERT( pl < width-1 ); + L = SOURCE_LOOKUP(srcT[pl]); + R = SOURCE_LOOKUP(srcT[pl+1]); + + dpT = (((((R & X_F81F)-(L & X_F81F))*ratios[r] + ((L & X_F81F)<> SHIFT_R6; + + L = SOURCE_LOOKUP(srcB[pl]); + R = SOURCE_LOOKUP(srcB[pl+1]); + + dpB = (((((R & X_F81F)-(L & X_F81F))*ratios[r] + ((L & X_F81F)<> SHIFT_R6; + + /* + * Vertical interpolation + */ +#if defined (COLOR_KEY) || defined (KEY_PROTECT) + l_ = ((((((dpB & X_F81F) - (dpT & X_F81F))*X) >> SHIFT_R5) + (dpT & X_F81F)) & X_F81F) + + ((((((dpB>>SHIFT_R5) & X_003F) - ((dpT>>SHIFT_R5) & X_003F))*X) + (dpT & X_07E0)) & X_07E0); + +#ifdef COLOR_KEY + if ((l_ & MASK_RGB) != (COLOR_KEY)) +#endif +#ifdef KEY_PROTECT + /* Write to destination with color key protection */ + dst16[0] = ((l_ & MASK_RGB) == KEY_PROTECT) ? l_^1 : l_; +#else + /* Write to destination without color key protection */ + dst16[0] = l_; +#endif +#else + /* Write to destination without color key protection */ + dst16[0] = ((((((dpB & X_F81F) - (dpT & X_F81F))*X) >> SHIFT_R5) + (dpT & X_F81F)) & X_F81F) + + ((((((dpB>>SHIFT_R5) & X_003F) - ((dpT>>SHIFT_R5) & X_003F))*X) + (dpT & X_07E0)) & X_07E0); +#endif + + dst16 += dpitch / 2; + line += vfraq; + } + } +} + + +#undef SHIFT_L6 +#undef SHIFT_L10 + +#undef X_003F + +#undef X_003E07C0 +#undef X_0001F800 + +#undef X_07E0F81F +#undef X_F81F07E0 + +#undef X_07C0F83F + + + +#ifdef SOURCE_LOOKUP_AUTO +#undef SOURCE_LOOKUP_AUTO +#undef SOURCE_LOOKUP +#endif + +#ifdef SOURCE_TYPE_AUTO +#undef SOURCE_TYPE_AUTO +#undef SOURCE_TYPE +#endif + diff --git a/Source/DirectFB/src/gfx/generic/stretch_hvx_32.h b/Source/DirectFB/src/gfx/generic/stretch_hvx_32.h new file mode 100755 index 0000000..289ff2c --- /dev/null +++ b/Source/DirectFB/src/gfx/generic/stretch_hvx_32.h @@ -0,0 +1,174 @@ +#ifndef SOURCE_LOOKUP +#define SOURCE_LOOKUP(x) (x) +#define SOURCE_LOOKUP_AUTO +#endif + +#ifndef SOURCE_TYPE +#define SOURCE_TYPE u32 +#define SOURCE_TYPE_AUTO +#endif + +#if 0 +#define HVX_DEBUG(x...) direct_log_printf( NULL, x ) +#else +#define HVX_DEBUG(x...) do {} while (0) +#endif + +/* stretch_hvx_up/down_32_KPI */( void *dst, + int dpitch, + const void *src, + int spitch, + int width, + int height, + int dst_width, + int dst_height, + const StretchCtx *ctx ) +{ + long x, y = 0; + long cw = ctx->clip.x2 - ctx->clip.x1 + 1; + long ch = ctx->clip.y2 - ctx->clip.y1 + 1; + long hfraq = ((long)(width - MINUS_1) << 18) / (long)(dst_width); + long vfraq = ((long)(height - MINUS_1) << 18) / (long)(dst_height); + long dp4 = dpitch / 4; + long point0 = POINT_0 + ctx->clip.x1 * hfraq; + long point = point0; + long line = LINE_0 + ctx->clip.y1 * vfraq; + long ratios[cw]; + u32 *dst32; + +#if defined (COLOR_KEY) || defined (KEY_PROTECT) + u32 dt; +#endif + + u32 _lbT[cw+8]; + u32 _lbB[cw+8]; + + u32 *lbX; + u32 *lbT = (u32*)((((ulong)(&_lbT[0])) + 31) & ~31); + u32 *lbB = (u32*)((((ulong)(&_lbB[0])) + 31) & ~31); + + long lineT = -2000; + + for (x=0; x %dx%d (0x%x, 0x%x)\n", width, height, dst_width, dst_height, hfraq, vfraq ); + + dst += ctx->clip.x1 * 4 + ctx->clip.y1 * dpitch; + + dst32 = dst; + + /* + * Scale line by line. + */ + for (y=0; y= 0 ); + D_ASSERT( nlT < height-1 ); + + /* + * Fill line buffer(s) ? + */ + if (nlT != lineT) { + u32 L, R; + const SOURCE_TYPE *srcT = src + spitch * nlT; + const SOURCE_TYPE *srcB = src + spitch * (nlT + 1); + long diff = nlT - lineT; + + if (diff > 1) { + /* + * Horizontal interpolation + */ + for (x=0, point=point0; x= 0 ); + D_ASSERT( pl < width-1 ); + + L = SOURCE_LOOKUP(srcT[pl]); + R = SOURCE_LOOKUP(srcT[pl+1]); + + lbT[x]= ((((((R & X_00FF00FF) - (L & X_00FF00FF))*ratios[x]) >> SHIFT_R8) + (L & X_00FF00FF)) & X_00FF00FF) + + ((((((R>>SHIFT_R8) & X_00FF00FF) - ((L>>SHIFT_R8) & X_00FF00FF))*ratios[x]) + (L & X_FF00FF00)) & X_FF00FF00); + + L = SOURCE_LOOKUP(srcB[pl]); + R = SOURCE_LOOKUP(srcB[pl+1]); + + lbB[x] = ((((((R & X_00FF00FF) - (L & X_00FF00FF))*ratios[x]) >> SHIFT_R8) + (L & X_00FF00FF)) & X_00FF00FF) + + ((((((R>>SHIFT_R8) & X_00FF00FF) - ((L>>SHIFT_R8) & X_00FF00FF))*ratios[x]) + (L & X_FF00FF00)) & X_FF00FF00); + } + } + else { + /* Swap */ + lbX = lbT; + lbT = lbB; + lbB = lbX; + + /* + * Horizontal interpolation + */ + for (x=0, point=point0; x= 0 ); + D_ASSERT( pl < width-1 ); + + L = SOURCE_LOOKUP(srcB[pl]); + R = SOURCE_LOOKUP(srcB[pl+1]); + + lbB[x] = ((((((R & X_00FF00FF) - (L & X_00FF00FF))*ratios[x]) >> SHIFT_R8) + (L & X_00FF00FF)) & X_00FF00FF) + + ((((((R>>SHIFT_R8) & X_00FF00FF) - ((L>>SHIFT_R8) & X_00FF00FF))*ratios[x]) + (L & X_FF00FF00)) & X_FF00FF00); + } + } + + lineT = nlT; + } + + /* + * Vertical interpolation + */ + X = LINE_TO_RATIO( line, vfraq ); + + for (x=0; x> SHIFT_R8) + (lbT[x] & X_00FF00FF)) & X_00FF00FF) + + ((((((lbB[x]>>SHIFT_R8) & X_00FF00FF) - ((lbT[x]>>SHIFT_R8) & X_00FF00FF))*X) + (lbT[x] & X_FF00FF00)) & X_FF00FF00); +#ifdef COLOR_KEY + if (dt != (COLOR_KEY)) +#endif +#ifdef KEY_PROTECT + /* Write to destination with color key protection */ + dst32[x] = ((dt & MASK_RGB) == KEY_PROTECT) ? dt^1 : dt; +#else + /* Write to destination without color key protection */ + dst32[x] = dt; +#endif +#else + /* Write to destination without color key protection */ + dst32[x] = ((((((lbB[x] & X_00FF00FF) - (lbT[x] & X_00FF00FF))*X) >> SHIFT_R8) + (lbT[x] & X_00FF00FF)) & X_00FF00FF) + + ((((((lbB[x]>>SHIFT_R8) & X_00FF00FF) - ((lbT[x]>>SHIFT_R8) & X_00FF00FF))*X) + (lbT[x] & X_FF00FF00)) & X_FF00FF00); +#endif + } + + dst32 += dp4; + line += vfraq; + } +} + +#ifdef SOURCE_LOOKUP_AUTO +#undef SOURCE_LOOKUP_AUTO +#undef SOURCE_LOOKUP +#endif + +#ifdef SOURCE_TYPE_AUTO +#undef SOURCE_TYPE_AUTO +#undef SOURCE_TYPE +#endif + diff --git a/Source/DirectFB/src/gfx/generic/stretch_hvx_8.h b/Source/DirectFB/src/gfx/generic/stretch_hvx_8.h new file mode 100755 index 0000000..e809304 --- /dev/null +++ b/Source/DirectFB/src/gfx/generic/stretch_hvx_8.h @@ -0,0 +1,149 @@ +#ifndef SOURCE_LOOKUP +#define SOURCE_LOOKUP(x) (x) +#define SOURCE_LOOKUP_AUTO +#endif + +#ifndef SOURCE_TYPE +#define SOURCE_TYPE u8 +#define SOURCE_TYPE_AUTO +#endif + +#if 0 +#define HVX_DEBUG(x...) direct_log_printf( NULL, x ) +#else +#define HVX_DEBUG(x...) do {} while (0) +#endif + +/*** OPTIMIZE by doing four pixels at once (vertically) with a 32 bit line buffer ***/ + +/*static void STRETCH_HVX_YV12( void *dst, + int dpitch, + const void *src, + int spitch, + int width, + int height, + int dst_width, + int dst_height, + DFBRegion *clip )*/ +{ + long x, y = 0; + long cw = clip->x2 - clip->x1 + 1; + long ch = clip->y2 - clip->y1 + 1; + long hfraq = ((long)(width - MINUS_1) << 18) / (long)(dst_width); + long vfraq = ((long)(height - MINUS_1) << 18) / (long)(dst_height); + long point0 = POINT_0 + clip->x1 * hfraq; + long point = point0; + long line = LINE_0 + clip->y1 * vfraq; + long ratios[cw]; + u8 *dst8; + + u8 _lbT[cw+32]; + u8 _lbB[cw+32]; + + u8 *lbX; + u8 *lbT = (u8*)((((ulong)(&_lbT[0])) + 31) & ~31); + u8 *lbB = (u8*)((((ulong)(&_lbB[0])) + 31) & ~31); + + long lineT = -2000; + + for (x=0; x %dx%d (0x%x, 0x%x)\n", width, height, dst_width, dst_height, hfraq, vfraq ); + + dst += clip->x1 + clip->y1 * dpitch; + + dst8 = dst; + + /* + * Scale line by line. + */ + for (y=0; y= 0 ); + D_ASSERT( nlT < height-1 ); + + /* + * Fill line buffer(s) ? + */ + if (nlT != lineT) { + u8 L, R; + const SOURCE_TYPE *srcT = src + spitch * nlT; + const SOURCE_TYPE *srcB = src + spitch * (nlT + 1); + long diff = nlT - lineT; + + if (diff > 1) { + /* + * Horizontal interpolation + */ + for (x=0, point=point0; x= 0 ); + D_ASSERT( pl < width-1 ); + + L = SOURCE_LOOKUP(srcT[pl]); + R = SOURCE_LOOKUP(srcT[pl+1]); + + lbT[x] = (((R - L) * ratios[x]) >> 8) + L; + + L = SOURCE_LOOKUP(srcB[pl]); + R = SOURCE_LOOKUP(srcB[pl+1]); + + lbB[x] = (((R - L) * ratios[x]) >> 8) + L; + } + } + else { + /* Swap */ + lbX = lbT; + lbT = lbB; + lbB = lbX; + + /* + * Horizontal interpolation + */ + for (x=0, point=point0; x= 0 ); + D_ASSERT( pl < width-1 ); + + L = SOURCE_LOOKUP(srcB[pl]); + R = SOURCE_LOOKUP(srcB[pl+1]); + + lbB[x] = (((R - L) * ratios[x]) >> 8) + L; + } + } + + lineT = nlT; + } + + /* + * Vertical interpolation + */ + long X = LINE_TO_RATIO( line, vfraq ); + + for (x=0; x> 8) + lbT[x]; + + dst8 += dpitch; + line += vfraq; + } +} + +#ifdef SOURCE_LOOKUP_AUTO +#undef SOURCE_LOOKUP_AUTO +#undef SOURCE_LOOKUP +#endif + +#ifdef SOURCE_TYPE_AUTO +#undef SOURCE_TYPE_AUTO +#undef SOURCE_TYPE +#endif + diff --git a/Source/DirectFB/src/gfx/generic/stretch_hvx_88.h b/Source/DirectFB/src/gfx/generic/stretch_hvx_88.h new file mode 100755 index 0000000..6394b5b --- /dev/null +++ b/Source/DirectFB/src/gfx/generic/stretch_hvx_88.h @@ -0,0 +1,152 @@ +#ifndef SOURCE_LOOKUP +#define SOURCE_LOOKUP(x) (x) +#define SOURCE_LOOKUP_AUTO +#endif + +#ifndef SOURCE_TYPE +#define SOURCE_TYPE u16 +#define SOURCE_TYPE_AUTO +#endif + +#if 0 +#define HVX_DEBUG(x...) direct_log_printf( NULL, x ) +#else +#define HVX_DEBUG(x...) do {} while (0) +#endif + + +/*** OPTIMIZE by doing two pixels at once (vertically) with a 32 bit line buffer ***/ + +/*static void STRETCH_HVX_NV16( void *dst, + int dpitch, + const void *src, + int spitch, + int width, + int height, + int dst_width, + int dst_height, + DFBRegion *clip )*/ +{ + long x, y = 0; + long cw = clip->x2 - clip->x1 + 1; + long ch = clip->y2 - clip->y1 + 1; + long hfraq = ((long)(width - MINUS_1) << 18) / (long)(dst_width); + long vfraq = ((long)(height - MINUS_1) << 18) / (long)(dst_height); + long point0 = POINT_0 + clip->x1 * hfraq; + long point = point0; + long line = LINE_0 + clip->y1 * vfraq; + long ratios[cw]; + u16 *dst16; + + u16 _lbT[cw+16]; + u16 _lbB[cw+16]; + + u16 *lbX; + u16 *lbT = (u16*)((((ulong)(&_lbT[0])) + 31) & ~31); + u16 *lbB = (u16*)((((ulong)(&_lbB[0])) + 31) & ~31); + + long lineT = -2000; + + for (x=0; xx1 * 2 + clip->y1 * dpitch; + + dst16 = dst; + + /* + * Scale line by line. + */ + for (y=0; y= 0 ); + D_ASSERT( nlT < height-1 ); + + /* + * Fill line buffer(s) ? + */ + if (nlT != lineT) { + u16 L, R; + const SOURCE_TYPE *srcT = src + spitch * nlT; + const SOURCE_TYPE *srcB = src + spitch * (nlT + 1); + long diff = nlT - lineT; + + if (diff > 1) { + /* + * Horizontal interpolation + */ + for (x=0, point=point0; x= 0 ); + D_ASSERT( pl < width-1 ); + + L = SOURCE_LOOKUP(srcT[pl]); + R = SOURCE_LOOKUP(srcT[pl+1]); + + lbT[x] = (((((R & 0x00ff)-(L & 0x00ff))*ratios[x] + ((L & 0x00ff)<<8)) & 0x00ff00) + + ((((R & 0xff00)-(L & 0xff00))*ratios[x] + ((L & 0xff00)<<8)) & 0xff0000)) >> 8; + + L = SOURCE_LOOKUP(srcB[pl]); + R = SOURCE_LOOKUP(srcB[pl+1]); + + lbB[x] = (((((R & 0x00ff)-(L & 0x00ff))*ratios[x] + ((L & 0x00ff)<<8)) & 0x00ff00) + + ((((R & 0xff00)-(L & 0xff00))*ratios[x] + ((L & 0xff00)<<8)) & 0xff0000)) >> 8; + } + } + else { + /* Swap */ + lbX = lbT; + lbT = lbB; + lbB = lbX; + + /* + * Horizontal interpolation + */ + for (x=0, point=point0; x= 0 ); + D_ASSERT( pl < width-1 ); + + L = SOURCE_LOOKUP(srcB[pl]); + R = SOURCE_LOOKUP(srcB[pl+1]); + + lbB[x] = (((((R & 0x00ff)-(L & 0x00ff))*ratios[x] + ((L & 0x00ff)<<8)) & 0x00ff00) + + ((((R & 0xff00)-(L & 0xff00))*ratios[x] + ((L & 0xff00)<<8)) & 0xff0000)) >> 8; + } + } + + lineT = nlT; + } + + /* + * Vertical interpolation + */ + long X = LINE_TO_RATIO( line, vfraq ); + + for (x=0; x> 8; + + dst16 += dpitch / 2; + line += vfraq; + } +} + +#ifdef SOURCE_LOOKUP_AUTO +#undef SOURCE_LOOKUP_AUTO +#undef SOURCE_LOOKUP +#endif + +#ifdef SOURCE_TYPE_AUTO +#undef SOURCE_TYPE_AUTO +#undef SOURCE_TYPE +#endif + diff --git a/Source/DirectFB/src/gfx/generic/stretch_hvx_N.h b/Source/DirectFB/src/gfx/generic/stretch_hvx_N.h new file mode 100755 index 0000000..c4922e1 --- /dev/null +++ b/Source/DirectFB/src/gfx/generic/stretch_hvx_N.h @@ -0,0 +1,121 @@ +#if UPDOWN == 1 +#define FUNC_NAME_(K,P,F) FUNC_NAME(up,K,P,F) +#else +#define FUNC_NAME_(K,P,F) FUNC_NAME(down,K,P,F) +#endif + + +/* NONE */ +static void FUNC_NAME_(_,_,DST_FORMAT) +#include STRETCH_HVX_N_H + +/* SRCKEY */ +#define COLOR_KEY ctx->key +static void FUNC_NAME_(K,_,DST_FORMAT) +#include STRETCH_HVX_N_H +#undef COLOR_KEY + +/* PROTECT */ +#define KEY_PROTECT ctx->protect +static void FUNC_NAME_(_,P,DST_FORMAT) +#include STRETCH_HVX_N_H + +/* PROTECT SRCKEY */ +#define COLOR_KEY ctx->key +static void FUNC_NAME_(K,P,DST_FORMAT) +#include STRETCH_HVX_N_H +#undef COLOR_KEY +#undef KEY_PROTECT + + +/* INDEXED */ +#define SOURCE_LOOKUP(x) ((const uN*)ctx->colors)[x] +#define SOURCE_TYPE u8 +static void FUNC_NAME_(_,_,DSPF_LUT8) +#include STRETCH_HVX_N_H + +/* INDEXED SRCKEY */ +#define COLOR_KEY ctx->key +static void FUNC_NAME_(K,_,DSPF_LUT8) +#include STRETCH_HVX_N_H +#undef COLOR_KEY + +/* INDEXED PROTECT */ +#define KEY_PROTECT ctx->protect +static void FUNC_NAME_(_,P,DSPF_LUT8) +#include STRETCH_HVX_N_H + +/* INDEXED PROTECT SRCKEY */ +#define COLOR_KEY ctx->key +static void FUNC_NAME_(K,P,DSPF_LUT8) +#include STRETCH_HVX_N_H +#undef COLOR_KEY +#undef KEY_PROTECT +#undef SOURCE_LOOKUP +#undef SOURCE_TYPE + + +/* FIXME: DST_FORMAT == DSPF_RGB16 doesn't work */ +#ifdef FORMAT_RGB16 +/* ARGB4444 */ +#define SOURCE_LOOKUP(x) PIXEL_RGB16( (((x) & 0x0f00) >> 4) | (((x) & 0x0f00) >> 8), \ + (((x) & 0x00f0) ) | (((x) & 0x00f0) >> 4), \ + (((x) & 0x000f) << 4) | (((x) & 0x000f) ) ) +static void FUNC_NAME_(_,_,DSPF_ARGB4444) +#include STRETCH_HVX_N_H + +/* ARGB4444 SRCKEY */ +#define COLOR_KEY ctx->key +static void FUNC_NAME_(K,_,DSPF_ARGB4444) +#include STRETCH_HVX_N_H +#undef COLOR_KEY + +/* ARGB4444 PROTECT */ +#define KEY_PROTECT ctx->protect +static void FUNC_NAME_(_,P,DSPF_ARGB4444) +#include STRETCH_HVX_N_H + +/* ARGB4444 PROTECT SRCKEY */ +#define COLOR_KEY ctx->key +static void FUNC_NAME_(K,P,DSPF_ARGB4444) +#include STRETCH_HVX_N_H +#undef COLOR_KEY +#undef KEY_PROTECT +#undef SOURCE_LOOKUP +#undef SOURCE_TYPE +#endif + + +/* FIXME: DST_FORMAT == DSPF_ARGB4444 doesn't work */ +#ifdef FORMAT_ARGB4444 +/* RGB16 */ +#define SOURCE_LOOKUP(x) PIXEL_ARGB4444( 0xff, \ + (((x) & 0xf800) >> 8), \ + (((x) & 0x07e0) >> 3), \ + (((x) & 0x001f) << 3) ) +static void FUNC_NAME_(_,_,DSPF_RGB16) +#include STRETCH_HVX_N_H + +/* RGB16 SRCKEY */ +#define COLOR_KEY ctx->key +static void FUNC_NAME_(K,_,DSPF_RGB16) +#include STRETCH_HVX_N_H +#undef COLOR_KEY + +/* RGB16 PROTECT */ +#define KEY_PROTECT ctx->protect +static void FUNC_NAME_(_,P,DSPF_RGB16) +#include STRETCH_HVX_N_H + +/* RGB16 PROTECT SRCKEY */ +#define COLOR_KEY ctx->key +static void FUNC_NAME_(K,P,DSPF_RGB16) +#include STRETCH_HVX_N_H +#undef COLOR_KEY +#undef KEY_PROTECT +#undef SOURCE_LOOKUP +#undef SOURCE_TYPE +#endif + +#undef FUNC_NAME_ + diff --git a/Source/DirectFB/src/gfx/generic/stretch_up_down_16.h b/Source/DirectFB/src/gfx/generic/stretch_up_down_16.h new file mode 100755 index 0000000..c6e4391 --- /dev/null +++ b/Source/DirectFB/src/gfx/generic/stretch_up_down_16.h @@ -0,0 +1,68 @@ +#define STRETCH_HVX_N_H "stretch_hvx_16.h" +#define uN u16 + +/**********************************************************************************************************************/ +/* Upscaling */ + +#define POINT_0 0 +#define LINE_0 0 +#define MINUS_1 1 +#define POINT_TO_RATIO(p,ps) ( ((p) & 0x3ffff) >> (18-SHIFT_L6) ) +#define LINE_TO_RATIO(l,ls) ( ((l) & 0x3ffff) >> (18-SHIFT_L5) ) + +#define POINT_L(p,ps) ( (((p)) >> 18) ) +#define POINT_R(p,ps) ( (((p)) >> 18) + 1 ) + +#define LINE_T(l,ls) ( (((l)) >> 18) ) +#define LINE_B(l,ls) ( (((l)) >> 18) + 1 ) + +#define UPDOWN 1 +#include "stretch_hvx_N.h" +#undef UPDOWN + +#undef POINT_0 +#undef LINE_0 +#undef MINUS_1 +#undef POINT_TO_RATIO +#undef LINE_TO_RATIO +#undef POINT_L +#undef POINT_R +#undef LINE_T +#undef LINE_B + +/**********************************************************************************************************************/ +/* Downscaling */ + +#define POINT_0 hfraq +#define LINE_0 vfraq +#define MINUS_1 0 +#define POINT_TO_RATIO(p,ps) ( (((((p)) & 0x3ffff) ? : 0x40000) << SHIFT_L6) / (ps) ) +#define LINE_TO_RATIO(l,ls) ( (((((l)) & 0x3ffff) ? : 0x40000) << SHIFT_L5) / (ls) ) + +#define POINT_L(p,ps) ( (((p)-1) >> 18) - 1 ) +#define POINT_R(p,ps) ( (((p)-1) >> 18) ) + +#define LINE_T(l,ls) ( (((l)-1) >> 18) - 1 ) +#define LINE_B(l,ls) ( (((l)-1) >> 18) ) + +#define UPDOWN 0 +#include "stretch_hvx_N.h" +#undef UPDOWN + +#undef POINT_0 +#undef LINE_0 +#undef MINUS_1 +#undef POINT_TO_RATIO +#undef LINE_TO_RATIO +#undef POINT_L +#undef POINT_R +#undef LINE_T +#undef LINE_B + +/**********************************************************************************************************************/ + +#undef STRETCH_HVX_N_H +#undef uN + +#include "stretch_up_down_table.h" + diff --git a/Source/DirectFB/src/gfx/generic/stretch_up_down_32.h b/Source/DirectFB/src/gfx/generic/stretch_up_down_32.h new file mode 100755 index 0000000..3fca697 --- /dev/null +++ b/Source/DirectFB/src/gfx/generic/stretch_up_down_32.h @@ -0,0 +1,68 @@ +#define STRETCH_HVX_N_H "stretch_hvx_32.h" +#define uN u32 + +/**********************************************************************************************************************/ +/* Upscaling */ + +#define POINT_0 0 +#define LINE_0 0 +#define MINUS_1 1 +#define POINT_TO_RATIO(p,ps) ( ((p) & 0x3ffff) >> (18-SHIFT_L8) ) +#define LINE_TO_RATIO(l,ls) ( ((l) & 0x3ffff) >> (18-SHIFT_L8) ) + +#define POINT_L(p,ps) ( (((p)) >> 18) ) +#define POINT_R(p,ps) ( (((p)) >> 18) + 1 ) + +#define LINE_T(l,ls) ( (((l)) >> 18) ) +#define LINE_B(l,ls) ( (((l)) >> 18) + 1 ) + +#define UPDOWN 1 +#include "stretch_hvx_N.h" +#undef UPDOWN + +#undef POINT_0 +#undef LINE_0 +#undef MINUS_1 +#undef POINT_TO_RATIO +#undef LINE_TO_RATIO +#undef POINT_L +#undef POINT_R +#undef LINE_T +#undef LINE_B + +/**********************************************************************************************************************/ +/* Downscaling */ + +#define POINT_0 hfraq +#define LINE_0 vfraq +#define MINUS_1 0 +#define POINT_TO_RATIO(p,ps) ( (((((p)) & 0x3ffff) ? : 0x40000) << SHIFT_L8) / (ps) ) +#define LINE_TO_RATIO(l,ls) ( (((((l)) & 0x3ffff) ? : 0x40000) << SHIFT_L8) / (ls) ) + +#define POINT_L(p,ps) ( (((p)-1) >> 18) - 1 ) +#define POINT_R(p,ps) ( (((p)-1) >> 18) ) + +#define LINE_T(l,ls) ( (((l)-1) >> 18) - 1 ) +#define LINE_B(l,ls) ( (((l)-1) >> 18) ) + +#define UPDOWN 0 +#include "stretch_hvx_N.h" +#undef UPDOWN + +#undef POINT_0 +#undef LINE_0 +#undef MINUS_1 +#undef POINT_TO_RATIO +#undef LINE_TO_RATIO +#undef POINT_L +#undef POINT_R +#undef LINE_T +#undef LINE_B + +/**********************************************************************************************************************/ + +#undef STRETCH_HVX_N_H +#undef uN + +#include "stretch_up_down_table.h" + diff --git a/Source/DirectFB/src/gfx/generic/stretch_up_down_32_indexed.h b/Source/DirectFB/src/gfx/generic/stretch_up_down_32_indexed.h new file mode 100755 index 0000000..655bf98 --- /dev/null +++ b/Source/DirectFB/src/gfx/generic/stretch_up_down_32_indexed.h @@ -0,0 +1,82 @@ +#define SOURCE_LOOKUP(x) (((const u32*)colors)[x]) +#define SOURCE_TYPE u8 + + +#define POINT_0 hfraq +#define LINE_0 vfraq +#define MINUS_1 0 +#define POINT_TO_RATIO(p,ps) ( (((((p)) & 0x3ffff) ? : 0x40000) << SHIFT_L8) / (ps) ) +#define LINE_TO_RATIO(l,ls) ( (((((l)) & 0x3ffff) ? : 0x40000) << SHIFT_L8) / (ls) ) + +#define POINT_L(p,ps) ( (((p)-1) >> 18) - 1 ) +#define POINT_R(p,ps) ( (((p)-1) >> 18) ) + +#define LINE_T(l,ls) ( (((l)-1) >> 18) - 1 ) +#define LINE_B(l,ls) ( (((l)-1) >> 18) ) + +static void FUNC_NAME(down)( void *dst, + int dpitch, + const void *src, + int spitch, + int width, + int height, + int dst_width, + int dst_height, + DFBRegion *clip, + const void *colors ) +{ +#include "stretch_hvx_32.h" +} + +#undef POINT_0 +#undef LINE_0 +#undef MINUS_1 +#undef POINT_TO_RATIO +#undef LINE_TO_RATIO +#undef POINT_L +#undef POINT_R +#undef LINE_T +#undef LINE_B + +/**********************************************************************************************************************/ + +#define POINT_0 0 +#define LINE_0 0 +#define MINUS_1 1 +#define POINT_TO_RATIO(p,ps) ( ((p) & 0x3ffff) >> (18-SHIFT_L8) ) +#define LINE_TO_RATIO(l,ls) ( ((l) & 0x3ffff) >> (18-SHIFT_L8) ) + +#define POINT_L(p,ps) ( (((p)) >> 18) ) +#define POINT_R(p,ps) ( (((p)) >> 18) + 1 ) + +#define LINE_T(l,ls) ( (((l)) >> 18) ) +#define LINE_B(l,ls) ( (((l)) >> 18) + 1 ) + +static void FUNC_NAME(up)( void *dst, + int dpitch, + const void *src, + int spitch, + int width, + int height, + int dst_width, + int dst_height, + DFBRegion *clip, + const void *colors ) +{ +#include "stretch_hvx_32.h" +} + +#undef POINT_0 +#undef LINE_0 +#undef MINUS_1 +#undef POINT_TO_RATIO +#undef LINE_TO_RATIO +#undef POINT_L +#undef POINT_R +#undef LINE_T +#undef LINE_B + + +#undef SOURCE_LOOKUP +#undef SOURCE_TYPE + diff --git a/Source/DirectFB/src/gfx/generic/stretch_up_down_8.h b/Source/DirectFB/src/gfx/generic/stretch_up_down_8.h new file mode 100755 index 0000000..5b43df9 --- /dev/null +++ b/Source/DirectFB/src/gfx/generic/stretch_up_down_8.h @@ -0,0 +1,72 @@ +#define POINT_0 hfraq +#define LINE_0 vfraq +#define MINUS_1 0 +#define POINT_TO_RATIO(p,ps) ( (((((p)) & 0x3ffff) ? : 0x40000) << 8) / (ps) ) +#define LINE_TO_RATIO(l,ls) ( (((((l)) & 0x3ffff) ? : 0x40000) << 8) / (ls) ) + +#define POINT_L(p,ps) ( (((p)-1) >> 18) - 1 ) +#define POINT_R(p,ps) ( (((p)-1) >> 18) ) + +#define LINE_T(l,ls) ( (((l)-1) >> 18) - 1 ) +#define LINE_B(l,ls) ( (((l)-1) >> 18) ) + +static void FUNC_NAME(down)( void *dst, + int dpitch, + const void *src, + int spitch, + int width, + int height, + int dst_width, + int dst_height, + DFBRegion *clip ) +{ +#include "stretch_hvx_8.h" +} + +#undef POINT_0 +#undef LINE_0 +#undef MINUS_1 +#undef POINT_TO_RATIO +#undef LINE_TO_RATIO +#undef POINT_L +#undef POINT_R +#undef LINE_T +#undef LINE_B + +/**********************************************************************************************************************/ + +#define POINT_0 0 +#define LINE_0 0 +#define MINUS_1 1 +#define POINT_TO_RATIO(p,ps) ( ((p) & 0x3ffff) >> (18-8) ) +#define LINE_TO_RATIO(l,ls) ( ((l) & 0x3ffff) >> (18-8) ) + +#define POINT_L(p,ps) ( (((p)) >> 18) ) +#define POINT_R(p,ps) ( (((p)) >> 18) + 1 ) + +#define LINE_T(l,ls) ( (((l)) >> 18) ) +#define LINE_B(l,ls) ( (((l)) >> 18) + 1 ) + +static void FUNC_NAME(up)( void *dst, + int dpitch, + const void *src, + int spitch, + int width, + int height, + int dst_width, + int dst_height, + DFBRegion *clip ) +{ +#include "stretch_hvx_8.h" +} + +#undef POINT_0 +#undef LINE_0 +#undef MINUS_1 +#undef POINT_TO_RATIO +#undef LINE_TO_RATIO +#undef POINT_L +#undef POINT_R +#undef LINE_T +#undef LINE_B + diff --git a/Source/DirectFB/src/gfx/generic/stretch_up_down_88.h b/Source/DirectFB/src/gfx/generic/stretch_up_down_88.h new file mode 100755 index 0000000..a91b6c9 --- /dev/null +++ b/Source/DirectFB/src/gfx/generic/stretch_up_down_88.h @@ -0,0 +1,72 @@ +#define POINT_0 hfraq +#define LINE_0 vfraq +#define MINUS_1 0 +#define POINT_TO_RATIO(p,ps) ( (((((p)) & 0x3ffff) ? : 0x40000) << 8) / (ps) ) +#define LINE_TO_RATIO(l,ls) ( (((((l)) & 0x3ffff) ? : 0x40000) << 8) / (ls) ) + +#define POINT_L(p,ps) ( (((p)-1) >> 18) - 1 ) +#define POINT_R(p,ps) ( (((p)-1) >> 18) ) + +#define LINE_T(l,ls) ( (((l)-1) >> 18) - 1 ) +#define LINE_B(l,ls) ( (((l)-1) >> 18) ) + +static void FUNC_NAME(down)( void *dst, + int dpitch, + const void *src, + int spitch, + int width, + int height, + int dst_width, + int dst_height, + DFBRegion *clip ) +{ +#include "stretch_hvx_88.h" +} + +#undef POINT_0 +#undef LINE_0 +#undef MINUS_1 +#undef POINT_TO_RATIO +#undef LINE_TO_RATIO +#undef POINT_L +#undef POINT_R +#undef LINE_T +#undef LINE_B + +/**********************************************************************************************************************/ + +#define POINT_0 0 +#define LINE_0 0 +#define MINUS_1 1 +#define POINT_TO_RATIO(p,ps) ( ((p) & 0x3ffff) >> (18-8) ) +#define LINE_TO_RATIO(l,ls) ( ((l) & 0x3ffff) >> (18-8) ) + +#define POINT_L(p,ps) ( (((p)) >> 18) ) +#define POINT_R(p,ps) ( (((p)) >> 18) + 1 ) + +#define LINE_T(l,ls) ( (((l)) >> 18) ) +#define LINE_B(l,ls) ( (((l)) >> 18) + 1 ) + +static void FUNC_NAME(up)( void *dst, + int dpitch, + const void *src, + int spitch, + int width, + int height, + int dst_width, + int dst_height, + DFBRegion *clip ) +{ +#include "stretch_hvx_88.h" +} + +#undef POINT_0 +#undef LINE_0 +#undef MINUS_1 +#undef POINT_TO_RATIO +#undef LINE_TO_RATIO +#undef POINT_L +#undef POINT_R +#undef LINE_T +#undef LINE_B + diff --git a/Source/DirectFB/src/gfx/generic/stretch_up_down_table.h b/Source/DirectFB/src/gfx/generic/stretch_up_down_table.h new file mode 100755 index 0000000..32f208b --- /dev/null +++ b/Source/DirectFB/src/gfx/generic/stretch_up_down_table.h @@ -0,0 +1,59 @@ +/**********************************************************************************************************************/ +/* Function table */ + +static const StretchFunctionTable TABLE_NAME = { +#define FUNC_NAME_(K,P,F) FUNC_NAME(up,K,P,F) + .f[DFB_PIXELFORMAT_INDEX(DST_FORMAT)].up[STRETCH_NONE] = FUNC_NAME_(_,_,DST_FORMAT), + .f[DFB_PIXELFORMAT_INDEX(DST_FORMAT)].up[STRETCH_PROTECT] = FUNC_NAME_(_,P,DST_FORMAT), + .f[DFB_PIXELFORMAT_INDEX(DST_FORMAT)].up[STRETCH_SRCKEY] = FUNC_NAME_(K,_,DST_FORMAT), + .f[DFB_PIXELFORMAT_INDEX(DST_FORMAT)].up[STRETCH_SRCKEY_PROTECT] = FUNC_NAME_(K,P,DST_FORMAT), + .f[DFB_PIXELFORMAT_INDEX(DSPF_LUT8)].up[STRETCH_NONE] = FUNC_NAME_(_,_,DSPF_LUT8), + .f[DFB_PIXELFORMAT_INDEX(DSPF_LUT8)].up[STRETCH_PROTECT] = FUNC_NAME_(_,P,DSPF_LUT8), + .f[DFB_PIXELFORMAT_INDEX(DSPF_LUT8)].up[STRETCH_SRCKEY] = FUNC_NAME_(K,_,DSPF_LUT8), + .f[DFB_PIXELFORMAT_INDEX(DSPF_LUT8)].up[STRETCH_SRCKEY_PROTECT] = FUNC_NAME_(K,P,DSPF_LUT8), +#undef FUNC_NAME_ + +#define FUNC_NAME_(K,P,F) FUNC_NAME(down,K,P,F) + .f[DFB_PIXELFORMAT_INDEX(DST_FORMAT)].down[STRETCH_NONE] = FUNC_NAME_(_,_,DST_FORMAT), + .f[DFB_PIXELFORMAT_INDEX(DST_FORMAT)].down[STRETCH_PROTECT] = FUNC_NAME_(_,P,DST_FORMAT), + .f[DFB_PIXELFORMAT_INDEX(DST_FORMAT)].down[STRETCH_SRCKEY] = FUNC_NAME_(K,_,DST_FORMAT), + .f[DFB_PIXELFORMAT_INDEX(DST_FORMAT)].down[STRETCH_SRCKEY_PROTECT] = FUNC_NAME_(K,P,DST_FORMAT), + .f[DFB_PIXELFORMAT_INDEX(DSPF_LUT8)].down[STRETCH_NONE] = FUNC_NAME_(_,_,DSPF_LUT8), + .f[DFB_PIXELFORMAT_INDEX(DSPF_LUT8)].down[STRETCH_PROTECT] = FUNC_NAME_(_,P,DSPF_LUT8), + .f[DFB_PIXELFORMAT_INDEX(DSPF_LUT8)].down[STRETCH_SRCKEY] = FUNC_NAME_(K,_,DSPF_LUT8), + .f[DFB_PIXELFORMAT_INDEX(DSPF_LUT8)].down[STRETCH_SRCKEY_PROTECT] = FUNC_NAME_(K,P,DSPF_LUT8), +#undef FUNC_NAME_ + +/* FIXME: DST_FORMAT == DSPF_RGB16 doesn't work */ +#ifdef FORMAT_RGB16 +#define FUNC_NAME_(K,P,F) FUNC_NAME(up,K,P,F) + .f[DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)].up[STRETCH_NONE] = FUNC_NAME_(_,_,DSPF_ARGB4444), + .f[DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)].up[STRETCH_PROTECT] = FUNC_NAME_(_,P,DSPF_ARGB4444), + .f[DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)].up[STRETCH_SRCKEY] = FUNC_NAME_(K,_,DSPF_ARGB4444), + .f[DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)].up[STRETCH_SRCKEY_PROTECT] = FUNC_NAME_(K,P,DSPF_ARGB4444), +#undef FUNC_NAME_ +#define FUNC_NAME_(K,P,F) FUNC_NAME(down,K,P,F) + .f[DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)].down[STRETCH_NONE] = FUNC_NAME_(_,_,DSPF_ARGB4444), + .f[DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)].down[STRETCH_PROTECT] = FUNC_NAME_(_,P,DSPF_ARGB4444), + .f[DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)].down[STRETCH_SRCKEY] = FUNC_NAME_(K,_,DSPF_ARGB4444), + .f[DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)].down[STRETCH_SRCKEY_PROTECT] = FUNC_NAME_(K,P,DSPF_ARGB4444), +#undef FUNC_NAME_ +#endif + +/* FIXME: DST_FORMAT == DSPF_ARGB4444 doesn't work */ +#ifdef FORMAT_ARGB4444 +#define FUNC_NAME_(K,P,F) FUNC_NAME(up,K,P,F) + .f[DFB_PIXELFORMAT_INDEX(DSPF_RGB16)].up[STRETCH_NONE] = FUNC_NAME_(_,_,DSPF_RGB16), + .f[DFB_PIXELFORMAT_INDEX(DSPF_RGB16)].up[STRETCH_PROTECT] = FUNC_NAME_(_,P,DSPF_RGB16), + .f[DFB_PIXELFORMAT_INDEX(DSPF_RGB16)].up[STRETCH_SRCKEY] = FUNC_NAME_(K,_,DSPF_RGB16), + .f[DFB_PIXELFORMAT_INDEX(DSPF_RGB16)].up[STRETCH_SRCKEY_PROTECT] = FUNC_NAME_(K,P,DSPF_RGB16), +#undef FUNC_NAME_ +#define FUNC_NAME_(K,P,F) FUNC_NAME(down,K,P,F) + .f[DFB_PIXELFORMAT_INDEX(DSPF_RGB16)].down[STRETCH_NONE] = FUNC_NAME_(_,_,DSPF_RGB16), + .f[DFB_PIXELFORMAT_INDEX(DSPF_RGB16)].down[STRETCH_PROTECT] = FUNC_NAME_(_,P,DSPF_RGB16), + .f[DFB_PIXELFORMAT_INDEX(DSPF_RGB16)].down[STRETCH_SRCKEY] = FUNC_NAME_(K,_,DSPF_RGB16), + .f[DFB_PIXELFORMAT_INDEX(DSPF_RGB16)].down[STRETCH_SRCKEY_PROTECT] = FUNC_NAME_(K,P,DSPF_RGB16), +#undef FUNC_NAME_ +#endif +}; + diff --git a/Source/DirectFB/src/gfx/generic/template_acc_16.h b/Source/DirectFB/src/gfx/generic/template_acc_16.h new file mode 100755 index 0000000..05cea6d --- /dev/null +++ b/Source/DirectFB/src/gfx/generic/template_acc_16.h @@ -0,0 +1,382 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* + * Example: + * #define A_SHIFT 15 + * #define R_SHIFT 10 + * #define G_SHIFT 5 + * #define B_SHIFT 0 + * #define A_MASK 0x8000 + * #define R_MASK 0x7c00 + * #define G_MASK 0x03e0 + * #define B_MASK 0x001f + * #define PIXEL_OUT( a, r, g, b ) PIXEL_ARGB1555( a, r, g, b ) + * #define EXPAND_Ato8( a ) EXPAND_1to8( a ) + * #define EXPAND_Rto8( r ) EXPAND_5to8( r ) + * #define EXPAND_Gto8( g ) EXPAND_5to8( g ) + * #define EXPAND_Bto8( b ) EXPAND_5to8( b ) + * #define Sop_PFI_OP_Dacc( op ) Sop_argb1555_##op##_Dacc + * #define Sacc_OP_Aop_PFI( op ) Sacc_##op##_Aop_argb1555 + * #include "template_acc_16.h" + */ + +#define RGB_MASK (R_MASK | G_MASK | B_MASK) + +#if RGB_MASK == 0xffff +#define MASK_RGB( p ) (p) +#else +#define MASK_RGB( p ) ((p) & RGB_MASK) +#endif + +#define PIXEL( x ) PIXEL_OUT( ((x).RGB.a & 0xFF00) ? 0xFF : (x).RGB.a, \ + ((x).RGB.r & 0xFF00) ? 0xFF : (x).RGB.r, \ + ((x).RGB.g & 0xFF00) ? 0xFF : (x).RGB.g, \ + ((x).RGB.b & 0xFF00) ? 0xFF : (x).RGB.b ) + +#define EXPAND( d, s ) do { \ + (d).RGB.a = EXPAND_Ato8( (s & A_MASK) >> A_SHIFT ); \ + (d).RGB.r = EXPAND_Rto8( (s & R_MASK) >> R_SHIFT ); \ + (d).RGB.g = EXPAND_Gto8( (s & G_MASK) >> G_SHIFT ); \ + (d).RGB.b = EXPAND_Bto8( (s & B_MASK) >> B_SHIFT ); \ +} while (0) + +/********************************* Sop_PFI_Sto_Dacc ***************************/ + +static void Sop_PFI_OP_Dacc(Sto)( GenefxState *gfxs ) +{ + int l = gfxs->length; + int i = gfxs->Xphase; + int SperD = gfxs->SperD; + u16 *S = gfxs->Sop[0]; + int Ostep = gfxs->Ostep; + GenefxAccumulator *D = gfxs->Dacc; + + if (Ostep != 1) + D_UNIMPLEMENTED(); + + while (l--) { + u16 s = S[i>>16]; + + EXPAND( *D, s ); + + D++; + i += SperD; + } +} + +/********************************* Sop_PFI_SKto_Dacc **************************/ + +static void Sop_PFI_OP_Dacc(SKto)( GenefxState *gfxs ) +{ + int l = gfxs->length; + int i = gfxs->Xphase; + int SperD = gfxs->SperD; + u16 *S = gfxs->Sop[0]; + int Ostep = gfxs->Ostep; + GenefxAccumulator *D = gfxs->Dacc; + u16 Skey = gfxs->Skey; + + if (Ostep != 1) + D_UNIMPLEMENTED(); + + while (l--) { + u16 s = S[i>>16]; + + if (MASK_RGB( s ) != Skey) + EXPAND( *D, s ); + else + D->RGB.a = 0xF000; + + D++; + i += SperD; + } +} + +/********************************* Sop_PFI_to_Dacc ****************************/ + +static void Sop_PFI_OP_Dacc(to)( GenefxState *gfxs ) +{ + int w, l = gfxs->length; + u16 *S = gfxs->Sop[0]; + GenefxAccumulator *D = gfxs->Dacc; + int Ostep = gfxs->Ostep; + + if (Ostep != 1) { + while (l--) { + u16 s = *S; + + EXPAND( *D, s ); + + S += Ostep; + + D++; + } + return; + } + + if ((long)S & 2) { + u16 s = *S++; + + EXPAND( *D, s ); + + D++; + l--; + } + + w = l >> 1; + while (w--) { + u32 s = *(u32 *) S; + +#ifdef WORDS_BIGENDIAN + EXPAND( D[0], s >> 16 ); + EXPAND( D[1], s ); +#else + EXPAND( D[0], s ); + EXPAND( D[1], s >> 16); +#endif + + S += 2; + D += 2; + } + + if (l & 1) { + u16 s = *S; + + EXPAND( *D, s ); + } +} + +/********************************* Sop_PFI_Kto_Dacc ***************************/ + +static void Sop_PFI_OP_Dacc(Kto)( GenefxState *gfxs ) +{ + int l = gfxs->length; + u16 *S = gfxs->Sop[0]; + GenefxAccumulator *D = gfxs->Dacc; + u16 Skey = gfxs->Skey; + int Ostep = gfxs->Ostep; + + while (l--) { + u16 s = *S; + + if (MASK_RGB( s ) != Skey) + EXPAND( *D, s ); + else + D->RGB.a = 0xF000; + + S += Ostep; + D++; + } +} + +/********************************* Sacc_to_Aop_PFI ****************************/ + +static void Sacc_OP_Aop_PFI(to)( GenefxState *gfxs ) +{ + int w, l = gfxs->length; + GenefxAccumulator *S = gfxs->Sacc; + u16 *D = gfxs->Aop[0]; + int Dstep = gfxs->Astep; + + if (Dstep != 1) { + while (l--) { + if (!(S->RGB.a & 0xF000)) + *D = PIXEL( *S ); + + S++; + D += Dstep; + } + return; + } + + if ((long)D & 2) { + if (!(S->RGB.a & 0xF000)) + *D = PIXEL( *S ); + + S++; + D++; + l--; + } + + w = l >> 1; + while (w--) { + u32 *D2 = (u32 *) D; + + if (!(S[0].RGB.a & 0xF000) && !(S[1].RGB.a & 0xF000)) { +#ifdef WORDS_BIGENDIAN + *D2 = PIXEL( S[1] ) | PIXEL( S[0] ) << 16; +#else + *D2 = PIXEL( S[0] ) | PIXEL( S[1] ) << 16; +#endif + } else { + if (!(S[0].RGB.a & 0xF000)) + D[0] = PIXEL( S[0] ); + else if (!(S[1].RGB.a & 0xF000)) + D[1] = PIXEL( S[1] ); + } + + S += 2; + D += 2; + } + + if (l & 1) { + if (!(S->RGB.a & 0xF000)) + *D = PIXEL( *S ); + } +} + +/********************************* Sacc_Sto_Aop_PFI ***************************/ + +static void Sacc_OP_Aop_PFI(Sto)( GenefxState *gfxs ) +{ + int w, l = gfxs->length; + int i = gfxs->Xphase; + int SperD = gfxs->SperD; + GenefxAccumulator *Sacc = gfxs->Sacc; + u16 *D = gfxs->Aop[0]; + int Dstep = gfxs->Astep; + + if (Dstep != 1) { + while (l--) { + GenefxAccumulator *S = &Sacc[i>>16]; + + if (!(S->RGB.a & 0xF000)) + *D = PIXEL( *S ); + + D += Dstep; + i += SperD; + } + return; + } + if ((long)D & 2) { + GenefxAccumulator *S = Sacc; + + if (!(S->RGB.a & 0xF000)) + *D = PIXEL( *S ); + + D++; + l--; + i += SperD; + } + + w = l >> 1; + while (w--) { + GenefxAccumulator *S0 = &Sacc[i>>16]; + GenefxAccumulator *S1 = &Sacc[(i+SperD)>>16]; + u32 *D2 = (u32 *) D; + + if (!(S0->RGB.a & 0xF000) && !(S1->RGB.a & 0xF000)) { +#ifdef WORDS_BIGENDIAN + *D2 = PIXEL( *S1 ) | PIXEL( *S0 ) << 16; +#else + *D2 = PIXEL( *S0 ) | PIXEL( *S1 ) << 16; +#endif + } else { + if (!(S0->RGB.a & 0xF000)) + D[0] = PIXEL( *S0 ); + else if (!(S1->RGB.a & 0xF000)) + D[1] = PIXEL( *S1 ); + } + + D += 2; + i += SperD << 1; + } + + if (l & 1) { + GenefxAccumulator *S = &Sacc[i>>16]; + + if (!(S->RGB.a & 0xF000)) + *D = PIXEL( *S ); + } +} + +/********************************* Sacc_toK_Aop_PFI ***************************/ + +static void Sacc_OP_Aop_PFI(toK)( GenefxState *gfxs ) +{ + int l = gfxs->length; + GenefxAccumulator *S = gfxs->Sacc; + u16 *D = gfxs->Aop[0]; + u16 Dkey = gfxs->Dkey; + int Dstep = gfxs->Astep; + + while (l--) { + if (!(S->RGB.a & 0xF000) && MASK_RGB( *D ) == Dkey) + *D = PIXEL( *S ); + + S++; + D += Dstep; + } +} + +/********************************* Sacc_StoK_Aop_PFI **************************/ + +static void Sacc_OP_Aop_PFI(StoK)( GenefxState *gfxs ) +{ + int l = gfxs->length; + int i = gfxs->Xphase; + int SperD = gfxs->SperD; + GenefxAccumulator *Sacc = gfxs->Sacc; + u16 *D = gfxs->Aop[0]; + u16 Dkey = gfxs->Dkey; + int Dstep = gfxs->Astep; + + while (l--) { + GenefxAccumulator *S = &Sacc[i>>16]; + + if (!(S->RGB.a & 0xF000) && MASK_RGB( *D ) == Dkey) + *D = PIXEL( *S ); + + D += Dstep; + i += SperD; + } +} + +/******************************************************************************/ + +#undef RGB_MASK +#undef MASK_RGB +#undef PIXEL +#undef EXPAND + +#undef A_SHIFT +#undef R_SHIFT +#undef G_SHIFT +#undef B_SHIFT +#undef A_MASK +#undef R_MASK +#undef G_MASK +#undef B_MASK +#undef PIXEL_OUT +#undef EXPAND_Ato8 +#undef EXPAND_Rto8 +#undef EXPAND_Gto8 +#undef EXPAND_Bto8 +#undef Sop_PFI_OP_Dacc +#undef Sacc_OP_Aop_PFI diff --git a/Source/DirectFB/src/gfx/generic/template_acc_32.h b/Source/DirectFB/src/gfx/generic/template_acc_32.h new file mode 100755 index 0000000..313d568 --- /dev/null +++ b/Source/DirectFB/src/gfx/generic/template_acc_32.h @@ -0,0 +1,261 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* + * Example: + * #define A_SHIFT 24 + * #define R_SHIFT 16 + * #define G_SHIFT 8 + * #define B_SHIFT 0 + * #define A_MASK 0xff000000 + * #define R_MASK 0x00ff0000 + * #define G_MASK 0x0000ff00 + * #define B_MASK 0x000000ff + * #define PIXEL_OUT( a, r, g, b ) PIXEL_AiRGB( a, r, g, b ) + * #define EXPAND_Ato8( a ) ((a) ^ 0xff) + * #define EXPAND_Rto8( r ) (r) + * #define EXPAND_Gto8( g ) (g) + * #define EXPAND_Bto8( b ) (b) + * #define Sop_PFI_OP_Dacc( op ) Sop_airgb_##op##_Dacc + * #define Sacc_OP_Aop_PFI( op ) Sacc_##op##_Aop_airgb + * #include "template_acc_32.h" + */ + +#define RGB_MASK (R_MASK | G_MASK | B_MASK) + +#define PIXEL( s ) PIXEL_OUT( ((s).RGB.a & 0xFF00) ? 0xFF : (s).RGB.a, \ + ((s).RGB.r & 0xFF00) ? 0xFF : (s).RGB.r, \ + ((s).RGB.g & 0xFF00) ? 0xFF : (s).RGB.g, \ + ((s).RGB.b & 0xFF00) ? 0xFF : (s).RGB.b ) + +#define EXPAND( d, s ) \ +do { \ + (d).RGB.a = EXPAND_Ato8( (s & A_MASK) >> A_SHIFT ); \ + (d).RGB.r = EXPAND_Rto8( (s & R_MASK) >> R_SHIFT ); \ + (d).RGB.g = EXPAND_Gto8( (s & G_MASK) >> G_SHIFT ); \ + (d).RGB.b = EXPAND_Bto8( (s & B_MASK) >> B_SHIFT ); \ +} while (0) + +/********************************* Sop_PFI_Sto_Dacc ***************************/ + +static void Sop_PFI_OP_Dacc(Sto)( GenefxState *gfxs ) +{ + int l = gfxs->length; + int i = gfxs->Xphase; + int SperD = gfxs->SperD; + u32 *S = gfxs->Sop[0]; + int Ostep = gfxs->Ostep; + GenefxAccumulator *D = gfxs->Dacc; + + if (Ostep != 1) + D_UNIMPLEMENTED(); + + while (l--) { + u32 s = S[i>>16]; + + EXPAND( *D, s ); + + D++; + i += SperD; + } +} + +/********************************* Sop_PFI_SKto_Dacc **************************/ + +static void Sop_PFI_OP_Dacc(SKto)( GenefxState *gfxs ) +{ + int l = gfxs->length; + int i = gfxs->Xphase; + int SperD = gfxs->SperD; + u32 *S = gfxs->Sop[0]; + int Ostep = gfxs->Ostep; + GenefxAccumulator *D = gfxs->Dacc; + u32 Skey = gfxs->Skey; + + if (Ostep != 1) + D_UNIMPLEMENTED(); + + while (l--) { + u32 s = S[i>>16]; + + if ((s & RGB_MASK) != Skey) + EXPAND( *D, s ); + else + D->RGB.a = 0xF000; + + D++; + i += SperD; + } +} + +/********************************* Sop_PFI_to_Dacc ****************************/ + +static void Sop_PFI_OP_Dacc(to)( GenefxState *gfxs ) +{ + int l = gfxs->length; + u32 *S = gfxs->Sop[0]; + GenefxAccumulator *D = gfxs->Dacc; + int Ostep = gfxs->Ostep; + + while (l--) { + u32 s = *S; + + EXPAND( *D, s ); + + S += Ostep; + + D++; + } +} + +/********************************* Sop_PFI_Kto_Dacc ***************************/ + +static void Sop_PFI_OP_Dacc(Kto)( GenefxState *gfxs ) +{ + int l = gfxs->length; + u32 *S = gfxs->Sop[0]; + GenefxAccumulator *D = gfxs->Dacc; + u32 Skey = gfxs->Skey; + int Ostep = gfxs->Ostep; + + while (l--) { + u32 s = *S; + + if ((s & RGB_MASK) != Skey) + EXPAND( *D, s ); + else + D->RGB.a = 0xF000; + + S += Ostep; + D++; + } +} + +/********************************* Sacc_to_Aop_PFI ****************************/ + +static void Sacc_OP_Aop_PFI(to)( GenefxState *gfxs ) +{ + int l = gfxs->length; + GenefxAccumulator *S = gfxs->Sacc; + u32 *D = gfxs->Aop[0]; + int Dstep = gfxs->Astep; + + while (l--) { + if (!(S->RGB.a & 0xF000)) + *D = PIXEL( *S ); + + S++; + D += Dstep; + } +} + +/********************************* Sacc_Sto_Aop_PFI ***************************/ + +static void Sacc_OP_Aop_PFI(Sto)( GenefxState *gfxs ) +{ + int l = gfxs->length; + int i = gfxs->Xphase; + int SperD = gfxs->SperD; + GenefxAccumulator *Sacc = gfxs->Sacc; + u32 *D = gfxs->Aop[0]; + int Dstep = gfxs->Astep; + + while (l--) { + GenefxAccumulator *S = &Sacc[i>>16]; + + if (!(S->RGB.a & 0xF000)) + *D = PIXEL( *S ); + + D += Dstep; + i += SperD; + } +} + +/********************************* Sacc_toK_Aop_PFI ***************************/ + +static void Sacc_OP_Aop_PFI(toK)( GenefxState *gfxs ) +{ + int l = gfxs->length; + GenefxAccumulator *S = gfxs->Sacc; + u32 *D = gfxs->Aop[0]; + int Dstep = gfxs->Astep; + u32 Dkey = gfxs->Dkey; + + while (l--) { + if (!(S->RGB.a & 0xF000) && (*D & RGB_MASK) == Dkey) + *D = PIXEL( *S ); + + S++; + D += Dstep; + } +} + +/********************************* Sacc_StoK_Aop_PFI **************************/ + +static void Sacc_OP_Aop_PFI(StoK)( GenefxState *gfxs ) +{ + int l = gfxs->length; + int i = gfxs->Xphase; + int SperD = gfxs->SperD; + GenefxAccumulator *Sacc = gfxs->Sacc; + u32 *D = gfxs->Aop[0]; + int Dstep = gfxs->Astep; + u32 Dkey = gfxs->Dkey; + + while (l--) { + GenefxAccumulator *S = &Sacc[i>>16]; + + if (!(S->RGB.a & 0xF000) && (*D & RGB_MASK) == Dkey) + *D = PIXEL( *S ); + + D += Dstep; + i += SperD; + } +} + +/******************************************************************************/ + +#undef RGB_MASK +#undef PIXEL +#undef EXPAND + +#undef A_SHIFT +#undef R_SHIFT +#undef G_SHIFT +#undef B_SHIFT +#undef A_MASK +#undef R_MASK +#undef G_MASK +#undef B_MASK +#undef PIXEL_OUT +#undef EXPAND_Ato8 +#undef EXPAND_Rto8 +#undef EXPAND_Gto8 +#undef EXPAND_Bto8 +#undef Sop_PFI_OP_Dacc +#undef Sacc_OP_Aop_PFI diff --git a/Source/DirectFB/src/gfx/generic/template_colorkey_16.h b/Source/DirectFB/src/gfx/generic/template_colorkey_16.h new file mode 100755 index 0000000..542dad2 --- /dev/null +++ b/Source/DirectFB/src/gfx/generic/template_colorkey_16.h @@ -0,0 +1,369 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* + * Example: + * #define RGB_MASK 0x7fff + * #define Cop_OP_Aop_PFI( op ) Cop_##op##_Aop_15 + * #define Bop_PFI_OP_Aop_PFI( op ) Bop_15_##op##_Aop_15 + * #include "template_ckey_16.h" + */ + +#if RGB_MASK == 0xffff +#define MASK_RGB( p ) (p) +#else +#define MASK_RGB( p ) ((p) & RGB_MASK) +#endif + +#define MASK_RGB_L( p ) ((p) & RGB_MASK) +#define MASK_RGB_H( p ) ((p) & (RGB_MASK << 16)) +#define MASK_RGB_32( p ) ((p) & (RGB_MASK << 16 | RGB_MASK)) + +/********************************* Cop_toK_Aop_PFI ****************************/ + +static void Cop_OP_Aop_PFI(toK)( GenefxState *gfxs ) +{ + int l = gfxs->length; + u16 *D = gfxs->Aop[0]; + u16 Dkey = gfxs->Dkey; + u16 Cop = gfxs->Cop; + + while (l--) { + if (MASK_RGB( *D ) == Dkey) + *D = Cop; + + D++; + } +} + +/********************************* Bop_PFI_Kto_Aop_PFI ************************/ + +static void Bop_PFI_OP_Aop_PFI(Kto)( GenefxState *gfxs ) +{ + int w, l = gfxs->length; + int Ostep = gfxs->Ostep; + u16 *S = gfxs->Bop[0]; + u16 *D = gfxs->Aop[0]; + u16 Skey = gfxs->Skey; + u32 SkeyH = gfxs->Skey << 16; + + /* blit direction */ + if (Ostep < 0) { + S += gfxs->length - 1; + D += gfxs->length - 1; + } + + if (((long)S & 2) != ((long)D & 2)) { + /* source and destination misaligned */ + while (l--) { + u16 s = *S; + + if (MASK_RGB( s ) != Skey) + *D = s; + + S += Ostep; + D += Ostep; + } + + return; + } + + /* fix alignment */ + if (Ostep > 0) { + if ((long)D & 2) { + /* align / leftmost pixel */ + u16 s = *S; + + if (MASK_RGB( s ) != Skey) + *D = s; + + S++; + D++; + l--; + } + } else { /* Ostep < 0 */ + if ((long)D & 2) { + /* align */ + S--; + D--; + } else { + /* rightmost pixel */ + u16 s = *S; + + if (MASK_RGB( s ) != Skey) + *D = s; + + S -= 2; + D -= 2; + l--; + } + } + + /* blit */ + Ostep <<= 1; + w = l >> 1; + while (w--) { + u32 s = *(u32 *) S; + + if (MASK_RGB_L( s ) != Skey) { + if (MASK_RGB_H( s ) != SkeyH) { + *(u32 *) D = s; + } else { +#ifdef WORDS_BIGENDIAN + D[1] = (u16) s; +#else + D[0] = (u16) s; +#endif + } + } else if (MASK_RGB_H( s ) != SkeyH) { +#ifdef WORDS_BIGENDIAN + D[0] = (u16) (s >> 16); +#else + D[1] = (u16) (s >> 16); +#endif + } + + S += Ostep; + D += Ostep; + } + + /* last potential pixel */ + if (l & 1) { + u16 s; + + if (Ostep < 0) { + S++; + D++; + } + + s = *S; + if (MASK_RGB( s ) != Skey) + *D = s; + } +} + +/********************************* Bop_PFI_toK_Aop_PFI ************************/ + +static void Bop_PFI_OP_Aop_PFI(toK)( GenefxState *gfxs ) +{ + int w, l = gfxs->length; + int Ostep = gfxs->Ostep; + u16 *S = gfxs->Bop[0]; + u16 *D = gfxs->Aop[0]; + u16 Dkey = gfxs->Dkey; + u32 DkeyH = gfxs->Dkey << 16; + + /* blit direction */ + if (Ostep < 0) { + S += gfxs->length - 1; + D += gfxs->length - 1; + } + + if (((long)S & 2) != ((long)D & 2)) { + /* source and destination misaligned */ + while (l--) { + if (MASK_RGB( *D ) == Dkey) + *D = *S; + + S += Ostep; + D += Ostep; + } + + return; + } + + /* fix alignment */ + if ((Ostep > 0)) { + if ((long)D & 2) { + /* align / leftmost pixel */ + if (MASK_RGB( *D ) == Dkey) + *D = *S; + + S++; + D++; + l--; + } + } else { /* Ostep < 0 */ + if ((long)D & 2) { + /* align */ + S--; + D--; + } else { + /* rightmost pixel */ + if (MASK_RGB( *D ) == Dkey) + *D = *S; + + S -= 2; + D -= 2; + l--; + } + } + + /* blit */ + Ostep <<= 1; + w = l >> 1; + while (w--) { + u32 d = *(u32 *) D; + + if (MASK_RGB_32( d ) == (DkeyH | Dkey)) { + *(u32 *) D = *(u32 *) S; + } else { + if (MASK_RGB_L( d ) == Dkey) { +#ifdef WORDS_BIGENDIAN + D[0] = S[0]; +#else + D[1] = S[1]; +#endif + } else + if (MASK_RGB_H( d ) == DkeyH) { +#ifdef WORDS_BIGENDIAN + D[1] = S[1]; +#else + D[0] = S[0]; +#endif + } + } + + S += Ostep; + D += Ostep; + } + + /* last potential pixel */ + if (l & 1) { + if (Ostep < 0) { + S++; + D++; + } + + if (MASK_RGB( *D ) == Dkey) + *D = *S; + } +} + +/********************************* Bop_PFI_KtoK_Aop_PFI ***********************/ + +static void Bop_PFI_OP_Aop_PFI(KtoK)( GenefxState *gfxs ) +{ + int l = gfxs->length; + int Ostep = gfxs->Ostep; + u16 *S = gfxs->Bop[0]; + u16 *D = gfxs->Aop[0]; + u16 Skey = gfxs->Skey; + u16 Dkey = gfxs->Dkey; + + if (Ostep < 0) { + S += gfxs->length - 1; + D += gfxs->length - 1; + } + + while (l--) { + u16 s = *S; + + if (MASK_RGB( s ) != Skey && MASK_RGB( *D ) == Dkey) + *D = s; + + S += Ostep; + D += Ostep; + } +} + +/********************************* Bop_PFI_SKto_Aop_PFI ***********************/ + +static void Bop_PFI_OP_Aop_PFI(SKto)( GenefxState *gfxs ) +{ + int l = gfxs->length; + int i = gfxs->Xphase; + int SperD = gfxs->SperD; + u16 *S = gfxs->Bop[0]; + u16 *D = gfxs->Aop[0]; + u16 Skey = gfxs->Skey; + + while (l--) { + u16 s = S[i>>16]; + + if (MASK_RGB( s ) != Skey) + *D = s; + + D++; + i += SperD; + } +} + +/********************************* Bop_PFI_StoK_Aop_PFI ***********************/ + +static void Bop_PFI_OP_Aop_PFI(StoK)( GenefxState *gfxs ) +{ + int l = gfxs->length; + int i = gfxs->Xphase; + int SperD = gfxs->SperD; + u16 *S = gfxs->Bop[0]; + u16 *D = gfxs->Aop[0]; + u16 Dkey = gfxs->Dkey; + + while (l--) { + if (MASK_RGB( *D ) != Dkey) + *D = S[i>>16]; + + D++; + i += SperD; + } +} + +/********************************* Bop_PFI_SKtoK_Aop_PFI **********************/ + +static void Bop_PFI_OP_Aop_PFI(SKtoK)( GenefxState *gfxs ) +{ + int l = gfxs->length; + int i = gfxs->Xphase; + int SperD = gfxs->SperD; + u16 *S = gfxs->Bop[0]; + u16 *D = gfxs->Aop[0]; + u16 Skey = gfxs->Skey; + u16 Dkey = gfxs->Dkey; + + while (l--) { + u16 s = S[i>>16]; + + if (MASK_RGB( s ) != Skey && MASK_RGB( *D ) == Dkey) + *D = s; + + D++; + i += SperD; + } +} + +/******************************************************************************/ + +#undef MASK_RGB +#undef MASK_RGB_L +#undef MASK_RGB_H +#undef MASK_RGB_32 + +#undef RGB_MASK +#undef Cop_OP_Aop_PFI +#undef Bop_PFI_OP_Aop_PFI diff --git a/Source/DirectFB/src/gfx/generic/template_colorkey_32.h b/Source/DirectFB/src/gfx/generic/template_colorkey_32.h new file mode 100755 index 0000000..7771d43 --- /dev/null +++ b/Source/DirectFB/src/gfx/generic/template_colorkey_32.h @@ -0,0 +1,206 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/* + * Example: + * #define RGB_MASK 0x00ffffff + * #define Cop_OP_Aop_PFI( op ) Cop_##op##_Aop_32 + * #define Bop_PFI_OP_Aop_PFI( op ) Bop_32_##op##_Aop_32 + * #include "template_colorkey_32.h" + */ + +/********************************* Cop_toK_Aop_PFI ****************************/ + +static void Cop_OP_Aop_PFI(toK)( GenefxState *gfxs ) +{ + int l = gfxs->length; + u32 *D = gfxs->Aop[0]; + u32 Dkey = gfxs->Dkey; + u32 Cop = gfxs->Cop; + + while (l--) { + if ((*D & RGB_MASK) == Dkey) + *D = Cop; + + D++; + } +} + +/********************************* Bop_PFI_Kto_Aop_PFI ************************/ + +static void Bop_PFI_OP_Aop_PFI(Kto)( GenefxState *gfxs ) +{ + int l = gfxs->length; + int Sstep = gfxs->Bstep; + int Dstep = gfxs->Astep; + u32 *S = gfxs->Bop[0]; + u32 *D = gfxs->Aop[0]; + u32 Skey = gfxs->Skey; + + if (Sstep < 0) { + S += gfxs->length - 1; + D += (gfxs->length - 1) * gfxs->Astep; + } + + while (l--) { + u32 s = *S; + + if ((s & RGB_MASK) != Skey) + *D = s; + + S += Sstep; + D += Dstep; + } +} + +/********************************* Bop_PFI_toK_Aop_PFI ************************/ + +static void Bop_PFI_OP_Aop_PFI(toK)( GenefxState *gfxs ) +{ + int l = gfxs->length; + int Sstep = gfxs->Bstep; + int Dstep = gfxs->Astep; + u32 *S = gfxs->Bop[0]; + u32 *D = gfxs->Aop[0]; + u32 Dkey = gfxs->Dkey; + + if (Sstep < 0) { + S += gfxs->length - 1; + D += (gfxs->length - 1) * gfxs->Astep; + } + + while (l--) { + if ((*D & RGB_MASK) == Dkey) + *D = *S; + + S += Sstep; + D += Dstep; + } +} + +/********************************* Bop_PFI_KtoK_Aop_PFI ***********************/ + +static void Bop_PFI_OP_Aop_PFI(KtoK)( GenefxState *gfxs ) +{ + int l = gfxs->length; + int Sstep = gfxs->Bstep; + int Dstep = gfxs->Astep; + u32 *S = gfxs->Bop[0]; + u32 *D = gfxs->Aop[0]; + u32 Skey = gfxs->Skey; + u32 Dkey = gfxs->Dkey; + + if (Sstep < 0) { + S += gfxs->length - 1; + D += (gfxs->length - 1) * gfxs->Astep; + } + + while (l--) { + u32 s = *S; + + if ((s & RGB_MASK) != Skey && (*D & RGB_MASK) == Dkey) + *D = s; + + S += Sstep; + D += Dstep; + } +} + +/********************************* Bop_PFI_SKto_Aop_PFI ***********************/ + +static void Bop_PFI_OP_Aop_PFI(SKto)( GenefxState *gfxs ) +{ + int l = gfxs->length; + int i = gfxs->Xphase; + int SperD = gfxs->SperD; + u32 *S = gfxs->Bop[0]; + u32 *D = gfxs->Aop[0]; + int Dstep = gfxs->Astep; + u32 Skey = gfxs->Skey; + + while (l--) { + u32 s = S[i>>16]; + + if ((s & RGB_MASK) != Skey) + *D = s; + + D += Dstep; + i += SperD; + } +} + +/********************************* Bop_PFI_StoK_Aop_PFI ***********************/ + +static void Bop_PFI_OP_Aop_PFI(StoK)( GenefxState *gfxs ) +{ + int l = gfxs->length; + int i = gfxs->Xphase; + int SperD = gfxs->SperD; + u32 *S = gfxs->Bop[0]; + u32 *D = gfxs->Aop[0]; + u32 Dkey = gfxs->Dkey; + int Dstep = gfxs->Astep; + + while (l--) { + if ((*D & RGB_MASK) != Dkey) + *D = S[i>>16]; + + D += Dstep; + i += SperD; + } +} + +/********************************* Bop_PFI_SKtoK_Aop_PFI **********************/ + +static void Bop_PFI_OP_Aop_PFI(SKtoK)( GenefxState *gfxs ) +{ + int l = gfxs->length; + int i = gfxs->Xphase; + int SperD = gfxs->SperD; + u32 *S = gfxs->Bop[0]; + u32 *D = gfxs->Aop[0]; + u32 Skey = gfxs->Skey; + u32 Dkey = gfxs->Dkey; + int Dstep = gfxs->Astep; + + while (l--) { + u32 s = S[i>>16]; + + if ((s & RGB_MASK) != Skey && (*D & RGB_MASK) == Dkey) + *D = s; + + D += Dstep; + i += SperD; + } +} + +/******************************************************************************/ + +#undef RGB_MASK +#undef Cop_OP_Aop_PFI +#undef Bop_PFI_OP_Aop_PFI diff --git a/Source/DirectFB/src/gfx/generic/yuvtbl-gen.c b/Source/DirectFB/src/gfx/generic/yuvtbl-gen.c new file mode 100755 index 0000000..43a487d --- /dev/null +++ b/Source/DirectFB/src/gfx/generic/yuvtbl-gen.c @@ -0,0 +1,199 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include +#include +#include +#include + +/* YCbCr->RGB: + * Standard ITU Rec. BT.601 derived coefficients. + */ +#define Y_FACTOR 1.16400 +#define VR_FACTOR 1.59600 +#define VG_FACTOR -0.81300 +#define UG_FACTOR -0.39100 +#define UB_FACTOR 2.01800 + +/* RGB->YCbCr: + * ITU Rec. BT.601 defines the following formula for EyEcbEcr: + * + * Ey = 0.299 * R + 0.587 * G + 0.114 * B + * Ecb = (B - Ey) * 0.564 + * Ecr = (R - Ey) * 0.713 + * + * Relationship between EyEcbEcr and YCbCr: + * + * Y = Ey * 219 / 255 + 16 + * Cb = Ecb * 224 / 255 + 128 + * Cr = Ecr * 224 / 255 + 128 + * + * Therefore, to convert RGB to YCbCr, we compute Ey from R G B, + * then we derive Y Cb Cr from Ey using 3 lookup tables. + */ +#define ECB_FACTOR 0.56400 +#define ECR_FACTOR 0.71300 + + +typedef struct { + const char *type; + const char *name; + int size; + struct { + int min; + int max; + } range; + struct { + int min; + int max; + } clamp; + float sub; + float mul; + float add; +} GenTable; + + +#define N_PER_LINE 10 + +static void +dump_table( GenTable *gt ) +{ + int i, n; + + printf( "\n%s %s[%i] = {\n", gt->type, gt->name, gt->size ); + + for (i = 0, n = 0; i < gt->size; i++) { + float num; + + num = (i < gt->range.min) + ? gt->range.min + : ((i > gt->range.max) ? gt->range.max : i); + num = ((num - gt->sub) * gt->mul) + gt->add; + num = (num < gt->clamp.min) + ? gt->clamp.min + : ((num > gt->clamp.max) ? gt->clamp.max : num); + + if (n == 0) + printf( " " ); + + printf( "%4i", (int) num ); + + if (i < (gt->size-1)) { + if (++n == N_PER_LINE) { + printf( ",\n" ); + n = 0; + } else + printf( ", " ); + } else + printf( "\n" ); + } + + printf( "};\n\n" ); +} + +int +main( int argc, char **argv ) +{ + GenTable gt = { + .size = 256, + .range.min = 16, + .clamp.min = -1000, + .clamp.max = +1000, + }; + + /* headers */ + puts( "#ifndef __YUV_TABLES_H__" ); + puts( "#define __YUV_TABLES_H__" ); + puts( "" ); + +/* YUV->RGB */ + /* luma */ + gt.type = "const u16"; + gt.name = "y_for_rgb"; + gt.range.max = 235; + gt.sub = 16; + gt.mul = Y_FACTOR; + gt.add = 0; + dump_table( > ); + + /* chroma */ + gt.type = "const s16"; + gt.range.max = 240; + gt.sub = 128; + + gt.name = "cr_for_r"; + gt.mul = VR_FACTOR; + dump_table( > ); + + gt.name = "cr_for_g"; + gt.mul = VG_FACTOR; + dump_table( > ); + + gt.name = "cb_for_g"; + gt.mul = UG_FACTOR; + dump_table( > ); + + gt.name = "cb_for_b"; + gt.mul = UB_FACTOR; + dump_table( > ); + +/* RGB->YUV */ + gt.size = 256; + gt.range.min = 0; + gt.range.max = 255; + gt.clamp.min = 16; + gt.sub = 0; + + /* luma */ + gt.type = "const u16"; + gt.name = "y_from_ey"; + gt.clamp.max = 235; + gt.mul = 219.0/255.0; + gt.add = 16; + dump_table( > ); + + /* chroma */ + gt.size = 512; + gt.range.max = 511; + gt.clamp.max = 240; + gt.sub = 255; + gt.add = 128; + + /* cb */ + gt.type = "const u16"; + gt.name = "cb_from_bey"; + gt.mul = ECB_FACTOR * 224.0 / 255.0; + dump_table( > ); + + /* cr */ + gt.type = "const u16"; + gt.name = "cr_from_rey"; + gt.mul = ECR_FACTOR * 224.0 / 255.0; + dump_table( > ); + + /* end headers */ + puts( "#endif /* __YUV_TABLES_H__ */" ); + + return 0; + } diff --git a/Source/DirectFB/src/gfx/generic/yuvtbl.h b/Source/DirectFB/src/gfx/generic/yuvtbl.h new file mode 100755 index 0000000..3769a35 --- /dev/null +++ b/Source/DirectFB/src/gfx/generic/yuvtbl.h @@ -0,0 +1,296 @@ +#ifndef __YUV_TABLES_H__ +#define __YUV_TABLES_H__ + + +const u16 y_for_rgb[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, + 4, 5, 6, 8, 9, 10, 11, 12, 13, 15, + 16, 17, 18, 19, 20, 22, 23, 24, 25, 26, + 27, 29, 30, 31, 32, 33, 34, 36, 37, 38, + 39, 40, 41, 43, 44, 45, 46, 47, 48, 50, + 51, 52, 53, 54, 55, 57, 58, 59, 60, 61, + 62, 64, 65, 66, 67, 68, 69, 71, 72, 73, + 74, 75, 76, 77, 79, 80, 81, 82, 83, 84, + 86, 87, 88, 89, 90, 91, 93, 94, 95, 96, + 97, 98, 100, 101, 102, 103, 104, 105, 107, 108, + 109, 110, 111, 112, 114, 115, 116, 117, 118, 119, + 121, 122, 123, 124, 125, 126, 128, 129, 130, 131, + 132, 133, 135, 136, 137, 138, 139, 140, 142, 143, + 144, 145, 146, 147, 148, 150, 151, 152, 153, 154, + 155, 157, 158, 159, 160, 161, 162, 164, 165, 166, + 167, 168, 169, 171, 172, 173, 174, 175, 176, 178, + 179, 180, 181, 182, 183, 185, 186, 187, 188, 189, + 190, 192, 193, 194, 195, 196, 197, 199, 200, 201, + 202, 203, 204, 206, 207, 208, 209, 210, 211, 213, + 214, 215, 216, 217, 218, 219, 221, 222, 223, 224, + 225, 226, 228, 229, 230, 231, 232, 233, 235, 236, + 237, 238, 239, 240, 242, 243, 244, 245, 246, 247, + 249, 250, 251, 252, 253, 254, 254, 254, 254, 254, + 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, + 254, 254, 254, 254, 254, 254 +}; + + +const s16 cr_for_r[256] = { + -178, -178, -178, -178, -178, -178, -178, -178, -178, -178, + -178, -178, -178, -178, -178, -178, -178, -177, -175, -173, + -172, -170, -169, -167, -165, -164, -162, -161, -159, -158, + -156, -154, -153, -151, -150, -148, -146, -145, -143, -142, + -140, -138, -137, -135, -134, -132, -130, -129, -127, -126, + -124, -122, -121, -119, -118, -116, -114, -113, -111, -110, + -108, -106, -105, -103, -102, -100, -98, -97, -95, -94, + -92, -90, -89, -87, -86, -84, -82, -81, -79, -78, + -76, -75, -73, -71, -70, -68, -67, -65, -63, -62, + -60, -59, -57, -55, -54, -52, -51, -49, -47, -46, + -44, -43, -41, -39, -38, -36, -35, -33, -31, -30, + -28, -27, -25, -23, -22, -20, -19, -17, -15, -14, + -12, -11, -9, -7, -6, -4, -3, -1, 0, 1, + 3, 4, 6, 7, 9, 11, 12, 14, 15, 17, + 19, 20, 22, 23, 25, 27, 28, 30, 31, 33, + 35, 36, 38, 39, 41, 43, 44, 46, 47, 49, + 51, 52, 54, 55, 57, 59, 60, 62, 63, 65, + 67, 68, 70, 71, 73, 75, 76, 78, 79, 81, + 82, 84, 86, 87, 89, 90, 92, 94, 95, 97, + 98, 100, 102, 103, 105, 106, 108, 110, 111, 113, + 114, 116, 118, 119, 121, 122, 124, 126, 127, 129, + 130, 132, 134, 135, 137, 138, 140, 142, 143, 145, + 146, 148, 150, 151, 153, 154, 156, 158, 159, 161, + 162, 164, 165, 167, 169, 170, 172, 173, 175, 177, + 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, + 178, 178, 178, 178, 178, 178 +}; + + +const s16 cr_for_g[256] = { + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 90, 89, 88, + 87, 86, 86, 85, 84, 83, 82, 82, 81, 80, + 79, 78, 78, 77, 76, 75, 74, 73, 73, 72, + 71, 70, 69, 69, 68, 67, 66, 65, 65, 64, + 63, 62, 61, 60, 60, 59, 58, 57, 56, 56, + 55, 54, 53, 52, 52, 51, 50, 49, 48, 47, + 47, 46, 45, 44, 43, 43, 42, 41, 40, 39, + 39, 38, 37, 36, 35, 34, 34, 33, 32, 31, + 30, 30, 29, 28, 27, 26, 26, 25, 24, 23, + 22, 21, 21, 20, 19, 18, 17, 17, 16, 15, + 14, 13, 13, 12, 11, 10, 9, 8, 8, 7, + 6, 5, 4, 4, 3, 2, 1, 0, 0, 0, + -1, -2, -3, -4, -4, -5, -6, -7, -8, -8, + -9, -10, -11, -12, -13, -13, -14, -15, -16, -17, + -17, -18, -19, -20, -21, -21, -22, -23, -24, -25, + -26, -26, -27, -28, -29, -30, -30, -31, -32, -33, + -34, -34, -35, -36, -37, -38, -39, -39, -40, -41, + -42, -43, -43, -44, -45, -46, -47, -47, -48, -49, + -50, -51, -52, -52, -53, -54, -55, -56, -56, -57, + -58, -59, -60, -60, -61, -62, -63, -64, -65, -65, + -66, -67, -68, -69, -69, -70, -71, -72, -73, -73, + -74, -75, -76, -77, -78, -78, -79, -80, -81, -82, + -82, -83, -84, -85, -86, -86, -87, -88, -89, -90, + -91, -91, -91, -91, -91, -91, -91, -91, -91, -91, + -91, -91, -91, -91, -91, -91 +}; + + +const s16 cb_for_g[256] = { + 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 43, 43, 42, + 42, 41, 41, 41, 40, 40, 39, 39, 39, 38, + 38, 37, 37, 37, 36, 36, 35, 35, 35, 34, + 34, 34, 33, 33, 32, 32, 32, 31, 31, 30, + 30, 30, 29, 29, 28, 28, 28, 27, 27, 26, + 26, 26, 25, 25, 25, 24, 24, 23, 23, 23, + 22, 22, 21, 21, 21, 20, 20, 19, 19, 19, + 18, 18, 17, 17, 17, 16, 16, 16, 15, 15, + 14, 14, 14, 13, 13, 12, 12, 12, 11, 11, + 10, 10, 10, 9, 9, 8, 8, 8, 7, 7, + 7, 6, 6, 5, 5, 5, 4, 4, 3, 3, + 3, 2, 2, 1, 1, 1, 0, 0, 0, 0, + 0, -1, -1, -1, -2, -2, -3, -3, -3, -4, + -4, -5, -5, -5, -6, -6, -7, -7, -7, -8, + -8, -8, -9, -9, -10, -10, -10, -11, -11, -12, + -12, -12, -13, -13, -14, -14, -14, -15, -15, -16, + -16, -16, -17, -17, -17, -18, -18, -19, -19, -19, + -20, -20, -21, -21, -21, -22, -22, -23, -23, -23, + -24, -24, -25, -25, -25, -26, -26, -26, -27, -27, + -28, -28, -28, -29, -29, -30, -30, -30, -31, -31, + -32, -32, -32, -33, -33, -34, -34, -34, -35, -35, + -35, -36, -36, -37, -37, -37, -38, -38, -39, -39, + -39, -40, -40, -41, -41, -41, -42, -42, -43, -43, + -43, -43, -43, -43, -43, -43, -43, -43, -43, -43, + -43, -43, -43, -43, -43, -43 +}; + + +const s16 cb_for_b[256] = { + -226, -226, -226, -226, -226, -226, -226, -226, -226, -226, + -226, -226, -226, -226, -226, -226, -226, -223, -221, -219, + -217, -215, -213, -211, -209, -207, -205, -203, -201, -199, + -197, -195, -193, -191, -189, -187, -185, -183, -181, -179, + -177, -175, -173, -171, -169, -167, -165, -163, -161, -159, + -157, -155, -153, -151, -149, -147, -145, -143, -141, -139, + -137, -135, -133, -131, -129, -127, -125, -123, -121, -119, + -117, -115, -113, -110, -108, -106, -104, -102, -100, -98, + -96, -94, -92, -90, -88, -86, -84, -82, -80, -78, + -76, -74, -72, -70, -68, -66, -64, -62, -60, -58, + -56, -54, -52, -50, -48, -46, -44, -42, -40, -38, + -36, -34, -32, -30, -28, -26, -24, -22, -20, -18, + -16, -14, -12, -10, -8, -6, -4, -2, 0, 2, + 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, + 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, + 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, + 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, + 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, + 104, 106, 108, 110, 113, 115, 117, 119, 121, 123, + 125, 127, 129, 131, 133, 135, 137, 139, 141, 143, + 145, 147, 149, 151, 153, 155, 157, 159, 161, 163, + 165, 167, 169, 171, 173, 175, 177, 179, 181, 183, + 185, 187, 189, 191, 193, 195, 197, 199, 201, 203, + 205, 207, 209, 211, 213, 215, 217, 219, 221, 223, + 226, 226, 226, 226, 226, 226, 226, 226, 226, 226, + 226, 226, 226, 226, 226, 226 +}; + + +const u16 y_from_ey[256] = { + 16, 16, 17, 18, 19, 20, 21, 22, 22, 23, + 24, 25, 26, 27, 28, 28, 29, 30, 31, 32, + 33, 34, 34, 35, 36, 37, 38, 39, 40, 40, + 41, 42, 43, 44, 45, 46, 46, 47, 48, 49, + 50, 51, 52, 52, 53, 54, 55, 56, 57, 58, + 58, 59, 60, 61, 62, 63, 64, 64, 65, 66, + 67, 68, 69, 70, 70, 71, 72, 73, 74, 75, + 76, 76, 77, 78, 79, 80, 81, 82, 82, 83, + 84, 85, 86, 87, 88, 89, 89, 90, 91, 92, + 93, 94, 95, 95, 96, 97, 98, 99, 100, 101, + 101, 102, 103, 104, 105, 106, 107, 107, 108, 109, + 110, 111, 112, 113, 113, 114, 115, 116, 117, 118, + 119, 119, 120, 121, 122, 123, 124, 125, 125, 126, + 127, 128, 129, 130, 131, 131, 132, 133, 134, 135, + 136, 137, 137, 138, 139, 140, 141, 142, 143, 143, + 144, 145, 146, 147, 148, 149, 149, 150, 151, 152, + 153, 154, 155, 155, 156, 157, 158, 159, 160, 161, + 162, 162, 163, 164, 165, 166, 167, 168, 168, 169, + 170, 171, 172, 173, 174, 174, 175, 176, 177, 178, + 179, 180, 180, 181, 182, 183, 184, 185, 186, 186, + 187, 188, 189, 190, 191, 192, 192, 193, 194, 195, + 196, 197, 198, 198, 199, 200, 201, 202, 203, 204, + 204, 205, 206, 207, 208, 209, 210, 210, 211, 212, + 213, 214, 215, 216, 216, 217, 218, 219, 220, 221, + 222, 222, 223, 224, 225, 226, 227, 228, 228, 229, + 230, 231, 232, 233, 234, 235 +}; + + +const u16 cb_from_bey[512] = { + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 17, 17, 18, 18, 19, 19, 19, 20, 20, + 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, + 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, + 31, 31, 32, 32, 33, 33, 34, 34, 35, 35, + 36, 36, 37, 37, 38, 38, 39, 39, 40, 40, + 41, 41, 42, 42, 43, 43, 44, 44, 45, 45, + 46, 46, 47, 47, 48, 48, 49, 49, 50, 50, + 51, 51, 52, 52, 53, 53, 54, 54, 55, 55, + 56, 56, 57, 57, 58, 58, 59, 59, 60, 60, + 61, 61, 62, 62, 63, 63, 64, 64, 65, 65, + 66, 66, 67, 67, 68, 68, 69, 69, 70, 70, + 71, 71, 72, 72, 73, 73, 73, 74, 74, 75, + 75, 76, 76, 77, 77, 78, 78, 79, 79, 80, + 80, 81, 81, 82, 82, 83, 83, 84, 84, 85, + 85, 86, 86, 87, 87, 88, 88, 89, 89, 90, + 90, 91, 91, 92, 92, 93, 93, 94, 94, 95, + 95, 96, 96, 97, 97, 98, 98, 99, 99, 100, + 100, 101, 101, 102, 102, 103, 103, 104, 104, 105, + 105, 106, 106, 107, 107, 108, 108, 109, 109, 110, + 110, 111, 111, 112, 112, 113, 113, 114, 114, 115, + 115, 116, 116, 117, 117, 118, 118, 119, 119, 120, + 120, 121, 121, 122, 122, 123, 123, 124, 124, 125, + 125, 126, 126, 127, 127, 128, 128, 128, 129, 129, + 130, 130, 131, 131, 132, 132, 133, 133, 134, 134, + 135, 135, 136, 136, 137, 137, 138, 138, 139, 139, + 140, 140, 141, 141, 142, 142, 143, 143, 144, 144, + 145, 145, 146, 146, 147, 147, 148, 148, 149, 149, + 150, 150, 151, 151, 152, 152, 153, 153, 154, 154, + 155, 155, 156, 156, 157, 157, 158, 158, 159, 159, + 160, 160, 161, 161, 162, 162, 163, 163, 164, 164, + 165, 165, 166, 166, 167, 167, 168, 168, 169, 169, + 170, 170, 171, 171, 172, 172, 173, 173, 174, 174, + 175, 175, 176, 176, 177, 177, 178, 178, 179, 179, + 180, 180, 181, 181, 182, 182, 182, 183, 183, 184, + 184, 185, 185, 186, 186, 187, 187, 188, 188, 189, + 189, 190, 190, 191, 191, 192, 192, 193, 193, 194, + 194, 195, 195, 196, 196, 197, 197, 198, 198, 199, + 199, 200, 200, 201, 201, 202, 202, 203, 203, 204, + 204, 205, 205, 206, 206, 207, 207, 208, 208, 209, + 209, 210, 210, 211, 211, 212, 212, 213, 213, 214, + 214, 215, 215, 216, 216, 217, 217, 218, 218, 219, + 219, 220, 220, 221, 221, 222, 222, 223, 223, 224, + 224, 225, 225, 226, 226, 227, 227, 228, 228, 229, + 229, 230, 230, 231, 231, 232, 232, 233, 233, 234, + 234, 235, 235, 236, 236, 236, 237, 237, 238, 238, + 239, 239, 240, 240, 240, 240, 240, 240, 240, 240, + 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, + 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, + 240, 240 +}; + + +const u16 cr_from_rey[512] = { + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, + 18, 19, 19, 20, 20, 21, 22, 22, 23, 24, + 24, 25, 25, 26, 27, 27, 28, 29, 29, 30, + 30, 31, 32, 32, 33, 34, 34, 35, 35, 36, + 37, 37, 38, 39, 39, 40, 40, 41, 42, 42, + 43, 44, 44, 45, 45, 46, 47, 47, 48, 49, + 49, 50, 50, 51, 52, 52, 53, 54, 54, 55, + 55, 56, 57, 57, 58, 59, 59, 60, 60, 61, + 62, 62, 63, 64, 64, 65, 65, 66, 67, 67, + 68, 69, 69, 70, 71, 71, 72, 72, 73, 74, + 74, 75, 76, 76, 77, 77, 78, 79, 79, 80, + 81, 81, 82, 82, 83, 84, 84, 85, 86, 86, + 87, 87, 88, 89, 89, 90, 91, 91, 92, 92, + 93, 94, 94, 95, 96, 96, 97, 97, 98, 99, + 99, 100, 101, 101, 102, 102, 103, 104, 104, 105, + 106, 106, 107, 107, 108, 109, 109, 110, 111, 111, + 112, 112, 113, 114, 114, 115, 116, 116, 117, 117, + 118, 119, 119, 120, 121, 121, 122, 122, 123, 124, + 124, 125, 126, 126, 127, 128, 128, 129, 129, 130, + 131, 131, 132, 133, 133, 134, 134, 135, 136, 136, + 137, 138, 138, 139, 139, 140, 141, 141, 142, 143, + 143, 144, 144, 145, 146, 146, 147, 148, 148, 149, + 149, 150, 151, 151, 152, 153, 153, 154, 154, 155, + 156, 156, 157, 158, 158, 159, 159, 160, 161, 161, + 162, 163, 163, 164, 164, 165, 166, 166, 167, 168, + 168, 169, 169, 170, 171, 171, 172, 173, 173, 174, + 174, 175, 176, 176, 177, 178, 178, 179, 179, 180, + 181, 181, 182, 183, 183, 184, 184, 185, 186, 186, + 187, 188, 188, 189, 190, 190, 191, 191, 192, 193, + 193, 194, 195, 195, 196, 196, 197, 198, 198, 199, + 200, 200, 201, 201, 202, 203, 203, 204, 205, 205, + 206, 206, 207, 208, 208, 209, 210, 210, 211, 211, + 212, 213, 213, 214, 215, 215, 216, 216, 217, 218, + 218, 219, 220, 220, 221, 221, 222, 223, 223, 224, + 225, 225, 226, 226, 227, 228, 228, 229, 230, 230, + 231, 231, 232, 233, 233, 234, 235, 235, 236, 236, + 237, 238, 238, 239, 240, 240, 240, 240, 240, 240, + 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, + 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, + 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, + 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, + 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, + 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, + 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, + 240, 240 +}; + +#endif /* __YUV_TABLES_H__ */ diff --git a/Source/DirectFB/src/gfx/util.c b/Source/DirectFB/src/gfx/util.c new file mode 100755 index 0000000..9e59b84 --- /dev/null +++ b/Source/DirectFB/src/gfx/util.c @@ -0,0 +1,270 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include + +#include + +#include + +#include + +#include +#include + +#include + +#include + + +static bool copy_state_inited; +static CardState copy_state; + +static bool btf_state_inited; +static CardState btf_state; + +#if FIXME_SC_3 +static bool cd_state_inited; +static CardState cd_state; +#endif + +static pthread_mutex_t copy_lock = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t btf_lock = PTHREAD_MUTEX_INITIALIZER; +#if FIXME_SC_3 +static pthread_mutex_t cd_lock = PTHREAD_MUTEX_INITIALIZER; +#endif + + +void +dfb_gfx_copy( CoreSurface *source, CoreSurface *destination, const DFBRectangle *rect ) +{ + dfb_gfx_copy_to( source, destination, rect, rect ? rect->x : 0, rect ? rect->y : 0, false ); +} + +void +dfb_gfx_copy_to( CoreSurface *source, CoreSurface *destination, const DFBRectangle *rect, int x, int y, bool from_back ) +{ + DFBRectangle sourcerect = { 0, 0, source->config.size.w, source->config.size.h }; + + pthread_mutex_lock( ©_lock ); + + if (!copy_state_inited) { + dfb_state_init( ©_state, NULL ); + copy_state_inited = true; + } + + copy_state.modified |= SMF_CLIP | SMF_SOURCE | SMF_DESTINATION; + + copy_state.clip.x2 = destination->config.size.w - 1; + copy_state.clip.y2 = destination->config.size.h - 1; + copy_state.source = source; + copy_state.destination = destination; + copy_state.from = from_back ? CSBR_BACK : CSBR_FRONT; + + if (rect) { + if (dfb_rectangle_intersect( &sourcerect, rect )) + dfb_gfxcard_blit( &sourcerect, + x + sourcerect.x - rect->x, + y + sourcerect.y - rect->y, ©_state ); + } + else + dfb_gfxcard_blit( &sourcerect, x, y, ©_state ); + + /* Signal end of sequence. */ + dfb_state_stop_drawing( ©_state ); + + pthread_mutex_unlock( ©_lock ); +} + +static void +back_to_front_copy( CoreSurface *surface, const DFBRegion *region, DFBSurfaceBlittingFlags flags, int rotation) +{ + DFBRectangle rect; + int dx, dy; + + if (region) { + rect.x = region->x1; + rect.y = region->y1; + rect.w = region->x2 - region->x1 + 1; + rect.h = region->y2 - region->y1 + 1; + } + else { + rect.x = 0; + rect.y = 0; + rect.w = surface->config.size.w; + rect.h = surface->config.size.h; + } + + dx = rect.x; + dy = rect.y; + + pthread_mutex_lock( &btf_lock ); + + if (!btf_state_inited) { + dfb_state_init( &btf_state, NULL ); + + btf_state.from = CSBR_BACK; + btf_state.to = CSBR_FRONT; + + btf_state_inited = true; + } + + btf_state.modified |= SMF_CLIP | SMF_SOURCE | SMF_DESTINATION; + + btf_state.clip.x2 = surface->config.size.w - 1; + btf_state.clip.y2 = surface->config.size.h - 1; + btf_state.source = surface; + btf_state.destination = surface; + + + if (rotation == 90) { + dx = rect.y; + dy = surface->config.size.w - rect.w - rect.x; + + flags |= DSBLIT_ROTATE90; + } + else if (rotation == 180) { + dx = surface->config.size.w - rect.w - rect.x; + dy = surface->config.size.h - rect.h - rect.y; + + flags |= DSBLIT_ROTATE180; + } + else if (rotation == 270) { + dx = surface->config.size.h - rect.h - rect.y; + dy = rect.x; + + flags |= DSBLIT_ROTATE270; + } + + + dfb_state_set_blitting_flags( &btf_state, flags ); + + dfb_gfxcard_blit( &rect, dx, dy, &btf_state ); + + /* Signal end of sequence. */ + dfb_state_stop_drawing( &btf_state ); + + pthread_mutex_unlock( &btf_lock ); +} + +void +dfb_back_to_front_copy( CoreSurface *surface, const DFBRegion *region ) +{ + back_to_front_copy( surface, region, DSBLIT_NOFX, 0); +} + +void +dfb_back_to_front_copy_rotation( CoreSurface *surface, const DFBRegion *region, int rotation ) +{ + back_to_front_copy( surface, region, DSBLIT_NOFX, rotation ); +} + +void +dfb_clear_depth( CoreSurface *surface, const DFBRegion *region ) +{ +#if FIXME_SC_3 + SurfaceBuffer *tmp; + DFBRectangle rect = { 0, 0, surface->config.size.w - 1, surface->config.size.h - 1 }; + + if (region && !dfb_rectangle_intersect_by_region( &rect, region )) + return; + + pthread_mutex_lock( &cd_lock ); + + if (!cd_state_inited) { + dfb_state_init( &cd_state, NULL ); + + cd_state.color.r = 0xff; + cd_state.color.g = 0xff; + cd_state.color.b = 0xff; + + cd_state_inited = true; + } + + cd_state.modified |= SMF_CLIP | SMF_DESTINATION; + + cd_state.clip.x2 = surface->config.size.w - 1; + cd_state.clip.y2 = surface->config.size.h - 1; + cd_state.destination = surface; + + dfb_surfacemanager_lock( surface->manager ); + + tmp = surface->back_buffer; + surface->back_buffer = surface->depth_buffer; + + dfb_gfxcard_fillrectangles( &rect, 1, &cd_state ); + + surface->back_buffer = tmp; + + dfb_surfacemanager_unlock( surface->manager ); + + /* Signal end of sequence. */ + dfb_state_stop_drawing( &cd_state ); + + pthread_mutex_unlock( &cd_lock ); +#endif +} + + +void dfb_sort_triangle( DFBTriangle *tri ) +{ + int temp; + + if (tri->y1 > tri->y2) { + temp = tri->x1; + tri->x1 = tri->x2; + tri->x2 = temp; + + temp = tri->y1; + tri->y1 = tri->y2; + tri->y2 = temp; + } + + if (tri->y2 > tri->y3) { + temp = tri->x2; + tri->x2 = tri->x3; + tri->x3 = temp; + + temp = tri->y2; + tri->y2 = tri->y3; + tri->y3 = temp; + } + + if (tri->y1 > tri->y2) { + temp = tri->x1; + tri->x1 = tri->x2; + tri->x2 = temp; + + temp = tri->y1; + tri->y1 = tri->y2; + tri->y2 = temp; + } +} + diff --git a/Source/DirectFB/src/gfx/util.h b/Source/DirectFB/src/gfx/util.h new file mode 100755 index 0000000..79cbd6d --- /dev/null +++ b/Source/DirectFB/src/gfx/util.h @@ -0,0 +1,42 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __GFX__UTIL_H__ +#define __GFX__UTIL_H__ + +#include + +void dfb_gfx_copy( CoreSurface *source, CoreSurface *destination, const DFBRectangle *rect ); +void dfb_gfx_copy_to( CoreSurface *source, CoreSurface *destination, const DFBRectangle *rect, int x, int y, bool from_back ); +void dfb_back_to_front_copy( CoreSurface *surface, const DFBRegion *region ); +void dfb_back_to_front_copy_rotation( CoreSurface *surface, const DFBRegion *region, int rotation ); +void dfb_clear_depth( CoreSurface *surface, const DFBRegion *region ); + +void dfb_sort_triangle( DFBTriangle *tri ); + +#endif diff --git a/Source/DirectFB/src/idirectfb.c b/Source/DirectFB/src/idirectfb.c new file mode 100755 index 0000000..144eaad --- /dev/null +++ b/Source/DirectFB/src/idirectfb.c @@ -0,0 +1,1965 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* FIXME */ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include + +D_DEBUG_DOMAIN( IDFB, "IDirectFB", "DirectFB Main Interface" ); + +/**********************************************************************************************************************/ + +typedef struct { + DFBScreenCallback callback; + void *callback_ctx; +} EnumScreens_Context; + +typedef struct { + IDirectFBScreen **interface; + DFBScreenID id; + DFBResult ret; +} GetScreen_Context; + +typedef struct { + DFBDisplayLayerCallback callback; + void *callback_ctx; +} EnumDisplayLayers_Context; + +typedef struct { + IDirectFBDisplayLayer **interface; + DFBDisplayLayerID id; + DFBResult ret; + CoreDFB *core; +} GetDisplayLayer_Context; + +typedef struct { + DFBInputDeviceCallback callback; + void *callback_ctx; +} EnumInputDevices_Context; + +typedef struct { + IDirectFBInputDevice **interface; + DFBInputDeviceID id; + DFBResult ret; +} GetInputDevice_Context; + +typedef struct { + IDirectFBEventBuffer **interface; + DFBInputDeviceCapabilities caps; +} CreateEventBuffer_Context; + +/**********************************************************************************************************************/ + +static DFBEnumerationResult EnumScreens_Callback ( CoreScreen *screen, + void *ctx ); +static DFBEnumerationResult GetScreen_Callback ( CoreScreen *screen, + void *ctx ); + +static DFBEnumerationResult EnumDisplayLayers_Callback( CoreLayer *layer, + void *ctx ); +static DFBEnumerationResult GetDisplayLayer_Callback ( CoreLayer *layer, + void *ctx ); + +static DFBEnumerationResult EnumInputDevices_Callback ( CoreInputDevice *device, + void *ctx ); +static DFBEnumerationResult GetInputDevice_Callback ( CoreInputDevice *device, + void *ctx ); + +static DFBEnumerationResult CreateEventBuffer_Callback( CoreInputDevice *device, + void *ctx ); + +static ReactionResult focus_listener( const void *msg_data, + void *ctx ); + +static bool input_filter_local( DFBEvent *evt, + void *ctx ); + +static bool input_filter_global( DFBEvent *evt, + void *ctx ); + +static void drop_window( IDirectFB_data *data ); + +/**********************************************************************************************************************/ + +/* + * Destructor + * + * Free data structure and set the pointer to NULL, + * to indicate the dead interface. + */ +void +IDirectFB_Destruct( IDirectFB *thiz ) +{ + int i; + IDirectFB_data *data = (IDirectFB_data*)thiz->priv; + + D_DEBUG_AT( IDFB, "%s( %p )\n", __FUNCTION__, thiz ); + + drop_window( data ); + + if (data->primary.context) + dfb_layer_context_unref( data->primary.context ); + + dfb_layer_context_unref( data->context ); + + for (i=0; ilayers[i].context) { + if (data->layers[i].palette) + dfb_palette_unref( data->layers[i].palette ); + + dfb_surface_unref( data->layers[i].surface ); + dfb_layer_region_unref( data->layers[i].region ); + dfb_layer_context_unref( data->layers[i].context ); + } + } + + dfb_core_destroy( data->core, false ); + + idirectfb_singleton = NULL; + + DIRECT_DEALLOCATE_INTERFACE( thiz ); + + direct_shutdown(); +} + + +static DirectResult +IDirectFB_AddRef( IDirectFB *thiz ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFB) + + D_DEBUG_AT( IDFB, "%s( %p )\n", __FUNCTION__, thiz ); + + data->ref++; + + return DFB_OK; +} + +static DirectResult +IDirectFB_Release( IDirectFB *thiz ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFB) + + D_DEBUG_AT( IDFB, "%s( %p )\n", __FUNCTION__, thiz ); + + if (--data->ref == 0) + IDirectFB_Destruct( thiz ); + + return DFB_OK; +} + +static DFBResult +IDirectFB_SetCooperativeLevel( IDirectFB *thiz, + DFBCooperativeLevel level ) +{ + DFBResult ret; + CoreLayerContext *context; + + DIRECT_INTERFACE_GET_DATA(IDirectFB) + + D_DEBUG_AT( IDFB, "%s( %p, %d )\n", __FUNCTION__, thiz, level ); + + if (level == data->level) + return DFB_OK; + + switch (level) { + case DFSCL_NORMAL: + data->primary.focused = false; + + dfb_layer_context_unref( data->primary.context ); + + data->primary.context = NULL; + break; + + case DFSCL_FULLSCREEN: + case DFSCL_EXCLUSIVE: + if (dfb_config->force_windowed || dfb_config->force_desktop) + return DFB_ACCESSDENIED; + + if (data->level == DFSCL_NORMAL) { + ret = dfb_layer_create_context( data->layer, &context ); + if (ret) + return ret; + + ret = dfb_layer_activate_context( data->layer, context ); + if (ret) { + dfb_layer_context_unref( context ); + return ret; + } + + drop_window( data ); + + data->primary.context = context; + } + + data->primary.focused = true; + break; + + default: + return DFB_INVARG; + } + + data->level = level; + + return DFB_OK; +} + +static DFBResult +IDirectFB_GetDeviceDescription( IDirectFB *thiz, + DFBGraphicsDeviceDescription *ret_desc ) +{ + GraphicsDeviceInfo device_info; + GraphicsDriverInfo driver_info; + + DIRECT_INTERFACE_GET_DATA(IDirectFB) + + D_DEBUG_AT( IDFB, "%s( %p )\n", __FUNCTION__, thiz ); + + if (!ret_desc) + return DFB_INVARG; + + dfb_gfxcard_get_device_info( &device_info ); + dfb_gfxcard_get_driver_info( &driver_info ); + + ret_desc->acceleration_mask = device_info.caps.accel; + ret_desc->blitting_flags = device_info.caps.blitting; + ret_desc->drawing_flags = device_info.caps.drawing; + ret_desc->video_memory = dfb_gfxcard_memory_length(); + + snprintf( ret_desc->name, DFB_GRAPHICS_DEVICE_DESC_NAME_LENGTH, device_info.name ); + snprintf( ret_desc->vendor, DFB_GRAPHICS_DEVICE_DESC_NAME_LENGTH, device_info.vendor ); + + ret_desc->driver.major = driver_info.version.major; + ret_desc->driver.minor = driver_info.version.minor; + + snprintf( ret_desc->driver.name, DFB_GRAPHICS_DRIVER_INFO_NAME_LENGTH, driver_info.name ); + snprintf( ret_desc->driver.vendor, DFB_GRAPHICS_DRIVER_INFO_VENDOR_LENGTH, driver_info.vendor ); + + return DFB_OK; +} + +static DFBResult +IDirectFB_EnumVideoModes( IDirectFB *thiz, + DFBVideoModeCallback callbackfunc, + void *callbackdata ) +{ + VideoMode *m; + + DIRECT_INTERFACE_GET_DATA(IDirectFB) + + D_DEBUG_AT( IDFB, "%s( %p, %p, %p )\n", __FUNCTION__, thiz, callbackfunc, callbackdata ); + + if (!callbackfunc) + return DFB_INVARG; + + m = dfb_system_modes(); + while (m) { + if (callbackfunc( m->xres, m->yres, + m->bpp, callbackdata ) == DFENUM_CANCEL) + break; + + m = m->next; + } + + return DFB_OK; +} + +static DFBResult +IDirectFB_SetVideoMode( IDirectFB *thiz, + int width, + int height, + int bpp ) +{ + DFBResult ret; + DFBSurfacePixelFormat format; + + DIRECT_INTERFACE_GET_DATA(IDirectFB) + + D_DEBUG_AT( IDFB, "%s( %p, %dx%d %dbit )\n", __FUNCTION__, thiz, width, height, bpp ); + + if (width < 1 || height < 1 || bpp < 1) + return DFB_INVARG; + + format = dfb_pixelformat_for_depth( bpp ); + if (format == DSPF_UNKNOWN) + return DFB_INVARG; + + switch (data->level) { + case DFSCL_NORMAL: + if (data->primary.window) { + ret = dfb_window_resize( data->primary.window, width, height ); + if (ret) + return ret; + } + break; + + case DFSCL_FULLSCREEN: + case DFSCL_EXCLUSIVE: { + DFBResult ret; + DFBDisplayLayerConfig config; + + config.flags = DLCONF_WIDTH | DLCONF_HEIGHT | + DLCONF_PIXELFORMAT; + config.width = width; + config.height = height; + config.pixelformat = format; + + ret = dfb_layer_context_set_configuration( data->primary.context, + &config ); + if (ret) + return ret; + + break; + } + } + + data->primary.width = width; + data->primary.height = height; + data->primary.format = format; + + return DFB_OK; +} + +static void +init_palette( CoreSurface *surface, const DFBSurfaceDescription *desc ) +{ + int num; + CorePalette *palette = surface->palette; + + if (!palette || !(desc->flags & DSDESC_PALETTE)) + return; + + num = MIN( desc->palette.size, palette->num_entries ); + + direct_memcpy( palette->entries, desc->palette.entries, num * sizeof(DFBColor)); + + dfb_palette_update( palette, 0, num - 1 ); +} + +static DFBResult +IDirectFB_CreateSurface( IDirectFB *thiz, + const DFBSurfaceDescription *desc, + IDirectFBSurface **interface ) +{ + IDirectFBSurface *iface; + DFBResult ret; + int width = 256; + int height = 256; + DFBSurfacePixelFormat format; + DFBSurfaceCapabilities caps = DSCAPS_NONE; + CoreSurface *surface = NULL; + unsigned long resource_id = 0; + DFBDisplayLayerConfig config; + + DIRECT_INTERFACE_GET_DATA(IDirectFB) + + D_DEBUG_AT( IDFB, "%s( %p )\n", __FUNCTION__, thiz ); + + if (data->primary.context) + dfb_layer_context_get_configuration( data->primary.context, &config ); + else + dfb_layer_context_get_configuration( data->context, &config ); + + if (desc->flags & DSDESC_HINTS && desc->hints & DSHF_FONT) { + format = dfb_config->font_format; + + if (dfb_config->font_premult) + caps = DSCAPS_PREMULTIPLIED; + } + else + format = config.pixelformat; + + if (!desc || !interface) + return DFB_INVARG; + + D_DEBUG_AT( IDFB, " -> flags 0x%08x\n", desc->flags ); + + if (desc->flags & DSDESC_WIDTH) { + D_DEBUG_AT( IDFB, " -> width %d\n", desc->width ); + + width = desc->width; + if (width < 1 || width > 20480) + return DFB_INVARG; + } + + if (desc->flags & DSDESC_HEIGHT) { + D_DEBUG_AT( IDFB, " -> height %d\n", desc->height ); + + height = desc->height; + if (height < 1 || height > 20480) + return DFB_INVARG; + } + + if (desc->flags & DSDESC_PALETTE) + if (!desc->palette.entries || !desc->palette.size) + return DFB_INVARG; + + if (desc->flags & DSDESC_CAPS) { + D_DEBUG_AT( IDFB, " -> caps 0x%08x\n", desc->caps ); + + caps = desc->caps; + } + + if (desc->flags & DSDESC_PIXELFORMAT) { + D_DEBUG_AT( IDFB, " -> format %s\n", dfb_pixelformat_name(desc->pixelformat) ); + + format = desc->pixelformat; + } + + if (desc->flags & DSDESC_RESOURCE_ID) + resource_id = desc->resource_id; + + switch (format) { + case DSPF_A1: + case DSPF_A4: + case DSPF_A8: + case DSPF_ARGB: + case DSPF_ARGB1555: + case DSPF_ARGB1666: + case DSPF_ARGB6666: + case DSPF_ARGB2554: + case DSPF_ARGB4444: + case DSPF_RGBA4444: + case DSPF_AYUV: + case DSPF_AiRGB: + case DSPF_I420: + case DSPF_LUT2: + case DSPF_LUT8: + case DSPF_ALUT44: + case DSPF_RGB16: + case DSPF_RGB18: + case DSPF_RGB24: + case DSPF_RGB32: + case DSPF_RGB332: + case DSPF_UYVY: + case DSPF_YUY2: + case DSPF_YV12: + case DSPF_NV12: + case DSPF_NV21: + case DSPF_NV16: + case DSPF_RGB444: + case DSPF_RGB555: + case DSPF_BGR555: + break; + + default: + return DFB_INVARG; + } + + if (caps & DSCAPS_PRIMARY) { + if (desc->flags & DSDESC_PREALLOCATED) + return DFB_INVARG; + + if (desc->flags & DSDESC_PIXELFORMAT) + format = desc->pixelformat; + else if (data->primary.format) + format = data->primary.format; + else if (dfb_config->mode.format) + format = dfb_config->mode.format; + else + format = config.pixelformat; + + if (desc->flags & DSDESC_WIDTH) + width = desc->width; + else if (data->primary.width) + width = data->primary.width; + else if (dfb_config->mode.width) + width = dfb_config->mode.width; + else + width = config.width; + + if (desc->flags & DSDESC_HEIGHT) + height = desc->height; + else if (data->primary.height) + height = data->primary.height; + else if (dfb_config->mode.height) + height = dfb_config->mode.height; + else + height = config.height; + + /* FIXME: should we allow to create more primaries in windowed mode? + should the primary surface be a singleton? + or should we return an error? */ + switch (data->level) { + case DFSCL_NORMAL: + if (dfb_config->force_desktop) { + CoreSurface *surface; + + /* Source compatibility with older programs */ + if ((caps & DSCAPS_FLIPPING) == DSCAPS_FLIPPING) + caps &= ~DSCAPS_TRIPLE; + + ret = dfb_surface_create_simple( data->core, + width, height, + format, caps, + CSTF_SHARED, resource_id, + NULL, &surface ); + if (ret) + return ret; + + surface->notifications |= CSNF_FLIP; + + init_palette( surface, desc ); + + DIRECT_ALLOCATE_INTERFACE( iface, IDirectFBSurface ); + + ret = IDirectFBSurface_Construct( iface, NULL, + NULL, NULL, NULL, surface, caps, data->core ); + if (ret == DFB_OK) { + dfb_windowstack_set_background_image( data->stack, surface ); + dfb_windowstack_set_background_mode( data->stack, DLBM_IMAGE ); + } + + dfb_surface_unref( surface ); + + if (!ret) + *interface = iface; + + return ret; + } + else { + CoreWindow *window; + DFBWindowDescription wd; + + if ((caps & DSCAPS_FLIPPING) == DSCAPS_TRIPLE) + return DFB_UNSUPPORTED; + + memset( &wd, 0, sizeof(wd) ); + + wd.flags = DWDESC_POSX | DWDESC_POSY | DWDESC_WIDTH | DWDESC_HEIGHT | + DWDESC_PIXELFORMAT | DWDESC_SURFACE_CAPS | DWDESC_CAPS | DWDESC_RESOURCE_ID; + + if (dfb_config->scaled.width && dfb_config->scaled.height) { + wd.posx = (config.width - dfb_config->scaled.width) / 2; + wd.posy = (config.height - dfb_config->scaled.height) / 2; + } + else { + wd.posx = (config.width - width) / 2; + wd.posy = (config.height - height) / 2; + } + + wd.width = width; + wd.height = height; + wd.pixelformat = format; + wd.surface_caps = caps & ~DSCAPS_FLIPPING; + wd.resource_id = resource_id; + + switch (format) { + case DSPF_ARGB4444: + case DSPF_RGBA4444: + case DSPF_ARGB2554: + case DSPF_ARGB1555: + case DSPF_ARGB: + case DSPF_AYUV: + case DSPF_AiRGB: + wd.caps |= DWCAPS_ALPHACHANNEL; + break; + + default: + break; + } + + if ((caps & DSCAPS_FLIPPING) == DSCAPS_DOUBLE) + wd.caps |= DWCAPS_DOUBLEBUFFER; + + ret = dfb_layer_context_create_window( data->core, data->context, &wd, &window ); + if (ret) + return ret; + + drop_window( data ); + + data->primary.window = window; + + dfb_window_attach( window, focus_listener, + data, &data->primary.reaction ); + + dfb_window_change_options( window, DWOP_NONE, DWOP_SCALE ); + if (dfb_config->scaled.width && dfb_config->scaled.height) + dfb_window_resize( window, dfb_config->scaled.width, + dfb_config->scaled.height ); + + init_palette( window->surface, desc ); + + DIRECT_ALLOCATE_INTERFACE( iface, IDirectFBSurface ); + + ret = IDirectFBSurface_Window_Construct( iface, NULL, + NULL, NULL, window, + caps, data->core ); + + if (!ret) + *interface = iface; + + return ret; + } + case DFSCL_FULLSCREEN: + case DFSCL_EXCLUSIVE: { + CoreLayerRegion *region; + CoreLayerContext *context = data->primary.context; + + config.flags |= DLCONF_BUFFERMODE | DLCONF_PIXELFORMAT | + DLCONF_WIDTH | DLCONF_HEIGHT; + + /* Source compatibility with older programs */ + if ((caps & DSCAPS_FLIPPING) == DSCAPS_FLIPPING) + caps &= ~DSCAPS_TRIPLE; + + if (caps & DSCAPS_PREMULTIPLIED) { + config.flags |= DLCONF_SURFACE_CAPS; + config.surface_caps = DSCAPS_PREMULTIPLIED; + } + + if (caps & DSCAPS_TRIPLE) { + if (caps & DSCAPS_SYSTEMONLY) + return DFB_UNSUPPORTED; + config.buffermode = DLBM_TRIPLE; + } else if (caps & DSCAPS_DOUBLE) { + if (caps & DSCAPS_SYSTEMONLY) + config.buffermode = DLBM_BACKSYSTEM; + else + config.buffermode = DLBM_BACKVIDEO; + } + else + config.buffermode = DLBM_FRONTONLY; + + config.pixelformat = format; + config.width = width; + config.height = height; + + ret = dfb_layer_context_set_configuration( context, &config ); + if (ret) { + if (!(caps & (DSCAPS_SYSTEMONLY | DSCAPS_VIDEOONLY)) && + config.buffermode == DLBM_BACKVIDEO) { + config.buffermode = DLBM_BACKSYSTEM; + + ret = dfb_layer_context_set_configuration( context, &config ); + if (ret) + return ret; + } + else + return ret; + } + + ret = dfb_layer_context_get_primary_region( context, true, + ®ion ); + if (ret) + return ret; + + ret = dfb_layer_region_get_surface( region, &surface ); + if (ret) { + dfb_layer_region_unref( region ); + return ret; + } + +/* FIXME_SC_3 if ((caps & DSCAPS_DEPTH) && !(surface->config.caps & DSCAPS_DEPTH)) { + ret = dfb_surface_allocate_depth( surface ); + if (ret) { + dfb_surface_unref( surface ); + dfb_layer_region_unref( region ); + return ret; + } + } + else if (!(caps & DSCAPS_DEPTH) && (surface->config.caps & DSCAPS_DEPTH)) { + dfb_surface_deallocate_depth( surface ); + } +*/ + + init_palette( surface, desc ); + + DIRECT_ALLOCATE_INTERFACE( iface, IDirectFBSurface ); + + ret = IDirectFBSurface_Layer_Construct( iface, NULL, + NULL, NULL, region, caps, data->core ); + + dfb_surface_unref( surface ); + dfb_layer_region_unref( region ); + + if (!ret) + *interface = iface; + + return ret; + } + } + } + + /* Source compatibility with older programs */ + if ((caps & DSCAPS_FLIPPING) == DSCAPS_FLIPPING) + caps &= ~DSCAPS_TRIPLE; + + if (caps & DSCAPS_TRIPLE) + return DFB_UNSUPPORTED; + + if (desc->flags & DSDESC_PREALLOCATED) { + int min_pitch; + CoreSurfaceConfig config; + + if (caps & DSCAPS_VIDEOONLY) + return DFB_INVARG; + + min_pitch = DFB_BYTES_PER_LINE(format, width); + + if (!desc->preallocated[0].data || + desc->preallocated[0].pitch < min_pitch) + { + return DFB_INVARG; + } + + if ((caps & DSCAPS_DOUBLE) && + (!desc->preallocated[1].data || + desc->preallocated[1].pitch < min_pitch)) + { + return DFB_INVARG; + } + + config.flags = CSCONF_SIZE | CSCONF_FORMAT | CSCONF_CAPS | CSCONF_PREALLOCATED; + config.size.w = width; + config.size.h = height; + config.format = format; + config.caps = caps; + + config.preallocated[0].addr = desc->preallocated[0].data; + config.preallocated[0].pitch = desc->preallocated[0].pitch; + + config.preallocated[1].addr = desc->preallocated[1].data; + config.preallocated[1].pitch = desc->preallocated[1].pitch; + + ret = dfb_surface_create( data->core, &config, CSTF_PREALLOCATED, resource_id, NULL, &surface ); + if (ret) + return ret; + } + else { + CoreSurfaceConfig config; + + config.flags = CSCONF_SIZE | CSCONF_FORMAT | CSCONF_CAPS; + config.size.w = width; + config.size.h = height; + config.format = format; + config.caps = caps; + + ret = dfb_surface_create( data->core, &config, CSTF_NONE, resource_id, NULL, &surface ); + if (ret) + return ret; + } + + init_palette( surface, desc ); + + DIRECT_ALLOCATE_INTERFACE( iface, IDirectFBSurface ); + + ret = IDirectFBSurface_Construct( iface, NULL, + NULL, NULL, NULL, surface, caps, data->core ); + + dfb_surface_unref( surface ); + + if (!ret) + *interface = iface; + + return ret; +} + +static DFBResult +IDirectFB_CreatePalette( IDirectFB *thiz, + const DFBPaletteDescription *desc, + IDirectFBPalette **interface ) +{ + DFBResult ret; + IDirectFBPalette *iface; + unsigned int size = 256; + CorePalette *palette = NULL; + + DIRECT_INTERFACE_GET_DATA(IDirectFB) + + D_DEBUG_AT( IDFB, "%s( %p )\n", __FUNCTION__, thiz ); + + if (!interface) + return DFB_INVARG; + + if (desc && desc->flags & DPDESC_SIZE) { + if (!desc->size) + return DFB_INVARG; + + size = desc->size; + } + + ret = dfb_palette_create( data->core, size, &palette ); + if (ret) + return ret; + + if (desc && desc->flags & DPDESC_ENTRIES) { + direct_memcpy( palette->entries, desc->entries, size * sizeof(DFBColor)); + + dfb_palette_update( palette, 0, size - 1 ); + } + else + dfb_palette_generate_rgb332_map( palette ); + + DIRECT_ALLOCATE_INTERFACE( iface, IDirectFBPalette ); + + ret = IDirectFBPalette_Construct( iface, palette ); + + dfb_palette_unref( palette ); + + if (!ret) + *interface = iface; + + return ret; +} + +static DFBResult +IDirectFB_EnumScreens( IDirectFB *thiz, + DFBScreenCallback callbackfunc, + void *callbackdata ) +{ + EnumScreens_Context context; + + DIRECT_INTERFACE_GET_DATA(IDirectFB) + + D_DEBUG_AT( IDFB, "%s( %p )\n", __FUNCTION__, thiz ); + + if (!callbackfunc) + return DFB_INVARG; + + context.callback = callbackfunc; + context.callback_ctx = callbackdata; + + dfb_screens_enumerate( EnumScreens_Callback, &context ); + + return DFB_OK; +} + +static DFBResult +IDirectFB_GetScreen( IDirectFB *thiz, + DFBScreenID id, + IDirectFBScreen **interface ) +{ + IDirectFBScreen *iface; + GetScreen_Context context; + + DIRECT_INTERFACE_GET_DATA(IDirectFB) + + D_DEBUG_AT( IDFB, "%s( %p, %d )\n", __FUNCTION__, thiz, id ); + + if (!interface) + return DFB_INVARG; + + if (dfb_config->primary_only && id != DLID_PRIMARY) + return DFB_IDNOTFOUND; + + context.interface = &iface; + context.id = id; + context.ret = DFB_IDNOTFOUND; + + dfb_screens_enumerate( GetScreen_Callback, &context ); + + if (!context.ret) + *interface = iface; + + return context.ret; +} + +static DFBResult +IDirectFB_EnumDisplayLayers( IDirectFB *thiz, + DFBDisplayLayerCallback callbackfunc, + void *callbackdata ) +{ + EnumDisplayLayers_Context context; + + DIRECT_INTERFACE_GET_DATA(IDirectFB) + + D_DEBUG_AT( IDFB, "%s( %p )\n", __FUNCTION__, thiz ); + + if (!callbackfunc) + return DFB_INVARG; + + context.callback = callbackfunc; + context.callback_ctx = callbackdata; + + dfb_layers_enumerate( EnumDisplayLayers_Callback, &context ); + + return DFB_OK; +} + +static DFBResult +IDirectFB_GetDisplayLayer( IDirectFB *thiz, + DFBDisplayLayerID id, + IDirectFBDisplayLayer **interface ) +{ + IDirectFBDisplayLayer *iface; + GetDisplayLayer_Context context; + + DIRECT_INTERFACE_GET_DATA(IDirectFB) + + D_DEBUG_AT( IDFB, "%s( %p, %d )\n", __FUNCTION__, thiz, id ); + + if (!interface) + return DFB_INVARG; + + if (dfb_config->primary_only && id != DLID_PRIMARY) + return DFB_IDNOTFOUND; + + context.interface = &iface; + context.id = id; + context.ret = DFB_IDNOTFOUND; + context.core = data->core; + + dfb_layers_enumerate( GetDisplayLayer_Callback, &context ); + + if (!context.ret) + *interface = iface; + + return context.ret; +} + +static DFBResult +IDirectFB_EnumInputDevices( IDirectFB *thiz, + DFBInputDeviceCallback callbackfunc, + void *callbackdata ) +{ + EnumInputDevices_Context context; + + DIRECT_INTERFACE_GET_DATA(IDirectFB) + + D_DEBUG_AT( IDFB, "%s( %p )\n", __FUNCTION__, thiz ); + + if (!callbackfunc) + return DFB_INVARG; + + context.callback = callbackfunc; + context.callback_ctx = callbackdata; + + dfb_input_enumerate_devices( EnumInputDevices_Callback, &context, DICAPS_ALL ); + + return DFB_OK; +} + +static DFBResult +IDirectFB_GetInputDevice( IDirectFB *thiz, + DFBInputDeviceID id, + IDirectFBInputDevice **interface ) +{ + IDirectFBInputDevice *iface; + GetInputDevice_Context context; + + DIRECT_INTERFACE_GET_DATA(IDirectFB) + + D_DEBUG_AT( IDFB, "%s( %p, %d )\n", __FUNCTION__, thiz, id ); + + if (!interface) + return DFB_INVARG; + + context.interface = &iface; + context.id = id; + context.ret = DFB_IDNOTFOUND; + + dfb_input_enumerate_devices( GetInputDevice_Callback, &context, DICAPS_ALL ); + + if (!context.ret) + *interface = iface; + + return context.ret; +} + +static DFBResult +IDirectFB_CreateEventBuffer( IDirectFB *thiz, + IDirectFBEventBuffer **interface) +{ + DFBResult ret; + IDirectFBEventBuffer *iface; + + DIRECT_INTERFACE_GET_DATA(IDirectFB) + + D_DEBUG_AT( IDFB, "%s( %p )\n", __FUNCTION__, thiz ); + + if (!interface) + return DFB_INVARG; + + DIRECT_ALLOCATE_INTERFACE( iface, IDirectFBEventBuffer ); + + ret = IDirectFBEventBuffer_Construct( iface, NULL, NULL ); + + if (!ret) + *interface = iface; + + return ret; +} + +static DFBResult +IDirectFB_CreateInputEventBuffer( IDirectFB *thiz, + DFBInputDeviceCapabilities caps, + DFBBoolean global, + IDirectFBEventBuffer **interface) +{ + DFBResult ret; + IDirectFBEventBuffer *iface; + CreateEventBuffer_Context context; + + DIRECT_INTERFACE_GET_DATA(IDirectFB) + + D_DEBUG_AT( IDFB, "%s( %p )\n", __FUNCTION__, thiz ); + + if (!interface) + return DFB_INVARG; + + DIRECT_ALLOCATE_INTERFACE( iface, IDirectFBEventBuffer ); + + ret = IDirectFBEventBuffer_Construct( iface, global ? input_filter_global : + input_filter_local, data ); + if (ret) + return ret; + + context.caps = caps; + context.interface = &iface; + + dfb_input_enumerate_devices( CreateEventBuffer_Callback, &context, caps ); + + *interface = iface; + + return DFB_OK; +} + +static DFBResult +IDirectFB_CreateImageProvider( IDirectFB *thiz, + const char *filename, + IDirectFBImageProvider **interface ) +{ + DFBResult ret; + DFBDataBufferDescription desc; + IDirectFBDataBuffer *databuffer; + IDirectFBImageProvider *iface; + + DIRECT_INTERFACE_GET_DATA(IDirectFB) + + D_DEBUG_AT( IDFB, "%s( %p, '%s' )\n", __FUNCTION__, thiz, filename ); + + /* Check arguments */ + if (!filename || !interface) + return DFB_INVARG; + + /* Create a data buffer. */ + desc.flags = DBDESC_FILE; + desc.file = filename; + + ret = thiz->CreateDataBuffer( thiz, &desc, &databuffer ); + if (ret) + return ret; + + /* Create (probing) the image provider. */ + ret = IDirectFBImageProvider_CreateFromBuffer( databuffer, data->core, &iface ); + + /* We don't need it anymore, image provider has its own reference. */ + databuffer->Release( databuffer ); + + if (!ret) + *interface = iface; + + return ret; +} + +static DFBResult +IDirectFB_CreateVideoProvider( IDirectFB *thiz, + const char *filename, + IDirectFBVideoProvider **interface ) +{ + DFBResult ret; + DFBDataBufferDescription desc; + IDirectFBDataBuffer *databuffer; + IDirectFBVideoProvider *iface; + + DIRECT_INTERFACE_GET_DATA(IDirectFB) + + D_DEBUG_AT( IDFB, "%s( %p, '%s' )\n", __FUNCTION__, thiz, filename ); + + /* Check arguments */ + if (!interface || !filename) + return DFB_INVARG; + + /* Create a data buffer. */ + desc.flags = DBDESC_FILE; + desc.file = filename; + + ret = thiz->CreateDataBuffer( thiz, &desc, &databuffer ); + if (ret) + return ret; + + /* Create (probing) the video provider. */ + ret = IDirectFBVideoProvider_CreateFromBuffer( databuffer, data->core, &iface ); + + /* We don't need it anymore, video provider has its own reference. */ + databuffer->Release( databuffer ); + + if (!ret) + *interface = iface; + + return ret; +} + +static DFBResult +IDirectFB_CreateFont( IDirectFB *thiz, + const char *filename, + const DFBFontDescription *desc, + IDirectFBFont **interface ) +{ + DFBResult ret; + DFBDataBufferDescription dbdesc; + IDirectFBDataBuffer *databuffer; + IDirectFBFont *font; + + DIRECT_INTERFACE_GET_DATA(IDirectFB) + + D_DEBUG_AT( IDFB, "%s( %p, '%s' )\n", __FUNCTION__, thiz, filename ); + + /* Check arguments */ + if (!interface) + return DFB_INVARG; + + if (desc) { + if ((desc->flags & DFDESC_HEIGHT) && desc->height < 1) + return DFB_INVARG; + + if ((desc->flags & DFDESC_WIDTH) && desc->width < 1) + return DFB_INVARG; + } + + if (filename) { + if (!desc) + return DFB_INVARG; + + if (access( filename, R_OK ) != 0) + return errno2result( errno ); + } + + /* Create a data buffer. */ + dbdesc.flags = DBDESC_FILE; + dbdesc.file = filename; + + ret = thiz->CreateDataBuffer( thiz, &dbdesc, &databuffer ); + if (ret) + return ret; + + /* Create (probing) the font. */ + ret = IDirectFBFont_CreateFromBuffer( databuffer, data->core, desc, &font ); + + /* We don't need it anymore, font has its own reference. */ + databuffer->Release( databuffer ); + + if (!ret) + *interface = font; + + return ret; +} + +static DFBResult +IDirectFB_CreateDataBuffer( IDirectFB *thiz, + const DFBDataBufferDescription *desc, + IDirectFBDataBuffer **interface ) +{ + DFBResult ret = DFB_INVARG; + IDirectFBDataBuffer *iface; + + DIRECT_INTERFACE_GET_DATA(IDirectFB) + + D_DEBUG_AT( IDFB, "%s( %p )\n", __FUNCTION__, thiz ); + + if (!interface) + return DFB_INVARG; + + if (!desc) { + DIRECT_ALLOCATE_INTERFACE( iface, IDirectFBDataBuffer ); + + ret = IDirectFBDataBuffer_Streamed_Construct( iface, data->core ); + } + else if (desc->flags & DBDESC_FILE) { + if (!desc->file) + return DFB_INVARG; + + DIRECT_ALLOCATE_INTERFACE( iface, IDirectFBDataBuffer ); + + ret = IDirectFBDataBuffer_File_Construct( iface, desc->file, data->core ); + } + else if (desc->flags & DBDESC_MEMORY) { + if (!desc->memory.data || !desc->memory.length) + return DFB_INVARG; + + DIRECT_ALLOCATE_INTERFACE( iface, IDirectFBDataBuffer ); + + ret = IDirectFBDataBuffer_Memory_Construct( iface, + desc->memory.data, + desc->memory.length, + data->core ); + } + else + return DFB_INVARG; + + if (!ret) + *interface = iface; + + return ret; +} + +static DFBResult +IDirectFB_SetClipboardData( IDirectFB *thiz, + const char *mime_type, + const void *clip_data, + unsigned int size, + struct timeval *timestamp ) +{ + DFBClipboardCore *clip_core; + + DIRECT_INTERFACE_GET_DATA(IDirectFB) + + D_DEBUG_AT( IDFB, "%s( %p )\n", __FUNCTION__, thiz ); + + if (!mime_type || !data || !size) + return DFB_INVARG; + + clip_core = DFB_CORE( data->core, CLIPBOARD ); + if (!clip_core) + return DFB_NOCORE; + + return dfb_clipboard_set( clip_core, mime_type, clip_data, size, timestamp ); +} + +static DFBResult +IDirectFB_GetClipboardData( IDirectFB *thiz, + char **mime_type, + void **clip_data, + unsigned int *size ) +{ + DFBClipboardCore *clip_core; + + DIRECT_INTERFACE_GET_DATA(IDirectFB) + + D_DEBUG_AT( IDFB, "%s( %p )\n", __FUNCTION__, thiz ); + + if (!mime_type && !data && !size) + return DFB_INVARG; + + clip_core = DFB_CORE( data->core, CLIPBOARD ); + if (!clip_core) + return DFB_NOCORE; + + return dfb_clipboard_get( clip_core, mime_type, clip_data, size ); +} + +static DFBResult +IDirectFB_GetClipboardTimeStamp( IDirectFB *thiz, + struct timeval *timestamp ) +{ + DFBClipboardCore *clip_core; + + DIRECT_INTERFACE_GET_DATA(IDirectFB) + + D_DEBUG_AT( IDFB, "%s( %p )\n", __FUNCTION__, thiz ); + + if (!timestamp) + return DFB_INVARG; + + clip_core = DFB_CORE( data->core, CLIPBOARD ); + if (!clip_core) + return DFB_NOCORE; + + return dfb_clipboard_get_timestamp( clip_core, timestamp ); +} + +static DFBResult +IDirectFB_Suspend( IDirectFB *thiz ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFB) + + D_DEBUG_AT( IDFB, "%s( %p )\n", __FUNCTION__, thiz ); + + return dfb_core_suspend( data->core ); +} + +static DFBResult +IDirectFB_Resume( IDirectFB *thiz ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFB) + + D_DEBUG_AT( IDFB, "%s( %p )\n", __FUNCTION__, thiz ); + + return dfb_core_resume( data->core ); +} + +static DFBResult +IDirectFB_WaitIdle( IDirectFB *thiz ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFB) + + D_DEBUG_AT( IDFB, "%s( %p )\n", __FUNCTION__, thiz ); + + dfb_gfxcard_sync(); + + return DFB_OK; +} + +static DFBResult +IDirectFB_WaitForSync( IDirectFB *thiz ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFB) + + D_DEBUG_AT( IDFB, "%s( %p )\n", __FUNCTION__, thiz ); + + dfb_layer_wait_vsync( data->layer ); + + return DFB_OK; +} + +static DFBResult +IDirectFB_GetInterface( IDirectFB *thiz, + const char *type, + const char *implementation, + void *arg, + void **interface ) +{ + DFBResult ret; + DirectInterfaceFuncs *funcs = NULL; + void *iface; + + DIRECT_INTERFACE_GET_DATA(IDirectFB) + + D_DEBUG_AT( IDFB, "%s( %p, '%s' )\n", __FUNCTION__, thiz, type ); + + if (!type || !interface) + return DFB_INVARG; + + ret = DirectGetInterface( &funcs, type, implementation, DirectProbeInterface, arg ); + if (ret) + return ret; + + ret = funcs->Allocate( &iface ); + if (ret) + return ret; + + ret = funcs->Construct( iface, arg, data->core ); + + if (!ret) + *interface = iface; + + return ret; +} + +static DFBResult +IDirectFB_RescanInputDevices( IDirectFB *thiz ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFB) + + D_DEBUG_AT( IDFB, "%s( %p )\n", __FUNCTION__, thiz ); + + return dfb_input_rescan_devices( data->core ); +} + +static void +LoadBackgroundImage( IDirectFB *dfb, + CoreWindowStack *stack, + DFBConfigLayer *conf ) +{ + DFBResult ret; + DFBSurfaceDescription desc; + IDirectFBImageProvider *provider; + IDirectFBSurface *image; + IDirectFBSurface_data *image_data; + + ret = dfb->CreateImageProvider( dfb, conf->background.filename, &provider ); + if (ret) { + D_DERROR( ret, "Failed loading background image '%s'!\n", conf->background.filename ); + return; + } + + if (conf->background.mode == DLBM_IMAGE) { + desc.flags = DSDESC_WIDTH | DSDESC_HEIGHT; + desc.width = conf->config.width; + desc.height = conf->config.height; + } + else { + provider->GetSurfaceDescription( provider, &desc ); + } + + desc.flags |= DSDESC_CAPS | DSDESC_PIXELFORMAT; + desc.caps = DSCAPS_SHARED; + desc.pixelformat = conf->config.pixelformat; + + ret = dfb->CreateSurface( dfb, &desc, &image ); + if (ret) { + DirectFBError( "Failed creating surface for background image", ret ); + provider->Release( provider ); + return; + } + + ret = provider->RenderTo( provider, image, NULL ); + if (ret) { + DirectFBError( "Failed loading background image", ret ); + image->Release( image ); + provider->Release( provider ); + return; + } + + provider->Release( provider ); + + image_data = (IDirectFBSurface_data*) image->priv; + + dfb_windowstack_set_background_image( stack, image_data->surface ); + + image->Release( image ); +} + +static DFBResult +InitLayerPalette( IDirectFB_data *data, + DFBConfigLayer *conf, + CoreSurface *surface, + CorePalette **ret_palette ) +{ + DFBResult ret; + CorePalette *palette; + + ret = dfb_palette_create( data->core, 256, &palette ); + if (ret) { + D_DERROR( ret, "InitLayerPalette: Could not create palette!\n" ); + return ret; + } + + direct_memcpy( palette->entries, conf->palette, sizeof(DFBColor) * 256 ); + + ret = dfb_surface_set_palette( surface, palette ); + if (ret) { + D_DERROR( ret, "InitLayerPalette: Could not set palette!\n" ); + dfb_palette_unref( palette ); + return ret; + } + + *ret_palette = palette; + + return DFB_OK; +} + +static DFBResult +InitLayers( IDirectFB *dfb, + IDirectFB_data *data ) +{ + DFBResult ret; + int i; + int num = dfb_layer_num(); + + for (i=0; ilayers[i]; + + if (conf->init) { + CoreLayerContext *context; + CoreWindowStack *stack; + CardCapabilities caps; + DFBDisplayLayerConfigFlags fail; + + ret = dfb_layer_get_primary_context( layer, false, &context ); + if (ret) { + D_DERROR( ret, "InitLayers: Could not get context of layer %d!\n", i ); + goto error; + } + + stack = dfb_layer_context_windowstack( context ); + D_ASSERT( stack != NULL ); + + + /* set default desktop configuration */ + if (!(conf->config.flags & DLCONF_BUFFERMODE)) { + dfb_gfxcard_get_capabilities( &caps ); + + conf->config.flags |= DLCONF_BUFFERMODE; + conf->config.buffermode = (caps.accel & DFXL_BLIT) ? DLBM_BACKVIDEO : DLBM_BACKSYSTEM; + } + + if (dfb_layer_context_test_configuration( context, &conf->config, &fail )) { + if (fail & (DLCONF_WIDTH | DLCONF_HEIGHT)) { + D_ERROR( "DirectFB/DirectFBCreate: " + "Setting desktop resolution to %dx%d failed!\n" + " -> Using default resolution.\n", + conf->config.width, conf->config.height ); + + conf->config.flags &= ~(DLCONF_WIDTH | DLCONF_HEIGHT); + } + + if (fail & DLCONF_PIXELFORMAT) { + D_ERROR( "DirectFB/DirectFBCreate: " + "Setting desktop format failed!\n" + " -> Using default format.\n" ); + + conf->config.flags &= ~DLCONF_PIXELFORMAT; + } + + if (fail & DLCONF_BUFFERMODE) { + D_ERROR( "DirectFB/DirectFBCreate: " + "Setting desktop buffer mode failed!\n" + " -> No virtual resolution support or not enough memory?\n" + " Falling back to system back buffer.\n" ); + + conf->config.buffermode = DLBM_BACKSYSTEM; + + if (dfb_layer_context_test_configuration( context, &conf->config, &fail )) { + D_ERROR( "DirectFB/DirectFBCreate: " + "Setting system memory desktop back buffer failed!\n" + " -> Using front buffer only mode.\n" ); + + conf->config.flags &= ~DLCONF_BUFFERMODE; + } + } + } + + if (conf->config.flags) { + ret = dfb_layer_context_set_configuration( context, &conf->config ); + if (ret) { + D_DERROR( ret, "InitLayers: Could not set configuration for layer %d!\n", i ); + dfb_layer_context_unref( context ); + goto error; + } + } + + ret = dfb_layer_context_get_configuration( context, &conf->config ); + D_ASSERT( ret == DFB_OK ); + + ret = dfb_layer_context_get_primary_region( context, true, &data->layers[i].region ); + if (ret) { + D_DERROR( ret, "InitLayers: Could not get primary region of layer %d!\n", i ); + dfb_layer_context_unref( context ); + goto error; + } + + ret = dfb_layer_region_get_surface( data->layers[i].region, &data->layers[i].surface ); + if (ret) { + D_DERROR( ret, "InitLayers: Could not get surface of primary region of layer %d!\n", i ); + dfb_layer_region_unref( data->layers[i].region ); + dfb_layer_context_unref( context ); + goto error; + } + + if (conf->palette_set) + InitLayerPalette( data, conf, data->layers[i].surface, &data->layers[i].palette ); + + if (conf->src_key_index >= 0 && conf->src_key_index < D_ARRAY_SIZE(conf->palette)) { + dfb_layer_context_set_src_colorkey( context, + conf->palette[conf->src_key_index].r, + conf->palette[conf->src_key_index].g, + conf->palette[conf->src_key_index].b, + conf->src_key_index ); + } + else + dfb_layer_context_set_src_colorkey( context, conf->src_key.r, conf->src_key.g, conf->src_key.b, -1 ); + + switch (conf->background.mode) { + case DLBM_COLOR: + dfb_windowstack_set_background_color( stack, &conf->background.color ); + dfb_windowstack_set_background_color_index( stack, conf->background.color_index ); + break; + + case DLBM_IMAGE: + case DLBM_TILE: + LoadBackgroundImage( dfb, stack, conf ); + break; + + default: + break; + } + + dfb_windowstack_set_background_mode( stack, conf->background.mode ); + + data->layers[i].context = context; + } + + data->layers[i].layer = layer; + } + + for (i=0; ilayers[i].context) + dfb_layer_activate_context( data->layers[i].layer, data->layers[i].context ); + } + + return DFB_OK; + +error: + for (i=num-1; i>=0; i--) { + if (data->layers[i].context) { + if (data->layers[i].palette) + dfb_palette_unref( data->layers[i].palette ); + + dfb_surface_unref( data->layers[i].surface ); + dfb_layer_region_unref( data->layers[i].region ); + dfb_layer_context_unref( data->layers[i].context ); + + data->layers[i].context = NULL; + } + } + + return ret; +} + +/* + * Constructor + * + * Fills in function pointers and intializes data structure. + */ +DFBResult +IDirectFB_Construct( IDirectFB *thiz, CoreDFB *core ) +{ + DFBResult ret; + + DIRECT_ALLOCATE_INTERFACE_DATA(thiz, IDirectFB) + + D_DEBUG_AT( IDFB, "%s( %p, %p )\n", __FUNCTION__, thiz, core ); + + data->ref = 1; + data->core = core; + data->level = DFSCL_NORMAL; + + if (dfb_layer_num() < 1) { + D_ERROR( "%s: No layers available! Missing driver?\n", __FUNCTION__ ); + return DFB_UNSUPPORTED; + } + + data->layer = dfb_layer_at_translated( DLID_PRIMARY ); + + ret = dfb_layer_get_primary_context( data->layer, true, &data->context ); + if (ret) { + D_ERROR( "%s: Could not get default context of primary layer!\n", __FUNCTION__ ); + DIRECT_DEALLOCATE_INTERFACE(thiz); + return ret; + } + + data->stack = dfb_layer_context_windowstack( data->context ); + + thiz->AddRef = IDirectFB_AddRef; + thiz->Release = IDirectFB_Release; + thiz->SetCooperativeLevel = IDirectFB_SetCooperativeLevel; + thiz->GetDeviceDescription = IDirectFB_GetDeviceDescription; + thiz->EnumVideoModes = IDirectFB_EnumVideoModes; + thiz->SetVideoMode = IDirectFB_SetVideoMode; + thiz->CreateSurface = IDirectFB_CreateSurface; + thiz->CreatePalette = IDirectFB_CreatePalette; + thiz->EnumScreens = IDirectFB_EnumScreens; + thiz->GetScreen = IDirectFB_GetScreen; + thiz->EnumDisplayLayers = IDirectFB_EnumDisplayLayers; + thiz->GetDisplayLayer = IDirectFB_GetDisplayLayer; + thiz->EnumInputDevices = IDirectFB_EnumInputDevices; + thiz->GetInputDevice = IDirectFB_GetInputDevice; + thiz->CreateEventBuffer = IDirectFB_CreateEventBuffer; + thiz->CreateInputEventBuffer = IDirectFB_CreateInputEventBuffer; + thiz->CreateImageProvider = IDirectFB_CreateImageProvider; + thiz->CreateVideoProvider = IDirectFB_CreateVideoProvider; + thiz->CreateFont = IDirectFB_CreateFont; + thiz->CreateDataBuffer = IDirectFB_CreateDataBuffer; + thiz->SetClipboardData = IDirectFB_SetClipboardData; + thiz->GetClipboardData = IDirectFB_GetClipboardData; + thiz->GetClipboardTimeStamp = IDirectFB_GetClipboardTimeStamp; + thiz->Suspend = IDirectFB_Suspend; + thiz->Resume = IDirectFB_Resume; + thiz->WaitIdle = IDirectFB_WaitIdle; + thiz->WaitForSync = IDirectFB_WaitForSync; + thiz->GetInterface = IDirectFB_GetInterface; + thiz->RescanInputDevices = IDirectFB_RescanInputDevices; + + if (dfb_core_is_master( core )) { + ret = InitLayers( thiz, data ); + if (ret) { + dfb_layer_context_unref( data->context ); + DIRECT_DEALLOCATE_INTERFACE(thiz); + return ret; + } + } + + return DFB_OK; +} + +DFBResult +IDirectFB_SetAppFocus( IDirectFB *thiz, DFBBoolean focused ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFB) + + D_DEBUG_AT( IDFB, "%s( %p, %s )\n", __FUNCTION__, thiz, focused ? "true" : "false" ); + + data->app_focus = focused; + + return DFB_OK; +} + +/* + * internal functions + */ + +static DFBEnumerationResult +EnumScreens_Callback( CoreScreen *screen, void *ctx ) +{ + DFBScreenDescription desc; + DFBScreenID id; + EnumScreens_Context *context = (EnumScreens_Context*) ctx; + + id = dfb_screen_id_translated( screen ); + + if (dfb_config->primary_only && id != DSCID_PRIMARY) + return DFENUM_OK; + + dfb_screen_get_info( screen, NULL, &desc ); + + return context->callback( id, desc, context->callback_ctx ); +} + +static DFBEnumerationResult +GetScreen_Callback( CoreScreen *screen, void *ctx ) +{ + GetScreen_Context *context = (GetScreen_Context*) ctx; + + if (dfb_screen_id_translated( screen ) != context->id) + return DFENUM_OK; + + DIRECT_ALLOCATE_INTERFACE( *context->interface, IDirectFBScreen ); + + context->ret = IDirectFBScreen_Construct( *context->interface, screen ); + + return DFENUM_CANCEL; +} + +static DFBEnumerationResult +EnumDisplayLayers_Callback( CoreLayer *layer, void *ctx ) +{ + DFBDisplayLayerDescription desc; + DFBDisplayLayerID id; + EnumDisplayLayers_Context *context = (EnumDisplayLayers_Context*) ctx; + + id = dfb_layer_id_translated( layer ); + + if (dfb_config->primary_only && id != DLID_PRIMARY) + return DFENUM_OK; + + dfb_layer_get_description( layer, &desc ); + + return context->callback( id, desc, context->callback_ctx ); +} + +static DFBEnumerationResult +GetDisplayLayer_Callback( CoreLayer *layer, void *ctx ) +{ + GetDisplayLayer_Context *context = (GetDisplayLayer_Context*) ctx; + + if (dfb_layer_id_translated( layer ) != context->id) + return DFENUM_OK; + + DIRECT_ALLOCATE_INTERFACE( *context->interface, IDirectFBDisplayLayer ); + + context->ret = IDirectFBDisplayLayer_Construct( *context->interface, + layer, context->core ); + + return DFENUM_CANCEL; +} + +static DFBEnumerationResult +EnumInputDevices_Callback( CoreInputDevice *device, void *ctx ) +{ + DFBInputDeviceDescription desc; + EnumInputDevices_Context *context = (EnumInputDevices_Context*) ctx; + + dfb_input_device_description( device, &desc ); + + return context->callback( dfb_input_device_id( device ), desc, + context->callback_ctx ); +} + +static DFBEnumerationResult +GetInputDevice_Callback( CoreInputDevice *device, void *ctx ) +{ + GetInputDevice_Context *context = (GetInputDevice_Context*) ctx; + + if (dfb_input_device_id( device ) != context->id) + return DFENUM_OK; + + DIRECT_ALLOCATE_INTERFACE( *context->interface, IDirectFBInputDevice ); + + context->ret = IDirectFBInputDevice_Construct( *context->interface, device ); + + return DFENUM_CANCEL; +} + +static DFBEnumerationResult +CreateEventBuffer_Callback( CoreInputDevice *device, void *ctx ) +{ + DFBInputDeviceDescription desc; + CreateEventBuffer_Context *context = (CreateEventBuffer_Context*) ctx; + + dfb_input_device_description( device, &desc ); + + IDirectFBEventBuffer_AttachInputDevice( *context->interface, device ); + + return DFENUM_OK; +} + +static ReactionResult +focus_listener( const void *msg_data, + void *ctx ) +{ + const DFBWindowEvent *evt = msg_data; + IDirectFB_data *data = ctx; + + switch (evt->type) { + case DWET_DESTROYED: + dfb_window_unref( data->primary.window ); + data->primary.window = NULL; + data->primary.focused = false; + return RS_REMOVE; + + case DWET_GOTFOCUS: + data->primary.focused = true; + break; + + case DWET_LOSTFOCUS: + data->primary.focused = false; + break; + + default: + break; + } + + return RS_OK; +} + +static bool +input_filter_local( DFBEvent *evt, + void *ctx ) +{ + IDirectFB_data *data = (IDirectFB_data*) ctx; + + if (evt->clazz == DFEC_INPUT) { + DFBInputEvent *event = &evt->input; + + if (!data->primary.focused && !data->app_focus) + return true; + + switch (event->type) { + case DIET_BUTTONPRESS: + if (data->primary.window) + dfb_windowstack_cursor_enable( data->core, data->stack, false ); + break; + case DIET_KEYPRESS: + if (data->primary.window) + dfb_windowstack_cursor_enable( data->core, data->stack, + (event->key_symbol == + DIKS_ESCAPE) || + (event->modifiers & + DIMM_META) ); + break; + default: + break; + } + } + + return false; +} + +static bool +input_filter_global( DFBEvent *evt, + void *ctx ) +{ + IDirectFB_data *data = (IDirectFB_data*) ctx; + + if (evt->clazz == DFEC_INPUT) { + DFBInputEvent *event = &evt->input; + + if (!data->primary.focused && !data->app_focus) + event->flags |= DIEF_GLOBAL; + } + + return false; +} + +static void +drop_window( IDirectFB_data *data ) +{ + if (!data->primary.window) + return; + + dfb_window_detach( data->primary.window, &data->primary.reaction ); + dfb_window_unref( data->primary.window ); + + data->primary.window = NULL; + data->primary.focused = false; + + dfb_windowstack_cursor_enable( data->core, data->stack, true ); +} + diff --git a/Source/DirectFB/src/idirectfb.h b/Source/DirectFB/src/idirectfb.h new file mode 100755 index 0000000..0d5f4d8 --- /dev/null +++ b/Source/DirectFB/src/idirectfb.h @@ -0,0 +1,89 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __IDIRECTFB_H__ +#define __IDIRECTFB_H__ + +#include + +#include + +#include +#include + +/* + * private data struct of IDirectFB + */ +typedef struct { + int ref; /* reference counter */ + CoreDFB *core; + + DFBCooperativeLevel level; /* current cooperative level */ + + CoreLayer *layer; /* primary display layer */ + CoreLayerContext *context; /* shared context of primary layer */ + CoreWindowStack *stack; /* window stack of primary layer */ + + struct { + int width; /* IDirectFB stores window width */ + int height; /* and height and the pixel depth */ + DFBSurfacePixelFormat format; /* from SetVideoMode() parameters. */ + + CoreWindow *window; /* implicitly created window */ + Reaction reaction; /* for the focus listener */ + bool focused; /* primary's window has the focus */ + + CoreLayerContext *context; /* context for fullscreen primary */ + } primary; /* Used for DFSCL_NORMAL's primary. */ + + bool app_focus; + + struct { + CoreLayer *layer; + CoreLayerContext *context; + CoreLayerRegion *region; + CoreSurface *surface; + CorePalette *palette; + } layers[MAX_LAYERS]; +} IDirectFB_data; + +/* + * IDirectFB constructor/destructor + */ +DFBResult IDirectFB_Construct ( IDirectFB *thiz, + CoreDFB *core ); + +void IDirectFB_Destruct ( IDirectFB *thiz ); + +DFBResult IDirectFB_SetAppFocus( IDirectFB *thiz, + DFBBoolean focused ); + + +extern IDirectFB *idirectfb_singleton; + +#endif diff --git a/Source/DirectFB/src/input/Makefile.am b/Source/DirectFB/src/input/Makefile.am new file mode 100755 index 0000000..b80f078 --- /dev/null +++ b/Source/DirectFB/src/input/Makefile.am @@ -0,0 +1,22 @@ +## Makefile.am for DirectFB/src/input + +INCLUDES = \ + -I$(top_builddir)/lib \ + -I$(top_builddir)/include \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/lib \ + -I$(top_srcdir)/src + + +internalincludedir = $(INTERNALINCLUDEDIR)/input + +internalinclude_HEADERS = \ + idirectfbinputdevice.h \ + idirectfbinputbuffer.h + + +noinst_LTLIBRARIES = libdirectfb_input.la + +libdirectfb_input_la_SOURCES = \ + idirectfbinputdevice.c \ + idirectfbinputbuffer.c diff --git a/Source/DirectFB/src/input/Makefile.in b/Source/DirectFB/src/input/Makefile.in new file mode 100755 index 0000000..2873417 --- /dev/null +++ b/Source/DirectFB/src/input/Makefile.in @@ -0,0 +1,556 @@ +# Makefile.in generated by automake 1.10.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = src/input +DIST_COMMON = $(internalinclude_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/as-ac-expand.m4 \ + $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libdirectfb_input_la_LIBADD = +am_libdirectfb_input_la_OBJECTS = idirectfbinputdevice.lo \ + idirectfbinputbuffer.lo +libdirectfb_input_la_OBJECTS = $(am_libdirectfb_input_la_OBJECTS) +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libdirectfb_input_la_SOURCES) +DIST_SOURCES = $(libdirectfb_input_la_SOURCES) +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(internalincludedir)" +internalincludeHEADERS_INSTALL = $(INSTALL_HEADER) +HEADERS = $(internalinclude_HEADERS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AS = @AS@ +ASFLAGS = @ASFLAGS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIR = @DATADIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DFB_CFLAGS_OMIT_FRAME_POINTER = @DFB_CFLAGS_OMIT_FRAME_POINTER@ +DFB_INTERNAL_CFLAGS = @DFB_INTERNAL_CFLAGS@ +DFB_LDFLAGS = @DFB_LDFLAGS@ +DFB_SMOOTH_SCALING = @DFB_SMOOTH_SCALING@ +DIRECTFB_BINARY_AGE = @DIRECTFB_BINARY_AGE@ +DIRECTFB_CSOURCE = @DIRECTFB_CSOURCE@ +DIRECTFB_INTERFACE_AGE = @DIRECTFB_INTERFACE_AGE@ +DIRECTFB_MAJOR_VERSION = @DIRECTFB_MAJOR_VERSION@ +DIRECTFB_MICRO_VERSION = @DIRECTFB_MICRO_VERSION@ +DIRECTFB_MINOR_VERSION = @DIRECTFB_MINOR_VERSION@ +DIRECTFB_VERSION = @DIRECTFB_VERSION@ +DIRECT_BUILD_DEBUG = @DIRECT_BUILD_DEBUG@ +DIRECT_BUILD_DEBUGS = @DIRECT_BUILD_DEBUGS@ +DIRECT_BUILD_GETTID = @DIRECT_BUILD_GETTID@ +DIRECT_BUILD_NETWORK = @DIRECT_BUILD_NETWORK@ +DIRECT_BUILD_STDBOOL = @DIRECT_BUILD_STDBOOL@ +DIRECT_BUILD_TEXT = @DIRECT_BUILD_TEXT@ +DIRECT_BUILD_TRACE = @DIRECT_BUILD_TRACE@ +DSYMUTIL = @DSYMUTIL@ +DYNLIB = @DYNLIB@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +FREETYPE_CFLAGS = @FREETYPE_CFLAGS@ +FREETYPE_LIBS = @FREETYPE_LIBS@ +FREETYPE_PROVIDER = @FREETYPE_PROVIDER@ +FUSION_BUILD_KERNEL = @FUSION_BUILD_KERNEL@ +FUSION_BUILD_MULTI = @FUSION_BUILD_MULTI@ +FUSION_MESSAGE_SIZE = @FUSION_MESSAGE_SIZE@ +GIF_PROVIDER = @GIF_PROVIDER@ +GREP = @GREP@ +HAVE_LINUX = @HAVE_LINUX@ +INCLUDEDIR = @INCLUDEDIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTERNALINCLUDEDIR = @INTERNALINCLUDEDIR@ +JPEG_PROVIDER = @JPEG_PROVIDER@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBJPEG = @LIBJPEG@ +LIBOBJS = @LIBOBJS@ +LIBPNG = @LIBPNG@ +LIBPNG_CONFIG = @LIBPNG_CONFIG@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_AGE = @LT_AGE@ +LT_BINARY = @LT_BINARY@ +LT_CURRENT = @LT_CURRENT@ +LT_RELEASE = @LT_RELEASE@ +LT_REVISION = @LT_REVISION@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MAN2HTML = @MAN2HTML@ +MKDIR_P = @MKDIR_P@ +MODULEDIR = @MODULEDIR@ +MODULEDIRNAME = @MODULEDIRNAME@ +NMEDIT = @NMEDIT@ +OBJEXT = @OBJEXT@ +OSX_LIBS = @OSX_LIBS@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PNG_PROVIDER = @PNG_PROVIDER@ +RANLIB = @RANLIB@ +RUNTIME_SYSROOT = @RUNTIME_SYSROOT@ +SDL_CFLAGS = @SDL_CFLAGS@ +SDL_LIBS = @SDL_LIBS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOPATH = @SOPATH@ +STRIP = @STRIP@ +SYSCONFDIR = @SYSCONFDIR@ +SYSFS_LIBS = @SYSFS_LIBS@ +THREADFLAGS = @THREADFLAGS@ +THREADLIB = @THREADLIB@ +TSLIB_CFLAGS = @TSLIB_CFLAGS@ +TSLIB_LIBS = @TSLIB_LIBS@ +VERSION = @VERSION@ +VNC_CFLAGS = @VNC_CFLAGS@ +VNC_CONFIG = @VNC_CONFIG@ +VNC_LIBS = @VNC_LIBS@ +X11_CFLAGS = @X11_CFLAGS@ +X11_LIBS = @X11_LIBS@ +ZLIB_LIBS = @ZLIB_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +INCLUDES = \ + -I$(top_builddir)/lib \ + -I$(top_builddir)/include \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/lib \ + -I$(top_srcdir)/src + +internalincludedir = $(INTERNALINCLUDEDIR)/input +internalinclude_HEADERS = \ + idirectfbinputdevice.h \ + idirectfbinputbuffer.h + +noinst_LTLIBRARIES = libdirectfb_input.la +libdirectfb_input_la_SOURCES = \ + idirectfbinputdevice.c \ + idirectfbinputbuffer.c + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/input/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/input/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libdirectfb_input.la: $(libdirectfb_input_la_OBJECTS) $(libdirectfb_input_la_DEPENDENCIES) + $(LINK) $(libdirectfb_input_la_OBJECTS) $(libdirectfb_input_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/idirectfbinputbuffer.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/idirectfbinputdevice.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-internalincludeHEADERS: $(internalinclude_HEADERS) + @$(NORMAL_INSTALL) + test -z "$(internalincludedir)" || $(MKDIR_P) "$(DESTDIR)$(internalincludedir)" + @list='$(internalinclude_HEADERS)'; for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + f=$(am__strip_dir) \ + echo " $(internalincludeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(internalincludedir)/$$f'"; \ + $(internalincludeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(internalincludedir)/$$f"; \ + done + +uninstall-internalincludeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(internalinclude_HEADERS)'; for p in $$list; do \ + f=$(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(internalincludedir)/$$f'"; \ + rm -f "$(DESTDIR)$(internalincludedir)/$$f"; \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(internalincludedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: install-internalincludeHEADERS + +install-dvi: install-dvi-am + +install-exec-am: + +install-html: install-html-am + +install-info: install-info-am + +install-man: + +install-pdf: install-pdf-am + +install-ps: install-ps-am + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-internalincludeHEADERS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am \ + install-internalincludeHEADERS install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-internalincludeHEADERS + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/Source/DirectFB/src/input/idirectfbinputbuffer.c b/Source/DirectFB/src/input/idirectfbinputbuffer.c new file mode 100755 index 0000000..6a4cf08 --- /dev/null +++ b/Source/DirectFB/src/input/idirectfbinputbuffer.c @@ -0,0 +1,1121 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include + +#include +#include + +#include "idirectfbinputbuffer.h" + + +D_DEBUG_DOMAIN( IDFBEvBuf, "IDFBEventBuffer", "IDirectFBEventBuffer Interface" ); + + +typedef struct { + DirectLink link; + DFBEvent evt; +} EventBufferItem; + +typedef struct { + DirectLink link; + + CoreInputDevice *device; /* pointer to input core device struct */ + Reaction reaction; + + DFBInputDeviceDescription desc; +} AttachedDevice; + +typedef struct { + DirectLink link; + + CoreWindow *window; /* pointer to core window struct */ + Reaction reaction; +} AttachedWindow; + +/* + * private data struct of IDirectFBInputDevice + */ +typedef struct { + int ref; /* reference counter */ + + EventBufferFilterCallback filter; + void *filter_ctx; + + DirectLink *devices; /* attached devices */ + + DirectLink *windows; /* attached windows */ + + DirectLink *events; /* linked list containing events */ + + pthread_mutex_t events_mutex; /* mutex lock for accessing the event queue */ + + pthread_cond_t wait_condition; /* condition for idle wait in WaitForEvent() */ + + bool pipe; /* file descriptor mode? */ + int pipe_fds[2]; /* read & write file descriptor */ + + DirectThread *pipe_thread; /* thread feeding the pipe */ + + DFBEventBufferStats stats; + bool stats_enabled; +} IDirectFBEventBuffer_data; + +/* + * adds an event to the event queue + */ +static void IDirectFBEventBuffer_AddItem( IDirectFBEventBuffer_data *data, + EventBufferItem *item ); + +#ifndef DIRECTFB_PURE_VOODOO +static ReactionResult IDirectFBEventBuffer_InputReact( const void *msg_data, + void *ctx ); + +static ReactionResult IDirectFBEventBuffer_WindowReact( const void *msg_data, + void *ctx ); +#endif + +static void *IDirectFBEventBuffer_Feed( DirectThread *thread, void *arg ); + +static void CollectEventStatistics( DFBEventBufferStats *stats, + const DFBEvent *event, + int incdec ); + + +static void +IDirectFBEventBuffer_Destruct( IDirectFBEventBuffer *thiz ) +{ + IDirectFBEventBuffer_data *data = thiz->priv; + AttachedDevice *device; + AttachedWindow *window; + EventBufferItem *item; + DirectLink *n; + + D_DEBUG_AT( IDFBEvBuf, "%s( %p )\n", __FUNCTION__, thiz ); + + pthread_mutex_lock( &data->events_mutex ); + + if (data->pipe) { + data->pipe = false; + + pthread_cond_broadcast( &data->wait_condition ); + + pthread_mutex_unlock( &data->events_mutex ); + + direct_thread_join( data->pipe_thread ); + direct_thread_destroy( data->pipe_thread ); + + pthread_mutex_lock( &data->events_mutex ); + + close( data->pipe_fds[0] ); + close( data->pipe_fds[1] ); + } + +#ifndef DIRECTFB_PURE_VOODOO + direct_list_foreach_safe (device, n, data->devices) { + dfb_input_detach( device->device, &device->reaction ); + + D_FREE( device ); + } + + direct_list_foreach_safe (window, n, data->windows) { + if (window->window) { + dfb_window_detach( window->window, &window->reaction ); + dfb_window_unref( window->window ); + } + + D_FREE( window ); + } +#endif + + direct_list_foreach_safe (item, n, data->events) + D_FREE( item ); + + pthread_cond_destroy( &data->wait_condition ); + pthread_mutex_destroy( &data->events_mutex ); + + DIRECT_DEALLOCATE_INTERFACE( thiz ); +} + +static DirectResult +IDirectFBEventBuffer_AddRef( IDirectFBEventBuffer *thiz ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBEventBuffer) + + D_DEBUG_AT( IDFBEvBuf, "%s( %p )\n", __FUNCTION__, thiz ); + + data->ref++; + + return DFB_OK; +} + +static DirectResult +IDirectFBEventBuffer_Release( IDirectFBEventBuffer *thiz ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBEventBuffer) + + D_DEBUG_AT( IDFBEvBuf, "%s( %p )\n", __FUNCTION__, thiz ); + + if (--data->ref == 0) + IDirectFBEventBuffer_Destruct( thiz ); + + return DFB_OK; +} + +static DFBResult +IDirectFBEventBuffer_Reset( IDirectFBEventBuffer *thiz ) +{ + EventBufferItem *item; + DirectLink *n; + + DIRECT_INTERFACE_GET_DATA(IDirectFBEventBuffer) + + D_DEBUG_AT( IDFBEvBuf, "%s( %p )\n", __FUNCTION__, thiz ); + + if (data->pipe) + return DFB_UNSUPPORTED; + + pthread_mutex_lock( &data->events_mutex ); + + direct_list_foreach_safe (item, n, data->events) + D_FREE( item ); + + data->events = NULL; + + pthread_mutex_unlock( &data->events_mutex ); + + return DFB_OK; +} + +static DFBResult +IDirectFBEventBuffer_WaitForEvent( IDirectFBEventBuffer *thiz ) +{ + DFBResult ret = DFB_OK; + + DIRECT_INTERFACE_GET_DATA(IDirectFBEventBuffer) + + D_DEBUG_AT( IDFBEvBuf, "%s( %p )\n", __FUNCTION__, thiz ); + + if (data->pipe) + return DFB_UNSUPPORTED; + + pthread_mutex_lock( &data->events_mutex ); + + if (!data->events) + pthread_cond_wait( &data->wait_condition, &data->events_mutex ); + if (!data->events) + ret = DFB_INTERRUPTED; + + pthread_mutex_unlock( &data->events_mutex ); + + return ret; +} + +static DFBResult +IDirectFBEventBuffer_WaitForEventWithTimeout( IDirectFBEventBuffer *thiz, + unsigned int seconds, + unsigned int milli_seconds ) +{ + struct timespec timeout; + DFBResult ret = DFB_OK; + int locked = 0; + long int nano_seconds = milli_seconds * 1000000; + + DIRECT_INTERFACE_GET_DATA(IDirectFBEventBuffer) + + D_DEBUG_AT( IDFBEvBuf, "%s( %p, %u, %u )\n", __FUNCTION__, thiz, seconds, milli_seconds ); + + if (data->pipe) + return DFB_UNSUPPORTED; + + if (pthread_mutex_trylock( &data->events_mutex ) == 0) { + if (data->events) { + pthread_mutex_unlock ( &data->events_mutex ); + return ret; + } + locked = 1; + } + + direct_util_get_monotonic_pthread_timeout(&timeout, seconds, nano_seconds); + + if (!locked) + pthread_mutex_lock( &data->events_mutex ); + + if (!data->events) { + if (pthread_cond_timedwait( &data->wait_condition, + &data->events_mutex, + &timeout ) == ETIMEDOUT) + ret = DFB_TIMEOUT; + else if (!data->events) + ret = DFB_INTERRUPTED; + } + + pthread_mutex_unlock( &data->events_mutex ); + + return ret; +} + +static DFBResult +IDirectFBEventBuffer_WakeUp( IDirectFBEventBuffer *thiz ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBEventBuffer) + + D_DEBUG_AT( IDFBEvBuf, "%s( %p )\n", __FUNCTION__, thiz ); + + if (data->pipe) + return DFB_UNSUPPORTED; + + pthread_cond_broadcast( &data->wait_condition ); + + return DFB_OK; +} + +static DFBResult +IDirectFBEventBuffer_GetEvent( IDirectFBEventBuffer *thiz, + DFBEvent *event ) +{ + EventBufferItem *item; + + DIRECT_INTERFACE_GET_DATA(IDirectFBEventBuffer) + + D_DEBUG_AT( IDFBEvBuf, "%s( %p, %p )\n", __FUNCTION__, thiz, event ); + + if (data->pipe) + return DFB_UNSUPPORTED; + + pthread_mutex_lock( &data->events_mutex ); + + if (!data->events) { + pthread_mutex_unlock( &data->events_mutex ); + return DFB_BUFFEREMPTY; + } + + item = (EventBufferItem*) data->events; + + switch (item->evt.clazz) { + case DFEC_INPUT: + event->input = item->evt.input; + break; + + case DFEC_WINDOW: + event->window = item->evt.window; + break; + + case DFEC_USER: + event->user = item->evt.user; + break; + + case DFEC_VIDEOPROVIDER: + event->videoprovider = item->evt.videoprovider; + break; + + case DFEC_UNIVERSAL: + direct_memcpy( event, &item->evt, item->evt.universal.size ); + break; + + default: + D_BUG("unknown event class"); + } + + if (data->stats_enabled) + CollectEventStatistics( &data->stats, &item->evt, -1 ); + + direct_list_remove( &data->events, &item->link ); + + D_FREE( item ); + + pthread_mutex_unlock( &data->events_mutex ); + + D_DEBUG_AT( IDFBEvBuf, " -> class %d, type/size %d, data/id %p\n", event->clazz, event->user.type, event->user.data ); + + return DFB_OK; +} + +static DFBResult +IDirectFBEventBuffer_PeekEvent( IDirectFBEventBuffer *thiz, + DFBEvent *event ) +{ + EventBufferItem *item; + + DIRECT_INTERFACE_GET_DATA(IDirectFBEventBuffer) + + D_DEBUG_AT( IDFBEvBuf, "%s( %p, %p )\n", __FUNCTION__, thiz, event ); + + if (data->pipe) + return DFB_UNSUPPORTED; + + pthread_mutex_lock( &data->events_mutex ); + + if (!data->events) { + pthread_mutex_unlock( &data->events_mutex ); + return DFB_BUFFEREMPTY; + } + + item = (EventBufferItem*) data->events; + + switch (item->evt.clazz) { + case DFEC_INPUT: + event->input = item->evt.input; + break; + + case DFEC_WINDOW: + event->window = item->evt.window; + break; + + case DFEC_USER: + event->user = item->evt.user; + break; + + case DFEC_VIDEOPROVIDER: + event->videoprovider = item->evt.videoprovider; + break; + + case DFEC_UNIVERSAL: + direct_memcpy( event, &item->evt, item->evt.universal.size ); + break; + + default: + D_BUG("unknown event class"); + } + + pthread_mutex_unlock( &data->events_mutex ); + + D_DEBUG_AT( IDFBEvBuf, " -> class %d, type/size %d, data/id %p\n", event->clazz, event->user.type, event->user.data ); + + return DFB_OK; +} + +static DFBResult +IDirectFBEventBuffer_HasEvent( IDirectFBEventBuffer *thiz ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBEventBuffer) + + D_DEBUG_AT( IDFBEvBuf, "%s( %p ) <- events: %p, pipe: %d\n", __FUNCTION__, thiz, data->events, data->pipe ); + + if (data->pipe) + return DFB_UNSUPPORTED; + + return (data->events ? DFB_OK : DFB_BUFFEREMPTY); +} + +static DFBResult +IDirectFBEventBuffer_PostEvent( IDirectFBEventBuffer *thiz, + const DFBEvent *event ) +{ + EventBufferItem *item; + int size; + + DIRECT_INTERFACE_GET_DATA(IDirectFBEventBuffer) + + D_DEBUG_AT( IDFBEvBuf, "%s( %p, %p [class %d, type/size %d, data/id %p] )\n", __FUNCTION__, + thiz, event, event->clazz, event->user.type, event->user.data ); + + switch (event->clazz) { + case DFEC_INPUT: + case DFEC_WINDOW: + case DFEC_USER: + case DFEC_VIDEOPROVIDER: + size = sizeof(EventBufferItem); + break; + + case DFEC_UNIVERSAL: + size = event->universal.size; + if (size < sizeof(DFBUniversalEvent)) + return DFB_INVARG; + /* We must not exceed the union to avoid crashes in generic code (reading DFBEvents) + * and to support pipe mode where each written block has to have a fixed size. */ + if (size > sizeof(DFBEvent)) + return DFB_INVARG; + size += sizeof(DirectLink); + break; + + default: + return DFB_INVARG; + } + + item = D_CALLOC( 1, size ); + if (!item) + return D_OOM(); + + switch (event->clazz) { + case DFEC_INPUT: + item->evt.input = event->input; + break; + + case DFEC_WINDOW: + item->evt.window = event->window; + break; + + case DFEC_USER: + item->evt.user = event->user; + break; + + case DFEC_VIDEOPROVIDER: + item->evt.videoprovider = event->videoprovider; + break; + + case DFEC_UNIVERSAL: + direct_memcpy( &item->evt, event, event->universal.size ); + break; + + default: + D_BUG("unexpected event class"); + } + + IDirectFBEventBuffer_AddItem( data, item ); + + return DFB_OK; +} + +static DFBResult +IDirectFBEventBuffer_CreateFileDescriptor( IDirectFBEventBuffer *thiz, + int *ret_fd ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBEventBuffer) + + D_DEBUG_AT( IDFBEvBuf, "%s( %p )\n", __FUNCTION__, thiz ); + + /* Check arguments. */ + if (!ret_fd) + return DFB_INVARG; + + /* Lock the event queue. */ + pthread_mutex_lock( &data->events_mutex ); + + /* Already in pipe mode? */ + if (data->pipe) { + pthread_mutex_unlock( &data->events_mutex ); + return DFB_BUSY; + } + + /* Create the file descriptor(s). */ + if (socketpair( PF_LOCAL, SOCK_STREAM, 0, data->pipe_fds )) { + D_PERROR( "%s(): socketpair( PF_LOCAL, SOCK_STREAM, 0, fds ) failed!\n", __FUNCTION__ ); + pthread_mutex_unlock( &data->events_mutex ); + return errno2result( errno ); + } + + D_DEBUG_AT( IDFBEvBuf, " -> entering pipe mode\n" ); + + /* Enter pipe mode. */ + data->pipe = true; + + /* Signal any waiting processes. */ + pthread_cond_broadcast( &data->wait_condition ); + + /* Create the feeding thread. */ + data->pipe_thread = direct_thread_create( DTT_MESSAGING, + IDirectFBEventBuffer_Feed, data, + "EventBufferFeed" ); + + /* Unlock the event queue. */ + pthread_mutex_unlock( &data->events_mutex ); + + /* Return the file descriptor for reading. */ + *ret_fd = data->pipe_fds[0]; + + D_DEBUG_AT( IDFBEvBuf, " -> fd %d/%d\n", data->pipe_fds[0], data->pipe_fds[1] ); + + return DFB_OK; +} + +static DFBResult +IDirectFBEventBuffer_EnableStatistics( IDirectFBEventBuffer *thiz, + DFBBoolean enable ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBEventBuffer) + + D_DEBUG_AT( IDFBEvBuf, "%s( %p, %sable )\n", __FUNCTION__, thiz, enable ? "en" : "dis" ); + + /* Lock the event queue. */ + pthread_mutex_lock( &data->events_mutex ); + + /* Already enabled/disabled? */ + if (data->stats_enabled == !!enable) { + pthread_mutex_unlock( &data->events_mutex ); + return DFB_OK; + } + + if (enable) { + EventBufferItem *item; + + /* Collect statistics for events already in the queue. */ + direct_list_foreach (item, data->events) + CollectEventStatistics( &data->stats, &item->evt, 1 ); + } + else { + /* Clear statistics. */ + memset( &data->stats, 0, sizeof(DFBEventBufferStats) ); + } + + /* Remember state. */ + data->stats_enabled = !!enable; + + /* Unlock the event queue. */ + pthread_mutex_unlock( &data->events_mutex ); + + return DFB_OK; +} + +static DFBResult +IDirectFBEventBuffer_GetStatistics( IDirectFBEventBuffer *thiz, + DFBEventBufferStats *ret_stats ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBEventBuffer) + + D_DEBUG_AT( IDFBEvBuf, "%s( %p, %p )\n", __FUNCTION__, thiz, ret_stats ); + + if (!ret_stats) + return DFB_INVARG; + + /* Lock the event queue. */ + pthread_mutex_lock( &data->events_mutex ); + + /* Not enabled? */ + if (!data->stats_enabled) { + pthread_mutex_unlock( &data->events_mutex ); + return DFB_UNSUPPORTED; + } + + /* Return current stats. */ + *ret_stats = data->stats; + + /* Unlock the event queue. */ + pthread_mutex_unlock( &data->events_mutex ); + + return DFB_OK; +} + +DFBResult +IDirectFBEventBuffer_Construct( IDirectFBEventBuffer *thiz, + EventBufferFilterCallback filter, + void *filter_ctx ) +{ + DIRECT_ALLOCATE_INTERFACE_DATA(thiz, IDirectFBEventBuffer) + + D_DEBUG_AT( IDFBEvBuf, "%s( %p, filter %p, ctx %p )\n", __FUNCTION__, thiz, filter, filter_ctx ); + + data->ref = 1; + data->filter = filter; + data->filter_ctx = filter_ctx; + + direct_util_recursive_pthread_mutex_init( &data->events_mutex ); + direct_util_monotonic_pthread_cond_init( &data->wait_condition ); + + thiz->AddRef = IDirectFBEventBuffer_AddRef; + thiz->Release = IDirectFBEventBuffer_Release; + thiz->Reset = IDirectFBEventBuffer_Reset; + thiz->WaitForEvent = IDirectFBEventBuffer_WaitForEvent; + thiz->WaitForEventWithTimeout = IDirectFBEventBuffer_WaitForEventWithTimeout; + thiz->GetEvent = IDirectFBEventBuffer_GetEvent; + thiz->PeekEvent = IDirectFBEventBuffer_PeekEvent; + thiz->HasEvent = IDirectFBEventBuffer_HasEvent; + thiz->PostEvent = IDirectFBEventBuffer_PostEvent; + thiz->WakeUp = IDirectFBEventBuffer_WakeUp; + thiz->CreateFileDescriptor = IDirectFBEventBuffer_CreateFileDescriptor; + thiz->EnableStatistics = IDirectFBEventBuffer_EnableStatistics; + thiz->GetStatistics = IDirectFBEventBuffer_GetStatistics; + + D_DEBUG_AT( IDFBEvBuf, " -> %p [%p]\n", thiz, thiz->priv ); + + return DFB_OK; +} + +/* directfb internals */ + +#ifndef DIRECTFB_PURE_VOODOO +DFBResult IDirectFBEventBuffer_AttachInputDevice( IDirectFBEventBuffer *thiz, + CoreInputDevice *device ) +{ + AttachedDevice *attached; + DFBInputDeviceDescription desc; + + DIRECT_INTERFACE_GET_DATA(IDirectFBEventBuffer) + + D_ASSERT( device != NULL ); + + dfb_input_device_description( device, &desc ); + + D_DEBUG_AT( IDFBEvBuf, "%s( %p, %p [%02u - %s] )\n", __FUNCTION__, thiz, device, + dfb_input_device_id(device), desc.name ); + + attached = D_CALLOC( 1, sizeof(AttachedDevice) ); + attached->device = device; + attached->desc = desc; + + direct_list_prepend( &data->devices, &attached->link ); + + dfb_input_attach( device, IDirectFBEventBuffer_InputReact, + data, &attached->reaction ); + + return DFB_OK; +} + +DFBResult IDirectFBEventBuffer_DetachInputDevice( IDirectFBEventBuffer *thiz, + CoreInputDevice *device ) +{ + AttachedDevice *attached; + DirectLink *link; + + DIRECT_INTERFACE_GET_DATA(IDirectFBEventBuffer) + + D_ASSERT( device != NULL ); + + D_DEBUG_AT( IDFBEvBuf, "%s( %p, %p [%02u] )\n", __FUNCTION__, thiz, device, + dfb_input_device_id(device) ); + + direct_list_foreach_safe (attached, link, data->devices) { + if (attached->device == device) { + direct_list_remove( &data->devices, &attached->link ); + + dfb_input_detach( attached->device, &attached->reaction ); + + D_FREE( attached ); + + return DFB_OK; + } + } + + return DFB_ITEMNOTFOUND; +} + +DFBResult IDirectFBEventBuffer_AttachWindow( IDirectFBEventBuffer *thiz, + CoreWindow *window ) +{ + AttachedWindow *attached; + + DIRECT_INTERFACE_GET_DATA(IDirectFBEventBuffer) + + D_ASSERT( window != NULL ); + + D_DEBUG_AT( IDFBEvBuf, "%s( %p, %p [%02u - %d,%d-%dx%d] )\n", __FUNCTION__, thiz, + window, window->id, window->config.bounds.x, window->config.bounds.y, + window->config.bounds.w, window->config.bounds.h ); + + attached = D_CALLOC( 1, sizeof(AttachedWindow) ); + attached->window = window; + + window->caps &= ~DWCAPS_NOFOCUS; //no focus patch PR brg36mgr#118432 + + dfb_window_ref( window ); + + direct_list_prepend( &data->windows, &attached->link ); + + dfb_window_attach( window, IDirectFBEventBuffer_WindowReact, + data, &attached->reaction ); + + return DFB_OK; +} + +DFBResult IDirectFBEventBuffer_DetachWindow( IDirectFBEventBuffer *thiz, + CoreWindow *window ) +{ + AttachedWindow *attached; + DirectLink *link; + + DIRECT_INTERFACE_GET_DATA(IDirectFBEventBuffer) + + D_ASSERT( window != NULL ); + + D_DEBUG_AT( IDFBEvBuf, "%s( %p, %p [%02u - %d,%d-%dx%d] )\n", __FUNCTION__, thiz, + window, window->id, window->config.bounds.x, window->config.bounds.y, + window->config.bounds.w, window->config.bounds.h ); + + direct_list_foreach_safe (attached, link, data->windows) { + if (!attached->window || attached->window == window) { + direct_list_remove( &data->windows, &attached->link ); + + if (attached->window) { + dfb_window_detach( attached->window, &attached->reaction ); + dfb_window_unref( attached->window ); + } + + D_FREE( attached ); + } + } + + return DFB_OK; +} +#endif + +/* file internals */ + +static void IDirectFBEventBuffer_AddItem( IDirectFBEventBuffer_data *data, + EventBufferItem *item ) +{ + if (data->filter && data->filter( &item->evt, data->filter_ctx )) { + D_FREE( item ); + return; + } + + pthread_mutex_lock( &data->events_mutex ); + + if (data->stats_enabled) + CollectEventStatistics( &data->stats, &item->evt, 1 ); + + direct_list_append( &data->events, &item->link ); + + pthread_cond_broadcast( &data->wait_condition ); + + pthread_mutex_unlock( &data->events_mutex ); +} + +#ifndef DIRECTFB_PURE_VOODOO +static ReactionResult IDirectFBEventBuffer_InputReact( const void *msg_data, + void *ctx ) +{ + const DFBInputEvent *evt = msg_data; + IDirectFBEventBuffer_data *data = ctx; + EventBufferItem *item; + + D_DEBUG_AT( IDFBEvBuf, "%s( %p, %p ) <- type %06x\n", __FUNCTION__, evt, data, evt->type ); + + if (dfb_config->discard_repeat_events && (evt->flags & DIEF_REPEAT)) { + D_DEBUG_AT( IDFBEvBuf, " -> discarding repeat event!\n" ); + return DFB_OK; + } + + item = D_CALLOC( 1, sizeof(EventBufferItem) ); + + item->evt.input = *evt; + item->evt.clazz = DFEC_INPUT; + + IDirectFBEventBuffer_AddItem( data, item ); + + return RS_OK; +} + +static ReactionResult IDirectFBEventBuffer_WindowReact( const void *msg_data, + void *ctx ) +{ + const DFBWindowEvent *evt = msg_data; + IDirectFBEventBuffer_data *data = ctx; + EventBufferItem *item; + + D_DEBUG_AT( IDFBEvBuf, "%s( %p, %p ) <- type %06x\n", __FUNCTION__, evt, data, evt->type ); + + if (dfb_config->discard_repeat_events && (evt->flags & DWEF_REPEAT)) { + D_DEBUG_AT( IDFBEvBuf, " -> discarding repeat event!\n" ); + return DFB_OK; + } + + item = D_CALLOC( 1, sizeof(EventBufferItem) ); + + item->evt.window = *evt; + item->evt.clazz = DFEC_WINDOW; + + IDirectFBEventBuffer_AddItem( data, item ); + + if (evt->type == DWET_DESTROYED) { + AttachedWindow *window; + + direct_list_foreach (window, data->windows) { + if (!window->window) + continue; + + if (dfb_window_id( window->window ) == evt->window_id) { + /* FIXME: free memory later, because reactor writes to it + after we return RS_REMOVE */ + dfb_window_unref( window->window ); + window->window = NULL; + } + } + + return RS_REMOVE; + } + + return RS_OK; +} +#endif + +static void * +IDirectFBEventBuffer_Feed( DirectThread *thread, void *arg ) +{ + IDirectFBEventBuffer_data *data = arg; + + pthread_mutex_lock( &data->events_mutex ); + + while (data->pipe) { + while (data->events && data->pipe) { + int ret; + EventBufferItem *item = (EventBufferItem*) data->events; + + if (data->stats_enabled) + CollectEventStatistics( &data->stats, &item->evt, -1 ); + + direct_list_remove( &data->events, &item->link ); + + if (item->evt.clazz == DFEC_UNIVERSAL) { + D_WARN( "universal events not supported in pipe mode" ); + continue; + } + + pthread_mutex_unlock( &data->events_mutex ); + + D_DEBUG_AT( IDFBEvBuf, "Going to write %zu bytes to file descriptor %d...\n", + sizeof(DFBEvent), data->pipe_fds[1] ); + + ret = write( data->pipe_fds[1], &item->evt, sizeof(DFBEvent) ); + + D_DEBUG_AT( IDFBEvBuf, "...wrote %d bytes to file descriptor %d.\n", + ret, data->pipe_fds[1] ); + + D_FREE( item ); + + pthread_mutex_lock( &data->events_mutex ); + } + + if (data->pipe) + pthread_cond_wait( &data->wait_condition, &data->events_mutex ); + } + + pthread_mutex_unlock( &data->events_mutex ); + + return NULL; +} + +static void +CollectEventStatistics( DFBEventBufferStats *stats, + const DFBEvent *event, + int incdec ) +{ + stats->num_events += incdec; + + switch (event->clazz) { + case DFEC_INPUT: + stats->DFEC_INPUT += incdec; + + switch (event->input.type) { + case DIET_KEYPRESS: + stats->DIET_KEYPRESS += incdec; + break; + + case DIET_KEYRELEASE: + stats->DIET_KEYRELEASE += incdec; + break; + + case DIET_BUTTONPRESS: + stats->DIET_BUTTONPRESS += incdec; + break; + + case DIET_BUTTONRELEASE: + stats->DIET_BUTTONRELEASE += incdec; + break; + + case DIET_AXISMOTION: + stats->DIET_AXISMOTION += incdec; + break; + + default: + D_BUG( "unknown input event type 0x%08x\n", event->input.type ); + } + break; + + case DFEC_WINDOW: + stats->DFEC_WINDOW += incdec; + + switch (event->window.type) { + case DWET_POSITION: + stats->DWET_POSITION += incdec; + break; + + case DWET_SIZE: + stats->DWET_SIZE += incdec; + break; + + case DWET_CLOSE: + stats->DWET_CLOSE += incdec; + break; + + case DWET_DESTROYED: + stats->DWET_DESTROYED += incdec; + break; + + case DWET_GOTFOCUS: + stats->DWET_GOTFOCUS += incdec; + break; + + case DWET_LOSTFOCUS: + stats->DWET_LOSTFOCUS += incdec; + break; + + case DWET_KEYDOWN: + stats->DWET_KEYDOWN += incdec; + break; + + case DWET_KEYUP: + stats->DWET_KEYUP += incdec; + break; + + case DWET_BUTTONDOWN: + stats->DWET_BUTTONDOWN += incdec; + break; + + case DWET_BUTTONUP: + stats->DWET_BUTTONUP += incdec; + break; + + case DWET_MOTION: + stats->DWET_MOTION += incdec; + break; + + case DWET_ENTER: + stats->DWET_ENTER += incdec; + break; + + case DWET_LEAVE: + stats->DWET_LEAVE += incdec; + break; + + case DWET_WHEEL: + stats->DWET_WHEEL += incdec; + break; + + case DWET_POSITION_SIZE: + stats->DWET_POSITION_SIZE += incdec; + break; + + default: + D_BUG( "unknown window event type 0x%08x\n", event->window.type ); + } + break; + + case DFEC_USER: + stats->DFEC_USER += incdec; + break; + + case DFEC_VIDEOPROVIDER: + stats->DFEC_VIDEOPROVIDER +=incdec; + + switch (event->videoprovider.type) { + case DVPET_STARTED: + stats->DVPET_STARTED += incdec; + break; + + case DVPET_STOPPED: + stats->DVPET_STOPPED += incdec; + break; + + case DVPET_SPEEDCHANGE: + stats->DVPET_SPEEDCHANGE += incdec; + break; + + case DVPET_STREAMCHANGE: + stats->DVPET_STREAMCHANGE += incdec; + break; + + case DVPET_FATALERROR: + stats->DVPET_FATALERROR += incdec; + break; + + case DVPET_FINISHED: + stats->DVPET_FINISHED += incdec; + break; + + case DVPET_SURFACECHANGE: + stats->DVPET_SURFACECHANGE += incdec; + break; + + case DVPET_FRAMEDECODED: + stats->DVPET_FRAMEDECODED += incdec; + break; + + case DVPET_FRAMEDISPLAYED: + stats->DVPET_FRAMEDISPLAYED += incdec; + break; + + case DVPET_DATAEXHAUSTED: + stats->DVPET_DATAEXHAUSTED += incdec; + break; + + case DVPET_VIDEOACTION: + stats->DVPET_VIDEOACTION += incdec; + break; + + case DVPET_DATALOW: + stats->DVPET_DATALOW += incdec; + break; + + case DVPET_DATAHIGH: + stats->DVPET_DATAHIGH += incdec; + break; + + case DVPET_BUFFERTIMELOW: + stats->DVPET_BUFFERTIMELOW += incdec; + break; + + case DVPET_BUFFERTIMEHIGH: + stats->DVPET_BUFFERTIMEHIGH += incdec; + break; + + default: + D_BUG( "unknown video provider event type 0x%08x\n", event->videoprovider.type ); + } + break; + + case DFEC_UNIVERSAL: + stats->DFEC_UNIVERSAL += incdec; + break; + + default: + D_BUG( "unknown event class 0x%08x\n", event->clazz ); + } +} + diff --git a/Source/DirectFB/src/input/idirectfbinputbuffer.h b/Source/DirectFB/src/input/idirectfbinputbuffer.h new file mode 100755 index 0000000..53b263b --- /dev/null +++ b/Source/DirectFB/src/input/idirectfbinputbuffer.h @@ -0,0 +1,56 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __IDIRECTFBEVENTBUFFER_H__ +#define __IDIRECTFBEVENTBUFFER_H__ + +#include +#include + +typedef bool (*EventBufferFilterCallback)( DFBEvent *evt, + void *ctx ); + +/* + * initializes event buffer, adds it to input listeners and initializes mutexes + */ +DFBResult IDirectFBEventBuffer_Construct( IDirectFBEventBuffer *thiz, + EventBufferFilterCallback filter, + void *filter_ctx ); + +DFBResult IDirectFBEventBuffer_AttachInputDevice( IDirectFBEventBuffer *thiz, + CoreInputDevice *device ); +DFBResult IDirectFBEventBuffer_DetachInputDevice( IDirectFBEventBuffer *thiz, + CoreInputDevice *device ); + +DFBResult IDirectFBEventBuffer_AttachWindow( IDirectFBEventBuffer *thiz, + CoreWindow *window ); +DFBResult IDirectFBEventBuffer_DetachWindow( IDirectFBEventBuffer *thiz, + CoreWindow *window ); + + +#endif diff --git a/Source/DirectFB/src/input/idirectfbinputdevice.c b/Source/DirectFB/src/input/idirectfbinputdevice.c new file mode 100755 index 0000000..f00af8e --- /dev/null +++ b/Source/DirectFB/src/input/idirectfbinputdevice.c @@ -0,0 +1,446 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include +#include +#include + +#include + +#include + +#include + +#include +#include + +#include + +#include +#include +#include + +#include "idirectfbinputdevice.h" +#include "idirectfbinputbuffer.h" + + +/* + * processes an event, updates device state + * (funcion is added to the event listeners) + */ +static ReactionResult +IDirectFBInputDevice_React( const void *msg_data, + void *ctx ); + +/* + * private data struct of IDirectFBInputDevice + */ +typedef struct { + int ref; /* reference counter */ + CoreInputDevice *device; /* pointer to input core + device struct*/ + + int axis[DIAI_LAST+1]; /* position of all axes */ + DFBInputDeviceKeyState keystates[DIKI_NUMBER_OF_KEYS]; + /* state of all keys */ + DFBInputDeviceModifierMask modifiers; /* bitmask reflecting the + state of the modifier + keys */ + DFBInputDeviceLockState locks; /* bitmask reflecting the + state of the key locks */ + DFBInputDeviceButtonMask buttonmask; /* bitmask reflecting the + state of the buttons */ + + DFBInputDeviceDescription desc; /* device description */ + + Reaction reaction; +} IDirectFBInputDevice_data; + + + +static void +IDirectFBInputDevice_Destruct( IDirectFBInputDevice *thiz ) +{ + IDirectFBInputDevice_data *data = (IDirectFBInputDevice_data*)thiz->priv; + + dfb_input_detach( data->device, &data->reaction ); + + DIRECT_DEALLOCATE_INTERFACE( thiz ); +} + +static DirectResult +IDirectFBInputDevice_AddRef( IDirectFBInputDevice *thiz ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBInputDevice) + + data->ref++; + + return DFB_OK; +} + +static DirectResult +IDirectFBInputDevice_Release( IDirectFBInputDevice *thiz ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBInputDevice) + + if (--data->ref == 0) + IDirectFBInputDevice_Destruct( thiz ); + + return DFB_OK; +} + +static DFBResult +IDirectFBInputDevice_GetID( IDirectFBInputDevice *thiz, + DFBInputDeviceID *id ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBInputDevice) + + if (!id) + return DFB_INVARG; + + *id = dfb_input_device_id( data->device ); + + return DFB_OK; +} + +static DFBResult +IDirectFBInputDevice_CreateEventBuffer( IDirectFBInputDevice *thiz, + IDirectFBEventBuffer **buffer ) +{ + IDirectFBEventBuffer *b; + + DIRECT_INTERFACE_GET_DATA(IDirectFBInputDevice) + + DIRECT_ALLOCATE_INTERFACE( b, IDirectFBEventBuffer ); + + IDirectFBEventBuffer_Construct( b, NULL, NULL ); + + IDirectFBEventBuffer_AttachInputDevice( b, data->device ); + + *buffer = b; + + return DFB_OK; +} + +static DFBResult +IDirectFBInputDevice_AttachEventBuffer( IDirectFBInputDevice *thiz, + IDirectFBEventBuffer *buffer ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBInputDevice) + + return IDirectFBEventBuffer_AttachInputDevice( buffer, data->device ); +} + +static DFBResult +IDirectFBInputDevice_DetachEventBuffer( IDirectFBInputDevice *thiz, + IDirectFBEventBuffer *buffer ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBInputDevice) + + return IDirectFBEventBuffer_DetachInputDevice( buffer, data->device ); +} + +static DFBResult +IDirectFBInputDevice_GetDescription( IDirectFBInputDevice *thiz, + DFBInputDeviceDescription *desc ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBInputDevice) + + if (!desc) + return DFB_INVARG; + + *desc = data->desc; + + return DFB_OK; +} + +static DFBResult +IDirectFBInputDevice_GetKeymapEntry( IDirectFBInputDevice *thiz, + int keycode, + DFBInputDeviceKeymapEntry *entry ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBInputDevice) + + if (!entry) + return DFB_INVARG; + + if (data->desc.min_keycode < 0 || data->desc.max_keycode < 0) + return DFB_UNSUPPORTED; + + if (keycode < data->desc.min_keycode || + keycode > data->desc.max_keycode) + return DFB_INVARG; + + return dfb_input_device_get_keymap_entry( data->device, keycode, entry ); +} + +static DFBResult +IDirectFBInputDevice_SetKeymapEntry( IDirectFBInputDevice *thiz, + int keycode, + DFBInputDeviceKeymapEntry *entry ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBInputDevice) + + if (!entry) + return DFB_INVARG; + + if (data->desc.min_keycode < 0 || data->desc.max_keycode < 0) + return DFB_UNSUPPORTED; + + if (keycode < data->desc.min_keycode || + keycode > data->desc.max_keycode) + return DFB_INVARG; + + return dfb_input_device_set_keymap_entry( data->device, keycode, entry ); +} + +static DFBResult +IDirectFBInputDevice_LoadKeymap ( IDirectFBInputDevice *thiz, + char *filename ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBInputDevice) + + if (!filename) + return DFB_INVARG; + + return dfb_input_device_load_keymap( data->device, filename ); +} + +static DFBResult +IDirectFBInputDevice_GetKeyState( IDirectFBInputDevice *thiz, + DFBInputDeviceKeyIdentifier key_id, + DFBInputDeviceKeyState *state ) +{ + unsigned int index = key_id - DFB_KEY(IDENTIFIER, 0); + DIRECT_INTERFACE_GET_DATA(IDirectFBInputDevice) + + if (!state || index >= DIKI_NUMBER_OF_KEYS) + return DFB_INVARG; + + *state = data->keystates[index]; + + return DFB_OK; +} + +static DFBResult +IDirectFBInputDevice_GetModifiers( IDirectFBInputDevice *thiz, + DFBInputDeviceModifierMask *modifiers ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBInputDevice) + + if (!modifiers) + return DFB_INVARG; + + *modifiers = data->modifiers; + + return DFB_OK; +} + +static DFBResult +IDirectFBInputDevice_GetLockState( IDirectFBInputDevice *thiz, + DFBInputDeviceLockState *locks ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBInputDevice) + + if (!locks) + return DFB_INVARG; + + *locks = data->locks; + + return DFB_OK; +} + +static DFBResult +IDirectFBInputDevice_GetButtons( IDirectFBInputDevice *thiz, + DFBInputDeviceButtonMask *buttons ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBInputDevice) + + if (!buttons) + return DFB_INVARG; + + *buttons = data->buttonmask; + + return DFB_OK; +} + +static DFBResult +IDirectFBInputDevice_GetButtonState( IDirectFBInputDevice *thiz, + DFBInputDeviceButtonIdentifier button, + DFBInputDeviceButtonState *state) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBInputDevice) + + if (!state || (int)button < DIBI_FIRST || button > DIBI_LAST) + return DFB_INVARG; + + *state = (data->buttonmask & (1 << button)) ? DIBS_DOWN : DIBS_UP; + + return DFB_OK; +} + +static DFBResult +IDirectFBInputDevice_GetAxis( IDirectFBInputDevice *thiz, + DFBInputDeviceAxisIdentifier axis, + int *pos ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBInputDevice) + + if (!pos || (int)axis < DIAI_FIRST || axis > DIAI_LAST) + return DFB_INVARG; + + *pos = data->axis[axis]; + + return DFB_OK; +} + +static DFBResult +IDirectFBInputDevice_GetXY( IDirectFBInputDevice *thiz, + int *x, + int *y ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBInputDevice) + + if (!x && !y) + return DFB_INVARG; + + if (x) + *x = data->axis[DIAI_X]; + + if (y) + *y = data->axis[DIAI_Y]; + + return DFB_OK; +} + +static DFBResult +IDirectFBInputDevice_SetSensitivity( IDirectFBInputDevice *thiz, + int sensitivity ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBInputDevice) + + return dfb_input_device_set_sensitivity( data->device, sensitivity ); +} + +static DFBResult +IDirectFBInputDevice_GetState( IDirectFBInputDevice *thiz, + DFBInputDeviceState *state ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBInputDevice) + + if (!state) + return DFB_INVARG; + + return dfb_input_device_get_state( data->device, state ); +} + + +DFBResult +IDirectFBInputDevice_Construct( IDirectFBInputDevice *thiz, + CoreInputDevice *device ) +{ + DIRECT_ALLOCATE_INTERFACE_DATA(thiz, IDirectFBInputDevice) + + data->ref = 1; + data->device = device; + + dfb_input_device_description( device, &data->desc ); + + dfb_input_attach( data->device, IDirectFBInputDevice_React, + data, &data->reaction ); + + thiz->AddRef = IDirectFBInputDevice_AddRef; + thiz->Release = IDirectFBInputDevice_Release; + thiz->GetID = IDirectFBInputDevice_GetID; + thiz->GetDescription = IDirectFBInputDevice_GetDescription; + thiz->GetKeymapEntry = IDirectFBInputDevice_GetKeymapEntry; + thiz->SetKeymapEntry = IDirectFBInputDevice_SetKeymapEntry; + thiz->LoadKeymap = IDirectFBInputDevice_LoadKeymap; + thiz->CreateEventBuffer = IDirectFBInputDevice_CreateEventBuffer; + thiz->AttachEventBuffer = IDirectFBInputDevice_AttachEventBuffer; + thiz->DetachEventBuffer = IDirectFBInputDevice_DetachEventBuffer; + thiz->GetKeyState = IDirectFBInputDevice_GetKeyState; + thiz->GetModifiers = IDirectFBInputDevice_GetModifiers; + thiz->GetLockState = IDirectFBInputDevice_GetLockState; + thiz->GetButtons = IDirectFBInputDevice_GetButtons; + thiz->GetButtonState = IDirectFBInputDevice_GetButtonState; + thiz->GetAxis = IDirectFBInputDevice_GetAxis; + thiz->GetXY = IDirectFBInputDevice_GetXY; + thiz->SetSensitivity = IDirectFBInputDevice_SetSensitivity; + thiz->GetState = IDirectFBInputDevice_GetState; + + return DFB_OK; +} + + +/* internals */ + +static ReactionResult +IDirectFBInputDevice_React( const void *msg_data, + void *ctx ) +{ + const DFBInputEvent *evt = msg_data; + IDirectFBInputDevice_data *data = ctx; + unsigned int index; + + if (evt->flags & DIEF_MODIFIERS) + data->modifiers = evt->modifiers; + if (evt->flags & DIEF_LOCKS) + data->locks = evt->locks; + if (evt->flags & DIEF_BUTTONS) + data->buttonmask = evt->buttons; + + switch (evt->type) { + case DIET_KEYPRESS: + index = evt->key_id - DFB_KEY(IDENTIFIER, 0); + if (index < DIKI_NUMBER_OF_KEYS) + data->keystates[index] = DIKS_DOWN; + break; + + case DIET_KEYRELEASE: + index = evt->key_id - DFB_KEY(IDENTIFIER, 0); + if (index < DIKI_NUMBER_OF_KEYS) + data->keystates[index] = DIKS_UP; + break; + + case DIET_AXISMOTION: + if (evt->flags & DIEF_AXISREL) + data->axis[evt->axis] += evt->axisrel; + if (evt->flags & DIEF_AXISABS) + data->axis[evt->axis] = evt->axisabs; + break; + + default: + D_DEBUG( "DirectFB/IDirectFBInputDevice: Unknown event type detected (0x%x), skipping!\n", evt->type ); + } + + return RS_OK; +} + diff --git a/Source/DirectFB/src/input/idirectfbinputdevice.h b/Source/DirectFB/src/input/idirectfbinputdevice.h new file mode 100755 index 0000000..65bdc23 --- /dev/null +++ b/Source/DirectFB/src/input/idirectfbinputdevice.h @@ -0,0 +1,40 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __IDIRECTFBINPUTDEVICE_H__ +#define __IDIRECTFBINPUTDEVICE_H__ + +#include + +/* + * initializes input device, adds it to input listeners and initializes mutexes + */ +DFBResult IDirectFBInputDevice_Construct( IDirectFBInputDevice *thiz, + CoreInputDevice *device ); + +#endif diff --git a/Source/DirectFB/src/media/Makefile.am b/Source/DirectFB/src/media/Makefile.am new file mode 100755 index 0000000..cb2ae12 --- /dev/null +++ b/Source/DirectFB/src/media/Makefile.am @@ -0,0 +1,29 @@ +## Makefile.am for DirectFB/src/media + +INCLUDES = \ + -I$(top_builddir)/lib \ + -I$(top_builddir)/include \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/lib \ + -I$(top_srcdir)/src + + +internalincludedir = $(INTERNALINCLUDEDIR)/media + +internalinclude_HEADERS = \ + idirectfbdatabuffer.h \ + idirectfbfont.h \ + idirectfbimageprovider.h \ + idirectfbvideoprovider.h + + +noinst_LTLIBRARIES = libdirectfb_media.la + +libdirectfb_media_la_SOURCES = \ + idirectfbdatabuffer.c \ + idirectfbdatabuffer_file.c \ + idirectfbdatabuffer_memory.c \ + idirectfbdatabuffer_streamed.c \ + idirectfbfont.c \ + idirectfbimageprovider.c \ + idirectfbvideoprovider.c diff --git a/Source/DirectFB/src/media/Makefile.in b/Source/DirectFB/src/media/Makefile.in new file mode 100755 index 0000000..930fe11 --- /dev/null +++ b/Source/DirectFB/src/media/Makefile.in @@ -0,0 +1,570 @@ +# Makefile.in generated by automake 1.10.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = src/media +DIST_COMMON = $(internalinclude_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/as-ac-expand.m4 \ + $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libdirectfb_media_la_LIBADD = +am_libdirectfb_media_la_OBJECTS = idirectfbdatabuffer.lo \ + idirectfbdatabuffer_file.lo idirectfbdatabuffer_memory.lo \ + idirectfbdatabuffer_streamed.lo idirectfbfont.lo \ + idirectfbimageprovider.lo idirectfbvideoprovider.lo +libdirectfb_media_la_OBJECTS = $(am_libdirectfb_media_la_OBJECTS) +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libdirectfb_media_la_SOURCES) +DIST_SOURCES = $(libdirectfb_media_la_SOURCES) +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(internalincludedir)" +internalincludeHEADERS_INSTALL = $(INSTALL_HEADER) +HEADERS = $(internalinclude_HEADERS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AS = @AS@ +ASFLAGS = @ASFLAGS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIR = @DATADIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DFB_CFLAGS_OMIT_FRAME_POINTER = @DFB_CFLAGS_OMIT_FRAME_POINTER@ +DFB_INTERNAL_CFLAGS = @DFB_INTERNAL_CFLAGS@ +DFB_LDFLAGS = @DFB_LDFLAGS@ +DFB_SMOOTH_SCALING = @DFB_SMOOTH_SCALING@ +DIRECTFB_BINARY_AGE = @DIRECTFB_BINARY_AGE@ +DIRECTFB_CSOURCE = @DIRECTFB_CSOURCE@ +DIRECTFB_INTERFACE_AGE = @DIRECTFB_INTERFACE_AGE@ +DIRECTFB_MAJOR_VERSION = @DIRECTFB_MAJOR_VERSION@ +DIRECTFB_MICRO_VERSION = @DIRECTFB_MICRO_VERSION@ +DIRECTFB_MINOR_VERSION = @DIRECTFB_MINOR_VERSION@ +DIRECTFB_VERSION = @DIRECTFB_VERSION@ +DIRECT_BUILD_DEBUG = @DIRECT_BUILD_DEBUG@ +DIRECT_BUILD_DEBUGS = @DIRECT_BUILD_DEBUGS@ +DIRECT_BUILD_GETTID = @DIRECT_BUILD_GETTID@ +DIRECT_BUILD_NETWORK = @DIRECT_BUILD_NETWORK@ +DIRECT_BUILD_STDBOOL = @DIRECT_BUILD_STDBOOL@ +DIRECT_BUILD_TEXT = @DIRECT_BUILD_TEXT@ +DIRECT_BUILD_TRACE = @DIRECT_BUILD_TRACE@ +DSYMUTIL = @DSYMUTIL@ +DYNLIB = @DYNLIB@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +FREETYPE_CFLAGS = @FREETYPE_CFLAGS@ +FREETYPE_LIBS = @FREETYPE_LIBS@ +FREETYPE_PROVIDER = @FREETYPE_PROVIDER@ +FUSION_BUILD_KERNEL = @FUSION_BUILD_KERNEL@ +FUSION_BUILD_MULTI = @FUSION_BUILD_MULTI@ +FUSION_MESSAGE_SIZE = @FUSION_MESSAGE_SIZE@ +GIF_PROVIDER = @GIF_PROVIDER@ +GREP = @GREP@ +HAVE_LINUX = @HAVE_LINUX@ +INCLUDEDIR = @INCLUDEDIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTERNALINCLUDEDIR = @INTERNALINCLUDEDIR@ +JPEG_PROVIDER = @JPEG_PROVIDER@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBJPEG = @LIBJPEG@ +LIBOBJS = @LIBOBJS@ +LIBPNG = @LIBPNG@ +LIBPNG_CONFIG = @LIBPNG_CONFIG@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_AGE = @LT_AGE@ +LT_BINARY = @LT_BINARY@ +LT_CURRENT = @LT_CURRENT@ +LT_RELEASE = @LT_RELEASE@ +LT_REVISION = @LT_REVISION@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MAN2HTML = @MAN2HTML@ +MKDIR_P = @MKDIR_P@ +MODULEDIR = @MODULEDIR@ +MODULEDIRNAME = @MODULEDIRNAME@ +NMEDIT = @NMEDIT@ +OBJEXT = @OBJEXT@ +OSX_LIBS = @OSX_LIBS@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PNG_PROVIDER = @PNG_PROVIDER@ +RANLIB = @RANLIB@ +RUNTIME_SYSROOT = @RUNTIME_SYSROOT@ +SDL_CFLAGS = @SDL_CFLAGS@ +SDL_LIBS = @SDL_LIBS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOPATH = @SOPATH@ +STRIP = @STRIP@ +SYSCONFDIR = @SYSCONFDIR@ +SYSFS_LIBS = @SYSFS_LIBS@ +THREADFLAGS = @THREADFLAGS@ +THREADLIB = @THREADLIB@ +TSLIB_CFLAGS = @TSLIB_CFLAGS@ +TSLIB_LIBS = @TSLIB_LIBS@ +VERSION = @VERSION@ +VNC_CFLAGS = @VNC_CFLAGS@ +VNC_CONFIG = @VNC_CONFIG@ +VNC_LIBS = @VNC_LIBS@ +X11_CFLAGS = @X11_CFLAGS@ +X11_LIBS = @X11_LIBS@ +ZLIB_LIBS = @ZLIB_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +INCLUDES = \ + -I$(top_builddir)/lib \ + -I$(top_builddir)/include \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/lib \ + -I$(top_srcdir)/src + +internalincludedir = $(INTERNALINCLUDEDIR)/media +internalinclude_HEADERS = \ + idirectfbdatabuffer.h \ + idirectfbfont.h \ + idirectfbimageprovider.h \ + idirectfbvideoprovider.h + +noinst_LTLIBRARIES = libdirectfb_media.la +libdirectfb_media_la_SOURCES = \ + idirectfbdatabuffer.c \ + idirectfbdatabuffer_file.c \ + idirectfbdatabuffer_memory.c \ + idirectfbdatabuffer_streamed.c \ + idirectfbfont.c \ + idirectfbimageprovider.c \ + idirectfbvideoprovider.c + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/media/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/media/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libdirectfb_media.la: $(libdirectfb_media_la_OBJECTS) $(libdirectfb_media_la_DEPENDENCIES) + $(LINK) $(libdirectfb_media_la_OBJECTS) $(libdirectfb_media_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/idirectfbdatabuffer.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/idirectfbdatabuffer_file.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/idirectfbdatabuffer_memory.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/idirectfbdatabuffer_streamed.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/idirectfbfont.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/idirectfbimageprovider.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/idirectfbvideoprovider.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-internalincludeHEADERS: $(internalinclude_HEADERS) + @$(NORMAL_INSTALL) + test -z "$(internalincludedir)" || $(MKDIR_P) "$(DESTDIR)$(internalincludedir)" + @list='$(internalinclude_HEADERS)'; for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + f=$(am__strip_dir) \ + echo " $(internalincludeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(internalincludedir)/$$f'"; \ + $(internalincludeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(internalincludedir)/$$f"; \ + done + +uninstall-internalincludeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(internalinclude_HEADERS)'; for p in $$list; do \ + f=$(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(internalincludedir)/$$f'"; \ + rm -f "$(DESTDIR)$(internalincludedir)/$$f"; \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(internalincludedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: install-internalincludeHEADERS + +install-dvi: install-dvi-am + +install-exec-am: + +install-html: install-html-am + +install-info: install-info-am + +install-man: + +install-pdf: install-pdf-am + +install-ps: install-ps-am + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-internalincludeHEADERS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am \ + install-internalincludeHEADERS install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-internalincludeHEADERS + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/Source/DirectFB/src/media/idirectfbdatabuffer.c b/Source/DirectFB/src/media/idirectfbdatabuffer.c new file mode 100755 index 0000000..68ccc4e --- /dev/null +++ b/Source/DirectFB/src/media/idirectfbdatabuffer.c @@ -0,0 +1,264 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include +#include +#include + +#include +#include + +#include + +#include + +#include +#include + +#include + +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + + +void +IDirectFBDataBuffer_Destruct( IDirectFBDataBuffer *thiz ) +{ + IDirectFBDataBuffer_data *data = (IDirectFBDataBuffer_data*) thiz->priv; + + if (data->filename) + D_FREE( data->filename ); + + DIRECT_DEALLOCATE_INTERFACE( thiz ); +} + +static DirectResult +IDirectFBDataBuffer_AddRef( IDirectFBDataBuffer *thiz ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBDataBuffer) + + data->ref++; + + return DFB_OK; +} + +static DirectResult +IDirectFBDataBuffer_Release( IDirectFBDataBuffer *thiz ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBDataBuffer) + + if (--data->ref == 0) + IDirectFBDataBuffer_Destruct( thiz ); + + return DFB_OK; +} + +static DFBResult +IDirectFBDataBuffer_Flush( IDirectFBDataBuffer *thiz ) +{ + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFBDataBuffer_Finish( IDirectFBDataBuffer *thiz ) +{ + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFBDataBuffer_SeekTo( IDirectFBDataBuffer *thiz, + unsigned int offset ) +{ + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFBDataBuffer_GetPosition( IDirectFBDataBuffer *thiz, + unsigned int *offset ) +{ + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFBDataBuffer_GetLength( IDirectFBDataBuffer *thiz, + unsigned int *length ) +{ + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFBDataBuffer_WaitForData( IDirectFBDataBuffer *thiz, + unsigned int length ) +{ + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFBDataBuffer_WaitForDataWithTimeout( IDirectFBDataBuffer *thiz, + unsigned int length, + unsigned int seconds, + unsigned int milli_seconds ) +{ + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFBDataBuffer_GetData( IDirectFBDataBuffer *thiz, + unsigned int length, + void *data, + unsigned int *read ) +{ + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFBDataBuffer_PeekData( IDirectFBDataBuffer *thiz, + unsigned int length, + int offset, + void *data, + unsigned int *read ) +{ + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFBDataBuffer_HasData( IDirectFBDataBuffer *thiz ) +{ + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFBDataBuffer_PutData( IDirectFBDataBuffer *thiz, + const void *data, + unsigned int length ) +{ + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFBDataBuffer_CreateImageProvider( IDirectFBDataBuffer *thiz, + IDirectFBImageProvider **interface ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBDataBuffer) + + /* Check arguments */ + if (!interface) + return DFB_INVARG; + +#ifndef DIRECTFB_PURE_VOODOO + return IDirectFBImageProvider_CreateFromBuffer( thiz, data->core, interface ); +#else + D_BUG( "%s in pure Voodoo build", __FUNCTION__ ); + return DFB_BUG; +#endif +} + +static DFBResult +IDirectFBDataBuffer_CreateVideoProvider( IDirectFBDataBuffer *thiz, + IDirectFBVideoProvider **interface ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBDataBuffer) + + /* Check arguments */ + if (!interface) + return DFB_INVARG; + +#ifndef DIRECTFB_PURE_VOODOO + return IDirectFBVideoProvider_CreateFromBuffer( thiz, data->core, interface ); +#else + D_BUG( "%s in pure Voodoo build", __FUNCTION__ ); + return DFB_BUG; +#endif +} + +static DFBResult +IDirectFBDataBuffer_CreateFont( IDirectFBDataBuffer *thiz, + const DFBFontDescription *desc, + IDirectFBFont **interface ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBDataBuffer) + + /* Check arguments */ + if (!interface || !desc) + return DFB_INVARG; + +#ifndef DIRECTFB_PURE_VOODOO + return IDirectFBFont_CreateFromBuffer( thiz, data->core, desc, interface ); +#else + D_BUG( "%s in pure Voodoo build", __FUNCTION__ ); + return DFB_BUG; +#endif +} + +DFBResult +IDirectFBDataBuffer_Construct( IDirectFBDataBuffer *thiz, + const char *filename, + CoreDFB *core ) +{ + DIRECT_ALLOCATE_INTERFACE_DATA(thiz, IDirectFBDataBuffer) + + data->ref = 1; + data->core = core; + + if (filename) + data->filename = D_STRDUP( filename ); + + thiz->AddRef = IDirectFBDataBuffer_AddRef; + thiz->Release = IDirectFBDataBuffer_Release; + thiz->Flush = IDirectFBDataBuffer_Flush; + thiz->Finish = IDirectFBDataBuffer_Finish; + thiz->SeekTo = IDirectFBDataBuffer_SeekTo; + thiz->GetPosition = IDirectFBDataBuffer_GetPosition; + thiz->GetLength = IDirectFBDataBuffer_GetLength; + thiz->WaitForData = IDirectFBDataBuffer_WaitForData; + thiz->WaitForDataWithTimeout = IDirectFBDataBuffer_WaitForDataWithTimeout; + thiz->GetData = IDirectFBDataBuffer_GetData; + thiz->PeekData = IDirectFBDataBuffer_PeekData; + thiz->HasData = IDirectFBDataBuffer_HasData; + thiz->PutData = IDirectFBDataBuffer_PutData; + thiz->CreateImageProvider = IDirectFBDataBuffer_CreateImageProvider; + thiz->CreateVideoProvider = IDirectFBDataBuffer_CreateVideoProvider; + thiz->CreateFont = IDirectFBDataBuffer_CreateFont; + + return DFB_OK; +} + diff --git a/Source/DirectFB/src/media/idirectfbdatabuffer.h b/Source/DirectFB/src/media/idirectfbdatabuffer.h new file mode 100755 index 0000000..4b19eb0 --- /dev/null +++ b/Source/DirectFB/src/media/idirectfbdatabuffer.h @@ -0,0 +1,104 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __IDIRECTFBDATABUFFER_H__ +#define __IDIRECTFBDATABUFFER_H__ + +#include + +/* + * private data struct of IDirectFBDataBuffer + */ +typedef struct { + int ref; /* reference counter */ + char *filename; /* Only set if databuffer is created from file. */ + + CoreDFB *core; + + bool is_memory; +} IDirectFBDataBuffer_data; + +/* + * private data struct of IDirectFBDataBuffer_File + */ +typedef struct { + IDirectFBDataBuffer_data base; + + DirectStream *stream; + pthread_mutex_t mutex; +} IDirectFBDataBuffer_File_data; + +/* + * private data struct of IDirectFBDataBuffer_Memory + */ +typedef struct { + IDirectFBDataBuffer_data base; + + const void *buffer; + unsigned int length; + + unsigned int pos; +} IDirectFBDataBuffer_Memory_data; + +/* + * base constructor + * + * If the databuffer is created for a file, the filename can be provided + * for fallbacks. + */ +DFBResult IDirectFBDataBuffer_Construct( IDirectFBDataBuffer *thiz, + const char *filename, + CoreDFB *core ); + +/* + * base destructor + */ +void IDirectFBDataBuffer_Destruct( IDirectFBDataBuffer *thiz ); + +/* + * generic streamed data buffer + */ +DFBResult IDirectFBDataBuffer_Streamed_Construct( IDirectFBDataBuffer *thiz, + CoreDFB *core ); + +/* + * file based static data buffer + */ +DFBResult IDirectFBDataBuffer_File_Construct( IDirectFBDataBuffer *thiz, + const char *filename, + CoreDFB *core ); + +/* + * memory based static data buffer + */ +DFBResult IDirectFBDataBuffer_Memory_Construct( IDirectFBDataBuffer *thiz, + const void *data, + unsigned int length, + CoreDFB *core ); + +#endif diff --git a/Source/DirectFB/src/media/idirectfbdatabuffer_file.c b/Source/DirectFB/src/media/idirectfbdatabuffer_file.c new file mode 100755 index 0000000..245ce02 --- /dev/null +++ b/Source/DirectFB/src/media/idirectfbdatabuffer_file.c @@ -0,0 +1,297 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include + +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include + + + +static void +IDirectFBDataBuffer_File_Destruct( IDirectFBDataBuffer *thiz ) +{ + IDirectFBDataBuffer_File_data *data = + (IDirectFBDataBuffer_File_data*) thiz->priv; + + direct_stream_destroy( data->stream ); + + pthread_mutex_destroy( &data->mutex ); + + IDirectFBDataBuffer_Destruct( thiz ); +} + +static DirectResult +IDirectFBDataBuffer_File_Release( IDirectFBDataBuffer *thiz ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBDataBuffer) + + if (--data->ref == 0) + IDirectFBDataBuffer_File_Destruct( thiz ); + + return DFB_OK; +} + +static DFBResult +IDirectFBDataBuffer_File_Flush( IDirectFBDataBuffer *thiz ) +{ + return DFB_UNSUPPORTED; +} + +static DFBResult +IDirectFBDataBuffer_File_Finish( IDirectFBDataBuffer *thiz ) +{ + return DFB_UNSUPPORTED; +} + +static DFBResult +IDirectFBDataBuffer_File_SeekTo( IDirectFBDataBuffer *thiz, + unsigned int offset ) +{ + DFBResult ret; + + DIRECT_INTERFACE_GET_DATA(IDirectFBDataBuffer_File) + + if (!direct_stream_seekable( data->stream )) + return DFB_UNSUPPORTED; + + pthread_mutex_lock( &data->mutex ); + ret = direct_stream_seek( data->stream, offset ); + pthread_mutex_unlock( &data->mutex ); + + return ret; +} + +static DFBResult +IDirectFBDataBuffer_File_GetPosition( IDirectFBDataBuffer *thiz, + unsigned int *offset ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBDataBuffer_File) + + if (!offset) + return DFB_INVARG; + + *offset = direct_stream_offset( data->stream ); + + return DFB_OK; +} + +static DFBResult +IDirectFBDataBuffer_File_GetLength( IDirectFBDataBuffer *thiz, + unsigned int *length ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBDataBuffer_File) + + if (!length) + return DFB_INVARG; + + *length = direct_stream_length( data->stream ); + + return DFB_OK; +} + +static DFBResult +IDirectFBDataBuffer_File_WaitForData( IDirectFBDataBuffer *thiz, + unsigned int length ) +{ + DFBResult ret; + + DIRECT_INTERFACE_GET_DATA(IDirectFBDataBuffer_File) + + pthread_mutex_lock( &data->mutex ); + ret = direct_stream_wait( data->stream, length, NULL ); + pthread_mutex_unlock( &data->mutex ); + + return ret; +} + +static DFBResult +IDirectFBDataBuffer_File_WaitForDataWithTimeout( IDirectFBDataBuffer *thiz, + unsigned int length, + unsigned int seconds, + unsigned int milli_seconds ) +{ + DFBResult ret; + struct timeval tv; + + DIRECT_INTERFACE_GET_DATA(IDirectFBDataBuffer_File) + + tv.tv_sec = seconds; + tv.tv_usec = milli_seconds*1000; + + while (pthread_mutex_trylock( &data->mutex )) { + struct timespec t, r; + + if (errno != EBUSY) + return errno2result( errno ); + + t.tv_sec = 0; + t.tv_nsec = 10000; + nanosleep( &t, &r ); + + tv.tv_usec -= (t.tv_nsec - r.tv_nsec + 500) / 1000; + if (tv.tv_usec < 0) { + if (tv.tv_sec < 1) + return DFB_TIMEOUT; + + tv.tv_sec--; + tv.tv_usec += 999999; + } + } + + ret = direct_stream_wait( data->stream, length, &tv ); + + pthread_mutex_unlock( &data->mutex ); + + return ret; +} + +static DFBResult +IDirectFBDataBuffer_File_GetData( IDirectFBDataBuffer *thiz, + unsigned int length, + void *data_buffer, + unsigned int *read_out ) +{ + DFBResult ret; + + DIRECT_INTERFACE_GET_DATA(IDirectFBDataBuffer_File) + + if (!data_buffer || !length) + return DFB_INVARG; + + pthread_mutex_lock( &data->mutex ); + ret = direct_stream_read( data->stream, length, data_buffer, read_out ); + pthread_mutex_unlock( &data->mutex ); + + return ret; +} + +static DFBResult +IDirectFBDataBuffer_File_PeekData( IDirectFBDataBuffer *thiz, + unsigned int length, + int offset, + void *data_buffer, + unsigned int *read_out ) +{ + DFBResult ret; + + DIRECT_INTERFACE_GET_DATA(IDirectFBDataBuffer_File) + + if (!data_buffer || !length) + return DFB_INVARG; + + pthread_mutex_lock( &data->mutex ); + ret = direct_stream_peek( data->stream, length, + offset, data_buffer, read_out ); + pthread_mutex_unlock( &data->mutex ); + + return ret; +} + +static DFBResult +IDirectFBDataBuffer_File_HasData( IDirectFBDataBuffer *thiz ) +{ + struct timeval tv = {0,0}; + + DIRECT_INTERFACE_GET_DATA(IDirectFBDataBuffer_File) + + return direct_stream_wait( data->stream, 1, &tv ); +} + +static DFBResult +IDirectFBDataBuffer_File_PutData( IDirectFBDataBuffer *thiz, + const void *data_buffer, + unsigned int length ) +{ + return DFB_UNSUPPORTED; +} + +DFBResult +IDirectFBDataBuffer_File_Construct( IDirectFBDataBuffer *thiz, + const char *filename, + CoreDFB *core ) +{ + DFBResult ret; + + DIRECT_ALLOCATE_INTERFACE_DATA(thiz, IDirectFBDataBuffer_File) + + ret = IDirectFBDataBuffer_Construct( thiz, filename, core ); + if (ret) + return ret; + + ret = direct_stream_create( filename, &data->stream ); + if (ret) { + DIRECT_DEALLOCATE_INTERFACE( thiz ); + return ret; + } + + direct_util_recursive_pthread_mutex_init( &data->mutex ); + + thiz->Release = IDirectFBDataBuffer_File_Release; + thiz->Flush = IDirectFBDataBuffer_File_Flush; + thiz->Finish = IDirectFBDataBuffer_File_Finish; + thiz->SeekTo = IDirectFBDataBuffer_File_SeekTo; + thiz->GetPosition = IDirectFBDataBuffer_File_GetPosition; + thiz->GetLength = IDirectFBDataBuffer_File_GetLength; + thiz->WaitForData = IDirectFBDataBuffer_File_WaitForData; + thiz->WaitForDataWithTimeout = IDirectFBDataBuffer_File_WaitForDataWithTimeout; + thiz->GetData = IDirectFBDataBuffer_File_GetData; + thiz->PeekData = IDirectFBDataBuffer_File_PeekData; + thiz->HasData = IDirectFBDataBuffer_File_HasData; + thiz->PutData = IDirectFBDataBuffer_File_PutData; + + return DFB_OK; +} + diff --git a/Source/DirectFB/src/media/idirectfbdatabuffer_memory.c b/Source/DirectFB/src/media/idirectfbdatabuffer_memory.c new file mode 100755 index 0000000..233e4b4 --- /dev/null +++ b/Source/DirectFB/src/media/idirectfbdatabuffer_memory.c @@ -0,0 +1,266 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include +#include +#include + +#include +#include + +#include + +#include + +#include +#include + +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include + + +static void +IDirectFBDataBuffer_Memory_Destruct( IDirectFBDataBuffer *thiz ) +{ + IDirectFBDataBuffer_Destruct( thiz ); +} + +static DirectResult +IDirectFBDataBuffer_Memory_Release( IDirectFBDataBuffer *thiz ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBDataBuffer) + + if (--data->ref == 0) + IDirectFBDataBuffer_Memory_Destruct( thiz ); + + return DFB_OK; +} + +static DFBResult +IDirectFBDataBuffer_Memory_Flush( IDirectFBDataBuffer *thiz ) +{ + return DFB_UNSUPPORTED; +} + +static DFBResult +IDirectFBDataBuffer_Memory_Finish( IDirectFBDataBuffer *thiz ) +{ + return DFB_UNSUPPORTED; +} + +static DFBResult +IDirectFBDataBuffer_Memory_SeekTo( IDirectFBDataBuffer *thiz, + unsigned int offset ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBDataBuffer_Memory) + + if (offset >= data->length) + return DFB_INVARG; + + data->pos = offset; + + return DFB_OK; +} + +static DFBResult +IDirectFBDataBuffer_Memory_GetPosition( IDirectFBDataBuffer *thiz, + unsigned int *offset ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBDataBuffer_Memory) + + if (!offset) + return DFB_INVARG; + + *offset = data->pos; + + return DFB_OK; +} + +static DFBResult +IDirectFBDataBuffer_Memory_GetLength( IDirectFBDataBuffer *thiz, + unsigned int *length ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBDataBuffer_Memory) + + if (!length) + return DFB_INVARG; + + *length = data->length; + + return DFB_OK; +} + +static DFBResult +IDirectFBDataBuffer_Memory_WaitForData( IDirectFBDataBuffer *thiz, + unsigned int length ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBDataBuffer_Memory) + + if (data->pos + length > data->length) + return DFB_EOF; + + return DFB_OK; +} + +static DFBResult +IDirectFBDataBuffer_Memory_WaitForDataWithTimeout( IDirectFBDataBuffer *thiz, + unsigned int length, + unsigned int seconds, + unsigned int milli_seconds ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBDataBuffer_Memory) + + if (data->pos + length > data->length) + return DFB_EOF; + + return DFB_OK; +} + +static DFBResult +IDirectFBDataBuffer_Memory_GetData( IDirectFBDataBuffer *thiz, + unsigned int length, + void *data_buffer, + unsigned int *read_out ) +{ + unsigned int size; + + DIRECT_INTERFACE_GET_DATA(IDirectFBDataBuffer_Memory) + + if (!data_buffer || !length) + return DFB_INVARG; + + if (data->pos >= data->length) + return DFB_EOF; + + size = MIN( length, data->length - data->pos ); + + direct_memcpy( data_buffer, data->buffer + data->pos, size ); + + data->pos += size; + + if (read_out) + *read_out = size; + + return DFB_OK; +} + +static DFBResult +IDirectFBDataBuffer_Memory_PeekData( IDirectFBDataBuffer *thiz, + unsigned int length, + int offset, + void *data_buffer, + unsigned int *read_out ) +{ + unsigned int size; + + DIRECT_INTERFACE_GET_DATA(IDirectFBDataBuffer_Memory) + + if (!data_buffer || !length) + return DFB_INVARG; + + if (data->pos + offset >= data->length) + return DFB_EOF; + + size = MIN( length, data->length - data->pos - offset ); + + direct_memcpy( data_buffer, data->buffer + data->pos + offset, size ); + + if (read_out) + *read_out = size; + + return DFB_OK; +} + +static DFBResult +IDirectFBDataBuffer_Memory_HasData( IDirectFBDataBuffer *thiz ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBDataBuffer_Memory) + + if (data->pos >= data->length) + return DFB_EOF; + + return DFB_OK; +} + +static DFBResult +IDirectFBDataBuffer_Memory_PutData( IDirectFBDataBuffer *thiz, + const void *data_buffer, + unsigned int length ) +{ + return DFB_UNSUPPORTED; +} + +DFBResult +IDirectFBDataBuffer_Memory_Construct( IDirectFBDataBuffer *thiz, + const void *data_buffer, + unsigned int length, + CoreDFB *core ) +{ + DFBResult ret; + + DIRECT_ALLOCATE_INTERFACE_DATA(thiz, IDirectFBDataBuffer_Memory) + + ret = IDirectFBDataBuffer_Construct( thiz, NULL, core ); + if (ret) + return ret; + + data->buffer = data_buffer; + data->length = length; + + data->base.is_memory = true; + + thiz->Release = IDirectFBDataBuffer_Memory_Release; + thiz->Flush = IDirectFBDataBuffer_Memory_Flush; + thiz->Finish = IDirectFBDataBuffer_Memory_Finish; + thiz->SeekTo = IDirectFBDataBuffer_Memory_SeekTo; + thiz->GetPosition = IDirectFBDataBuffer_Memory_GetPosition; + thiz->GetLength = IDirectFBDataBuffer_Memory_GetLength; + thiz->WaitForData = IDirectFBDataBuffer_Memory_WaitForData; + thiz->WaitForDataWithTimeout = IDirectFBDataBuffer_Memory_WaitForDataWithTimeout; + thiz->GetData = IDirectFBDataBuffer_Memory_GetData; + thiz->PeekData = IDirectFBDataBuffer_Memory_PeekData; + thiz->HasData = IDirectFBDataBuffer_Memory_HasData; + thiz->PutData = IDirectFBDataBuffer_Memory_PutData; + + return DFB_OK; +} + diff --git a/Source/DirectFB/src/media/idirectfbdatabuffer_streamed.c b/Source/DirectFB/src/media/idirectfbdatabuffer_streamed.c new file mode 100755 index 0000000..5ce1168 --- /dev/null +++ b/Source/DirectFB/src/media/idirectfbdatabuffer_streamed.c @@ -0,0 +1,529 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include +#include +#include + +#include +#include + +#include + +#include + +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include + +#include + +typedef struct { + DirectLink link; + + void *data; /* actual data hold */ + unsigned int length; /* length of chunk */ + + unsigned int done; /* number of bytes already consumed */ +} DataChunk; + +static DataChunk * +create_chunk( const void *data, int length ); + +static void +destroy_chunk( DataChunk *chunk ); + +/* + * private data struct of IDirectFBDataBuffer_Streamed + */ +typedef struct { + IDirectFBDataBuffer_data base; + + DirectLink *chunks; /* data chunks */ + + unsigned int length; /* total length of all chunks */ + + bool finished; /* whether Finish() has been called */ + + pthread_mutex_t chunks_mutex; /* mutex lock for accessing + the chunk list */ + + pthread_cond_t wait_condition; /* condition used for idle + wait in WaitForEvent() */ +} IDirectFBDataBuffer_Streamed_data; + +static void +DestroyAllChunks( IDirectFBDataBuffer_Streamed_data *data ); + +static void +ReadChunkData( IDirectFBDataBuffer_Streamed_data *data, + void *buffer, + unsigned int offset, + unsigned int length, + bool flush ); + + +static void +IDirectFBDataBuffer_Streamed_Destruct( IDirectFBDataBuffer *thiz ) +{ + IDirectFBDataBuffer_Streamed_data *data = + (IDirectFBDataBuffer_Streamed_data*) thiz->priv; + + pthread_cond_destroy( &data->wait_condition ); + pthread_mutex_destroy( &data->chunks_mutex ); + + IDirectFBDataBuffer_Destruct( thiz ); +} + +static DirectResult +IDirectFBDataBuffer_Streamed_Release( IDirectFBDataBuffer *thiz ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBDataBuffer) + + if (--data->ref == 0) + IDirectFBDataBuffer_Streamed_Destruct( thiz ); + + return DFB_OK; +} + +static DFBResult +IDirectFBDataBuffer_Streamed_Flush( IDirectFBDataBuffer *thiz ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBDataBuffer_Streamed) + + pthread_mutex_lock( &data->chunks_mutex ); + + DestroyAllChunks( data ); + + pthread_mutex_unlock( &data->chunks_mutex ); + + return DFB_OK; +} + +static DFBResult +IDirectFBDataBuffer_Streamed_Finish( IDirectFBDataBuffer *thiz ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBDataBuffer_Streamed) + + if (!data->finished) { + data->finished = true; + + pthread_mutex_lock( &data->chunks_mutex ); + pthread_cond_broadcast( &data->wait_condition ); + pthread_mutex_unlock( &data->chunks_mutex ); + } + + return DFB_OK; +} + +static DFBResult +IDirectFBDataBuffer_Streamed_SeekTo( IDirectFBDataBuffer *thiz, + unsigned int offset ) +{ + return DFB_UNSUPPORTED; +} + +static DFBResult +IDirectFBDataBuffer_Streamed_GetPosition( IDirectFBDataBuffer *thiz, + unsigned int *offset ) +{ + return DFB_UNSUPPORTED; +} + +static DFBResult +IDirectFBDataBuffer_Streamed_GetLength( IDirectFBDataBuffer *thiz, + unsigned int *length ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBDataBuffer_Streamed) + + /* Check arguments. */ + if (!length) + return DFB_INVARG; + + /* Return total length of all chunks. */ + *length = data->length; + + return DFB_OK; +} + +static DFBResult +IDirectFBDataBuffer_Streamed_WaitForData( IDirectFBDataBuffer *thiz, + unsigned int length ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBDataBuffer_Streamed) + + if (data->finished && !data->chunks) + return DFB_EOF; + + pthread_mutex_lock( &data->chunks_mutex ); + + while (data->length < length && !data->finished) + pthread_cond_wait( &data->wait_condition, &data->chunks_mutex ); + + pthread_mutex_unlock( &data->chunks_mutex ); + + return DFB_OK; +} + +static DFBResult +IDirectFBDataBuffer_Streamed_WaitForDataWithTimeout( IDirectFBDataBuffer *thiz, + unsigned int length, + unsigned int seconds, + unsigned int milli_seconds ) +{ + struct timespec timeout; + DFBResult ret = DFB_OK; + bool locked = false; + long int nano_seconds = milli_seconds * 1000000; + + DIRECT_INTERFACE_GET_DATA(IDirectFBDataBuffer_Streamed) + + if (data->finished && !data->chunks) + return DFB_EOF; + + if (pthread_mutex_trylock( &data->chunks_mutex ) == 0) { + if (data->length >= length) { + pthread_mutex_unlock( &data->chunks_mutex ); + + return DFB_OK; + } + + locked = true; + } + + direct_util_get_monotonic_pthread_timeout(&timeout, seconds, nano_seconds); + + if (!locked) + pthread_mutex_lock( &data->chunks_mutex ); + + while (data->length < length && !data->finished) { + if (pthread_cond_timedwait( &data->wait_condition, + &data->chunks_mutex, + &timeout ) == ETIMEDOUT) + { + ret = DFB_TIMEOUT; + break; + } + } + + pthread_mutex_unlock( &data->chunks_mutex ); + + return ret; +} + +static DFBResult +IDirectFBDataBuffer_Streamed_GetData( IDirectFBDataBuffer *thiz, + unsigned int length, + void *data_buffer, + unsigned int *read_out ) +{ + unsigned int len; + + DIRECT_INTERFACE_GET_DATA(IDirectFBDataBuffer_Streamed) + + if (!data_buffer || !length) + return DFB_INVARG; + + pthread_mutex_lock( &data->chunks_mutex ); + + if (!data->chunks) { + pthread_mutex_unlock( &data->chunks_mutex ); + return data->finished ? DFB_EOF : DFB_BUFFEREMPTY; + } + + /* Calculate maximum number of bytes to be read. */ + len = MIN( length, data->length ); + + /* Read data from chunks (destructive). */ + ReadChunkData( data, data_buffer, 0, len, true ); + + /* Decrease total number of bytes. */ + data->length -= len; + + /* Return number of bytes read. */ + if (read_out) + *read_out = len; + + pthread_mutex_unlock( &data->chunks_mutex ); + + return DFB_OK; +} + +static DFBResult +IDirectFBDataBuffer_Streamed_PeekData( IDirectFBDataBuffer *thiz, + unsigned int length, + int offset, + void *data_buffer, + unsigned int *read_out ) +{ + unsigned int len; + + DIRECT_INTERFACE_GET_DATA(IDirectFBDataBuffer_Streamed) + + if (!data_buffer || !length || offset < 0) + return DFB_INVARG; + + pthread_mutex_lock( &data->chunks_mutex ); + + if (!data->chunks || (unsigned int) offset >= data->length) { + pthread_mutex_unlock( &data->chunks_mutex ); + return data->finished ? DFB_EOF : DFB_BUFFEREMPTY; + } + + /* Calculate maximum number of bytes to be read. */ + len = MIN( length, data->length - offset ); + + /* Read data from chunks (non-destructive). */ + ReadChunkData( data, data_buffer, offset, len, false ); + + /* Return number of bytes read. */ + if (read_out) + *read_out = len; + + pthread_mutex_unlock( &data->chunks_mutex ); + + return DFB_OK; +} + +static DFBResult +IDirectFBDataBuffer_Streamed_HasData( IDirectFBDataBuffer *thiz ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBDataBuffer_Streamed) + + /* If there's no chunk there's no data. */ + if (!data->chunks) + return data->finished ? DFB_EOF : DFB_BUFFEREMPTY; + + return DFB_OK; +} + +static DFBResult +IDirectFBDataBuffer_Streamed_PutData( IDirectFBDataBuffer *thiz, + const void *data_buffer, + unsigned int length ) +{ + DataChunk *chunk; + + DIRECT_INTERFACE_GET_DATA(IDirectFBDataBuffer_Streamed) + + /* Check arguments. */ + if (!data_buffer || !length) + return DFB_INVARG; + + /* Fail if Finish() has been called. */ + if (data->finished) + return DFB_UNSUPPORTED; + + /* Create a chunk containing a copy of the provided data. */ + chunk = create_chunk( data_buffer, length ); + if (!chunk) + return DFB_NOSYSTEMMEMORY; + + pthread_mutex_lock( &data->chunks_mutex ); + + /* Append new chunk. */ + direct_list_append( &data->chunks, &chunk->link ); + + /* Increase total length. */ + data->length += length; + + pthread_cond_broadcast( &data->wait_condition ); + + pthread_mutex_unlock( &data->chunks_mutex ); + + return DFB_OK; +} + +DFBResult +IDirectFBDataBuffer_Streamed_Construct( IDirectFBDataBuffer *thiz, + CoreDFB *core ) +{ + DFBResult ret; + + DIRECT_ALLOCATE_INTERFACE_DATA(thiz, IDirectFBDataBuffer_Streamed) + + ret = IDirectFBDataBuffer_Construct( thiz, NULL, core ); + if (ret) + return ret; + + direct_util_recursive_pthread_mutex_init( &data->chunks_mutex ); + direct_util_monotonic_pthread_cond_init( &data->wait_condition ); + + thiz->Release = IDirectFBDataBuffer_Streamed_Release; + thiz->Flush = IDirectFBDataBuffer_Streamed_Flush; + thiz->Finish = IDirectFBDataBuffer_Streamed_Finish; + thiz->SeekTo = IDirectFBDataBuffer_Streamed_SeekTo; + thiz->GetPosition = IDirectFBDataBuffer_Streamed_GetPosition; + thiz->GetLength = IDirectFBDataBuffer_Streamed_GetLength; + thiz->WaitForData = IDirectFBDataBuffer_Streamed_WaitForData; + thiz->WaitForDataWithTimeout = IDirectFBDataBuffer_Streamed_WaitForDataWithTimeout; + thiz->GetData = IDirectFBDataBuffer_Streamed_GetData; + thiz->PeekData = IDirectFBDataBuffer_Streamed_PeekData; + thiz->HasData = IDirectFBDataBuffer_Streamed_HasData; + thiz->PutData = IDirectFBDataBuffer_Streamed_PutData; + + return DFB_OK; +} + +/******************************************************************************/ + +static void +DestroyAllChunks( IDirectFBDataBuffer_Streamed_data *data ) +{ + DirectLink *l, *n; + + D_ASSERT( data != NULL ); + + /* Loop through list. */ + direct_list_foreach_safe (l, n, data->chunks) { + /* Deallocate chunk. */ + destroy_chunk( (DataChunk*) l ); + } + + /* Clear lists. */ + data->chunks = NULL; +} + +static void +ReadChunkData( IDirectFBDataBuffer_Streamed_data *data, + void *buffer, + unsigned int offset, + unsigned int length, + bool flush ) +{ + DirectLink *l, *n; + + D_ASSERT( data != NULL ); + D_ASSERT( buffer != NULL ); + + /* Loop through links. */ + direct_list_foreach_safe (l, n, data->chunks) { + unsigned int len; + unsigned int off = 0; + DataChunk *chunk = (DataChunk*) l; + + /* Is there data to be skipped? */ + if (offset) { + /* Calculate number of bytes to be skipped from this chunk. */ + off = MIN( offset, chunk->length - chunk->done ); + + /* Decrease number of bytes to skipped. */ + offset -= off; + } + + /* Calculate number of bytes to be read from this chunk. */ + len = MIN( length, chunk->length - chunk->done - off ); + + /* Can we read from this chunk? */ + if (len) { + /* Copy as many bytes as possible. */ + direct_memcpy( buffer, chunk->data + chunk->done + off, len ); + + /* Increase write pointer. */ + buffer += len; + + /* Decrease number of bytes to read. */ + length -= len; + } + + /* Destructive read? */ + if (flush) { + /* Increase number of consumed bytes. */ + chunk->done += len + off; + + /* Completely consumed? */ + if (chunk->done == chunk->length) { + /* Remove the chunk from the list. */ + direct_list_remove( &data->chunks, l ); + + /* Deallocate chunk. */ + destroy_chunk( chunk ); + } + } + } + + D_ASSERT( length == 0 ); + D_ASSERT( offset == 0 ); +} + +/******************************************************************************/ + +static DataChunk * +create_chunk( const void *data, int length ) +{ + DataChunk *chunk; + + D_ASSERT( data != NULL ); + D_ASSERT( length > 0 ); + + /* Allocate chunk information. */ + chunk = D_CALLOC( 1, sizeof(DataChunk) ); + if (!chunk) + return NULL; + + /* Allocate chunk data. */ + chunk->data = D_MALLOC( length ); + if (!chunk->data) { + D_FREE( chunk ); + return NULL; + } + + /* Fill chunk data. */ + direct_memcpy( chunk->data, data, length ); + + /* Remember chunk length. */ + chunk->length = length; + + return chunk; +} + +static void +destroy_chunk( DataChunk *chunk ) +{ + D_ASSERT( chunk != NULL ); + D_ASSERT( chunk->data != NULL ); + + /* Deallocate chunk data. */ + D_FREE( chunk->data ); + + /* Deallocate chunk information. */ + D_FREE( chunk ); +} + diff --git a/Source/DirectFB/src/media/idirectfbfont.c b/Source/DirectFB/src/media/idirectfbfont.c new file mode 100755 index 0000000..4ce0946 --- /dev/null +++ b/Source/DirectFB/src/media/idirectfbfont.c @@ -0,0 +1,965 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "directfb.h" + +#include "core/coretypes.h" + +#include "core/fonts.h" + +#include +#include +#include +#include + +#include +#include + +#include "misc/util.h" + + +D_DEBUG_DOMAIN( Font, "IDirectFBFont", "DirectFB Font Interface" ); + +/**********************************************************************************************************************/ + +void +IDirectFBFont_Destruct( IDirectFBFont *thiz ) +{ + IDirectFBFont_data *data = (IDirectFBFont_data*)thiz->priv; + + D_DEBUG_AT( Font, "%s( %p )\n", __FUNCTION__, thiz ); + + dfb_font_destroy (data->font); + + /* release memory, if any */ + if (data->content) { + if (data->content_mapped) + munmap( data->content, data->content_size ); + else + D_FREE( data->content ); + } + + DIRECT_DEALLOCATE_INTERFACE( thiz ); +} + +/**********************************************************************************************************************/ + +/* + * increments reference count of font + */ +static DirectResult +IDirectFBFont_AddRef( IDirectFBFont *thiz ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBFont) + + D_DEBUG_AT( Font, "%s( %p )\n", __FUNCTION__, thiz ); + + data->ref++; + + return DFB_OK; +} + +/* + * decrements reference count, destructs interface data if reference count is 0 + */ +static DirectResult +IDirectFBFont_Release( IDirectFBFont *thiz ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBFont) + + D_DEBUG_AT( Font, "%s( %p )\n", __FUNCTION__, thiz ); + + if (--data->ref == 0) + IDirectFBFont_Destruct( thiz ); + + return DFB_OK; +} + +/* + * Get the distance from the baseline to the top. + */ +static DFBResult +IDirectFBFont_GetAscender( IDirectFBFont *thiz, int *ascender ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBFont) + + D_DEBUG_AT( Font, "%s( %p )\n", __FUNCTION__, thiz ); + + if (!ascender) + return DFB_INVARG; + + *ascender = data->font->ascender; + + return DFB_OK; +} + +/* + * Get the distance from the baseline to the bottom. + * This is a negative value! + */ +static DFBResult +IDirectFBFont_GetDescender( IDirectFBFont *thiz, int *descender ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBFont) + + D_DEBUG_AT( Font, "%s( %p )\n", __FUNCTION__, thiz ); + + if (!descender) + return DFB_INVARG; + + *descender = data->font->descender; + + return DFB_OK; +} + +/* + * Get the height of this font. + */ +static DFBResult +IDirectFBFont_GetHeight( IDirectFBFont *thiz, int *height ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBFont) + + D_DEBUG_AT( Font, "%s( %p )\n", __FUNCTION__, thiz ); + + if (!height) + return DFB_INVARG; + + *height = data->font->height; + + return DFB_OK; +} + +/* + * Get the line spacing vector of this font. + */ +static DFBResult +IDirectFBFont_GetLineSpacingVector( IDirectFBFont *thiz, int *xspacing, int *yspacing ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBFont) + + D_DEBUG_AT( Font, "%s( %p )\n", __FUNCTION__, thiz ); + + if (!xspacing && !yspacing) + return DFB_INVARG; + + if (xspacing) { + *xspacing = - data->font->height * data->font->up_unit_x; + } + + if (yspacing) { + *yspacing = - data->font->height * data->font->up_unit_y; + } + + return DFB_OK; +} + +/* + * Get the maximum character width. + */ +static DFBResult +IDirectFBFont_GetMaxAdvance( IDirectFBFont *thiz, int *maxadvance ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBFont) + + D_DEBUG_AT( Font, "%s( %p )\n", __FUNCTION__, thiz ); + + if (!maxadvance) + return DFB_INVARG; + + *maxadvance = data->font->maxadvance; + + return DFB_OK; +} + +/* + * Get the kerning to apply between two glyphs. + */ +static DFBResult +IDirectFBFont_GetKerning( IDirectFBFont *thiz, + unsigned int prev, unsigned int current, + int *kern_x, int *kern_y) +{ + DFBResult ret; + CoreFont *font; + int x = 0, y = 0; + unsigned int prev_index, current_index; + + DIRECT_INTERFACE_GET_DATA(IDirectFBFont) + + D_DEBUG_AT( Font, "%s( %p )\n", __FUNCTION__, thiz ); + + if (!kern_x && !kern_y) + return DFB_INVARG; + + font = data->font; + + dfb_font_lock( font ); + + if (font->GetKerning) { + ret = dfb_font_decode_character( font, data->encoding, prev, &prev_index ); + if (ret) + goto error; + + ret = dfb_font_decode_character( font, data->encoding, current, ¤t_index ); + if (ret) + goto error; + + ret = font->GetKerning (font, prev_index, current_index, &x, &y); + if (ret) + goto error; + } + + dfb_font_unlock( font ); + + if (kern_x) + *kern_x = x; + if (kern_y) + *kern_y = y; + + return DFB_OK; + + +error: + dfb_font_unlock( font ); + + return ret; +} + +/* + * Get the logical and ink extents of the specified string. + */ +static DFBResult +IDirectFBFont_GetStringExtents( IDirectFBFont *thiz, + const char *text, int bytes, + DFBRectangle *logical_rect, + DFBRectangle *ink_rect ) +{ + DFBResult ret; + CoreFont *font; + int xbaseline = 0; + int ybaseline = 0; + + + DIRECT_INTERFACE_GET_DATA(IDirectFBFont) + + D_DEBUG_AT( Font, "%s( %p )\n", __FUNCTION__, thiz ); + + + if (!text) + return DFB_INVARG; + + if (!logical_rect && !ink_rect) + return DFB_INVARG; + + if (bytes < 0) + bytes = strlen (text); + + if (ink_rect) + memset (ink_rect, 0, sizeof (DFBRectangle)); + + font = data->font; + + dfb_font_lock( font ); + + if (bytes > 0) { + int i, num; + unsigned int prev = 0; + unsigned int indices[bytes]; + + /* Decode string to character indices. */ + ret = dfb_font_decode_text( font, data->encoding, text, bytes, indices, &num ); + if (ret) { + dfb_font_unlock( font ); + return ret; + } + + for (i=0; iGetKerning && + font->GetKerning( font, prev, current, &kx, &ky ) == DFB_OK) { + xbaseline += kx; + ybaseline += ky; + } + + if (ink_rect) { + DFBRectangle glyph_rect = { xbaseline + glyph->left, + ybaseline + glyph->top, + glyph->width, glyph->height}; + dfb_rectangle_union (ink_rect, &glyph_rect); + } + + xbaseline += glyph->xadvance; + ybaseline += glyph->yadvance; + } + + prev = current; + } + } + + if (logical_rect) { + // We already have the text baseline vector in (xbaseline,ybaseline). + // Now find the ascender and descender vectors: + int xascender = font->ascender * font->up_unit_x; + int yascender = font->ascender * font->up_unit_y; + int xdescender = font->descender * font->up_unit_x; + int ydescender = font->descender * font->up_unit_y; + + // Now find top/bottom left/right points relative to the text: + int top_left_x = xascender; + int top_left_y = yascender; + int bottom_left_x = xdescender; + int bottom_left_y = ydescender; + int top_right_x = top_left_x + xbaseline; + int top_right_y = top_left_y + ybaseline; + int bottom_right_x = bottom_left_x + xbaseline; + int bottom_right_y = bottom_left_y + ybaseline; + + // The logical rectangle is the bounding-box of these points: +#define MIN4(a,b,c,d) (MIN(MIN((a),(b)),MIN((c),(d)))) +#define MAX4(a,b,c,d) (MAX(MAX((a),(b)),MAX((c),(d)))) + logical_rect->x = MIN4(top_left_x, bottom_left_x, top_right_x, bottom_right_x); + logical_rect->y = MIN4(top_left_y, bottom_left_y, top_right_y, bottom_right_y); + logical_rect->w = MAX4(top_left_x, bottom_left_x, top_right_x, bottom_right_x) - logical_rect->x; + logical_rect->h = MAX4(top_left_y, bottom_left_y, top_right_y, bottom_right_y) - logical_rect->y; + } + + if (ink_rect) { + if (ink_rect->w < 0) { /* PBE FIXME what is this doing? */ + ink_rect->x += ink_rect->w; + ink_rect->w = -ink_rect->w; + } + ink_rect->x += font->ascender * font->up_unit_x; + ink_rect->y += font->ascender * font->up_unit_y; + } + + dfb_font_unlock( font ); + + return DFB_OK; +} + +/* + * Get the logical width of the specified string. + */ +static DFBResult +IDirectFBFont_GetStringWidth( IDirectFBFont *thiz, + const char *text, + int bytes, + int *ret_width ) +{ + DFBResult ret; + int xsize = 0; + int ysize = 0; + + DIRECT_INTERFACE_GET_DATA(IDirectFBFont) + + D_DEBUG_AT( Font, "%s( %p )\n", __FUNCTION__, thiz ); + + if (!text || !ret_width) + return DFB_INVARG; + + if (bytes < 0) + bytes = strlen (text); + + if (bytes > 0) { + int i, num, kx, ky; + unsigned int prev = 0; + unsigned int indices[bytes]; + CoreFont *font = data->font; + + dfb_font_lock( font ); + + /* Decode string to character indices. */ + ret = dfb_font_decode_text( font, data->encoding, text, bytes, indices, &num ); + if (ret) { + dfb_font_unlock( font ); + return ret; + } + + /* Calculate string width. */ + for (i=0; ixadvance; + ysize += glyph->yadvance; + + if (prev && font->GetKerning && + font->GetKerning( font, prev, current, &kx, &ky ) == DFB_OK) { + xsize += kx; + ysize += ky; + } + } + + prev = current; + } + + dfb_font_unlock( font ); + } + + if (!ysize) { + *ret_width = xsize; + } + else if (!xsize) { + *ret_width = ysize; + } + else { + *ret_width = sqrt(xsize*xsize + ysize*ysize); + } + + return DFB_OK; +} + +/* + * Get the extents of the specified glyph. + */ +static DFBResult +IDirectFBFont_GetGlyphExtents( IDirectFBFont *thiz, + unsigned int character, + DFBRectangle *rect, + int *advance ) +{ + DFBResult ret; + CoreFont *font; + CoreGlyphData *glyph; + unsigned int index; + + DIRECT_INTERFACE_GET_DATA(IDirectFBFont) + + D_DEBUG_AT( Font, "%s( %p )\n", __FUNCTION__, thiz ); + + if (!rect && !advance) + return DFB_INVARG; + + font = data->font; + + dfb_font_lock( font ); + + ret = dfb_font_decode_character( font, data->encoding, character, &index ); + if (ret) { + dfb_font_unlock( font ); + return ret; + } + + if (dfb_font_get_glyph_data (font, index, 0, &glyph) != DFB_OK) { // FIXME: support font layers + if (rect) + rect->x = rect->y = rect->w = rect->h = 0; + + if (advance) + *advance = 0; + } + else { + if (rect) { + rect->x = glyph->left; + rect->y = glyph->top - font->ascender; + rect->w = glyph->width; + rect->h = glyph->height; + } + + if (advance) + *advance = glyph->xadvance; + } + + dfb_font_unlock( font ); + + return DFB_OK; +} + +static DFBResult +IDirectFBFont_GetStringBreak( IDirectFBFont *thiz, + const char *text, + int bytes, + int max_width, + int *ret_width, + int *ret_str_length, + const char **ret_next_line) +{ + DFBResult ret; + CoreFont *font; + const u8 *string; + const u8 *end; + CoreGlyphData *glyph; + int kern_x; + int kern_y; + int length = 0; + int xsize = 0; + int ysize = 0; + int width = 0; + unichar current; + unsigned int index; + unsigned int prev = 0; + + DIRECT_INTERFACE_GET_DATA(IDirectFBFont) + + if (!text || !ret_next_line || !ret_str_length || !ret_width) + return DFB_INVARG; + + /* FIXME: Try to change the font module API *slightly* to support this. */ + if (data->encoding != DTEID_UTF8) + return DFB_UNSUPPORTED; + + if (bytes < 0) + bytes = strlen (text); + + if (!bytes) { + *ret_next_line = NULL; + *ret_str_length = 0; + *ret_width = 0; + + return DFB_OK; + } + + font = data->font; + string = (const u8*) text; + end = string + bytes; + *ret_next_line = NULL; + + dfb_font_lock( font ); + + do { + *ret_width = width; + length ++; + + current = DIRECT_UTF8_GET_CHAR( string ); + + string += DIRECT_UTF8_SKIP( string[0] ); + + if (current == ' ' || current == 0x0a) { + *ret_next_line = (const char*) string; + *ret_str_length = length; + *ret_width = width; + } + + ret = dfb_font_decode_character( font, data->encoding, current, &index ); + if (ret) + continue; + + ret = dfb_font_get_glyph_data( font, index, 0, &glyph ); // FIXME: support font layers + if (ret) + continue; + + xsize += glyph->xadvance; + ysize += glyph->yadvance; + + if (prev && font->GetKerning && font->GetKerning( font, prev, index, &kern_x, &kern_y) == DFB_OK) { + xsize += kern_x; + ysize += kern_y; + } + + if (!ysize) { + width = xsize; + } + else if (!xsize) { + width = ysize; + } + else { + width = sqrt(xsize*xsize + ysize*ysize); + } + + prev = index; + } while (width < max_width && string < end && current != 0x0a); + + dfb_font_unlock( font ); + + if (width= end) { + *ret_next_line = NULL; + *ret_str_length = length; + *ret_width = width; + + return DFB_OK; + } + + if (*ret_next_line == NULL) { + if (length == 1) { + *ret_str_length = length; + *ret_next_line = (const char*) string; + *ret_width = width; + } else { + *ret_str_length = length-1; + *ret_next_line = (const char*) string-1; + /* ret_width already set in the loop */ + } + } + + return DFB_OK; +} + +static DFBResult +IDirectFBFont_SetEncoding( IDirectFBFont *thiz, + DFBTextEncodingID encoding ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBFont) + + D_DEBUG_AT( Font, "%s( %p, %d )\n", __FUNCTION__, thiz, encoding ); + + if (encoding > data->font->last_encoding) + return DFB_IDNOTFOUND; + + data->encoding = encoding; + + return DFB_OK; +} + +static DFBResult +IDirectFBFont_EnumEncodings( IDirectFBFont *thiz, + DFBTextEncodingCallback callback, + void *context ) +{ + int i; + CoreFont *font; + + DIRECT_INTERFACE_GET_DATA(IDirectFBFont) + + if (!callback) + return DFB_INVARG; + + D_DEBUG_AT( Font, "%s( %p, %p, %p )\n", __FUNCTION__, thiz, callback, context ); + + font = data->font; + + if (callback( DTEID_UTF8, "UTF8", context ) == DFENUM_OK) { + for (i=DTEID_OTHER; i<=font->last_encoding; i++) { + if (callback( i, font->encodings[i]->name, context ) != DFENUM_OK) + break; + } + } + + return DFB_OK; +} + +static DFBResult +IDirectFBFont_FindEncoding( IDirectFBFont *thiz, + const char *name, + DFBTextEncodingID *ret_id ) +{ + int i; + CoreFont *font; + + DIRECT_INTERFACE_GET_DATA(IDirectFBFont) + + if (!name || !ret_id) + return DFB_INVARG; + + D_DEBUG_AT( Font, "%s( %p, '%s', %p )\n", __FUNCTION__, thiz, name, ret_id ); + + if (!strcasecmp( name, "UTF8" )) { + *ret_id = DTEID_UTF8; + return DFB_OK; + } + + font = data->font; + + for (i=DTEID_OTHER; i<=font->last_encoding; i++) { + if (!strcasecmp( name, font->encodings[i]->name )) { + *ret_id = i; + return DFB_OK; + } + } + + return DFB_IDNOTFOUND; +} + +/* + * Get the extents of the specified glyph. + */ +static DFBResult +IDirectFBFont_GetGlyphExtentsXY( IDirectFBFont *thiz, + unsigned int character, + DFBRectangle *rect, + int *xadvance, + int *yadvance ) +{ + DFBResult ret; + CoreFont *font; + CoreGlyphData *glyph; + unsigned int index; + + DIRECT_INTERFACE_GET_DATA(IDirectFBFont) + + D_DEBUG_AT( Font, "%s( %p )\n", __FUNCTION__, thiz ); + + if (!rect && !xadvance && !yadvance) + return DFB_INVARG; + + font = data->font; + + dfb_font_lock( font ); + + ret = dfb_font_decode_character( font, data->encoding, character, &index ); + if (ret) { + dfb_font_unlock( font ); + return ret; + } + + if (dfb_font_get_glyph_data (font, index, 0, &glyph) != DFB_OK) { // FIXME: support font layers + if (rect) + rect->x = rect->y = rect->w = rect->h = 0; + + if (xadvance) + *xadvance = 0; + + if (yadvance) + *yadvance = 0; + } + else { + if (rect) { + rect->x = glyph->left + font->ascender * font->up_unit_x; + rect->y = glyph->top + font->ascender * font->up_unit_y; + rect->w = glyph->width; + rect->h = glyph->height; + } + + if (xadvance) + *xadvance = glyph->xadvance; + + if (yadvance) + *yadvance = glyph->yadvance; + } + + dfb_font_unlock( font ); + + return DFB_OK; +} + +/* + * Get the description of the font. + */ +static DFBResult +IDirectFBFont_GetDescription( IDirectFBFont *thiz, + DFBFontDescription *ret_description ) +{ + DIRECT_INTERFACE_GET_DATA(IDirectFBFont) + + D_DEBUG_AT( Font, "%s( %p )\n", __FUNCTION__, thiz ); + + if (!ret_description) + return DFB_INVARG; + + *ret_description = data->font->description; + + return DFB_OK; +} + +/**********************************************************************************************************************/ + +DFBResult +IDirectFBFont_Construct( IDirectFBFont *thiz, CoreFont *font ) +{ + DIRECT_ALLOCATE_INTERFACE_DATA(thiz, IDirectFBFont) + + data->ref = 1; + data->font = font; + + thiz->AddRef = IDirectFBFont_AddRef; + thiz->Release = IDirectFBFont_Release; + thiz->GetAscender = IDirectFBFont_GetAscender; + thiz->GetDescender = IDirectFBFont_GetDescender; + thiz->GetHeight = IDirectFBFont_GetHeight; + thiz->GetMaxAdvance = IDirectFBFont_GetMaxAdvance; + thiz->GetKerning = IDirectFBFont_GetKerning; + thiz->GetStringWidth = IDirectFBFont_GetStringWidth; + thiz->GetStringExtents = IDirectFBFont_GetStringExtents; + thiz->GetGlyphExtents = IDirectFBFont_GetGlyphExtents; + thiz->GetStringBreak = IDirectFBFont_GetStringBreak; + thiz->SetEncoding = IDirectFBFont_SetEncoding; + thiz->EnumEncodings = IDirectFBFont_EnumEncodings; + thiz->FindEncoding = IDirectFBFont_FindEncoding; + thiz->GetLineSpacingVector = IDirectFBFont_GetLineSpacingVector; + thiz->GetGlyphExtentsXY = IDirectFBFont_GetGlyphExtentsXY; + thiz->GetDescription = IDirectFBFont_GetDescription; + + return DFB_OK; +} + +static DFBResult +try_map_file( IDirectFBDataBuffer_data *buffer_data, + IDirectFBFont_ProbeContext *ctx ) +{ + /* try to map the "file" content first */ + if (!access( buffer_data->filename, O_RDONLY )) { + int fd; + struct stat st; + + fd = open( buffer_data->filename, O_RDONLY ); + if (fd < 0) { + D_PERROR( "IDirectFBFont: Could not open '%s'\n", buffer_data->filename ); + return DFB_IO; + } + + if (fstat( fd, &st )) { + D_PERROR( "IDirectFBFont: Could not stat '%s'\n", buffer_data->filename ); + close( fd ); + return DFB_IO; + } + + ctx->content = mmap( NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0 ); + if (ctx->content == MAP_FAILED) { + D_PERROR( "IDirectFBFont: Could not mmap '%s'\n", buffer_data->filename ); + close( fd ); + return DFB_IO; + } + + ctx->content_size = st.st_size; + ctx->content_mapped = true; + + close( fd ); + + return DFB_OK; + } + + return DFB_UNSUPPORTED; +} + +static void +unmap_or_free( IDirectFBFont_ProbeContext *ctx ) +{ + if (ctx->content) { + if (ctx->content_mapped) + munmap( ctx->content, ctx->content_size ); + else + D_FREE( ctx->content ); + } +} + +DFBResult +IDirectFBFont_CreateFromBuffer( IDirectFBDataBuffer *buffer, + CoreDFB *core, + const DFBFontDescription *desc, + IDirectFBFont **interface ) +{ + DFBResult ret; + DirectInterfaceFuncs *funcs = NULL; + IDirectFBDataBuffer_data *buffer_data; + IDirectFBFont *ifont; + IDirectFBFont_ProbeContext ctx = {0}; + + /* Get the private information of the data buffer. */ + buffer_data = (IDirectFBDataBuffer_data*) buffer->priv; + if (!buffer_data) + return DFB_DEAD; + + /* Provide a fallback for image providers without data buffer support. */ + ctx.filename = buffer_data->filename; + + /* try to map the "file" content first */ + if (try_map_file( buffer_data, &ctx ) != DFB_OK) { + /* try to load the "file" content from the buffer */ + + /* we need to be able to seek (this implies non-streamed, + so we also know the size) so we can reuse the buffer */ + if (buffer->SeekTo( buffer, 0 ) == DFB_OK) { + unsigned int size, got; + + /* get the "file" length */ + buffer->GetLength( buffer, &size ); + + ctx.content = D_MALLOC( size ); + if (!ctx.content) + return DR_NOLOCALMEMORY; + + ctx.content_size = 0; + + while (ctx.content_size < size) { + unsigned int get = size - ctx.content_size; + + if (get > 8192) + get = 8192; + + ret = buffer->WaitForData( buffer, get ); + if (ret) { + D_DERROR( ret, "%s: WaitForData failed!\n", __FUNCTION__ ); + break; + } + + ret = buffer->GetData( buffer, get, ctx.content + ctx.content_size, &got ); + if (ret) { + D_DERROR( ret, "%s: GetData failed!\n", __FUNCTION__ ); + break; + } + + if (!got) + break; + + ctx.content_size += got; + } + + if (ctx.content_size != size) { + D_ERROR( "%s: Got size %u differs from supposed %u!\n", __FUNCTION__, ctx.content_size, size ); + D_FREE( ctx.content ); + return DFB_FAILURE; + } + } + } + + /* Find a suitable implementation. */ + ret = DirectGetInterface( &funcs, "IDirectFBFont", NULL, DirectProbeInterface, &ctx ); + if (ret) { + unmap_or_free( &ctx ); + return ret; + } + + DIRECT_ALLOCATE_INTERFACE( ifont, IDirectFBFont ); + + /* Construct the interface. */ + ret = funcs->Construct( ifont, core, &ctx, desc ); + if (ret) { + unmap_or_free( &ctx ); + return ret; + } + + /* store pointer for deletion at destroy */ + { + IDirectFBFont_data *data = (IDirectFBFont_data*)(ifont->priv); + data->content = ctx.content; + data->content_size = ctx.content_size; + data->content_mapped = ctx.content_mapped; + } + + *interface = ifont; + + return DFB_OK; +} + diff --git a/Source/DirectFB/src/media/idirectfbfont.h b/Source/DirectFB/src/media/idirectfbfont.h new file mode 100755 index 0000000..85bdb0c --- /dev/null +++ b/Source/DirectFB/src/media/idirectfbfont.h @@ -0,0 +1,82 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __IDIRECTFBFONT_H__ +#define __IDIRECTFBFONT_H__ + +#include + +#include + +/* + * probing context + */ +typedef struct { + /* Only set if databuffer is created from file. + deprecated - use memory location below. */ + const char *filename; + + /* if !=NULL, pointer to the file content */ + unsigned char *content; + unsigned int content_size; + bool content_mapped; +} IDirectFBFont_ProbeContext; + +DFBResult +IDirectFBFont_CreateFromBuffer( IDirectFBDataBuffer *buffer, + CoreDFB *core, + const DFBFontDescription *desc, + IDirectFBFont **interface ); + +/**********************************************************************************************************************/ + +/* + * private data struct of IDirectFBFont + * used by implementors of IDirectFBFont + */ +typedef struct { + int ref; /* reference counter */ + CoreFont *font; /* pointer to core font */ + unsigned char *content; /* possible allocation, free at intf. close */ + unsigned int content_size; + bool content_mapped; + + DFBTextEncodingID encoding; /* text encoding */ +} IDirectFBFont_data; + +/* + * common code to construct the interface (internal usage only) + */ +DFBResult IDirectFBFont_Construct( IDirectFBFont *thiz, CoreFont *font ); + +/* + * deinitialize font and its surfaces + */ +void IDirectFBFont_Destruct( IDirectFBFont *thiz ); + +#endif diff --git a/Source/DirectFB/src/media/idirectfbimageprovider.c b/Source/DirectFB/src/media/idirectfbimageprovider.c new file mode 100755 index 0000000..f54319c --- /dev/null +++ b/Source/DirectFB/src/media/idirectfbimageprovider.c @@ -0,0 +1,167 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include +#include + +#include + +#include + +#include +#include + +#include +#include + + +static DirectResult +IDirectFBImageProvider_AddRef( IDirectFBImageProvider *thiz ) +{ + return DFB_UNIMPLEMENTED; +} + +static DirectResult +IDirectFBImageProvider_Release( IDirectFBImageProvider *thiz ) +{ + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFBImageProvider_GetSurfaceDescription( IDirectFBImageProvider *thiz, + DFBSurfaceDescription *ret_dsc ) +{ + if (!ret_dsc) + return DFB_INVARG; + + ret_dsc->flags = DSDESC_NONE; + + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFBImageProvider_GetImageDescription( IDirectFBImageProvider *thiz, + DFBImageDescription *ret_dsc ) +{ + if (!ret_dsc) + return DFB_INVARG; + + ret_dsc->caps = DICAPS_NONE; + + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFBImageProvider_RenderTo( IDirectFBImageProvider *thiz, + IDirectFBSurface *destination, + const DFBRectangle *destination_rect ) +{ + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFBImageProvider_SetRenderCallback( IDirectFBImageProvider *thiz, + DIRenderCallback callback, + void *callback_data ) +{ + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFBImageProvider_WriteBack( IDirectFBImageProvider *thiz, + IDirectFBSurface *surface, + const DFBRectangle *src_rect, + const char *filename ) +{ + return DFB_UNIMPLEMENTED; +} + +static void +IDirectFBImageProvider_Construct( IDirectFBImageProvider *thiz ) +{ + thiz->AddRef = IDirectFBImageProvider_AddRef; + thiz->Release = IDirectFBImageProvider_Release; + thiz->GetSurfaceDescription = IDirectFBImageProvider_GetSurfaceDescription; + thiz->GetImageDescription = IDirectFBImageProvider_GetImageDescription; + thiz->RenderTo = IDirectFBImageProvider_RenderTo; + thiz->SetRenderCallback = IDirectFBImageProvider_SetRenderCallback; + thiz->WriteBack = IDirectFBImageProvider_WriteBack; +} + +DFBResult +IDirectFBImageProvider_CreateFromBuffer( IDirectFBDataBuffer *buffer, + CoreDFB *core, + IDirectFBImageProvider **interface ) +{ + DFBResult ret; + DirectInterfaceFuncs *funcs = NULL; + IDirectFBDataBuffer_data *buffer_data; + IDirectFBImageProvider *imageprovider; + IDirectFBImageProvider_ProbeContext ctx; + + /* Get the private information of the data buffer. */ + buffer_data = (IDirectFBDataBuffer_data*) buffer->priv; + if (!buffer_data) + return DFB_DEAD; + + /* Clear for safety, especially header data. */ + memset( &ctx, 0, sizeof(ctx) ); + + /* Provide a fallback for image providers without data buffer support. */ + ctx.filename = buffer_data->filename; + + /* Wait until 32 bytes are available. */ + ret = buffer->WaitForData( buffer, 32 ); + if (ret) + return ret; + + /* Read the first 32 bytes. */ + buffer->PeekData( buffer, 32, 0, ctx.header, NULL ); + + /* Find a suitable implementation. */ + ret = DirectGetInterface( &funcs, "IDirectFBImageProvider", NULL, DirectProbeInterface, &ctx ); + if (ret) + return ret; + + DIRECT_ALLOCATE_INTERFACE( imageprovider, IDirectFBImageProvider ); + + /* Initialize interface pointers. */ + IDirectFBImageProvider_Construct( imageprovider ); + + /* Construct the interface. */ + ret = funcs->Construct( imageprovider, buffer, core ); + if (ret) + return ret; + + *interface = imageprovider; + + return DFB_OK; +} + diff --git a/Source/DirectFB/src/media/idirectfbimageprovider.h b/Source/DirectFB/src/media/idirectfbimageprovider.h new file mode 100755 index 0000000..afbd613 --- /dev/null +++ b/Source/DirectFB/src/media/idirectfbimageprovider.h @@ -0,0 +1,48 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __IDIRECTFBIMAGEPROVIDER_H__ +#define __IDIRECTFBIMAGEPROVIDER_H__ + +#include + +/* + * probing context + */ +typedef struct { + unsigned char header[32]; + + const char *filename; /* Only set if databuffer is created from file. */ +} IDirectFBImageProvider_ProbeContext; + +DFBResult +IDirectFBImageProvider_CreateFromBuffer( IDirectFBDataBuffer *buffer, + CoreDFB *core, + IDirectFBImageProvider **interface ); + +#endif diff --git a/Source/DirectFB/src/media/idirectfbvideoprovider.c b/Source/DirectFB/src/media/idirectfbvideoprovider.c new file mode 100755 index 0000000..fcea1ba --- /dev/null +++ b/Source/DirectFB/src/media/idirectfbvideoprovider.c @@ -0,0 +1,387 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include +#include + +#include + +#include +#include + +#include +#include + + +static DirectResult +IDirectFBVideoProvider_AddRef( IDirectFBVideoProvider *thiz ) +{ + return DFB_UNIMPLEMENTED; +} + +static DirectResult +IDirectFBVideoProvider_Release( IDirectFBVideoProvider *thiz ) +{ + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFBVideoProvider_GetCapabilities( IDirectFBVideoProvider *thiz, + DFBVideoProviderCapabilities *ret_caps ) +{ + if (!ret_caps) + return DFB_INVARG; + + *ret_caps = 0; + + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFBVideoProvider_GetSurfaceDescription( IDirectFBVideoProvider *thiz, + DFBSurfaceDescription *ret_dsc ) +{ + if (!ret_dsc) + return DFB_INVARG; + + ret_dsc->flags = DSDESC_NONE; + + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFBVideoProvider_GetStreamDescription( IDirectFBVideoProvider *thiz, + DFBStreamDescription *ret_dsc ) +{ + if (!ret_dsc) + return DFB_INVARG; + + memset( ret_dsc, 0, sizeof(DFBStreamDescription) ); + + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFBVideoProvider_GetBufferOccupancy( IDirectFBVideoProvider *thiz, + DFBBufferOccupancy *ret_occ ) +{ + if (!ret_occ) + return DFB_INVARG; + + memset( ret_occ, 0, sizeof(DFBBufferOccupancy) ); + + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFBVideoProvider_GetBufferThresholds( IDirectFBVideoProvider *thiz, + DFBBufferThresholds *ret_thresh ) +{ + if (!ret_thresh) + return DFB_INVARG; + + memset( ret_thresh, 0, sizeof(DFBBufferThresholds) ); + + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFBVideoProvider_SetBufferThresholds( IDirectFBVideoProvider *thiz, + DFBBufferThresholds thresh ) +{ + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFBVideoProvider_PlayTo( IDirectFBVideoProvider *thiz, + IDirectFBSurface *destination, + const DFBRectangle *destination_rect, + DVFrameCallback callback, + void *ctx ) +{ + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFBVideoProvider_Stop( IDirectFBVideoProvider *thiz ) +{ + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFBVideoProvider_GetStatus( IDirectFBVideoProvider *thiz, + DFBVideoProviderStatus *ret_status ) +{ + if (!ret_status) + return DFB_INVARG; + + *ret_status = DVSTATE_UNKNOWN; + + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFBVideoProvider_SeekTo( IDirectFBVideoProvider *thiz, + double seconds ) +{ + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFBVideoProvider_GetPos( IDirectFBVideoProvider *thiz, + double *ret_seconds ) +{ + if (!ret_seconds) + return DFB_INVARG; + + *ret_seconds = 0.0; + + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFBVideoProvider_GetLength( IDirectFBVideoProvider *thiz, + double *ret_seconds ) +{ + if (!ret_seconds) + return DFB_INVARG; + + *ret_seconds = 0.0; + + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFBVideoProvider_GetColorAdjustment( IDirectFBVideoProvider *thiz, + DFBColorAdjustment *ret_adj ) +{ + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFBVideoProvider_SetColorAdjustment( IDirectFBVideoProvider *thiz, + const DFBColorAdjustment *adj ) +{ + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFBVideoProvider_SendEvent( IDirectFBVideoProvider *thiz, + const DFBEvent *event ) +{ + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFBVideoProvider_SetPlaybackFlags( IDirectFBVideoProvider *thiz, + DFBVideoProviderPlaybackFlags flags ) +{ + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFBVideoProvider_SetSpeed( IDirectFBVideoProvider *thiz, + double multiplier ) +{ + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFBVideoProvider_GetSpeed( IDirectFBVideoProvider *thiz, + double *ret_multiplier ) +{ + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFBVideoProvider_SetVolume( IDirectFBVideoProvider *thiz, + float level ) +{ + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFBVideoProvider_GetVolume( IDirectFBVideoProvider *thiz, + float *ret_level ) +{ + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFBVideoProvider_SetStreamAttributes(IDirectFBVideoProvider *thiz, + DFBStreamAttributes attr) +{ + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFBVideoProvider_SetAudioOutputs(IDirectFBVideoProvider *thiz, + DFBVideoProviderAudioUnits* audioUnits) +{ + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFBVideoProvider_GetAudioOutputs(IDirectFBVideoProvider *thiz, + DFBVideoProviderAudioUnits* audioUnits) +{ + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFBVideoProvider_SetAudioDelay( IDirectFBVideoProvider *thiz, + long delay ) +{ + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFBVideoProvider_CreateEventBuffer( IDirectFBVideoProvider *thiz, + IDirectFBEventBuffer **buffer ) +{ + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFBVideoProvider_AttachEventBuffer( IDirectFBVideoProvider *thiz, + IDirectFBEventBuffer *buffer ) +{ + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFBVideoProvider_EnableEvents(IDirectFBVideoProvider *thiz, + DFBVideoProviderEventType mask ) +{ + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFBVideoProvider_DisableEvents(IDirectFBVideoProvider *thiz, + DFBVideoProviderEventType mask ) +{ + return DFB_UNIMPLEMENTED; +} + +static DFBResult +IDirectFBVideoProvider_DetachEventBuffer( IDirectFBVideoProvider *thiz, + IDirectFBEventBuffer *buffer ) +{ + return DFB_UNIMPLEMENTED; +} + +static void +IDirectFBVideoProvider_Construct( IDirectFBVideoProvider *thiz ) +{ + thiz->AddRef = IDirectFBVideoProvider_AddRef; + thiz->Release = IDirectFBVideoProvider_Release; + thiz->GetCapabilities = IDirectFBVideoProvider_GetCapabilities; + thiz->GetSurfaceDescription = IDirectFBVideoProvider_GetSurfaceDescription; + thiz->GetStreamDescription = IDirectFBVideoProvider_GetStreamDescription; + thiz->GetBufferOccupancy = IDirectFBVideoProvider_GetBufferOccupancy; + thiz->SetBufferThresholds = IDirectFBVideoProvider_SetBufferThresholds; + thiz->GetBufferThresholds = IDirectFBVideoProvider_GetBufferThresholds; + thiz->PlayTo = IDirectFBVideoProvider_PlayTo; + thiz->Stop = IDirectFBVideoProvider_Stop; + thiz->GetStatus = IDirectFBVideoProvider_GetStatus; + thiz->SeekTo = IDirectFBVideoProvider_SeekTo; + thiz->GetPos = IDirectFBVideoProvider_GetPos; + thiz->GetLength = IDirectFBVideoProvider_GetLength; + thiz->GetColorAdjustment = IDirectFBVideoProvider_GetColorAdjustment; + thiz->SetColorAdjustment = IDirectFBVideoProvider_SetColorAdjustment; + thiz->SendEvent = IDirectFBVideoProvider_SendEvent; + thiz->SetPlaybackFlags = IDirectFBVideoProvider_SetPlaybackFlags; + thiz->SetSpeed = IDirectFBVideoProvider_SetSpeed; + thiz->GetSpeed = IDirectFBVideoProvider_GetSpeed; + thiz->SetVolume = IDirectFBVideoProvider_SetVolume; + thiz->GetVolume = IDirectFBVideoProvider_GetVolume; + thiz->SetStreamAttributes = IDirectFBVideoProvider_SetStreamAttributes; + thiz->SetAudioOutputs = IDirectFBVideoProvider_SetAudioOutputs; + thiz->GetAudioOutputs = IDirectFBVideoProvider_GetAudioOutputs; + thiz->CreateEventBuffer = IDirectFBVideoProvider_CreateEventBuffer; + thiz->AttachEventBuffer = IDirectFBVideoProvider_AttachEventBuffer; + thiz->EnableEvents = IDirectFBVideoProvider_EnableEvents; + thiz->DisableEvents = IDirectFBVideoProvider_DisableEvents; + thiz->DetachEventBuffer = IDirectFBVideoProvider_DetachEventBuffer; + thiz->SetAudioDelay = IDirectFBVideoProvider_SetAudioDelay; +} + + +DFBResult +IDirectFBVideoProvider_CreateFromBuffer( IDirectFBDataBuffer *buffer, + CoreDFB *core, + IDirectFBVideoProvider **interface ) +{ + DFBResult ret; + DirectInterfaceFuncs *funcs = NULL; + IDirectFBDataBuffer_data *buffer_data; + IDirectFBVideoProvider *videoprovider; + IDirectFBVideoProvider_ProbeContext ctx; + + /* Get the private information of the data buffer. */ + buffer_data = (IDirectFBDataBuffer_data*) buffer->priv; + if (!buffer_data) + return DFB_DEAD; + + /* Provide a fallback for video providers without data buffer support. */ + ctx.filename = buffer_data->filename; + ctx.buffer = buffer; + + /* Wait until 64 bytes are available. */ + ret = buffer->WaitForData( buffer, sizeof(ctx.header) ); + if (ret) + return ret; + + /* Clear context header. */ + memset( ctx.header, 0, sizeof(ctx.header) ); + + /* Read the first 64 bytes. */ + buffer->PeekData( buffer, sizeof(ctx.header), 0, ctx.header, NULL ); + + /* Find a suitable implementation. */ + ret = DirectGetInterface( &funcs, "IDirectFBVideoProvider", NULL, DirectProbeInterface, &ctx ); + if (ret) + return ret; + + DIRECT_ALLOCATE_INTERFACE( videoprovider, IDirectFBVideoProvider ); + + /* Initialize interface pointers. */ + IDirectFBVideoProvider_Construct( videoprovider ); + + /* Construct the interface. */ + ret = funcs->Construct( videoprovider, buffer, core ); + if (ret) + return ret; + + *interface = videoprovider; + + return DFB_OK; +} + diff --git a/Source/DirectFB/src/media/idirectfbvideoprovider.h b/Source/DirectFB/src/media/idirectfbvideoprovider.h new file mode 100755 index 0000000..24e9ea1 --- /dev/null +++ b/Source/DirectFB/src/media/idirectfbvideoprovider.h @@ -0,0 +1,54 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __IDIRECTFBVIDEOPROVIDER_H__ +#define __IDIRECTFBVIDEOPROVIDER_H__ + +#include + +/* + * probing context + */ +typedef struct { + unsigned char header[64]; + + /* Only set if databuffer is created from file. */ + const char *filename; + + /* Usefull if provider needs more data for probing. */ + IDirectFBDataBuffer *buffer; +} IDirectFBVideoProvider_ProbeContext; + + +DFBResult +IDirectFBVideoProvider_CreateFromBuffer( IDirectFBDataBuffer *buffer, + CoreDFB *core, + IDirectFBVideoProvider **interface ); + +#endif + diff --git a/Source/DirectFB/src/misc/Makefile.am b/Source/DirectFB/src/misc/Makefile.am new file mode 100755 index 0000000..d1e77b7 --- /dev/null +++ b/Source/DirectFB/src/misc/Makefile.am @@ -0,0 +1,29 @@ +## Makefile.am for DirectFB/src/misc + +INCLUDES = \ + -I$(top_builddir)/lib \ + -I$(top_builddir)/include \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/lib \ + -I$(top_srcdir)/src + +AM_CPPFLAGS = \ + -DMODULEDIR=\"@MODULEDIR@\" \ + -DSOPATH=\"@SOPATH@\" \ + -DSYSCONFDIR=\"@sysconfdir@\" + +internalincludedir = $(INTERNALINCLUDEDIR)/misc + +internalinclude_HEADERS = \ + conf.h \ + gfx_util.h \ + util.h + + +noinst_LTLIBRARIES = libdirectfb_misc.la + +libdirectfb_misc_la_SOURCES = \ + conf.c \ + dither565.h \ + gfx_util.c \ + util.c diff --git a/Source/DirectFB/src/misc/Makefile.in b/Source/DirectFB/src/misc/Makefile.in new file mode 100755 index 0000000..ce04ff7 --- /dev/null +++ b/Source/DirectFB/src/misc/Makefile.in @@ -0,0 +1,564 @@ +# Makefile.in generated by automake 1.10.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = src/misc +DIST_COMMON = $(internalinclude_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/as-ac-expand.m4 \ + $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +libdirectfb_misc_la_LIBADD = +am_libdirectfb_misc_la_OBJECTS = conf.lo gfx_util.lo util.lo +libdirectfb_misc_la_OBJECTS = $(am_libdirectfb_misc_la_OBJECTS) +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libdirectfb_misc_la_SOURCES) +DIST_SOURCES = $(libdirectfb_misc_la_SOURCES) +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(internalincludedir)" +internalincludeHEADERS_INSTALL = $(INSTALL_HEADER) +HEADERS = $(internalinclude_HEADERS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AS = @AS@ +ASFLAGS = @ASFLAGS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIR = @DATADIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DFB_CFLAGS_OMIT_FRAME_POINTER = @DFB_CFLAGS_OMIT_FRAME_POINTER@ +DFB_INTERNAL_CFLAGS = @DFB_INTERNAL_CFLAGS@ +DFB_LDFLAGS = @DFB_LDFLAGS@ +DFB_SMOOTH_SCALING = @DFB_SMOOTH_SCALING@ +DIRECTFB_BINARY_AGE = @DIRECTFB_BINARY_AGE@ +DIRECTFB_CSOURCE = @DIRECTFB_CSOURCE@ +DIRECTFB_INTERFACE_AGE = @DIRECTFB_INTERFACE_AGE@ +DIRECTFB_MAJOR_VERSION = @DIRECTFB_MAJOR_VERSION@ +DIRECTFB_MICRO_VERSION = @DIRECTFB_MICRO_VERSION@ +DIRECTFB_MINOR_VERSION = @DIRECTFB_MINOR_VERSION@ +DIRECTFB_VERSION = @DIRECTFB_VERSION@ +DIRECT_BUILD_DEBUG = @DIRECT_BUILD_DEBUG@ +DIRECT_BUILD_DEBUGS = @DIRECT_BUILD_DEBUGS@ +DIRECT_BUILD_GETTID = @DIRECT_BUILD_GETTID@ +DIRECT_BUILD_NETWORK = @DIRECT_BUILD_NETWORK@ +DIRECT_BUILD_STDBOOL = @DIRECT_BUILD_STDBOOL@ +DIRECT_BUILD_TEXT = @DIRECT_BUILD_TEXT@ +DIRECT_BUILD_TRACE = @DIRECT_BUILD_TRACE@ +DSYMUTIL = @DSYMUTIL@ +DYNLIB = @DYNLIB@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +FREETYPE_CFLAGS = @FREETYPE_CFLAGS@ +FREETYPE_LIBS = @FREETYPE_LIBS@ +FREETYPE_PROVIDER = @FREETYPE_PROVIDER@ +FUSION_BUILD_KERNEL = @FUSION_BUILD_KERNEL@ +FUSION_BUILD_MULTI = @FUSION_BUILD_MULTI@ +FUSION_MESSAGE_SIZE = @FUSION_MESSAGE_SIZE@ +GIF_PROVIDER = @GIF_PROVIDER@ +GREP = @GREP@ +HAVE_LINUX = @HAVE_LINUX@ +INCLUDEDIR = @INCLUDEDIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTERNALINCLUDEDIR = @INTERNALINCLUDEDIR@ +JPEG_PROVIDER = @JPEG_PROVIDER@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBJPEG = @LIBJPEG@ +LIBOBJS = @LIBOBJS@ +LIBPNG = @LIBPNG@ +LIBPNG_CONFIG = @LIBPNG_CONFIG@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_AGE = @LT_AGE@ +LT_BINARY = @LT_BINARY@ +LT_CURRENT = @LT_CURRENT@ +LT_RELEASE = @LT_RELEASE@ +LT_REVISION = @LT_REVISION@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MAN2HTML = @MAN2HTML@ +MKDIR_P = @MKDIR_P@ +MODULEDIR = @MODULEDIR@ +MODULEDIRNAME = @MODULEDIRNAME@ +NMEDIT = @NMEDIT@ +OBJEXT = @OBJEXT@ +OSX_LIBS = @OSX_LIBS@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PNG_PROVIDER = @PNG_PROVIDER@ +RANLIB = @RANLIB@ +RUNTIME_SYSROOT = @RUNTIME_SYSROOT@ +SDL_CFLAGS = @SDL_CFLAGS@ +SDL_LIBS = @SDL_LIBS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOPATH = @SOPATH@ +STRIP = @STRIP@ +SYSCONFDIR = @SYSCONFDIR@ +SYSFS_LIBS = @SYSFS_LIBS@ +THREADFLAGS = @THREADFLAGS@ +THREADLIB = @THREADLIB@ +TSLIB_CFLAGS = @TSLIB_CFLAGS@ +TSLIB_LIBS = @TSLIB_LIBS@ +VERSION = @VERSION@ +VNC_CFLAGS = @VNC_CFLAGS@ +VNC_CONFIG = @VNC_CONFIG@ +VNC_LIBS = @VNC_LIBS@ +X11_CFLAGS = @X11_CFLAGS@ +X11_LIBS = @X11_LIBS@ +ZLIB_LIBS = @ZLIB_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +INCLUDES = \ + -I$(top_builddir)/lib \ + -I$(top_builddir)/include \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/lib \ + -I$(top_srcdir)/src + +AM_CPPFLAGS = \ + -DMODULEDIR=\"@MODULEDIR@\" \ + -DSOPATH=\"@SOPATH@\" \ + -DSYSCONFDIR=\"@sysconfdir@\" + +internalincludedir = $(INTERNALINCLUDEDIR)/misc +internalinclude_HEADERS = \ + conf.h \ + gfx_util.h \ + util.h + +noinst_LTLIBRARIES = libdirectfb_misc.la +libdirectfb_misc_la_SOURCES = \ + conf.c \ + dither565.h \ + gfx_util.c \ + util.c + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/misc/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/misc/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libdirectfb_misc.la: $(libdirectfb_misc_la_OBJECTS) $(libdirectfb_misc_la_DEPENDENCIES) + $(LINK) $(libdirectfb_misc_la_OBJECTS) $(libdirectfb_misc_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conf.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gfx_util.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/util.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-internalincludeHEADERS: $(internalinclude_HEADERS) + @$(NORMAL_INSTALL) + test -z "$(internalincludedir)" || $(MKDIR_P) "$(DESTDIR)$(internalincludedir)" + @list='$(internalinclude_HEADERS)'; for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + f=$(am__strip_dir) \ + echo " $(internalincludeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(internalincludedir)/$$f'"; \ + $(internalincludeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(internalincludedir)/$$f"; \ + done + +uninstall-internalincludeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(internalinclude_HEADERS)'; for p in $$list; do \ + f=$(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(internalincludedir)/$$f'"; \ + rm -f "$(DESTDIR)$(internalincludedir)/$$f"; \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(internalincludedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: install-internalincludeHEADERS + +install-dvi: install-dvi-am + +install-exec-am: + +install-html: install-html-am + +install-info: install-info-am + +install-man: + +install-pdf: install-pdf-am + +install-ps: install-ps-am + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-internalincludeHEADERS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am \ + install-internalincludeHEADERS install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-internalincludeHEADERS + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/Source/DirectFB/src/misc/conf.c b/Source/DirectFB/src/misc/conf.c new file mode 100755 index 0000000..5772ba9 --- /dev/null +++ b/Source/DirectFB/src/misc/conf.c @@ -0,0 +1,1947 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include + +#include + +#include + +D_DEBUG_DOMAIN( DirectFB_Config, "DirectFB/Config", "Runtime configuration options for DirectFB" ); + +DFBConfig *dfb_config = NULL; + +static const char *config_usage = + "DirectFB version " DIRECTFB_VERSION "\n" + "\n" + " --dfb-help Output DirectFB usage information and exit\n" + " --dfb: