diff --git a/generic/etc/init.d/lldpd b/generic/etc/init.d/lldpd new file mode 100644 index 0000000..00c8240 --- /dev/null +++ b/generic/etc/init.d/lldpd @@ -0,0 +1,139 @@ +#!/bin/sh + +PATH=/sbin:/usr/sbin:/bin:/usr/bin +DESC="LLDP daemon" +NAME=lldpd +DAEMON=/usr/sbin/$NAME +DAEMON_ARGS="@DAEMON_ARGS@" +PIDFILE=/var/run/$NAME.pid +SCRIPTNAME=/etc/init.d/$NAME +CHROOT=@PRIVSEP_CHROOT@ + +# exit if binary is missing +[ -x "$DAEMON" ] || exit 0 + +# read further config if present +[ -r /etc/default/$NAME ] && . /etc/default/$NAME + +is_running() { + start-stop-daemon -K --quiet --test --exec $DAEMON --pidfile $PIDFILE +} + +do_chroot() { + oldumask=$(umask) + umask 022 + [ -d $CHROOT/etc ] || mkdir -p $CHROOT/etc + [ -f $CHROOT/etc/localtime ] || [ ! -f /etc/localtime ] || \ + cp /etc/localtime $CHROOT/etc/localtime + umask $oldumask +} + +do_start() { + do_chroot + is_running && return 1 + start-stop-daemon -S --quiet --pidfile $PIDFILE --exec $DAEMON -- \ + $DAEMON_ARGS \ + || return 2 +} + +do_stop() { + is_running || return 0 + start-stop-daemon -K --quiet --pidfile $PIDFILE --name $NAME + RETVAL="$?" + + # wait up to 30 seconds until daemon stopped + for i in $(seq 30) + do + sleep 1 + echo -n '.' + if ! is_running + then + break + fi + done + + # see if it's still running + if is_running + then + start-stop-daemon -K --quiet --signal KILL --pidfile $PIDFILE --name $NAME + + for i in $(seq 5) + do + sleep 1 + echo -n '.' + if ! is_running + then + break + fi + done + + if is_running + then + return 2 + fi + fi + + rm -f $PIDFILE + return "$RETVAL" +} + +do_reload() { + # send SIGHUP + start-stop-daemon -K --signal 1 --quiet --pidfile $PIDFILE --name $NAME + return 0 +} + +case "$1" in + start) + echo -n "Starting $DESC ..." + do_start + case "$?" in + 0|1) echo " Done." ;; + 2) echo " Failed." ;; + esac + ;; + stop) + echo -n "Stopping $DESC ." + do_stop + case "$?" in + 0|1) echo " Done." ;; + 2) echo " Failed." ;; + esac + ;; + reload) + echo -n "Reloading $DESC ..." + do_reload + echo " Done." + ;; + restart|force-reload) + echo -n "Restarting $DESC .." + do_stop + case "$?" in + 0|1) + do_start + case "$?" in + 0) echo " Done." ;; + 1) echo " Failed." ;; # Old process still running + *) echo " Failed." ;; # Failed to start + esac + ;; + *) + echo " Failed." # Failed to stop + ;; + esac + ;; + status) + if is_running + then + echo "$NAME is running with PID $(cat $PIDFILE) ..." + else + echo "$NAME is not running" + fi + ;; + *) + echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload|status}" >&2 + exit 3 + ;; +esac + +: diff --git a/patches/DirectFB-1.4.3/0001-fix-X11-detection.patch b/patches/DirectFB-1.4.3/0001-fix-X11-detection.patch deleted file mode 100644 index 9570ad2..0000000 --- a/patches/DirectFB-1.4.3/0001-fix-X11-detection.patch +++ /dev/null @@ -1,42 +0,0 @@ -From ab900fcc9de2c1e2146cbf56abe95caebeba1caa Mon Sep 17 00:00:00 2001 -From: Erwin Rol -Date: Wed, 20 Jan 2010 00:15:56 +0100 -Subject: [PATCH 1/2] fix X11 detection - -Use pkgconfig for X11 detection. This diff is simply cherrypicked from -upstream and should not be needed anymore for the next release -of directfb. - -Signed-off-by: Erwin Rol ---- - configure.in | 14 ++------------ - 1 files changed, 2 insertions(+), 12 deletions(-) - -diff --git a/configure.in b/configure.in -index 1ca4d6d..6b7e0ba 100644 ---- a/configure.in -+++ b/configure.in -@@ -134,18 +134,8 @@ AC_ARG_ENABLE(x11, - enable_x11=yes) - - if test "$enable_x11" = "yes"; then -- CFLAGS_saved="$CFLAGS" -- CFLAGS="$CFLAGS -I/usr/X11R6/include" -- AC_CHECK_HEADER(X11/X.h, x11_found=yes, x11_found=no) -- CFLAGS="$CFLAGS_saved" -- if test "$x11_found" = no; then -- enable_x11=no -- AC_MSG_WARN([ --*** no X11/X.h found -- building without X11 support.]) -- else -- X11_LIBS="-L/usr/X11R6/lib -lX11 -lXext" -- X11_CFLAGS="-I/usr/X11R6/include" -- fi -+ PKG_CHECK_MODULES([X11], [xproto x11 xext], [enable_x11="yes"], [enable_x11="no", -+ AC_MSG_WARN([*** no X11 found -- building without X11 support])]) - fi - - AM_CONDITIONAL(X11_CORE, test "$enable_x11" = "yes") --- -1.6.6 - diff --git a/patches/DirectFB-1.4.3/0002-disable-ppc-memcpy-that-needs-kernel-kernel-config-f.patch b/patches/DirectFB-1.4.3/0002-disable-ppc-memcpy-that-needs-kernel-kernel-config-f.patch deleted file mode 100644 index fa00110..0000000 --- a/patches/DirectFB-1.4.3/0002-disable-ppc-memcpy-that-needs-kernel-kernel-config-f.patch +++ /dev/null @@ -1,33 +0,0 @@ -From be2ee14c009408145dcb2fe26a4667b3e7ed554b Mon Sep 17 00:00:00 2001 -From: Marc Kleine-Budde -Date: Wed, 20 Jan 2010 00:16:34 +0100 -Subject: [PATCH 2/2] disable ppc memcpy that needs kernel kernel config file - -ppcasm_memcpy_cachable.S needs the kernel config to compile. -This patch simply disables the file. - -Signed-off-by: Marc Kleine-Budde ---- - lib/direct/Makefile.am | 5 ----- - 1 files changed, 0 insertions(+), 5 deletions(-) - -diff --git a/lib/direct/Makefile.am b/lib/direct/Makefile.am -index ff89144..33ed187 100644 ---- a/lib/direct/Makefile.am -+++ b/lib/direct/Makefile.am -@@ -22,12 +22,7 @@ EXTRA_DIST = \ - ppc_asm.h - - if BUILDPPCASM --if HAVE_LINUX --ppcasm_sources = ppcasm_memcpy.S ppcasm_memcpy_cachable.S --else - ppcasm_sources = ppcasm_memcpy.S --endif -- - ppcasm_headers = ppcasm_memcpy.h ppc_asm.h - endif - --- -1.6.6 - diff --git a/patches/DirectFB-1.4.3/series b/patches/DirectFB-1.4.3/series deleted file mode 100644 index d8faf44..0000000 --- a/patches/DirectFB-1.4.3/series +++ /dev/null @@ -1,2 +0,0 @@ -0001-fix-X11-detection.patch -0002-disable-ppc-memcpy-that-needs-kernel-kernel-config-f.patch diff --git a/patches/DirectFB-1.6.3/DirectFB-1.6.3.stm.patch b/patches/DirectFB-1.6.3/DirectFB-1.6.3.stm.patch new file mode 100644 index 0000000..f2b568c --- /dev/null +++ b/patches/DirectFB-1.6.3/DirectFB-1.6.3.stm.patch @@ -0,0 +1,21527 @@ +diff --git a/SPECS/stm-target-directfb.template b/SPECS/stm-target-directfb.template +new file mode 100644 +index 0000000..16e23e6 +--- /dev/null ++++ b/SPECS/stm-target-directfb.template +@@ -0,0 +1,616 @@ ++%define _dfb_build_config x@BUILD_CONFIG@ ++ ++Name: %{_stm_pkg_prefix}-target-directfb@BUILD_CONFIG@ ++Summary: Hardware graphics acceleration library ++Group: DirectFB/Libraries ++%define _dfbversion 1.6.3 ++%define _abiversion 1.6-0 ++%define _stmversion +STM2013.08.30 ++Version: 1.6.3%{_stmversion} ++Release: 1 ++Epoch: 1 ++License: LGPL ++# created by: ++# git archive --format=tar --prefix=DirectFB-1.6.3/ DIRECTFB_1_6_3 | bzip2 --best > DirectFB-1.6.3.tar.bz2 ++# git diff DIRECTFB_1_6_3..DIRECTFB_1_6_3_STM2013.08.30 | bzip2 --best > DirectFB-1.6.3.stm.patch.bz2 ++# old way: ++# git archive --format=tar --prefix=DirectFB-1.6.1+STM2012.07.25/ DIRECTFB_1_6_1_STM2012.07.25 | bzip2 --best > DirectFB-1.6.1+STM2012.07.25.tar.bz2 ++Source0: DirectFB-%{_dfbversion}.tar.bz2 ++Patch0: DirectFB-%{_dfbversion}.stm.patch.bz2 ++ ++ ++URL: http://www.directfb.org ++Buildroot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-%{_stm_target_arch}-XXXXXX) ++Prefix: %{_stm_cross_target_dir} ++ ++BuildRequires: %{_stm_pkg_prefix}-%{_stm_target_arch}-libpng-dev ++BuildRequires: %{_stm_pkg_prefix}-host-fluxcomp >= 1.4.3 ++%if %target_cpu arm sh ++%define _mme_enabled yes ++%define _stmfbdev --enable-stmfbdev ++%else ++%define _mme_enabled no ++%define _stmfbdev --disable-stmfbdev ++%endif ++%if %target_cpu arm ++%define _multicore_enabled yes ++%else ++%define _multicore_enabled no ++%endif ++%if "%{_dfb_build_config}" == "x-multi" ++BuildRequires: %{_stm_pkg_prefix}-%{_stm_target_arch}-linux-fusion-headers >= 9.0.0 ++%define _dfb_multiapp --enable-multi ++%else ++%if "%{_dfb_build_config}" == "x" ++%define _dfb_multiapp --disable-multi ++%else ++# unsupported, error out ++unsupported BUILD_CONFIG option ++%endif ++%endif ++ ++%define _pkgname %{_stm_pkg_prefix}-%{_stm_target_arch}-directfb ++%define _fullname directfb-%{_abiversion} ++%define _docdir %{_stm_cross_target_dir}%{_stm_target_doc_dir} ++ ++ ++# ++# SRPM Package ++# ++%description ++The source package for directfb. ++ ++# ++# RPMS ++# ++%package -n %{_pkgname}@BUILD_CONFIG@ ++Summary: Hardware graphics acceleration library ++Group: DirectFB/Libraries ++Provides: %{_pkgname} = %{version}-%{release} ++ ++%if "%{_dfb_build_config}" == "x-multi" ++Provides: %{_pkgname}-multi = %{version}-%{release} ++Conflicts: %{_pkgname}-single ++%else ++%if "%{_dfb_build_config}" == "x" ++Provides: %{_pkgname}-single = %{version}-%{release} ++Conflicts: %{_pkgname}-multi ++%endif ++%endif ++%description -n %{_pkgname}@BUILD_CONFIG@ ++DirectFB is a thin library that provides developers with hardware graphics ++acceleration, input device handling and abstraction, an integrated windowing ++system with support for translucent windows and multiple display layers on top ++of the Linux frame buffer device. It is a complete hardware abstraction layer ++with software fallbacks for every graphics operation that is not supported by ++the underlying hardware. ++%if "%{_dfb_build_config}" == "x-multi" ++This version has been built with the Multi Application Core. ++%else ++%if "%{_dfb_build_config}" == "x" ++This version has been built with the Single Application Core. ++%endif ++%endif ++ ++%package -n %{_pkgname}@BUILD_CONFIG@-dev ++Summary: Hardware graphics acceleration library - development ++Group: DirectFB/Development ++AutoReq: no ++Provides: %{_pkgname}-dev = %{version}-%{release} ++%if "%{_dfb_build_config}" == "x-multi" ++Requires: %{_pkgname}-multi = %{version}-%{release} ++Provides: %{_pkgname}-multi-dev = %{version}-%{release} ++%else ++%if "%{_dfb_build_config}" == "x" ++Requires: %{_pkgname}-single = %{version}-%{release} ++Provides: %{_pkgname}-single-dev = %{version}-%{release} ++%endif ++%endif ++%description -n %{_pkgname}@BUILD_CONFIG@-dev ++DirectFB header files needed for building DirectFB applications. ++ ++%package -n %{_pkgname}@BUILD_CONFIG@-dbg ++Summary: Hardware graphics acceleration library - debug info ++Group: DirectFB/Development ++AutoReq: no ++Provides: %{_pkgname}-dbg = %{version}-%{release} ++%if "%{_dfb_build_config}" == "x-multi" ++Requires: %{_pkgname}-multi = %{version}-%{release} ++Provides: %{_pkgname}-multi-dbg = %{version}-%{release} ++%else ++%if "%{_dfb_build_config}" == "x" ++Requires: %{_pkgname}-single = %{version}-%{release} ++Provides: %{_pkgname}-single-dbg = %{version}-%{release} ++%endif ++%endif ++%description -n %{_pkgname}@BUILD_CONFIG@-dbg ++This package provides debug information for DirectFB. Debug information ++is useful for providing meaningful backtraces in case of bugs. ++ ++%package -n %{_pkgname}-bin ++Summary: Hardware graphics acceleration library - binaries ++Group: DirectFB/Development ++%description -n %{_pkgname}-bin ++ DirectFB is a graphics library which was designed with embedded systems ++ in mind. It offers maximum hardware accelerated performance at a minimum ++ of resource usage and overhead. ++ . ++ This package contains the various DirectFB tools, e.g. a background ++ configuration tool, and also the directfbrc man page. ++ ++%package -n %{_pkgname}-tests ++Summary: Hardware graphics acceleration library - tests ++Group: DirectFB/Development ++%description -n %{_pkgname}-tests ++ DirectFB is a graphics library which was designed with embedded systems ++ in mind. It offers maximum hardware accelerated performance at a minimum ++ of resource usage and overhead. ++ . ++ This package various tests that come with the DirectFB source tree. They ++ are normally not needed, except for maybe driver validatation. ++ ++ ++%prep ++%target_setup ++%setup -qn DirectFB-%{_dfbversion} ++%patch0 -p1 ++# the patch contains symlinks (in git format), but only git-patch can ++# deal with these, do it manually ++for i in fb.h vt.h ; do ++ rm -f systems/stmfbdev/${i} ++ ln -s ../fbdev/${i} systems/stmfbdev/ ++done ++%target_autoreconf ++ ++%build ++%target_setup ++# the st231 compiler emits a warning when it encounters multiple -O statements, ++# which makes auto* assume that some of its tests failed. Strip out existing -O ++# and add -O3 ++_stripped_flags= ++for _this_flag in $CFLAGS ; do ++ _stripped_flags="${_stripped_flags} `echo $_this_flag | sed -e 's,-O.,,'`" ++done ++export CFLAGS="${_stripped_flags} -O3" ++export CPPFLAGS="$CPPFLAGS -DDIRECTFB_VERSION_VENDOR=\\\"%{_stmversion}\\\"" ++# add -g for debug package ++export CFLAGS="${CFLAGS} -g3" ++export CXXFLAGS="${CFLAGS} -g3" ++ ++%target_do_configure \ ++ --enable-static \ ++ \ ++ --disable-devmem \ ++ --disable-sdl \ ++ %{_stmfbdev} \ ++ \ ++ --enable-voodoo \ ++ \ ++ --with-gfxdrivers=none \ ++ --enable-mme=%{_mme_enabled} \ ++ --enable-multicore=%{_multicore_enabled} \ ++ --with-message-size=65536 \ ++ \ ++ %{_dfb_multiapp} \ ++ \ ++ --with-tests ++%make ++ ++ ++%install ++%target_setup ++%target_makeinstall_destdir ++# make sure the graphics drivers directory exists as we don't (necessarily) ++# build graphics drivers. This will ensure a defined owner of this directory ++# (the DirectFB RPMs), also ensuring that the directory is removed during ++# uninstall of the DFB RPMs. ++mkdir -p %{buildroot}%{_stm_cross_target_dir}%{_stm_target_lib_dir}/%{_fullname}/gfxdrivers ++ ++# build directfb-config for host environment ++# we assume that _stm_target_lib_dir is in the default search path of both the cross ++# and target dynamic linkers, to suppres spurious -L/usr/lib in *.la files ++mkdir -p %{buildroot}%{_stm_cross_bin_dir} ++sed -e "s,libs=-L%{_stm_target_lib_dir},libs=,g" \ ++ -e "s,%{_stm_target_prefix},%{_stm_cross_target_dir}%{_stm_target_prefix},g" \ ++ < %{buildroot}%{_stm_cross_target_dir}%{_stm_target_bin_dir}/directfb-config \ ++ > %{buildroot}%{_stm_cross_bin_dir}/%{_stm_target_toolprefix}directfb-config ++chmod +x %{buildroot}%{_stm_cross_bin_dir}/%{_stm_target_toolprefix}directfb-config ++ ++%target_install_fixup ++# Process target .pc files so they are useful in a cross environment ++for f in %{buildroot}%{_stm_cross_target_dir}%{_stm_target_pkgconfig_dir}/*.pc ; do ++ sed -i '/^prefix=/!s,%{_stm_target_prefix},${prefix},' $f ++done ++ ++ ++cd .. ++cp COPYING LICENSE ++ ++ ++# pull debug from elf files out into separate files, to be packaged in the -dbg package ++: > debugfiles.list ++files=`find %{buildroot}%{_stm_cross_target_dir}%{_stm_target_bin_dir} -type f` || true ++files="${files} `find %{buildroot}%{_stm_cross_target_dir}%{_stm_target_lib_dir} -name '*so*' -type f | egrep -v '\.debug$' | egrep '(\.so$|\.so\.)'`" ++for elffile in ${files} ; do ++ sofile=`readelf -h ${elffile} 2> /dev/null | grep "DYN"` || true ++ execfile=`readelf -h ${elffile} 2> /dev/null | grep "EXEC"` || true ++ if [ "X${sofile}" != "X" -o "X${execfile}" != "X" ] ; then ++ debugfile=%{_stm_cross_target_dir}%{_stm_target_debug_dir}`echo ${elffile} | sed -e s,%{buildroot}%{_stm_cross_target_dir},,`.debug ++ mkdir -p `dirname %{buildroot}${debugfile}` ++ %{_stm_target_toolprefix}objcopy --only-keep-debug ${elffile} %{buildroot}${debugfile} ++ %{_stm_target_toolprefix}objcopy --strip-debug ${elffile} ++ %{_stm_target_toolprefix}objcopy --add-gnu-debuglink=%{buildroot}${debugfile} ${elffile} ++ echo ${debugfile} >> debugfiles.list ++ fi ++done ++ ++ ++%clean ++rm -rf %{buildroot} ++ ++ ++%files -n %{_pkgname}@BUILD_CONFIG@ ++%defattr(-,root,root) ++%{_stm_cross_target_dir}%{_stm_target_lib_dir}/lib*.so.* ++%dir %{_stm_cross_target_dir}%{_stm_target_lib_dir}/%{_fullname} ++%dir %{_stm_cross_target_dir}%{_stm_target_lib_dir}/%{_fullname}/* ++%{_stm_cross_target_dir}%{_stm_target_lib_dir}/%{_fullname}/*/lib*.so ++%dir %{_stm_cross_target_dir}%{_stm_target_lib_dir}/%{_fullname}/interfaces/* ++%{_stm_cross_target_dir}%{_stm_target_lib_dir}/%{_fullname}/interfaces/*/lib*.so ++%dir %{_stm_cross_target_dir}%{_stm_target_data_dir}/directfb-%{_dfbversion} ++%{_stm_cross_target_dir}%{_stm_target_data_dir}/directfb-%{_dfbversion}/cursor.dat ++%doc AUTHORS ChangeLog LICENSE NEWS README TODO ++ ++%files -n %{_pkgname}@BUILD_CONFIG@-dev ++%defattr(-,root,root) ++%{_stm_cross_target_dir}%{_stm_target_bin_dir}/directfb-config ++%{_stm_cross_target_dir}%{_stm_target_bin_dir}/directfb-csource ++%{_stm_cross_target_dir}%{_stm_target_include_dir}/directfb ++%{_stm_cross_target_dir}%{_stm_target_include_dir}/directfb-internal ++%{_stm_cross_target_dir}%{_stm_target_lib_dir}/lib*.so ++%{_stm_cross_target_dir}%{_stm_target_lib_dir}/lib*.a ++%{_stm_cross_target_dir}%{_stm_target_lib_dir}/lib*.la ++%{_stm_cross_target_dir}%{_stm_target_lib_dir}/%{_fullname}/*/lib*.a ++%{_stm_cross_target_dir}%{_stm_target_lib_dir}/%{_fullname}/*/lib*.la ++%{_stm_cross_target_dir}%{_stm_target_lib_dir}/%{_fullname}/*/lib*.o ++%{_stm_cross_target_dir}%{_stm_target_lib_dir}/%{_fullname}/interfaces/*/lib*.a ++%{_stm_cross_target_dir}%{_stm_target_lib_dir}/%{_fullname}/interfaces/*/lib*.la ++%{_stm_cross_target_dir}%{_stm_target_lib_dir}/%{_fullname}/interfaces/*/lib*.o ++%{_stm_cross_target_dir}%{_stm_target_pkgconfig_dir}/*.pc ++%{_stm_cross_target_dir}%{_stm_target_data_dir}/man/man1/directfb-csource*1* ++%{_stm_cross_bin_dir}/* ++%doc AUTHORS ChangeLog LICENSE NEWS README TODO ++ ++%files -n %{_pkgname}@BUILD_CONFIG@-dbg -f debugfiles.list ++%defattr(-,root,root) ++%doc AUTHORS ChangeLog LICENSE NEWS README TODO ++ ++%files -n %{_pkgname}-bin ++%defattr(-,root,root) ++%{_stm_cross_target_dir}%{_stm_target_bin_dir}/dfbdump ++%{_stm_cross_target_dir}%{_stm_target_bin_dir}/dfbfx ++%{_stm_cross_target_dir}%{_stm_target_bin_dir}/dfbg ++%{_stm_cross_target_dir}%{_stm_target_bin_dir}/dfbinfo ++%{_stm_cross_target_dir}%{_stm_target_bin_dir}/dfbinput ++%{_stm_cross_target_dir}%{_stm_target_bin_dir}/dfbinspector ++%{_stm_cross_target_dir}%{_stm_target_bin_dir}/dfblayer ++%{_stm_cross_target_dir}%{_stm_target_bin_dir}/dfbmaster ++%{_stm_cross_target_dir}%{_stm_target_bin_dir}/dfbpenmount ++%{_stm_cross_target_dir}%{_stm_target_bin_dir}/dfbproxy ++%{_stm_cross_target_dir}%{_stm_target_bin_dir}/dfbscreen ++%{_stm_cross_target_dir}%{_stm_target_bin_dir}/dfbdumpinput ++%{_stm_cross_target_dir}%{_stm_target_bin_dir}/mkdfiff ++%{_stm_cross_target_dir}%{_stm_target_bin_dir}/mkdgiff ++%{_stm_cross_target_dir}%{_stm_target_bin_dir}/mkdgifft ++%{_stm_cross_target_dir}%{_stm_target_bin_dir}/voodooplay ++%{_stm_cross_target_dir}%{_stm_target_bin_dir}/voodooplay_client ++%{_stm_cross_target_dir}%{_stm_target_bin_dir}/voodooplay_server ++%{_stm_cross_target_dir}%{_stm_target_data_dir}/man/man1/dfbg*1* ++%{_stm_cross_target_dir}%{_stm_target_data_dir}/man/man5/directfbrc*5* ++%doc AUTHORS ChangeLog LICENSE NEWS README TODO ++ ++%files -n %{_pkgname}-tests ++%defattr(-,root,root) ++%{_stm_cross_target_dir}%{_stm_target_bin_dir}/coretest_* ++%{_stm_cross_target_dir}%{_stm_target_bin_dir}/dfbtest_* ++%{_stm_cross_target_dir}%{_stm_target_bin_dir}/direct_* ++%{_stm_cross_target_dir}%{_stm_target_bin_dir}/fusion_* ++%{_stm_cross_target_dir}%{_stm_target_bin_dir}/voodoo_bench* ++%dir %{_stm_cross_target_dir}%{_stm_target_data_dir}/directfb-%{_dfbversion} ++%{_stm_cross_target_dir}%{_stm_target_data_dir}/directfb-%{_dfbversion}/decker.dgiff ++%doc AUTHORS ChangeLog LICENSE NEWS README TODO ++ ++ ++%changelog ++* Fri Aug 30 2013 Ilyes Gouta - 1:1.6.3+STM2013.08.30-1 ++- [Bugzilla: 29557] colour fill to NV12 and NV21 broken ++- [Bugzilla: 29559] IDirectFBSurface::Dump() for DSPF_YUV444P incorrect ++- [Bugzilla: 29496] IDirectFBSurface::Dump() for DSPF_(A)VYU incorrect ++- [Bugzilla: 29512] IDirectFBSurface::Dump() for DSPF_YV16 incorrect ++- [Bugzilla: 29985] DSPF_NV12MB and DSPF_NV16MB aren't marked as YCbCr ++- [Bugzilla: 35133] WebP imageprovider crashes when doing multiple RenderTo() ++- inputdrivers: set DICAPS_KEYS only for input devices with keys ++- imageprovider: add a new TIFF image provider ++ ++* Wed Jun 12 2013 André Draszik - 1:1.6.3+STM2013.04.10-2 ++- [Spec; Bugzilla: 31952] make sure we create and own the gfxdrivers directory ++ ++* Wed Apr 10 2013 Ilyes Gouta - 1:1.6.3+STM2013.04.10-1 ++- [Bugzilla: 29280] idirectfb: allow creating NV1xMB surfaces with ++ DSCAPS_PREMULTIPLIED set ++- imageprovider: add WebP imageprovider ++- hwjpeg: early validate the JPEG buffer with the h/w decoder ++- hwjpeg: don't downsample NV24 to a temporary NV16 buffer ++- [Bugzilla: 27188] fusion: ref: immediately execute FusionCall in ++ fusion_ref_down() ++- [Bugzilla: 16971] Revert ++ "direct: replace C++ style comments by standard C comments" ++- [Bugzilla: 27699] interfaces: gif: fix up DVPLAY_PACED decoding mode ++- [Bugzilla: 27886] idirectfb: don't clear config.surface_caps if already set ++ ++* Mon Feb 25 2013 Francesco Virlinzi 2 ++- [Spec; Bugzilla: 23138] Make compatible with rpm-build 4.10. ++ ++* Fri Feb 01 2013 Ilyes Gouta - 1:1.6.3+STM2013.02.01-1 ++- [Update: 1.6.3] update to 1.6.3 release ++- [Bugzilla: 25124] direct: reimplement direct_waitqueue_wait_timeout() to use ++ clock_gettime() ++- interfaces: jpeg: new hwjpeg-v4l2 image provider ++- directfb: new DSPF_NV24 pixel format ++- directfb: new DSPF_BYTE pixel format ++ ++* Fri Sep 21 2012 Ilyes Gouta - 1:1.6.1+STM2012.09.21-1 ++- [Bugzilla: 21232] DirectFB-1.6: Grayscale JPEG decoding is broken ++- [Bugzilla: 21233] DirectFB-1.6: LUT4 (or LUT2) animated gif doesn't ++ get rendered properly ++- [Bugzilla: 16971] DirectFB-1.6: replace C++ style comments by ++ standard C comments ++- [Bugzilla: 18969] Bad interaction between libmme.so and DirectFB ++ ++* Wed Aug 01 2012 Ilyes Gouta - 1:1.6.1+STM2012.07.25-1 ++- [Spec] configure with a 65356 bytes per Fusion message buffer (IPC) ++- [Spec] disable parallel build process (fluxcomp/gcc concurrency) ++ ++* Wed Jul 25 2012 André Draszik - 1:1.6.1+STM2012.07.25-1 ++- [Update: 1.6.1] update to 1.6.1 release ++- [Spec] change contents of SRPM to contain pristine tarball + STM patch ++- [Spec] add BuildRequires for fluxcomp ++- [Spec] enable voodoo during configure ++- [Spec] package binaries in new -bin package and move man pages here ++- [Spec] package tests in new -tests package ++- [Spec] always fully disable gfxdrivers, stgfx(1) is completely gone, ++ and stgfx2 is now hosted elsewhere ++- [Spec] build armv7 version with multicore support (SMP) ++- [Spec] always fully disable gfxdrivers, stgfx(1) is completely gone, ++ and stgfx2 is now hosted elsewhere ++- [Spec] forcefully enable stmfbdev on SH4 and ARM ++- [Bugzilla: 18771] stmfbdev: don't error out if display driver announced no ++ supported modes ++- stmfbdev: fix to actually allow configuring DVO, allow selection ++ between RGB 24bit and YCbCr 444 16bit ++- stmfbdev: add support for 960x540 and 1440x540 NTG5 modes ++- stmfbdev: for HDMI outputs, be more explicit about YCbCr 444 / 422 / RGB ++- move all of the stmfbdev layer and screen handling out of stgfx2, so that ++ stmfbdev can be used independently of any hardware acceleration ++- [Bugzilla: 12425] JPEG decode segfaults for iDCT downscaled grayscale images ++- [Bugzilla: 16039] jpeg software decode error path broken in case h/w decode ++ failed earlier ++- [Bugzilla: 16040] jpeg: optimise grayscale JPEG decoding ++- jpeg: use JDCT_FASTEST instead of JDCT_IFAST ++- image providers: change the backgrounded image provider API to use the ++ DIRenderFlags that upstream added recently, instead of our ++ DFBImageProviderFlags ++- rle: remove image provider ++- add DSPF_LUT4 implementation ++- add DSPF_BGR24 implementation ++- add DSPF_NV12MB and DSPF_NV16MB and (incomplete) implementation ++- directfb: extend IDirectFBInputDevice to recognize sensors-based input devices ++ ++* Fri Jun 08 2012 Ilyes Gouta 1:1.4.12+STM2011.09.27-3 ++- [Bugzilla: 17925] jpeg: fix stack corruption when going through hardware ++ assisted decode ++- [Bugzilla: 17956] fix SIGSEGV when downscaling via iDCT in the JPEG raw ++ decode path ++- [Bugzilla: 17958] image provider: have to wait for the hardware in certain ++ cases ++- [Bugzilla: 18969] prefer runtime dynamic linking for certain image providers ++- [Delete patch: DirectFB-1.4.12-directfb-improved-idirectfbvideoprovider_gif.patch, ++ DirectFB-1.4.12-directfb-DVPLAY_PACED-declaration.patch, ++ DirectFB-1.4.12-directfb-palette_pass_data-core_instead_of_NULL.patch] ++ not needed anymore ++ ++* Thu Feb 16 2012 Mohamed Hafsia 1:1.4.12+STM2011.09.27-2 ++- [Bugzilla: 16564] Rework IDirectFBVideoProvider_GIF to implement a paced decode ++- [Add patch: DirectFB-1.4.12-directfb-improved-idirectfbvideoprovider_gif.patch, ++ DirectFB-1.4.12-directfb-DVPLAY_PACED-declaration.patch ++ DirectFB-1.4.12-directfb-palette_pass_data-core_instead_of_NULL.patch] ++ Improved DirectFB IDirectFBVideoProvider_gif ++ ++* Tue Sep 27 2011 André Draszik - 1:1.4.12+STM2011.09.27-1 ++- [Bugzilla: 14222] subpixel based backwards blits don't look perfect ++- [Delete patch: ++ DirectFB-1.4.12+STM2011.05.05-bdisp2_accel-fix-directions-for-backwards-copy.patch, ++ DirectFB-1.4.12+STM2011.05.05-bdisp_accel-hot-fix-for-backwards-blits-than-don-t-r.patch] ++ not needed anymore ++ ++* Fri Sep 16 2011 André Draszik - 1:1.4.12+STM2011.05.05-3 ++- [Bugzilla: 14177; Add patch: ++ DirectFB-1.4.12+STM2011.05.05-bdisp2_accel-fix-directions-for-backwards-copy.patch, ++ DirectFB-1.4.12+STM2011.05.05-bdisp_accel-hot-fix-for-backwards-blits-than-don-t-r.patch] ++ hotfix for STLinux bugzilla 14177 ++ ++* Wed Aug 31 2011 Giuseppe Condorelli 1:1.4.12+STM2011.05.05-2 ++- [Spec] Add libpng BuildRequires, also rebuilding package against updated libpng ++ ++* Thu May 05 2011 André Draszik 1:1.4.12+STM2011.05.05-1 ++- [Bugzilla: 11922] really fix raw jpeg decoding for libjpeg >= v7 ++- [Bugzilla: 10850, 12050] clipping in "fb_gfxcard_drawstring" not checked correctly ++- fix small memory leak in DirectGetInterface() ++ ++* Thu Apr 14 2011 André Draszik 1:1.4.12+STM2011.04.14-1 ++- [Update: 1.4.12+STM2011.04.14] update to DirectFB 1.4.12 and latest STM version ++- [Bugzilla: 11689] inputdrivers: support lirc>=0.8.6 ++- [Bugzilla: 11884] build: libidirectfbfont_ft2 must be linked against libm ++- [Delete patch: DirectFB-1.4.11-non-mme-hotfix.patch] not needed anymore ++- [Bugzilla: 11922] fix raw jpeg decoding for libjpeg >= v7 ++ ++* Tue Apr 05 2011 André Draszik 1:1.4.11+STM2010.12.15-4 ++- [Bugzilla: 11825; Spec] add debug info package ++- [Spec] update summary of -dev package ++ ++* Thu Jan 06 2011 André Draszik 1:1.4.11+STM2010.12.15-3 ++- [Add patch: DirectFB-1.4.11-non-mme-hotfix.patch] hotfix for builds with ++ disabled MME ++- Breaks binary compatibility with Mali drivers (Mali drivers need to be rebuilt) ++ ++* Wed Jan 05 2011 André Draszik 1:1.4.11+STM2010.12.15-2 ++- [Spec] disable MME use for image decoding for non sh4 builds during configure ++ to fix build failures on ARM ++ ++* Wed Dec 15 2010 André Draszik 1:1.4.11+STM2010.12.15-1 ++- [Update: 1.4.11+STM2010.12.15] new release based on 1.4.11 + git 811a8c0 ++- [Bugzilla: 10320] don't set any output resolution on startup ++- [Bugzilla: 10344] take DirectFB's init-layer= option into account ++- [Bugzilla: 10769] want SOURCE2 support in DirectFB BDisp driver ++- image providers: accelerate JPEG and PNG using MME ++- fixed point fixes ++- [Delete patch: DirectFB-1.4.3-0001-stgfx2-version-bump.patch] integrated upstream ++- [Spec] Bump BuildRequires for linux-fusion to 8.2.0 ++- [Spec] drop setting of LIBPNG_CONFIG - it's not needed anymore ++ ++* Thu Oct 21 2010 André Draszik 1:1.4.3+STM2010.10.15-1 ++- [Add patch: DirectFB-1.4.3-0001-stgfx2-version-bump.patch] bump stgfx2 version ++ to 0.8 ++ ++* Fri Oct 15 2010 André Draszik 1:1.4.3+STM2010.10.15-1 ++- [Update: 1.4.3+STM2010.10.15] new release ++- [Bugzilla: 10253] jpeg: fix raw decode error paths ++- [Bugzilla: 10242] stgfx2: DSBLIT_XOR does not work ++- [Bugzilla: 10254] stgfx2: incorrect use of line filters for 'slim' stretch blits ++- [Bugzilla: 10228] stgfx2: disable use of hw based clipping ++- [Bugzilla: 10226] stgfx2: full DSBLIT_BLEND_COLORALPHA support ++- [Bugzilla: 10227] stgfx2: fix some 'unusual' PorterDuff blends ++- [Bugzilaa: 10247] stgfx2: DSPD_CLEAR crashes the BDisp in 422r modes ++- stgfx2 cleanup: blit state rewrite, compiler warnings, debug for DirectFB 1.4.3, ++ fixes for RGB32 ++- [Spec] some changes so as to make future updates easier ++ ++* Thu Aug 26 2010 André Draszik 1:1.4.3+STM2010.06.22-2 ++- [Spec] fix build requires to reference correct stmfb headers package version ++ on sh4 ++ ++* Wed Aug 25 2010 André Draszik 1:1.4.3+STM2010.06.22-1 ++- [Update: 1.4.3+STM2010.06.22] new release ++- [Delete patch: DirectFB-1.4.3+STM2010.06.16-stmfb0029.patch] we have an up to ++ date stmfb in STLinux 2.4 now, so this patch is a) harmful for STi7108 support ++ and b) not needed anymore anyway ++- stgfx2: fix clip validation ++ ++* Wed Jun 16 2010 André Draszik 1:1.4.3+STM2010.06.16-1 ++- [Update: 1.4.3.STM2010.06.16] new release ++- [Delete patch: DirectFB-1.4.3.STM2010.03.10-libjpeg7.patch, ++ DirectFB-1.4.3.STM2010.03.10-libjpeg7_2.patch] ++ jpeg problems correctly fixed upstream ++- [Delete patch: DirectFB-1.4-Revert-versioned-DirectFB-libraries.patch] ++ not needed anymore ++- [Add patch: DirectFB-1.4.3+STM2010.06.16-stmfb0029.patch] needed now ++ ++* Tue Apr 27 2010 André Draszik 1.4.3.STM2010.03.10-4 ++- [Bugzilla: 8912; Add patch: DirectFB-1.4.3.STM2010.03.10-libjpeg7.patch, ++ DirectFB-1.4.3.STM2010.03.10-libjpeg7_2.patch] ++ fix libjpeg usage for libjpeg versions >= 7 ++- [Spec] simplify file ownership list ++- [Spec] bump version to rebuild against updated libjpeg ++ ++* Tue Apr 13 2010 André Draszik 1.4.3.STM2010.03.10-3 ++- [Spec] fix source package name ++ ++* Wed Mar 31 2010 Stuart Menefy 2 ++- [Spec] Bump the release number for 2.4 product release. ++- [Spec] Update BuildRoot to use %%(mktemp ...) to guarantee a unique name. ++ ++* Wed Mar 09 2010 André Draszik 1.4.3.STM2010.03.10-1 ++- [Spec] add some more files to main package's documentation ++- merge in latest updates from DirectFB/master branch ++- input: handle button devices with just up/down keys as keyboards, too ++- stgfx2: fix shutdown error path ++- stgfx2: big cleanup regarding the destination address ++- stgfx2: slightly smaller cleanup regarding the s3 address & type ++- stgfx2: cleanup regarding s2 address & type ++- stgfx2: huge cleanup regarding drawing state ++- the above four changes yield in about 10% less CPU usage on fills! ++- [Bugzilla: 8256] XOR doesn't work as expected ++- [Bugzilla: 8406] prevent BDisp crash when doing YCbCr422R fast blit ++- [Bugzilla: 8366] desaturation of YCbCr surfaces ++- stgfx2: back to bdisp_aq_VideoYCbCr601_2_RGB matrix for YCbCr->RGB conversions ++- stgfx2: allow 'other' accelerators to access our surface pools ++- stgfx2: RGB32 updates ++ ++* Fri Feb 05 2010 André Draszik 1.4.3.STM2010.02.08-1 ++- [Bugzilla: 8193] do necessary changes (pollvsync_after) ++- [Bugzilla: 7360, 8077] subpixel vertical filter setup has been ++ greatly simplified and corrected ++ ++* Fri Feb 05 2010 André Draszik 1.4.3.STM2010.02.05-1 ++- stgfx stgfx2: fix shutdown when not running in stmfbdev system ++- linux_input: fix compilation if stmfbdev is disabled ++ ++* Sun Jan 31 2010 André Draszik 1.4.3.STM2010.01.31-1 ++- merge in latest updates from DirectFB/master branch ++- stmfbdev: address compiler warnings in non debug builds ++- stmfbdev: fix crash in shutdown ++- stmfbdev: optimize ioctl handling ++- stmfbdev: don't instanciate screens, layers & surface pools anymore ++- stgfx/stgfx2: move instanciation of the above here, this gets us rid of more of DirectFB's startup warnings ++ ++* Fri Jan 29 2010 André Draszik 1.4.3.STM2010.01.29-1 ++- [Bugzilla: 7995] new system: 'stmfbdev' for many new features reg. screen control ++- stgfx2: ++ + some fixes for blit and fill if destination is YUV ++ + WA for https://bugzilla.stlinux.com/show_bug.cgi?id=7084 ++ + update alignment restrictions for STi7108 ++ + stgfx surface pools: prevent confusing startup message ++- stgfx: ++ + update alignment restrictions for STi7108 ++ + stgfx surface pools: prevent confusing startup message ++- misc: ++ + dfbscreen: little fixes ++ + generic: LUT8 is not a YUV format ++ + screen: NTSC and PAL60 standards are defined as 59.94Hz not 60Hz ++ + IDirectFBScreen: add IDirectFBScreen::GetVSyncCount() ++ + directfb.h: add a DVO 656 'connector' ++ + dfblayer: allow to set layer position and size using command line ++ + dfbinspector: add DSPF_AVYU and DSPF_VYU pixelformats ++- [Delete patch: DirectFB-1.4.3.STM2009.12.11-CLUT8_fix.patch] integrated upstream ++ ++* Fri Jan 29 2010 André Draszik 1.4.3.STM2009.12.11-4 ++- [Add patch: DirectFB-1.4.3.STM2009.12.11-CLUT8_fix.patch] fix CLUT8 issue in ++ software renderer ++ ++* Mon Jan 11 2010 André Draszik 1.4.3.STM2009.12.11-3 ++- [Spec] unify multi app and single app spec files ++ ++* Wed Dec 16 2009 André Draszik 1.4.3.STM2009.12.11-2 ++- [Add patch: DirectFB-1.4.3.STM2009.12.11-autoconf259.patch] so as to enable ++ successful build on arm with old autotools in STLinux-2.3 ++ ++* Fri Dec 11 2009 André Draszik 1.4.3.STM2009.12.11-1 ++- [update: 2009-12.11] update to DirectFB 1.4.3 ++- misc: use pkgconfig to detect X11 ++- misc: surface: replace GetFramebufferOffset() with GetPhysicalAddress() ++- stgfx2: pick up all updates from 1.0.1 branch ++- stgfx2: release surface pools on shutdown ++- [Bugzilla: 7776] stgfx2: cleanup draw/blitting wrt flags ++- stgfx: release surface pools on shutdown ++- [Bugzilla: 7570] jpeg: implement decimated decode for software JPEG decoder ++- [Bugzilla: 7636] jpeg: implement raw libjpeg decode for possible HW acceleration (using stgfx2) ++ ++* Fri Aug 21 2009 André Draszik 1.4.1.STM2009.08.21-1 ++- [update: 2009-08-21] ++ allow source widths and heights < 1.0 (but > 0) in BatchStretchBlit() ++ ++* Tue Aug 18 2009 André Draszik 1.4.1.STM2009.08.18-1 ++- [update: 2009-08-18] ++ ++* Tue Jul 29 2009 André Draszik 1 ++- [update: 1.4.1] new upstream version with all the STM patches +diff --git a/configure.in b/configure.in +index 38d7e78..ec26981 100644 +--- a/configure.in ++++ b/configure.in +@@ -818,6 +818,46 @@ AM_CONDITIONAL(FBDEV_CORE, test "$enable_fbdev" = "yes") + + + ++dnl Test for STMicroelectronics frame buffer system ++stmfbdev_own_headers=no ++AC_ARG_ENABLE(stmfbdev, ++ AC_HELP_STRING([--enable-stmfbdev], ++ [build with STMicroelectronics stmfb system support @<:@default=auto@:>@]), ++ [], [enable_stmfbdev=yes]) ++if test "$have_linux" = "no"; then ++ enable_stmfbdev=no ++ AC_MSG_WARN([ ++*** no linux kernel -- building without STMicroelectronics stmfb system support.]) ++fi ++ ++if test "$enable_stmfbdev" = "yes"; then ++ orig_CFLAGS="$CFLAGS" ++ ++ AC_CHECK_HEADER([linux/stmfb.h], ++ [AC_MSG_CHECKING([whether linux/stmfb.h has stereoscopy support]) ++ AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([[#include ++ #include ]], ++ [[struct stmfbio_3d_configuration 3d_config;]])], ++ [have_stmfbdev_h=yes], ++ [have_stmfbdev_h=no] ++ ) ++ AC_MSG_RESULT([$have_stmfbdev_h]) ++ ], ++ [have_stmfbdev_h=no], ++ [[#include ]]) ++ ++ if test "x$have_stmfbdev_h" != "xyes"; then ++ AC_MSG_WARN([*** STMFB header files not found. Will use own copy!]) ++ fi ++ ++ CFLAGS="$orig_CFLAGS" ++fi ++ ++AM_CONDITIONAL(STMFBDEV_CORE, test "$enable_stmfbdev" = "yes") ++AM_CONDITIONAL([STMFBDEV_USE_OWN_HEADERS], [test "x$have_stmfbdev_h" != "xyes"]) ++ ++ ++ + dnl Test for SDL + AC_ARG_ENABLE(sdl, + AC_HELP_STRING([--enable-sdl], +@@ -884,13 +924,61 @@ AC_SUBST(MESA_CFLAGS) + + + ++dnl test for MME ++MME=no ++mme_own_headers=no ++mme_own_transformers=no ++AC_ARG_ENABLE(mme, ++ AC_HELP_STRING([--enable-mme], ++ [build with MME support @<:@default=yes@:>@]), ++ [], [enable_mme=yes]) ++if test "$enable_mme" = "yes" ; then ++ MME=yes ++ AC_DEFINE(USE_MME, 1, [Define to 1 if MME should be used]) ++ ++ dnl use our own copy of mme.h and try to dlopen() libmme.so ++ AC_MSG_WARN([*** MME library not found. Will use dlopen().]) ++ AC_DEFINE(MME_USE_DLOPEN, 1, [Define to 1 if dlopen() etc should be used for MME libraries]) ++ LIBMME= ++ ++ AC_CHECK_HEADER([mme.h], [mme_ok="yes"], [mme_ok="no"]) ++ if test "$mme_ok" != "yes"; then ++ AC_MSG_WARN([*** MME header files not found. Will use own copy!]) ++ AC_DEFINE(MME_USE_OWN_HEADERS, 1, [Define to 1 if builtin MME headers should be used]) ++ mme_own_headers=yes ++ fi ++ AC_CHECK_HEADERS([JPEG_TransformerTypes.h JPEGDECHW_VideoTransformerTypes.h PNGDecode_interface.h], ++ [mme_ok="yes"], [mme_ok="no"]) ++ if test "$mme_ok" != "yes"; then ++ AC_MSG_WARN([*** MME Transformer header files not found. Will use own copies!]) ++ mme_own_transformers=yes ++ fi ++else ++ MME=no ++fi ++ ++AM_CONDITIONAL(MME_USE_OWN_HEADERS, test "$mme_own_headers" = "yes") ++AM_CONDITIONAL(MME_USE_OWN_TRANSFORMERS, test "$mme_own_transformers" = "yes") ++AC_SUBST(LIBMME) ++ ++ + dnl Test for libjpeg + JPEG=no ++JPEG_HW=no ++JPEG_HW_V4L2=no + + AC_ARG_ENABLE(jpeg, + AC_HELP_STRING([--enable-jpeg], + [build JPEG image provider @<:@default=yes@:>@]), + [], [enable_jpeg=yes]) ++AC_ARG_ENABLE(hwjpeg, ++ AC_HELP_STRING([--enable-hwjpeg], ++ [add hardware acceleration to JPEG image provider @<:@default=yes@:>@]), ++ [], [enable_hwjpeg=yes]) ++AC_ARG_ENABLE(hwjpeg_v4l2, ++ AC_HELP_STRING([--enable-hwjpeg-v4l2], ++ [enable a new JPEG image provider featuring h/w accelerated decoding via V4L2 @<:@default=yes@:>@]), ++ [], [enable_hwjpeg_v4l2=no]) + + if test "$enable_jpeg" = "yes"; then + if test -z "$LIBJPEG"; then +@@ -919,11 +1007,37 @@ if test "$enable_jpeg" = "yes"; then + fi + fi + ++if test "$enable_hwjpeg" != "no"; then ++ if test "$JPEG" = "yes"; then ++ if test "$MME" = "yes" ; then ++ AC_DEFINE(JPEG_PROVIDER_USE_MME, 1, [Define to 1 to enable hardware JPEG decoder]) ++ JPEG_HW=yes ++ JPEG_LIBMME=$LIBMME ++ else ++ AC_MSG_WARN([*** MME not found. Hardware JPEG image provider will not be built.]) ++ JPEG_HW=no ++ fi ++ else ++ AC_MSG_WARN([*** JPEG decoding not enabled. Hardware JPEG image provider can not be built.]) ++ JPEG_HW=no ++ fi ++else ++ JPEG_HW=no ++fi ++ ++if test "$enable_hwjpeg_v4l2" = "yes"; then ++ JPEG_HW_V4L2=yes ++fi ++ + AM_CONDITIONAL(JPEG_PROVIDER, test "$JPEG" = "yes") ++AM_CONDITIONAL(JPEG_PROVIDER_HW, test "$JPEG_HW" = "yes") ++AM_CONDITIONAL(JPEG_PROVIDER_HW_V4L2, test "$JPEG_HW_V4L2" = "yes") + +-if test "$enable_jpeg" != "no" && test "$JPEG" != "yes"; then +- jpeg_warning=" ++if test "$JPEG" != "yes"; then ++ if test "$enable_jpeg" != "no" || test "$enable_hwjpeg" != "no" ; then ++ jpeg_warning=" + JPEG support is missing - many applications won't work correctly!" ++ fi + fi + + +@@ -957,22 +1071,49 @@ AC_SUBST(ZLIB_LIBS) + + dnl Test for libpng + PNG=no ++PNG_HW=no + + AC_ARG_ENABLE(png, + AC_HELP_STRING([--enable-png], + [build PNG image provider, @<:@default=yes@:>@]), + [], [enable_png=yes]) ++AC_ARG_ENABLE(hwpng, ++ AC_HELP_STRING([--enable-hwpng], ++ [add hardware acceleration to PNG image provider @<:@default=yes@:>@]), ++ [], enable_hwpng="yes") ++ + if test "$enable_png" = "yes"; then + PKG_CHECK_MODULES([LIBPNG], [libpng >= 1.2.2], [PNG=yes], [PNG=no + AC_MSG_WARN([*** PNG library not found. PNG image provider will not be built.])]) + fi + ++if test "$enable_hwpng" != "no"; then ++ if test "$PNG" = "yes" ; then ++ if test "$MME" = "yes"; then ++ AC_DEFINE(PNG_PROVIDER_USE_MME, 1, [Define to 1 to enable hardware PNG decoder]) ++ PNG_HW=yes ++ PNG_LIBMME=$LIBMME ++ else ++ AC_MSG_WARN([*** MME not found. Hardware PNG image provider will not be built.]) ++ PNG_HW=no ++ fi ++ else ++ AC_MSG_WARN([*** PNG decoding not enabled. Hardware PNG image provider can not be built.]) ++ PNG_HW=no ++ fi ++else ++ PNG_HW=no ++fi ++ + AM_CONDITIONAL(PNG_PROVIDER, test "$PNG" = "yes") ++AM_CONDITIONAL(PNG_PROVIDER_HW, test "$PNG_HW" = "yes") + AM_CONDITIONAL(BUILD_DIRECTFB_CSOURCE, test "$PNG" = "yes") + +-if test "$enable_png" != "no" && test "$PNG" != "yes"; then +- png_warning=" ++if test "$PNG" != "yes"; then ++ if test "$enable_png" != "no" || "$enable_hwpng" != "no" ; then ++ png_warning=" + PNG support is missing - many applications won't work correctly!" ++ fi + fi + + +@@ -1080,6 +1221,18 @@ AC_ARG_ENABLE(gif, + + AM_CONDITIONAL(GIF_PROVIDER, test "$enable_gif" = "yes") + ++tiff="no" ++AC_ARG_ENABLE(tiff, ++ AC_HELP_STRING([--enable-tiff], ++ [build TIFF image provider, @<:@default=auto@:>@]), ++ [], [enable_tiff=yes]) ++if test "$enable_tiff" = "yes"; then ++ PKG_CHECK_MODULES([LIBTIFF], [libtiff-4], [tiff=yes], [tiff=no ++ AC_MSG_WARN([*** TIFF library not found. TIFF image provider will not be built.])]) ++fi ++ ++AM_CONDITIONAL(TIFF_PROVIDER, test "$tiff" = "yes") ++ + + + dnl Imlib2 check +@@ -1247,6 +1400,21 @@ if test "$V4L" = "yes"; then + fi + fi + ++dnl Test for libwebp ++webp=no ++ ++AC_ARG_ENABLE(webp, ++ AC_HELP_STRING([--enable-webp], ++ [build WebP image provider, @<:@default=auto@:>@]), ++ [], [enable_webp="yes"]) ++if test "$enable_webp" = "yes"; then ++ PKG_CHECK_MODULES([LIBWEBP], [libwebp >= 0.2.1], [webp=yes], [webp=no ++ AC_MSG_WARN([*** WebP library not found. WEBP image provider will not be built.])]) ++fi ++ ++AM_CONDITIONAL(WEBP_PROVIDER, test "$webp" = "yes") ++ ++ + + dnl check which gfxdrivers to build + ati128=no +@@ -2087,11 +2255,13 @@ AC_SUBST(ZLIB_LIBS) + AC_SUBST(GIF_PROVIDER) + AC_SUBST(JPEG_PROVIDER) + AC_SUBST(LIBJPEG) ++AC_SUBST(JPEG_LIBMME) + AC_SUBST(MNG_PROVIDER) + AC_SUBST(LIBMNG) + AC_SUBST(PNG_PROVIDER) + AC_SUBST(LIBPNG_CFLAGS) + AC_SUBST(LIBPNG_LIBS) ++AC_SUBST(PNG_LIBMME) + AC_SUBST(FREETYPE_PROVIDER) + AC_SUBST(FREETYPE_CFLAGS) + AC_SUBST(FREETYPE_LIBS) +@@ -2186,6 +2356,7 @@ systems/x11vdpau/Makefile + systems/osx/Makefile + systems/sdl/Makefile + systems/vnc/Makefile ++systems/stmfbdev/Makefile + + wm/Makefile + wm/default/Makefile +@@ -2323,6 +2494,7 @@ Building System Modules: + OSX support $enable_osx $OSX_CFLAGS $OSX_LIBS + SDL support $enable_sdl $SDL_CFLAGS $SDL_LIBS + VNC support $enable_vnc $VNC_CFLAGS $VNC_LIBS ++ STM stmfb support $enable_stmfbdev + + Building Window Manager Modules: + Default yes +@@ -2331,13 +2503,19 @@ Building Window Manager Modules: + Building Image Provider Modules: + GIF $enable_gif + JPEG $JPEG $LIBJPEG ++ - hardware $JPEG_HW $JPEG_LIBMME ++ - hardware via v4l2 $JPEG_HW_V4L2 + PNG $PNG $LIBPNG_CFLAGS $LIBPNG_LIBS ++ - hardware $PNG_HW $PNG_LIBMME + Imlib2 $imlib2 $IMLIB2_CFLAGS $IMLIB2_LIBS + PNM $pnm + SVG $svg $LIBSVG_CFLAGS $LIBSVG_LIBS + BMP $bmp ++ WEBP $webp $LIBWEBP_CFLAGS $LIBWEBP_LIBS + JPEG2000 $jpeg2000 $JASPER_LIBS + MPEG2 $mpeg2 ++ TIFF $tiff $LIBTIFF_CFLAGS $LIBTIFF_LIBS ++ + + + Building Video Provider Modules: +diff --git a/gfxdrivers/davinci/davinci_osd.c b/gfxdrivers/davinci/davinci_osd.c +index 2effb2e..4c4d4f1 100644 +--- a/gfxdrivers/davinci/davinci_osd.c ++++ b/gfxdrivers/davinci/davinci_osd.c +@@ -565,6 +565,7 @@ update_rgb( DavinciDriverData *ddrv, + dfb_convert_to_rgb16( buffer->format, + lock->addr + rect.y * lock->pitch + DFB_BYTES_PER_LINE( buffer->format, rect.x ), + lock->pitch, ++ NULL, 0, NULL, 0, + surface->config.size.h, + ddrv->fb[OSD0].mem + rect.y * ddev->fix[OSD0].line_length + rect.x * 2, + ddev->fix[OSD0].line_length, +diff --git a/include/directfb.h b/include/directfb.h +index dc7448c..db116b2 100644 +--- a/include/directfb.h ++++ b/include/directfb.h +@@ -599,7 +599,8 @@ typedef enum { + typedef enum { + DIRENDER_NONE = 0x00000000, + DIRENDER_FAST = 0x00000001, /* Select fast rendering method */ +- DIRENDER_ALL = 0x00000001 ++ DIRENDER_BACKGROUND = 0x00000002, /* Async rendering */ ++ DIRENDER_ALL = 0x00000003 + } DIRenderFlags; + + /* +@@ -914,8 +915,9 @@ typedef enum { + DIDTF_JOYSTICK = 0x00000004, /* Can be used as a joystick. */ + DIDTF_REMOTE = 0x00000008, /* Is a remote control. */ + DIDTF_VIRTUAL = 0x00000010, /* Is a virtual input device. */ ++ DIDTF_SENSOR = 0x00000020, /* Is a motion sensing input device. */ + +- DIDTF_ALL = 0x0000001F /* All type flags set. */ ++ DIDTF_ALL = 0x0000003F /* All type flags set. */ + } DFBInputDeviceTypeFlags; + + /* +@@ -926,8 +928,9 @@ typedef enum { + DICAPS_KEYS = 0x00000001, /* device supports key events */ + DICAPS_AXES = 0x00000002, /* device supports axis events */ + DICAPS_BUTTONS = 0x00000004, /* device supports button events */ ++ DICAPS_SENSORS = 0x00000008, /* device supports sensor events */ + +- DICAPS_ALL = 0x00000007 /* all capabilities */ ++ DICAPS_ALL = 0x0000000F /* all capabilities */ + #else + DIDCAPS_NONE = 0x00000000, /* device supports no events */ + DIDCAPS_KEYS = 0x00000001, /* device supports key events */ +@@ -968,6 +971,26 @@ typedef enum { + DIAI_LAST = 0x0000001F /* 32 axes maximum */ + } DFBInputDeviceAxisIdentifier; + ++ ++/* ++ * Sensors identifiers for sensors-equipped input devices ++ * ++ * Only motion generating sensors are defined here. Depending on its type as ++ * specified by DFBInputDeviceSensorIdentifier, the actual sensor data is ++ * stored in the sensor_data field of the DFBInputEvent structure and ++ * is expressed in a common referential (unit) across devices. ++ */ ++typedef enum { ++ DISI_ACCELEROMETER = 0x00000001, /* Accelerometer sensor type */ ++ DISI_GYROSCOPE = 0x00000002, /* Device rotation around ++ X, Y and Z axes */ ++ DISI_LINEAR_ACCELERATION = 0x00000010, /* Acceleration along each device ++ axis (without gravity value) */ ++ DISI_ORIENTATION = 0x00000020, /* Yaw, pitch and roll */ ++ DISI_ALL = 0x0000003F /* All sensors mask */ ++} DFBInputDeviceSensorIdentifier; ++ ++ + /* + * Flags defining which fields of a DFBWindowDescription are valid. + */ +@@ -1362,12 +1385,27 @@ typedef enum { + DSPF_LUT4 = DFB_SURFACE_PIXELFORMAT( 39, 4, 0, 1, 4, 0, 1, 0, 0, 1, 0 ), + + /* 16 bit LUT (1 byte alpha and 8 bit color lookup from palette) */ +- DSPF_ALUT8 = DFB_SURFACE_PIXELFORMAT( 40, 8, 8, 1, 0, 2, 0, 0, 0, 1, 0 ) ++ DSPF_ALUT8 = DFB_SURFACE_PIXELFORMAT( 40, 8, 8, 1, 0, 2, 0, 0, 0, 1, 0 ), ++ ++ /* 24 bit RGB (3 byte, blue 8@16, green 8@8, red 8@0) */ ++ DSPF_BGR24 = DFB_SURFACE_PIXELFORMAT( 41, 24, 0, 0, 0, 3, 0, 0, 0, 0, 0 ), ++ ++ /* 12 bit YUV (8 bit Y plane followed by one 16 bit quarter size Cb|Cr [7:0|7:0] plane) in Omega2 macroblock format */ ++ DSPF_NV12MB = DFB_SURFACE_PIXELFORMAT( 42, 12, 0, 0, 0, 1, 0, 2, 0, 0, 0 ), ++ ++ /* 16 bit YUV (8 bit Y plane followed by one 16 bit half width Cb|Cr [7:0|7:0] plane) in Omega2 macroblock format */ ++ DSPF_NV16MB = DFB_SURFACE_PIXELFORMAT( 43, 24, 0, 0, 0, 1, 0, 0, 1, 0, 0 ), ++ ++ /* 8 bit (1 byte w/ no pixel-padding, opaque buffer for carrying arbitray data) */ ++ DSPF_BYTE = DFB_SURFACE_PIXELFORMAT( 44, 8, 0, 0, 0, 1, 0, 0, 0, 0, 0 ), ++ ++ /* 24 bit YUV (8 bit Y plane followed by one 16 bit full width Cb|Cr [7:0|7:0] plane) */ ++ DSPF_NV24 = DFB_SURFACE_PIXELFORMAT( 45, 24, 0, 0, 0, 1, 0, 0, 2, 0, 0 ) + + } DFBSurfacePixelFormat; + + /* Number of pixelformats defined */ +-#define DFB_NUM_PIXELFORMATS 41 ++#define DFB_NUM_PIXELFORMATS 46 + + /* These macros extract information about the pixel format. */ + #define DFB_PIXELFORMAT_INDEX(fmt) (((fmt) & 0x0000007F) ) +@@ -1420,7 +1458,10 @@ typedef enum { + ((fmt) == DSPF_YV12) || \ + ((fmt) == DSPF_NV12) || \ + ((fmt) == DSPF_NV16) || \ ++ ((fmt) == DSPF_NV12MB) || \ ++ ((fmt) == DSPF_NV16MB) || \ + ((fmt) == DSPF_NV21) || \ ++ ((fmt) == DSPF_NV24) || \ + ((fmt) == DSPF_AYUV) || \ + ((fmt) == DSPF_YUV444P) || \ + ((fmt) == DSPF_AVYU) || \ +@@ -1600,6 +1641,8 @@ typedef struct { + identifier */ + DFBInputDeviceButtonIdentifier max_button; /* highest button + identifier */ ++ DFBInputDeviceSensorIdentifier sensors; /* supported sensors ++ identifier */ + + char name[DFB_INPUT_DEVICE_DESC_NAME_LENGTH]; /* Device name */ + +@@ -1791,12 +1834,25 @@ typedef enum { + typedef enum { + DVPLAY_NOFX = 0x00000000, /* normal playback */ + DVPLAY_REWIND = 0x00000001, /* reverse playback */ +- DVPLAY_LOOPING = 0x00000002 /* automatically restart ++ DVPLAY_LOOPING = 0x00000002, /* automatically restart + playback when end-of-stream + is reached (gapless). */ ++ DVPLAY_PACED = 0x00000004, /* decoding pace is controlled ++ by the caller, the decoder ++ won't wait on its own while ++ decoding frames. */ + } DFBVideoProviderPlaybackFlags; + + /* ++ * Playback context passed to IDirectFBVideoProvider::PlayTo() ++ * when decoding in DVPLAY_PACED mode. ++ */ ++typedef struct { ++ unsigned int num_frame; ++ void *ctx; ++} DFBVideoProviderPacedPlaybackCtx; ++ ++/* + * Flags to allow Audio Unit selection. + */ + typedef enum { +@@ -5217,7 +5273,8 @@ typedef enum { + DIET_KEYRELEASE, /* a key is been released */ + DIET_BUTTONPRESS, /* a (mouse) button is been pressed */ + DIET_BUTTONRELEASE, /* a (mouse) button is been released */ +- DIET_AXISMOTION /* mouse/joystick movement */ ++ DIET_AXISMOTION, /* mouse/joystick movement */ ++ DIET_SENSOR /* sensor event */ + } DFBInputEventType; + + /* +@@ -5251,7 +5308,10 @@ typedef enum { + DIEF_FOLLOW = 0x0800, /* another event will follow immediately, e.g. x/y axis */ + + DIEF_MIN = 0x1000, /* minimum value is set, e.g. for absolute axis motion */ +- DIEF_MAX = 0x2000 /* maximum value is set, e.g. for absolute axis motion */ ++ DIEF_MAX = 0x2000, /* maximum value is set, e.g. for absolute axis motion */ ++ ++ DIEF_SENSOR = 0x4000 /* sensor type and data are valid, contents ++ depend on sensor type */ + } DFBInputEventFlags; + + /* +@@ -5302,6 +5362,11 @@ typedef struct { + /* general information */ + int min; /* minimum possible value */ + int max; /* maximum possible value */ ++ ++/* DIET_SENSOR */ ++ DFBInputDeviceSensorIdentifier sensor; /* in case of a sensor event */ ++ float sensor_data[3]; /* sensor data, depending ++ on DFBInputDeviceSensorIdentifier */ + } DFBInputEvent; + + /* +@@ -5550,6 +5615,7 @@ typedef struct { + unsigned int DIET_BUTTONPRESS; + unsigned int DIET_BUTTONRELEASE; + unsigned int DIET_AXISMOTION; ++ unsigned int DIET_SENSOR; + + unsigned int DWET_POSITION; + unsigned int DWET_SIZE; +@@ -6712,6 +6778,14 @@ D_DEFINE_INTERFACE( IDirectFBFont, + ) + + /* ++ * Flags for image providers. ++ */ ++typedef enum { ++ DIPSYNCFLAGS_SYNC, /* sync, i.e. wait for the image provider to finish */ ++ DIPSYNCFLAGS_TRYSYNC /* figure out if image provider is finished or still busy */ ++} DFBImageProviderSyncFlags; ++ ++/* + * Capabilities of an image. + */ + typedef enum { +@@ -6808,6 +6882,10 @@ D_DEFINE_INTERFACE( IDirectFBImageProvider, + * Registers a callback for progressive image loading. + * + * The function is called each time a chunk of the image is decoded. ++ * ++ * In case of an image provider working in the background, the ++ * callback could be called in a different thread context! So you ++ * might have to take appropriate actions to handle this. + */ + DFBResult (*SetRenderCallback) ( + IDirectFBImageProvider *thiz, +@@ -6820,6 +6898,30 @@ D_DEFINE_INTERFACE( IDirectFBImageProvider, + * + * This is optional and might be unsupported by some image providers + */ ++ /* ++ * Set image provider flags. ++ * ++ * This allows one to switch an image provider's mode of ++ * operation, between default and background. ++ * ++ * In default (which is also the traditional) mode, a call to ++ * RenderTo() will block until the image provider has finished ++ * decoding the image. This is also the behaviour if this API ++ * is not used at all. ++ * ++ * In background mode, the image is being decoded in the background, ++ * i.e. the call to RenderTo() will return almost immediately. The ++ * application may do other useful processing while the image is being ++ * decoded. In most implementations, background decode will just use ++ * a worker thread. ++ * ++ * Not all image providers support background mode and will return ++ * DFB_UNSUPPORTED in that case. ++ * ++ * Calling SetFlags() after RenderTo() makes no sense and is ++ * unsupported. ++ * ++ */ + DFBResult (*SetRenderFlags) ( + IDirectFBImageProvider *thiz, + DIRenderFlags flags +@@ -6836,6 +6938,25 @@ D_DEFINE_INTERFACE( IDirectFBImageProvider, + const DFBRectangle *src_rect, + const char *filename + ); ++ ++ ++ /** Rendering **/ ++ ++ /* ++ * For a background image provider, waits for it to finish ++ * decoding the image. ++ * ++ * For a default image provider, does nothing. ++ * ++ * This needs to be called for background image providers ++ * before accessing the destination surface (using either the ++ * software or the hardware), to make sure that the image has been ++ * completely decoded. ++ */ ++ DFBResult (*Sync) ( ++ IDirectFBImageProvider *thiz, ++ DFBImageProviderSyncFlags flags ++ ); + ) + + /* +diff --git a/inputdrivers/linux_input/linux_input.c b/inputdrivers/linux_input/linux_input.c +index a715c7a..b5a2b06 100644 +--- a/inputdrivers/linux_input/linux_input.c ++++ b/inputdrivers/linux_input/linux_input.c +@@ -112,6 +112,7 @@ typedef unsigned long kernel_ulong_t; + #define DISABLE_INPUT_HOTPLUG_FUNCTION_STUB + + #include ++#include + + #include + +@@ -1063,12 +1064,6 @@ get_device_info( int fd, + if (test_bit( EV_KEY, evbit )) { + int i; + +-#ifndef DIRECTFB_DISABLE_DEPRECATED +- info->desc.caps |= DICAPS_KEYS; +-#else +- info->desc.caps |= DIDCAPS_KEYS; +-#endif +- + /* get keyboard bits */ + ioctl( fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit ); + +@@ -1092,6 +1087,14 @@ get_device_info( int fd, + for (i=BTN_MOUSE; idesc.caps |= DICAPS_KEYS; ++#else ++ info->desc.caps |= DIDCAPS_KEYS; ++#endif ++ + } + + if (test_bit( EV_REL, evbit )) { +@@ -1252,7 +1255,7 @@ driver_get_available( void ) + int i; + char *tsdev; + +- if (!(dfb_config->linux_input_force || (dfb_system_type() == CORE_FBDEV) || (dfb_system_type() == CORE_MESA) )) ++ if (!(dfb_config->linux_input_force || (dfb_system_type() == CORE_FBDEV) || (dfb_system_type() == CORE_MESA) || (dfb_system_type() == CORE_STMFBDEV) )) + return 0; + + if (dfb_system_type() == CORE_FBDEV && !dfb_config->linux_input_force) { +@@ -1265,6 +1268,16 @@ driver_get_available( void ) + if (!dfb_fbdev->vt || dfb_fbdev->vt->fd < 0) + return 0; + } ++ else if (dfb_system_type() == CORE_STMFBDEV) { ++ const STMfbdev * const dfb_stm_fbdev = dfb_system_data(); ++ D_ASSERT( dfb_stm_fbdev ); ++ ++ // Only allow USB keyboard and mouse support if the systems driver has ++ // the Virtual Terminal file ("/dev/tty0") open and available for use. ++ // FIXME: Additional logic needed for system drivers not similar to fbdev? ++ if (!dfb_stm_fbdev->vt || dfb_stm_fbdev->vt->fd < 0) ++ return 0; ++ } + + /* Use the devices specified in the configuration. */ + if (fusion_vector_has_elements( &dfb_config->linux_input_devices )) { +@@ -1469,7 +1482,7 @@ get_capability( void ) + + InputDriverCapability capabilities = IDC_NONE; + +- if (!(dfb_config->linux_input_force || (dfb_system_type() == CORE_FBDEV) || (dfb_system_type() == CORE_MESA) )) ++ if (!(dfb_config->linux_input_force || (dfb_system_type() == CORE_FBDEV) || (dfb_system_type() == CORE_MESA) || (dfb_system_type() == CORE_STMFBDEV) )) + goto exit; + + if (dfb_system_type() == CORE_FBDEV) { +@@ -1484,6 +1497,16 @@ get_capability( void ) + goto exit; + } + } ++ else if (dfb_system_type() == CORE_STMFBDEV) { ++ const STMfbdev * const dfb_stm_fbdev = dfb_system_data(); ++ D_ASSERT( dfb_stm_fbdev ); ++ ++ // Only allow USB keyboard and mouse support if the systems driver has ++ // the Virtual Terminal file ("/dev/tty0") open and available for use. ++ // FIXME: Additional logic needed for system drivers not similar to fbdev? ++ if (!dfb_stm_fbdev->vt || dfb_stm_fbdev->vt->fd < 0) ++ goto exit; ++ } + + D_DEBUG_AT( Debug_LinuxInput, " -> returning HOTPLUG\n" ); + +@@ -1857,6 +1880,11 @@ driver_open_device( CoreInputDevice *device, + + if (dfb_fbdev->vt) + data->vt_fd = dup( dfb_fbdev->vt->fd ); ++ } else if (dfb_system_type() == CORE_STMFBDEV) { ++ const STMfbdev * const dfb_stm_fbdev = dfb_system_data(); ++ ++ if (dfb_stm_fbdev->vt) ++ data->vt_fd = dup( dfb_stm_fbdev->vt->fd ); + } + if (data->vt_fd < 0) + data->vt_fd = open( "/dev/tty0", O_RDWR | O_NOCTTY ); +diff --git a/interfaces/IDirectFBImageProvider/Makefile.am b/interfaces/IDirectFBImageProvider/Makefile.am +index 4b733aa..deab8da 100644 +--- a/interfaces/IDirectFBImageProvider/Makefile.am ++++ b/interfaces/IDirectFBImageProvider/Makefile.am +@@ -59,13 +59,46 @@ else + MPEG2_PROVIDER = + endif + ++if JPEG_PROVIDER_HW_V4L2 ++JPEG_PROVIDER_HW_V4L2_PROVIDER = libidirectfbimageprovider_hwjpeg_v4l2.la ++else ++JPEG_PROVIDER_HW_V4L2_PROVIDER = ++endif ++ ++if MME_USE_OWN_HEADERS ++MME_INCLUDE_PATH = -I$(top_srcdir)/interfaces/IDirectFBImageProvider/mme ++else ++MME_INCLUDE_PATH = ++endif ++if MME_USE_OWN_TRANSFORMERS ++TRANSFORMER_INCLUDE_PATH = -I$(srcdir)/mme/transform ++else ++TRANSFORMER_INCLUDE_PATH = ++endif ++ ++if WEBP_PROVIDER ++WEBP_PROVIDER = libidirectfbimageprovider_webp.la ++else ++WEBP_PROVIDER = ++endif ++ ++if TIFF_PROVIDER ++TIFF_PROVIDER = libidirectfbimageprovider_tiff.la ++else ++TIFF_PROVIDER = ++endif ++ ++ + INCLUDES = \ + -I$(top_builddir)/include \ + -I$(top_builddir)/lib \ + -I$(top_builddir)/src \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/lib \ +- -I$(top_srcdir)/src ++ -I$(top_srcdir)/src \ ++ -I$(top_srcdir)/systems \ ++ $(MME_INCLUDE_PATH) \ ++ $(TRANSFORMER_INCLUDE_PATH) + + AM_CPPFLAGS = -DDATADIR=\"${RUNTIME_SYSROOT}@DATADIR@\" $(LIBJPEG_CFLAGS) $(LIBPNG_CFLAGS) + +@@ -79,8 +112,11 @@ idirectfbimageprovider_LTLIBRARIES = \ + $(SVG_PROVIDER) \ + $(BMP_PROVIDER) \ + $(JPEG2000_PROVIDER) \ +- $(MPEG2_PROVIDER) +- ++ $(MPEG2_PROVIDER) \ ++ $(JPEG_PROVIDER_HW_V4L2_PROVIDER) \ ++ $(WEBP_PROVIDER) \ ++ $(TIFF_PROVIDER) ++ + if BUILD_STATIC + idirectfbimageprovider_DATA = $(idirectfbimageprovider_LTLIBRARIES:.la=.o) + endif +@@ -89,9 +125,16 @@ endif + libdirect = $(top_builddir)/lib/direct/libdirect.la + libdirectfb = $(top_builddir)/src/libdirectfb.la + ++libidirectfbimageprovider_tiff_la_SOURCES = idirectfbimageprovider_tiff.c ++libidirectfbimageprovider_tiff_la_LIBADD = $(libdirect) $(libdirectfb) $(LIBTIFF_LIBS) ++libidirectfbimageprovider_tiff_la_LDFLAGS = -avoid-version -module ++ ++libidirectfbimageprovider_webp_la_SOURCES = idirectfbimageprovider_webp.c ++libidirectfbimageprovider_webp_la_LIBADD = $(libdirect) $(libdirectfb) $(LIBWEBP_LIBS) ++libidirectfbimageprovider_webp_la_LDFLAGS = -avoid-version -module + + libidirectfbimageprovider_png_la_SOURCES = idirectfbimageprovider_png.c +-libidirectfbimageprovider_png_la_LIBADD = $(libdirect) $(libdirectfb) $(LIBPNG_LIBS) ++libidirectfbimageprovider_png_la_LIBADD = $(libdirect) $(libdirectfb) $(LIBPNG_LIBS) $(PNG_LIBMME) + libidirectfbimageprovider_png_la_LDFLAGS = -avoid-version -module + + libidirectfbimageprovider_dfiff_la_SOURCES = idirectfbimageprovider_dfiff.c +@@ -103,7 +146,7 @@ libidirectfbimageprovider_gif_la_LIBADD = $(libdirect) $(libdirectfb) + libidirectfbimageprovider_gif_la_LDFLAGS = -avoid-version -module + + libidirectfbimageprovider_jpeg_la_SOURCES = idirectfbimageprovider_jpeg.c +-libidirectfbimageprovider_jpeg_la_LIBADD = $(libdirect) $(libdirectfb) $(LIBJPEG) ++libidirectfbimageprovider_jpeg_la_LIBADD = $(libdirect) $(libdirectfb) $(LIBJPEG) $(JPEG_LIBMME) + libidirectfbimageprovider_jpeg_la_LDFLAGS = -avoid-version -module + + libidirectfbimageprovider_imlib2_la_SOURCES = idirectfbimageprovider_imlib2.c +@@ -130,5 +173,8 @@ libidirectfbimageprovider_mpeg2_la_SOURCES = idirectfbimageprovider_mpeg2.c + libidirectfbimageprovider_mpeg2_la_LIBADD = $(libdirect) $(libdirectfb) mpeg2/libmpeg2decode.la + libidirectfbimageprovider_mpeg2_la_LDFLAGS = -avoid-version -module + ++libidirectfbimageprovider_hwjpeg_v4l2_la_SOURCES = idirectfbimageprovider_hwjpeg_v4l2.c ++libidirectfbimageprovider_hwjpeg_v4l2_la_LIBADD = $(libdirect) $(libdirectfb) ++libidirectfbimageprovider_hwjpeg_v4l2_la_LDFLAGS = -avoid-version -module + + include $(top_srcdir)/rules/libobject.make +diff --git a/interfaces/IDirectFBImageProvider/debug_helper.h b/interfaces/IDirectFBImageProvider/debug_helper.h +new file mode 100644 +index 0000000..f3062c2 +--- /dev/null ++++ b/interfaces/IDirectFBImageProvider/debug_helper.h +@@ -0,0 +1,53 @@ ++#ifndef __DEBUG_HELPER_H__ ++#define __DEBUG_HELPER_H__ ++ ++ ++/* Some colour for debug */ ++#define BLACK "\033[22;30m" ++#define RED "\033[22;31m" ++#define GREEN "\033[22;32m" ++#define BROWN "\033[22;33m" ++ ++ ++ ++/* These messages should be provided through DirectFB's error and warning */ ++#define DEBUG_ERROR(x) D_ERROR x ++#define DEBUG_WARNING(x) D_WARN x ++ ++ ++#ifdef DEBUG ++/* *Very* Verbose */ ++# define DEBUG_INFO(x) D_PRINTF x ++/* Outputs various Buffer and surface sizes */ ++# define DEBUG_SCALE(x) D_PRINTF x ++/* Outputs Timing Information */ ++# define DEBUG_PERFORMANCE(x) D_PRINTF x ++ ++#else ++ ++# define DEBUG_INFO(x) __debug_msg x ++# define DEBUG_SCALE(x) __debug_msg x ++static inline int __attribute__ ((format (printf, 1, 2))) ++__debug_msg (const char *format, ...) ++{ ++ return 0; ++} ++ ++#endif ++ ++ ++#ifdef DIRECT_BUILD_DEBUG ++ ++# define deb_gettimeofday(tv,tz) gettimeofday(tv, tz) ++# define deb_timersub(a,b,res) timersub(a, b, res) ++ ++#else ++ ++# define deb_gettimeofday(tv,tz) ( { } ) ++# define deb_timersub(a,b,res) ( { } ) ++ ++#endif ++ ++ ++ ++#endif /* __DEBUG_HELPER_H__ */ +diff --git a/interfaces/IDirectFBImageProvider/idirectfbimageprovider_hwjpeg_v4l2.c b/interfaces/IDirectFBImageProvider/idirectfbimageprovider_hwjpeg_v4l2.c +new file mode 100644 +index 0000000..f5c9d0f +--- /dev/null ++++ b/interfaces/IDirectFBImageProvider/idirectfbimageprovider_hwjpeg_v4l2.c +@@ -0,0 +1,753 @@ ++/* ++ (c) Copyright 2012 STMicroelectronics R&D ++ ++based on code: ++ (c) Copyright 2001-2010 The world wide DirectFB Open Source Community (directfb.org) ++ (c) Copyright 2000-2004 Convergence (integrated media) GmbH ++ ++ All rights reserved. ++ ++ Written by Ilyes Gouta ++ Based on code by: ++ Andre' Draszik , ++ Denis Oliver Kropp , ++ Andreas Hundt , ++ Sven Neumann , ++ Ville Syrjälä and ++ Claudio Ciccani . ++ ++ This library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2 of the License, or (at your option) any later version. ++ ++ This library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with this library; if not, write to the ++ Free Software Foundation, Inc., 59 Temple Place - Suite 330, ++ Boston, MA 02111-1307, USA. ++*/ ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++ ++#include ++ ++#include ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include ++ ++#include "idirectfbimageprovider_hwjpeg_v4l2.h" ++ ++D_DEBUG_DOMAIN (HWJPEG_V4L2, "HWJPEG_V4L2", "STM h/w JPEG V4L2 decoder"); ++ ++static DFBResult ++Probe( IDirectFBImageProvider_ProbeContext *ctx ); ++ ++static DFBResult ++Construct( IDirectFBImageProvider *thiz, ++ ... ); ++ ++#include ++ ++DIRECT_INTERFACE_IMPLEMENTATION( IDirectFBImageProvider, hwJPEG ) ++ ++static DFBResult ++IDirectFBImageProvider_hwJPEG_RenderTo( IDirectFBImageProvider *thiz, ++ IDirectFBSurface *destination, ++ const DFBRectangle *destination_rect ); ++ ++static DFBResult ++IDirectFBImageProvider_hwJPEG_GetSurfaceDescription( IDirectFBImageProvider *thiz, ++ DFBSurfaceDescription *dsc ); ++ ++static DFBResult ++IDirectFBImageProvider_hwJPEG_GetImageDescription( IDirectFBImageProvider *thiz, ++ DFBImageDescription *dsc ); ++ ++static DFBResult ++IDirectFBImageProvider_hwJPEG_SetRenderFlags( IDirectFBImageProvider *thiz, ++ DIRenderFlags flags ); ++ ++static DFBResult ++JPEG_hwRenderTo( IDirectFBImageProvider_hwJPEG_data *data, ++ CoreSurface *dst_surface, ++ DFBRectangle *rect, ++ const DFBRegion *clip ); ++ ++static void ++IDirectFBImageProvider_hwJPEG_Destruct( IDirectFBImageProvider *thiz ) ++{ ++ IDirectFBImageProvider_hwJPEG_data *data = ++ (IDirectFBImageProvider_hwJPEG_data*)thiz->priv; ++ ++ if (data->decode_surface) { ++ dfb_gfxcard_wait_serial( &data->serial ); ++ dfb_surface_unref( data->decode_surface ); ++ data->decode_surface = NULL; ++ } ++} ++ ++static DFBResult ++Probe( IDirectFBImageProvider_ProbeContext *ctx ) ++{ ++ /* Look of the Jpeg SOI marker */ ++ if (ctx->header[0] == 0xff && ctx->header[1] == 0xd8) { ++ /* Look for JFIF or Exif strings, also could look at header[3:2] for APP0(0xFFE0), ++ * APP1(0xFFE1) or even other APPx markers. ++ */ ++ if (strncmp ((char*) ctx->header + 6, "JFIF", 4) == 0 || ++ strncmp ((char*) ctx->header + 6, "Exif", 4) == 0 || ++ strncmp ((char*) ctx->header + 6, "VVL", 3) == 0 || ++ strncmp ((char*) ctx->header + 6, "WANG", 4) == 0) ++ return DFB_OK; ++ ++ /* Else look for Quantization table marker or Define Huffman table marker, ++ * useful for EXIF thumbnails that have no APPx markers. ++ */ ++ if (ctx->header[2] == 0xff && (ctx->header[3] == 0xdb || ctx->header[3] == 0xc4)) ++ return DFB_OK; ++ ++ if (ctx->filename && strchr (ctx->filename, '.' ) && ++ (strcasecmp ( strchr (ctx->filename, '.' ), ".jpg" ) == 0 || ++ strcasecmp ( strchr (ctx->filename, '.' ), ".jpeg") == 0)) ++ return DFB_OK; ++ } ++ ++ return DFB_UNSUPPORTED; ++} ++ ++static DFBResult ++Construct( IDirectFBImageProvider *thiz, ++ ... ) ++{ ++ IDirectFBDataBuffer *buffer; ++ CoreDFB *core; ++ va_list tag; ++ struct v4l2_fmtdesc fmtdesc; ++ ++ DFBRegion region = { ++ .x1 = 0, ++ .y1 = 0, ++ .x2 = 255, ++ .y2 = 255 ++ }; ++ ++ DIRECT_ALLOCATE_INTERFACE_DATA( thiz, IDirectFBImageProvider_hwJPEG ) ++ ++ va_start( tag, thiz ); ++ buffer = va_arg( tag, IDirectFBDataBuffer * ); ++ core = va_arg( tag, CoreDFB * ); ++ va_end( tag ); ++ ++ D_ASSERT( core != NULL ); ++ ++ data->fd = open( "/dev/video0", O_RDWR ); ++ ++ if (data->fd < 0) { ++ D_DEBUG_AT( HWJPEG_V4L2, ++ "%s: couldn't open /dev/video0\n", ++ __FUNCTION__ ); ++ DIRECT_DEALLOCATE_INTERFACE( thiz ); ++ return DFB_FAILURE; ++ } ++ ++ memset( &fmtdesc, 0, sizeof(fmtdesc) ); ++ ++ fmtdesc.index = 0; ++ fmtdesc.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; ++ ++ if (ioctl( data->fd, VIDIOC_ENUM_FMT, &fmtdesc ) < 0) { ++ D_DEBUG_AT( HWJPEG_V4L2, ++ "%s: couldn't enumerate output formats on /dev/video0\n", ++ __FUNCTION__ ); ++ close( data->fd ); ++ DIRECT_DEALLOCATE_INTERFACE( thiz ); ++ return DFB_FAILURE; ++ } ++ ++ close( data->fd ); ++ ++ if (fmtdesc.pixelformat != V4L2_PIX_FMT_JPEG) { ++ D_DEBUG_AT( HWJPEG_V4L2, ++ "%s: /dev/video0 doesn't accept JPEG streams\n", ++ __FUNCTION__ ); ++ DIRECT_DEALLOCATE_INTERFACE( thiz ); ++ return DFB_FAILURE; ++ } ++ ++ data->base.ref = 1; ++ data->base.buffer = buffer; ++ data->base.core = core; ++ ++ /* check if the h/w decoder can really decode the JPEG. ++ It will return the recommended destination buffer width, height ++ and pixel format on success. */ ++ if (JPEG_hwRenderTo( data, NULL, NULL, ®ion ) != DFB_OK) { ++ D_DEBUG_AT( HWJPEG_V4L2, ++ "%s: /dev/video0 can't decode the JPEG picture\n", ++ __FUNCTION__ ); ++ DIRECT_DEALLOCATE_INTERFACE( thiz ); ++ return DFB_FAILURE; ++ } ++ ++ buffer->AddRef( buffer ); ++ ++ data->base.Destruct = IDirectFBImageProvider_hwJPEG_Destruct; ++ ++ thiz->RenderTo = IDirectFBImageProvider_hwJPEG_RenderTo; ++ thiz->Sync = NULL; ++ thiz->GetImageDescription = ++ IDirectFBImageProvider_hwJPEG_GetImageDescription; ++ thiz->SetRenderFlags = IDirectFBImageProvider_hwJPEG_SetRenderFlags; ++ thiz->GetSurfaceDescription = ++ IDirectFBImageProvider_hwJPEG_GetSurfaceDescription; ++ ++ return DFB_OK; ++} ++ ++static void ++JPEG_stretchblit( IDirectFBImageProvider_hwJPEG_data *data, ++ CardState *state, ++ DFBRectangle *src_rect, ++ DFBRectangle *dst_rect ) ++{ ++ D_DEBUG_AT( HWJPEG_V4L2, "StretchBlit %dx%d -> %dx%d (%s -> %s)\n", ++ src_rect->w, src_rect->h, dst_rect->w, dst_rect->h, ++ dfb_pixelformat_name( state->source->config.format), ++ dfb_pixelformat_name( state->destination->config.format ) ); ++ ++ /* thankfully this is intelligent enough to do a simple blit if ++ possible */ ++ dfb_gfxcard_stretchblit( src_rect, dst_rect, state ); ++ /* we need to remember the serial in case a new surface is created ++ (and written to) at the same address as the decode_surface before the ++ blit operation is finished. This can happen if we get into the ++ destructor before the blit operation is finished, which can happen on ++ fast CPUs. */ ++ data->serial = state->serial; ++} ++ ++DFBResult ++JPEG_hwRenderTo( IDirectFBImageProvider_hwJPEG_data *data, ++ CoreSurface *dst_surface, ++ DFBRectangle *rect, ++ const DFBRegion *clip ) ++{ ++ DFBResult ret = DFB_OK; ++ unsigned int length; ++ unsigned int ret_read; ++ int type; ++ int size = 0; ++ ++ CoreSurfaceConfig config; ++ ++ IDirectFBDataBuffer *buffer; ++ ++ struct v4l2_requestbuffers reqbufs; ++ ++ struct v4l2_format src_format; ++ struct v4l2_format dst_format; ++ ++ struct v4l2_buffer srcbuf; ++ struct v4l2_buffer dstbuf; ++ ++ CoreSurfaceBufferLock src_lock = { .pitch = 0 }; ++ CoreSurfaceBufferLock dst_lock = { .pitch = 0 }; ++ ++ D_ASSERT( data != NULL ); ++ D_ASSERT( clip != NULL ); ++ ++ D_ASSERT( data->base.core != NULL ); ++ ++ if (!data->base.core) ++ return DFB_FAILURE; ++ ++ if (data->decode_surface) { ++ dfb_gfxcard_wait_serial( &data->serial ); ++ dfb_surface_unref( data->decode_surface ); ++ data->decode_surface = NULL; ++ } ++ ++ D_ASSERT( data->source_surface == NULL ); ++ D_ASSERT( data->decode_surface == NULL ); ++ ++ data->fd = open( "/dev/video0", O_RDWR ); ++ ++ if (data->fd < 0) { ++ D_DEBUG_AT( HWJPEG_V4L2, ++ "%s: couldn't open /dev/video0\n", ++ __FUNCTION__ ); ++ return DFB_FAILURE; ++ } ++ ++ data->source_surface = NULL; ++ ++ data->width = -1; ++ data->height = -1; ++ ++ buffer = data->base.buffer; ++ ++ if (buffer->GetLength( buffer, &length )) { ++ D_ERROR( "%s: failed getting source length\n", ++ __FUNCTION__ ); ++ close( data->fd ); ++ return DFB_UNSUPPORTED; ++ } ++ ++ config.size.w = 4 * sysconf(_SC_PAGESIZE); ++ config.size.h = length / config.size.w + 1; ++ ++ if ((ret = dfb_surface_create_simple( data->base.core, ++ config.size.w, ++ config.size.h, ++ DSPF_BYTE, ++ DSCS_BT601, ++ DSCAPS_VIDEOONLY, ++ CSTF_EXTERNAL, ++ 0, ++ NULL, ++ &data->source_surface ))) { ++ D_ERROR( "%s: failed to create the source surface\n", ++ __FUNCTION__ ); ++ ++ close( data->fd ); ++ return ret; ++ } ++ ++ D_DEBUG_AT( HWJPEG_V4L2, "allocated a %s surface (%dx%d) for JPEG data\n", ++ dfb_pixelformat_name( data->source_surface->config.format ), ++ config.size.w, config.size.h ); ++ ++ if ((ret = dfb_surface_lock_buffer( data->source_surface, ++ CSBR_BACK, CSAID_CPU, ++ CSAF_WRITE, &src_lock ))) { ++ D_ERROR( "%s: couldn't lock source buffer\n", ++ __FUNCTION__ ); ++ ++ dfb_surface_unref( data->source_surface ); ++ data->source_surface = NULL; ++ ++ close( data->fd ); ++ return ret; ++ } ++ ++ buffer->SeekTo( buffer, 0 ); ++ ++ if ((ret = buffer->GetData( buffer, length, src_lock.addr, &ret_read ))) { ++ D_ERROR( "%s: couldn't upload source data to video memory\n", ++ __FUNCTION__ ); ++ goto fini; ++ } ++ ++ ++ memset( &reqbufs, 0, sizeof( reqbufs ) ); ++ ++ reqbufs.count = 1; ++ reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ reqbufs.memory = V4L2_MEMORY_USERPTR; ++ ++ if (ioctl( data->fd, VIDIOC_REQBUFS, &reqbufs ) < 0) { ++ D_ERROR( "%s: couldn't request capture buffers\n", ++ __FUNCTION__ ); ++ ret = DFB_FAILURE; ++ goto fini; ++ } ++ ++ reqbufs.count = 1; ++ reqbufs.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; ++ reqbufs.memory = V4L2_MEMORY_USERPTR; ++ ++ if (ioctl( data->fd, VIDIOC_REQBUFS, &reqbufs ) < 0) { ++ D_ERROR( "%s: couldn't request output buffers\n", ++ __FUNCTION__ ); ++ ret = DFB_FAILURE; ++ goto fini; ++ } ++ ++ type = V4L2_BUF_TYPE_VIDEO_OUTPUT; ++ ++ if (ioctl( data->fd, VIDIOC_STREAMON, &type ) < 0) { ++ D_ERROR( "%s: couldn't toggle streaming on\n", ++ __FUNCTION__ ); ++ ret = DFB_FAILURE; ++ goto fini; ++ } ++ ++ type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ ++ if (ioctl( data->fd, VIDIOC_STREAMON, &type ) < 0) { ++ D_ERROR( "%s: couldn't toggle streaming on\n", ++ __FUNCTION__ ); ++ ret = DFB_FAILURE; ++ goto fini; ++ } ++ ++ memset( &src_format, 0, sizeof( src_format ) ); ++ ++ src_format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; ++ src_format.fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG; ++ ++ if (ioctl( data->fd, VIDIOC_S_FMT, &src_format ) < 0) { ++ D_ERROR( "%s: couldn't set output format\n", ++ __FUNCTION__ ); ++ ret = DFB_FAILURE; ++ goto fini; ++ } ++ ++ memset( &srcbuf, 0, sizeof( srcbuf ) ); ++ ++ srcbuf.index = 0; ++ srcbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; ++ srcbuf.memory = V4L2_MEMORY_USERPTR; ++ srcbuf.m.userptr = (unsigned long)src_lock.addr; ++ srcbuf.length = length; ++ ++ if (ioctl( data->fd, VIDIOC_QBUF, &srcbuf ) < 0) { ++ D_ERROR( "%s: couldn't queue source buffer\n", ++ __FUNCTION__ ); ++ ret = DFB_FAILURE; ++ goto fini; ++ } ++ ++ memset( &src_format, 0, sizeof( src_format ) ); ++ ++ src_format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; ++ ++ if (ioctl( data->fd, VIDIOC_G_FMT, &src_format ) < 0) { ++ D_ERROR( "%s: couldn't get source format\n", ++ __FUNCTION__ ); ++ ret = DFB_FAILURE; ++ goto fini; ++ } ++ ++ D_DEBUG_AT( HWJPEG_V4L2, "JPEG picture is a %dx%d w/ fourcc 0x%08x\n", ++ src_format.fmt.pix.width, src_format.fmt.pix.height, ++ src_format.fmt.pix.pixelformat ); ++ ++ src_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ src_format.fmt.pix.width = rect ? rect->w : src_format.fmt.pix.width; ++ src_format.fmt.pix.height = rect ? rect->h : src_format.fmt.pix.height; ++ ++ dst_format = src_format; ++ ++ if (ioctl( data->fd, VIDIOC_TRY_FMT, &dst_format ) < 0) { ++ D_ERROR( "%s: couldn't get suggested capture format\n", ++ __FUNCTION__ ); ++ ret = DFB_FAILURE; ++ goto fini; ++ } ++ ++ if (dst_format.fmt.pix.pixelformat != V4L2_PIX_FMT_NV12 ++ && dst_format.fmt.pix.pixelformat != V4L2_PIX_FMT_NV16 ++ && dst_format.fmt.pix.pixelformat != V4L2_PIX_FMT_NV24) { ++ D_ERROR( "%s: capture format isn't a valid NV fourcc\n", ++ __FUNCTION__ ); ++ ret = DFB_FAILURE; ++ goto fini; ++ } ++ ++ config.flags = CSCONF_SIZE | CSCONF_FORMAT; ++ ++ switch (dst_format.fmt.pix.pixelformat) { ++ case V4L2_PIX_FMT_NV12: ++ config.format = DSPF_NV12; ++ break; ++ case V4L2_PIX_FMT_NV16: ++ config.format = DSPF_NV16; ++ break; ++ case V4L2_PIX_FMT_NV24: ++ config.format = DSPF_NV24; ++ break; ++ default: ++ D_DEBUG_AT( HWJPEG_V4L2, "invalid pixelformat!\n" ); ++ ret = DFB_FAILURE; ++ goto fini; ++ } ++ ++ D_DEBUG_AT( HWJPEG_V4L2, "h/w decoder suggested %dx%d %s buffer " ++ "(%dx%d requested)\n", ++ dst_format.fmt.pix.width, ++ dst_format.fmt.pix.height, ++ dfb_pixelformat_name( config.format ), ++ src_format.fmt.pix.width, ++ src_format.fmt.pix.height ); ++ ++ /* Construct() will provide a dst_surface == NULL so once we're here ++ the JPEG header has been parsed and the recommended width, height and ++ pixel format have been retrieved. */ ++ if (!dst_surface) { ++ data->width = dst_format.fmt.pix.width; ++ data->height = dst_format.fmt.pix.height; ++ data->pixelformat = config.format; ++ ret = DFB_OK; ++ goto fini; ++ } ++ ++ /* specify the pitch returned by VIDIOC_TRY_FMT as a width */ ++ config.size.w = dst_format.fmt.pix.bytesperline; ++ config.size.h = dst_format.fmt.pix.height; ++ ++ if ((ret = dfb_surface_create_simple( data->base.core, ++ config.size.w, ++ config.size.h, ++ config.format, ++ DSCS_BT601, ++ DSCAPS_VIDEOONLY, ++ CSTF_EXTERNAL, ++ 0, ++ NULL, ++ &data->decode_surface ))) { ++ D_ERROR( "%s: failed to create the nv1x decode surface\n", ++ __FUNCTION__ ); ++ goto fini; ++ } ++ ++ D_DEBUG_AT( HWJPEG_V4L2, "allocated a %s surface (%dx%d) for decode\n", ++ dfb_pixelformat_name( data->decode_surface->config.format ), ++ config.size.w, config.size.h ); ++ ++ dfb_surface_calc_buffer_size( data->decode_surface, 1, 1, NULL, &size ); ++ ++ src_format.fmt.pix.sizeimage = size; ++ src_format.fmt.pix.pixelformat = dst_format.fmt.pix.pixelformat; ++ ++ /* VIDIOC_S_FMT takes the original requested dimensions */ ++ if (ioctl( data->fd, VIDIOC_S_FMT, &src_format ) < 0) { ++ D_ERROR( "%s: couldn't set capture format\n", ++ __FUNCTION__ ); ++ ret = DFB_FAILURE; ++ goto fini; ++ } ++ ++ if ((ret = dfb_surface_lock_buffer( data->decode_surface, ++ CSBR_BACK, CSAID_GPU, ++ CSAF_WRITE, &dst_lock ))) { ++ D_ERROR( "%s: couldn't lock source buffer\n", ++ __FUNCTION__ ); ++ goto fini; ++ } ++ ++ D_DEBUG_AT( HWJPEG_V4L2, "locked h/w decode buffer @ 0x%08x, pitch: %d\n", ++ (unsigned int)dst_lock.addr, dst_lock.pitch ); ++ ++ if (dst_lock.pitch != dst_format.fmt.pix.bytesperline) { ++ D_ERROR( "%s: unaligned decode surface pitch!\n", ++ __FUNCTION__ ); ++ ret = DFB_FAILURE; ++ goto fini; ++ } ++ ++ memset( &dstbuf, 0, sizeof( dstbuf ) ); ++ ++ /* planar capture */ ++ dstbuf.index = 0; ++ dstbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ dstbuf.memory = V4L2_MEMORY_USERPTR; ++ dstbuf.m.userptr = (unsigned long)dst_lock.addr; ++ dstbuf.length = dst_format.fmt.pix.sizeimage; ++ ++ if (ioctl( data->fd, VIDIOC_QBUF, &dstbuf ) < 0) { ++ D_ERROR( "%s: couldn't queue capture buffer\n", ++ __FUNCTION__ ); ++ ret = DFB_FAILURE; ++ goto fini; ++ } ++ ++ if (ioctl( data->fd, VIDIOC_DQBUF, &dstbuf ) < 0) { ++ D_ERROR( "%s: couldn't dequeue capture buffer\n", ++ __FUNCTION__ ); ++ ret = DFB_FAILURE; ++ goto fini; ++ } ++ ++ memset( &dst_format, 0, sizeof( dst_format ) ); ++ ++ dst_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ ++ if (ioctl( data->fd, VIDIOC_G_FMT, &dst_format ) < 0) { ++ D_ERROR( "%s: couldn't get capture final format\n", ++ __FUNCTION__ ); ++ ret = DFB_FAILURE; ++ goto fini; ++ } ++ ++ D_DEBUG_AT( HWJPEG_V4L2, "decoded picture is a %dx%d %s buffer " ++ "(pitch: %d)\n", dst_format.fmt.pix.width, ++ dst_format.fmt.pix.height, ++ (dst_format.fmt.pix.pixelformat == V4L2_PIX_FMT_NV12) ? "NV12" ++ : ((dst_format.fmt.pix.pixelformat == V4L2_PIX_FMT_NV16) ++ ? "NV16" : "NV24"), ++ dst_format.fmt.pix.bytesperline ); ++ ++fini: ++ if (data->decode_surface && dst_lock.pitch) ++ dfb_surface_unlock_buffer( data->decode_surface, &dst_lock ); ++ ++ type = V4L2_BUF_TYPE_VIDEO_OUTPUT; ++ ++ if (ioctl( data->fd, VIDIOC_STREAMOFF, &type ) < 0) ++ D_ERROR( "%s: couldn't turn streaming off\n", ++ __FUNCTION__ ); ++ ++ type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ ++ if (ioctl( data->fd, VIDIOC_STREAMOFF, &type ) < 0) ++ D_ERROR( "%s: couldn't turn streaming off\n", ++ __FUNCTION__ ); ++ ++ if (data->source_surface) { ++ if (src_lock.pitch) ++ dfb_surface_unlock_buffer( data->source_surface, &src_lock ); ++ ++ dfb_surface_unref( data->source_surface ); ++ data->source_surface = NULL; ++ } ++ ++ close( data->fd ); ++ ++ /* don't blit to destination if something went wrong */ ++ if (data->decode_surface && ret == DFB_OK) { ++ CardState state; ++ DFBRectangle src_rect = { ++ .x = 0, ++ .y = 0, ++ .w = dst_format.fmt.pix.width, ++ .h = dst_format.fmt.pix.height ++ }; ++ ++ /* use DFB to convert the intermediary NV format to the ++ final destination format, applying any necessary additional ++ clip/stretch */ ++ dfb_state_init( &state, data->base.core ); ++ dfb_state_set_source( &state, data->decode_surface ); ++ dfb_state_set_destination( &state, dst_surface ); ++ dfb_state_set_clip( &state, clip ); ++ ++ JPEG_stretchblit( data, &state, &src_rect, rect ); ++ ++ /* remove the state */ ++ dfb_state_set_source( &state, NULL ); ++ dfb_state_set_destination( &state, NULL ); ++ dfb_state_destroy( &state ); ++ ++ if (data->base.render_callback) { ++ DFBRectangle r = { 0, 0, ++ dst_format.fmt.pix.width, ++ dst_format.fmt.pix.height }; ++ data->base.render_callback( &r, ++ data->base.render_callback_context ); ++ } ++ } ++ ++ return ret; ++} ++ ++static DFBResult ++IDirectFBImageProvider_hwJPEG_RenderTo( IDirectFBImageProvider *thiz, ++ IDirectFBSurface *destination, ++ const DFBRectangle *dest_rect ) ++{ ++ IDirectFBSurface_data *dst_data; ++ CoreSurface *dst_surface; ++ ++ DIRECT_INTERFACE_GET_DATA(IDirectFBImageProvider_hwJPEG) ++ ++ dst_data = (IDirectFBSurface_data*) destination->priv; ++ if (!dst_data) ++ return DFB_DEAD; ++ ++ dst_surface = dst_data->surface; ++ if (!dst_surface) ++ return DFB_DESTROYED; ++ ++ dfb_region_from_rectangle( &data->clip, &dst_data->area.current ); ++ ++ if (dest_rect) { ++ if (dest_rect->w < 1 || dest_rect->h < 1) ++ return DFB_INVARG; ++ ++ data->rect = *dest_rect; ++ data->rect.x += dst_data->area.wanted.x; ++ data->rect.y += dst_data->area.wanted.y; ++ ++ if (!dfb_rectangle_region_intersects( &data->rect, &data->clip )) ++ return DFB_OK; ++ } ++ else { ++ data->rect = dst_data->area.wanted; ++ } ++ ++ return JPEG_hwRenderTo( data, dst_surface, &data->rect, &data->clip ); ++} ++ ++static DFBResult ++IDirectFBImageProvider_hwJPEG_GetSurfaceDescription( IDirectFBImageProvider *thiz, ++ DFBSurfaceDescription *dsc ) ++{ ++ DIRECT_INTERFACE_GET_DATA(IDirectFBImageProvider_hwJPEG) ++ ++ if (!dsc) ++ return DFB_INVARG; ++ ++ if (data->width < 0 ++ || data->height < 0) ++ return DFB_INVARG; ++ ++ dsc->flags = DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT; ++ dsc->width = data->width; ++ dsc->height = data->height; ++ dsc->pixelformat = data->pixelformat; ++ ++ return DFB_OK; ++} ++ ++static DFBResult ++IDirectFBImageProvider_hwJPEG_SetRenderFlags( IDirectFBImageProvider *thiz, ++ DIRenderFlags flags ) ++{ ++ DIRECT_INTERFACE_GET_DATA(IDirectFBImageProvider_hwJPEG) ++ ++ return DFB_UNSUPPORTED; ++} ++ ++static DFBResult ++IDirectFBImageProvider_hwJPEG_GetImageDescription( IDirectFBImageProvider *thiz, ++ DFBImageDescription *dsc ) ++{ ++ DIRECT_INTERFACE_GET_DATA(IDirectFBImageProvider_hwJPEG) ++ ++ if (!dsc) ++ return DFB_INVARG; ++ ++ dsc->caps = DICAPS_NONE; ++ ++ return DFB_OK; ++} +diff --git a/interfaces/IDirectFBImageProvider/idirectfbimageprovider_hwjpeg_v4l2.h b/interfaces/IDirectFBImageProvider/idirectfbimageprovider_hwjpeg_v4l2.h +new file mode 100644 +index 0000000..c997182 +--- /dev/null ++++ b/interfaces/IDirectFBImageProvider/idirectfbimageprovider_hwjpeg_v4l2.h +@@ -0,0 +1,59 @@ ++/* ++ (c) Copyright 2012 STMicroelectronics R&D ++ ++based on code: ++ (c) Copyright 2001-2010 The world wide DirectFB Open Source Community (directfb.org) ++ (c) Copyright 2000-2004 Convergence (integrated media) GmbH ++ ++ All rights reserved. ++ ++ Written by Ilyes Gouta ++ Based on code by: ++ Andre' Draszik , ++ Denis Oliver Kropp , ++ Andreas Hundt , ++ Sven Neumann , ++ Ville Syrjälä and ++ Claudio Ciccani . ++ ++ This library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2 of the License, or (at your option) any later version. ++ ++ This library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with this library; if not, write to the ++ Free Software Foundation, Inc., 59 Temple Place - Suite 330, ++ Boston, MA 02111-1307, USA. ++*/ ++ ++#ifndef __IDIRECTFBIMAGEPROVIDER_HWJPEG_H__ ++#define __IDIRECTFBIMAGEPROVIDER_HWJPEG_H__ ++ ++/* private data struct of IDirectFBImageProvider_hwJPEG */ ++typedef struct ++{ ++ IDirectFBImageProvider_data base; ++ ++ int fd; ++ ++ unsigned int width; ++ unsigned int height; ++ ++ DFBSurfacePixelFormat pixelformat; ++ ++ CoreSurface *source_surface; ++ CoreSurface *decode_surface; ++ ++ CoreGraphicsSerial serial; ++ ++ DFBRectangle rect; ++ DFBRegion clip; ++} IDirectFBImageProvider_hwJPEG_data; ++ ++#endif /* __IDIRECTFBIMAGEPROVIDER_HWJPEG_H__ */ +diff --git a/interfaces/IDirectFBImageProvider/idirectfbimageprovider_jpeg.c b/interfaces/IDirectFBImageProvider/idirectfbimageprovider_jpeg.c +index a7430f7..5aa1e30 100644 +--- a/interfaces/IDirectFBImageProvider/idirectfbimageprovider_jpeg.c ++++ b/interfaces/IDirectFBImageProvider/idirectfbimageprovider_jpeg.c +@@ -1,4 +1,7 @@ + /* ++ (c) Copyright 2006-2010 ST Microelectronics R&D ++ ++based on code: + (c) Copyright 2001-2010 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + +@@ -44,12 +47,14 @@ + #include + + #include ++#include + + #include + #include + #include + #include + #include ++#include + #include + + #include +@@ -58,6 +63,36 @@ + #undef HAVE_STDLIB_H + #include + ++#if !defined(JPEG_PROVIDER_USE_MME) ++#undef USE_MME ++#endif ++ ++ ++#include "debug_helper.h" ++ ++D_DEBUG_DOMAIN (JPEG, "JPEG", "STM JPEG decoder"); ++D_DEBUG_DOMAIN (JPEG_RAW, "JPEG/raw", "STM JPEG decoder (raw decode)"); ++D_DEBUG_DOMAIN (JPEG_MME, "JPEG/MME", "STM JPEG decoder (MME)"); ++D_DEBUG_DOMAIN (JPEG_SEMA, "JPEG/SEMA", "STM JPEG decoder (semaphores"); ++D_DEBUG_DOMAIN (JPEG_TIME, "JPEG/Time", "STM JPEG decoder (timing"); ++#define MME_DEBUG_DOMAIN JPEG_MME ++#define SEMA_DEBUG_DOMAIN JPEG_SEMA ++#define MME_TEXT_DOMAIN "JPEG" ++ ++#include "mme_helper.h" ++#include "idirectfbimageprovider_jpeg.h" ++#if defined(JPEG_PROVIDER_USE_MME) ++#include "sema_helper.h" ++static DFBResult JPEG_HardwareRenderTo( IDirectFBImageProvider_JPEG_data *data, ++ CoreSurface *dst_surface, ++ DFBSurfacePixelFormat format, ++ DFBRectangle *rect, ++ const DFBRegion *clip ); ++#else /* JPEG_PROVIDER_USE_MME */ ++#define JPEG_HardwareRenderTo(data,dst_surface, \ ++ format,rect,clip) DFB_NOSUCHINSTANCE ++#endif /* JPEG_PROVIDER_USE_MME */ ++ + + static DFBResult + Probe( IDirectFBImageProvider_ProbeContext *ctx ); +@@ -68,23 +103,11 @@ Construct( IDirectFBImageProvider *thiz, + + #include + +-DIRECT_INTERFACE_IMPLEMENTATION( IDirectFBImageProvider, JPEG ) +- +-/* +- * private data struct of IDirectFBImageProvider_JPEG +- */ +-typedef struct { +- IDirectFBImageProvider_data base; +- +- int width; /* width of the JPEG image */ +- int height; /* height of the JPEG image */ +- +- u32 *image; /* decoded image data */ +- int image_width; /* width of image data */ +- int image_height; /* height of image data */ +- +- DIRenderFlags flags; /* selected idct method */ +-} IDirectFBImageProvider_JPEG_data; ++#if defined(JPEG_PROVIDER_USE_MME) ++DIRECT_INTERFACE_IMPLEMENTATION( IDirectFBImageProvider, hwJPEG ) ++#else /* JPEG_PROVIDER_USE_MME */ ++DIRECT_INTERFACE_IMPLEMENTATION( IDirectFBImageProvider, swJPEG ) ++#endif /* JPEG_PROVIDER_USE_MME */ + + + static DFBResult +@@ -93,6 +116,10 @@ IDirectFBImageProvider_JPEG_RenderTo( IDirectFBImageProvider *thiz, + const DFBRectangle *destination_rect ); + + static DFBResult ++IDirectFBImageProvider_JPEG_Sync( IDirectFBImageProvider *thiz, ++ DFBImageProviderSyncFlags flags ); ++ ++static DFBResult + IDirectFBImageProvider_JPEG_GetSurfaceDescription( IDirectFBImageProvider *thiz, + DFBSurfaceDescription *dsc ); + +@@ -104,6 +131,10 @@ static DFBResult + IDirectFBImageProvider_JPEG_SetRenderFlags( IDirectFBImageProvider *thiz, + DIRenderFlags flags ); + ++static void * ++JPEGrenderThread( DirectThread *thread, void *driver_data ); ++ ++ + #define JPEG_PROG_BUF_SIZE 0x10000 + + typedef struct { +@@ -224,74 +255,6 @@ jpeglib_panic(j_common_ptr cinfo) + longjmp(myerr->setjmp_buffer, 1); + } + +-static inline void +-copy_line32( u32 *argb, const u8 *rgb, int width ) +-{ +- while (width--) { +- *argb++ = 0xFF000000 | (rgb[0] << 16) | (rgb[1] << 8) | rgb[2]; +- +- rgb += 3; +- } +-} +- +-static inline void +-copy_line_nv16( u16 *yy, u16 *cbcr, const u8 *src_ycbcr, int width ) +-{ +- int x; +- +- for (x=0; x> 1); +-#else +- yy[x] = (src_ycbcr[3] << 8) | src_ycbcr[0]; +- +- cbcr[x] = (((src_ycbcr[2] + src_ycbcr[5]) << 7) & 0xff00) | +- ((src_ycbcr[1] + src_ycbcr[4]) >> 1); +-#endif +- +- src_ycbcr += 6; +- } +- +- if (width & 1) { +- u8 *y = (u8*) yy; +- +- y[width-1] = src_ycbcr[0]; +- +-#ifdef WORDS_BIGENDIAN +- cbcr[x] = (src_ycbcr[1] << 8) | src_ycbcr[2]; +-#else +- cbcr[x] = (src_ycbcr[2] << 8) | src_ycbcr[1]; +-#endif +- } +-} +- +-static inline void +-copy_line_uyvy( u32 *uyvy, const u8 *src_ycbcr, int width ) +-{ +- int x; +- +- for (x=0; xpriv; + +- if (data->image) +- D_FREE( data->image ); ++ if (data->thread) { ++ /* terminate the decoding thread, if necessary... */ ++ direct_thread_cancel( data->thread ); ++ direct_thread_join( data->thread ); ++ direct_thread_destroy( data->thread ); ++ ++ pthread_mutex_destroy( &data->lock ); ++ pthread_cond_destroy( &data->cond ); ++ } ++ ++ if (data->common.decode_surface) { ++ dfb_gfxcard_wait_serial( &data->common.serial ); ++ dfb_surface_unref( data->common.decode_surface ); ++ } + } + + static DFBResult +@@ -350,9 +325,9 @@ Construct( IDirectFBImageProvider *thiz, + core = va_arg( tag, CoreDFB * ); + va_end( tag ); + +- data->base.ref = 1; +- data->base.buffer = buffer; +- data->base.core = core; ++ data->common.base.ref = 1; ++ data->common.base.buffer = buffer; ++ data->common.base.core = core; + + buffer->AddRef( buffer ); + +@@ -373,8 +348,13 @@ Construct( IDirectFBImageProvider *thiz, + jpeg_read_header(&cinfo, TRUE); + jpeg_start_decompress(&cinfo); + +- data->width = cinfo.output_width; +- data->height = cinfo.output_height; ++ data->common.width = cinfo.output_width; ++ data->common.height = cinfo.output_height; ++ ++#if defined(JPEG_PROVIDER_USE_MME) ++ data->num_components = cinfo.num_components; ++ data->progressive_mode = cinfo.progressive_mode; ++#endif + + data->flags = DIRENDER_NONE; + +@@ -387,9 +367,10 @@ Construct( IDirectFBImageProvider *thiz, + return DFB_FAILURE; + } + +- data->base.Destruct = IDirectFBImageProvider_JPEG_Destruct; ++ data->common.base.Destruct = IDirectFBImageProvider_JPEG_Destruct; + + thiz->RenderTo = IDirectFBImageProvider_JPEG_RenderTo; ++ thiz->Sync = IDirectFBImageProvider_JPEG_Sync; + thiz->GetImageDescription =IDirectFBImageProvider_JPEG_GetImageDescription; + thiz->SetRenderFlags = IDirectFBImageProvider_JPEG_SetRenderFlags; + thiz->GetSurfaceDescription = +@@ -407,73 +388,597 @@ wrap_setjmp( struct my_error_mgr *jerr ) + return 0; + } + ++static void ++JPEG_stretchblit( IDirectFBImageProvider_JPEG_data *data, ++ CardState *state, ++ DFBRectangle *src_rect, ++ DFBRectangle *dst_rect ) ++{ ++ D_DEBUG_AT( JPEG, "StretchBlit %dx%d -> %dx%d (%s -> %s)\n", ++ src_rect->w, src_rect->h, dst_rect->w, dst_rect->h, ++ dfb_pixelformat_name( state->source->config.format), ++ dfb_pixelformat_name( state->destination->config.format ) ); ++ ++ /* thankfully this is intelligent enough to do a simple blit if ++ possible */ ++ dfb_gfxcard_stretchblit( src_rect, dst_rect, state ); ++ /* we need to remember the serial in case a new surface is created ++ (and written to) at the same address as the decode_surface before the ++ blit operation is finished. This can happen if we get into the ++ destructor before the blit operation is finished, which can happen on ++ fast CPUs. */ ++ data->common.serial = state->serial; ++} ++ ++#define _ROUND_UP_8(x) (((x)+ 7) & ~ 7) ++#define _ROUND_UP_16(x) (((x)+15) & ~15) ++static void ++JPEG_setup_yuv444p( const struct jpeg_decompress_struct *cinfo, ++ CoreSurfaceConfig *config, ++ int *pitch_y, ++ int *pitch_cb, ++ int *pitch_cr, ++ int *offset_cb, ++ int *offset_cr ) ++{ ++ config->format = DSPF_YUV444P; ++ ++ config->size.w = _ROUND_UP_8( cinfo->cur_comp_info[0] ++ ->downsampled_width ); ++ config->size.h = _ROUND_UP_8( cinfo->cur_comp_info[0] ++ ->downsampled_height ); ++ ++ /* pad an extra (decimated) MCU row for the iDCT write-out */ ++#if JPEG_LIB_VERSION >= 70 ++ config->size.h += cinfo->max_v_samp_factor * ++ cinfo->min_DCT_v_scaled_size; ++#else ++ config->size.h += cinfo->max_v_samp_factor * ++ cinfo->min_DCT_scaled_size; ++#endif ++ ++ *pitch_y = config->size.w; ++ if (cinfo->num_components == 3) { ++ *pitch_cb = _ROUND_UP_8( cinfo->cur_comp_info[1]->downsampled_width ); ++ *pitch_cr = _ROUND_UP_8( cinfo->cur_comp_info[2]->downsampled_width ); ++ } ++ ++ *offset_cb ++ = *offset_cr ++ = *pitch_y * config->size.h; ++} ++ + static DFBResult +-IDirectFBImageProvider_JPEG_RenderTo( IDirectFBImageProvider *thiz, +- IDirectFBSurface *destination, +- const DFBRectangle *dest_rect ) ++JPEG_raw_decode_common( IDirectFBImageProvider_JPEG_data *data, ++ CoreSurface *dst_surface, ++ DFBRectangle *rect, ++ struct jpeg_decompress_struct *cinfo, ++ CardState *state, ++ CoreSurfaceBufferLock *lock, ++ CoreSurfaceConfig *config, ++ CorePalette *palette, ++ int pitch_y, ++ int pitch_cb, ++ int pitch_cr, ++ int offset_cb, ++ int offset_cr, ++ int y_v_sampl, ++ int cb_v_sampl, ++ int cr_v_sampl) + { +- DFBResult ret; +- bool direct = false; +- DFBRegion clip; +- DFBRectangle rect; +- DFBSurfacePixelFormat format; +- IDirectFBSurface_data *dst_data; +- CoreSurface *dst_surface; +- CoreSurfaceBufferLock lock; ++ DFBResult res; + DIRenderCallbackResult cb_result = DIRCR_OK; ++ DFBRectangle src_rect; + +- DIRECT_INTERFACE_GET_DATA(IDirectFBImageProvider_JPEG) ++ int i; + +- dst_data = (IDirectFBSurface_data*) destination->priv; +- if (!dst_data) +- return DFB_DEAD; ++ /* Worst case, is 4x4 chroma subsampling where an MCU is 32 lines. libjpeg ++ won't decode more than one MCU in any one go. */ ++#if JPEG_LIB_VERSION >= 70 ++ const int idct_window_size = (cinfo->max_v_samp_factor ++ * cinfo->min_DCT_v_scaled_size); ++#else ++ const int idct_window_size = (cinfo->max_v_samp_factor ++ * cinfo->min_DCT_scaled_size); ++#endif + +- dst_surface = dst_data->surface; +- if (!dst_surface) +- return DFB_DESTROYED; ++#undef _NO_STACK ++#ifndef _NO_STACK ++ JSAMPROW Yrows[idct_window_size]; ++ JSAMPROW Cbrows[idct_window_size]; ++ JSAMPROW Crrows[idct_window_size]; ++ JSAMPARRAY jpeg_buffer[3] = { ++ [0] = Yrows ++ }; ++#else ++ /* valgrind can't check stack variables */ ++#warning this is not for production use, as we do not clean up on errors ++ JSAMPROW *Yrows, *Cbrows, *Crrows; ++ JSAMPARRAY *jpeg_buffer; ++ ++ /* over allocate, least trouble */ ++ Yrows = malloc( sizeof(JSAMPROW) * idct_window_size) ; ++ Cbrows = malloc( sizeof(JSAMPROW) * idct_window_size ); ++ Crrows = malloc( sizeof(JSAMPROW) * idct_window_size ); ++ ++ jpeg_buffer = malloc( 3 * sizeof(JSAMPARRAY) ); ++ jpeg_buffer[0] = Yrows; ++#endif + +- ret = destination->GetPixelFormat( destination, &format ); +- if (ret) +- return ret; + +- dfb_region_from_rectangle( &clip, &dst_data->area.current ); ++ if (cb_v_sampl) { ++ jpeg_buffer[1] = Cbrows; ++ jpeg_buffer[2] = Crrows; ++ } + +- if (dest_rect) { +- if (dest_rect->w < 1 || dest_rect->h < 1) +- return DFB_INVARG; ++ config->flags = CSCONF_SIZE | CSCONF_FORMAT | CSCONF_COLORSPACE | CSCONF_CAPS; ++ #ifdef __SH4__ ++ config->caps = DSCAPS_VIDEOONLY; ++ #else ++ config->caps = 0; ++ #endif ++ #ifdef DIRECT_BUILD_DEBUG ++ config->caps |= DSCAPS_SHARED; ++ #endif ++ ++ res = dfb_surface_create( data->common.base.core, config, CSTF_NONE, 0, ++ palette, ++ &data->common.decode_surface ); ++ if (palette) ++ /* decode_surface holds a reference to the palette now */ ++ dfb_palette_unref( palette ); ++ ++ if (res != DFB_OK) { ++ D_ERROR( "failed to create temporary decode surface\n" ); ++ return DFB_UNSUPPORTED; ++ } + +- rect = *dest_rect; +- rect.x += dst_data->area.wanted.x; +- rect.y += dst_data->area.wanted.y; ++ if (dfb_surface_lock_buffer( data->common.decode_surface, ++ CSBR_BACK, CSAID_CPU, CSAF_WRITE, lock )) { ++ dfb_surface_unref( data->common.decode_surface ); ++ data->common.decode_surface = NULL; ++ return DFB_UNSUPPORTED; ++ } + +- if (!dfb_rectangle_region_intersects( &rect, &clip )) +- return DFB_OK; ++ cinfo->raw_data_out = true; ++ jpeg_start_decompress( cinfo ); ++ ++ dfb_state_set_source( state, data->common.decode_surface ); ++ ++ /* Initialize the various pointers to build a planar YUV buffer. */ ++ for (i = 0; i < idct_window_size; ++i) ++ Yrows[i] = lock->addr + i * pitch_y; ++ if (cb_v_sampl) { ++ void *cbaddr = lock->addr + offset_cb; ++ void *craddr = cbaddr + offset_cr; ++ for (i = 0; i < idct_window_size; ++i) { ++ Cbrows[i] = cbaddr + i * pitch_cb; ++ Crrows[i] = craddr + i * pitch_cr; ++ } ++ } ++ ++ while (cinfo->output_scanline < data->common.decoded_height ++ && cb_result == DIRCR_OK) { ++ int x = jpeg_read_raw_data( cinfo, jpeg_buffer, ++ idct_window_size ); ++ if (x <= 0) ++ /* Actually, x == 0 means that we don't have enough data to ++ continue decoding the picture. */ ++ break; ++ ++ D_DEBUG_AT( JPEG_RAW, ++ " -> decoded %d scanlines (out of %d (%d))\n", ++ cinfo->output_scanline, data->common.decoded_height, ++ config->size.h ); ++ ++ /* increment the pointers by the number of decoded (luma) ++ scanlines. */ ++ for (i = 0; i < idct_window_size; ++i) ++ Yrows[i] += (x * pitch_y) / y_v_sampl; ++ if (cb_v_sampl) { ++ for (i = 0; i < idct_window_size; ++i) { ++ Cbrows[i] += (x * pitch_cb) / cb_v_sampl; ++ Crrows[i] += (x * pitch_cr) / cr_v_sampl; ++ } ++ } ++ ++ if (data->common.base.render_callback) { ++ DFBRectangle r; ++ DFBRectangle dst_rect; ++ float factor; ++ ++ src_rect = (DFBRectangle) { ++ .x = 0, ++ .y = cinfo->output_scanline - x, ++ .w = data->common.decoded_width, ++ .h = x, ++ }; ++ r = src_rect; ++ factor = (rect->h / (float) data->common.decoded_height); ++ dst_rect = (DFBRectangle) { ++ .x = rect->x, ++ .y = (int) (src_rect.y * factor), ++ .w = rect->w, ++ .h = (int) (src_rect.h * factor), ++ }; ++ ++ D_DEBUG_AT( JPEG_RAW, ++ " -> render callback %d,%d %dx%d -> %d,%d %dx%d\n", ++ src_rect.x, src_rect.y, src_rect.w, ++ src_rect.h, dst_rect.x, dst_rect.y, ++ dst_rect.w, dst_rect.h ); ++ ++ JPEG_stretchblit( data, state, &src_rect, &dst_rect ); ++ ++ cb_result = data->common.base.render_callback( &r, ++ data->common.base.render_callback_context ); ++ } ++ } ++ ++ D_DEBUG_AT( JPEG_RAW, " -> decoded %d scanlines (out of %d)\n", ++ cinfo->output_scanline, data->common.decoded_height ); ++ ++ if (cinfo->output_scanline < data->common.decoded_height ++ || cb_result != DIRCR_OK) { ++ if (cb_result != DIRCR_OK) ++ D_ERROR( "raw decode failed after %d of %d scanlines, " ++ "trying pure software\n", ++ cinfo->output_scanline, cinfo->output_height ); ++ jpeg_abort_decompress( cinfo ); ++ jpeg_destroy_decompress( cinfo ); ++ dfb_surface_unlock_buffer( data->common.decode_surface, lock ); ++ lock->pitch = 0; ++ dfb_surface_unref( data->common.decode_surface ); ++ data->common.decode_surface = NULL; ++ ++ if (cb_result != DIRCR_OK) ++ return DFB_INTERRUPTED; ++ ++ return DFB_FAILURE; /* restart */ ++ } ++ ++ jpeg_finish_decompress( cinfo ); ++ jpeg_destroy_decompress( cinfo ); ++ ++ dfb_surface_unlock_buffer( data->common.decode_surface, lock ); ++ lock->pitch = 0; ++ ++ /* use DFB to convert raw YCbCr to destination format, and apply any ++ necessary additional clip/stretch */ ++ src_rect = (DFBRectangle) { ++ .x = 0, ++ .y = 0, ++ .w = data->common.decoded_width, ++ .h = data->common.decoded_height ++ }; ++ ++ JPEG_stretchblit( data, state, &src_rect, rect ); ++ ++ if (data->common.base.render_callback) ++ data->common.base.render_callback( &src_rect, ++ data->common.base.render_callback_context ); ++ ++#ifdef _NO_STACK ++ free( Yrows ); ++ if (cb_v_sampl) { ++ free( Cbrows ); ++ free( Crrows ); ++ } ++ free( jpeg_buffer ); ++#endif ++ ++ return DFB_OK; ++} ++ ++static DFBResult ++JPEG_raw_decode_YCbCr( IDirectFBImageProvider_JPEG_data *data, ++ CoreSurface *dst_surface, ++ DFBRectangle *rect, ++ struct jpeg_decompress_struct *cinfo, ++ CardState *state, ++ CoreSurfaceBufferLock *lock ) ++{ ++ CoreSurfaceConfig config; ++ int pitch_y, pitch_cb, pitch_cr; ++ int offset_cb; /* cb from y */ ++ int offset_cr; /* cr from cb */ ++ int y_v_sampl = 1; ++ int cb_v_sampl = 1; ++ int cr_v_sampl = 1; ++ ++ const int v_samp[3] = { cinfo->cur_comp_info[0]->v_samp_factor, ++ cinfo->cur_comp_info[1]->v_samp_factor, ++ cinfo->cur_comp_info[2]->v_samp_factor }; ++ ++#if JPEG_LIB_VERSION >= 70 ++ const int idct_window_size = (cinfo->max_v_samp_factor ++ * cinfo->min_DCT_v_scaled_size); ++#else ++ const int idct_window_size = (cinfo->max_v_samp_factor ++ * cinfo->min_DCT_scaled_size); ++#endif ++ ++ D_DEBUG_AT( JPEG_RAW, "trying YCbCr raw decode\n" ); ++ ++ if (cinfo->max_h_samp_factor == 1 ++ && cinfo->max_v_samp_factor == 1 ++ && cinfo->cur_comp_info[0]->h_samp_factor == 1 ++ && v_samp[0] == 1 ++ && cinfo->cur_comp_info[1]->h_samp_factor == 1 ++ && v_samp[1] == 1 ++ && cinfo->cur_comp_info[2]->h_samp_factor == 1 ++ && v_samp[2] == 1) { ++ /* The image is YCbCr 4:4:4 */ ++ D_DEBUG_AT( JPEG_RAW, " -> 4:4:4 image\n" ); ++ ++ JPEG_setup_yuv444p( cinfo, &config, ++ &pitch_y, &pitch_cb, &pitch_cr, ++ &offset_cb, &offset_cr ); ++ } ++ else if (cinfo->max_h_samp_factor == 2 ++ && cinfo->max_v_samp_factor == 2 ++ && cinfo->cur_comp_info[0]->h_samp_factor == 2 ++ && v_samp[0] == 2 ++ && cinfo->cur_comp_info[1]->h_samp_factor == 1 ++ && v_samp[1] == 1 ++ && cinfo->cur_comp_info[2]->h_samp_factor == 1 ++ && v_samp[2] == 1) { ++ /* The image is YCbCr 4:2:0 ... */ ++ D_DEBUG_AT( JPEG_RAW, " -> 4:2:0 (I420) image\n" ); ++ ++ if ((cinfo->scale_num != cinfo->scale_denom) ++ && ((((float)cinfo->scale_denom / cinfo->scale_num) ++ == (float)(cinfo->scale_denom / cinfo->scale_num)) ++ || (cinfo->scale_num < 4 && cinfo->scale_num != 1)) /* only when JPEG_LIB_VERSION >= 70 */ ++ && (cinfo->cur_comp_info[1]->downsampled_width ++ == cinfo->cur_comp_info[0]->downsampled_width) ++ && (cinfo->cur_comp_info[2]->downsampled_width ++ == cinfo->cur_comp_info[0]->downsampled_width)) { ++ /* ... but because we are iDCT scaling during decompression it ++ might end up scaled to 4:4:4, as libjpeg can (and will) apply ++ different scaling factors for the three components. */ ++ D_DEBUG_AT( JPEG_RAW, " -> iDCT %u/%u scaled to 4:4:4\n", ++ cinfo->scale_num, cinfo->scale_denom ); ++ ++ JPEG_setup_yuv444p( cinfo, &config, ++ &pitch_y, &pitch_cb, &pitch_cr, ++ &offset_cb, &offset_cr ); ++ } ++ else if ((cinfo->scale_num == cinfo->scale_denom) ++ || (((float)cinfo->scale_denom / cinfo->scale_num) ++ != (float)(cinfo->scale_denom / cinfo->scale_num)) ++ || ((cinfo->cur_comp_info[1]->downsampled_width ++ == ((cinfo->cur_comp_info[0]->downsampled_width + 1) ++ / 2)) ++ && (cinfo->cur_comp_info[2]->downsampled_width ++ == ((cinfo->cur_comp_info[0]->downsampled_width + 1) ++ / 2)))) { ++ /* ... no iDCT scaling, which means it really ends up ++ as 4:2:0. */ ++ config.format = DSPF_I420; ++ ++ config.size.w = _ROUND_UP_16( cinfo->cur_comp_info[0] ++ ->downsampled_width ); ++ config.size.h = _ROUND_UP_16( cinfo->cur_comp_info[0] ++ ->downsampled_height ); ++ ++ /* pad an extra (decimated) MCU row for the iDCT write-out */ ++ config.size.h += idct_window_size; ++ ++ pitch_y = config.size.w; ++ pitch_cb ++ = pitch_cr ++ = pitch_y / 2; ++ ++ offset_cb = pitch_y * config.size.h; ++ offset_cr = pitch_cb * config.size.h / 2; ++ ++ cb_v_sampl ++ = cr_v_sampl ++ = 2; ++ } ++ else { ++ /* shouldn't happen, really */ ++ D_DEBUG_AT( JPEG_RAW, " -> unsupported (unexpected)!\n" ); ++ return DFB_UNSUPPORTED; ++ } ++ } ++ else if (cinfo->max_h_samp_factor == 2 ++ && cinfo->max_v_samp_factor == 1 ++ && cinfo->cur_comp_info[0]->h_samp_factor == 2 ++ && v_samp[0] == 1 ++ && cinfo->cur_comp_info[1]->h_samp_factor == 1 ++ && v_samp[1] == 1 ++ && cinfo->cur_comp_info[2]->h_samp_factor == 1 ++ && v_samp[2] == 1) { ++ /* The image is YCbCr 4:2:2 ... */ ++ D_DEBUG_AT( JPEG_RAW, " -> 4:2:2 (YV16) image\n" ); ++ ++ if ((cinfo->scale_num != cinfo->scale_denom) ++ && ((((float)cinfo->scale_denom / cinfo->scale_num) ++ == (float)(cinfo->scale_denom / cinfo->scale_num)) ++ || (cinfo->scale_num < 4 && cinfo->scale_num != 1)) /* only when JPEG_LIB_VERSION >= 70 */ ++ && (cinfo->cur_comp_info[1]->downsampled_width ++ == cinfo->cur_comp_info[0]->downsampled_width) ++ && (cinfo->cur_comp_info[2]->downsampled_width ++ == cinfo->cur_comp_info[0]->downsampled_width)) { ++ /* ... iDCT scaling again, as above. */ ++ D_DEBUG_AT( JPEG_RAW, " -> iDCT %u/%u scaled to 4:4:4\n", ++ cinfo->scale_num, cinfo->scale_denom ); ++ ++ JPEG_setup_yuv444p( cinfo, &config, ++ &pitch_y, &pitch_cb, &pitch_cr, ++ &offset_cb, &offset_cr ); ++ } ++ else if ((cinfo->scale_num == cinfo->scale_denom) ++ || (((float)cinfo->scale_denom / cinfo->scale_num) ++ != (float)(cinfo->scale_denom / cinfo->scale_num)) ++ || ((cinfo->cur_comp_info[1]->downsampled_width ++ == ((cinfo->cur_comp_info[0]->downsampled_width + 1) ++ / 2)) ++ && (cinfo->cur_comp_info[2]->downsampled_width ++ == ((cinfo->cur_comp_info[0]->downsampled_width + 1) ++ / 2)))) { ++ /* ... no iDCT scaling, as above. */ ++ config.format = DSPF_YV16; ++ ++ config.size.w = _ROUND_UP_16( cinfo->cur_comp_info[0] ++ ->downsampled_width ); ++ config.size.h = _ROUND_UP_16( cinfo->cur_comp_info[0] ++ ->downsampled_height ); ++ ++ /* pad an extra (decimated) MCU row for the iDCT write-out */ ++ config.size.h += idct_window_size; ++ ++ pitch_y = config.size.w; ++ pitch_cb ++ = pitch_cr ++ = pitch_y / 2; ++ ++ /* YV16 has Cr/Cb planes not Cb/Cr */ ++ offset_cb = (pitch_y + pitch_cr) * config.size.h; ++ offset_cr = -pitch_cr * config.size.h; ++ } ++ else { ++ /* shouldn't happen, really */ ++ D_DEBUG_AT( JPEG_RAW, " -> unsupported (unexpected)!\n" ); ++ return DFB_UNSUPPORTED; ++ } + } + else { +- rect = dst_data->area.wanted; ++ D_DEBUG_AT( JPEG_RAW, " -> unsupported!\n" ); ++ return DFB_UNSUPPORTED; + } + +- ret = dfb_surface_lock_buffer( dst_surface, CSBR_BACK, CSAID_CPU, CSAF_WRITE, &lock ); +- if (ret) +- return ret; ++ /* FIXME: is this correct for all JPEG images? */ ++ config.colorspace = DSCS_BT601_FULLRANGE; ++ ++ /* We can handle this raw format! */ ++ return JPEG_raw_decode_common( data, dst_surface, rect, ++ cinfo, state, lock, ++ &config, NULL, ++ pitch_y, pitch_cb, pitch_cr, ++ offset_cb, offset_cr, ++ y_v_sampl, cb_v_sampl, cr_v_sampl ); ++} ++ ++static DFBResult ++JPEG_raw_decode_Grayscale( IDirectFBImageProvider_JPEG_data *data, ++ CoreSurface *dst_surface, ++ DFBRectangle *rect, ++ struct jpeg_decompress_struct *cinfo, ++ CardState *state, ++ CoreSurfaceBufferLock *lock ) ++{ ++ CoreSurfaceConfig config; ++ CorePalette *lut8_palette; ++ int pitch_y; ++ ++ unsigned int i; ++ ++ D_DEBUG_AT( JPEG_RAW, "trying grayscale raw decode\n" ); + +- if (data->image && +- (rect.x || rect.y || rect.w != data->image_width || rect.h != data->image_height)) { +- D_FREE( data->image ); +- data->image = NULL; +- data->image_width = 0; +- data->image_height = 0; ++ if (cinfo->max_h_samp_factor == 1 ++ && cinfo->max_v_samp_factor == 1 ++ && cinfo->cur_comp_info[0]->h_samp_factor == 1 ++ && cinfo->cur_comp_info[0]->v_samp_factor == 1) { ++ int dummy; ++ ++ /* The image is grayscale 4:4:4 */ ++ D_DEBUG_AT( JPEG_RAW, " -> 4:4:4 grayscale image\n" ); ++ ++ JPEG_setup_yuv444p( cinfo, &config, &pitch_y, &dummy, &dummy, ++ &dummy, &dummy ); ++ ++ /* Override the YUV444P format set by JPEG_setup_yuv444p() */ ++ config.format = DSPF_LUT8; ++ } ++ else { ++ D_DEBUG_AT( JPEG_RAW, " -> unsupported grayscale image!\n" ); ++ return DFB_UNSUPPORTED; ++ } ++ ++ /* We can handle this raw format! */ ++ if (dfb_palette_create( data->common.base.core, 256, &lut8_palette )) { ++ D_ERROR( "failed to create a palette for the decode surface\n" ); ++ return DFB_UNSUPPORTED; ++ } ++ ++ for (i = 0; i < lut8_palette->num_entries; i++) { ++ lut8_palette->entries[i].a = 255; ++ lut8_palette->entries[i].r = i; ++ lut8_palette->entries[i].g = i; ++ lut8_palette->entries[i].b = i; ++ } ++ ++ config.colorspace = DSCS_RGB; ++ ++ return JPEG_raw_decode_common( data, dst_surface, rect, ++ cinfo, state, lock, ++ &config, lut8_palette, ++ pitch_y, 0, 0, ++ 0, 0, ++ 1, 0, 0 ); ++} ++ ++static DFBResult ++JPEG_raw_decode( IDirectFBImageProvider_JPEG_data *data, ++ CoreSurface *dst_surface, ++ DFBRectangle *rect, ++ struct jpeg_decompress_struct *cinfo, ++ CardState *state, ++ CoreSurfaceBufferLock *lock ) ++{ ++ if (cinfo->data_precision != 8) ++ return DFB_UNSUPPORTED; ++ ++ if (cinfo->num_components == 3 ++ && cinfo->jpeg_color_space == JCS_YCbCr) ++ return JPEG_raw_decode_YCbCr( data, dst_surface, rect, ++ cinfo, state, lock ); ++ ++ if (cinfo->num_components == 1 ++ && cinfo->jpeg_color_space == JCS_GRAYSCALE) ++ return JPEG_raw_decode_Grayscale( data, dst_surface, rect, ++ cinfo, state, lock ); ++ ++ return DFB_UNSUPPORTED; ++} ++ ++static DFBResult ++JPEG_SoftwareRenderTo( IDirectFBImageProvider_JPEG_data *data, ++ CoreSurface *dst_surface, ++ DFBSurfacePixelFormat format, ++ DFBRectangle *rect, ++ const DFBRegion *clip ) ++{ ++ DFBResult ret; ++ DIRenderCallbackResult cb_result = DIRCR_OK; ++ bool try_raw = true; ++ ++ D_ASSERT( data != NULL ); ++ D_ASSERT( dst_surface != NULL ); ++ D_ASSERT( clip != NULL ); ++ D_ASSERT( rect != NULL ); ++ ++ if (data->common.decode_surface && ++ (rect->x || rect->y || rect->w != data->common.decoded_width || rect->h != data->common.decoded_height)) { ++ dfb_gfxcard_wait_serial( &data->common.serial ); ++ dfb_surface_unref( data->common.decode_surface ); ++ data->common.decode_surface = NULL; ++ data->common.decoded_width = 0; ++ data->common.decoded_height = 0; + } + + /* actual loading and rendering */ +- if (!data->image) { ++ if (!data->common.decode_surface) { + struct jpeg_decompress_struct cinfo; + struct my_error_mgr jerr; + JSAMPARRAY buffer; /* Output row buffer */ +- int row_stride; /* physical row width in output buffer */ +- u32 *row_ptr; ++ JSAMPLE *row_ptr; + int y = 0; +- int uv_offset = 0; ++ CardState state; ++ CoreSurfaceBufferLock lock_raw = { .pitch = 0 }; + + cinfo.err = jpeg_std_error(&jerr.pub); + jerr.pub.error_exit = jpeglib_panic; +@@ -483,28 +988,59 @@ IDirectFBImageProvider_JPEG_RenderTo( IDirectFBImageProvider *thiz, + + jpeg_destroy_decompress( &cinfo ); + +- if (data->image) { +- dfb_scale_linear_32( data->image, data->image_width, data->image_height, +- lock.addr, lock.pitch, &rect, dst_surface, &clip ); +- dfb_surface_unlock_buffer( dst_surface, &lock ); +- if (data->base.render_callback) { +- DFBRectangle r = { 0, 0, data->image_width, data->image_height }; +- +- if (data->base.render_callback( &r, +- data->base.render_callback_context ) != DIRCR_OK) ++ if (try_raw) { ++ dfb_state_set_source( &state, NULL ); ++ dfb_state_set_destination( &state, NULL ); ++ dfb_state_destroy( &state); ++ } ++ if (data->common.decode_surface) { ++ CardState state; ++ DFBRectangle src_rect = { ++ .x = 0, ++ .y = 0, ++ .w = data->common.decoded_width, ++ .h = data->common.decoded_height ++ }; ++ ++ if (lock_raw.pitch) ++ dfb_surface_unlock_buffer( data->common.decode_surface, ++ &lock_raw ); ++ ++ /* use DFB to convert the raw or BGR24 to destination ++ format, and apply any necessary additional ++ clip/stretch */ ++ dfb_state_init( &state, data->common.base.core ); ++ dfb_state_set_source( &state, data->common.decode_surface ); ++ dfb_state_set_destination( &state, dst_surface ); ++ dfb_state_set_clip( &state, clip ); ++ ++ JPEG_stretchblit( data, &state, &src_rect, rect ); ++ ++ /* remove the state */ ++ dfb_state_set_source( &state, NULL ); ++ dfb_state_set_destination( &state, NULL ); ++ dfb_state_destroy( &state ); ++ ++ dfb_gfxcard_wait_serial( &data->common.serial ); ++ dfb_surface_unref( data->common.decode_surface ); ++ data->common.decode_surface = NULL; ++ ++ if (data->common.base.render_callback) { ++ DFBRectangle r = { 0, 0, data->common.decoded_width, data->common.decoded_height }; ++ ++ if (data->common.base.render_callback( &r, data->common.base.render_callback_context ) != DIRCR_OK) + return DFB_INTERRUPTED; + } + + return DFB_INCOMPLETE; + } + else +- dfb_surface_unlock_buffer( dst_surface, &lock ); +- +- return DFB_FAILURE; ++ return DFB_FAILURE; + } + ++restart: + jpeg_create_decompress( &cinfo ); +- jpeg_buffer_src( &cinfo, data->base.buffer, 0 ); ++ jpeg_buffer_src( &cinfo, data->common.base.buffer, 0 ); + jpeg_read_header( &cinfo, TRUE ); + + #if JPEG_LIB_VERSION >= 70 +@@ -516,19 +1052,16 @@ IDirectFBImageProvider_JPEG_RenderTo( IDirectFBImageProvider *thiz, + #endif + jpeg_calc_output_dimensions( &cinfo ); + +- if (cinfo.output_width == (unsigned)rect.w && cinfo.output_height == (unsigned)rect.h) { +- direct = true; +- } +- else if (rect.x == 0 && rect.y == 0) { ++ if (rect->x == 0 && rect->y == 0) { + #if JPEG_LIB_VERSION >= 70 + /* The supported scaling ratios in libjpeg 7 and 8 + * are N/8 with all N from 1 to 16. + */ + cinfo.scale_num = 1; + jpeg_calc_output_dimensions( &cinfo ); +- while (cinfo.scale_num < 16 +- && cinfo.output_width < (unsigned)rect.w +- && cinfo.output_height < (unsigned)rect.h) { ++ while (cinfo.scale_num < 8 ++ && cinfo.output_width < (unsigned)rect->w ++ && cinfo.output_height < (unsigned)rect->h) { + ++cinfo.scale_num; + jpeg_calc_output_dimensions( &cinfo ); + } +@@ -537,8 +1070,8 @@ IDirectFBImageProvider_JPEG_RenderTo( IDirectFBImageProvider *thiz, + * are 1/1, 1/2, 1/4, and 1/8. + */ + while (cinfo.scale_denom < 8 +- && ((cinfo.output_width >> 1) >= (unsigned)rect.w) +- && ((cinfo.output_height >> 1) >= (unsigned)rect.h)) { ++ && ((cinfo.output_width >> 1) >= (unsigned)rect->w) ++ && ((cinfo.output_height >> 1) >= (unsigned)rect->h)) { + cinfo.scale_denom <<= 1; + jpeg_calc_output_dimensions( &cinfo ); + } +@@ -547,138 +1080,147 @@ IDirectFBImageProvider_JPEG_RenderTo( IDirectFBImageProvider *thiz, + + cinfo.output_components = 3; + +- switch (dst_surface->config.format) { +- case DSPF_NV16: +- uv_offset = dst_surface->config.size.h * lock.pitch; +- +- if (direct && !rect.x && !rect.y) { +- D_INFO( "JPEG: Using YCbCr color space directly! (%dx%d)\n", +- cinfo.output_width, cinfo.output_height ); +- cinfo.out_color_space = JCS_YCbCr; +- break; +- } +- D_INFO( "JPEG: Going through RGB color space! (%dx%d -> %dx%d @%d,%d)\n", +- cinfo.output_width, cinfo.output_height, rect.w, rect.h, rect.x, rect.y ); +- cinfo.out_color_space = JCS_RGB; +- break; +- +- case DSPF_UYVY: +- if (direct && !rect.x && !rect.y) { +- cinfo.out_color_space = JCS_YCbCr; ++ data->common.decoded_width = cinfo.output_width; ++ data->common.decoded_height = cinfo.output_height; ++ ++ cinfo.do_fancy_upsampling = FALSE; ++ cinfo.do_block_smoothing = FALSE; ++ ++ if (try_raw) { ++ /* init a state, so that we can use gfxcard/blit to convert ++ YCbCr to requested destination format */ ++ dfb_state_init( &state, data->common.base.core ); ++ dfb_state_set_destination( &state, dst_surface ); ++ dfb_state_set_clip( &state, clip ); ++ ++ ret = JPEG_raw_decode( data, dst_surface, rect, &cinfo, ++ &state, &lock_raw ); ++ ++ /* remove the state */ ++ dfb_state_set_source( &state, NULL ); ++ dfb_state_set_destination( &state, NULL ); ++ dfb_state_destroy( &state ); ++ ++ switch (ret) { ++ case DFB_OK: ++ case DFB_INTERRUPTED: ++ /* All ok, or callback signalled abort. */ ++ return ret; ++ ++ case DFB_UNSUPPORTED: ++ /* Not enough video memory or source image format not ++ supported. jpeg_start_decompress() was not yet ++ called, so we can just break. ++ We have to reset try_raw, in case the software ++ decode throws an exception, though. */ ++ try_raw = false; + break; +- } +- D_INFO( "JPEG: Going through RGB color space! (%dx%d -> %dx%d @%d,%d)\n", +- cinfo.output_width, cinfo.output_height, rect.w, rect.h, rect.x, rect.y ); +- cinfo.out_color_space = JCS_RGB; +- break; +- +- default: +- cinfo.out_color_space = JCS_RGB; +- break; +- } +- +- if (data->flags & DIRENDER_FAST) +- cinfo.dct_method = JDCT_IFAST; + +- jpeg_start_decompress( &cinfo ); +- +- data->image_width = cinfo.output_width; +- data->image_height = cinfo.output_height; ++ default: ++ D_BUG( "JPEG_raw_decode() returned unknown " ++ "result %d\n", ret ); ++ case DFB_FAILURE: ++ /* General failure during compression, we restart ++ trying a software decoding and in for that have to ++ reinitialise cinfo. */ ++ try_raw = false; ++ goto restart; ++ } ++ } + +- row_stride = cinfo.output_width * 3; + +- buffer = (*cinfo.mem->alloc_sarray)( (j_common_ptr) &cinfo, +- JPOOL_IMAGE, row_stride, 1 ); ++ /* start using the full software decode path */ ++ cinfo.out_color_space = JCS_RGB; + +- data->image = D_CALLOC( data->image_height, data->image_width * 4 ); +- if (!data->image) { +- dfb_surface_unlock_buffer( dst_surface, &lock ); +- return D_OOM(); ++ if (data->flags & DIRENDER_FAST) ++ cinfo.dct_method = JDCT_FASTEST; ++ ++ CoreSurfaceConfig config = { .flags = (CSCONF_SIZE ++ | CSCONF_FORMAT ++ | CSCONF_COLORSPACE), ++ .format = DSPF_BGR24, ++ .colorspace = DSCS_RGB, ++ .size.w = data->common.decoded_width, ++ .size.h = data->common.decoded_height }; ++ if (dfb_surface_create( data->common.base.core, &config, CSTF_NONE, ++ 0, NULL, &data->common.decode_surface )) { ++ D_ERROR( "failed to create temporary decode surface\n" ); ++ return DFB_UNSUPPORTED; + } +- row_ptr = data->image; +- +- while (cinfo.output_scanline < cinfo.output_height && cb_result == DIRCR_OK) { +- jpeg_read_scanlines( &cinfo, buffer, 1 ); + +- switch (dst_surface->config.format) { +- case DSPF_NV16: +- case DSPF_UYVY: +- if (direct) { +- switch (dst_surface->config.format) { +- case DSPF_NV16: +- copy_line_nv16( lock.addr, (u16*)lock.addr + uv_offset, *buffer, rect.w ); +- break; ++ if ((ret = dfb_surface_lock_buffer( data->common.decode_surface, ++ CSBR_BACK, CSAID_CPU, ++ CSAF_WRITE, &lock_raw ))) { ++ dfb_surface_unref( data->common.decode_surface ); ++ data->common.decode_surface = NULL; + +- case DSPF_UYVY: +- copy_line_uyvy( lock.addr, *buffer, rect.w ); +- break; ++ jpeg_abort_decompress( &cinfo ); ++ jpeg_destroy_decompress( &cinfo ); + +- default: +- break; +- } ++ return ret; ++ } + +- lock.addr = (u8*)lock.addr + lock.pitch; ++ jpeg_start_decompress( &cinfo ); + +- if (data->base.render_callback) { +- DFBRectangle r = { 0, y, data->image_width, 1 }; ++ row_ptr = lock_raw.addr; ++ buffer = &row_ptr; + +- cb_result = data->base.render_callback( &r, +- data->base.render_callback_context ); +- } +- break; +- } ++ while (cinfo.output_scanline < cinfo.output_height && cb_result == DIRCR_OK) { ++ jpeg_read_scanlines( &cinfo, buffer, 1 ); + +- default: +- copy_line32( row_ptr, *buffer, data->image_width ); +- +- if (direct) { +- DFBRectangle r = { rect.x, rect.y+y, rect.w, 1 }; +- dfb_copy_buffer_32( row_ptr, lock.addr, lock.pitch, +- &r, dst_surface, &clip ); +- if (data->base.render_callback) { +- r = (DFBRectangle){ 0, y, data->image_width, 1 }; +- cb_result = data->base.render_callback( &r, +- data->base.render_callback_context ); +- } +- } +- break; ++ if (data->common.base.render_callback) { ++ DFBRectangle r = ++ (DFBRectangle){ 0, y, data->common.decoded_width, 1 }; ++ cb_result = data->common.base.render_callback( &r, ++ data->common.base.render_callback_context ); + } + +- row_ptr += data->image_width; ++ row_ptr += lock_raw.pitch; + y++; + } + +- if (!direct) { +- dfb_scale_linear_32( data->image, data->image_width, data->image_height, +- lock.addr, lock.pitch, &rect, dst_surface, &clip ); +- if (data->base.render_callback) { +- DFBRectangle r = { 0, 0, data->image_width, data->image_height }; +- cb_result = data->base.render_callback( &r, +- data->base.render_callback_context ); +- } +- } ++ dfb_surface_unlock_buffer( data->common.decode_surface, &lock_raw ); + + if (cb_result != DIRCR_OK) { + jpeg_abort_decompress( &cinfo ); +- D_FREE( data->image ); +- data->image = NULL; + } + else { + jpeg_finish_decompress( &cinfo ); + } + jpeg_destroy_decompress( &cinfo ); + } +- else { +- dfb_scale_linear_32( data->image, data->image_width, data->image_height, +- lock.addr, lock.pitch, &rect, dst_surface, &clip ); +- if (data->base.render_callback) { +- DFBRectangle r = { 0, 0, data->image_width, data->image_height }; +- data->base.render_callback( &r, +- data->base.render_callback_context ); ++ ++ if (data->common.decode_surface) { ++ CardState state; ++ DFBRectangle src_rect = { ++ .x = 0, ++ .y = 0, ++ .w = data->common.decoded_width, ++ .h = data->common.decoded_height ++ }; ++ ++ /* use DFB to convert the YCbCr or BGR24 to destination format and ++ apply any necessary additional clip/stretch */ ++ dfb_state_init( &state, data->common.base.core ); ++ dfb_state_set_source( &state, data->common.decode_surface ); ++ dfb_state_set_destination( &state, dst_surface ); ++ dfb_state_set_clip( &state, clip ); ++ ++ JPEG_stretchblit( data, &state, &src_rect, rect ); ++ ++ /* remove the state */ ++ dfb_state_set_source( &state, NULL ); ++ dfb_state_set_destination( &state, NULL ); ++ dfb_state_destroy( &state ); ++ ++ if (data->common.base.render_callback) { ++ DFBRectangle r = { 0, 0, data->common.decoded_width, data->common.decoded_height }; ++ data->common.base.render_callback( &r, ++ data->common.base.render_callback_context ); + } + } + +- dfb_surface_unlock_buffer( dst_surface, &lock ); ++ D_DEBUG_AT( JPEG, "software decoding finished\n" ); + + if (cb_result != DIRCR_OK) + return DFB_INTERRUPTED; +@@ -686,6 +1228,167 @@ IDirectFBImageProvider_JPEG_RenderTo( IDirectFBImageProvider *thiz, + return DFB_OK; + } + ++ ++ ++static DFBResult ++JPEG_RenderTo( IDirectFBImageProvider_JPEG_data *data, ++ CoreSurface *dst_surface, ++ DFBSurfacePixelFormat format, ++ DFBRectangle *rect, ++ const DFBRegion *clip ) ++{ ++ DFBResult res; ++ ++ D_ASSERT( data != NULL ); ++ D_ASSERT( dst_surface != NULL ); ++ D_ASSERT( clip != NULL ); ++ D_ASSERT( rect != NULL ); ++ ++ res = JPEG_HardwareRenderTo( data, dst_surface, format, rect, clip ); ++ if (res != DFB_OK) { ++ if (res == DFB_IO) { ++ /* IO error - there's no point in retrying */ ++ D_DEBUG_AT( JPEG, "hardware decode failed: %d (%s)\n", ++ res, DirectFBErrorString( res ) ); ++ return res; ++ } ++ ++ D_DEBUG_AT( JPEG, "hardware decode failed: %d (%s) - " ++ "attempting software fallback\n", ++ res, DirectFBErrorString( res ) ); ++ ++ res = JPEG_SoftwareRenderTo( data, dst_surface, format, rect, clip ); ++ if (unlikely (res != DFB_OK)) ++ D_DEBUG_AT( JPEG, "software decode failed: %d (%s)\n", ++ res, DirectFBErrorString( res ) ); ++ } ++ ++ return res; ++} ++ ++static DFBResult ++IDirectFBImageProvider_JPEG_RenderTo( IDirectFBImageProvider *thiz, ++ IDirectFBSurface *destination, ++ const DFBRectangle *dest_rect ) ++{ ++ IDirectFBSurface_data *dst_data; ++ CoreSurface *dst_surface; ++ DFBSurfacePixelFormat format; ++ DFBResult ret; ++ ++ DIRECT_INTERFACE_GET_DATA(IDirectFBImageProvider_JPEG) ++ ++ dst_data = (IDirectFBSurface_data*) destination->priv; ++ if (!dst_data) ++ return DFB_DEAD; ++ ++ dst_surface = dst_data->surface; ++ if (!dst_surface) ++ return DFB_DESTROYED; ++ ++ ret = destination->GetPixelFormat( destination, &format ); ++ if (ret) ++ return ret; ++ ++ if (data->thread) ++ pthread_mutex_lock( &data->lock ); ++ ++ dfb_region_from_rectangle( &data->clip, &dst_data->area.current ); ++ ++ if (dest_rect) { ++ if (dest_rect->w < 1 || dest_rect->h < 1) { ++ if (data->thread) ++ pthread_mutex_unlock( &data->lock ); ++ return DFB_INVARG; ++ } ++ ++ data->rect = *dest_rect; ++ data->rect.x += dst_data->area.wanted.x; ++ data->rect.y += dst_data->area.wanted.y; ++ ++ if (!dfb_rectangle_region_intersects( &data->rect, &data->clip )) { ++ if (data->thread) ++ pthread_mutex_unlock( &data->lock ); ++ return DFB_OK; ++ } ++ } ++ else { ++ data->rect = dst_data->area.wanted; ++ } ++ ++ if (!D_FLAGS_IS_SET (data->flags, DIRENDER_BACKGROUND)) { ++ /* threaded operation was not requested */ ++ data->thread_res = JPEG_RenderTo( data, dst_surface, format, ++ &data->rect, &data->clip ); ++ if (data->thread) ++ pthread_mutex_unlock( &data->lock ); ++ return data->thread_res; ++ } ++ ++ if (!data->thread) { ++ /* for the case that somebody does a RenderTo() twice on us, we ++ have to create new thread, because the initial thread will have ++ finished already */ ++ ++ D_ASSERT( data->destination == NULL ); ++ ++ /* as long as we haven't even started yet, we are in INIT state */ ++ data->thread_res = DFB_INIT; ++ data->thread = direct_thread_create( DTT_DEFAULT, JPEGrenderThread, ++ thiz, "JPEG" ); ++ } ++ ++ D_ASSERT( data->destination == NULL ); ++ ++ destination->AddRef( destination ); ++ data->destination = destination; ++ ++ pthread_cond_signal( &data->cond ); ++ pthread_mutex_unlock( &data->lock ); ++ ++ return DFB_OK; ++} ++ ++static DFBResult ++IDirectFBImageProvider_JPEG_Sync( IDirectFBImageProvider *thiz, ++ DFBImageProviderSyncFlags flags ) ++{ ++ DFBResult res; ++ ++ DIRECT_INTERFACE_GET_DATA(IDirectFBImageProvider_JPEG) ++ ++ switch (flags) ++ { ++ case DIPSYNCFLAGS_TRYSYNC: ++ if (data->thread) { ++ if (data->thread_res == DFB_INIT ++ || data->thread_res == DFB_BUSY) { ++ /* DFB_INIT (user didn't call RenderTo() yet) ++ DFB_BUSY (still busy decoding) */ ++ return data->thread_res; ++ } ++ /* else we are done, either because of some error or because ++ we have processed all the data already */ ++ } ++ /* fall through */ ++ ++ case DIPSYNCFLAGS_SYNC: ++ if (data->thread) { ++ direct_thread_join( data->thread ); ++ direct_thread_destroy( data->thread ); ++ data->thread = NULL; ++ } ++ break; ++ ++ default: ++ return DFB_OK; ++ } ++ ++ res = data->thread_res; ++ data->thread_res = DFB_OK; ++ return res; ++} ++ + static DFBResult + IDirectFBImageProvider_JPEG_GetSurfaceDescription( IDirectFBImageProvider *thiz, + DFBSurfaceDescription *dsc ) +@@ -696,8 +1399,8 @@ IDirectFBImageProvider_JPEG_GetSurfaceDescription( IDirectFBImageProvider *thiz, + return DFB_INVARG; + + dsc->flags = DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT; +- dsc->height = data->height; +- dsc->width = data->width; ++ dsc->width = data->common.width; ++ dsc->height = data->common.height; + dsc->pixelformat = dfb_primary_layer_pixelformat(); + + return DFB_OK; +@@ -708,6 +1411,30 @@ IDirectFBImageProvider_JPEG_SetRenderFlags( IDirectFBImageProvider *thiz, + { + DIRECT_INTERFACE_GET_DATA(IDirectFBImageProvider_JPEG) + ++ /* if we have decoded the image already, don't do anything... */ ++ if (data->common.decode_surface) ++ return DFB_UNSUPPORTED; ++ ++ if (!(flags & DIRENDER_BACKGROUND) && data->thread) { ++ /* terminate the decoding thread, if necessary... */ ++ direct_thread_cancel( data->thread ); ++ direct_thread_join( data->thread ); ++ direct_thread_destroy( data->thread ); ++ data->thread = NULL; ++ ++ pthread_cond_destroy( &data->cond ); ++ pthread_mutex_destroy( &data->lock ); ++ } ++ else if (flags & DIRENDER_BACKGROUND && !data->thread) { ++ /* or create it */ ++ pthread_cond_init( &data->cond, NULL ); ++ pthread_mutex_init( &data->lock, NULL ); ++ /* as long as we haven't even started yet, we are in INIT state */ ++ data->thread_res = DFB_INIT; ++ data->thread = direct_thread_create( DTT_DEFAULT, JPEGrenderThread, ++ thiz, "JPEG_DECODER?" ); ++ } ++ + data->flags = flags; + + return DFB_OK; +@@ -726,3 +1453,1147 @@ IDirectFBImageProvider_JPEG_GetImageDescription( IDirectFBImageProvider *thiz, + + return DFB_OK; + } ++ ++static void ++render_cleanup( void *cleanup_data ) ++{ ++ IDirectFBImageProvider *thiz = cleanup_data; ++ IDirectFBImageProvider_JPEG_data *data; ++ ++ D_MAGIC_ASSERT( (IAny*)thiz, DirectInterface ); ++ data = (IDirectFBImageProvider_JPEG_data *) thiz->priv; ++ D_ASSERT( data != NULL ); ++ ++ if (data->destination) { ++ data->destination->Release( data->destination ); ++ data->destination = NULL; ++ } ++ ++ /* in case we get terminated from outside, set the state to DFB_DEAD */ ++ data->thread_res = DFB_DEAD; ++ ++ pthread_mutex_unlock( &data->lock ); ++} ++ ++static void * ++JPEGrenderThread( DirectThread *thread, void *driver_data ) ++{ ++ IDirectFBImageProvider *thiz = driver_data; ++ IDirectFBImageProvider_JPEG_data *data; ++ IDirectFBSurface_data *dst_data; ++ CoreSurface *dst_surface; ++ DFBSurfacePixelFormat format; ++ DFBResult res; ++ ++ D_MAGIC_ASSERT( (IAny*)thiz, DirectInterface ); ++ data = (IDirectFBImageProvider_JPEG_data *) thiz->priv; ++ D_ASSERT( data != NULL ); ++ ++ pthread_mutex_lock( &data->lock ); ++ ++ pthread_cleanup_push( render_cleanup, thiz ); ++ ++ while (!data->destination) { ++ pthread_cond_wait( &data->cond, &data->lock ); ++ } ++ ++ dst_data = (IDirectFBSurface_data*) data->destination->priv; ++ D_ASSERT( dst_data != NULL ); ++ ++ dst_surface = dst_data->surface; ++ D_ASSERT( dst_surface != NULL ); ++ ++ res = data->destination->GetPixelFormat( data->destination, &format ); ++ D_ASSERT( res == DFB_OK ); ++ ++ /* as long as we haven't finished decoding we are busy */ ++ data->thread_res = DFB_BUSY; ++ ++ res = JPEG_RenderTo( data, dst_surface, format, &data->rect, &data->clip ); ++ ++ pthread_cleanup_pop( 1 ); ++ ++ /* in case we exit normally, apply the real return value */ ++ data->thread_res = res; ++ ++ return NULL; ++} ++ ++ ++#if defined(JPEG_PROVIDER_USE_MME) ++static DFBResult ++fetch_data( IDirectFBDataBuffer *buffer, ++ MME_DataBuffer_t *dbuf, ++ int len ) ++{ ++ dbuf->ScatterPages_p[0].BytesUsed = 0; ++ dbuf->ScatterPages_p[0].FlagsIn = 0; ++ dbuf->ScatterPages_p[0].FlagsOut = 0; ++ ++ return buffer_to_ptr_copy( buffer, dbuf->ScatterPages_p[0].Page_p, len ); ++} ++ ++ ++static void ++TransformerCallback( MME_Event_t Event, ++ MME_Command_t *CallbackData, ++ void *UserData ) ++{ ++ const JPEGDEC_TransformReturnParams_t *transform_result = ++ CallbackData->CmdStatus.AdditionalInfo_p; ++// const JPEGDECHW_VideoDecodeReturnParams_t *transform_result_hw = ++// CallbackData->CmdStatus.AdditionalInfo_p; ++ struct _MMECommon * const mme = (struct _MMECommon *) UserData; ++ IDirectFBImageProvider_JPEG_data * const jpeg = ++ container_of( mme, IDirectFBImageProvider_JPEG_data, common ); ++ ++/* if (CallbackData->CmdStatus.AdditionalInfo_p == &jpeg->hw_return_params) { ++ transform_result_hw = CallbackData->CmdStatus.AdditionalInfo_p; ++ transform_result = NULL; ++ } else */ { ++ transform_result = CallbackData->CmdStatus.AdditionalInfo_p; ++// transform_result_hw = NULL; ++ } ++ ++ if (!mme->name_set) { ++ char name[25]; ++ snprintf( name, sizeof(name), ++ "MME (%s)", mme->transformer_name ); ++ direct_thread_set_name( name ); ++ mme->name_set = true; ++ } ++ ++ D_DEBUG_AT( JPEG_MME, ++ "%sTransformerCallback: Event: %d: (%s)%s\n", ++ RED, Event, get_mme_event_string( Event ), BLACK ); ++ D_DEBUG_AT( JPEG_MME, ++ " -> CallbackData->CmdStatus.State: %d (%s)\n", ++ CallbackData->CmdStatus.State, ++ get_mme_state_string( CallbackData->CmdStatus.State ) ); ++ D_DEBUG_AT( JPEG_MME, ++ " -> CallbackData->CmdStatus.CmdId: %u (%.8x)\n", ++ CallbackData->CmdStatus.CmdId, ++ CallbackData->CmdStatus.CmdId ); ++ D_DEBUG_AT( JPEG_MME, ++ " -> CallbackData->CmdStatus.AdditionalInfoSize: %u\n", ++ CallbackData->CmdStatus.AdditionalInfoSize ); ++ D_DEBUG_AT( JPEG_MME, ++ " -> mme->decode_success: %d\n", ++ mme->decode_success ); ++ ++ switch (Event) { ++ case MME_COMMAND_COMPLETED_EVT: ++ pthread_mutex_lock( &mme->pending_commands_lock ); ++ direct_hash_remove( mme->pending_commands, ++ CallbackData->CmdStatus.CmdId ); ++ if (likely (CallbackData->CmdStatus.CmdId != mme->TransformCommand.CmdStatus.CmdId)) ++ --mme->n_pending_buffers; ++ pthread_mutex_unlock( &mme->pending_commands_lock ); ++ ++ switch (CallbackData->CmdStatus.State) { ++ case MME_COMMAND_COMPLETED: ++ if (unlikely (CallbackData->CmdStatus.CmdId ++ == mme->TransformCommand.CmdStatus.CmdId)) { ++ deb_gettimeofday( &mme->endtime, NULL ); ++ deb_timersub( &mme->endtime, &mme->starttime, ++ &mme->endtime ); ++ D_DEBUG_AT( JPEG_TIME, " -> total time %lu.%06lu\n", ++ mme->endtime.tv_sec, mme->endtime.tv_usec ); ++ ++ /* This info is available as data->ReturnParams. too! ++ mme->decoded_bytes = (unsigned int) transform_result->bytes_written; ++ mme->decoded_height = (int) transform_result->decodedImageHeight; ++ mme->decoded_width = (int) transform_result->decodedImageWidth; ++ */ ++ ++ if (transform_result) { ++ D_DEBUG_AT( JPEG_MME, " -> expanded bytes: %u\n", ++ transform_result->bytes_written ); ++ D_DEBUG_AT( JPEG_MME, " -> decoded w/h: %dx%d\n", ++ transform_result->decodedImageWidth, ++ transform_result->decodedImageHeight ); ++ ++ if (jpeg->progressive_mode) { ++ mme->width = transform_result->decodedImageWidth; ++ mme->height = transform_result->decodedImageHeight; ++ } ++ ++ if (transform_result->Total_cycle) ++ D_DEBUG_AT( JPEG_MME, ++ " -> cycles: total/dmiss/imiss: %u/%u/%u\n", ++ transform_result->Total_cycle, ++ transform_result->DMiss_Cycle, ++ transform_result->IMiss_Cycle ); ++ D_DEBUG_AT( JPEG_MME, ++ " -> JPEG result code: %d (%s)\n", ++ transform_result->ErrorType, ++ get_jpeg_error_string( transform_result->ErrorType ) ); ++ } /* else { ++ D_DEBUG_AT( JPEG_MME, ++ " -> cycles/dmiss/imiss: %u/%u/%u\n", ++ transform_result_hw->pm_cycles, ++ transform_result_hw->pm_dmiss, ++ transform_result_hw->pm_imiss ); ++ D_DEBUG_AT( JPEG_MME, ++ " -> bundles/prefetches: %u/%u\n", ++ transform_result_hw->pm_bundles, ++ transform_result_hw->pm_pft ); ++ ++ D_DEBUG_AT( JPEG_MME, ++ " -> JPEGHW result code: %d (%s)\n", ++ transform_result_hw->ErrorCode, ++ get_jpeghw_error_string( transform_result_hw->ErrorCode ) ); ++ } ++*/ ++ mme->decode_success = 1; ++ sema_signal_event( &mme->decode_event ); ++ ++ /* in case of bogus data (too much), abort pending data ++ buffers */ ++ abort_transformer( mme ); ++ } else { ++ /* buffer completed */ ++ struct _MMEHelper_buffer *buf = ++ container_of( CallbackData->DataBuffers_p, ++ struct _MMEHelper_buffer, buffer ); ++ ++ D_DEBUG_AT( JPEG_MME, ++ " -> buffer %p completed (container @ %p)\n", ++ CallbackData->DataBuffers_p[0], buf ); ++ ++ sema_signal_event( &buf->sema ); ++ } ++ break; /* MME_COMMAND_COMPLETED */ ++ ++ case MME_COMMAND_FAILED: ++ D_WARN( "(%5d) %s: command %u (%.8x) failed: error %d (%s)", ++ direct_gettid(), mme->name, ++ CallbackData->CmdStatus.CmdId, ++ CallbackData->CmdStatus.CmdId, ++ CallbackData->CmdStatus.Error, ++ get_mme_error_string( CallbackData->CmdStatus.Error ) ); ++ ++ if (likely (CallbackData->CmdStatus.CmdId ++ == mme->TransformCommand.CmdStatus.CmdId)) { ++ /* transform command failed */ ++ D_WARN( "(%5d) %s: jpeg failure code: %d (%s)", ++ direct_gettid(), mme->name, ++ transform_result->ErrorType, ++ get_jpeg_error_string( transform_result->ErrorType ) ); ++ switch (transform_result->ErrorType) { ++ case UNSUPPORTED_COLORSPACE: ++ case UNABLE_ALLOCATE_MEMORY: ++ case UNSUPPORTED_SCALING: ++ case INSUFFICIENT_OUTPUTBUFFER_SIZE: ++ /* the transformer doesn't support this, but pure ++ libjpeg should. */ ++ mme->decode_success = -1; ++ break; ++ ++ case UNSUPPORTED_ROTATION_ANGLE: ++ default: ++ /* fake a success, there's no point in retrying ++ libjpeg, as it already failed via MME. */ ++ mme->decode_success = 1; ++ D_DEBUG_AT( JPEG_MME, " -> faking success\n" ); ++ break; ++ } ++ ++ sema_signal_event( &mme->decode_event ); ++ } else { ++ /* buffer failed */ ++ struct _MMEHelper_buffer *buf = ++ container_of( CallbackData->DataBuffers_p, ++ struct _MMEHelper_buffer, buffer ); ++ if (mme->decode_success == 0) ++ /* only if we didn't succeed yet */ ++ mme->decode_success = -1; ++ sema_signal_event( &buf->sema ); ++ } ++ break; /* MME_COMMAND_FAILED */ ++ ++ case MME_COMMAND_IDLE: ++ case MME_COMMAND_PENDING: ++ case MME_COMMAND_EXECUTING: ++ default: ++ D_WARN( "(%5d) %s: command %u (%.8x) completed in unknown state: %d (%s)", ++ direct_gettid(), mme->name, ++ CallbackData->CmdStatus.CmdId, ++ CallbackData->CmdStatus.CmdId, ++ CallbackData->CmdStatus.State, ++ get_mme_state_string( CallbackData->CmdStatus.State ) ); ++ break; ++ } ++ break; /* MME_COMMAND_COMPLETED_EVT */ ++ ++ case MME_DATA_UNDERFLOW_EVT: ++ /* because of the way the transformer works (and how we communicate ++ with it), we get exactly one underflow event on startup */ ++ D_DEBUG_AT( JPEG_MME, ++ " -> %sdata underflow on command %u (%.8x)\n", ++ (mme->n_underflows == 0) ? "(anticipated) " : "", ++ CallbackData->CmdStatus.CmdId, ++ CallbackData->CmdStatus.CmdId); ++ if (++mme->n_underflows > 1) { ++ /* check if the IDirectFBDataBuffer definitely(!) hit an EOF ++ and we have no buffers queued */ ++ bool end_of_data; ++ char tmp; ++ pthread_mutex_lock( &mme->pending_commands_lock ); ++ DFBResult has_data = mme->base.buffer->PeekData( mme->base.buffer, ++ 1, 0, ++ &tmp, NULL ); ++ /* n_pending_buffers is checked to be == 0 because the ++ TransformCommand itself is not stored in there. */ ++ end_of_data = (has_data == DFB_EOF ++ && mme->n_pending_buffers == 0); ++ pthread_mutex_unlock( &mme->pending_commands_lock ); ++ ++ /* if so, signal completion */ ++ if (end_of_data) { ++ D_DEBUG_AT( JPEG_MME, ++ " -> no more data available, signalling fail\n" ); ++ mme->decode_success = -2; ++ sema_signal_event( &mme->decode_event ); ++ } ++ } ++ break; /* MME_DATA_UNDERFLOW_EVT */ ++ ++ case MME_NOT_ENOUGH_MEMORY_EVT: ++ case MME_NEW_COMMAND_EVT: ++ default: ++ D_WARN( "(%5d) %s: unhandled event %d (%s) occured on command %u (%.8x)", ++ direct_gettid(), mme->name, Event, ++ get_mme_event_string( Event ), ++ CallbackData->CmdStatus.CmdId, ++ CallbackData->CmdStatus.CmdId ); ++ ++ D_WARN( "(%5d) %s: CallbackData->CmdStatus.AdditionalInfoSize: %u", ++ direct_gettid(), mme->name, ++ CallbackData->CmdStatus.AdditionalInfoSize ); ++ ++ if (CallbackData->CmdStatus.CmdId == mme->TransformCommand.CmdStatus.CmdId) { ++ if (transform_result) { ++ D_WARN( "(%5d) %s: transform_result->bytes_written: %u", ++ direct_gettid(), mme->name, ++ transform_result->bytes_written ); ++ D_WARN( "(%5d) %s: transform_result->decodedImageHeight: %d", ++ direct_gettid(), mme->name, ++ transform_result->decodedImageHeight ); ++ D_WARN( "(%5d) %s: transform_result->decodedImageWidth: %d", ++ direct_gettid(), mme->name, ++ transform_result->decodedImageWidth ); ++ if (transform_result->Total_cycle) ++ D_WARN( "(%5d) %s: transform_result->cycles: total/dmiss/imiss: %u/%u/%u\n", ++ direct_gettid(), mme->name, ++ transform_result->Total_cycle, ++ transform_result->DMiss_Cycle, ++ transform_result->IMiss_Cycle ); ++ D_WARN( "(%5d) %s: result code: %d (%s)\n", ++ direct_gettid(), mme->name, ++ transform_result->ErrorType, ++ get_jpeg_error_string( transform_result->ErrorType ) ); ++ } /* else if (transform_result_hw) { ++ D_WARN( "(%5d) %s: transform_result->cycles/dmiss/imiss: %u/%u/%u\n", ++ direct_gettid(), mme->name, ++ transform_result_hw->pm_cycles, ++ transform_result_hw->pm_dmiss, ++ transform_result_hw->pm_imiss ); ++ D_WARN( "(%5d) %s: transform_result->bundles/prefetches: %u/%u\n", ++ direct_gettid(), mme->name, ++ transform_result_hw->pm_bundles, ++ transform_result_hw->pm_pft ); ++ ++ D_WARN( "(%5d) %s: transform_result->JPEGHW result code: %d (%s)\n", ++ direct_gettid(), mme->name, ++ transform_result_hw->ErrorCode, ++ get_jpeghw_error_string( transform_result_hw->ErrorCode ) ); ++ } ++*/ ++ } ++ break; ++ } ++} ++ ++#if 0 ++static void ++TransformerCallback2( MME_Event_t Event, ++ MME_Command_t *CallbackData, ++ void *UserData ) ++{ ++ const JPEGDECHW_VideoDecodeReturnParams_t * const transform_result_hw = ++ CallbackData->CmdStatus.AdditionalInfo_p; ++ struct _MMECommon * const mme = (struct _MMECommon *) UserData; ++ ++ if (!mme->name_set) { ++ direct_thread_set_name( "MME (hwjpeg)" ); ++ mme->name_set = true; ++ } ++ ++ D_DEBUG_AT( JPEG_MME, ++ "%sTransformerCallback2: Event: %d: (%s)%s\n", ++ RED, Event, get_mme_event_string( Event ), BLACK ); ++ D_DEBUG_AT( JPEG_MME, ++ " -> CallbackData->CmdStatus.State: %d (%s)\n", ++ CallbackData->CmdStatus.State, ++ get_mme_state_string( CallbackData->CmdStatus.State ) ); ++ D_DEBUG_AT( JPEG_MME, ++ " -> CallbackData->CmdStatus.CmdId: %u (%.8x)\n", ++ CallbackData->CmdStatus.CmdId, ++ CallbackData->CmdStatus.CmdId ); ++ D_DEBUG_AT( JPEG_MME, ++ " -> CallbackData->CmdStatus.AdditionalInfoSize: %u\n", ++ CallbackData->CmdStatus.AdditionalInfoSize ); ++ D_DEBUG_AT( JPEG_MME, ++ " -> mme->decode_success: %d\n", mme->decode_success ); ++} ++#endif ++ ++ ++/* Pre-Scaling Calculations for JPEG Hardware Scaling ++ * These functions should be used anywhere where SOURCE width and height are ++ referenced */ ++static unsigned int ++pre_scale_value( const IDirectFBImageProvider_JPEG_data *data, ++ const DFBRectangle *dest_rect ) ++{ ++ unsigned int scale; ++ ++ D_ASSERT( data != NULL ); ++ ++#ifdef PRE_SCALE_SPEED_SPACE_OPTIMISED ++ /* Speed and Space */ ++ if (data->common.width <= dest_rect->w || data->common.height <= dest_rect->h) ++ scale = 1; ++ else if ((data->common.width / 2 <= dest_rect->w) && (data->common.height / 2 <= dest_rect->h)) ++ scale = 2; ++ else if ((data->common.width / 4 <= dest_rect->w) && (data->common.height / 4 <= dest_rect->h)) ++ scale = 4; ++ else if ((data->common.width / 8 <= dest_rect->w) && (data->common.height / 8 <= dest_rect->h)) ++ scale = 8; ++ else ++ scale = 1; ++#endif ++ ++#ifdef PRE_SCALE_QUALITY_OPTIMISED ++ /* Quality */ ++ if ((data->common.width / 8 >= dest_rect->w) && (data->common.height / 8 >= dest_rect->h)) ++ scale = 8; ++ else if ((data->common.width / 4 >= dest_rect->w) && (data->common.height / 4 >= dest_rect->h)) ++ scale = 4; ++ else if ((data->common.width / 2 >= dest_rect->w) && (data->common.height / 2 >= dest_rect->h)) ++ scale = 2; ++ else ++ scale = 1; ++#endif ++ ++#if !defined(PRE_SCALE_SPEED_SPACE_OPTIMISED) && !defined(PRE_SCALE_QUALITY_OPTIMISED) ++ scale = 1; ++#endif ++ ++ return scale; ++} ++ ++static inline unsigned int ++pre_scaled_width( const IDirectFBImageProvider_JPEG_data *data, ++ const DFBRectangle *dest_rect ) ++{ ++ D_ASSERT( data != NULL ); ++ ++ unsigned int w = (data->common.width + 15) & ~15; /* Macro Block Rounding */ ++ return w / pre_scale_value( data, dest_rect ); ++} ++ ++static inline unsigned int ++pre_scaled_height( const IDirectFBImageProvider_JPEG_data *data, ++ const DFBRectangle *dest_rect ) ++{ ++ D_ASSERT( data != NULL ); ++ ++ unsigned int h = (data->common.height + 15) & ~15; /* Macro Block Rounding */ ++ return h / pre_scale_value( data, dest_rect ); ++} ++ ++/* warning: MME_AbortCommand() works only for the MME_TRANSFORM command; ++ individual buffers can be aborted, too, but MME_TermTransformer() will ++ not work afterwards anymore! */ ++static bool ++pending_fe_func( DirectHash *hash, ++ unsigned long key, ++ void *value, ++ void *ctx ) ++{ ++ struct _MMECommon * const mme = ctx; ++ MME_CommandId_t CmdId = key; ++ ++ if (key != mme->TransformCommand.CmdStatus.CmdId) { ++ if (direct_hash_lookup( hash, ++ mme->TransformCommand.CmdStatus.CmdId )) ++ D_WARN( "(%5d) aborting MME command %u (%.8x) can lead to a " ++ "crash somewhere in the JPEG transformer!", ++ direct_gettid(), CmdId, CmdId ); ++ } else ++ D_DEBUG_AT( JPEG_MME, ++ "aborting (main transform) command %u (%.8x)\n", ++ CmdId, CmdId ); ++ ++ MME_ERROR res = MME_AbortCommand( mme->Handle, CmdId ); ++ if (res != MME_SUCCESS) ++ D_WARN( "(%5d) MME_AbortCommand(%x, %.8x) for %s failed: %d (%s)\n", ++ direct_gettid(), mme->Handle, CmdId, ++ mme->name, res, get_mme_error_string( res ) ); ++ ++ /* continue iterating */ ++ return true; ++} ++ ++static DFBResult ++abort_transformer( struct _MMECommon * const mme ) ++{ ++ if (!mme) ++ return DFB_THIZNULL; ++ ++ /* FIXME: what about locking? */ ++ direct_hash_iterate( mme->pending_commands, ++ pending_fe_func, ++ mme ); ++ ++ return DFB_OK; ++} ++ ++ ++static void ++_imageprovider_update_transform_params( struct _MMECommon * const mme, ++ void * const params, ++ const CoreSurfaceBufferLock * const lock ) ++{ ++ IDirectFBImageProvider_JPEG_data * const data = ++ container_of( mme, IDirectFBImageProvider_JPEG_data, common ); ++ ++ data->OutputParams.outputSettings.Pitch = lock->pitch; ++ data->OutputParams.outputSettings.ROTATEFLAG |= 0x80000000; ++} ++ ++/* ++ * Set up JPEG transform command ++ * Establish Decode Parameters, ++ * and prepare destination surface ++ * ++ */ ++static DFBResult ++jpeg_start_transformer( IDirectFBImageProvider_JPEG_data *data, ++ CoreSurface *dst_surface, ++ CoreSurfaceBufferLock *lock ) ++{ ++ DFBResult res; ++ MME_ERROR mme_res; ++ ++ /* If height and width are NOT values divisible by 16 - then decode will ++ not work as expected. */ ++ data->OutputParams.outputSettings.xvalue0 = 0; ++ data->OutputParams.outputSettings.xvalue1 = 0; ++ data->OutputParams.outputSettings.yvalue0 = 0; ++ data->OutputParams.outputSettings.yvalue1 = 0; ++ ++ data->OutputParams.outputSettings.outputWidth = 0; //Buffersize used to prevent bufferoverflows; ++ data->OutputParams.outputSettings.outputHeight = 0; //Buffersize used to prevent bufferoverflows; ++ data->OutputParams.outputSettings.ROTATEFLAG = 0; ++ data->OutputParams.outputSettings.Rotatedegree = 0; ++ data->OutputParams.outputSettings.HorizantalFlip = 0; ++ data->OutputParams.outputSettings.VerticalFlip = 0; ++ ++ res = _mme_helper_start_transformer_core( &data->common, ++ sizeof(data->ReturnParams), ++ &data->ReturnParams, ++ sizeof(data->OutputParams), ++ &data->OutputParams, ++ dst_surface, lock ); ++ if (res != DFB_OK) ++ return res; ++ ++ _imageprovider_update_transform_params( &data->common, ++ &data->OutputParams, lock ); ++ ++ /* if pitch != width - we'll have issues with the hardware decode */ ++ /* FIXME: the comment makes no sense. And the D_ASSUME() does sth ++ different... */ ++ D_ASSUME( lock->pitch != dst_surface->config.size.w ); ++ ++ D_DEBUG_AT( MME_DEBUG_DOMAIN, "issuing MME_TRANSFORM\n" ); ++ ++ /* lock access to hash, because otherwise the callback could be called ++ before we've had a chance to put the command id into the hash */ ++ D_ASSERT( &data->common.pending_commands != NULL ); ++ pthread_mutex_lock( &data->common.pending_commands_lock ); ++ ++ mme_res = MME_SendCommand( data->common.Handle, ++ &data->common.TransformCommand ); ++ if (mme_res != MME_SUCCESS) { ++ pthread_mutex_unlock( &data->common.pending_commands_lock ); ++ ++ D_WARN( "(%5d) %s: starting transformer failed: %d (%s)", ++ direct_gettid(), data->common.name, ++ mme_res, get_mme_error_string( mme_res ) ); ++ ++ dfb_surface_unlock_buffer( dst_surface, lock ); ++ ++ D_FREE( data->common.OutDataBuffers ); ++ data->common.OutDataBuffers = NULL; ++ ++ return DFB_FAILURE; ++ } ++ ++ direct_hash_insert( data->common.pending_commands, ++ data->common.TransformCommand.CmdStatus.CmdId, ++ (void *) 1 ); ++ D_DEBUG_AT( JPEG_MME, "sent packet's CmdId is %u (%.8x)\n", ++ data->common.TransformCommand.CmdStatus.CmdId, ++ data->common.TransformCommand.CmdStatus.CmdId ); ++ ++ deb_gettimeofday( &data->common.starttime, NULL ); ++ ++ pthread_mutex_unlock( &data->common.pending_commands_lock ); ++ ++ return DFB_OK; ++} ++ ++#if 0 ++#include <../gfxdrivers/stgfx/stgfx.h> ++#include <../gfxdrivers/stgfx2/stm_gfxdriver.h> ++static STMFB_GFXMEMORY_PARTITION ++bdisp_surface_pool_get_partition( const CoreSurfacePool * const pool ) ++{ ++ unsigned i; ++ ++ switch (dfb_system_get_accelerator()) { ++ case FB_ACCEL_ST_GAMMA: ++ case FB_ACCEL_ST_BDISP: ++ { ++ const STGFXDeviceData * const stdev = dfb_gfxcard_get_device_data(); ++ for (i = 0; i < D_ARRAY_SIZE(stdev->aux_pools); ++i) ++ if (stdev->aux_pools[i] == pool) ++ return STMFBGP_GFX0 + i; ++ } ++ break; ++ ++ case FB_ACCEL_ST_BDISP_USER: ++ { ++ const STGFX2DeviceData * const stdev = dfb_gfxcard_get_device_data(); ++ for (i = 0; i < D_ARRAY_SIZE(stdev->aux_pools); ++i) ++ if (stdev->aux_pools[i] == pool) ++ return STMFBGP_GFX0 + i; ++ } ++ break; ++ ++ default: ++ return STMFBGP_FRAMEBUFFER; ++ } ++ ++ return STMFBGP_FRAMEBUFFER; ++} ++#endif ++ ++#if 0 ++static DFBResult ++jpeg_start_transformer2( IDirectFBImageProvider_JPEG_data *data, ++ CoreSurface *dst_surface, ++ CoreSurfaceBufferLock *lock ) ++{ ++ DFBResult res; ++ CoreSurfaceBufferLock raw_lock; ++ CoreSurfaceBufferLock chr_lock; ++ ++ ++ /* src surface */ ++ CoreSurface *raw_surface; ++ ++ /* FIXME: this is BAD (tm) -> think streaming media! */ ++ data->common.buffer->SeekTo( data->common.buffer, 0 ); ++ /* find out the length of the buffer */ ++ unsigned int src_bytes; ++ data->common.buffer->GetLength( data->common.buffer, &src_bytes ); ++ ++ { ++ CoreSurfaceConfig config = { .size.w = src_bytes, ++ .size.h = 1 }; ++ /* create temporary surface to store the compressed data in. */ ++ config.flags = CSCONF_SIZE | CSCONF_FORMAT | CSCONF_CAPS; ++ config.format = DSPF_LUT8; ++ config.caps = DSCAPS_VIDEOONLY; ++ #ifdef DIRECT_BUILD_DEBUG ++ config.caps |= DSCAPS_SHARED; ++ #endif ++ if ((res = dfb_surface_create( data->common.core, ++ &config, ++ CSTF_NONE, ++ 0, ++ NULL, ++ &raw_surface )) != DFB_OK) ++ goto out1; ++ if ((res = dfb_surface_lock_buffer( raw_surface, CSBR_BACK, CSAID_CPU, ++ CSAF_WRITE, &raw_lock )) != DFB_OK) ++ goto out2; ++ } ++ ++ { ++ unsigned int sz; ++ u8 *addr = raw_lock.addr; ++ res = data->common.buffer->GetData( data->common.buffer, ++ src_bytes, addr, &sz ); ++ if (sz != src_bytes) ++ goto out3; ++ printf( "src data @ %.8lx\n", lock->phys ); ++ } ++ /* FIXME: this is BAD (tm) -> think streaming media! */ ++ data->common.buffer->SeekTo( data->common.buffer, 0 ); ++ res = dfb_surface_unlock_buffer( raw_surface, &raw_lock ); ++ ++ ++ CoreSurface *chr_surface; ++ { ++ CoreSurfaceConfig config = { .size.w = data->common.width, ++ .size.h = data->common.height }; ++ config.size.h += 2; ++ /* create temporary surface to store the compressed data in. */ ++ config.flags = CSCONF_SIZE | CSCONF_FORMAT | CSCONF_COLORSPACE | CSCONF_CAPS; ++ config.format = DSPF_ARGB; ++ config.caps = DSCAPS_VIDEOONLY; ++ #ifdef DIRECT_BUILD_DEBUG ++ config.caps |= DSCAPS_SHARED; ++ #endif ++ config.colorspace = DSCS_RGB; ++ if ((res = dfb_surface_create( data->common.core, ++ &config, ++ CSTF_NONE, ++ 0, ++ NULL, ++ &chr_surface )) != DFB_OK) ++ goto out4; ++ } ++ ++ ++ res = dfb_surface_lock_buffer( raw_surface, ++ CSBR_FRONT, CSAID_ACCEL0, CSAF_READ, ++ &raw_lock ); ++ res = dfb_surface_lock_buffer( data->common.decode_surface, ++ CSBR_BACK, CSAID_ACCEL0, CSAF_WRITE, ++ lock ); ++ res = dfb_surface_lock_buffer( chr_surface, ++ CSBR_BACK, CSAID_ACCEL0, CSAF_WRITE, ++ &chr_lock ); ++ ++ /* should be aligned on 256byte boundary */ ++ D_ASSUME( (chr_lock.phys & 0xff) == 0 ); ++ D_ASSUME( (lock->phys & 0xff) == 0 ); ++ printf( "raw/dst/chr phys: 0x%.8lx 0x%.8lx 0x%.8lx\n", ++ raw_lock.phys, lock->phys, chr_lock.phys ); ++ ++ u32 raw_phys = raw_lock.phys; ++ u32 dst_phys = (lock->phys + 255) & 0xffffff00; ++ printf( "dst_phys %.8x\n", dst_phys ); ++ u32 chr_phys = (chr_lock.phys + 255) & 0xffffff00; ++ printf( "chr_phys %.8x\n", chr_phys ); ++ ++ raw_phys += 0x10000000; ++ dst_phys += 0x10000000; ++ chr_phys += 0x10000000; ++ ++ /* If height and width are NOT values divisible by 16 - then decode will ++ not work as expected. */ ++ data->hw_decode_params.PictureStartAddr_p = (void *) raw_phys; ++ data->hw_decode_params.PictureEndAddr_p = (void *) (raw_phys + src_bytes); ++ data->hw_decode_params.DecodedBufferAddr.Luma_p = (void *) dst_phys; ++ data->hw_decode_params.DecodedBufferAddr.Chroma_p = (void *) chr_phys; ++ data->hw_decode_params.DecodedBufferAddr.LumaDecimated_p = (void *) (dst_phys + 512); ++ data->hw_decode_params.DecodedBufferAddr.ChromaDecimated_p = (void *) (chr_phys + 512); ++ data->hw_decode_params.MainAuxEnable = JPEGDECHW_MAINOUT_EN; ++ data->hw_decode_params.HorizontalDecimationFactor = JPEGDECHW_HDEC_1; ++ data->hw_decode_params.VerticalDecimationFactor = JPEGDECHW_VDEC_1; ++ data->hw_decode_params.xvalue0 = 0; ++ data->hw_decode_params.yvalue0 = 0; ++ data->hw_decode_params.xvalue1 = 0; ++ data->hw_decode_params.yvalue1 = 0; ++ data->hw_decode_params.DecodingMode = JPEGDECHW_NORMAL_DECODE; ++ data->hw_decode_params.AdditionalFlags = JPEGDECHW_ADDITIONAL_FLAG_NONE; ++ ++ data->hw_decode_params.MainAuxEnable = JPEGDECHW_AUXOUT_EN; ++ data->hw_decode_params.AdditionalFlags = 64; /* raster */ ++ ++ /* set up the transform command */ ++ data->common.TransformCommand.StructSize = sizeof(MME_Command_t); ++ data->common.TransformCommand.CmdCode = MME_TRANSFORM; ++ data->common.TransformCommand.CmdEnd = MME_COMMAND_END_RETURN_NOTIFY; ++ data->common.TransformCommand.DueTime = (MME_Time_t) 0; ++ data->common.TransformCommand.NumberInputBuffers = 0; ++ data->common.TransformCommand.NumberOutputBuffers = 0; ++ data->common.TransformCommand.DataBuffers_p = NULL; ++ data->common.TransformCommand.ParamSize = sizeof(data->hw_decode_params); ++ data->common.TransformCommand.Param_p = &data->hw_decode_params; ++ ++ /* init the transform command */ ++ memset( &(data->common.TransformCommand.CmdStatus), 0, sizeof(MME_CommandStatus_t) ); ++ data->common.TransformCommand.CmdStatus.AdditionalInfoSize = sizeof(data->hw_return_params); ++ data->common.TransformCommand.CmdStatus.AdditionalInfo_p = &data->hw_return_params; ++ ++ D_DEBUG_AT( MME_DEBUG_DOMAIN, "issuing MME_TRANSFORM\n" ); ++ ++ /* lock access to hash, because otherwise the callback could be called ++ before we've had a chance to put the command id into the hash */ ++ D_ASSERT( &data->common.pending_commands != NULL ); ++ pthread_mutex_lock( &data->common.pending_commands_lock ); ++ ++ res = MME_SendCommand( data->common.Handle, ++ &data->common.TransformCommand ); ++ if (res != MME_SUCCESS) { ++ pthread_mutex_unlock( &data->common.pending_commands_lock ); ++ ++ D_WARN( "(%5d) %s: starting transformer failed: %d (%s)", ++ direct_gettid(), data->common.name, ++ res, get_mme_error_string( res ) ); ++ ++ res = DFB_FAILURE; ++ ++ goto out5; ++ } ++ ++ direct_hash_insert( data->common.pending_commands, ++ data->common.TransformCommand.CmdStatus.CmdId, ++ (void *) 1 ); ++ D_DEBUG_AT( JPEG_MME, "sent packet's CmdId is %u (%.8x)\n", ++ data->common.TransformCommand.CmdStatus.CmdId, ++ data->common.TransformCommand.CmdStatus.CmdId ); ++ ++ deb_gettimeofday( &data->common.starttime, NULL ); ++ ++ pthread_mutex_unlock( &data->common.pending_commands_lock ); ++ ++ ++ /* wait until the decode is complete (or until the abort was ++ acknowledged) */ ++ D_DEBUG_AT( JPEG_MME, "waiting for completion\n" ); ++ while ((sema_wait_event( &data->common.decode_event ) == -1) ++ && errno == EINTR) ++ ; ++ if (data->common.decode_success != 1) ++ res = DFB_FAILURE; ++ ++ ++ mme_helper_deinit_transformer( &data->common ); ++ ++ ++out5: ++ dfb_surface_unlock_buffer( chr_surface, &chr_lock ); ++ dfb_surface_unref( chr_surface ); ++ dfb_surface_unlock_buffer( data->common.decode_surface, lock ); ++ ++ ++out4: ++out3: ++ dfb_surface_unlock_buffer( raw_surface, &raw_lock ); ++out2: ++ dfb_surface_unref( raw_surface ); ++out1: ++ return res; ++} ++#endif ++ ++ ++static DFBResult ++JPEG_HardwareRenderTo( IDirectFBImageProvider_JPEG_data *data, ++ CoreSurface *dst_surface, ++ DFBSurfacePixelFormat format, ++ DFBRectangle *rect, ++ const DFBRegion *clip ) ++{ ++ DFBResult dfbret = dfbret; ++ CoreSurfaceBufferLock lock; ++ ++ D_ASSERT( data != NULL ); ++ D_ASSERT( dst_surface != NULL ); ++ D_ASSERT( rect != NULL ); ++ D_ASSERT( clip != NULL ); ++ ++ CoreSurfaceConfig config; ++ ++ config.size.w = pre_scaled_width( data, rect ); ++ config.size.h = pre_scaled_height( data, rect ); ++ ++ if (unlikely (data->progressive_mode)) { ++ int src_width = (data->common.width + 15) & ~15; ++ int src_height = (data->common.height + 15) & ~15; ++ int totalsize = data->num_components * src_width * src_height; ++ int scale; ++ ++#define MAX_MEMORY_FOR_PROGRESSIVE_IMAGE (1 * 1024 * 1024) ++ if (totalsize < MAX_MEMORY_FOR_PROGRESSIVE_IMAGE) ++ scale = 1; ++ else if (totalsize/4 < MAX_MEMORY_FOR_PROGRESSIVE_IMAGE) ++ scale = 2; ++ else if (totalsize/16 < MAX_MEMORY_FOR_PROGRESSIVE_IMAGE) ++ scale = 4; ++ else if (totalsize/64 < MAX_MEMORY_FOR_PROGRESSIVE_IMAGE) ++ scale = 8; ++ else ++ return DFB_UNSUPPORTED; ++ ++ data->common.width /= scale; ++ data->common.height /= scale; ++// data->common.width = src_width / scale; ++// data->common.height = src_height / scale; ++ ++ config.size.w = src_width / scale; ++ config.size.h = src_height / scale; ++ } else { ++ int pre_scale = pre_scale_value( data, rect ); ++ ++ config.size.w = pre_scaled_width( data, rect ); ++ config.size.h = pre_scaled_height( data, rect ); ++ data->common.width /= pre_scale; ++ data->common.height /= pre_scale; ++ } ++ ++ /* FIXME: check if the image is big enough to warrant a HW decode */ ++ if (!data->common.decode_surface ++ || config.size.w != data->common.decode_surface->config.size.w ++ || config.size.h != data->common.decode_surface->config.size.h) { ++ /* create destination surface to MME-decode the image onto before ++ stretchblit ... and if we can't create a surface in video memory ++ then we can't blit */ ++ /* Also, decide on the decode size. ++ Limitations are: ++ - closest match to a 1/1 1/2 1/4 1/8 reduction ++ - AND a 16 pixel macroblock size. */ ++ config.flags = CSCONF_SIZE | CSCONF_FORMAT | CSCONF_COLORSPACE | CSCONF_CAPS; ++ config.format = DSPF_UYVY; ++ config.colorspace = DSCS_BT601_FULLRANGE; ++#ifdef __SH4__ ++ config.caps = DSCAPS_VIDEOONLY; ++#else ++ config.caps = 0; ++#endif ++ #ifdef DIRECT_BUILD_DEBUG ++ config.caps |= DSCAPS_SHARED; ++ #endif ++ ++ D_DEBUG_AT( JPEG_MME, "%dx%d prescaled to %dx%d\n", ++ rect->w, rect->h, config.size.w, config.size.h ); ++ ++ if (data->common.decode_surface) ++ dfb_surface_unref( data->common.decode_surface ); ++ ++ if (dfb_surface_create( data->common.base.core, ++ &config, ++ CSTF_NONE, ++ 0, ++ NULL, ++ &data->common.decode_surface )) { ++ data->common.decode_surface = NULL; ++ return DFB_NOVIDEOMEMORY; ++ } ++ ++ data->common.decode_success = 0; ++ } ++ ++ if (data->common.decode_success <= 0) { ++ data->common.name = "hwJPEG"; ++ data->common.decode_success = 0; ++ ++#if 0 ++ data->common.name = "hwJPEGHW"; ++ { ++ static const char * const transformers[] = { ++ "JPEG_DECODER_HW1", ++ "JPEG_DECODER_HW0", ++ "JPEG_DECODER_HW4", ++ "JPEG_DECODER_HW3", ++ "JPEG_DECODER_HW2", ++ "JPEG_DECODER_HW", ++ NULL ++ }; ++ unsigned int index; ++ JPEGDECHW_VideoDecodeInitParams_t init; ++ /* we should probably allocate some mme memory 2048*2048 */ ++ init.CircularBufferBeginAddr_p = (JPEGDECHW_CompressedData_t) 0x00000000; ++ init.CircularBufferEndAddr_p = (JPEGDECHW_CompressedData_t) 0xfffffff8; ++// init.CircularBufferBeginAddr_p = 0; ++// init.CircularBufferEndAddr_p = 0; ++ dfbret = mme_helper_init_transformer2( &data->common, transformers, ++ sizeof(init), &init, &index, ++ &TransformerCallback ); ++ if (dfbret != DFB_OK) ++ goto cont; ++ ++ MME_TransformerCapability_t cap; ++ _mme_helper_get_capability( &data->common, ++ transformers[index], &cap ); ++ ++ if (data->flags & DIPFLAGS_BACKGROUND_DECODE) ++ direct_thread_set_name( transformers[index] ); ++ ++ /* store the current data buffer position for software fallback ++ should we not succeed */ ++ unsigned int bufpos; ++ data->common.buffer->GetPosition( data->common.buffer, &bufpos ); ++ ++ sema_init_event( &data->common.decode_event, 0 ); ++ ++ /* Tell the transformer what to do and where to put result. ++ Depending on dst - may need to consider pitch! */ ++ dfbret = jpeg_start_transformer2( data, data->common.decode_surface, ++ &lock ); ++ goto stretch; ++ } ++ ++cont: ; ++#endif ++ ++ static const char * const transformers[] = { ++ JPEGDEC_MME_TRANSFORMER_NAME"0", ++ JPEGDEC_MME_TRANSFORMER_NAME"1", ++ JPEGDEC_MME_TRANSFORMER_NAME"2", ++ JPEGDEC_MME_TRANSFORMER_NAME"3", ++ JPEGDEC_MME_TRANSFORMER_NAME"4", ++ JPEGDEC_MME_TRANSFORMER_NAME, ++ NULL ++ }; ++ unsigned int index; ++ dfbret = mme_helper_init_transformer( &data->common, transformers, ++ 0, NULL, &index ); ++ if (dfbret == DFB_OK) { ++ MME_TransformerCapability_t cap; ++ _mme_helper_get_capability( &data->common, ++ transformers[index], &cap ); ++ ++#if 0 ++ if (cap.Version != 2) { ++ /* incompatible with old transformer, it has just way too ++ many bugs! */ ++ mme_helper_deinit_transformer( &data->common ); ++ dfbret = DFB_FAILURE; ++ continue; ++ } ++ ++ data->common.transformer_name = *transformers[transformer_index]; ++ if (data->flags & DIPFLAGS_BACKGROUND_DECODE) ++ direct_thread_set_name( *transformers[transformer_index] ); ++ ++ break; ++#endif ++ } ++ ++ if (dfbret == DFB_OK) { ++ bool locked = false; ++ ++ data->common.transformer_name = transformers[index]; ++ if (data->flags & DIRENDER_BACKGROUND) ++ direct_thread_set_name( transformers[index] ); ++ ++ /* store the current data buffer position for software ++ fallback should we not succeed */ ++ unsigned int bufpos; ++ data->common.base.buffer->GetPosition( data->common.base.buffer, ++ &bufpos ); ++ ++ sema_init_event( &data->common.decode_event, 0 ); ++ ++ /* Tell the transformer what to do and where to put result. ++ Depending on dst - may need to consider pitch! */ ++ dfbret = jpeg_start_transformer( data, ++ data->common.decode_surface, ++ &lock ); ++ if (dfbret == DFB_OK) { ++ locked = true; ++ ++ D_DEBUG_AT( JPEG_MME, ++ "Transform sent, sending data buffers now\n" ); ++ ++ mme_helper_calculate_packets( &data->common ); ++ dfbret = mme_helper_send_packets( &data->common, -1 ); ++ if (dfbret != DFB_OK) { ++ D_DEBUG_AT( JPEG_MME, ++ "aborting (main) transform command %u (%.8x)\n", ++ data->common.TransformCommand.CmdStatus.CmdId, ++ data->common.TransformCommand.CmdStatus.CmdId ); ++ MME_ERROR res = MME_AbortCommand( data->common.Handle, ++ data->common.TransformCommand.CmdStatus.CmdId ); ++ if (res != MME_SUCCESS) ++ D_WARN( "(%5d) MME_AbortCommand(%x, %.8x) for %s failed: %d (%s)\n", ++ direct_gettid(), data->common.Handle, ++ data->common.TransformCommand.CmdStatus.CmdId, ++ data->common.name, ++ res, get_mme_error_string( res ) ); ++ } ++ ++ /* wait until the decode is complete (or until the abort ++ was acknowledged) */ ++ D_DEBUG_AT( JPEG_MME, "waiting for completion\n" ); ++ while ((sema_wait_event( &data->common.decode_event ) == -1) ++ && errno == EINTR) ++ ; ++ if (data->common.decode_success != 1) ++ dfbret = DFB_FAILURE; ++ } else { ++ if (data->common.decode_success < 0) ++ dfbret = DFB_FAILURE; ++ D_DEBUG_AT( JPEG_MME, "couldn't start transformer\n" ); ++ } ++ ++ /* we always get an underflow on startup at the moment - update ++ the value so only interesting underflow get printed ... */ ++ if (data->common.n_underflows) ++ --data->common.n_underflows; ++ ++ abort_transformer( &data->common ); ++ /* wait till all commands are aborted and acknowledged */ ++ while (data->common.n_pending_buffers ++ || direct_hash_lookup( data->common.pending_commands, ++ data->common.TransformCommand.CmdStatus.CmdId )) ++ usleep( 1 ); ++ ++ mme_helper_deinit_transformer( &data->common ); ++ ++ if (likely (locked)) ++ dfb_surface_unlock_buffer( data->common.decode_surface, ++ &lock ); ++ ++ if (data->common.OutDataBuffers) { ++ D_FREE( data->common.OutDataBuffers ); ++ data->common.OutDataBuffers = NULL; ++ } ++ ++ unsigned int i; ++ for (i = 0; i < D_ARRAY_SIZE(data->common.SendDataBuffers); ++i) { ++ if (data->common.SendDataBuffers[i].buffer) { ++ MME_FreeDataBuffer( data->common.SendDataBuffers[i].buffer ); ++ data->common.SendDataBuffers[i].buffer = NULL; ++ ++ sema_close_event( &data->common.SendDataBuffers[i].sema ); ++ } ++ } ++ ++ sema_close_event( &data->common.decode_event ); ++ ++ data->common.base.buffer->SeekTo( data->common.base.buffer, ++ bufpos ); ++ } else { ++ D_ASSUME( data->common.decode_surface != NULL ); ++ dfb_surface_unref( data->common.decode_surface ); ++ data->common.decode_surface = NULL; ++ } ++ } ++ ++ if (data->common.decode_success == 1) { ++ /* stretch blit the decoded image to the destination surface and ++ size */ ++ mme_helper_stretch_blit( &data->common, data->common.decode_surface, ++ dst_surface, rect ); ++ dfbret = DFB_OK; ++ } else { ++ if (data->common.decode_surface) ++ dfb_surface_unref( data->common.decode_surface ); ++ data->common.decode_surface = NULL; ++ } ++ ++ return dfbret; ++} ++#endif /* JPEG_PROVIDER_USE_MME */ +diff --git a/interfaces/IDirectFBImageProvider/idirectfbimageprovider_jpeg.h b/interfaces/IDirectFBImageProvider/idirectfbimageprovider_jpeg.h +new file mode 100644 +index 0000000..19514d9 +--- /dev/null ++++ b/interfaces/IDirectFBImageProvider/idirectfbimageprovider_jpeg.h +@@ -0,0 +1,113 @@ ++#ifndef __IDIRECTFBIMAGEPROVIDER_JPEG_H__ ++#define __IDIRECTFBIMAGEPROVIDER_JPEG_H__ ++ ++#if defined(JPEG_PROVIDER_USE_MME) ++/* HW Decode Requirements */ ++#include ++#include ++ ++#include ++//#include ++#endif /* JPEG_PROVIDER_USE_MME */ ++ ++/* The following define controls prescaling ++ * ++ * PRE_SCALE_QUALITY_OPTIMISED : Better Quality ++ * When defined pre-scale will scale to larger than the requested ++ * size and use the blitter to reduce down. ++ * - This option will take precedence if both options are defined. ++ * ++ * PRE_SCALE_SPACE_OPTIMISED : Faster and Less Memory ++ * When defined pre-scale will scale below requested size, and ++ * use the blitter to enlarge ++ * ++ * Removing both defines will safely disable the pre-scaler ++ */ ++#define PRE_SCALE_QUALITY_OPTIMISED ++//#define PRE_SCALE_SPEED_SPACE_OPTIMISED ++ ++ ++ ++/* private data struct of IDirectFBImageProvider_JPEG */ ++typedef struct ++{ ++ /* hardware decode specifics */ ++ struct _MMECommon common; ++ ++ DFBRectangle rect; ++ DFBRegion clip; ++ ++ /* thread stuff */ ++ DIRenderFlags flags; ++ pthread_mutex_t lock; ++ pthread_cond_t cond; ++ DirectThread *thread; ++ IDirectFBSurface *destination; ++ DFBResult thread_res; ++ ++#if defined(JPEG_PROVIDER_USE_MME) ++ int num_components; ++ bool progressive_mode; ++ ++ JPEGDEC_TransformParams_t OutputParams; ++ JPEGDEC_TransformReturnParams_t ReturnParams; ++ ++// JPEGDECHW_VideoDecodeParams_t hw_decode_params; ++// JPEGDECHW_VideoDecodeReturnParams_t hw_return_params; ++#endif /* JPEG_PROVIDER_USE_MME */ ++} IDirectFBImageProvider_JPEG_data; ++ ++ ++#if defined(JPEG_PROVIDER_USE_MME) ++static inline const char * ++get_jpeg_error_string (unsigned int e) ++{ ++ static const char *JpegErrorType_strings[] = { ++ "Successfully Decoded", /* JPEG_NO_ERROR */ ++ "UNDEFINED_HUFF_TABLE", ++ "UNSUPPORTED_MARKER", ++ "UNABLE_ALLOCATE_MEMORY", ++ "NON_SUPPORTED_SAMP_FACTORS", ++ "BAD_PARAMETER", ++ "DECODE_ERROR", ++ "BAD_RESTART_MARKER", ++ "UNSUPPORTED_COLORSPACE", ++ "BAD_SOS_SPECTRAL", ++ "BAD_SOS_SUCCESSIVE", ++ "BAD_HEADER_LENGTH", ++ "BAD_COUNT_VALUE", ++ "BAD_DHT_MARKER", ++ "BAD_INDEX_VALUE", ++ "BAD_NUMBER_HUFFMAN_TABLES", ++ "BAD_QUANT_TABLE_LENGHT", ++ "BAD_NUMBER_QUANT_TABLES", ++ "BAD_COMPONENT_COUNT", ++ "DIVIDE_BY_ZERO_ERROR", ++ "NOT_JPG_IMAGE", ++ "UNSUPPORTED_ROTATION_ANGLE", ++ "UNSUPPORTED_SCALING", ++ "INSUFFICIENT_OUTPUTBUFFER_SIZE" ++ }; ++ ++ return ((e < D_ARRAY_SIZE (JpegErrorType_strings)) ++ ? JpegErrorType_strings[e] ++ : "* Unknown JpegError code *"); ++} ++ ++static inline const char * ++get_jpeghw_error_string (unsigned int e) ++{ ++ static const char *JpegHWErrorType_strings[] = { ++ "Successfully Decoded", /* JPEG_DECODER_NO_ERROR */ ++ "", "", "", "", "", "", "", "", ++ "JPEG_DECODER_ERROR_TASK_TIMEOUT" ++ }; ++ ++ return ((e < D_ARRAY_SIZE (JpegHWErrorType_strings)) ++ ? JpegHWErrorType_strings[e] ++ : "* Unknown JpegHWError code *"); ++} ++#endif /* JPEG_PROVIDER_USE_MME */ ++ ++ ++#endif /* __IDIRECTFBIMAGEPROVIDER_JPEG_H__ */ +diff --git a/interfaces/IDirectFBImageProvider/idirectfbimageprovider_png.c b/interfaces/IDirectFBImageProvider/idirectfbimageprovider_png.c +index 1ccf9c5..b7e2158 100644 +--- a/interfaces/IDirectFBImageProvider/idirectfbimageprovider_png.c ++++ b/interfaces/IDirectFBImageProvider/idirectfbimageprovider_png.c +@@ -1,4 +1,7 @@ + /* ++ (c) Copyright 2006-2010 ST Microelectronics R&D ++ ++based on code: + (c) Copyright 2001-2010 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + +@@ -60,10 +63,40 @@ + #include + #include + #include ++#include + #include + #include + +-#include "config.h" ++#if !defined(PNG_PROVIDER_USE_MME) ++#undef USE_MME ++#endif ++ ++ ++#include "debug_helper.h" ++ ++D_DEBUG_DOMAIN (HWPNG, "PNG", "STM MME-based PNG decoder"); ++D_DEBUG_DOMAIN (HWPNG_MME, "PNG/MME", "STM MME-based PNG decoder (MME)"); ++D_DEBUG_DOMAIN (HWPNG_SEMA, "PNG/SEMA", "STM MME-based PNG decoder (semaphores"); ++D_DEBUG_DOMAIN (HWPNG_TIME, "PNG/Time", "STM MME-based PNG decoder (timing"); ++#define MME_DEBUG_DOMAIN HWPNG_MME ++#define SEMA_DEBUG_DOMAIN HWPNG_SEMA ++#define MME_TEXT_DOMAIN "PNG" ++ ++#define fetch_data buffer_to_mme_copy ++#include "mme_helper.h" ++#include "idirectfbimageprovider_png.h" ++#if defined(PNG_PROVIDER_USE_MME) ++#include "sema_helper.h" ++static DFBResult PNG_HardwareRenderTo( IDirectFBImageProvider_PNG_data *data, ++ CoreSurface *dst_surface, ++ DFBSurfacePixelFormat format, ++ DFBRectangle *rect, ++ const DFBRegion *clip ); ++#else /* PNG_PROVIDER_USE_MME */ ++#define PNG_HardwareRenderTo(data,dst_surface, \ ++ format, rect, clip) DFB_NOSUCHINSTANCE ++#endif /* PNG_PROVIDER_USE_MME */ ++ + + D_DEBUG_DOMAIN( imageProviderPNG, "ImageProvider/PNG", "libPNG based image decoder" ); + +@@ -81,8 +114,11 @@ Construct( IDirectFBImageProvider *thiz, + + #include + +-DIRECT_INTERFACE_IMPLEMENTATION( IDirectFBImageProvider, PNG ) +- ++#if defined(PNG_PROVIDER_USE_MME) ++DIRECT_INTERFACE_IMPLEMENTATION( IDirectFBImageProvider, hwPNG ) ++#else /* PNG_PROVIDER_USE_MME */ ++DIRECT_INTERFACE_IMPLEMENTATION( IDirectFBImageProvider, swPNG ) ++#endif /* PNG_PROVIDER_USE_MME */ + + enum { + STAGE_ABORT = -2, +@@ -93,31 +129,10 @@ enum { + STAGE_END + }; + +-/* +- * private data struct of IDirectFBImageProvider_PNG +- */ +-typedef struct { +- IDirectFBImageProvider_data base; +- +- int stage; +- int rows; +- +- png_structp png_ptr; +- png_infop info_ptr; +- +- png_int_32 width; +- png_int_32 height; +- int bpp; +- int color_type; +- png_uint_32 color_key; +- bool color_keyed; +- +- void *image; +- int pitch; +- u32 palette[256]; +- DFBColor colors[256]; +-} IDirectFBImageProvider_PNG_data; + ++static DFBResult ++IDirectFBImageProvider_PNG_SetRenderFlags ( IDirectFBImageProvider *thiz, ++ DIRenderFlags flags ); + + static DFBResult + IDirectFBImageProvider_PNG_RenderTo( IDirectFBImageProvider *thiz, +@@ -125,6 +140,10 @@ IDirectFBImageProvider_PNG_RenderTo( IDirectFBImageProvider *thiz, + const DFBRectangle *destination_rect ); + + static DFBResult ++IDirectFBImageProvider_PNG_Sync( IDirectFBImageProvider *thiz, ++ DFBImageProviderSyncFlags flags ); ++ ++static DFBResult + IDirectFBImageProvider_PNG_GetSurfaceDescription( IDirectFBImageProvider *thiz, + DFBSurfaceDescription *dsc ); + +@@ -132,6 +151,10 @@ static DFBResult + IDirectFBImageProvider_PNG_GetImageDescription( IDirectFBImageProvider *thiz, + DFBImageDescription *dsc ); + ++static void * ++PNGrenderThread( DirectThread *thread, void *driver_data ); ++ ++ + /* Called at the start of the progressive load, once we have image info */ + static void + png_info_callback (png_structp png_read_ptr, +@@ -164,11 +187,31 @@ IDirectFBImageProvider_PNG_Destruct( IDirectFBImageProvider *thiz ) + IDirectFBImageProvider_PNG_data *data = + (IDirectFBImageProvider_PNG_data*)thiz->priv; + +- png_destroy_read_struct( &data->png_ptr, &data->info_ptr, NULL ); ++ if (data->thread) { ++ /* terminate the decoding thread, if necessary... */ ++ direct_thread_cancel( data->thread ); ++ direct_thread_join( data->thread ); ++ direct_thread_destroy( data->thread ); ++ ++ pthread_mutex_destroy( &data->lock ); ++ pthread_cond_destroy( &data->cond ); ++ } ++ ++ if (data->png_ptr) { ++ png_destroy_read_struct( &data->png_ptr, &data->info_ptr, NULL ); ++ data->png_ptr = NULL; ++ } + + /* Deallocate image data. */ +- if (data->image) +- D_FREE( data->image ); ++ if (data->common.image) ++ D_FREE( data->common.image ); ++ ++#if defined(PNG_PROVIDER_USE_MME) ++ if (data->common.decode_surface) { ++ dfb_gfxcard_wait_serial( &data->common.serial ); ++ dfb_surface_unref( data->common.decode_surface ); ++ } ++#endif + } + + /**********************************************************************************************************************/ +@@ -201,9 +244,9 @@ Construct( IDirectFBImageProvider *thiz, + core = va_arg( tag, CoreDFB * ); + va_end( tag ); + +- data->base.ref = 1; +- data->base.buffer = buffer; +- data->base.core = core; ++ data->common.base.ref = 1; ++ data->common.base.buffer = buffer; ++ data->common.base.core = core; + + /* Increase the data buffer reference counter. */ + buffer->AddRef( buffer ); +@@ -230,15 +273,16 @@ Construct( IDirectFBImageProvider *thiz, + png_row_callback, + png_end_callback ); + +- + /* Read until info callback is called. */ + ret = push_data_until_stage( data, STAGE_INFO, 64 ); + if (ret) + goto error; + +- data->base.Destruct = IDirectFBImageProvider_PNG_Destruct; ++ data->common.base.Destruct = IDirectFBImageProvider_PNG_Destruct; + ++ thiz->SetRenderFlags = IDirectFBImageProvider_PNG_SetRenderFlags; + thiz->RenderTo = IDirectFBImageProvider_PNG_RenderTo; ++ thiz->Sync = IDirectFBImageProvider_PNG_Sync; + thiz->GetImageDescription = IDirectFBImageProvider_PNG_GetImageDescription; + thiz->GetSurfaceDescription = IDirectFBImageProvider_PNG_GetSurfaceDescription; + +@@ -250,8 +294,8 @@ error: + + buffer->Release( buffer ); + +- if (data->image) +- D_FREE( data->image ); ++ if (data->common.image) ++ D_FREE( data->common.image ); + + DIRECT_DEALLOCATE_INTERFACE(thiz); + +@@ -261,42 +305,66 @@ error: + /**********************************************************************************************************************/ + + static DFBResult +-IDirectFBImageProvider_PNG_RenderTo( IDirectFBImageProvider *thiz, +- IDirectFBSurface *destination, +- const DFBRectangle *dest_rect ) ++IDirectFBImageProvider_PNG_SetRenderFlags( IDirectFBImageProvider *thiz, ++ DIRenderFlags flags ) + { +- DFBResult ret = DFB_OK; +- IDirectFBSurface_data *dst_data; +- CoreSurface *dst_surface; +- DFBRegion clip; +- DFBRectangle rect; +- int x, y; +- DFBRectangle clipped; ++ DIRECT_INTERFACE_GET_DATA(IDirectFBImageProvider_PNG) + +- DIRECT_INTERFACE_GET_DATA (IDirectFBImageProvider_PNG) ++ /* if we have decoded the image already, don't do anything... */ ++ if (data->common.image ++#if defined(PNG_PROVIDER_USE_MME) ++ || data->common.decode_surface ++#endif /* PNG_PROVIDER_USE_MME */ ++ ) ++ return DFB_UNSUPPORTED; ++ ++ if (!(flags & DIRENDER_NONE) && data->thread) { ++ /* terminate the decoding thread, if necessary... */ ++ direct_thread_cancel( data->thread ); ++ direct_thread_join( data->thread ); ++ direct_thread_destroy( data->thread ); ++ data->thread = NULL; ++ ++ pthread_cond_destroy( &data->cond ); ++ pthread_mutex_destroy( &data->lock ); ++ } ++ else if (flags & DIRENDER_BACKGROUND && !data->thread) { ++ /* or create it */ ++ pthread_cond_init( &data->cond, NULL ); ++ pthread_mutex_init( &data->lock, NULL ); ++ /* as long as we haven't even started yet, we are in INIT state */ ++ data->thread_res = DFB_INIT; ++ data->thread = direct_thread_create( DTT_DEFAULT, PNGrenderThread, ++ thiz, "PNG_DECODER?" ); ++ } + +- D_DEBUG_AT( imageProviderPNG, "%s(%d)\n", __FUNCTION__, __LINE__ ); ++ data->flags = flags; + +- dst_data = (IDirectFBSurface_data*) destination->priv; +- if (!dst_data) +- return DFB_DEAD; ++ return DFB_OK; ++} + +- dst_surface = dst_data->surface; +- if (!dst_surface) +- return DFB_DESTROYED; + +- dfb_region_from_rectangle( &clip, &dst_data->area.current ); ++static DFBResult ++PNG_SoftwareRenderTo( IDirectFBImageProvider_PNG_data *data, ++ CoreSurface *dst_surface, ++ DFBSurfacePixelFormat format, ++ DFBRectangle *rect, ++ const DFBRegion *clip ) ++{ ++ ++ DFBResult ret = DFB_OK; ++ png_infop info; ++ int x, y; ++ DFBRectangle clipped; + +- if (dest_rect) { +- if (dest_rect->w < 1 || dest_rect->h < 1) +- return DFB_INVARG; +- rect = *dest_rect; +- rect.x += dst_data->area.wanted.x; +- rect.y += dst_data->area.wanted.y; +- } +- else { +- rect = dst_data->area.wanted; +- } ++ D_ASSERT( data != NULL ); ++ D_ASSERT( dst_surface != NULL ); ++ D_ASSERT( clip != NULL ); ++ D_ASSERT( rect != NULL ); ++ ++ D_DEBUG_AT(imageProviderPNG,"%s(%d)\n",__FUNCTION__,__LINE__); ++ ++ info = data->info_ptr; + + if (setjmp( png_jmpbuf(data->png_ptr) )) { + D_ERROR( "ImageProvider/PNG: Error during decoding!\n" ); +@@ -314,23 +382,23 @@ IDirectFBImageProvider_PNG_RenderTo( IDirectFBImageProvider *thiz, + return ret; + } + +- clipped = rect; ++ clipped = *rect; + +- if (!dfb_rectangle_intersect_by_region( &clipped, &clip )) ++ if (!dfb_rectangle_intersect_by_region( &clipped, clip )) + return DFB_INVAREA; + + /* actual rendering */ + if (0 && // FIXME +- rect.w == data->width && rect.h == data->height && ++ rect->w == data->common.width && rect->h == data->common.height && + (data->color_type == PNG_COLOR_TYPE_RGB || data->color_type == PNG_COLOR_TYPE_RGBA) && + (dst_surface->config.format == DSPF_RGB32 || dst_surface->config.format == DSPF_ARGB) && + !(dst_surface->config.caps & DSCAPS_PREMULTIPLIED)) + { + //ret = dfb_surface_write_buffer( dst_surface, CSBR_BACK, +- // data->image + +- // (clipped.x - rect.x) * 4 + +- // (clipped.y - rect.y) * data->width * 4, +- // data->width * 4, &clipped ); ++ // data->common.image + ++ // (clipped.x - rect->x) * 4 + ++ // (clipped.y - rect->y) * data->common.width * 4, ++ // data->common.width * 4, &clipped ); + } + else { + CoreSurfaceBufferLock lock; +@@ -349,17 +417,17 @@ IDirectFBImageProvider_PNG_RenderTo( IDirectFBImageProvider *thiz, + */ + + /* FIXME: Limitation for LUT8 is to load complete surface only. */ +- dfb_clip_rectangle( &clip, &rect ); +- if (rect.x == 0 && rect.y == 0 && +- rect.w == dst_surface->config.size.w && +- rect.h == dst_surface->config.size.h && +- rect.w == data->width && +- rect.h == data->height) ++ dfb_clip_rectangle( clip, rect ); ++ if (rect->x == 0 && rect->y == 0 && ++ rect->w == dst_surface->config.size.w && ++ rect->h == dst_surface->config.size.h && ++ rect->w == data->common.width && ++ rect->h == data->common.height) + { +- for (y = 0; y < data->height; y++) ++ for (y = 0; y < data->common.height; y++) + direct_memcpy( (u8*)lock.addr + lock.pitch * y, +- (u8*)data->image + data->pitch * y, +- data->width ); ++ (u8*)data->common.image + data->pitch * y, ++ data->common.width ); + + break; + } +@@ -376,15 +444,15 @@ IDirectFBImageProvider_PNG_RenderTo( IDirectFBImageProvider *thiz, + for (x = 0; x < 256; x++) + data->palette[x] = 0xff000000 | (x << 16) | (x << 8) | x; + +- dfb_scale_linear_32( data->image, data->width, data->height, +- lock.addr, lock.pitch, &rect, dst_surface, &clip ); ++ dfb_scale_linear_32( data->common.image, data->common.width, data->common.height, ++ lock.addr, lock.pitch, rect, dst_surface, clip ); + break; + } + + // FIXME: allocates four additional bytes because the scaling functions + // in src/misc/gfx_util.c have an off-by-one bug which causes + // segfaults on darwin/osx (not on linux) +- int size = data->width * data->height * 4 + 4; ++ int size = data->common.width * data->common.height * 4 + 4; + + /* allocate image data */ + void *image_argb = D_MALLOC( size ); +@@ -407,21 +475,21 @@ IDirectFBImageProvider_PNG_RenderTo( IDirectFBImageProvider *thiz, + + switch (bit_depth) { + case 8: +- for (y = 0; y < data->height; y++) { +- u8 *S = (u8*)data->image + data->pitch * y; +- u32 *D = (u32*)((u8*)image_argb + data->width * y * 4); ++ for (y = 0; y < data->common.height; y++) { ++ u8 *S = (u8*)data->common.image + data->pitch * y; ++ u32 *D = (u32*)((u8*)image_argb + data->common.width * y * 4); + +- for (x = 0; x < data->width; x++) ++ for (x = 0; x < data->common.width; x++) + D[x] = data->palette[ S[x] ]; + } + break; + + case 4: +- for (y = 0; y < data->height; y++) { +- u8 *S = (u8*)data->image + data->pitch * y; +- u32 *D = (u32*)((u8*)image_argb + data->width * y * 4); ++ for (y = 0; y < data->common.height; y++) { ++ u8 *S = (u8*)data->common.image + data->pitch * y; ++ u32 *D = (u32*)((u8*)image_argb + data->common.width * y * 4); + +- for (x = 0; x < data->width; x++) { ++ for (x = 0; x < data->common.width; x++) { + if (x & 1) + D[x] = data->palette[ S[x>>1] & 0xf ]; + else +@@ -431,12 +499,12 @@ IDirectFBImageProvider_PNG_RenderTo( IDirectFBImageProvider *thiz, + break; + + case 2: +- for (y = 0; y < data->height; y++) { ++ for (y = 0; y < data->common.height; y++) { + int n = 6; +- u8 *S = (u8*)data->image + data->pitch * y; +- u32 *D = (u32*)((u8*)image_argb + data->width * y * 4); ++ u8 *S = (u8*)data->common.image + data->pitch * y; ++ u32 *D = (u32*)((u8*)image_argb + data->common.width * y * 4); + +- for (x = 0; x < data->width; x++) { ++ for (x = 0; x < data->common.width; x++) { + D[x] = data->palette[ (S[x>>2] >> n) & 3 ]; + + n = (n ? n - 2 : 6); +@@ -445,12 +513,12 @@ IDirectFBImageProvider_PNG_RenderTo( IDirectFBImageProvider *thiz, + break; + + case 1: +- for (y = 0; y < data->height; y++) { ++ for (y = 0; y < data->common.height; y++) { + int n = 7; +- u8 *S = (u8*)data->image + data->pitch * y; +- u32 *D = (u32*)((u8*)image_argb + data->width * y * 4); ++ u8 *S = (u8*)data->common.image + data->pitch * y; ++ u32 *D = (u32*)((u8*)image_argb + data->common.width * y * 4); + +- for (x = 0; x < data->width; x++) { ++ for (x = 0; x < data->common.width; x++) { + D[x] = data->palette[ (S[x>>3] >> n) & 1 ]; + + n = (n ? n - 1 : 7); +@@ -463,19 +531,20 @@ IDirectFBImageProvider_PNG_RenderTo( IDirectFBImageProvider *thiz, + bit_depth ); + } + +- dfb_scale_linear_32( image_argb, data->width, data->height, +- lock.addr, lock.pitch, &rect, dst_surface, &clip ); ++ dfb_scale_linear_32( image_argb, data->common.width, data->common.height, ++ lock.addr, lock.pitch, rect, dst_surface, clip ); + + D_FREE( image_argb ); + } + break; + } ++ + default: + /* + * Generic loading code. + */ +- dfb_scale_linear_32( data->image, data->width, data->height, +- lock.addr, lock.pitch, &rect, dst_surface, &clip ); ++ dfb_scale_linear_32( data->common.image, data->common.width, data->common.height, ++ lock.addr, lock.pitch, rect, dst_surface, clip ); + break; + } + +@@ -488,6 +557,164 @@ IDirectFBImageProvider_PNG_RenderTo( IDirectFBImageProvider *thiz, + return ret; + } + ++ ++static DFBResult ++PNG_RenderTo( IDirectFBImageProvider_PNG_data *data, ++ CoreSurface *dst_surface, ++ DFBSurfacePixelFormat format, ++ DFBRectangle *rect, ++ const DFBRegion *clip ) ++{ ++ DFBResult res; ++ ++ D_ASSERT( data != NULL ); ++ D_ASSERT( dst_surface != NULL ); ++ D_ASSERT( clip != NULL ); ++ D_ASSERT( rect != NULL ); ++ ++ res = PNG_HardwareRenderTo (data, dst_surface, format, rect, clip); ++ if (res != DFB_OK) { ++ if (unlikely (res == DFB_IO)) { ++ /* IO error - there's no point in retrying */ ++ D_DEBUG_AT (HWPNG, "hardware decode failed: %d (%s)\n", ++ res, DirectFBErrorString (res)); ++ return res; ++ } ++ ++ if (res == DFB_UNSUPPORTED) ++ D_DEBUG_AT (HWPNG, "doing software decode since it's faster " ++ "than hardware for this image\n"); ++ else ++ D_DEBUG_AT (HWPNG, "hardware decode failed: %d (%s) - " ++ "attempting software fallback\n", ++ res, DirectFBErrorString (res)); ++ ++ res = PNG_SoftwareRenderTo (data, dst_surface, format, rect, clip); ++ if (unlikely (res != DFB_OK)) ++ D_DEBUG_AT (HWPNG, "software decode failed: %d (%s)\n", ++ res, DirectFBErrorString (res)); ++ } ++ ++ return res; ++} ++ ++static DFBResult ++IDirectFBImageProvider_PNG_RenderTo( IDirectFBImageProvider *thiz, ++ IDirectFBSurface *destination, ++ const DFBRectangle *dest_rect ) ++{ ++ IDirectFBSurface_data *dst_data; ++ CoreSurface *dst_surface; ++ DFBSurfacePixelFormat format; ++ DFBResult ret; ++ ++ DIRECT_INTERFACE_GET_DATA(IDirectFBImageProvider_PNG) ++ ++ dst_data = (IDirectFBSurface_data*) destination->priv; ++ if (!dst_data) ++ return DFB_DEAD; ++ ++ dst_surface = dst_data->surface; ++ if (!dst_surface) ++ return DFB_DESTROYED; ++ ++ ret = destination->GetPixelFormat( destination, &format ); ++ if (ret) ++ return ret; ++ ++ if (data->thread) ++ pthread_mutex_lock( &data->lock ); ++ ++ dfb_region_from_rectangle( &data->clip, &dst_data->area.current ); ++ ++ if (dest_rect) { ++ if (dest_rect->w < 1 || dest_rect->h < 1) { ++ if (data->thread) ++ pthread_mutex_unlock (&data->lock); ++ return DFB_INVARG; ++ } ++ ++ data->rect = *dest_rect; ++ data->rect.x += dst_data->area.wanted.x; ++ data->rect.y += dst_data->area.wanted.y; ++ } ++ else { ++ data->rect = dst_data->area.wanted; ++ } ++ ++ if (!D_FLAGS_IS_SET (data->flags, DIRENDER_BACKGROUND)) { ++ /* threaded operation was not requested */ ++ data->thread_res = PNG_RenderTo( data, dst_surface, format, ++ &data->rect, &data->clip ); ++ if (data->thread) ++ pthread_mutex_unlock( &data->lock ); ++ return data->thread_res; ++ } ++ ++ if (!data->thread) { ++ /* for the case that somebody does a RenderTo() twice on us, we ++ have to create new thread, because the initial thread will have ++ finished already */ ++ ++ D_ASSERT( data->destination == NULL ); ++ ++ /* as long as we haven't even started yet, we are in INIT state */ ++ data->thread_res = DFB_INIT; ++ data->thread = direct_thread_create( DTT_DEFAULT, PNGrenderThread, ++ thiz, "PNG" ); ++ } ++ ++ D_ASSERT( data->destination == NULL ); ++ ++ destination->AddRef( destination ); ++ data->destination = destination; ++ ++ pthread_cond_signal( &data->cond ); ++ pthread_mutex_unlock( &data->lock ); ++ ++ return DFB_OK; ++} ++ ++static DFBResult ++IDirectFBImageProvider_PNG_Sync( IDirectFBImageProvider *thiz, ++ DFBImageProviderSyncFlags flags ) ++{ ++ DFBResult res; ++ ++ DIRECT_INTERFACE_GET_DATA(IDirectFBImageProvider_PNG) ++ ++ switch (flags) ++ { ++ case DIPSYNCFLAGS_TRYSYNC: ++ if (data->thread) { ++ if (data->thread_res == DFB_INIT ++ || data->thread_res == DFB_BUSY) { ++ /* DFB_INIT (user didn't call RenderTo() yet) ++ DFB_BUSY (still busy decoding) */ ++ return data->thread_res; ++ } ++ /* else we are done, either because of some error or because ++ we have processed all the data already */ ++ } ++ /* fall through */ ++ ++ case DIPSYNCFLAGS_SYNC: ++ if (data->thread) { ++ direct_thread_join( data->thread ); ++ direct_thread_destroy( data->thread ); ++ data->thread = NULL; ++ } ++ break; ++ ++ default: ++ return DFB_OK; ++ } ++ ++ res = data->thread_res; ++ data->thread_res = DFB_OK; ++ return res; ++} ++ + static DFBResult + IDirectFBImageProvider_PNG_GetSurfaceDescription( IDirectFBImageProvider *thiz, + DFBSurfaceDescription *dsc ) +@@ -497,13 +724,13 @@ IDirectFBImageProvider_PNG_GetSurfaceDescription( IDirectFBImageProvider *thiz, + DIRECT_INTERFACE_GET_DATA (IDirectFBImageProvider_PNG) + + dsc->flags = DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT; +- dsc->width = data->width; +- dsc->height = data->height; ++ dsc->width = data->common.width; ++ dsc->height = data->common.height; + + if (data->color_type & PNG_COLOR_MASK_ALPHA) + dsc->pixelformat = DFB_PIXELFORMAT_HAS_ALPHA(primary_format) ? primary_format : DSPF_ARGB; + else +- dsc->pixelformat = primary_format; ++ dsc->pixelformat = DSPF_RGB24; + + if (data->color_type == PNG_COLOR_TYPE_PALETTE) { + dsc->flags |= DSDESC_PALETTE; +@@ -540,6 +767,71 @@ IDirectFBImageProvider_PNG_GetImageDescription( IDirectFBImageProvider *thiz, + return DFB_OK; + } + ++static void ++render_cleanup( void *cleanup_data ) ++{ ++ IDirectFBImageProvider *thiz = cleanup_data; ++ IDirectFBImageProvider_PNG_data *data; ++ ++ D_MAGIC_ASSERT( (IAny*)thiz, DirectInterface ); ++ data = (IDirectFBImageProvider_PNG_data *) thiz->priv; ++ D_ASSERT( data != NULL ); ++ ++ if (data->destination) { ++ data->destination->Release( data->destination ); ++ data->destination = NULL; ++ } ++ ++ /* in case we get terminated from outside, set the state to DFB_DEAD */ ++ data->thread_res = DFB_DEAD; ++ ++ pthread_mutex_unlock( &data->lock ); ++} ++ ++static void * ++PNGrenderThread( DirectThread *thread, void *driver_data ) ++{ ++ IDirectFBImageProvider *thiz = driver_data; ++ IDirectFBImageProvider_PNG_data *data; ++ IDirectFBSurface_data *dst_data; ++ CoreSurface *dst_surface; ++ DFBSurfacePixelFormat format; ++ DFBResult res; ++ ++ D_MAGIC_ASSERT( (IAny*)thiz, DirectInterface ); ++ data = (IDirectFBImageProvider_PNG_data *) thiz->priv; ++ D_ASSERT( data != NULL ); ++ ++ pthread_mutex_lock( &data->lock ); ++ ++ pthread_cleanup_push( render_cleanup, thiz ); ++ ++ while (!data->destination) { ++ pthread_cond_wait( &data->cond, &data->lock ); ++ } ++ ++ dst_data = (IDirectFBSurface_data*) data->destination->priv; ++ D_ASSERT( dst_data != NULL ); ++ ++ dst_surface = dst_data->surface; ++ D_ASSERT( dst_surface != NULL ); ++ ++ res = data->destination->GetPixelFormat( data->destination, &format ); ++ D_ASSERT( res == DFB_OK ); ++ ++ /* as long as we haven't finished decoding we are busy */ ++ data->thread_res = DFB_BUSY; ++ ++ res = PNG_RenderTo( data, dst_surface, format, &data->rect, &data->clip ); ++ ++ pthread_cleanup_pop( 1 ); ++ ++ /* in case we exit normally, apply the real return value */ ++ data->thread_res = res; ++ ++ return NULL; ++} ++ + /**********************************************************************************************************************/ + + #define MAXCOLORMAPSIZE 256 +@@ -598,6 +890,8 @@ png_info_callback( png_structp png_read_ptr, + { + int i,ret; + IDirectFBImageProvider_PNG_data *data; ++ png_int_32 width; ++ png_int_32 height; + + u32 bpp1[2] = {0, 0xff}; + u32 bpp2[4] = {0, 0x55, 0xaa, 0xff}; +@@ -617,13 +911,16 @@ png_info_callback( png_structp png_read_ptr, + data->stage = STAGE_INFO; + + ret = png_get_IHDR( data->png_ptr, data->info_ptr, +- (png_uint_32 *)&data->width, (png_uint_32 *)&data->height, &data->bpp, &data->color_type, ++ (png_uint_32 *)&width, (png_uint_32 *)&height, &data->bpp, &data->color_type, + NULL, NULL, NULL ); + + /* Let's not do anything with badly sized or corrupted images */ +- if ( (data->height == 0) || (data->width == 0) || (ret != 1) ) ++ if ( (height == 0) || (width == 0) || (ret != 1) ) + return; + ++ data->common.width = width; ++ data->common.height = height; ++ + if (png_get_valid( data->png_ptr, data->info_ptr, PNG_INFO_tRNS )) { + data->color_keyed = true; + +@@ -773,13 +1070,13 @@ png_info_callback( png_structp png_read_ptr, + data->colors[i].b ); + } + +- data->pitch = (data->width + 7) & ~7; ++ data->pitch = (data->common.width + 7) & ~7; + break; + } + + case PNG_COLOR_TYPE_GRAY: + if (data->bpp < 16) { +- data->pitch = data->width; ++ data->pitch = data->common.width; + break; + } + +@@ -789,7 +1086,7 @@ png_info_callback( png_structp png_read_ptr, + + /* fall through */ + default: +- data->pitch = data->width * 4; ++ data->pitch = data->common.width * 4; + + if (!data->color_keyed) + png_set_strip_16( data->png_ptr ); /* if it is color keyed we will handle conversion ourselves */ +@@ -838,15 +1135,15 @@ png_row_callback( png_structp png_read_ptr, + data->stage = STAGE_IMAGE; + + /* check image data pointer */ +- if (!data->image) { ++ if (!data->common.image) { + // FIXME: allocates four additional bytes because the scaling functions + // in src/misc/gfx_util.c have an off-by-one bug which causes + // segfaults on darwin/osx (not on linux) +- int size = data->pitch * data->height + 4; ++ int size = data->pitch * data->common.height + 4; + + /* allocate image data */ +- data->image = D_CALLOC( 1, size ); +- if (!data->image) { ++ data->common.image = D_CALLOC( 1, size ); ++ if (!data->common.image) { + D_ERROR( "DirectFB/ImageProvider_PNG: Could not " + "allocate %d bytes of system memory!\n", size ); + +@@ -859,7 +1156,7 @@ png_row_callback( png_structp png_read_ptr, + + /* write to image data */ + if (data->bpp == 16 && data->color_keyed) { +- u8 *dst = (u8*)((u8*)data->image + row_num * data->pitch); ++ u8 *dst = (u8*)((u8*)data->common.image + row_num * data->pitch); + u8 *src = (u8*)new_row; + + if (src) { +@@ -908,7 +1205,7 @@ png_row_callback( png_structp png_read_ptr, + u16 *src16 = (u16*)src + src16_initial_offset; + u32 *dst32 = (u32*)dst + dst32_initial_offset; + +- int remaining = data->width - dst32_initial_offset; ++ int remaining = data->common.width - dst32_initial_offset; + + while (remaining > 0) { + int keyed = 0; +@@ -948,17 +1245,17 @@ png_row_callback( png_structp png_read_ptr, + } + } + else +- png_progressive_combine_row( data->png_ptr, (png_bytep)((u8*)data->image + row_num * data->pitch), new_row ); ++ png_progressive_combine_row( data->png_ptr, (png_bytep)((u8*)data->common.image + row_num * data->pitch), new_row ); + + /* increase row counter, FIXME: interlaced? */ + data->rows++; + +- if (data->base.render_callback) { ++ if (data->common.base.render_callback) { + DIRenderCallbackResult r; +- DFBRectangle rect = { 0, row_num, data->width, 1 }; ++ DFBRectangle rect = { 0, row_num, data->common.width, 1 }; + +- r = data->base.render_callback( &rect, +- data->base.render_callback_context ); ++ r = data->common.base.render_callback( &rect, ++ data->common.base.render_callback_context ); + if (r != DIRCR_OK) + data->stage = STAGE_ABORT; + } +@@ -992,7 +1289,7 @@ push_data_until_stage (IDirectFBImageProvider_PNG_data *data, + int buffer_size) + { + DFBResult ret; +- IDirectFBDataBuffer *buffer = data->base.buffer; ++ IDirectFBDataBuffer *buffer = data->common.base.buffer; + + while (data->stage < stage) { + unsigned int len; +@@ -1034,3 +1331,711 @@ push_data_until_stage (IDirectFBImageProvider_PNG_data *data, + + return DFB_OK; + } ++ ++ ++ ++#if defined(PNG_PROVIDER_USE_MME) ++static void ++TransformerCallback (MME_Event_t Event, ++ MME_Command_t *CallbackData, ++ void *UserData) ++{ ++ static const char *color_types[] = { "gray", "?", "rgb", "palette", ++ "alpha", "?", "rgba" }; ++ static const char *interlace_types[] = { "none", "adam7" }; ++ ++ const PNGDecode_TransformReturnParams_t * const transform_result = ++ CallbackData->CmdStatus.AdditionalInfo_p; ++ const PNGDecode_GlobalTransformReturnParams_t * const global_transform_result = ++ CallbackData->CmdStatus.AdditionalInfo_p; ++ struct _MMECommon * const mme = (struct _MMECommon *) UserData; ++ IDirectFBImageProvider_PNG_data * const data = ++ container_of (mme, IDirectFBImageProvider_PNG_data, common); ++ ++ if (!mme->name_set) ++ { ++ char name[20]; ++ snprintf (name, sizeof (name), "MME (%s)", mme->transformer_name); ++ direct_thread_set_name (name); ++ mme->name_set = true; ++ } ++ ++ D_DEBUG_AT (HWPNG, "%sTransformerCallback: Event: %d: (%s)%s\n", ++ RED, Event, get_mme_event_string (Event), BLACK); ++ D_DEBUG_AT (HWPNG, " -> CallbackData->CmdStatus.State: %d (%s)\n", ++ CallbackData->CmdStatus.State, ++ get_mme_state_string (CallbackData->CmdStatus.State)); ++ D_DEBUG_AT (HWPNG, " -> CallbackData->CmdStatus.CmdId: %u (%.8x)\n", ++ CallbackData->CmdStatus.CmdId, ++ CallbackData->CmdStatus.CmdId); ++ D_DEBUG_AT (HWPNG, " -> CallbackData->CmdStatus.Error: %d (%s)\n", ++ CallbackData->CmdStatus.Error, ++ get_mme_error_string (CallbackData->CmdStatus.Error)); ++ D_DEBUG_AT (HWPNG, " -> CallbackData->CmdStatus.AdditionalInfoSize: %u\n", ++ CallbackData->CmdStatus.AdditionalInfoSize); ++ D_DEBUG_AT (HWPNG, " -> mme->decode_success: %d\n", mme->decode_success); ++ ++ switch (Event) ++ { ++ case MME_COMMAND_COMPLETED_EVT: ++ pthread_mutex_lock (&mme->pending_commands_lock); ++ direct_hash_remove (mme->pending_commands, ++ CallbackData->CmdStatus.CmdId); ++ if (likely (CallbackData->CmdStatus.CmdId != mme->TransformCommand.CmdStatus.CmdId ++ && CallbackData->CmdStatus.CmdId != data->SetGlobalCommand.CmdStatus.CmdId)) ++ --mme->n_pending_buffers; ++ pthread_mutex_unlock (&mme->pending_commands_lock); ++ ++ switch (CallbackData->CmdStatus.State) ++ { ++ case MME_COMMAND_COMPLETED: ++ if (unlikely (CallbackData->CmdStatus.CmdId ++ == mme->TransformCommand.CmdStatus.CmdId)) ++ { ++ deb_gettimeofday (&mme->endtime, NULL); ++ deb_timersub (&mme->endtime, &mme->starttime, &mme->endtime); ++ D_DEBUG_AT (HWPNG_TIME, " -> total time %lu.%06lu\n", ++ mme->endtime.tv_sec, mme->endtime.tv_usec); ++ ++ D_DEBUG_AT (HWPNG, " -> expanded bytes: %u\n", ++ transform_result->BytesWritten); ++ ++ D_DEBUG_AT (HWPNG, " -> PNG result code: %d (%s)\n", ++ transform_result->ErrorType, ++ get_png_error_string (transform_result->ErrorType)); ++ ++ if (transform_result->Cycles) ++ { ++ D_DEBUG_AT (HWPNG, " -> profiling data: cyc/bu/i/d/n: " ++ "%u/%u/%u/%u/%u\n", ++ transform_result->Cycles, ++ transform_result->Bundles, ++ transform_result->ICacheMiss, ++ transform_result->DCacheMiss, ++ transform_result->NopBundles); ++ } ++ ++ mme->decode_success = 1; ++ sema_signal_event (&mme->decode_event); ++ ++ /* in case of bogus data (too much), abort pending data ++ buffers */ ++ abort_transformer (mme); ++ } ++ else if (unlikely (CallbackData->CmdStatus.CmdId ++ == data->SetGlobalCommand.CmdStatus.CmdId)) ++ { ++ D_DEBUG_AT (HWPNG, " -> size: %ux%u @ %ubpp\n", ++ global_transform_result->PictureWidth, ++ global_transform_result->PictureHeight, ++ global_transform_result->BitDepth); ++ D_DEBUG_AT (HWPNG, " -> ColorType : %d (%s)\n", ++ global_transform_result->ColorType, ++ (global_transform_result->ColorType ++ < D_ARRAY_SIZE (color_types)) ++ ? color_types[global_transform_result->ColorType] ++ : "?" ); ++ D_DEBUG_AT (HWPNG, " -> InterlaceType : %d (%s)\n", ++ global_transform_result->InterlaceType, ++ (global_transform_result->InterlaceType ++ < D_ARRAY_SIZE (interlace_types)) ++ ? interlace_types[global_transform_result->InterlaceType] ++ : "?"); ++ D_DEBUG_AT (HWPNG, " -> CompressionType: %d\n", global_transform_result->CompressionType); ++ D_DEBUG_AT (HWPNG, " -> FilterMethod : %d\n", global_transform_result->FilterMethod); ++ D_DEBUG_AT (HWPNG, " -> ErrorType : %d (%s)\n", global_transform_result->ErrorType, get_png_error_string (global_transform_result->ErrorType)); ++ ++ D_DEBUG_AT (HWPNG, " -> ColorFormatOutput: %d\n", global_transform_result->ColorFormatOutput); ++ D_DEBUG_AT (HWPNG, " -> ColorKey: %c\n", global_transform_result->HaveColorKey ? 'y' : 'n'); ++ if (global_transform_result->HaveColorKey) ++ D_DEBUG_AT (HWPNG, " -> ColorKey (xRGB): %.6x\n", global_transform_result->ColorKey); ++ D_DEBUG_AT (HWPNG, " -> pitch: %d\n", global_transform_result->pitch); ++ ++ sema_signal_event (&data->global_event); ++ } ++ else ++ { ++ /* buffer completed */ ++ struct _MMEHelper_buffer *buf = ++ container_of (CallbackData->DataBuffers_p, ++ struct _MMEHelper_buffer, buffer); ++ ++ D_DEBUG_AT (HWPNG, " -> buffer %p completed (container @ %p)\n", ++ CallbackData->DataBuffers_p[0], buf); ++ ++ sema_signal_event (&buf->sema); ++ } ++ break; /* MME_COMMAND_COMPLETED */ ++ ++ case MME_COMMAND_FAILED: ++ if (CallbackData->CmdStatus.Error != MME_COMMAND_ABORTED) ++ D_WARN ("(%5d) %s: command %u (%.8x) failed: error %d (%s)", ++ direct_gettid (), mme->name, ++ CallbackData->CmdStatus.CmdId, ++ CallbackData->CmdStatus.CmdId, ++ CallbackData->CmdStatus.Error, ++ get_mme_error_string (CallbackData->CmdStatus.Error)); ++ ++ if (likely (CallbackData->CmdStatus.CmdId ++ == mme->TransformCommand.CmdStatus.CmdId)) ++ { ++ /* transform command failed */ ++ D_DEBUG_AT (HWPNG, " -> transform->ErrorType: %d (%s)\n", ++ transform_result->ErrorType, ++ get_png_error_string (transform_result->ErrorType)); ++ ++ mme->decode_success = -1; ++ sema_signal_event (&mme->decode_event); ++ } ++ else if (likely (CallbackData->CmdStatus.CmdId ++ == data->SetGlobalCommand.CmdStatus.CmdId)) ++ { ++ /* global transform params command failed */ ++ D_DEBUG_AT (HWPNG, " -> global->ErrorType: %d (%s)\n", ++ global_transform_result->ErrorType, ++ get_png_error_string (global_transform_result->ErrorType)); ++ ++ mme->decode_success = -1; ++ sema_signal_event (&data->global_event); ++ } ++ else ++ { ++ /* buffer failed */ ++ struct _MMEHelper_buffer *buf = ++ container_of (CallbackData->DataBuffers_p, ++ struct _MMEHelper_buffer, buffer); ++ if (mme->decode_success == 0) ++ /* only if we didn't succeed yet */ ++ mme->decode_success = -1; ++ sema_signal_event (&buf->sema); ++ } ++ break; /* MME_COMMAND_FAILED */ ++ ++ case MME_COMMAND_IDLE: ++ case MME_COMMAND_PENDING: ++ case MME_COMMAND_EXECUTING: ++ default: ++ D_WARN ("(%5d) %s: command %u (%.8x) completed in unknown state: %d (%s)", ++ direct_gettid (), mme->name, ++ CallbackData->CmdStatus.CmdId, CallbackData->CmdStatus.CmdId, ++ CallbackData->CmdStatus.State, ++ get_mme_state_string (CallbackData->CmdStatus.State)); ++ break; ++ } ++ break; /* MME_COMMAND_COMPLETED_EVT */ ++ ++ case MME_DATA_UNDERFLOW_EVT: ++ ++mme->n_underflows; ++ { ++ /* check if the IDirectFBDataBuffer definitely(!) hit an EOF and ++ we have no buffers queued */ ++ bool end_of_data; ++ char tmp; ++ pthread_mutex_lock (&mme->pending_commands_lock); ++ DFBResult has_data = mme->base.buffer->PeekData (mme->base.buffer, ++ 1, 0, &tmp, NULL); ++ /* n_pending_buffers is checked to be == 0 because the ++ TransformCommand itself is not stored in there. */ ++ end_of_data = (has_data == DFB_EOF ++ && mme->n_pending_buffers == 0); ++ pthread_mutex_unlock (&mme->pending_commands_lock); ++ ++ /* if so, signal completion */ ++ if (end_of_data) ++ { ++ D_DEBUG_AT (HWPNG, " -> no more data available, signalling fail\n"); ++ mme->decode_success = -2; ++ sema_signal_event (&mme->decode_event); ++ } ++ } ++ break; /* MME_DATA_UNDERFLOW_EVT */ ++ ++ case MME_NOT_ENOUGH_MEMORY_EVT: ++ case MME_NEW_COMMAND_EVT: ++ default: ++ D_WARN ("(%5d) %s: unhandled event %d (%s) occured on command %u (%.8x)", ++ direct_gettid (), mme->name, Event, ++ get_mme_event_string (Event), CallbackData->CmdStatus.CmdId, ++ CallbackData->CmdStatus.CmdId); ++ ++ D_WARN ("(%5d) %s: CallbackData->CmdStatus.AdditionalInfoSize: %u", ++ direct_gettid (), mme->name, CallbackData->CmdStatus.AdditionalInfoSize); ++ ++ if (CallbackData->CmdStatus.CmdId == mme->TransformCommand.CmdStatus.CmdId) ++ { ++ D_WARN ("(%5d) %s: transform_result->bytes_written: %u", ++ direct_gettid (), mme->name, transform_result->BytesWritten); ++ D_WARN ("(%5d) %s: result code: %d (%s)\n", direct_gettid (), ++ mme->name, transform_result->ErrorType, ++ get_png_error_string (transform_result->ErrorType)); ++ } ++ else if (CallbackData->CmdStatus.CmdId == data->SetGlobalCommand.CmdStatus.CmdId) ++ { ++ D_WARN ("(%5d) %s: size: %ux%u @ %ubpp\n", ++ direct_gettid (), mme->name, ++ global_transform_result->PictureWidth, ++ global_transform_result->PictureHeight, ++ global_transform_result->BitDepth); ++ D_WARN ("(%5d) %s: ColorType : %d (%s)\n", ++ direct_gettid (), mme->name, ++ global_transform_result->ColorType, ++ (global_transform_result->ColorType ++ < D_ARRAY_SIZE (color_types)) ++ ? color_types[global_transform_result->ColorType] ++ : "?" ); ++ D_WARN ("(%5d) %s: InterlaceType : %d (%s)\n", ++ direct_gettid (), mme->name, ++ global_transform_result->InterlaceType, ++ (global_transform_result->InterlaceType ++ < D_ARRAY_SIZE (interlace_types)) ++ ? interlace_types[global_transform_result->InterlaceType] ++ : "?"); ++ D_WARN ("(%5d) %s: CompressionType: %d\n", direct_gettid (), mme->name, global_transform_result->CompressionType); ++ D_WARN ("(%5d) %s: FilterMethod : %d\n", direct_gettid (), mme->name, global_transform_result->FilterMethod); ++ D_WARN ("(%5d) %s: ErrorType : %d (%s)\n", direct_gettid (), mme->name, global_transform_result->ErrorType, get_png_error_string (global_transform_result->ErrorType)); ++ ++ D_DEBUG_AT (HWPNG, " -> ColorFormatOutput: %d\n", global_transform_result->ColorFormatOutput); ++ D_DEBUG_AT (HWPNG, " -> ColorKey: %c\n", global_transform_result->HaveColorKey ? 'y' : 'n'); ++ if (global_transform_result->HaveColorKey) ++ D_DEBUG_AT (HWPNG, " -> ColorKey (xRGB): %.6x\n", global_transform_result->ColorKey); ++ D_DEBUG_AT (HWPNG, " -> pitch: %d\n", global_transform_result->pitch); ++ } ++ break; ++ } ++} ++ ++ ++/* warning: MME_AbortCommand() works only for the MME_TRANSFORM command; ++ individual buffers can be aborted, too, but MME_TermTransformer() will ++ not work afterwards anymore! */ ++static bool ++pending_fe_func (DirectHash *hash, ++ unsigned long key, ++ void *value, ++ void *ctx) ++{ ++ struct _MMECommon * const mme = ctx; ++ __attribute__((unused)) ++ IDirectFBImageProvider_PNG_data * const data = ++ container_of (mme, IDirectFBImageProvider_PNG_data, common); ++ MME_CommandId_t CmdId = key; ++ ++ D_DEBUG_AT (HWPNG, "aborting %s command %u (%.8x)\n", ++ ((CmdId == mme->TransformCommand.CmdStatus.CmdId) ++ ? "(main transform)" ++ : ((CmdId == data->SetGlobalCommand.CmdStatus.CmdId) ++ ? "(global)" ++ : "(buffer)" ++ ) ++ ), CmdId, CmdId); ++ ++ MME_ERROR res = MME_AbortCommand (mme->Handle, CmdId); ++ if (res != MME_SUCCESS) ++ { ++ /* this would mean the command is about to finish, but we didn't ++ notice yet... */ ++ D_WARN ("(%5d) MME_AbortCommand(%x, %.8x) for %s failed: %d (%s)\n", ++ direct_gettid (), mme->Handle, CmdId, ++ mme->name, res, get_mme_error_string (res)); ++ } ++ ++ /* continue iterating */ ++ return true; ++} ++ ++static DFBResult ++abort_transformer (struct _MMECommon * const mme) ++{ ++ if (!mme) ++ return DFB_THIZNULL; ++ ++ /* FIXME: what about locking? */ ++ direct_hash_iterate (mme->pending_commands, ++ pending_fe_func, ++ mme); ++ ++ return DFB_OK; ++} ++ ++ ++static DFBResult ++set_global_transform_params (IDirectFBImageProvider_PNG_data *data) ++{ ++ MME_ERROR ret; ++ ++ data->SetGlobalCommand.StructSize = sizeof (MME_Command_t); ++ data->SetGlobalCommand.CmdCode = MME_SET_GLOBAL_TRANSFORM_PARAMS; ++ data->SetGlobalCommand.CmdEnd = MME_COMMAND_END_RETURN_NOTIFY; ++ data->SetGlobalCommand.DueTime = (MME_Time_t) 0; ++ data->SetGlobalCommand.NumberInputBuffers = 0; ++ data->SetGlobalCommand.NumberOutputBuffers = 0; ++ data->SetGlobalCommand.DataBuffers_p = NULL; ++ ++ /* clear the commandstatus from the previous run */ ++ memset (&( data->SetGlobalCommand.CmdStatus), 0, sizeof (MME_CommandStatus_t)); ++ ++ data->SetGlobalCommand.CmdStatus.AdditionalInfoSize = sizeof (PNGDecode_GlobalTransformReturnParams_t); ++ data->SetGlobalCommand.CmdStatus.AdditionalInfo_p = &data->GlobalReturnParams; ++ ++ data->SetGlobalCommand.NumberInputBuffers = 0; ++ data->SetGlobalCommand.NumberOutputBuffers = 0; ++ ++ /* set parameters - just settings flags to 0 should make this compatible ++ with old transformer versions, 0 means PNGDECODE_OF_EXPAND */ ++// data->GlobalParams.flags = PNGDECODE_PARAM_FORMAT; ++// data->GlobalParams.format = PNGDECODE_OF_EXPAND; ++// data->SetGlobalCommand.ParamSize = sizeof (PNGDecode_GlobalParams_t); ++// data->SetGlobalCommand.Param_p = &data->GlobalParams; ++ data->SetGlobalCommand.ParamSize = 0; ++ data->SetGlobalCommand.Param_p = NULL; ++ ++ D_DEBUG_AT (HWPNG, "sending global command\n"); ++ ++ pthread_mutex_lock (&data->common.pending_commands_lock); ++ ret = MME_SendCommand (data->common.Handle, &data->SetGlobalCommand); ++ if (ret != MME_SUCCESS) ++ { ++ pthread_mutex_unlock (&data->common.pending_commands_lock); ++ D_INFO ("%s: MME_SendCommand() failed: %d (%s)\n", ++ data->common.name, ret, get_mme_error_string (ret)); ++ return DFB_FAILURE; ++ } ++ ++ direct_hash_insert (data->common.pending_commands, ++ data->SetGlobalCommand.CmdStatus.CmdId, ++ (void *) 1); ++ D_DEBUG_AT (HWPNG, "sent packet's CmdId is %u (%.8x)\n", ++ data->SetGlobalCommand.CmdStatus.CmdId, ++ data->SetGlobalCommand.CmdStatus.CmdId); ++ pthread_mutex_unlock (&data->common.pending_commands_lock); ++ ++ return DFB_OK; ++} ++ ++ ++static void ++_imageprovider_update_transform_params (struct _MMECommon * const mme, ++ void * const params, ++ const CoreSurfaceBufferLock * const lock) ++{ ++ IDirectFBImageProvider_PNG_data * const data = ++ container_of (mme, IDirectFBImageProvider_PNG_data, common); ++ ++ if (data->GlobalReturnParams.pitch != lock->pitch) ++ { ++ PNGDecode_TransformParams_t * const p = params; ++ ++ p->flags |= PNGDECODE_PARAM_PITCH; ++ p->pitch = lock->pitch; ++ } ++} ++ ++ ++#define HWREND_THRESHOLD 20000 ++ ++static pthread_mutex_t transformer_index_mutex = PTHREAD_MUTEX_INITIALIZER; ++static unsigned int transformer_index; ++static DFBResult ++PNG_HardwareRenderTo( IDirectFBImageProvider_PNG_data *data, ++ CoreSurface *dst_surface, ++ DFBSurfacePixelFormat format, ++ DFBRectangle *rect, ++ const DFBRegion *clip ) ++{ ++ DFBResult dfbret = dfbret; ++ CoreSurfaceBufferLock lock; ++ unsigned int bufpos = 0; ++ ++ D_ASSERT( data != NULL ); ++ D_ASSERT( dst_surface != NULL); ++ D_ASSERT( rect != NULL ); ++ D_ASSERT( clip != NULL ); ++ ++ /* FIXME: check if the image is big enough to warrant a HW decode */ ++ if ((dst_surface->config.size.w * dst_surface->config.size.h) < HWREND_THRESHOLD) ++ return DFB_UNSUPPORTED; ++ ++ /* only decode if we haven't decoded before */ ++ if (data->common.decode_success <= 0) ++ { ++ MME_TransformerCapability_t cap; ++ bool surface_locked = false; ++ ++ data->common.name = "hwPNG"; ++ static const char *transformers0[] = { PNGDECODER_MME_TRANSFORMER_NAME"0", NULL }; ++ static const char *transformers1[] = { PNGDECODER_MME_TRANSFORMER_NAME"1", NULL }; ++ static const char *transformers2[] = { PNGDECODER_MME_TRANSFORMER_NAME"2", NULL }; ++ static const char *transformers3[] = { PNGDECODER_MME_TRANSFORMER_NAME"3", NULL }; ++ static const char *transformers4[] = { PNGDECODER_MME_TRANSFORMER_NAME"4", NULL }; ++ static const char *transformers5[] = { PNGDECODER_MME_TRANSFORMER_NAME, NULL }; ++ static const char **transformers[] = { transformers0, transformers1, ++ transformers2, transformers3, ++ transformers4, transformers5 }; ++ ++ unsigned i; ++ transformer_index = -1; ++ pthread_mutex_lock (&transformer_index_mutex); ++ for (i = 0; i < D_ARRAY_SIZE (transformers); ++i) ++ { ++ ++transformer_index; ++ transformer_index %= D_ARRAY_SIZE (transformers); ++ ++ PNGDecode_InitTransformerParams_t png_init; ++ png_init.flags = PNGDECODE_PARAM_FORMAT; ++ png_init.format = PNGDECODE_OF_EXPAND; ++ dfbret = mme_helper_init_transformer (&data->common, ++ transformers[transformer_index], ++ sizeof (png_init), ++ &png_init, NULL); ++ if (dfbret == DFB_OK) ++ { ++ /* need to init this because old transformer versions didn't ++ touch it at all. */ ++ cap.Version = 0; ++ _mme_helper_get_capability (&data->common, ++ *transformers[transformer_index], ++ &cap); ++ ++ if (cap.Version != 11) ++ { ++ /* incompatible with old transformer, it has just way too ++ many bugs! */ ++ mme_helper_deinit_transformer (&data->common); ++ dfbret = DFB_FAILURE; ++ continue; ++ } ++ ++ data->common.transformer_name = *transformers[transformer_index]; ++ if (data->flags & DIRENDER_BACKGROUND) ++ direct_thread_set_name (*transformers[transformer_index]); ++ ++ break; ++ } ++ } ++ pthread_mutex_unlock (&transformer_index_mutex); ++ ++ if (dfbret != DFB_OK) ++ return dfbret; ++ ++ sema_init_event (&data->common.decode_event, 0); /* Alerts to completion */ ++ sema_init_event (&data->global_event, 0); ++ ++ { ++ /* store the current data buffer position for software fallback should ++ we not succeed */ ++ data->common.base.buffer->GetPosition (data->common.base.buffer, ++ &bufpos); ++ ++ /* as an optimization we first send one packet, otherwise ++ SET_GLOBAL_TRANSFORM_COMMAND would through a data underflow event */ ++ mme_helper_calculate_packets (&data->common); ++ dfbret = mme_helper_send_packets (&data->common, 1); ++ if (dfbret != DFB_OK) ++ goto err_abort_commands; ++ ++ dfbret = set_global_transform_params (data); ++ if (dfbret != DFB_OK) ++ goto err_abort_commands; ++ ++ D_DEBUG_AT (HWPNG, " -> waiting for global transform to finish\n"); ++ while ((sema_wait_event (&data->global_event) == -1) ++ && errno == EINTR) ++ ; ++ D_DEBUG_AT (HWPNG, " -> global transform finished (failed: %c)\n", ++ (data->common.decode_success != 0) ? 'y' : 'n'); ++ ++ /* the transformer encountered an error */ ++ if (data->common.decode_success != 0) ++ { ++ dfbret = DFB_FAILURE; ++ goto err_abort_commands; ++ } ++ ++ if (!data->common.decode_surface) ++ { ++ /* create a destination surface to MME-decode the image onto before ++ stretchblit ... and if we can't create a surface in video ++ memory then we can't blit */ ++ CoreSurfaceConfig config; ++ CorePalette *palette = NULL; ++ ++ switch (data->GlobalReturnParams.ColorFormatOutput) ++ { ++ case PNGDECODE_COLOR_TYPE_PALETTE: ++ config.format = DSPF_LUT8; ++ ++ dfbret = dfb_palette_create (data->common.base.core, ++ 256, &palette); ++ if (dfbret != DFB_OK) ++ goto err_abort_commands; ++ ++ direct_memcpy (palette->entries, ++ data->GlobalReturnParams.palette, ++ 256 * sizeof (DFBColor)); ++ dfb_palette_update (palette, 0, 256 - 1); ++ break; ++ ++ case PNGDECODE_COLOR_TYPE_RGB: ++ config.format = DSPF_RGB24; ++ break; ++ ++ case PNGDECODE_COLOR_TYPE_RGB_ALPHA: ++ default: ++ config.format = DSPF_ARGB; ++ break; ++ } ++ config.flags = CSCONF_SIZE | CSCONF_FORMAT | CSCONF_CAPS; ++ config.size.w = data->common.width; ++ config.size.h = data->common.height; ++ config.caps = DSCAPS_VIDEOONLY; ++ #ifdef DIRECT_BUILD_DEBUG ++ config.caps |= DSCAPS_SHARED; ++ #endif ++ ++ dfbret = dfb_surface_create (data->common.base.core, &config, ++ CSTF_NONE, 0, palette, ++ &data->common.decode_surface); ++ if (palette) ++ dfb_palette_unref (palette); ++ ++ if (dfbret != DFB_OK) ++ goto err_abort_commands; ++ } ++ ++ /* tell the transformer what to do and where to put the result */ ++ data->TransformParams.flags = 0; ++ dfbret = mme_helper_start_transformer (&data->common, ++ sizeof (data->ReturnParams), ++ &data->ReturnParams, ++ sizeof (data->TransformParams), ++ &data->TransformParams, ++ data->common.decode_surface, ++ &lock); ++ if (dfbret != DFB_OK) ++ { ++ D_DEBUG_AT (HWPNG, "couldn't start transformer\n"); ++ goto err_abort_commands; ++ } ++ ++ surface_locked = true; ++ ++ /* Now send the rest of the data */ ++ D_DEBUG_AT (HWPNG, "Transform sent, sending data buffers now\n"); ++ dfbret = mme_helper_send_packets (&data->common, -1); ++ if (dfbret != DFB_OK) ++ { ++ D_DEBUG_AT (HWPNG, "couldn't send all buffers\n"); ++ goto err_abort_commands; ++ } ++ ++ /* wait until the decode is complete */ ++ D_DEBUG_AT (HWPNG, "waiting for completion\n"); ++ while ((sema_wait_event (&data->common.decode_event) == -1) ++ && errno == EINTR) ++ ; ++ /* the transformer encountered an error */ ++ if (data->common.decode_success != 1) ++ { ++ dfbret = DFB_FAILURE; ++ goto err_abort_commands; ++ } ++ } ++ ++err_abort_commands: ++ { ++ /* we need to do this explicitly here because the generic code will ++ not call abort_transformer() if no TransformCommand is pending. ++ Unfortunately in the PNG case, we always send a buffer before the ++ transform command. This buffer would otherwise not be aborted. ++ Should probably change the code to be more in line with JPEG. */ ++ abort_transformer (&data->common); ++ /* wait till all commands are aborted and acknowledged */ ++ while (data->common.n_pending_buffers ++ || direct_hash_lookup (data->common.pending_commands, ++ data->common.TransformCommand.CmdStatus.CmdId)) ++ usleep (1); ++ ++ if (surface_locked) ++ { ++ mme_helper_deinit_transformer (&data->common); ++ ++ dfb_surface_unlock_buffer (data->common.decode_surface, &lock); ++ } ++ ++ ++ if (data->common.OutDataBuffers) ++ { ++ D_FREE (data->common.OutDataBuffers); ++ data->common.OutDataBuffers = NULL; ++ } ++ ++ unsigned int i; ++ for (i = 0; i < D_ARRAY_SIZE (data->common.SendDataBuffers); ++i) ++ { ++ if (data->common.SendDataBuffers[i].buffer) ++ { ++ MME_FreeDataBuffer (data->common.SendDataBuffers[i].buffer); ++ data->common.SendDataBuffers[i].buffer = NULL; ++ ++ sema_close_event (&data->common.SendDataBuffers[i].sema); ++ } ++ } ++ ++ sema_close_event (&data->common.decode_event); ++ sema_close_event (&data->global_event); ++ ++ if (data->common.decode_success != 1) ++ { ++ /* if we saw corrupt data, there's no point in trying libpng, just ++ display the result as far as possible. */ ++ if (data->common.TransformCommand.CmdStatus.State == MME_COMMAND_FAILED ++ && data->common.TransformCommand.CmdStatus.Error == MME_INVALID_ARGUMENT) ++ { ++ const PNGDecode_TransformReturnParams_t * __restrict r = ++ &data->ReturnParams; ++ ++ switch (r->ErrorType) ++ { ++ case PNGDECODE_CRC_ERROR: ++ case PNGDECODE_INVALID_STREAM: ++ case PNGDECODE_STREAM_ERROR: ++ /* just assume invalid data and display what we have */ ++ D_DEBUG_AT (HWPNG, "faking success due to corrupt data\n"); ++ data->common.decode_success = 1; ++ ++ default: ++ break; ++ } ++ } ++ else if (dfbret == DFB_IO) ++ { ++ D_DEBUG_AT (HWPNG, "faking success due to EOF\n"); ++ dfbret = DFB_OK; ++ data->common.decode_success = 1; ++ } ++ ++ if (data->common.decode_success != 1) ++ data->common.base.buffer->SeekTo (data->common.base.buffer, ++ bufpos); ++ } ++ } ++ } ++ ++ ++ if (data->common.decode_success == 1) ++ { ++ /* stretch blit the decoded image to the destination surface and size */ ++ mme_helper_stretch_blit (&data->common, data->common.decode_surface, ++ dst_surface, rect); ++ dfbret = DFB_OK; ++ ++ if (data->GlobalReturnParams.HaveColorKey) ++ { ++ data->color_keyed = true; ++ data->color_key = data->GlobalReturnParams.ColorKey; ++ } ++ } ++ ++ return dfbret; ++} ++#endif /* PNG_PROVIDER_USE_MME */ +diff --git a/interfaces/IDirectFBImageProvider/idirectfbimageprovider_png.h b/interfaces/IDirectFBImageProvider/idirectfbimageprovider_png.h +new file mode 100644 +index 0000000..510a64d +--- /dev/null ++++ b/interfaces/IDirectFBImageProvider/idirectfbimageprovider_png.h +@@ -0,0 +1,83 @@ ++#ifndef __IDIRECTFBIMAGEPROVIDER_PNG_H__ ++#define __IDIRECTFBIMAGEPROVIDER_PNG_H__ ++ ++#if defined(PNG_PROVIDER_USE_MME) ++/* HW Decode Requirements */ ++#include ++#include ++ ++#define PNGDEC_MME_VERSION 11 ++#define PNGDECODE_PROFILING_ENABLE ++#include ++#endif /* PNG_PROVIDER_USE_MME */ ++ ++ ++/* private data struct of IDirectFBImageProvider_PNG */ ++typedef struct ++{ ++ struct _MMECommon common; ++ ++ int stage; ++ int rows; ++ ++ png_structp png_ptr; ++ png_infop info_ptr; ++ ++ int bpp; ++ int color_type; ++ png_uint_32 color_key; ++ bool color_keyed; ++ ++ int pitch; ++ u32 palette[256]; ++ DFBColor colors[256]; ++ ++ DFBRectangle rect; ++ DFBRegion clip; ++ ++ /* thread stuff */ ++ DIRenderFlags flags; ++ pthread_mutex_t lock; ++ pthread_cond_t cond; ++ DirectThread *thread; ++ IDirectFBSurface *destination; ++ DFBResult thread_res; ++ ++#if defined(PNG_PROVIDER_USE_MME) ++ PNGDecode_TransformParams_t TransformParams; ++ PNGDecode_TransformReturnParams_t ReturnParams; ++ ++ PNGDecode_GlobalTransformReturnParams_t GlobalReturnParams; ++ ++ MME_Command_t SetGlobalCommand; ++ ++ sem_t global_event; ++#endif /* PNG_PROVIDER_USE_MME */ ++} IDirectFBImageProvider_PNG_data; ++ ++ ++ ++#if defined(PNG_PROVIDER_USE_MME) ++/****************************************************************************/ ++static inline const char * ++get_png_error_string (PNGDecode_ErrorCodes_t e) ++{ ++ static const char *PNGErrorType_strings[] = { ++ "PNGDECODE_NO_ERROR", ++ "PNGDECODE_MEMEORY_ALLOCATION_ERROR", ++ "PNGDECODE_CRC_ERROR", ++ "PNGDECODE_INVALID_STREAM", ++ "PNGDECODE_INTERNAL_ERROR", ++ "PNGDECODE_INVALID_ARGUMENT", ++ "PNGDECODE_STREAM_ERROR" ++ }; ++ ++ return (((unsigned int) e) < D_ARRAY_SIZE (PNGErrorType_strings)) ++ ? PNGErrorType_strings[e] ++ : "* Unknown PngError code *"; ++} ++#endif /* PNG_PROVIDER_USE_MME */ ++ ++ ++ ++#endif /* __IDIRECTFBIMAGEPROVIDER_PNG_H__ */ +diff --git a/interfaces/IDirectFBImageProvider/idirectfbimageprovider_tiff.c b/interfaces/IDirectFBImageProvider/idirectfbimageprovider_tiff.c +new file mode 100644 +index 0000000..b67d851 +--- /dev/null ++++ b/interfaces/IDirectFBImageProvider/idirectfbimageprovider_tiff.c +@@ -0,0 +1,469 @@ ++/* ++ Copyright (c) 2013 Haithem Rahmani ++based on code: ++ (c) Copyright 2001-2013 The world wide DirectFB Open Source Community (directfb.org) ++ (c) Copyright 2000-2004 Convergence (integrated media) GmbH ++ ++ All rights reserved. ++ ++ Written by Haithem Rahmani ++ Based on code by: ++ Andre' Draszik , ++ Denis Oliver Kropp , ++ Andreas Hundt , ++ Sven Neumann , ++ Ville Syrjälä and ++ Claudio Ciccani . ++ ++ ++ ++ This library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2 of the License, or (at your option) any later version. ++ ++ This library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with this library; if not, write to the ++ Free Software Foundation, Inc., 59 Temple Place - Suite 330, ++ Boston, MA 02111-1307, USA. ++*/ ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++ ++#include ++ ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "config.h" ++ ++static DFBResult ++Probe( IDirectFBImageProvider_ProbeContext *ctx ); ++ ++static DFBResult ++Construct( IDirectFBImageProvider *thiz, ++ ... ); ++ ++#include ++ ++DIRECT_INTERFACE_IMPLEMENTATION( IDirectFBImageProvider, TIFF ) ++ ++ ++/* ++ * private data struct of IDirectFBImageProvider_TIFF ++ */ ++typedef struct { ++ IDirectFBImageProvider_data base; ++ ++ TIFF *tiff; ++ ++ int image_width; ++ int image_height; ++ ++ CoreSurface *decode_surface; ++ CoreGraphicsSerial *serial; ++ ++ DIRenderCallback render_callback; ++ void *render_callback_ctx; ++ ++} IDirectFBImageProvider_TIFF_data; ++ ++/* ++ * custom I/O functions to access TIFF Handle ++ */ ++static tsize_t ++_readTIFF( thandle_t, tdata_t, tsize_t ); ++ ++static tsize_t ++_writeTIFF( thandle_t, tdata_t, tsize_t ); ++ ++static toff_t ++_seekTIFF(thandle_t, toff_t, int); ++static int ++_closeTIFF(thandle_t); ++ ++static toff_t ++_sizeTIFF(thandle_t); ++ ++static int ++_mapdataTIFF(thandle_t, tdata_t*, toff_t*); ++ ++static void ++_unmapdataTIFF(thandle_t, tdata_t, toff_t); ++ ++static DirectResult ++IDirectFBImageProvider_TIFF_AddRef ( IDirectFBImageProvider *thiz ); ++ ++static DirectResult ++IDirectFBImageProvider_TIFF_Release ( IDirectFBImageProvider *thiz ); ++ ++static DFBResult ++IDirectFBImageProvider_TIFF_RenderTo( IDirectFBImageProvider *thiz, ++ IDirectFBSurface *destination, ++ const DFBRectangle *destination_rect ); ++ ++static DFBResult ++IDirectFBImageProvider_TIFF_SetRenderCallback( IDirectFBImageProvider *thiz, ++ DIRenderCallback callback, ++ void *context ); ++ ++static DFBResult ++IDirectFBImageProvider_TIFF_GetSurfaceDescription( IDirectFBImageProvider *thiz, ++ DFBSurfaceDescription *dsc ); ++ ++static DFBResult ++IDirectFBImageProvider_TIFF_GetImageDescription( IDirectFBImageProvider *thiz, ++ DFBImageDescription *dsc ); ++ ++ ++/**********************************************************************************************************************/ ++ ++static DFBResult ++Probe( IDirectFBImageProvider_ProbeContext *ctx ) ++{ ++ unsigned short tiff_magic = (ctx->header[0] | (ctx->header[1] << 8)); ++ ++ if ((tiff_magic != TIFF_BIGENDIAN) && ++ (tiff_magic != TIFF_LITTLEENDIAN) && ++ (tiff_magic != MDI_LITTLEENDIAN)) ++ { ++ return DFB_UNSUPPORTED; ++ } ++ ++ return DFB_OK; ++} ++ ++static DFBResult ++Construct( IDirectFBImageProvider *thiz, ++ ... ) ++{ ++ IDirectFBDataBuffer *buffer; ++ CoreDFB *core; ++ va_list tag; ++ ++ DIRECT_ALLOCATE_INTERFACE_DATA(thiz, IDirectFBImageProvider_TIFF) ++ ++ va_start( tag, thiz ); ++ buffer = va_arg( tag, IDirectFBDataBuffer * ); ++ core = va_arg( tag, CoreDFB * ); ++ va_end( tag ); ++ ++ data->base.ref = 1; ++ data->base.buffer = buffer; ++ data->base.core = core; ++ ++ buffer->AddRef( buffer ); ++ ++ data->tiff = TIFFClientOpen( "TIFF", "rM", (thandle_t)data, _readTIFF, ++ _writeTIFF, _seekTIFF, _closeTIFF, ++ _sizeTIFF, _mapdataTIFF, _unmapdataTIFF ); ++ ++ TIFFGetField( data->tiff, TIFFTAG_IMAGEWIDTH, &data->image_width ); ++ TIFFGetField( data->tiff, TIFFTAG_IMAGELENGTH, &data->image_height ); ++ if (!data->tiff) ++ { ++ buffer->Release( buffer ); ++ data->base.buffer = NULL; ++ DIRECT_DEALLOCATE_INTERFACE( thiz ); ++ return DFB_FAILURE; ++ } ++ ++ thiz->AddRef = IDirectFBImageProvider_TIFF_AddRef; ++ thiz->Release = IDirectFBImageProvider_TIFF_Release; ++ thiz->RenderTo = IDirectFBImageProvider_TIFF_RenderTo; ++ thiz->SetRenderCallback = IDirectFBImageProvider_TIFF_SetRenderCallback; ++ thiz->GetImageDescription = IDirectFBImageProvider_TIFF_GetImageDescription; ++ thiz->GetSurfaceDescription = IDirectFBImageProvider_TIFF_GetSurfaceDescription; ++ ++ return DFB_OK; ++} ++ ++/**********************************************************************************************************************/ ++ ++static void ++IDirectFBImageProvider_TIFF_Destruct( IDirectFBImageProvider *thiz ) ++{ ++ IDirectFBImageProvider_TIFF_data *data = ++ (IDirectFBImageProvider_TIFF_data*)thiz->priv; ++ ++ if (data->decode_surface) { ++ dfb_gfxcard_wait_serial( data->serial ); ++ dfb_surface_unref( data->decode_surface ); ++ } ++ ++ if (data->base.buffer) ++ data->base.buffer->Release( data->base.buffer ); ++ ++ DIRECT_DEALLOCATE_INTERFACE( thiz ); ++} ++ ++static DirectResult ++IDirectFBImageProvider_TIFF_AddRef( IDirectFBImageProvider *thiz ) ++{ ++ DIRECT_INTERFACE_GET_DATA (IDirectFBImageProvider_TIFF) ++ data->base.ref++; ++ ++ return DFB_OK; ++} ++ ++static DirectResult ++IDirectFBImageProvider_TIFF_Release( IDirectFBImageProvider *thiz ) ++{ ++ DIRECT_INTERFACE_GET_DATA( IDirectFBImageProvider_TIFF ) ++ ++ if (--data->base.ref == 0) { ++ IDirectFBImageProvider_TIFF_Destruct( thiz ); ++ } ++ ++ return DFB_OK; ++} ++ ++/**********************************************************************************************************************/ ++ ++static DFBResult ++IDirectFBImageProvider_TIFF_RenderTo( IDirectFBImageProvider *thiz, ++ IDirectFBSurface *destination, ++ const DFBRectangle *dest_rect ) ++{ ++ DFBResult ret; ++ DFBRegion clip; ++ ++ IDirectFBSurface_data *dst_data; ++ ++ CoreSurface *dst_surface; ++ CardState state; ++ ++ CoreSurfaceBufferLock lock; ++ ++ DFBRectangle rect; ++ DFBRectangle src_rect; ++ ++ DIRECT_INTERFACE_GET_DATA (IDirectFBImageProvider_TIFF) ++ ++ dst_data = (IDirectFBSurface_data*) destination->priv; ++ if (!dst_data) ++ return DFB_DEAD; ++ ++ dst_surface = dst_data->surface; ++ if (!dst_surface) ++ return DFB_DESTROYED; ++ ++ dfb_region_from_rectangle( &clip, &dst_data->area.current ); ++ ++ if (dest_rect) { ++ if (dest_rect->w < 1 || dest_rect->h < 1) ++ return DFB_INVARG; ++ rect = *dest_rect; ++ rect.x += dst_data->area.wanted.x; ++ rect.y += dst_data->area.wanted.y; ++ } ++ else { ++ rect = dst_data->area.wanted; ++ } ++ ++ if (!dfb_rectangle_region_intersects( &rect, &clip )) ++ return DFB_OK; ++ ++ ret = dfb_surface_create_simple( data->base.core, data->image_width, data->image_height, DSPF_ARGB, ++ DSCS_RGB, DSCAPS_NONE, CSTF_NONE, ++ 0, NULL, &data->decode_surface ); ++ ++ ret = dfb_surface_lock_buffer( data->decode_surface, CSBR_BACK, CSAID_CPU, CSAF_WRITE, &lock ); ++ if (ret) { ++ D_PERROR( "Failed to create decode surface\n" ); ++ goto error; ++ } ++ ++ TIFFReadRGBAImageOriented( data->tiff, data->image_width, data->image_height, ++ (uint32 *)(lock.addr), ORIENTATION_TOPLEFT, 0 ); ++ ++ dfb_surface_unlock_buffer( data->decode_surface, &lock ); ++ ++ dfb_state_init( &state, data->base.core ); ++ ++ state.modified |= SMF_CLIP; ++ ++ state.clip = DFB_REGION_INIT_FROM_RECTANGLE_VALS( rect.x, rect.y, rect.w, rect.h ); ++ src_rect = (DFBRectangle){0, 0, data->image_width, data->image_height}; ++ ++ dfb_state_set_source( &state, data->decode_surface ); ++ dfb_state_set_destination( &state, dst_surface ); ++ ++ dfb_gfxcard_batchstretchblit( &src_rect, &rect, 1, &state ); ++ ++ data->serial = &state.serial; ++ ++ dfb_gfxcard_wait_serial( &data->serial ); ++ dfb_surface_unref( data->decode_surface ); ++ data->decode_surface = NULL; ++ ++ dfb_state_set_source( &state, NULL ); ++ dfb_state_set_destination( &state, NULL ); ++ ++ dfb_state_destroy( &state ); ++ ++ if (data->render_callback) { ++ DIRenderCallbackResult r; ++ ++ rect.x = 0; ++ rect.y = 0; ++ rect.w = data->image_width; ++ rect.h = data->image_height; ++ ++ r = data->render_callback( &rect, data->render_callback_ctx ); ++ ++ if (r != DIRCR_OK) ++ return DFB_INTERRUPTED; ++ } ++ ++ return DFB_OK; ++ ++error: ++ dfb_surface_unref( data->decode_surface ); ++ return ret; ++} ++ ++static DFBResult ++IDirectFBImageProvider_TIFF_SetRenderCallback( IDirectFBImageProvider *thiz, ++ DIRenderCallback callback, ++ void *context ) ++{ ++ DIRECT_INTERFACE_GET_DATA( IDirectFBImageProvider_TIFF ) ++ ++ data->render_callback = callback; ++ data->render_callback_ctx = context; ++ ++ return DFB_OK; ++} ++ ++static DFBResult ++IDirectFBImageProvider_TIFF_GetSurfaceDescription( IDirectFBImageProvider *thiz, ++ DFBSurfaceDescription *dsc ) ++{ ++ DIRECT_INTERFACE_GET_DATA( IDirectFBImageProvider_TIFF ) ++ ++ dsc->flags = DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT; ++ dsc->width = data->image_width; ++ dsc->height = data->image_height; ++ dsc->pixelformat = DSPF_ARGB; ++ ++ return DFB_OK; ++} ++ ++static DFBResult ++IDirectFBImageProvider_TIFF_GetImageDescription( IDirectFBImageProvider *thiz, ++ DFBImageDescription *dsc ) ++{ ++ DIRECT_INTERFACE_GET_DATA( IDirectFBImageProvider_TIFF ) ++ ++ dsc->caps = DICAPS_NONE; ++ ++ return DFB_OK; ++} ++ ++static tsize_t ++_readTIFF(thandle_t handle, tdata_t data, tsize_t size) ++{ ++ unsigned int ret_size; ++ ++ IDirectFBImageProvider_TIFF_data *priv = (IDirectFBImageProvider_TIFF_data*)handle; ++ priv->base.buffer->GetData( priv->base.buffer, size, data, &ret_size ); ++ ++ return (tsize_t)ret_size; ++} ++ ++static tsize_t ++_writeTIFF( thandle_t handle, tdata_t data, tsize_t size ) ++{ ++ return -1; ++} ++static toff_t ++_seekTIFF( thandle_t handle, toff_t offset, int whence ) ++{ ++ unsigned int off; ++ ++ IDirectFBImageProvider_TIFF_data *data = (IDirectFBImageProvider_TIFF_data*)handle; ++ ++ switch (whence) ++ { ++ case SEEK_SET: ++ off = offset; ++ break; ++ case SEEK_CUR: ++ data->base.buffer->GetPosition( data->base.buffer, &off ); ++ off += offset; ++ break; ++ case SEEK_END: ++ data->base.buffer->GetLength( data->base.buffer, &off ); ++ off += offset; ++ break; ++ default: ++ break; ++ } ++ ++ data->base.buffer->SeekTo( data->base.buffer, off ); ++ ++ return (tsize_t)off; ++} ++ ++static int ++_closeTIFF( thandle_t handle ) ++{ ++ return 0; ++} ++ ++static toff_t ++_sizeTIFF( thandle_t handle ) ++{ ++ unsigned int length; ++ ++ IDirectFBImageProvider_TIFF_data *data = (IDirectFBImageProvider_TIFF_data*)handle; ++ ++ data->base.buffer->GetLength( data->base.buffer, &length ); ++ ++ return (toff_t)length; ++} ++ ++static int ++_mapdataTIFF(thandle_t handle, tdata_t* data, toff_t* offset) ++{ ++ return 0; ++} ++ ++static void ++_unmapdataTIFF( thandle_t handle, tdata_t data, toff_t offset ) ++{ ++} +diff --git a/interfaces/IDirectFBImageProvider/idirectfbimageprovider_webp.c b/interfaces/IDirectFBImageProvider/idirectfbimageprovider_webp.c +new file mode 100644 +index 0000000..fdce208 +--- /dev/null ++++ b/interfaces/IDirectFBImageProvider/idirectfbimageprovider_webp.c +@@ -0,0 +1,390 @@ ++/* ++ Copyright (c) 2013 Haithem Rahmani ++based on code: ++ (c) Copyright 2001-2013 The world wide DirectFB Open Source Community (directfb.org) ++ (c) Copyright 2000-2004 Convergence (integrated media) GmbH ++ ++ All rights reserved. ++ ++ Written by Haithem Rahmani ++ Based on code by: ++ Andre' Draszik , ++ Denis Oliver Kropp , ++ Andreas Hundt , ++ Sven Neumann , ++ Ville Syrjälä and ++ Claudio Ciccani . ++ ++ ++ ++ This library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2 of the License, or (at your option) any later version. ++ ++ This library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with this library; if not, write to the ++ Free Software Foundation, Inc., 59 Temple Place - Suite 330, ++ Boston, MA 02111-1307, USA. ++*/ ++ ++#include ++ ++#include ++#include ++#include ++ ++#include ++ ++#include ++ ++#include ++ ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++ ++D_DEBUG_DOMAIN( imageProviderWebP, "ImageProvider/WebP", "libWebP based image decoder" ); ++ ++static DFBResult Probe( IDirectFBImageProvider_ProbeContext *ctx ); ++ ++static DFBResult Construct( IDirectFBImageProvider *thiz, ++ ... ); ++ ++#include ++ ++DIRECT_INTERFACE_IMPLEMENTATION( IDirectFBImageProvider, WebP ) ++ ++typedef struct { ++ IDirectFBImageProvider_data base; ++ ++ WebPDecoderConfig config; /* WebP decoder config to intialize before starting the decoding */ ++ ++ int width; /* image width */ ++ int height; /* image height */ ++ DFBSurfacePixelFormat pixelformat; /* image pixelformat DSPF_ARGB or DFB_RGB24 */ ++ uint32_t image_size; /* image data size */ ++ ++ CoreSurface *decode_surface; /* surface containing the decoded image*/ ++ CoreGraphicsSerial *serial; ++} IDirectFBImageProvider_WebP_data; ++ ++static void ++IDirectFBImageProvider_WebP_Destruct( IDirectFBImageProvider *thiz ) ++{ ++ IDirectFBImageProvider_WebP_data *data = thiz->priv; ++ ++ if (data->decode_surface) { ++ dfb_gfxcard_wait_serial( data->serial ); ++ dfb_surface_unref( data->decode_surface ); ++ } ++ ++ if (data->base.buffer) ++ data->base.buffer->Release( data->base.buffer ); ++} ++ ++static DFBResult ++WebP_decode_image( IDirectFBImageProvider_WebP_data *data, ++ CoreSurfaceBufferLock *lock ) ++{ ++ VP8StatusCode status; ++ DFBResult ret; ++ ++ uint32_t read_size; ++ u8 image[data->image_size]; ++ ++ WebPIDecoder* WebP_dec; ++ IDirectFBDataBuffer *buffer = data->base.buffer; ++ ++ WebP_dec = WebPINewDecoder( &data->config.output ); ++ ++ data->config.output.colorspace = (data->pixelformat == DSPF_ARGB) ? MODE_bgrA : MODE_BGR; ++ ++ data->config.output.u.RGBA.rgba = (uint8_t*)lock->addr; ++ data->config.output.u.RGBA.stride = lock->pitch; ++ data->config.output.u.RGBA.size = lock->pitch * data->height; ++ ++ data->config.output.is_external_memory = 1; ++ ++ ret = DFB_OK; ++ buffer->SeekTo( buffer, 0 ); ++ ++ while (ret != DFB_EOF && buffer->HasData( buffer ) == DFB_OK) { ++ ret = buffer->GetData( buffer, data->image_size, image, &read_size ); ++ ++ status = WebPIAppend( WebP_dec, image, read_size ); ++ if (!(status == VP8_STATUS_OK || status == VP8_STATUS_SUSPENDED)) ++ break; ++ } ++ ++ WebPIDelete( WebP_dec ); ++ ++ return (status == VP8_STATUS_OK) ? DFB_OK : DFB_FAILURE; ++} ++ ++static DFBResult ++IDirectFBImageProvider_WebP_RenderTo( IDirectFBImageProvider *thiz, ++ IDirectFBSurface *destination, ++ const DFBRectangle *dest_rect ) ++{ ++ DFBResult ret; ++ ++ DFBRegion clip; ++ CoreSurface *dst_surface; ++ CardState state; ++ ++ CoreSurfaceBufferLock lock; ++ ++ IDirectFBSurface_data *dst_data; ++ DIRenderCallbackResult cb_result = DIRCR_OK; ++ ++ DFBRectangle src_rect; ++ DFBRectangle rect; ++ ++ DIRECT_INTERFACE_GET_DATA( IDirectFBImageProvider_WebP ) ++ ++ if (!destination) ++ return DFB_INVARG; ++ ++ dst_data = destination->priv; ++ if (!dst_data || !dst_data->surface) ++ return DFB_DESTROYED; ++ ++ dst_surface = dst_data->surface; ++ ++ if (dest_rect) { ++ if (dest_rect->w < 1 || dest_rect->h < 1) ++ return DFB_INVARG; ++ ++ rect = *dest_rect; ++ rect.x += dst_data->area.wanted.x; ++ rect.y += dst_data->area.wanted.y; ++ } ++ else { ++ rect = dst_data->area.wanted; ++ } ++ ++ dfb_region_from_rectangle( &clip, &dst_data->area.current ); ++ if (!dfb_rectangle_region_intersects( &rect, &clip )) ++ return DFB_OK; ++ ++ ++ ret = dfb_surface_create_simple( data->base.core, data->width, data->height, data->pixelformat, ++ DSCS_RGB, DSCAPS_NONE, CSTF_NONE, ++ 0, NULL, &data->decode_surface ); ++ if (ret) { ++ D_ERROR( "Failed to create surface : '%s'\n", DirectResultString(ret) ); ++ goto error; ++ } ++ ++ ret = dfb_surface_lock_buffer( data->decode_surface, CSBR_BACK, CSAID_CPU, CSAF_WRITE, &lock ); ++ if (ret) { ++ D_ERROR( "Failed to lock the surface : '%s'\n", DirectResultString(ret) ); ++ goto error; ++ } ++ ++ ret = WebP_decode_image( data, &lock ); ++ if (ret) { ++ D_ERROR( "Failed to decode the image : '%s'\n", DirectResultString(ret) ); ++ goto error; ++ } ++ ++ dfb_surface_unlock_buffer( data->decode_surface, &lock ); ++ ++ dfb_state_init( &state, data->base.core ); ++ ++ state.modified |= SMF_CLIP; ++ ++ state.clip = DFB_REGION_INIT_FROM_RECTANGLE_VALS( rect.x, rect.y, rect.w, rect.h ); ++ src_rect = (DFBRectangle){0, 0, data->width, data->height}; ++ ++ dfb_state_set_source( &state, data->decode_surface ); ++ dfb_state_set_destination( &state, dst_surface ); ++ ++ dfb_gfxcard_stretchblit( &src_rect, &rect, &state ); ++ ++ data->serial = &state.serial; ++ ++ dfb_gfxcard_wait_serial( data->serial ); ++ dfb_surface_unref( data->decode_surface ); ++ ++ dfb_state_set_source(&state, NULL); ++ dfb_state_set_destination(&state, NULL); ++ ++ dfb_state_destroy(&state); ++ ++ if (data->base.render_callback) { ++ DFBRectangle r = { 0, 0, data->width, data->height }; ++ cb_result=data->base.render_callback( &r, data->base.render_callback_context ); ++ } ++ ++ return DFB_OK; ++ ++error: ++ if (data->decode_surface && lock.pitch) ++ dfb_surface_unlock_buffer( data->decode_surface, &lock ); ++ ++ dfb_surface_unref( data->decode_surface ); ++ ++ return ret; ++} ++ ++static DFBResult ++IDirectFBImageProvider_WebP_SetRenderCallback( IDirectFBImageProvider *thiz, ++ DIRenderCallback callback, ++ void *ctx ) ++{ ++ DIRECT_INTERFACE_GET_DATA( IDirectFBImageProvider_WebP ) ++ ++ data->base.render_callback = callback; ++ data->base.render_callback_context = ctx; ++ ++ return DFB_OK; ++} ++ ++static DFBResult ++IDirectFBImageProvider_WebP_GetImageDescription( IDirectFBImageProvider *thiz, ++ DFBImageDescription *desc ) ++{ ++ DIRECT_INTERFACE_GET_DATA( IDirectFBImageProvider_WebP ) ++ ++ if (!desc) ++ return DFB_INVARG; ++ ++ desc->caps = DFB_PIXELFORMAT_HAS_ALPHA( data->pixelformat ) ? DICAPS_ALPHACHANNEL : DICAPS_NONE; ++ ++ return DFB_OK; ++} ++ ++static DFBResult ++IDirectFBImageProvider_WebP_GetSurfaceDescription( IDirectFBImageProvider *thiz, ++ DFBSurfaceDescription *desc ) ++{ ++ DIRECT_INTERFACE_GET_DATA( IDirectFBImageProvider_WebP ) ++ ++ if (!desc) ++ return DFB_INVARG; ++ ++ desc->flags = DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT | DSDESC_CAPS; ++ ++ desc->caps = DFB_PIXELFORMAT_HAS_ALPHA( data->pixelformat ) ? DSCAPS_PREMULTIPLIED : DSCAPS_NONE; ++ ++ desc->width = data->width; ++ desc->height = data->height; ++ ++ desc->pixelformat = data->pixelformat; ++ ++ return DFB_OK; ++} ++ ++static DFBResult ++Probe( IDirectFBImageProvider_ProbeContext *ctx ) ++{ ++ ++ if (WebPGetInfo( ctx->header, D_ARRAY_SIZE( ctx->header ), NULL, NULL ) != 0) ++ return DFB_OK; ++ ++ return DFB_UNSUPPORTED; ++} ++ ++static DFBResult ++get_image_features( IDirectFBImageProvider_WebP_data *data ) ++{ ++ u32 buffer_size = 32; ++ u32 read = 0; ++ u8 buffer[buffer_size]; ++ ++ WebPBitstreamFeatures image_features; ++ DFBResult ret; ++ ++ ret = data->base.buffer->WaitForData( data->base.buffer, buffer_size ); ++ ++ /* ++ * Get the actual image size manually ++ * as webp api doesn't return that info ++ */ ++ if (ret == DFB_OK) ++ ret = data->base.buffer->PeekData( data->base.buffer, 4, 4, &data->image_size, &read ); ++ ++ data->image_size += 8; ++ ++ ret = data->base.buffer->PeekData( data->base.buffer, buffer_size, 0, buffer, &read ); ++ if (ret) ++ return ret; ++ ++ if (WebPGetFeatures( buffer, buffer_size, &image_features ) != VP8_STATUS_OK) ++ return DFB_FAILURE; ++ ++ data->width = image_features.width; ++ data->height = image_features.height; ++ data->pixelformat = image_features.has_alpha ? DSPF_ARGB : DSPF_RGB24; ++ ++ return DFB_OK; ++} ++ ++static DFBResult ++Construct( IDirectFBImageProvider *thiz, ++ ... ) ++{ ++ IDirectFBDataBuffer *buffer; ++ CoreDFB *core; ++ va_list tag; ++ ++ D_DEBUG_AT( imageProviderWebP, "%s(%d)\n", __FUNCTION__, __LINE__ ); ++ ++ DIRECT_ALLOCATE_INTERFACE_DATA(thiz, IDirectFBImageProvider_WebP) ++ ++ va_start( tag, thiz ); ++ buffer = va_arg( tag, IDirectFBDataBuffer * ); ++ core = va_arg( tag, CoreDFB * ); ++ va_end( tag ); ++ ++ data->base.ref = 1; ++ data->base.buffer = buffer; ++ data->base.core = core; ++ ++ /* Increase the data buffer reference counter. */ ++ buffer->AddRef( buffer ); ++ ++ if (get_image_features( data )) ++ goto error; ++ ++ D_DEBUG_AT( imageProviderWebP, "%s( %dx%d -%s)\n", __FUNCTION__, data->width, ++ data->height, dfb_pixelformat_name( data->pixelformat ) ); ++ ++ data->base.Destruct = IDirectFBImageProvider_WebP_Destruct; ++ ++ thiz->RenderTo = IDirectFBImageProvider_WebP_RenderTo; ++ thiz->GetImageDescription = IDirectFBImageProvider_WebP_GetImageDescription; ++ thiz->GetSurfaceDescription = IDirectFBImageProvider_WebP_GetSurfaceDescription; ++ thiz->SetRenderCallback = IDirectFBImageProvider_WebP_SetRenderCallback; ++ ++ return DFB_OK; ++ ++error: ++ buffer->Release( buffer ); ++ DIRECT_DEALLOCATE_INTERFACE(thiz); ++ ++ return DFB_FAILURE; ++} +diff --git a/interfaces/IDirectFBImageProvider/mme/mme.h b/interfaces/IDirectFBImageProvider/mme/mme.h +new file mode 100644 +index 0000000..b29d243 +--- /dev/null ++++ b/interfaces/IDirectFBImageProvider/mme/mme.h +@@ -0,0 +1,586 @@ ++/************************************************************** ++ * Copyright (C) 2010 STMicroelectronics. All Rights Reserved. ++ * This file is part of the latest release of the Multicom4 project. This release ++ * is fully functional and provides all of the original MME functionality.This ++ * release is now considered stable and ready for integration with other software ++ * components. ++ ++ * Multicom4 is a free software; you can redistribute it and/or modify it under the ++ * terms of the GNU General Public License as published by the Free Software Foundation ++ * version 2. ++ ++ * Multicom4 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 General Public License for more details. ++ ++ * You should have received a copy of the GNU General Public License along with Multicom4; ++ * see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - ++ * Suite 330, Boston, MA 02111-1307, USA. ++ ++ * Written by Multicom team at STMicroelectronics in November 2010. ++ * Contact multicom.support@st.com. ++**************************************************************/ ++ ++/* ++ * ++ */ ++ ++#ifndef _MME_H ++#define _MME_H ++ ++#ifdef __cplusplus ++extern "C" { ++#endif /* __cplusplus */ ++ ++/* Constants */ ++ ++#define MME_MAX_TRANSFORMER_NAME (63U) ++ ++#define MME_MAX_CACHE_LINE (32) ++#define MME_CACHE_LINE_ALIGN(X) ((void*)(((unsigned) (X) + (MME_MAX_CACHE_LINE-1)) & ~(MME_MAX_CACHE_LINE-1))) ++#define MME_CACHE_LINE_ALIGNED(X) (((unsigned) (X) & (MME_MAX_CACHE_LINE-1)) == 0) ++ ++/* Aliased names for some of the inconsistently named (or simply overly long) identifiers */ ++ ++#define MME_Deinit MME_Term ++#define MME_Error_t MME_ERROR ++#define MME_NO_MEMORY MME_NOMEM ++#define MME_SET_GLOBAL_TRANSFORM_PARAMS MME_SET_PARAMS ++#define MME_EMBX_ERROR MME_ICS_ERROR ++ ++/* Version info */ ++ ++#define __MULTICOM_VERSION__ "4.0.51 : Orly" ++#define __MULTICOM_VERSION_MAJOR__ (4) ++#define __MULTICOM_VERSION_MINOR__ (0) ++#define __MULTICOM_VERSION_PATCH__ (51) ++ ++/* Version macros like the ones found in Linux */ ++#define MULTICOM_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) ++#define MULTICOM_VERSION_CODE MULTICOM_VERSION(__MULTICOM_VERSION_MAJOR__, __MULTICOM_VERSION_MINOR__, __MULTICOM_VERSION_PATCH__) ++ ++/* Enumerations */ ++ ++/* MME_AllocationFlags_t: ++ * Used to qualify MME_DataBuffer_t memory allocation ++ */ ++typedef enum MME_AllocationFlags_t { ++ MME_ALLOCATION_PHYSICAL = 1, ++ MME_ALLOCATION_CACHED = 2, ++ MME_ALLOCATION_UNCACHED = 4 ++} MME_AllocationFlags_t; ++ ++/* MME_CommandCode_t: ++ * Used to specify a command to a transformer ++ */ ++typedef enum MME_CommandCode_t { ++ MME_SET_PARAMS, ++ MME_TRANSFORM, ++ MME_SEND_BUFFERS, ++ MME_PING /* MME4 API extension */ ++} MME_CommandCode_t; ++ ++/* MME_CommandState_t: ++ * Used to specify the current state of a submitted command ++ */ ++typedef enum MME_CommandState_t { ++ MME_COMMAND_IDLE, ++ MME_COMMAND_PENDING, ++ MME_COMMAND_EXECUTING, ++ MME_COMMAND_COMPLETED, ++ MME_COMMAND_FAILED ++} MME_CommandState_t; ++ ++/* MME_CommandEndType_t: ++ * Used to specify whether the Client callback or Wake ++ * should be actioned on command completion ++ * ++ * MME_COMMAND_END_RETURN_NO_INFO - No Callback/Wake ++ * MME_COMMAND_END_RETURN_NOTIFY - Call Client callback ++ * MME_COMMAND_END_RETURN_WAKE - Wakeup MME_Wait() call ++ */ ++typedef enum MME_CommandEndType_t { ++ MME_COMMAND_END_RETURN_NO_INFO, ++ MME_COMMAND_END_RETURN_NOTIFY, ++ MME_COMMAND_END_RETURN_WAKE /* MME4 API extension */ ++} MME_CommandEndType_t; ++ ++/* MME_Event_t: ++ * Used to indicate a transform event type to the Client callback ++ */ ++typedef enum MME_Event_t { ++ MME_COMMAND_COMPLETED_EVT, ++ MME_DATA_UNDERFLOW_EVT, ++ MME_NOT_ENOUGH_MEMORY_EVT, ++ MME_NEW_COMMAND_EVT, ++ MME_TRANSFORMER_TIMEOUT ++} MME_Event_t; ++ ++ ++/* MME_ERROR: ++ * The errors that may be returned by MME API functions or by ++ * transformer entry point functions ++ */ ++typedef enum MME_ERROR { ++ MME_SUCCESS = 0, ++ MME_DRIVER_NOT_INITIALIZED = 1, ++ MME_DRIVER_ALREADY_INITIALIZED = 2, ++ MME_NOMEM = 3, ++ MME_INVALID_TRANSPORT = 4, /* DEPRECATED */ ++ MME_INVALID_HANDLE = 5, ++ MME_INVALID_ARGUMENT = 6, ++ MME_UNKNOWN_TRANSFORMER = 7, ++ MME_TRANSFORMER_NOT_RESPONDING = 8, ++ MME_HANDLES_STILL_OPEN = 9, ++ MME_COMMAND_STILL_EXECUTING = 10, ++ MME_COMMAND_ABORTED = 11, ++ MME_DATA_UNDERFLOW = 12, ++ MME_DATA_OVERFLOW = 13, ++ MME_TRANSFORM_DEFERRED = 14, ++ MME_SYSTEM_INTERRUPT = 15, ++ MME_ICS_ERROR = 16, ++ MME_INTERNAL_ERROR = 17, ++ MME_NOT_IMPLEMENTED = 18, ++ MME_COMMAND_TIMEOUT = 19 /* MME4 API extension */ ++} MME_ERROR; ++ ++/* MME_CacheFlags_t ++ * Cache management flags used allow optimizations to be applied ++ * for each MME_ScatterPage_t (FlagsIn/FlagsOut) ++ */ ++typedef enum MME_CacheFlags_t { ++ MME_DATA_CACHE_COHERENT = (1 << 31), /* In/Out: Memory/Page is already coherent with cache */ ++ MME_DATA_TRANSIENT = (1 << 30), /* In: Cache flush is not necessary in Companion */ ++ MME_REMOTE_CACHE_COHERENT = (1 << 29), /* Out: Remote Page translation should be COHERENT */ ++ MME_DATA_PHYSICAL = (1 << 28) /* In/Out: Memory address is Physical don't translate */ ++} MME_CacheFlags_t; ++ ++/* MME_Tuneable_t: ++ * Keys used to modify tuneable parameters ++ */ ++typedef enum { ++ /* no need to MME_THREAD_STACK_SIZE, this is managed by the ICS call */ ++ MME_TUNEABLE_MANAGER_THREAD_PRIORITY, ++ MME_TUNEABLE_TRANSFORMER_THREAD_PRIORITY, ++ MME_TUNEABLE_EXECUTION_LOOP_HIGHEST_PRIORITY, ++ MME_TUNEABLE_EXECUTION_LOOP_ABOVE_NORMAL_PRIORITY, ++ MME_TUNEABLE_EXECUTION_LOOP_NORMAL_PRIORITY, ++ MME_TUNEABLE_EXECUTION_LOOP_BELOW_NORMAL_PRIORITY, ++ MME_TUNEABLE_EXECUTION_LOOP_LOWEST_PRIORITY, ++ /* TIMEOUT SUPPORT - allow default timeout to be modified */ ++ MME_TUNEABLE_TRANSFORMER_TIMEOUT, ++ MME_TUNEABLE_BUFFER_POOL_SIZE, /* MME4 API Extension */ ++ MME_TUNEABLE_COMMAND_TIMEOUT, /* MME4 API Extension */ ++ ++ MME_TUNEABLE_MAX ++} MME_Tuneable_t; ++ ++/* MME_Priority_t: ++ * The MME scheduler priority at which a transform is executed ++ */ ++typedef enum MME_Priority_t { ++ MME_PRIORITY_HIGHEST = 5000, ++ MME_PRIORITY_ABOVE_NORMAL = 4000, ++ MME_PRIORITY_NORMAL = 3000, ++ MME_PRIORITY_BELOW_NORMAL = 2000, ++ MME_PRIORITY_LOWEST = 1000 ++} MME_Priority_t; ++ ++/* Types: simple */ ++ ++/* CPU architecture-specific */ ++ ++#if defined __sh__ || defined(__st200__) || defined(__ILP32__) || defined(__arm__) ++/* SH4/ST40 */ ++typedef unsigned int MME_UINT; ++typedef unsigned long MME_ULONG; ++typedef unsigned long MME_SIZE; ++typedef double MME_GENERIC64; ++#define MME_MaxTime_c 0xffffffff ++#else ++#error Unsupported CPU type ++#endif ++ ++/* TIMEOUT SUPPORT: Maximum timeout value which basically means don't timeout */ ++#define MME_TIMEOUT_INFINITE MME_MaxTime_c ++ ++/* Architecture neutral */ ++/* MME_Time_t: ++ * MME time ++ */ ++typedef MME_UINT MME_Time_t; ++ ++/* MME_GenericParams_t: ++ * A transformer specific parameter ++ */ ++typedef void* MME_GenericParams_t; ++ ++/* MME_CommandId_t: ++ * The identifier assigned by MME to a submitted command ++ */ ++typedef MME_UINT MME_CommandId_t; ++ ++/* MME_TransformerHandle_t: ++ * The handle of a transformer instance assigned by MME ++ */ ++typedef MME_UINT MME_TransformerHandle_t; ++ ++/* MME_MemoryHandle_t: ++ * The handle of a registered memory region assigned by MME ++ */ ++typedef MME_UINT MME_MemoryHandle_t; ++ ++/* Types: structures */ ++ ++/* MME_CommandStatus_t: ++ * Structure containing state associated with a command ++ */ ++typedef struct MME_CommandStatus_t { ++ MME_CommandId_t CmdId; ++ MME_CommandState_t State; ++ MME_Time_t ProcessedTime; ++ MME_ERROR Error; ++ MME_UINT AdditionalInfoSize; ++ MME_GenericParams_t AdditionalInfo_p; ++} MME_CommandStatus_t; ++ ++/* MME_ScatterPage_t: ++ * Structure describing a single scatter page - see MME_DataBuffer_t ++ */ ++typedef struct MME_ScatterPage_t { ++ void* Page_p; ++ MME_UINT Size; ++ MME_UINT BytesUsed; ++ MME_UINT FlagsIn; ++ MME_UINT FlagsOut; ++} MME_ScatterPage_t; ++ ++/* MME_DataBuffer_t: ++ * Structure describing a data buffer ++ */ ++typedef struct MME_DataBuffer_t { ++ MME_UINT StructSize; ++ void* UserData_p; ++ MME_UINT Flags; ++ MME_UINT StreamNumber; ++ MME_UINT NumberOfScatterPages; ++ MME_ScatterPage_t* ScatterPages_p; ++ MME_UINT TotalSize; ++ MME_UINT StartOffset; ++} MME_DataBuffer_t; ++ ++/* MME_Command_t: ++ * Structure to pass a command to a transformer ++ */ ++typedef struct MME_Command_t { ++ MME_UINT StructSize; ++ MME_CommandCode_t CmdCode; ++ MME_CommandEndType_t CmdEnd; ++ MME_Time_t DueTime; ++ MME_UINT NumberInputBuffers; ++ MME_UINT NumberOutputBuffers; ++ MME_DataBuffer_t** DataBuffers_p; ++ MME_CommandStatus_t CmdStatus; ++ MME_UINT ParamSize; ++ MME_GenericParams_t Param_p; ++} MME_Command_t; ++ ++/* MME_DataFormat_t: ++ * Structure describing the data format that a transformer supports ++ */ ++typedef struct MME_DataFormat_t { ++ unsigned char FourCC[4]; ++} MME_DataFormat_t; ++ ++ ++/* MME_TransformerCapability_t: ++ * Structure containing information pertaining to a transformer's capability ++ */ ++typedef struct MME_TransformerCapability_t { ++ MME_UINT StructSize; ++ MME_UINT Version; ++ MME_DataFormat_t InputType; ++ MME_DataFormat_t OutputType; ++ MME_UINT TransformerInfoSize; ++ MME_GenericParams_t TransformerInfo_p; ++} MME_TransformerCapability_t; ++ ++ ++/* Transformer Client callback function */ ++typedef void (*MME_GenericCallback_t) (MME_Event_t event, MME_Command_t * callbackData, void *userData); ++ ++/* MME_TransformerInitParams_t: ++ * The parameters with which to initialize a transformer ++ */ ++typedef struct MME_TransformerInitParams_t { ++ MME_UINT StructSize; ++ MME_Priority_t Priority; ++ MME_GenericCallback_t Callback; ++ void* CallbackUserData; ++ MME_UINT TransformerInitParamsSize; ++ MME_GenericParams_t TransformerInitParams_p; ++} MME_TransformerInitParams_t; ++ ++/* Types: functions */ ++ ++/* Transformer: AbortCommand entry point */ ++typedef MME_ERROR (*MME_AbortCommand_t) (void *context, MME_CommandId_t commandId); ++ ++/* Transformer: GetTransformerCapability entry point */ ++typedef MME_ERROR (*MME_GetTransformerCapability_t) (MME_TransformerCapability_t * capability); ++ ++/* Transformer: InitTransformer entry point */ ++typedef MME_ERROR (*MME_InitTransformer_t) (MME_UINT initParamsLength, MME_GenericParams_t initParams, void **context); ++ ++/* Transformer: ProcessCommand entry point */ ++typedef MME_ERROR (*MME_ProcessCommand_t) (void *context, MME_Command_t * commandInfo); ++ ++/* Transformer: TermTransformer entry point */ ++typedef MME_ERROR (*MME_TermTransformer_t) (void *context); ++ ++/* Macros */ ++ ++/* These macros are shown in their most simplistic form. On mixed endian ++ * systems these macros can use (sizeof(field) == n) if networks to cope. ++ * Since such a network can be solved at compile time this would not impact ++ * runtime performance. ++ */ ++ ++/* MME_PARAM has a different implementation of machines with a different ++ * endian. This permits the MME implementation on a big endian machine ++ * to perform a 64-bit byte swap ++ */ ++ ++#if defined(__sh__) || defined(__st200__) || defined(__LITTLE_ENDIAN__) || defined(__arm__) ++/* this is the definition of MME_PARAM for little endian machines */ ++#define _MME_PARAM_ADDRESS(p, f) ((MME_TYPE_##f*)(((MME_GENERIC64*)p)+MME_OFFSET_##f)) ++ ++#else ++/* this is the definition of MME_PARAM for big endian machines */ ++#define _MME_PARAM_ADDRESS(p, f) \ ++ ((MME_TYPE_##f *)(((char *)((MME_GENERIC64*)p+MME_OFFSET_##f))+(sizeof(MME_GENERIC64)-sizeof(MME_TYPE_##f)))) ++ ++/* At the moment we do not support BE machines */ ++#error Unsupported CPU type ++#endif ++ ++/* A parameter */ ++#define MME_PARAM(p, f) (*_MME_PARAM_ADDRESS(p, f)) ++ ++/* A parameter sublist */ ++#define MME_PARAM_SUBLIST(p, f) _MME_PARAM_ADDRESS(p, f) ++ ++/* Access a parameter at a given index */ ++#define MME_INDEXED_PARAM(p, f, i) (*((MME_TYPE_##f*)(((MME_GENERIC64*)p)+MME_OFFSET_##f+(i)))) ++ ++/* Get number of paramters */ ++#define MME_LENGTH(id) (MME_LENGTH_##id) ++ ++/* Get number of paramters */ ++#define MME_LENGTH_BYTES(id) ((MME_LENGTH_##id)*sizeof(MME_GENERIC64)) ++ ++/* Function declarations */ ++ ++/* MME_AbortCommand() ++ * Attempt to abort a submitted command ++ * ++ * Asyncrhonous operation whose success will be observed in the CmdStatus of the aborted command ++ */ ++MME_ERROR MME_AbortCommand (MME_TransformerHandle_t handle, MME_CommandId_t cmdId); ++ ++/* MME_KillCommand() ++ * Abort a command without communicating with the remote processor. Should only be used ++ * when we know the transformer processor has definitely crashed ++ */ ++MME_ERROR MME_KillCommand (MME_TransformerHandle_t handle, MME_CommandId_t cmdId); ++ ++/* MME_KillCommandAll() ++ * Abort all commands without communicating with the remote processor. Should only be used ++ * when we know the transformer processor has definitely crashed ++ */ ++MME_ERROR MME_KillCommandAll (MME_TransformerHandle_t handle); ++ ++/* MME_AllocDataBuffer() ++ * Allocate a data buffer that is optimal for the transformer instantiation ++ * to pass between a Client and companion ++ */ ++MME_ERROR MME_AllocDataBuffer (MME_TransformerHandle_t handle, ++ MME_UINT size, ++ MME_AllocationFlags_t flags, ++ MME_DataBuffer_t ** dataBuffer_p); ++ ++/* MME_DeregisterTransformer() ++ * Deregister a transformer that has been registered ++ */ ++MME_ERROR MME_DeregisterTransformer (const char *name); ++ ++/* MME_DeregisterTransport() ++ * Deregister an EMBX transport being used by MME ++ * ++ * DEPRECATED ++ */ ++MME_ERROR MME_DeregisterTransport (const char *name); ++ ++/* MME_FreeDataBuffer() ++ * Free a buffer previously allocated with MME_AllocDataBuffer ++ */ ++MME_ERROR MME_FreeDataBuffer (MME_DataBuffer_t * DataBuffer); ++ ++/* MME_GetTransformerCapability() ++ * Obtain the capabilities of a transformer ++ */ ++MME_ERROR MME_GetTransformerCapability (const char *name, ++ MME_TransformerCapability_t * capability); ++ ++/* MME_Init() ++ * Initialize MME ++ */ ++MME_ERROR MME_Init (void); ++ ++/* MME_InitTransformer() ++ * Create a transformer instance on a companion ++ */ ++MME_ERROR MME_InitTransformer (const char *name, ++ MME_TransformerInitParams_t * params, ++ MME_TransformerHandle_t * handlep); ++ ++/* MME_ModifyTuneable() ++ * Modify system wide configuration parameters such as thread priority. ++ */ ++MME_ERROR MME_ModifyTuneable (MME_Tuneable_t key, MME_UINT value); ++ ++/* MME_GetTuneable() ++ * Returns current value of system wide configuration parameters such as thread priority. ++ */ ++MME_UINT MME_GetTuneable (MME_Tuneable_t key); ++ ++/* MME_NotifyHost() ++ * Notify the Command Client that a transformer event has occurred ++ */ ++MME_ERROR MME_NotifyHost (MME_Event_t event, MME_Command_t * commandInfo, MME_ERROR res); ++ ++/* MME_RegisterTransformer() ++ * Register a transformer after which instantiations may be made ++ */ ++MME_ERROR MME_RegisterTransformer (const char *name, ++ MME_AbortCommand_t abortFunc, ++ MME_GetTransformerCapability_t getTransformerCapabilityFunc, ++ MME_InitTransformer_t initTransformerFunc, ++ MME_ProcessCommand_t processCommandFunc, ++ MME_TermTransformer_t termTransformerFunc); ++ ++/* MME_RegisterTransport() ++ * Register an existing EMBX transport for use by MME ++ * ++ * DEPRECATED ++ */ ++MME_ERROR MME_RegisterTransport (const char *name); ++ ++/* MME_Run() ++ * Run the MME message loop on a companion CPU ++ * ++ * DEPRECATED ++ */ ++MME_ERROR MME_Run (void); ++ ++/* MME_SendCommand() ++ * Send a transformer command to a transformer instance ++ */ ++MME_ERROR MME_SendCommand (MME_TransformerHandle_t handle, MME_Command_t *commandInfo); ++ ++/* MME_Term() ++ * Terminate MME on the local CPU. ++ */ ++MME_ERROR MME_Term (void); ++ ++/* MME_TermTransformer() ++ * Terminate a transformer instance ++ */ ++MME_ERROR MME_TermTransformer (MME_TransformerHandle_t handle); ++ ++/* MME_KillTransformer() ++ * Terminate a transformer instance, without communicating ++ * with the remote processor, which we assume has crashed ++ */ ++MME_ERROR MME_KillTransformer (MME_TransformerHandle_t handle); ++ ++/* MME_IsStillAlive() ++ * Ping a remote transformer to see if it's still running ++ * Sets alive to be non zero if it replies, zero otherwise ++ */ ++MME_ERROR MME_IsStillAlive (MME_TransformerHandle_t handle, MME_UINT *alive); ++ ++/* ++ * Multihost extensions - DEPRECATED ++ */ ++MME_ERROR MME_HostRegisterTransport(const char *name); ++MME_ERROR MME_HostDeregisterTransport(const char* name); ++MME_ERROR MME_HostInit(void); ++MME_ERROR MME_HostTerm(void); ++ ++/* ++ * MME4 New APIs ++ */ ++ ++/* ++ * Return a pointer to the MME version string ++ * ++ * This string takes the form: ++ * ++ * {major number}.{minor number}.{patch number} [text] ++ * ++ * That is, a major, minor and release number, separated by ++ * decimal points, and optionally followed by a space and a text string. ++ */ ++const char *MME_Version (void); ++ ++/* MME_WaitCommand() ++ * Block waiting for an issued Command to complete. Command must have been ++ * issued using the MME_COMMAND_END_RETURN_WAKE CmdEnd notification type ++ * ++ * Returns MME_SUCCESS when transformation has completed and CmdStatus has been updated ++ * Corresponding MME_Event status is updated via eventp ++ * ++ * Can return MME_COMMAND_TIMEOUT, MME_SYSTEM_INTERRUPT or MME_ICS_ERROR ++ */ ++MME_ERROR MME_WaitCommand (MME_TransformerHandle_t handle, ++ MME_CommandId_t cmdId, ++ MME_Event_t *eventp, ++ MME_Time_t timeout); ++ ++/* MME_PingTransformer() ++ * Ping a remote transformer to see if it's still running ++ * Waits for timeout period for response before returning an error ++ */ ++MME_ERROR MME_PingTransformer (MME_TransformerHandle_t handle, MME_Time_t timeout); ++ ++/* ++ * Register a memory region for use with the specified transformer instance ++ * ++ * Only data buffers which lie within the specified region can be used ++ * during transform operations ++ * ++ */ ++MME_ERROR MME_RegisterMemory (MME_TransformerHandle_t handle, ++ void *base, ++ MME_SIZE size, ++ MME_MemoryHandle_t *handlep); ++ ++MME_ERROR MME_DeregisterMemory (MME_MemoryHandle_t handle); ++ ++ ++#include /* Debug logging */ ++ ++ ++#ifdef __cplusplus ++} ++#endif /* __cplusplus */ ++#endif /* _MME_H */ ++ ++/* ++ * Local Variables: ++ * tab-width: 8 ++ * c-indent-level: 2 ++ * c-basic-offset: 2 ++ * End: ++ */ +diff --git a/interfaces/IDirectFBImageProvider/mme/mme_debug.h b/interfaces/IDirectFBImageProvider/mme/mme_debug.h +new file mode 100644 +index 0000000..7b4ed03 +--- /dev/null ++++ b/interfaces/IDirectFBImageProvider/mme/mme_debug.h +@@ -0,0 +1,63 @@ ++/************************************************************** ++ * Copyright (C) 2010 STMicroelectronics. All Rights Reserved. ++ * This file is part of the latest release of the Multicom4 project. This release ++ * is fully functional and provides all of the original MME functionality.This ++ * release is now considered stable and ready for integration with other software ++ * components. ++ ++ * Multicom4 is a free software; you can redistribute it and/or modify it under the ++ * terms of the GNU General Public License as published by the Free Software Foundation ++ * version 2. ++ ++ * Multicom4 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 General Public License for more details. ++ ++ * You should have received a copy of the GNU General Public License along with Multicom4; ++ * see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - ++ * Suite 330, Boston, MA 02111-1307, USA. ++ ++ * Written by Multicom team at STMicroelectronics in November 2010. ++ * Contact multicom.support@st.com. ++**************************************************************/ ++ ++/* ++ * ++ */ ++ ++#ifndef _MME_DEBUG_H ++#define _MME_DEBUG_H ++ ++typedef enum mme_debug_flags ++{ ++ MME_DBG = 0x0000, /* Always displayed */ ++ ++ MME_DBG_ERR = 0x0001, /* Display all error paths */ ++ MME_DBG_INIT = 0x0002, /* Initialisation operations */ ++ MME_DBG_MANAGER = 0x0004, /* MME management operations */ ++ ++ MME_DBG_RECEIVER = 0x0010, /* Transformer receiver task (companion) */ ++ MME_DBG_TRANSFORMER = 0x0020, /* Transformer operations (host) */ ++ MME_DBG_EXEC = 0x0040, /* Execution tasks */ ++ ++ MME_DBG_COMMAND = 0x0100, /* Transformer Command issue */ ++ MME_DBG_BUFFER = 0x0200, /* DataBuffer Alloc/Free */ ++ ++} MME_DBG_FLAGS; ++ ++const char *MME_ErrorStr (MME_ERROR res); ++MME_ERROR MME_DebugFlags (MME_DBG_FLAGS flags); ++ ++/* These were inconsistently named originally */ ++#define MME_Error_Str MME_ErrorStr ++#define MME_Debug_Flags MME_DebugFlags ++ ++#endif /* _MME_DEBUG_H */ ++ ++/* ++ * Local Variables: ++ * tab-width: 8 ++ * c-indent-level: 2 ++ * c-basic-offset: 2 ++ * End: ++ */ +diff --git a/interfaces/IDirectFBImageProvider/mme/transform/JPEGDECHW_VideoTransformerTypes.h b/interfaces/IDirectFBImageProvider/mme/transform/JPEGDECHW_VideoTransformerTypes.h +new file mode 100644 +index 0000000..c32292c +--- /dev/null ++++ b/interfaces/IDirectFBImageProvider/mme/transform/JPEGDECHW_VideoTransformerTypes.h +@@ -0,0 +1,379 @@ ++/// ++/// @file : JPEGDECHW_VideoTransformerTypes.h ++/// ++/// @brief : JPEG Video Decoder specific types for MME ++/// ++/// @par OWNER: ++/// ++/// @author : Prabhat Awasthi ++/// ++/// @par SCOPE: ++/// ++/// @date : 2008-08-01 ++/// ++/// © 2006 ST Microelectronics. All Rights Reserved. ++/// ++ ++#ifndef _JPEGDECHW_VIDEOTRANSFORMERTYPES_H_ ++#define _JPEGDECHW_VIDEOTRANSFORMERTYPES_H_ ++ ++#include "stddefs.h" ++ ++/*=============================================== ++ JPEG_DECODER ++===============================================*/ ++ ++#define JPEGHWDEC_MME_TRANSFORMER_NAME "JPEG_DECODER_HW" ++ ++/* ++JPEGHW_MME_VERSION: ++Identifies the MME API version of the JPEGHW firmware. ++If wants to build the firmware for old MME API version, change this string correspondingly. ++*/ ++#ifndef JPEGHW_MME_VERSION ++ #define JPEGHW_MME_VERSION 17 /* Latest MME API version */ ++#endif ++ ++#if (JPEGHW_MME_VERSION >= 17) ++ #define JPEGHWDEC_MME_API_VERSION "1.7" ++#elif (JPEGHW_MME_VERSION >= 16) ++ #define JPEGHWDEC_MME_API_VERSION "1.6" ++#elif (JPEGHW_MME_VERSION >= 15) ++ #define JPEGHWDEC_MME_API_VERSION "1.5" ++#elif (JPEGHW_MME_VERSION >= 14) ++ #define JPEGHWDEC_MME_API_VERSION "1.4" ++#elif (JPEGHW_MME_VERSION >= 13) ++ #define JPEGHWDEC_MME_API_VERSION "1.3" ++#elif (JPEGHW_MME_VERSION >= 12) ++ #define JPEGHWDEC_MME_API_VERSION "1.2" ++#elif (JPEGHW_MME_VERSION >= 11) ++ #define JPEGHWDEC_MME_API_VERSION "1.1" ++#else ++ #define JPEGHWDEC_MME_API_VERSION "1.0" ++#endif ++ ++ ++#define JPEGDECHW_NUMBER_OF_CEH_INTERVALS 32 ++ ++/* ++** JPEGDECHW_CompressedData_t : ++** Defines the address type for the JPEGDECHW compressed data ++*/ ++typedef U32 *JPEGDECHW_CompressedData_t; ++ ++ ++/* ++** JPEGDECHW_LumaAddress_t : ++** Defines the address type for the JPEGDECHW decoded Luma data’s ++** Bits 0 to 7 shall be set to 0 ++*/ ++typedef U32 *JPEGDECHW_LumaAddress_t; ++ ++ ++/* ++** JPEGDECHW_ChromaAddress_t : ++** Defines the address type for the JPEGDECHW decoded Chroma data’s ++** Bits 0 to 7 shall be set to 0 ++*/ ++typedef U32 *JPEGDECHW_ChromaAddress_t; ++ ++ ++/* ++** JPEGDECHW_DecodedBufferAddress_t : ++** Defines the addresses where the decoded picture/additional info related to the block ++** structures will be stored ++*/ ++typedef struct _JPEGDECHWDECODEDBUFFERADDRESS_T_ ++{ ++ JPEGDECHW_LumaAddress_t Luma_p; ++ JPEGDECHW_ChromaAddress_t Chroma_p; ++#if (JPEGHW_MME_VERSION < 15) /* Not required For Reference reconstruction block*/ ++ JPEGDECHW_LumaAddress_t LumaDecimated_p; ++ JPEGDECHW_ChromaAddress_t ChromaDecimated_p; ++#endif ++} JPEGDECHW_DecodedBufferAddress_t; ++ ++ ++#if (JPEGHW_MME_VERSION >= 15) ++/* ++** JPEGDECHW_DisplayBufferAddress_t : ++** Defines the addresses (used by Display Reconstruction block) where the pictures to be displayed will be stored ++*/ ++typedef struct _JPEGDECHWDISPLAYBUFFERADDRESS_T_ ++{ ++ U32 StructSize; /* Size of the structure in bytes */ ++ JPEGDECHW_LumaAddress_t DisplayLuma_p; /* address of the Luma buffer */ ++ JPEGDECHW_ChromaAddress_t DisplayChroma_p; /* address of the Chroma buffer */ ++ JPEGDECHW_LumaAddress_t DisplayDecimatedLuma_p; /* address of the decimated Luma buffer */ ++ JPEGDECHW_ChromaAddress_t DisplayDecimatedChroma_p; /* address of the decimated Chroma buffer */ ++} JPEGDECHW_DisplayBufferAddress_t; ++#endif ++ ++ ++#if (JPEGHW_MME_VERSION >= 15) ++/* ++** JPEGDECHW_RcnRefDispEnable_t : ++** Used for enabling Main/Aux outputs for both Display & Reference reconstruction blocks ++*/ ++typedef enum _JPEGDECHW_RCNREFDISPENABLE_T_ ++{ ++ JPEGDECHW_DISP_AUX_EN = 0x00000010, /* Enable decimated (for display) reconstruction */ ++ JPEGDECHW_DISP_MAIN_EN = 0x00000020, /* Enable main (for display) reconstruction */ ++ JPEGDECHW_DISP_AUX_MAIN_EN = 0x00000030, /* Enable both main & decimated (for display) reconstruction */ ++ JPEGDECHW_REF_MAIN_EN = 0x00000100, /* Enable only reference output(ex. for Trick modes)*/ ++ JPEGDECHW_REF_MAIN_DISP_AUX_EN = 0x00000110, /* Enable reference output with decimated (for display) reconstruction */ ++ JPEGDECHW_REF_MAIN_DISP_MAIN_EN = 0x00000120, /* Enable reference output with main (for display) reconstruction */ ++ JPEGDECHW_REF_MAIN_DISP_MAIN_AUX_EN = 0x00000130 /* Enable reference output with main & decimated (for display) reconstruction */ ++} JPEGDECHW_RcnRefDispEnable_t; ++ ++#else ++ ++/* ++** JPEGDECHW_MainAuxEnable_t : ++** Used for enabling Main/Aux outputs ++*/ ++typedef enum _JPEGDECHW_MAINAUXENABLE_T_ ++{ ++ JPEGDECHW_AUXOUT_EN = 0x00000010, /* enable decimated reconstruction */ ++ JPEGDECHW_MAINOUT_EN = 0x00000020, /* enable main reconstruction */ ++ JPEGDECHW_AUX_MAIN_OUT_EN = 0x00000030 /* enable both main & decimated reconstruction */ ++} JPEGDECHW_MainAuxEnable_t; ++ ++#endif ++ ++ ++/* ++** JPEGDECHW_HorizontalDeciFactor _t : ++** Identifies the horizontal decimation factor ++*/ ++typedef enum _JPEGDECHW_HORIZONTALDECIFACTOR_T_ ++{ ++ JPEGDECHW_HDEC_1 = 0x00000000, /* no resize */ ++ JPEGDECHW_HDEC_ADVANCED_2 = 0x00000101, /* Advanced H/2 resize using improved 8-tap filters */ ++ JPEGDECHW_HDEC_ADVANCED_4 = 0x00000102 /* Advanced H/4 resize using improved 8-tap filters */ ++} JPEGDECHW_HorizontalDeciFactor_t; ++ ++ ++/* ++** JPEGDECHW_VerticalDeciFactor _t : ++** Identifies the vertical decimation factor ++*/ ++typedef enum _JPEGDECHW_VERTICALDECIFACTOR_T_ ++{ ++ JPEGDECHW_VDEC_1 = 0x00000000, /* no resize */ ++ JPEGDECHW_VDEC_ADVANCED_2_PROG = 0x00000204, /* V/2 , progressive resize */ ++ JPEGDECHW_VDEC_ADVANCED_2_INT = 0x000000208 /* V/2 , interlaced resize */ ++} JPEGDECHW_VerticalDeciFactor_t; ++ ++ ++/* ++** JPEGDECHW_VideoDecodeInitParams_t : ++** Identifies the Initialization parameters for the transformer. ++*/ ++typedef struct _JPEGDECHW_VIDEODECODEINITPARAMS_T_ ++{ ++ JPEGDECHW_CompressedData_t CircularBufferBeginAddr_p; ++ JPEGDECHW_CompressedData_t CircularBufferEndAddr_p; ++} JPEGDECHW_VideoDecodeInitParams_t; ++ ++ ++/* ++** JPEGDECHW_DecodingError_t : ++** Status of the decoding process ++*/ ++typedef enum ++{ ++ /* The firmware has been sucessful */ ++#if (JPEGHW_MME_VERSION >= 13) ++ JPEG_DECODER_NO_ERROR = 0, ++ JPEG_DECODER_UNDEFINED_HUFF_TABLE = 1, ++ JPEG_DECODER_UNSUPPORTED_MARKER = 2, ++ JPEG_DECODER_UNABLE_ALLOCATE_MEMORY = 3, ++ JPEG_DECODER_NON_SUPPORTED_SAMP_FACTORS = 4, ++ JPEG_DECODER_BAD_PARAMETER = 5, ++ JPEG_DECODER_DECODE_ERROR = 6, ++ JPEG_DECODER_BAD_RESTART_MARKER = 7, ++ JPEG_DECODER_UNSUPPORTED_COLORSPACE = 8, ++ JPEG_DECODER_BAD_SOS_SPECTRAL = 9, ++ JPEG_DECODER_BAD_SOS_SUCCESSIVE = 10, ++ JPEG_DECODER_BAD_HEADER_LENGHT = 11, ++ JPEG_DECODER_BAD_COUNT_VALUE = 12, ++ JPEG_DECODER_BAD_DHT_MARKER = 13, ++ JPEG_DECODER_BAD_INDEX_VALUE = 14, ++ JPEG_DECODER_BAD_NUMBER_HUFFMAN_TABLES = 15, ++ JPEG_DECODER_BAD_QUANT_TABLE_LENGHT = 16, ++ JPEG_DECODER_BAD_NUMBER_QUANT_TABLES = 17, ++ JPEG_DECODER_BAD_COMPONENT_COUNT = 18, ++ JPEG_DECODER_DIVIDE_BY_ZERO_ERROR = 19, ++ JPEG_DECODER_NOT_JPG_IMAGE = 20, ++ JPEG_DECODER_UNSUPPORTED_ROTATION_ANGLE = 21, ++ JPEG_DECODER_UNSUPPORTED_SCALING = 22, ++ JPEG_DECODER_INSUFFICIENT_OUTPUTBUFFER_SIZE = 23, ++ JPEG_DECODER_BAD_HWCFG_GP_VERSION_VALUE = 24, ++ JPEG_DECODER_BAD_VALUE_FROM_RED = 25, ++ JPEG_DECODER_BAD_SUBREGION_PARAMETERS = 26, ++ JPEG_DECODER_PROGRESSIVE_DECODE_NOT_SUPPORTED = 27, ++ JPEG_DECODER_ERROR_TASK_TIMEOUT = 28 ++#else ++ JPEG_DECODER_NO_ERROR = 0, ++ JPEG_DECODER_ERROR_NOT_RECOVERED = 4, ++ JPEG_DECODER_ERROR_TASK_TIMEOUT = 8 ++#endif ++} JPEGDECHW_DecodingError_t; ++ ++ ++/* ++** JPEGDECHW_DecodingMode_t : ++** Identifies the decoding mode. ++*/ ++typedef enum ++{ ++ JPEGDECHW_NORMAL_DECODE = 0, ++ /* Other values to be added later */ ++} JPEGDECHW_DecodingMode_t; ++ ++ ++/* ++** JPEGDECHW_AdditionalFlags_t : ++** Identifies the different flags that will be passed to JPEG firmware ++*/ ++#if (JPEGHW_MME_VERSION >= 14) ++typedef enum ++{ ++ JPEGDECHW_ADDITIONAL_FLAG_NONE = 0, ++ JPEGDECHW_ADDITIONAL_FLAG_CEH = 1, /* Request firmware to return values of the CEH registers */ ++ JPEGDECHW_ADDITIONAL_FLAG_RASTER = 64, /* Output storage of Auxillary reconstruction in Raster format. */ ++ JPEGDECHW_ADDITIONAL_FLAG_420MB = 128 /* Output storage of Auxillary reconstruction in 420MB format. */ ++} JPEGDECHW_AdditionalFlags_t; ++#elif (JPEGHW_MME_VERSION >= 12) ++typedef enum ++{ ++ JPEGDECHW_ADDITIONAL_FLAG_NONE = 0, ++ JPEGDECHW_ADDITIONAL_FLAG_CEH = 1, /* Request firmware to return values of the CEH registers */ ++ JPEGDECHW_ADDITIONAL_FLAG_RASTER = 64 /* Output storage of Auxillary reconstruction in Raster format. */ ++} JPEGDECHW_AdditionalFlags_t; ++#else ++typedef enum ++{ ++ JPEGDECHW_ADDITIONAL_FLAG_NONE = 0, ++ JPEGDECHW_ADDITIONAL_FLAG_CEH = 1 /* Request firmware to return values of the CEH registers */ ++} JPEGDECHW_AdditionalFlags_t; ++#endif ++ ++ ++/* ++** JPEGDECHW_VideoDecodeReturnParams_t : ++** Identifies the parameters to be returned back to the driver by decoder. ++*/ ++typedef struct _JPEGDECHWVIDEODECODERETURNPARAMS_T_ ++{ ++ /* profiling info */ ++#if (JPEGHW_MME_VERSION >= 17) ++ U32 DecodeTimeInMicros; ++#endif ++#if (JPEGHW_MME_VERSION <= 16) || defined (DUMP_PROFILE_INFO) ++ U32 pm_cycles; ++ U32 pm_dmiss; ++ U32 pm_imiss; ++ U32 pm_bundles; ++ U32 pm_pft; ++#endif ++ JPEGDECHW_DecodingError_t ErrorCode; ++ // CEHRegisters[] is an array where values of the ++ // Contrast Enhancement Histogram (CEH) registers will be stored. ++ // CEHRegisters[0] will correspond to register MBE_CEH_0_7, CEHRegisters[1] will ++ // correspond to register MBE_CEH_8_15., CEHRegisters[2], correspond to register ++ // MBE_CEH_16_23. ++ // Note that elements of this array will be updated only if ++ // VC9_TransformParam_t.AdditionalFlags will have the flag ++ // VC9_ADDITIONAL_FLAG_CEH set. They will remain unchanged otherwise. ++ U32 CEHRegisters[JPEGDECHW_NUMBER_OF_CEH_INTERVALS]; ++#ifdef JPEGHW_DEBUG ++ S32 LastDecodedMB; ++#endif ++} JPEGDECHW_VideoDecodeReturnParams_t; ++ ++ ++/* ++** JPEGDECHW_VideoDecodeCapabilityParams_t : ++** Transformer capability parameters. ++*/ ++typedef struct _JPEGDECHW_VIDEODECODECAPABILITYPARAMS_T_ ++{ ++ U32 api_version; // Omega2 frame buffer size (luma+chroma) ++} JPEGDECHW_VideoDecodeCapabilityParams_t; ++ ++ ++/* ++** JPEGDECHW_VideoDecodeParams_t : ++** Parameters to be sent along with the Transform command ++*/ ++typedef struct _JPEGDECHW_VIDEODECODEPARAMS_T_ ++{ ++ JPEGDECHW_CompressedData_t PictureStartAddr_p; ++ JPEGDECHW_CompressedData_t PictureEndAddr_p; ++ JPEGDECHW_DecodedBufferAddress_t DecodedBufferAddr; ++#if (JPEGHW_MME_VERSION >= 15) ++ JPEGDECHW_DisplayBufferAddress_t DisplayBufferAddr; ++#endif ++#if (JPEGHW_MME_VERSION >= 15) ++ JPEGDECHW_RcnRefDispEnable_t MainAuxEnable; /* enable Main and/or Aux outputs */ ++#else ++ JPEGDECHW_MainAuxEnable_t MainAuxEnable; /* enable Main and/or Aux outputs */ ++#endif ++ JPEGDECHW_HorizontalDeciFactor_t HorizontalDecimationFactor; ++ JPEGDECHW_VerticalDeciFactor_t VerticalDecimationFactor; ++ U32 xvalue0; /* The X(0) coordinate for subregion decoding */ ++ U32 xvalue1; /* The X(1) coordinate for subregion decoding */ ++ U32 yvalue0; /* The Y(0) coordinate for subregion decoding */ ++ U32 yvalue1; /* The Y(1) coordinate for subregion decoding */ ++ JPEGDECHW_DecodingMode_t DecodingMode; ++#if (JPEGHW_MME_VERSION >= 12) ++ U32 AdditionalFlags; /* Additonal Flags */ ++#else ++ JPEGDECHW_AdditionalFlags_t AdditionalFlags; /* Additonal Flags */ ++#endif ++#if (JPEGHW_MME_VERSION >= 16) ++ U32 FieldFlag; /* Determines Frame/Field Scan */ ++#endif ++#ifdef JPEG_PIC_SEQ_DEBUG_INFO ++ U8 *DebugBufferPtr; ++#endif ++} JPEGDECHW_VideoDecodeParams_t; ++ ++ ++#ifdef JPEG_PIC_SEQ_DEBUG_INFO ++/* ++** JPEG_DebugPicture_t : ++** Parameters to be sent along with the Transform command ++*/ ++typedef struct _JPEG_DEBUGPICTURE_T_ ++{ ++ U32 PicStdConfig; ++ U32 PictureWidthWord; ++ U32 PictureHeightWord; ++ U32 PicType_IPF; ++ U32 PictureWidthWord_IPF; ++ U32 PictureHeightWord_IPF; ++} JPEG_DebugPicture_t; ++#endif ++ ++#ifdef JPEG_MB_DEBUG_INFO ++/* ++** JPEG_DebugMb_t : ++** Parameters to be sent along with the Transform command ++*/ ++typedef struct _JPEG_DEBUGMB_T_ ++{ ++ U32 SMB_WORD_0; ++ U32 SMB_WORD_1; ++ U32 MbType; ++ U32 LmbWord2; ++ U32 Data2PipeWord[192]; ++ U32 BitBuf_LSB[6]; ++ U32 BitBuf_MSB[6]; ++} JPEG_DebugMb_t; ++#endif ++ ++#endif /* _JPEGDECHW_VIDEOTRANSFORMERTYPES_H_ */ ++ +diff --git a/interfaces/IDirectFBImageProvider/mme/transform/JPEG_VideoTransformerTypes.h b/interfaces/IDirectFBImageProvider/mme/transform/JPEG_VideoTransformerTypes.h +new file mode 100644 +index 0000000..c88ae6d +--- /dev/null ++++ b/interfaces/IDirectFBImageProvider/mme/transform/JPEG_VideoTransformerTypes.h +@@ -0,0 +1,192 @@ ++/* ++ ST Microelectronics MME JPEG transformer - user API ++ ++ (c) Copyright 2010 STMicroelectronics Ltd. ++ ++ All rights reserved. ++*/ ++ ++#ifndef __JPEG_VIDEOTRANSFORMERTYPES_H__ ++#define __JPEG_VIDEOTRANSFORMERTYPES_H__ ++ ++ ++#define JPEGDEC_MME_TRANSFORMER_NAME "JPEG_Transformer" ++ ++#if JPEGDEC_MME_VERSION == 0 ++# define JPEGDEC_MME_VERSION 1 ++#endif ++ ++#if (JPEGDEC_MME_VERSION == 20) ++# define JPEGDEC_MME_API_VERSION "2.0" ++#elif (JPEGDEC_MME_VERSION == 1) ++# define JPEGDEC_MME_API_VERSION "1.0" ++#else ++# error only API versions 1 or 2.0 are supported ++#endif ++ ++/* Common driver error constants */ ++#if (JPEGDEC_MME_VERSION == 1) ++# define JPEGDEC_ERROR_ID 0 ++# define JPEGDEC_ERROR_BASE (JPEG_ERROR_ID << 16) ++#else ++# include ++#endif ++ ++ ++ ++ ++#if (JPEGDEC_MME_VERSION == 1) ++/* Structure for GetTransformerCapability() */ ++typedef struct ++{ ++ /* for further expansion... */ ++ unsigned int dummy; ++} JPEGDEC_TransformerInfo_t; ++ ++typedef struct ++{ ++ unsigned int caps_len; ++}JPEGDEC_Capability_t; ++#elif (JPEGDEC_MME_VERSION == 20) ++enum JPEGDEC_TransformFlags { ++ JDIF_ROTATE90 = 0x00000001, ++ JDIF_ROTATE270 = 0x00000002, ++ JDIF_FLIP_HORIZONTAL = 0x00000004, ++ JDIF_FLIP_VERTICAL = 0x00000008, ++ JDIF_ALL = 0x0000000f, ++}; ++#endif ++ ++ ++ ++/* Structure for the Transformer Initialization */ ++typedef struct ++{ ++ /* coardinates for subregion decoding */ ++ unsigned int xvalue0; ++ unsigned int xvalue1; ++ unsigned int yvalue0; ++ unsigned int yvalue1; ++ ++ /* Output width and height of the decoded image. Used for IDCT select and ++ resizing (if done in the core). */ ++ int outputWidth; ++ int outputHeight; ++ ++#if (JPEGDEC_MME_VERSION == 1) ++ /* TRUE if Rotatedegree is other than zero degree ++ Rotation clockwise/anticlockwise is required */ ++ int ROTATEFLAG; ++ /* degree of rotation clockwise/anti-clockwise || 90 | 180 | 270 */ ++ int Rotatedegree; ++ /* Flag set TRUE when vertical flip of the picture is required */ ++ int VerticalFlip; ++ /* Flag set TRUE when vertical flip of the picture is required */ ++ int HorizantalFlip; ++ ++ /* the pitch. Valid only if ROTATEFLAG & 0x80000000 */ ++ int Pitch; ++#elif (JPEGDEC_MME_VERSION == 20) ++ /* you should really set this, otherwise some default value is used, which ++ doesn't necessarily coincides with what you assume. */ ++ int pitch; ++#endif ++} JPEGDEC_InitParams_t; ++ ++ ++ ++ ++ ++typedef enum ++{ ++ /* planar 3 buffer YCbCr, 4:4:4, 4:2:2 or 4:2:0 (not implemented) */ ++ /* 24 bit YUV planar (3 planes, Y Cb Cr, each 8 bit) */ ++ JPEGDEC_OF_YCbCr4xxp, ++ /* 16 bit YUV ( 8 bit Y plane followed by one ++ 16 bit half width CbCr [15:0] plane) */ ++ JPEGDEC_OF_NV16, ++ /* 16 bit YUV (4 byte/ 2 pixel, macropixel contains YCbYCr [31:0]) */ ++ JPEGDEC_OF_UYVY, ++ /* 24 bit VYU 4:4:4 (3 byte, Cr 8@16, Y 8@8, Cb 8@0) */ ++ JPEGDEC_OF_YCbCr444r, /* DSPF_VYU in DirectFB */ ++ /* 24 bit RGB (3 byte, red 8@16, green 8@8, blue 8@0) */ ++ JPEGDEC_OF_RGB, ++} JPEGDEC_OutputFormat_t; ++ ++ ++/* Structure for the databuffers passed with TRANSFORM commands */ ++typedef struct ++{ ++ /* Steering of size/widht/height of output picture */ ++ JPEGDEC_InitParams_t outputSettings; ++#if (JPEGDEC_MME_VERSION == 20) ++ JPEGDEC_OutputFormat_t OutputFormat; ++ enum JPEGDEC_TransformFlags flags; ++#endif ++} JPEGDEC_TransformParams_t; ++ ++ ++#if (JPEGDEC_MME_VERSION == 1) ++typedef enum ++{ ++ JPEG_NO_ERROR, ++ UNDEFINED_HUFF_TABLE, ++ UNSUPPORTED_MARKER, ++ UNABLE_ALLOCATE_MEMORY, ++ NON_SUPPORTED_SAMP_FACTORS, ++ BAD_PARAMETER, ++ DECODE_ERROR, ++ BAD_RESTART_MARKER, ++ UNSUPPORTED_COLORSPACE, ++ BAD_SOS_SPECTRAL, ++ BAD_SOS_SUCCESSIVE, ++ BAD_HEADER_LENGHT, ++ BAD_COUNT_VALUE, ++ BAD_DHT_MARKER, ++ BAD_INDEX_VALUE, ++ BAD_NUMBER_HUFFMAN_TABLES, ++ BAD_QUANT_TABLE_LENGHT, ++ BAD_NUMBER_QUANT_TABLES, ++ BAD_COMPONENT_COUNT, ++ DIVIDE_BY_ZERO_ERROR, ++ NOT_JPG_IMAGE, ++ UNSUPPORTED_ROTATION_ANGLE, ++ UNSUPPORTED_SCALING, ++ INSUFFICIENT_OUTPUTBUFFER_SIZE ++}JPEGDEC_ErrorCodes_t; ++#endif ++ ++ ++/* Structure for return parameters of TRANSFORM commands */ ++typedef struct ++{ ++ /* bytes written to the o/p buffer sent back to the host */ ++ unsigned int bytes_written; ++ /* scaled image output height / width */ ++ int decodedImageHeight; ++ int decodedImageWidth; ++ ++#if (JPEGDEC_MME_VERSION == 1) ++ unsigned int Total_cycle; ++ unsigned int DMiss_Cycle; ++ unsigned int IMiss_Cycle; ++ JPEGDEC_ErrorCodes_t ErrorType; ++#elif (JPEGDEC_MME_VERSION == 20) ++ ++ int pitch; ++ ++ J_MESSAGE_CODE ErrorType; ++# if defined(JPEGDEC_PROFILING_ENABLE) ++ unsigned int Cycles; ++ unsigned int Bundles; ++ unsigned int ICacheMiss; ++ unsigned int DCacheMiss; ++ unsigned int NopBundles; ++# endif ++ ++#endif ++} JPEGDEC_TransformReturnParams_t; ++ ++ ++ ++#endif /* __JPEG_VIDEOTRANSFORMERTYPES_H__ */ +diff --git a/interfaces/IDirectFBImageProvider/mme/transform/PNGDecode_interface.h b/interfaces/IDirectFBImageProvider/mme/transform/PNGDecode_interface.h +new file mode 100644 +index 0000000..ea3516d +--- /dev/null ++++ b/interfaces/IDirectFBImageProvider/mme/transform/PNGDecode_interface.h +@@ -0,0 +1,191 @@ ++#ifndef PNGDECODERINTERFACE_H ++#define PNGDECODERINTERFACE_H ++ ++#define PNGDECODER_MME_TRANSFORMER_NAME "PNGDECODER" ++ ++#if (PNGDEC_MME_VERSION == 11) ++ #define PNGDECODER_MME_API_VERSION "1.1" ++#elif (PNGDEC_MME_VERSION == 10) ++ #define PNGDECODER_MME_API_VERSION "1.0" ++#else ++ #define PNGDECODER_MME_API_VERSION "undefined" ++#endif ++ ++#define PNGDECODE_COLOR_MASK_PALETTE 1 ++#define PNGDECODE_COLOR_MASK_COLOR 2 ++#define PNGDECODE_COLOR_MASK_ALPHA 4 ++ ++#define PNGDECODE_MAX_PALETTE 256 ++ ++typedef enum ++{ ++ PNGDECODE_COLOR_TYPE_GRAY = 0 /* PNG_COLOR_TYPE_GRAY */, ++ PNGDECODE_COLOR_TYPE_PALETTE = PNGDECODE_COLOR_MASK_COLOR | PNGDECODE_COLOR_MASK_PALETTE /* PNG_COLOR_TYPE_PALETTE */, ++ PNGDECODE_COLOR_TYPE_RGB = PNGDECODE_COLOR_MASK_COLOR /* PNG_COLOR_TYPE_RGB */, ++ PNGDECODE_COLOR_TYPE_RGB_ALPHA = PNGDECODE_COLOR_MASK_COLOR | PNGDECODE_COLOR_MASK_ALPHA /* PNG_COLOR_TYPE_RGB_ALPHA */, ++ PNGDECODE_COLOR_TYPE_GRAY_ALPHA = PNGDECODE_COLOR_MASK_ALPHA /* PNG_COLOR_TYPE_GRAY_ALPHA*/ ++}PNGDecode_ColorType_t; ++ ++typedef enum ++{ ++ PNGDECODE_INTERLACE_NONE = 0 /* PNG_INTERLACE_NONE */, ++ PNGDECODE_INTERLACE_ADAM7 = 1 /* PNG_INTERLACE_ADAM7 */ ++}PNGDecode_InterlaceType_t; ++ ++typedef enum ++{ ++ PNGDECODE_COMPRESSION_TYPE_BASE = 0 /* PNG_COMPRESSION_TYPE_BASE */ ++}PNGDecode_CompressionType_t; ++ ++ ++typedef enum ++{ ++ PNGDECODE_FILTER_TYPE_BASE = 0 /* PNG_FILTER_TYPE_BASE */ ++}PNGDecode_FilterMethod_t; ++ ++/* for an MME_TRANSFORM command the ones marked with a star or plus denote ++ possibly corrupt data when seen together with MME_INVALID_ARGUMENT. A plus ++ is given for PNGDEC_MME_VERSION == 10 and a star for ++ PNGDEC_MME_VERSION == 11. In theory, PNGDECODE_MEMORY_ALLOCATION_ERROR ++ could denote corrupt data, too, but it's unlikely any data was decoded ++ at all, thus it doesn't make sense to display the result, either try ++ again or use libpng on the host! For version 10, ++ PNGDECODE_INTERNAL_ERROR is returned in more occasions than just data ++ corruption. */ ++typedef enum ++{ ++ PNGDECODE_NO_ERROR, ++ PNGDECODE_MEMORY_ALLOCATION_ERROR, ++ PNGDECODE_CRC_ERROR /* +* */, ++ PNGDECODE_INVALID_STREAM /* +* */, ++ PNGDECODE_INTERNAL_ERROR /* + */ ++#if (PNGDEC_MME_VERSION > 10) ++ ,PNGDECODE_INVALID_ARGUMENT ++ ,PNGDECODE_STREAM_ERROR /* * */ ++#endif ++} PNGDecode_ErrorCodes_t; ++ ++ ++typedef struct ++{ ++ /* Picture Width in pixels */ ++ unsigned int PictureWidth; ++ ++ /* Picture Height in pixels */ ++ unsigned int PictureHeight; ++ ++ /* bitstream information: */ ++ /* Number of bits per sample or palette index */ ++ unsigned int BitDepth; ++ /* Color type as encoded in the bitstream */ ++ PNGDecode_ColorType_t ColorType; ++ /* Transmission order of image data */ ++ PNGDecode_InterlaceType_t InterlaceType; ++ /* Only compression type 0 is supported */ ++ PNGDecode_CompressionType_t CompressionType; ++ /* Only Filter method 0 is supported */ ++ PNGDecode_FilterMethod_t FilterMethod; ++ ++ PNGDecode_ErrorCodes_t ErrorType; ++ ++#if (PNGDEC_MME_VERSION > 10) ++ /* transformer return params: */ ++ /* Color type as returned by the transformer: ++ - PNGDECODE_COLOR_TYPE_PALETTE (LUT8) ++ - PNGDECODE_COLOR_TYPE_RGB (RGB24) ++ - PNGDECODE_COLOR_TYPE_RGB_ALPHA (ARGB32) */ ++ PNGDecode_ColorType_t ColorFormatOutput; ++ ++ int HaveColorKey; ++ unsigned int ColorKey; /* 32 bit xRGB */ ++ ++ unsigned int pitch; ++ ++ unsigned char palette[4 * PNGDECODE_MAX_PALETTE]; /* ARGB ARGB ARGB */ ++#endif ++} PNGDecode_GlobalTransformReturnParams_t; ++ ++ ++#if (PNGDEC_MME_VERSION == 10) ++ ++typedef enum ++{ ++ /* always ARGB */ ++ PNGDECODE_OUTPUTFORMAT_ARGB = 0 ++} PNGDecode_OutputFormat_t; ++ ++typedef struct ++{ ++ /* indicates seven step display in case of interlaced pictures */ ++ unsigned int ProgressiveDisplayFlag; ++ PNGDecode_OutputFormat_t OutputFormat; ++} PNGDecode_GlobalParams_t; ++ ++typedef struct ++{ ++ unsigned int caps_len; ++} caps_len_t; ++ ++typedef struct ++{ ++ unsigned char *caps; ++} caps_t; ++ ++#elif (PNGDEC_MME_VERSION > 10) ++ ++typedef enum ++{ ++ /* PNGDecode_OutputFormat_t, valid in PNGDecode_GlobalParams_t and ++ PNGDecode_InitTransformerParams_t */ ++ PNGDECODE_PARAM_FORMAT = 0x00000001, ++ /* pitch, only valid in PNGDecode_TransformParams_t */ ++ PNGDECODE_PARAM_PITCH = 0x00000002 ++} PNGDecode_Params_Flags_t; ++ ++typedef enum ++{ ++ /* expand everything to RGB24 (if the image has no alpha components, else ++ to ARGB32) */ ++ PNGDECODE_OF_EXPAND, ++ /* keep indexed images: ++ - LUT8 for all (non alpha) greyscale (any bitdepth) and 8bit palette ++ images ++ - RGB24 for all other non alpha images ++ - ARGB32 for alpha images */ ++ PNGDECODE_OF_COMPRESSED, ++ /* always expand to ARGB32 */ ++ PNGDECODE_OF_EXPAND_FORCE_ALPHA ++} PNGDecode_OutputFormat_t; ++ ++typedef struct ++{ ++ PNGDecode_Params_Flags_t flags; ++ /* if not specified, PNGDECODE_OF_EXPAND is assumed */ ++ PNGDecode_OutputFormat_t format; ++ /* if not specified, the pitch will be as returned in ++ PNGDecode_GlobalTransformReturnParams_t */ ++ int pitch; ++} PNGDecode_InitTransformerParams_t, ++ PNGDecode_TransformParams_t, ++ PNGDecode_GlobalParams_t; ++ ++#endif ++ ++ ++typedef struct ++{ /* Number of bytes written by the decoder into the output buffer*/ ++ unsigned int BytesWritten; ++ /* Error encountered while decoding the picture */ ++ PNGDecode_ErrorCodes_t ErrorType; ++ ++#if defined(PNGDECODE_PROFILING_ENABLE) ++ unsigned int Cycles; ++ unsigned int Bundles; ++ unsigned int ICacheMiss; ++ unsigned int DCacheMiss; ++ unsigned int NopBundles; ++#endif ++} PNGDecode_TransformReturnParams_t; ++ ++ ++#endif /* PNGDECODERINTERFACE_H */ +diff --git a/interfaces/IDirectFBImageProvider/mme_helper.h b/interfaces/IDirectFBImageProvider/mme_helper.h +new file mode 100644 +index 0000000..786d6e6 +--- /dev/null ++++ b/interfaces/IDirectFBImageProvider/mme_helper.h +@@ -0,0 +1,1042 @@ ++#ifndef __MME_HELPER_H__ ++#define __MME_HELPER_H__ ++ ++ ++#if defined(USE_MME) ++#include ++#include ++#include ++#endif /* USE_MME */ ++#include ++#include "sema_helper.h" ++ ++#define likely(x) __builtin_expect(!!(x),1) ++#define unlikely(x) __builtin_expect(!!(x),0) ++ ++#define container_of(ptr, type, member) ({ \ ++ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ ++ (type *)( (char *)__mptr - offsetof(type,member) );}) ++ ++#ifndef MAX_STREAMING_COMMANDS ++ #define MAX_STREAMING_COMMANDS 5 ++#endif ++#ifndef MME_STREAMING_BUFFERSIZE ++ #define MME_STREAMING_BUFFERSIZE (32 * 1024) /* this must _not_ be less ++ than 8 k */ ++#endif ++ ++ ++#if defined(USE_MME) ++struct _MMEHelper_buffer { ++ MME_DataBuffer_t *buffer; ++ MME_Command_t command; ++ sem_t sema; ++}; ++#endif /* USE_MME */ ++ ++typedef struct _MMECommon ++{ ++ IDirectFBImageProvider_data base; ++ ++ const char *name; ++ ++ void *image; /* decoded image data */ ++ unsigned int width; /* width of the JPEG/PNG image */ ++ unsigned int height; /* height of the JPEG/PNG image */ ++ ++#ifdef DIRECT_BUILD_DEBUG ++ /* performance monitoring */ ++ struct timeval starttime, endtime; ++#endif /* DIRECT_BUILD_DEBUG */ ++ ++ CoreSurface *decode_surface; ++ CoreGraphicsSerial serial; ++ ++ unsigned int decoded_width; ++ unsigned int decoded_height; ++ ++#if defined(USE_MME) ++ bool name_set; ++ const char *transformer_name; ++ ++ /* hardware decode specifics */ ++ MME_TransformerHandle_t Handle; ++ ++ MME_DataBuffer_t **OutDataBuffers; ++ MME_ScatterPage_t OutDataBufferScatterPage; ++ MME_DataBuffer_t OutDataBuffer; ++ ++ struct _MMEHelper_buffer SendDataBuffers[MAX_STREAMING_COMMANDS]; ++ ++ MME_Command_t TransformCommand; /* provide the output buffer and request ++ transform */ ++ ++ pthread_mutex_t pending_commands_lock; ++ DirectHash *pending_commands; ++ unsigned int n_pending_buffers; ++ ++ sem_t decode_event; ++ ++ int decode_success; ++ ++ /* bytes remaining to be decoded */ ++ unsigned int bytes; ++ unsigned int packets; ++ ++ /* just for statistics */ ++ unsigned int n_underflows; ++#endif /* USE_MME */ ++} MMECommon; ++ ++ ++#if defined(USE_MME) ++/* every user should provide those... */ ++static void TransformerCallback( MME_Event_t Event, ++ MME_Command_t *CallbackData, ++ void *UserData ); ++static DFBResult abort_transformer( struct _MMECommon *mme ); ++static DFBResult fetch_data( IDirectFBDataBuffer *buffer, ++ MME_DataBuffer_t *dbuf, ++ int len ); ++static void ++_imageprovider_update_transform_params (MMECommon * const mme, ++ void * const params, ++ const CoreSurfaceBufferLock * const lock); ++#endif /* USE_MME */ ++ ++ ++static DFBResult ++buffer_to_ptr_copy (IDirectFBDataBuffer * const buffer, ++ void * ptr, ++ int len) ++{ ++ DFBResult ret; ++ ++ while (len > 0) ++ { ++ unsigned int read; ++ ++ ret = buffer->WaitForData (buffer, len); ++ if (ret == DFB_OK) ++ ret = buffer->GetData (buffer, len, ptr, &read); ++ ++ if (ret) ++ return ret; ++ ++ ptr += read; ++ len -= read; ++ } ++ ++ return DFB_OK; ++} ++ ++ ++#if !defined(USE_MME) ++ ++#define mme_helper_LoadLib (data) DFB_FILENOTFOUND ++#define mme_helper_UnloadLib (struct _MMECommon * const data) {( )} ++ ++#else /* USE_MME */ ++ ++/* Some Error and Debug Management */ ++ ++ ++static inline const char * ++get_mme_event_string (MME_Event_t ev) ++{ ++ static const char *mme_event_strings[] = { ++ "MME_COMMAND_COMPLETED_EVT", ++ "MME_DATA_UNDERFLOW_EVT", ++ "MME_NOT_ENOUGH_MEMORY_EVT", ++ "MME_NEW_COMMAND_EVT", ++ }; ++ ++ return (((unsigned int) ev) < D_ARRAY_SIZE (mme_event_strings)) ++ ? mme_event_strings[ev] ++ : "* Unknown Event code *"; ++} ++ ++static inline const char * ++get_mme_state_string (MME_CommandState_t s) ++{ ++ static const char *mme_command_state_strings[] ={ ++ "MME_COMMAND_IDLE", ++ "MME_COMMAND_PENDING", ++ "MME_COMMAND_EXECUTING", ++ "MME_COMMAND_COMPLETED", ++ "MME_COMMAND_FAILED" ++ }; ++ ++ return (((unsigned int) s) < D_ARRAY_SIZE (mme_command_state_strings)) ++ ? mme_command_state_strings[s] ++ : "* Unknown State code *"; ++} ++ ++static inline const char * ++get_mme_error_string (MME_ERROR e) ++{ ++ static const char *mme_error_type_strings[] = { ++ "MME_SUCCESS", ++ "MME_DRIVER_NOT_INITIALIZED", ++ "MME_DRIVER_ALREADY_INITIALIZED", ++ "MME_NOMEM", ++ "MME_INVALID_TRANSPORT", ++ "MME_INVALID_HANDLE", ++ "MME_INVALID_ARGUMENT", ++ "MME_UNKNOWN_TRANSFORMER", ++ "MME_TRANSFORMER_NOT_RESPONDING", ++ "MME_HANDLES_STILL_OPEN", ++ "MME_COMMAND_STILL_EXECUTING", ++ "MME_COMMAND_ABORTED", ++ "MME_DATA_UNDERFLOW", ++ "MME_DATA_OVERFLOW", ++ "MME_TRANSFORM_DEFERRED", ++ "MME_SYSTEM_INTERRUPT", ++ "MME_EMBX_ERROR", ++ "MME_INTERNAL_ERROR", ++ "MME_NOT_IMPLEMENTED" ++ }; ++ ++ return (((unsigned int) e) < D_ARRAY_SIZE (mme_error_type_strings)) ++ ? mme_error_type_strings[e] ++ : "* Unknown Error code *"; ++} ++ ++ ++#if defined(MME_USE_DLOPEN) ++#include ++typedef MME_ERROR (*MME_Init_func) (void); ++typedef MME_ERROR (*MME_Term_func) (void); ++typedef MME_ERROR (*MME_SendCommand_func) (MME_TransformerHandle_t Handle, ++ MME_Command_t *CmdInfo_p); ++typedef MME_ERROR (*MME_AbortCommand_func) (MME_TransformerHandle_t Handle, ++ MME_CommandId_t CmdId); ++typedef MME_ERROR (*MME_AllocDataBuffer_func) (MME_TransformerHandle_t handle, ++ MME_UINT size, ++ MME_AllocationFlags_t flags, ++ MME_DataBuffer_t **dataBuffer_p); ++typedef MME_ERROR (*MME_FreeDataBuffer_func) (MME_DataBuffer_t *DataBuffer_p); ++typedef MME_ERROR (*MME_GetTransformerCapability_func) (const char *TransformerName, ++ MME_TransformerCapability_t *TransformerCapability_p); ++typedef MME_ERROR (*MME_InitTransformer_func) (const char *Name, ++ MME_TransformerInitParams_t *Params_p, ++ MME_TransformerHandle_t *Handle_p); ++typedef MME_ERROR (*MME_IsTransformerRegistered_func) (const char *name); ++typedef MME_ERROR (*MME_TermTransformer_func) (MME_TransformerHandle_t handle); ++typedef const char (*MME_Version_func) (void); ++ ++static MME_ERROR _mme_helper_MME_func (void) ++{ ++ return MME_DRIVER_NOT_INITIALIZED; ++} ++ ++static MME_Init_func _MME_Init = (MME_Init_func) _mme_helper_MME_func; ++static MME_Term_func _MME_Term = (MME_Term_func) _mme_helper_MME_func; ++static MME_SendCommand_func _MME_SendCommand = (MME_SendCommand_func) _mme_helper_MME_func; ++static MME_AbortCommand_func _MME_AbortCommand = (MME_AbortCommand_func) _mme_helper_MME_func; ++static MME_AllocDataBuffer_func _MME_AllocDataBuffer = (MME_AllocDataBuffer_func) _mme_helper_MME_func; ++static MME_FreeDataBuffer_func _MME_FreeDataBuffer = (MME_FreeDataBuffer_func) _mme_helper_MME_func; ++static MME_GetTransformerCapability_func _MME_GetTransformerCapability = (MME_GetTransformerCapability_func) _mme_helper_MME_func; ++static MME_InitTransformer_func _MME_InitTransformer = (MME_InitTransformer_func) _mme_helper_MME_func; ++static MME_IsTransformerRegistered_func _MME_IsTransformerRegistered = (MME_IsTransformerRegistered_func) _mme_helper_MME_func; ++static MME_TermTransformer_func _MME_TermTransformer = (MME_TermTransformer_func) _mme_helper_MME_func; ++static MME_Version_func _MME_Version = (MME_Version_func) _mme_helper_MME_func; ++#define MME_Init _MME_Init ++#define MME_Term _MME_Term ++#define MME_SendCommand _MME_SendCommand ++#define MME_AbortCommand _MME_AbortCommand ++#define MME_AllocDataBuffer _MME_AllocDataBuffer ++#define MME_FreeDataBuffer _MME_FreeDataBuffer ++#define MME_GetTransformerCapability _MME_GetTransformerCapability ++#define MME_InitTransformer _MME_InitTransformer ++#define MME_IsTransformerRegistered _MME_IsTransformerRegistered ++#define MME_TermTransformer _MME_TermTransformer ++#define MME_Version _MME_Version ++ ++static void *mme_helper_libmme; ++#endif /* MME_USE_DLOPEN */ ++ ++static bool mme_lib_inited; ++ ++ ++static void ++__attribute__((constructor)) ++mme_helper_ctor(void) ++{ ++#if defined(MME_USE_DLOPEN) ++ if ((mme_helper_libmme = dlopen ("libmme.so", RTLD_LAZY)) != NULL ++ || (mme_helper_libmme = dlopen ("libmme_host.so", RTLD_LAZY)) != NULL) ++ { ++ _MME_Init = dlsym (mme_helper_libmme, "MME_Init"); ++ _MME_Term = dlsym (mme_helper_libmme, "MME_Term"); ++ _MME_SendCommand = dlsym (mme_helper_libmme, "MME_SendCommand"); ++ _MME_AbortCommand = dlsym (mme_helper_libmme, "MME_AbortCommand"); ++ _MME_AllocDataBuffer = dlsym (mme_helper_libmme, "MME_AllocDataBuffer"); ++ _MME_FreeDataBuffer = dlsym (mme_helper_libmme, "MME_FreeDataBuffer"); ++ _MME_GetTransformerCapability = dlsym (mme_helper_libmme, "MME_GetTransformerCapability"); ++ _MME_InitTransformer = dlsym (mme_helper_libmme, "MME_InitTransformer"); ++ ++ /* only available in Multicom 4 and onward */ ++ _MME_Version = dlsym (mme_helper_libmme, "MME_Version"); ++ if (_MME_Version) ++ _MME_IsTransformerRegistered = dlsym (mme_helper_libmme, "MME_IsTransformerRegistered"); ++ ++ _MME_TermTransformer = dlsym (mme_helper_libmme, "MME_TermTransformer"); ++ ++ if (unlikely (!_MME_Init || !_MME_Term ++ || !_MME_SendCommand || !_MME_AbortCommand ++ || !_MME_AllocDataBuffer || !_MME_FreeDataBuffer ++ || !_MME_GetTransformerCapability ++ || (_MME_Version && !_MME_IsTransformerRegistered) ++ || !_MME_InitTransformer || !_MME_TermTransformer)) ++ { ++ _MME_Init = (MME_Init_func) _mme_helper_MME_func; ++ _MME_Term = (MME_Term_func) _mme_helper_MME_func; ++ _MME_SendCommand = (MME_SendCommand_func) _mme_helper_MME_func; ++ _MME_AbortCommand = (MME_AbortCommand_func) _mme_helper_MME_func; ++ _MME_AllocDataBuffer = (MME_AllocDataBuffer_func) _mme_helper_MME_func; ++ _MME_FreeDataBuffer = (MME_FreeDataBuffer_func) _mme_helper_MME_func; ++ _MME_GetTransformerCapability = (MME_GetTransformerCapability_func) _mme_helper_MME_func; ++ _MME_InitTransformer = (MME_InitTransformer_func) _mme_helper_MME_func; ++ _MME_IsTransformerRegistered = (MME_IsTransformerRegistered_func) _mme_helper_MME_func; ++ _MME_TermTransformer = (MME_TermTransformer_func) _mme_helper_MME_func; ++ _MME_Version = (MME_Version_func) _mme_helper_MME_func; ++ ++ dlclose (mme_helper_libmme); ++ mme_helper_libmme = NULL; ++ ++ D_WARN ("Unable to use libmme.so for "MME_TEXT_DOMAIN": (%s)", ++ dlerror ()); ++ } ++ else ++#endif /* MME_USE_DLOPEN */ ++ { ++ MME_ERROR mme_res = MME_Init (); ++ D_DEBUG_AT (MME_DEBUG_DOMAIN, "MME_Init() returned %d (%s)\n", ++ mme_res, get_mme_error_string (mme_res)); ++ switch (mme_res) ++ { ++ case MME_DRIVER_ALREADY_INITIALIZED: ++ mme_res = MME_SUCCESS; ++ case MME_SUCCESS: ++ break; ++ ++ default: ++ /* probably kernel module or /dev node required */ ++ D_ONCE ("failed to initialize MME for "MME_TEXT_DOMAIN": %d (%s)", ++ mme_res, get_mme_error_string (mme_res)); ++ break; ++ } ++ ++ mme_lib_inited = (mme_res == MME_SUCCESS); ++ D_DEBUG_AT (MME_DEBUG_DOMAIN, "mme_lib_inited %d\n", mme_lib_inited); ++ } ++#if defined(MME_USE_DLOPEN) ++ } ++ else ++ D_INFO ("Couldn't resolve libmme.so for "MME_TEXT_DOMAIN", can't " ++ "use MME for hw accelerated decoding\n"); ++#endif /* MME_USE_DLOPEN */ ++} ++ ++static void ++__attribute__((destructor)) ++mme_helper_dtor(void) ++{ ++ /* we can't MME_Term() here - there might be other users of MME still ++ active. MME should implement some use counters instead. */ ++// MME_ERROR mme_res = MME_Term (); ++// D_DEBUG_AT (MME_DEBUG_DOMAIN, "MME_Term() returned %d (%s)\n", ++// mme_res, get_mme_error_string (mme_res)); ++ mme_lib_inited = false; ++ ++#if defined(MME_USE_DLOPEN) ++ if (mme_helper_libmme) ++ { ++ _MME_Init = (MME_Init_func) _mme_helper_MME_func; ++ _MME_Term = (MME_Term_func) _mme_helper_MME_func; ++ _MME_SendCommand = (MME_SendCommand_func) _mme_helper_MME_func; ++ _MME_AbortCommand = (MME_AbortCommand_func) _mme_helper_MME_func; ++ _MME_AllocDataBuffer = (MME_AllocDataBuffer_func) _mme_helper_MME_func; ++ _MME_FreeDataBuffer = (MME_FreeDataBuffer_func) _mme_helper_MME_func; ++ _MME_InitTransformer = (MME_InitTransformer_func) _mme_helper_MME_func; ++ _MME_IsTransformerRegistered = (MME_IsTransformerRegistered_func) _mme_helper_MME_func; ++ _MME_TermTransformer = (MME_TermTransformer_func) _mme_helper_MME_func; ++ _MME_Version = (MME_Version_func) _mme_helper_MME_func; ++ ++ dlclose (mme_helper_libmme); ++ mme_helper_libmme = NULL; ++ } ++#endif /* MME_USE_DLOPEN */ ++} ++ ++ ++/***************************************/ ++ ++static DFBResult ++__attribute__((unused)) ++_mme_helper_get_capability (struct _MMECommon * const data, ++ const char * const name, ++ MME_TransformerCapability_t * const cap) ++{ ++ volatile u32 _len = 0; ++ MME_ERROR res; ++ ++ cap->TransformerInfoSize = sizeof (_len); ++ cap->TransformerInfo_p = (u32 *) &_len; ++ ++ cap->StructSize = sizeof (*cap); ++ ++ res = MME_GetTransformerCapability (name, cap); ++ if (res != MME_SUCCESS) ++ return DFB_FAILURE; ++ ++ D_DEBUG_AT (MME_DEBUG_DOMAIN, ++ "'%s' 1: sz/v/it/ot/is/p: %u, %u (%x), %.2x%.2x%.2x%.2x, " ++ "%.2x%.2x%.2x%.2x, %u, %p (%u bytes)\n", ++ name, ++ cap->StructSize, cap->Version, cap->Version, ++ cap->InputType.FourCC[0], cap->InputType.FourCC[1], ++ cap->InputType.FourCC[2], cap->InputType.FourCC[3], ++ cap->OutputType.FourCC[0], cap->OutputType.FourCC[1], ++ cap->OutputType.FourCC[2], cap->OutputType.FourCC[3], ++ cap->TransformerInfoSize, cap->TransformerInfo_p, _len); ++ if (_len) ++ { ++ char *buf = D_CALLOC (1, _len); ++ ++ cap->TransformerInfo_p = buf; ++ cap->TransformerInfoSize = _len; ++ ++ res = MME_GetTransformerCapability (name, cap); ++ if (res != MME_SUCCESS) ++ { ++ D_FREE (buf); ++ return DFB_FAILURE; ++ } ++ ++ D_DEBUG_AT (MME_DEBUG_DOMAIN, ++ "'%s' 2: sz/v/it/ot/is/p: %u, %u (%x), '%c%c%c%c' " ++ "(%.2x%.2x%.2x%.2x), '%c%c%c%c' (%.2x%.2x%.2x%.2x), %u, " ++ "%p (%u bytes)\n", ++ name, ++ cap->StructSize, cap->Version, cap->Version, ++ cap->InputType.FourCC[0], cap->InputType.FourCC[1], ++ cap->InputType.FourCC[2], cap->InputType.FourCC[3], ++ cap->InputType.FourCC[0], cap->InputType.FourCC[1], ++ cap->InputType.FourCC[2], cap->InputType.FourCC[3], ++ cap->OutputType.FourCC[0], cap->OutputType.FourCC[1], ++ cap->OutputType.FourCC[2], cap->OutputType.FourCC[3], ++ cap->OutputType.FourCC[0], cap->OutputType.FourCC[1], ++ cap->OutputType.FourCC[2], cap->OutputType.FourCC[3], ++ cap->TransformerInfoSize, cap->TransformerInfo_p, _len); ++ D_DEBUG_AT (MME_DEBUG_DOMAIN, "caps: '%s'\n", buf); ++ ++ D_FREE (buf); ++ cap->TransformerInfo_p = NULL; ++ } ++ ++ return DFB_OK; ++} ++ ++static DFBResult ++mme_helper_deinit_transformer (struct _MMECommon * const data) ++{ ++ MME_ERROR ret; ++ ++ if (!data->Handle) ++ return DFB_OK; ++ ++ D_DEBUG_AT (MME_DEBUG_DOMAIN, "terminating %s transformer w/ handle %x\n", ++ data->name, data->Handle); ++ ++ /* if we are still waiting for the main decode command to finish (because ++ we ran out of data but the transformer is still waiting), abort it. ++ JPEG needs this. */ ++ /* FIXME: what about locking? */ ++ if (direct_hash_lookup (data->pending_commands, ++ data->TransformCommand.CmdStatus.CmdId)) ++ { ++ abort_transformer (data); ++ while ((sema_wait_event (&data->decode_event) == -1) ++ && errno == EINTR) ++ ; ++ } ++ ++ if (data->n_underflows) ++ { ++ D_INFO ("%s: %d data underflow(s) during decode\n", ++ data->name, data->n_underflows); ++ data->n_underflows = 0; ++ } ++ ++ ret = MME_TermTransformer (data->Handle); ++ if (ret != MME_SUCCESS) ++ { ++ D_WARN ("(%5d) Couldn't terminate %s transformer w/ handle %x: %d (%s)", ++ direct_gettid (), data->name, data->Handle, ret, ++ get_mme_error_string (ret)); ++ return DFB_FAILURE; ++ } ++ ++ D_DEBUG_AT (MME_DEBUG_DOMAIN, " -> terminated %s transformer w/ handle %x\n", ++ data->name, data->Handle); ++ ++ if (data->pending_commands) ++ { ++ pthread_mutex_destroy (&data->pending_commands_lock); ++ direct_hash_destroy (data->pending_commands); ++ data->pending_commands = NULL; ++ } ++ ++ data->Handle = 0; ++ return DFB_OK; ++} ++ ++static DFBResult ++mme_helper_init_transformer2 (struct _MMECommon * const data, ++ const char const * const transformer_names[], ++ size_t transformer_params_size, ++ void * const transformer_params, ++ unsigned int * const ret_index, ++ MME_GenericCallback_t Callback) ++{ ++ DFBResult dfb_res; ++ unsigned int index; ++ ++ MME_ERROR ret; ++ MME_TransformerInitParams_t params; ++ ++ D_ASSUME (data->Handle == 0); ++ D_ASSUME ((transformer_params_size == 0 && transformer_params == NULL) ++ || (transformer_params_size && transformer_params)); ++ ++ if (!mme_lib_inited) ++ return DFB_NOSUCHINSTANCE; ++ ++ params.StructSize = sizeof (params); ++ params.Priority = MME_PRIORITY_BELOW_NORMAL; ++ params.Callback = Callback; ++ params.CallbackUserData = data; ++ params.TransformerInitParamsSize = transformer_params_size; ++ params.TransformerInitParams_p = transformer_params; ++ ++ D_DEBUG_AT (MME_DEBUG_DOMAIN, "initializing %s tranformer:\n", data->name); ++ ++ index = 0; ++ do ++ { ++ D_DEBUG_AT (MME_DEBUG_DOMAIN, " -> %s\n", transformer_names[index]); ++ ++ if (MME_IsTransformerRegistered != (MME_IsTransformerRegistered_func) _mme_helper_MME_func) ++ { ++ ret = MME_IsTransformerRegistered (transformer_names[index]); ++ if (ret != MME_SUCCESS) ++ continue; ++ } ++ ++ ret = MME_InitTransformer (transformer_names[index], ++ ¶ms, &data->Handle); ++ } ++ while (ret != MME_SUCCESS && transformer_names[++index] != NULL); ++ ++ if (ret != MME_SUCCESS) ++ { ++ if (ret != MME_DRIVER_NOT_INITIALIZED ++ && ret != MME_DRIVER_ALREADY_INITIALIZED ++ && ret != MME_UNKNOWN_TRANSFORMER) ++ D_WARN ("(%5d) %s transformer initialisation failed: %s", ++ direct_gettid (), data->name, get_mme_error_string (ret)); ++ data->Handle = 0; ++ return DFB_IDNOTFOUND; ++ } ++ ++ D_DEBUG_AT (MME_DEBUG_DOMAIN, " -> OK (handle %x)\n", data->Handle); ++ ++ D_ASSUME (data->n_pending_buffers == 0); ++ data->n_pending_buffers = 0; ++ pthread_mutex_init (&data->pending_commands_lock, NULL); ++ if ((dfb_res = direct_hash_create (17, &data->pending_commands)) != DFB_OK) ++ { ++ data->pending_commands = NULL; ++ mme_helper_deinit_transformer (data); ++ } ++ ++ if (ret_index) ++ *ret_index = index; ++ ++ return dfb_res; ++} ++ ++static DFBResult ++mme_helper_init_transformer (struct _MMECommon * const data, ++ const char const * const transformer_names[], ++ size_t transformer_params_size, ++ void * const transformer_params, ++ unsigned int * const ret_index) ++{ ++ return mme_helper_init_transformer2 (data, transformer_names, ++ transformer_params_size, ++ transformer_params, ++ ret_index, ++ &TransformerCallback); ++} ++ ++ ++/* Create MME_DataBuffer Structures required to map an Existing Buffer */ ++static void ++create_MME_output_data_buffer (struct _MMECommon * const data, ++ MME_DataBuffer_t * const buf, ++ unsigned int flags, ++ void * const dstbuf, ++ unsigned int size) ++{ ++ buf->StructSize = sizeof (MME_DataBuffer_t); ++ buf->Flags = flags; ++ buf->StreamNumber = 0; ++ buf->NumberOfScatterPages = 1; ++ ++ /* create scatter page detail */ ++ buf->ScatterPages_p = &data->OutDataBufferScatterPage; ++ buf->TotalSize = size; ++ buf->StartOffset = 0; ++ ++ /* scatter page for the data buffer passed in */ ++ buf->ScatterPages_p[0].Page_p = dstbuf; ++ buf->ScatterPages_p[0].Size = size; ++ buf->ScatterPages_p[0].BytesUsed = 0; ++ buf->ScatterPages_p[0].FlagsIn = 0; ++ buf->ScatterPages_p[0].FlagsOut = 0; ++} ++ ++ ++static inline DFBResult ++buffer_to_mme_copy (IDirectFBDataBuffer * const buffer, ++ MME_DataBuffer_t * const dbuf, ++ int len) ++{ ++ dbuf->ScatterPages_p[0].BytesUsed = len; ++ ++ return buffer_to_ptr_copy (buffer, dbuf->ScatterPages_p[0].Page_p, len); ++} ++ ++ ++ ++ ++static DFBResult ++_mme_helper_start_transformer_core (struct _MMECommon * const data, ++ size_t return_params_size, ++ void * const return_params, ++ size_t params_size, ++ void * const params, ++ CoreSurface * const dst_surface, ++ CoreSurfaceBufferLock * const lock) ++{ ++ DFBResult res; ++ unsigned int buffersize; ++ ++ D_ASSERT (data->OutDataBuffers == NULL); ++ ++ res = dfb_surface_lock_buffer (dst_surface, CSBR_BACK, CSAID_ACCEL0, ++ CSAF_WRITE, lock); ++ if (res != DFB_OK) ++ return res; ++ ++ buffersize = lock->pitch * dst_surface->config.size.h; ++ ++ data->OutDataBuffers = (MME_DataBuffer_t **) D_MALLOC (sizeof (MME_DataBuffer_t *)); ++ if (!data->OutDataBuffers) ++ goto out; ++ create_MME_output_data_buffer (data, &data->OutDataBuffer, ++ MME_ALLOCATION_PHYSICAL, ++ lock->addr, buffersize); ++ data->OutDataBuffers[0] = &data->OutDataBuffer; ++ ++ data->TransformCommand.DataBuffers_p = data->OutDataBuffers; ++ ++ D_DEBUG_AT (MME_DEBUG_DOMAIN, "surface locked @ %p (pitch %u)\n", ++ lock->addr, lock->pitch); ++ ++ /* init the commandstatus */ ++ memset (&(data->TransformCommand.CmdStatus), 0, sizeof (MME_CommandStatus_t)); ++ data->TransformCommand.CmdStatus.AdditionalInfoSize = return_params_size; ++ data->TransformCommand.CmdStatus.AdditionalInfo_p = return_params; ++ ++ /* Setting up the command */ ++ data->TransformCommand.StructSize = sizeof (MME_Command_t); ++ data->TransformCommand.CmdCode = MME_TRANSFORM; ++ data->TransformCommand.CmdEnd = MME_COMMAND_END_RETURN_NOTIFY; ++ data->TransformCommand.DueTime = (MME_Time_t) 0; ++ data->TransformCommand.NumberInputBuffers = 0; ++ data->TransformCommand.NumberOutputBuffers = 1; ++ data->TransformCommand.ParamSize = params_size; ++ data->TransformCommand.Param_p = params; ++ ++ data->TransformCommand.DataBuffers_p[0]->ScatterPages_p[0].Size ++ = data->TransformCommand.DataBuffers_p[0]->TotalSize; ++ data->TransformCommand.DataBuffers_p[0]->ScatterPages_p[0].BytesUsed = 0; ++ data->TransformCommand.DataBuffers_p[0]->ScatterPages_p[0].FlagsIn = 0; ++ data->TransformCommand.DataBuffers_p[0]->ScatterPages_p[0].FlagsOut = 0; ++ ++ return DFB_OK; ++ ++out: ++ dfb_surface_unlock_buffer (dst_surface, lock); ++ return D_OOM (); ++} ++ ++ ++static DFBResult ++__attribute__((unused)) ++mme_helper_start_transformer (struct _MMECommon * const data, ++ size_t return_params_size, ++ void * const return_params, ++ size_t params_size, ++ void * const params, ++ CoreSurface * const dst_surface, ++ CoreSurfaceBufferLock * const lock) ++{ ++ DFBResult dfb_res; ++ MME_ERROR mme_res; ++ ++ /* setup transform command */ ++ dfb_res = _mme_helper_start_transformer_core (data, ++ return_params_size, ++ return_params, ++ params_size, params, ++ dst_surface, lock); ++ if (dfb_res != DFB_OK) ++ return dfb_res; ++ ++ _imageprovider_update_transform_params (data, params, lock); ++ ++ D_DEBUG_AT (MME_DEBUG_DOMAIN, "issuing MME_TRANSFORM\n"); ++ ++ /* lock access to hash, because otherwise the callback could be called ++ before we've had a chance to put the command id into the hash */ ++ D_ASSERT (data->pending_commands != NULL); ++ pthread_mutex_lock (&data->pending_commands_lock); ++ ++ mme_res = MME_SendCommand (data->Handle, &data->TransformCommand); ++ if (mme_res != MME_SUCCESS) ++ { ++ pthread_mutex_unlock (&data->pending_commands_lock); ++ ++ D_WARN ("(%5d) %s: starting transformer failed: %d (%s)", ++ direct_gettid (), data->name, mme_res, ++ get_mme_error_string (mme_res)); ++ ++ dfb_surface_unlock_buffer (dst_surface, lock); ++ ++ D_FREE (data->OutDataBuffers); ++ data->OutDataBuffers = NULL; ++ ++ return DFB_FAILURE; ++ } ++ ++ direct_hash_insert (data->pending_commands, ++ data->TransformCommand.CmdStatus.CmdId, ++ (void *) 1); ++ D_DEBUG_AT (MME_DEBUG_DOMAIN, "sent packet's CmdId is %u (%.8x)\n", ++ data->TransformCommand.CmdStatus.CmdId, ++ data->TransformCommand.CmdStatus.CmdId); ++ ++ deb_gettimeofday (&data->starttime, NULL); ++ ++ pthread_mutex_unlock (&data->pending_commands_lock); ++ ++ return DFB_OK; ++} ++ ++ ++static DFBResult ++_alloc_send_buffer (MME_TransformerHandle_t handle, ++ size_t size, ++ struct _MMEHelper_buffer * const buffer) ++{ ++ MME_ERROR res; ++ size_t this_size = MIN (size, MME_STREAMING_BUFFERSIZE); ++ ++ D_ASSERT (buffer != NULL); ++ D_ASSUME (size != 0); ++ D_ASSERT (buffer->buffer == NULL); ++ ++ D_DEBUG_AT (MME_DEBUG_DOMAIN, " -> allocating MME buffer for %u bytes\n", ++ this_size); ++ ++ res = MME_AllocDataBuffer (handle, this_size, MME_ALLOCATION_PHYSICAL, ++ &buffer->buffer); ++ if (unlikely (res)) ++ { ++ D_WARN ("(%5d) MME_AllocDataBuffer() for %u bytes failed: %s", ++ direct_gettid (), this_size, get_mme_error_string (res)); ++ ++ return DFB_NOSYSTEMMEMORY; ++ } ++ ++ buffer->command.StructSize = sizeof (MME_Command_t); ++ buffer->command.CmdCode = MME_SEND_BUFFERS; ++ buffer->command.CmdEnd = MME_COMMAND_END_RETURN_NOTIFY; ++ buffer->command.DueTime = (MME_Time_t) 0; ++ buffer->command.NumberInputBuffers = 1; ++ buffer->command.NumberOutputBuffers = 0; ++ buffer->command.DataBuffers_p = &buffer->buffer; ++ buffer->command.ParamSize = 0; ++ buffer->command.Param_p = NULL; ++ ++ sema_init_event (&buffer->sema, 0); ++ ++ D_DEBUG_AT (MME_DEBUG_DOMAIN, " -> @ %p (%p)\n", ++ buffer, buffer->buffer); ++ ++ return DFB_OK; ++} ++ ++ ++static void ++mme_helper_calculate_packets (struct _MMECommon * const data) ++{ ++ D_ASSUME (data->bytes == 0); ++ ++ /* FIXME: this is BAD (tm) -> think streaming media! */ ++ data->base.buffer->SeekTo (data->base.buffer, 0); ++ ++ /* find out the length of the buffer */ ++ data->base.buffer->GetLength (data->base.buffer, &data->bytes); ++ ++ data->packets = data->bytes / MME_STREAMING_BUFFERSIZE; ++ if ((data->packets * MME_STREAMING_BUFFERSIZE) < data->bytes) ++ ++data->packets; ++ ++ D_DEBUG_AT (MME_DEBUG_DOMAIN, ++ "calculated transfer: %u bytes (%u packets, %u bytes each)\n", ++ data->bytes, data->packets, MME_STREAMING_BUFFERSIZE); ++} ++ ++static DFBResult ++__attribute__((unused)) ++mme_helper_send_packets (struct _MMECommon * const data, ++ unsigned int n_packets) ++{ ++ unsigned int orig_packets; ++ unsigned int currentbuffer = currentbuffer; ++ ++ D_ASSUME (n_packets != 0); ++ ++ if (!data->packets && !data->bytes) ++ return DFB_OK; ++ ++ D_ASSUME (data->packets != 0); ++ D_ASSUME (data->bytes != 0); ++ ++ DFBResult res = DFB_OK; ++ MME_ERROR mme_res; ++ ++ orig_packets = n_packets = MIN (n_packets, data->packets); ++ D_DEBUG_AT (MME_DEBUG_DOMAIN, "Sending %u buffers (out of %u remaining)\n", ++ n_packets, data->packets); ++ ++//#define MME_OOM ++//#define MME_IOERR ++//#define MME_SENDFAIL ++//#define MME_DATA_CORRUPTION ++#if defined(MME_OOM) || defined(MME_IOERR) || defined(MME_SENDFAIL) || defined(MME_DATA_CORRUPTION) ++int i = 0; ++#endif ++ for (; n_packets && data->packets; --data->packets, --n_packets) ++ { ++ struct _MMEHelper_buffer *buffer; ++ unsigned int this_read = MIN (data->bytes, MME_STREAMING_BUFFERSIZE); ++ ++ ++currentbuffer; ++ currentbuffer %= MAX_STREAMING_COMMANDS; ++ ++ buffer = &data->SendDataBuffers[currentbuffer]; ++ ++ /* some checking - We've waited ... should we continue ... */ ++ if (data->decode_success == -1) ++ { ++ D_WARN ("(%5d) ImageProvider/%s: error sending data. Transform " ++ "error reported from callback", ++ direct_gettid (), data->name); ++ return DFB_FAILURE; ++ } ++ ++ /* if we are allocating a new buffer, we don't have to wait on the ++ semaphore, as the new buffer will not yet be known to mme, and thus ++ not in use, of course */ ++ if (!buffer->buffer) ++ { ++#ifdef MME_OOM ++if (++i == 4) ++ { ++ fprintf (stderr, "emulating MME_AllocDataBuffer() failure (MME OOM)\n"); ++ res = DFB_NOSYSTEMMEMORY; ++ } ++else ++#endif ++ res = _alloc_send_buffer (data->Handle, this_read, buffer); ++ if (res != DFB_OK) ++ return res; ++ } ++ else ++ { ++ /* wait for some buffer to be available */ ++ if (unlikely (sema_trywait (&buffer->sema) == -1)) ++ { ++ ++data->packets; ++ ++n_packets; ++ usleep (1); ++ continue; ++ } ++ } ++ ++ D_DEBUG_AT (MME_DEBUG_DOMAIN, " -> sending packet %u, using buffer %u @ %p (%p)\n", ++ orig_packets - n_packets, currentbuffer, buffer, ++ buffer->buffer); ++ D_DEBUG_AT (MME_DEBUG_DOMAIN, " -> %u bytes remaining (this read: %u)\n", ++ data->bytes, this_read); ++ ++ /* lock access to hash, because otherwise the callback could be called ++ before we've had a chance to put the command id into the hash */ ++ /* it also locks acces to data->buffer, because otherwise the callback ++ might determine we ran out of data if called between fetch_data() ++ and actually sending the MME_SendCommand() below. */ ++ D_ASSERT (data->pending_commands != NULL); ++ pthread_mutex_lock (&data->pending_commands_lock); ++ ++ /* don't move the abort out of the pending_commands lock! The JPEG ++ transformer might deadlock otherwise */ ++ if (data->decode_success == 1) ++ { ++ /* corrupt data -> file can be bigger than actual JPEG data */ ++ pthread_mutex_unlock (&data->pending_commands_lock); ++ return DFB_OK; ++ } ++ ++#ifdef MME_IOERR ++if (++i == 8) ++ { ++ fprintf (stderr, "emulating IO (read) error\n"); ++ res = DFB_FAILURE; ++ usleep (1 * 1000 * 1000); ++ } ++else ++#endif ++ res = fetch_data (data->base.buffer, buffer->buffer, this_read); ++ if (res != DFB_OK) ++ { ++ pthread_mutex_unlock (&data->pending_commands_lock); ++ ++ D_WARN ("(%5d) Fetching %u bytes of data failed: res: %d", ++ direct_gettid (), this_read, res); ++ sema_signal_event (&buffer->sema); ++ /* hm, DirectFB (always?) returns DFB_FAILURE here... */ ++ return DFB_IO; ++ } ++#ifdef MME_DATA_CORRUPTION ++if (++i == 2) ++ { ++ fprintf (stderr, "emulating data corruption\n"); ++ memset (&buffer->buffer->ScatterPages_p[0].Page_p[15], 0x15, 10); ++ } ++#endif ++ ++ /* we just read data, nobody should have determined that we ran into ++ an EOF! */ ++ D_ASSERT (data->decode_success != -2); ++ ++ data->bytes -= this_read; ++ ++ D_DEBUG_AT (MME_DEBUG_DOMAIN, " -> sending command in buffer %u\n", ++ currentbuffer); ++ ++ /* send the command */ ++#ifdef MME_SENDFAIL ++if (++i == 4) ++ { ++ fprintf (stderr, "emulating MME_SendCommand() failure\n"); ++ mme_res = MME_NOMEM; ++ } ++else ++#endif ++ mme_res = MME_SendCommand (data->Handle, &buffer->command); ++ if (mme_res != MME_SUCCESS) ++ { ++ pthread_mutex_unlock (&data->pending_commands_lock); ++ ++ D_WARN ("(%5d) send DataCommand failed: %s", ++ direct_gettid (), get_mme_error_string (mme_res)); ++ res = DFB_FAILURE; ++ return DFB_FAILURE; ++ } ++ ++ res = DFB_OK; ++ ++ direct_hash_insert (data->pending_commands, ++ buffer->command.CmdStatus.CmdId, (void *) 1); ++ ++data->n_pending_buffers; ++ D_DEBUG_AT (MME_DEBUG_DOMAIN, "sent packet's CmdId is %u (%.8x), %u packets pending now\n", ++ buffer->command.CmdStatus.CmdId, ++ buffer->command.CmdStatus.CmdId, ++ data->n_pending_buffers); ++ pthread_mutex_unlock (&data->pending_commands_lock); ++ } ++ ++ D_DEBUG_AT (MME_DEBUG_DOMAIN, "done sending packets (%u remaining)\n", ++ data->packets); ++ ++ return res; ++} ++ ++ ++static DFBResult ++__attribute__((unused)) ++mme_helper_stretch_blit (struct _MMECommon * const data, ++ CoreSurface * const src, ++ CoreSurface * const dst, ++ DFBRectangle * const dst_rect) ++{ ++ CardState state; ++ DFBRectangle src_rect; ++ ++ dfb_state_init (&state, data->base.core); ++ ++ /* set clipping and sizes */ ++ state.clip.x1 = 0; ++ state.clip.y1 = 0; ++ state.clip.x2 = dst_rect->w - 1; ++ state.clip.y2 = dst_rect->h - 1; ++ ++ state.modified |= SMF_CLIP; ++ ++ src_rect.x = 0; ++ src_rect.y = 0; ++ src_rect.w = data->width; ++ src_rect.h = data->height; ++ ++ dfb_state_set_source (&state, src); ++ dfb_state_set_destination (&state, dst); ++ ++ extern const char *dfb_pixelformat_name( DFBSurfacePixelFormat format ); ++ D_DEBUG_AT (MME_DEBUG_DOMAIN, "StretchBlit %dx%d (%dx%d) -> %dx%d (%s -> %s)\n", ++ data->width, data->height, src_rect.w, src_rect.h, ++ dst_rect->w, dst_rect->h, ++ dfb_pixelformat_name (src->config.format), ++ dfb_pixelformat_name (dst->config.format)); ++ ++ /* thankfully this is intelligent enough to do a simple blit if possible */ ++ dfb_gfxcard_stretchblit (&src_rect, dst_rect, &state); ++ data->serial = state.serial; ++ ++ /* remove the state */ ++ dfb_state_set_source (&state, NULL); ++ dfb_state_set_destination (&state, NULL); ++ dfb_state_destroy (&state); ++ ++ return DFB_OK; ++} ++#endif /* USE_MME */ ++ ++ ++#endif /* __MME_HELPER_H__ */ +diff --git a/interfaces/IDirectFBImageProvider/sema_helper.h b/interfaces/IDirectFBImageProvider/sema_helper.h +new file mode 100644 +index 0000000..31b2b30 +--- /dev/null ++++ b/interfaces/IDirectFBImageProvider/sema_helper.h +@@ -0,0 +1,61 @@ ++#ifndef __SEMA_HELPER_H__ ++#define __SEMA_HELPER_H__ ++ ++#include ++ ++ ++static inline unsigned int ++__attribute__((warn_unused_result)) ++sema_get_event_val (sem_t * const sema) ++{ ++ int semval; ++ ++ sem_getvalue (sema, &semval); ++ ++ return semval; ++} ++ ++static inline int ++__attribute__((warn_unused_result)) ++sema_wait_event (sem_t * const sema) ++{ ++ D_DEBUG_AT (SEMA_DEBUG_DOMAIN, "waiting on %p (val: %u)\n", sema, sema_get_event_val (sema)); ++ ++ return sem_wait (sema); ++} ++ ++static inline int ++__attribute__((warn_unused_result)) ++sema_trywait (sem_t * const sema) ++{ ++ D_DEBUG_AT (SEMA_DEBUG_DOMAIN, "trywait on %p (val: %u)\n", sema, sema_get_event_val (sema)); ++ ++ return sem_trywait (sema); ++} ++ ++static inline void ++sema_signal_event (sem_t * const sema) ++{ ++ D_DEBUG_AT (SEMA_DEBUG_DOMAIN, "signalling %p (val: %u)\n", sema, sema_get_event_val (sema)); ++ ++ sem_post (sema); ++} ++ ++static inline void ++sema_init_event (sem_t * const sema, ++ unsigned int val) ++{ ++ D_DEBUG_AT (SEMA_DEBUG_DOMAIN, "init'ing sema %p to %u\n", sema, val); ++ ++ sem_init (sema, 0, val); ++} ++ ++static inline void ++sema_close_event (sem_t * const sema) ++{ ++ D_DEBUG_AT (SEMA_DEBUG_DOMAIN, "destroying sema %p\n", sema); ++ ++ sem_destroy (sema); ++} ++ ++#endif /* __SEMA_HELPER_H__ */ +diff --git a/interfaces/IDirectFBVideoProvider/idirectfbvideoprovider_gif.c b/interfaces/IDirectFBVideoProvider/idirectfbvideoprovider_gif.c +index aeb9e82..4266115 100644 +--- a/interfaces/IDirectFBVideoProvider/idirectfbvideoprovider_gif.c ++++ b/interfaces/IDirectFBVideoProvider/idirectfbvideoprovider_gif.c +@@ -32,7 +32,9 @@ + #include + #include + #include ++#include + #include ++#include + + #include + +@@ -60,7 +62,7 @@ + static DFBResult Probe( IDirectFBVideoProvider_ProbeContext *ctx ); + + static DFBResult Construct( IDirectFBVideoProvider *thiz, +- IDirectFBDataBuffer *buffer ); ++ ... ); + + + #include +@@ -93,19 +95,28 @@ typedef struct { + IDirectFBSurface *destination; + IDirectFBSurface_data *dst_data; + DFBRectangle dst_rect; +- +- u32 *image; +- ++ ++ DFBColor palette[MAXCOLORMAPSIZE]; ++ ++ CoreSurface *decode_surface; ++ CoreSurfaceBufferLock buffer_lock; ++ + DirectThread *thread; + pthread_mutex_t lock; + pthread_cond_t cond; + ++ int paused; ++ + DFBVideoProviderStatus status; + DFBVideoProviderPlaybackFlags flags; + double speed; + + unsigned int start_pos; + ++ unsigned int frame; ++ unsigned int target_frame; /* only in DVPLAY_PACED */ ++ unsigned int last_frame; /* only in DVPLAY_PACED */ ++ + char Version[4]; + unsigned int Width; + unsigned int Height; +@@ -133,6 +144,8 @@ typedef struct { + + DVFrameCallback callback; + void *callback_ctx; ++ ++ CoreDFB *core; + } IDirectFBVideoProvider_GIF_data; + + #define GIFERRORMSG(x, ...) \ +@@ -167,7 +180,7 @@ FetchData( IDirectFBDataBuffer *buffer, void *data, unsigned int len ) + } + + static int ReadColorMap( IDirectFBDataBuffer *buffer, int number, +- u8 buf[3][MAXCOLORMAPSIZE] ) ++ DFBColor palette[MAXCOLORMAPSIZE] ) + { + int i; + u8 rgb[3*number]; +@@ -178,9 +191,10 @@ static int ReadColorMap( IDirectFBDataBuffer *buffer, int number, + } + + for (i = 0; i < number; ++i) { +- buf[CM_RED][i] = rgb[i*3+0]; +- buf[CM_GREEN][i] = rgb[i*3+1]; +- buf[CM_BLUE][i] = rgb[i*3+2]; ++ palette[i].r = rgb[i*3+0]; ++ palette[i].g = rgb[i*3+1]; ++ palette[i].b = rgb[i*3+2]; ++ palette[i].a = 0xff; + } + + return 0; +@@ -403,12 +417,13 @@ static int LWZReadByte( IDirectFBVideoProvider_GIF_data *data, int flag, int inp + + static int ReadImage( IDirectFBVideoProvider_GIF_data *data, + int left, int top, int width, int height, +- u8 cmap[3][MAXCOLORMAPSIZE], bool interlace, bool ignore ) ++ int pitch, DFBColor palette[MAXCOLORMAPSIZE], ++ bool interlace, bool ignore ) + { + u8 c; + int v; + int xpos = 0, ypos = 0, pass = 0; +- u32 *image, *dst; ++ u32 *image = image, *dst = dst; + + /* + ** Initialize the decompression routines +@@ -422,7 +437,7 @@ static int ReadImage( IDirectFBVideoProvider_GIF_data *data, + /* + ** If this is an "uninteresting picture" ignore it. + */ +- if (ignore) { ++ if (ignore && !data->disposal) { + GIFDEBUGMSG("skipping image..."); + + while (LWZReadByte( data, false, c ) >= 0) +@@ -432,8 +447,7 @@ static int ReadImage( IDirectFBVideoProvider_GIF_data *data, + + switch (data->disposal) { + case 2: +- GIFDEBUGMSG("restoring to background color..."); +- memset( data->image, 0, data->Width * data->Height * 4 ); ++ GIFDEBUGMSG("restoring to background color is unsupported"); + break; + case 3: + GIFERRORMSG("restoring to previous frame is unsupported"); +@@ -442,17 +456,18 @@ static int ReadImage( IDirectFBVideoProvider_GIF_data *data, + break; + } + +- dst = image = data->image + (top * data->Width + left); ++ dst = image = ((u32 *)(data->buffer_lock.addr) ++ + (top * (pitch / 4) + left)); + + GIFDEBUGMSG("reading %dx%d at %dx%d %sGIF image", + width, height, left, top, interlace ? " interlaced " : "" ); + + while ((v = LWZReadByte( data, false, c )) >= 0 ) { + if (v != data->transparent) { +- dst[xpos] = (0xFF000000 | +- cmap[CM_RED][v] << 16 | +- cmap[CM_GREEN][v] << 8 | +- cmap[CM_BLUE][v]); ++ dst[xpos] = (0xFF000000 | ++ palette[v].r << 16 | ++ palette[v].g << 8 | ++ palette[v].b); + } + + ++xpos; +@@ -492,8 +507,10 @@ static int ReadImage( IDirectFBVideoProvider_GIF_data *data, + else { + ++ypos; + } +- dst = image + ypos * data->Width; +- } ++ ++ dst = image + ypos * (pitch >> 2); ++ } ++ + if (ypos >= height) { + break; + } +@@ -515,9 +532,6 @@ static void GIFReset( IDirectFBVideoProvider_GIF_data *data ) + data->delayTime = 1000000; /* default: 1s */ + data->inputFlag = -1; + data->disposal = 0; +- +- if (data->image) +- memset( data->image, 0, data->Width*data->Height*4 ); + } + + static DFBResult GIFReadHeader( IDirectFBVideoProvider_GIF_data *data ) +@@ -557,7 +571,7 @@ static DFBResult GIFReadHeader( IDirectFBVideoProvider_GIF_data *data ) + data->AspectRatio = (data->Width << 8) / data->Height; + + if (BitSet(buf[4], LOCALCOLORMAP)) { /* Global Colormap */ +- if (ReadColorMap( data->buffer, data->BitPixel, data->ColorMap )) { ++ if (ReadColorMap( data->buffer, data->BitPixel, data->palette )) { + GIFERRORMSG("error reading global colormap"); + return DFB_FAILURE; + } +@@ -571,8 +585,10 @@ static DFBResult GIFReadFrame( IDirectFBVideoProvider_GIF_data *data ) + u8 buf[16], c; + int top, left; + int width, height; +- u8 localColorMap[3][MAXCOLORMAPSIZE]; ++ DFBColor local_palette[MAXCOLORMAPSIZE]; + bool useGlobalColormap; ++ int ignore = 0; ++ int num_frames = 0; + + data->curbit = data->lastbit = data->done = data->last_byte = 0; + +@@ -582,21 +598,41 @@ static DFBResult GIFReadFrame( IDirectFBVideoProvider_GIF_data *data ) + data->firstcode = data->oldcode = + data->clear_code = data->end_code = 0; + +- for (;;) { ++ dfb_surface_lock_buffer( data->decode_surface, ++ CSBR_BACK, CSAID_CPU, CSAF_WRITE, ++ &data->buffer_lock ); ++ ++ if (data->flags & DVPLAY_PACED ++ && data->target_frame != -1) { ++ ignore = data->target_frame != (data->frame + 1); ++ num_frames = data->target_frame - data->frame - 1; ++ } ++ ++ if (!data->frame) ++ num_frames++; ++ ++ for (; num_frames >= 0;) { + DFBResult ret; + + ret = FetchData( data->buffer, &c, 1); + if (ret) { + GIFERRORMSG("EOF / read error on image data" ); ++ dfb_surface_unlock_buffer( data->decode_surface, ++ &data->buffer_lock ); + return DFB_EOF; + } + +- if (c == ';') /* GIF terminator */ ++ if (c == ';') { /* GIF terminator */ ++ dfb_surface_unlock_buffer( data->decode_surface, ++ &data->buffer_lock ); + return DFB_EOF; ++ } + + if (c == '!') { /* Extension */ + if (FetchData( data->buffer, &c, 1)) { + GIFERRORMSG("EOF / read error on extention function code"); ++ dfb_surface_unlock_buffer( data->decode_surface, ++ &data->buffer_lock ); + return DFB_EOF; + } + DoExtension( data, c ); +@@ -611,6 +647,8 @@ static DFBResult GIFReadFrame( IDirectFBVideoProvider_GIF_data *data ) + ret = FetchData( data->buffer, buf, 9 ); + if (ret) { + GIFERRORMSG("couldn't read left/top/width/height"); ++ dfb_surface_unlock_buffer( data->decode_surface, ++ &data->buffer_lock ); + return ret; + } + +@@ -623,21 +661,28 @@ static DFBResult GIFReadFrame( IDirectFBVideoProvider_GIF_data *data ) + + if (!useGlobalColormap) { + int bitPixel = 2 << (buf[8] & 0x07); +- if (ReadColorMap( data->buffer, bitPixel, localColorMap )) ++ if (ReadColorMap( data->buffer, bitPixel, local_palette )) + GIFERRORMSG("error reading local colormap"); + } + ++ data->frame++; ++ num_frames--; ++ ++ + if (ReadImage( data, left, top, width, height, +- (useGlobalColormap ? +- data->ColorMap : localColorMap), +- BitSet( buf[8], INTERLACE ), 0 )) { ++ data->buffer_lock.pitch, ++ (useGlobalColormap ? ++ data->palette : local_palette), ++ BitSet( buf[8], INTERLACE ), ignore )) { + GIFERRORMSG("error reading image"); ++ dfb_surface_unlock_buffer( data->decode_surface, ++ &data->buffer_lock ); + return DFB_FAILURE; + } +- +- break; + } + ++ dfb_surface_unlock_buffer( data->decode_surface, &data->buffer_lock ); ++ + return DFB_OK; + } + +@@ -649,13 +694,31 @@ IDirectFBVideoProvider_GIF_Destruct( IDirectFBVideoProvider *thiz ) + IDirectFBVideoProvider_GIF_data *data = thiz->priv; + + thiz->Stop( thiz ); +- +- if (data->image) +- D_FREE( data->image ); +- ++ ++ if (data->thread) { ++ direct_thread_cancel( data->thread ); ++ pthread_mutex_lock( &data->lock ); ++ pthread_cond_signal( &data->cond ); ++ pthread_mutex_unlock( &data->lock ); ++ direct_thread_join( data->thread ); ++ direct_thread_destroy( data->thread ); ++ data->thread = NULL; ++ } ++ + if (data->buffer) + data->buffer->Release( data->buffer ); +- ++ ++ if (data->destination) { ++ data->destination->Release( data->destination ); ++ data->destination = NULL; ++ data->dst_data = NULL; ++ } ++ ++ if (data->decode_surface) { ++ dfb_surface_unref( data->decode_surface ); ++ data->decode_surface = NULL; ++ } ++ + pthread_cond_destroy( &data->cond ); + pthread_mutex_destroy( &data->lock ); + +@@ -705,12 +768,11 @@ IDirectFBVideoProvider_GIF_GetSurfaceDescription( IDirectFBVideoProvider *thiz, + + if (!desc) + return DFB_INVARG; +- +- desc->flags = DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT; +- desc->width = data->Width; +- desc->height = data->Height; +- desc->pixelformat = DSPF_ARGB; + ++ desc->width = data->Width; ++ desc->height = data->Height; ++ desc->pixelformat = DSPF_ARGB; ++ + return DFB_OK; + } + +@@ -738,19 +800,58 @@ IDirectFBVideoProvider_GIF_GetStreamDescription( IDirectFBVideoProvider *thiz, + return DFB_OK; + } + ++static void ++clear_decode_surface(IDirectFBVideoProvider_GIF_data *data) ++{ ++ CardState state; ++ DFBRectangle rect = { .x = 0, ++ .y = 0, ++ .w = data->Width, ++ .h = data->Height }; ++ ++ DFBColor color = { .r = 0, ++ .g = 0, ++ .b = 0, ++ .a = 0 }; ++ ++ DFBRegion clip = { .x1 = 0, ++ .y1 = 0, ++ .x2 = data->Width - 1, ++ .y2 = data->Height - 1 }; ++ ++ /* init a fillrect state */ ++ dfb_state_init( &state, data->core ); ++ dfb_state_set_color( &state, &color ); ++ dfb_state_set_source( &state, NULL ); ++ dfb_state_set_destination( &state, data->decode_surface ); ++ dfb_state_set_clip( &state, &clip ); ++ ++ dfb_gfxcard_fillrectangles( &rect, 1, &state ); ++ ++ /* wait for the h/w to complete */ ++ dfb_gfxcard_wait_serial( &state.serial ); ++ ++ /* remove the state */ ++ dfb_state_set_source( &state, NULL ); ++ dfb_state_set_destination( &state, NULL ); ++ dfb_state_destroy( &state ); ++} ++ + static void* + GIFVideo( DirectThread *self, void *arg ) + { + IDirectFBVideoProvider_GIF_data *data = arg; + + pthread_setcancelstate( PTHREAD_CANCEL_DISABLE, NULL ); +- ++ ++ data->frame = 0; ++ ++ clear_decode_surface( data ); ++ + while (!direct_thread_is_canceled( self )) { + DFBResult ret; + DFBRectangle rect; + DFBRegion clip; +- CoreSurface *surface; +- CoreSurfaceBufferLock lock; + + pthread_mutex_lock( &data->lock ); + +@@ -759,10 +860,36 @@ GIFVideo( DirectThread *self, void *arg ) + break; + } + ++ /* check if the requested frame doesn't exist */ ++ if (data->flags & DVPLAY_PACED ++ && data->last_frame ++ && data->target_frame > data->last_frame) { ++ /* notify the caller */ ++ data->target_frame = -1; ++ data->callback( data->callback_ctx ); ++ /* wait for the next call */ ++ data->status = DVSTATE_STOP; ++ pthread_cond_wait( &data->cond, &data->lock ); ++ pthread_mutex_unlock( &data->lock ); ++ continue; ++ } ++ ++ /* restart decoding if the newly requested frame precedes or is ++ the last decoded one when in DVPLAY_PACED mode */ ++ if (data->flags & DVPLAY_PACED ++ && data->target_frame != -1 ++ && data->target_frame < data->frame) { ++ GIFReset( data ); ++ data->frame = 0; ++ data->buffer->SeekTo( data->buffer, data->start_pos ); ++ } ++ + ret = GIFReadFrame( data ); + if (ret) { + if (ret == DFB_EOF) { ++ data->last_frame = data->frame; + GIFReset( data ); ++ data->frame = 0; + if (data->flags & DVPLAY_LOOPING) { + data->buffer->SeekTo( data->buffer, data->start_pos ); + } +@@ -772,6 +899,15 @@ GIFVideo( DirectThread *self, void *arg ) + break; + } + } ++ /* bail out if stream is invalid */ ++ if (data->flags & DVPLAY_PACED) { ++ /* notify the caller */ ++ data->target_frame = -1; /* error */ ++ data->callback( data->callback_ctx ); ++ /* wait for the next call */ ++ data->status = DVSTATE_STOP; ++ pthread_cond_wait( &data->cond, &data->lock ); ++ } + pthread_mutex_unlock( &data->lock ); + continue; + } +@@ -780,41 +916,58 @@ GIFVideo( DirectThread *self, void *arg ) + ? data->dst_data->area.wanted : data->dst_rect; + dfb_region_from_rectangle( &clip, &data->dst_data->area.current ); + +- surface = data->dst_data->surface; +- D_MAGIC_ASSERT( surface, CoreSurface ); +- +- if (dfb_rectangle_region_intersects( &rect, &clip ) && +- dfb_surface_lock_buffer( surface, CSBR_BACK, CSAID_CPU, CSAF_WRITE, &lock ) == DFB_OK) ++ CardState state; ++ CoreSurface *dst_surface; ++ DFBRectangle srect = { .x = 0, ++ .y = 0, ++ .w = data->Width, ++ .h = data->Height, }; ++ ++ dst_surface = data->dst_data->surface; ++ D_MAGIC_ASSERT( dst_surface, CoreSurface ); ++ ++ /* init a state, so that we can use gfxcard/blit to do the ++ format conversion. */ ++ dfb_state_init( &state, data->core ); ++ dfb_state_set_source( &state, data->decode_surface ); ++ dfb_state_set_destination( &state, dst_surface ); ++ dfb_state_set_clip( &state, &clip ); ++ ++ dfb_gfxcard_stretchblit( &srect, &rect, &state ); ++ ++ /* remove the state */ ++ dfb_state_set_source( &state, NULL ); ++ dfb_state_set_destination( &state, NULL ); ++ dfb_state_destroy( &state ); ++ ++ if (data->callback) ++ data->callback( data->callback_ctx ); ++ ++ if (!(data->flags & DVPLAY_PACED)) + { +- dfb_scale_linear_32( data->image, data->Width, data->Height, +- lock.addr, lock.pitch, &rect, data->dst_data->surface, &clip ); +- +- dfb_surface_unlock_buffer( surface, &lock ); +- +- if (data->callback) +- data->callback( data->callback_ctx ); +- } ++ if (!data->speed) ++ pthread_cond_wait( &data->cond, &data->lock ); ++ else { ++ struct timespec ts; ++ struct timeval tv; ++ unsigned long us; ++ ++ gettimeofday( &tv, NULL ); + +- if (!data->speed) { ++ us = data->delayTime; ++ if (data->speed != 1.0) ++ us = ((double)us / data->speed + .5); ++ us += tv.tv_usec; ++ ++ ts.tv_sec = tv.tv_sec + us/1000000; ++ ts.tv_nsec = (us%1000000) * 1000; ++ ++ pthread_cond_timedwait( &data->cond, &data->lock, &ts ); ++ } ++ } else { ++ data->status = DVSTATE_STOP; + pthread_cond_wait( &data->cond, &data->lock ); + } +- else { +- struct timespec ts; +- struct timeval tv; +- unsigned long us; +- +- gettimeofday( &tv, NULL ); +- +- us = data->delayTime; +- if (data->speed != 1.0) +- us = ((double)us / data->speed + .5); +- us += tv.tv_usec; +- +- ts.tv_sec = tv.tv_sec + us/1000000; +- ts.tv_nsec = (us%1000000) * 1000; +- +- pthread_cond_timedwait( &data->cond, &data->lock, &ts ); +- } + + pthread_mutex_unlock( &data->lock ); + } +@@ -832,7 +985,10 @@ IDirectFBVideoProvider_GIF_PlayTo( IDirectFBVideoProvider *thiz, + IDirectFBSurface_data *dst_data; + DFBRectangle rect = { 0, 0, 0, 0 }; + DFBResult ret; +- ++ ++ DFBVideoProviderPacedPlaybackCtx *Ctx = ++ (DFBVideoProviderPacedPlaybackCtx *)ctx; ++ + DIRECT_INTERFACE_GET_DATA( IDirectFBVideoProvider_GIF ) + + if (!destination) +@@ -841,7 +997,7 @@ IDirectFBVideoProvider_GIF_PlayTo( IDirectFBVideoProvider *thiz, + dst_data = destination->priv; + if (!dst_data || !dst_data->surface) + return DFB_DESTROYED; +- ++ + if (dest_rect) { + if (dest_rect->w < 1 || dest_rect->h < 1) + return DFB_INVARG; +@@ -851,6 +1007,11 @@ IDirectFBVideoProvider_GIF_PlayTo( IDirectFBVideoProvider *thiz, + rect.y += dst_data->area.wanted.y; + } + ++ if (data->flags & DVPLAY_PACED) { ++ if (!Ctx || !callback) ++ return DFB_INVARG; ++ } ++ + pthread_mutex_lock( &data->lock ); + + if (data->status == DVSTATE_FINISHED) { +@@ -862,14 +1023,6 @@ IDirectFBVideoProvider_GIF_PlayTo( IDirectFBVideoProvider *thiz, + } + data->status = DVSTATE_PLAY; + +- if (!data->image) { +- data->image = D_CALLOC( 4, data->Width * data->Height ); +- if (!data->image) { +- pthread_mutex_unlock( &data->lock ); +- return D_OOM(); +- } +- } +- + if (data->destination) + data->destination->Release( data->destination ); + +@@ -877,10 +1030,32 @@ IDirectFBVideoProvider_GIF_PlayTo( IDirectFBVideoProvider *thiz, + data->destination = destination; + data->dst_data = dst_data; + data->dst_rect = rect; +- ++ + data->callback = callback; + data->callback_ctx = ctx; ++ if (data->flags & DVPLAY_PACED) ++ data->target_frame = Ctx->num_frame; + ++ if (!data->decode_surface) { ++ ret = dfb_surface_create_simple( data->core, ++ data->Width, data->Height, ++ DSPF_ARGB, DSCS_RGB, ++ DSCAPS_NONE, CSTF_NONE, 0, ++ NULL, &data->decode_surface ); ++ if (ret != DFB_OK) { ++ pthread_mutex_unlock( &data->lock ); ++ return ret; ++ } ++ } ++ ++ /* Playback has already been started by a previous call to PlayTo() */ ++ if (data->thread && (data->flags & DVPLAY_PACED)) { ++ data->paused = 0; ++ pthread_cond_signal( &data->cond ); ++ pthread_mutex_unlock( &data->lock ); ++ return DFB_OK; ++ } ++ + if (!data->thread) { + data->thread = direct_thread_create( DTT_DEFAULT, GIFVideo, + (void*)data, "GIF Video" ); +@@ -895,25 +1070,33 @@ static DFBResult + IDirectFBVideoProvider_GIF_Stop( IDirectFBVideoProvider *thiz ) + { + DIRECT_INTERFACE_GET_DATA( IDirectFBVideoProvider_GIF ) +- +- if (data->thread) { +- direct_thread_cancel( data->thread ); +- pthread_mutex_lock( &data->lock ); +- pthread_cond_signal( &data->cond ); +- pthread_mutex_unlock( &data->lock ); +- direct_thread_join( data->thread ); +- direct_thread_destroy( data->thread ); +- data->thread = NULL; +- } +- +- if (data->destination) { +- data->destination->Release( data->destination ); +- data->destination = NULL; +- data->dst_data = NULL; ++ ++ if (data->flags & DVPLAY_PACED) { ++ /* sync with the decoding thread */ ++ pthread_mutex_lock( &data->lock ); ++ assert( data->status == DVSTATE_STOP ); ++ pthread_mutex_unlock( &data->lock ); ++ return DFB_OK; ++ } else { ++ if (data->thread) { ++ direct_thread_cancel( data->thread ); ++ pthread_mutex_lock( &data->lock ); ++ pthread_cond_signal( &data->cond ); ++ pthread_mutex_unlock( &data->lock ); ++ direct_thread_join( data->thread ); ++ direct_thread_destroy( data->thread ); ++ data->thread = NULL; ++ } ++ ++ if (data->destination) { ++ data->destination->Release( data->destination ); ++ data->destination = NULL; ++ data->dst_data = NULL; ++ } ++ ++ data->status = DVSTATE_STOP; + } + +- data->status = DVSTATE_STOP; +- + return DFB_OK; + } + +@@ -977,11 +1160,14 @@ IDirectFBVideoProvider_GIF_SetPlaybackFlags( IDirectFBVideoProvider *thiz + { + DIRECT_INTERFACE_GET_DATA( IDirectFBVideoProvider_GIF ) + +- if (flags & ~DVPLAY_LOOPING) ++ if (flags & ~(DVPLAY_LOOPING | DVPLAY_PACED)) + return DFB_UNSUPPORTED; + + if (flags & DVPLAY_LOOPING && !data->seekable) + return DFB_UNSUPPORTED; ++ ++ if (flags & DVPLAY_PACED) ++ data->target_frame = -1; + + data->flags = flags; + +@@ -1033,12 +1219,22 @@ Probe( IDirectFBVideoProvider_ProbeContext *ctx ) + + static DFBResult + Construct( IDirectFBVideoProvider *thiz, +- IDirectFBDataBuffer *buffer ) ++ ... ) + { + DFBResult ret; + ++ IDirectFBDataBuffer *buffer; ++ CoreDFB *core; ++ va_list tag; ++ + DIRECT_ALLOCATE_INTERFACE_DATA( thiz, IDirectFBVideoProvider_GIF ) + ++ va_start( tag, thiz ); ++ buffer = va_arg( tag, IDirectFBDataBuffer * ); ++ core = va_arg( tag, CoreDFB * ); ++ va_end( tag ); ++ ++ data->core = core; + data->ref = 1; + data->status = DVSTATE_STOP; + data->buffer = buffer; +@@ -1056,9 +1252,13 @@ Construct( IDirectFBVideoProvider *thiz, + + data->buffer->GetPosition( data->buffer, &data->start_pos ); + +- direct_util_recursive_pthread_mutex_init( &data->lock ); ++ pthread_mutex_init( &data->lock, NULL ); + pthread_cond_init( &data->cond, NULL ); + ++ data->paused = 0; ++ data->decode_surface = NULL; ++ data->last_frame = 0; ++ + thiz->AddRef = IDirectFBVideoProvider_GIF_AddRef; + thiz->Release = IDirectFBVideoProvider_GIF_Release; + thiz->GetCapabilities = IDirectFBVideoProvider_GIF_GetCapabilities; +diff --git a/lib/direct/clock.c b/lib/direct/clock.c +index d8f1ec0..e394c6a 100644 +--- a/lib/direct/clock.c ++++ b/lib/direct/clock.c +@@ -36,28 +36,28 @@ D_LOG_DOMAIN( Direct_Clock, "Direct/Clock", "Time measurement etc." ); + + /**********************************************************************************************************************/ + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + long long + direct_clock_get_micros( void ) + { + return direct_clock_get_time( DIRECT_CLOCK_SESSION ); + } + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + long long + direct_clock_get_millis( void ) + { + return direct_clock_get_time( DIRECT_CLOCK_SESSION ) / 1000LL; + } + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + long long + direct_clock_get_abs_micros( void ) + { + return direct_clock_get_time( DIRECT_CLOCK_REALTIME ); + } + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + long long + direct_clock_get_abs_millis( void ) + { +diff --git a/lib/direct/debug.c b/lib/direct/debug.c +index 2fd2072..1117e7e 100644 +--- a/lib/direct/debug.c ++++ b/lib/direct/debug.c +@@ -48,7 +48,7 @@ + + #if DIRECT_BUILD_DEBUGS /* Build with debug support? */ + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + void + direct_debug_log( DirectLogDomain *domain, + unsigned int debug_level, /* 1-9, 0 = info */ +@@ -63,7 +63,7 @@ direct_debug_log( DirectLogDomain *domain, + va_end( ap ); + } + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + void + direct_debug_at( DirectLogDomain *domain, + const char *format, ... ) +@@ -77,7 +77,7 @@ direct_debug_at( DirectLogDomain *domain, + + #endif /* DIRECT_BUILD_DEBUGS */ + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + void + direct_debug_at_always( DirectLogDomain *domain, + const char *format, ... ) +@@ -93,7 +93,7 @@ direct_debug_at_always( DirectLogDomain *domain, + + #if DIRECT_BUILD_DEBUGS /* Build with debug support? */ + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + void + direct_break( const char *func, + const char *file, +@@ -123,7 +123,7 @@ direct_break( const char *func, + direct_trap( "Break", SIGABRT ); + } + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + void + direct_assertion( const char *exp, + const char *func, +@@ -144,7 +144,7 @@ direct_assertion( const char *exp, + direct_trap( "Assertion", SIGTRAP ); + } + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + void + direct_assumption( const char *exp, + const char *func, +diff --git a/lib/direct/interface.c b/lib/direct/interface.c +index 1a5a926..faaecd5 100644 +--- a/lib/direct/interface.c ++++ b/lib/direct/interface.c +@@ -522,7 +522,7 @@ direct_print_interface_leaks( void ) + + /**************************************************************************************************/ + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + static InterfaceDesc * + allocate_interface_desc( void ) + { +@@ -543,7 +543,7 @@ allocate_interface_desc( void ) + return &alloc_list[alloc_count++]; + } + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + static __inline__ void + fill_interface_desc( InterfaceDesc *desc, + const void *interface_ptr, +@@ -565,7 +565,7 @@ fill_interface_desc( InterfaceDesc *desc, + + /**************************************************************************************************/ + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + void + direct_dbg_interface_add( const char *func, + const char *file, +@@ -586,7 +586,7 @@ direct_dbg_interface_add( const char *func, + direct_mutex_unlock( &alloc_lock ); + } + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + void + direct_dbg_interface_remove( const char *func, + const char *file, +diff --git a/lib/direct/log.c b/lib/direct/log.c +index 4645939..0ec9189 100644 +--- a/lib/direct/log.c ++++ b/lib/direct/log.c +@@ -128,7 +128,7 @@ direct_log_destroy( DirectLog *log ) + return DR_OK; + } + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + DirectResult + direct_log_printf( DirectLog *log, + const char *format, ... ) +@@ -197,7 +197,7 @@ direct_log_set_default( DirectLog *log ) + return DR_OK; + } + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + void + direct_log_lock( DirectLog *log ) + { +@@ -211,7 +211,7 @@ direct_log_lock( DirectLog *log ) + direct_mutex_lock( &log->lock ); + } + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + void + direct_log_unlock( DirectLog *log ) + { +@@ -262,7 +262,7 @@ direct_log_flush( DirectLog *log, + + /**********************************************************************************************************************/ + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + DirectLog * + direct_log_default( void ) + { +diff --git a/lib/direct/log_domain.c b/lib/direct/log_domain.c +index dcadbed..cf2c94c 100644 +--- a/lib/direct/log_domain.c ++++ b/lib/direct/log_domain.c +@@ -69,7 +69,7 @@ __D_log_domain_deinit() + + /**********************************************************************************************************************/ + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + static __inline__ LogDomainEntry * + lookup_domain( const char *name, bool sub ); + +@@ -104,7 +104,7 @@ lookup_domain( const char *name, bool sub ) + return NULL; + } + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + static DirectLogLevel + check_domain( DirectLogDomain *domain ); + +@@ -199,7 +199,7 @@ direct_log_domain_check( DirectLogDomain *domain ) + /* FIXME: merge following */ + + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + DirectResult + direct_log_domain_vprintf( DirectLogDomain *domain, + DirectLogLevel level, +@@ -260,7 +260,7 @@ direct_log_domain_vprintf( DirectLogDomain *domain, + return DR_OK; + } + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + DirectResult + direct_log_domain_log( DirectLogDomain *domain, + DirectLogLevel level, +diff --git a/lib/direct/mem.c b/lib/direct/mem.c +index 401e4c8..ac064da 100644 +--- a/lib/direct/mem.c ++++ b/lib/direct/mem.c +@@ -121,7 +121,7 @@ direct_print_memleaks( void ) + + /**********************************************************************************************************************/ + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + static __inline__ MemDesc * + fill_mem_desc( MemDesc *desc, int bytes, const char *func, const char *file, int line, DirectTraceBuffer *trace ) + { +diff --git a/lib/direct/messages.c b/lib/direct/messages.c +index 0331e68..be3148b 100644 +--- a/lib/direct/messages.c ++++ b/lib/direct/messages.c +@@ -40,7 +40,7 @@ + + #if DIRECT_BUILD_TEXT + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + void + direct_messages_info( const char *format, ... ) + { +@@ -57,7 +57,7 @@ direct_messages_info( const char *format, ... ) + direct_log_printf( NULL, "(*) %s", buf ); + } + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + void + direct_messages_error( const char *format, ... ) + { +@@ -76,7 +76,7 @@ direct_messages_error( const char *format, ... ) + direct_trace_print_stack( NULL ); + } + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + void + direct_messages_derror( DirectResult result, const char *format, ... ) + { +@@ -95,7 +95,7 @@ direct_messages_derror( DirectResult result, const char *format, ... ) + direct_trace_print_stack( NULL ); + } + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + void + direct_messages_perror( int erno, const char *format, ... ) + { +@@ -114,7 +114,7 @@ direct_messages_perror( int erno, const char *format, ... ) + direct_trace_print_stack( NULL ); + } + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + void + direct_messages_dlerror( const char *dlerr, const char *format, ... ) + { +@@ -133,7 +133,7 @@ direct_messages_dlerror( const char *dlerr, const char *format, ... ) + direct_trace_print_stack( NULL ); + } + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + void + direct_messages_once( const char *func, + const char *file, +@@ -155,7 +155,7 @@ direct_messages_once( const char *func, + direct_trace_print_stack( NULL ); + } + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + void + direct_messages_unimplemented( const char *func, + const char *file, +@@ -166,7 +166,7 @@ direct_messages_unimplemented( const char *func, + direct_trace_print_stack( NULL ); + } + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + void + direct_messages_bug( const char *func, + const char *file, +@@ -188,7 +188,7 @@ direct_messages_bug( const char *func, + direct_trace_print_stack( NULL ); + } + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + void + direct_messages_warn( const char *func, + const char *file, +diff --git a/lib/direct/os/linux/glibc/types.h b/lib/direct/os/linux/glibc/types.h +index 55c570b..c7e0f94 100644 +--- a/lib/direct/os/linux/glibc/types.h ++++ b/lib/direct/os/linux/glibc/types.h +@@ -74,7 +74,7 @@ typedef int64_t s64; + + #define __inline__ inline + #define D_UNUSED __attribute__((unused)) +-#define __no_instrument_function__ __attribute__((no_instrument_function)) ++#define __dfb_no_instrument_function__ __attribute__((no_instrument_function)) + #define __constructor__ __attribute__((constructor)) + #define __destructor__ __attribute__((destructor)) + #define __typeof__(x) __typeof__(x) +diff --git a/lib/direct/os/linux/glibc/waitqueue.h b/lib/direct/os/linux/glibc/waitqueue.h +index 9ba37e9..f861f11 100644 +--- a/lib/direct/os/linux/glibc/waitqueue.h ++++ b/lib/direct/os/linux/glibc/waitqueue.h +@@ -68,14 +68,12 @@ direct_waitqueue_wait( DirectWaitQueue *queue, DirectMutex *mutex ) + static inline DirectResult + direct_waitqueue_wait_timeout( DirectWaitQueue *queue, DirectMutex *mutex, unsigned long micros ) + { +- struct timeval now; + struct timespec timeout; +- long int nano_seconds = micros * 1000; + +- gettimeofday( &now, NULL ); ++ clock_gettime( CLOCK_REALTIME, &timeout ); + +- timeout.tv_sec = now.tv_sec; +- timeout.tv_nsec = (now.tv_usec * 1000) + nano_seconds; ++ timeout.tv_sec += micros/1000000; ++ timeout.tv_nsec += (micros % 1000000) * 1000000000; + + timeout.tv_sec += timeout.tv_nsec / 1000000000; + timeout.tv_nsec %= 1000000000; +diff --git a/lib/direct/os/tls.h b/lib/direct/os/tls.h +index 3fef22c..ad08543 100644 +--- a/lib/direct/os/tls.h ++++ b/lib/direct/os/tls.h +@@ -33,17 +33,17 @@ + + /**********************************************************************************************************************/ + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + static __inline__ void * direct_tls_get ( DirectTLS *tls ); + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + static __inline__ DirectResult direct_tls_set ( DirectTLS *tls, + void *value ); + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + static __inline__ DirectResult direct_tls_register ( DirectTLS *tls, void (*destructor)( void* ) ); + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + static __inline__ DirectResult direct_tls_unregister( DirectTLS *tls ); + + #endif +diff --git a/lib/direct/os/win32/clock_win32.c b/lib/direct/os/win32/clock_win32.c +index 5043843..3bc098d 100644 +--- a/lib/direct/os/win32/clock_win32.c ++++ b/lib/direct/os/win32/clock_win32.c +@@ -40,7 +40,7 @@ static long long session_clock_offset; + + /**********************************************************************************************************************/ + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + long long + direct_clock_get_time( DirectClockType type ) + { +diff --git a/lib/direct/os/win32/log_win32.c b/lib/direct/os/win32/log_win32.c +index ef9d948..a6ce5b3 100644 +--- a/lib/direct/os/win32/log_win32.c ++++ b/lib/direct/os/win32/log_win32.c +@@ -33,7 +33,7 @@ + + /**********************************************************************************************************************/ + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + static DirectResult + log_write( DirectLog *log, + const char *buffer, +@@ -47,7 +47,7 @@ log_write( DirectLog *log, + + /**********************************************************************************************************************/ + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + DirectResult + direct_log_init( DirectLog *log, + const char *param ) +diff --git a/lib/direct/os/win32/mem_win32.c b/lib/direct/os/win32/mem_win32.c +index d374db1..eacb3cb 100644 +--- a/lib/direct/os/win32/mem_win32.c ++++ b/lib/direct/os/win32/mem_win32.c +@@ -43,7 +43,7 @@ + #define TOTAL_SENTINEL ((PREFIX_SENTINEL) + (SUFFIX_SENTINEL)) + + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + static inline void + install_sentinels( void *p, size_t size ) + { +@@ -63,7 +63,7 @@ install_sentinels( void *p, size_t size ) + suffix[i] = i; + } + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + static inline void + remove_sentinels( void *p ) + { +@@ -79,7 +79,7 @@ remove_sentinels( void *p ) + suffix[i] = 0; + } + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + static inline void + check_sentinels( void *p ) + { +@@ -102,7 +102,7 @@ check_sentinels( void *p ) + } + + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + void * + direct_malloc( size_t bytes ) + { +@@ -116,7 +116,7 @@ direct_malloc( size_t bytes ) + return p + PREFIX_SENTINEL; + } + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + void * + direct_calloc( size_t count, size_t bytes) + { +@@ -130,7 +130,7 @@ direct_calloc( size_t count, size_t bytes) + return p + PREFIX_SENTINEL; + } + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + void * + direct_realloc( void *mem, size_t bytes ) + { +@@ -156,7 +156,7 @@ direct_realloc( void *mem, size_t bytes ) + return p + PREFIX_SENTINEL; + } + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + char * + direct_strdup( const char *str ) + { +@@ -173,7 +173,7 @@ direct_strdup( const char *str ) + return p + PREFIX_SENTINEL; + } + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + void + direct_free( void *mem ) + { +@@ -192,35 +192,35 @@ direct_free( void *mem ) + + #else + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + void * + direct_malloc( size_t bytes ) + { + return malloc( bytes ); + } + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + void * + direct_calloc( size_t count, size_t bytes) + { + return calloc( count, bytes ); + } + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + void * + direct_realloc( void *mem, size_t bytes ) + { + return realloc( mem, bytes ); + } + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + char * + direct_strdup( const char *str ) + { + return _strdup( str ); + } + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + void + direct_free( void *mem ) + { +diff --git a/lib/direct/os/win32/system_win32.c b/lib/direct/os/win32/system_win32.c +index cbed316..250b06f 100644 +--- a/lib/direct/os/win32/system_win32.c ++++ b/lib/direct/os/win32/system_win32.c +@@ -67,7 +67,7 @@ direct_getpid( void ) + return GetCurrentThreadId(); + } + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + pid_t + direct_gettid( void ) + { +diff --git a/lib/direct/os/win32/thread_win32.c b/lib/direct/os/win32/thread_win32.c +index 67774b8..b5a2a61 100644 +--- a/lib/direct/os/win32/thread_win32.c ++++ b/lib/direct/os/win32/thread_win32.c +@@ -126,7 +126,7 @@ direct_thread_self( void ) + return NULL; + } + +-__no_instrument_function__ ++__dfb_no_instrument_function__ + const char * + direct_thread_self_name( void ) + { +diff --git a/lib/direct/os/win32/types.h b/lib/direct/os/win32/types.h +index 55790f6..e88cdab 100644 +--- a/lib/direct/os/win32/types.h ++++ b/lib/direct/os/win32/types.h +@@ -89,7 +89,7 @@ struct timespec { + + #define __inline__ __inline + #define D_UNUSED //__attribute__((unused)) +-#define __no_instrument_function__ //__attribute__((no_instrument_function)) ++#define __dfb_no_instrument_function__ //__attribute__((no_instrument_function)) + #define __constructor__ //__attribute__((constructor)) + #define __destructor__ //__attribute__((destructor)) + #define __typeof__(x) void* +diff --git a/lib/direct/util.c b/lib/direct/util.c +index e9fccc3..8ec8fa9 100644 +--- a/lib/direct/util.c ++++ b/lib/direct/util.c +@@ -110,7 +110,7 @@ direct_strerror( int erno ) + /* + * translates errno to DirectResult + */ +-__no_instrument_function__ ++__dfb_no_instrument_function__ + DirectResult + errno2result( int erno ) + { +diff --git a/lib/fusion/fusion.c b/lib/fusion/fusion.c +index 29e37c0..58a16f7 100644 +--- a/lib/fusion/fusion.c ++++ b/lib/fusion/fusion.c +@@ -453,8 +453,13 @@ map_shared_root( void *shm_base, + + + ++#if defined(__SH4__) ++# define shm_align_mask (0x3fff) ++#else ++# define shm_align_mask (0xffff) ++#endif + /* Map shared area. */ +- map = mmap( shm_base + 0x10000 * world_index, sizeof(FusionWorldShared), ++ map = mmap( shm_base + (shm_align_mask + 1) * world_index, sizeof(FusionWorldShared), + prot, MAP_FIXED | MAP_SHARED, fd, 0 ); + if (map == MAP_FAILED) { + ret = errno2result(errno); +diff --git a/lib/fusion/ref.c b/lib/fusion/ref.c +index 0679e2f..739b23a 100644 +--- a/lib/fusion/ref.c ++++ b/lib/fusion/ref.c +@@ -848,7 +848,7 @@ fusion_ref_down (FusionRef *ref, bool global) + FusionCall *call = ref->single.call; + + if (call->handler) { +- fusion_call_execute( call, FCEF_NODIRECT | FCEF_ONEWAY, ref->single.call_arg, NULL, NULL ); ++ fusion_call_execute( call, FCEF_ONEWAY, ref->single.call_arg, NULL, NULL ); + + direct_mutex_unlock( &ref->single.lock ); + +diff --git a/lib/fusion/shm/heap.c b/lib/fusion/shm/heap.c +index 2c08c1d..65e569f 100644 +--- a/lib/fusion/shm/heap.c ++++ b/lib/fusion/shm/heap.c +@@ -653,7 +653,7 @@ __shmalloc_init_heap( FusionSHM *shm, + goto error; + } + +- D_DEBUG_AT( Fusion_SHMHeap, " -> mmaping shared memory file... (%d bytes)\n", size ); ++ D_DEBUG_AT( Fusion_SHMHeap, " -> mmaping shared memory file... (%p %d bytes)\n", addr_base, size ); + + /* map it shared */ + heap = mmap( addr_base, size + space, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, fd, 0 ); +diff --git a/lib/fusion/shm/pool.c b/lib/fusion/shm/pool.c +index af5de6f..b960718 100644 +--- a/lib/fusion/shm/pool.c ++++ b/lib/fusion/shm/pool.c +@@ -712,7 +712,12 @@ init_pool( FusionSHM *shm, + BLOCKALIGN( (max_size + BLOCKSIZE-1) / BLOCKSIZE * sizeof(shmalloc_info) ); + + pool_addr_base = world->shared->pool_base; +- world->shared->pool_base += ((pool_max_size + page_size - 1) & ~(page_size - 1)) + page_size; ++#ifdef __SH4__ ++ #define SHM_ALIGN_SIZE 0x4000 ++#else ++ #define SHM_ALIGN_SIZE page_size ++#endif ++ world->shared->pool_base += ((pool_max_size + page_size - 1) & ~(SHM_ALIGN_SIZE - 1)) + SHM_ALIGN_SIZE; + /* Exceeded limit? */ + if (world->shared->pool_base > world->shared->pool_max) + return DR_NOSHAREDMEMORY; +diff --git a/src/core/gfxcard.c b/src/core/gfxcard.c +index 5394748..d808964 100644 +--- a/src/core/gfxcard.c ++++ b/src/core/gfxcard.c +@@ -4027,7 +4027,8 @@ dfb_gfxcard_calc_buffer_size( CoreGraphicsDevice *device, + buffer, &pitch, &length ); + } + +- if (ret != DFB_OK) { ++ if (ret != DFB_OK ++ && surface->config.format != DSPF_BYTE) { + /* calculate the required length depending on limitations */ + pitch = MAX( surface->config.size.w, surface->config.min_size.w ); + +@@ -4060,6 +4061,12 @@ dfb_gfxcard_calc_buffer_size( CoreGraphicsDevice *device, + } + } + ++ if (ret != DFB_OK ++ && surface->config.format == DSPF_BYTE) { ++ pitch = 1; ++ length = surface->config.size.w * surface->config.size.h; ++ } ++ + if (ret_pitch) + *ret_pitch = pitch; + +diff --git a/src/core/surface.c b/src/core/surface.c +index b84fa50..03870af 100644 +--- a/src/core/surface.c ++++ b/src/core/surface.c +@@ -258,6 +258,9 @@ dfb_surface_create( CoreDFB *core, + if (surface->config.caps & DSCAPS_SHARED) + surface->type |= CSTF_SHARED; + ++ if (surface->config.format == DSPF_BYTE) ++ surface->type |= CSTF_BUFFEROBJECT; ++ + surface->resource_id = resource_id; + + if (surface->config.caps & DSCAPS_TRIPLE) +@@ -430,6 +433,8 @@ dfb_surface_create_simple ( CoreDFB *core, + config.colorspace = colorspace; + config.caps = caps; + ++ type |= (format == DSPF_BYTE) ? CSTF_BUFFEROBJECT : 0; ++ + return CoreDFB_CreateSurface( core, &config, type, resource_id, palette, ret_surface ); + } + +@@ -1306,6 +1311,7 @@ dfb_surface_dump_buffer2( CoreSurface *surface, + char head[30]; + bool rgb = false; + bool alpha = false; ++ bool IsYCbCrMb = false; + #ifdef USE_ZLIB + gzFile gz_p = NULL, gz_g = NULL; + static const char *gz_ext = ".gz"; +@@ -1351,6 +1357,7 @@ dfb_surface_dump_buffer2( CoreSurface *surface, + + /* Check pixel format. */ + switch (lock.buffer->format) { ++ case DSPF_LUT4: + case DSPF_LUT8: + palette = surface->palette; + +@@ -1390,6 +1397,7 @@ dfb_surface_dump_buffer2( CoreSurface *surface, + case DSPF_RGB332: + case DSPF_RGB16: + case DSPF_RGB24: ++ case DSPF_BGR24: + case DSPF_RGB32: + case DSPF_YUY2: + case DSPF_UYVY: +@@ -1399,10 +1407,16 @@ dfb_surface_dump_buffer2( CoreSurface *surface, + case DSPF_RGB555: + case DSPF_BGR555: + case DSPF_YUV444P: ++ case DSPF_NV24: + case DSPF_VYU: + rgb = true; + break; + ++ case DSPF_NV12MB: ++ case DSPF_NV16MB: ++ IsYCbCrMb = true; ++ break; ++ + + default: + D_ERROR( "DirectFB/core/surfaces: surface dump for format " +@@ -1482,6 +1496,24 @@ dfb_surface_dump_buffer2( CoreSurface *surface, + } + } + ++ /* Create a .gam file for Omega2 MB buffers. */ ++ if (IsYCbCrMb) { ++ if (prefix) ++ snprintf( filename, len, "%s/%s_%04d.gam", path, prefix, num ); ++ else ++ snprintf( filename, len, "%s.gam", path ); ++ ++ 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; ++ } ++ } ++ + #ifdef USE_ZLIB + if (rgb) + gz_p = gzdopen( fd_p, "wb" ); +@@ -1512,12 +1544,47 @@ dfb_surface_dump_buffer2( CoreSurface *surface, + #endif + } + ++ /* Write the .gam header. */ ++ if (IsYCbCrMb) { ++ struct GamPictureHeader { ++ uint16_t header_size; ++ uint16_t signature; ++ uint16_t type; ++ uint16_t properties; ++ uint32_t pictureWidth; ++ uint32_t pictureHeight; ++ uint32_t lumaSize; ++ uint32_t chromaSize; ++ } header; ++ ++ unsigned int chromaHeight = surface->config.size.h; ++ if (lock.buffer->format == DSPF_NV12MB) ++ chromaHeight >>= 1; ++ ++ header.header_size = 0x6; ++ header.signature = (lock.buffer->format == DSPF_NV12MB) ? 0x420f : 0x422f; ++ header.type = (lock.buffer->format == DSPF_NV12MB) ? 0x94 : 0x95; ++ header.properties = 0x10; ++ header.pictureWidth = surface->config.size.w; ++ header.pictureHeight = surface->config.size.h; ++ header.lumaSize = surface->config.size.w * surface->config.size.h; ++ header.chromaSize = surface->config.size.w * chromaHeight; ++ ++ res = write( fd_p, &header, sizeof(header) ); ++ } ++ + /* Write the pixmap (and graymap) data. */ + for (i=0; iconfig.size.h; i++) { + int n3; + + /* Prepare one row. */ +- u8 *src8 = dfb_surface_data_offset( surface, lock.addr, lock.pitch, 0, i ); ++ u8 *srces[3]; ++ int pitches[3]; ++ u8 *src8; ++ ++ dfb_surface_get_data_offsets( &surface->config, lock.addr, lock.pitch, 0, i, ++ 3, srces, pitches ); ++ src8 = srces[0]; + + /* Write color buffer to pixmap file. */ + if (rgb) { +@@ -1530,8 +1597,23 @@ dfb_surface_dump_buffer2( CoreSurface *surface, + buf_p[n3+2] = palette->entries[src8[n]].b; + } + } ++ else if (lock.buffer->format == DSPF_LUT4) { ++ for (n=0, n3=0; n<(surface->config.size.w>>1); n+=1, n3+=6) { ++ int i = src8[n] & 0xf; /* 4 lsbs */ ++ buf_p[n3+0] = palette->entries[i].r; ++ buf_p[n3+1] = palette->entries[i].g; ++ buf_p[n3+2] = palette->entries[i].b; ++ i = src8[n] >> 4; /* 4 msbs */ ++ buf_p[n3+3] = palette->entries[i].r; ++ buf_p[n3+4] = palette->entries[i].g; ++ buf_p[n3+5] = palette->entries[i].b; ++ } ++ } + else +- dfb_convert_to_rgb24( lock.buffer->format, src8, lock.pitch, surface->config.size.h, ++ dfb_convert_to_rgb24( lock.buffer->format, ++ srces[0], pitches[0], ++ srces[1], pitches[1], srces[2], pitches[2], ++ 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 ); +@@ -1548,8 +1630,16 @@ dfb_surface_dump_buffer2( CoreSurface *surface, + for (n=0; nconfig.size.w; n++) + buf_g[n] = palette->entries[src8[n]].a; + } ++ else if (lock.buffer->format == DSPF_LUT4) { ++ for (n=0; n<(surface->config.size.w>>1); n++) { ++ int i = src8[n] & 0xf; /* 4 lsbs */ ++ buf_g[2 * n] = palette->entries[i].a; ++ i = src8[n] >> 4; /* 4 msbs */ ++ buf_g[2 * n + 1] = palette->entries[i].a; ++ } ++ } + else +- dfb_convert_to_a8( lock.buffer->format, src8, lock.pitch, surface->config.size.h, ++ dfb_convert_to_a8( lock.buffer->format, srces[0], pitches[0], 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 ); +@@ -1557,6 +1647,20 @@ dfb_surface_dump_buffer2( CoreSurface *surface, + res = write( fd_g, buf_g, surface->config.size.w ); + #endif + } ++ ++ /* Write luma data. */ ++ if (IsYCbCrMb) ++ res = write( fd_p, src8, surface->config.size.w ); ++ } ++ ++ /* Write chroma data. */ ++ if (IsYCbCrMb) { ++ unsigned int chroma_height = surface->config.size.h; ++ if (lock.buffer->format == DSPF_NV12MB) ++ chroma_height >>= 1; ++ res = write( fd_p, ++ lock.addr + lock.pitch * surface->config.size.h, ++ lock.pitch * chroma_height ); + } + + /* Unlock the surface buffer. */ +@@ -1582,6 +1686,10 @@ dfb_surface_dump_buffer2( CoreSurface *surface, + if (alpha) + close( fd_g ); + ++ /* Close the .gam file. */ ++ if (IsYCbCrMb) ++ close( fd_p ); ++ + return DFB_OK; + } + +diff --git a/src/core/surface.h b/src/core/surface.h +index 6172d13..dba8d8a 100644 +--- a/src/core/surface.h ++++ b/src/core/surface.h +@@ -113,7 +113,9 @@ typedef enum { + + CSTF_PREALLOCATED = 0x00000400, /* preallocated memory */ + +- CSTF_ALL = 0x0000071F ++ CSTF_BUFFEROBJECT = 0x00000800, /* opaque buffer object */ ++ ++ CSTF_ALL = 0x00000F1F + } CoreSurfaceTypeFlags; + + typedef struct { +@@ -460,29 +462,152 @@ dfb_surface_get_buffer3( CoreSurface *surface, + return surface->right_buffers[ surface->buffer_indices[(flip_count + role) % surface->num_buffers] ]; + } + +-static __inline__ void * +-dfb_surface_data_offset( const CoreSurface *surface, +- void *data, +- int pitch, +- int x, +- int y ) ++static __inline__ void ++dfb_surface_get_data_offsets( const CoreSurfaceConfig * const config, ++ const void * const data, ++ int pitch, ++ int x, ++ int y, ++ unsigned int num, ++ u8 ** const pointers, ++ int * const pitches ) + { +- D_ASSERT( surface != NULL ); ++ D_ASSERT( config != NULL ); + D_ASSERT( data != NULL ); + D_ASSERT( pitch > 0 ); + D_ASSERT( x >= 0 ); +- D_ASSERT( x < surface->config.size.w ); ++ D_ASSERT( x < config->size.w ); + D_ASSERT( y >= 0 ); +- D_ASSERT( y < surface->config.size.h ); ++ D_ASSERT( y < config->size.h ); ++ D_ASSERT( !num ++ || (num && pointers && pitches) ); ++ ++ if (!num) ++ return; ++ ++ switch (config->format) { ++ case DSPF_NV12: ++ case DSPF_NV21: ++ case DSPF_NV16: ++ if (num < 2) ++ return; ++ break; ++ ++ case DSPF_I420: ++ case DSPF_YV12: ++ case DSPF_YV16: ++ case DSPF_YUV444P: ++ if (num < 3) ++ return; ++ break; + +- if (surface->config.caps & DSCAPS_SEPARATED) { ++ default: ++ if (num < 1) ++ return; ++ break; ++ } ++ ++ if (config->caps & DSCAPS_SEPARATED) { + if (y & 1) +- y += surface->config.size.h; ++ y += config->size.h; + + y >>= 1; + } + +- return (u8*)data + pitch * y + DFB_BYTES_PER_LINE( surface->config.format, x ); ++ switch (config->format) { ++ case DSPF_NV12: ++ case DSPF_NV21: ++ pitches[1] = pitch; ++ pointers[1] = ( (u8*)data ++ + pitch * config->size.h ++ + pitches[1] * y/2 ++ + DFB_BYTES_PER_LINE( config->format, x/2 ) ); ++ break; ++ ++ case DSPF_NV16: ++ pitches[1] = pitch; ++ pointers[1] = ( (u8*)data ++ + pitch * config->size.h ++ + pitches[1] * y ++ + DFB_BYTES_PER_LINE( config->format, x/2 ) ); ++ break; ++ ++ case DSPF_I420: ++ pitches[1] = pitches[2] = pitch / 2; ++ pointers[1] = ( (u8*)data ++ + pitch * config->size.h ++ + pitches[1] * y/2 ++ + DFB_BYTES_PER_LINE( config->format, x/2 ) ); ++ pointers[2] = ( (u8*)data ++ + pitch * config->size.h ++ + pitches[1] * config->size.h/2 ++ + pitches[2] * y/2 ++ + DFB_BYTES_PER_LINE( config->format, x/2 ) ); ++ break; ++ ++ case DSPF_YV12: ++ pitches[1] = pitches[2] = pitch / 2; ++ pointers[2] = ( (u8*)data ++ + pitch * config->size.h ++ + pitches[2] * y/2 ++ + DFB_BYTES_PER_LINE( config->format, x/2 ) ); ++ pointers[1] = ( (u8*)data ++ + pitch * config->size.h ++ + pitches[2] * config->size.h/2 ++ + pitches[1] * y/2 ++ + DFB_BYTES_PER_LINE( config->format, x/2 ) ); ++ break; ++ ++ case DSPF_YV16: ++ pitches[1] = pitches[2] = pitch / 2; ++ pointers[2] = ( (u8*)data ++ + pitch * config->size.h ++ + pitches[2] * y ++ + DFB_BYTES_PER_LINE( config->format, x/2 ) ); ++ pointers[1] = ( (u8*)data ++ + pitch * config->size.h ++ + pitches[2] * config->size.h ++ + pitches[1] * y ++ + DFB_BYTES_PER_LINE( config->format, x/2 ) ); ++ break; ++ ++ case DSPF_YUV444P: ++ pitches[1] = pitches[2] = pitch; ++ pointers[1] = ( (u8*)data ++ + pitch * config->size.h ++ + pitches[1] * y ++ + DFB_BYTES_PER_LINE( config->format, x ) ); ++ pointers[2] = ( (u8*)data ++ + pitch * config->size.h ++ + pitches[1] * config->size.h ++ + pitches[2] * y ++ + DFB_BYTES_PER_LINE( config->format, x ) ); ++ break; ++ ++ default: ++ break; ++ } ++ ++ pointers[0] = ( (u8*)data ++ + pitch * y ++ + DFB_BYTES_PER_LINE( config->format, x ) ); ++ pitches[0] = pitch; ++} ++ ++static __inline__ void * ++dfb_surface_data_offset( const CoreSurface *surface, ++ void *data, ++ int pitch, ++ int x, ++ int y ) ++{ ++ u8 *pointers[1]; ++ int pitches[1]; ++ ++ dfb_surface_get_data_offsets( &surface->config, data, pitch, x, y, ++ 1, pointers, pitches); ++ ++ return pointers[0]; + } + + static __inline__ void +diff --git a/src/core/surface_allocation.c b/src/core/surface_allocation.c +index 9773d30..0ef959e 100644 +--- a/src/core/surface_allocation.c ++++ b/src/core/surface_allocation.c +@@ -308,6 +308,15 @@ transfer_buffer( CoreSurfaceBuffer *buffer, + } + break; + ++ case DSPF_NV24: ++ for (i=0; iconfig.size.h; i++) { ++ direct_memcpy( dst, src, ++ DFB_BYTES_PER_LINE( buffer->format, surface->config.size.w ) * 2 ); ++ src += srcpitch; ++ dst += dstpitch; ++ } ++ break; ++ + case DSPF_YUV444P: + for (i=0; iconfig.size.h*2; i++) { + direct_memcpy( dst, src, +diff --git a/src/core/surface_buffer.c b/src/core/surface_buffer.c +index e67457e..a77d7c3 100644 +--- a/src/core/surface_buffer.c ++++ b/src/core/surface_buffer.c +@@ -681,6 +681,7 @@ dfb_surface_buffer_dump( CoreSurfaceBuffer *buffer, + char head[30]; + bool rgb = false; + bool alpha = false; ++ bool IsYCbCrMb = false; + #ifdef USE_ZLIB + gzFile gz_p = NULL, gz_g = NULL; + static const char *gz_ext = ".gz"; +@@ -703,6 +704,7 @@ dfb_surface_buffer_dump( CoreSurfaceBuffer *buffer, + + /* Check pixel format. */ + switch (buffer->format) { ++ case DSPF_LUT4: + case DSPF_LUT8: + palette = surface->palette; + +@@ -739,6 +741,7 @@ dfb_surface_buffer_dump( CoreSurfaceBuffer *buffer, + case DSPF_RGB332: + case DSPF_RGB16: + case DSPF_RGB24: ++ case DSPF_BGR24: + case DSPF_RGB32: + case DSPF_YUY2: + case DSPF_UYVY: +@@ -748,10 +751,16 @@ dfb_surface_buffer_dump( CoreSurfaceBuffer *buffer, + case DSPF_RGB555: + case DSPF_BGR555: + case DSPF_YUV444P: ++ case DSPF_NV24: + case DSPF_VYU: + rgb = true; + break; + ++ case DSPF_NV12MB: ++ case DSPF_NV16MB: ++ IsYCbCrMb = true; ++ break; ++ + + default: + D_ERROR( "DirectFB/core/surfaces: surface dump for format " +@@ -838,6 +847,24 @@ dfb_surface_buffer_dump( CoreSurfaceBuffer *buffer, + } + } + ++ /* Create a .gam file for Omega2 MB buffers. */ ++ if (IsYCbCrMb) { ++ if (prefix) ++ snprintf( filename, len, "%s/%s_%04d.gam", directory, prefix, num ); ++ else ++ snprintf( filename, len, "%s.gam", directory ); ++ ++ 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; ++ } ++ } ++ + #ifdef USE_ZLIB + if (rgb) + gz_p = gzdopen( fd_p, "wb" ); +@@ -870,12 +897,47 @@ dfb_surface_buffer_dump( CoreSurfaceBuffer *buffer, + #endif + } + ++ /* Write the .gam header. */ ++ if (IsYCbCrMb) { ++ struct GamPictureHeader { ++ uint16_t header_size; ++ uint16_t signature; ++ uint16_t type; ++ uint16_t properties; ++ uint32_t pictureWidth; ++ uint32_t pictureHeight; ++ uint32_t lumaSize; ++ uint32_t chromaSize; ++ } header; ++ ++ unsigned int chromaHeight = surface->config.size.h; ++ if (buffer->format == DSPF_NV12MB) ++ chromaHeight >>= 1; ++ ++ header.header_size = 0x6; ++ header.signature = (buffer->format == DSPF_NV12MB) ? 0x420f : 0x422f; ++ header.type = (buffer->format == DSPF_NV12MB) ? 0x94 : 0x95; ++ header.properties = 0x10; ++ header.pictureWidth = surface->config.size.w; ++ header.pictureHeight = surface->config.size.h; ++ header.lumaSize = surface->config.size.w * surface->config.size.h; ++ header.chromaSize = surface->config.size.w * chromaHeight; ++ ++ res = write( fd_p, &header, sizeof(header) ); ++ (void)res; ++ } ++ + /* Write the pixmap (and graymap) data. */ + for (i=0; iconfig.size.h; i++) { + int n3; + + /* Prepare one row. */ +- u8 *src8 = dfb_surface_data_offset( surface, lock.addr, lock.pitch, 0, i ); ++ u8 *srces[3]; ++ int pitches[3]; ++ u8 *src8; ++ dfb_surface_get_data_offsets( &surface->config, lock.addr, lock.pitch, 0, i, ++ 3, srces, pitches ); ++ src8 = srces[0]; + + /* Write color buffer to pixmap file. */ + if (rgb) { +@@ -888,8 +950,23 @@ dfb_surface_buffer_dump( CoreSurfaceBuffer *buffer, + buf_p[n3+2] = palette->entries[src8[n]].b; + } + } ++ else if (buffer->format == DSPF_LUT4) { ++ for (n=0, n3=0; n<(surface->config.size.w>>1); n+=1, n3+=6) { ++ int i = src8[n] & 0xf; /* 4 lsbs */ ++ buf_p[n3+0] = palette->entries[i].r; ++ buf_p[n3+1] = palette->entries[i].g; ++ buf_p[n3+2] = palette->entries[i].b; ++ i = src8[n] >> 4; /* 4 msbs */ ++ buf_p[n3+3] = palette->entries[i].r; ++ buf_p[n3+4] = palette->entries[i].g; ++ buf_p[n3+5] = palette->entries[i].b; ++ } ++ } + else +- dfb_convert_to_rgb24( buffer->format, src8, lock.pitch, surface->config.size.h, ++ dfb_convert_to_rgb24( buffer->format, ++ srces[0], pitches[0], ++ srces[1], pitches[1], srces[2], pitches[2], ++ 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 ); +@@ -907,8 +984,16 @@ dfb_surface_buffer_dump( CoreSurfaceBuffer *buffer, + for (n=0; nconfig.size.w; n++) + buf_g[n] = palette->entries[src8[n]].a; + } ++ else if (buffer->format == DSPF_LUT4) { ++ for (n=0; n<(surface->config.size.w>>1); n++) { ++ int i = src8[n] & 0xf; /* 4 lsbs */ ++ buf_g[2 * n] = palette->entries[i].a; ++ i = src8[n] >> 4; /* 4 msbs */ ++ buf_g[2 * n + 1] = palette->entries[i].a; ++ } ++ } + else +- dfb_convert_to_a8( buffer->format, src8, lock.pitch, surface->config.size.h, ++ dfb_convert_to_a8( buffer->format, srces[0], pitches[0], 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 ); +@@ -917,6 +1002,23 @@ dfb_surface_buffer_dump( CoreSurfaceBuffer *buffer, + (void)res; + #endif + } ++ ++ /* Write luma data. */ ++ if (IsYCbCrMb) { ++ res = write( fd_p, srces[0], surface->config.size.w ); ++ (void)res; ++ } ++ } ++ ++ /* Write chroma data. */ ++ if (IsYCbCrMb) { ++ unsigned int chroma_height = surface->config.size.h; ++ if (buffer->format == DSPF_NV12MB) ++ chroma_height >>= 1; ++ res = write( fd_p, ++ lock.addr + lock.pitch * surface->config.size.h, ++ lock.pitch * chroma_height ); ++ (void)res; + } + + /* Unlock the surface buffer. */ +@@ -942,6 +1044,10 @@ dfb_surface_buffer_dump( CoreSurfaceBuffer *buffer, + if (alpha) + close( fd_g ); + ++ /* Close the .gam file. */ ++ if (IsYCbCrMb) ++ close( fd_p ); ++ + return DFB_OK; + } + +diff --git a/src/core/surface_pool.c b/src/core/surface_pool.c +index f54c101..f31e8f7 100644 +--- a/src/core/surface_pool.c ++++ b/src/core/surface_pool.c +@@ -480,6 +480,9 @@ dfb_surface_pools_negotiate( CoreSurfaceBuffer *buffer, + + if (type & CSTF_PREALLOCATED) + D_DEBUG_AT( Core_SurfacePool, " -> PREALLOCATED\n" ); ++ ++ if (type & CSTF_BUFFEROBJECT) ++ D_DEBUG_AT( Core_SurfacePool, " -> BUFFEROBJECT\n" ); + #endif + + for (i=0; itype & CSTF_FONT) ? " FONT" : "", + (surface->type & CSTF_INTERNAL) ? " INTERNAL" : "", + (surface->type & CSTF_EXTERNAL) ? " EXTERNAL" : "", +- (surface->type & CSTF_PREALLOCATED) ? " PREALLOCATED" : "" ); ++ (surface->type & CSTF_PREALLOCATED) ? " PREALLOCATED" : "", ++ (surface->type & CSTF_BUFFEROBJECT) ? " BUFFEROBJECT" : ""); + + D_ASSERT( accessor >= CSAID_CPU ); + D_ASSUME( accessor < _CSAID_NUM ); +diff --git a/src/core/system.h b/src/core/system.h +index abb40d0..255eaaf 100644 +--- a/src/core/system.h ++++ b/src/core/system.h +@@ -51,7 +51,8 @@ typedef enum { + CORE_PVR2D, + CORE_CARE1, + CORE_ANDROID, +- CORE_EGL ++ CORE_EGL, ++ CORE_STMFBDEV + } CoreSystemType; + + typedef enum { +diff --git a/src/gfx/convert.c b/src/gfx/convert.c +index 538a31a..ab6acd7 100644 +--- a/src/gfx/convert.c ++++ b/src/gfx/convert.c +@@ -115,6 +115,7 @@ dfb_pixel_to_color( DFBSurfacePixelFormat format, + + case DSPF_ABGR: + ret_color->a = pixel >> 24; ++ case DSPF_BGR24: + ret_color->b = (pixel & 0xff0000) >> 16; + ret_color->g = (pixel & 0x00ff00) >> 8; + ret_color->r = (pixel & 0x0000ff); +@@ -204,6 +205,9 @@ dfb_pixel_from_color( DFBSurfacePixelFormat format, + case DSPF_RGB24: + return PIXEL_RGB32( color->r, color->g, color->b ) & 0xffffff; + ++ case DSPF_BGR24: ++ return PIXEL_RGB32( color->b, color->g, color->r ) & 0xffffff; ++ + case DSPF_RGB32: + return PIXEL_RGB32( color->r, color->g, color->b ) & 0xffffff; + +@@ -332,6 +336,7 @@ dfb_pixel_to_components( DFBSurfacePixelFormat format, + + case DSPF_ABGR: + *a = pixel >> 24; ++ case DSPF_BGR24: + *c0 = (pixel & 0xff0000) >> 16; + *c1 = (pixel & 0x00ff00) >> 8; + *c2 = (pixel & 0x0000ff); +@@ -392,6 +397,10 @@ void + dfb_convert_to_rgb16( DFBSurfacePixelFormat format, + const void *src, + int spitch, ++ const void *src_cb, ++ int scbpitch, ++ const void *src_cr, ++ int scrpitch, + int surface_height, + u16 *dst, + int dpitch, +@@ -433,6 +442,28 @@ dfb_convert_to_rgb16( DFBSurfacePixelFormat format, + } + break; + ++ case DSPF_NV24: ++ while (height--) { ++ const u8 *src8 = src; ++ const u16 *src16 = src + surface_height * spitch; ++ ++ for (x=0; x> 8, src16[x] & 0xff, r, g, b ); ++#else ++ YCBCR_TO_RGB( src8[x], src16[x] & 0xff, src16[x] >> 8, r, g, b ); ++#endif ++ ++ dst[x] = PIXEL_RGB16( r, g, b ); ++ } ++ ++ src += spitch; ++ dst += dp2; ++ } ++ break; ++ + case DSPF_UYVY: + while (height--) { + const u32 *src32 = src; +@@ -599,7 +630,11 @@ dfb_convert_to_rgb16( DFBSurfacePixelFormat format, + for (x=0,x3=0; x> 8, src16[x] & 0xff, r, g, b ); ++#else ++ YCBCR_TO_RGB( src8[x], src16[x] & 0xff, src16[x] >> 8, r, g, b ); ++#endif ++ ++ dst[x] = PIXEL_RGB555( r, g, b ); ++ } ++ ++ src += spitch; ++ dst += dp2; ++ } ++ break; ++ + case DSPF_RGB444: + case DSPF_ARGB4444: + while (height--) { +@@ -919,14 +978,15 @@ dfb_convert_to_rgb555( DFBSurfacePixelFormat format, + case DSPF_VYU: + while (height--) { + const u8 *src8 = src; ++ int x3; + +- for (x=0; x> 8, src16[x] & 0xff, r, g, b ); ++#else ++ YCBCR_TO_RGB( src8[x], src16[x] & 0xff, src16[x] >> 8, r, g, b ); ++#endif ++ ++ dst[x] = PIXEL_RGB32( r, g, b ); ++ } ++ ++ src += spitch; ++ dst += dp4; ++ } ++ break; ++ + case DSPF_RGB444: + case DSPF_ARGB4444: + while (height--) { +@@ -1222,14 +1326,15 @@ dfb_convert_to_rgb32( DFBSurfacePixelFormat format, + case DSPF_VYU: + while (height--) { + const u8 *src8 = src; ++ int x3; + +- for (x=0; x> 8, src16[x] & 0xff, r, g, b ); ++#else ++ YCBCR_TO_RGB( src8[x], src16[x] & 0xff, src16[x] >> 8, r, g, b ); ++#endif ++ ++ dst[x] = PIXEL_ARGB( 0xff, r, g, b ); ++ } ++ ++ src += spitch; ++ dst += dp4; ++ } ++ break; ++ + case DSPF_ARGB4444: + while (height--) { + const u16 *src16 = src; +@@ -1572,14 +1721,15 @@ dfb_convert_to_argb( DFBSurfacePixelFormat format, + case DSPF_VYU: + while (height--) { + const u8 *src8 = src; ++ int x3; + +- for (x=0; x> 16; + y = (src32[n] & 0x00ff00) >> 8; + cb = (src32[n] & 0x0000ff) >> 0; +-#ifdef WORDS_BIGENDIAN + YCBCR_TO_RGB (y, cb, cr, + dst[n3+0], dst[n3+1], dst[n3+2]); +-#else +- YCBCR_TO_RGB (y, cb, cr, +- dst[n3+2], dst[n3+1], dst[n3+0]); +-#endif + } + + src += spitch; +@@ -1940,19 +2107,12 @@ dfb_convert_to_rgb24( DFBSurfacePixelFormat format, + const u8 * __restrict src8 = src; + + for (n=0, n3=0; n> 8, cbcr[n] & 0xff, ++ dst[n3+0], dst[n3+1], dst[n3+2] ); ++#else ++ YCBCR_TO_RGB( src8[n], cbcr[n] & 0xff, cbcr[n] >> 8, ++ dst[n3+0], dst[n3+1], dst[n3+2] ); ++#endif ++ } ++ ++ src += spitch; ++ dst += dpitch; ++ } ++ break; + case DSPF_RGBA5551: + while (height--) { + const u16 *src16 = src; +@@ -2047,13 +2226,8 @@ dfb_convert_to_rgb24( DFBSurfacePixelFormat format, + const u8 * __restrict cr = src + 2 * surface_height * spitch; + + for (n=0, n3=0; nCop & 0xf) << 4) | (gfxs->Cop & 0xf); ++ memset( gfxs->Aop[0], color, gfxs->length >> 1 ); ++} ++ + static void Cop_to_Aop_8( GenefxState *gfxs ) + { + memset( gfxs->Aop[0], gfxs->Cop, gfxs->length ); +@@ -632,7 +661,7 @@ static void Cop_to_Aop_vyu( GenefxState *gfxs ) + u8 *D = gfxs->Aop[0]; + + while (--w) { +-#ifdef BIG_ENDIAN ++#ifdef WORDS_BIGENDIAN + D[0] = gfxs->CrCop; + D[1] = gfxs->YCop; + D[2] = gfxs->CbCop; +@@ -748,6 +777,18 @@ static void Cop_to_Aop_nv12( GenefxState *gfxs ) + } + } + ++static void Cop_to_Aop_nv24( GenefxState *gfxs ) ++{ ++ u16 *D = gfxs->Aop[1]; ++ int w = gfxs->length + 1; ++ u16 Cop = gfxs->CbCop | (gfxs->CrCop << 8); ++ ++ memset( gfxs->Aop[0], gfxs->YCop, gfxs->length ); ++ ++ while (--w) ++ *D++ = Cop; ++} ++ + static void Cop_to_Aop_nv21( GenefxState *gfxs ) + { + memset( gfxs->Aop[0], gfxs->YCop, gfxs->length ); +@@ -763,6 +804,14 @@ static void Cop_to_Aop_nv21( GenefxState *gfxs ) + } + } + ++static void Cop_to_Aop_nv12mb( GenefxState *gfxs ) ++{ ++ int y0 = (short)(((u32)gfxs->Aop[2] >> 16) & 0xffff); ++ ++ dfb_write_nv1xmb_span( NULL, gfxs->YCop, (u8**) gfxs->Aop, ++ gfxs->length, gfxs->AopY - y0 ); ++} ++ + static void Cop_to_Aop_yuv444p( GenefxState *gfxs ) + { + memset( gfxs->Aop[0], gfxs->YCop, gfxs->length ); +@@ -789,6 +838,7 @@ static GenefxFunc Cop_to_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + [DFB_PIXELFORMAT_INDEX(DSPF_A1)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_NV12)] = Cop_to_Aop_nv12, + [DFB_PIXELFORMAT_INDEX(DSPF_NV16)] = Cop_to_Aop_nv12, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV24)] = Cop_to_Aop_nv24, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)] = Cop_to_Aop_16, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)] = Cop_to_Aop_16, + [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)] = Cop_to_Aop_16, +@@ -810,10 +860,36 @@ static GenefxFunc Cop_to_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + [DFB_PIXELFORMAT_INDEX(DSPF_VYU)] = Cop_to_Aop_vyu, + [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_YV16)] = Cop_to_Aop_yv16, ++ [DFB_PIXELFORMAT_INDEX(DSPF_LUT4)] = Cop_to_Aop_4, ++ [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)] = Cop_to_Aop_24, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV12MB)] = Cop_to_Aop_nv12mb, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV16MB)] = Cop_to_Aop_nv12mb, + }; + + /********************************* Cop_toK_Aop_PFI ****************************/ + ++static void Cop_toK_Aop_4( GenefxState *gfxs ) ++{ ++ int w = (gfxs->length >> 1) + 1; ++ u8 *D = gfxs->Aop[0]; ++ u32 Cop = gfxs->Cop; ++ u32 Dkey = gfxs->Dkey; ++ u8 pixel; ++ ++ while (--w) { ++ pixel = *D; ++ ++ if (Dkey == (*D & 0x0F)) ++ pixel = Cop; ++ if (Dkey == (*D >> 4)) { ++ pixel &= 0x0F; ++ pixel |= (Cop << 4); ++ } ++ ++ *D++ = pixel; ++ } ++} ++ + static void Cop_toK_Aop_8( GenefxState *gfxs ) + { + int w = gfxs->length+1; +@@ -939,6 +1015,7 @@ static const GenefxFunc Cop_toK_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + [DFB_PIXELFORMAT_INDEX(DSPF_A1)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_NV12)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_NV16)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV24)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)] = Cop_toK_Aop_14, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)] = Cop_toK_Aop_12, + [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)] = Cop_toK_Aop_12vv, +@@ -960,6 +1037,10 @@ static const GenefxFunc Cop_toK_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + [DFB_PIXELFORMAT_INDEX(DSPF_VYU)] = Cop_toK_Aop_24_24, + [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_YV16)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_LUT4)] = Cop_toK_Aop_4, ++ [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)] = Cop_toK_Aop_24_24, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV12MB)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV16MB)] = NULL, + }; + + /********************************* Bop_PFI_to_Aop_PFI *************************/ +@@ -1012,6 +1093,17 @@ static void Bop_NV_to_Aop( GenefxState *gfxs ) + direct_memmove( gfxs->Aop[1], gfxs->Bop[1], gfxs->length&~1 ); + } + ++static void Bop_NV24_to_Aop( GenefxState *gfxs ) ++{ ++ direct_memmove( gfxs->Aop[0], gfxs->Bop[0], gfxs->length ); ++ direct_memmove( gfxs->Aop[1], gfxs->Bop[1], gfxs->length * 2 ); ++} ++ ++static void Bop_nv12mb_to_Aop( GenefxState *gfxs ) ++{ ++ direct_memmove( gfxs->Aop[0], gfxs->Bop[0], gfxs->length ); ++} ++ + static void Bop_yuv444p_to_Aop( GenefxState *gfxs ) + { + direct_memmove( gfxs->Aop[0], gfxs->Bop[0], gfxs->length ); +@@ -1038,6 +1130,7 @@ static const GenefxFunc Bop_PFI_to_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + [DFB_PIXELFORMAT_INDEX(DSPF_A1)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_NV12)] = Bop_NV_to_Aop, + [DFB_PIXELFORMAT_INDEX(DSPF_NV16)] = Bop_NV_to_Aop, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV24)] = Bop_NV24_to_Aop, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)] = Bop_16_to_Aop, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)] = Bop_16_to_Aop, + [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)] = Bop_16_to_Aop, +@@ -1059,6 +1152,10 @@ static const GenefxFunc Bop_PFI_to_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + [DFB_PIXELFORMAT_INDEX(DSPF_VYU)] = Bop_24_to_Aop, + [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_YV16)] = Bop_yv16_to_Aop, ++ [DFB_PIXELFORMAT_INDEX(DSPF_LUT4)] = Bop_4_to_Aop, ++ [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)] = Bop_24_to_Aop, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV12MB)] = Bop_nv12mb_to_Aop, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV16MB)] = Bop_nv12mb_to_Aop, + }; + + /********************************* Bop_PFI_toR_Aop_PFI *************************/ +@@ -1192,6 +1289,22 @@ static void Bop_NV_toR_Aop( GenefxState *gfxs ) + } + } + ++static void Bop_NV24_toR_Aop( GenefxState *gfxs ) ++{ ++ int w = gfxs->length + 1; ++ int Dstep = gfxs->Astep; ++ u16 * S = gfxs->Bop[1]; ++ u16 * D = gfxs->Aop[1]; ++ ++ Bop_8_toR_Aop( gfxs ); ++ ++ while(--w) ++ { ++ *D = *S++; ++ D += Dstep; ++ } ++} ++ + static void Bop_yuv444p_toR_Aop( GenefxState *gfxs ) + { + int w = gfxs->length + 1; +@@ -1238,6 +1351,7 @@ static const GenefxFunc Bop_PFI_toR_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + [DFB_PIXELFORMAT_INDEX(DSPF_A1)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_NV12)] = Bop_NV_toR_Aop, + [DFB_PIXELFORMAT_INDEX(DSPF_NV16)] = Bop_NV_toR_Aop, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV24)] = Bop_NV24_toR_Aop, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)] = Bop_16_toR_Aop, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)] = Bop_16_toR_Aop, + [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)] = Bop_16_toR_Aop, +@@ -1259,10 +1373,20 @@ static const GenefxFunc Bop_PFI_toR_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + [DFB_PIXELFORMAT_INDEX(DSPF_VYU)] = Bop_24_toR_Aop, + [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_YV16)] = Bop_yv16_toR_Aop, ++ [DFB_PIXELFORMAT_INDEX(DSPF_LUT4)] = Bop_4_toR_Aop, ++ [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)] = Bop_24_toR_Aop, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV12MB)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV16MB)] = NULL, + }; + + /********************************* Bop_PFI_Kto_Aop_PFI ************************/ + ++static void Bop_lut4_Kto_Aop( GenefxState *gfxs ) ++{ ++ /* no color to key */ ++ direct_memmove( gfxs->Aop[0], gfxs->Bop[0], gfxs->length >> 1 ); ++} ++ + static void Bop_a8_Kto_Aop( GenefxState *gfxs ) + { + /* no color to key */ +@@ -1435,6 +1559,7 @@ static GenefxFunc Bop_PFI_Kto_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + [DFB_PIXELFORMAT_INDEX(DSPF_A1)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_NV12)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_NV16)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV24)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)] = Bop_14_Kto_Aop, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)] = Bop_12_Kto_Aop, + [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)] = Bop_12vv_Kto_Aop, +@@ -1456,6 +1581,10 @@ static GenefxFunc Bop_PFI_Kto_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + [DFB_PIXELFORMAT_INDEX(DSPF_VYU)] = Bop_24_24_Kto_Aop, + [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_YV16)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_LUT4)] = Bop_lut4_Kto_Aop, ++ [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)] = Bop_24_24_Kto_Aop, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV12MB)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV16MB)] = NULL, + }; + + /********************************* Bop_PFI_toK_Aop_PFI ************************/ +@@ -1557,6 +1686,29 @@ static void Bop_yuv444p_toK_Aop( GenefxState *gfxs ) + } + } + ++static void Bop_4_toK_Aop( GenefxState *gfxs ) ++{ ++ int w = (gfxs->length >> 1) + 1; ++ u8 *D = gfxs->Aop[0]; ++ u8 *S = gfxs->Bop[0]; ++ u8 Dkey = gfxs->Dkey; ++ u8 pixel; ++ ++ while (--w) { ++ pixel = *D; ++ ++ if (Dkey == (*D & 0x0F)) ++ pixel = *S & 0xF; ++ if (Dkey == (*D >> 4)) { ++ pixel &= 0x0F; ++ pixel |= *S & 0xF0; ++ } ++ ++ *D++ = pixel; ++ S++; ++ } ++} ++ + static void Bop_8_toK_Aop( GenefxState *gfxs ) + { + int w = gfxs->length+1; +@@ -1592,6 +1744,7 @@ static GenefxFunc Bop_PFI_toK_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + [DFB_PIXELFORMAT_INDEX(DSPF_A1)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_NV12)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_NV16)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV24)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)] = Bop_14_toK_Aop, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)] = Bop_12_toK_Aop, + [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)] = Bop_12vv_toK_Aop, +@@ -1613,6 +1766,10 @@ static GenefxFunc Bop_PFI_toK_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + [DFB_PIXELFORMAT_INDEX(DSPF_VYU)] = Bop_24_24_toK_Aop, + [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_YV16)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_LUT4)] = Bop_4_toK_Aop, ++ [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)] = Bop_24_24_toK_Aop, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV12MB)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV16MB)] = NULL, + }; + + /********************************* Bop_PFI_KtoK_Aop_PFI ***********************/ +@@ -1675,6 +1832,7 @@ static const GenefxFunc Bop_PFI_KtoK_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + [DFB_PIXELFORMAT_INDEX(DSPF_A1)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_NV12)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_NV16)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV24)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)] = Bop_14_KtoK_Aop, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)] = Bop_12_KtoK_Aop, + [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)] = Bop_12vv_KtoK_Aop, +@@ -1696,6 +1854,10 @@ static const GenefxFunc Bop_PFI_KtoK_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + [DFB_PIXELFORMAT_INDEX(DSPF_VYU)] = Bop_24_24_KtoK_Aop, + [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_YV16)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_LUT4)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)] = Bop_24_24_KtoK_Aop, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV12MB)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV16MB)] = NULL, + }; + + /********************************* Bop_PFI_Sto_Aop_PFI ************************/ +@@ -1940,6 +2102,25 @@ static void Bop_NV_Sto_Aop( GenefxState *gfxs ) + } + } + ++static void Bop_NV24_Sto_Aop( GenefxState *gfxs ) ++{ ++ int w = gfxs->length + 1; ++ int i = gfxs->Xphase; ++ u8 *Dy = gfxs->Aop[0]; ++ u8 *Sy = gfxs->Bop[0]; ++ int SperD = gfxs->SperD; ++ ++ u16 *Duv = gfxs->Aop[1]; ++ u16 *Suv = gfxs->Bop[1]; ++ ++ while (--w) { ++ *Dy++ = Sy[i>>16]; ++ *Duv++ = Suv[i>>16]; ++ ++ i += SperD; ++ } ++} ++ + static void Bop_yuv444p_Sto_Aop( GenefxState *gfxs ) + { + int w = gfxs->length + 1; +@@ -1984,6 +2165,7 @@ static GenefxFunc Bop_PFI_Sto_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + [DFB_PIXELFORMAT_INDEX(DSPF_A1)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_NV12)] = Bop_NV_Sto_Aop, + [DFB_PIXELFORMAT_INDEX(DSPF_NV16)] = Bop_NV_Sto_Aop, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV24)] = Bop_NV24_Sto_Aop, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)] = Bop_16_Sto_Aop, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)] = Bop_16_Sto_Aop, + [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)] = Bop_16_Sto_Aop, +@@ -2005,6 +2187,10 @@ static GenefxFunc Bop_PFI_Sto_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + [DFB_PIXELFORMAT_INDEX(DSPF_VYU)] = Bop_24_Sto_Aop, + [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_YV16)] = Bop_yv16_Sto_Aop, ++ [DFB_PIXELFORMAT_INDEX(DSPF_LUT4)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)] = Bop_24_Sto_Aop, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV12MB)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV16MB)] = NULL, + }; + + /********************************* Bop_PFI_SKto_Aop_PFI ***********************/ +@@ -2225,6 +2411,7 @@ static const GenefxFunc Bop_PFI_SKto_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + [DFB_PIXELFORMAT_INDEX(DSPF_A1)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_NV12)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_NV16)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV24)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)] = Bop_14_SKto_Aop, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)] = Bop_12_SKto_Aop, + [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)] = Bop_12vv_SKto_Aop, +@@ -2246,6 +2433,10 @@ static const GenefxFunc Bop_PFI_SKto_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + [DFB_PIXELFORMAT_INDEX(DSPF_VYU)] = Bop_24_24_SKto_Aop, + [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_YV16)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_LUT4)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)] = Bop_24_24_SKto_Aop, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV12MB)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV16MB)] = NULL, + }; + + /********************************* Bop_PFI_StoK_Aop_PFI ***********************/ +@@ -2302,6 +2493,7 @@ static const GenefxFunc Bop_PFI_StoK_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + [DFB_PIXELFORMAT_INDEX(DSPF_A1)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_NV12)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_NV16)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV24)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)] = Bop_14_StoK_Aop, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)] = Bop_12_StoK_Aop, + [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)] = Bop_12vv_StoK_Aop, +@@ -2323,6 +2515,10 @@ static const GenefxFunc Bop_PFI_StoK_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + [DFB_PIXELFORMAT_INDEX(DSPF_VYU)] = Bop_24_24_StoK_Aop, + [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_YV16)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_LUT4)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)] = Bop_24_24_StoK_Aop, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV12MB)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV16MB)] = NULL, + }; + + /********************************* Bop_PFI_SKtoK_Aop_PFI **********************/ +@@ -2381,6 +2577,7 @@ static const GenefxFunc Bop_PFI_SKtoK_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + [DFB_PIXELFORMAT_INDEX(DSPF_A1)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_NV12)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_NV16)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV24)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)] = Bop_14_SKtoK_Aop, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)] = Bop_12_SKtoK_Aop, + [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)] = Bop_12vv_SKtoK_Aop, +@@ -2402,6 +2599,10 @@ static const GenefxFunc Bop_PFI_SKtoK_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + [DFB_PIXELFORMAT_INDEX(DSPF_VYU)] = Bop_24_24_SKtoK_Aop, + [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_YV16)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_LUT4)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)] = Bop_24_24_SKtoK_Aop, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV12MB)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV16MB)] = NULL, + }; + + /********************************* Bop_PFI_TEX_to_Aop_PFI ************************/ +@@ -2503,6 +2704,7 @@ static GenefxFunc Bop_PFI_TEX_to_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + [DFB_PIXELFORMAT_INDEX(DSPF_A1)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_NV12)] = NULL,//Bop_NV_TEX_to_Aop, + [DFB_PIXELFORMAT_INDEX(DSPF_NV16)] = NULL,//Bop_NV_TEX_to_Aop, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV24)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)] = NULL,//Bop_16_TEX_to_Aop, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)] = NULL,//Bop_16_TEX_to_Aop, + [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)] = NULL,//Bop_16_TEX_to_Aop, +@@ -2524,6 +2726,10 @@ static GenefxFunc Bop_PFI_TEX_to_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + [DFB_PIXELFORMAT_INDEX(DSPF_VYU)] = Bop_24_TEX_to_Aop, + [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_YV16)] = NULL,//Bop_yv16_TEX_to_Aop, ++ [DFB_PIXELFORMAT_INDEX(DSPF_LUT4)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)] = Bop_24_TEX_to_Aop, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV12MB)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV16MB)] = NULL, + }; + + /********************************* Sop_PFI_Sto_Dacc ***************************/ +@@ -2744,6 +2950,28 @@ static void Sop_nv12_Sto_Dacc( GenefxState *gfxs ) + } + } + ++static void Sop_nv24_Sto_Dacc( GenefxState *gfxs ) ++{ ++ int w = gfxs->length+1; ++ int i = gfxs->Xphase; ++ int SperD = gfxs->SperD; ++ ++ GenefxAccumulator *D = gfxs->Dacc; ++ u8 *Sy = gfxs->Sop[0]; ++ u16 *Suv = gfxs->Sop[1]; ++ ++ while (--w) { ++ D->YUV.a = 0xFF; ++ D->YUV.y = Sy[i>>16]; ++ D->YUV.u = Suv[i>>16] & 0xFF; ++ D->YUV.v = Suv[i>>16] >> 8; ++ ++ i += SperD; ++ ++ ++D; ++ } ++} ++ + static void Sop_nv21_Sto_Dacc( GenefxState *gfxs ) + { + int w = gfxs->length+1; +@@ -2912,6 +3140,7 @@ static GenefxFunc Sop_PFI_Sto_Dacc[DFB_NUM_PIXELFORMATS] = { + [DFB_PIXELFORMAT_INDEX(DSPF_A1)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_NV12)] = Sop_nv12_Sto_Dacc, + [DFB_PIXELFORMAT_INDEX(DSPF_NV16)] = Sop_nv12_Sto_Dacc, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV24)] = Sop_nv24_Sto_Dacc, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)] = Sop_argb2554_Sto_Dacc, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)] = Sop_argb4444_Sto_Dacc, + [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)] = Sop_rgba4444_Sto_Dacc, +@@ -2933,6 +3162,10 @@ static GenefxFunc Sop_PFI_Sto_Dacc[DFB_NUM_PIXELFORMATS] = { + [DFB_PIXELFORMAT_INDEX(DSPF_VYU)] = Sop_vyu_Sto_Dacc, + [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_YV16)] = Sop_i420_Sto_Dacc, ++ [DFB_PIXELFORMAT_INDEX(DSPF_LUT4)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)] = Sop_bgr24_Sto_Dacc, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV12MB)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV16MB)] = NULL, + }; + + /********************************* Sop_PFI_SKto_Dacc **************************/ +@@ -3302,6 +3535,7 @@ static const GenefxFunc Sop_PFI_SKto_Dacc[DFB_NUM_PIXELFORMATS] = { + [DFB_PIXELFORMAT_INDEX(DSPF_A1)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_NV12)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_NV16)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV24)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)] = Sop_argb2554_SKto_Dacc, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)] = Sop_argb4444_SKto_Dacc, + [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)] = Sop_rgba4444_SKto_Dacc, +@@ -3323,6 +3557,10 @@ static const GenefxFunc Sop_PFI_SKto_Dacc[DFB_NUM_PIXELFORMATS] = { + [DFB_PIXELFORMAT_INDEX(DSPF_VYU)] = Sop_vyu_SKto_Dacc, + [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_YV16)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_LUT4)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)] = Sop_bgr24_SKto_Dacc, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV12MB)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV16MB)] = NULL, + }; + + /********************************* Sop_PFI_to_Dacc ****************************/ +@@ -3453,6 +3691,33 @@ static void Sop_uyvy_to_Dacc( GenefxState *gfxs ) + } + } + ++static void Sop_lut4_to_Dacc( GenefxState *gfxs ) ++{ ++ int w = (gfxs->length >> 1) + 1; ++ GenefxAccumulator *D = gfxs->Dacc; ++ u8 *S = gfxs->Sop[0]; ++ ++ DFBColor *entries = gfxs->Slut->entries; ++ ++ while (--w) { ++ u8 s = *S++; ++ ++ D->RGB.a = entries[s & 0xF].a; ++ D->RGB.r = entries[s & 0xF].r; ++ D->RGB.g = entries[s & 0xF].g; ++ D->RGB.b = entries[s & 0xF].b; ++ ++ D++; ++ ++ D->RGB.a = entries[s >> 4].a; ++ D->RGB.r = entries[s >> 4].r; ++ D->RGB.g = entries[s >> 4].g; ++ D->RGB.b = entries[s >> 4].b; ++ ++ D++; ++ } ++} ++ + static void Sop_lut8_to_Dacc( GenefxState *gfxs ) + { + int w = gfxs->length+1; +@@ -3538,6 +3803,88 @@ static void Sop_nv12_to_Dacc( GenefxState *gfxs ) + } + } + ++static void Sop_nv24_to_Dacc( GenefxState *gfxs ) ++{ ++ int w = gfxs->length+1; ++ GenefxAccumulator *D = gfxs->Dacc; ++ u8 *Sy = gfxs->Sop[0]; ++ u16 *Suv = gfxs->Sop[1]; ++ ++ while (--w) { ++ D[0].YUV.a = 0xFF; ++ D[0].YUV.y = *Sy++; ++ D[0].YUV.u = Suv[0] & 0xFF; ++ D[0].YUV.v = Suv[0] >> 8; ++ ++ ++Suv; ++ D++; ++ } ++} ++ ++static void Sop_nv12mb_to_Dacc( GenefxState *gfxs ) ++{ ++ int i, l, idx; ++ short dy; ++ u8 *d1, *dy1; ++ int y0; ++ ++ GenefxAccumulator *D = gfxs->Dacc; ++ ++ int y_offet_table[32] = { ++ 8, 72, 136, 200, 0, 64, 128, 192, 24, 88, 152, 216, 16, ++ 80, 144, 208, 40, 104, 168, 232, 32, 96, 160, 224, 56, 120, ++ 184, 248, 48, 112, 176, 240 ++ }; ++ ++ d1 = gfxs->Sop[0]; ++ ++ y0 = (short)(((u32)gfxs->Aop[2] >> 16) & 0xffff); ++ ++ if (gfxs->Sop == gfxs->Aop) ++ dy = gfxs->AopY - y0; ++ else ++ dy = gfxs->BopY - y0; ++ ++ idx = (dy % 16) * 2; ++ dy1 = d1 + y_offet_table[idx]; ++ ++ /* gfxs->length is assumed to be always even */ ++ for (i = 0, l = 0; i < (gfxs->length - 1); i += 2) ++ { ++ if (l == 16) { ++ d1 += 2 * 256; ++ ++ idx = (dy % 16) * 2; ++ dy1 = d1 + y_offet_table[idx]; ++ ++ l = 0; ++ } ++ ++ if (l < 8) { ++ D[0].YUV.y = dy1[7 - l]; ++ D[1].YUV.y = dy1[7 - (l + 1)]; ++ ++ D[0].YUV.u = D[1].YUV.u = 127; ++ D[0].YUV.v = D[1].YUV.v = 127; ++ D[0].YUV.a = D[1].YUV.a = 255; ++ } else { ++ if (l == 8) { ++ dy1 = d1 + y_offet_table[++idx]; ++ } ++ ++ D[0].YUV.y = dy1[15 - l]; ++ D[1].YUV.y = dy1[15 - (l + 1)]; ++ ++ D[0].YUV.u = D[1].YUV.u = 127; ++ D[0].YUV.v = D[1].YUV.v = 127; ++ D[0].YUV.a = D[1].YUV.a = 255; ++ } ++ ++ l += 2; ++ D += 2; ++ } ++} ++ + static void Sop_nv21_to_Dacc( GenefxState *gfxs ) + { + int w = (gfxs->length>>1)+1; +@@ -3657,6 +4004,7 @@ static GenefxFunc Sop_PFI_to_Dacc[DFB_NUM_PIXELFORMATS] = { + [DFB_PIXELFORMAT_INDEX(DSPF_A1)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_NV12)] = Sop_nv12_to_Dacc, + [DFB_PIXELFORMAT_INDEX(DSPF_NV16)] = Sop_nv12_to_Dacc, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV24)] = Sop_nv24_to_Dacc, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)] = Sop_argb2554_to_Dacc, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)] = Sop_argb4444_to_Dacc, + [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)] = Sop_rgba4444_to_Dacc, +@@ -3678,6 +4026,10 @@ static GenefxFunc Sop_PFI_to_Dacc[DFB_NUM_PIXELFORMATS] = { + [DFB_PIXELFORMAT_INDEX(DSPF_VYU)] = Sop_vyu_to_Dacc, + [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_YV16)] = Sop_i420_to_Dacc, ++ [DFB_PIXELFORMAT_INDEX(DSPF_LUT4)] = Sop_lut4_to_Dacc, ++ [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)] = Sop_bgr24_to_Dacc, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV12MB)] = Sop_nv12mb_to_Dacc, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV16MB)] = Sop_nv12mb_to_Dacc, + }; + + /********************************* Sop_PFI_Kto_Dacc ***************************/ +@@ -4033,6 +4385,7 @@ static const GenefxFunc Sop_PFI_Kto_Dacc[DFB_NUM_PIXELFORMATS] = { + [DFB_PIXELFORMAT_INDEX(DSPF_A1)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_NV12)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_NV16)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV24)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)] = Sop_argb2554_Kto_Dacc, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)] = Sop_argb4444_Kto_Dacc, + [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)] = Sop_rgba4444_Kto_Dacc, +@@ -4054,6 +4407,10 @@ static const GenefxFunc Sop_PFI_Kto_Dacc[DFB_NUM_PIXELFORMATS] = { + [DFB_PIXELFORMAT_INDEX(DSPF_VYU)] = Sop_vyu_Kto_Dacc, + [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_YV16)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_LUT4)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)] = Sop_bgr24_Kto_Dacc, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV12MB)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV16MB)] = NULL, + }; + + /********************************* Sacc_to_Aop_PFI ****************************/ +@@ -4209,6 +4566,35 @@ static void Sacc_to_Aop_uyvy( GenefxState *gfxs ) + } + } + ++static void Sacc_to_Aop_lut4( GenefxState *gfxs ) ++{ ++ int w = (gfxs->length >> 1) + 1; ++ GenefxAccumulator *S = gfxs->Sacc; ++ u8 *D = gfxs->Aop[0]; ++ u8 pixel; ++ ++ while (--w) { ++ pixel = 0; ++ if (!(S->RGB.a & 0xF000)) { ++ pixel = dfb_palette_search( gfxs->Alut, ++ (S->RGB.r & 0xFF00) ? 0xFF : S->RGB.r, ++ (S->RGB.g & 0xFF00) ? 0xFF : S->RGB.g, ++ (S->RGB.b & 0xFF00) ? 0xFF : S->RGB.b, ++ (S->RGB.a & 0xFF00) ? 0xFF : S->RGB.a ); ++ } ++ S++; ++ if (!(S->RGB.a & 0xF000)) { ++ pixel |= (dfb_palette_search( gfxs->Alut, ++ (S->RGB.r & 0xFF00) ? 0xFF : S->RGB.r, ++ (S->RGB.g & 0xFF00) ? 0xFF : S->RGB.g, ++ (S->RGB.b & 0xFF00) ? 0xFF : S->RGB.b, ++ (S->RGB.a & 0xFF00) ? 0xFF : S->RGB.a )) << 4; ++ } ++ *D++ = pixel; ++ S++; ++ } ++} ++ + static void Sacc_to_Aop_lut8( GenefxState *gfxs ) + { + int w = gfxs->length+1; +@@ -4401,6 +4787,96 @@ static void Sacc_to_Aop_nv12( GenefxState *gfxs ) + } + } + ++static void Sacc_to_Aop_nv24( GenefxState *gfxs ) ++{ ++ int w = gfxs->length+1; ++ GenefxAccumulator *S = gfxs->Sacc; ++ u8 *Dy = gfxs->Aop[0]; ++ u16 *Duv = gfxs->Aop[1]; ++ ++ while (--w) { ++ if (!(S->YUV.a & 0xF000)) ++ *Dy = (S->YUV.y & 0xFF00) ? 0xFF : S->YUV.y; ++ ++ ++S; ++ ++Dy; ++ } ++ ++ w = gfxs->length+1; ++ S = gfxs->Sacc; ++ ++ while (--w) { ++ u32 cb, cr; ++ ++ if (!(S[0].YUV.a & 0xF000)) { ++ cb = ((*Duv & 0xFF) + ((S[0].YUV.u & 0xFF00) ? 0xFF : S[0].YUV.u)) >> 1; ++ cr = ((*Duv >> 8) + ((S[0].YUV.v & 0xFF00) ? 0xFF : S[0].YUV.v)) >> 1; ++ *Duv = cb | (cr << 8); ++ } ++ ++ S++; ++ ++Duv; ++ } ++} ++ ++static void Sacc_to_Aop_nv12mb( GenefxState *gfxs ) ++{ ++ int i, l, idx; ++ short dy; ++ u8 *d1, *dy1; ++ int y0; ++ ++ GenefxAccumulator *src; ++ ++ int y_offet_table[32] = { ++ 8, 72, 136, 200, 0, 64, 128, 192, 24, 88, 152, 216, 16, ++ 80, 144, 208, 40, 104, 168, 232, 32, 96, 160, 224, 56, 120, ++ 184, 248, 48, 112, 176, 240 ++ }; ++ ++ d1 = gfxs->Aop[0]; ++ ++ y0 = (short)(((u32)gfxs->Aop[2] >> 16) & 0xffff); ++ dy = gfxs->AopY - y0; ++ ++ src = gfxs->Sacc; ++ ++ idx = (dy % 16) * 2; ++ dy1 = d1 + y_offet_table[idx]; ++ ++ /* gfxs->length is assumed to be always even */ ++ for (i = 0, l = 0; i < (gfxs->length - 1); i += 2) ++ { ++ int y0, y1; ++ ++ if (l == 16) { ++ d1 += 2 * 256; ++ ++ idx = (dy % 16) * 2; ++ dy1 = d1 + y_offet_table[idx]; ++ ++ l = 0; ++ } ++ ++ y0 = src[i + 0].YUV.y; ++ y1 = src[i + 1].YUV.y; ++ ++ if (l < 8) { ++ dy1[7 - l] = (y0 & 0xFF00) ? 0xFF : y0; ++ dy1[7 - (l + 1)] = (y1 & 0xFF00) ? 0xFF : y1; ++ } else { ++ if (l == 8) { ++ dy1 = d1 + y_offet_table[++idx]; ++ } ++ ++ dy1[15 - l] = (y0 & 0xFF00) ? 0xFF : y0; ++ dy1[15 - (l + 1)] = (y1 & 0xFF00) ? 0xFF : y1; ++ } ++ ++ l += 2; ++ } ++} ++ + static void Sacc_to_Aop_nv21( GenefxState *gfxs ) + { + int w = gfxs->length+1; +@@ -4586,6 +5062,7 @@ static GenefxFunc Sacc_to_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + [DFB_PIXELFORMAT_INDEX(DSPF_A1)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_NV12)] = Sacc_to_Aop_nv12, + [DFB_PIXELFORMAT_INDEX(DSPF_NV16)] = Sacc_to_Aop_nv12, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV24)] = Sacc_to_Aop_nv24, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)] = Sacc_to_Aop_argb2554, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)] = Sacc_to_Aop_argb4444, + [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)] = Sacc_to_Aop_rgba4444, +@@ -4607,6 +5084,10 @@ static GenefxFunc Sacc_to_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + [DFB_PIXELFORMAT_INDEX(DSPF_VYU)] = Sacc_to_Aop_vyu, + [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_YV16)] = Sacc_to_Aop_yv16, ++ [DFB_PIXELFORMAT_INDEX(DSPF_LUT4)] = Sacc_to_Aop_lut4, ++ [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)] = Sacc_to_Aop_bgr24, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV12MB)] = Sacc_to_Aop_nv12mb, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV16MB)] = Sacc_to_Aop_nv12mb, + }; + + /********************************* Sop_PFI_TEX_to_Dacc ****************************/ +@@ -4652,6 +5133,7 @@ static const GenefxFunc Sop_PFI_TEX_to_Dacc[DFB_NUM_PIXELFORMATS] = { + [DFB_PIXELFORMAT_INDEX(DSPF_A1)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_NV12)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_NV16)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV24)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)] = Sop_argb2554_TEX_to_Dacc, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)] = Sop_argb4444_TEX_to_Dacc, + [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)] = Sop_rgba4444_TEX_to_Dacc, +@@ -4673,6 +5155,10 @@ static const GenefxFunc Sop_PFI_TEX_to_Dacc[DFB_NUM_PIXELFORMATS] = { + [DFB_PIXELFORMAT_INDEX(DSPF_VYU)] = NULL,//Sop_vyu_TEX_to_Dacc, + [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_YV16)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_LUT4)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)] = Sop_bgr24_TEX_to_Dacc, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV12MB)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV16MB)] = NULL, + }; + + /********************************* Sop_PFI_TEX_Kto_Dacc ****************************/ +@@ -4697,6 +5183,7 @@ static const GenefxFunc Sop_PFI_TEX_Kto_Dacc[DFB_NUM_PIXELFORMATS] = { + [DFB_PIXELFORMAT_INDEX(DSPF_A1)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_NV12)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_NV16)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV24)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)] = Sop_argb2554_TEX_Kto_Dacc, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)] = Sop_argb4444_TEX_Kto_Dacc, + [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)] = Sop_rgba4444_TEX_Kto_Dacc, +@@ -4718,6 +5205,10 @@ static const GenefxFunc Sop_PFI_TEX_Kto_Dacc[DFB_NUM_PIXELFORMATS] = { + [DFB_PIXELFORMAT_INDEX(DSPF_VYU)] = NULL,//Sop_vyu_TEX_Kto_Dacc, + [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_YV16)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_LUT4)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)] = Sop_bgr24_TEX_Kto_Dacc, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV12MB)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV16MB)] = NULL, + }; + + /********************************* Sacc_Sto_Aop_PFI ***************************/ +@@ -5118,6 +5609,44 @@ static void Sacc_Sto_Aop_nv12( GenefxState *gfxs ) + } + } + ++static void Sacc_Sto_Aop_nv24( GenefxState *gfxs ) ++{ ++ int i = gfxs->Xphase; ++ int w = gfxs->length+1; ++ GenefxAccumulator *Sacc = gfxs->Sacc; ++ u8 *Dy = gfxs->Aop[0]; ++ int SperD = gfxs->SperD; ++ ++ while (--w) { ++ GenefxAccumulator *S = &Sacc[i>>16]; ++ ++ if (!(S->YUV.a & 0xF000)) ++ *Dy = (S->YUV.y & 0xFF00) ? 0xFF : S->YUV.y; ++ ++ ++Dy; ++ i += SperD; ++ } ++ ++ u16 *Duv = gfxs->Aop[1]; ++ ++ w = gfxs->length+1; ++ i = gfxs->Xphase; ++ ++ while (--w) { ++ GenefxAccumulator *S0 = &Sacc[i>>16]; ++ u32 cb, cr; ++ ++ if (!(S0->YUV.a & 0xF000)) { ++ cb = ((*Duv & 0xFF) + ((S0->YUV.u & 0xFF00) ? 0xFF : S0->YUV.u)) >> 1; ++ cr = ((*Duv >> 8) + ((S0->YUV.v & 0xFF00) ? 0xFF : S0->YUV.v)) >> 1; ++ *Duv = cb | (cr << 8); ++ } ++ ++ ++Duv; ++ i += SperD; ++ } ++} ++ + static void Sacc_Sto_Aop_nv21( GenefxState *gfxs ) + { + int i = gfxs->Xphase; +@@ -5177,6 +5706,69 @@ static void Sacc_Sto_Aop_nv21( GenefxState *gfxs ) + } + } + ++static void Sacc_Sto_Aop_nv12mb( GenefxState *gfxs ) ++{ ++ int i, l, idx; ++ short dy; ++ u8 *d1, *dy1; ++ int SperD, phase; ++ int y0; ++ ++ GenefxAccumulator *src; ++ ++ int y_offet_table[32] = { ++ 8, 72, 136, 200, 0, 64, 128, 192, 24, 88, 152, 216, 16, ++ 80, 144, 208, 40, 104, 168, 232, 32, 96, 160, 224, 56, 120, ++ 184, 248, 48, 112, 176, 240 ++ }; ++ ++ d1 = gfxs->Aop[0]; ++ ++ y0 = (short)(((u32)gfxs->Aop[2] >> 16) & 0xffff); ++ dy = gfxs->AopY - y0; ++ ++ src = gfxs->Sacc; ++ ++ SperD = gfxs->SperD; ++ phase = gfxs->Xphase; ++ ++ idx = (dy % 16) * 2; ++ dy1 = d1 + y_offet_table[idx]; ++ ++ /* gfxs->length is assumed to be always even */ ++ for (i = 0, l = 0; i < (gfxs->length - 1); i += 2) ++ { ++ int y0, y1; ++ ++ if (l == 16) { ++ d1 += 2 * 256; ++ ++ idx = (dy % 16) * 2; ++ dy1 = d1 + y_offet_table[idx]; ++ ++ l = 0; ++ } ++ ++ y0 = src[(phase >> 16)].YUV.y; ++ y1 = src[(phase + SperD) >> 16].YUV.y; ++ ++ if (l < 8) { ++ dy1[7 - l] = (y0 & 0xFF00) ? 0xFF : y0; ++ dy1[7 - (l + 1)] = (y1 & 0xFF00) ? 0xFF : y1; ++ } else { ++ if (l == 8) { ++ dy1 = d1 + y_offet_table[++idx]; ++ } ++ ++ dy1[15 - l] = (y0 & 0xFF00) ? 0xFF : y0; ++ dy1[15 - (l + 1)] = (y1 & 0xFF00) ? 0xFF : y1; ++ } ++ ++ l += 2; ++ phase += (2 * SperD); ++ } ++} ++ + static void Sacc_Sto_Aop_ayuv( GenefxState *gfxs ) + { + int w = gfxs->length+1; +@@ -5263,7 +5855,7 @@ static void Sacc_Sto_Aop_vyu( GenefxState *gfxs ) + u8 u = (S->YUV.u & 0xFF00) ? 0xFF : S->YUV.u; + u8 v = (S->YUV.v & 0xFF00) ? 0xFF : S->YUV.v; + +-#ifdef BIG_ENDIAN ++#ifdef WORDS_BIGENDIAN + D[0] = v; + D[1] = y; + D[2] = u; +@@ -5299,6 +5891,7 @@ static GenefxFunc Sacc_Sto_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + [DFB_PIXELFORMAT_INDEX(DSPF_A1)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_NV12)] = Sacc_Sto_Aop_nv12, + [DFB_PIXELFORMAT_INDEX(DSPF_NV16)] = Sacc_Sto_Aop_nv12, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV24)] = Sacc_Sto_Aop_nv24, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)] = Sacc_Sto_Aop_argb2554, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)] = Sacc_Sto_Aop_argb4444, + [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)] = Sacc_Sto_Aop_rgba4444, +@@ -5320,6 +5913,10 @@ static GenefxFunc Sacc_Sto_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + [DFB_PIXELFORMAT_INDEX(DSPF_VYU)] = Sacc_Sto_Aop_vyu, + [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_YV16)] = Sacc_Sto_Aop_yv16, ++ [DFB_PIXELFORMAT_INDEX(DSPF_LUT4)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)] = Sacc_Sto_Aop_bgr24, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV12MB)] = Sacc_Sto_Aop_nv12mb, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV16MB)] = Sacc_Sto_Aop_nv12mb, + }; + + /********************************* Sacc_toK_Aop_PFI ***************************/ +@@ -5641,6 +6238,7 @@ static const GenefxFunc Sacc_toK_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + [DFB_PIXELFORMAT_INDEX(DSPF_A1)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_NV12)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_NV16)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV24)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)] = Sacc_toK_Aop_argb2554, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)] = Sacc_toK_Aop_argb4444, + [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)] = Sacc_toK_Aop_rgba4444, +@@ -5662,6 +6260,10 @@ static const GenefxFunc Sacc_toK_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + [DFB_PIXELFORMAT_INDEX(DSPF_VYU)] = Sacc_toK_Aop_vyu, + [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_YV16)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_LUT4)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)] = Sacc_toK_Aop_bgr24, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV12MB)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV16MB)] = NULL, + }; + + /********************************* Sacc_StoK_Aop_PFI **************************/ +@@ -5776,6 +6378,7 @@ static const GenefxFunc Sacc_StoK_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + [DFB_PIXELFORMAT_INDEX(DSPF_A1)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_NV12)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_NV16)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV24)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)] = Sacc_StoK_Aop_argb2554, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)] = Sacc_StoK_Aop_argb4444, + [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)] = Sacc_StoK_Aop_rgba4444, +@@ -5797,6 +6400,10 @@ static const GenefxFunc Sacc_StoK_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + [DFB_PIXELFORMAT_INDEX(DSPF_VYU)] = Sacc_StoK_Aop_vyu, + [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_YV16)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_LUT4)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)] = Sacc_StoK_Aop_bgr24, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV12MB)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV16MB)] = NULL, + }; + + /************** Bop_a8_set_alphapixel_Aop_PFI *********************************/ +@@ -6087,6 +6694,42 @@ static void Bop_a8_set_alphapixel_Aop_rgb24( GenefxState *gfxs ) + #undef SET_PIXEL + } + ++static void Bop_a8_set_alphapixel_Aop_bgr24( GenefxState *gfxs ) ++{ ++ int w = gfxs->length; ++ u8 *S = gfxs->Bop[0]; ++ u8 *D = gfxs->Aop[0]; ++ DFBColor color = gfxs->color; ++ ++#define SET_PIXEL(d,r,g,b,a)\ ++ switch (a) {\ ++ case 0xff:\ ++ d[0] = r;\ ++ d[1] = g;\ ++ d[2] = b;\ ++ case 0: break;\ ++ default: {\ ++ register u16 s = a+1;\ ++ d[0] = ((r-d[0]) * s + (d[0] << 8)) >> 8;\ ++ d[1] = ((g-d[1]) * s + (d[1] << 8)) >> 8;\ ++ d[2] = ((b-d[2]) * s + (d[2] << 8)) >> 8;\ ++ }\ ++ } ++ ++ while (w>4) { ++ SET_PIXEL( D, color.r, color.g, color.b, *S ); D+=3; S++; ++ SET_PIXEL( D, color.r, color.g, color.b, *S ); D+=3; S++; ++ SET_PIXEL( D, color.r, color.g, color.b, *S ); D+=3; S++; ++ SET_PIXEL( D, color.r, color.g, color.b, *S ); D+=3; S++; ++ w-=4; ++ } ++ while (w--) { ++ SET_PIXEL( D, color.r, color.g, color.b, *S ); D+=3, S++; ++ } ++ ++#undef SET_PIXEL ++} ++ + static void Bop_a8_set_alphapixel_Aop_rgb32( GenefxState *gfxs ) + { + int w = gfxs->length; +@@ -6497,6 +7140,7 @@ static const GenefxFunc Bop_a8_set_alphapixel_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + [DFB_PIXELFORMAT_INDEX(DSPF_A1)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_NV12)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_NV16)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV24)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)] = NULL, +@@ -6518,6 +7162,10 @@ static const GenefxFunc Bop_a8_set_alphapixel_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + [DFB_PIXELFORMAT_INDEX(DSPF_VYU)] = Bop_a8_set_alphapixel_Aop_vyu, + [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_YV16)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_LUT4)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)] = Bop_a8_set_alphapixel_Aop_bgr24, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV12MB)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV16MB)] = NULL, + }; + + /************** Bop_a1_set_alphapixel_Aop_PFI *********************************/ +@@ -6673,6 +7321,25 @@ static void Bop_a1_set_alphapixel_Aop_rgb24( GenefxState *gfxs ) + } + } + ++static void Bop_a1_set_alphapixel_Aop_bgr24( GenefxState *gfxs ) ++{ ++ int i; ++ int w = gfxs->length; ++ u8 *S = gfxs->Bop[0]; ++ u8 *D = gfxs->Aop[0]; ++ DFBColor color = gfxs->color; ++ ++ for (i=0; i>3] & (0x80 >> (i&7))) { ++ D[0] = color.r; ++ D[1] = color.g; ++ D[2] = color.b; ++ } ++ ++ D += 3; ++ } ++} ++ + static void Bop_a1_set_alphapixel_Aop_rgb32( GenefxState *gfxs ) + { + int i; +@@ -6881,6 +7548,7 @@ static const GenefxFunc Bop_a1_set_alphapixel_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + [DFB_PIXELFORMAT_INDEX(DSPF_A1)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_NV12)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_NV16)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV24)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)] = Bop_a1_set_alphapixel_Aop_argb2554, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)] = Bop_a1_set_alphapixel_Aop_argb4444, + [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)] = Bop_a1_set_alphapixel_Aop_rgba4444, +@@ -6902,6 +7570,10 @@ static const GenefxFunc Bop_a1_set_alphapixel_Aop_PFI[DFB_NUM_PIXELFORMATS] = { + [DFB_PIXELFORMAT_INDEX(DSPF_VYU)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_YV16)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_LUT4)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)] = Bop_a1_set_alphapixel_Aop_bgr24, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV12MB)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV16MB)] = NULL, + }; + + /************** Bop_a1_lsb_set_alphapixel_Aop_PFI *********************************/ +@@ -7016,6 +7688,25 @@ static void Bop_a1_lsb_set_alphapixel_Aop_rgb24( GenefxState *gfxs ) + } + } + ++static void Bop_a1_lsb_set_alphapixel_Aop_bgr24( GenefxState *gfxs ) ++{ ++ int i; ++ int w = gfxs->length; ++ u8 *S = gfxs->Bop[0]; ++ u8 *D = gfxs->Aop[0]; ++ DFBColor color = gfxs->color; ++ ++ for (i=0; i>3] & (1 << (i&7))) { ++ D[0] = color.r; ++ D[1] = color.g; ++ D[2] = color.b; ++ } ++ ++ D += 3; ++ } ++} ++ + static void Bop_a1_lsb_set_alphapixel_Aop_rgb32( GenefxState *gfxs ) + { + int i; +@@ -7192,6 +7883,7 @@ static const GenefxFunc Bop_a1_lsb_set_alphapixel_Aop_PFI[DFB_NUM_PIXELFORMATS] + [DFB_PIXELFORMAT_INDEX(DSPF_A1)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_NV12)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_NV16)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV24)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)] = Bop_a1_lsb_set_alphapixel_Aop_argb2554, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)] = Bop_a1_lsb_set_alphapixel_Aop_argb4444, + [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)] = NULL, +@@ -7213,6 +7905,10 @@ static const GenefxFunc Bop_a1_lsb_set_alphapixel_Aop_PFI[DFB_NUM_PIXELFORMATS] + [DFB_PIXELFORMAT_INDEX(DSPF_VYU)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_YV16)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_LUT4)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)] = Bop_a1_lsb_set_alphapixel_Aop_bgr24, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV12MB)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV16MB)] = NULL, + }; + + /**************************** Bop_translate_to_Aop ****************************/ +@@ -8050,6 +8746,7 @@ static const GenefxFunc Bop_argb_blend_alphachannel_src_invsrc_Aop_PFI[DFB_NUM_P + [DFB_PIXELFORMAT_INDEX(DSPF_A1)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_NV12)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_NV16)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV24)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)] = NULL, +@@ -8071,6 +8768,10 @@ static const GenefxFunc Bop_argb_blend_alphachannel_src_invsrc_Aop_PFI[DFB_NUM_P + [DFB_PIXELFORMAT_INDEX(DSPF_VYU)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_YV16)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_LUT4)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV12MB)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV16MB)] = NULL, + }; + + /**********************************************************************************************************************/ +@@ -8129,6 +8830,7 @@ static const GenefxFunc Bop_argb_blend_alphachannel_one_invsrc_Aop_PFI[DFB_NUM_P + [DFB_PIXELFORMAT_INDEX(DSPF_A1)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_NV12)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_NV16)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV24)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)] = NULL, +@@ -8150,6 +8852,10 @@ static const GenefxFunc Bop_argb_blend_alphachannel_one_invsrc_Aop_PFI[DFB_NUM_P + [DFB_PIXELFORMAT_INDEX(DSPF_VYU)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_YV16)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_LUT4)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV12MB)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV16MB)] = NULL, + }; + + /**********************************************************************************************************************/ +@@ -8213,6 +8919,7 @@ static const GenefxFunc Bop_argb_blend_alphachannel_one_invsrc_premultiply_Aop_P + [DFB_PIXELFORMAT_INDEX(DSPF_A1)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_NV12)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_NV16)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV24)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB2554)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_ARGB4444)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_RGBA4444)] = NULL, +@@ -8234,6 +8941,10 @@ static const GenefxFunc Bop_argb_blend_alphachannel_one_invsrc_premultiply_Aop_P + [DFB_PIXELFORMAT_INDEX(DSPF_VYU)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_YV16)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_LUT4)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV12MB)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV16MB)] = NULL, + }; + + /**********************************************************************************************************************/ +@@ -8674,6 +9385,9 @@ gAcquireSetup( CardState *state, DFBAccelerationMask accel ) + case DSPF_NV12: + case DSPF_NV21: + case DSPF_NV16: ++ case DSPF_NV24: ++ case DSPF_NV12MB: ++ case DSPF_NV16MB: + gfxs->dst_org[1] = gfxs->dst_org[0] + gfxs->dst_height * gfxs->dst_pitch; + break; + case DSPF_YUV444P: +@@ -8717,6 +9431,9 @@ gAcquireSetup( CardState *state, DFBAccelerationMask accel ) + case DSPF_NV12: + case DSPF_NV21: + case DSPF_NV16: ++ case DSPF_NV24: ++ case DSPF_NV12MB: ++ case DSPF_NV16MB: + gfxs->src_org[1] = gfxs->src_org[0] + gfxs->src_height * gfxs->src_pitch; + break; + case DSPF_YUV444P: +@@ -8759,6 +9476,9 @@ gAcquireSetup( CardState *state, DFBAccelerationMask accel ) + case DSPF_RGB24: + gfxs->Cop = PIXEL_RGB32( color.r, color.g, color.b ); + break; ++ case DSPF_BGR24: ++ gfxs->Cop = PIXEL_RGB32( color.b, color.g, color.r ); ++ break; + case DSPF_RGB32: + gfxs->Cop = PIXEL_RGB32( color.r, color.g, color.b ); + break; +@@ -8803,18 +9523,18 @@ gAcquireSetup( CardState *state, DFBAccelerationMask accel ) + case DSPF_YV12: + case DSPF_YV16: + case DSPF_NV12: ++ case DSPF_NV21: + case DSPF_NV16: ++ case DSPF_NV24: ++ case DSPF_NV12MB: ++ case DSPF_NV16MB: + case DSPF_YUV444P: + RGB_TO_YCBCR( color.r, color.g, color.b, + gfxs->YCop, gfxs->CbCop, gfxs->CrCop ); + gfxs->Cop = gfxs->YCop; + break; +- case DSPF_NV21: +- RGB_TO_YCBCR( color.r, color.g, color.b, +- gfxs->YCop, gfxs->CrCop, gfxs->CbCop ); +- gfxs->Cop = gfxs->YCop; +- break; + case DSPF_LUT2: ++ case DSPF_LUT4: + case DSPF_LUT8: + gfxs->Cop = state->color_index; + gfxs->Alut = destination->palette; +@@ -8875,6 +9595,7 @@ gAcquireSetup( CardState *state, DFBAccelerationMask accel ) + if (DFB_BLITTING_FUNCTION( accel )) { + switch (gfxs->src_format) { + case DSPF_LUT2: ++ case DSPF_LUT4: + case DSPF_LUT8: + case DSPF_ALUT44: + gfxs->Blut = source->palette; +@@ -8889,6 +9610,7 @@ gAcquireSetup( CardState *state, DFBAccelerationMask accel ) + case DSPF_RGB16: + case DSPF_RGB18: + case DSPF_RGB24: ++ case DSPF_BGR24: + case DSPF_RGB32: + case DSPF_ARGB: + case DSPF_ABGR: +@@ -8917,6 +9639,9 @@ gAcquireSetup( CardState *state, DFBAccelerationMask accel ) + case DSPF_NV12: + case DSPF_NV21: + case DSPF_NV16: ++ case DSPF_NV24: ++ case DSPF_NV12MB: ++ case DSPF_NV16MB: + if (state->blittingflags & DSBLIT_SRC_COLORKEY) + return false; + case DSPF_YUY2: +diff --git a/src/gfx/generic/generic_stretch_blit.c b/src/gfx/generic/generic_stretch_blit.c +index e642d4c..869e672 100644 +--- a/src/gfx/generic/generic_stretch_blit.c ++++ b/src/gfx/generic/generic_stretch_blit.c +@@ -295,6 +295,11 @@ static const StretchFunctionTable *stretch_tables[DFB_NUM_PIXELFORMATS] = { + [DFB_PIXELFORMAT_INDEX(DSPF_VYU)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_A1_LSB)] = NULL, + [DFB_PIXELFORMAT_INDEX(DSPF_YV16)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_LUT4)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_BGR24)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV12MB)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV16MB)] = NULL, ++ [DFB_PIXELFORMAT_INDEX(DSPF_NV24)] = NULL, + }; + + /**********************************************************************************************************************/ +diff --git a/src/gfx/generic/generic_util.c b/src/gfx/generic/generic_util.c +index 644008d..5a686d9 100644 +--- a/src/gfx/generic/generic_util.c ++++ b/src/gfx/generic/generic_util.c +@@ -106,7 +106,14 @@ void Genefx_Aop_xy( GenefxState *gfxs, int x, int y ) + case DSPF_NV16: + x &= ~1; + break; ++ case DSPF_NV12MB: ++ case DSPF_NV16MB: ++ y &= ~31L; ++ x &= ~31L; ++ gfxs->AopY = y; ++ break; + case DSPF_YUV444P: /* nothing to adjust */ ++ case DSPF_NV24: + default: + break; + } +@@ -121,6 +128,25 @@ void Genefx_Aop_xy( GenefxState *gfxs, int x, int y ) + + gfxs->Aop[1] += y * pitch + x; + gfxs->Aop[2] += y * pitch + x; ++ ++ switch (gfxs->dst_format) { ++ /* overwrite Aop[] when dst_format is a DSPF_NV1xMB */ ++ case DSPF_NV12MB: ++ case DSPF_NV16MB: ++ gfxs->Aop[0] = RASTER_TO_NV1xMB_ADDR(gfxs->dst_org[0], ++ pitch, x, y, 0); ++ /* we don't handle chroma yet */ ++ gfxs->Aop[1] = 0; ++ /* orignal signed coordinates */ ++ gfxs->Aop[2] = (void*)(((y & 0xffff) << 16) | (x & 0xffff)); ++ break; ++ case DSPF_NV24: ++ /* adjust again as chroma is fully sampled */ ++ gfxs->Aop[1] += y * pitch + x; ++ break; ++ default: ++ break; ++ } + } + } + +@@ -215,6 +241,18 @@ void Genefx_Aop_next( GenefxState *gfxs ) + gfxs->Aop[2] += pitch; + } + } ++ else if (gfxs->dst_format == DSPF_NV12MB ++ || gfxs->dst_format == DSPF_NV16MB) { ++ int x0 = ((u32)gfxs->Aop[2] & 0xffff); ++ int y0 = (short)(((u32)gfxs->Aop[2] >> 16) & 0xffff); ++ gfxs->Aop[0] = RASTER_TO_NV1xMB_ADDR(gfxs->dst_org[0], pitch, ++ x0, (gfxs->AopY + 1), ++ (gfxs->AopY + 1) - y0); ++ gfxs->Aop[1] = 0; ++ } ++ else if (gfxs->dst_format == DSPF_NV24) { ++ gfxs->Aop[1] += pitch * 2; ++ } + else { /* NV16 */ + if (gfxs->dst_caps & DSCAPS_SEPARATED) { + if (gfxs->Aop_field & 1) +@@ -310,6 +348,18 @@ void Genefx_Aop_prev( GenefxState *gfxs ) + gfxs->Aop[2] -= pitch; + } + } ++ else if (gfxs->dst_format == DSPF_NV12MB ++ || gfxs->dst_format == DSPF_NV16MB) { ++ int x0 = ((u32)gfxs->Aop[2] & 0xffff); ++ int y0 = (short)(((u32)gfxs->Aop[2] >> 16) & 0xffff); ++ gfxs->Aop[0] = RASTER_TO_NV1xMB_ADDR(gfxs->dst_org[0], pitch, ++ x0, (gfxs->AopY - 1), ++ (gfxs->AopY - 1) - y0); ++ gfxs->Aop[1] = 0; ++ } ++ else if (gfxs->dst_format == DSPF_NV24) { ++ gfxs->Aop[1] -= pitch * 2; ++ } + else { /* NV16 */ + if (gfxs->dst_caps & DSCAPS_SEPARATED) { + if (gfxs->Aop_field & 1) +@@ -369,7 +419,14 @@ void Genefx_Bop_xy( GenefxState *gfxs, int x, int y ) + case DSPF_NV16: + x &= ~1; + break; ++ case DSPF_NV12MB: ++ case DSPF_NV16MB: ++ y &= ~31L; ++ x &= ~31L; ++ gfxs->BopY = y; ++ break; + case DSPF_YUV444P: /* nothing to adjust */ ++ case DSPF_NV24: + default: + break; + } +@@ -384,6 +441,25 @@ void Genefx_Bop_xy( GenefxState *gfxs, int x, int y ) + + gfxs->Bop[1] += y * pitch + x; + gfxs->Bop[2] += y * pitch + x; ++ ++ switch (gfxs->src_format) { ++ /* overwrite Aop[] when dst_format is & DSPF_NV1xMB */ ++ case DSPF_NV12MB: ++ case DSPF_NV16MB: ++ gfxs->Bop[0] = RASTER_TO_NV1xMB_ADDR(gfxs->src_org[0], ++ pitch, x, y, 0); ++ /* we don't handle chroma yet */ ++ gfxs->Bop[1] = 0; ++ /* orignal signed coordinates */ ++ gfxs->Bop[2] = (void*)(((y & 0xffff) << 16) | (x & 0xffff)); ++ break; ++ case DSPF_NV24: ++ /* adjust again as chroma is fully sampled */ ++ gfxs->Bop[1] += y * pitch + x; ++ break; ++ default: ++ break; ++ } + } + } + +@@ -466,6 +542,18 @@ void Genefx_Bop_next( GenefxState *gfxs ) + gfxs->Bop[2] += pitch; + } + } ++ else if (gfxs->src_format == DSPF_NV12MB ++ || gfxs->src_format == DSPF_NV16MB) { ++ int x0 = ((u32)gfxs->Bop[2] & 0xffff); ++ int y0 = (short)(((u32)gfxs->Bop[2] >> 16) & 0xffff); ++ gfxs->Bop[0] = RASTER_TO_NV1xMB_ADDR(gfxs->src_org[0], pitch, ++ x0, (gfxs->BopY + 1), ++ (gfxs->BopY + 1) - y0); ++ gfxs->Bop[1] = 0; ++ } ++ else if (gfxs->src_format == DSPF_NV24) { ++ gfxs->Bop[1] += pitch * 2; ++ } + else { /* NV16 */ + if (gfxs->src_caps & DSCAPS_SEPARATED) { + if (gfxs->Bop_field & 1) +@@ -561,6 +649,18 @@ void Genefx_Bop_prev( GenefxState *gfxs ) + gfxs->Bop[2] -= pitch; + } + } ++ else if (gfxs->src_format == DSPF_NV12MB ++ || gfxs->src_format == DSPF_NV16MB) { ++ int x0 = ((u32)gfxs->Bop[2] & 0xffff); ++ int y0 = (short)(((u32)gfxs->Bop[2] >> 16) & 0xffff); ++ gfxs->Bop[0] = RASTER_TO_NV1xMB_ADDR(gfxs->src_org[0], pitch, ++ x0, (gfxs->BopY - 1), ++ (gfxs->BopY - 1) - y0); ++ gfxs->Bop[1] = 0; ++ } ++ else if (gfxs->src_format == DSPF_NV24) { ++ gfxs->Bop[1] -= pitch * 2; ++ } + else { /* NV16 */ + if (gfxs->src_caps & DSCAPS_SEPARATED) { + if (gfxs->Bop_field & 1) +diff --git a/src/idirectfb.c b/src/idirectfb.c +index 72da997..59d3dba 100644 +--- a/src/idirectfb.c ++++ b/src/idirectfb.c +@@ -660,11 +660,13 @@ IDirectFB_CreateSurface( IDirectFB *thiz, + case DSPF_AiRGB: + case DSPF_I420: + case DSPF_LUT2: ++ case DSPF_LUT4: + case DSPF_LUT8: + case DSPF_ALUT44: + case DSPF_RGB16: + case DSPF_RGB18: + case DSPF_RGB24: ++ case DSPF_BGR24: + case DSPF_RGB32: + case DSPF_RGB332: + case DSPF_UYVY: +@@ -680,6 +682,19 @@ IDirectFB_CreateSurface( IDirectFB *thiz, + case DSPF_BGR555: + case DSPF_RGBAF88871: + case DSPF_YUV444P: ++ case DSPF_NV24: ++ break; ++ ++ case DSPF_NV12MB: ++ case DSPF_NV16MB: ++ if ((width & 31L) || (height & 31L) ++ || (caps & (DSCAPS_SEPARATED ++ | DSCAPS_INTERLACED))) ++ return DFB_INVARG; ++ break; ++ case DSPF_BYTE: ++ if (caps != DSCAPS_VIDEOONLY) ++ return DFB_INVARG; + break; + + default: +@@ -894,7 +909,8 @@ IDirectFB_CreateSurface( IDirectFB *thiz, + if ((caps & DSCAPS_FLIPPING) == DSCAPS_FLIPPING) + caps &= ~DSCAPS_TRIPLE; + +- config.surface_caps = DSCAPS_NONE; ++ if (!(config.flags & DLCONF_SURFACE_CAPS)) ++ config.surface_caps = DSCAPS_NONE; + + if (caps & DSCAPS_PREMULTIPLIED) { + config.flags |= DLCONF_SURFACE_CAPS; +@@ -1054,6 +1070,7 @@ IDirectFB_CreateSurface( IDirectFB *thiz, + } + else { + CoreSurfaceConfig config; ++ CoreSurfaceTypeFlags type; + + config.flags = CSCONF_SIZE | CSCONF_FORMAT | CSCONF_COLORSPACE | CSCONF_CAPS; + config.size.w = width; +@@ -1062,7 +1079,9 @@ IDirectFB_CreateSurface( IDirectFB *thiz, + config.colorspace = colorspace; + config.caps = caps; + +- ret = CoreDFB_CreateSurface( data->core, &config, CSTF_NONE, resource_id, NULL, &surface ); ++ type = (format == DSPF_BYTE) ? CSTF_BUFFEROBJECT : 0; ++ ++ ret = CoreDFB_CreateSurface( data->core, &config, CSTF_NONE | type, resource_id, NULL, &surface ); + if (ret) + return ret; + } +diff --git a/src/media/idirectfbimageprovider.c b/src/media/idirectfbimageprovider.c +index a4e5a4f..e4d472e 100644 +--- a/src/media/idirectfbimageprovider.c ++++ b/src/media/idirectfbimageprovider.c +@@ -123,6 +123,16 @@ static DFBResult + IDirectFBImageProvider_SetRenderFlags( IDirectFBImageProvider *thiz, + DIRenderFlags flags ) + { ++ if (flags == DIRENDER_NONE) ++ return DFB_OK; ++ ++ return DFB_UNIMPLEMENTED; ++} ++ ++static DFBResult ++IDirectFBImageProvider_Sync( IDirectFBImageProvider *thiz, ++ DFBImageProviderSyncFlags flags ) ++{ + return DFB_UNIMPLEMENTED; + } + +@@ -145,6 +155,7 @@ IDirectFBImageProvider_Construct( IDirectFBImageProvider *thiz ) + thiz->RenderTo = IDirectFBImageProvider_RenderTo; + thiz->SetRenderCallback = IDirectFBImageProvider_SetRenderCallback; + thiz->SetRenderFlags = IDirectFBImageProvider_SetRenderFlags; ++ thiz->Sync = IDirectFBImageProvider_Sync; + thiz->WriteBack = IDirectFBImageProvider_WriteBack; + } + +diff --git a/src/misc/gfx_util.c b/src/misc/gfx_util.c +index f948e3d..166349b 100644 +--- a/src/misc/gfx_util.c ++++ b/src/misc/gfx_util.c +@@ -76,6 +76,68 @@ struct _PixopsFilter { + }; + + ++/* Only write to the 4:2:x Omega2 MB buffer's luma channel */ ++void dfb_write_nv1xmb_span( u32 *src, u8 color, u8 *dst[], int len, int dy ) ++{ ++ int i, l, idx; ++ u8 *d1, *dy1; ++ ++ static const int y_offet_table[32] = { ++ 8, 72, 136, 200, 0, 64, 128, 192, 24, 88, ++ 152, 216, 16, 80, 144, 208, 40, 104, 168, 232, ++ 32, 96, 160, 224, 56, 120, 184, 248, 48, 112, ++ 176, 240 ++ }; ++ ++ d1 = dst[0]; ++ ++ idx = (dy % 16) * 2; ++ dy1 = d1 + y_offet_table[idx]; ++ ++ /* len is assumed to be always even */ ++ for (i = 0, l = 0; i < (len - 1); i += 2) { ++ u32 y0, u0, v0; ++ u32 y1, u1, v1; ++ ++ if (l == 16) { ++ d1 += 2 * 256; ++ ++ idx = (dy % 16) * 2; ++ dy1 = d1 + y_offet_table[idx]; ++ ++ l = 0; ++ } ++ ++ if (src) { ++ RGB_TO_YCBCR( (src[i + 0] >> 16) & 0xff, ++ (src[i + 0] >> 8) & 0xff, ++ (src[i + 0] ) & 0xff, y0, u0, v0 ); ++ RGB_TO_YCBCR( (src[i + 1] >> 16) & 0xff, ++ (src[i + 1] >> 8) & 0xff, ++ (src[i + 1] ) & 0xff, y1, u1, v1 ); ++ /* we currently only handle luma */ ++ (void) u0; ++ (void) v0; ++ (void) u1; ++ (void) v1; ++ } else ++ y0 = y1 = color; ++ ++ if (l < 8) { ++ dy1[7 - l] = y0; ++ dy1[7 - (l + 1)] = y1; ++ } else { ++ if (l == 8) ++ dy1 = d1 + y_offet_table[++idx]; ++ ++ dy1[15 - l] = y0; ++ dy1[15 - (l + 1)] = y1; ++ } ++ ++ l += 2; ++ } ++} ++ + static void write_argb_span (u32 *src, u8 *dst[], int len, + int dx, int dy, CoreSurface *dst_surface, + bool premultiply) +@@ -263,6 +325,20 @@ static void write_argb_span (u32 *src, u8 *dst[], int len, + } + break; + ++ case DSPF_BGR24: ++ for (i = 0; i < len; i++) { ++#ifdef WORDS_BIGENDIAN ++ *d++ = src[i]; ++ *d++ = src[i] >> 8; ++ *d++ = src[i] >> 16; ++#else ++ *d++ = src[i] >> 16; ++ *d++ = src[i] >> 8; ++ *d++ = src[i]; ++#endif ++ } ++ break; ++ + case DSPF_RGB32: + case DSPF_ARGB: + direct_memcpy( d, src, len*4 ); +@@ -278,6 +354,25 @@ static void write_argb_span (u32 *src, u8 *dst[], int len, + ((u32*)d)[i] = src[i] ^ 0xff000000; + break; + ++ case DSPF_LUT4: ++ if (palette) { ++ for (i = 0; i < len; i += 2) { ++ u8 pixel = 0; ++ pixel = dfb_palette_search( palette, ++ (src[i] >> 16) & 0xff, ++ (src[i] >> 8) & 0xff, ++ (src[i] ) & 0xff, ++ (src[i] >> 24) & 0xff ); ++ pixel |= (dfb_palette_search( palette, ++ (src[i + 1] >> 16) & 0xff, ++ (src[i + 1] >> 8) & 0xff, ++ (src[i + 1] ) & 0xff, ++ (src[i + 1] >> 24) & 0xff )) << 4; ++ d[i] = pixel; ++ } ++ } ++ break; ++ + case DSPF_LUT8: + if (palette) { + for (i = 0; i < len; i++) { +@@ -523,6 +618,26 @@ static void write_argb_span (u32 *src, u8 *dst[], int len, + } + break; + ++ case DSPF_NV24: ++ d1 = dst[1]; ++ for (i = 0; i < len; i++) { ++ u32 y0, u0, v0; ++ ++ RGB_TO_YCBCR( (src[i+0] >> 16) & 0xff, ++ (src[i+0] >> 8) & 0xff, ++ (src[i+0] ) & 0xff, y0, u0, v0 ); ++ ++ d[i + 0] = y0; ++ d1[2 * i + 0] = u0; ++ d1[2 * i + 1] = v0; ++ } ++ break; ++ ++ case DSPF_NV12MB: ++ case DSPF_NV16MB: ++ dfb_write_nv1xmb_span( src, 0, dst, len, dy ); ++ break; ++ + case DSPF_NV21: + d1 = dst[1]; + for (i = 0; i < (len-1); i += 2) { +@@ -723,6 +838,34 @@ void dfb_copy_buffer_32( u32 *src, + } + break; + ++ case DSPF_NV12MB: ++ case DSPF_NV16MB: ++ dst1 = dst + dpitch * dst_surface->config.size.h; ++ ++ if ((x & 31L) || (drect->y & 31L) ++ || (drect->h & 31L) || (drect->w & 15L)) { ++ D_WARN ("nv1xmb copy not performed because of a non 32 pixels aligned offsets."); ++ break; ++ } ++ ++ /* Clear the chroma channel for 4:2:x Omega2 MB buffers */ ++ if (dst_surface->config.format == DSPF_NV12MB) ++ memset(dst1, 127, dpitch * (dst_surface->config.size.h >> 1)); ++ if (dst_surface->config.format == DSPF_NV16MB) ++ memset(dst1, 127, dpitch * dst_surface->config.size.h); ++ ++ for (y = drect->y; y < drect->y + drect->h; y++) { ++ u8 *d[2]; ++ ++ d[0] = RASTER_TO_NV1xMB_ADDR( dst, dpitch, drect->x, ++ y, y - drect->y ); ++ ++ write_argb_span( src, d, drect->w, x, y - drect->y, dst_surface, true ); ++ ++ src += sw; ++ } ++ break; ++ + case DSPF_NV16: + dst1 = (u8*)dst + dpitch * dst_surface->config.size.h; + +@@ -740,6 +883,23 @@ void dfb_copy_buffer_32( u32 *src, + } + break; + ++ case DSPF_NV24: ++ dst1 = (u8*)dst + dpitch * dst_surface->config.size.h; ++ ++ for (y = drect->y; y < drect->y + drect->h; y++) { ++ u8 *d[2]; ++ ++ d[0] = LINE_PTR( dst, dst_surface->config.caps, y, ++ dst_surface->config.size.h, dpitch ) + x; ++ d[1] = LINE_PTR( dst1, dst_surface->config.caps, y, ++ dst_surface->config.size.h, dpitch * 2 ) + x * 2; ++ ++ write_argb_span( src, d, drect->w, x, y, dst_surface, true ); ++ ++ src += sw; ++ } ++ break; ++ + case DSPF_YUV444P: + dst1 = (u8*)dst + dpitch * dst_surface->config.size.h; + dst2 = dst1 + dpitch * dst_surface->config.size.h; +@@ -1027,8 +1187,11 @@ void dfb_scale_linear_32( u32 *src, int sw, int sh, + dst1 = dst2 + dpitch/2 * dst_surface->config.size.h; + break; + case DSPF_NV12: ++ case DSPF_NV12MB: ++ case DSPF_NV16MB: + case DSPF_NV21: + case DSPF_NV16: ++ case DSPF_NV24: + dst1 = (u8*)dst + dpitch * dst_surface->config.size.h; + break; + case DSPF_YUV444P: +@@ -1039,6 +1202,12 @@ void dfb_scale_linear_32( u32 *src, int sw, int sh, + break; + } + ++ /* Clear the chroma channel for 4:2:x Omega2 MB buffers */ ++ if (dst_surface->config.format == DSPF_NV12MB) ++ memset(dst1, 127, dpitch * (dst_surface->config.size.h >> 1)); ++ if (dst_surface->config.format == DSPF_NV16MB) ++ memset(dst1, 127, dpitch * dst_surface->config.size.h); ++ + buf = (u32*) alloca( drect->w * 4 ); + + for (i = drect->y; i < drect->y + drect->h; i++) { +@@ -1126,6 +1295,15 @@ void dfb_scale_linear_32( u32 *src, int sw, int sh, + d[1] = LINE_PTR( dst1, dst_surface->config.caps, i, + dst_surface->config.size.h, dpitch ) + (drect->x&~1); + break; ++ case DSPF_NV24: ++ d[1] = LINE_PTR( dst1, dst_surface->config.caps, i, ++ dst_surface->config.size.h, dpitch * 2 ) + (drect->x * 2); ++ break; ++ case DSPF_NV16MB: ++ case DSPF_NV12MB: ++ d[0] = RASTER_TO_NV1xMB_ADDR( dst, dpitch, drect->x, ++ i, i - drect->y ); ++ break; + case DSPF_YUV444P: + d[1] = LINE_PTR( dst1, dst_surface->config.caps, i, + dst_surface->config.size.h, dpitch ) + drect->x; +@@ -1136,7 +1314,11 @@ void dfb_scale_linear_32( u32 *src, int sw, int sh, + break; + } + +- write_argb_span( buf, d, drect->w, drect->x, i, dst_surface, false ); ++ if ((dst_surface->config.format == DSPF_NV12MB) ++ || (dst_surface->config.format == DSPF_NV16MB)) ++ write_argb_span( buf, d, drect->w, drect->x, i - drect->y, dst_surface, false ); ++ else ++ write_argb_span( buf, d, drect->w, drect->x, i, dst_surface, false ); + } + + D_FREE(filter.weights); +diff --git a/src/misc/gfx_util.h b/src/misc/gfx_util.h +index 56b7944..68cbe7b 100644 +--- a/src/misc/gfx_util.h ++++ b/src/misc/gfx_util.h +@@ -44,5 +44,11 @@ void dfb_scale_linear_32( u32 *src, int sw, int sh, + void *dst, int dpitch, DFBRectangle *drect, + CoreSurface *dst_surface, const DFBRegion *dst_clip ); + ++#define RASTER_TO_NV1xMB_ADDR( dst, pitch, dx, y, dy ) \ ++ (dst + ((y / 32) * (pitch / 16) * 256 * 2) \ ++ + (((dy / 16) & 1L) ? ((dx / 16) * 2 + 1) * 256 \ ++ : (dx / 16) * 2 * 256)) ++ ++void dfb_write_nv1xmb_span( u32 *src, u8 color, u8 *dst[], int len, int dy ); + + #endif +diff --git a/src/misc/util.c b/src/misc/util.c +index 2fbefed..9ad9670 100644 +--- a/src/misc/util.c ++++ b/src/misc/util.c +@@ -464,6 +464,8 @@ dfb_pixelformat_for_depth( int depth ) + switch (depth) { + case 2: + return DSPF_LUT2; ++ case 4: ++ return DSPF_LUT4; + case 8: + return DSPF_LUT8; + case 12: +diff --git a/systems/Makefile.am b/systems/Makefile.am +index 163acdc..e379afe 100644 +--- a/systems/Makefile.am ++++ b/systems/Makefile.am +@@ -60,6 +60,12 @@ else + VNC_DIR = + endif + ++if STMFBDEV_CORE ++STMFBDEV_DIR = stmfbdev ++else ++STMFBDEV_DIR = ++endif ++ + + SUBDIRS = \ + android \ +@@ -73,4 +79,5 @@ SUBDIRS = \ + $(X11VDPAU_DIR) \ + $(SDL_DIR) \ + $(OSX_DIR) \ +- $(VNC_DIR) ++ $(VNC_DIR) \ ++ $(STMFBDEV_DIR) +diff --git a/systems/fbdev/fbdev_surface_pool.c b/systems/fbdev/fbdev_surface_pool.c +index 0d5742b..adad130 100644 +--- a/systems/fbdev/fbdev_surface_pool.c ++++ b/systems/fbdev/fbdev_surface_pool.c +@@ -112,7 +112,7 @@ fbdevInitPool( CoreDFB *core, + ret_desc->caps = CSPCAPS_PHYSICAL | CSPCAPS_VIRTUAL; + ret_desc->access[CSAID_CPU] = CSAF_READ | CSAF_WRITE | CSAF_SHARED; + ret_desc->access[CSAID_GPU] = CSAF_READ | CSAF_WRITE | CSAF_SHARED; +- ret_desc->types = CSTF_LAYER | CSTF_WINDOW | CSTF_CURSOR | CSTF_FONT | CSTF_SHARED | CSTF_EXTERNAL; ++ ret_desc->types = CSTF_LAYER | CSTF_WINDOW | CSTF_CURSOR | CSTF_FONT | CSTF_SHARED | CSTF_EXTERNAL | CSTF_BUFFEROBJECT; + ret_desc->priority = CSPP_DEFAULT; + + /* For hardware layers */ +diff --git a/systems/sdl/primary.c b/systems/sdl/primary.c +index 6848bc8..7551515 100644 +--- a/systems/sdl/primary.c ++++ b/systems/sdl/primary.c +@@ -334,7 +334,8 @@ update_screen( int x, int y, int w, int h ) + #if 0 + int i, n; + void *dst; +- void *src; ++ u8 *srces[3]; ++ int pitches[3]; + DFBResult ret; + CoreSurface *surface; + CoreSurfaceBuffer *buffer; +@@ -385,23 +386,25 @@ update_screen( int x, int y, int w, int h ) + return ret; + } + +- src = lock.addr; + dst = screen->pixels; +- +- src += DFB_BYTES_PER_LINE( surface->config.format, x ) + y * lock.pitch; + dst += DFB_BYTES_PER_LINE( surface->config.format, x ) + y * screen->pitch; + ++ dfb_surface_get_data_offsets( surface->data, lock.addr, lock.pitch, x, y, ++ 3, srces, pitches ); ++ + D_DEBUG_AT( SDL_Updates, " -> copying pixels...\n" ); + + switch (screen->format->BitsPerPixel) { + case 16: + dfb_convert_to_rgb16( surface->config.format, +- src, lock.pitch, surface->config.size.h, ++ srces[0], pitches[0], ++ srces[1], pitches[1], srces[2], pitches[2], ++ surface->config.size.h, + dst, screen->pitch, w, h ); + break; + + default: +- direct_memcpy( dst, src, DFB_BYTES_PER_LINE( surface->config.format, w ) ); ++ direct_memcpy( dst, srces[0], DFB_BYTES_PER_LINE( surface->config.format, w ) ); + } + + D_DEBUG_AT( SDL_Updates, " -> unlocking dfb surface...\n" ); +diff --git a/systems/stmfbdev/Makefile.am b/systems/stmfbdev/Makefile.am +new file mode 100644 +index 0000000..3df3151 +--- /dev/null ++++ b/systems/stmfbdev/Makefile.am +@@ -0,0 +1,55 @@ ++## Makefile.am for DirectFB/systems/stmfbdev ++ ++if STMFBDEV_USE_OWN_HEADERS ++STMFB_INCLUDE_PATH = -I$(srcdir)/include ++else ++STMFB_INCLUDE_PATH = ++endif ++ ++INCLUDES = \ ++ -I$(top_builddir)/include \ ++ -I$(top_builddir)/lib \ ++ -I$(top_srcdir)/include \ ++ -I$(top_srcdir)/lib \ ++ -I$(top_srcdir)/src \ ++ $(STMFB_INCLUDE_PATH) ++ ++ ++internalincludedir = $(INTERNALINCLUDEDIR)/stmfbdev ++ ++internalinclude_HEADERS = \ ++ fb.h \ ++ vt.h \ ++ surfacemanager.h \ ++ stmfbdev.h ++ ++systemsdir = $(MODULEDIR)/systems ++ ++if BUILD_STATIC ++systems_DATA = libdirectfb_stmfbdev.o ++endif ++systems_LTLIBRARIES = libdirectfb_stmfbdev.la ++ ++libdirectfb_stmfbdev_la_LDFLAGS = \ ++ -avoid-version \ ++ -module ++ ++libdirectfb_stmfbdev_la_SOURCES = \ ++ vt.c \ ++ \ ++ stmfbdev_screen.c \ ++ stmfbdev_layer.c \ ++ \ ++ surfacemanager.c \ ++ stmfbdev_surface_pool.c \ ++ stmfb_aux_surface_pool.c \ ++ \ ++ stmfbdev.c ++ ++libdirectfb_stmfbdev_la_LIBADD = \ ++ $(top_builddir)/lib/direct/libdirect.la \ ++ $(top_builddir)/lib/fusion/libfusion.la \ ++ $(top_builddir)/src/libdirectfb.la ++ ++ ++include $(top_srcdir)/rules/libobject.make +diff --git a/systems/stmfbdev/fb.h b/systems/stmfbdev/fb.h +new file mode 120000 +index 0000000..887b227 +--- /dev/null ++++ b/systems/stmfbdev/fb.h +@@ -0,0 +1 @@ ++../fbdev/fb.h +\ No newline at end of file +diff --git a/systems/stmfbdev/include/linux/stmfb.h b/systems/stmfbdev/include/linux/stmfb.h +new file mode 100644 +index 0000000..e65f4c9 +--- /dev/null ++++ b/systems/stmfbdev/include/linux/stmfb.h +@@ -0,0 +1,785 @@ ++/*********************************************************************** ++ * ++ * File: linux/kernel/drivers/video/stmfb.h ++ * Copyright (c) 2000, 2004, 2005 STMicroelectronics Limited. ++ * ++ * This file is subject to the terms and conditions of the GNU General Public ++ * License. See the file COPYING in the main directory of this archive for ++ * more details. ++ * ++\***********************************************************************/ ++ ++#ifndef _STMFB_H ++#define _STMFB_H ++ ++/* ++ * Surface definitions for usermode, in the kernel driver they are ++ * already defined internally as part of the generic framework. ++ */ ++#if !defined(__KERNEL__) ++#include ++typedef enum ++{ ++ SURF_NULL_PAD, ++ SURF_RGB565 , ++ SURF_RGB888 , ++ SURF_ARGB8565, ++ SURF_ARGB8888, ++ SURF_ARGB1555, ++ SURF_ARGB4444, ++ SURF_CRYCB888, /* Note the order of the components */ ++ SURF_YCBCR422R, ++ SURF_YCBCR422MB, ++ SURF_YCBCR420MB, ++ SURF_ACRYCB8888, /* Note the order, not compatible with DirectFB's AYUV */ ++ SURF_CLUT1, ++ SURF_CLUT2, ++ SURF_CLUT4, ++ SURF_CLUT8, ++ SURF_ACLUT44, ++ SURF_ACLUT88, ++ SURF_A1, ++ SURF_A8, ++ SURF_BGRA8888, /* Bigendian ARGB */ ++ SURF_YUYV, /* 422R with luma and chroma byteswapped */ ++ SURF_YUV420, /* Planar YUV with 1/2 horizontal and vertical chroma */ ++ /* in three separate buffers Y,Cb then Cr */ ++ SURF_YVU420, /* Planar YUV with 1/2 horizontal and vertical chroma */ ++ /* in three separate buffers Y,Cr then Cb */ ++ SURF_YUV422P, /* Planar YUV with 1/2 horizontal chroma */ ++ /* in three separate buffers Y,Cb then Cr */ ++ ++ SURF_RLD_BD, /* RLE Decoding controlled by setting source format */ ++ SURF_RLD_H2, ++ SURF_RLD_H8, ++ SURF_CLUT8_ARGB4444_ENTRIES, /* For cursor plane support */ ++ SURF_YCbCr420R2B, /* fourCC: NV12: 12 bit YCbCr (8 bit Y plane followed by ++ one 16 bit quarter size ++ Cb|Cr [7:0|7:0] plane) */ ++ SURF_YCbCr422R2B, /* fourCC: NV16: 16 bit YCbCr (8 bit Y plane followed by ++ one 16 bit half width ++ Cb|Cr [7:0|7:0] plane) */ ++ ++ SURF_END, ++ SURF_COUNT = SURF_END ++}stm_pixel_format_t; ++ ++typedef stm_pixel_format_t SURF_FMT; /*!< For backwards compatibility */ ++ ++#endif /* !__KERNEL__ */ ++ ++typedef enum ++{ ++ STMFBGP_FRAMEBUFFER, ++ ++ STMFBGP_GFX_FIRST, ++ STMFBGP_GFX0 = STMFBGP_GFX_FIRST, ++ STMFBGP_GFX1, ++ STMFBGP_GFX2, ++ STMFBGP_GFX3, ++ STMFBGP_GFX4, ++ STMFBGP_GFX_LAST = STMFBGP_GFX4 ++ ++} STMFB_GFXMEMORY_PARTITION; ++ ++ ++/* ++ * Defined for STMFBIO_CGMS_ANALOG (use as bitfield) ++ */ ++#define STMFBIO_CGMS_ANALOG_COPYRIGHT_ASSERTED 1 /* copyright bit */ ++#define STMFBIO_CGMS_ANALOG_COPYING_RESTRICTED 2 /* generation bit */ ++ ++ ++#define STMFBIO_COLOURKEY_FLAGS_ENABLE 0x00000001 ++#define STMFBIO_COLOURKEY_FLAGS_INVERT 0x00000002 ++ ++typedef enum { ++ STMFBIO_FF_OFF, ++ STMFBIO_FF_SIMPLE, ++ STMFBIO_FF_ADAPTIVE ++} stmfbio_ff_state; ++ ++ ++#define STMFBIO_VAR_CAPS_NONE (0) ++#define STMFBIO_VAR_CAPS_COLOURKEY (1L<<1) ++#define STMFBIO_VAR_CAPS_FLICKER_FILTER (1L<<2) ++#define STMFBIO_VAR_CAPS_PREMULTIPLIED (1L<<3) ++#define STMFBIO_VAR_CAPS_OPACITY (1L<<4) ++#define STMFBIO_VAR_CAPS_GAIN (1L<<5) ++#define STMFBIO_VAR_CAPS_BRIGHTNESS (1L<<6) ++#define STMFBIO_VAR_CAPS_SATURATION (1L<<7) ++#define STMFBIO_VAR_CAPS_CONTRAST (1L<<8) ++#define STMFBIO_VAR_CAPS_TINT (1L<<9) ++#define STMFBIO_VAR_CAPS_ALPHA_RAMP (1L<<10) ++#define STMFBIO_VAR_CAPS_ZPOSITION (1L<<11) ++#define STBFBIO_VAR_CAPS_RESCALE_COLOUR_TO_VIDEO_RANGE (1L<<12) ++ ++enum stmfbio_output_id { ++ STMFBIO_OUTPUTID_INVALID, ++ ++ STMFBIO_OUTPUTID_MAIN, ++}; ++ ++ ++typedef enum _stmfbio_activate { ++ STMFBIO_ACTIVATE_IMMEDIATE = 0x00000000, ++ STMFBIO_ACTIVATE_ON_NEXT_CHANGE = 0x00000001, ++ STMFBIO_ACTIVATE_TEST = 0x00000002, ++ STMFBIO_ACTIVATE_MASK = 0x0000000f, ++ ++ STMFBIO_ACTIVATE_VBL = 0x00000010, ++} stmfbio_activate; ++ ++ ++enum stmfbio_output_standard { ++ STMFBIO_STD_UNKNOWN, ++ /* */ ++ STMFBIO_STD_PAL_BDGHI = 0x4000000000000000LLU, ++ STMFBIO_STD_SECAM = 0x2000000000000000LLU, ++ ++ /* analogue standards are a mess - the following values ++ coincidentially coincide with the v4l2 defines... */ ++ STMFBIO_STD_PAL_M = 0x0000000000000100LLU, ++ STMFBIO_STD_PAL_N = 0x0000000000000200LLU, ++ STMFBIO_STD_PAL_Nc = 0x0000000000000400LLU, ++ STMFBIO_STD_PAL_60 = 0x0000000000000800LLU, ++ ++ STMFBIO_STD_NTSC_M = 0x0000000000001000LLU, ++ STMFBIO_STD_NTSC_M_JP = 0x0000000000002000LLU, ++ STMFBIO_STD_NTSC_443 = 0x0000000000004000LLU, ++ ++ /* */ ++ STMFBIO_STD_VGA_60 = 0x0000000100000000LLU, ++ STMFBIO_STD_VGA_59_94 = 0x0000000200000000LLU, ++ STMFBIO_STD_480P_60 = 0x0000000400000000LLU, ++ STMFBIO_STD_480P_59_94 = 0x0000000800000000LLU, ++ STMFBIO_STD_576P_50 = 0x0000001000000000LLU, ++ STMFBIO_STD_1080P_60 = 0x0000002000000000LLU, ++ STMFBIO_STD_1080P_59_94 = 0x0000004000000000LLU, ++ STMFBIO_STD_1080P_50 = 0x0000008000000000LLU, ++ STMFBIO_STD_1080P_23_976 = 0x0000010000000000LLU, ++ STMFBIO_STD_1080P_24 = 0x0000020000000000LLU, ++ STMFBIO_STD_1080P_25 = 0x0000040000000000LLU, ++ STMFBIO_STD_1080P_29_97 = 0x0000080000000000LLU, ++ STMFBIO_STD_1080P_30 = 0x0000100000000000LLU, ++ STMFBIO_STD_1080I_60 = 0x0000200000000000LLU, ++ STMFBIO_STD_1080I_59_94 = 0x0000400000000000LLU, ++ STMFBIO_STD_1080I_50 = 0x0000800000000000LLU, ++ STMFBIO_STD_720P_60 = 0x0001000000000000LLU, ++ STMFBIO_STD_720P_59_94 = 0x0002000000000000LLU, ++ STMFBIO_STD_720P_50 = 0x0004000000000000LLU, ++ ++ STMFBIO_STD_QFHD3660 = 0x0010000000000000LLU, ++ STMFBIO_STD_QFHD3650 = 0x0020000000000000LLU, ++ STMFBIO_STD_WQFHD5660 = 0x0040000000000000LLU, ++ STMFBIO_STD_WQFHD5650 = 0x0080000000000000LLU, ++ STMFBIO_STD_QFHD5660 = 0x0100000000000000LLU, ++ STMFBIO_STD_QFHD5650 = 0x0200000000000000LLU, ++ STMFBIO_STD_QFHD1830 = 0x0400000000000000LLU, ++ STMFBIO_STD_QFHD1825 = 0x0800000000000000LLU, ++ ++ STMFBIO_STD_XGA_60 = 0x1000000000000000LLU, ++ STMFBIO_STD_XGA_75 = 0x2000000000000000LLU, ++ STMFBIO_STD_XGA_85 = 0x4000000000000000LLU, ++}; ++ ++ ++#define STMFBIO_STD_NTSC (STMFBIO_STD_NTSC_M \ ++ | STMFBIO_STD_NTSC_M_JP) ++ ++#define STMFBIO_STD_PAL (STMFBIO_STD_PAL_BDGHI) ++ ++#define STMFBIO_STD_525_60 (STMFBIO_STD_PAL_M \ ++ | STMFBIO_STD_PAL_60 \ ++ | STMFBIO_STD_NTSC \ ++ | STMFBIO_STD_NTSC_443) ++#define STMFBIO_STD_625_50 (STMFBIO_STD_PAL \ ++ | STMFBIO_STD_PAL_N \ ++ | STMFBIO_STD_PAL_Nc \ ++ | STMFBIO_STD_SECAM) ++ ++#define STMFBIO_STD_SMPTE293M (STMFBIO_STD_480P_60 \ ++ | STMFBIO_STD_480P_59_94 \ ++ | STMFBIO_STD_576P_50) ++ ++#define STMFBIO_STD_SMPTE274M (STMFBIO_STD_1080P_60 \ ++ | STMFBIO_STD_1080P_59_94 \ ++ | STMFBIO_STD_1080P_50 \ ++ | STMFBIO_STD_1080P_23_976 \ ++ | STMFBIO_STD_1080P_24 \ ++ | STMFBIO_STD_1080P_25 \ ++ | STMFBIO_STD_1080P_29_97 \ ++ | STMFBIO_STD_1080P_30 \ ++ | STMFBIO_STD_1080I_60 \ ++ | STMFBIO_STD_1080I_59_94 \ ++ | STMFBIO_STD_1080I_50) ++ ++#define STMFBIO_STD_SMPTE296M (STMFBIO_STD_720P_60 \ ++ | STMFBIO_STD_720P_59_94 \ ++ | STMFBIO_STD_720P_50) ++ ++#define STMFBIO_STD_SD (STMFBIO_STD_525_60 \ ++ | STMFBIO_STD_625_50) ++ ++#define STMFBIO_STD_ED (STMFBIO_STD_SMPTE293M) ++ ++#define STMFBIO_STD_HD (STMFBIO_STD_SMPTE274M \ ++ | STMFBIO_STD_SMPTE296M) ++ ++#define STMFBIO_STD_VESA (STMFBIO_STD_VGA_60 \ ++ | STMFBIO_STD_VGA_59_94 \ ++ | STMFBIO_STD_XGA_60 \ ++ | STMFBIO_STD_XGA_75 \ ++ | STMFBIO_STD_XGA_85) ++ ++#define STMFBIO_STD_CEA861 (STMFBIO_STD_525_60 \ ++ | STMFBIO_STD_625_50 \ ++ | STMFBIO_STD_VGA_60 \ ++ | STMFBIO_STD_VGA_59_94 \ ++ | STMFBIO_STD_SMPTE293M \ ++ | STMFBIO_STD_SMPTE274M \ ++ | STMFBIO_STD_SMPTE296M) ++ ++#define STMFBIO_STD_NTG5 (STMFBIO_STD_QFHD3660 \ ++ | STMFBIO_STD_QFHD3650 \ ++ | STMFBIO_STD_WQFHD5660 \ ++ | STMFBIO_STD_WQFHD5650 \ ++ | STMFBIO_STD_QFHD5660 \ ++ | STMFBIO_STD_QFHD5650 \ ++ | STMFBIO_STD_QFHD1830 \ ++ | STMFBIO_STD_QFHD1825) ++ ++#define STMFBIO_STD_INTERLACED (STMFBIO_STD_525_60 \ ++ | STMFBIO_STD_625_50 \ ++ | STMFBIO_STD_1080I_60 \ ++ | STMFBIO_STD_1080I_59_94 \ ++ | STMFBIO_STD_1080I_50) ++ ++#define STMFBIO_STD_PROGRESSIVE (STMFBIO_STD_VGA_60 \ ++ | STMFBIO_STD_VGA_59_94 \ ++ | STMFBIO_STD_SMPTE293M \ ++ | STMFBIO_STD_1080P_60 \ ++ | STMFBIO_STD_1080P_59_94 \ ++ | STMFBIO_STD_1080P_50 \ ++ | STMFBIO_STD_1080P_23_976 \ ++ | STMFBIO_STD_1080P_24 \ ++ | STMFBIO_STD_1080P_25 \ ++ | STMFBIO_STD_1080P_29_97 \ ++ | STMFBIO_STD_1080P_30 \ ++ | STMFBIO_STD_SMPTE296M \ ++ | STMFBIO_STD_NTG5) ++ ++struct stmfbio_outputinfo ++{ ++ enum stmfbio_output_id outputid; ++ enum _stmfbio_activate activate; ++ enum stmfbio_output_standard standard; ++}; ++ ++struct stmfbio_outputstandards ++{ ++ enum stmfbio_output_id outputid; ++ enum stmfbio_output_standard all_standards; ++}; ++ ++struct stmfbio_plane_dimension { ++ __u32 w; ++ __u32 h; ++}; ++ ++struct stmfbio_plane_rect { ++ __u32 x; ++ __u32 y; ++ struct stmfbio_plane_dimension dim; ++}; ++ ++struct stmfbio_plane_config { ++ unsigned long baseaddr; ++ /* FIXME: the source API is incomplete! Should be updated to support a ++ real source 'viewport' inside a source surface. */ ++ struct stmfbio_plane_dimension source; /* resolution */ ++ struct stmfbio_plane_rect dest; ++ stm_pixel_format_t format; ++ __u32 pitch; /* desired pitch */ ++ ++ /* private */ ++ __u32 bitdepth; /* will be updated on successful return */ ++}; ++ ++struct stmfbio_planeinfo ++{ ++ __u32 layerid; /* must be 0 (for now) */ ++ enum _stmfbio_activate activate; ++ struct stmfbio_plane_config config; ++}; ++ ++struct stmfbio_plane_pan ++{ ++ __u32 layerid; /* must be 0 (for now) */ ++ enum _stmfbio_activate activate; ++ unsigned long baseaddr; ++}; ++ ++struct stmfbio_var_screeninfo_ex ++{ ++ /* ++ * Display layer to operate on, 0 is always the layer showing the framebuffer. ++ * No other layers have to be defined and the IOCTL will return ENODEV ++ * if given an invalid layerid. ++ */ ++ __u32 layerid; ++ __u32 caps; /* Valid entries in structure */ ++ __u32 failed; /* Indicates entries that failed during set */ ++ stmfbio_activate activate; ++ ++ /* ++ * STMFBIO_VAR_CAPS_COLOURKEY ++ */ ++ __u32 min_colour_key; ++ __u32 max_colour_key; ++ __u32 colourKeyFlags; ++ ++ stmfbio_ff_state ff_state; /* STMFBIO_VAR_CAPS_FLICKER_FILTER */ ++ ++ __u8 premultiplied_alpha; /* STMFBIO_VAR_CAPS_PREMULTIPLIED */ ++ __u8 rescale_colour_to_video_range; /* STBFBIO_VAR_CAPS_RESCALE_COLOUR_... */ ++ ++ __u8 opacity; /* STMFBIO_VAR_CAPS_OPACITY */ ++ __u8 gain; /* STMFBIO_VAR_CAPS_GAIN */ ++ __u8 brightness; /* STMFBIO_VAR_CAPS_BRIGHTNESS */ ++ __u8 saturation; /* STMFBIO_VAR_CAPS_SATURATION */ ++ __u8 contrast; /* STMFBIO_VAR_CAPS_CONTRAST */ ++ __u8 tint; /* STMFBIO_VAR_CAPS_HUE */ ++ __u8 alpha_ramp[2]; /* STMFBIO_CAR_CAPS_ALPHA_RAMP */ ++ ++ __u32 z_position; /* STMFBIO_VAR_CAPS_ZPOSITION */ ++}; ++ ++struct stmfbio_vps ++{ ++ __u8 vps_enable; ++ __u8 vps_data[6]; ++}; ++ ++/* ++ * Note: The standards are a bitfield in order to match the internal driver ++ * representation. Do not modify! ++ */ ++#define STMFBIO_OUTPUT_STD_PAL_BDGHI (1L<<0) ++#define STMFBIO_OUTPUT_STD_PAL_M (1L<<1) ++#define STMFBIO_OUTPUT_STD_PAL_N (1L<<2) ++#define STMFBIO_OUTPUT_STD_PAL_Nc (1L<<3) ++#define STMFBIO_OUTPUT_STD_NTSC_M (1L<<4) ++#define STMFBIO_OUTPUT_STD_NTSC_J (1L<<5) ++#define STMFBIO_OUTPUT_STD_NTSC_443 (1L<<6) ++#define STMFBIO_OUTPUT_STD_SECAM (1L<<7) ++#define STMFBIO_OUTPUT_STD_PAL_60 (1L<<8) ++ ++#define STMFBIO_OUTPUT_ANALOGUE_RGB (1L<<0) ++#define STMFBIO_OUTPUT_ANALOGUE_YPrPb (1L<<1) ++#define STMFBIO_OUTPUT_ANALOGUE_YC (1L<<2) ++#define STMFBIO_OUTPUT_ANALOGUE_CVBS (1L<<3) ++#define STMFBIO_OUTPUT_ANALOGUE_MASK (0xf) ++ ++#define STMFBIO_OUTPUT_ANALOGUE_CLIP_VIDEORANGE (0) ++#define STMFBIO_OUTPUT_ANALOGUE_CLIP_FULLRANGE (1L<<8) ++ ++#define STMFBIO_OUTPUT_ANALOGUE_COLORSPACE_AUTO (0) ++#define STMFBIO_OUTPUT_ANALOGUE_COLORSPACE_601 (1L<<9) ++#define STMFBIO_OUTPUT_ANALOGUE_COLORSPACE_709 (2L<<9) ++#define STMFBIO_OUTPUT_ANALOGUE_COLORSPACE_MASK (3L<<9) ++ ++ ++#define STMFBIO_OUTPUT_DVO_ENABLED (0) ++#define STMFBIO_OUTPUT_DVO_DISABLED (1L<<0) ++#define STMFBIO_OUTPUT_DVO_YUV_444_16BIT (0) ++#define STMFBIO_OUTPUT_DVO_YUV_444_24BIT (1L<<1) ++#define STMFBIO_OUTPUT_DVO_YUV_422_16BIT (2L<<1) ++#define STMFBIO_OUTPUT_DVO_ITUR656 (3L<<1) ++#define STMFBIO_OUTPUT_DVO_RGB_24BIT (4L<<1) ++#define STMFBIO_OUTPUT_DVO_MODE_MASK (7L<<1) ++ ++#define STMFBIO_OUTPUT_DVO_CLIP_VIDEORANGE (0) ++#define STMFBIO_OUTPUT_DVO_CLIP_FULLRANGE (1L<<8) ++#define STMFBIO_OUTPUT_DVO_CHROMA_FILTER_DISABLED (0) ++#define STMFBIO_OUTPUT_DVO_CHROMA_FILTER_ENABLED (1L<<9) ++ ++#define STMFBIO_OUTPUT_HDMI_ENABLED (0) ++#define STMFBIO_OUTPUT_HDMI_DISABLED (1L<<0) ++#define STMFBIO_OUTPUT_HDMI_RGB (0) ++#define STMFBIO_OUTPUT_HDMI_YUV (1L<<1) ++#define STMFBIO_OUTPUT_HDMI_444 (0) ++#define STMFBIO_OUTPUT_HDMI_422 (1L<<2) ++#define STMFBIO_OUTPUT_HDMI_COLOURDEPTH_SHIFT (3) ++#define STMFBIO_OUTPUT_HDMI_COLOURDEPTH_24BIT (0) ++#define STMFBIO_OUTPUT_HDMI_COLOURDEPTH_30BIT (1L< and should not be changed. ++ */ ++ ++/* ++ * The picture aspect ratio indicates the intended aspect ratio ++ * of the full content of a 720x480 or 720x576 picture being ++ * displayed on an SD/ED display, i.e. it is indicating the pixel aspect ratio ++ * of the image. It does not necessarily indicate (but in all probability is the ++ * same as) the aspect ratio of the display. ++ * ++ * HD pictures always have a pixel aspect ratio of 1:1, hence the picture ++ * aspect ratio should always match the display size ratio i.e. 16:9. ++ */ ++#define STMFBIO_PIC_PICTURE_ASPECT_UNKNOWN (0) ++#define STMFBIO_PIC_PICTURE_ASPECT_4_3 (1) ++#define STMFBIO_PIC_PICTURE_ASPECT_16_9 (2) ++ ++/* ++ * The video aspect indicates the actual aspect ratio of video contained in ++ * the picture on the display. ++ */ ++#define STMFBIO_PIC_VIDEO_ASPECT_UNKNOWN (0) ++#define STMFBIO_PIC_VIDEO_ASPECT_4_3 (1) ++#define STMFBIO_PIC_VIDEO_ASPECT_16_9 (2) ++#define STMFBIO_PIC_VIDEO_ASPECT_14_9 (3) ++#define STMFBIO_PIC_VIDEO_ASPECT_GT_16_9 (4) ++ ++/* ++ * When the picture aspect ratio and video aspect ratio do not match then ++ * the letterbox style indicates how the video is positioned inside the picture. ++ * See CEA-861 Annex H, or standards for analogue video VBI signals ++ * for details. ++ */ ++#define STMFBIO_PIC_LETTERBOX_NONE (0) ++#define STMFBIO_PIC_LETTERBOX_CENTER (1) ++#define STMFBIO_PIC_LETTERBOX_TOP (2) ++#define STMFBIO_PIC_LETTERBOX_SAP_14_9 (3) ++#define STMFBIO_PIC_LETTERBOX_SAP_4_3 (4) ++ ++#define STMFBIO_PIC_RESCALE_NONE (0) ++#define STMFBIO_PIC_RESCALE_HORIZONTAL (1) ++#define STMFBIO_PIC_RESCALE_VERTICAL (2) ++#define STMFBIO_PIC_RESCALE_BOTH (3) ++ ++#define STMFBIO_PIC_BAR_DISABLE (0) ++#define STMFBIO_PIC_BAR_ENABLE (1) ++ ++#define STMFBIO_PICTURE_FLAGS_PICUTRE_ASPECT (1L<<0) ++#define STMFBIO_PICTURE_FLAGS_VIDEO_ASPECT (1L<<1) ++#define STMFBIO_PICTURE_FLAGS_LETTERBOX (1L<<2) ++#define STMFBIO_PICTURE_FLAGS_RESCALE_INFO (1L<<3) ++#define STMFBIO_PICTURE_FLAGS_BAR_INFO (1L<<4) ++#define STMFBIO_PICTURE_FLAGS_BAR_INFO_ENABLE (1L<<5) ++ ++struct stmfbio_picture_configuration ++{ ++ /* Which fields in the structure should be changed */ ++ __u32 flags; ++ ++ /* ++ * {0,0} = immediate, otherwise this should be a time in the ++ * future based on clock_gettime(CLOCK_MONOTONIC,...), not gettimeofday() ++ */ ++ struct timeval timestamp; ++ ++ __u16 picture_aspect; ++ __u16 video_aspect; ++ __u16 letterbox_style; ++ ++ /* Indicate if the displayed image (usually video) has been rescaled */ ++ __u16 picture_rescale; ++ ++ /* ++ * Black bar information, in pixels/lines from the start of the active video ++ * area. The enable allows bar information to be switched on/off without ++ * changing the actual bar data. ++ */ ++ __u16 bar_enable; ++ __u16 top_bar_end; ++ __u16 bottom_bar_start; ++ __u16 left_bar_end; ++ __u16 right_bar_start; ++}; ++ ++ ++struct stmfbio_auxmem2 ++{ ++ __u32 index; ++ __u32 physical; ++ __u32 size; ++}; ++ ++ ++typedef enum stmfbio_3d_mode ++{ ++ /* No 3D i.e. 2D */ ++ STMFBIO_3D_NONE, ++ /* Sub-sampled 3D formats in a normal 2D frame */ ++ STMFBIO_3D_SBS_HALF, ++ STMFBIO_3D_TOP_BOTTOM, ++ /* Full frame 3D formats, double clocked */ ++ STMFBIO_3D_FRAME_PACKED, ++ STMFBIO_3D_FIELD_ALTERNATIVE, ++ /* TV panel specific 3D modes */ ++ STMFBIO_3D_FRAME_SEQUENTIAL, ++ STMFBIO_3D_LL_RR, ++ STMFBIO_LINE_ALTERNATIVE ++} stmfbio_3d_mode; ++ ++ ++enum stmfbio_3d_framebuffer_type ++{ ++ STMFBIO_3D_FB_MONO, /* Single 2D framebuffer (or packed 3D SbS Half/TopBottom) */ ++ STMFBIO_3D_FB_STEREO /* Stereo 3D framebuffer for framepacked/sequential style modes */ ++}; ++ ++ ++struct stmfbio_3d_configuration ++{ ++ enum stmfbio_output_id outputid; ++ enum _stmfbio_activate activate; ++ enum stmfbio_3d_mode mode; ++ enum stmfbio_3d_framebuffer_type framebuffer_type; ++ __s8 framebuffer_depth; ++}; ++ ++ ++/* ++ * non-standard ioctls to control the FB plane, although ++ * these can be used directly they are really provided for the DirectFB ++ * driver ++ */ ++#define STMFBIO_GET_OUTPUTSTANDARDS _IOWR('B', 0x10, struct stmfbio_outputstandards) ++#define STMFBIO_GET_OUTPUTINFO _IOWR('B', 0x11, struct stmfbio_outputinfo) ++#define STMFBIO_SET_OUTPUTINFO _IOWR('B', 0x12, struct stmfbio_outputinfo) ++#define STMFBIO_GET_PLANEMODE _IOWR('B', 0x11, struct stmfbio_planeinfo) ++#define STMFBIO_SET_PLANEMODE _IOW ('B', 0x12, struct stmfbio_planeinfo) ++#define STMFBIO_PAN_PLANE _IOW ('B', 0x10, struct stmfbio_planeinfo) ++ ++#define STMFBIO_GET_VAR_SCREENINFO_EX _IOR ('B', 0x12, struct stmfbio_var_screeninfo_ex) ++#define STMFBIO_SET_VAR_SCREENINFO_EX _IOWR('B', 0x13, struct stmfbio_var_screeninfo_ex) ++#define STMFBIO_GET_OUTPUT_CONFIG _IOR ('B', 0x14, struct stmfbio_output_configuration) ++#define STMFBIO_SET_OUTPUT_CONFIG _IOWR('B', 0x15, struct stmfbio_output_configuration) ++#define STMFBIO_GET_3D_CONFIG _IOWR('B', 0x20, struct stmfbio_3d_configuration) ++#define STMFBIO_SET_3D_CONFIG _IOW ('B', 0x21, struct stmfbio_3d_configuration) ++ ++#define STMFBIO_SET_PICTURE_CONFIG _IOWR('B', 0x16, struct stmfbio_picture_configuration) ++#define STMFBIO_GET_AUXMEMORY2 _IOWR('B', 0x17, struct stmfbio_auxmem2) ++ ++#define STMFBIO_SET_DAC_HD_POWER _IO ('B', 0xd) ++#define STMFBIO_SET_CGMS_ANALOG _IO ('B', 0xe) ++#define STMFBIO_SET_DAC_HD_FILTER _IO ('B', 0xf) ++#define STMFBIO_SET_VPS_ANALOG _IOW ('B', 0x1f, struct stmfbio_vps) ++ ++/* ++ * Implement the matrox FB extension for VSync synchronisation, again for ++ * DirectFB. ++ */ ++#ifndef FBIO_WAITFORVSYNC ++#define FBIO_WAITFORVSYNC _IOW('F', 0x20, u_int32_t) ++#endif ++ ++/* ++ * Implement panel configuration ++ */ ++ ++#define PANEL_IO ++ ++#ifdef PANEL_IO ++#define STMFBIO_SET_PANEL_CONFIG _IOWR('B', 0x18, struct stmfbio_panel_config) ++ ++typedef enum ++{ ++ STMFB_PANEL_DITHER_METHOD_NONE, ++ STMFB_PANEL_DITHER_METHOD_TRUNC, ++ STMFB_PANEL_DITHER_METHOD_ROUND, ++ STMFB_PANEL_DITHER_METHOD_RANDOM, ++ STMFB_PANEL_DITHER_METHOD_SPATIAL, ++}stmfbio_display_panel_dither_mode; ++ ++typedef enum ++{ ++ STMFB_PANEL_FREERUN, ++ STMFB_PANEL_FIXED_FRAME_LOCK, ++ STMFB_PANEL_DYNAMIC_FRAME_LOCK, ++ STMFB_PANEL_LOCK_LOAD, ++}stmfbio_display_panel_lock_method; ++ ++typedef enum stmfbio_display_panel_lvds_bus_width_select_e ++{ ++ STMFBIO_PANEL_LVDS_SINGLE, ++ STMFBIO_PANEL_LVDS_DUAL, ++ STMFBIO_PANEL_LVDS_QUAD, ++} stmfbio_display_panel_lvds_bus_width_select_t; ++ ++ ++typedef enum stmfbio_display_panel_lvds_bus_swap_e ++{ ++ STMFBIO_PANEL_LVDS_SWAP_AB = 1, ++ STMFBIO_PANEL_LVDS_SWAP_CD = 2, ++ STMFBIO_PANEL_LVDS_SWAP_AB_CD = 3 ++} stmfbio_display_panel_lvds_bus_swap_t; ++ ++ ++typedef enum stmfbio_display_panel_lvds_pair_swap_e ++{ ++ STMFBIO_PANEL_LVDS_SWAP_PAIR0_PN = (1L<<0), ++ STMFBIO_PANEL_LVDS_SWAP_PAIR1_PN = (1L<<1), ++ STMFBIO_PANEL_LVDS_SWAP_PAIR2_PN = (1L<<2), ++ STMFBIO_PANEL_LVDS_SWAP_PAIR3_PN = (1L<<3), ++ STMFBIO_PANEL_LVDS_SWAP_PAIR4_PN = (1L<<4), ++ STMFBIO_PANEL_LVDS_SWAP_PAIR5_PN = (1L<<5), ++ STMFBIO_PANEL_LVDS_SWAP_CLOCK_PN = (1L<<6), ++} stmfbio_display_panel_lvds_pair_swap_t; ++ ++ ++typedef struct stmfbio_display_panel_lvds_ch_swap_config_s ++{ ++ stmfbio_display_panel_lvds_bus_swap_t swap_options; ++ stmfbio_display_panel_lvds_pair_swap_t pair_swap_ch_a; ++ stmfbio_display_panel_lvds_pair_swap_t pair_swap_ch_b; ++ stmfbio_display_panel_lvds_pair_swap_t pair_swap_ch_c; ++ stmfbio_display_panel_lvds_pair_swap_t pair_swap_ch_d; ++}stmfbio_display_panel_lvds_ch_swap_config_t; ++ ++ ++typedef struct stmfbio_display_panel_lvds_signal_pol_config_s ++{ ++ __u8 hs_pol; /*!< hsync polarity */ ++ __u8 vs_pol; /*!< vsync polarity */ ++ __u8 de_pol; /*!< data enable polarity */ ++ __u8 odd_pol; /*!< odd not even field polarity */ ++} stmfbio_display_panel_lvds_signal_pol_config_t; ++ ++ ++typedef enum stmfbio_display_panel_lvds_map_e ++{ ++ STMFBIO_PANEL_LVDS_MAP_STANDARD1, ++ STMFBIO_PANEL_LVDS_MAP_STANDARD2, ++ STMFBIO_PANEL_LVDS_MAP_CUSTOM ++} stmfbio_display_panel_lvds_map_t; ++ ++ ++typedef enum stmfbio_display_lvds_common_mode_voltage_e ++{ ++ STMFBIO_PANEL_LVDS_1_25V, /*!< 1.25v */ ++ STMFBIO_PANEL_LVDS_1_10V, /*!< 1.10v */ ++ STMFBIO_PANEL_LVDS_1_35V /*!< 1.35v */ ++}stmfbio_display_lvds_common_mode_voltage_t; ++ ++ ++typedef enum stmfbio_display_lvds_bias_current_e ++{ ++ STMFBIO_PANEL_LVDS_0_5_MA, /*!< 0.5 mA */ ++ STMFBIO_PANEL_LVDS_1_0_MA, /*!< 1.0 mA */ ++ STMFBIO_PANEL_LVDS_1_5_MA, /*!< 1.5 mA */ ++ STMFBIO_PANEL_LVDS_2_0_MA, /*!< 2.0 mA */ ++ STMFBIO_PANEL_LVDS_2_5_MA, /*!< 2.5 mA */ ++ STMFBIO_PANEL_LVDS_3_0_MA, /*!< 3.0 mA */ ++ STMFBIO_PANEL_LVDS_3_5_MA, /*!< 3.5 mA */ ++ STMFBIO_PANEL_LVDS_4_0_MA /*!< 4.0 mA */ ++}stmfbio_display_lvds_bias_current_t; ++ ++ ++typedef struct stmfbio_display_panel_lvds_bias_control_s ++{ ++ stmfbio_display_lvds_common_mode_voltage_t common_mode_voltage; ++ stmfbio_display_lvds_bias_current_t bias_current; ++} stmfbio_display_panel_lvds_bias_control_t; ++ ++ ++typedef struct stmfbio_display_panel_lvds_config_s ++{ ++ stmfbio_display_panel_lvds_bus_width_select_t lvds_bus_width_sel; ++ stmfbio_display_panel_lvds_ch_swap_config_t swap_options; ++ stmfbio_display_panel_lvds_signal_pol_config_t signal_polarity; ++ stmfbio_display_panel_lvds_map_t lvds_signal_map; ++ __u32 custom_lvds_map[8]; ++ __u16 clock_data_adj; ++ stmfbio_display_panel_lvds_bias_control_t bias_control_value; ++} stmfbio_display_panel_lvds_config_t; ++ ++struct stmfbio_panel_config ++{ ++ __u32 lookup_table1_p; ++ __u32 lookup_table2_p; ++ __u32 linear_color_remap_table_p; ++ __u32 vertical_refresh_rate; /*!< Vertical refresh rate in mHz */ ++ __u32 active_area_width; /*!< */ ++ __u32 active_area_height; /*!< */ ++ __u32 active_area_start_pixel; /*!< Pixels are counted from 0 */ ++ __u32 active_area_start_line; /*!< Lines are counted from 1, starting ++ with the first vsync blanking line */ ++ __u32 pixels_per_line; /*!< Total number of pixels per line ++ including the blanking area */ ++ __u32 lines_per_frame; /*!< Total number of lines per progressive ++ frame or pair of interlaced fields ++ including the blanking area */ ++ __u32 pixel_clock_freq; /*!< In Hz, e.g. 27000000 (27MHz) */ ++ __u32 hsync_width; /*!< */ ++ __u32 vsync_width; /*!< */ ++ stmfbio_display_panel_dither_mode dither; ++ stmfbio_display_panel_lock_method lock_method; ++ __u16 pwr_to_de_delay_during_power_on; ++ __u16 de_to_bklt_on_delay_during_power_on; ++ __u16 bklt_to_de_off_delay_during_power_off; ++ __u16 de_to_pwr_delay_during_power_off; ++ __u8 enable_lut1; ++ __u8 enable_lut2; ++ __u8 afr_enable; ++ __u8 is_half_display_clock; ++ __u8 hsync_polarity; /*!< 0: Negative 1: Positive */ ++ __u8 vsync_polarity; /*!< 0: Negative 1: Positive */ ++// stmfbio_display_panel_lvds_config_t lvds_config; ++}; ++#endif ++ ++#endif /* _STMFB_H */ +diff --git a/systems/stmfbdev/stmfb_aux_surface_pool.c b/systems/stmfbdev/stmfb_aux_surface_pool.c +new file mode 100644 +index 0000000..9ec6e5d +--- /dev/null ++++ b/systems/stmfbdev/stmfb_aux_surface_pool.c +@@ -0,0 +1,675 @@ ++/* ++ ST Microelectronics system driver - surface pool memory (auxmem) ++ ++ (c) Copyright 2009-2012 STMicroelectronics Ltd. ++ ++ Written by André Draszik ++ ++ This library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2 of the License, or (at your option) any later version. ++ ++ This library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with this library; if not, write to the ++ Free Software Foundation, Inc., 59 Temple Place - Suite 330, ++ Boston, MA 02111-1307, USA. ++*/ ++ ++#include ++ ++#include ++#include ++#include ++ ++#include ++ ++#include ++#include ++ ++#include ++#include ++ ++#include ++ ++#include ++ ++#include "stmfbdev.h" ++#include "surfacemanager.h" ++ ++#include ++#include "stmfb_aux_surface_pool.h" ++ ++#include ++#include ++ ++D_DEBUG_DOMAIN (STMfbdev_Surfaces_Aux, "STMfbdev/Surfaces/Aux", "STMfb Aux Surface Pool"); ++D_DEBUG_DOMAIN (STMfbdev_SurfLock_Aux, "STMfbdev/SurfLock/Aux", "STMfb Aux Surface Pool Locks"); ++ ++/****************************************************************************/ ++ ++typedef struct ++{ ++ int magic; ++ ++ SurfaceManager *manager; ++ ++ unsigned long part_base; ++ unsigned int aux_part; ++} STMFB_AuxSurfacePoolData; ++ ++typedef struct ++{ ++ int magic; ++ ++ CoreDFB *core; ++ void *mem; ++} STMFB_AuxSurfacePoolLocalData; ++ ++typedef struct ++{ ++ int magic; ++ ++ Chunk *chunk; ++} STMFB_AuxSurfacePoolAllocationData; ++ ++/****************************************************************************/ ++ ++static int ++stmfb_aux_PoolDataSize (void) ++{ ++ return sizeof (STMFB_AuxSurfacePoolData); ++} ++ ++static int ++stmfb_aux_PoolLocalDataSize (void) ++{ ++ return sizeof (STMFB_AuxSurfacePoolLocalData); ++} ++ ++static int ++stmfb_aux_AllocationDataSize (void) ++{ ++ return sizeof (STMFB_AuxSurfacePoolAllocationData); ++} ++ ++static DFBResult ++stmfb_aux_LeavePool (CoreSurfacePool *pool, ++ void *pool_data, ++ void *pool_local) ++{ ++ STMFB_AuxSurfacePoolData * const data = pool_data; ++ STMFB_AuxSurfacePoolLocalData * const local = pool_local; ++ ++ D_DEBUG_AT (STMfbdev_Surfaces_Aux, "%s (%d)\n", __func__, data->aux_part); ++ ++ D_MAGIC_ASSERT (pool, CoreSurfacePool); ++ D_MAGIC_ASSERT (data, STMFB_AuxSurfacePoolData); ++ D_MAGIC_ASSERT (local, STMFB_AuxSurfacePoolLocalData); ++ ++ D_UNUSED_P (data); ++ ++ if (local->mem && local->mem != MAP_FAILED) ++ { ++ munmap (local->mem, pool->desc.size); ++ local->mem = NULL; ++ } ++ ++ D_MAGIC_CLEAR (local); ++ ++ return DFB_OK; ++} ++ ++static DFBResult ++stmfb_aux_JoinPool (CoreDFB *core, ++ CoreSurfacePool *pool, ++ void *pool_data, ++ void *pool_local, ++ void *system_data) ++{ ++ STMFB_AuxSurfacePoolData * const data = pool_data; ++ STMFB_AuxSurfacePoolLocalData * const local = pool_local; ++ STMfbdev * const stmfbdev = dfb_system_data (); ++ ++ D_DEBUG_AT (STMfbdev_Surfaces_Aux, "%s (%d)\n", __func__, data->aux_part); ++ ++ D_ASSERT (core != NULL); ++ D_MAGIC_ASSERT (pool, CoreSurfacePool); ++ D_MAGIC_ASSERT (data, STMFB_AuxSurfacePoolData); ++ D_ASSERT (local != NULL); ++ ++ D_MAGIC_SET (local, STMFB_AuxSurfacePoolLocalData); ++ ++ local->mem = mmap (NULL, pool->desc.size, PROT_READ | PROT_WRITE, ++ MAP_SHARED, stmfbdev->fd, data->part_base); ++ if (local->mem == MAP_FAILED) ++ { ++ D_PERROR ("STMfbdev/Surfaces/Aux: Could not mmap gfx part %d!\n", ++ data->aux_part); ++ return DFB_INIT; ++ } ++ ++ local->core = core; ++ ++ return DFB_OK; ++} ++ ++static DFBResult ++stmfb_aux_DestroyPool (CoreSurfacePool *pool, ++ void *pool_data, ++ void *pool_local) ++{ ++ STMFB_AuxSurfacePoolData * const data = pool_data; ++ STMFB_AuxSurfacePoolLocalData * const local = pool_local; ++ ++ D_DEBUG_AT (STMfbdev_Surfaces_Aux, "%s (%d)\n", __func__, data->aux_part); ++ ++ D_MAGIC_ASSERT (pool, CoreSurfacePool); ++ D_MAGIC_ASSERT (data, STMFB_AuxSurfacePoolData); ++ D_MAGIC_ASSERT (local, STMFB_AuxSurfacePoolLocalData); ++ ++ D_UNUSED_P (local); ++ ++ stmfb_aux_LeavePool (pool, pool_data, pool_local); ++ ++ dfb_surfacemanager_destroy (data->manager); ++ ++ D_MAGIC_CLEAR (data); ++ ++ return DFB_OK; ++} ++ ++static DFBResult ++stmfb_aux_InitPool (CoreDFB *core, ++ CoreSurfacePool *pool, ++ void *pool_data, ++ void *pool_local, ++ void *system_data, ++ CoreSurfacePoolDescription *ret_desc) ++{ ++ DFBResult ret; ++ STMFB_AuxSurfacePoolData * const data = pool_data; ++ STMFB_AuxSurfacePoolLocalData * const local = pool_local; ++ const STMfbdev * const stmfbdev = dfb_system_data (); ++ struct stmfbio_auxmem2 auxmem; ++ ++ D_DEBUG_AT (STMfbdev_Surfaces_Aux, "%s (%d)\n", __func__, ++ stmfbdev->shared->aux_pool_index); ++ ++ D_ASSERT (core != NULL); ++ D_MAGIC_ASSERT (pool, CoreSurfacePool); ++ D_ASSERT (data != NULL); ++ D_ASSERT (local != NULL); ++ D_ASSERT (ret_desc != NULL); ++ ++ D_UNUSED_P (local); ++ ++ D_MAGIC_SET (data, STMFB_AuxSurfacePoolData); ++ ++ auxmem.index = stmfbdev->shared->aux_pool_index; ++ ++ snprintf (ret_desc->name, DFB_SURFACE_POOL_DESC_NAME_LENGTH, ++ "STMFB AuxMemory %d", auxmem.index); ++ ++ /* query auxmem */ ++ if (ioctl (stmfbdev->fd, STMFBIO_GET_AUXMEMORY2, &auxmem) != 0) ++ return DFB_IO; ++ ++ if (!auxmem.size) ++ return DFB_ITEMNOTFOUND; ++ ++ D_INFO ("STMfbdev/Surfaces/Aux: found auxmem @ %.8x (%ukB)!\n", ++ auxmem.physical, auxmem.size / 1024); ++ /* auxmem partitions will never cross a 64MB boundary, stmfb should make ++ sure that's the case. And it does in fact :-), which is why we don't need ++ to check for configuration errors. */ ++ ++ ret = dfb_surfacemanager_create (core, auxmem.size, &data->manager); ++ if (ret) ++ return ret; ++ ++ data->aux_part = auxmem.index; ++ data->part_base = auxmem.physical; ++ ++ ret_desc->caps = CSPCAPS_PHYSICAL | CSPCAPS_VIRTUAL; ++ ret_desc->access[CSAID_CPU] = CSAF_READ | CSAF_WRITE | CSAF_SHARED; ++ ret_desc->access[CSAID_GPU] = CSAF_READ | CSAF_WRITE | CSAF_SHARED; ++ ret_desc->types = (0 ++ | CSTF_WINDOW | CSTF_CURSOR | CSTF_FONT ++ | CSTF_SHARED | CSTF_EXTERNAL ++ | CSTF_BUFFEROBJECT ++ ); ++ ret_desc->priority = CSPP_PREFERED; ++ ret_desc->size = auxmem.size; ++ ++ /* other accelerators */ ++ ret_desc->access[CSAID_ACCEL0] = CSAF_READ | CSAF_WRITE; ++ ret_desc->access[CSAID_ACCEL1] = CSAF_READ | CSAF_WRITE; ++ ret_desc->access[CSAID_ACCEL2] = CSAF_READ | CSAF_WRITE; ++ ret_desc->access[CSAID_ACCEL3] = CSAF_READ | CSAF_WRITE; ++ ret_desc->access[CSAID_ACCEL4] = CSAF_READ | CSAF_WRITE; ++ ret_desc->access[CSAID_ACCEL5] = CSAF_READ | CSAF_WRITE; ++ ++#if 0 ++ /* FIXME: this depends on the hardware, but we have no interface at the ++ moment anyway... */ ++ ret_desc->access[CSAID_LAYER0] = CSAF_READ; ++ ret_desc->access[CSAID_LAYER1] = CSAF_READ; ++ ret_desc->access[CSAID_LAYER2] = CSAF_READ; ++ ret_desc->access[CSAID_LAYER3] = CSAF_READ; ++ ret_desc->access[CSAID_LAYER4] = CSAF_READ; ++ ret_desc->access[CSAID_LAYER5] = CSAF_READ; ++ ret_desc->access[CSAID_LAYER6] = CSAF_READ; ++ ret_desc->access[CSAID_LAYER7] = CSAF_READ; ++ ret_desc->access[CSAID_LAYER8] = CSAF_READ; ++ ret_desc->access[CSAID_LAYER9] = CSAF_READ; ++ ret_desc->access[CSAID_LAYER10] = CSAF_READ; ++ ret_desc->access[CSAID_LAYER11] = CSAF_READ; ++ ret_desc->access[CSAID_LAYER12] = CSAF_READ; ++ ret_desc->access[CSAID_LAYER13] = CSAF_READ; ++ ret_desc->access[CSAID_LAYER14] = CSAF_READ; ++ ret_desc->access[CSAID_LAYER15] = CSAF_READ; ++#endif ++ ++ ret = stmfb_aux_JoinPool (core, pool, pool_data, pool_local, system_data); ++ if (ret) ++ { ++ stmfb_aux_DestroyPool (pool, pool_data, pool_local); ++ return ret; ++ } ++ ++ return DFB_OK; ++} ++ ++static DFBResult ++stmfb_aux_TestConfig (CoreSurfacePool *pool, ++ void *pool_data, ++ void *pool_local, ++ CoreSurfaceBuffer *buffer, ++ const CoreSurfaceConfig *config) ++{ ++ CoreSurface *surface; ++ STMFB_AuxSurfacePoolData * const data = pool_data; ++ STMFB_AuxSurfacePoolLocalData * const local = pool_local; ++ DFBResult ret; ++ ++ D_MAGIC_ASSERT (pool, CoreSurfacePool); ++ D_MAGIC_ASSERT (data, STMFB_AuxSurfacePoolData); ++ D_MAGIC_ASSERT (local, STMFB_AuxSurfacePoolLocalData); ++ D_MAGIC_ASSERT (buffer, CoreSurfaceBuffer); ++ D_ASSERT (config != NULL); ++ ++ surface = buffer->surface; ++ D_MAGIC_ASSERT (surface, CoreSurface); ++ ++ D_DEBUG_AT (STMfbdev_Surfaces_Aux, ++ "%s (part/buffer/type/id: %u/%p/0x%x/%lu)\n", ++ __func__, data->aux_part, buffer, ++ surface->type, surface->resource_id); ++ ++ /* FIXME: this depends on the hardware, but we have no interface at the ++ moment anyway... */ ++ if (surface->type & CSTF_LAYER) ++ return DFB_BUG; ++ ++ ret = dfb_surfacemanager_allocate (local->core, data->manager, ++ buffer, NULL, NULL, false); ++ ++ D_DEBUG_AT (STMfbdev_Surfaces_Aux, " -> %s\n", DirectFBErrorString (ret)); ++ ++ return ret; ++} ++ ++static DFBResult ++stmfb_aux_AllocateBuffer (CoreSurfacePool *pool, ++ void *pool_data, ++ void *pool_local, ++ CoreSurfaceBuffer *buffer, ++ CoreSurfaceAllocation *allocation, ++ void *alloc_data) ++{ ++ CoreSurface *surface; ++ STMFB_AuxSurfacePoolData * const data = pool_data; ++ STMFB_AuxSurfacePoolLocalData * const local = pool_local; ++ STMFB_AuxSurfacePoolAllocationData * const alloc = alloc_data; ++ DFBResult ret; ++ Chunk *chunk; ++ ++ D_DEBUG_AT (STMfbdev_Surfaces_Aux, "%s (%d, %p)\n", __func__, ++ data->aux_part, buffer); ++ ++ D_MAGIC_ASSERT (pool, CoreSurfacePool); ++ D_MAGIC_ASSERT (data, STMFB_AuxSurfacePoolData); ++ D_MAGIC_ASSERT (local, STMFB_AuxSurfacePoolLocalData); ++ D_MAGIC_ASSERT (buffer, CoreSurfaceBuffer); ++ D_MAGIC_ASSERT (allocation, CoreSurfaceAllocation); ++ ++ surface = buffer->surface; ++ D_MAGIC_ASSERT (surface, CoreSurface); ++ ++ /* FIXME: this depends on the hardware, but we have no interface at the ++ moment anyway... */ ++ if (surface->type & CSTF_LAYER) ++ return DFB_BUG; ++ ++ ret = dfb_surfacemanager_allocate (local->core, data->manager, buffer, ++ allocation, &chunk, false); ++ if (ret) ++ return ret; ++ ++ D_MAGIC_ASSERT (chunk, Chunk); ++ ++ alloc->chunk = chunk; ++ ++ D_DEBUG_AT (STMfbdev_Surfaces_Aux, ++ " -> offset 0x%.8x (%u), format: %s, pitch %d, size %d\n", ++ chunk->offset, chunk->offset, ++ dfb_pixelformat_name (buffer->format), chunk->pitch, ++ chunk->length); ++ ++ allocation->size = chunk->length; ++ allocation->offset = chunk->offset; ++ ++#if STGFX_DRIVER == 2 ++ if (unlikely (buffer->format == DSPF_RGB32)) ++ { ++ /* for RGB32, we need to set the alpha to 0xff */ ++ /* FIXME: check if we can hook into dfb_gfx_clear() or ++ dfb_surface_clear_buffers() */ ++ STGFX2DriverData * const stdrv = dfb_gfxcard_get_driver_data (); ++ STGFX2DeviceData * const stdev = dfb_gfxcard_get_device_data (); ++ DFBRectangle rect = { .x = 0, .y = 0, ++ .w = buffer->surface->config.size.w, ++ .h = buffer->surface->config.size.h }; ++ ++ D_DEBUG_AT (STMfbdev_Surfaces_Aux, " -> rgb32 allocation!\n"); ++ ++ D_WARN ("STMfbdev/Surfaces/Aux: RGB32 support is experimental and slow!"); ++ ++ dfb_gfxcard_lock (GDLF_WAIT); ++ ++ _bdisp_aq_RGB32_init (stdrv, stdev, ++ data->part_base + chunk->offset, chunk->pitch, ++ &rect); ++ dfb_gfxcard_unlock (); ++ } ++#endif ++ ++ D_MAGIC_SET (alloc, STMFB_AuxSurfacePoolAllocationData); ++ ++ return DFB_OK; ++} ++ ++static DFBResult ++stmfb_aux_DeallocateBuffer (CoreSurfacePool *pool, ++ void *pool_data, ++ void *pool_local, ++ CoreSurfaceBuffer *buffer, ++ CoreSurfaceAllocation *allocation, ++ void *alloc_data) ++{ ++ STMFB_AuxSurfacePoolData * const data = pool_data; ++ const STMFB_AuxSurfacePoolLocalData * const local = pool_local; ++ STMFB_AuxSurfacePoolAllocationData * const alloc = alloc_data; ++ ++ D_DEBUG_AT (STMfbdev_Surfaces_Aux, "%s (%d, %p)\n", __func__, ++ data->aux_part, buffer); ++ ++ D_MAGIC_ASSERT (pool, CoreSurfacePool); ++ D_MAGIC_ASSERT (data, STMFB_AuxSurfacePoolData); ++ D_MAGIC_ASSERT (local, STMFB_AuxSurfacePoolLocalData); ++ D_MAGIC_ASSERT (allocation, CoreSurfaceAllocation); ++ D_MAGIC_ASSERT (alloc, STMFB_AuxSurfacePoolAllocationData); ++ ++ (void) local; ++ ++ D_ASSERT (alloc->chunk != NULL); ++ dfb_surfacemanager_deallocate (data->manager, alloc->chunk); ++ ++ D_MAGIC_CLEAR (alloc); ++ ++ return DFB_OK; ++} ++ ++static DFBResult ++stmfb_aux_MuckOut (CoreSurfacePool *pool, ++ void *pool_data, ++ void *pool_local, ++ CoreSurfaceBuffer *buffer ) ++{ ++ STMFB_AuxSurfacePoolData * const data = pool_data; ++ const STMFB_AuxSurfacePoolLocalData * const local = pool_local; ++ ++ D_DEBUG_AT (STMfbdev_Surfaces_Aux, "%s (%p)\n", __func__, buffer); ++ ++ D_MAGIC_ASSERT (pool, CoreSurfacePool); ++ D_MAGIC_ASSERT (data, STMFB_AuxSurfacePoolData); ++ D_MAGIC_ASSERT (local, STMFB_AuxSurfacePoolLocalData); ++ D_MAGIC_ASSERT (buffer, CoreSurfaceBuffer); ++ ++ return dfb_surfacemanager_displace (local->core, data->manager, buffer); ++} ++ ++static DFBResult ++stmfb_aux_Lock (CoreSurfacePool *pool, ++ void *pool_data, ++ void *pool_local, ++ CoreSurfaceAllocation *allocation, ++ void *alloc_data, ++ CoreSurfaceBufferLock *lock) ++{ ++ const STMFB_AuxSurfacePoolData * const data = pool_data; ++ const STMFB_AuxSurfacePoolLocalData * const local = pool_local; ++ const STMFB_AuxSurfacePoolAllocationData * const alloc = alloc_data; ++ const Chunk *chunk; ++ ++ D_MAGIC_ASSERT (pool, CoreSurfacePool); ++ D_MAGIC_ASSERT (data, STMFB_AuxSurfacePoolData); ++ D_MAGIC_ASSERT (local, STMFB_AuxSurfacePoolLocalData); ++ D_MAGIC_ASSERT (allocation, CoreSurfaceAllocation); ++ D_MAGIC_ASSERT (alloc, STMFB_AuxSurfacePoolAllocationData); ++ D_MAGIC_ASSERT (lock, CoreSurfaceBufferLock); ++ ++ D_DEBUG_AT (STMfbdev_SurfLock_Aux, "%s (%d, %p)\n", __func__, ++ data->aux_part, lock->buffer); ++ ++ D_MAGIC_ASSERT (alloc->chunk, Chunk); ++ chunk = alloc->chunk; ++ ++ lock->pitch = chunk->pitch; ++ lock->offset = chunk->offset; ++ lock->addr = local->mem + chunk->offset; ++ lock->phys = data->part_base + chunk->offset; ++ ++ D_DEBUG_AT (STMfbdev_SurfLock_Aux, ++ " -> offset 0x%.8lx (%lu), pitch %d, addr %p, phys 0x%.8lx\n", ++ lock->offset, lock->offset, lock->pitch, lock->addr, lock->phys); ++ ++ return DFB_OK; ++} ++ ++static DFBResult ++stmfb_aux_Unlock (CoreSurfacePool *pool, ++ void *pool_data, ++ void *pool_local, ++ CoreSurfaceAllocation *allocation, ++ void *alloc_data, ++ CoreSurfaceBufferLock *lock) ++{ ++ const STMFB_AuxSurfacePoolData * const data = pool_data; ++ const STMFB_AuxSurfacePoolLocalData * const local = pool_local; ++ const STMFB_AuxSurfacePoolAllocationData * const alloc = alloc_data; ++ ++ D_MAGIC_ASSERT (pool, CoreSurfacePool); ++ D_MAGIC_ASSERT (data, STMFB_AuxSurfacePoolData); ++ D_MAGIC_ASSERT (local, STMFB_AuxSurfacePoolLocalData); ++ D_MAGIC_ASSERT (allocation, CoreSurfaceAllocation); ++ D_MAGIC_ASSERT (alloc, STMFB_AuxSurfacePoolAllocationData); ++ D_MAGIC_ASSERT (lock, CoreSurfaceBufferLock); ++ ++ D_DEBUG_AT (STMfbdev_SurfLock_Aux, "%s (%d, %p)\n", __func__, ++ data->aux_part, lock->buffer); ++ ++ D_UNUSED_P (data); ++ D_UNUSED_P (local); ++ D_UNUSED_P (alloc); ++ ++#if STGFX_DRIVER == 2 ++ if (unlikely (lock->buffer->format == DSPF_RGB32 ++ && lock->accessor != CSAID_GPU ++ && lock->access & CSAF_WRITE)) ++ { ++ /* if a non-GPU accessor did a write access to an RGB32 surface, we ++ should make sure the alpha is forced to 0xff, as the BDisp doesn't ++ support this format natively */ ++ STGFX2DriverData * const stdrv = dfb_gfxcard_get_driver_data (); ++ STGFX2DeviceData * const stdev = dfb_gfxcard_get_device_data (); ++ DFBRectangle rect = { .x = 0, .y = 0, ++ .w = lock->buffer->surface->config.size.w, ++ .h = lock->buffer->surface->config.size.h }; ++ ++ D_DEBUG_AT (STMfbdev_SurfLock_Aux, " -> rgb32 write release!\n"); ++ dfb_gfxcard_lock (GDLF_WAIT); ++ _bdisp_aq_RGB32_fixup (stdrv, stdev, ++ lock->phys, lock->pitch, ++ &rect); ++ dfb_gfxcard_unlock (); ++ } ++#endif ++ ++ return DFB_OK; ++} ++ ++static const SurfacePoolFuncs stmfb_aux_SurfacePoolFuncs = { ++ .PoolDataSize = stmfb_aux_PoolDataSize, ++ .PoolLocalDataSize = stmfb_aux_PoolLocalDataSize, ++ .AllocationDataSize = stmfb_aux_AllocationDataSize, ++ ++ .InitPool = stmfb_aux_InitPool, ++ .JoinPool = stmfb_aux_JoinPool, ++ .DestroyPool = stmfb_aux_DestroyPool, ++ .LeavePool = stmfb_aux_LeavePool, ++ ++ .TestConfig = stmfb_aux_TestConfig, ++ .AllocateBuffer = stmfb_aux_AllocateBuffer, ++ .DeallocateBuffer = stmfb_aux_DeallocateBuffer, ++ ++ .MuckOut = stmfb_aux_MuckOut, ++ ++ .Lock = stmfb_aux_Lock, ++ .Unlock = stmfb_aux_Unlock, ++}; ++ ++void ++stmfb_aux_surface_pools_init (CoreDFB * const core) ++{ ++ unsigned long total_auxmem = 0; ++ STMfbdev * const stmfbdev = dfb_system_data (); ++ struct stmfbio_auxmem2 auxmem; ++ int i; ++ ++ D_ASSERT (dfb_core_is_master (core)); ++ ++ D_ASSUME (D_ARRAY_SIZE (stmfbdev->shared->aux_pools) == ++ (STMFBGP_GFX_LAST - STMFBGP_GFX_FIRST + 1)); ++ ++ for (i = -1, auxmem.index = 0; ++ auxmem.index < D_ARRAY_SIZE (stmfbdev->shared->aux_pools); ++ ++auxmem.index) ++ { ++ CoreSurfacePool *pool; ++ ++ if (ioctl (stmfbdev->fd, STMFBIO_GET_AUXMEMORY2, &auxmem) != 0) ++ break; ++ ++ if (!auxmem.size) ++ continue; ++ ++ stmfbdev->shared->aux_pool_index = auxmem.index; ++ ++ if (dfb_surface_pool_initialize (core, ++ &stmfb_aux_SurfacePoolFuncs, &pool)) ++ continue; ++ ++ stmfbdev->shared->aux_pools[++i] = pool; ++ total_auxmem += pool->desc.size; ++ } ++ ++ stmfbdev->shared->aux_pool_index = -1; ++ ++ if (total_auxmem) ++ D_INFO ("STMfbdev/Surfaces/Aux: %lukB of auxmem!\n", total_auxmem / 1024); ++ else ++ D_INFO ("STMfbdev/Surfaces/Aux: no auxmem available!\n"); ++} ++ ++void ++stmfb_aux_surface_pools_destroy (CoreDFB * const core) ++{ ++ STMfbdev * const stmfbdev = dfb_system_data (); ++ int i; ++ ++ D_ASSERT (dfb_core_is_master (core)); ++ ++ for (i = 0; i < D_ARRAY_SIZE (stmfbdev->shared->aux_pools); ++i) ++ { ++ CoreSurfacePool * const pool = stmfbdev->shared->aux_pools[i]; ++ if (!pool) ++ continue; ++ ++ if (dfb_surface_pool_destroy (pool)) ++ continue; ++ ++ stmfbdev->shared->aux_pools[i] = NULL; ++ } ++} ++ ++void ++stmfb_aux_surface_pools_join (CoreDFB * const core) ++{ ++ STMfbdev * const stmfbdev = dfb_system_data (); ++ unsigned long total_auxmem = 0; ++ int i; ++ ++ D_ASSERT (!dfb_core_is_master (core)); ++ ++ for (i = 0; i < D_ARRAY_SIZE (stmfbdev->shared->aux_pools); ++i) ++ { ++ CoreSurfacePool * const pool = stmfbdev->shared->aux_pools[i]; ++ if (!pool) ++ continue; ++ ++ if (dfb_surface_pool_join (core, pool, &stmfb_aux_SurfacePoolFuncs)) ++ continue; ++ ++ total_auxmem += pool->desc.size; ++ } ++ ++ if (total_auxmem) ++ D_INFO ("STMfbdev/Surfaces/Aux: %lukB of auxmem!\n", total_auxmem / 1024); ++ else ++ D_INFO ("STMfbdev/Surfaces/Aux: no auxmem available!\n"); ++} ++ ++void ++stmfb_aux_surface_pools_leave (CoreDFB * const core) ++{ ++ STMfbdev * const stmfbdev = dfb_system_data (); ++ int i; ++ ++ D_ASSERT (!dfb_core_is_master (core)); ++ ++ for (i = 0; i < D_ARRAY_SIZE (stmfbdev->shared->aux_pools); ++i) ++ { ++ CoreSurfacePool * const pool = stmfbdev->shared->aux_pools[i]; ++ if (!pool) ++ continue; ++ ++ dfb_surface_pool_leave (pool); ++ } ++} +diff --git a/systems/stmfbdev/stmfb_aux_surface_pool.h b/systems/stmfbdev/stmfb_aux_surface_pool.h +new file mode 100644 +index 0000000..a253646 +--- /dev/null ++++ b/systems/stmfbdev/stmfb_aux_surface_pool.h +@@ -0,0 +1,42 @@ ++/* ++ ST Microelectronics BDispII driver - surface pool memory (auxmem) ++ ++ (c) Copyright 2009 STMicroelectronics Ltd. ++ ++ Written by André Draszik ++ ++ 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 __STMFB_AUX_SURFACE_POOL_H__ ++#define __STMFB_AUX_SURFACE_POOL_H__ ++ ++#include ++ ++extern void ++stmfb_aux_surface_pools_init (CoreDFB * const core); ++ ++extern void ++stmfb_aux_surface_pools_destroy (CoreDFB * const core); ++ ++extern void ++stmfb_aux_surface_pools_join (CoreDFB * const core); ++ ++extern void ++stmfb_aux_surface_pools_leave (CoreDFB * const core); ++ ++ ++#endif /* __STMFB_AUX_SURFACE_POOL_H__ */ +diff --git a/systems/stmfbdev/stmfbdev.c b/systems/stmfbdev/stmfbdev.c +new file mode 100644 +index 0000000..fc8f848 +--- /dev/null ++++ b/systems/stmfbdev/stmfbdev.c +@@ -0,0 +1,591 @@ ++/* ++ (c) Copyright 2010 STMicroelectronics (R&D) Ltd. ++ (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 André Draszik . ++ ++ Based on work by Denis Oliver Kropp , ++ Andreas Hundt , ++ Sven Neumann , ++ Ville Syrjälä and ++ Claudio Ciccani . ++ ++ This library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2 of the License, or (at your option) any later version. ++ ++ This library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with this library; if not, write to the ++ Free Software Foundation, Inc., 59 Temple Place - Suite 330, ++ Boston, MA 02111-1307, USA. ++*/ ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "stmfbdev.h" ++#include "fb.h" ++ ++#include ++ ++#include "stmfb_aux_surface_pool.h" ++ ++DFB_CORE_SYSTEM( stmfbdev ) ++ ++D_DEBUG_DOMAIN( STMfbdev_System, "STMfbdev/System", "STMfb System Module" ); ++ ++/******************************************************************************/ ++ ++extern const SurfacePoolFuncs _g_stmfbdevSurfacePoolFuncs; ++extern ScreenFuncs _g_stmfbdevScreenFuncs; ++extern DisplayLayerFuncs _g_stmfbdevLayerFuncs; ++ ++/******************************************************************************/ ++ ++STMfbdev *dfb_stmfbdev; ++ ++/******************************************************************************/ ++ ++static DFBResult ++dfb_stmfbdev_open( STMfbdev * const stmfbdev ) ++{ ++ mode_t mode = O_RDWR; ++#ifdef O_CLOEXEC ++ /* should be closed automatically in children upon exec(...), but is ++ only available since Linux 2.6.23 */ ++ mode |= O_CLOEXEC; ++#endif ++ ++ D_MAGIC_ASSERT( stmfbdev, STMfbdev ); ++ D_ASSERT( stmfbdev->fd < 0 ); ++ ++ if (dfb_config->fb_device) { ++ stmfbdev->fd = open( dfb_config->fb_device, mode ); ++ if (stmfbdev->fd < 0) { ++ D_PERROR( "DirectFB/STMfbdev: Error opening '%s'!\n", ++ dfb_config->fb_device); ++ ++ return errno2result( errno ); ++ } ++ } ++ else if (getenv( "FRAMEBUFFER" ) && *getenv( "FRAMEBUFFER" ) != '\0') { ++ stmfbdev->fd = open( getenv ( "FRAMEBUFFER" ), mode ); ++ if (stmfbdev->fd < 0) { ++ D_PERROR( "DirectFB/STMfbdev: Error opening '%s'!\n", ++ getenv( "FRAMEBUFFER" ) ); ++ ++ return errno2result( errno ); ++ } ++ } ++ else { ++ stmfbdev->fd = direct_try_open( "/dev/fb0", "/dev/fb/0", mode, true ); ++ if (stmfbdev->fd < 0) { ++ D_ERROR( "DirectFB/STMfbdev: Error opening framebuffer device!\n" ); ++ D_ERROR( "DirectFB/STMfbdev: Use 'fbdev' option or set FRAMEBUFFER environment variable.\n" ); ++ return DFB_INIT; ++ } ++ } ++ ++#ifndef O_CLOEXEC ++ if (fcntl( stmfbdev->fd, F_SETFD, FD_CLOEXEC ) < 0) { ++ D_PERROR( "DirectFB/STMfbdev: Setting FD_CLOEXEC flag failed!\n" ); ++ return errno2result( errno ); ++ } ++#endif ++ ++ return DFB_OK; ++} ++ ++ ++ ++ ++static void ++system_get_info( CoreSystemInfo *info ) ++{ ++ info->version.major = 0; ++ info->version.minor = 9; ++ ++ info->type = CORE_STMFBDEV; ++ info->caps = CSCAPS_ACCELERATION; ++ ++ snprintf( info->name, sizeof (info->name), "STMfbdev" ); ++ snprintf( info->vendor, sizeof (info->vendor), "STMicroelectronics (R&D) Ltd." ); ++ snprintf( info->url, sizeof (info->url), "http://www.stlinux.com" ); ++ snprintf( info->license, sizeof (info->license), "LGPL" ); ++} ++ ++static DFBResult ++system_initialize( CoreDFB *core, void **data ) ++{ ++ DFBResult ret; ++ CoreScreen *screen; ++ long page_size; ++ STMfbdevSharedData *shared; ++ FusionSHMPoolShared *shmpool; ++ STMfbdev *stmfbdev; ++ ++ D_DEBUG_AT( STMfbdev_System, "%s()\n", __FUNCTION__ ); ++ ++ D_ASSERT( dfb_stmfbdev == NULL ); ++ ++ shmpool = dfb_core_shmpool( core ); ++ ++ *data = dfb_stmfbdev = stmfbdev = D_CALLOC( 1, sizeof(STMfbdev) ); ++ if (!stmfbdev) ++ return D_OOM(); ++ ++ D_MAGIC_SET( stmfbdev, STMfbdev ); ++ stmfbdev->fd = -1; ++ ++ shared = (STMfbdevSharedData *) SHCALLOC( shmpool, 1, ++ sizeof(STMfbdevSharedData) ); ++ if (!shared) { ++ ret = D_OOSHM(); ++ goto error; ++ } ++ ++ D_MAGIC_SET( shared, STMfbdevSharedData ); ++ ++ shared->shmpool = shmpool; ++ ++ core_arena_add_shared_field( core, "stmfbdev", shared ); ++ ++ stmfbdev->core = core; ++ stmfbdev->shared = shared; ++ ++ page_size = direct_pagesize(); ++ shared->page_mask = page_size < 0 ? 0 : (page_size - 1); ++ ++ ret = dfb_stmfbdev_open( stmfbdev ); ++ if (ret) ++ goto error; ++ ++ if (dfb_config->vt) { ++ ret = dfb_vt_initialize(); ++ if (ret) ++ goto error; ++ } ++ ++ /* Retrieve fixed information like video ram size */ ++ if (ioctl( stmfbdev->fd, FBIOGET_FSCREENINFO, &shared->fix ) < 0) { ++ D_PERROR( "DirectFB/STMfbdev: " ++ "Could not get fixed screen information!\n" ); ++ ret = errno2result( errno ); ++ goto error; ++ } ++ ++ D_INFO( "DirectFB/STMfbdev: Found '%s' (ID %d) with frame buffer at 0x%08lx, %dk (MMIO 0x%08lx, %dk)\n", ++ shared->fix.id, shared->fix.accel, ++ shared->fix.smem_start, shared->fix.smem_len >> 10, ++ shared->fix.mmio_start, shared->fix.mmio_len >> 10 ); ++ ++ /* Map the framebuffer */ ++ stmfbdev->framebuffer_base = mmap( NULL, shared->fix.smem_len, ++ PROT_READ | PROT_WRITE, MAP_SHARED, ++ stmfbdev->fd, 0 ); ++ if (stmfbdev->framebuffer_base == MAP_FAILED) { ++ D_PERROR( "DirectFB/STMfbdev: " ++ "Could not mmap the framebuffer!\n"); ++ stmfbdev->framebuffer_base = NULL; ++ ret = errno2result( errno ); ++ goto error; ++ } ++ ++ /* as we're running on ST hardware, we can assume pollvsync_after. We ++ set it here as well as in the gfxdriver, so that it does not matter ++ which system is used (fbdev vs. stmfbdev) or if a gfxdriver is used ++ at all (via disable-module=) */ ++ dfb_config->pollvsync_after = true; ++ ++ dfb_surface_pool_initialize( core, &_g_stmfbdevSurfacePoolFuncs, ++ &stmfbdev->shared->pool ); ++ stmfb_aux_surface_pools_init( core ); ++ ++ /* Register primary screen functions */ ++ screen = dfb_screens_register( NULL, stmfbdev, &_g_stmfbdevScreenFuncs ); ++ ++ /* Register primary layer functions */ ++ dfb_layers_register( screen, stmfbdev, &_g_stmfbdevLayerFuncs ); ++ ++ return DFB_OK; ++ ++ ++error: ++ if (shared) ++ SHFREE( shmpool, shared ); ++ ++ if (stmfbdev->framebuffer_base) ++ munmap( stmfbdev->framebuffer_base, shared->fix.smem_len ); ++ ++ if (stmfbdev->fd != -1) ++ close( stmfbdev->fd ); ++ ++ D_FREE( stmfbdev ); ++ *data = dfb_stmfbdev = NULL; ++ ++ return ret; ++} ++ ++static DFBResult ++system_join( CoreDFB *core, void **data ) ++{ ++ DFBResult ret; ++ CoreScreen *screen; ++ STMfbdev *stmfbdev; ++ void *shared; ++ ++ D_DEBUG_AT( STMfbdev_System, "%s()\n", __FUNCTION__ ); ++ ++ D_ASSERT( dfb_stmfbdev == NULL ); ++ ++ *data = dfb_stmfbdev = stmfbdev = D_CALLOC( 1, sizeof(STMfbdev) ); ++ if (!stmfbdev) ++ return D_OOM(); ++ ++ D_MAGIC_SET( stmfbdev, STMfbdev ); ++ stmfbdev->fd = -1; ++ ++ core_arena_get_shared_field( core, "stmfbdev", &shared ); ++ stmfbdev->shared = shared; ++ D_MAGIC_ASSERT( stmfbdev->shared, STMfbdevSharedData ); ++ ++ stmfbdev->core = core; ++ ++ /* Open framebuffer device */ ++ ret = dfb_stmfbdev_open( stmfbdev ); ++ if (ret) ++ goto error; ++ ++ if (dfb_config->vt) { ++ ret = dfb_vt_join(); ++ if (ret) ++ goto error; ++ } ++ ++ /* Map the framebuffer */ ++ stmfbdev->framebuffer_base = mmap( NULL, stmfbdev->shared->fix.smem_len, ++ PROT_READ | PROT_WRITE, MAP_SHARED, ++ stmfbdev->fd, 0 ); ++ if (stmfbdev->framebuffer_base == MAP_FAILED) { ++ D_PERROR( "DirectFB/STMfbdev: " ++ "Could not mmap the framebuffer!\n"); ++ stmfbdev->framebuffer_base = NULL; ++ ret = errno2result( errno ); ++ goto error; ++ } ++ ++ dfb_surface_pool_join( core, stmfbdev->shared->pool, ++ &_g_stmfbdevSurfacePoolFuncs ); ++ stmfb_aux_surface_pools_join( core ); ++ ++ /* Register primary screen functions */ ++ screen = dfb_screens_register( NULL, stmfbdev, &_g_stmfbdevScreenFuncs ); ++ ++ /* Register primary layer functions */ ++ dfb_layers_register( screen, stmfbdev, &_g_stmfbdevLayerFuncs ); ++ ++ return DFB_OK; ++ ++ ++error: ++ if (stmfbdev->fd != -1) ++ close( stmfbdev->fd ); ++ ++ D_FREE( stmfbdev ); ++ *data = dfb_stmfbdev = NULL; ++ ++ return ret; ++} ++ ++static DFBResult ++system_shutdown( bool emergency ) ++{ ++ DFBResult ret; ++ ++ D_DEBUG_AT( STMfbdev_System, "%s()\n", __FUNCTION__ ); ++ ++ D_MAGIC_ASSERT( dfb_stmfbdev, STMfbdev ); ++ D_MAGIC_ASSERT( dfb_stmfbdev->shared, STMfbdevSharedData ); ++ D_MAGIC_ASSERT( dfb_stmfbdev->shared->pool, CoreSurfacePool ); ++ ++ stmfb_aux_surface_pools_destroy( dfb_stmfbdev->core ); ++ dfb_surface_pool_destroy( dfb_stmfbdev->shared->pool ); ++ ++ munmap( dfb_stmfbdev->framebuffer_base, ++ dfb_stmfbdev->shared->fix.smem_len ); ++ ++ if (dfb_config->vt) { ++ ret = dfb_vt_shutdown( emergency ); ++ if (ret) ++ return ret; ++ } ++ ++ close( dfb_stmfbdev->fd ); ++ ++ D_MAGIC_CLEAR( dfb_stmfbdev->shared ); ++ D_MAGIC_CLEAR( dfb_stmfbdev ); ++ ++ SHFREE( dfb_stmfbdev->shared->shmpool, dfb_stmfbdev->shared ); ++ D_FREE( dfb_stmfbdev ); ++ dfb_stmfbdev = NULL; ++ ++ return DFB_OK; ++} ++ ++static DFBResult ++system_leave( bool emergency ) ++{ ++ DFBResult ret; ++ ++ D_DEBUG_AT( STMfbdev_System, "%s()\n", __FUNCTION__ ); ++ ++ D_MAGIC_ASSERT( dfb_stmfbdev, STMfbdev ); ++ D_MAGIC_ASSERT( dfb_stmfbdev->shared, STMfbdevSharedData ); ++ D_MAGIC_ASSERT( dfb_stmfbdev->shared->pool, CoreSurfacePool ); ++ ++ stmfb_aux_surface_pools_leave( dfb_stmfbdev->core ); ++ dfb_surface_pool_leave( dfb_stmfbdev->shared->pool ); ++ ++ munmap( dfb_stmfbdev->framebuffer_base, ++ dfb_stmfbdev->shared->fix.smem_len ); ++ ++ if (dfb_config->vt) { ++ ret = dfb_vt_leave( emergency ); ++ if (ret) ++ return ret; ++ } ++ ++ close( dfb_stmfbdev->fd ); ++ ++ D_MAGIC_CLEAR( dfb_stmfbdev ); ++ ++ D_FREE( dfb_stmfbdev ); ++ dfb_stmfbdev = NULL; ++ ++ return DFB_OK; ++} ++ ++static DFBResult ++system_suspend( void ) ++{ ++ return DFB_OK; ++} ++ ++static DFBResult ++system_resume( void ) ++{ ++ return DFB_OK; ++} ++ ++/******************************************************************************/ ++ ++static volatile void * ++system_map_mmio( unsigned int offset, ++ int length ) ++{ ++ void *addr; ++ ++ D_MAGIC_ASSERT( dfb_stmfbdev, STMfbdev ); ++ ++ if (length <= 0) ++ length = dfb_stmfbdev->shared->fix.mmio_len; ++ ++ addr = mmap( NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, ++ dfb_stmfbdev->fd, ++ dfb_stmfbdev->shared->fix.smem_len + offset ); ++ if (addr == MAP_FAILED) { ++ D_PERROR( "DirectFB/STMfbdev: Could not mmap MMIO region " ++ "(offset %d, length %d)!\n", offset, length ); ++ return NULL; ++ } ++ ++ return(volatile void*) ((u8*) addr + (dfb_stmfbdev->shared->fix.mmio_start ++ & dfb_stmfbdev->shared->page_mask)); ++} ++ ++static void ++system_unmap_mmio( volatile void *addr, ++ int length ) ++{ ++ D_MAGIC_ASSERT( dfb_stmfbdev, STMfbdev ); ++ ++ if (length <= 0) ++ length = dfb_stmfbdev->shared->fix.mmio_len; ++ ++ if (munmap( (void*) ((u8*) addr - (dfb_stmfbdev->shared->fix.mmio_start ++ & dfb_stmfbdev->shared->page_mask)), ++ length ) < 0) ++ D_PERROR( "DirectFB/STMfbdev: Could not unmap MMIO region " ++ "at %p (length %d)!\n", addr, length ); ++} ++ ++static int ++system_get_accelerator( void ) ++{ ++ D_MAGIC_ASSERT( dfb_stmfbdev, STMfbdev ); ++ ++ if (dfb_config->accelerator) ++ return dfb_config->accelerator; ++ ++ return dfb_stmfbdev->shared->fix.accel; ++} ++ ++static VideoMode * ++system_get_modes( void ) ++{ ++ return NULL; ++} ++ ++static VideoMode * ++system_get_current_mode( void ) ++{ ++ return NULL; ++} ++ ++static DFBResult ++system_thread_init( void ) ++{ ++ if (dfb_config->block_all_signals) ++ direct_signals_block_all(); ++ ++ return DFB_OK; ++} ++ ++static bool ++system_input_filter( CoreInputDevice *device, ++ DFBInputEvent *event ) ++{ ++ if (dfb_config->vt && dfb_config->vt_switching) { ++ switch (event->type) { ++ case DIET_KEYPRESS: ++ if (DFB_KEY_TYPE(event->key_symbol) == DIKT_FUNCTION && ++ event->modifiers == (DIMM_CONTROL | DIMM_ALT)) ++ return dfb_vt_switch( event->key_symbol - DIKS_F1 + 1 ); ++ ++ break; ++ ++ case DIET_KEYRELEASE: ++ if (DFB_KEY_TYPE(event->key_symbol) == DIKT_FUNCTION && ++ event->modifiers == (DIMM_CONTROL | DIMM_ALT)) ++ return true; ++ ++ break; ++ ++ default: ++ break; ++ } ++ } ++ ++ return false; ++} ++ ++static unsigned long ++system_video_memory_physical( unsigned int offset ) ++{ ++ D_MAGIC_ASSERT( dfb_stmfbdev, STMfbdev ); ++ ++ return dfb_stmfbdev->shared->fix.smem_start + offset; ++} ++ ++static void * ++system_video_memory_virtual( unsigned int offset ) ++{ ++ D_MAGIC_ASSERT( dfb_stmfbdev, STMfbdev ); ++ ++ return(void*)((u8*)(dfb_stmfbdev->framebuffer_base) + offset); ++} ++ ++static unsigned int ++system_videoram_length( void ) ++{ ++ D_MAGIC_ASSERT( dfb_stmfbdev, STMfbdev ); ++ ++ return dfb_stmfbdev->shared->fix.smem_len; ++} ++ ++static unsigned long ++system_aux_memory_physical( unsigned int offset ) ++{ ++ return 0; ++} ++ ++static void * ++system_aux_memory_virtual( unsigned int offset ) ++{ ++ return NULL; ++} ++ ++static unsigned int ++system_auxram_length( void ) ++{ ++ return 0; ++} ++ ++static void ++system_get_busid( int *ret_bus, int *ret_dev, int *ret_func ) ++{ ++ return; ++} ++ ++static void ++system_get_deviceid( unsigned int *ret_vendor_id, ++ unsigned int *ret_device_id ) ++{ ++ *ret_vendor_id = 0x104a; /* STMicroelectronics */ ++ ++ return; ++} ++ ++static int ++system_surface_data_size( void ) ++{ ++ /* Return zero because shared surface data is unneeded. */ ++ return 0; ++} ++ ++static void ++system_surface_data_init( CoreSurface *surface, void *data ) ++{ ++ /* Ignore since unneeded. */ ++} ++ ++static void ++system_surface_data_destroy( CoreSurface *surface, void *data ) ++{ ++ /* Ignore since unneeded. */ ++} +diff --git a/systems/stmfbdev/stmfbdev.h b/systems/stmfbdev/stmfbdev.h +new file mode 100644 +index 0000000..762d12d +--- /dev/null ++++ b/systems/stmfbdev/stmfbdev.h +@@ -0,0 +1,77 @@ ++/* ++ (c) Copyright 2010 STMicroelectronics (R&D) Ltd. ++ (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 André Draszik . ++ ++ Based on work by Denis Oliver Kropp , ++ Andreas Hundt , ++ Sven Neumann , ++ Ville Syrjälä and ++ Claudio Ciccani . ++ ++ This library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2 of the License, or (at your option) any later version. ++ ++ This library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with this library; if not, write to the ++ Free Software Foundation, Inc., 59 Temple Place - Suite 330, ++ Boston, MA 02111-1307, USA. ++*/ ++ ++#ifndef __STMFBDEV__STMFBDEV_H__ ++#define __STMFBDEV__STMFBDEV_H__ ++ ++#include ++ ++#include ++ ++#include ++ ++#include "fb.h" ++#include "vt.h" ++ ++ ++typedef struct { ++ int magic; ++ ++ struct fb_fix_screeninfo fix; /* fbdev fixed screeninfo, contains info ++ about memory and type of card */ ++ ++ int num_screens; ++ int num_layers; ++ ++ unsigned long page_mask; ++ ++ CoreSurfacePool *pool; ++ ++ CoreSurfacePool *aux_pools[5]; /* STMFBGP_GFX_LAST - STMFBGP_GFX_FIRST + 1 */ ++ /* for exclusive use by stmfb_aux_surface_pool.c */ ++ unsigned int aux_pool_index; ++ ++ FusionSHMPoolShared *shmpool; ++} STMfbdevSharedData; ++ ++typedef struct { ++ int magic; ++ ++ CoreDFB *core; ++ ++ STMfbdevSharedData *shared; ++ int fd; ++ void *framebuffer_base; ++ VirtualTerminal *vt; ++} STMfbdev; ++ ++ ++#endif /* __STMFBDEV__STMFBDEV_H__ */ +diff --git a/systems/stmfbdev/stmfbdev_layer.c b/systems/stmfbdev/stmfbdev_layer.c +new file mode 100644 +index 0000000..1fece04 +--- /dev/null ++++ b/systems/stmfbdev/stmfbdev_layer.c +@@ -0,0 +1,988 @@ ++/* ++ (c) Copyright 2010 STMicroelectronics (R&D) Ltd. ++ (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 André Draszik . ++ ++ Based on work by Denis Oliver Kropp , ++ Andreas Hundt , ++ Sven Neumann , ++ Ville Syrjälä and ++ Claudio Ciccani . ++ ++ This library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2 of the License, or (at your option) any later version. ++ ++ This library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with this library; if not, write to the ++ Free Software Foundation, Inc., 59 Temple Place - Suite 330, ++ Boston, MA 02111-1307, USA. ++*/ ++ ++#include ++ ++#include ++ ++#include ++#include ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++ ++#include "stmfbdev.h" ++ ++D_DEBUG_DOMAIN( STMfbdev_Layer, "STMfbdev/Layer", "STMfb System Module Layer Handling" ); ++ ++ ++typedef struct { ++ int magic; ++ ++ int layerid; ++ DFBDisplayLayerOptions supported_options; ++ DFBSurfaceCapabilities supported_surfacecaps; ++ ++ struct stmfbio_planeinfo cur_planeinfo; ++ ++ struct fb_cmap current_cmap; ++ ++ DFBColorAdjustmentFlags supported_adjustments; ++ ++ struct stmfbio_planeinfo orig_planeinfo; ++ struct stmfbio_var_screeninfo_ex orig_varex; ++ struct fb_cmap orig_cmap; ++ void *cmap_memory[2]; /* orig and current */ ++ FusionSHMPoolShared *shmpool_data; ++} STMfbdevLayerSharedData; ++ ++ ++ ++/* supported surface formats */ ++#define STM_supported_pixelformat \ ++ DSPF_ARGB1555: case DSPF_RGB16: case DSPF_RGB24: case DSPF_ARGB: \ ++ case DSPF_A8: case DSPF_UYVY: case DSPF_LUT8: \ ++ case DSPF_ALUT44: case DSPF_A1: case DSPF_ARGB4444: case DSPF_LUT2: \ ++ case DSPF_ARGB8565: case DSPF_AVYU: case DSPF_VYU ++ ++static const SURF_FMT dspf_to_stmfb[DFB_NUM_PIXELFORMATS] = { ++ [DFB_PIXELFORMAT_INDEX (DSPF_UNKNOWN)] = SURF_NULL_PAD, ++ [DFB_PIXELFORMAT_INDEX (DSPF_ARGB1555)] = SURF_ARGB1555, ++ [DFB_PIXELFORMAT_INDEX (DSPF_RGB16)] = SURF_RGB565, ++ [DFB_PIXELFORMAT_INDEX (DSPF_RGB24)] = SURF_RGB888, ++ [DFB_PIXELFORMAT_INDEX (DSPF_RGB32)] = SURF_NULL_PAD, ++ [DFB_PIXELFORMAT_INDEX (DSPF_ARGB)] = SURF_ARGB8888, ++ [DFB_PIXELFORMAT_INDEX (DSPF_A8)] = SURF_A8, ++ [DFB_PIXELFORMAT_INDEX (DSPF_YUY2)] = SURF_NULL_PAD, ++ [DFB_PIXELFORMAT_INDEX (DSPF_RGB332)] = SURF_NULL_PAD, ++ [DFB_PIXELFORMAT_INDEX (DSPF_UYVY)] = SURF_YCBCR422R, ++ [DFB_PIXELFORMAT_INDEX (DSPF_I420)] = SURF_NULL_PAD, ++ [DFB_PIXELFORMAT_INDEX (DSPF_YV12)] = SURF_NULL_PAD, ++ [DFB_PIXELFORMAT_INDEX (DSPF_LUT8)] = SURF_CLUT8, ++ [DFB_PIXELFORMAT_INDEX (DSPF_ALUT44)] = SURF_ACLUT44, ++ [DFB_PIXELFORMAT_INDEX (DSPF_AiRGB)] = SURF_NULL_PAD, ++ [DFB_PIXELFORMAT_INDEX (DSPF_A1)] = SURF_A1, ++ [DFB_PIXELFORMAT_INDEX (DSPF_NV12)] = SURF_NULL_PAD, ++ [DFB_PIXELFORMAT_INDEX (DSPF_NV16)] = SURF_NULL_PAD, ++ [DFB_PIXELFORMAT_INDEX (DSPF_ARGB2554)] = SURF_NULL_PAD, ++ [DFB_PIXELFORMAT_INDEX (DSPF_ARGB4444)] = SURF_ARGB4444, ++ [DFB_PIXELFORMAT_INDEX (DSPF_RGBA4444)] = SURF_NULL_PAD, ++ [DFB_PIXELFORMAT_INDEX (DSPF_NV21)] = SURF_NULL_PAD, ++ [DFB_PIXELFORMAT_INDEX (DSPF_AYUV)] = SURF_NULL_PAD, ++ [DFB_PIXELFORMAT_INDEX (DSPF_A4)] = SURF_NULL_PAD, ++ [DFB_PIXELFORMAT_INDEX (DSPF_ARGB1666)] = SURF_NULL_PAD, ++ [DFB_PIXELFORMAT_INDEX (DSPF_ARGB6666)] = SURF_NULL_PAD, ++ [DFB_PIXELFORMAT_INDEX (DSPF_RGB18)] = SURF_NULL_PAD, ++ [DFB_PIXELFORMAT_INDEX (DSPF_LUT2)] = SURF_CLUT2, ++ [DFB_PIXELFORMAT_INDEX (DSPF_RGB444)] = SURF_NULL_PAD, ++ [DFB_PIXELFORMAT_INDEX (DSPF_RGB555)] = SURF_NULL_PAD, ++ [DFB_PIXELFORMAT_INDEX (DSPF_BGR555)] = SURF_NULL_PAD, ++ [DFB_PIXELFORMAT_INDEX (DSPF_RGBA5551)] = SURF_NULL_PAD, ++ [DFB_PIXELFORMAT_INDEX (DSPF_YUV444P)] = SURF_NULL_PAD, ++ [DFB_PIXELFORMAT_INDEX (DSPF_ARGB8565)] = SURF_ARGB8565, ++ [DFB_PIXELFORMAT_INDEX (DSPF_AVYU)] = SURF_ACRYCB8888, ++ [DFB_PIXELFORMAT_INDEX (DSPF_VYU)] = SURF_CRYCB888, ++ [DFB_PIXELFORMAT_INDEX (DSPF_A1_LSB)] = SURF_NULL_PAD, ++ [DFB_PIXELFORMAT_INDEX (DSPF_YV16)] = SURF_NULL_PAD, ++#if 0 ++ /* unsupported in DirectFB */ ++ [DFB_PIXELFORMAT_INDEX (DSPF_BGRA)] = { SURF_BGRA8888, ++ [DFB_PIXELFORMAT_INDEX (DSPF_LUT1)] = { SURF_CLUT1, ++ [DFB_PIXELFORMAT_INDEX (DSPF_LUT4)] = { SURF_CLUT4, ++ [DFB_PIXELFORMAT_INDEX (DSPF_ALUT88)] = { SURF_ACLUT88, ++#endif ++}; ++ ++static DFBSurfacePixelFormat ++stmfb_to_dsbf( SURF_FMT fmt ) ++{ ++ switch (fmt) { ++ case SURF_ARGB1555: return DSPF_ARGB1555; ++ case SURF_RGB565: return DSPF_RGB16; ++ case SURF_RGB888: return DSPF_RGB24; ++ case SURF_ARGB8888: return DSPF_ARGB; ++ case SURF_A8: return DSPF_A8; ++ case SURF_YCBCR422R: return DSPF_UYVY; ++ case SURF_CLUT8: return DSPF_LUT8; ++ case SURF_ACLUT44: return DSPF_ALUT44; ++ case SURF_A1: return DSPF_A1; ++ case SURF_ARGB4444: return DSPF_ARGB4444; ++ case SURF_CLUT2: return DSPF_LUT2; ++ case SURF_ARGB8565: return DSPF_ARGB8565; ++ case SURF_ACRYCB8888: return DSPF_AVYU; ++ case SURF_CRYCB888: return DSPF_VYU; ++ default: ++ break; ++ } ++ return DSPF_UNKNOWN; ++}; ++ ++ ++/******************************************************************************/ ++ ++static int ++stmfbdevLayerDataSize( void ) ++{ ++ D_DEBUG_AT( STMfbdev_Layer, "%s() <- %u\n", ++ __FUNCTION__, sizeof(STMfbdevLayerSharedData) ); ++ ++ return sizeof(STMfbdevLayerSharedData); ++} ++ ++static int ++stmfbdevRegionDataSize( void ) ++{ ++ return 0; ++} ++ ++static DFBResult ++stmfbdevInitLayer( CoreLayer *layer, ++ void *driver_data, ++ void *layer_data, ++ DFBDisplayLayerDescription *description, ++ DFBDisplayLayerConfig *config, ++ DFBColorAdjustment *adjustment ) ++{ ++ const STMfbdev * const stmfbdev = driver_data; ++ STMfbdevLayerSharedData * const shared = layer_data; ++ const struct stmfbio_plane_config *pc; ++ u32 hw_caps; ++ ++ D_DEBUG_AT( STMfbdev_Layer, "%s( %p %d )\n", ++ __FUNCTION__, layer, stmfbdev->shared->num_layers + 1 ); ++ ++ D_MAGIC_ASSERT( stmfbdev, STMfbdev ); ++ D_MAGIC_ASSERT( stmfbdev->shared, STMfbdevSharedData ); ++ ++ D_MAGIC_SET( shared, STMfbdevLayerSharedData ); ++ ++ shared->layerid = stmfbdev->shared->num_layers++; ++ ++ shared->shmpool_data = dfb_core_shmpool_data( stmfbdev->core ); ++ ++ /* remember startup config, so we can restore it on shutdown */ ++ shared->orig_planeinfo.layerid = shared->layerid; ++ if (ioctl( stmfbdev->fd, STMFBIO_GET_PLANEMODE, &shared->orig_planeinfo ) < 0) { ++ D_PERROR( "STMfbdev/Layer: Could not get planeinfo!\n" ); ++ return errno2result( errno ); ++ } ++ shared->orig_planeinfo.activate = STMFBIO_ACTIVATE_IMMEDIATE; ++ shared->cur_planeinfo = shared->orig_planeinfo; ++ pc = &shared->cur_planeinfo.config; ++ ++ D_DEBUG_AT( STMfbdev_Layer, ++ " -> current: %dx%d @ %d,%d-%dx%d (%d: %s) %ubpp pitch %u @ 0x%08lx\n", ++ pc->source.w, pc->source.h, pc->dest.x, pc->dest.y, ++ pc->dest.dim.w, pc->dest.dim.h, pc->format, ++ dfb_pixelformat_name( stmfb_to_dsbf( pc->format ) ), ++ pc->bitdepth, pc->pitch, pc->baseaddr ); ++ ++ /* same for stmfb's extended var */ ++ shared->orig_varex.layerid = shared->layerid; ++ if (ioctl( stmfbdev->fd, ++ STMFBIO_GET_VAR_SCREENINFO_EX, &shared->orig_varex ) < 0) { ++ D_PERROR( "STMfbdev/Layer: Could not get extended planeinfo!\n" ); ++ return errno2result( errno ); ++ } ++ shared->orig_varex.activate = STMFBIO_ACTIVATE_IMMEDIATE; ++ hw_caps = shared->orig_varex.caps; ++ D_DEBUG_AT( STMfbdev_Layer, " -> extended caps: 0x%08x\n", hw_caps ); ++ ++ /* allocate space for two colormaps - one to work with ... */ ++ shared->cmap_memory[0] = SHMALLOC( shared->shmpool_data, 256 * 2 * 4 ); ++ if (!shared->cmap_memory[0]) ++ return D_OOSHM(); ++ shared->current_cmap.start = 0; ++ shared->current_cmap.len = 256; ++ shared->current_cmap.red = shared->cmap_memory[0] + 256 * 2 * 0; ++ shared->current_cmap.green = shared->cmap_memory[0] + 256 * 2 * 1; ++ shared->current_cmap.blue = shared->cmap_memory[0] + 256 * 2 * 2; ++ shared->current_cmap.transp = shared->cmap_memory[0] + 256 * 2 * 3; ++ ++ /* ... and one to store the original colormap */ ++ shared->cmap_memory[1] = SHMALLOC( shared->shmpool_data, 256 * 2 * 4 ); ++ if (!shared->cmap_memory[1]) { ++ SHFREE( shared->shmpool_data, shared->cmap_memory[0] ); ++ shared->cmap_memory[0] = NULL; ++ shared->current_cmap.len = 0; ++ return D_OOSHM(); ++ } ++ shared->orig_cmap.start = 0; ++ shared->orig_cmap.len = 256; ++ shared->orig_cmap.red = shared->cmap_memory[1] + 256 * 2 * 0; ++ shared->orig_cmap.green = shared->cmap_memory[1] + 256 * 2 * 1; ++ shared->orig_cmap.blue = shared->cmap_memory[1] + 256 * 2 * 2; ++ shared->orig_cmap.transp = shared->cmap_memory[1] + 256 * 2 * 3; ++ ++ if (ioctl( stmfbdev->fd, FBIOGETCMAP, &shared->orig_cmap ) < 0) { ++ D_DEBUG( "STMfbdev/Layer: Could not retrieve palette for backup!\n" ); ++ ++ memset( &shared->orig_cmap, 0, sizeof(shared->orig_cmap) ); ++ ++ SHFREE( shared->shmpool_data, shared->cmap_memory[1] ); ++ shared->cmap_memory[1] = NULL; ++ } ++ ++ ++ /* set name */ ++ snprintf( description->name, sizeof (description->name), ++ "STM Layer %d", shared->cur_planeinfo.layerid ); ++ ++ /* set capabilities and type */ ++ description->caps = (DLCAPS_SURFACE ++ | DLCAPS_SCREEN_POSITION | DLCAPS_SCREEN_SIZE ++ | DLCAPS_SCREEN_LOCATION ++ | DLCAPS_ALPHACHANNEL ++ ); ++ description->type = DLTF_GRAPHICS; ++ description->regions = 1; ++ ++ /* fill out the default configuration */ ++ config->flags = (DLCONF_WIDTH | DLCONF_HEIGHT | DLCONF_PIXELFORMAT ++ | DLCONF_BUFFERMODE ++ | DLCONF_OPTIONS ++ ); ++ config->buffermode = DLBM_FRONTONLY; ++ if (D_FLAGS_ARE_SET (dfb_config->layers[shared->layerid].config.flags, ++ (DLCONF_WIDTH | DLCONF_HEIGHT))) { ++ config->width = dfb_config->layers[shared->layerid].config.width; ++ config->height = dfb_config->layers[shared->layerid].config.height; ++ } ++ else if (dfb_config->mode.width && dfb_config->mode.height) { ++ config->width = dfb_config->mode.width; ++ config->height = dfb_config->mode.height; ++ } ++ else { ++ config->width = pc->source.w; ++ config->height = pc->source.h; ++ } ++ if (D_FLAGS_ARE_SET (dfb_config->layers[shared->layerid].config.flags, ++ DLCONF_PIXELFORMAT)) ++ config->pixelformat = dfb_config->layers[shared->layerid].config.pixelformat; ++ else if (dfb_config->mode.format) ++ config->pixelformat = dfb_config->mode.format; ++ else ++ config->pixelformat = stmfb_to_dsbf( pc->format ); ++ ++ config->options = DLOP_ALPHACHANNEL; ++ ++ adjustment->flags = DCAF_NONE; ++ ++ shared->supported_options = DLOP_ALPHACHANNEL; ++ shared->supported_adjustments = DCAF_NONE; ++ shared->supported_surfacecaps = DSCAPS_NONE; ++ ++ if (D_FLAGS_IS_SET( hw_caps, STMFBIO_VAR_CAPS_COLOURKEY )) { ++ D_DEBUG_AT( STMfbdev_Layer, " +> src colorkey\n" ); ++ description->caps |= DLCAPS_SRC_COLORKEY; ++ shared->supported_options |= DLOP_SRC_COLORKEY; ++ } ++ if (D_FLAGS_IS_SET( hw_caps, STMFBIO_VAR_CAPS_FLICKER_FILTER )) { ++ D_DEBUG_AT( STMfbdev_Layer, " +> flicker filtering (state: %d)\n", ++ shared->orig_varex.ff_state ); ++ description->caps |= DLCAPS_FLICKER_FILTERING; ++ shared->supported_options |= DLOP_FLICKER_FILTERING; ++ } ++ if (D_FLAGS_IS_SET( hw_caps, STMFBIO_VAR_CAPS_PREMULTIPLIED )) { ++ D_DEBUG_AT( STMfbdev_Layer, " +> pre-multiplied alpha (state: %d)\n", ++ shared->orig_varex.premultiplied_alpha ); ++ description->caps |= DLCAPS_PREMULTIPLIED; ++ shared->supported_surfacecaps |= DSCAPS_PREMULTIPLIED; ++ ++ /* we force this to on! */ ++ config->flags |= DLCONF_SURFACE_CAPS; ++ config->surface_caps = DSCAPS_PREMULTIPLIED; ++ } ++ if (D_FLAGS_IS_SET( hw_caps, STMFBIO_VAR_CAPS_OPACITY )) { ++ D_DEBUG_AT( STMfbdev_Layer, " +> opacity (%d)\n", ++ shared->orig_varex.opacity ); ++ description->caps |= DLCAPS_OPACITY; ++ shared->supported_options |= DLOP_OPACITY; ++ ++ config->options |= DLOP_OPACITY; ++ /* Strangely we cannot specify the default layer opacity, lets hope ++ it's fully opaque! */ ++ } ++ if (D_FLAGS_IS_SET( hw_caps, (STMFBIO_VAR_CAPS_GAIN ++ | STMFBIO_VAR_CAPS_BRIGHTNESS ))) { ++ D_DEBUG_AT( STMfbdev_Layer, " +> brightness/gain adjustment (%d %d)\n", ++ shared->orig_varex.brightness, shared->orig_varex.gain ); ++ description->caps |= DLCAPS_BRIGHTNESS; ++ shared->supported_adjustments |= DCAF_BRIGHTNESS; ++ ++ adjustment->flags |= DCAF_BRIGHTNESS; ++ adjustment->brightness = 0x8000; ++ } ++ if (D_FLAGS_IS_SET( hw_caps, STMFBIO_VAR_CAPS_CONTRAST )) { ++ D_DEBUG_AT( STMfbdev_Layer, " +> contrast adjustment (%d)\n", ++ shared->orig_varex.contrast ); ++ description->caps |= DLCAPS_CONTRAST; ++ shared->supported_adjustments |= DCAF_CONTRAST; ++ ++ adjustment->flags |= DCAF_CONTRAST; ++ adjustment->contrast = 0x8000; ++ } ++ if (D_FLAGS_IS_SET( hw_caps, STMFBIO_VAR_CAPS_TINT )) { ++ D_DEBUG_AT( STMfbdev_Layer, " +> tint adjustment (%d)\n", ++ shared->orig_varex.tint ); ++ description->caps |= DLCAPS_HUE; ++ shared->supported_adjustments |= DCAF_HUE; ++ ++ adjustment->flags |= DCAF_HUE; ++ adjustment->hue = 0x8000; ++ } ++ if (D_FLAGS_IS_SET( hw_caps, STMFBIO_VAR_CAPS_SATURATION )) { ++ D_DEBUG_AT( STMfbdev_Layer, " +> saturation adjustment (%d)\n", ++ shared->orig_varex.saturation ); ++ description->caps |= DLCAPS_SATURATION; ++ shared->supported_adjustments |= DCAF_SATURATION; ++ ++ adjustment->flags |= DCAF_SATURATION; ++ adjustment->saturation = 0x8000; ++ } ++ if (D_FLAGS_IS_SET( hw_caps, STMFBIO_VAR_CAPS_ALPHA_RAMP )) { ++ D_DEBUG_AT( STMfbdev_Layer, " +> RGB1555 alpha ramp\n" ); ++ description->caps |= DLCAPS_ALPHA_RAMP; ++ } ++ if (D_FLAGS_IS_SET( hw_caps, STMFBIO_VAR_CAPS_ZPOSITION )) { ++ D_DEBUG_AT( STMfbdev_Layer, " +> plane re-ordering (%d)\n", ++ shared->orig_varex.z_position ); ++ description->caps |= DLCAPS_LEVELS; ++ description->level = shared->orig_varex.z_position; ++ } ++ ++ return DFB_OK; ++} ++ ++static DFBResult ++stmfbdevShutdownLayer( CoreLayer *layer, ++ void *driver_data, ++ void *layer_data ) ++{ ++ const STMfbdev * const stmfbdev = driver_data; ++ STMfbdevLayerSharedData * const shared = layer_data; ++ ++ D_DEBUG_AT( STMfbdev_Layer, "%s()\n", __FUNCTION__ ); ++ ++ D_MAGIC_ASSERT( stmfbdev, STMfbdev ); ++ D_MAGIC_ASSERT( shared, STMfbdevLayerSharedData ); ++ ++ if (shared->cmap_memory[1]) { ++ if (ioctl( stmfbdev->fd, FBIOPUTCMAP, &shared->orig_cmap ) < 0) ++ D_DEBUG( "STMfbdev/Layer: " ++ "Could not restore palette!\n" ); ++ ++ SHFREE( shared->shmpool_data, shared->cmap_memory[1] ); ++ } ++ ++ if (shared->cmap_memory[0]) ++ SHFREE( shared->shmpool_data, shared->cmap_memory[0] ); ++ ++ /* restore the original plane configuration */ ++ if (ioctl( stmfbdev->fd, STMFBIO_SET_PLANEMODE, &shared->orig_planeinfo ) < 0) ++ D_PERROR( "STMfbdev/Layer: Could not restore planeinfo\n" ); ++ ++ /* restore the extended state */ ++ if (ioctl( stmfbdev->fd, STMFBIO_SET_VAR_SCREENINFO_EX, &shared->orig_varex ) < 0) ++ D_PERROR( "STMfbdev/Layer: Could not restore extended state\n" ); ++ ++ D_MAGIC_CLEAR( shared ); ++ ++ return DFB_OK; ++} ++ ++static DFBResult ++stmfbdevTestRegion( CoreLayer *layer, ++ void *driver_data, ++ void *layer_data, ++ CoreLayerRegionConfig *config, ++ CoreLayerRegionConfigFlags *failed ) ++{ ++ const STMfbdev * const stmfbdev = driver_data; ++ STMfbdevLayerSharedData * const shared = layer_data; ++ struct stmfbio_planeinfo plane; ++ CoreLayerRegionConfigFlags fail = CLRCF_NONE; ++ ++ D_DEBUG_AT( STMfbdev_Layer, "%s()\n", __FUNCTION__ ); ++ ++ D_MAGIC_ASSERT( stmfbdev, STMfbdev ); ++ D_MAGIC_ASSERT( shared, STMfbdevLayerSharedData ); ++ D_ASSERT( config != NULL ); ++ ++ (void) stmfbdev; ++ ++ DFB_CORE_LAYER_REGION_CONFIG_DEBUG_AT( STMfbdev_Layer, config ); ++ ++ if (D_FLAGS_INVALID( config->options, shared->supported_options )) ++ fail |= CLRCF_OPTIONS; ++ ++ /* some defaults - the original base address should always be ok, as it ++ should be at the beginning of the framebuffer, thus any plane should ++ fit. */ ++ plane.layerid = shared->orig_planeinfo.layerid; ++ plane.config.baseaddr = shared->orig_planeinfo.config.baseaddr; ++ ++ /* we can't (and don't want to) test these individually, as the driver ++ does some comprehensive checking on the parameters, and they must ++ all be consistent, e.g. size/pitch/memory/scaling etc. */ ++ plane.activate = STMFBIO_ACTIVATE_TEST; ++ plane.config.source.w = config->width; ++ plane.config.source.h = config->height; ++ plane.config.dest.x = config->dest.x; ++ plane.config.dest.y = config->dest.y; ++ plane.config.dest.dim.w = config->dest.w; ++ plane.config.dest.dim.h = config->dest.h; ++ plane.config.format = dspf_to_stmfb[DFB_PIXELFORMAT_INDEX( config->format )]; ++ plane.config.pitch = DFB_BYTES_PER_LINE( config->format, config->width ); ++ if (ioctl( stmfbdev->fd, STMFBIO_SET_PLANEMODE, &plane ) < 0) ++ fail |= CLRCF_FORMAT | CLRCF_WIDTH | CLRCF_HEIGHT | CLRCF_DEST; ++ ++ /* can there be more flags set? */ ++ if (D_FLAGS_IS_SET( config->surface_caps, DSCAPS_PREMULTIPLIED ) ++ && !D_FLAGS_IS_SET( shared->supported_surfacecaps, ++ DSCAPS_PREMULTIPLIED )) ++ fail |= CLRCF_SURFACE_CAPS; ++ ++ if (failed) ++ *failed = fail; ++ ++ if (fail) { ++ D_DEBUG_AT( STMfbdev_Layer, " => FAILED!\n" ); ++ return DFB_UNSUPPORTED; ++ } ++ ++ D_DEBUG_AT( STMfbdev_Layer, " => SUCCESS\n" ); ++ ++ return DFB_OK; ++} ++ ++static DFBResult ++stmfbdevAddRegion( CoreLayer *layer, ++ void *driver_data, ++ void *layer_data, ++ void *region_data, ++ CoreLayerRegionConfig *config ) ++{ ++ const STMfbdev * const stmfbdev = driver_data; ++ STMfbdevLayerSharedData * const shared = layer_data; ++ ++ D_DEBUG_AT( STMfbdev_Layer, "%s()\n", __FUNCTION__ ); ++ ++ D_MAGIC_ASSERT( stmfbdev, STMfbdev ); ++ D_MAGIC_ASSERT( shared, STMfbdevLayerSharedData ); ++ D_ASSERT( config != NULL ); ++ ++ (void) stmfbdev; ++ (void) shared; ++ ++ return DFB_OK; ++} ++ ++static DFBResult ++stmfbdevSetRegion( CoreLayer *layer, ++ void *driver_data, ++ void *layer_data, ++ void *region_data, ++ CoreLayerRegionConfig *config, ++ CoreLayerRegionConfigFlags updated, ++ CoreSurface *surface, ++ CorePalette *palette, ++ CoreSurfaceBufferLock *left_lock, ++ CoreSurfaceBufferLock *right_lock ) ++{ ++ const STMfbdev * const stmfbdev = driver_data; ++ STMfbdevLayerSharedData * const shared = layer_data; ++ struct stmfbio_planeinfo plane; ++ struct stmfbio_var_screeninfo_ex var_ex; ++ u32 hw_caps; ++ bool need_update = false; ++ ++ D_DEBUG_AT( STMfbdev_Layer, "%s()\n", __FUNCTION__ ); ++ ++ D_MAGIC_ASSERT( stmfbdev, STMfbdev ); ++ D_MAGIC_ASSERT( shared, STMfbdevLayerSharedData ); ++ D_ASSERT( config != NULL ); ++ ++ (void) stmfbdev; ++ ++ if (updated) ++ DFB_CORE_LAYER_REGION_CONFIG_DEBUG_AT( STMfbdev_Layer, config ); ++ ++ D_DEBUG_AT( STMfbdev_Layer, " -> updated: %x\n", updated); ++ ++ plane.layerid = shared->cur_planeinfo.layerid; ++ plane.activate = STMFBIO_ACTIVATE_IMMEDIATE; ++ plane.config = shared->cur_planeinfo.config; ++ ++ /* Update position? */ ++ if (D_FLAGS_IS_SET( updated, CLRCF_DEST )) { ++ /* Set horizontal and vertical offset & size. */ ++ D_DEBUG_AT( STMfbdev_Layer, " +> destination: %d,%d - %dx%d\n", ++ config->dest.x, config->dest.y, ++ config->dest.w, config->dest.h ); ++ ++ need_update = true; ++ ++ plane.config.dest.x = config->dest.x; ++ plane.config.dest.y = config->dest.y; ++ plane.config.dest.dim.w = config->dest.w; ++ plane.config.dest.dim.h = config->dest.h; ++ } ++ ++ /* Update size? */ ++ if (D_FLAGS_IS_SET( updated, (CLRCF_WIDTH | CLRCF_HEIGHT) )) { ++ /* Set width and height. */ ++ D_DEBUG_AT( STMfbdev_Layer, " +> width/height: %dx%d, vp: %d,%d - %dx%d\n", ++ config->width, config->height, ++ config->source.x, config->source.y, ++ config->source.w, config->source.h); ++ ++ need_update = true; ++ ++ /* FIXME: stmfb driver API is incomplete! Should be updated to ++ support a real source 'viewport' inside a source surface. */ ++ plane.config.source.w = config->width; ++ plane.config.source.h = config->height; ++ ++ /* fixme: clipping? */ ++#if 0 ++ if (config->dest.x + config->width > screen_width) ++ plane.config.source.w = screen_width - config->dest.x; ++ ++ if (config->dest.y + config->height > screen_height) ++ plane.config.source.h = screen_height - config->dest.y; ++#endif ++ } ++ D_ASSUME (config->width == config->source.w); ++ D_ASSUME (config->height == config->source.h); ++ D_ASSUME (config->source.x == 0); ++ D_ASSUME (config->source.y == 0); ++ ++ /* Update surface? */ ++ if (D_FLAGS_IS_SET( updated, CLRCF_SURFACE )) { ++ /* Set buffer base address and pitch. */ ++ D_DEBUG_AT( STMfbdev_Layer, ++ " +> offset 0x%.8lx, pitch %d, addr %p, phys 0x%.8lx\n", ++ left_lock->offset, left_lock->pitch, ++ left_lock->addr, left_lock->phys); ++ ++ need_update = true; ++ ++ plane.config.baseaddr = left_lock->phys; ++ plane.config.pitch = left_lock->pitch; ++ } ++ ++ /* Update format? */ ++ if (D_FLAGS_IS_SET( updated, CLRCF_FORMAT )) { ++ /* Set pixel format. */ ++ switch (config->format) { ++ case STM_supported_pixelformat: ++ plane.config.format = dspf_to_stmfb[DFB_PIXELFORMAT_INDEX( config->format )]; ++ need_update = true; ++ break; ++ ++ default: ++ break; ++ } ++ ++ D_DEBUG_AT( STMfbdev_Layer, " +> pixelformat: %x (%s) -> %d\n", ++ config->format, dfb_pixelformat_name( config->format ), ++ plane.config.format ); ++ } ++ D_ASSUME( surface->config.format == config->format ); ++ ++ ++ /* now for the extended state stuff */ ++ hw_caps = shared->orig_varex.caps; ++ var_ex.layerid = shared->orig_varex.layerid; ++ var_ex.activate = STMFBIO_ACTIVATE_IMMEDIATE; ++ var_ex.caps = 0; ++ ++ if (D_FLAGS_IS_SET( updated, CLRCF_OPTIONS )) { ++ D_DEBUG_AT( STMfbdev_Layer, " +> options: 0x%.8x %s%s%s%s%s%s%s\n", ++ config->options, ++ (config->options & DLOP_ALPHACHANNEL) ? "ALPHA " : "", ++ (config->options & DLOP_FLICKER_FILTERING) ? "FLICKER " : "", ++ (config->options & DLOP_DEINTERLACING) ? "DEI " : "", ++ (config->options & DLOP_SRC_COLORKEY) ? "SRCKEY " : "", ++ (config->options & DLOP_DST_COLORKEY) ? "DSTKEY " : "", ++ (config->options & DLOP_OPACITY) ? "OPACITY " : "", ++ (config->options & DLOP_FIELD_PARITY) ? "PARITY " : "" ); ++ ++ D_ASSUME( D_FLAGS_IS_SET( config->options, DLOP_ALPHACHANNEL )); ++ ++ if (D_FLAGS_IS_SET( hw_caps, STMFBIO_VAR_CAPS_FLICKER_FILTER )) { ++ var_ex.caps |= STMFBIO_VAR_CAPS_FLICKER_FILTER; ++ var_ex.ff_state = ((config->options & DLOP_FLICKER_FILTERING) ++ ? STMFBIO_FF_ADAPTIVE ++ : STMFBIO_FF_OFF ++ ); ++ } ++ } ++ ++ if (D_FLAGS_IS_SET( updated, (CLRCF_OPTIONS | CLRCF_SRCKEY) )) { ++ D_DEBUG_AT( STMfbdev_Layer, " +> srckey: %02x%02x%02x\n", ++ config->src_key.r, config->src_key.g, config->src_key.b ); ++ ++ if (D_FLAGS_IS_SET( hw_caps, STMFBIO_VAR_CAPS_COLOURKEY )) { ++ ++ var_ex.caps |= STMFBIO_VAR_CAPS_COLOURKEY; ++ var_ex.colourKeyFlags = ((config->options & DLOP_SRC_COLORKEY) ++ ? STMFBIO_COLOURKEY_FLAGS_ENABLE ++ : 0 ++ ); ++ var_ex.min_colour_key ++ = var_ex.max_colour_key ++ = PIXEL_ARGB (0, config->src_key.r, config->src_key.g, ++ config->src_key.b); ++ } ++ } ++ ++ if (D_FLAGS_IS_SET( updated, CLRCF_SURFACE_CAPS )) { ++ D_DEBUG_AT( STMfbdev_Layer, " +> surface caps: %spremultiplied alpha\n", ++ ((config->surface_caps & DSCAPS_PREMULTIPLIED) ++ ? "" : "non-") ); ++ ++ D_ASSUME( D_FLAGS_IS_SET( hw_caps, STMFBIO_VAR_CAPS_PREMULTIPLIED )); ++ ++ var_ex.caps |= STMFBIO_VAR_CAPS_PREMULTIPLIED; ++ var_ex.premultiplied_alpha = ((config->surface_caps & DSCAPS_PREMULTIPLIED) ++ ? 1 ++ : 0 ++ ); ++ } ++ ++ if (D_FLAGS_IS_SET( updated, CLRCF_OPACITY )) { ++ D_DEBUG_AT( STMfbdev_Layer, " +> opacity: %d\n", config->opacity ); ++ ++ D_ASSUME( D_FLAGS_IS_SET( hw_caps, STMFBIO_VAR_CAPS_OPACITY )); ++ ++ var_ex.caps |= STMFBIO_VAR_CAPS_OPACITY; ++ var_ex.opacity = ((config->options & DLOP_OPACITY) ++ ? config->opacity ++ : 255 ++ ); ++ } ++ ++ if (D_FLAGS_IS_SET( updated, CLRCF_ALPHA_RAMP )) { ++ D_DEBUG_AT( STMfbdev_Layer, " +> alpha ramp: 0x%02x 0x%02x 0x%02x 0x%02x\n", ++ config->alpha_ramp[0], config->alpha_ramp[1], ++ config->alpha_ramp[2], config->alpha_ramp[3] ); ++ ++ D_ASSUME( D_FLAGS_IS_SET( hw_caps, STMFBIO_VAR_CAPS_ALPHA_RAMP )); ++ ++ var_ex.caps |= STMFBIO_VAR_CAPS_ALPHA_RAMP; ++ var_ex.alpha_ramp[0] = config->alpha_ramp[0]; ++ var_ex.alpha_ramp[1] = config->alpha_ramp[3]; ++ } ++ ++ if (need_update) { ++ if (ioctl( stmfbdev->fd, STMFBIO_SET_PLANEMODE, &plane ) < 0) { ++ D_PERROR( " => STMFBIO_SET_PLANEINFO failed\n" ); ++ ++ /* not being able to set the new configuration is fatal, I ++ would say. */ ++ return errno2result( errno ); ++ } ++ ++ shared->cur_planeinfo = plane; ++ } ++ ++ if (var_ex.caps ++ && ioctl( stmfbdev->fd, STMFBIO_SET_VAR_SCREENINFO_EX, &var_ex) < 0) ++ D_PERROR( " => STMFBIO_SET_VAR_SCREENINFO_EX failed\n" ); ++ ++ /* Update CLUT? */ ++ if (D_FLAGS_IS_SET( updated, CLRCF_PALETTE ) && palette) { ++ struct fb_cmap *cmap = &shared->current_cmap; ++ unsigned int i; ++ ++ cmap->len = ((palette->num_entries <= 256) ++ ? palette->num_entries : 256); ++ ++ D_DEBUG_AT( STMfbdev_Layer, " +> palette (%u entries)\n", cmap->len); ++ ++ for (i = 0; i < cmap->len; ++i) { ++ /* expand to 16 bit */ ++ cmap->red[i] = palette->entries[i].r * 0x0101; ++ cmap->green[i] = palette->entries[i].g * 0x0101; ++ cmap->blue[i] = palette->entries[i].b * 0x0101; ++ cmap->transp[i] = (0xff - palette->entries[i].a) * 0x0101; ++ } ++ ++ if (ioctl( stmfbdev->fd, FBIOPUTCMAP, cmap ) < 0) ++ D_PERROR( "STMfbdev/Layer: Could not set the palette!\n" ); ++ } ++ ++ return DFB_OK; ++} ++ ++static DFBResult ++stmfbdevRemoveRegion( CoreLayer *layer, ++ void *driver_data, ++ void *layer_data, ++ void *region_data ) ++{ ++ const STMfbdev * const stmfbdev = driver_data; ++ STMfbdevLayerSharedData * const shared = layer_data; ++ ++ D_DEBUG_AT( STMfbdev_Layer, "%s()\n", __FUNCTION__ ); ++ ++ D_MAGIC_ASSERT( stmfbdev, STMfbdev ); ++ D_MAGIC_ASSERT( shared, STMfbdevLayerSharedData ); ++ ++ (void) stmfbdev; ++ (void) shared; ++ ++ return DFB_OK; ++} ++ ++static DFBResult ++stmfbdevFlipRegion( CoreLayer *layer, ++ void *driver_data, ++ void *layer_data, ++ void *region_data, ++ CoreSurface *surface, ++ DFBSurfaceFlipFlags flags, ++ CoreSurfaceBufferLock *left_lock, ++ CoreSurfaceBufferLock *right_lock ) ++{ ++ const STMfbdev * const stmfbdev = driver_data; ++ STMfbdevLayerSharedData * const shared = layer_data; ++ struct stmfbio_plane_pan pan; ++ ++ D_DEBUG_AT( STMfbdev_Layer, "%s()\n", __FUNCTION__ ); ++ ++ D_MAGIC_ASSERT( stmfbdev, STMfbdev ); ++ D_MAGIC_ASSERT( shared, STMfbdevLayerSharedData ); ++ ++ D_DEBUG_AT( STMfbdev_Layer, " -> buffer: %p\n", left_lock->buffer ); ++ D_DEBUG_AT( STMfbdev_Layer, ++ " -> offset 0x%.8lx, pitch %d, addr %p, phys 0x%.8lx\n", ++ left_lock->offset, left_lock->pitch, ++ left_lock->addr, left_lock->phys); ++ ++ pan.layerid = shared->cur_planeinfo.layerid; ++ pan.activate = (((flags & DSFLIP_WAITFORSYNC) == DSFLIP_ONSYNC) ++ ? STMFBIO_ACTIVATE_VBL : STMFBIO_ACTIVATE_IMMEDIATE); ++ pan.baseaddr = left_lock->phys; ++ ++ if (((flags & DSFLIP_WAITFORSYNC) == DSFLIP_WAITFORSYNC) ++ && !dfb_config->pollvsync_after) ++ dfb_screen_wait_vsync( layer->screen ); ++ ++ if (ioctl( stmfbdev->fd, STMFBIO_PAN_PLANE, &pan ) < 0) { ++ D_PERROR( "STMfbdev/Layer: Panning display to %lx (%s) failed\n", ++ pan.baseaddr, ++ (pan.activate & STMFBIO_ACTIVATE_VBL) ? "vbl" : "now"); ++ ++ return errno2result( errno ); ++ } ++ ++ if ((flags & DSFLIP_WAIT) ++ && (dfb_config->pollvsync_after || !(flags & DSFLIP_ONSYNC))) ++ dfb_screen_wait_vsync( dfb_screens_at( DSCID_PRIMARY ) ); ++ ++ dfb_surface_flip( surface, false ); ++ ++ shared->cur_planeinfo.config.baseaddr = pan.baseaddr; ++ ++ return DFB_OK; ++} ++ ++static DFBResult ++stmfbdevGetLevel( CoreLayer *layer, ++ void *driver_data, ++ void *layer_data, ++ int *level ) ++{ ++ const STMfbdev * const stmfbdev = driver_data; ++ const STMfbdevLayerSharedData * const shared = layer_data; ++ struct stmfbio_var_screeninfo_ex var_ex; ++ ++ D_DEBUG_AT( STMfbdev_Layer, "%s()\n", __FUNCTION__ ); ++ ++ D_MAGIC_ASSERT( stmfbdev, STMfbdev ); ++ D_MAGIC_ASSERT( shared, STMfbdevLayerSharedData ); ++ ++ (void) stmfbdev; ++ ++ if (!D_FLAGS_IS_SET( shared->orig_varex.caps, STMFBIO_VAR_CAPS_ZPOSITION )) ++ return DFB_UNSUPPORTED; ++ ++ var_ex.layerid = shared->orig_varex.layerid; ++ if (ioctl( stmfbdev->fd, STMFBIO_GET_VAR_SCREENINFO_EX, &var_ex ) < 0 ) ++ return errno2result( errno ); ++ ++ *level = (int) var_ex.z_position; ++ ++ return DFB_OK; ++} ++ ++static DFBResult ++stmfbdevSetLevel( CoreLayer *layer, ++ void *driver_data, ++ void *layer_data, ++ int level ) ++{ ++ const STMfbdev * const stmfbdev = driver_data; ++ const STMfbdevLayerSharedData * const shared = layer_data; ++ struct stmfbio_var_screeninfo_ex var_ex; ++ ++ D_DEBUG_AT( STMfbdev_Layer, "%s()\n", __FUNCTION__ ); ++ ++ D_MAGIC_ASSERT( stmfbdev, STMfbdev ); ++ D_MAGIC_ASSERT( shared, STMfbdevLayerSharedData ); ++ ++ (void) stmfbdev; ++ ++ D_DEBUG_AT( STMfbdev_Layer, " -> %d\n", level ); ++ ++ if (!D_FLAGS_IS_SET( shared->orig_varex.caps, STMFBIO_VAR_CAPS_ZPOSITION )) ++ return DFB_UNSUPPORTED; ++ ++ var_ex.layerid = shared->orig_varex.layerid; ++ var_ex.activate = STMFBIO_ACTIVATE_IMMEDIATE; ++ var_ex.caps = STMFBIO_VAR_CAPS_ZPOSITION; ++ var_ex.z_position = (level < 0) ? 0 : level; ++ ++ if (ioctl( stmfbdev->fd, STMFBIO_SET_VAR_SCREENINFO_EX, &var_ex ) < 0 ) ++ return errno2result( errno ); ++ ++ return DFB_OK; ++} ++ ++static DFBResult ++stmfbdevSetColorAdjustment( CoreLayer *layer, ++ void *driver_data, ++ void *layer_data, ++ DFBColorAdjustment *adjustment ) ++{ ++ const STMfbdev * const stmfbdev = driver_data; ++ const STMfbdevLayerSharedData * const shared = layer_data; ++ struct stmfbio_var_screeninfo_ex var_ex; ++ ++ D_DEBUG_AT( STMfbdev_Layer, "%s()\n", __FUNCTION__ ); ++ ++ D_MAGIC_ASSERT( stmfbdev, STMfbdev ); ++ D_MAGIC_ASSERT( shared, STMfbdevLayerSharedData ); ++ ++ (void) stmfbdev; ++ ++ if (D_FLAGS_INVALID( adjustment->flags, shared->supported_adjustments )) ++ return DFB_INVARG; ++ ++ var_ex.layerid = shared->orig_varex.layerid; ++ var_ex.activate = STMFBIO_ACTIVATE_IMMEDIATE; ++ var_ex.caps = 0; ++ ++ D_DEBUG_AT( STMfbdev_Layer, " -> flags: %x\n", adjustment->flags ); ++ ++ if (D_FLAGS_IS_SET( adjustment->flags, DCAF_BRIGHTNESS )) { ++ D_DEBUG_AT( STMfbdev_Layer, " +> brightness: 0x%04x\n", ++ adjustment->brightness ); ++ ++ if (D_FLAGS_IS_SET( shared->orig_varex.caps, ++ STMFBIO_VAR_CAPS_BRIGHTNESS )) { ++ var_ex.caps |= STMFBIO_VAR_CAPS_BRIGHTNESS; ++ var_ex.brightness = adjustment->brightness >> 8; ++ } ++ else { ++ var_ex.caps |= STMFBIO_VAR_CAPS_GAIN; ++ /* 0-0x8000 -> 0-255 */ ++ var_ex.gain = ((adjustment->brightness > 0x8000) ++ ? 255 ++ : (((adjustment->brightness >> 8) * 255) / 128) ++ ); ++ } ++ } ++ ++ if (D_FLAGS_IS_SET( adjustment->flags, DCAF_CONTRAST )) { ++ D_DEBUG_AT( STMfbdev_Layer, " +> contrast: 0x%04x\n", ++ adjustment->contrast ); ++ ++ var_ex.caps |= STMFBIO_VAR_CAPS_CONTRAST; ++ var_ex.contrast = adjustment->contrast >> 8; ++ } ++ ++ if (D_FLAGS_IS_SET( adjustment->flags, DCAF_HUE )) { ++ D_DEBUG_AT( STMfbdev_Layer, " +> hue: 0x%04x\n", ++ adjustment->hue ); ++ ++ var_ex.caps |= STMFBIO_VAR_CAPS_TINT; ++ var_ex.tint = adjustment->hue >> 8; ++ } ++ ++ if (D_FLAGS_IS_SET( adjustment->flags, DCAF_SATURATION )) { ++ D_DEBUG_AT( STMfbdev_Layer, " +> saturation: 0x%04x\n", ++ adjustment->saturation ); ++ ++ var_ex.caps |= STMFBIO_VAR_CAPS_SATURATION; ++ var_ex.saturation = adjustment->saturation >> 8; ++ } ++ ++ if (ioctl( stmfbdev->fd, STMFBIO_SET_VAR_SCREENINFO_EX, &var_ex ) < 0 ) ++ return errno2result( errno ); ++ ++ return DFB_OK; ++} ++ ++ ++DisplayLayerFuncs _g_stmfbdevLayerFuncs = { ++ .LayerDataSize = stmfbdevLayerDataSize, ++ .RegionDataSize = stmfbdevRegionDataSize, ++ ++ .InitLayer = stmfbdevInitLayer, ++ .ShutdownLayer = stmfbdevShutdownLayer, ++ ++ .TestRegion = stmfbdevTestRegion, ++ .AddRegion = stmfbdevAddRegion, ++ .SetRegion = stmfbdevSetRegion, ++ .RemoveRegion = stmfbdevRemoveRegion, ++ .FlipRegion = stmfbdevFlipRegion, ++ ++ .GetLevel = stmfbdevGetLevel, ++ .SetLevel = stmfbdevSetLevel, ++ ++ .SetColorAdjustment = stmfbdevSetColorAdjustment, ++}; +diff --git a/systems/stmfbdev/stmfbdev_screen.c b/systems/stmfbdev/stmfbdev_screen.c +new file mode 100644 +index 0000000..acee807 +--- /dev/null ++++ b/systems/stmfbdev/stmfbdev_screen.c +@@ -0,0 +1,1338 @@ ++/* ++ (c) Copyright 2010 STMicroelectronics (R&D) Ltd. ++ (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 André Draszik . ++ ++ Based on work by Denis Oliver Kropp , ++ Andreas Hundt , ++ Sven Neumann , ++ Ville Syrjälä and ++ Claudio Ciccani . ++ ++ This library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2 of the License, or (at your option) any later version. ++ ++ This library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with this library; if not, write to the ++ Free Software Foundation, Inc., 59 Temple Place - Suite 330, ++ Boston, MA 02111-1307, USA. ++*/ ++ ++#include ++ ++#include ++#include ++ ++#include ++#include ++ ++#include ++ ++#include ++ ++#include ++#include ++ ++#include ++ ++#include "stmfbdev.h" ++#include "fb.h" ++#ifndef FBIO_WAITFORVSYNC ++#define FBIO_WAITFORVSYNC _IOW('F', 0x20, u_int32_t) ++#endif ++ ++D_DEBUG_DOMAIN( STMfbdev_Screen, "STMfbdev/Screen", "STMfb System Module Screen Handling" ); ++ ++ ++typedef struct __attribute__((__aligned__(32))) _STMfbdevScreenVideoMode { ++ enum stmfbio_output_standard stm_standard; ++ ++ DFBScreenOutputResolution resolution; ++ DFBScreenEncoderScanMode scanmode; ++ DFBScreenEncoderFrequency frequency; ++ DFBScreenEncoderTVStandards tv_standard; ++ ++ struct _STMfbdevScreenVideoMode *next; ++ ++#if D_DEBUG_ENABLED ++ const char *frequency_str; ++ const char *resolution_str; ++ const char *scanmode_str; ++ const char *tv_standard_str; ++#endif ++} STMfbdevScreenVideoMode; ++ ++#if D_DEBUG_ENABLED ++# define ASSIGN(x,y) x = y, x##_str = #y ++#else /* D_DEBUG_ENABLED */ ++# define ASSIGN(x,y) x = y ++#endif /* D_DEBUG_ENABLED */ ++ ++typedef struct { ++ int magic; ++ ++ int screenid; ++ /* the DirectFB indexes, assigned to these encoders */ ++ unsigned int encoder_main; ++ unsigned int encoder_sd; ++ unsigned int encoder_analog; ++ unsigned int encoder_hdmi; ++ unsigned int encoder_dvo; ++ ++ STMfbdevScreenVideoMode *modes; /* list of modes supported */ ++ STMfbdevScreenVideoMode mode; /* current mode */ ++ ++ struct stmfbio_outputinfo orig_info; /* startup */ ++ struct stmfbio_output_configuration orig_config; /* startup */ ++ ++ FusionSHMPoolShared *shmpool; ++} STMfbdevScreenSharedData; ++ ++/******************************************************************************/ ++/* Parallel Count carries out bit counting in a parallel fashion. Consider n ++ after the first line has finished executing. Imagine splitting n into ++ pairs of bits. Each pair contains the number of ones in those two bit ++ positions in the original n. After the second line has finished executing, ++ each nibble contains the number of ones in those four bits positions in ++ the original n. Continuing this for five iterations, the 64 bits contain ++ the number of ones among these sixty-four bit positions in the original n. ++ That is what we wanted to compute. */ ++ ++#define TWO64(c) (0x1llu << (c)) ++#define MASK64(c) (((unsigned long long)(-1)) / (TWO64(TWO64(c)) + 1llu)) ++#define COUNT64(x,c) ((x) & MASK64(c)) + (((x) >> (TWO64(c))) & MASK64(c)) ++static unsigned int ++_bitcount64 (unsigned long long n) ++{ ++ n = COUNT64 (n, 0); ++ n = COUNT64 (n, 1); ++ n = COUNT64 (n, 2); ++ n = COUNT64 (n, 3); ++ n = COUNT64 (n, 4); ++ n = COUNT64 (n, 5); ++ return n ; ++} ++ ++ ++static void ++stmfbdevScreen_build_full_videomode( STMfbdevScreenVideoMode * const m ) ++{ ++ D_ASSERT( _bitcount64( m->stm_standard ) == 1 ); ++ ++ /* resolution */ ++ if (D_FLAGS_IS_SET( m->stm_standard, STMFBIO_STD_SMPTE274M )) ++ ASSIGN( m->resolution, DSOR_1920_1080 ); ++ else if (D_FLAGS_IS_SET( m->stm_standard, (STMFBIO_STD_WQFHD5660 ++ | STMFBIO_STD_WQFHD5650) )) ++ ASSIGN( m->resolution, DSOR_1440_540 ); ++ else if (D_FLAGS_IS_SET( m->stm_standard, STMFBIO_STD_SMPTE296M )) ++ ASSIGN( m->resolution, DSOR_1280_720 ); ++ else if (D_FLAGS_IS_SET( m->stm_standard, (STMFBIO_STD_QFHD1830 ++ | STMFBIO_STD_QFHD1825 ++ | STMFBIO_STD_QFHD3660 ++ | STMFBIO_STD_QFHD3650 ++ | STMFBIO_STD_QFHD5660 ++ | STMFBIO_STD_QFHD5650) )) ++ ASSIGN( m->resolution, DSOR_960_540 ); ++ else if (D_FLAGS_IS_SET( m->stm_standard, (STMFBIO_STD_576P_50 ++ | STMFBIO_STD_625_50) )) ++ ASSIGN( m->resolution, DSOR_720_576 ); ++ else if (D_FLAGS_IS_SET( m->stm_standard, (STMFBIO_STD_480P_60 ++ | STMFBIO_STD_480P_59_94 ++ | STMFBIO_STD_525_60) )) ++ ASSIGN( m->resolution, DSOR_720_480 ); ++ else if (D_FLAGS_IS_SET( m->stm_standard, STMFBIO_STD_VESA )) ++ ASSIGN( m->resolution, DSOR_640_480 ); ++ else ++ ASSIGN( m->resolution, DSOR_UNKNOWN ); ++ ++ /* scanmode */ ++ if (D_FLAGS_IS_SET( m->stm_standard, STMFBIO_STD_PROGRESSIVE )) ++ ASSIGN( m->scanmode, DSESM_PROGRESSIVE ); ++ else if (D_FLAGS_IS_SET( m->stm_standard, STMFBIO_STD_INTERLACED )) ++ ASSIGN( m->scanmode, DSESM_INTERLACED ); ++ else ++ ASSIGN( m->scanmode, DSESM_UNKNOWN ); ++ ++ /* frequency */ ++ if (D_FLAGS_IS_SET( m->stm_standard, STMFBIO_STD_1080P_23_976 )) ++ ASSIGN( m->frequency, DSEF_23_976HZ ); ++ else if (D_FLAGS_IS_SET( m->stm_standard, STMFBIO_STD_1080P_24 )) ++ ASSIGN( m->frequency, DSEF_24HZ ); ++ else if (D_FLAGS_IS_SET( m->stm_standard, (STMFBIO_STD_1080P_25 ++ | STMFBIO_STD_QFHD1825) )) ++ ASSIGN( m->frequency, DSEF_25HZ ); ++ else if (D_FLAGS_IS_SET( m->stm_standard, (STMFBIO_STD_1080P_29_97 ++ | STMFBIO_STD_QFHD1830) )) ++ ASSIGN( m->frequency, DSEF_29_97HZ ); ++ else if (D_FLAGS_IS_SET( m->stm_standard, STMFBIO_STD_1080P_30 )) ++ ASSIGN( m->frequency, DSEF_30HZ ); ++ else if (D_FLAGS_IS_SET( m->stm_standard, (STMFBIO_STD_1080P_50 ++ | STMFBIO_STD_1080I_50 ++ | STMFBIO_STD_720P_50 ++ | STMFBIO_STD_576P_50 ++ | STMFBIO_STD_625_50 ++ | STMFBIO_STD_QFHD3650 ++ | STMFBIO_STD_WQFHD5650 ++ | STMFBIO_STD_QFHD5650) )) ++ ASSIGN( m->frequency, DSEF_50HZ ); ++ else if (D_FLAGS_IS_SET( m->stm_standard, (STMFBIO_STD_1080P_59_94 ++ | STMFBIO_STD_1080I_59_94 ++ | STMFBIO_STD_720P_59_94 ++ | STMFBIO_STD_480P_59_94 ++ | STMFBIO_STD_VGA_59_94 ++ | STMFBIO_STD_525_60 ++ | STMFBIO_STD_QFHD3660 ++ | STMFBIO_STD_WQFHD5660 ++ | STMFBIO_STD_QFHD5660) )) ++ ASSIGN( m->frequency, DSEF_59_94HZ ); ++ else if (D_FLAGS_IS_SET( m->stm_standard, (STMFBIO_STD_1080P_60 ++ | STMFBIO_STD_1080I_60 ++ | STMFBIO_STD_720P_60 ++ | STMFBIO_STD_480P_60 ++ | STMFBIO_STD_VGA_60) )) ++ ASSIGN( m->frequency, DSEF_60HZ ); ++ else ++ ASSIGN( m->frequency, DSEF_UNKNOWN ); ++ ++ /* analogue standard - DSETV_PAL and DSETV_NTSC denote _any_ specific ++ compatible standard */ ++ if (D_FLAGS_IS_SET( m->stm_standard, STMFBIO_STD_PAL_BDGHI )) ++ ASSIGN( m->tv_standard, DSETV_PAL | DSETV_PAL_BG | DSETV_PAL_I ); ++ else if (D_FLAGS_IS_SET( m->stm_standard, STMFBIO_STD_PAL_M )) ++ ASSIGN( m->tv_standard, DSETV_PAL | DSETV_PAL_M ); ++ else if (D_FLAGS_IS_SET( m->stm_standard, STMFBIO_STD_PAL_N )) ++ ASSIGN( m->tv_standard, DSETV_PAL | DSETV_PAL_N ); ++ else if (D_FLAGS_IS_SET( m->stm_standard, STMFBIO_STD_PAL_Nc )) ++ ASSIGN( m->tv_standard, DSETV_PAL | DSETV_PAL_NC ); ++ else if (D_FLAGS_IS_SET( m->stm_standard, STMFBIO_STD_PAL_60 )) ++ ASSIGN( m->tv_standard, DSETV_PAL_60 ); ++ else if (D_FLAGS_IS_SET( m->stm_standard, STMFBIO_STD_SECAM )) ++ ASSIGN( m->tv_standard, DSETV_SECAM ); ++ else if (D_FLAGS_IS_SET( m->stm_standard, STMFBIO_STD_NTSC_M )) ++ ASSIGN( m->tv_standard, DSETV_NTSC ); ++ else if (D_FLAGS_IS_SET( m->stm_standard, STMFBIO_STD_NTSC_M_JP )) ++ ASSIGN( m->tv_standard, DSETV_NTSC | DSETV_NTSC_M_JPN ); ++ else if (D_FLAGS_IS_SET( m->stm_standard, STMFBIO_STD_NTSC_443 )) ++ ASSIGN( m->tv_standard, DSETV_NTSC | DSETV_NTSC_443 ); ++ else ++ ASSIGN( m->tv_standard, DSETV_DIGITAL ); ++} ++ ++static DFBResult ++stmfbdevScreen_set_mode( const STMfbdev * const stmfbdev, ++ STMfbdevScreenSharedData * const shared, ++ const STMfbdevScreenVideoMode * const m, ++ bool test ) ++{ ++ struct stmfbio_outputinfo info; ++ ++ D_DEBUG_AT( STMfbdev_Screen, "%s( mode: %p )\n", __FUNCTION__, m ); ++ ++ D_MAGIC_ASSERT( shared, STMfbdevScreenSharedData ); ++ D_ASSERT( m != NULL ); ++ ++ /* start with current config */ ++ info.outputid = shared->orig_info.outputid; ++ ++ info.activate = test ? STMFBIO_ACTIVATE_TEST : STMFBIO_ACTIVATE_IMMEDIATE; ++ info.standard = m->stm_standard; ++ ++ D_DEBUG_AT( STMfbdev_Screen, " -> %.16llx\n", info.standard ); ++ ++ if (ioctl( stmfbdev->fd, STMFBIO_SET_OUTPUTINFO, &info ) < 0) { ++ typeof (errno) errno_backup = errno; ++ D_DEBUG_AT( STMfbdev_Screen, " => FAILED (%d %m)!\n", errno ); ++ return errno2result( errno_backup ); ++ } ++ ++ D_DEBUG_AT( STMfbdev_Screen, " => SUCCESS\n" ); ++ ++ /* remember new config */ ++ if (!test) { ++ shared->orig_info.standard = info.standard; ++ ++ if (&shared->mode != m) ++ shared->mode = *m; ++ } ++ ++ return DFB_OK; ++} ++ ++static DFBResult ++stmfbdevScreen_get_supported_modes( const STMfbdev * const stmfbdev, ++ STMfbdevScreenSharedData *shared ) ++{ ++ struct stmfbio_outputstandards standards; ++ unsigned int n_modes; ++ ++ D_DEBUG_AT( STMfbdev_Screen, "%s()\n", __FUNCTION__ ); ++ ++ D_MAGIC_ASSERT( shared, STMfbdevScreenSharedData ); ++ ++ /* get output standards supported on the current platform */ ++ standards.outputid = shared->orig_info.outputid; ++ if (ioctl( stmfbdev->fd, STMFBIO_GET_OUTPUTSTANDARDS, &standards ) < 0) { ++ typeof (errno) errno_backup = errno; ++ D_PERROR( "STMfbdev/Screen: Could not get supported output mode!\n" ); ++ return errno2result( errno_backup ); ++ } ++ ++ n_modes = _bitcount64( standards.all_standards ); ++ D_DEBUG_AT( STMfbdev_Screen, " -> %u modes\n", n_modes ); ++ ++ shared->modes = SHCALLOC( shared->shmpool, n_modes ? : 1, ++ sizeof(STMfbdevScreenVideoMode) ); ++ if (!shared->modes) ++ return D_OOSHM(); ++ ++ /* in the (unlikely) case no modes where reported, try the current ++ mode, and if that is not possible, fail. */ ++ if (!n_modes) { ++ *shared->modes = shared->mode; ++ if (stmfbdevScreen_set_mode( stmfbdev, shared, shared->modes, true )) { ++ D_ERROR( "STMfbdev/Screen: " ++ "No modes announced and current mode not supported!\n" ); ++ ++ return DFB_INIT; ++ } ++ ++ D_DEBUG_AT( STMfbdev_Screen, " -> Modelist\n" ); ++ D_DEBUG_AT( STMfbdev_Screen, " +> %.16llx: %s %s %s %s\n", ++ shared->mode.stm_standard, shared->mode.resolution_str, ++ shared->mode.scanmode_str, shared->mode.frequency_str, ++ shared->mode.tv_standard_str ); ++ ++ return DFB_OK; ++ } ++ ++ { ++ STMfbdevScreenVideoMode *m = shared->modes; ++ ++ D_DEBUG_AT( STMfbdev_Screen, " -> Modelist\n" ); ++ do { ++ m->stm_standard = standards.all_standards & -standards.all_standards; ++ standards.all_standards &= ~m->stm_standard; ++ ++ stmfbdevScreen_build_full_videomode( m ); ++ D_DEBUG_AT( STMfbdev_Screen, " +> %.16llx: %.2x %.2x %.2x %.3x %s %s %s %s\n", ++ m->stm_standard, m->resolution, m->scanmode, ++ m->frequency, m->tv_standard, ++ m->resolution_str, m->scanmode_str, ++ m->frequency_str, m->tv_standard_str ); ++ ++ m->next = m+1; ++ ++m; ++ } while (--n_modes > 0); ++ --m; m->next = NULL; ++ } ++ ++ D_ASSUME( n_modes == 0 ); ++ D_ASSUME( standards.all_standards == STMFBIO_STD_UNKNOWN ); ++ ++ return DFB_OK; ++} ++ ++static const STMfbdevScreenVideoMode * ++stmfbdevScreen_find_mode (const STMfbdevScreenSharedData * const shared, ++ const DFBScreenEncoderConfig * const config) ++{ ++ const STMfbdevScreenVideoMode *m, *best_match; ++ ++ D_MAGIC_ASSERT( shared, STMfbdevScreenSharedData ); ++ D_ASSERT( config != NULL ); ++ ++ if (!D_FLAGS_ARE_SET (config->flags, (DSECONF_SCANMODE ++ | DSECONF_FREQUENCY ++ | DSECONF_RESOLUTION))) ++ return NULL; ++ ++ D_DEBUG_AT( STMfbdev_Screen, "%s: %.2x %.2x %.2x %s%.3x%s\n", ++ __FUNCTION__, ++ config->resolution, config->scanmode, config->frequency, ++ (config->flags & DSECONF_TV_STANDARD) ? "" : " (", ++ config->tv_standard, ++ (config->flags & DSECONF_TV_STANDARD) ? "" : ")" ); ++ ++ for (best_match = NULL, m = shared->modes; m; m = m->next) { ++ if (config->frequency != m->frequency) ++ continue; ++ if (config->scanmode != m->scanmode) ++ continue; ++ if (config->resolution != m->resolution) ++ continue; ++ ++ if (!(config->flags & DSECONF_TV_STANDARD)) { ++ D_DEBUG_AT( STMfbdev_Screen, " -> exact: %s %s %s (%s)\n", ++ m->resolution_str, m->scanmode_str, ++ m->frequency_str, m->tv_standard_str ); ++ return m; ++ } ++ ++ if (config->tv_standard == DSETV_ALL) ++ best_match = m; ++ else if ((config->tv_standard & m->tv_standard) == config->tv_standard) { ++ /* exact match */ ++ D_DEBUG_AT( STMfbdev_Screen, " -> exact: %s %s %s %s\n", ++ m->resolution_str, m->scanmode_str, ++ m->frequency_str, m->tv_standard_str ); ++ return m; ++ } ++ } ++ ++ if (!best_match) ++ D_WARN( " -> couldn't find a matching output standard for res/scan/hz/tv: %.2x %.2x %.2x %s%.3x%s\n", ++ config->resolution, config->scanmode, config->frequency, ++ (config->flags & DSECONF_TV_STANDARD) ? "" : "(", ++ config->tv_standard, ++ (config->flags & DSECONF_TV_STANDARD) ? "" : ")" ); ++ else ++ D_DEBUG_AT( STMfbdev_Screen, ++ " -> best match: %s %s %s %s\n", ++ best_match->resolution_str, best_match->scanmode_str, ++ best_match->frequency_str, ++ best_match->tv_standard_str ); ++ ++ return best_match; ++} ++ ++/******************************************************************************/ ++ ++static int ++stmfbdevScreenDataSize( void ) ++{ ++ D_DEBUG_AT( STMfbdev_Screen, "%s() <- %u\n", ++ __FUNCTION__, sizeof(STMfbdevScreenSharedData) ); ++ ++ return sizeof(STMfbdevScreenSharedData); ++} ++ ++static DFBResult ++stmfbdevInitScreen( CoreScreen *screen, ++ CoreGraphicsDevice *device, ++ void *driver_data, ++ void *screen_data, ++ DFBScreenDescription *description ) ++{ ++ const STMfbdev * const stmfbdev = driver_data; ++ STMfbdevScreenSharedData * const shared = screen_data; ++ u32 hw_caps; ++ int n_outputs = -1; ++ int n_encoders = -1; ++ ++ D_DEBUG_AT( STMfbdev_Screen, "%s( %p %d )\n", __FUNCTION__, screen, ++ stmfbdev->shared->num_screens + 1 ); ++ ++ D_MAGIC_ASSERT( stmfbdev, STMfbdev ); ++ D_ASSERT( shared != NULL ); ++ ++ D_MAGIC_SET( shared, STMfbdevScreenSharedData ); ++ ++ shared->screenid = stmfbdev->shared->num_screens++; ++ ++ shared->shmpool = stmfbdev->shared->shmpool; ++ ++ shared->encoder_main ++ = shared->encoder_sd ++ = shared->encoder_analog ++ = shared->encoder_hdmi ++ = shared->encoder_dvo ++ = -1; ++ ++ /* remember startup output info, so we can restore it on shutdown*/ ++ shared->orig_info.outputid = STMFBIO_OUTPUTID_MAIN; ++ if (ioctl( stmfbdev->fd, STMFBIO_GET_OUTPUTINFO, &shared->orig_info ) < 0) { ++ typeof (errno) errno_backup = errno; ++ D_PERROR( "STMfbdev/Screen: Could not get current output mode\n" ); ++ return errno2result( errno_backup ); ++ } ++ ++/* D_DEBUG_AT( STMfbdev_Screen, ++ " -> current: %dx%d @ %d,%d-%dx%d (%d: %s) %ubpp pitch %u @ 0x%08lx\n", ++ pc->source.w, pc->source.h, pc->dest.x, pc->dest.y, ++ pc->dest.dim.w, pc->dest.dim.h, pc->format, ++ dfb_pixelformat_name( stmfb_to_dsbf( pc->format ) ), ++ pc->bitdepth, pc->pitch, pc->baseaddr ); ++*/ ++ D_DEBUG_AT( STMfbdev_Screen, " -> current mode: 0x%.16llx\n", ++ shared->orig_info.standard ); ++ ++ /* remember stmfb's output config */ ++ shared->orig_config.outputid = STMFBIO_OUTPUTID_MAIN; ++ if (ioctl( stmfbdev->fd, ++ STMFBIO_GET_OUTPUT_CONFIG, &shared->orig_config ) < 0) { ++ typeof (errno) errno_backup = errno; ++ D_PERROR( "STMfbdev/Screen: Could not get current output config\n" ); ++ return errno2result( errno_backup ); ++ } ++ hw_caps = shared->orig_config.caps; ++ D_DEBUG_AT( STMfbdev_Screen, " -> extended caps: 0x%08x\n", hw_caps ); ++ ++ /* Set the screen name */ ++ snprintf( description->name, sizeof (description->name), ++ "STMfbdev Screen %d", shared->screenid ); ++ ++ /* Set the screen capabilities. */ ++ description->caps = DSCCAPS_VSYNC; ++ ++ if (D_FLAGS_IS_SET( hw_caps, STMFBIO_OUTPUT_CAPS_MIXER_BACKGROUND )) { ++ D_DEBUG_AT( STMfbdev_Screen, " +> have mixer background\n" ); ++ description->caps |= DSCCAPS_MIXERS; ++ ++description->mixers; ++ } ++ ++ if (D_FLAGS_IS_SET( hw_caps, (STMFBIO_OUTPUT_CAPS_ANALOGUE_CONFIG ++ | STMFBIO_OUTPUT_CAPS_HDMI_CONFIG ++ | STMFBIO_OUTPUT_CAPS_DVO_CONFIG) )) { ++ D_DEBUG_AT( STMfbdev_Screen, " +> have main encoder\n" ); ++ description->caps |= DSCCAPS_ENCODERS; ++ shared->encoder_main = ++n_encoders; ++ } ++ /* all additional encoders are slaved off the main one */ ++ if (D_FLAGS_IS_SET( hw_caps, STMFBIO_OUTPUT_CAPS_ANALOGUE_CONFIG )) { ++ D_DEBUG_AT( STMfbdev_Screen, " +> have analogue\n" ); ++ if (D_FLAGS_IS_SET( hw_caps, STMFBIO_OUTPUT_CAPS_SDTV_ENCODING )) ++ D_DEBUG_AT( STMfbdev_Screen, " +> with SDTV\n" ); ++ shared->encoder_analog = ++n_encoders; ++ } ++ if (D_FLAGS_IS_SET( hw_caps, STMFBIO_OUTPUT_CAPS_HDMI_CONFIG )) { ++ D_DEBUG_AT( STMfbdev_Screen, " +> have HDMI\n" ); ++ shared->encoder_hdmi = ++n_encoders; ++ } ++ if (D_FLAGS_IS_SET( hw_caps, STMFBIO_OUTPUT_CAPS_DVO_CONFIG )) { ++ D_DEBUG_AT( STMfbdev_Screen, " +> have DVO\n" ); ++ shared->encoder_dvo = ++n_encoders; ++ } ++ if (D_FLAGS_IS_SET( hw_caps, STMFBIO_OUTPUT_CAPS_PSI_MASK )) { ++ D_DEBUG_AT( STMfbdev_Screen, " +> have PSI\n" ); ++ description->caps |= DSCCAPS_ENCODERS; ++ shared->encoder_sd = ++n_encoders; ++ } ++ ++ description->outputs = ++n_outputs; ++ description->encoders = ++n_encoders; ++ ++ return DFB_OK; ++} ++ ++static DFBResult ++stmfbdevShutdownScreen( CoreScreen *screen, ++ void *driver_data, ++ void *screen_data ) ++{ ++ const STMfbdev * const stmfbdev = driver_data; ++ STMfbdevScreenSharedData * const shared = screen_data; ++ ++ D_DEBUG_AT( STMfbdev_Screen, "%s( %p )\n", __FUNCTION__, screen ); ++ ++ D_MAGIC_ASSERT( stmfbdev, STMfbdev ); ++ D_MAGIC_ASSERT( shared, STMfbdevScreenSharedData ); ++ ++ /* try and restore the driver's state. */ ++ shared->orig_info.activate = STMFBIO_ACTIVATE_IMMEDIATE; ++ if (ioctl( stmfbdev->fd, STMFBIO_SET_OUTPUTINFO, &shared->orig_info ) < 0) ++ D_PERROR( "STMfbdev/Screen: Could not restore output mode\n" ); ++ ++ shared->orig_config.activate = STMFBIO_ACTIVATE_IMMEDIATE; ++ if (ioctl( stmfbdev->fd, STMFBIO_SET_OUTPUT_CONFIG, &shared->orig_config ) < 0) ++ D_PERROR( "STMfbdev/Screen: Could not restore output config: %.8x\n", ++ shared->orig_config.failed ); ++ ++ SHFREE( shared->shmpool, shared->modes ); ++ ++ D_MAGIC_CLEAR( shared ); ++ ++ return DFB_OK; ++} ++ ++/* Mixer configuration */ ++static DFBResult ++stmfbdevInitMixer( CoreScreen *screen, ++ void *driver_data, ++ void *screen_data, ++ int mixer, ++ DFBScreenMixerDescription *description, ++ DFBScreenMixerConfig *config ) ++{ ++ const STMfbdev * const stmfbdev = driver_data; ++ const STMfbdevScreenSharedData * const shared = screen_data; ++ const struct stmfbio_output_configuration *oc; ++ ++ D_DEBUG_AT( STMfbdev_Screen, "%s( %p %d )\n", ++ __FUNCTION__, screen, mixer ); ++ ++ D_MAGIC_ASSERT( stmfbdev, STMfbdev ); ++ D_MAGIC_ASSERT( shared, STMfbdevScreenSharedData ); ++ ++ (void) stmfbdev; ++ ++ description->caps = DSMCAPS_FULL | DSMCAPS_BACKGROUND; ++ ++ DFB_DISPLAYLAYER_IDS_ADD( description->layers, DLID_PRIMARY ); ++ ++ snprintf( description->name, sizeof (description->name), ++ "STMfbdev Mixer" ); ++ ++ config->flags = DSMCONF_TREE | DSMCONF_BACKGROUND; ++ config->tree = DSMT_FULL; ++ ++ oc = &shared->orig_config; ++ config->background.a = (oc->mixer_background >> 24) & 0xff; ++ config->background.r = (oc->mixer_background >> 16) & 0xff; ++ config->background.g = (oc->mixer_background >> 8) & 0xff; ++ config->background.b = (oc->mixer_background >> 0) & 0xff; ++ ++ D_DEBUG_AT( STMfbdev_Screen, " -> background colour: 0x%08x\n", ++ oc->mixer_background ); ++ ++ return DFB_OK; ++} ++ ++static DFBResult ++stmfbdevDoMixerConfig( CoreScreen *screen, ++ const STMfbdev * const stmfbdev, ++ const STMfbdevScreenSharedData * const shared, ++ int mixer, ++ const DFBScreenMixerConfig *config, ++ DFBScreenMixerConfigFlags *failed, ++ bool test ) ++{ ++ DFBScreenMixerConfigFlags fail = DSMCONF_NONE; ++ struct stmfbio_output_configuration cfg; ++ ++ D_DEBUG_AT( STMfbdev_Screen, "%s( %p %d ) test: %c\n", ++ __FUNCTION__, screen, mixer, test ? 'y' : 'n' ); ++ ++ D_MAGIC_ASSERT( stmfbdev, STMfbdev ); ++ D_MAGIC_ASSERT( shared, STMfbdevScreenSharedData ); ++ ++ if (!D_FLAGS_ARE_IN( config->flags, DSMCONF_TREE | DSMCONF_BACKGROUND )) ++ fail |= (config->flags & ~(DSMCONF_TREE | DSMCONF_BACKGROUND)); ++ ++ cfg.outputid = STMFBIO_OUTPUTID_MAIN; ++ cfg.activate = test ? STMFBIO_ACTIVATE_TEST : STMFBIO_ACTIVATE_IMMEDIATE; ++ cfg.caps = 0; ++ ++ if (D_FLAGS_IS_SET( config->flags, DSMCONF_BACKGROUND )) { ++ D_DEBUG_AT( STMfbdev_Screen, " -> background %.2x%.2x%.2x%.2x\n", ++ config->background.a, config->background.r, ++ config->background.g, config->background.b ); ++ ++ cfg.caps |= STMFBIO_OUTPUT_CAPS_MIXER_BACKGROUND; ++ cfg.mixer_background = (0 ++ | (config->background.a << 24) ++ | (config->background.r << 16) ++ | (config->background.g << 8) ++ | (config->background.b << 0)); ++ } ++ ++ if (ioctl( stmfbdev->fd, STMFBIO_SET_OUTPUT_CONFIG, &cfg ) < 0) ++ fail |= DSMCONF_BACKGROUND; ++ ++ if (D_FLAGS_IS_SET( config->flags, DSMCONF_TREE ) ++ && D_FLAGS_INVALID( config->tree, DSMT_FULL )) ++ fail |= (config->tree & ~DSMT_FULL); ++ ++ if (failed) ++ *failed = fail; ++ ++ if (fail) { ++ D_DEBUG_AT( STMfbdev_Screen, " => FAILED!\n" ); ++ return DFB_UNSUPPORTED; ++ } ++ ++ D_DEBUG_AT( STMfbdev_Screen, " => SUCCESS\n" ); ++ ++ return DFB_OK; ++} ++ ++static DFBResult ++stmfbdevTestMixerConfig( CoreScreen *screen, ++ void *driver_data, ++ void *screen_data, ++ int mixer, ++ const DFBScreenMixerConfig *config, ++ DFBScreenMixerConfigFlags *failed ) ++{ ++ return stmfbdevDoMixerConfig (screen, driver_data, screen_data, mixer, ++ config, failed, true); ++} ++ ++static DFBResult ++stmfbdevSetMixerConfig( CoreScreen *screen, ++ void *driver_data, ++ void *screen_data, ++ int mixer, ++ const DFBScreenMixerConfig *config ) ++{ ++ return stmfbdevDoMixerConfig (screen, driver_data, screen_data, mixer, ++ config, NULL, false); ++} ++ ++ ++/* Encoder configuration */ ++static DFBResult ++stmfbdevInitEncoder( CoreScreen *screen, ++ void *driver_data, ++ void *screen_data, ++ int encoder, ++ DFBScreenEncoderDescription *description, ++ DFBScreenEncoderConfig *config ) ++{ ++ const STMfbdev * const stmfbdev = driver_data; ++ STMfbdevScreenSharedData * const shared = screen_data; ++ DFBResult res; ++ const struct stmfbio_output_configuration *oc; ++ u32 hw_caps; ++ const STMfbdevScreenVideoMode *m; ++ ++ D_DEBUG_AT( STMfbdev_Screen, "%s( %p %d )\n", ++ __FUNCTION__, screen, encoder ); ++ ++ D_MAGIC_ASSERT( stmfbdev, STMfbdev ); ++ D_MAGIC_ASSERT( shared, STMfbdevScreenSharedData ); ++ ++ oc = &shared->orig_config; ++ hw_caps = oc->caps; ++ ++ if (encoder == shared->encoder_main) { ++ /* current mode */ ++ shared->mode.stm_standard = shared->orig_info.standard; ++ stmfbdevScreen_build_full_videomode( &shared->mode ); ++ ++ res = stmfbdevScreen_get_supported_modes( stmfbdev, shared ); ++ if (res != DFB_OK) ++ return res; ++ ++ /* master DFBScreenEncoder - signals and connectors can not be ++ changed on this one - only the output standard. */ ++ snprintf( description->name, sizeof (description->name), ++ "STMfbdev master output" ); ++ ++ D_ASSUME( D_FLAGS_IS_SET( hw_caps, ++ (STMFBIO_OUTPUT_CAPS_ANALOGUE_CONFIG ++ | STMFBIO_OUTPUT_CAPS_HDMI_CONFIG ++ | STMFBIO_OUTPUT_CAPS_DVO_CONFIG) )); ++ ++ description->type = DSET_DIGITAL; ++ ++ /* supported resolutions */ ++ for (m = shared->modes; m; m = m->next) ++ description->all_resolutions |= m->resolution; ++ if (description->all_resolutions) ++ description->caps = (DSECAPS_SCANMODE | DSECAPS_FREQUENCY ++ | DSECAPS_RESOLUTION); ++ ++ if (D_FLAGS_IS_SET( oc->caps, STMFBIO_OUTPUT_CAPS_ANALOGUE_CONFIG )) { ++ D_DEBUG_AT( STMfbdev_Screen, " +> have analogue (slave)\n" ); ++ description->caps |= (DSECAPS_CONNECTORS ++ | DSECAPS_OUT_SIGNALS); ++ ++ description->all_connectors |= DSOC_COMPONENT; ++ description->out_signals |= DSOS_RGB | DSOS_YCBCR; ++ ++ if (D_FLAGS_IS_SET( oc->caps, STMFBIO_OUTPUT_CAPS_SDTV_ENCODING )) { ++ D_DEBUG_AT( STMfbdev_Screen, " +> with SDTV\n" ); ++ description->type |= DSET_TV; ++ /* add in supported TV standards */ ++ for (m = shared->modes; m; m = m->next) ++ description->tv_standards |= m->tv_standard; ++ D_FLAGS_CLEAR( description->tv_standards, DSETV_DIGITAL ); ++ if (description->tv_standards) ++ D_FLAGS_SET( description->caps, DSECAPS_TV_STANDARDS ); ++ ++ description->all_connectors |= DSOC_SCART | DSOC_YC | DSOC_CVBS; ++ description->out_signals |= DSOS_RGB | DSOS_YC | DSOS_CVBS; ++ } ++ } ++ if (D_FLAGS_IS_SET( oc->caps, STMFBIO_OUTPUT_CAPS_HDMI_CONFIG )) { ++ D_DEBUG_AT( STMfbdev_Screen, " +> have HDMI (slave)\n" ); ++ description->caps |= (DSECAPS_CONNECTORS ++ | DSECAPS_OUT_SIGNALS); ++ ++ description->all_connectors |= DSOC_HDMI; ++ description->out_signals |= DSOS_HDMI | DSOS_RGB | DSOS_YCBCR; ++ } ++ if (D_FLAGS_IS_SET( oc->caps, STMFBIO_OUTPUT_CAPS_DVO_CONFIG )) { ++ D_DEBUG_AT( STMfbdev_Screen, " +> have DVO (slave)\n" ); ++ description->caps |= (DSECAPS_CONNECTORS ++ | DSECAPS_OUT_SIGNALS); ++ ++ description->all_connectors |= DSOC_656; ++ description->out_signals |= DSOS_656; ++ } ++ ++ /* current config */ ++ m = &shared->mode; ++ config->resolution = m->resolution; ++ config->scanmode = m->scanmode; ++ config->frequency = m->frequency; ++ config->tv_standard = m->tv_standard; ++ ++ config->flags |= (m->resolution != DSOR_UNKNOWN) ? DSECONF_RESOLUTION : 0; ++ config->flags |= (m->scanmode != DSESM_UNKNOWN) ? DSECONF_SCANMODE : 0; ++ config->flags |= (m->frequency != DSEF_UNKNOWN) ? DSECONF_FREQUENCY : 0; ++ config->flags |= (m->tv_standard != DSETV_UNKNOWN) ? DSECONF_TV_STANDARD : 0; ++ } ++ else if (encoder == shared->encoder_analog) { ++ D_ASSUME( D_FLAGS_IS_SET( hw_caps, STMFBIO_OUTPUT_CAPS_ANALOGUE_CONFIG ) ); ++ ++ snprintf( description->name, sizeof (description->name), ++ "STMfbdev Analogue slave" ); ++ ++ /* caps */ ++ description->caps |= DSECAPS_OUT_SIGNALS | DSECAPS_CONNECTORS; ++ description->all_connectors |= DSOC_COMPONENT; ++ description->out_signals = DSOS_RGB | DSOS_YCBCR; ++ if (D_FLAGS_IS_SET( hw_caps, STMFBIO_OUTPUT_CAPS_SDTV_ENCODING )) { ++ description->all_connectors |= DSOC_SCART | DSOC_YC | DSOC_CVBS; ++ description->out_signals |= DSOS_CVBS | DSOS_YC; ++ } ++ ++ /* current config */ ++ D_FLAGS_SET( config->flags, DSECONF_OUT_SIGNALS | DSECONF_CONNECTORS ); ++ D_FLAGS_SET( config->out_connectors, DSOC_COMPONENT ); ++ if (D_FLAGS_IS_SET( hw_caps, STMFBIO_OUTPUT_CAPS_SDTV_ENCODING )) ++ config->out_connectors |= DSOC_SCART | DSOC_YC | DSOC_CVBS; ++ ++ D_FLAGS_SET( config->out_signals, DSOS_NONE ); ++ if (D_FLAGS_IS_SET( oc->analogue_config, STMFBIO_OUTPUT_ANALOGUE_RGB )) ++ D_FLAGS_SET( config->out_signals, DSOS_RGB ); ++ if (D_FLAGS_IS_SET( oc->analogue_config, STMFBIO_OUTPUT_ANALOGUE_YPrPb )) ++ D_FLAGS_SET( config->out_signals, DSOS_YCBCR ); ++ if (D_FLAGS_IS_SET( oc->analogue_config, STMFBIO_OUTPUT_ANALOGUE_YC )) ++ D_FLAGS_SET( config->out_signals, DSOS_YC ); ++ if (D_FLAGS_IS_SET( oc->analogue_config, STMFBIO_OUTPUT_ANALOGUE_CVBS )) ++ D_FLAGS_SET( config->out_signals, DSOS_CVBS ); ++ } ++ else if (encoder == shared->encoder_hdmi) { ++ D_ASSUME( D_FLAGS_IS_SET( hw_caps, STMFBIO_OUTPUT_CAPS_HDMI_CONFIG ) ); ++ ++ snprintf( description->name, sizeof (description->name), ++ "STMfbdev HDMI slave" ); ++ ++ /* caps */ ++ description->caps |= DSECAPS_OUT_SIGNALS | DSECAPS_CONNECTORS; ++ description->all_connectors |= DSOC_HDMI; ++ description->out_signals |= DSOS_HDMI | DSOS_RGB | DSOS_YCBCR; ++ ++ /* current config */ ++ D_FLAGS_SET( config->flags, DSECONF_OUT_SIGNALS | DSECONF_CONNECTORS ); ++ D_FLAGS_SET( config->out_connectors, DSOC_HDMI ); ++ ++ if (D_FLAGS_IS_SET( oc->hdmi_config, STMFBIO_OUTPUT_HDMI_DISABLED )) ++ D_FLAGS_SET( config->out_signals, DSOS_NONE ); ++ else { ++ D_FLAGS_SET( config->out_signals, DSOS_HDMI ); ++ /* A bit of bending the interface to specify the HDMI ++ colourspace */ ++ if (D_FLAGS_IS_SET( oc->hdmi_config, STMFBIO_OUTPUT_HDMI_YUV )) ++ D_FLAGS_SET( config->out_signals, DSOS_YCBCR ); ++ else ++ D_FLAGS_SET( config->out_signals, DSOS_RGB ); ++ } ++ } ++ else if (encoder == shared->encoder_dvo) { ++ D_ASSUME( D_FLAGS_IS_SET( hw_caps, STMFBIO_OUTPUT_CAPS_DVO_CONFIG ) ); ++ ++ snprintf( description->name, sizeof (description->name), ++ "STMfbdev DVO slave" ); ++ ++ /* caps */ ++ description->caps |= DSECAPS_OUT_SIGNALS | DSECAPS_CONNECTORS; ++ description->all_connectors |= DSOC_656; ++ description->out_signals |= DSOS_656; ++ ++ /* current config */ ++ D_FLAGS_SET( config->flags, DSECONF_OUT_SIGNALS | DSECONF_CONNECTORS ); ++ D_FLAGS_SET( config->out_connectors, DSOC_656 ); ++ ++ if (D_FLAGS_IS_SET( oc->dvo_config, STMFBIO_OUTPUT_DVO_DISABLED )) ++ D_FLAGS_SET( config->out_signals, DSOS_NONE ); ++ else { ++ D_FLAGS_SET( config->out_signals, DSOS_656 ); ++ /* A bit of bending the interface to specify the DVO ++ colourspace */ ++ switch( oc->dvo_config & STMFBIO_OUTPUT_DVO_MODE_MASK ) { ++ case STMFBIO_OUTPUT_DVO_YUV_444_16BIT: ++ case STMFBIO_OUTPUT_DVO_YUV_444_24BIT: ++ case STMFBIO_OUTPUT_DVO_YUV_422_16BIT: ++ D_FLAGS_SET( config->out_signals, DSOS_YCBCR ); ++ break; ++ ++ case STMFBIO_OUTPUT_DVO_ITUR656: ++ case STMFBIO_OUTPUT_DVO_RGB_24BIT: ++ D_FLAGS_SET( config->out_signals, DSOS_RGB ); ++ ++ default: ++ /* should not be reached */ ++ break; ++ } ++ } ++ } ++ else if (encoder == shared->encoder_sd) { ++ D_ASSUME( D_FLAGS_IS_SET( oc->caps, STMFBIO_OUTPUT_CAPS_SDTV_ENCODING )); ++ D_ASSUME( D_FLAGS_IS_SET( oc->caps, STMFBIO_OUTPUT_CAPS_PSI_MASK )); ++ ++ /* the outputs and signals are handled by the main analogue ++ DFBScreenEncoder, this one just adds in the colour ++ adjustments. */ ++ snprintf( description->name, sizeof (description->name), ++ "STMfbdev DENC slave" ); ++ ++ /* caps and current config in one go */ ++ if (D_FLAGS_IS_SET( hw_caps, STMFBIO_OUTPUT_CAPS_BRIGHTNESS )) { ++ /* caps */ ++ description->caps |= DSECAPS_BRIGHTNESS; ++ /* current config */ ++ config->flags |= DSECONF_ADJUSTMENT; ++ config->adjustment.flags |= DCAF_BRIGHTNESS; ++ config->adjustment.brightness = ((u16) oc->brightness) << 8; ++ D_DEBUG_AT( STMfbdev_Screen, " => brightness: %u\n", ++ config->adjustment.brightness ); ++ } ++ if (D_FLAGS_IS_SET( hw_caps, STMFBIO_OUTPUT_CAPS_CONTRAST )) { ++ /* caps */ ++ description->caps |= DSECAPS_CONTRAST; ++ /* current config */ ++ config->flags |= DSECONF_ADJUSTMENT; ++ config->adjustment.flags |= DCAF_CONTRAST; ++ config->adjustment.contrast = ((u16) oc->contrast) << 8; ++ D_DEBUG_AT( STMfbdev_Screen, " => contrast: %u\n", ++ config->adjustment.contrast ); ++ } ++ if (D_FLAGS_IS_SET( hw_caps, STMFBIO_OUTPUT_CAPS_SATURATION )) { ++ /* caps */ ++ description->caps |= DSECAPS_SATURATION; ++ /* current config */ ++ config->flags |= DSECONF_ADJUSTMENT; ++ config->adjustment.flags |= DCAF_SATURATION; ++ config->adjustment.saturation = ((u16) oc->saturation) << 8; ++ D_DEBUG_AT( STMfbdev_Screen, " => saturation: %u\n", ++ config->adjustment.saturation ); ++ } ++ if (D_FLAGS_IS_SET( hw_caps, STMFBIO_OUTPUT_CAPS_HUE )) { ++ /* caps */ ++ description->caps |= DSECAPS_HUE; ++ /* current config */ ++ config->flags |= DSECONF_ADJUSTMENT; ++ config->adjustment.flags |= DCAF_HUE; ++ config->adjustment.hue = ((u16) oc->hue) << 8; ++ D_DEBUG_AT( STMfbdev_Screen, " => hue: %u\n", ++ config->adjustment.hue ); ++ } ++ } ++ else ++ return DFB_BUG; ++ ++ return DFB_OK; ++} ++ ++static DFBResult ++stmfbdevDoEncoderConfig( CoreScreen *screen, ++ void *driver_data, ++ void *screen_data, ++ int encoder, ++ const DFBScreenEncoderConfig *config, ++ DFBScreenEncoderConfigFlags *failed, ++ bool test ) ++{ ++ const STMfbdev * const stmfbdev = driver_data; ++ STMfbdevScreenSharedData * const shared = screen_data; ++ u32 hw_caps; ++ struct stmfbio_output_configuration cfg; ++ ++ D_DEBUG_AT( STMfbdev_Screen, "%s( %p %d ) test: %c\n", ++ __FUNCTION__, screen, encoder, test ? 'y' : 'n' ); ++ ++ D_MAGIC_ASSERT( stmfbdev, STMfbdev ); ++ D_MAGIC_ASSERT( shared, STMfbdevScreenSharedData ); ++ ++ cfg.outputid = STMFBIO_OUTPUTID_MAIN; ++ if ( ioctl( stmfbdev->fd, STMFBIO_GET_OUTPUT_CONFIG, &cfg ) < 0 ) { ++ *failed = config->flags; ++ return DFB_IO; ++ } ++ ++ hw_caps = shared->orig_config.caps; ++ cfg.activate = test ? STMFBIO_ACTIVATE_TEST : STMFBIO_ACTIVATE_IMMEDIATE; ++ cfg.caps = 0; ++ ++ if (encoder == shared->encoder_main) { ++ const STMfbdevScreenVideoMode *mode; ++ ++ *failed |= config->flags & ~(DSECONF_SCANMODE | DSECONF_FREQUENCY ++ | DSECONF_RESOLUTION ++ | DSECONF_TV_STANDARD); ++ if (!*failed) { ++ mode = stmfbdevScreen_find_mode( shared, config ); ++ if (!mode ++ || stmfbdevScreen_set_mode( stmfbdev, shared, mode, ++ test ) != DFB_OK) { ++ *failed |= (DSECONF_SCANMODE | DSECONF_FREQUENCY ++ | DSECONF_RESOLUTION); ++ *failed |= (config->flags & DSECONF_TV_STANDARD); ++ } ++ } ++ } ++ else if (encoder == shared->encoder_analog) { ++ D_DEBUG_AT( STMfbdev_Screen, " -> analogue 0x%.2x (outsig %x flg %x conn %x)\n", ++ config->out_signals, config->out_signals, ++ config->flags, config->out_connectors ); ++ ++ *failed |= config->flags & ~(DSECONF_CONNECTORS ++ | DSECONF_OUT_SIGNALS); ++ if (config->flags & DSECONF_OUT_SIGNALS ++ && D_FLAGS_INVALID( config->out_signals, (DSOS_RGB ++ | DSOS_YCBCR ++ | DSOS_CVBS ++ | DSOS_YC) )) ++ *failed |= DSECONF_OUT_SIGNALS; ++ /* it's not allowed to change connectors, they merely serve an ++ informational purpose. */ ++ if (config->flags & DSECONF_CONNECTORS ++ && config->out_connectors != (DSOC_SCART | DSOC_YC ++ | DSOC_CVBS | DSOC_COMPONENT) ) ++ *failed |= DSECONF_CONNECTORS; ++ ++ /* you can change the signals coming out of the connectors, ++ though. */ ++ if (!*failed) { ++ if (!D_FLAGS_IS_SET( hw_caps, STMFBIO_OUTPUT_CAPS_ANALOGUE_CONFIG )) { ++ if (config->out_signals != DSOS_NONE) ++ *failed |= DSECONF_OUT_SIGNALS; ++ } ++ else { ++ cfg.caps = STMFBIO_OUTPUT_CAPS_ANALOGUE_CONFIG; ++ ++ D_FLAGS_CLEAR( cfg.analogue_config, ++ STMFBIO_OUTPUT_ANALOGUE_MASK ); ++ ++ if (!config->out_signals) ++ D_DEBUG_AT( STMfbdev_Screen, " +> off\n" ); ++ if (D_FLAGS_IS_SET( config->out_signals, DSOS_RGB )) { ++ D_DEBUG_AT( STMfbdev_Screen, " +> RGB\n" ); ++ cfg.analogue_config |= STMFBIO_OUTPUT_ANALOGUE_RGB; ++ } ++ if (D_FLAGS_IS_SET( config->out_signals, DSOS_YCBCR )) { ++ D_DEBUG_AT( STMfbdev_Screen, " +> YPrPb\n" ); ++ cfg.analogue_config |= STMFBIO_OUTPUT_ANALOGUE_YPrPb; ++ } ++ if (D_FLAGS_IS_SET( config->out_signals, DSOS_CVBS )) { ++ D_DEBUG_AT( STMfbdev_Screen, " +> CVBS\n" ); ++ cfg.analogue_config |= STMFBIO_OUTPUT_ANALOGUE_CVBS; ++ } ++ if (D_FLAGS_IS_SET( config->out_signals, DSOS_YC )) { ++ D_DEBUG_AT( STMfbdev_Screen, " +> Y/C\n" ); ++ cfg.analogue_config |= STMFBIO_OUTPUT_ANALOGUE_YC; ++ } ++ } ++ } ++ } ++ else if (encoder == shared->encoder_hdmi) { ++ D_DEBUG_AT( STMfbdev_Screen, " -> HDMI 0x%.2x\n", ++ config->out_signals ); ++ ++ *failed |= config->flags & ~(DSECONF_CONNECTORS ++ | DSECONF_OUT_SIGNALS); ++ if (config->flags & DSECONF_OUT_SIGNALS ++ /* only HDMI + (RGB or YCbCr) supported */ ++ && (D_FLAGS_INVALID( config->out_signals, (DSOS_HDMI ++ | DSOS_RGB ++ | DSOS_YCBCR) ) ++ /* can't have both, RGB and YCbCr */ ++ || D_FLAGS_ARE_SET( config->out_signals, (DSOS_RGB ++ | DSOS_YCBCR) ))) ++ *failed |= DSECONF_OUT_SIGNALS; ++ /* it's not allowed to change connectors, they merely serve an ++ informational purpose. */ ++ if (config->flags & DSECONF_CONNECTORS ++ && config->out_connectors != DSOC_HDMI) ++ *failed |= DSECONF_CONNECTORS; ++ ++ if (!*failed) { ++ if (!D_FLAGS_IS_SET( hw_caps, STMFBIO_OUTPUT_CAPS_HDMI_CONFIG )) { ++ if (config->out_signals != DSOS_NONE) ++ *failed |= DSECONF_OUT_SIGNALS; ++ } ++ else { ++ cfg.caps = STMFBIO_OUTPUT_CAPS_HDMI_CONFIG; ++ ++ D_FLAGS_CLEAR( cfg.hdmi_config, ++ (STMFBIO_OUTPUT_HDMI_DISABLED ++ | STMFBIO_OUTPUT_HDMI_YUV ++ | STMFBIO_OUTPUT_HDMI_422) ); ++ ++ if (D_FLAGS_IS_SET( config->out_signals, DSOS_HDMI )) { ++ cfg.hdmi_config |= STMFBIO_OUTPUT_HDMI_ENABLED; ++ /* HDMI colourspace is RGB by default, only change it ++ when YCBCR is specified. */ ++ if (D_FLAGS_IS_SET( config->out_signals, DSOS_YCBCR )) { ++ D_DEBUG_AT( STMfbdev_Screen, " +> YCbCr\n" ); ++ cfg.hdmi_config |= STMFBIO_OUTPUT_HDMI_YUV; ++ cfg.hdmi_config |= STMFBIO_OUTPUT_HDMI_444; ++ } ++ else if (D_FLAGS_IS_SET( config->out_signals, ++ DSOS_RGB )) { ++ D_DEBUG_AT( STMfbdev_Screen, " +> RGB\n" ); ++ cfg.hdmi_config |= STMFBIO_OUTPUT_HDMI_RGB; ++ } ++ else { ++ D_DEBUG_AT( STMfbdev_Screen, " +> unknown\n" ); ++ *failed |= DSECONF_OUT_SIGNALS; ++ } ++ } ++ else if (config->out_signals == DSOS_NONE) { ++ D_DEBUG_AT( STMfbdev_Screen, " +> off\n" ); ++ cfg.hdmi_config |= STMFBIO_OUTPUT_HDMI_DISABLED; ++ } ++ } ++ } ++ } ++ else if (encoder == shared->encoder_dvo) { ++ D_DEBUG_AT( STMfbdev_Screen, " -> DVO 0x%.2x\n", ++ config->out_signals ); ++ ++ *failed |= config->flags & ~(DSECONF_CONNECTORS ++ | DSECONF_OUT_SIGNALS); ++ if (config->flags & DSECONF_OUT_SIGNALS ++ && (D_FLAGS_INVALID( config->out_signals, (DSOS_656 ++ | DSOS_RGB ++ | DSOS_YCBCR) ) ++ /* can't have both, RGB and YCbCr */ ++ || D_FLAGS_ARE_SET( config->out_signals, (DSOS_RGB ++ | DSOS_YCBCR) ))) ++ *failed |= DSECONF_OUT_SIGNALS; ++ /* it's not allowed to change connectors, they merely serve an ++ informational purpose. */ ++ if (config->flags & DSECONF_CONNECTORS ++ && config->out_connectors != DSOC_656) ++ *failed |= DSECONF_CONNECTORS; ++ ++ if (!*failed) { ++ if (!D_FLAGS_IS_SET( hw_caps, STMFBIO_OUTPUT_CAPS_DVO_CONFIG )) { ++ if (config->out_signals != DSOS_NONE) ++ *failed |= DSECONF_OUT_SIGNALS; ++ } ++ else { ++ cfg.caps = STMFBIO_OUTPUT_CAPS_DVO_CONFIG; ++ ++ D_FLAGS_CLEAR( cfg.dvo_config, ++ (STMFBIO_OUTPUT_DVO_DISABLED ++ | STMFBIO_OUTPUT_DVO_MODE_MASK) ); ++ ++ if (D_FLAGS_IS_SET( config->out_signals, DSOS_656 )) { ++ cfg.dvo_config |= STMFBIO_OUTPUT_DVO_ENABLED; ++ /* DVO colourspace is YUV444 16bit by default, only ++ change it when RGB is specified. */ ++ if (D_FLAGS_IS_SET( config->out_signals, DSOS_RGB )) { ++ D_DEBUG_AT( STMfbdev_Screen, " +> RGB 24bit\n" ); ++ cfg.dvo_config |= STMFBIO_OUTPUT_DVO_RGB_24BIT; ++ } ++ else if (D_FLAGS_IS_SET( config->out_signals, ++ DSOS_YCBCR )) { ++ D_DEBUG_AT( STMfbdev_Screen, " +> YCbCr 444 16bit\n" ); ++ cfg.dvo_config |= STMFBIO_OUTPUT_DVO_YUV_444_16BIT; ++ } ++ else { ++ D_DEBUG_AT( STMfbdev_Screen, " +> unknown\n" ); ++ *failed |= DSECONF_OUT_SIGNALS; ++ } ++ } ++ else if (config->out_signals == DSOS_NONE) { ++ D_DEBUG_AT( STMfbdev_Screen, " +> off\n" ); ++ cfg.dvo_config |= STMFBIO_OUTPUT_DVO_DISABLED; ++ } ++ } ++ } ++ } ++ else if (encoder == shared->encoder_sd) { ++ D_DEBUG_AT( STMfbdev_Screen, " -> DENC adjustment 0x%.2x\n", ++ config->out_signals ); ++ ++ *failed = config->flags & ~DSECONF_ADJUSTMENT; ++ if (!*failed) { ++ if (config->adjustment.flags & DCAF_BRIGHTNESS) { ++ cfg.caps |= STMFBIO_OUTPUT_CAPS_BRIGHTNESS; ++ cfg.brightness = config->adjustment.brightness >> 8; ++ } ++ if (config->adjustment.flags & DCAF_SATURATION) { ++ cfg.caps |= STMFBIO_OUTPUT_CAPS_SATURATION; ++ cfg.saturation = config->adjustment.saturation >> 8; ++ } ++ if (config->adjustment.flags & DCAF_CONTRAST) { ++ cfg.caps |= STMFBIO_OUTPUT_CAPS_CONTRAST; ++ cfg.contrast = config->adjustment.contrast >> 8; ++ } ++ if (config->adjustment.flags & DCAF_HUE) { ++ cfg.caps |= STMFBIO_OUTPUT_CAPS_HUE; ++ cfg.hue = config->adjustment.hue >> 8; ++ } ++ } ++ } ++ else ++ return DFB_BUG; ++ ++ if (!*failed && cfg.caps ++ && ioctl( stmfbdev->fd, STMFBIO_SET_OUTPUT_CONFIG, &cfg ) < 0) ++ *failed = config->flags; ++ ++ if (*failed) { ++ D_DEBUG_AT( STMfbdev_Screen, " => FAILED (0x%.8x)\n", *failed ); ++ return DFB_INVARG; ++ } ++ ++ D_DEBUG_AT( STMfbdev_Screen, " => SUCCESS\n" ); ++ return DFB_OK; ++} ++ ++static DFBResult ++stmfbdevTestEncoderConfig( CoreScreen *screen, ++ void *driver_data, ++ void *screen_data, ++ int encoder, ++ const DFBScreenEncoderConfig *config, ++ DFBScreenEncoderConfigFlags *failed ) ++{ ++ return stmfbdevDoEncoderConfig( screen, driver_data, screen_data, ++ encoder, config, failed, true ); ++} ++ ++static DFBResult ++stmfbdevSetEncoderConfig( CoreScreen *screen, ++ void *driver_data, ++ void *screen_data, ++ int encoder, ++ const DFBScreenEncoderConfig *config ) ++{ ++ DFBScreenEncoderConfigFlags dummy = DSECONF_NONE; ++ return stmfbdevDoEncoderConfig( screen, driver_data, screen_data, ++ encoder, config, &dummy, false ); ++} ++ ++/* remaining screen things */ ++static DFBResult ++stmfbdevWaitVSync( CoreScreen *screen, ++ void *driver_data, ++ void *screen_data ) ++{ ++ STMfbdev * const stmfbdev = driver_data; ++ STMfbdevScreenSharedData * const shared = screen_data; ++ static const int zero = 0; ++ ++ D_DEBUG_AT( STMfbdev_Screen, "%s( %p )\n", __FUNCTION__, screen ); ++ ++ D_MAGIC_ASSERT( stmfbdev, STMfbdev ); ++ D_MAGIC_ASSERT( shared, STMfbdevScreenSharedData ); ++ (void) shared; ++ ++ if (dfb_config->pollvsync_none) ++ return DFB_OK; ++ ++ if (ioctl( stmfbdev->fd, FBIO_WAITFORVSYNC, &zero )) ++ return errno2result( errno ); ++ ++ return DFB_OK; ++} ++ ++static DFBResult ++stmfbdevGetVSyncCount( CoreScreen *screen, ++ void *driver_data, ++ void *screen_data, ++ unsigned long *ret_count ) ++{ ++ STMfbdev * const stmfbdev = driver_data; ++ STMfbdevScreenSharedData * const shared = screen_data; ++ struct fb_vblank vblank; ++ ++ D_DEBUG_AT( STMfbdev_Screen, "%s( %p )\n", __FUNCTION__, screen ); ++ ++ D_MAGIC_ASSERT( stmfbdev, STMfbdev ); ++ D_MAGIC_ASSERT( shared, STMfbdevScreenSharedData ); ++ D_ASSERT( ret_count != NULL ); ++ (void) shared; ++ ++ if (!ret_count) ++ return DFB_INVARG; ++ ++ if (ioctl( stmfbdev->fd, FBIOGET_VBLANK, &vblank )) ++ return errno2result( errno ); ++ ++ if (!D_FLAGS_IS_SET( vblank.flags, FB_VBLANK_HAVE_COUNT )) ++ return DFB_UNSUPPORTED; ++ ++ *ret_count = vblank.count; ++ ++ return DFB_OK; ++} ++ ++static DFBResult ++stmfbdevGetScreenSize( CoreScreen *screen, ++ void *driver_data, ++ void *screen_data, ++ int *ret_width, ++ int *ret_height ) ++{ ++ STMfbdev * const stmfbdev = driver_data; ++ STMfbdevScreenSharedData * const shared = screen_data; ++ ++ D_DEBUG_AT( STMfbdev_Screen, "%s( %p )\n", __FUNCTION__, screen ); ++ ++ D_MAGIC_ASSERT( stmfbdev, STMfbdev ); ++ D_MAGIC_ASSERT( shared, STMfbdevScreenSharedData ); ++ ++ (void) stmfbdev; ++ ++ switch (shared->mode.resolution) { ++ case DSOR_1920_1080: ++ *ret_width = 1920; *ret_height = 1080; break; ++ case DSOR_1280_720: ++ *ret_width = 1280; *ret_height = 720; break; ++ case DSOR_1440_540: ++ *ret_width = 1440; *ret_height = 540; break; ++ case DSOR_960_540: ++ *ret_width = 960; *ret_height = 540; break; ++ case DSOR_720_576: ++ *ret_width = 720; *ret_height = 576; break; ++ case DSOR_720_480: ++ *ret_width = 720; *ret_height = 480; break; ++ case DSOR_640_480: ++ *ret_width = 640; *ret_height = 480; break; ++ ++ default: ++ return DFB_FAILURE; ++ } ++ ++ return DFB_OK; ++} ++ ++ ++ScreenFuncs _g_stmfbdevScreenFuncs = { ++ .ScreenDataSize = stmfbdevScreenDataSize, ++ ++ .InitScreen = stmfbdevInitScreen, ++ .ShutdownScreen = stmfbdevShutdownScreen, ++ ++ .InitMixer = stmfbdevInitMixer, ++ .TestMixerConfig = stmfbdevTestMixerConfig, ++ .SetMixerConfig = stmfbdevSetMixerConfig, ++ ++ .InitEncoder = stmfbdevInitEncoder, ++ .TestEncoderConfig = stmfbdevTestEncoderConfig, ++ .SetEncoderConfig = stmfbdevSetEncoderConfig, ++ ++ .WaitVSync = stmfbdevWaitVSync, ++ .GetVSyncCount = stmfbdevGetVSyncCount, ++ .GetScreenSize = stmfbdevGetScreenSize, ++}; +diff --git a/systems/stmfbdev/stmfbdev_surface_pool.c b/systems/stmfbdev/stmfbdev_surface_pool.c +new file mode 100644 +index 0000000..e5bc936 +--- /dev/null ++++ b/systems/stmfbdev/stmfbdev_surface_pool.c +@@ -0,0 +1,622 @@ ++/* ++ (c) Copyright 2010-2012 STMicroelectronics (R&D) Ltd. ++ (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 André Draszik . ++ ++ Based on work by Denis Oliver Kropp , ++ Andreas Hundt , ++ Sven Neumann , ++ Ville Syrjälä and ++ Claudio Ciccani . ++ ++ This library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2 of the License, or (at your option) any later version. ++ ++ This library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with this library; if not, write to the ++ Free Software Foundation, Inc., 59 Temple Place - Suite 330, ++ Boston, MA 02111-1307, USA. ++*/ ++ ++#include ++ ++#include ++ ++#include ++ ++#include ++#include ++ ++#include ++ ++#include ++ ++#include "stmfbdev.h" ++#include "surfacemanager.h" ++ ++D_DEBUG_DOMAIN (STMfbdev_Surfaces_Main, "STMfbdev/Surfaces/Main", "STMfb Surface Pool"); ++D_DEBUG_DOMAIN (STMfbdev_SurfLock_Main, "STMfbdev/SurfLock/Main", "STMfb Surface Pool Locks"); ++ ++/****************************************************************************/ ++ ++typedef struct ++{ ++ int magic; ++ ++ SurfaceManager *manager; ++ ++ unsigned long physical; ++} STMfbdevPoolData; ++ ++typedef struct ++{ ++ int magic; ++ ++ CoreDFB *core; ++ void *mem; ++} STMfbdevPoolLocalData; ++ ++typedef struct ++{ ++ int magic; ++ ++ Chunk *chunk; ++} STMfbdevPoolAllocationData; ++ ++/****************************************************************************/ ++ ++static int ++stmfbdevPoolDataSize (void) ++{ ++ return sizeof (STMfbdevPoolData); ++} ++ ++static int ++stmfbdevPoolLocalDataSize (void) ++{ ++ return sizeof (STMfbdevPoolLocalData); ++} ++ ++static int ++stmfbdevAllocationDataSize (void) ++{ ++ return sizeof (STMfbdevPoolAllocationData); ++} ++ ++static DFBResult ++stmfbdevLeavePool (CoreSurfacePool *pool, ++ void *pool_data, ++ void *pool_local) ++{ ++ STMfbdevPoolData * const data = pool_data; ++ STMfbdevPoolLocalData * const local = pool_local; ++ ++ D_DEBUG_AT (STMfbdev_Surfaces_Main, "%s()\n", __func__); ++ ++ D_MAGIC_ASSERT (pool, CoreSurfacePool); ++ D_MAGIC_ASSERT (data, STMfbdevPoolData); ++ D_MAGIC_ASSERT (local, STMfbdevPoolLocalData); ++ ++ D_UNUSED_P (data); ++ ++ local->mem = NULL; ++ ++ D_MAGIC_CLEAR (local); ++ ++ return DFB_OK; ++} ++ ++static DFBResult ++stmfbdevJoinPool (CoreDFB *core, ++ CoreSurfacePool *pool, ++ void *pool_data, ++ void *pool_local, ++ void *system_data) ++{ ++ STMfbdevPoolData * const data = pool_data; ++ STMfbdevPoolLocalData * const local = pool_local; ++ STMfbdev * const stmfbdev = dfb_system_data (); ++ ++ D_DEBUG_AT (STMfbdev_Surfaces_Main, "%s()\n", __func__); ++ ++ D_ASSERT (core != NULL); ++ D_MAGIC_ASSERT (pool, CoreSurfacePool); ++ D_MAGIC_ASSERT (data, STMfbdevPoolData); ++ D_ASSERT (local != NULL); ++ D_MAGIC_ASSERT (stmfbdev, STMfbdev); ++ ++ D_UNUSED_P (data); ++ ++ D_MAGIC_SET (local, STMfbdevPoolLocalData); ++ ++ local->mem = stmfbdev->framebuffer_base; ++ D_ASSERT (local->mem != NULL); ++ ++ local->core = core; ++ ++ return DFB_OK; ++} ++ ++static DFBResult ++stmfbdevDestroyPool (CoreSurfacePool *pool, ++ void *pool_data, ++ void *pool_local) ++{ ++ STMfbdevPoolData * const data = pool_data; ++ STMfbdevPoolLocalData * const local = pool_local; ++ ++ D_DEBUG_AT (STMfbdev_Surfaces_Main, "%s()\n", __func__); ++ ++ D_MAGIC_ASSERT (pool, CoreSurfacePool); ++ D_MAGIC_ASSERT (data, STMfbdevPoolData); ++ D_MAGIC_ASSERT (local, STMfbdevPoolLocalData); ++ ++ D_UNUSED_P (local); ++ ++ stmfbdevLeavePool (pool, pool_data, pool_local); ++ ++ dfb_surfacemanager_destroy (data->manager); ++ ++ D_MAGIC_CLEAR (data); ++ ++ return DFB_OK; ++} ++ ++static DFBResult ++stmfbdevInitPool (CoreDFB *core, ++ CoreSurfacePool *pool, ++ void *pool_data, ++ void *pool_local, ++ void *system_data, ++ CoreSurfacePoolDescription *ret_desc) ++{ ++ DFBResult ret; ++ STMfbdevPoolData * const data = pool_data; ++ STMfbdevPoolLocalData * const local = pool_local; ++ STMfbdev * const stmfbdev = dfb_system_data (); ++ ++ D_DEBUG_AT (STMfbdev_Surfaces_Main, "%s()\n", __func__); ++ ++ D_ASSERT (core != NULL); ++ D_MAGIC_ASSERT (pool, CoreSurfacePool); ++ D_ASSERT (data != NULL); ++ D_ASSERT (local != NULL); ++ D_ASSERT (ret_desc != NULL); ++ ++ D_UNUSED_P (local); ++ ++ D_MAGIC_ASSERT (stmfbdev, STMfbdev); ++ D_MAGIC_ASSERT (stmfbdev->shared, STMfbdevSharedData); ++ ++ D_MAGIC_SET (data, STMfbdevPoolData); ++ ++ snprintf (ret_desc->name, ++ DFB_SURFACE_POOL_DESC_NAME_LENGTH, "STMfb Memory"); ++ ++ ret = dfb_surfacemanager_create (core, stmfbdev->shared->fix.smem_len, ++ &data->manager); ++ ++ if (ret) ++ return ret; ++ ++ data->physical = stmfbdev->shared->fix.smem_start; ++ ++ ret_desc->caps = CSPCAPS_PHYSICAL | CSPCAPS_VIRTUAL; ++ ret_desc->access[CSAID_CPU] = CSAF_READ | CSAF_WRITE | CSAF_SHARED; ++ ret_desc->access[CSAID_GPU] = CSAF_READ | CSAF_WRITE | CSAF_SHARED; ++ ret_desc->types = (0 ++ | CSTF_LAYER ++ | CSTF_WINDOW | CSTF_CURSOR | CSTF_FONT ++ | CSTF_SHARED | CSTF_EXTERNAL ++ | CSTF_BUFFEROBJECT ++ ); ++ ret_desc->priority = CSPP_DEFAULT; ++ ret_desc->size = stmfbdev->shared->fix.smem_len; ++ ++ /* other accelerators */ ++ ret_desc->access[CSAID_ACCEL0] = CSAF_READ | CSAF_WRITE; ++ ret_desc->access[CSAID_ACCEL1] = CSAF_READ | CSAF_WRITE; ++ ret_desc->access[CSAID_ACCEL2] = CSAF_READ | CSAF_WRITE; ++ ret_desc->access[CSAID_ACCEL3] = CSAF_READ | CSAF_WRITE; ++ ret_desc->access[CSAID_ACCEL4] = CSAF_READ | CSAF_WRITE; ++ ret_desc->access[CSAID_ACCEL5] = CSAF_READ | CSAF_WRITE; ++ ++ /* For hardware layers */ ++ ret_desc->access[CSAID_LAYER0] = CSAF_READ; ++ ret_desc->access[CSAID_LAYER1] = CSAF_READ; ++ ret_desc->access[CSAID_LAYER2] = CSAF_READ; ++ ret_desc->access[CSAID_LAYER3] = CSAF_READ; ++ ret_desc->access[CSAID_LAYER4] = CSAF_READ; ++ ret_desc->access[CSAID_LAYER5] = CSAF_READ; ++ ret_desc->access[CSAID_LAYER6] = CSAF_READ; ++ ret_desc->access[CSAID_LAYER7] = CSAF_READ; ++ ret_desc->access[CSAID_LAYER8] = CSAF_READ; ++ ret_desc->access[CSAID_LAYER9] = CSAF_READ; ++ ret_desc->access[CSAID_LAYER10] = CSAF_READ; ++ ret_desc->access[CSAID_LAYER11] = CSAF_READ; ++ ret_desc->access[CSAID_LAYER12] = CSAF_READ; ++ ret_desc->access[CSAID_LAYER13] = CSAF_READ; ++ ret_desc->access[CSAID_LAYER14] = CSAF_READ; ++ ret_desc->access[CSAID_LAYER15] = CSAF_READ; ++ ++ ret = stmfbdevJoinPool (core, pool, pool_data, pool_local, system_data); ++ if (ret) ++ { ++ stmfbdevDestroyPool (pool, pool_data, pool_local); ++ return ret; ++ } ++ ++ return DFB_OK; ++} ++ ++static DFBResult ++stmfbdevTestConfig (CoreSurfacePool *pool, ++ void *pool_data, ++ void *pool_local, ++ CoreSurfaceBuffer *buffer, ++ const CoreSurfaceConfig *config) ++{ ++ CoreSurface *surface; ++ STMfbdevPoolData * const data = pool_data; ++ STMfbdevPoolLocalData * const local = pool_local; ++ DFBResult ret; ++ ++ D_DEBUG_AT (STMfbdev_Surfaces_Main, "%s (%p)\n", __func__, buffer); ++ ++ D_MAGIC_ASSERT (pool, CoreSurfacePool); ++ D_MAGIC_ASSERT (data, STMfbdevPoolData); ++ D_MAGIC_ASSERT (local, STMfbdevPoolLocalData); ++ D_MAGIC_ASSERT (buffer, CoreSurfaceBuffer); ++ D_ASSERT (config != NULL); ++ ++ surface = buffer->surface; ++ D_MAGIC_ASSERT (surface, CoreSurface); ++ D_UNUSED_P( surface ); ++ ++ D_DEBUG_AT (STMfbdev_Surfaces_Main, " -> buffer/type/id %p/0x%x/%lu\n", ++ buffer, surface->type, surface->resource_id); ++ ++ ret = dfb_surfacemanager_allocate (local->core, data->manager, ++ buffer, NULL, NULL, true); ++ ++ D_DEBUG_AT (STMfbdev_Surfaces_Main, " -> %s\n", DirectFBErrorString (ret)); ++ ++ return ret; ++} ++ ++static DFBResult ++stmfbdevAllocateBuffer (CoreSurfacePool *pool, ++ void *pool_data, ++ void *pool_local, ++ CoreSurfaceBuffer *buffer, ++ CoreSurfaceAllocation *allocation, ++ void *alloc_data) ++{ ++ CoreSurface *surface; ++ STMfbdevPoolData * const data = pool_data; ++ STMfbdevPoolLocalData * const local = pool_local; ++ STMfbdevPoolAllocationData * const alloc = alloc_data; ++ DFBResult ret; ++ Chunk *chunk; ++ ++ D_DEBUG_AT (STMfbdev_Surfaces_Main, "%s (%p)\n", __func__, buffer); ++ ++ D_MAGIC_ASSERT (pool, CoreSurfacePool); ++ D_MAGIC_ASSERT (data, STMfbdevPoolData); ++ D_MAGIC_ASSERT (local, STMfbdevPoolLocalData); ++ D_MAGIC_ASSERT (buffer, CoreSurfaceBuffer); ++ D_MAGIC_ASSERT (allocation, CoreSurfaceAllocation); ++ ++ surface = buffer->surface; ++ D_MAGIC_ASSERT (surface, CoreSurface); ++ D_UNUSED_P( surface ); ++ ++ ret = dfb_surfacemanager_allocate (local->core, data->manager, buffer, ++ allocation, &chunk, true); ++ if (ret) ++ return ret; ++ ++ D_MAGIC_ASSERT (chunk, Chunk); ++ ++ alloc->chunk = chunk; ++ ++ D_DEBUG_AT (STMfbdev_Surfaces_Main, ++ " -> offset 0x%.8x (%u), format: %s, pitch %d, size %d\n", ++ chunk->offset, chunk->offset, ++ dfb_pixelformat_name (buffer->format), chunk->pitch, ++ chunk->length); ++ ++ allocation->size = chunk->length; ++ allocation->offset = chunk->offset; ++ ++#if STGFX_DRIVER == 2 ++ if (unlikely (buffer->format == DSPF_RGB32)) ++ { ++ /* for RGB32, we need to set the alpha to 0xff */ ++ /* FIXME: check if we can hook into dfb_gfx_clear() or ++ dfb_surface_clear_buffers() */ ++ STGFX2DriverData * const stdrv = dfb_gfxcard_get_driver_data (); ++ STGFX2DeviceData * const stdev = dfb_gfxcard_get_device_data (); ++ DFBRectangle rect = { .x = 0, .y = 0, ++ .w = buffer->surface->config.size.w, ++ .h = buffer->surface->config.size.h }; ++ ++ D_DEBUG_AT (STMfbdev_Surfaces_Main, " -> rgb32 allocation!\n"); ++ ++ D_WARN ("STMfbdev/Surfaces/Main: RGB32 support is experimental and slow!"); ++ ++ dfb_gfxcard_lock (GDLF_WAIT); ++ _bdisp_aq_RGB32_init (stdrv, stdev, ++ data->physical + chunk->offset, chunk->pitch, ++ &rect); ++ dfb_gfxcard_unlock (); ++ } ++#endif ++ ++ D_MAGIC_SET (alloc, STMfbdevPoolAllocationData); ++ ++ return DFB_OK; ++} ++ ++static DFBResult ++stmfbdevDeallocateBuffer (CoreSurfacePool *pool, ++ void *pool_data, ++ void *pool_local, ++ CoreSurfaceBuffer *buffer, ++ CoreSurfaceAllocation *allocation, ++ void *alloc_data) ++{ ++ STMfbdevPoolData * const data = pool_data; ++ const STMfbdevPoolLocalData * const local = pool_local; ++ STMfbdevPoolAllocationData * const alloc = alloc_data; ++ ++ D_DEBUG_AT (STMfbdev_Surfaces_Main, "%s (%p)\n", __func__, buffer); ++ ++ D_MAGIC_ASSERT (pool, CoreSurfacePool); ++ D_MAGIC_ASSERT (data, STMfbdevPoolData); ++ D_MAGIC_ASSERT (local, STMfbdevPoolLocalData); ++ D_MAGIC_ASSERT (allocation, CoreSurfaceAllocation); ++ D_MAGIC_ASSERT (alloc, STMfbdevPoolAllocationData); ++ ++ (void) local; ++ ++ D_ASSERT (alloc->chunk != NULL); ++ dfb_surfacemanager_deallocate (data->manager, alloc->chunk); ++ ++ D_MAGIC_CLEAR (alloc); ++ ++ return DFB_OK; ++} ++ ++static DFBResult ++stmfbdevMuckOut (CoreSurfacePool *pool, ++ void *pool_data, ++ void *pool_local, ++ CoreSurfaceBuffer *buffer ) ++{ ++ STMfbdevPoolData * const data = pool_data; ++ const STMfbdevPoolLocalData * const local = pool_local; ++ ++ D_DEBUG_AT (STMfbdev_Surfaces_Main, "%s (%p)\n", __func__, buffer); ++ ++ D_MAGIC_ASSERT (pool, CoreSurfacePool); ++ D_MAGIC_ASSERT (data, STMfbdevPoolData); ++ D_MAGIC_ASSERT (local, STMfbdevPoolLocalData); ++ D_MAGIC_ASSERT (buffer, CoreSurfaceBuffer); ++ ++ return dfb_surfacemanager_displace (local->core, data->manager, buffer); ++} ++ ++#if D_DEBUG_ENABLED ++static char * ++_accessor_str (CoreSurfaceAccessorID accessor) ++{ ++ char *str = malloc (220); ++ int pos = 0; ++ ++ pos += sprintf (str + pos, "%.8x -> ", accessor); ++ if (accessor == CSAID_NONE) ++ pos += sprintf (str + pos, "NONE"); ++ else if (accessor == CSAID_CPU) ++ pos += sprintf (str + pos, "CPU"); ++ else if (accessor == CSAID_GPU) ++ pos += sprintf (str + pos, "GPU"); ++ else if (accessor == CSAID_ACCEL0) ++ pos += sprintf (str + pos, "ACCEL0"); ++ else if (accessor == CSAID_ACCEL1) ++ pos += sprintf (str + pos, "ACCEL1"); ++ else if (accessor == CSAID_ACCEL2) ++ pos += sprintf (str + pos, "ACCEL2"); ++ else if (accessor == CSAID_ACCEL3) ++ pos += sprintf (str + pos, "ACCEL3"); ++ else if (accessor == CSAID_ACCEL4) ++ pos += sprintf (str + pos, "ACCEL4"); ++ else if (accessor == CSAID_ACCEL5) ++ pos += sprintf (str + pos, "ACCEL5"); ++ else if (accessor == CSAID_LAYER0) ++ pos += sprintf (str + pos, "LAYER0"); ++ else if (accessor == CSAID_LAYER1) ++ pos += sprintf (str + pos, "LAYER1"); ++ else if (accessor == CSAID_LAYER2) ++ pos += sprintf (str + pos, "LAYER2"); ++ else if (accessor == CSAID_LAYER3) ++ pos += sprintf (str + pos, "LAYER3"); ++ else if (accessor == CSAID_LAYER4) ++ pos += sprintf (str + pos, "LAYER4"); ++ else if (accessor == CSAID_LAYER5) ++ pos += sprintf (str + pos, "LAYER5"); ++ else if (accessor == CSAID_LAYER6) ++ pos += sprintf (str + pos, "LAYER6"); ++ else if (accessor == CSAID_LAYER7) ++ pos += sprintf (str + pos, "LAYER7"); ++ else ++ pos += sprintf (str + pos, "UNKNOWN"); ++ ++ return str; ++} ++ ++static char * ++_access_str (CoreSurfaceAccessFlags access) ++{ ++ char *str = malloc (220); ++ int pos = 0; ++ ++ pos += sprintf (str + pos, "%.8x ->", access); ++ if (access == CSAF_NONE) ++ pos += sprintf (str + pos, " NONE"); ++ else ++ { ++ if (access & CSAF_READ) ++ pos += sprintf (str + pos, " READ"); ++ if (access & CSAF_WRITE) ++ pos += sprintf (str + pos, " WRITE"); ++ if (access & CSAF_SHARED) ++ pos += sprintf (str + pos, " SHARED"); ++ } ++ ++ return str; ++} ++#endif ++ ++static DFBResult ++stmfbdevLock (CoreSurfacePool *pool, ++ void *pool_data, ++ void *pool_local, ++ CoreSurfaceAllocation *allocation, ++ void *alloc_data, ++ CoreSurfaceBufferLock *lock) ++{ ++ const STMfbdevPoolData * const data = pool_data; ++ const STMfbdevPoolLocalData * const local = pool_local; ++ const STMfbdevPoolAllocationData * const alloc = alloc_data; ++ const Chunk *chunk; ++ ++ D_MAGIC_ASSERT (pool, CoreSurfacePool); ++ D_MAGIC_ASSERT (data, STMfbdevPoolData); ++ D_MAGIC_ASSERT (local, STMfbdevPoolLocalData); ++ D_MAGIC_ASSERT (allocation, CoreSurfaceAllocation); ++ D_MAGIC_ASSERT (alloc, STMfbdevPoolAllocationData); ++ D_MAGIC_ASSERT (lock, CoreSurfaceBufferLock); ++ ++ D_DEBUG_AT (STMfbdev_SurfLock_Main, "%s (%p)\n", __func__, lock->buffer); ++ ++ D_MAGIC_ASSERT (alloc->chunk, Chunk); ++ chunk = alloc->chunk; ++ ++#if D_DEBUG_ENABLED ++ { ++ /* heavy performance hit */ ++ char *accessor = _accessor_str (lock->accessor); ++ char *access = _access_str (lock->access); ++ D_DEBUG_AT (STMfbdev_SurfLock_Main, " -> by %s for %s\n", ++ accessor, access); ++ free (access); ++ free (accessor); ++ } ++#endif ++ ++ lock->pitch = chunk->pitch; ++ lock->offset = chunk->offset; ++ lock->addr = local->mem + chunk->offset; ++ lock->phys = data->physical + chunk->offset; ++ ++ D_DEBUG_AT (STMfbdev_SurfLock_Main, ++ " -> offset 0x%.8lx (%lu), pitch %d, addr %p, phys 0x%.8lx\n", ++ lock->offset, lock->offset, lock->pitch, lock->addr, lock->phys); ++ ++ return DFB_OK; ++} ++ ++static DFBResult ++stmfbdevUnlock (CoreSurfacePool *pool, ++ void *pool_data, ++ void *pool_local, ++ CoreSurfaceAllocation *allocation, ++ void *alloc_data, ++ CoreSurfaceBufferLock *lock) ++{ ++ const STMfbdevPoolData * const data = pool_data; ++ const STMfbdevPoolLocalData * const local = pool_local; ++ const STMfbdevPoolAllocationData * const alloc = alloc_data; ++ ++ D_MAGIC_ASSERT (pool, CoreSurfacePool); ++ D_MAGIC_ASSERT (data, STMfbdevPoolData); ++ D_MAGIC_ASSERT (local, STMfbdevPoolLocalData); ++ D_MAGIC_ASSERT (allocation, CoreSurfaceAllocation); ++ D_MAGIC_ASSERT (alloc, STMfbdevPoolAllocationData); ++ D_MAGIC_ASSERT (lock, CoreSurfaceBufferLock); ++ ++ D_DEBUG_AT (STMfbdev_SurfLock_Main, "%s (%p)\n", __func__, lock->buffer); ++ ++ D_UNUSED_P (data); ++ D_UNUSED_P (local); ++ D_UNUSED_P (alloc); ++ ++#if D_DEBUG_ENABLED ++ { ++ /* heavy performance hit */ ++ char *accessor = _accessor_str (lock->accessor); ++ char *access = _access_str (lock->access); ++ D_DEBUG_AT (STMfbdev_SurfLock_Main, " -> by %s for %s\n", ++ accessor, access); ++ free (access); ++ free (accessor); ++ } ++#endif ++ ++#if STGFX_DRIVER == 2 ++ if (unlikely (lock->buffer->format == DSPF_RGB32 ++ && lock->accessor != CSAID_GPU ++ && lock->access & CSAF_WRITE)) ++ { ++ /* if a non-GPU accessor did a write access to an RGB32 surface, we ++ should make sure the alpha is forced to 0xff, as the BDisp doesn't ++ support this format natively */ ++ STGFX2DriverData * const stdrv = dfb_gfxcard_get_driver_data (); ++ STGFX2DeviceData * const stdev = dfb_gfxcard_get_device_data (); ++ DFBRectangle rect = { .x = 0, .y = 0, ++ .w = lock->buffer->surface->config.size.w, ++ .h = lock->buffer->surface->config.size.h }; ++ ++ D_DEBUG_AT (STMfbdev_SurfLock_Main, " -> rgb32 write release!\n"); ++ dfb_gfxcard_lock (GDLF_WAIT); ++ _bdisp_aq_RGB32_fixup (stdrv, stdev, ++ lock->phys, lock->pitch, ++ &rect); ++ dfb_gfxcard_unlock (); ++ } ++#endif ++ ++ return DFB_OK; ++} ++ ++const SurfacePoolFuncs _g_stmfbdevSurfacePoolFuncs = { ++ .PoolDataSize = stmfbdevPoolDataSize, ++ .PoolLocalDataSize = stmfbdevPoolLocalDataSize, ++ .AllocationDataSize = stmfbdevAllocationDataSize, ++ ++ .InitPool = stmfbdevInitPool, ++ .JoinPool = stmfbdevJoinPool, ++ .DestroyPool = stmfbdevDestroyPool, ++ .LeavePool = stmfbdevLeavePool, ++ ++ .TestConfig = stmfbdevTestConfig, ++ .AllocateBuffer = stmfbdevAllocateBuffer, ++ .DeallocateBuffer = stmfbdevDeallocateBuffer, ++ ++ .MuckOut = stmfbdevMuckOut, ++ ++ .Lock = stmfbdevLock, ++ .Unlock = stmfbdevUnlock, ++}; +diff --git a/systems/stmfbdev/surfacemanager.c b/systems/stmfbdev/surfacemanager.c +new file mode 100644 +index 0000000..f23b573 +--- /dev/null ++++ b/systems/stmfbdev/surfacemanager.c +@@ -0,0 +1,585 @@ ++/* ++ (c) Copyright 2010 STMicroelectronics (R&D) Ltd. ++ (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 André Draszik . ++ ++ Based on work by Denis Oliver Kropp , ++ Andreas Hundt , ++ Sven Neumann , ++ Ville Syrjälä and ++ Claudio Ciccani . ++ ++ This library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2 of the License, or (at your option) any later version. ++ ++ This library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with this library; if not, write to the ++ Free Software Foundation, Inc., 59 Temple Place - Suite 330, ++ Boston, MA 02111-1307, USA. ++*/ ++ ++#include ++ ++#include ++ ++#include ++#include ++ ++#include ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++ ++#include "surfacemanager.h" ++ ++D_DEBUG_DOMAIN( SurfMan, "SurfaceManager", "DirectFB Surface Manager" ); ++ ++ ++static Chunk *split_chunk ( SurfaceManager *manager, ++ Chunk *chunk, ++ int length ); ++ ++static Chunk *free_chunk ( SurfaceManager *manager, ++ Chunk *chunk ); ++ ++static Chunk *occupy_chunk( SurfaceManager *manager, ++ Chunk *chunk, ++ CoreSurfaceAllocation *allocation, ++ int length, ++ int pitch ); ++ ++ ++DFBResult ++dfb_surfacemanager_create( CoreDFB *core, ++ unsigned int length, ++ SurfaceManager **ret_manager ) ++{ ++ FusionSHMPoolShared *pool; ++ SurfaceManager *manager; ++ Chunk *chunk; ++ ++ D_DEBUG_AT( SurfMan, "%s( %p, %d )\n", __FUNCTION__, core, length ); ++ ++ D_ASSERT( core != NULL ); ++ D_ASSERT( ret_manager != NULL ); ++ ++ pool = dfb_core_shmpool( core ); ++ ++ manager = SHCALLOC( pool, 1, sizeof(SurfaceManager) ); ++ if (!manager) ++ return D_OOSHM(); ++ ++ chunk = SHCALLOC( pool, 1, sizeof(Chunk) ); ++ if (!chunk) { ++ D_OOSHM(); ++ SHFREE( pool, manager ); ++ return DFB_NOSHAREDMEMORY; ++ } ++ ++ manager->shmpool = pool; ++ manager->chunks = chunk; ++ manager->offset = 0; ++ manager->length = length; ++ manager->avail = manager->length - manager->offset; ++ ++ D_MAGIC_SET( manager, SurfaceManager ); ++ ++ chunk->offset = manager->offset; ++ chunk->length = manager->avail; ++ ++ D_MAGIC_SET( chunk, Chunk ); ++ ++ D_DEBUG_AT( SurfMan, " -> %p\n", manager ); ++ ++ *ret_manager = manager; ++ ++ return DFB_OK; ++} ++ ++void ++dfb_surfacemanager_destroy( SurfaceManager *manager ) ++{ ++ Chunk *chunk; ++ void *next; ++ ++ D_DEBUG_AT( SurfMan, "%s( %p )\n", __FUNCTION__, manager ); ++ ++ D_MAGIC_ASSERT( manager, SurfaceManager ); ++ ++ /* Deallocate all video chunks. */ ++ chunk = manager->chunks; ++ while (chunk) { ++ next = chunk->next; ++ ++ D_MAGIC_CLEAR( chunk ); ++ ++ SHFREE( manager->shmpool, chunk ); ++ ++ chunk = next; ++ } ++ ++ D_MAGIC_CLEAR( manager ); ++ ++ /* Deallocate manager struct. */ ++ SHFREE( manager->shmpool, manager ); ++} ++ ++/** public functions NOT locking the surfacemanger theirself, ++ to be called between lock/unlock of surfacemanager **/ ++ ++DFBResult dfb_surfacemanager_allocate( CoreDFB *core, ++ SurfaceManager *manager, ++ CoreSurfaceBuffer *buffer, ++ CoreSurfaceAllocation *allocation, ++ Chunk **ret_chunk, ++ bool need_workaround ) ++{ ++ int pitch; ++ int length; ++ Chunk *c; ++ CoreGraphicsDevice *device; ++ ++ Chunk *best_free = NULL; ++ ++ D_MAGIC_ASSERT( manager, SurfaceManager ); ++ D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); ++ D_MAGIC_ASSERT( buffer->surface, CoreSurface ); ++ ++ if (ret_chunk) ++ D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation ); ++ else ++ D_ASSUME( allocation == NULL ); ++ ++ D_DEBUG_AT( SurfMan, "%s( %p ) <- %dx%d %s\n", __FUNCTION__, buffer, ++ buffer->surface->config.size.w, buffer->surface->config.size.h, ++ dfb_pixelformat_name( buffer->surface->config.format ) ); ++ ++ if (manager->suspended) ++ return DFB_SUSPENDED; ++ ++ /* FIXME: Only one global device at the moment. */ ++ device = dfb_core_get_part( core, DFCP_GRAPHICS ); ++ D_ASSERT( device != NULL ); ++ ++ dfb_gfxcard_calc_buffer_size( device, buffer, &pitch, &length ); ++ ++ D_DEBUG_AT( SurfMan, " -> pitch %d, length %d, available %d\n", pitch, length, manager->avail ); ++ ++ if (manager->avail < length) ++ return DFB_TEMPUNAVAIL; ++ ++ /* examine chunks */ ++ c = manager->chunks; ++ D_MAGIC_ASSERT( c, Chunk ); ++ ++ /* FIXME: Work around creation happening before graphics driver ++ initialization. */ ++ if (need_workaround && !c->next) { ++ int length = dfb_gfxcard_memory_length(); ++ ++ if (c->length != length - manager->offset) { ++ D_WARN( "workaround due to reserved video memory" ); ++ ++ manager->length = length; ++ manager->avail = length - manager->offset; ++ ++ c->length = length - manager->offset; ++ } ++ } ++ ++ while (c) { ++ D_MAGIC_ASSERT( c, Chunk ); ++ ++ if (!c->buffer && c->length >= length) { ++ /* NULL means check only. */ ++ if (!ret_chunk) ++ return DFB_OK; ++ ++ /* found a nice place to chill */ ++ if (!best_free || best_free->length > c->length) ++ /* first found or better one? */ ++ best_free = c; ++ ++ if (c->length == length) ++ break; ++ } ++ ++ c = c->next; ++ } ++ ++ /* if we found a place */ ++ if (best_free) { ++ D_DEBUG_AT( SurfMan, " -> found free (%d)\n", best_free->length ); ++ ++ /* NULL means check only. */ ++ if (ret_chunk) ++ *ret_chunk = occupy_chunk( manager, best_free, allocation, length, pitch ); ++ ++ return DFB_OK; ++ } ++ ++ D_DEBUG_AT( SurfMan, " -> failed (%d/%d avail)\n", manager->avail, manager->length ); ++ ++ /* no luck */ ++ return DFB_NOVIDEOMEMORY; ++} ++ ++DFBResult dfb_surfacemanager_displace( CoreDFB *core, ++ SurfaceManager *manager, ++ CoreSurfaceBuffer *buffer ) ++{ ++ int length; ++ Chunk *multi_start = NULL; ++ int multi_size = 0; ++ int multi_tsize = 0; ++ int multi_count = 0; ++ Chunk *bestm_start = NULL; ++ int bestm_count = 0; ++ int bestm_size = 0; ++ int min_toleration; ++ Chunk *chunk; ++ CoreGraphicsDevice *device; ++ CoreSurfaceAllocation *smallest = NULL; ++ ++ D_MAGIC_ASSERT( manager, SurfaceManager ); ++ D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); ++ D_MAGIC_ASSERT( buffer->surface, CoreSurface ); ++ ++ D_DEBUG_AT( SurfMan, "%s( %p ) <- %dx%d %s\n", __FUNCTION__, buffer, ++ buffer->surface->config.size.w, buffer->surface->config.size.h, ++ dfb_pixelformat_name( buffer->surface->config.format ) ); ++ ++ /* FIXME: Only one global device at the moment. */ ++ device = dfb_core_get_part( core, DFCP_GRAPHICS ); ++ D_ASSERT( device != NULL ); ++ D_UNUSED_P( device ); ++ ++ dfb_gfxcard_calc_buffer_size( dfb_core_get_part( core, DFCP_GRAPHICS ), buffer, NULL, &length ); ++ ++ min_toleration = manager->min_toleration/8 + 2; ++ ++ D_DEBUG_AT( SurfMan, " -> %7d required, min toleration %d\n", length, min_toleration ); ++ ++ chunk = manager->chunks; ++ while (chunk) { ++ CoreSurfaceAllocation *allocation; ++ ++ D_MAGIC_ASSERT( chunk, Chunk ); ++ ++ allocation = chunk->allocation; ++ if (allocation) { ++ CoreSurfaceBuffer *other; ++ int size, locks; ++ ++ D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation ); ++ D_ASSERT( chunk->buffer == allocation->buffer ); ++ D_ASSERT( chunk->length >= allocation->size ); ++ ++ other = allocation->buffer; ++ D_MAGIC_ASSERT( other, CoreSurfaceBuffer ); ++ ++ locks = dfb_surface_allocation_locks( allocation ); ++ if (locks) { ++ D_DEBUG_AT( SurfMan, " ++ %7d locked %dx\n", allocation->size, locks ); ++ goto next_reset; ++ } ++ ++ if (other->policy > buffer->policy) { ++ D_DEBUG_AT( SurfMan, " ++ %7d policy %d > %d\n", allocation->size, other->policy, buffer->policy ); ++ goto next_reset; ++ } ++ ++ if (other->policy == CSP_VIDEOONLY) { ++ D_DEBUG_AT( SurfMan, " ++ %7d policy videoonly\n", allocation->size ); ++ goto next_reset; ++ } ++ ++ chunk->tolerations++; ++ if (chunk->tolerations > 0xff) ++ chunk->tolerations = 0xff; ++ ++ if (other->policy == buffer->policy && chunk->tolerations < min_toleration) { ++ D_DEBUG_AT( SurfMan, " ++ %7d tolerations %d/%d\n", ++ allocation->size, chunk->tolerations, min_toleration ); ++ goto next_reset; ++ } ++ ++ size = allocation->size; ++ ++ if (chunk->prev && !chunk->prev->allocation) ++ size += chunk->prev->length; ++ ++ if (chunk->next && !chunk->next->allocation) ++ size += chunk->next->length; ++ ++ if (size >= length) { ++ if (!smallest || smallest->size > allocation->size) { ++ D_DEBUG_AT( SurfMan, " => %7d [%d] < %d, tolerations %d\n", ++ allocation->size, size, smallest ? smallest->size : 0, chunk->tolerations ); ++ ++ smallest = allocation; ++ } ++ else ++ D_DEBUG_AT( SurfMan, " -> %7d [%d] > %d\n", allocation->size, size, smallest->size ); ++ } ++ else ++ D_DEBUG_AT( SurfMan, " -> %7d [%d]\n", allocation->size, size ); ++ } ++ else ++ D_DEBUG_AT( SurfMan, " - %7d free\n", chunk->length ); ++ ++ ++ if (!smallest) { ++ if (!multi_start) { ++ multi_start = chunk; ++ multi_tsize = chunk->length; ++ multi_size = chunk->allocation ? chunk->length : 0; ++ multi_count = chunk->allocation ? 1 : 0; ++ } ++ else { ++ multi_tsize += chunk->length; ++ multi_size += chunk->allocation ? chunk->length : 0; ++ multi_count += chunk->allocation ? 1 : 0; ++ ++ while (multi_tsize >= length && multi_count > 1) { ++ if (!bestm_start || bestm_size > multi_size * multi_count / bestm_count) { ++ D_DEBUG_AT( SurfMan, " =====> %7d, %7d %2d used [%7d %2d]\n", ++ multi_tsize, multi_size, multi_count, bestm_size, bestm_count ); ++ ++ bestm_size = multi_size; ++ bestm_start = multi_start; ++ bestm_count = multi_count; ++ } ++ else ++ D_DEBUG_AT( SurfMan, " -----> %7d, %7d %2d used\n", ++ multi_tsize, multi_size, multi_count ); ++ ++ if (multi_count <= 2) ++ break; ++ ++ if (!multi_start->allocation) { ++ multi_tsize -= multi_start->length; ++ multi_start = multi_start->next; ++ } ++ ++ D_ASSUME( multi_start->allocation != NULL ); ++ ++ multi_tsize -= multi_start->length; ++ multi_size -= multi_start->allocation ? multi_start->length : 0; ++ multi_count -= multi_start->allocation ? 1 : 0; ++ multi_start = multi_start->next; ++ } ++ } ++ } ++ ++ chunk = chunk->next; ++ ++ continue; ++ ++ ++next_reset: ++ multi_start = NULL; ++ ++ chunk = chunk->next; ++ } ++ ++ if (smallest) { ++ D_MAGIC_ASSERT( smallest, CoreSurfaceAllocation ); ++ D_MAGIC_ASSERT( smallest->buffer, CoreSurfaceBuffer ); ++ ++ smallest->flags |= CSALF_MUCKOUT; ++ ++ D_DEBUG_AT( SurfMan, " -> offset %lu, size %d\n", smallest->offset, smallest->size ); ++ ++ return DFB_OK; ++ } ++ ++ if (bestm_start) { ++ chunk = bestm_start; ++ ++ while (bestm_count) { ++ CoreSurfaceAllocation *allocation = chunk->allocation; ++ ++ if (allocation) { ++ D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation ); ++ D_MAGIC_ASSERT( allocation->buffer, CoreSurfaceBuffer ); ++ ++ allocation->flags |= CSALF_MUCKOUT; ++ ++ bestm_count--; ++ } ++ ++ D_DEBUG_AT( SurfMan, " ---> offset %d, length %d\n", chunk->offset, chunk->length ); ++ ++ chunk = chunk->next; ++ } ++ ++ return DFB_OK; ++ } ++ ++ return DFB_NOVIDEOMEMORY; ++} ++ ++DFBResult dfb_surfacemanager_deallocate( SurfaceManager *manager, ++ Chunk *chunk ) ++{ ++ CoreSurfaceBuffer *buffer; ++ ++ D_MAGIC_ASSERT( manager, SurfaceManager ); ++ D_MAGIC_ASSERT( chunk, Chunk ); ++ ++ buffer = chunk->buffer; ++ D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); ++ D_MAGIC_ASSERT( buffer->surface, CoreSurface ); ++ D_UNUSED_P( buffer ); ++ ++ D_DEBUG_AT( SurfMan, "%s( %p ) <- %dx%d %s\n", __FUNCTION__, buffer, ++ buffer->surface->config.size.w, buffer->surface->config.size.h, ++ dfb_pixelformat_name( buffer->surface->config.format ) ); ++ ++ free_chunk( manager, chunk ); ++ ++ return DFB_OK; ++} ++ ++/** internal functions NOT locking the surfacemanager **/ ++ ++static Chunk * ++split_chunk( SurfaceManager *manager, Chunk *c, int length ) ++{ ++ Chunk *newchunk; ++ ++ D_MAGIC_ASSERT( c, Chunk ); ++ ++ if (c->length == length) /* does not need be splitted */ ++ return c; ++ ++ newchunk = (Chunk*) SHCALLOC( manager->shmpool, 1, sizeof(Chunk) ); ++ if (!newchunk) { ++ D_OOSHM(); ++ return NULL; ++ } ++ ++ /* calculate offsets and lengths of resulting chunks */ ++ newchunk->offset = c->offset + c->length - length; ++ newchunk->length = length; ++ c->length -= newchunk->length; ++ ++ /* insert newchunk after chunk c */ ++ newchunk->prev = c; ++ newchunk->next = c->next; ++ if (c->next) ++ c->next->prev = newchunk; ++ c->next = newchunk; ++ ++ D_MAGIC_SET( newchunk, Chunk ); ++ ++ return newchunk; ++} ++ ++static Chunk * ++free_chunk( SurfaceManager *manager, Chunk *chunk ) ++{ ++ D_MAGIC_ASSERT( manager, SurfaceManager ); ++ D_MAGIC_ASSERT( chunk, Chunk ); ++ ++ if (!chunk->buffer) { ++ D_BUG( "freeing free chunk" ); ++ return chunk; ++ } ++ ++ D_DEBUG_AT( SurfMan, "%s( %d bytes at offset %d )\n", __FUNCTION__, chunk->length, chunk->offset ); ++ ++ if (chunk->buffer->policy == CSP_VIDEOONLY) ++ manager->avail += chunk->length; ++ ++ D_DEBUG_AT( SurfMan, " -> freed %d, available %d\n", chunk->length, manager->avail ); ++ ++ chunk->allocation = NULL; ++ chunk->buffer = NULL; ++ ++ manager->min_toleration--; ++ ++ if (chunk->prev && !chunk->prev->buffer) { ++ Chunk *prev = chunk->prev; ++ ++ //D_DEBUG_AT( SurfMan, " -> merging with previous chunk at %d\n", prev->offset ); ++ ++ prev->length += chunk->length; ++ ++ prev->next = chunk->next; ++ if (prev->next) ++ prev->next->prev = prev; ++ ++ //D_DEBUG_AT( SurfMan, " -> freeing %p (prev %p, next %p)\n", chunk, chunk->prev, chunk->next); ++ ++ D_MAGIC_CLEAR( chunk ); ++ ++ SHFREE( manager->shmpool, chunk ); ++ chunk = prev; ++ } ++ ++ if (chunk->next && !chunk->next->buffer) { ++ Chunk *next = chunk->next; ++ ++ //D_DEBUG_AT( SurfMan, " -> merging with next chunk at %d\n", next->offset ); ++ ++ chunk->length += next->length; ++ ++ chunk->next = next->next; ++ if (chunk->next) ++ chunk->next->prev = chunk; ++ ++ D_MAGIC_CLEAR( next ); ++ ++ SHFREE( manager->shmpool, next ); ++ } ++ ++ return chunk; ++} ++ ++static Chunk * ++occupy_chunk( SurfaceManager *manager, Chunk *chunk, CoreSurfaceAllocation *allocation, int length, int pitch ) ++{ ++ D_MAGIC_ASSERT( manager, SurfaceManager ); ++ D_MAGIC_ASSERT( chunk, Chunk ); ++ D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation ); ++ D_MAGIC_ASSERT( allocation->buffer, CoreSurfaceBuffer ); ++ ++ if (allocation->buffer->policy == CSP_VIDEOONLY) ++ manager->avail -= length; ++ ++ chunk = split_chunk( manager, chunk, length ); ++ if (!chunk) ++ return NULL; ++ ++ D_DEBUG_AT( SurfMan, "%s( %d bytes at offset %d )\n", __FUNCTION__, chunk->length, chunk->offset ); ++ ++ D_DEBUG_AT( SurfMan, " -> occupied %d, available %d\n", chunk->length, manager->avail ); ++ ++ chunk->allocation = allocation; ++ chunk->buffer = allocation->buffer; ++ chunk->pitch = pitch; ++ ++ manager->min_toleration++; ++ ++ return chunk; ++} +diff --git a/systems/stmfbdev/surfacemanager.h b/systems/stmfbdev/surfacemanager.h +new file mode 100644 +index 0000000..43fe950 +--- /dev/null ++++ b/systems/stmfbdev/surfacemanager.h +@@ -0,0 +1,110 @@ ++/* ++ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) ++ (c) Copyright 2000-2004 Convergence (integrated media) GmbH ++ ++ All rights reserved. ++ ++ Written by Denis Oliver Kropp , ++ Andreas Hundt , ++ Sven Neumann , ++ Ville Syrjälä and ++ Claudio Ciccani . ++ ++ This library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2 of the License, or (at your option) any later version. ++ ++ This library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with this library; if not, write to the ++ Free Software Foundation, Inc., 59 Temple Place - Suite 330, ++ Boston, MA 02111-1307, USA. ++*/ ++ ++#ifndef __SURFACEMANAGER_H__ ++#define __SURFACEMANAGER_H__ ++ ++#include ++ ++#include ++ ++typedef struct _SurfaceManager SurfaceManager; ++typedef struct _Chunk Chunk; ++ ++/* ++ * initially there is one big free chunk, ++ * chunks are splitted into a free and an occupied chunk if memory is allocated, ++ * two chunks are merged to one free chunk if memory is deallocated ++ */ ++struct _Chunk { ++ int magic; ++ ++ int offset; /* offset in memory, ++ is greater or equal to the heap offset */ ++ int length; /* length of this chunk in bytes */ ++ ++ int pitch; ++ ++ CoreSurfaceBuffer *buffer; /* pointer to surface buffer occupying ++ this chunk, or NULL if chunk is free */ ++ CoreSurfaceAllocation *allocation; ++ ++ int tolerations; /* number of times this chunk was scanned ++ occupied, resetted in assure_video */ ++ ++ Chunk *prev; ++ Chunk *next; ++}; ++ ++struct _SurfaceManager { ++ int magic; ++ ++ FusionSHMPoolShared *shmpool; ++ ++ Chunk *chunks; ++ ++ int offset; ++ int length; /* length of the heap in bytes */ ++ int avail; /* amount of available memory in bytes */ ++ ++ int min_toleration; ++ ++ bool suspended; ++}; ++ ++ ++DFBResult dfb_surfacemanager_create ( CoreDFB *core, ++ unsigned int length, ++ SurfaceManager **ret_manager ); ++ ++void dfb_surfacemanager_destroy( SurfaceManager *manager ); ++ ++/* ++ * finds and allocates one for the surface or fails, ++ * after success the video health is CSH_RESTORE. ++ * NOTE: this does not notify the listeners ++ */ ++DFBResult dfb_surfacemanager_allocate( CoreDFB *core, ++ SurfaceManager *manager, ++ CoreSurfaceBuffer *buffer, ++ CoreSurfaceAllocation *allocation, ++ Chunk **ret_chunk, ++ bool need_workaround ); ++ ++DFBResult dfb_surfacemanager_displace( CoreDFB *core, ++ SurfaceManager *manager, ++ CoreSurfaceBuffer *buffer ); ++ ++/* ++ * sets the video health to CSH_INVALID frees the chunk and ++ * notifies the listeners ++ */ ++DFBResult dfb_surfacemanager_deallocate( SurfaceManager *manager, ++ Chunk *chunk ); ++ ++#endif +diff --git a/systems/stmfbdev/vt.c b/systems/stmfbdev/vt.c +new file mode 100644 +index 0000000..78236a0 +--- /dev/null ++++ b/systems/stmfbdev/vt.c +@@ -0,0 +1,681 @@ ++/* ++ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) ++ (c) Copyright 2000-2004 Convergence (integrated media) GmbH ++ ++ All rights reserved. ++ ++ Written by Denis Oliver Kropp , ++ Andreas Hundt , ++ Sven Neumann , ++ Ville Syrjälä and ++ Claudio Ciccani . ++ ++ This library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2 of the License, or (at your option) any later version. ++ ++ This library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with this library; if not, write to the ++ Free Software Foundation, Inc., 59 Temple Place - Suite 330, ++ Boston, MA 02111-1307, USA. ++*/ ++ ++#include ++ ++#include /* Needs to be included before dfb_types.h */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "stmfbdev.h" ++#include "fb.h" ++#include "vt.h" ++ ++D_DEBUG_DOMAIN( VT, "STMfbdev/VT", "STMfbdev System Module VT Handling" ); ++ ++/* ++ * FIXME: the following looks like a bad hack. ++ * ++ * SIGUNUSED is no longer unused, but is defined for backwards compatibility. ++ * sparc, mips and alpha signal.h however do not define SIGUNUSED. ++ */ ++ ++#ifdef SIGUNUSED ++ #define SIG_SWITCH_FROM (SIGUNUSED + 10) ++ #define SIG_SWITCH_TO (SIGUNUSED + 11) ++#else ++ #define SIG_SWITCH_FROM (31 + 10) ++ #define SIG_SWITCH_TO (31 + 11) ++#endif ++ ++#ifndef SI_KERNEL ++/* glibc 2.1.x doesn't have this in /usr/include/bits/siginfo.h */ ++ #define SI_KERNEL 0x80 ++#endif ++ ++ ++extern STMfbdev *dfb_stmfbdev; ++ ++static VirtualTerminal *dfb_vt = NULL; ++ ++static DFBResult vt_init_switching( void ); ++static int vt_get_fb( int vt ); ++static void vt_set_fb( int vt, int fb ); ++static void *vt_thread( DirectThread *thread, void *arg ); ++ ++static void vt_start_flushing( void ); ++static void vt_stop_flushing( void ); ++static void *vt_flush_thread( DirectThread *thread, void *arg ); ++ ++DFBResult ++dfb_vt_initialize( void ) ++{ ++ DFBResult ret; ++ struct vt_stat vs; ++ ++ D_DEBUG_AT( VT, "%s()\n", __FUNCTION__ ); ++ ++ dfb_vt = D_CALLOC( 1, sizeof(VirtualTerminal) ); ++ if (!dfb_vt) ++ return D_OOM(); ++ ++ setsid(); ++ dfb_vt->fd0 = open( "/dev/tty0", O_RDONLY | O_NOCTTY ); ++ if (dfb_vt->fd0 < 0) { ++ if (errno == ENOENT) { ++ dfb_vt->fd0 = open( "/dev/vc/0", O_RDONLY | O_NOCTTY ); ++ if (dfb_vt->fd0 < 0) { ++ if (errno == ENOENT) { ++ D_PERROR( "DirectFB/core/vt: Couldn't open " ++ "neither `/dev/tty0' nor `/dev/vc/0'!\n" ); ++ } ++ else { ++ D_PERROR( "DirectFB/core/vt: " ++ "Error opening `/dev/vc/0'!\n" ); ++ } ++ ++ D_FREE( dfb_vt ); ++ dfb_vt = NULL; ++ ++ return DFB_INIT; ++ } ++ } ++ else { ++ D_PERROR( "DirectFB/core/vt: Error opening `/dev/tty0'!\n"); ++ ++ D_FREE( dfb_vt ); ++ dfb_vt = NULL; ++ ++ return DFB_INIT; ++ } ++ } ++ ++ if (ioctl( dfb_vt->fd0, VT_GETSTATE, &vs ) < 0) { ++ D_PERROR( "DirectFB/core/vt: VT_GETSTATE failed!\n" ); ++ close( dfb_vt->fd0 ); ++ D_FREE( dfb_vt ); ++ dfb_vt = NULL; ++ return DFB_INIT; ++ } ++ ++ dfb_vt->prev = vs.v_active; ++ ++ ++ if (!dfb_config->vt_switch) { ++ if (dfb_config->vt_num != -1) ++ dfb_vt->num = dfb_config->vt_num; ++ else ++ dfb_vt->num = dfb_vt->prev; ++ ++ /* move vt to framebuffer */ ++ dfb_vt->old_fb = vt_get_fb( dfb_vt->num ); ++ vt_set_fb( dfb_vt->num, -1 ); ++ } ++ else { ++ if (dfb_config->vt_num == -1) { ++ int n; ++ ++ n = ioctl( dfb_vt->fd0, VT_OPENQRY, &dfb_vt->num ); ++ if (n < 0 || dfb_vt->num == -1) { ++ D_PERROR( "DirectFB/core/vt: Cannot allocate VT!\n" ); ++ close( dfb_vt->fd0 ); ++ D_FREE( dfb_vt ); ++ dfb_vt = NULL; ++ return DFB_INIT; ++ } ++ } ++ else { ++ dfb_vt->num = dfb_config->vt_num; ++ } ++ ++ /* move vt to framebuffer */ ++ dfb_vt->old_fb = vt_get_fb( dfb_vt->num ); ++ vt_set_fb( dfb_vt->num, -1 ); ++ ++ /* switch to vt */ ++ while (ioctl( dfb_vt->fd0, VT_ACTIVATE, dfb_vt->num ) < 0) { ++ if (errno == EINTR) ++ continue; ++ D_PERROR( "DirectFB/core/vt: VT_ACTIVATE failed!\n" ); ++ close( dfb_vt->fd0 ); ++ D_FREE( dfb_vt ); ++ dfb_vt = NULL; ++ return DFB_INIT; ++ } ++ ++ while (ioctl( dfb_vt->fd0, VT_WAITACTIVE, dfb_vt->num ) < 0) { ++ if (errno == EINTR) ++ continue; ++ D_PERROR( "DirectFB/core/vt: VT_WAITACTIVE failed!\n" ); ++ close( dfb_vt->fd0 ); ++ D_FREE( dfb_vt ); ++ dfb_vt = NULL; ++ return DFB_INIT; ++ } ++ ++ usleep( 40000 ); ++ } ++ ++ ret = vt_init_switching(); ++ if (ret) { ++ if (dfb_config->vt_switch) { ++ D_DEBUG_AT( VT, " -> switching back...\n" ); ++ ioctl( dfb_vt->fd0, VT_ACTIVATE, dfb_vt->prev ); ++ ioctl( dfb_vt->fd0, VT_WAITACTIVE, dfb_vt->prev ); ++ D_DEBUG_AT( VT, " -> ...switched back\n" ); ++ ioctl( dfb_vt->fd0, VT_DISALLOCATE, dfb_vt->num ); ++ } ++ ++ close( dfb_vt->fd0 ); ++ D_FREE( dfb_vt ); ++ dfb_vt = NULL; ++ return ret; ++ } ++ ++ vt_start_flushing(); ++ ++ dfb_stmfbdev->vt = dfb_vt; ++ ++ return DFB_OK; ++} ++ ++DFBResult ++dfb_vt_join( void ) ++{ ++ D_DEBUG_AT( VT, "%s()\n", __FUNCTION__ ); ++ ++ dfb_vt_detach( true ); ++ ++ return DFB_OK; ++} ++ ++DFBResult ++dfb_vt_shutdown( bool emergency ) ++{ ++ int res; ++ const char cursoron_str[] = "\033[?0;0;0c"; ++ const char blankon_str[] = "\033[9;10]"; ++ ++ (void) res; ++ ++ D_DEBUG_AT( VT, "%s()\n", __FUNCTION__ ); ++ ++ if (!dfb_vt) ++ return DFB_OK; ++ ++ vt_stop_flushing(); ++ ++ if (dfb_config->vt_switching) { ++ if (ioctl( dfb_vt->fd, VT_SETMODE, &dfb_vt->vt_mode ) < 0) ++ D_PERROR( "DirectFB/fbdev/vt: Unable to restore VT mode!!!\n" ); ++ ++ sigaction( SIG_SWITCH_FROM, &dfb_vt->sig_usr1, NULL ); ++ sigaction( SIG_SWITCH_TO, &dfb_vt->sig_usr2, NULL ); ++ ++ direct_thread_cancel( dfb_vt->thread ); ++ direct_thread_join( dfb_vt->thread ); ++ direct_thread_destroy( dfb_vt->thread ); ++ ++ pthread_mutex_destroy( &dfb_vt->lock ); ++ pthread_cond_destroy( &dfb_vt->wait ); ++ } ++ ++ if (dfb_config->kd_graphics) { ++ if (ioctl( dfb_vt->fd, KDSETMODE, KD_TEXT ) < 0) ++ D_PERROR( "DirectFB/fbdev/vt: KD_TEXT failed!\n" ); ++ } ++ else { ++ res = write( dfb_vt->fd, blankon_str, sizeof(blankon_str) ); ++ } ++ res = write( dfb_vt->fd, cursoron_str, sizeof(cursoron_str) ); ++ ++ if (tcsetattr( dfb_vt->fd, TCSAFLUSH, &dfb_vt->old_ts ) < 0) ++ D_PERROR("DirectFB/fbdev/vt: tcsetattr for original values failed!\n"); ++ ++ if (ioctl( dfb_vt->fd, KDSKBMODE, K_XLATE ) < 0) ++ D_PERROR( "DirectFB/fbdev/vt: K_XLATE failed!\n" ); ++ ++ if (dfb_config->vt_switch) { ++ D_DEBUG_AT( VT, " -> switching back...\n" ); ++ ++ if (ioctl( dfb_vt->fd0, VT_ACTIVATE, dfb_vt->prev ) < 0) ++ D_PERROR( "DirectFB/core/vt: VT_ACTIVATE" ); ++ ++ if (ioctl( dfb_vt->fd0, VT_WAITACTIVE, dfb_vt->prev ) < 0) ++ D_PERROR( "DirectFB/core/vt: VT_WAITACTIVE" ); ++ ++ D_DEBUG_AT( VT, " -> switched back...\n" ); ++ ++ usleep( 40000 ); ++ ++ /* restore con2fbmap */ ++ vt_set_fb( dfb_vt->num, dfb_vt->old_fb ); ++ ++ if (close( dfb_vt->fd ) < 0) ++ D_PERROR( "DirectFB/core/vt: Unable to " ++ "close file descriptor of allocated VT!\n" ); ++ ++ if (ioctl( dfb_vt->fd0, VT_DISALLOCATE, dfb_vt->num ) < 0) ++ D_PERROR( "DirectFB/core/vt: Unable to disallocate VT!\n" ); ++ } ++ else { ++ /* restore con2fbmap */ ++ vt_set_fb( dfb_vt->num, dfb_vt->old_fb ); ++ ++ if (close( dfb_vt->fd ) < 0) ++ D_PERROR( "DirectFB/core/vt: Unable to " ++ "close file descriptor of current VT!\n" ); ++ } ++ ++ if (close( dfb_vt->fd0 ) < 0) ++ D_PERROR( "DirectFB/core/vt: Unable to " ++ "close file descriptor of tty0!\n" ); ++ ++ D_FREE( dfb_vt ); ++ dfb_vt = dfb_stmfbdev->vt = NULL; ++ ++ return DFB_OK; ++} ++ ++DFBResult ++dfb_vt_leave( bool emergency ) ++{ ++ D_DEBUG_AT( VT, "%s()\n", __FUNCTION__ ); ++ ++ return DFB_OK; ++} ++ ++DFBResult ++dfb_vt_detach( bool force ) ++{ ++ D_DEBUG_AT( VT, "%s()\n", __FUNCTION__ ); ++ ++ if (dfb_config->vt_switch || force) { ++ int fd; ++ struct vt_stat vt_state; ++ ++ fd = open( "/dev/tty", O_RDONLY | O_NOCTTY ); ++ if (fd < 0) { ++ if (errno == ENXIO) ++ return DFB_OK; ++ ++ D_PERROR( "DirectFB/VT: Opening /dev/tty failed!\n" ); ++ return errno2result( errno ); ++ } ++ ++ if (ioctl( fd, VT_GETSTATE, &vt_state )) { ++ close( fd ); ++ return DFB_OK; ++ } ++ ++ if (ioctl( fd, TIOCNOTTY )) { ++ D_PERROR( "DirectFB/VT: TIOCNOTTY on /dev/tty failed\n" ); ++ close( fd ); ++ return errno2result( errno ); ++ } ++ ++ close( fd ); ++ } ++ ++ return DFB_OK; ++} ++ ++bool ++dfb_vt_switch( int num ) ++{ ++ D_DEBUG_AT( VT, "%s( %d )\n", __FUNCTION__, num ); ++ ++ if (!dfb_config->vt_switching) ++ return false; ++ ++ D_DEBUG_AT( VT, " -> switching to vt %d...\n", num ); ++ ++ if (ioctl( dfb_vt->fd0, VT_ACTIVATE, num ) < 0) ++ D_PERROR( "DirectFB/fbdev/vt: VT_ACTIVATE failed\n" ); ++ ++ return true; ++} ++ ++static void * ++vt_thread( DirectThread *thread, void *arg ) ++{ ++ D_DEBUG_AT( VT, "%s( %p, %p )\n", __FUNCTION__, thread, arg ); ++ ++ pthread_mutex_lock( &dfb_vt->lock ); ++ ++ while (true) { ++ direct_thread_testcancel( thread ); ++ ++ D_DEBUG_AT( VT, "...%s (signal %d)\n", __FUNCTION__, dfb_vt->vt_sig); ++ ++ switch (dfb_vt->vt_sig) { ++ default: ++ D_BUG( "unexpected vt_sig" ); ++ /* fall through */ ++ ++ case -1: ++ pthread_cond_wait( &dfb_vt->wait, &dfb_vt->lock ); ++ continue; ++ ++ case SIG_SWITCH_FROM: ++ if (dfb_core_suspend( dfb_stmfbdev->core ) == DFB_OK) { ++ if (ioctl( dfb_vt->fd, VT_RELDISP, VT_ACKACQ ) < 0) ++ D_PERROR( "DirectFB/fbdev/vt: VT_RELDISP failed\n" ); ++ } ++ ++ break; ++ ++ case SIG_SWITCH_TO: ++ if (dfb_core_resume( dfb_stmfbdev->core ) == DFB_OK) { ++ if (ioctl( dfb_vt->fd, VT_RELDISP, VT_ACKACQ ) < 0) ++ D_PERROR( "DirectFB/fbdev/vt: VT_RELDISP failed\n" ); ++ ++ if (dfb_config->kd_graphics) { ++ if (ioctl( dfb_vt->fd, KDSETMODE, KD_GRAPHICS ) < 0) ++ D_PERROR( "DirectFB/fbdev/vt: KD_GRAPHICS failed!\n" ); ++ } ++ } ++ ++ break; ++ } ++ ++ dfb_vt->vt_sig = -1; ++ ++ pthread_cond_signal( &dfb_vt->wait ); ++ } ++ ++ return NULL; ++} ++ ++static void ++vt_switch_handler( int signum ) ++{ ++ D_DEBUG_AT( VT, "%s( %d )\n", __FUNCTION__, signum ); ++ ++ pthread_mutex_lock( &dfb_vt->lock ); ++ ++ while (dfb_vt->vt_sig != -1) ++ pthread_cond_wait( &dfb_vt->wait, &dfb_vt->lock ); ++ ++ dfb_vt->vt_sig = signum; ++ ++ pthread_cond_signal( &dfb_vt->wait ); ++ ++ pthread_mutex_unlock( &dfb_vt->lock ); ++} ++ ++static DFBResult ++vt_init_switching( void ) ++{ ++ struct termios ts; ++ const char cursoroff_str[] = "\033[?1;0;0c"; ++ const char blankoff_str[] = "\033[9;0]"; ++ char buf[32]; ++ ++ int res; ++ (void)res; ++ ++ D_DEBUG_AT( VT, "%s()\n", __FUNCTION__ ); ++ ++ /* FIXME: Opening the device should be moved out of this function. */ ++ ++ snprintf(buf, 32, "/dev/tty%d", dfb_vt->num); ++ dfb_vt->fd = open( buf, O_RDWR | O_NOCTTY ); ++ if (dfb_vt->fd < 0) { ++ if (errno == ENOENT) { ++ snprintf(buf, 32, "/dev/vc/%d", dfb_vt->num); ++ dfb_vt->fd = open( buf, O_RDWR | O_NOCTTY ); ++ if (dfb_vt->fd < 0) { ++ if (errno == ENOENT) { ++ D_PERROR( "DirectFB/core/vt: Couldn't open " ++ "neither `/dev/tty%d' nor `/dev/vc/%d'!\n", ++ dfb_vt->num, dfb_vt->num ); ++ } ++ else { ++ D_PERROR( "DirectFB/core/vt: " ++ "Error opening `%s'!\n", buf ); ++ } ++ ++ return errno2result( errno ); ++ } ++ } ++ else { ++ D_PERROR( "DirectFB/core/vt: Error opening `%s'!\n", buf ); ++ return errno2result( errno ); ++ } ++ } ++ ++ /* attach to the new TTY before doing anything like KDSETMODE with it, ++ otherwise we'd get access denied error: */ ++ ioctl( dfb_vt->fd, TIOCSCTTY, 0 ); ++ ++ if (ioctl( dfb_vt->fd, KDSKBMODE, K_MEDIUMRAW ) < 0) { ++ D_PERROR( "DirectFB/fbdev/vt: K_MEDIUMRAW failed!\n" ); ++ close( dfb_vt->fd ); ++ return DFB_INIT; ++ } ++ ++ if (tcgetattr( dfb_vt->fd, &dfb_vt->old_ts ) < 0) { ++ D_PERROR( "DirectFB/fbdev/vt: tcgetattr failed!\n" ); ++ ioctl( dfb_vt->fd, KDSKBMODE, K_XLATE ); ++ close( dfb_vt->fd ); ++ return DFB_INIT; ++ } ++ ts = dfb_vt->old_ts; ++ ts.c_cc[VTIME] = 0; ++ ts.c_cc[VMIN] = 1; ++ ts.c_lflag &= ~(ICANON|ECHO|ISIG); ++ ts.c_iflag = 0; ++ if (tcsetattr( dfb_vt->fd, TCSAFLUSH, &ts ) < 0) { ++ D_PERROR( "DirectFB/fbdev/vt: tcsetattr for new values failed!\n" ); ++ ioctl( dfb_vt->fd, KDSKBMODE, K_XLATE ); ++ close( dfb_vt->fd ); ++ return DFB_INIT; ++ } ++ ++ res = write( dfb_vt->fd, cursoroff_str, sizeof(cursoroff_str) ); ++ if (dfb_config->kd_graphics) { ++ if (ioctl( dfb_vt->fd, KDSETMODE, KD_GRAPHICS ) < 0) { ++ D_PERROR( "DirectFB/fbdev/vt: KD_GRAPHICS failed!\n" ); ++ tcsetattr( dfb_vt->fd, TCSAFLUSH, &dfb_vt->old_ts ); ++ ioctl( dfb_vt->fd, KDSKBMODE, K_XLATE ); ++ close( dfb_vt->fd ); ++ return DFB_INIT; ++ } ++ } ++ else { ++ res = write( dfb_vt->fd, blankoff_str, sizeof(blankoff_str) ); ++ } ++ ++ if (dfb_config->vt_switching) { ++ struct vt_mode vt; ++ struct sigaction sig_tty; ++ ++ memset( &sig_tty, 0, sizeof( sig_tty ) ); ++ sig_tty.sa_handler = vt_switch_handler; ++ sigfillset( &sig_tty.sa_mask ); ++ ++ if (sigaction( SIG_SWITCH_FROM, &sig_tty, &dfb_vt->sig_usr1 ) || ++ sigaction( SIG_SWITCH_TO, &sig_tty, &dfb_vt->sig_usr2 )) { ++ D_PERROR( "DirectFB/fbdev/vt: sigaction failed!\n" ); ++ tcsetattr( dfb_vt->fd, TCSAFLUSH, &dfb_vt->old_ts ); ++ ioctl( dfb_vt->fd, KDSKBMODE, K_XLATE ); ++ close( dfb_vt->fd ); ++ return DFB_INIT; ++ } ++ ++ ++ vt.mode = VT_PROCESS; ++ vt.waitv = 0; ++ vt.relsig = SIG_SWITCH_FROM; ++ vt.acqsig = SIG_SWITCH_TO; ++ ++ if (ioctl( dfb_vt->fd, VT_SETMODE, &vt ) < 0) { ++ D_PERROR( "DirectFB/fbdev/vt: VT_SETMODE failed!\n" ); ++ ++ sigaction( SIG_SWITCH_FROM, &dfb_vt->sig_usr1, NULL ); ++ sigaction( SIG_SWITCH_TO, &dfb_vt->sig_usr2, NULL ); ++ ++ tcsetattr( dfb_vt->fd, TCSAFLUSH, &dfb_vt->old_ts ); ++ ioctl( dfb_vt->fd, KDSKBMODE, K_XLATE ); ++ close( dfb_vt->fd ); ++ ++ return DFB_INIT; ++ } ++ ++ direct_util_recursive_pthread_mutex_init( &dfb_vt->lock ); ++ ++ pthread_cond_init( &dfb_vt->wait, NULL ); ++ ++ dfb_vt->vt_sig = -1; ++ ++ dfb_vt->thread = direct_thread_create( DTT_CRITICAL, vt_thread, NULL, "VT Switcher" ); ++ } ++ ++ return DFB_OK; ++} ++ ++static int ++vt_get_fb( int vt ) ++{ ++ struct fb_con2fbmap c2m; ++ ++ D_DEBUG_AT( VT, "%s( %d )\n", __FUNCTION__, vt ); ++ ++ c2m.console = vt; ++ ++ if (ioctl( dfb_stmfbdev->fd, FBIOGET_CON2FBMAP, &c2m )) { ++ D_PERROR( "DirectFB/FBDev/vt: " ++ "FBIOGET_CON2FBMAP failed!\n" ); ++ return 0; ++ } ++ ++ D_DEBUG_AT( VT, " -> %d\n", c2m.framebuffer ); ++ ++ return c2m.framebuffer; ++} ++ ++static void ++vt_set_fb( int vt, int fb ) ++{ ++ struct fb_con2fbmap c2m; ++ struct stat sbf; ++ ++ D_DEBUG_AT( VT, "%s( %d, %d )\n", __FUNCTION__, vt, fb ); ++ ++ if (fstat( dfb_stmfbdev->fd, &sbf )) { ++ D_PERROR( "DirectFB/FBDev/vt: Could not fstat fb device!\n" ); ++ return; ++ } ++ ++ if (fb >= 0) ++ c2m.framebuffer = fb; ++ else ++ c2m.framebuffer = (sbf.st_rdev & 0xFF) >> 5; ++ ++ c2m.console = vt; ++ ++ if (ioctl( dfb_stmfbdev->fd, FBIOPUT_CON2FBMAP, &c2m ) < 0) { ++ D_PERROR( "DirectFB/FBDev/vt: " ++ "FBIOPUT_CON2FBMAP failed!\n" ); ++ } ++} ++ ++static void ++vt_start_flushing( void ) ++{ ++ dfb_vt->flush = true; ++ dfb_vt->flush_thread = direct_thread_create( DTT_DEFAULT, vt_flush_thread, NULL, "VT Flusher" ); ++} ++ ++static void ++vt_stop_flushing( void ) ++{ ++ dfb_vt->flush = false; ++ direct_thread_cancel( dfb_vt->flush_thread ); ++ direct_thread_join( dfb_vt->flush_thread ); ++ direct_thread_destroy( dfb_vt->flush_thread ); ++ dfb_vt->flush_thread = NULL; ++} ++ ++/* ++ * If the vt buffer in not kept clean the kernel may stop sleeping. ++ */ ++static void * ++vt_flush_thread( DirectThread *thread, void *arg ) ++{ ++ D_DEBUG_AT( VT, "%s( %p, %p )\n", __FUNCTION__, thread, arg ); ++ ++ while (dfb_vt->flush) { ++ fd_set set; ++ int ret; ++ ++ FD_ZERO( &set ); ++ FD_SET( dfb_vt->fd, &set ); ++ ++ ret = select( dfb_vt->fd + 1, &set, NULL, NULL, NULL ); ++ ++ if (ret < 0 && errno == EINTR) ++ continue; ++ ++ if (ret < 0 || !dfb_vt->flush) ++ break; ++ ++ tcflush( dfb_vt->fd, TCIFLUSH ); ++ } ++ ++ return NULL; ++} +diff --git a/systems/stmfbdev/vt.h b/systems/stmfbdev/vt.h +new file mode 120000 +index 0000000..70958ae +--- /dev/null ++++ b/systems/stmfbdev/vt.h +@@ -0,0 +1 @@ ++../fbdev/vt.h +\ No newline at end of file +diff --git a/systems/x11/primary.c b/systems/x11/primary.c +index be07d70..622d19b 100644 +--- a/systems/x11/primary.c ++++ b/systems/x11/primary.c +@@ -691,7 +691,8 @@ static DFBResult + update_screen( DFBX11 *x11, const DFBRectangle *clip, CoreSurfaceBufferLock *lock, XWindow *xw ) + { + void *dst; +- void *src; ++ u8 *srces[3]; ++ int pitches[3]; + unsigned int offset = 0; + XImage *ximage; + CoreSurfaceAllocation *allocation; +@@ -799,23 +800,28 @@ update_screen( DFBX11 *x11, const DFBRectangle *clip, CoreSurfaceBufferLock *loc + } + + dst = xw->virtualscreen + rect.x * xw->bpp + (rect.y + offset) * ximage->bytes_per_line; +- src = lock->addr + DFB_BYTES_PER_LINE( allocation->config.format, rect.x ) + rect.y * lock->pitch; ++ dfb_surface_get_data_offsets( allocation->surface, lock->addr, lock->pitch, rect.x, rect.y, ++ 3, srces, pitches ); + + switch (xw->depth) { + case 32: +- dfb_convert_to_argb( allocation->config.format, src, lock->pitch, ++ dfb_convert_to_argb( allocation->config.format, ++ srces[0], pitches[0], ++ srces[1], pitches[1], srces[2], pitches[2], + allocation->config.size.h, dst, ximage->bytes_per_line, rect.w, rect.h ); + break; + + case 24: +- dfb_convert_to_rgb32( allocation->config.format, src, lock->pitch, ++ dfb_convert_to_rgb32( allocation->config.format, ++ srces[0], pitches[0], ++ srces[1], pitches[1], srces[2], pitches[2], + allocation->config.size.h, dst, ximage->bytes_per_line, rect.w, rect.h ); + break; + + case 16: + if (allocation->config.format == DSPF_LUT8) { + int width = rect.w; int height = rect.h; +- const u8 *src8 = src; ++ const u8 *src8 = srces[0]; + u16 *dst16 = dst; + CorePalette *palette = allocation->surface->palette;//FIXME + int x; +@@ -826,18 +832,22 @@ update_screen( DFBX11 *x11, const DFBRectangle *clip, CoreSurfaceBufferLock *loc + dst16[x] = PIXEL_RGB16( color.r, color.g, color.b ); + } + +- src8 += lock->pitch; ++ src8 += pitches[0]; + dst16 += ximage->bytes_per_line / 2; + } + } + else { +- dfb_convert_to_rgb16( allocation->config.format, src, lock->pitch, ++ dfb_convert_to_rgb16( allocation->config.format, ++ srces[0], pitches[0], ++ srces[1], pitches[1], srces[2], pitches[2], + allocation->config.size.h, dst, ximage->bytes_per_line, rect.w, rect.h ); + } + break; + + case 15: +- dfb_convert_to_rgb555( allocation->config.format, src, lock->pitch, ++ dfb_convert_to_rgb555( allocation->config.format, ++ srces[0], pitches[0], ++ srces[1], pitches[1], srces[2], pitches[2], + allocation->config.size.h, dst, ximage->bytes_per_line, rect.w, rect.h ); + break; + +diff --git a/tests/Makefile.am b/tests/Makefile.am +index 5f961c1..fcf3462 100644 +--- a/tests/Makefile.am ++++ b/tests/Makefile.am +@@ -46,7 +46,7 @@ GL_PROGS = $(GL_PROGS_) + endif + + if DIRECTFB_BUILD_PURE_VOODOO +-NON_PURE_VOODOO_PROGS = ++NON_PURE_VOODOO_PROGS = + else + NON_PURE_VOODOO_PROGS = \ + coretest_blit2 \ +diff --git a/tools/mkdgifft.cpp b/tools/mkdgifft.cpp +index 4e347e7..de84eeb 100644 +--- a/tools/mkdgifft.cpp ++++ b/tools/mkdgifft.cpp +@@ -790,6 +790,7 @@ write_glyph( DGIFFGlyphInfo *glyph, const DFBSurfaceDescription &desc, void *dst + switch (m_format) { + case DSPF_ARGB: + dfb_convert_to_argb( desc.pixelformat, desc.preallocated[0].data, desc.preallocated[0].pitch, ++ NULL, 0, NULL, 0, + desc.height, (u32*) dst, pitch, desc.width, desc.height ); + break; + diff --git a/patches/DirectFB-1.6.3/autogen.sh b/patches/DirectFB-1.6.3/autogen.sh new file mode 100755 index 0000000..df78c38 --- /dev/null +++ b/patches/DirectFB-1.6.3/autogen.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +set -e + +aclocal $ACLOCAL_FLAGS + +libtoolize \ + --force \ + --copy + +autoreconf \ + --force \ + --install \ + --warnings=cross \ + --warnings=syntax \ + --warnings=obsolete \ + --warnings=unsupported + diff --git a/patches/DirectFB-1.6.3/directfb-1.6.3.enigma2remote.diff b/patches/DirectFB-1.6.3/directfb-1.6.3.enigma2remote.diff new file mode 100644 index 0000000..8221f5e --- /dev/null +++ b/patches/DirectFB-1.6.3/directfb-1.6.3.enigma2remote.diff @@ -0,0 +1,444 @@ +--- DirectFB-1.4.11/configure.in 2012-03-13 04:11:46.537293991 -0700 ++++ DirectFB-1.4.11_2/configure.in 2012-03-13 03:34:20.925293996 -0700 +@@ -1722,6 +1722,7 @@ + checkfor_dbox2remote=no + checkfor_dreamboxremote=no + checkfor_dynapro=no ++checkfor_enigma2remote=no + checkfor_elo=no + checkfor_gunze=no + checkfor_h3600ts=no +@@ -1746,7 +1747,7 @@ + [LIST is a comma separated selection of] + [inputdrivers to build. Possible inputdrivers] + [are: all (builds all drivers), none (builds none),] +- [dbox2remote, dreamboxremote, dynapro, elo-input,] ++ [dbox2remote, dreamboxremote, dynapro, enigma2remote, elo-input,] + [gunze, h3600_ts, input_hub, joystick, keyboard, linuxinput,] + [lirc, mutouch, penmount, ps2mouse, serialmouse,] + [sonypijogdial, tslib, ucb1x00, wm97xx, zytronic.] +@@ -1757,6 +1758,7 @@ + checkfor_dbox2remote=yes + checkfor_dreamboxremote=yes + checkfor_dynapro=no ++ checkfor_enigma2remote=yes + checkfor_elo=no + checkfor_gunze=no + checkfor_h3600ts=yes +@@ -1790,6 +1792,9 @@ + dynapro) + checkfor_dynapro=yes + ;; ++ enigma2remote) ++ checkfor_enigma2remote=yes ++ ;; + elo-input) + checkfor_elo=yes + ;; +@@ -1871,6 +1876,12 @@ + enable_dynapro_ts=yes + fi + ++enable_enigma2remote=no ++if test "$checkfor_enigma2remote" = "yes"; then ++ dnl Test for Enigma2 remote support ++ enable_enigma2remote=yes ++fi ++ + enable_elo_input=no + if test "$checkfor_elo" = "yes"; then + dnl Test for ELO Touchscreen support +@@ -2187,6 +2198,7 @@ + AM_CONDITIONAL(DBOX2REMOTE, test "$enable_dbox2remote" = "yes") + AM_CONDITIONAL(DREAMBOXREMOTE, test "$enable_dreamboxremote" = "yes") + AM_CONDITIONAL(DYNAPRO_INPUT, test "$enable_dynapro_ts" = "yes") ++AM_CONDITIONAL(ENIGMA2REMOTE, test "$enable_enigma2remote" = "yes") + AM_CONDITIONAL(ELO_INPUT, test "$enable_elo_input" = "yes") + AM_CONDITIONAL(GUNZE_INPUT, test "$enable_gunze_input" = "yes") + AM_CONDITIONAL(H3600_TS, test "$enable_h3600_ts" = "yes") +@@ -2397,6 +2409,7 @@ + inputdrivers/dbox2remote/Makefile + inputdrivers/dreamboxremote/Makefile + inputdrivers/dynapro/Makefile ++inputdrivers/enigma2remote/Makefile + inputdrivers/elo/Makefile + inputdrivers/gunze/Makefile + inputdrivers/h3600_ts/Makefile +@@ -2565,6 +2578,7 @@ + DBox2 Remote $enable_dbox2remote + DreamBox Remote $enable_dreamboxremote + Dynapro Touchscreen $enable_dynapro_ts ++ Enigma2 Remote $enable_enigma2remote + ELO Touchscreen $enable_elo_input + Gunze Touchscreen $enable_gunze_input + H3600 Touchscreen $enable_h3600_ts +--- DirectFB-1.4.11/inputdrivers/Makefile.am 2010-10-31 01:49:49.000000000 -0700 ++++ DirectFB-1.4.11_2/inputdrivers/Makefile.am 2012-03-13 03:42:50.417293998 -0700 +@@ -8,6 +8,10 @@ + DREAMBOXREMOTE_DIR = dreamboxremote + endif + ++if ENIGMA2REMOTE ++ENIGMA2REMOTE_DIR = enigma2remote ++endif ++ + if DYNAPRO_INPUT + DYNAPRO_INPUT_DIR = dynapro + endif +@@ -80,6 +84,7 @@ + $(DBOX2REMOTE_DIR) \ + $(DREAMBOXREMOTE_DIR) \ + $(DYNAPRO_INPUT_DIR) \ ++ $(ENIGMA2REMOTE_DIR) \ + $(ELO_INPUT_DIR) \ + $(GUNZE_INPUT_DIR) \ + $(H3600_TS_DIR) \ +diff -Nur DirectFB-1.4.11/inputdrivers/enigma2remote/enigma2remote.c DirectFB-1.4.11_2/inputdrivers/enigma2remote/enigma2remote.c +--- DirectFB-1.4.11/inputdrivers/enigma2remote/enigma2remote.c 1969-12-31 16:00:00.000000000 -0800 ++++ DirectFB-1.4.11_2/inputdrivers/enigma2remote/enigma2remote.c 2012-03-13 03:21:53.341293991 -0700 +@@ -0,0 +1,309 @@ ++/* ++ This library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2 of the License, or (at your option) any later version. ++ ++ This library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with this library; if not, write to the ++ Free Software Foundation, Inc., 59 Temple Place - Suite 330, ++ Boston, MA 02111-1307, USA. ++*/ ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include ++ ++#include ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include ++ ++DFB_INPUT_DRIVER( enigma2remote ) ++ ++#define DEVICE "/tmp/rc_enigma2" ++ ++typedef struct { ++ DFBInputDeviceKeySymbol key; ++ char* rccode; ++} KeyCode; ++ ++static KeyCode keycodes_remote[] = { ++ { DIKS_0, "0" }, ++ { DIKS_1, "1" }, ++ { DIKS_2, "2" }, ++ { DIKS_3, "3" }, ++ { DIKS_4, "4" }, ++ { DIKS_5, "5" }, ++ { DIKS_6, "6" }, ++ { DIKS_7, "7" }, ++ { DIKS_8, "8" }, ++ { DIKS_9, "9" }, ++ { DIKS_CURSOR_LEFT, "LEFT" }, ++ { DIKS_CURSOR_RIGHT, "RIGHT" }, ++ { DIKS_CURSOR_UP, "UP" }, ++ { DIKS_CURSOR_DOWN, "DOWN" }, ++ { DIKS_RETURN, "ENTER" }, ++ { DIKS_OK, "OK" }, ++ { DIKS_ESCAPE, "ESC" }, ++ { DIKS_BACK, "BACK" }, ++ { DIKS_RED, "RED" }, ++ { DIKS_GREEN, "GREEN" }, ++ { DIKS_YELLOW, "YELLOW" }, ++ { DIKS_BLUE, "BLUE" }, ++ { DIKS_PLAY, "PLAY" }, ++ { DIKS_PAUSE, "PAUSE" }, ++ { DIKS_STOP, "STOP" }, ++ ++ { DIKS_NULL, "" } ++}; ++ ++ ++/* ++ * declaration of private data ++ */ ++typedef struct { ++ CoreInputDevice *device; ++ DirectThread *thread; ++ ++ int fd; ++} Enigma2remoteData; ++ ++ ++/* ++ * helper function for translating rccode ++ */ ++static DFBInputDeviceKeySymbol ++enigma2remote_parse_rccode( char* rccode ) ++{ ++ KeyCode *keycode; ++ static u16 rccodeOld = 0; ++ ++ keycode = keycodes_remote; ++ ++ while (keycode->key != DIKS_NULL) { ++ if (!strcmp(keycode->rccode, rccode)) { ++ return keycode->key; ++ } ++ keycode++; ++ } ++ return DIKS_NULL; ++} ++ ++/* ++ * Input thread reading from device. ++ * Generates events on incoming data. ++ */ ++static void* ++enigma2remoteEventThread( DirectThread *thread, void *driver_data ) ++{ ++ Enigma2remoteData *data = (Enigma2remoteData*) driver_data; ++ int readlen; ++ u16 rccode; ++ char recvBuffer[1024]; ++ DFBInputEvent evt; ++ int len; ++ struct sockaddr_un remote; ++ ++ printf("Trying to connect...\n"); ++ ++ remote.sun_family = AF_UNIX; ++ strcpy(remote.sun_path, DEVICE); ++ len = strlen(remote.sun_path) + sizeof(remote.sun_family); ++ if (connect(data->fd, (struct sockaddr *)&remote, len) == -1) { ++ D_PERROR ("enigma2remote connect failes"); ++ return NULL; ++ } ++ ++ printf("Connected.\n"); ++ ++ while (1) { ++ int recvBufferPos = 0; ++ //if (readLineControlPipe(driver_data, recvBuffer, 1024) <= 0) ++ // break; ++ ++ if ((readlen=recv(data->fd, recvBuffer, 1024, 0)) <= 0) ++ break; ++ recvBuffer[readlen] = '\0'; ++ printf("CMD [\'%s\']\n", recvBuffer); ++ direct_thread_testcancel( thread ); ++ ++ while (1) { //OK\nENTER\n\0 ++ int i; ++ char keyBuffer[16]; ++ for (i = 0; i < readlen && i < 16 && recvBuffer[recvBufferPos + i] != '\n' && recvBuffer[recvBufferPos + i] != '\0'; i++) { ++ keyBuffer[i] = recvBuffer[recvBufferPos + i]; ++ } ++ if (i == 0) break; ++ keyBuffer[i] = '\0'; ++ recvBufferPos += i + 1; ++ ++ /* translate rccode to DirectFB keycode */ ++ evt.key_symbol = enigma2remote_parse_rccode( keyBuffer ); ++ ++ ++ printf("KEY [\'%s\' -> \'%d\']\n", keyBuffer, evt.key_symbol); ++ ++ if (evt.key_symbol != DIKS_NULL) { ++ /* set event type and dispatch*/ ++ evt.type = DIET_KEYPRESS; ++ evt.flags = DIEF_KEYSYMBOL; ++ dfb_input_dispatch( data->device, &evt ); ++ ++ /* set event type and dispatch*/ ++ evt.type = DIET_KEYRELEASE; ++ evt.flags = DIEF_KEYSYMBOL; ++ dfb_input_dispatch( data->device, &evt ); ++ } ++ if ( i >= readlen) break; ++ } ++ } ++ ++ //if (readlen <= 0 && errno != EINTR) ++ D_PERROR ("enigma2remote thread died\n"); ++ ++ return NULL; ++} ++ ++/* exported symbols */ ++ ++/* ++ * Return the number of available devices. ++ * Called once during initialization of DirectFB. ++ */ ++static int ++driver_get_available( void ) ++{ ++ /* Check if we are able to read from device */ ++ if (access( DEVICE, R_OK )) ++ return 0; ++ ++ return 1; ++} ++ ++/* ++ * Fill out general information about this driver. ++ * Called once during initialization of DirectFB. ++ */ ++static void ++driver_get_info( InputDriverInfo *info ) ++{ ++ /* fill driver info structure */ ++ snprintf ( info->name, ++ DFB_INPUT_DRIVER_INFO_NAME_LENGTH, "enigma2 remote" ); ++ snprintf ( info->vendor, ++ DFB_INPUT_DRIVER_INFO_VENDOR_LENGTH, "mws" ); ++ ++ info->version.major = 0; ++ info->version.minor = 1; ++} ++ ++/* ++ * Open the device, fill out information about it, ++ * allocate and fill private data, start input thread. ++ * Called during initialization, resuming or taking over mastership. ++ */ ++static DFBResult ++driver_open_device( CoreInputDevice *device, ++ unsigned int number, ++ InputDeviceInfo *info, ++ void **driver_data ) ++{ ++ int fd; ++ Enigma2remoteData *data; ++ ++ /* open device */ ++ if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { ++ D_PERROR( "DirectFB/dreamboxremote: could not open device" ); ++ return DFB_INIT; ++ } ++ ++ /* set device name */ ++ snprintf( info->desc.name, ++ DFB_INPUT_DEVICE_DESC_NAME_LENGTH, "enigma2 remote control" ); ++ ++ /* set device vendor */ ++ snprintf( info->desc.vendor, ++ DFB_INPUT_DEVICE_DESC_VENDOR_LENGTH, "ENIGMA2" ); ++ ++ /* set one of the primary input device IDs */ ++ info->prefered_id = DIDID_REMOTE; ++ ++ /* set type flags */ ++ info->desc.type = DIDTF_REMOTE; ++ ++ /* set capabilities */ ++ info->desc.caps = DICAPS_KEYS; ++ ++ ++ /* allocate and fill private data */ ++ data = D_CALLOC( 1, sizeof(Enigma2remoteData) ); ++ if (!data) { ++ close( fd ); ++ return D_OOM(); ++ } ++ ++ data->fd = fd; ++ data->device = device; ++ ++ /* start input thread */ ++ data->thread = direct_thread_create( DTT_INPUT, enigma2remoteEventThread, data, "Enigma2 Input" ); ++ ++ /* set private data pointer */ ++ *driver_data = data; ++ ++ return DFB_OK; ++} ++ ++/* ++ * Fetch one entry from the device's keymap if supported. ++ */ ++static DFBResult ++driver_get_keymap_entry( CoreInputDevice *device, ++ void *driver_data, ++ DFBInputDeviceKeymapEntry *entry ) ++{ ++ return DFB_UNSUPPORTED; ++} ++ ++/* ++ * End thread, close device and free private data. ++ */ ++static void ++driver_close_device( void *driver_data ) ++{ ++ Enigma2remoteData *data = (Enigma2remoteData*) driver_data; ++ ++ /* stop input thread */ ++ direct_thread_cancel( data->thread ); ++ direct_thread_join( data->thread ); ++ direct_thread_destroy( data->thread ); ++ ++ /* close file */ ++ fclose( data->fd ); ++ ++ /* free private data */ ++ D_FREE ( data ); ++} +diff -Nur DirectFB-1.4.11/inputdrivers/enigma2remote/Makefile.am DirectFB-1.4.11_2/inputdrivers/enigma2remote/Makefile.am +--- DirectFB-1.4.11/inputdrivers/enigma2remote/Makefile.am 1969-12-31 16:00:00.000000000 -0800 ++++ DirectFB-1.4.11_2/inputdrivers/enigma2remote/Makefile.am 2012-03-13 03:25:08.437293917 -0700 +@@ -0,0 +1,32 @@ ++## Makefile.am for DirectFB/inputdrivers/dreamboxremote ++ ++INCLUDES = \ ++ -I$(top_builddir)/include \ ++ -I$(top_builddir)/lib \ ++ -I$(top_srcdir)/include \ ++ -I$(top_srcdir)/lib \ ++ -I$(top_srcdir)/src ++ ++enigma2remote_LTLIBRARIES = libdirectfb_enigma2remote.la ++ ++if BUILD_STATIC ++enigma2remote_DATA = $(enigma2remote_LTLIBRARIES:.la=.o) ++endif ++ ++enigma2remotedir = $(MODULEDIR)/inputdrivers ++ ++libdirectfb_enigma2remote_la_SOURCES = \ ++ enigma2remote.c ++ ++libdirectfb_enigma2remote_la_LDFLAGS = \ ++ -module \ ++ -avoid-version \ ++ $(DFB_LDFLAGS) ++ ++libdirectfb_enigma2remote_la_LIBADD = \ ++ $(top_builddir)/lib/direct/libdirect.la \ ++ $(top_builddir)/src/libdirectfb.la ++ ++ ++include $(top_srcdir)/rules/libobject.make ++ diff --git a/patches/DirectFB-1.6.3/directfb-1.6.3.no-vt.diff b/patches/DirectFB-1.6.3/directfb-1.6.3.no-vt.diff new file mode 100644 index 0000000..57a9be9 --- /dev/null +++ b/patches/DirectFB-1.6.3/directfb-1.6.3.no-vt.diff @@ -0,0 +1,106 @@ +diff -Nur DirectFB-1.4.11.orig/systems/stmfbdev/stmfbdev.c DirectFB-1.4.11/systems/stmfbdev/stmfbdev.c +--- DirectFB-1.4.11.orig/systems/stmfbdev/stmfbdev.c 2010-11-15 13:35:37.000000000 -0800 ++++ DirectFB-1.4.11/systems/stmfbdev/stmfbdev.c 1969-12-31 16:00:00.000000000 -0800 +@@ -195,11 +195,13 @@ + if (ret) + goto error; + ++#ifdef HAVE_VT + if (dfb_config->vt) { + ret = dfb_vt_initialize(); + if (ret) + goto error; + } ++#endif + + /* Retrieve fixed information like video ram size */ + if (ioctl( stmfbdev->fd, FBIOGET_FSCREENINFO, &shared->fix ) < 0) { +@@ -291,11 +293,13 @@ + if (ret) + goto error; + ++#ifdef HAVE_VT + if (dfb_config->vt) { + ret = dfb_vt_join(); + if (ret) + goto error; + } ++#endif + + /* Map the framebuffer */ + stmfbdev->framebuffer_base = mmap( NULL, stmfbdev->shared->fix.smem_len, +@@ -349,11 +353,13 @@ + munmap( dfb_stmfbdev->framebuffer_base, + dfb_stmfbdev->shared->fix.smem_len ); + ++#ifdef HAVE_VT + if (dfb_config->vt) { + ret = dfb_vt_shutdown( emergency ); + if (ret) + return ret; + } ++#endif + + close( dfb_stmfbdev->fd ); + +@@ -384,11 +390,13 @@ + munmap( dfb_stmfbdev->framebuffer_base, + dfb_stmfbdev->shared->fix.smem_len ); + ++#ifdef HAVE_VT + if (dfb_config->vt) { + ret = dfb_vt_leave( emergency ); + if (ret) + return ret; + } ++#endif + + close( dfb_stmfbdev->fd ); + +@@ -490,6 +498,7 @@ + system_input_filter( CoreInputDevice *device, + DFBInputEvent *event ) + { ++#ifdef HAVE_VT + if (dfb_config->vt && dfb_config->vt_switching) { + switch (event->type) { + case DIET_KEYPRESS: +@@ -510,6 +519,7 @@ + break; + } + } ++#endif + + return false; + } + +diff -Nur DirectFB-1.4.11.orig/inputdrivers/linux_input/linux_input.c DirectFB-1.4.11/inputdrivers/linux_input/linux_input.c +--- DirectFB-1.4.11.orig/inputdrivers/linux_input/linux_input.c 2010-11-15 13:35:37.000000000 -0800 ++++ DirectFB-1.4.11/inputdrivers/linux_input/linux_input.c 1969-12-31 16:00:00.000000000 -0800 +@@ -1275,8 +1275,10 @@ + // Only allow USB keyboard and mouse support if the systems driver has + // the Virtual Terminal file ("/dev/tty0") open and available for use. + // FIXME: Additional logic needed for system drivers not similar to fbdev? ++#if HAVE_VT + if (!dfb_stm_fbdev->vt || dfb_stm_fbdev->vt->fd < 0) + return 0; ++#endif + } + + /* Use the devices specified in the configuration. */ +@@ -1874,6 +1876,7 @@ + /* Track associated entry in device_nums and device_names array. */ + data->index = number; + ++#ifdef HAVE_VT + if (info->desc.min_keycode >= 0 && info->desc.max_keycode >= info->desc.min_keycode) { + if (dfb_system_type() == CORE_FBDEV) { + FBDev *dfb_fbdev = dfb_system_data(); +@@ -1892,6 +1895,7 @@ + if (data->vt_fd < 0) + D_WARN( "no keymap support (requires /dev/tty0 - CONFIG_VT)" ); + } ++#endif + + /* check if the device has LEDs */ + ret = ioctl( fd, EVIOCGBIT(EV_LED, sizeof(ledbit)), ledbit ); diff --git a/patches/DirectFB-1.6.3/series b/patches/DirectFB-1.6.3/series new file mode 100644 index 0000000..1e99103 --- /dev/null +++ b/patches/DirectFB-1.6.3/series @@ -0,0 +1,3 @@ +DirectFB-1.6.3.stm.patch +directfb-1.6.3.no-vt.diff +directfb-1.6.3.enigma2remote.diff diff --git a/patches/MesaLib-8.0.3/0001-remove-crosscompile-check.patch b/patches/MesaLib-8.0.3/0001-remove-crosscompile-check.patch deleted file mode 100644 index a874846..0000000 --- a/patches/MesaLib-8.0.3/0001-remove-crosscompile-check.patch +++ /dev/null @@ -1,41 +0,0 @@ -From: Erwin Rol -Date: Wed, 7 Jul 2010 10:57:40 +0200 -Subject: [PATCH] remove crosscompile check - -When cross compiling it refuses to use assembly since it assumes it can -not use the gen_matypes tool. But we fixed the gen_matypes so now the -test is not needed anymore. - -Signed-off-by: Erwin Rol -Signed-off-by: Marc Kleine-Budde ---- - configure.ac | 16 ++++++++-------- - 1 file changed, 8 insertions(+), 8 deletions(-) - -diff --git a/configure.ac b/configure.ac -index fbaa376..1777d91 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -457,14 +457,14 @@ GLAPI_ASM_SOURCES="" - AC_MSG_CHECKING([whether to enable assembly]) - test "x$enable_asm" = xno && AC_MSG_RESULT([no]) - # disable if cross compiling on x86/x86_64 since we must run gen_matypes --if test "x$enable_asm" = xyes && test "x$cross_compiling" = xyes; then -- case "$host_cpu" in -- i?86 | x86_64) -- enable_asm=no -- AC_MSG_RESULT([no, cross compiling]) -- ;; -- esac --fi -+#if test "x$enable_asm" = xyes && test "x$cross_compiling" = xyes; then -+# case "$host_cpu" in -+# i?86 | x86_64) -+# enable_asm=no -+# AC_MSG_RESULT([no, cross compiling]) -+# ;; -+# esac -+#fi - # check for supported arches - if test "x$enable_asm" = xyes; then - case "$host_cpu" in diff --git a/patches/MesaLib-8.0.3/0002-HACK-allow-compiling-host-tools-without-configure.patch b/patches/MesaLib-8.0.3/0002-HACK-allow-compiling-host-tools-without-configure.patch deleted file mode 100644 index 7f43860..0000000 --- a/patches/MesaLib-8.0.3/0002-HACK-allow-compiling-host-tools-without-configure.patch +++ /dev/null @@ -1,48 +0,0 @@ -From: Michael Olbrich -Date: Wed, 7 Jul 2010 10:58:14 +0200 -Subject: [PATCH] HACK: allow compiling host tools without configure - -This patch modifies the Makefiles for the hosttools to allow -compiling without configure. This way we can avoid -unnecessary dependencies when only compiling host tools. - -Signed-off-by: Michael Olbrich ---- - src/glsl/Makefile | 9 +++++++-- - 1 file changed, 7 insertions(+), 2 deletions(-) - -diff --git a/src/glsl/Makefile b/src/glsl/Makefile -index d9ecbc8..c6726a7 100644 ---- a/src/glsl/Makefile -+++ b/src/glsl/Makefile -@@ -3,7 +3,11 @@ - - TOP = ../.. - -+ifeq ($(wildcard $(TOP)/configs/current),) -+include $(TOP)/configs/default -+else - include $(TOP)/configs/current -+endif - - LIBNAME = glsl - -@@ -118,7 +122,8 @@ endif - - # Dummy target - install: $(DRICORE_INSTALL_TARGET) -- @echo -n "" -+ $(INSTALL) -d $(DESTDIR)/bin/mesa/ -+ $(INSTALL) -m 755 builtin_compiler $(DESTDIR)/bin/mesa/ - - install-dricore: default - $(INSTALL) -d $(DESTDIR)$(DRI_DRIVER_INSTALL_DIR) -@@ -165,7 +170,7 @@ glcpp/glcpp-parse.c: glcpp/glcpp-parse.y - builtin_compiler: $(GLSL2_OBJECTS) $(OBJECTS) builtin_stubs.o - $(APP_CXX) $(INCLUDES) $(CXXFLAGS) $(LDFLAGS) $(OBJECTS) $(GLSL2_OBJECTS) builtin_stubs.o -o $@ - --builtin_function.cpp: builtins/profiles/* builtins/ir/* builtins/tools/generate_builtins.py builtins/tools/texture_builtins.py builtin_compiler -+builtin_function.cpp: builtins/profiles/* builtins/ir/* builtins/tools/generate_builtins.py builtins/tools/texture_builtins.py - @echo Regenerating builtin_function.cpp... - $(PYTHON2) $(PYTHON_FLAGS) builtins/tools/generate_builtins.py ./builtin_compiler > builtin_function.cpp || rm -f builtin_function.cpp - diff --git a/patches/MesaLib-8.0.3/autogen.sh b/patches/MesaLib-8.0.3/autogen.sh deleted file mode 120000 index 9f8a4cb..0000000 --- a/patches/MesaLib-8.0.3/autogen.sh +++ /dev/null @@ -1 +0,0 @@ -../autogen.sh \ No newline at end of file diff --git a/patches/MesaLib-8.0.3/series b/patches/MesaLib-8.0.3/series deleted file mode 100644 index d6e472d..0000000 --- a/patches/MesaLib-8.0.3/series +++ /dev/null @@ -1,5 +0,0 @@ -# generated by git-ptx-patches -#tag:base --start-number 1 -0001-remove-crosscompile-check.patch -0002-HACK-allow-compiling-host-tools-without-configure.patch -# 4eecf2c7eca888d7920cf111797a97d5 - git-ptx-patches magic diff --git a/patches/DirectFB-1.4.3/autogen.sh b/patches/MesaLib-9.2.0/autogen.sh similarity index 100% rename from patches/DirectFB-1.4.3/autogen.sh rename to patches/MesaLib-9.2.0/autogen.sh diff --git a/rules/directfb.in b/rules/directfb.in index 2fee80f..731550a 100644 --- a/rules/directfb.in +++ b/rules/directfb.in @@ -1,9 +1,9 @@ ## SECTION=multimedia_directfb menuconfig DIRECTFB - tristate - prompt "directfb " - + tristate + prompt "directfb" + select HOST_FLUXCOMP select HOST_DIRECTFB select MENU_XORG_FONTS select LIBPNG if DIRECTFB_IMAGE_PNG @@ -39,6 +39,9 @@ config DIRECTFB_X11 config DIRECTFB_FBDEV bool "Framebuffer Device support" +config DIRECTFB_STMFBDEV + bool "STM Framebuffer Device support" + config DIRECTFB_V4L bool "Video for Linux support" @@ -48,6 +51,12 @@ config DIRECTFB_V4L2 config DIRECTFB_FONT_FREETYPE bool "build freetype2 font provider" +config DIRECTFB_FONT_LINOTYPE + bool "build linotype font provider" + +config DIRECTFB_MME + bool "build with mme support" + config DIRECTFB_WM_UNIQUE bool "enable unique (wm module)" select DIRECTFB_IMAGE_PNG @@ -152,6 +161,9 @@ config DIRECTFB_INPUT_PS2MOUSE config DIRECTFB_INPUT_TSLIB bool "tslib" +config DIRECTFB_INPUT_ENIMGA2REMOTE + bool "enigma2remote" + endmenu endif diff --git a/rules/directfb.make b/rules/directfb.make index 53dca32..def6130 100644 --- a/rules/directfb.make +++ b/rules/directfb.make @@ -17,16 +17,16 @@ PACKAGES-$(PTXCONF_DIRECTFB) += directfb # # Paths and names # -DIRECTFB_VERSION := 1.4.3 -DIRECTFB_MD5 := 223e036da906ceb4bd44708026839ff1 -DIRECTFB := DirectFB-$(DIRECTFB_VERSION) -DIRECTFB_SUFFIX := tar.gz +DIRECTFB_VERSION := 1.6.3 +DIRECTFB_MD5 := bc6703bda1ab85f1d85a1633aa7de3a5 +DIRECTFB := DirectFB-$(DIRECTFB_VERSION) +DIRECTFB_SUFFIX := tar.bz2 DIRECTFB_SOURCE := $(SRCDIR)/$(DIRECTFB).$(DIRECTFB_SUFFIX) DIRECTFB_DIR := $(BUILDDIR)/$(DIRECTFB) DIRECTFB_URL := \ - http://www.directfb.org/downloads/Core/DirectFB-1.4/$(DIRECTFB).$(DIRECTFB_SUFFIX) \ - http://www.directfb.org/downloads/Old/$(DIRECTFB).$(DIRECTFB_SUFFIX) + http://ptxdist.sat-universum.de/$(DIRECTFB).$(DIRECTFB_SUFFIX) + # ---------------------------------------------------------------------------- # Prepare @@ -41,6 +41,7 @@ DIRECTFB_INPUT-$(PTXCONF_DIRECTFB_INPUT_KEYBOARD) += keyboard DIRECTFB_INPUT-$(PTXCONF_DIRECTFB_INPUT_LINUXINPUT) += linuxinput DIRECTFB_INPUT-$(PTXCONF_DIRECTFB_INPUT_PS2MOUSE) += ps2mouse DIRECTFB_INPUT-$(PTXCONF_DIRECTFB_INPUT_TSLIB) += tslib +DIRECTFB_INPUT-$(PTXCONF_DIRECTFB_INPUT_ENIMGA2REMOTE) += enigma2remote DIRECTFB_GFX-$(PTXCONF_DIRECTFB_GFX_ATI128) += ati128 @@ -69,15 +70,20 @@ DIRECTFB_GFX-$(PTXCONF_DIRECTFB_GFX_VMWARE) += vmware # DIRECTFB_AUTOCONF := \ $(CROSS_AUTOCONF_USR) \ - --without-tests \ + --enable-static \ + --with-tests \ --with-tools \ --disable-osx \ --disable-network \ + --disable-multicore \ --disable-multi \ - --disable-voodoo \ + --enable-voodoo \ + --disable-devmem \ --disable-sdl \ + --disable-webp \ + --with-message-size=65536 \ + --disable-linotype \ --disable-vnc \ - --disable-sysfs \ --disable-zlib \ --with-gfxdrivers=$(subst $(space),$(comma),$(DIRECTFB_GFX-y)) \ --with-inputdrivers=$(subst $(space),$(comma),$(DIRECTFB_INPUT-y)) @@ -94,6 +100,12 @@ else DIRECTFB_AUTOCONF += --disable-fbdev endif +ifdef PTXCONF_DIRECTFB_STMFBDEV +DIRECTFB_AUTOCONF += --enable-stmfbdev +else +DIRECTFB_AUTOCONF += --disable-stmfbdev +endif + ifdef PTXCONF_DIRECTFB_V4L DIRECTFB_AUTOCONF += --enable-video4linux else @@ -108,10 +120,10 @@ endif ifdef PTXCONF_DIRECTFB_DEBUG DIRECTFB_AUTOCONF += --enable-debug -DIRECTFB_MODULE_DIRECTORY := /usr/lib/directfb-1.4-0 +DIRECTFB_MODULE_DIRECTORY := /usr/lib/directfb-1.6-0 else DIRECTFB_AUTOCONF += --disable-debug-support -DIRECTFB_MODULE_DIRECTORY := /usr/lib/directfb-1.4-0-pure +DIRECTFB_MODULE_DIRECTORY := /usr/lib/directfb-1.6-0-pure endif ifdef PTXCONF_DIRECTFB_TRACE @@ -120,6 +132,12 @@ else DIRECTFB_AUTOCONF += --disable-trace endif +ifdef PTXCONF_DIRECTFB_MME +DIRECTFB_AUTOCONF += --enable-mme +else +DIRECTFB_AUTOCONF += --disable-mme +endif + ifdef PTXCONF_DIRECTFB_WM_UNIQUE DIRECTFB_AUTOCONF += --enable-unique else @@ -150,6 +168,12 @@ else DIRECTFB_AUTOCONF += --disable-freetype endif +ifdef PTXCONF_DIRECTFB_FONT_LINOTYPE +DIRECTFB_AUTOCONF += --enable-linotype +else +DIRECTFB_AUTOCONF += --disable-linotype +endif + # ---------------------------------------------------------------------------- # Target-Install # ---------------------------------------------------------------------------- @@ -194,12 +218,13 @@ endif @$(call install_copy, directfb, 0, 0, 0755, -, /usr/bin/dfbinfo) - @$(call install_lib, directfb, 0, 0, 0644, libdirectfb-1.4) - @$(call install_lib, directfb, 0, 0, 0644, libfusion-1.4) - @$(call install_lib, directfb, 0, 0, 0644, libdirect-1.4) + @$(call install_lib, directfb, 0, 0, 0644, libdirectfb-1.6) + @$(call install_lib, directfb, 0, 0, 0644, libfusion-1.6) + @$(call install_lib, directfb, 0, 0, 0644, libdirect-1.6) + @$(call install_lib, directfb, 0, 0, 0644, libvoodoo-1.6) ifdef PTXCONF_DIRECTFB_WM_UNIQUE - @$(call install_lib, directfb, 0, 0, 0644, libuniquewm-1.4) + @$(call install_lib, directfb, 0, 0, 0644, libuniquewm-1.6) endif @cd $(DIRECTFB_PKGDIR) && for plugin in `find ./$(DIRECTFB_MODULE_DIRECTORY) -name "*.so"`; do \ diff --git a/rules/flex.make b/rules/flex.make index 4ce6489..93a20d0 100644 --- a/rules/flex.make +++ b/rules/flex.make @@ -16,7 +16,7 @@ PACKAGES-$(PTXCONF_FLEX) += flex # # Paths and names # -FLEX_VERSION := 2.5.35 +FLEX_VERSION := 2.5.37 FLEX_MD5 := 10714e50cea54dc7a227e3eddcd44d57 FLEX := flex-$(FLEX_VERSION) FLEX_SUFFIX := tar.bz2 diff --git a/rules/fluxcomp.in b/rules/fluxcomp.in new file mode 100644 index 0000000..5f0eb3e --- /dev/null +++ b/rules/fluxcomp.in @@ -0,0 +1,29 @@ +## SECTION=system_libraries + +config FLUXCOMP + tristate + prompt "fluxcomp" + help + A fast lexical analyzer generator + + Flex is a tool for generating scanners: programs which + recognized lexical patterns in text. It reads the given + input files for a description of a scanner to generate. The + description is in the form of pairs of regular expressions + and C code, called rules. Flex generates as output a C + source file, lex.yy.c, which defines a routine yylex(). This + file is compiled and linked with the -lfl library to produce + an executable. When the executable is run, it analyzes its + input for occurrences of the regular expressions. Whenever + it finds one, it executes the corresponding C code. + + The behaviour of Flex has undergone a major change since + version 2.5.4a. Flex scanners are now reentrant, and it is + now possible to have multiple scanners in the same program + with differing sets of defaults, and the scanners play nicer + with modern C and C++ compilers. The Flip side is that Flex + no longer conforms to the POSIX lex behaviour, and the + scanners require conforming implementations when flex is + used in ANSI C mode. + + Homepage: http://flex.sf.net/ diff --git a/rules/fluxcomp.make b/rules/fluxcomp.make new file mode 100644 index 0000000..922478f --- /dev/null +++ b/rules/fluxcomp.make @@ -0,0 +1,82 @@ +# -*-makefile-*- +# +# Copyright (C) 2009 by Marc Kleine-Budde +# +# See CREDITS for details about who has contributed to this project. +# +# For further information about the PTXdist project and license conditions +# see the README file. +# + +# +# We provide this package +# +PACKAGES-$(PTXCONF_FLUXCOMP) += fluxcomp + +# +# Paths and names +# +FLUXCOMP_VERSION := f4ebde5d16ea1cba3e16e1ec3a1cf51a40c77eea +FLUXCOMP := fluxcomp-$(FLUXCOMP_VERSION) +FLUXCOMP_URL := git://git.directfb.org/git/directfb/core/flux +FLUXCOMP_BRANCH := master +FLUXCOMP_GIT_HEAD := $(FLUXCOMP_VERSION) +FLUXCOMP_SOURCE := $(SRCDIR)/flux.git +FLUXCOMP_DIR := $(BUILDDIR)/$(FLUXCOMP) +FLUXCOMP_LICENSE := unknown + +# ---------------------------------------------------------------------------- +# Extract +# ---------------------------------------------------------------------------- + +$(STATEDIR)/fluxcomp.extract: + @$(call targetinfo) + @$(call clean, $(FLUXCOMP_DIR)) + @$(call extract, FLUXCOMP) + + @$(call patchin, FLUXCOMP) + + cd $(FLUXCOMP_DIR) && [ -f configure ] || sh autogen.sh + @$(call touch) + +# ---------------------------------------------------------------------------- +# Prepare +# ---------------------------------------------------------------------------- + +FLUXCOMP_PATH := PATH=$(CROSS_PATH) +FLUXCOMP_ENV := $(CROSS_ENV) + +# +# autoconf +# +FLUXCOMP_AUTOCONF := $(CROSS_AUTOCONF_USR) + +# ---------------------------------------------------------------------------- +# Target-Install +# ---------------------------------------------------------------------------- + +$(STATEDIR)/fluxcomp.targetinstall: + @$(call targetinfo) + + @$(call install_init, fluxcomp) + @$(call install_fixup, fluxcomp,PRIORITY,optional) + @$(call install_fixup, fluxcomp,SECTION,base) + @$(call install_fixup, fluxcomp,AUTHOR,"Marc Kleine-Budde ") + @$(call install_fixup, fluxcomp,DESCRIPTION,missing) + +# +# HACK: +# +# we need a ipkg, because some packages may depend on us, e.g.: +# "at" +# +# because we don't provide any shared libraries, +# we just put an existing dir into the package +# +# @$(call install_copy, fluxcomp, 0, 0, 0755, /usr/sbin) + +# @$(call install_finish, fluxcomp) + + @$(call touch) + +# vim: syntax=make diff --git a/rules/fuse.make b/rules/fuse.make index 3033f56..a43e9a0 100644 --- a/rules/fuse.make +++ b/rules/fuse.make @@ -16,8 +16,8 @@ PACKAGES-$(PTXCONF_FUSE) += fuse # # Paths and names # -FUSE_VERSION := 2.9.0 -FUSE_MD5 := 894ee11674f89a915ae87524aed55bc4 +FUSE_VERSION := 2.9.3 +FUSE_MD5 := 33cae22ca50311446400daf8a6255c6a FUSE := fuse-$(FUSE_VERSION) FUSE_SUFFIX := tar.gz FUSE_URL := $(call ptx/mirror, SF, fuse/$(FUSE).$(FUSE_SUFFIX)) diff --git a/rules/glew.make b/rules/glew.make index 08acaff..0869c62 100644 --- a/rules/glew.make +++ b/rules/glew.make @@ -16,8 +16,8 @@ PACKAGES-$(PTXCONF_GLEW) += glew # # Paths and names # -GLEW_VERSION := 1.5.2 -GLEW_MD5 := 310916d887253dc9f4be6ab13501603a +GLEW_VERSION := 1.10.0 +GLEW_MD5 := 2f09e5e6cb1b9f3611bcac79bc9c2d5d GLEW := glew-$(GLEW_VERSION) GLEW_SUFFIX := tgz GLEW_URL := $(call ptx/mirror, SF, glew/$(GLEW_VERSION)/$(GLEW).$(GLEW_SUFFIX)) @@ -39,9 +39,9 @@ GLEW_MAKE_OPT := \ $(CROSS_ENV_CC) \ $(CROSS_ENV_AR) \ LD=$(CROSS_CC) \ - CFLAGS.EXTRA='$(CROSS_CPPFLAGS) $(CROSS_CFLAGS)' \ - LDFLAGS.EXTRA='$(CROSS_LDFLAGS)' \ - LDFLAGS.GL='`$(CROSS_ENV) eval PATH=$(CROSS_PATH) $$PKG_CONFIG --libs glu`' \ + CFLAGS.EXTRA='' \ + LDFLAGS.EXTRA='' \ + LDFLAGS.GL='-lGL -lX11' \ GLEW_DEST=$(GLEW_PKGDIR)/usr \ LIBDIR=$(GLEW_PKGDIR)/usr/lib \ M_ARCH=$(PTXCONF_ARCH_STRING) diff --git a/rules/glu.in b/rules/glu.in new file mode 100644 index 0000000..1f4a798 --- /dev/null +++ b/rules/glu.in @@ -0,0 +1,9 @@ +## SECTION=multimedia_libs + +config GLU + tristate + prompt "glu" + select MESALIB + select MESALIB_OPENGL + help + Mesa OpenGL utility library (GLU) diff --git a/rules/glu.make b/rules/glu.make new file mode 100644 index 0000000..b268081 --- /dev/null +++ b/rules/glu.make @@ -0,0 +1,61 @@ +# -*-makefile-*- +# +# Copyright (C) 2013 by Michael Olbrich +# +# See CREDITS for details about who has contributed to this project. +# +# For further information about the PTXdist project and license conditions +# see the README file. +# + +# +# We provide this package +# +PACKAGES-$(PTXCONF_GLU) += glu + +# +# Paths and names +# +GLU_VERSION := 9.0.0 +GLU_MD5 := be9249132ff49275461cf92039083030 +GLU := glu-$(GLU_VERSION) +GLU_SUFFIX := tar.bz2 +GLU_URL := ftp://ftp.freedesktop.org/pub/mesa/glu/$(GLU).$(GLU_SUFFIX) +GLU_SOURCE := $(SRCDIR)/$(GLU).$(GLU_SUFFIX) +GLU_DIR := $(BUILDDIR)/$(GLU) +GLU_LICENSE := unknown + +# ---------------------------------------------------------------------------- +# Prepare +# ---------------------------------------------------------------------------- + +# +# autoconf +# +GLU_CONF_TOOL := autoconf +GLU_CONF_OPT := \ + $(CROSS_AUTOCONF_USR) \ + --disable-static \ + --disable-debug \ + --disable-osmesa + +# ---------------------------------------------------------------------------- +# Target-Install +# ---------------------------------------------------------------------------- + +$(STATEDIR)/glu.targetinstall: + @$(call targetinfo) + + @$(call install_init, glu) + @$(call install_fixup, glu,PRIORITY,optional) + @$(call install_fixup, glu,SECTION,base) + @$(call install_fixup, glu,AUTHOR,"Michael Olbrich ") + @$(call install_fixup, glu,DESCRIPTION,missing) + + @$(call install_lib, glu, 0, 0, 0644, libGLU) + + @$(call install_finish, glu) + + @$(call touch) + +# vim: syntax=make diff --git a/rules/host-fluxcomp.in b/rules/host-fluxcomp.in new file mode 100644 index 0000000..bed53f1 --- /dev/null +++ b/rules/host-fluxcomp.in @@ -0,0 +1,8 @@ +## SECTION=hosttools_noprompt + +config HOST_FLUXCOMP + tristate + default ALLYES + help + Flex, the fast lexical analyser generator. + diff --git a/rules/host-fluxcomp.make b/rules/host-fluxcomp.make new file mode 100644 index 0000000..35936ae --- /dev/null +++ b/rules/host-fluxcomp.make @@ -0,0 +1,63 @@ +# -*-makefile-*- +# +# Copyright (C) 2008 by mol@pengutronix.de +# +# See CREDITS for details about who has contributed to this project. +# +# For further information about the PTXdist project and license conditions +# see the README file. +# + +# +# We provide this package +# +HOST_PACKAGES-$(PTXCONF_HOST_FLUXCOMP) += host-fluxcomp +# +# Paths and names +# +HOST_FLEX_DIR = $(HOST_BUILDDIR)/$(FLUXCOMP) +# ---------------------------------------------------------------------------- +# Extract +# ---------------------------------------------------------------------------- + +$(STATEDIR)/host-fluxcomp.extract: + @$(call targetinfo) + @$(call clean, $(HOST_FLUXCOMP_DIR)) + @$(call extract, HOST_FLUXCOMP) + + @$(call patchin, HOST_FLUXCOMP) + + cd $(HOST_FLUXCOMP_DIR) && [ -f configure ] || sh autogen.sh + @$(call touch) + +# ---------------------------------------------------------------------------- +# Prepare +# ---------------------------------------------------------------------------- + +# +# autoconf +# +HOST_FLUXCOMP_CONF_TOOL := autoconf +HOST_FLUXCOMP_CONF_OPT = \ + $(HOST_AUTOCONF) \ + $(FLUXCOMP_AUTOCONF_SHARED) + +$(STATEDIR)/host-fluxcomp.compile: + @$(call targetinfo) + + cd $(HOST_FLUXCOMP_DIR) && $(HOST_FLUXCOMP_PATH) $(HOST_FLUXCOMP_CONF_ENV) \ + $(MAKE) $(PARALLELMFLAGS_BROKEN) $(HOST_FLUXCOMP_MAKEVARS) all + @$(call touch) + +# ---------------------------------------------------------------------------- +# Install +# ---------------------------------------------------------------------------- + +$(STATEDIR)/host-fluxcomp.install: + @$(call targetinfo) + @$(call world/install, HOST_FLUXCOMP) +# # don't install headers, so packages like the kernel don't use it + @rm -r $(HOST_FLUXCOMP_PKGDIR)/include + @$(call touch) + +# vim: syntax=make diff --git a/rules/host-mesalib.in b/rules/host-mesalib.in index 6e64e0b..1627c51 100644 --- a/rules/host-mesalib.in +++ b/rules/host-mesalib.in @@ -3,3 +3,5 @@ config HOST_MESALIB tristate select HOST_MAKEDEPEND + select HOST_SYSTEM_PYTHON + select HOST_SYSTEM_PYTHON_XML2 diff --git a/rules/host-mesalib.make b/rules/host-mesalib.make index 364b194..db2cdd3 100644 --- a/rules/host-mesalib.make +++ b/rules/host-mesalib.make @@ -14,14 +14,56 @@ HOST_PACKAGES-$(PTXCONF_HOST_MESALIB) += host-mesalib HOST_MESALIB_DIR = $(HOST_BUILDDIR)/Mesa-$(MESALIB_VERSION) -HOST_MESALIB_SUBDIR := src/glsl # ---------------------------------------------------------------------------- # Prepare # ---------------------------------------------------------------------------- -HOST_MESALIB_CONF_TOOL := NO -# gcc & g++ are provided by the wrappers and call the correct tools -HOST_MESALIB_MAKE_OPT := CC=gcc CXX=g++ builtin_compiler +HOST_MESALIB_CONF_ENV := \ + $(HOST_ENV) \ + ac_cv_prog_PYTHON2=$(PTXDIST_TOPDIR)/bin/python + +HOST_MESALIB_CONF_TOOL := autoconf +HOST_MESALIB_CONF_OPT := \ + $(HOST_AUTOCONF) \ + --disable-static \ + --enable-shared \ + --disable-debug \ + --disable-mangling \ + --disable-texture-float \ + --disable-asm \ + --disable-selinux \ + --enable-opengl \ + --disable-gles1 \ + --disable-gles2 \ + --disable-openvg \ + --disable-dri \ + --disable-glx \ + --disable-osmesa \ + --disable-gallium-osmesa \ + --disable-egl \ + --disable-xorg \ + --disable-xa \ + --disable-gbm \ + --disable-xvmc \ + --disable-vdpau \ + --disable-opencl \ + --disable-xlib-glx \ + --disable-gallium-egl \ + --disable-gallium-gbm \ + --disable-r600-llvm-compiler \ + --disable-gallium-tests \ + --disable-shared-glapi \ + --disable-driglx-direct \ + --disable-glx-tls \ + --disable-gallium-llvm \ + --with-gallium-drivers= \ + --with-dri-drivers= \ + --without-expat + +$(STATEDIR)/host-mesalib.install: + @$(call targetinfo) + install -D -m755 $(HOST_MESALIB_DIR)/src/glsl/builtin_compiler/builtin_compiler $(HOST_MESALIB_PKGDIR)/bin/mesa/builtin_compiler + @$(call touch) # vim: syntax=make diff --git a/rules/libdrm.in b/rules/libdrm.in index c4cf5f4..2710722 100644 --- a/rules/libdrm.in +++ b/rules/libdrm.in @@ -21,5 +21,33 @@ config LIBDRM_INTEL bool prompt "intel KMS support" +config LIBDRM_RADEON + bool + prompt "radeon KMS support" + +config LIBDRM_NOUVEAU + bool + prompt "nouveau KMS support" + +config LIBDRM_VMWGFX + bool + prompt "vmwgfx KMS support" + +config LIBDRM_OMAP + bool + prompt "omap KMS support" + +config LIBDRM_EXYNOS + bool + prompt "exynos KMS support" + +config LIBDRM_FREEDRENO + bool + prompt "freedreno KMS support" + +config LIBDRM_TESTS + bool + prompt "install test programs" + endif diff --git a/rules/libdrm.make b/rules/libdrm.make index d029d56..e6e7820 100644 --- a/rules/libdrm.make +++ b/rules/libdrm.make @@ -17,8 +17,8 @@ PACKAGES-$(PTXCONF_LIBDRM) += libdrm # # Paths and names # -LIBDRM_VERSION := 2.4.35 -LIBDRM_MD5 := 77992a226118a55e214f315bf23d4273 +LIBDRM_VERSION := 2.4.46 +LIBDRM_MD5 := b454a43366eb386294f87a5cd16699e6 LIBDRM := libdrm-$(LIBDRM_VERSION) LIBDRM_SUFFIX := tar.gz LIBDRM_URL := http://dri.freedesktop.org/libdrm/$(LIBDRM).$(LIBDRM_SUFFIX) @@ -29,6 +29,23 @@ LIBDRM_DIR := $(BUILDDIR)/$(LIBDRM) # Prepare # ---------------------------------------------------------------------------- +ifdef PTXCONF_ARCH_X86 +LIBDRM_BACKENDS-$(PTXCONF_LIBDRM_INTEL) += intel +endif +LIBDRM_BACKENDS-$(PTXCONF_LIBDRM_RADEON) += radeon +LIBDRM_BACKENDS-$(PTXCONF_LIBDRM_NOUVEAU) += nouveau +LIBDRM_BACKENDSC-$(PTXCONF_LIBDRM_VMWGFX) += vmwgfx +LIBDRM_BACKENDSC-$(PTXCONF_LIBDRM_OMAP) += omap-experimental-api +LIBDRM_BACKENDSL-$(PTXCONF_LIBDRM_OMAP) += omap +LIBDRM_BACKENDSC-$(PTXCONF_LIBDRM_EXYNOS) += exynos-experimental-api +LIBDRM_BACKENDSL-$(PTXCONF_LIBDRM_EXYNOS) += exynos +LIBDRM_BACKENDSC-$(PTXCONF_LIBDRM_FREEDRENO) += freedreno-experimental-api +LIBDRM_BACKENDSL-$(PTXCONF_LIBDRM_FREEDRENO) += freedreno + +LIBDRM_BACKENDSC-y += $(LIBDRM_BACKENDS-y) +LIBDRM_BACKENDSC- += $(LIBDRM_BACKENDS-) +LIBDRM_BACKENDSL-y += $(LIBDRM_BACKENDS-y) + # # autoconf # @@ -37,9 +54,12 @@ LIBDRM_CONF_OPT := \ $(CROSS_AUTOCONF_USR) \ --enable-udev \ --$(call ptx/endis, PTXCONF_LIBDRM_LIBKMS)-libkms \ - --$(call ptx/endis, PTXCONF_LIBDRM_INTEL)-intel \ - --disable-radeon \ - --disable-nouveau + $(addprefix --enable-,$(LIBDRM_BACKENDSC-y)) \ + $(addprefix --disable-,$(LIBDRM_BACKENDSC-)) \ + --$(call ptx/endis, PTXCONF_LIBDRM_TESTS)-install-test-programs \ + --disable-cairo-tests \ + --disable-manpages + # ---------------------------------------------------------------------------- # Target-Install @@ -59,10 +79,14 @@ $(STATEDIR)/libdrm.targetinstall: ifdef PTXCONF_LIBDRM_LIBKMS @$(call install_lib, libdrm, 0, 0, 0644, libkms) endif -ifdef PTXCONF_ARCH_X86 -ifdef PTXCONF_LIBDRM_INTEL - @$(call install_lib, libdrm, 0, 0, 0644, libdrm_intel) -endif + @$(foreach backend,$(LIBDRM_BACKENDSL-y), \ + $(call install_lib, libdrm, 0, 0, 0644, libdrm_$(backend));) + +ifdef PTXCONF_LIBDRM_TESTS + @$(call install_copy, libdrm, 0, 0, 0755, -, /usr/bin/kmstest) + @$(call install_copy, libdrm, 0, 0, 0755, -, /usr/bin/modeprint) + @$(call install_copy, libdrm, 0, 0, 0755, -, /usr/bin/modetest) + @$(call install_copy, libdrm, 0, 0, 0755, -, /usr/bin/vbltest) endif @$(call install_finish, libdrm) diff --git a/rules/lldpd-bbinit.in b/rules/lldpd-bbinit.in new file mode 100644 index 0000000..103452a --- /dev/null +++ b/rules/lldpd-bbinit.in @@ -0,0 +1,9 @@ +## SECTION=initmethod_bbinit + +config LLDPD_BBINIT_LINK + string + depends on LLDPD_STARTSCRIPT + prompt "lldpd" + default "S28lldpd" + +# vim: ft=kconfig noet tw=72 diff --git a/rules/lldpd.in b/rules/lldpd.in new file mode 100644 index 0000000..c4b4434 --- /dev/null +++ b/rules/lldpd.in @@ -0,0 +1,95 @@ +## SECTION=networking + +menuconfig LLDPD + tristate + prompt "lldpd " + select INITMETHOD + select LIBEVENT + select NET_SNMP if LLDPD_SNMP + select NET_SNMP_MIB_MODULES_AGENTX if LLDPD_SNMP + select LIBXML2 if LLDPD_XML + select BUSYBOX_START_STOP_DAEMON if LLDPD_STARTSCRIPT + select BUSYBOX_FEATURE_START_STOP_DAEMON_LONG_OPTIONS if LLDPD_STARTSCRIPT + help + lldpd is an ISC-licensed implementation of LLDP for various + Unixes. It also supports some proprietary protocols. + +if LLDPD + +config LLDPD_PRIVSEP_USER + string + prompt "Which user to use for privilege separation" + default "nobody" + +config LLDPD_PRIVSEP_GROUP + string + prompt "Which group to use for privilege separation" + default "nogroup" + +config LLDPD_PRIVSEP_CHROOT + string + prompt "Which directory to use to chroot lldpd" + default "/var/run/lldpd" + +config LLDPD_CDP + bool + prompt "Enable Cisco Discovery Protocol" + default y + +config LLDPD_FDP + bool + prompt "Enable Foundry Discovery Protocol" + default y + +config LLDPD_EDP + bool + prompt "Enable Extreme Discovery Protocol" + default y + +config LLDPD_SONMP + bool + prompt "Enable SynOptics Network Management Protocol" + default y + +config LLDPD_LLDPMED + bool + prompt "Enable LLDP-MED extension" + default y + +config LLDPD_DOT1 + bool + prompt "Enable Dot1 extension (VLAN stuff)" + default y + +config LLDPD_DOT3 + bool + prompt "Enable Dot3 extension (PHY stuff)" + default y + +config LLDPD_OLDIES + bool + prompt "Enable compatibility with Linux kernel older than 2.6.18" + +config LLDPD_SNMP + bool + prompt "Enable the use of SNMP" + +config LLDPD_XML + bool + prompt "Enable XML output via libxml2" + +config LLDPD_STARTSCRIPT + bool + prompt "install /etc/init.d/lldpd" + default y + +config LLDPD_DAEMON_ARGS + string + prompt "additional arguments for daemon startup" + default "" + help + This could be -c -e -f -s … + +endif + +# vim: ft=kconfig noet tw=72 diff --git a/rules/lldpd.make b/rules/lldpd.make new file mode 100644 index 0000000..a999100 --- /dev/null +++ b/rules/lldpd.make @@ -0,0 +1,89 @@ +# -*-makefile-*- +# +# Copyright (C) 2013 by Alexander Dahl +# +# See CREDITS for details about who has contributed to this project. +# +# For further information about the PTXdist project and license conditions +# see the README file. +# + +# +# We provide this package +# +PACKAGES-$(PTXCONF_LLDPD) += lldpd + +# +# Paths and names +# +LLDPD_VERSION := 0.7.6 +LLDPD_MD5 := dbd90a68b91448dcb94a4a77c5d8ef65 +LLDPD := lldpd-$(LLDPD_VERSION) +LLDPD_SUFFIX := tar.gz +LLDPD_URL := http://media.luffy.cx/files/lldpd//$(LLDPD).$(LLDPD_SUFFIX) +LLDPD_SOURCE := $(SRCDIR)/$(LLDPD).$(LLDPD_SUFFIX) +LLDPD_DIR := $(BUILDDIR)/$(LLDPD) +LLDPD_LICENSE := ICS + +# ---------------------------------------------------------------------------- +# Prepare +# ---------------------------------------------------------------------------- + +LLDPD_CONF_TOOL := autoconf +LLDPD_CONF_OPT := $(CROSS_AUTOCONF_USR) \ + --disable-doxygen-doc \ + --without-embedded-libevent \ + --$(call ptx/endis, PTXCONF_LLDPD_CDP)-cdp \ + --$(call ptx/endis, PTXCONF_LLDPD_FDP)-fdp \ + --$(call ptx/endis, PTXCONF_LLDPD_EDP)-edp \ + --$(call ptx/endis, PTXCONF_LLDPD_SONMP)-sonmp \ + --$(call ptx/endis, PTXCONF_LLDPD_LLDPMED)-lldpmed \ + --$(call ptx/endis, PTXCONF_LLDPD_DOT1)-dot1 \ + --$(call ptx/endis, PTXCONF_LLDPD_DOT3)-dot3 \ + --$(call ptx/endis, PTXCONF_LLDPD_OLDIES)-oldies \ + --$(call ptx/wwo, PTXCONF_LLDPD_SNMP)-snmp \ + --$(call ptx/wwo, PTXCONF_LLDPD_XML)-xml \ + --with-privsep-user="$(PTXCONF_LLDPD_PRIVSEP_USER)" \ + --with-privsep-group="$(PTXCONF_LLDPD_PRIVSEP_GROUP)" \ + --with-privsep-chroot="$(PTXCONF_LLDPD_PRIVSEP_CHROOT)" + +# ---------------------------------------------------------------------------- +# Target-Install +# ---------------------------------------------------------------------------- + +$(STATEDIR)/lldpd.targetinstall: + @$(call targetinfo) + + @$(call install_init, lldpd) + @$(call install_fixup, lldpd,PRIORITY,optional) + @$(call install_fixup, lldpd,SECTION,base) + @$(call install_fixup, lldpd,AUTHOR,"Alexander Dahl ") + @$(call install_fixup, lldpd,DESCRIPTION,missing) + + @$(call install_copy, lldpd, 0, 0, 0755, -, /usr/sbin/lldpd) + @$(call install_copy, lldpd, $(PTXCONF_LLDPD_PRIVSEP_USER), \ + $(PTXCONF_LLDPD_PRIVSEP_GROUP), 4750, -, /usr/sbin/lldpcli) + @$(call install_link, lldpd, lldpcli, /usr/sbin/lldpctl) + + @$(call install_lib, lldpd, 0, 0, 0644, liblldpctl) + +ifdef PTXCONF_INITMETHOD_BBINIT +ifdef PTXCONF_LLDPD_STARTSCRIPT + @$(call install_alternative, lldpd, 0, 0, 0755, /etc/init.d/lldpd) + @$(call install_replace, lldpd, /etc/init.d/lldpd, \ + @DAEMON_ARGS@, $(PTXCONF_LLDPD_DAEMON_ARGS)) + @$(call install_replace, lldpd, /etc/init.d/lldpd, \ + @PRIVSEP_CHROOT@, $(PTXCONF_LLDPD_PRIVSEP_CHROOT)) + +ifneq ($(call remove_quotes,$(PTXCONF_LLDPD_BBINIT_LINK)),) + @$(call install_link, lldpd, ../init.d/lldpd, \ + /etc/rc.d/$(PTXCONF_LLDPD_BBINIT_LINK)) +endif +endif +endif + + @$(call install_finish, lldpd) + + @$(call touch) + +# vim: ft=make noet diff --git a/rules/log4cplus.make b/rules/log4cplus.make index b91ea67..b389dd0 100644 --- a/rules/log4cplus.make +++ b/rules/log4cplus.make @@ -17,8 +17,8 @@ PACKAGES-$(PTXCONF_LOG4CPLUS) += log4cplus # # Paths and names # -LOG4CPLUS_VERSION := 1.1.0 -LOG4CPLUS_MD5 := 8f04a7b2db55384440b0ab83b6362d5d +LOG4CPLUS_VERSION := 1.1.1 +LOG4CPLUS_MD5 := e7844ba5c18073d9936e14def184d60a LOG4CPLUS := log4cplus-$(LOG4CPLUS_VERSION) LOG4CPLUS_SUFFIX := tar.xz LOG4CPLUS_URL := $(call ptx/mirror, SF, log4cplus/$(LOG4CPLUS).$(LOG4CPLUS_SUFFIX)) diff --git a/rules/mesa-demos.in b/rules/mesa-demos.in index 8e10794..d244d02 100644 --- a/rules/mesa-demos.in +++ b/rules/mesa-demos.in @@ -1,13 +1,40 @@ -## SECTION=multimedia_xorg_support_libs +## SECTION=multimedia_libs menuconfig MESA_DEMOS bool select MESALIB select GLEW + select GLU + select MESALIB_EGL if MESA_DEMOS_EGL + select MESALIB_GLES1 if MESA_DEMOS_GLES1 + select MESALIB_GLES2 if MESA_DEMOS_GLES2 + select MESALIB_OPENVG if MESA_DEMOS_VG + select MESALIB_EGL_WAYLAND if MESA_DEMOS_WAYLAND + select XORG_LIB_X11 if MESA_DEMOS_X11 + select XORG_LIB_XEXT if MESA_DEMOS_X11 prompt "mesa tools & demos " if MESA_DEMOS +config MESA_DEMOS_GLES1 + bool + +config MESA_DEMOS_EGL + bool + +config MESA_DEMOS_X11 + bool + +config MESA_DEMOS_WAYLAND + bool + +menuconfig MESA_DEMOS_X + bool + select MESA_DEMOS_X11 + prompt "X demos" + +if MESA_DEMOS_X11 + config MESA_DEMOS_CORENDER bool prompt "corender" @@ -88,6 +115,10 @@ config MESA_DEMOS_PBINFO bool prompt "pbinfo" +config MESA_DEMOS_SHAPE + bool + prompt "shape" + config MESA_DEMOS_SHAREDTEX bool prompt "sharedtex" @@ -111,5 +142,55 @@ config MESA_DEMOS_XFONT config MESA_DEMOS_XROTFONTDEMO bool prompt "xrotfontdemo" +endif + +menuconfig MESA_DEMOS_GLES2 + bool + select MESA_DEMOS_EGL + prompt "OpenGL ES2 demos" + +if MESA_DEMOS_GLES2 + +config MESA_DEMOS_ES2_INFO + bool + prompt "es2_info" + +config MESA_DEMOS_ES2GEARS_SCREEN + bool + prompt "es2gears_screen" + +config MESA_DEMOS_ES2GEARS_X11 + bool + prompt "es2gears_x11" + +config MESA_DEMOS_ES2TRI + bool + prompt "es2tri" + +config MESA_DEMOS_ES2GEARS_WAYLAND + bool + select MESA_DEMOS_WAYLAND + prompt "es2gears_wayland" + +endif + +menuconfig MESA_DEMOS_VG + bool + select MESA_DEMOS_GLES1 + select MESA_DEMOS_EGL + select MESA_DEMOS_X11 + prompt "OpenVG demos" + +if MESA_DEMOS_VG + +config MESA_DEMOS_VGIMAGE2TEX + bool + prompt "vgimage2tex" + +config MESA_DEMOS_TEX2VGIMAGE + bool + prompt "tex2vgimage" + +endif endif diff --git a/rules/mesa-demos.make b/rules/mesa-demos.make index 25bfbdf..d2d6de6 100644 --- a/rules/mesa-demos.make +++ b/rules/mesa-demos.make @@ -16,8 +16,8 @@ PACKAGES-$(PTXCONF_MESA_DEMOS) += mesa-demos # # Paths and names # -MESA_DEMOS_VERSION := 8.0.1 -MESA_DEMOS_MD5 := 320c2a4b6edc6faba35d9cb1e2a30bf4 +MESA_DEMOS_VERSION := 8.1.0 +MESA_DEMOS_MD5 := 9df33ba69a26bbfbc7c8148602e59542 MESA_DEMOS := mesa-demos-$(MESA_DEMOS_VERSION) MESA_DEMOS_SUFFIX := tar.bz2 MESA_DEMOS_URL := ftp://ftp.freedesktop.org/pub/mesa/demos/$(MESA_DEMOS_VERSION)/$(MESA_DEMOS).$(MESA_DEMOS_SUFFIX) @@ -29,10 +29,29 @@ MESA_DEMOS_LICENSE := unknown # Prepare # ---------------------------------------------------------------------------- +MESA_DEMOS_CONF_ENV := \ + $(CROSS_ENV) \ + ac_cv_header_GL_glut_h=no \ + ac_cv_lib_glut_glutInit=no + # # autoconf # MESA_DEMOS_CONF_TOOL := autoconf +MESA_DEMOS_CONF_OPT := \ + $(CROSS_AUTOCONF_USR) \ + --disable-static \ + --$(call ptx/endis, PTXCONF_MESA_DEMOS_EGL)-egl \ + --$(call ptx/endis, PTXCONF_MESA_DEMOS_GLES1)-gles1 \ + --$(call ptx/endis, PTXCONF_MESA_DEMOS_GLES2)-gles2 \ + --$(call ptx/endis, PTXCONF_MESA_DEMOS_VG)-vg \ + --disable-osmesa \ + --disable-libdrm \ + --$(call ptx/endis, PTXCONF_MESA_DEMOS_X11)-x11 \ + --$(call ptx/endis, PTXCONF_MESA_DEMOS_WAYLAND)-wayland \ + --disable-gbm \ + --disable-freetype2 \ + # ---------------------------------------------------------------------------- # Target-Install @@ -41,7 +60,7 @@ MESA_DEMOS_CONF_TOOL := autoconf MESA_DEMOS_BIN-$(PTXCONF_MESA_DEMOS_CORENDER) += corender MESA_DEMOS_BIN-$(PTXCONF_MESA_DEMOS_GLSYNC) += glsync MESA_DEMOS_BIN-$(PTXCONF_MESA_DEMOS_GLTHREADS) += glthreads -MESA_DEMOS_BIN-$(PTXCONF_MESA_DEMOS_GLXCONTEXTS) += glxcontexts +MESA_DEMOS_BIN-$(PTXCONF_MESA_DEMOS_GLXCONTEXTS) += glxcontexts MESA_DEMOS_BIN-$(PTXCONF_MESA_DEMOS_GLXDEMO) += glxdemo MESA_DEMOS_BIN-$(PTXCONF_MESA_DEMOS_GLXGEARS) += glxgears MESA_DEMOS_BIN-$(PTXCONF_MESA_DEMOS_GLXGEARS_FBCONFIG) += glxgears_fbconfig @@ -58,12 +77,20 @@ MESA_DEMOS_BIN-$(PTXCONF_MESA_DEMOS_OFFSET) += offset MESA_DEMOS_BIN-$(PTXCONF_MESA_DEMOS_OVERLAY) += overlay MESA_DEMOS_BIN-$(PTXCONF_MESA_DEMOS_PBDEMO) += pbdemo MESA_DEMOS_BIN-$(PTXCONF_MESA_DEMOS_PBINFO) += pbinfo +MESA_DEMOS_BIN-$(PTXCONF_MESA_DEMOS_SHAPE) += shape MESA_DEMOS_BIN-$(PTXCONF_MESA_DEMOS_SHAREDTEX) += sharedtex MESA_DEMOS_BIN-$(PTXCONF_MESA_DEMOS_SHAREDTEX_MT) += sharedtex_mt MESA_DEMOS_BIN-$(PTXCONF_MESA_DEMOS_TEXTURE_FROM_PIXMAP)+= texture_from_pixmap MESA_DEMOS_BIN-$(PTXCONF_MESA_DEMOS_WINCOPY) += wincopy MESA_DEMOS_BIN-$(PTXCONF_MESA_DEMOS_XFONT) += xfont MESA_DEMOS_BIN-$(PTXCONF_MESA_DEMOS_XROTFONTDEMO) += xrotfontdemo +MESA_DEMOS_BIN-$(PTXCONF_MESA_DEMOS_ES2_INFO) += es2_info +MESA_DEMOS_BIN-$(PTXCONF_MESA_DEMOS_ES2GEARS_SCREEN) += es2gears_screen +MESA_DEMOS_BIN-$(PTXCONF_MESA_DEMOS_ES2GEARS_WAYLAND) += es2gears_wayland +MESA_DEMOS_BIN-$(PTXCONF_MESA_DEMOS_ES2GEARS_X11) += es2gears_x11 +MESA_DEMOS_BIN-$(PTXCONF_MESA_DEMOS_ES2TRI) += es2tri +MESA_DEMOS_BIN-$(PTXCONF_MESA_DEMOS_TEX2VGIMAGE) += tex2vgimage +MESA_DEMOS_BIN-$(PTXCONF_MESA_DEMOS_VGIMAGE2TEX) += vgimage2tex $(STATEDIR)/mesa-demos.targetinstall: @$(call targetinfo) diff --git a/rules/mesalib.in b/rules/mesalib.in index 9494949..617a3d6 100644 --- a/rules/mesalib.in +++ b/rules/mesalib.in @@ -1,23 +1,32 @@ -## SECTION=multimedia_xorg_support_libs +## SECTION=multimedia_libs menuconfig MESALIB tristate prompt "mesa " - select LIBDRM - select DRI2PROTO select HOST_MESALIB select HOST_MAKEDEPEND select HOST_SYSTEM_PYTHON select HOST_SYSTEM_PYTHON_XML2 - select XORG_LIB_X11 if MESALIB_DRI - select XORG_LIB_XEXT if MESALIB_DRI || MESALIB_XLIB_GLX - select XORG_LIB_XXF86VM if MESALIB_DRI - select XORG_LIB_XDAMAGE if MESALIB_DRI - select XORG_LIB_XFIXES if MESALIB_DRI - select XORG_PROTO_GL if MESALIB_DRI - select EXPAT if MESALIB_DRI select GCCLIBS select GCCLIBS_CXX + select LIBDRM + select UDEV if MESALIB_UDEV + select UDEV_LIBUDEV if MESALIB_UDEV + select WAYLAND if MESALIB_EGL_WAYLAND + select LIBDRM_RADEON if MESALIB_DRI_R200 + select LIBDRM_RADEON if MESALIB_DRI_R300 + select LIBDRM_RADEON if MESALIB_DRI_R600 + select LIBDRM_RADEON if MESALIB_DRI_RADEONSI + select LIBDRM_NOUVEAU if MESALIB_DRI_NOUVEAU + select LIBDRM_FREEDRENO if MESALIB_DRI_FREEDRENO + select DRI2PROTO if MESALIB_GLX + select XORG_LIB_X11 if MESALIB_GLX + select XORG_LIB_XEXT if MESALIB_GLX + select XORG_LIB_XXF86VM if MESALIB_GLX + select XORG_LIB_XDAMAGE if MESALIB_GLX + select XORG_LIB_XFIXES if MESALIB_GLX + select XORG_PROTO_GL if MESALIB_GLX + select EXPAT if MESALIB_GLX help Mesa is a 3-D graphics library with an API which is very similar to that of OpenGL. See the project homepage for @@ -27,84 +36,107 @@ menuconfig MESALIB if MESALIB -config MESALIB_DRI - prompt "DRI modules" +config MESALIB_UDEV bool config MESALIB_GLX prompt "GLX library" bool -config MESALIB_XLIB_GLX - depends on MESALIB_GLX - default !MESALIB_DRI && !MESALIB_OSMESA +comment "Drivers" + +config MESALIB_DRI_SWRAST bool + prompt "Software Rasterizer" -config MESALIB_OSMESA - prompt "OSMesa library" +config MESALIB_DRI_I915 bool + select MESALIB_OPENGL + prompt "Intel i915" -if MESALIB_DRI +config MESALIB_DRI_I965 + bool + select MESALIB_OPENGL + prompt "Intel i965" -config MESALIB_DRI_SWRAST +config MESALIB_DRI_R200 bool - prompt "Software Rasterizer " + select MESALIB_OPENGL + prompt "AMD R200" -menuconfig MESALIB_DRI_INTEL +config MESALIB_DRI_R300 bool - prompt "Intel DRI drivers " + prompt "AMD R300" -if MESALIB_DRI_INTEL +config MESALIB_DRI_R600 + bool + prompt "AMD R600" -config MESALIB_DRI_I915 +config MESALIB_DRI_RADEONSI bool - prompt "i915" + # needs LLVM + depends on BROKEN + prompt "AMD RadeonSI" -config MESALIB_DRI_I965 +config MESALIB_DRI_NOUVEAU_VIEUX bool - prompt "i965" + select MESALIB_OPENGL + prompt "Nvidia <= GForce4" -endif +config MESALIB_DRI_NOUVEAU + bool + prompt "Nvidia > GForce4" -menuconfig MESALIB_DRI_ATI +config MESALIB_DRI_FREEDRENO bool - prompt "Ati DRI drivers " + prompt "Freedreno" -if MESALIB_DRI_ATI +comment "API Support" -config MESALIB_DRI_R200 +config MESALIB_OPENGL bool - # needs libdrm_radeon - depends on BROKEN - prompt "r200" + prompt "OpenGL" -config MESALIB_DRI_R300 +config MESALIB_GLES1 bool - prompt "r300" + prompt "OpenGL ES1" -config MESALIB_DRI_R600 +config MESALIB_GLES2 bool - prompt "r600" + select MESALIB_OPENGL + prompt "OpenGL ES2" -config MESALIB_DRI_RADEON +config MESALIB_OPENVG bool - # needs libdrm_radeon - depends on BROKEN - prompt "radeon" + prompt "OpenVG" -endif +config MESALIB_EGL + bool + select MESALIB_UDEV + prompt "EGL" -menu "Other DRI Drivers " +config MESALIB_GBM + bool + select MESALIB_UDEV + prompt "GBM" -config MESALIB_DRI_NOUVEAU +if MESALIB_EGL + +comment "EGL Platforms" + +config MESALIB_EGL_X11 bool - # need libdrm_nouveau - depends on BROKEN - prompt "nouveau" + default MESALIB_GLX -endmenu +config MESALIB_EGL_DRM + bool + select MESALIB_GBM + prompt "DRM" -endif +config MESALIB_EGL_WAYLAND + bool + prompt "Wayland" endif +endif diff --git a/rules/mesalib.make b/rules/mesalib.make index e988333..1efdcef 100644 --- a/rules/mesalib.make +++ b/rules/mesalib.make @@ -19,11 +19,11 @@ PACKAGES-$(PTXCONF_MESALIB) += mesalib # # Paths and names # -MESALIB_VERSION := 8.0.3 -MESALIB_MD5 := cc5ee15e306b8c15da6a478923797171 +MESALIB_VERSION := 9.2.0 +MESALIB_MD5 := 4185b6aae890bc62a964f4b24cc1aca8 MESALIB := MesaLib-$(MESALIB_VERSION) MESALIB_SUFFIX := tar.bz2 -MESALIB_URL := ftp://ftp.freedesktop.org/pub/mesa/$(MESALIB_VERSION)/$(MESALIB).$(MESALIB_SUFFIX) +MESALIB_URL := ftp://ftp.freedesktop.org/pub/mesa/9.2/$(MESALIB).$(MESALIB_SUFFIX) MESALIB_SOURCE := $(SRCDIR)/$(MESALIB).$(MESALIB_SUFFIX) MESALIB_DIR := $(BUILDDIR)/Mesa-$(MESALIB_VERSION) @@ -39,22 +39,40 @@ ifdef PTXCONF_ARCH_X86 MESALIB_DRI_DRIVERS-$(PTXCONF_MESALIB_DRI_I915) += i915 MESALIB_DRI_DRIVERS-$(PTXCONF_MESALIB_DRI_I965) += i965 endif -MESALIB_DRI_DRIVERS-$(PTXCONF_MESALIB_DRI_NOUVEAU) += nouveau +MESALIB_DRI_DRIVERS-$(PTXCONF_MESALIB_DRI_NOUVEAU_VIEUX)+= nouveau MESALIB_DRI_DRIVERS-$(PTXCONF_MESALIB_DRI_R200) += r200 -MESALIB_DRI_DRIVERS-$(PTXCONF_MESALIB_DRI_RADEON) += radeon -MESALIB_DRI_DRIVERS-$(PTXCONF_MESALIB_DRI_SWRAST) += swrast -ifdef PTXCONF_ARCH_X86 -MESALIB_GALLIUM_DRIVERS-$(PTXCONF_MESALIB_DRI_I915) += i915 -endif ifndef PTXCONF_ARCH_X86 # needs llvm MESALIB_GALLIUM_DRIVERS-$(PTXCONF_MESALIB_DRI_R300) += r300 endif MESALIB_GALLIUM_DRIVERS-$(PTXCONF_MESALIB_DRI_R600) += r600 +MESALIB_GALLIUM_DRIVERS-$(PTXCONF_MESALIB_DRI_RADEONSI) += radeonsi + MESALIB_GALLIUM_DRIVERS-$(PTXCONF_MESALIB_DRI_NOUVEAU) += nouveau +MESALIB_GALLIUM_DRIVERS-$(PTXCONF_MESALIB_DRI_FREEDRENO)+= freedreno + MESALIB_GALLIUM_DRIVERS-$(PTXCONF_MESALIB_DRI_SWRAST) += swrast -MESALIB_DRI_LIBS-y += $(MESALIB_DRI_DRIVERS-y) $(MESALIB_GALLIUM_DRIVERS-y) +MESALIB_DRI_LIBS-y += \ + $(MESALIB_DRI_DRIVERS-y) \ + $(subst freedreno,kgsl,$(MESALIB_GALLIUM_DRIVERS-y)) + +MESALIB_LIBS-y := libglapi +ifneq ($(MESALIB_DRI_DRIVERS-y),) +MESALIB_LIBS-y += libdricore$(MESALIB_VERSION) +endif +MESALIB_LIBS-$(PTXCONF_MESALIB_GLX) += libGL +MESALIB_LIBS-$(PTXCONF_MESALIB_GLES1) += libGLESv1_CM +MESALIB_LIBS-$(PTXCONF_MESALIB_GLES2) += libGLESv2 +MESALIB_LIBS-$(PTXCONF_MESALIB_OPENVG) += libOpenVG +MESALIB_LIBS-$(PTXCONF_MESALIB_EGL) += libEGL egl/egl_gallium +MESALIB_LIBS-$(PTXCONF_MESALIB_GBM) += libgbm gbm/gbm_gallium_drm + +MESALIB_LIBS-y += $(addprefix gallium-pipe/pipe_,$(filter-out freedreno,$(MESALIB_GALLIUM_DRIVERS-y))) + +MESALIBS_EGL_PLATFORMS-$(PTXCONF_MESALIB_EGL_X11) += x11 +MESALIBS_EGL_PLATFORMS-$(PTXCONF_MESALIB_EGL_DRM) += drm +MESALIBS_EGL_PLATFORMS-$(PTXCONF_MESALIB_EGL_WAYLAND) += wayland MESALIB_CONF_TOOL := autoconf MESALIB_CONF_OPT := \ @@ -65,46 +83,35 @@ MESALIB_CONF_OPT := \ --disable-mangling \ --disable-texture-float \ --disable-asm \ - --enable-pic \ --disable-selinux \ - --enable-opengl \ - --disable-gles1 \ - --disable-gles2 \ - --disable-openvg \ - --$(call ptx/endis, PTXCONF_MESALIB_DRI)-dri \ + --$(call ptx/endis, PTXCONF_MESALIB_OPENGL)-opengl \ + --$(call ptx/endis, PTXCONF_MESALIB_GLES1)-gles1 \ + --$(call ptx/endis, PTXCONF_MESALIB_GLES2)-gles2 \ + --$(call ptx/endis, PTXCONF_MESALIB_OPENVG)-openvg \ + --enable-dri \ --$(call ptx/endis, PTXCONF_MESALIB_GLX)-glx \ - --$(call ptx/endis, PTXCONF_MESALIB_OSMESA)-osmesa \ - --disable-egl \ + --disable-osmesa \ + --disable-gallium-osmesa \ + --$(call ptx/endis, PTXCONF_MESALIB_EGL)-egl \ --disable-xorg \ --disable-xa \ - --disable-d3d1x \ - --disable-gbm \ + --$(call ptx/endis, PTXCONF_MESALIB_GBM)-gbm \ --disable-xvmc \ --disable-vdpau \ - --disable-va \ - --$(call ptx/endis, PTXCONF_MESALIB_XLIB_GLX)-xlib-glx \ - --disable-gallium-egl \ - --disable-gallium-gbm \ - --disable-shared-glapi \ + --disable-opencl \ + --disable-xlib-glx \ + --$(call ptx/endis, PTXCONF_MESALIB_EGL)-gallium-egl \ + --$(call ptx/endis, PTXCONF_MESALIB_GBM)-gallium-gbm \ + --disable-r600-llvm-compiler \ + --disable-gallium-tests \ + --enable-shared-glapi \ --enable-driglx-direct \ - --disable-shared-dricore \ - --$(call ptx/endis,PTXCONF_XORG_SERVER_OPT_GLX_TLS)-glx-tls \ - --disable-gallium-g3dvl \ - --enable-glu \ + --enable-glx-tls \ --disable-gallium-llvm \ --with-gallium-drivers=$(subst $(space),$(comma),$(MESALIB_GALLIUM_DRIVERS-y)) \ --with-dri-drivers=$(subst $(space),$(comma),$(MESALIB_DRI_DRIVERS-y)) \ - --with-expat=$(SYSROOT)/usr - - -# the 32/64 bit options result in CFLAGS -> -m32 and -m64 which seem -# only to be available on x86 - -ifdef PTXCONF_ARCH_X86 -MESALIB_CONF_OPT += \ - --enable-32-bit \ - --disable-64-bit -endif + --with-expat=$(SYSROOT)/usr \ + --with-egl-platforms="$(MESALIBS_EGL_PLATFORMS-y)" # ---------------------------------------------------------------------------- # Compile @@ -114,7 +121,7 @@ MESALIB_MAKE_OPT := HOST_CC=$(HOSTCC) $(STATEDIR)/mesalib.compile: @$(call targetinfo) - cp $(PTXCONF_SYSROOT_HOST)/bin/mesa/* $(MESALIB_DIR)/src/glsl/ + cp $(PTXCONF_SYSROOT_HOST)/bin/mesa/builtin_compiler $(MESALIB_DIR)/src/glsl/builtin_compiler/ @$(call compile, MESALIB) @$(call touch) @@ -131,16 +138,12 @@ $(STATEDIR)/mesalib.targetinstall: @$(call install_fixup, mesalib,AUTHOR,"Robert Schwebel ") @$(call install_fixup, mesalib,DESCRIPTION,missing) -ifdef PTXCONF_MESALIB_DRI @$(foreach lib, $(MESALIB_DRI_LIBS-y), \ - $(call install_copy, mesalib, 0, 0, 0644, -, /usr/lib/dri/$(lib)_dri.so);) -endif + $(call install_copy, mesalib, 0, 0, 0644, -, \ + /usr/lib/dri/$(lib)_dri.so);) - @$(call install_lib, mesalib, 0, 0, 0644, libGL) - @$(call install_lib, mesalib, 0, 0, 0644, libGLU) -ifdef PTXCONF_MESALIB_OSMESA - @$(call install_lib, mesalib, 0, 0, 0644, libOSMesa) -endif + @$(foreach lib, $(MESALIB_LIBS-y), \ + $(call install_lib, mesalib, 0, 0, 0644, $(lib));) @$(call install_finish, mesalib) diff --git a/rules/net-snmp.in b/rules/net-snmp.in index aed84a8..98829b3 100644 --- a/rules/net-snmp.in +++ b/rules/net-snmp.in @@ -6,57 +6,146 @@ menuconfig NET_SNMP select GCCLIBS_GCC_S if NET_SNMP_AGENT select LIBC_DL if NET_SNMP_AGENT || NET_SNMP_APPLICATIONS select LIBNL if NET_SNMP_AGENT || NET_SNMP_APPLICATIONS + select LM_SENSORS if NET_SNMP_MIB_MODULES_LM_SENSORS if NET_SNMP -config NET_SNMP_MINI_AGENT +menu "additional mib modules " + +config NET_SNMP_MIB_MODULES_AGENTX + prompt "agentx" bool - default y - prompt "minimal agent" + help + AgentX support (includes both agentx/master and agentx/client). -config NET_SNMP_AGENT +config NET_SNMP_MIB_MODULES_UCD_SNMP + prompt "ucd_snmp" bool - prompt "agent (snmpd)" + help + UCD-SNMP-MIB specific extensions. -config NET_SNMP_APPLICATIONS +config NET_SNMP_MIB_MODULES_LM_SENSORS + prompt "ucd-snmp/lmsensorsMib" bool - prompt "apps (snmpget, ...)" + help + hardware monitoring (LM-SENSORS-MIB) -config NET_SNMP_SCRIPTS +config NET_SNMP_MIB_MODULES + prompt "additional mib modules" + string + default "" + help + space separated list of optional modules + tunnel Linux TUNNEL-MIB support (ifTable extension) + mibII/interfaces (old ifTable implementation) + misc/ipfwacc accounting rules IP firewall information + ipfwchains/ipfwchains firewall chains under ipfw + sctp-mib support for the SCTP-MIB + etherlike-mib support for the EtherLike-MIB + +config NET_SNMP_WITHOUT_MIB_MODULES + prompt "without these mib modules" + string + default "" + help + space separated list of default mib modules compiled into the + agent (which can be removed): + mibII support for the mib-II tree. + snmpv3mibs support for the snmpv3 mib modules. + agent_mibs NET-SNMP-AGENT-MIB extensions + notification mibs supporting specification of trap destinations. + target Support for the SNMP WGs TARGET-MIB. + utilities general agent configuration utilities. + disman/event support for the DISMAN-EVENT-MIB + disman/schedule support for the DISMAN-SCHEDULE-MIB + host host resources mib support. + +endmenu + +menuconfig NET_SNMP_MIBS bool - prompt "scripts (mib2c, ...)" + prompt "mib files " -config NET_SNMP_MIBS +if NET_SNMP_MIBS + +config NET_SNMP_V1MIBS bool - prompt "mib files" + prompt "v1 MIBS" + default y + help + RFC1155-SMI, RFC1213-MIB, RFC-1215 -config NET_SNMP_MIB_LOADING +config NET_SNMP_V2MIBS bool - prompt "include code that parses and manipulates mib files" + prompt "v2 MIBS" + default y + help + SNMPv2-CONF, SNMPv2-SMI, SNMPv2-TC, SNMPv2-TM, SNMPv2-MIB -config NET_SNMP_SNMPV1 +config NET_SNMP_V3MIBS bool - prompt "support for SNMPv1" + prompt "v3 MIBS" + default y + help + SNMP-FRAMEWORK-MIB, SNMP-MPD-MIB, SNMP-TARGET-MIB, + SNMP-NOTIFICATION-MIB, SNMP-PROXY-MIB, SNMP-USER-BASED-SM-MIB, + SNMP-VIEW-BASED-ACM-MIB, SNMP-COMMUNITY-MIB, TRANSPORT-ADDRESS-MIB -config NET_SNMP_SNMPV2C +config NET_SNMP_AGENTMIBS bool - prompt "support for SNMPv2c" + prompt "agent MIBS" + default y + help + AGENTX-MIB, SMUX-MIB -config NET_SNMP_DES +config NET_SNMP_IANAMIBS bool - prompt "DES encryption" + prompt "IANA MIBS" + default y + help + IANAifType-MIB, IANA-LANGUAGE-MIB, IANA-ADDRESS-FAMILY-NUMBERS-MIB -config NET_SNMP_MD5 +config NET_SNMP_RFCMIBS bool - prompt "MD5 authentication" + prompt "RFC MIBS" + default y + help + IF-MIB, IF-INVERTED-STACK-MIB, EtherLike-MIB, IP-MIB, + IP-FORWARD-MIB, IANA-RTPROTO-MIB, TCP-MIB, UDP-MIB, + INET-ADDRESS-MIB, HCNUM-TC, HOST-RESOURCES-MIB, + HOST-RESOURCES-TYPES, RMON-MIB, IPV6-TC, IPV6-MIB, IPV6-ICMP-MIB, + IPV6-TCP-MIB, IPV6-UDP-MIB, DISMAN-EVENT-MIB, DISMAN-SCRIPT-MIB, + DISMAN-SCHEDULE-MIB, NOTIFICATION-LOG-MIB, SNMP-USM-AES-MIB, + SNMP-USM-DH-OBJECTS-MIB -config NET_SNMP_SNMPTRAPD +config NET_SNMP_NETSNMPMIBS bool - prompt "agentx subagent code in snmptrapd" + prompt "Net-SNMP MIBS" + default y + help + NET-SNMP-TC, NET-SNMP-MIB, NET-SNMP-AGENT-MIB, + NET-SNMP-EXAMPLES-MIB, NET-SNMP-EXTEND-MIB, NET-SNMP-PASS-MIB -config NET_SNMP_LOCAL_SMUX +config NET_SNMP_UCDMIBS bool - prompt "restrict SMUX connections to localhost (by default)" + prompt "UCD MIBS" + default y + help + UCD-SNMP-MIB, UCD-DEMO-MIB, UCD-IPFWACC-MIB, UCD-DLMOD-MIB, + UCD-DISKIO-MIB + +config NET_SNMP_LMSENSORS_MIB + bool "lm-sensors MIBS" if NET_SNMP_MIB_MODULES_LM_SENSORS + help + LM-SENSORS-MIB + +config NET_SNMP_OTHERMIBS + bool + prompt "other MIBS" + help + BRIDGE-MIB, IPV6-FLOW-LABEL-MIB, SCTP-MIB, TUNNEL-MIB + +endif choice prompt "debugging" @@ -82,6 +171,59 @@ config NET_SNMP_STRIP_DEBUGGING endchoice +config NET_SNMP_MINI_AGENT + bool + default y + prompt "minimal agent" + +config NET_SNMP_AGENT + bool + prompt "agent (snmpd)" + +config NET_SNMP_APPLICATIONS + bool + prompt "apps (snmpget, ...)" + +config NET_SNMP_SCRIPTS + bool + prompt "scripts (mib2c, ...)" + +config NET_SNMP_MIB_LOADING + bool + prompt "include code that parses and manipulates mib files" + +config NET_SNMP_SNMPV1 + bool + prompt "support for SNMPv1" + +config NET_SNMP_SNMPV2C + bool + prompt "support for SNMPv2c" + +config NET_SNMP_DES + bool + prompt "DES encryption" + +config NET_SNMP_MD5 + bool + prompt "MD5 authentication" + +config NET_SNMP_DOM_SOCK_ONLY + bool "Disable UDP/TCP transports for agentx" if NET_SNMP_AGENT + default y + help + Enable this to disable TCP and UDP connections for subagent + connections with AgentX protocol. Only unix socket connections are + allowed then. + +config NET_SNMP_SNMPTRAPD + bool + prompt "agentx subagent code in snmptrapd" + +config NET_SNMP_LOCAL_SMUX + bool + prompt "restrict SMUX connections to localhost (by default)" + config NET_SNMP_DEVELOPER bool prompt "super-duper-extra-compile-warnings using gcc" @@ -101,15 +243,14 @@ config NET_SNMP_PERSISTENT_DIR string default "/var/net-snmp" -config NET_SNMP_MIB_MODULES - prompt "additional mib modules" - string - default "" - config NET_SNMP_DEFAULT_MIBS prompt "default mib id's to read" string - default "" + default "SNMPv2-MIB:IF-MIB:IP-MIB:TCP-MIB:UDP-MIB" + help + Colon separated list of default mib IDs to read. (The default list + is "SNMPv2-MIB:IF-MIB:IP-MIB:TCP-MIB:UDP-MIB" with the addition of + any mibs used by the mib modules the agent is configured with) config NET_SNMP_MIB_INSTALL_DIR prompt "directory to install mib files" @@ -122,3 +263,5 @@ config NET_SNMP_DOM_SOCK_ONLY help Enable this to disable TCP and UDP connections to the agent. endif + +# vim: ft=kconfig noet tw=72 diff --git a/rules/net-snmp.make b/rules/net-snmp.make index 7a25043..6bdecd8 100644 --- a/rules/net-snmp.make +++ b/rules/net-snmp.make @@ -2,6 +2,7 @@ # # Copyright (C) 2006 by Randall Loomis # 2010 Michael Olbrich +# 2013 Alexander Dahl # # See CREDITS for details about who has contributed to this project. # @@ -31,7 +32,12 @@ NET_SNMP_DIR := $(BUILDDIR)/$(NET_SNMP) NET_SNMP_PATH := PATH=$(CROSS_PATH) NET_SNMP_ENV := $(CROSS_ENV) -NET_SNMP_BINCONFIG_GLOB := net-snmp-config + +NET_SNMP_MIB_MODULES-y := $(call remove_quotes,$(PTXCONF_NET_SNMP_MIB_MODULES)) +NET_SNMP_MIB_MODULES- := $(call remove_quotes,$(PTXCONF_NET_SNMP_WITHOUT_MIB_MODULES)) +NET_SNMP_MIB_MODULES-$(PTXCONF_NET_SNMP_MIB_MODULES_AGENTX) += agentx +NET_SNMP_MIB_MODULES-$(PTXCONF_NET_SNMP_MIB_MODULES_UCD_SNMP) += ucd_snmp +NET_SNMP_MIB_MODULES-$(PTXCONF_NET_SNMP_MIB_MODULES_LM_SENSORS) += ucd-snmp/lmsensorsMib # # autoconf @@ -42,7 +48,8 @@ NET_SNMP_AUTOCONF := \ --with-defaults \ --disable-manuals \ --without-openssl \ - --with-mib-modules=$(PTXCONF_NET_SNMP_MIB_MODULES) \ + --with-mib-modules="$(NET_SNMP_MIB_MODULES-y)" \ + --with-out-mib-modules="$(NET_SNMP_MIB_MODULES-)" \ --with-mibs=$(PTXCONF_NET_SNMP_DEFAULT_MIBS) \ --with-logfile=$(call remove_quotes,$(PTXCONF_NET_SNMP_LOGFILE)) \ --with-persistent-directory=$(call remove_quotes,$(PTXCONF_NET_SNMP_PERSISTENT_DIR)) \ @@ -54,11 +61,10 @@ NET_SNMP_AUTOCONF := \ --disable-privacy \ --disable-internal-md5 \ --$(call ptx/endis, PTXCONF_NET_SNMP_DOM_SOCK_ONLY)-agentx-dom-sock-only \ - --disable-mib-config-checking \ - --disable-mfd-rewrites \ + --enable-mib-config-checking \ + --enable-mfd-rewrites \ --disable-testing-code \ --disable-reentrant \ - --disable-embedded-perl \ --disable-ucd-snmp-compatibility ifdef PTXCONF_ENDIAN_LITTLE @@ -153,57 +159,79 @@ else NET_SNMP_AUTOCONF += --disable-developer endif -##NET_SNMP_AUTOCONF += --with-mib-modules=mibII -##NET_SNMP_AUTOCONF += --with-sys-contact=root@localhost -##NET_SNMP_AUTOCONF += --with-sys-location=unknown - NET_SNMP_MAKE_PAR := NO # ---------------------------------------------------------------------------- # Target-Install # ---------------------------------------------------------------------------- -NET_SNMP_LIBMAJOR := 25 -NET_SNMP_LIBMINOR := 0.1 -NET_SNMP_LIBVER :=$(NET_SNMP_LIBMAJOR).$(NET_SNMP_LIBMINOR) +NET_SNMP_MIBS := + +ifdef PTXCONF_NET_SNMP_MIBS -NET_SNMP_V1MIBS := RFC1155-SMI.txt RFC1213-MIB.txt RFC-1215.txt +ifdef PTXCONF_NET_SNMP_V1MIBS +NET_SNMP_MIBS += RFC1155-SMI.txt RFC1213-MIB.txt RFC-1215.txt +endif -NET_SNMP_V2MIBS := SNMPv2-CONF.txt SNMPv2-SMI.txt SNMPv2-TC.txt SNMPv2-TM.txt SNMPv2-MIB.txt +ifdef PTXCONF_NET_SNMP_V2MIBS +NET_SNMP_MIBS += SNMPv2-CONF.txt SNMPv2-SMI.txt SNMPv2-TC.txt \ + SNMPv2-TM.txt SNMPv2-MIB.txt +endif -NET_SNMP_V3MIBS := SNMP-FRAMEWORK-MIB.txt SNMP-MPD-MIB.txt SNMP-TARGET-MIB.txt \ - SNMP-NOTIFICATION-MIB.txt SNMP-PROXY-MIB.txt \ - SNMP-USER-BASED-SM-MIB.txt SNMP-VIEW-BASED-ACM-MIB.txt \ +ifdef PTXCONF_NET_SNMP_V3MIBS +NET_SNMP_MIBS += SNMP-FRAMEWORK-MIB.txt SNMP-MPD-MIB.txt \ + SNMP-TARGET-MIB.txt SNMP-NOTIFICATION-MIB.txt \ + SNMP-PROXY-MIB.txt SNMP-USER-BASED-SM-MIB.txt \ + SNMP-VIEW-BASED-ACM-MIB.txt \ SNMP-COMMUNITY-MIB.txt TRANSPORT-ADDRESS-MIB.txt +endif -NET_SNMP_AGENTMIBS := AGENTX-MIB.txt SMUX-MIB.txt +ifdef PTXCONF_NET_SNMP_AGENTMIBS +NET_SNMP_MIBS += AGENTX-MIB.txt SMUX-MIB.txt +endif -NET_SNMP_IANAMIBS := IANAifType-MIB.txt IANA-LANGUAGE-MIB.txt \ +ifdef PTXCONF_NET_SNMP_IANAMIBS +NET_SNMP_MIBS += IANAifType-MIB.txt IANA-LANGUAGE-MIB.txt \ IANA-ADDRESS-FAMILY-NUMBERS-MIB.txt +endif -NET_SNMP_RFCMIBS := IF-MIB.txt IF-INVERTED-STACK-MIB.txt \ - EtherLike-MIB.txt \ - IP-MIB.txt IP-FORWARD-MIB.txt IANA-RTPROTO-MIB.txt \ - TCP-MIB.txt UDP-MIB.txt \ - INET-ADDRESS-MIB.txt HCNUM-TC.txt \ - HOST-RESOURCES-MIB.txt HOST-RESOURCES-TYPES.txt \ - RMON-MIB.txt \ - IPV6-TC.txt IPV6-MIB.txt IPV6-ICMP-MIB.txt IPV6-TCP-MIB.txt \ - IPV6-UDP-MIB.txt \ - DISMAN-EVENT-MIB.txt DISMAN-SCRIPT-MIB.txt DISMAN-SCHEDULE-MIB.txt \ +ifdef PTXCONF_NET_SNMP_RFCMIBS +NET_SNMP_MIBS += IF-MIB.txt IF-INVERTED-STACK-MIB.txt \ + EtherLike-MIB.txt IP-MIB.txt \ + IP-FORWARD-MIB.txt IANA-RTPROTO-MIB.txt \ + TCP-MIB.txt UDP-MIB.txt INET-ADDRESS-MIB.txt \ + HCNUM-TC.txt HOST-RESOURCES-MIB.txt \ + HOST-RESOURCES-TYPES.txt RMON-MIB.txt \ + IPV6-TC.txt IPV6-MIB.txt IPV6-ICMP-MIB.txt \ + IPV6-TCP-MIB.txt IPV6-UDP-MIB.txt \ + DISMAN-EVENT-MIB.txt DISMAN-SCRIPT-MIB.txt \ + DISMAN-SCHEDULE-MIB.txt \ NOTIFICATION-LOG-MIB.txt SNMP-USM-AES-MIB.txt \ SNMP-USM-DH-OBJECTS-MIB.txt +endif -NET_SNMP_NETSNMPMIBS := NET-SNMP-TC.txt NET-SNMP-MIB.txt NET-SNMP-AGENT-MIB.txt \ - NET-SNMP-EXAMPLES-MIB.txt NET-SNMP-EXTEND-MIB.txt \ - NET-SNMP-PASS-MIB.txt +ifdef PTXCONF_NET_SNMP_NETSNMPMIBS +NET_SNMP_MIBS += NET-SNMP-TC.txt NET-SNMP-MIB.txt \ + NET-SNMP-AGENT-MIB.txt \ + NET-SNMP-EXAMPLES-MIB.txt \ + NET-SNMP-EXTEND-MIB.txt NET-SNMP-PASS-MIB.txt +endif -NET_SNMP_UCDMIBS := UCD-SNMP-MIB.txt UCD-DEMO-MIB.txt UCD-IPFWACC-MIB.txt \ +ifdef PTXCONF_NET_SNMP_UCDMIBS +NET_SNMP_MIBS += UCD-SNMP-MIB.txt UCD-DEMO-MIB.txt UCD-IPFWACC-MIB.txt \ UCD-DLMOD-MIB.txt UCD-DISKIO-MIB.txt +endif -## FIXME: for now, you need to manually edit this list to represent what mibs to install on target. -NET_SNMP_MIBS := $(NET_SNMP_V1MIBS) $(NET_SNMP_V2MIBS) $(NET_SNMP_V3MIBS) \ - $(NET_SNMP_AGENTMIBS) $(NET_SNMP_IANAMIBS) $(NET_SNMP_RFCMIBS) $(NET_SNMP_NETSNMPMIBS) $(NET_SNMP_UCDMIBS) +ifdef PTXCONF_NET_SNMP_LMSENSORS_MIB +NET_SNMP_MIBS += LM-SENSORS-MIB.txt +endif + +ifdef PTXCONF_NET_SNMP_OTHERMIBS +NET_SNMP_MIBS += BRIDGE-MIB.txt IPV6-FLOW-LABEL-MIB.txt SCTP-MIB.txt \ + TUNNEL-MIB.txt +endif + +endif $(STATEDIR)/net-snmp.targetinstall: @$(call targetinfo) @@ -264,9 +292,7 @@ endif # snmplib @$(call install_lib, net-snmp, 0, 0, 0644, libnetsnmp) -# MIB files ifdef PTXCONF_NET_SNMP_MIBS - @for i in $(NET_SNMP_MIBS); do \ $(call install_copy, net-snmp, 0, 0, 0644, -, \ $(call remove_quotes,$(PTXCONF_NET_SNMP_MIB_INSTALL_DIR))/$$i, n) ; \ @@ -276,4 +302,4 @@ endif @$(call install_finish, net-snmp) @$(call touch) -# vim: syntax=make +# vim: ft=make noet diff --git a/rules/pre/kernel.make b/rules/pre/kernel.make index b5f8092..3704c53 100644 --- a/rules/pre/kernel.make +++ b/rules/pre/kernel.make @@ -55,7 +55,7 @@ kernel/opts = \ HOSTCC=$(HOSTCC) \ ARCH=$(GENERIC_KERNEL_ARCH) \ CROSS_COMPILE=$(COMPILER_PREFIX) \ - DEPMOD=$(PTXCONF_SYSROOT_HOST)/sbin/depmod + DEPMOD=$(PTXCONF_SYSROOT_HOST)/sbin/depmod \ \ INSTALL_MOD_PATH=$($(1)_PKGDIR) \ PTX_KERNEL_DIR=$($(1)_DIR) diff --git a/rules/rtmpdump.make b/rules/rtmpdump.make index 109001c..60c8fc7 100644 --- a/rules/rtmpdump.make +++ b/rules/rtmpdump.make @@ -16,10 +16,10 @@ PACKAGES-$(PTXCONF_RTMPDUMP) += rtmpdump # # Paths and names # -RTMPDUMP_VERSION := 2.3 -RTMPDUMP_MD5 := eb961f31cd55f0acf5aad1a7b900ef59 +RTMPDUMP_VERSION := 2.4 +RTMPDUMP_MD5 := 8241345cf6476c1c1b9689494d6e820f RTMPDUMP := rtmpdump-$(RTMPDUMP_VERSION) -RTMPDUMP_SUFFIX := tgz +RTMPDUMP_SUFFIX := tar.gz RTMPDUMP_URL := http://rtmpdump.mplayerhq.hu/download/$(RTMPDUMP).$(RTMPDUMP_SUFFIX) RTMPDUMP_SOURCE := $(SRCDIR)/$(RTMPDUMP).$(RTMPDUMP_SUFFIX) RTMPDUMP_DIR := $(BUILDDIR)/$(RTMPDUMP) diff --git a/rules/sdparm.make b/rules/sdparm.make index 6c4dea1..924782c 100644 --- a/rules/sdparm.make +++ b/rules/sdparm.make @@ -16,8 +16,8 @@ PACKAGES-$(PTXCONF_SDPARM) += sdparm # # Paths and names # -SDPARM_VERSION := 1.04 -SDPARM_MD5 := b20c281bc185ea7d3c5e78a8c0be2a46 +SDPARM_VERSION := 1.07 +SDPARM_MD5 := c807f9db3dd7af175214be0d7fece494 SDPARM := sdparm-$(SDPARM_VERSION) SDPARM_SUFFIX := tgz SDPARM_URL := http://sg.danny.cz/sg/p/$(SDPARM).$(SDPARM_SUFFIX) diff --git a/rules/usb-modeswitch.make b/rules/usb-modeswitch.make index 6f49f1d..8b09d4a 100644 --- a/rules/usb-modeswitch.make +++ b/rules/usb-modeswitch.make @@ -16,8 +16,8 @@ PACKAGES-$(PTXCONF_USB_MODESWITCH) += usb-modeswitch # # Paths and names # -USB_MODESWITCH_VERSION := 1.2.5 -USB_MODESWITCH_MD5 := c393603908eceab95444c5bde790f6f0 +USB_MODESWITCH_VERSION := 1.2.7 +USB_MODESWITCH_MD5 := 18d889d72195534ae9133a8181cad42b USB_MODESWITCH := usb-modeswitch-$(USB_MODESWITCH_VERSION) USB_MODESWITCH_SUFFIX := tar.bz2 USB_MODESWITCH_URL := http://www.draisberghof.de/usb_modeswitch/$(USB_MODESWITCH).$(USB_MODESWITCH_SUFFIX) diff --git a/rules/wayland.make b/rules/wayland.make index c84de5c..5d833d9 100644 --- a/rules/wayland.make +++ b/rules/wayland.make @@ -16,8 +16,8 @@ PACKAGES-$(PTXCONF_WAYLAND) += wayland # # Paths and names # -WAYLAND_VERSION := 1.1.0 -WAYLAND_MD5 := d2dc9398a83692cafc16eba6e45f85d8 +WAYLAND_VERSION := 1.2.1 +WAYLAND_MD5 := dc75d060f23c0ef17ae95307cd525240 WAYLAND := wayland-$(WAYLAND_VERSION) WAYLAND_SUFFIX := tar.xz WAYLAND_URL := http://wayland.freedesktop.org/releases/$(WAYLAND).$(WAYLAND_SUFFIX) diff --git a/rules/xorg-server.in b/rules/xorg-server.in index cdee20e..8f73e32 100644 --- a/rules/xorg-server.in +++ b/rules/xorg-server.in @@ -384,7 +384,6 @@ config XORG_SERVER_EXT_GLX bool # This select doesn't work! But it is workarounded by mesalib only # presenting the DRI driver as it's backend if GLX is active. - select MESALIB_DRI select MESALIB_GLX prompt "glx extension" help