summaryrefslogtreecommitdiff
path: root/Source/DirectFB/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'Source/DirectFB/src/core')
-rwxr-xr-xSource/DirectFB/src/core/Makefile.am84
-rwxr-xr-xSource/DirectFB/src/core/Makefile.in648
-rwxr-xr-xSource/DirectFB/src/core/clipboard.c298
-rwxr-xr-xSource/DirectFB/src/core/clipboard.h53
-rwxr-xr-xSource/DirectFB/src/core/colorhash.c366
-rwxr-xr-xSource/DirectFB/src/core/colorhash.h54
-rwxr-xr-xSource/DirectFB/src/core/core.c1160
-rwxr-xr-xSource/DirectFB/src/core/core.h162
-rwxr-xr-xSource/DirectFB/src/core/core_parts.c202
-rwxr-xr-xSource/DirectFB/src/core/core_parts.h131
-rwxr-xr-xSource/DirectFB/src/core/core_system.h141
-rwxr-xr-xSource/DirectFB/src/core/coredefs.h48
-rwxr-xr-xSource/DirectFB/src/core/coretypes.h89
-rwxr-xr-xSource/DirectFB/src/core/fonts.c660
-rwxr-xr-xSource/DirectFB/src/core/fonts.h250
-rwxr-xr-xSource/DirectFB/src/core/gfxcard.c2921
-rwxr-xr-xSource/DirectFB/src/core/gfxcard.h470
-rwxr-xr-xSource/DirectFB/src/core/graphics_driver.h86
-rwxr-xr-xSource/DirectFB/src/core/input.c2668
-rwxr-xr-xSource/DirectFB/src/core/input.h203
-rwxr-xr-xSource/DirectFB/src/core/input_driver.h103
-rwxr-xr-xSource/DirectFB/src/core/layer_context.c1947
-rwxr-xr-xSource/DirectFB/src/core/layer_context.h149
-rwxr-xr-xSource/DirectFB/src/core/layer_control.c589
-rwxr-xr-xSource/DirectFB/src/core/layer_control.h72
-rwxr-xr-xSource/DirectFB/src/core/layer_region.c1129
-rwxr-xr-xSource/DirectFB/src/core/layer_region.h100
-rwxr-xr-xSource/DirectFB/src/core/layers.c640
-rwxr-xr-xSource/DirectFB/src/core/layers.h359
-rwxr-xr-xSource/DirectFB/src/core/layers_internal.h196
-rwxr-xr-xSource/DirectFB/src/core/local_surface_pool.c313
-rwxr-xr-xSource/DirectFB/src/core/palette.c317
-rwxr-xr-xSource/DirectFB/src/core/palette.h106
-rwxr-xr-xSource/DirectFB/src/core/prealloc_surface_pool.c192
-rwxr-xr-xSource/DirectFB/src/core/screen.c540
-rwxr-xr-xSource/DirectFB/src/core/screen.h122
-rwxr-xr-xSource/DirectFB/src/core/screens.c591
-rwxr-xr-xSource/DirectFB/src/core/screens.h263
-rwxr-xr-xSource/DirectFB/src/core/screens_internal.h81
-rwxr-xr-xSource/DirectFB/src/core/shared_surface_pool.c227
-rwxr-xr-xSource/DirectFB/src/core/state.c416
-rwxr-xr-xSource/DirectFB/src/core/state.h362
-rwxr-xr-xSource/DirectFB/src/core/surface.c768
-rwxr-xr-xSource/DirectFB/src/core/surface.h446
-rwxr-xr-xSource/DirectFB/src/core/surface_buffer.c1206
-rwxr-xr-xSource/DirectFB/src/core/surface_buffer.h257
-rwxr-xr-xSource/DirectFB/src/core/surface_core.c214
-rwxr-xr-xSource/DirectFB/src/core/surface_pool.c1263
-rwxr-xr-xSource/DirectFB/src/core/surface_pool.h272
-rwxr-xr-xSource/DirectFB/src/core/surface_pool_bridge.c531
-rwxr-xr-xSource/DirectFB/src/core/surface_pool_bridge.h187
-rwxr-xr-xSource/DirectFB/src/core/system.c464
-rwxr-xr-xSource/DirectFB/src/core/system.h258
-rwxr-xr-xSource/DirectFB/src/core/windows.c1908
-rwxr-xr-xSource/DirectFB/src/core/windows.h316
-rwxr-xr-xSource/DirectFB/src/core/windows_internal.h211
-rwxr-xr-xSource/DirectFB/src/core/windowstack.c998
-rwxr-xr-xSource/DirectFB/src/core/windowstack.h105
-rwxr-xr-xSource/DirectFB/src/core/wm.c1440
-rwxr-xr-xSource/DirectFB/src/core/wm.h468
-rwxr-xr-xSource/DirectFB/src/core/wm_module.h274
61 files changed, 31094 insertions, 0 deletions
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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <config.h>
+
+#include <directfb.h>
+
+#include <direct/debug.h>
+#include <direct/memcpy.h>
+
+#include <fusion/shmalloc.h>
+
+#include <core/core.h>
+#include <core/core_parts.h>
+#include <core/clipboard.h>
+
+
+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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <directfb.h>
+
+#include <core/coretypes.h>
+
+
+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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <config.h>
+
+#include <direct/debug.h>
+#include <direct/memcpy.h>
+
+#include <fusion/arena.h>
+#include <fusion/shmalloc.h>
+
+#include <core/core.h>
+#include <core/core_parts.h>
+#include <core/palette.h>
+#include <core/colorhash.h>
+
+#include <misc/util.h>
+#include <gfx/convert.h>
+
+
+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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <directfb.h>
+
+#include <core/coretypes.h>
+
+
+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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <config.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <dlfcn.h>
+#include <errno.h>
+
+#include <pthread.h>
+
+#include <fusion/fusion.h>
+#include <fusion/arena.h>
+#include <direct/list.h>
+#include <fusion/shmalloc.h>
+
+#include <directfb.h>
+
+#include <core/coredefs.h>
+#include <core/coretypes.h>
+
+#include <core/core.h>
+#include <core/core_parts.h>
+#include <core/layer_context.h>
+#include <core/layer_region.h>
+#include <core/palette.h>
+#include <core/surface.h>
+#include <core/system.h>
+#include <core/windows.h>
+#include <core/windows_internal.h>
+
+#include <direct/build.h>
+#include <direct/debug.h>
+#include <direct/direct.h>
+#include <direct/interface.h>
+#include <direct/mem.h>
+#include <direct/memcpy.h>
+#include <direct/messages.h>
+#include <direct/signals.h>
+#include <direct/thread.h>
+#include <direct/util.h>
+
+#include <fusion/build.h>
+#include <fusion/conf.h>
+
+#include <misc/conf.h>
+#include <misc/util.h>
+
+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<D_ARRAY_SIZE(core_parts); i++) {
+ DFBResult ret;
+
+ if ((ret = dfb_core_part_initialize( core, core_parts[i] ))) {
+ dfb_core_shutdown( core, true );
+ return ret;
+ }
+ }
+
+ return DFB_OK;
+}
+
+static int
+dfb_core_leave( CoreDFB *core, bool emergency )
+{
+ int i;
+
+ D_MAGIC_ASSERT( core, CoreDFB );
+
+ for (i=D_ARRAY_SIZE(core_parts)-1; 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; i<D_ARRAY_SIZE(core_parts); i++) {
+ DFBResult ret;
+
+ if ((ret = dfb_core_part_join( core, core_parts[i] ))) {
+ dfb_core_leave( core, true );
+ return ret;
+ }
+ }
+
+ return DFB_OK;
+}
+
+/******************************************************************************/
+
+static int
+dfb_core_arena_initialize( FusionArena *arena,
+ void *ctx )
+{
+ DFBResult ret;
+ CoreDFB *core = ctx;
+ CoreDFBShared *shared;
+ FusionSHMPoolShared *pool;
+
+ D_MAGIC_ASSERT( core, CoreDFB );
+
+ D_DEBUG_AT( DirectFB_Core, "Initializing...\n" );
+
+ /* Create the shared memory pool first! */
+ ret = fusion_shm_pool_create( core->world, "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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <fusion/types.h>
+#include <fusion/lock.h>
+#include <fusion/object.h>
+
+#include <directfb.h>
+
+#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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <config.h>
+
+#include <fusion/arena.h>
+#include <fusion/shmalloc.h>
+
+#include <directfb.h>
+
+#include <core/coredefs.h>
+#include <core/coretypes.h>
+
+#include <core/core.h>
+#include <core/core_parts.h>
+
+#include <direct/mem.h>
+#include <direct/messages.h>
+
+
+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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <fusion/types.h>
+#include <fusion/lock.h>
+
+#include <directfb.h>
+
+#include <core/coretypes.h>
+#include <core/coredefs.h>
+
+
+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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <core/system.h>
+
+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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <dfb_types.h>
+
+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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <pthread.h>
+
+#include <directfb.h>
+
+#include <core/core.h>
+#include <core/coredefs.h>
+#include <core/coretypes.h>
+
+#include <core/fonts.h>
+#include <core/gfxcard.h>
+#include <core/surface.h>
+
+#include <direct/debug.h>
+#include <direct/hash.h>
+#include <direct/mem.h>
+#include <direct/messages.h>
+#include <direct/utf8.h>
+#include <direct/util.h>
+
+#include <gfx/convert.h>
+
+#include <misc/conf.h>
+#include <misc/util.h>
+
+
+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; i<DFB_FONT_MAX_LAYERS; i++) {
+ ret = direct_hash_create( 163, &font->layers[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; i<DFB_FONT_MAX_LAYERS; i++) {
+ direct_hash_iterate( font->layers[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; i<font->num_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; i<font->num_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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <pthread.h>
+
+#include <fusion/lock.h>
+
+#include <directfb.h>
+
+#include <core/coretypes.h>
+
+#include <core/state.h>
+
+/*
+ * 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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <config.h>
+
+#include <limits.h>
+#include <string.h>
+
+#include <directfb.h>
+
+#include <direct/debug.h>
+#include <direct/memcpy.h>
+
+#include <fusion/fusion.h>
+#include <fusion/shmalloc.h>
+#include <fusion/arena.h>
+#include <fusion/property.h>
+
+#include <core/core.h>
+#include <core/coredefs.h>
+#include <core/coretypes.h>
+
+#include <core/core_parts.h>
+#include <core/gfxcard.h>
+#include <core/fonts.h>
+#include <core/state.h>
+#include <core/palette.h>
+#include <core/surface.h>
+#include <core/surface_buffer.h>
+#include <core/surface_pool.h>
+#include <core/system.h>
+
+#include <gfx/generic/generic.h>
+#include <gfx/clip.h>
+#include <gfx/util.h>
+
+#include <direct/hash.h>
+#include <direct/mem.h>
+#include <direct/messages.h>
+#include <direct/modules.h>
+#include <direct/utf8.h>
+#include <direct/util.h>
+
+#include <misc/conf.h>
+#include <misc/util.h>
+
+
+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 (; i<num; i++) {
+ if (!(state->render_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 (; i<num; i++) {
+ rect = rects[i];
+
+ if (dfb_clip_rectangle( &state->clip, &rect ))
+ gFillRectangle( state, &rect );
+ }
+ }
+ else if (state->matrix[1] == 0 && state->matrix[3] == 0) {
+ /* Scaled/Translated Rectangle. */
+ for (; i<num; i++) {
+ int x1, y1, x2, y2;
+
+ x1 = rects[i].x; y1 = rects[i].y;
+ x2 = x1+rects[i].w; y2 = y1+rects[i].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 {
+ /* Rotated rectangle. Split into triangles. */
+ for (; i<num; i++) {
+ DFBTriangle tri;
+
+ tri.x1 = rects[i].x; tri.y1 = rects[i].y;
+ tri.x2 = rects[i].x+rects[i].w; tri.y2 = rects[i].y;
+ tri.x3 = rects[i].x+rects[i].w; 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 );
+
+ 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 (; i<num; i++) {
+ hw = rects[i].w <= card->limits.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 (; i<num; i++)
+ gFillRectangle( state, &rects[i] );
+
+ gRelease( state );
+ }
+ }
+ else {
+ if (gAcquire( state, DFXL_DRAWLINE )) {
+ DFBRegion line;
+ int x1, x2, x3, x4;
+ int y1, y2, y3, y4;
+
+ x1 = rect->x; 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 (; i<num_lines; i++) {
+ if (!D_FLAGS_IS_SET( card->caps.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 (; i<num_lines; i++) {
+ if (state->render_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<num_spans; i++) {
+ DFBRectangle rect = { spans[i].x, y + i, spans[i].w, 1 };
+
+ if (rect.w > 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 (; i<num_spans; i++) {
+ DFBRectangle rect = { spans[i].x, y + i, spans[i].w, 1 };
+
+ if (state->render_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 (; i<num; i++) {
+ if ((state->render_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 (; i<num; i++) {
+ DFBRectangle drect;
+ int x1, y1, x2, y2;
+
+ x1 = points[i].x; y1 = points[i].y;
+ x2 = x1+rects[i].w; y2 = y1+rects[i].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, &rects[i], &drect );
+ }
+
+ gRelease( state );
+ }
+ }
+ else {
+ if (gAcquire( state, DFXL_BLIT )) {
+ for (; i<num; i++) {
+ if (dfb_clip_blit_precheck( &state->clip,
+ 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<num; i++) {
+ DFBResult ret;
+ CoreGlyphData *glyph;
+ unsigned int current = indices[i];
+
+ ret = dfb_font_get_glyph_data( font, current, l, &glyph );
+ if (ret) {
+ D_DEBUG_AT( Core_GraphicsOps, " -> 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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <pthread.h>
+
+#include <direct/modules.h>
+
+#include <fusion/lock.h>
+
+#include <directfb.h>
+#include <core/coretypes.h>
+
+
+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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <direct/modules.h>
+
+#include <core/gfxcard.h>
+
+
+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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <directfb.h>
+#include <directfb_keynames.h>
+
+#include <direct/debug.h>
+#include <direct/list.h>
+#include <direct/memcpy.h>
+#include <direct/messages.h>
+
+
+#include <fusion/shmalloc.h>
+#include <fusion/reactor.h>
+#include <fusion/arena.h>
+
+#include <core/core.h>
+#include <core/coredefs.h>
+#include <core/coretypes.h>
+
+#include <core/core_parts.h>
+
+#include <core/gfxcard.h>
+#include <core/surface.h>
+#include <core/surface_buffer.h>
+#include <core/system.h>
+#include <core/layer_context.h>
+#include <core/layer_control.h>
+#include <core/layer_region.h>
+#include <core/layers.h>
+#include <core/input.h>
+#include <core/windows.h>
+#include <core/windows_internal.h>
+
+#include <direct/mem.h>
+#include <direct/memcpy.h>
+#include <direct/messages.h>
+#include <direct/modules.h>
+#include <direct/trace.h>
+
+#include <fusion/build.h>
+
+#include <misc/conf.h>
+#include <misc/util.h>
+
+#include <gfx/convert.h>
+
+
+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<MAX_INPUT_GLOBALS; i++) {
+ if (!dfb_input_globals[i]) {
+ dfb_input_globals[i] = func;
+
+ D_DEBUG_AT( Core_Input, " -> 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; i<core_input->num; 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; i<data->num; 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; i<data->num; 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; i<data->num; 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; i<data->num; 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; i<core_local->num; 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 "<invalid>";
+}
+
+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; i<core_local->num; 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, &notification, 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; i<num_entries; i++)
+ entries[i].code = -1;
+
+ shared->keymap.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; i<core_local->num; 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; i<shared->keymap.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; i<num; i++) {
+ ret = funcs->GetAxisInfo( 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; i<num; i++) {
+ char buf[128];
+ CoreInputDevice *device;
+ InputDeviceInfo device_info;
+ InputDeviceShared *shared;
+ void *driver_data;
+
+ device = D_CALLOC( 1, sizeof(CoreInputDevice) );
+ if (!device) {
+ D_OOM();
+ continue;
+ }
+
+ shared = SHCALLOC( pool, 1, sizeof(InputDeviceShared) );
+ if (!shared) {
+ D_OOSHM();
+ D_FREE( device );
+ continue;
+ }
+
+ device->core = 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<strlen(symbolname); i++ )
+ if( symbolname[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<strlen(identifiername); i++ )
+ if( identifiername[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; i<map->num_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; i<map->num_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; i<D_ARRAY_SIZE(deadkey_maps); i++) {
+ const DeadKeyMap *map = &deadkey_maps[i];
+
+ if (map->deadkey == 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, &region ) == 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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <pthread.h>
+#include <directfb.h>
+
+#include <direct/modules.h>
+
+#include <fusion/reactor.h>
+
+#include <core/coretypes.h>
+
+
+
+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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <core/input.h>
+
+
+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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <config.h>
+
+#include <unistd.h>
+#include <string.h>
+
+#include <directfb.h>
+
+#include <direct/memcpy.h>
+#include <direct/messages.h>
+#include <direct/util.h>
+
+#include <fusion/shmalloc.h>
+
+#include <core/coredefs.h>
+#include <core/coretypes.h>
+
+#include <core/core.h>
+#include <core/layer_context.h>
+#include <core/layer_control.h>
+#include <core/layer_region.h>
+#include <core/screen.h>
+#include <core/surface.h>
+#include <core/system.h>
+#include <core/windows.h>
+#include <core/windowstack.h>
+#include <core/wm.h>
+
+#include <core/layers_internal.h>
+#include <core/windows_internal.h>
+
+#include <fusion/shmalloc.h>
+
+
+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, &region->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, &region );
+ 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, &region_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,
+ &region_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, &region_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,
+ &region_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; i<shared->description.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, &region->surface_lock );
+ }
+ }
+
+ /* (Re)allocate the region's surface. */
+ if (surface) {
+ flags |= CLRCF_SURFACE | CLRCF_PALETTE;
+
+ if (region->surface) {
+ ret = reallocate_surface( layer, region, &region_config );
+ if (ret)
+ D_DERROR( ret, "Core/Layers: Reallocation of layer surface failed!\n" );
+ }
+ else {
+ ret = allocate_surface( layer, region, &region_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, &region_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, &region->surface_reaction );
+
+ /* Unlink from structure. */
+ dfb_surface_unlink( &region->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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <directfb.h>
+
+#include <core/coretypes.h>
+#include <fusion/object.h>
+
+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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <fusion/shmalloc.h>
+#include <fusion/arena.h>
+#include <fusion/property.h>
+
+#include <directfb.h>
+
+#include <core/core.h>
+#include <core/coredefs.h>
+#include <core/coretypes.h>
+
+#include <core/core_parts.h>
+
+#include <core/input.h>
+#include <core/gfxcard.h>
+#include <core/layer_context.h>
+#include <core/layer_control.h>
+#include <core/layer_region.h>
+#include <core/layers.h>
+#include <core/screen.h>
+#include <core/state.h>
+#include <core/palette.h>
+#include <core/system.h>
+#include <core/windows.h>
+
+#include <gfx/convert.h>
+#include <gfx/util.h>
+
+#include <misc/util.h>
+
+#include <direct/debug.h>
+#include <direct/mem.h>
+#include <direct/memcpy.h>
+#include <direct/messages.h>
+
+#include <core/layers_internal.h>
+
+
+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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <directfb.h>
+
+#include <core/coretypes.h>
+
+
+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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <config.h>
+
+#include <directfb.h>
+
+#include <core/coredefs.h>
+#include <core/coretypes.h>
+
+#include <direct/debug.h>
+#include <direct/messages.h>
+#include <direct/util.h>
+
+#include <fusion/shmalloc.h>
+
+#include <core/core.h>
+#include <core/gfxcard.h>
+#include <core/layer_context.h>
+#include <core/layer_control.h>
+#include <core/layer_region.h>
+#include <core/layers_internal.h>
+#include <core/surface.h>
+
+#include <gfx/util.h>
+
+
+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,
+ &region->surface_reaction );
+
+ /* Unlink from structure. */
+ dfb_surface_unlink( &region->surface );
+ }
+
+ /* Unlink the context from the structure. */
+ dfb_layer_context_unlink( &region->context );
+
+ /* Free driver's region data. */
+ if (region->region_data)
+ SHFREE( shared->shmpool, region->region_data );
+
+ /* Deinitialize the lock. */
+ fusion_skirmish_destroy( &region->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( &region->context, context )) {
+ fusion_object_destroy( &region->object );
+ return DFB_FUSION;
+ }
+
+ /* Initialize the lock. */
+ if (fusion_skirmish_init( &region->lock, "Layer Region", dfb_core_world(layer->core) )) {
+ dfb_layer_context_unlink( &region->context );
+ fusion_object_destroy( &region->object );
+ return DFB_FUSION;
+ }
+
+ /* Change global reaction lock. */
+ fusion_object_set_lock( &region->object, &region->lock );
+
+ region->state = CLRSF_FROZEN;
+
+ /* Activate the object. */
+ fusion_object_activate( &region->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, &region->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,
+ &region->surface_reaction );
+
+ /* Unlink surface from structure. */
+ dfb_surface_unlink( &region->surface );
+ }
+
+ /* Take the new surface. */
+ if (surface) {
+ /* Link surface into structure. */
+ if (dfb_surface_link( &region->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, &region->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, &region->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, &region->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, &region->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( &region->lock );
+}
+
+DirectResult
+dfb_layer_region_unlock( CoreLayerRegion *region )
+{
+ D_ASSERT( region != NULL );
+
+ return fusion_skirmish_dismiss( &region->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, &region->config,
+ CLRCF_PALETTE, surface, surface->palette,
+ &region->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, &region->config,
+ CLRCF_ALPHA_RAMP, surface, surface->palette,
+ &region->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, &region->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, &region->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, &region->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, &region->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, &region->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, &region->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, &region->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, &region->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, &region->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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <directfb.h>
+
+#include <core/coretypes.h>
+#include <core/layers.h>
+
+#include <fusion/object.h>
+
+
+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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <directfb.h>
+
+#include <direct/debug.h>
+#include <direct/mem.h>
+#include <direct/memcpy.h>
+#include <direct/messages.h>
+
+#include <fusion/shmalloc.h>
+#include <fusion/arena.h>
+#include <fusion/property.h>
+
+#include <core/core.h>
+#include <core/coredefs.h>
+#include <core/coretypes.h>
+
+#include <core/core_parts.h>
+
+#include <core/input.h>
+#include <core/gfxcard.h>
+#include <core/layer_context.h>
+#include <core/layer_control.h>
+#include <core/layer_region.h>
+#include <core/layers.h>
+#include <core/state.h>
+#include <core/palette.h>
+#include <core/system.h>
+#include <core/windows.h>
+
+#include <gfx/convert.h>
+#include <gfx/util.h>
+
+#include <misc/conf.h>
+#include <misc/util.h>
+
+#include <core/layers_internal.h>
+#include <core/screens_internal.h>
+
+
+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; i<dfb_num_layers; i++) {
+ char buf[24];
+ CoreLayerShared *lshared;
+ CoreLayer *layer = dfb_layers[i];
+ const DisplayLayerFuncs *funcs = layer->funcs;
+
+ /* 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; n<lshared->description.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; i<dfb_num_layers; i++) {
+ CoreLayer *layer = dfb_layers[i];
+ CoreLayerShared *lshared = shared->layers[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( &region->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; i<dfb_num_layers; i++) {
+ CoreLayer *layer = dfb_layers[i];
+
+ /* Deinitialize the state for window stack repaints. */
+ dfb_state_destroy( &layer->state );
+
+ /* 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; i<dfb_num_layers; i++)
+ dfb_layer_resume( dfb_layers[i] );
+
+ return DFB_OK;
+}
+
+/**********************************************************************************************************************/
+
+CoreLayer *
+dfb_layers_register( CoreScreen *screen,
+ void *driver_data,
+ const DisplayLayerFuncs *funcs )
+{
+ CoreLayer *layer;
+
+ D_ASSERT( screen != NULL );
+ D_ASSERT( funcs != NULL );
+
+ if (dfb_num_layers == MAX_LAYERS) {
+ D_ERROR( "DirectFB/Core/Layers: "
+ "Maximum number of layers reached!\n" );
+ return NULL;
+ }
+
+ /* allocate local data */
+ layer = D_CALLOC( 1, sizeof(CoreLayer) );
+
+ /* assign local pointers */
+ layer->device = 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; i<entries; i++) {
+ AnyFunc *newfuncs = (AnyFunc*) funcs;
+ AnyFunc *oldfuncs = (AnyFunc*) primary->funcs;
+
+ 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<dfb_num_layers; i++) {
+ if (callback( dfb_layers[i], ctx ) == DFENUM_CANCEL)
+ break;
+ }
+}
+
+int
+dfb_layer_num( void )
+{
+ return dfb_num_layers;
+}
+
+CoreLayer *
+dfb_layer_at( DFBDisplayLayerID id )
+{
+ D_ASSERT( id >= 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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <directfb.h>
+
+#include <core/coretypes.h>
+
+#include <core/gfxcard.h>
+#include <core/surface_buffer.h>
+
+
+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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <directfb.h>
+
+#include <core/coredefs.h>
+#include <core/coretypes.h>
+
+#include <fusion/object.h>
+#include <fusion/property.h>
+#include <fusion/vector.h>
+
+#include <core/layers.h>
+#include <core/layer_region.h>
+#include <core/state.h>
+
+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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <config.h>
+
+#include <direct/debug.h>
+#include <direct/mem.h>
+
+#include <fusion/fusion.h>
+
+#include <core/core.h>
+#include <core/surface_pool.h>
+
+
+/**********************************************************************************************************************/
+
+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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <config.h>
+
+#include <directfb.h>
+
+#include <fusion/shmalloc.h>
+
+#include <core/coredefs.h>
+#include <core/coretypes.h>
+
+#include <core/core.h>
+#include <core/surface.h>
+#include <core/gfxcard.h>
+#include <core/palette.h>
+#include <core/colorhash.h>
+
+#include <gfx/convert.h>
+
+#include <misc/util.h>
+
+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, &notification, 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; i<palette->num_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; i<palette->num_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, &notification, 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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <directfb.h>
+#include <core/coretypes.h>
+#include <fusion/object.h>
+
+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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <config.h>
+
+#include <direct/debug.h>
+
+#include <fusion/conf.h>
+#include <fusion/shmalloc.h>
+#include <fusion/shm/pool.h>
+
+#include <core/core.h>
+#include <core/surface_pool.h>
+
+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; index<MAX_SURFACE_BUFFERS; index++) {
+ if (surface->buffers[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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <config.h>
+
+#include <directfb.h>
+
+#include <direct/debug.h>
+
+#include <core/layers.h>
+#include <core/screen.h>
+#include <core/screens_internal.h>
+
+
+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; i<shared->description.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; i<shared->description.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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <core/coretypes.h>
+
+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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <config.h>
+
+#include <directfb.h>
+
+#include <direct/debug.h>
+#include <direct/mem.h>
+#include <direct/memcpy.h>
+#include <direct/messages.h>
+
+#include <fusion/shmalloc.h>
+
+#include <core/core.h>
+#include <core/core_parts.h>
+
+#include <core/screen.h>
+#include <core/screens.h>
+#include <core/screens_internal.h>
+
+#include <core/layers.h>
+
+#include <misc/conf.h>
+
+
+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; i<num_screens; i++) {
+ char buf[24];
+ CoreScreenShared *sshared;
+ CoreScreen *screen = screens[i];
+ ScreenFuncs *funcs = screen->funcs;
+ 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; i<sshared->description.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; i<sshared->description.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; i<sshared->description.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; i<num_screens; i++) {
+ CoreScreen *screen = screens[i];
+ CoreScreenShared *shared = core_screens->screens[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; i<num_screens; i++) {
+ CoreScreen *screen = screens[i];
+
+ /* Free local screen data. */
+ D_FREE( screen );
+ }
+
+ core_screens = NULL;
+ num_screens = 0;
+
+
+ D_MAGIC_CLEAR( data );
+
+ return DFB_OK;
+}
+
+static DFBResult
+dfb_screen_core_suspend( DFBScreenCore *data )
+{
+ int i;
+ DFBScreenCoreShared *shared;
+
+ D_DEBUG_AT( Core_Screen, "dfb_screen_core_suspend( %p )\n", data );
+
+ D_MAGIC_ASSERT( data, DFBScreenCore );
+ D_MAGIC_ASSERT( data->shared, 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; i<num_screens; i++)
+ dfb_screen_resume( screens[i] );
+
+ return DFB_OK;
+}
+
+/**********************************************************************************************************************/
+
+CoreScreen *
+dfb_screens_register( CoreGraphicsDevice *device,
+ void *driver_data,
+ ScreenFuncs *funcs )
+{
+ CoreScreen *screen;
+
+ D_ASSERT( funcs != NULL );
+
+ if (num_screens == MAX_SCREENS) {
+ D_ERROR( "DirectFB/Core/screen: "
+ "Maximum number of screens reached!\n" );
+ return NULL;
+ }
+
+ /* allocate local data */
+ screen = D_CALLOC( 1, sizeof(CoreScreen) );
+
+ /* assign local pointers */
+ screen->device = 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; i<entries; i++) {
+ AnyFunc *newfuncs = (AnyFunc*) funcs;
+ AnyFunc *oldfuncs = (AnyFunc*) primary->funcs;
+
+ 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<num_screens; i++) {
+ if (callback( screens[i], ctx ) == DFENUM_CANCEL)
+ break;
+ }
+}
+
+CoreScreen *
+dfb_screens_at( DFBScreenID screen_id )
+{
+ D_ASSERT( screen_id >= 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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <directfb.h>
+
+#include <core/coretypes.h>
+
+
+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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <directfb.h>
+
+#include <fusion/lock.h>
+
+#include <core/coretypes.h>
+#include <core/screens.h>
+
+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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <config.h>
+
+#include <direct/debug.h>
+
+#include <fusion/conf.h>
+#include <fusion/shmalloc.h>
+#include <fusion/shm/pool.h>
+
+#include <core/core.h>
+#include <core/surface_pool.h>
+
+#include <misc/conf.h>
+
+/**********************************************************************************************************************/
+
+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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <config.h>
+
+#include <string.h>
+
+#include <pthread.h>
+
+#include <fusion/fusion.h>
+#include <fusion/reactor.h>
+
+#include <directfb.h>
+
+#include <core/core.h>
+#include <core/coretypes.h>
+
+#include <core/palette.h>
+#include <core/state.h>
+#include <core/surface.h>
+
+#include <direct/mem.h>
+#include <direct/memcpy.h>
+#include <direct/util.h>
+
+#include <misc/conf.h>
+
+
+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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <pthread.h>
+
+#include <directfb.h>
+
+#include <direct/serial.h>
+
+#include <fusion/reactor.h>
+
+#include <core/coredefs.h>
+#include <core/coretypes.h>
+#include <core/gfxcard.h>
+#include <core/surface_buffer.h>
+
+#include <gfx/generic/generic.h>
+
+#include <misc/conf.h>
+#include <misc/util.h>
+
+
+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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <config.h>
+
+#include <direct/debug.h>
+
+#include <core/core.h>
+#include <core/palette.h>
+#include <core/surface.h>
+
+#include <core/layers_internal.h>
+#include <core/windows_internal.h>
+
+#include <gfx/convert.h>
+
+
+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; i<MAX_SURFACE_BUFFERS; i++) {
+ if (surface->buffers[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; i<buffers; i++) {
+ CoreSurfaceBuffer *buffer;
+
+ ret = dfb_surface_buffer_new( surface, CSBF_NONE, &buffer );
+ if (ret) {
+ D_DERROR( ret, "Core/Surface: Error creating surface buffer!\n" );
+ goto error;
+ }
+
+ surface->buffers[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; i<MAX_SURFACE_BUFFERS; i++) {
+ if (surface->buffers[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, &notification, 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; i<surface->num_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; i<surface->num_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; i<buffers; i++) {
+ CoreSurfaceBuffer *buffer;
+
+ ret = dfb_surface_buffer_new( surface, CSBF_NONE, &buffer );
+ if (ret) {
+ D_DERROR( ret, "Core/Surface: Error creating surface buffer!\n" );
+ goto error;
+ }
+
+ surface->buffers[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; i<surface->num_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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <directfb.h>
+
+#include <direct/list.h>
+#include <direct/serial.h>
+#include <direct/util.h>
+
+#include <fusion/object.h>
+#include <fusion/reactor.h>
+
+#include <core/coredefs.h>
+#include <core/coretypes.h>
+
+
+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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <config.h>
+
+#include <string.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#ifdef USE_ZLIB
+#include <zlib.h>
+#endif
+
+#include <directfb_util.h>
+
+#include <direct/debug.h>
+#include <direct/memcpy.h>
+
+#include <fusion/shmalloc.h>
+
+#include <core/gfxcard.h>
+#include <core/palette.h>
+#include <core/surface.h>
+#include <core/surface_buffer.h>
+#include <core/surface_pool.h>
+#include <core/surface_pool_bridge.h>
+
+#include <misc/conf.h>
+
+#include <gfx/convert.h>
+
+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; y<rect.h; y++) {
+ memset( destination, 0, bytes );
+
+ destination += pitch;
+ }
+
+ return DFB_OK;
+ }
+
+ /* Use last written allocation if it's up to date... */
+ if (buffer->written && 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; y<rect.h; y++) {
+ direct_memcpy( destination, lock.addr, bytes );
+
+ destination += pitch;
+ lock.addr += lock.pitch;
+ }
+
+ /* Unlock the allocation. */
+ ret = dfb_surface_pool_unlock( allocation->pool, 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; y<rect.h; y++) {
+ if (source) {
+ direct_memcpy( lock.addr, source, bytes );
+
+ source += pitch;
+ }
+ else
+ memset( lock.addr, 0, bytes );
+
+ lock.addr += lock.pitch;
+ }
+
+ /* Unlock the allocation. */
+ ret = dfb_surface_pool_unlock( allocation->pool, 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; i<surface->config.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; n<surface->config.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; n<surface->config.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; i<surface->config.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; i<surface->config.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; i<surface->config.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; i<surface->config.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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <direct/debug.h>
+#include <direct/list.h>
+
+#include <fusion/vector.h>
+
+#include <core/surface.h>
+
+#include <directfb.h>
+
+
+/*
+ * 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; index<MAX_SURFACE_BUFFERS; index++) {
+ if (surface->buffers[index] == buffer)
+ return index;
+ }
+
+ D_ASSERT( index<MAX_SURFACE_BUFFERS );
+
+ return 0;
+}
+
+DFBResult dfb_surface_allocation_update( CoreSurfaceAllocation *allocation,
+ CoreSurfaceAccessFlags access );
+
+#endif
+
diff --git a/Source/DirectFB/src/core/surface_core.c b/Source/DirectFB/src/core/surface_core.c
new file mode 100755
index 0000000..11aa286
--- /dev/null
+++ b/Source/DirectFB/src/core/surface_core.c
@@ -0,0 +1,214 @@
+/*
+ (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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <config.h>
+
+#include <directfb.h>
+
+#include <direct/debug.h>
+#include <direct/mem.h>
+#include <direct/messages.h>
+
+#include <fusion/shmalloc.h>
+
+#include <core/core_parts.h>
+#include <core/surface.h>
+#include <core/surface_buffer.h>
+#include <core/surface_pool.h>
+
+
+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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <directfb.h>
+#include <directfb_util.h>
+
+#include <direct/debug.h>
+#include <direct/mem.h>
+
+#include <fusion/shmalloc.h>
+
+#include <core/core.h>
+#include <core/coredefs.h>
+
+#include <core/surface_buffer.h>
+#include <core/surface_pool.h>
+#include <core/system.h>
+
+#include <gfx/convert.h>
+
+#include <misc/conf.h>
+
+
+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<pool_count; i++) {
+ CoreSurfacePool *pool;
+
+ D_ASSERT( pool_order[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; i<free_count && num<max_pools; i++)
+ ret_pools[num++] = free_pools[i];
+
+ for (i=0; i<oom_count && num<max_pools; i++)
+ ret_pools[num++] = oom_pools[i];
+
+ *ret_num = num;
+
+ return free_count ? DFB_OK : oom_count ? DFB_NOVIDEOMEMORY : DFB_UNSUPPORTED;
+}
+
+DFBResult
+dfb_surface_pools_enumerate( CoreSurfacePoolCallback callback,
+ void *ctx )
+{
+ int i;
+
+ D_ASSERT( callback != NULL );
+
+ D_DEBUG_AT( Core_SurfacePool, "%s( %p, %p )\n", __FUNCTION__, callback, ctx );
+
+ for (i=0; i<pool_count; i++) {
+ CoreSurfacePool *pool = pool_array[i];
+
+ D_MAGIC_ASSERT( pool, CoreSurfacePool );
+
+ if (callback( pool, ctx ) == DFENUM_CANCEL)
+ break;
+ }
+
+ return DFB_OK;
+}
+
+DFBResult
+dfb_surface_pools_allocate( CoreSurfaceBuffer *buffer,
+ CoreSurfaceAccessorID accessor,
+ CoreSurfaceAccessFlags access,
+ CoreSurfaceAllocation **ret_allocation )
+{
+ DFBResult ret;
+ int i;
+ CoreSurface *surface;
+ CoreSurfaceAllocation *allocation = NULL;
+ CoreSurfacePool *pools[pool_count];
+ unsigned int num_pools;
+
+ D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );
+ D_FLAGS_ASSERT( access, CSAF_ALL );
+ D_ASSERT( ret_allocation != NULL );
+
+ surface = buffer->surface;
+ 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<num_pools; i++) {
+ CoreSurfacePool *pool = pools[i];
+
+ D_MAGIC_ASSERT( pool, CoreSurfacePool );
+
+ ret = dfb_surface_pool_allocate( pool, buffer, &allocation );
+
+ if (ret == DFB_OK)
+ break;
+
+ /* When an error other than out of memory happens... */
+ if (ret != DFB_NOVIDEOMEMORY) {
+ D_DEBUG_AT( Core_SurfacePool, " -> 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<num_pools; i++) {
+ CoreSurfacePool *pool = pools[i];
+
+ /* Pools with non-oom errors were sorted out above */
+ if (!pool)
+ continue;
+
+ D_MAGIC_ASSERT( pool, CoreSurfacePool );
+
+ ret = dfb_surface_pool_displace( pool, buffer, &allocation );
+
+ if (ret == DFB_OK)
+ break;
+ }
+ }
+
+ /* Still no luck? */
+ if (!allocation) {
+ D_DEBUG_AT( Core_SurfacePool, " -> 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; i<surface->num_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; i<surface->num_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<pool_count-1; i++) {
+ D_ASSERT( pool_order[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<pool_count; i++) {
+ D_DEBUG_AT( Core_SurfacePool, " %c> [%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; i<pool_count; i++) {
+ if (pool_order[i] == pool_count) {
+ direct_memmove( &pool_order[i], &pool_order[i+1], sizeof(pool_order[0]) * (pool_count - i) );
+ break;
+ }
+ }
+ }
+}
+
+/**********************************************************************************************************************/
+
+static void
+remove_allocation( CoreSurfacePool *pool,
+ CoreSurfaceBuffer *buffer,
+ CoreSurfaceAllocation *allocation )
+{
+ int index_buffer;
+ int index_pool;
+
+ 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 );
+
+ /* 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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <directfb.h>
+
+#include <core/coretypes.h>
+
+#include <core/surface.h>
+#include <core/surface_buffer.h>
+
+
+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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <config.h>
+
+#include <directfb.h>
+#include <directfb_util.h>
+
+#include <direct/debug.h>
+#include <direct/mem.h>
+
+#include <fusion/shmalloc.h>
+
+#include <core/core.h>
+#include <core/coredefs.h>
+
+#include <core/surface_buffer.h>
+#include <core/surface_pool.h>
+#include <core/surface_pool_bridge.h>
+#include <core/system.h>
+
+#include <gfx/convert.h>
+
+#include <misc/conf.h>
+
+
+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<bridge_count; i++) {
+ CoreSurfacePoolBridge *bridge = bridge_array[i];
+
+ D_MAGIC_ASSERT( bridge, CoreSurfacePoolBridge );
+
+ if (callback( bridge, ctx ) == DFENUM_CANCEL)
+ break;
+ }
+
+ return DFB_OK;
+}
+
+static DFBResult
+allocate_transfer( CoreSurfacePoolBridge *bridge,
+ CoreSurfaceBuffer *buffer,
+ CoreSurfaceAllocation *from,
+ CoreSurfaceAllocation *to,
+ const DFBRectangle *rects,
+ unsigned int num_rects,
+ CoreSurfacePoolTransfer **ret_transfer )
+{
+ CoreSurfacePoolTransfer *transfer;
+ unsigned int alloc_size;
+
+ D_MAGIC_ASSERT( bridge, CoreSurfacePoolBridge );
+ D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );
+ CORE_SURFACE_ALLOCATION_ASSERT( from );
+ CORE_SURFACE_ALLOCATION_ASSERT( to );
+ D_ASSERT( rects != NULL );
+ D_ASSERT( num_rects > 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 = &rect;
+ num_rects = 1;
+ }
+
+ for (i=0; i<bridge_count; i++) {
+ bridge = bridge_array[i];
+ D_MAGIC_ASSERT( bridge, CoreSurfacePoolBridge );
+
+ funcs = get_funcs( bridge );
+ D_ASSERT( funcs->CheckTransfer != 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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <directfb.h>
+
+#include <core/coretypes.h>
+
+#include <core/surface.h>
+#include <core/surface_buffer.h>
+
+
+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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <config.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include <directfb.h>
+
+#include <direct/list.h>
+
+#include <core/coredefs.h>
+#include <core/coretypes.h>
+#include <core/core_parts.h>
+#include <core/layers.h>
+#include <core/palette.h>
+#include <core/surface.h>
+#include <core/system.h>
+
+#include <gfx/convert.h>
+
+#include <misc/conf.h>
+
+#include <direct/mem.h>
+#include <direct/messages.h>
+#include <direct/modules.h>
+
+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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <directfb.h>
+
+#include <core/coretypes.h>
+
+#include <direct/modules.h>
+
+#include <fusion/types.h>
+
+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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+
+#include <pthread.h>
+
+#include <fusion/shmalloc.h>
+
+#include <directfb.h>
+
+#include <core/coredefs.h>
+#include <core/coretypes.h>
+
+#include <core/core.h>
+#include <core/layers.h>
+#include <core/layer_context.h>
+#include <core/gfxcard.h>
+#include <core/input.h>
+#include <core/palette.h>
+#include <core/state.h>
+#include <core/system.h>
+#include <core/windows.h>
+#include <core/windowstack.h>
+#include <core/wm.h>
+
+#include <misc/conf.h>
+#include <misc/util.h>
+
+#include <direct/debug.h>
+#include <direct/mem.h>
+#include <direct/messages.h>
+#include <direct/trace.h>
+#include <direct/util.h>
+
+#include <gfx/convert.h>
+#include <gfx/util.h>
+
+#include <core/layers_internal.h>
+#include <core/windows_internal.h>
+
+
+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, &region );
+ 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, &region, &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, &region );
+ 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 "<invalid>";
+}
+
+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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <directfb.h>
+#include <directfb_windows.h>
+
+#include <core/coredefs.h>
+#include <core/coretypes.h>
+
+#include <fusion/object.h>
+
+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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <directfb.h>
+
+#include <core/coredefs.h>
+#include <core/coretypes.h>
+
+#include <core/gfxcard.h>
+#include <core/surface.h>
+#include <core/surface_buffer.h>
+#include <core/windows.h>
+
+#include <direct/list.h>
+#include <fusion/lock.h>
+#include <fusion/object.h>
+
+
+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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <config.h>
+
+#include <string.h>
+
+#include <directfb.h>
+
+#include <direct/debug.h>
+#include <direct/list.h>
+#include <direct/messages.h>
+
+#include <fusion/reactor.h>
+#include <fusion/shmalloc.h>
+
+#include <core/core.h>
+#include <core/input.h>
+#include <core/layer_context.h>
+#include <core/layers_internal.h>
+#include <core/surface.h>
+#include <core/windows_internal.h>
+#include <core/windowstack.h>
+#include <core/wm.h>
+
+#include <misc/conf.h>
+
+#include <gfx/convert.h>
+#include <gfx/util.h>
+
+
+#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, &region, 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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <core/coredefs.h>
+#include <core/coretypes.h>
+
+#include <fusion/lock.h>
+
+/*
+ * 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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <config.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include <directfb.h>
+
+#include <direct/debug.h>
+#include <direct/list.h>
+#include <direct/mem.h>
+#include <direct/messages.h>
+#include <direct/modules.h>
+
+#include <fusion/shmalloc.h>
+
+#include <core/core.h>
+#include <core/coredefs.h>
+#include <core/coretypes.h>
+#include <core/core_parts.h>
+#include <core/layer_context.h>
+#include <core/layers_internal.h>
+#include <core/windowstack.h>
+#include <core/windows_internal.h>
+#include <core/wm.h>
+
+#include <misc/conf.h>
+#include <misc/util.h>
+
+
+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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <directfb.h>
+#include <directfb_windows.h>
+
+#include <direct/modules.h>
+
+#include <core/coretypes.h>
+#include <core/windows.h>
+
+
+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 <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ 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 <core/wm.h>
+
+
+/** 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
+