summaryrefslogtreecommitdiff
path: root/Source/DirectFB/systems/fbdev
diff options
context:
space:
mode:
Diffstat (limited to 'Source/DirectFB/systems/fbdev')
-rwxr-xr-xSource/DirectFB/systems/fbdev/Makefile.am48
-rwxr-xr-xSource/DirectFB/systems/fbdev/Makefile.in637
-rwxr-xr-xSource/DirectFB/systems/fbdev/agp.c511
-rwxr-xr-xSource/DirectFB/systems/fbdev/agp.h53
-rwxr-xr-xSource/DirectFB/systems/fbdev/fb.h366
-rwxr-xr-xSource/DirectFB/systems/fbdev/fbdev.c2782
-rwxr-xr-xSource/DirectFB/systems/fbdev/fbdev.h142
-rwxr-xr-xSource/DirectFB/systems/fbdev/fbdev_surface_pool.c423
-rwxr-xr-xSource/DirectFB/systems/fbdev/surfacemanager.c617
-rwxr-xr-xSource/DirectFB/systems/fbdev/surfacemanager.h117
-rwxr-xr-xSource/DirectFB/systems/fbdev/vt.c675
-rwxr-xr-xSource/DirectFB/systems/fbdev/vt.h83
12 files changed, 6454 insertions, 0 deletions
diff --git a/Source/DirectFB/systems/fbdev/Makefile.am b/Source/DirectFB/systems/fbdev/Makefile.am
new file mode 100755
index 0000000..9aa25b4
--- /dev/null
+++ b/Source/DirectFB/systems/fbdev/Makefile.am
@@ -0,0 +1,48 @@
+## Makefile.am for DirectFB/systems/fbdev
+
+INCLUDES = \
+ -I$(top_srcdir)/include \
+ -I$(top_builddir)/include \
+ -I$(top_builddir)/lib \
+ -I$(top_srcdir)/lib \
+ -I$(top_srcdir)/src
+
+AM_CPPFLAGS = -D_XOPEN_SOURCE=500
+
+
+internalincludedir = $(INTERNALINCLUDEDIR)/fbdev
+
+internalinclude_HEADERS = \
+ agp.h \
+ fb.h \
+ fbdev.h \
+ surfacemanager.h \
+ vt.h
+
+
+systemsdir = $(MODULEDIR)/systems
+
+if BUILD_STATIC
+systems_DATA = libdirectfb_fbdev.o
+endif
+systems_LTLIBRARIES = libdirectfb_fbdev.la
+
+libdirectfb_fbdev_la_LDFLAGS = \
+ -avoid-version \
+ -module \
+ $(SYSFS_LIBS)
+
+libdirectfb_fbdev_la_SOURCES = \
+ agp.c \
+ fbdev.c \
+ fbdev_surface_pool.c \
+ surfacemanager.c \
+ vt.c
+
+libdirectfb_fbdev_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/Source/DirectFB/systems/fbdev/Makefile.in b/Source/DirectFB/systems/fbdev/Makefile.in
new file mode 100755
index 0000000..ddf7e26
--- /dev/null
+++ b/Source/DirectFB/systems/fbdev/Makefile.in
@@ -0,0 +1,637 @@
+# Makefile.in generated by automake 1.10.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+DIST_COMMON = $(internalinclude_HEADERS) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in $(top_srcdir)/rules/libobject.make
+subdir = systems/fbdev
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/as-ac-expand.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(systemsdir)" "$(DESTDIR)$(systemsdir)" \
+ "$(DESTDIR)$(internalincludedir)"
+systemsLTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(systems_LTLIBRARIES)
+libdirectfb_fbdev_la_DEPENDENCIES = \
+ $(top_builddir)/lib/direct/libdirect.la \
+ $(top_builddir)/lib/fusion/libfusion.la \
+ $(top_builddir)/src/libdirectfb.la
+am_libdirectfb_fbdev_la_OBJECTS = agp.lo fbdev.lo \
+ fbdev_surface_pool.lo surfacemanager.lo vt.lo
+libdirectfb_fbdev_la_OBJECTS = $(am_libdirectfb_fbdev_la_OBJECTS)
+libdirectfb_fbdev_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(libdirectfb_fbdev_la_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libdirectfb_fbdev_la_SOURCES)
+DIST_SOURCES = $(libdirectfb_fbdev_la_SOURCES)
+systemsDATA_INSTALL = $(INSTALL_DATA)
+DATA = $(systems_DATA)
+internalincludeHEADERS_INSTALL = $(INSTALL_HEADER)
+HEADERS = $(internalinclude_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AS = @AS@
+ASFLAGS = @ASFLAGS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCAS = @CCAS@
+CCASDEPMODE = @CCASDEPMODE@
+CCASFLAGS = @CCASFLAGS@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIR = @DATADIR@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DFB_CFLAGS_OMIT_FRAME_POINTER = @DFB_CFLAGS_OMIT_FRAME_POINTER@
+DFB_INTERNAL_CFLAGS = @DFB_INTERNAL_CFLAGS@
+DFB_LDFLAGS = @DFB_LDFLAGS@
+DFB_SMOOTH_SCALING = @DFB_SMOOTH_SCALING@
+DIRECTFB_BINARY_AGE = @DIRECTFB_BINARY_AGE@
+DIRECTFB_CSOURCE = @DIRECTFB_CSOURCE@
+DIRECTFB_INTERFACE_AGE = @DIRECTFB_INTERFACE_AGE@
+DIRECTFB_MAJOR_VERSION = @DIRECTFB_MAJOR_VERSION@
+DIRECTFB_MICRO_VERSION = @DIRECTFB_MICRO_VERSION@
+DIRECTFB_MINOR_VERSION = @DIRECTFB_MINOR_VERSION@
+DIRECTFB_VERSION = @DIRECTFB_VERSION@
+DIRECT_BUILD_DEBUG = @DIRECT_BUILD_DEBUG@
+DIRECT_BUILD_DEBUGS = @DIRECT_BUILD_DEBUGS@
+DIRECT_BUILD_GETTID = @DIRECT_BUILD_GETTID@
+DIRECT_BUILD_NETWORK = @DIRECT_BUILD_NETWORK@
+DIRECT_BUILD_STDBOOL = @DIRECT_BUILD_STDBOOL@
+DIRECT_BUILD_TEXT = @DIRECT_BUILD_TEXT@
+DIRECT_BUILD_TRACE = @DIRECT_BUILD_TRACE@
+DSYMUTIL = @DSYMUTIL@
+DYNLIB = @DYNLIB@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+FREETYPE_CFLAGS = @FREETYPE_CFLAGS@
+FREETYPE_LIBS = @FREETYPE_LIBS@
+FREETYPE_PROVIDER = @FREETYPE_PROVIDER@
+FUSION_BUILD_KERNEL = @FUSION_BUILD_KERNEL@
+FUSION_BUILD_MULTI = @FUSION_BUILD_MULTI@
+FUSION_MESSAGE_SIZE = @FUSION_MESSAGE_SIZE@
+GIF_PROVIDER = @GIF_PROVIDER@
+GREP = @GREP@
+HAVE_LINUX = @HAVE_LINUX@
+INCLUDEDIR = @INCLUDEDIR@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTERNALINCLUDEDIR = @INTERNALINCLUDEDIR@
+JPEG_PROVIDER = @JPEG_PROVIDER@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBJPEG = @LIBJPEG@
+LIBOBJS = @LIBOBJS@
+LIBPNG = @LIBPNG@
+LIBPNG_CONFIG = @LIBPNG_CONFIG@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_AGE = @LT_AGE@
+LT_BINARY = @LT_BINARY@
+LT_CURRENT = @LT_CURRENT@
+LT_RELEASE = @LT_RELEASE@
+LT_REVISION = @LT_REVISION@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MAN2HTML = @MAN2HTML@
+MKDIR_P = @MKDIR_P@
+MODULEDIR = @MODULEDIR@
+MODULEDIRNAME = @MODULEDIRNAME@
+NMEDIT = @NMEDIT@
+OBJEXT = @OBJEXT@
+OSX_LIBS = @OSX_LIBS@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PNG_PROVIDER = @PNG_PROVIDER@
+RANLIB = @RANLIB@
+RUNTIME_SYSROOT = @RUNTIME_SYSROOT@
+SDL_CFLAGS = @SDL_CFLAGS@
+SDL_LIBS = @SDL_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOPATH = @SOPATH@
+STRIP = @STRIP@
+SYSCONFDIR = @SYSCONFDIR@
+SYSFS_LIBS = @SYSFS_LIBS@
+THREADFLAGS = @THREADFLAGS@
+THREADLIB = @THREADLIB@
+TSLIB_CFLAGS = @TSLIB_CFLAGS@
+TSLIB_LIBS = @TSLIB_LIBS@
+VERSION = @VERSION@
+VNC_CFLAGS = @VNC_CFLAGS@
+VNC_CONFIG = @VNC_CONFIG@
+VNC_LIBS = @VNC_LIBS@
+X11_CFLAGS = @X11_CFLAGS@
+X11_LIBS = @X11_LIBS@
+ZLIB_LIBS = @ZLIB_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+INCLUDES = \
+ -I$(top_srcdir)/include \
+ -I$(top_builddir)/include \
+ -I$(top_builddir)/lib \
+ -I$(top_srcdir)/lib \
+ -I$(top_srcdir)/src
+
+AM_CPPFLAGS = -D_XOPEN_SOURCE=500
+internalincludedir = $(INTERNALINCLUDEDIR)/fbdev
+internalinclude_HEADERS = \
+ agp.h \
+ fb.h \
+ fbdev.h \
+ surfacemanager.h \
+ vt.h
+
+systemsdir = $(MODULEDIR)/systems
+@BUILD_STATIC_TRUE@systems_DATA = libdirectfb_fbdev.o
+systems_LTLIBRARIES = libdirectfb_fbdev.la
+libdirectfb_fbdev_la_LDFLAGS = \
+ -avoid-version \
+ -module \
+ $(SYSFS_LIBS)
+
+libdirectfb_fbdev_la_SOURCES = \
+ agp.c \
+ fbdev.c \
+ fbdev_surface_pool.c \
+ surfacemanager.c \
+ vt.c
+
+libdirectfb_fbdev_la_LIBADD = \
+ $(top_builddir)/lib/direct/libdirect.la \
+ $(top_builddir)/lib/fusion/libfusion.la \
+ $(top_builddir)/src/libdirectfb.la
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/rules/libobject.make $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu systems/fbdev/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu systems/fbdev/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-systemsLTLIBRARIES: $(systems_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(systemsdir)" || $(MKDIR_P) "$(DESTDIR)$(systemsdir)"
+ @list='$(systems_LTLIBRARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ f=$(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(systemsLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(systemsdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(systemsLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(systemsdir)/$$f"; \
+ else :; fi; \
+ done
+
+uninstall-systemsLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(systems_LTLIBRARIES)'; for p in $$list; do \
+ p=$(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(systemsdir)/$$p'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(systemsdir)/$$p"; \
+ done
+
+clean-systemsLTLIBRARIES:
+ -test -z "$(systems_LTLIBRARIES)" || rm -f $(systems_LTLIBRARIES)
+ @list='$(systems_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libdirectfb_fbdev.la: $(libdirectfb_fbdev_la_OBJECTS) $(libdirectfb_fbdev_la_DEPENDENCIES)
+ $(libdirectfb_fbdev_la_LINK) -rpath $(systemsdir) $(libdirectfb_fbdev_la_OBJECTS) $(libdirectfb_fbdev_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/agp.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fbdev.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fbdev_surface_pool.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/surfacemanager.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vt.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-systemsDATA: $(systems_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(systemsdir)" || $(MKDIR_P) "$(DESTDIR)$(systemsdir)"
+ @list='$(systems_DATA)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f=$(am__strip_dir) \
+ echo " $(systemsDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(systemsdir)/$$f'"; \
+ $(systemsDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(systemsdir)/$$f"; \
+ done
+
+uninstall-systemsDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(systems_DATA)'; for p in $$list; do \
+ f=$(am__strip_dir) \
+ echo " rm -f '$(DESTDIR)$(systemsdir)/$$f'"; \
+ rm -f "$(DESTDIR)$(systemsdir)/$$f"; \
+ done
+install-internalincludeHEADERS: $(internalinclude_HEADERS)
+ @$(NORMAL_INSTALL)
+ test -z "$(internalincludedir)" || $(MKDIR_P) "$(DESTDIR)$(internalincludedir)"
+ @list='$(internalinclude_HEADERS)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f=$(am__strip_dir) \
+ echo " $(internalincludeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(internalincludedir)/$$f'"; \
+ $(internalincludeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(internalincludedir)/$$f"; \
+ done
+
+uninstall-internalincludeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(internalinclude_HEADERS)'; for p in $$list; do \
+ f=$(am__strip_dir) \
+ echo " rm -f '$(DESTDIR)$(internalincludedir)/$$f'"; \
+ rm -f "$(DESTDIR)$(internalincludedir)/$$f"; \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(DATA) $(HEADERS)
+installdirs:
+ for dir in "$(DESTDIR)$(systemsdir)" "$(DESTDIR)$(systemsdir)" "$(DESTDIR)$(internalincludedir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-systemsLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-internalincludeHEADERS install-systemsDATA \
+ install-systemsLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-info: install-info-am
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-ps: install-ps-am
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-internalincludeHEADERS uninstall-systemsDATA \
+ uninstall-systemsLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-systemsLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am \
+ install-internalincludeHEADERS install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ install-systemsDATA install-systemsLTLIBRARIES installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-internalincludeHEADERS \
+ uninstall-systemsDATA uninstall-systemsLTLIBRARIES
+
+%.o: .libs/%.a %.la
+ rm -f $<.tmp/*.o
+ if test -d $<.tmp; then rmdir $<.tmp; fi
+ mkdir $<.tmp
+ (cd $<.tmp && $(AR) x ../../$<)
+ $(LD) -o $@ -r $<.tmp/*.o
+ rm -f $<.tmp/*.o && rmdir $<.tmp
+
+.PHONY: $(LTLIBRARIES:%.la=.libs/%.a)
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/Source/DirectFB/systems/fbdev/agp.c b/Source/DirectFB/systems/fbdev/agp.c
new file mode 100755
index 0000000..286d4db
--- /dev/null
+++ b/Source/DirectFB/systems/fbdev/agp.c
@@ -0,0 +1,511 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+
+#include <asm/types.h> /* Needs to be included before dfb_types.h */
+
+#include <directfb.h>
+
+#include <direct/mem.h>
+#include <direct/messages.h>
+#include <direct/util.h>
+
+#include <fusion/fusion.h>
+#include <fusion/shmalloc.h>
+
+#include <core/core.h>
+#include <core/coredefs.h>
+#include <core/coretypes.h>
+
+#include <misc/conf.h>
+
+#include "fbdev.h"
+#include "agp.h"
+
+#define PAGE_SIZE direct_pagesize()
+
+/*****************************************************************************/
+
+extern FBDev *dfb_fbdev;
+
+static AGPDevice *dfb_agp = NULL;
+
+/*****************************************************************************/
+
+static DFBResult
+dfb_agp_info( agp_info *info )
+{
+ D_ASSERT( info != NULL );
+
+ if (ioctl( dfb_agp->fd, AGPIOC_INFO, info )) {
+ D_PERROR( "DirectFB/FBDev/agp: Could not get AGP info!\n" );
+ return errno2result( errno );
+ }
+
+ return DFB_OK;
+}
+
+static DFBResult
+dfb_agp_setup( u32 mode )
+{
+ agp_setup setup;
+
+ setup.agp_mode = mode;
+
+ if (ioctl( dfb_agp->fd, AGPIOC_SETUP, &setup )) {
+ D_PERROR( "DirectFB/FBDev/agp: AGP setup failed!\n" );
+ return errno2result( errno );
+ }
+
+ return DFB_OK;
+}
+
+static DFBResult
+dfb_agp_acquire( void )
+{
+ if (ioctl( dfb_agp->fd, AGPIOC_ACQUIRE, 0 )) {
+ D_PERROR( "DirectFB/FBDev/agp: Acquire failed!\n" );
+ return errno2result( errno );
+ }
+
+ return DFB_OK;
+}
+
+static DFBResult
+dfb_agp_release( void )
+{
+ if (ioctl( dfb_agp->fd, AGPIOC_RELEASE, 0 )) {
+ D_PERROR( "DirectFB/FBDev/agp: Release failed!\n" );
+ return errno2result( errno );
+ }
+
+ return DFB_OK;
+}
+
+static DFBResult
+dfb_agp_allocate( unsigned long size, int *key )
+{
+ agp_allocate alloc;
+ int pages;
+
+ D_ASSERT( key != NULL );
+
+ pages = size / PAGE_SIZE;
+ if (pages % PAGE_SIZE)
+ pages++;
+
+ if (pages == 0) {
+ D_BUG( "attempted to allocate 0 pages!");
+ return DFB_BUG;
+ }
+
+ alloc.pg_count = pages;
+ alloc.type = 0;
+
+ if (ioctl( dfb_agp->fd, AGPIOC_ALLOCATE, &alloc )) {
+ D_PERROR( "DirectFB/FBDev/agp: "
+ "Could not allocate %d pages!\n", pages );
+ return errno2result( errno );
+ }
+
+ *key = alloc.key;
+
+ return DFB_OK;
+}
+
+static DFBResult
+dfb_agp_deallocate( int key )
+{
+ if (ioctl( dfb_agp->fd, AGPIOC_DEALLOCATE, key )) {
+ D_PERROR( "DirectFB/FBDev/agp: "
+ "Deallocate failed (key = %d)!\n", key );
+ return errno2result( errno );
+ }
+
+ return DFB_OK;
+}
+
+static DFBResult
+dfb_agp_bind( unsigned int offset, int key )
+{
+ agp_bind bind;
+
+ if (offset % PAGE_SIZE) {
+ D_BUG( "offset is not page-aligned!" );
+ return DFB_BUG;
+ }
+
+ bind.pg_start = offset / PAGE_SIZE;
+ bind.key = key;
+
+ if (ioctl( dfb_agp->fd, AGPIOC_BIND, &bind )) {
+ D_PERROR( "DirectFB/FBDev/agp: "
+ "Bind failed (key = %d, offset = 0x%x)!\n",
+ key, offset );
+ return errno2result( errno );
+ }
+
+ return DFB_OK;
+}
+
+static DFBResult
+dfb_agp_unbind( int key )
+{
+ agp_unbind unbind;
+
+ unbind.priority = 0;
+ unbind.key = key;
+
+ if (ioctl( dfb_agp->fd, AGPIOC_UNBIND, &unbind )) {
+ D_PERROR( "DirectFB/FBDev/agp: "
+ "Unbind failed (key = %d)!\n",
+ key );
+ return errno2result( errno );
+ }
+
+ return DFB_OK;
+}
+
+/*****************************************************************************/
+
+static inline u16
+pci_read_word( int fd, int pos )
+{
+ u8 b[2];
+
+ if (pread( fd, b, 2, pos ) < 2)
+ return 0;
+
+ return b[0] | (b[1] << 8);
+}
+
+static inline u8
+pci_read_byte( int fd, int pos )
+{
+ u8 b;
+
+ if (pread( fd, &b, 1, pos ) < 1)
+ return 0;
+
+ return b;
+}
+
+#define PCI_STATUS 0x06
+#define PCI_STATUS_CAP_LIST 0x10
+#define PCI_CAPABILITY_LIST 0x34
+#define PCI_CAP_ID_AGP 0x02
+
+static bool
+dfb_agp_capable( int bus, int dev, int func )
+{
+ bool found = false;
+ char path[22];
+ int fd;
+
+ /* XXX: the following detection method requires suid root */
+
+ snprintf( path, sizeof(path),
+ "/proc/bus/pci/%02x/%02x.%01x", bus, dev, func );
+
+ fd = open( path, O_RDONLY | O_SYNC );
+ if (fd < 0) {
+ D_PERROR( "DirectFB/FBDev/agp: "
+ "Couldn't open '%s'!\n", path );
+ return false;
+ }
+
+ /* stolen from linux/drivers/pci/pci.c */
+ if (pci_read_word( fd, PCI_STATUS ) & PCI_STATUS_CAP_LIST) {
+ int pos, id;
+ int ttl = 48;
+
+ pos = pci_read_byte( fd, PCI_CAPABILITY_LIST );
+ while (ttl-- && pos >= 0x40) {
+ pos &= ~3;
+
+ id = pci_read_byte( fd, pos );
+ if (id == 0xff)
+ break;
+ if (id == PCI_CAP_ID_AGP) {
+ found = true;
+ break;
+ }
+
+ pos = pci_read_byte( fd, pos+1 );
+ }
+ }
+
+ close( fd );
+
+ return found;
+}
+
+/*****************************************************************************/
+
+DFBResult
+dfb_agp_initialize( void )
+{
+ AGPShared *shared;
+ unsigned int agp_avail;
+ DFBResult ret = DFB_FAILURE;
+
+ if (dfb_agp) {
+ D_BUG( "dfb_agp_initialize() already called!" );
+ return DFB_BUG;
+ }
+
+ /* Precheck for AGP capable device. */
+ if (!dfb_agp_capable( dfb_fbdev->shared->pci.bus,
+ dfb_fbdev->shared->pci.dev,
+ dfb_fbdev->shared->pci.func ))
+ return DFB_UNSUPPORTED;
+
+ dfb_agp = D_CALLOC( 1, sizeof(AGPDevice) );
+ if (!dfb_agp)
+ return D_OOM();
+
+ shared = SHCALLOC( dfb_fbdev->shared->shmpool, 1, sizeof(AGPShared) );
+ if (!shared) {
+ D_ERROR( "DirectFB/FBDev/agp: Could not allocate shared memory!\n" );
+ ret = DFB_NOSHAREDMEMORY;
+ goto error0;
+ }
+
+ dfb_agp->fd = direct_try_open( "/dev/agpgart",
+ "/dev/misc/agpgart", O_RDWR, true );
+ if (dfb_agp->fd < 0) {
+ ret = errno2result( errno );
+ D_ERROR( "DirectFB/FBDev/agp: Error opening AGP device!\n" );
+ goto error1;
+ }
+
+ ret = dfb_agp_acquire();
+ if (ret)
+ goto error2;
+
+ ret = dfb_agp_info( &shared->info );
+ if (ret)
+ goto error2;
+
+ D_DEBUG( "DirectFB/FBDev/agp: "
+ "Bridge supports: AGP%s%s%s%s%s%s\n",
+ shared->info.agp_mode & 0x001 ? " 1X" : "",
+ shared->info.agp_mode & 0x002 ? " 2X" : "",
+ shared->info.agp_mode & 0x004 ? " 4X" : "",
+ shared->info.agp_mode & 0x008 ? " 8X" : "",
+ shared->info.agp_mode & 0x200 ? ", SBA" : "",
+ shared->info.agp_mode & 0x010 ? ", FW" : "" );
+
+ shared->info.agp_mode &= ~0xf;
+ shared->info.agp_mode |= dfb_config->agp;
+ shared->info.agp_mode |= dfb_config->agp - 1;
+
+ ret = dfb_agp_setup( shared->info.agp_mode );
+ if (ret)
+ goto error2;
+ dfb_agp_info( &shared->info );
+
+ D_DEBUG( "DirectFB/FBDev/agp: "
+ "AGP aperture at 0x%x (%zu MB)\n",
+ (unsigned int)shared->info.aper_base, shared->info.aper_size );
+
+ agp_avail = (shared->info.pg_total - shared->info.pg_used) * PAGE_SIZE;
+ if (agp_avail == 0) {
+ D_ERROR( "DirectFB/FBDev/agp: No AGP memory available!\n" );
+ ret = DFB_INIT;
+ goto error2;
+ }
+
+ shared->agp_mem = shared->info.aper_size << 20;
+ if (shared->agp_mem > agp_avail)
+ shared->agp_mem = agp_avail;
+
+ ret = dfb_agp_allocate( shared->agp_mem, &shared->agp_key );
+ if (ret)
+ goto error3;
+
+ ret = dfb_agp_bind( shared->agp_key, 0 );
+ if (ret)
+ goto error4;
+
+ dfb_agp->base = mmap( NULL, shared->info.aper_size << 20,
+ PROT_READ | PROT_WRITE, MAP_SHARED,
+ dfb_agp->fd, 0 );
+ if (dfb_agp->base == MAP_FAILED) {
+ D_PERROR( "DirectFB/FBDev/agp: Could not mmap the AGP aperture!\n" );
+ ret = DFB_INIT;
+ goto error5;
+ }
+
+ dfb_agp_release();
+
+ dfb_fbdev->agp = dfb_agp;
+ dfb_fbdev->shared->agp = shared;
+
+ return DFB_OK;
+
+error5:
+ dfb_agp_unbind( shared->agp_key );
+error4:
+ dfb_agp_deallocate( shared->agp_key );
+error3:
+ dfb_agp_release();
+error2:
+ close( dfb_agp->fd );
+error1:
+ SHFREE( dfb_fbdev->shared->shmpool, shared );
+error0:
+ D_FREE( dfb_agp );
+ dfb_agp = NULL;
+
+ return ret;
+}
+
+DFBResult
+dfb_agp_join( void )
+{
+ AGPShared *shared;
+ DFBResult ret = DFB_FAILURE;
+
+ if (dfb_agp) {
+ D_BUG( "dfb_agp_join() already called!" );
+ return DFB_BUG;
+ }
+
+ shared = dfb_fbdev->shared->agp;
+ if (!shared)
+ return DFB_OK;
+
+ dfb_agp = D_CALLOC( 1, sizeof(AGPDevice) );
+ if (!dfb_agp)
+ return D_OOM();
+
+ dfb_agp->fd = direct_try_open( "/dev/agpgart",
+ "/dev/misc/agpgart", O_RDWR, true );
+ if (dfb_agp->fd < 0) {
+ ret = errno2result( errno );
+ D_ERROR( "DirectFB/FBDev/agp: Error opening AGP device!\n" );
+ goto error0;
+ }
+
+ ret = dfb_agp_acquire();
+ if (ret)
+ goto error1;
+
+ dfb_agp->base = mmap( NULL, shared->info.aper_size << 20,
+ PROT_READ | PROT_WRITE, MAP_SHARED,
+ dfb_agp->fd, 0 );
+ if (dfb_agp->base == MAP_FAILED) {
+ D_PERROR( "DirectFB/FBDev/agp: Could not mmap the AGP aperture!\n" );
+ ret = DFB_INIT;
+ goto error2;
+ }
+
+ D_DEBUG( "DirectFB/FBDev/agp: AGP aperture mapped at %p\n", dfb_agp->base );
+
+ dfb_agp_release();
+
+ dfb_fbdev->agp = dfb_agp;
+
+ return DFB_OK;
+
+error2:
+ dfb_agp_release();
+error1:
+ close( dfb_agp->fd );
+error0:
+ D_FREE( dfb_agp );
+ dfb_agp = NULL;
+
+ return ret;
+}
+
+DFBResult
+dfb_agp_shutdown( void )
+{
+ AGPShared *shared;
+
+ if (!dfb_agp)
+ return DFB_INVARG;
+
+ shared = dfb_fbdev->shared->agp;
+
+ dfb_agp_acquire();
+
+ munmap( dfb_agp->base, shared->info.aper_size << 20 );
+
+ dfb_agp_unbind( shared->agp_key );
+ dfb_agp_deallocate( shared->agp_key );
+
+ dfb_agp_release();
+ close( dfb_agp->fd );
+
+ SHFREE( dfb_fbdev->shared->shmpool, shared );
+ D_FREE( dfb_agp );
+
+ dfb_fbdev->shared->agp = NULL;
+ dfb_fbdev->agp = dfb_agp = NULL;
+
+ return DFB_OK;
+}
+
+DFBResult
+dfb_agp_leave( void )
+{
+ AGPShared *shared;
+
+ if (!dfb_agp)
+ return DFB_INVARG;
+
+ shared = dfb_fbdev->shared->agp;
+
+ dfb_agp_acquire();
+
+ munmap( dfb_agp->base, shared->info.aper_size << 20 );
+
+ dfb_agp_release();
+
+ close( dfb_agp->fd );
+ D_FREE( dfb_agp );
+
+ dfb_fbdev->agp = dfb_agp = NULL;
+
+ return DFB_OK;
+}
+
diff --git a/Source/DirectFB/systems/fbdev/agp.h b/Source/DirectFB/systems/fbdev/agp.h
new file mode 100755
index 0000000..44313a3
--- /dev/null
+++ b/Source/DirectFB/systems/fbdev/agp.h
@@ -0,0 +1,53 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __AGP_H__
+#define __AGP_H__
+
+#include <linux/agpgart.h>
+
+typedef struct {
+ unsigned int agp_mem;
+ int agp_key;
+ agp_info info;
+} AGPShared;
+
+typedef struct {
+ int fd;
+ void *base;
+} AGPDevice;
+
+
+DFBResult dfb_agp_initialize( void );
+DFBResult dfb_agp_shutdown( void );
+
+DFBResult dfb_agp_join( void );
+DFBResult dfb_agp_leave( void );
+
+#endif /* __AGP_H__ */
+
diff --git a/Source/DirectFB/systems/fbdev/fb.h b/Source/DirectFB/systems/fbdev/fb.h
new file mode 100755
index 0000000..6cc1399
--- /dev/null
+++ b/Source/DirectFB/systems/fbdev/fb.h
@@ -0,0 +1,366 @@
+#ifndef _LINUX_FB_H
+#define _LINUX_FB_H
+
+#include <dfb_types.h>
+
+/* Definitions of frame buffers */
+
+#define FB_MAJOR 29
+#define FB_MAX 32 /* sufficient for now */
+
+/* ioctls
+ 0x46 is 'F' */
+#define FBIOGET_VSCREENINFO 0x4600
+#define FBIOPUT_VSCREENINFO 0x4601
+#define FBIOGET_FSCREENINFO 0x4602
+#define FBIOGETCMAP 0x4604
+#define FBIOPUTCMAP 0x4605
+#define FBIOPAN_DISPLAY 0x4606
+#define FBIO_CURSOR _IOWR('F', 0x08, struct fb_cursor)
+/* 0x4607-0x460B are defined below */
+/* #define FBIOGET_MONITORSPEC 0x460C */
+/* #define FBIOPUT_MONITORSPEC 0x460D */
+/* #define FBIOSWITCH_MONIBIT 0x460E */
+#define FBIOGET_CON2FBMAP 0x460F
+#define FBIOPUT_CON2FBMAP 0x4610
+#define FBIOBLANK 0x4611 /* arg: 0 or vesa level + 1 */
+#define FBIOGET_VBLANK _IOR('F', 0x12, struct fb_vblank)
+#define FBIO_ALLOC 0x4613
+#define FBIO_FREE 0x4614
+#define FBIOGET_GLYPH 0x4615
+#define FBIOGET_HWCINFO 0x4616
+#define FBIOPUT_MODEINFO 0x4617
+#define FBIOGET_DISPINFO 0x4618
+
+
+#define FB_TYPE_PACKED_PIXELS 0 /* Packed Pixels */
+#define FB_TYPE_PLANES 1 /* Non interleaved planes */
+#define FB_TYPE_INTERLEAVED_PLANES 2 /* Interleaved planes */
+#define FB_TYPE_TEXT 3 /* Text/attributes */
+#define FB_TYPE_VGA_PLANES 4 /* EGA/VGA planes */
+
+#define FB_AUX_TEXT_MDA 0 /* Monochrome text */
+#define FB_AUX_TEXT_CGA 1 /* CGA/EGA/VGA Color text */
+#define FB_AUX_TEXT_S3_MMIO 2 /* S3 MMIO fasttext */
+#define FB_AUX_TEXT_MGA_STEP16 3 /* MGA Millenium I: text, attr, 14 reserved bytes */
+#define FB_AUX_TEXT_MGA_STEP8 4 /* other MGAs: text, attr, 6 reserved bytes */
+
+#define FB_AUX_VGA_PLANES_VGA4 0 /* 16 color planes (EGA/VGA) */
+#define FB_AUX_VGA_PLANES_CFB4 1 /* CFB4 in planes (VGA) */
+#define FB_AUX_VGA_PLANES_CFB8 2 /* CFB8 in planes (VGA) */
+
+#define FB_VISUAL_MONO01 0 /* Monochr. 1=Black 0=White */
+#define FB_VISUAL_MONO10 1 /* Monochr. 1=White 0=Black */
+#define FB_VISUAL_TRUECOLOR 2 /* True color */
+#define FB_VISUAL_PSEUDOCOLOR 3 /* Pseudo color (like atari) */
+#define FB_VISUAL_DIRECTCOLOR 4 /* Direct color */
+#define FB_VISUAL_STATIC_PSEUDOCOLOR 5 /* Pseudo color readonly */
+
+#define FB_ACCEL_NONE 0 /* no hardware accelerator */
+#define FB_ACCEL_ATARIBLITT 1 /* Atari Blitter */
+#define FB_ACCEL_AMIGABLITT 2 /* Amiga Blitter */
+#define FB_ACCEL_S3_TRIO64 3 /* Cybervision64 (S3 Trio64) */
+#define FB_ACCEL_NCR_77C32BLT 4 /* RetinaZ3 (NCR 77C32BLT) */
+#define FB_ACCEL_S3_VIRGE 5 /* Cybervision64/3D (S3 ViRGE) */
+#define FB_ACCEL_ATI_MACH64GX 6 /* ATI Mach 64GX family */
+#define FB_ACCEL_DEC_TGA 7 /* DEC 21030 TGA */
+#define FB_ACCEL_ATI_MACH64CT 8 /* ATI Mach 64CT family */
+#define FB_ACCEL_ATI_MACH64VT 9 /* ATI Mach 64CT family VT class */
+#define FB_ACCEL_ATI_MACH64GT 10 /* ATI Mach 64CT family GT class */
+#define FB_ACCEL_SUN_CREATOR 11 /* Sun Creator/Creator3D */
+#define FB_ACCEL_SUN_CGSIX 12 /* Sun cg6 */
+#define FB_ACCEL_SUN_LEO 13 /* Sun leo/zx */
+#define FB_ACCEL_IMS_TWINTURBO 14 /* IMS Twin Turbo */
+#define FB_ACCEL_3DLABS_PERMEDIA2 15 /* 3Dlabs Permedia 2 */
+#define FB_ACCEL_MATROX_MGA2064W 16 /* Matrox MGA2064W (Millenium) */
+#define FB_ACCEL_MATROX_MGA1064SG 17 /* Matrox MGA1064SG (Mystique) */
+#define FB_ACCEL_MATROX_MGA2164W 18 /* Matrox MGA2164W (Millenium II) */
+#define FB_ACCEL_MATROX_MGA2164W_AGP 19 /* Matrox MGA2164W (Millenium II) */
+#define FB_ACCEL_MATROX_MGAG100 20 /* Matrox G100 (Productiva G100) */
+#define FB_ACCEL_MATROX_MGAG200 21 /* Matrox G200 (Myst, Mill, ...) */
+#define FB_ACCEL_SUN_CG14 22 /* Sun cgfourteen */
+#define FB_ACCEL_SUN_BWTWO 23 /* Sun bwtwo */
+#define FB_ACCEL_SUN_CGTHREE 24 /* Sun cgthree */
+#define FB_ACCEL_SUN_TCX 25 /* Sun tcx */
+#define FB_ACCEL_MATROX_MGAG400 26 /* Matrox G400 */
+#define FB_ACCEL_NV3 27 /* nVidia RIVA 128 */
+#define FB_ACCEL_NV4 28 /* nVidia RIVA TNT */
+#define FB_ACCEL_NV5 29 /* nVidia RIVA TNT2 */
+#define FB_ACCEL_CT_6555x 30 /* C&T 6555x */
+#define FB_ACCEL_3DFX_BANSHEE 31 /* 3Dfx Banshee */
+#define FB_ACCEL_ATI_RAGE128 32 /* ATI Rage128 family */
+#define FB_ACCEL_IGS_CYBER2000 33 /* CyberPro 2000 */
+#define FB_ACCEL_IGS_CYBER2010 34 /* CyberPro 2010 */
+#define FB_ACCEL_IGS_CYBER5000 35 /* CyberPro 5000 */
+#define FB_ACCEL_SIS_GLAMOUR 36 /* SiS 300/630/540 */
+#define FB_ACCEL_3DLABS_PERMEDIA3 37 /* 3Dlabs Permedia 3 */
+#define FB_ACCEL_ATI_RADEON 38 /* ATI Radeon family */
+#define FB_ACCEL_I810 39 /* Intel 810/815 */
+#define FB_ACCEL_SIS_GLAMOUR_2 40 /* SiS 315, 650, 740 */
+#define FB_ACCEL_SIS_XABRE 41 /* SiS 330 ("Xabre") */
+#define FB_ACCEL_I830 42 /* Intel 830M/845G/85x/865G */
+#define FB_ACCEL_NV_10 43 /* nVidia Arch 10 */
+#define FB_ACCEL_NV_20 44 /* nVidia Arch 20 */
+#define FB_ACCEL_NV_30 45 /* nVidia Arch 30 */
+#define FB_ACCEL_NV_40 46 /* nVidia Arch 40 */
+#define FB_ACCEL_XGI_VOLARI_V 47 /* XGI Volari V3XT, V5, V8 */
+#define FB_ACCEL_XGI_VOLARI_Z 48 /* XGI Volari Z7 */
+#define FB_ACCEL_NEOMAGIC_NM2070 90 /* NeoMagic NM2070 */
+#define FB_ACCEL_NEOMAGIC_NM2090 91 /* NeoMagic NM2090 */
+#define FB_ACCEL_NEOMAGIC_NM2093 92 /* NeoMagic NM2093 */
+#define FB_ACCEL_NEOMAGIC_NM2097 93 /* NeoMagic NM2097 */
+#define FB_ACCEL_NEOMAGIC_NM2160 94 /* NeoMagic NM2160 */
+#define FB_ACCEL_NEOMAGIC_NM2200 95 /* NeoMagic NM2200 */
+#define FB_ACCEL_NEOMAGIC_NM2230 96 /* NeoMagic NM2230 */
+#define FB_ACCEL_NEOMAGIC_NM2360 97 /* NeoMagic NM2360 */
+#define FB_ACCEL_NEOMAGIC_NM2380 98 /* NeoMagic NM2380 */
+#define FB_ACCEL_EP9X 99 /* CirrusLogic EP9X family */
+
+#define FB_ACCEL_SAVAGE4 0x80 /* S3 Savage4 */
+#define FB_ACCEL_SAVAGE3D 0x81 /* S3 Savage3D */
+#define FB_ACCEL_SAVAGE3D_MV 0x82 /* S3 Savage3D-MV */
+#define FB_ACCEL_SAVAGE2000 0x83 /* S3 Savage2000 */
+#define FB_ACCEL_SAVAGE_MX_MV 0x84 /* S3 Savage/MX-MV */
+#define FB_ACCEL_SAVAGE_MX 0x85 /* S3 Savage/MX */
+#define FB_ACCEL_SAVAGE_IX_MV 0x86 /* S3 Savage/IX-MV */
+#define FB_ACCEL_SAVAGE_IX 0x87 /* S3 Savage/IX */
+#define FB_ACCEL_PROSAVAGE_PM 0x88 /* S3 ProSavage PM133 */
+#define FB_ACCEL_PROSAVAGE_KM 0x89 /* S3 ProSavage KM133 */
+#define FB_ACCEL_S3TWISTER_P 0x8a /* S3 Twister */
+#define FB_ACCEL_S3TWISTER_K 0x8b /* S3 TwisterK */
+#define FB_ACCEL_SUPERSAVAGE 0x8c /* S3 Supersavage */
+#define FB_ACCEL_PROSAVAGE_DDR 0x8d /* S3 ProSavage DDR */
+#define FB_ACCEL_PROSAVAGE_DDRK 0x8e /* S3 ProSavage DDR-K */
+
+struct fb_fix_screeninfo {
+ char id[16]; /* identification string eg "TT Builtin" */
+ unsigned long smem_start; /* Start of frame buffer mem */
+ /* (physical address) */
+ u32 smem_len; /* Length of frame buffer mem */
+ u32 type; /* see FB_TYPE_* */
+ u32 type_aux; /* Interleave for interleaved Planes */
+ u32 visual; /* see FB_VISUAL_* */
+ u16 xpanstep; /* zero if no hardware panning */
+ u16 ypanstep; /* zero if no hardware panning */
+ u16 ywrapstep; /* zero if no hardware ywrap */
+ u32 line_length; /* length of a line in bytes */
+ unsigned long mmio_start; /* Start of Memory Mapped I/O */
+ /* (physical address) */
+ u32 mmio_len; /* Length of Memory Mapped I/O */
+ u32 accel; /* Indicate to driver which */
+ /* specific chip/card we have */
+ u16 reserved[3]; /* Reserved for future compatibility */
+};
+
+/* Interpretation of offset for color fields: All offsets are from the right,
+ * inside a "pixel" value, which is exactly 'bits_per_pixel' wide (means: you
+ * can use the offset as right argument to <<). A pixel afterwards is a bit
+ * stream and is written to video memory as that unmodified. This implies
+ * big-endian byte order if bits_per_pixel is greater than 8.
+ */
+struct fb_bitfield {
+ u32 offset; /* beginning of bitfield */
+ u32 length; /* length of bitfield */
+ u32 msb_right; /* != 0 : Most significant bit is */
+ /* right */
+};
+
+#define FB_NONSTD_HAM 1 /* Hold-And-Modify (HAM) */
+
+#define FB_ACTIVATE_NOW 0 /* set values immediately (or vbl)*/
+#define FB_ACTIVATE_NXTOPEN 1 /* activate on next open */
+#define FB_ACTIVATE_TEST 2 /* don't set, round up impossible */
+#define FB_ACTIVATE_MASK 15
+ /* values */
+#define FB_ACTIVATE_VBL 16 /* activate values on next vbl */
+#define FB_CHANGE_CMAP_VBL 32 /* change colormap on vbl */
+#define FB_ACTIVATE_ALL 64 /* change all VCs on this fb */
+#define FB_ACTIVATE_FORCE 128 /* force apply even when no change*/
+#define FB_ACTIVATE_INV_MODE 256 /* invalidate videomode */
+
+#define FB_ACCELF_TEXT 1 /* (OBSOLETE) see fb_info.flags and vc_mode */
+
+#define FB_SYNC_HOR_HIGH_ACT 1 /* horizontal sync high active */
+#define FB_SYNC_VERT_HIGH_ACT 2 /* vertical sync high active */
+#define FB_SYNC_EXT 4 /* external sync */
+#define FB_SYNC_COMP_HIGH_ACT 8 /* composite sync high active */
+#define FB_SYNC_BROADCAST 16 /* broadcast video timings */
+ /* vtotal = 144d/288n/576i => PAL */
+ /* vtotal = 121d/242n/484i => NTSC */
+#define FB_SYNC_ON_GREEN 32 /* sync on green */
+
+#define FB_VMODE_NONINTERLACED 0 /* non interlaced */
+#define FB_VMODE_INTERLACED 1 /* interlaced */
+#define FB_VMODE_DOUBLE 2 /* double scan */
+#define FB_VMODE_MASK 255
+
+#define FB_VMODE_YWRAP 256 /* ywrap instead of panning */
+#define FB_VMODE_SMOOTH_XPAN 512 /* smooth xpan possible (internally used) */
+#define FB_VMODE_CONUPDATE 512 /* don't update x/yoffset */
+
+/*
+ * Display rotation support
+ */
+#define FB_ROTATE_UR 0
+#define FB_ROTATE_CW 1
+#define FB_ROTATE_UD 2
+#define FB_ROTATE_CCW 3
+
+#define PICOS2KHZ(a) (1000000000UL/(a))
+#define KHZ2PICOS(a) (1000000000UL/(a))
+
+struct fb_var_screeninfo {
+ u32 xres; /* visible resolution */
+ u32 yres;
+ u32 xres_virtual; /* virtual resolution */
+ u32 yres_virtual;
+ u32 xoffset; /* offset from virtual to visible */
+ u32 yoffset; /* resolution */
+
+ u32 bits_per_pixel; /* guess what */
+ u32 grayscale; /* != 0 Graylevels instead of colors */
+
+ struct fb_bitfield red; /* bitfield in fb mem if true color, */
+ struct fb_bitfield green; /* else only length is significant */
+ struct fb_bitfield blue;
+ struct fb_bitfield transp; /* transparency */
+
+ u32 nonstd; /* != 0 Non standard pixel format */
+
+ u32 activate; /* see FB_ACTIVATE_* */
+
+ u32 height; /* height of picture in mm */
+ u32 width; /* width of picture in mm */
+
+ u32 accel_flags; /* (OBSOLETE) see fb_info.flags */
+
+ /* Timing: All values in pixclocks, except pixclock (of course) */
+ u32 pixclock; /* pixel clock in ps (pico seconds) */
+ u32 left_margin; /* time from sync to picture */
+ u32 right_margin; /* time from picture to sync */
+ u32 upper_margin; /* time from sync to picture */
+ u32 lower_margin;
+ u32 hsync_len; /* length of horizontal sync */
+ u32 vsync_len; /* length of vertical sync */
+ u32 sync; /* see FB_SYNC_* */
+ u32 vmode; /* see FB_VMODE_* */
+ u32 rotate; /* angle we rotate counter clockwise */
+ u32 reserved[5]; /* Reserved for future compatibility */
+};
+
+struct fb_cmap {
+ u32 start; /* First entry */
+ u32 len; /* Number of entries */
+ u16 *red; /* Red values */
+ u16 *green;
+ u16 *blue;
+ u16 *transp; /* transparency, can be NULL */
+};
+
+struct fb_con2fbmap {
+ u32 console;
+ u32 framebuffer;
+};
+
+/* VESA Blanking Levels */
+#define VESA_NO_BLANKING 0
+#define VESA_VSYNC_SUSPEND 1
+#define VESA_HSYNC_SUSPEND 2
+#define VESA_POWERDOWN 3
+
+
+enum {
+ /* screen: unblanked, hsync: on, vsync: on */
+ FB_BLANK_UNBLANK = VESA_NO_BLANKING,
+
+ /* screen: blanked, hsync: on, vsync: on */
+ FB_BLANK_NORMAL = VESA_NO_BLANKING + 1,
+
+ /* screen: blanked, hsync: on, vsync: off */
+ FB_BLANK_VSYNC_SUSPEND = VESA_VSYNC_SUSPEND + 1,
+
+ /* screen: blanked, hsync: off, vsync: on */
+ FB_BLANK_HSYNC_SUSPEND = VESA_HSYNC_SUSPEND + 1,
+
+ /* screen: blanked, hsync: off, vsync: off */
+ FB_BLANK_POWERDOWN = VESA_POWERDOWN + 1
+};
+
+#define FB_VBLANK_VBLANKING 0x001 /* currently in a vertical blank */
+#define FB_VBLANK_HBLANKING 0x002 /* currently in a horizontal blank */
+#define FB_VBLANK_HAVE_VBLANK 0x004 /* vertical blanks can be detected */
+#define FB_VBLANK_HAVE_HBLANK 0x008 /* horizontal blanks can be detected */
+#define FB_VBLANK_HAVE_COUNT 0x010 /* global retrace counter is available */
+#define FB_VBLANK_HAVE_VCOUNT 0x020 /* the vcount field is valid */
+#define FB_VBLANK_HAVE_HCOUNT 0x040 /* the hcount field is valid */
+#define FB_VBLANK_VSYNCING 0x080 /* currently in a vsync */
+#define FB_VBLANK_HAVE_VSYNC 0x100 /* verical syncs can be detected */
+
+struct fb_vblank {
+ u32 flags; /* FB_VBLANK flags */
+ u32 count; /* counter of retraces since boot */
+ u32 vcount; /* current scanline position */
+ u32 hcount; /* current scandot position */
+ u32 reserved[4]; /* reserved for future compatibility */
+};
+
+/* Internal HW accel */
+#define ROP_COPY 0
+#define ROP_XOR 1
+
+struct fb_copyarea {
+ u32 dx;
+ u32 dy;
+ u32 width;
+ u32 height;
+ u32 sx;
+ u32 sy;
+};
+
+struct fb_fillrect {
+ u32 dx; /* screen-relative */
+ u32 dy;
+ u32 width;
+ u32 height;
+ u32 color;
+ u32 rop;
+};
+
+struct fb_image {
+ u32 dx; /* Where to place image */
+ u32 dy;
+ u32 width; /* Size of image */
+ u32 height;
+ u32 fg_color; /* Only used when a mono bitmap */
+ u32 bg_color;
+ u8 depth; /* Depth of the image */
+ const char *data; /* Pointer to image data */
+ struct fb_cmap cmap; /* color map info */
+};
+
+/*
+ * hardware cursor control
+ */
+
+#define FB_CUR_SETIMAGE 0x01
+#define FB_CUR_SETPOS 0x02
+#define FB_CUR_SETHOT 0x04
+#define FB_CUR_SETCMAP 0x08
+#define FB_CUR_SETSHAPE 0x10
+#define FB_CUR_SETSIZE 0x20
+#define FB_CUR_SETALL 0xFF
+
+struct fbcurpos {
+ u16 x, y;
+};
+
+struct fb_cursor {
+ u16 set; /* what to set */
+ u16 enable; /* cursor on/off */
+ u16 rop; /* bitop operation */
+ const char *mask; /* cursor mask bits */
+ struct fbcurpos hot; /* cursor hot spot */
+ struct fb_image image; /* Cursor image */
+};
+
+#endif /* _LINUX_FB_H */
diff --git a/Source/DirectFB/systems/fbdev/fbdev.c b/Source/DirectFB/systems/fbdev/fbdev.c
new file mode 100755
index 0000000..3691cff
--- /dev/null
+++ b/Source/DirectFB/systems/fbdev/fbdev.c
@@ -0,0 +1,2782 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+
+#include <asm/types.h> /* Needs to be included before dfb_types.h */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <strings.h>
+#if defined(HAVE_SYSIO)
+# include <sys/io.h>
+#endif
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/kd.h>
+
+#include <pthread.h>
+
+#ifdef USE_SYSFS
+# include <sysfs/libsysfs.h>
+#endif
+
+#include <fusion/arena.h>
+#include <fusion/fusion.h>
+#include <fusion/reactor.h>
+#include <fusion/shmalloc.h>
+
+#include <directfb.h>
+
+#include <core/core.h>
+#include <core/coredefs.h>
+#include <core/coretypes.h>
+
+#include <core/layer_control.h>
+#include <core/layers.h>
+#include <core/gfxcard.h>
+#include <core/palette.h>
+#include <core/screen.h>
+#include <core/screens.h>
+#include <core/surface.h>
+#include <core/surface_buffer.h>
+#include <core/surface_pool.h>
+#include <core/state.h>
+#include <core/windows.h>
+
+#include <gfx/convert.h>
+
+#include <direct/mem.h>
+#include <direct/memcpy.h>
+#include <direct/messages.h>
+#include <direct/signals.h>
+#include <direct/system.h>
+#include <direct/util.h>
+
+#include <misc/conf.h>
+#include <misc/util.h>
+
+#include "fbdev.h"
+#include "fb.h"
+#include "vt.h"
+#include "agp.h"
+
+#include <core/core_system.h>
+
+DFB_CORE_SYSTEM( fbdev )
+
+
+D_DEBUG_DOMAIN( FBDev_Mode, "FBDev/Mode", "FBDev System Module Mode Switching" );
+
+/******************************************************************************/
+
+extern const SurfacePoolFuncs fbdevSurfacePoolFuncs;
+
+static FusionCallHandlerResult
+fbdev_ioctl_call_handler( int caller,
+ int call_arg,
+ void *call_ptr,
+ void *ctx,
+ unsigned int serial,
+ int *ret_val );
+
+static int fbdev_ioctl( int request, void *arg, int arg_size );
+
+#define FBDEV_IOCTL(request,arg) fbdev_ioctl( request, arg, sizeof(*(arg)) )
+
+FBDev *dfb_fbdev = NULL;
+
+/******************************************************************************/
+
+static int primaryLayerDataSize ( void );
+
+static int primaryRegionDataSize( void );
+
+static DFBResult primaryInitLayer ( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ DFBDisplayLayerDescription *description,
+ DFBDisplayLayerConfig *config,
+ DFBColorAdjustment *adjustment );
+
+static DFBResult primarySetColorAdjustment( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ DFBColorAdjustment *adjustment );
+
+static DFBResult primaryTestRegion ( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ CoreLayerRegionConfig *config,
+ CoreLayerRegionConfigFlags *failed );
+
+static DFBResult primaryAddRegion ( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ void *region_data,
+ CoreLayerRegionConfig *config );
+
+static DFBResult primarySetRegion ( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ void *region_data,
+ CoreLayerRegionConfig *config,
+ CoreLayerRegionConfigFlags updated,
+ CoreSurface *surface,
+ CorePalette *palette,
+ CoreSurfaceBufferLock *lock );
+
+static DFBResult primaryRemoveRegion ( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ void *region_data );
+
+static DFBResult primaryFlipRegion ( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ void *region_data,
+ CoreSurface *surface,
+ DFBSurfaceFlipFlags flags,
+ CoreSurfaceBufferLock *lock );
+
+
+static DisplayLayerFuncs primaryLayerFuncs = {
+ .LayerDataSize = primaryLayerDataSize,
+ .RegionDataSize = primaryRegionDataSize,
+ .InitLayer = primaryInitLayer,
+
+ .SetColorAdjustment = primarySetColorAdjustment,
+
+ .TestRegion = primaryTestRegion,
+ .AddRegion = primaryAddRegion,
+ .SetRegion = primarySetRegion,
+ .RemoveRegion = primaryRemoveRegion,
+ .FlipRegion = primaryFlipRegion,
+};
+
+/******************************************************************************/
+
+static DFBResult primaryInitScreen ( CoreScreen *screen,
+ CoreGraphicsDevice *device,
+ void *driver_data,
+ void *screen_data,
+ DFBScreenDescription *description );
+
+static DFBResult primarySetPowerMode( CoreScreen *screen,
+ void *driver_data,
+ void *screen_data,
+ DFBScreenPowerMode mode );
+
+static DFBResult primaryWaitVSync ( CoreScreen *screen,
+ void *driver_data,
+ void *layer_data );
+
+static DFBResult primaryGetScreenSize( CoreScreen *screen,
+ void *driver_data,
+ void *screen_data,
+ int *ret_width,
+ int *ret_height );
+
+static ScreenFuncs primaryScreenFuncs = {
+ .InitScreen = primaryInitScreen,
+ .SetPowerMode = primarySetPowerMode,
+ .WaitVSync = primaryWaitVSync,
+ .GetScreenSize = primaryGetScreenSize,
+};
+
+/******************************************************************************/
+
+static DFBResult dfb_fbdev_read_modes( void );
+static DFBResult dfb_fbdev_set_gamma_ramp( DFBSurfacePixelFormat format );
+static DFBResult dfb_fbdev_set_palette( CorePalette *palette );
+static DFBResult dfb_fbdev_set_rgb332_palette( void );
+static DFBResult dfb_fbdev_pan( int xoffset, int yoffset, bool onsync );
+static DFBResult dfb_fbdev_blank( int level );
+static void dfb_fbdev_var_to_mode( const struct fb_var_screeninfo *var,
+ VideoMode *mode );
+
+/******************************************************************************/
+
+static inline
+void waitretrace (void)
+{
+#if defined(HAVE_INB_OUTB_IOPL)
+ if (iopl(3))
+ return;
+
+ if (!(inb (0x3cc) & 1)) {
+ while ((inb (0x3ba) & 0x8))
+ ;
+
+ while (!(inb (0x3ba) & 0x8))
+ ;
+ }
+ else {
+ while ((inb (0x3da) & 0x8))
+ ;
+
+ while (!(inb (0x3da) & 0x8))
+ ;
+ }
+#endif
+}
+
+/******************************************************************************/
+
+static DFBResult dfb_fbdev_open( void )
+{
+ DFBResult error_result = DFB_FAILURE;
+
+ if (dfb_config->fb_device) {
+ dfb_fbdev->fd = open( dfb_config->fb_device, O_RDWR );
+ if (dfb_fbdev->fd < 0) {
+ D_PERROR( "DirectFB/FBDev: Error opening '%s'!\n",
+ dfb_config->fb_device);
+
+ error_result = errno2result( errno );
+ goto error;
+ }
+ }
+ else if (getenv( "FRAMEBUFFER" ) && *getenv( "FRAMEBUFFER" ) != '\0') {
+ dfb_fbdev->fd = open( getenv ("FRAMEBUFFER"), O_RDWR );
+ if (dfb_fbdev->fd < 0) {
+ D_PERROR( "DirectFB/FBDev: Error opening '%s'!\n",
+ getenv ("FRAMEBUFFER"));
+
+ error_result = errno2result( errno );
+ goto error;
+ }
+ }
+ else {
+ dfb_fbdev->fd = direct_try_open( "/dev/fb0", "/dev/fb/0", O_RDWR, true );
+ if (dfb_fbdev->fd < 0) {
+ D_ERROR( "DirectFB/FBDev: Error opening framebuffer device!\n" );
+ D_ERROR( "DirectFB/FBDev: Use 'fbdev' option or set FRAMEBUFFER environment variable.\n" );
+ error_result = DFB_INIT;
+ goto error;
+ }
+ }
+
+ /* should be closed automatically in children upon exec(...) */
+ if (fcntl( dfb_fbdev->fd, F_SETFD, FD_CLOEXEC ) < 0)
+ {
+ D_PERROR( "Fusion/Init: Setting FD_CLOEXEC flag failed!\n" );
+ goto error;
+ }
+
+ return DFB_OK;
+error:
+ return error_result;
+}
+
+/******************************************************************************/
+
+static void
+dfb_fbdev_get_pci_info( FBDevShared *shared )
+{
+ char buf[512];
+ int vendor = -1;
+ int model = -1;
+
+#ifdef USE_SYSFS
+ if (!sysfs_get_mnt_path( buf, 512 )) {
+ struct sysfs_class_device *classdev;
+ struct sysfs_device *device;
+ struct sysfs_attribute *attr;
+ char *fbdev;
+ char dev[5] = { 'f', 'b', '0', 0, 0 };
+
+ fbdev = dfb_config->fb_device;
+ if (!fbdev)
+ fbdev = getenv( "FRAMEBUFFER" );
+
+ if (fbdev) {
+ if (!strncmp( fbdev, "/dev/fb/", 8 ))
+ snprintf( dev, 5, "fb%s", fbdev+8 );
+ else if (!strncmp( fbdev, "/dev/fb", 7 ))
+ snprintf( dev, 5, "fb%s", fbdev+7 );
+ }
+
+ classdev = sysfs_open_class_device( "graphics", dev );
+ if (classdev) {
+ device = sysfs_get_classdev_device( classdev );
+
+ if (device) {
+ attr = sysfs_get_device_attr( device, "vendor" );
+ if (attr)
+ sscanf( attr->value, "0x%04x", &vendor );
+
+ attr = sysfs_get_device_attr( device, "device" );
+ if (attr)
+ sscanf( attr->value, "0x%04x", &model );
+
+ if (vendor != -1 && model != -1) {
+ sscanf( device->name, "0000:%02x:%02x.%1x",
+ &shared->pci.bus,
+ &shared->pci.dev,
+ &shared->pci.func );
+
+ shared->device.vendor = vendor;
+ shared->device.model = model;
+ }
+ }
+
+ sysfs_close_class_device( classdev );
+ }
+ }
+#endif /* USE_SYSFS */
+
+ /* try /proc interface */
+ if (vendor == -1 || model == -1) {
+ FILE *fp;
+ int id;
+ int bus;
+ int dev;
+ int func;
+
+ fp = fopen( "/proc/bus/pci/devices", "r" );
+ if (!fp) {
+ D_DEBUG( "DirectFB/FBDev: "
+ "couldn't access /proc/bus/pci/devices!\n" );
+ return;
+ }
+
+ while (fgets( buf, 512, fp )) {
+ if (sscanf( buf, "%04x\t%04x%04x", &id, &vendor, &model ) == 3) {
+ bus = (id & 0xff00) >> 8;
+ dev = (id & 0x00ff) >> 3;
+ func = (id & 0x0007);
+
+ if (bus == dfb_config->pci.bus &&
+ dev == dfb_config->pci.dev &&
+ func == dfb_config->pci.func)
+ {
+ shared->pci.bus = bus;
+ shared->pci.dev = dev;
+ shared->pci.func = func;
+
+ shared->device.vendor = vendor;
+ shared->device.model = model;
+
+ break;
+ }
+ }
+ }
+
+ fclose( fp );
+ }
+}
+
+
+/** public **/
+
+static void
+system_get_info( CoreSystemInfo *info )
+{
+ info->type = CORE_FBDEV;
+ info->caps = CSCAPS_ACCELERATION;
+
+ snprintf( info->name, DFB_CORE_SYSTEM_INFO_NAME_LENGTH, "FBDev" );
+}
+
+static DFBResult
+system_initialize( CoreDFB *core, void **data )
+{
+ DFBResult ret;
+ CoreScreen *screen;
+ long page_size;
+ FBDevShared *shared = NULL;
+ FusionSHMPoolShared *pool;
+ FusionSHMPoolShared *pool_data;
+
+ D_ASSERT( dfb_fbdev == NULL );
+
+ pool = dfb_core_shmpool( core );
+ pool_data = dfb_core_shmpool_data( core );
+
+ dfb_fbdev = D_CALLOC( 1, sizeof(FBDev) );
+ if (!dfb_fbdev)
+ return D_OOM();
+
+ dfb_fbdev->fd = -1;
+
+ shared = (FBDevShared*) SHCALLOC( pool, 1, sizeof(FBDevShared) );
+ if (!shared) {
+ ret = D_OOSHM();
+ goto error;
+ }
+
+ shared->shmpool = pool;
+ shared->shmpool_data = pool_data;
+
+ fusion_arena_add_shared_field( dfb_core_arena( core ), "fbdev", shared );
+
+ dfb_fbdev->core = core;
+ dfb_fbdev->shared = shared;
+
+ page_size = direct_pagesize();
+
+ shared->page_mask = page_size < 0 ? 0 : (page_size - 1);
+
+ ret = dfb_fbdev_open();
+ if (ret)
+ goto error;
+
+ if (dfb_config->vt) {
+ ret = dfb_vt_initialize();
+ if (ret)
+ goto error;
+ }
+
+ ret = DFB_INIT;
+
+ /* Retrieve fixed informations like video ram size */
+ if (ioctl( dfb_fbdev->fd, FBIOGET_FSCREENINFO, &shared->fix ) < 0) {
+ D_PERROR( "DirectFB/FBDev: "
+ "Could not get fixed screen information!\n" );
+ goto error;
+ }
+
+ D_INFO( "DirectFB/FBDev: 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 */
+ dfb_fbdev->framebuffer_base = mmap( NULL, shared->fix.smem_len,
+ PROT_READ | PROT_WRITE, MAP_SHARED,
+ dfb_fbdev->fd, 0 );
+ if (dfb_fbdev->framebuffer_base == MAP_FAILED) {
+ D_PERROR( "DirectFB/FBDev: "
+ "Could not mmap the framebuffer!\n");
+ dfb_fbdev->framebuffer_base = NULL;
+ goto error;
+ }
+
+ if (ioctl( dfb_fbdev->fd, FBIOGET_VSCREENINFO, &shared->orig_var ) < 0) {
+ D_PERROR( "DirectFB/FBDev: "
+ "Could not get variable screen information!\n" );
+ goto error;
+ }
+
+ shared->current_var = shared->orig_var;
+ shared->current_var.accel_flags = 0;
+
+ if (ioctl( dfb_fbdev->fd, FBIOPUT_VSCREENINFO, &shared->current_var ) < 0) {
+ D_PERROR( "DirectFB/FBDev: "
+ "Could not disable console acceleration!\n" );
+ goto error;
+ }
+
+ dfb_fbdev_var_to_mode( &shared->current_var,
+ &shared->current_mode );
+
+ shared->orig_cmap_memory = SHMALLOC( pool_data, 256 * 2 * 4 );
+ if (!shared->orig_cmap_memory) {
+ ret = D_OOSHM();
+ goto error;
+ }
+
+ shared->orig_cmap.start = 0;
+ shared->orig_cmap.len = 256;
+ shared->orig_cmap.red = shared->orig_cmap_memory + 256 * 2 * 0;
+ shared->orig_cmap.green = shared->orig_cmap_memory + 256 * 2 * 1;
+ shared->orig_cmap.blue = shared->orig_cmap_memory + 256 * 2 * 2;
+ shared->orig_cmap.transp = shared->orig_cmap_memory + 256 * 2 * 3;
+
+ if (ioctl( dfb_fbdev->fd, FBIOGETCMAP, &shared->orig_cmap ) < 0) {
+ D_DEBUG( "DirectFB/FBDev: "
+ "Could not retrieve palette for backup!\n" );
+
+ memset( &shared->orig_cmap, 0, sizeof(shared->orig_cmap) );
+
+ SHFREE( pool_data, shared->orig_cmap_memory );
+ shared->orig_cmap_memory = NULL;
+ }
+
+ shared->temp_cmap_memory = SHMALLOC( pool_data, 256 * 2 * 4 );
+ if (!shared->temp_cmap_memory) {
+ ret = D_OOSHM();
+ goto error;
+ }
+
+ shared->temp_cmap.start = 0;
+ shared->temp_cmap.len = 256;
+ shared->temp_cmap.red = shared->temp_cmap_memory + 256 * 2 * 0;
+ shared->temp_cmap.green = shared->temp_cmap_memory + 256 * 2 * 1;
+ shared->temp_cmap.blue = shared->temp_cmap_memory + 256 * 2 * 2;
+ shared->temp_cmap.transp = shared->temp_cmap_memory + 256 * 2 * 3;
+
+ shared->current_cmap_memory = SHMALLOC( pool_data, 256 * 2 * 4 );
+ if (!shared->current_cmap_memory) {
+ ret = D_OOSHM();
+ goto error;
+ }
+
+ shared->current_cmap.start = 0;
+ shared->current_cmap.len = 256;
+ shared->current_cmap.red = shared->current_cmap_memory + 256 * 2 * 0;
+ shared->current_cmap.green = shared->current_cmap_memory + 256 * 2 * 1;
+ shared->current_cmap.blue = shared->current_cmap_memory + 256 * 2 * 2;
+ shared->current_cmap.transp = shared->current_cmap_memory + 256 * 2 * 3;
+
+ dfb_fbdev_get_pci_info( shared );
+
+ if (dfb_config->agp) {
+ /* Do not fail here, AGP slot could be unavailable */
+ ret = dfb_agp_initialize();
+ if (ret) {
+ D_DEBUG( "DirectFB/FBDev: dfb_agp_initialize()\n\t->%s\n",
+ DirectFBErrorString( ret ) );
+ ret = DFB_OK;
+ }
+ }
+
+ fusion_call_init( &shared->fbdev_ioctl,
+ fbdev_ioctl_call_handler, NULL, dfb_core_world(core) );
+
+ dfb_surface_pool_initialize( core, &fbdevSurfacePoolFuncs, &dfb_fbdev->shared->pool );
+
+ /* Register primary screen functions */
+ screen = dfb_screens_register( NULL, NULL, &primaryScreenFuncs );
+
+ /* Register primary layer functions */
+ dfb_layers_register( screen, NULL, &primaryLayerFuncs );
+
+ *data = dfb_fbdev;
+
+ return DFB_OK;
+
+
+error:
+ if (shared) {
+ if (shared->orig_cmap_memory)
+ SHFREE( pool_data, shared->orig_cmap_memory );
+
+ if (shared->temp_cmap_memory)
+ SHFREE( pool_data, shared->temp_cmap_memory );
+
+ if (shared->current_cmap_memory)
+ SHFREE( pool_data, shared->current_cmap_memory );
+
+ SHFREE( pool, shared );
+ }
+
+ if (dfb_fbdev->framebuffer_base)
+ munmap( dfb_fbdev->framebuffer_base, shared->fix.smem_len );
+
+ if (dfb_fbdev->fd != -1)
+ close( dfb_fbdev->fd );
+
+ D_FREE( dfb_fbdev );
+ dfb_fbdev = NULL;
+
+ return ret;
+}
+
+static DFBResult
+system_join( CoreDFB *core, void **data )
+{
+ DFBResult ret;
+ CoreScreen *screen;
+ void *shared;
+
+ D_ASSERT( dfb_fbdev == NULL );
+
+ if (dfb_config->vt) {
+ ret = dfb_vt_join();
+ if (ret)
+ return ret;
+ }
+
+ dfb_fbdev = D_CALLOC( 1, sizeof(FBDev) );
+ if (!dfb_fbdev)
+ return D_OOM();
+
+ fusion_arena_get_shared_field( dfb_core_arena( core ),
+ "fbdev", &shared );
+
+ dfb_fbdev->core = core;
+ dfb_fbdev->shared = shared;
+
+ /* Open framebuffer device */
+ ret = dfb_fbdev_open();
+ if (ret) {
+ D_FREE( dfb_fbdev );
+ dfb_fbdev = NULL;
+ return ret;
+ }
+
+ /* Map the framebuffer */
+ dfb_fbdev->framebuffer_base = mmap( NULL, dfb_fbdev->shared->fix.smem_len,
+ PROT_READ | PROT_WRITE, MAP_SHARED,
+ dfb_fbdev->fd, 0 );
+ if (dfb_fbdev->framebuffer_base == MAP_FAILED) {
+ D_PERROR( "DirectFB/FBDev: "
+ "Could not mmap the framebuffer!\n");
+ close( dfb_fbdev->fd );
+ D_FREE( dfb_fbdev );
+ dfb_fbdev = NULL;
+
+ return DFB_INIT;
+ }
+
+ /* Open AGP device */
+ ret = dfb_agp_join();
+ if (ret) {
+ D_ERROR( "DirectFB/FBDev: Could not join AGP!\n" );
+ munmap( dfb_fbdev->framebuffer_base,
+ dfb_fbdev->shared->fix.smem_len );
+ close( dfb_fbdev->fd );
+ D_FREE( dfb_fbdev );
+ dfb_fbdev = NULL;
+
+ return ret;
+ }
+
+ dfb_surface_pool_join( core, dfb_fbdev->shared->pool, &fbdevSurfacePoolFuncs );
+
+ /* Register primary screen functions */
+ screen = dfb_screens_register( NULL, NULL, &primaryScreenFuncs );
+
+ /* Register primary layer functions */
+ dfb_layers_register( screen, NULL, &primaryLayerFuncs );
+
+ *data = dfb_fbdev;
+
+ return DFB_OK;
+}
+
+static DFBResult
+system_shutdown( bool emergency )
+{
+ DFBResult ret;
+ VideoMode *m;
+ FBDevShared *shared;
+ FusionSHMPoolShared *pool;
+
+ D_ASSERT( dfb_fbdev != NULL );
+
+ shared = dfb_fbdev->shared;
+
+ D_ASSERT( shared != NULL );
+
+ pool = shared->shmpool;
+
+ D_ASSERT( pool != NULL );
+
+ m = shared->modes;
+ while (m) {
+ VideoMode *next = m->next;
+ SHFREE( pool, m );
+ m = next;
+ }
+
+ if (ioctl( dfb_fbdev->fd, FBIOPUT_VSCREENINFO, &shared->orig_var ) < 0) {
+ D_PERROR( "DirectFB/FBDev: "
+ "Could not restore variable screen information!\n" );
+ }
+
+ if (shared->orig_cmap.len) {
+ if (ioctl( dfb_fbdev->fd, FBIOPUTCMAP, &shared->orig_cmap ) < 0)
+ D_DEBUG( "DirectFB/FBDev: "
+ "Could not restore palette!\n" );
+ }
+
+ if (shared->orig_cmap_memory)
+ SHFREE( shared->shmpool_data, shared->orig_cmap_memory );
+
+ if (shared->temp_cmap_memory)
+ SHFREE( shared->shmpool_data, shared->temp_cmap_memory );
+
+ if (shared->current_cmap_memory)
+ SHFREE( shared->shmpool_data, shared->current_cmap_memory );
+
+ fusion_call_destroy( &shared->fbdev_ioctl );
+
+ dfb_agp_shutdown();
+
+ dfb_surface_pool_destroy( dfb_fbdev->shared->pool );
+
+ munmap( dfb_fbdev->framebuffer_base, shared->fix.smem_len );
+
+ if (dfb_config->vt) {
+ ret = dfb_vt_shutdown( emergency );
+ if (ret)
+ return ret;
+ }
+
+ close( dfb_fbdev->fd );
+
+ SHFREE( pool, shared );
+ D_FREE( dfb_fbdev );
+ dfb_fbdev = NULL;
+
+ return DFB_OK;
+}
+
+static DFBResult
+system_leave( bool emergency )
+{
+ DFBResult ret;
+
+ D_ASSERT( dfb_fbdev != NULL );
+
+ dfb_agp_leave();
+
+ dfb_surface_pool_leave( dfb_fbdev->shared->pool );
+
+ munmap( dfb_fbdev->framebuffer_base,
+ dfb_fbdev->shared->fix.smem_len );
+
+ if (dfb_config->vt) {
+ ret = dfb_vt_leave( emergency );
+ if (ret)
+ return ret;
+ }
+
+ close( dfb_fbdev->fd );
+
+ D_FREE( dfb_fbdev );
+ dfb_fbdev = 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;
+
+ if (length <= 0)
+ length = dfb_fbdev->shared->fix.mmio_len;
+
+ addr = mmap( NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED,
+ dfb_fbdev->fd, dfb_fbdev->shared->fix.smem_len + offset );
+ if (addr == MAP_FAILED) {
+ D_PERROR( "DirectFB/FBDev: Could not mmap MMIO region "
+ "(offset %d, length %d)!\n", offset, length );
+ return NULL;
+ }
+
+ return(volatile void*) ((u8*) addr + (dfb_fbdev->shared->fix.mmio_start &
+ dfb_fbdev->shared->page_mask));
+}
+
+static void
+system_unmap_mmio( volatile void *addr,
+ int length )
+{
+ if (length <= 0)
+ length = dfb_fbdev->shared->fix.mmio_len;
+
+ if (munmap( (void*) ((u8*) addr - (dfb_fbdev->shared->fix.mmio_start &
+ dfb_fbdev->shared->page_mask)), length ) < 0)
+ D_PERROR( "DirectFB/FBDev: Could not unmap MMIO region "
+ "at %p (length %d)!\n", addr, length );
+}
+
+static int
+system_get_accelerator( void )
+{
+#ifdef FB_ACCEL_MATROX_MGAG400
+ if (!strcmp( dfb_fbdev->shared->fix.id, "MATROX DH" ))
+ return FB_ACCEL_MATROX_MGAG400;
+#endif
+#ifdef FB_ACCEL_EP9X
+ if (!strcmp( dfb_fbdev->shared->fix.id, "ep9xfb" ))
+ return FB_ACCEL_EP9X;
+#endif
+
+ if (dfb_config->accelerator)
+ return dfb_config->accelerator;
+
+ if (dfb_fbdev->shared->fix.mmio_len > 0)
+ return dfb_fbdev->shared->fix.accel;
+ return -1;
+}
+
+static VideoMode *
+system_get_modes( void )
+{
+ return dfb_fbdev->shared->modes;
+}
+
+static VideoMode *
+system_get_current_mode( void )
+{
+ return &dfb_fbdev->shared->current_mode;
+}
+
+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 )
+{
+ return dfb_fbdev->shared->fix.smem_start + offset;
+}
+
+static void *
+system_video_memory_virtual( unsigned int offset )
+{
+ return(void*)((u8*)(dfb_fbdev->framebuffer_base) + offset);
+}
+
+static unsigned int
+system_videoram_length( void )
+{
+ return dfb_fbdev->shared->fix.smem_len;
+}
+
+static unsigned long
+system_aux_memory_physical( unsigned int offset )
+{
+ if (dfb_fbdev->shared->agp)
+ return dfb_fbdev->shared->agp->info.aper_base + offset;
+ return 0;
+}
+
+static void *
+system_aux_memory_virtual( unsigned int offset )
+{
+ if (dfb_fbdev->agp)
+ return (void*)(u8*)dfb_fbdev->agp->base + offset;
+ return NULL;
+}
+
+static unsigned int
+system_auxram_length( void )
+{
+ if (dfb_fbdev->shared->agp)
+ return dfb_fbdev->shared->agp->agp_mem;
+ return 0;
+}
+
+static void
+system_get_busid( int *ret_bus, int *ret_dev, int *ret_func )
+{
+ *ret_bus = dfb_fbdev->shared->pci.bus;
+ *ret_dev = dfb_fbdev->shared->pci.dev;
+ *ret_func = dfb_fbdev->shared->pci.func;
+}
+
+static void
+system_get_deviceid( unsigned int *ret_vendor_id,
+ unsigned int *ret_device_id )
+{
+ *ret_vendor_id = dfb_fbdev->shared->device.vendor;
+ *ret_device_id = dfb_fbdev->shared->device.model;
+}
+
+/******************************************************************************/
+
+static DFBResult
+init_modes( void )
+{
+ dfb_fbdev_read_modes();
+
+ if (!dfb_fbdev->shared->modes) {
+ /* try to use current mode*/
+ dfb_fbdev->shared->modes = (VideoMode*) SHCALLOC( dfb_fbdev->shared->shmpool,
+ 1, sizeof(VideoMode) );
+ if (!dfb_fbdev->shared->modes)
+ return D_OOSHM();
+
+ *dfb_fbdev->shared->modes = dfb_fbdev->shared->current_mode;
+
+ if (dfb_fbdev_test_mode_simple(dfb_fbdev->shared->modes)) {
+ D_ERROR("DirectFB/FBDev: "
+ "No supported modes found in /etc/fb.modes and "
+ "current mode not supported!\n");
+
+ D_ERROR( "DirectFB/FBDev: Current mode's pixelformat: "
+ "rgba %d/%d, %d/%d, %d/%d, %d/%d (%dbit)\n",
+ dfb_fbdev->shared->orig_var.red.length,
+ dfb_fbdev->shared->orig_var.red.offset,
+ dfb_fbdev->shared->orig_var.green.length,
+ dfb_fbdev->shared->orig_var.green.offset,
+ dfb_fbdev->shared->orig_var.blue.length,
+ dfb_fbdev->shared->orig_var.blue.offset,
+ dfb_fbdev->shared->orig_var.transp.length,
+ dfb_fbdev->shared->orig_var.transp.offset,
+ dfb_fbdev->shared->orig_var.bits_per_pixel );
+
+ return DFB_INIT;
+ }
+ }
+
+ return DFB_OK;
+}
+
+/******************************************************************************/
+
+static DFBResult
+primaryInitScreen( CoreScreen *screen,
+ CoreGraphicsDevice *device,
+ void *driver_data,
+ void *screen_data,
+ DFBScreenDescription *description )
+{
+ /* Set the screen capabilities. */
+ description->caps = DSCCAPS_VSYNC | DSCCAPS_POWER_MANAGEMENT;
+
+ /* Set the screen name. */
+ snprintf( description->name,
+ DFB_SCREEN_DESC_NAME_LENGTH, "FBDev Primary Screen" );
+
+ return DFB_OK;
+}
+
+static DFBResult
+primarySetPowerMode( CoreScreen *screen,
+ void *driver_data,
+ void *screen_data,
+ DFBScreenPowerMode mode )
+{
+ int level;
+
+ switch (mode) {
+ case DSPM_OFF:
+ level = 4;
+ break;
+ case DSPM_SUSPEND:
+ level = 3;
+ break;
+ case DSPM_STANDBY:
+ level = 2;
+ break;
+ case DSPM_ON:
+ level = 0;
+ break;
+ default:
+ return DFB_INVARG;
+ }
+
+ return dfb_fbdev_blank( level );
+}
+
+static DFBResult
+primaryWaitVSync( CoreScreen *screen,
+ void *driver_data,
+ void *screen_data )
+{
+ static const int zero = 0;
+
+ if (dfb_config->pollvsync_none)
+ return DFB_OK;
+
+ if (ioctl( dfb_fbdev->fd, FBIO_WAITFORVSYNC, &zero ))
+ waitretrace();
+
+ return DFB_OK;
+}
+
+static DFBResult
+primaryGetScreenSize( CoreScreen *screen,
+ void *driver_data,
+ void *screen_data,
+ int *ret_width,
+ int *ret_height )
+{
+ D_ASSERT( dfb_fbdev != NULL );
+ D_ASSERT( dfb_fbdev->shared != NULL );
+
+ *ret_width = dfb_fbdev->shared->current_mode.xres;
+ *ret_height = dfb_fbdev->shared->current_mode.yres;
+
+ return DFB_OK;
+}
+
+/******************************************************************************/
+
+static int
+primaryLayerDataSize( void )
+{
+ return 0;
+}
+
+static int
+primaryRegionDataSize( void )
+{
+ return 0;
+}
+
+static DFBResult
+primaryInitLayer( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ DFBDisplayLayerDescription *description,
+ DFBDisplayLayerConfig *config,
+ DFBColorAdjustment *adjustment )
+{
+ DFBResult ret;
+ VideoMode *default_mode;
+
+ /* initialize mode table */
+ ret = init_modes();
+ if (ret)
+ return ret;
+
+ default_mode = dfb_fbdev->shared->modes;
+
+ /* set capabilities and type */
+ description->caps = DLCAPS_SURFACE | DLCAPS_CONTRAST |
+ DLCAPS_SATURATION | DLCAPS_BRIGHTNESS;
+ description->type = DLTF_GRAPHICS;
+
+ /* set name */
+ snprintf( description->name,
+ DFB_DISPLAY_LAYER_DESC_NAME_LENGTH, "FBDev Primary Layer" );
+
+ /* fill out default color adjustment */
+ adjustment->flags = DCAF_BRIGHTNESS | DCAF_CONTRAST | DCAF_SATURATION;
+ adjustment->brightness = 0x8000;
+ adjustment->contrast = 0x8000;
+ adjustment->saturation = 0x8000;
+
+ /* fill out the default configuration */
+ config->flags = DLCONF_WIDTH | DLCONF_HEIGHT |
+ DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE;
+ config->buffermode = DLBM_FRONTONLY;
+ config->width = dfb_config->mode.width ? dfb_config->mode.width : default_mode->xres;
+ config->height = dfb_config->mode.height ? dfb_config->mode.height : default_mode->yres;
+
+ if (dfb_config->mode.format)
+ config->pixelformat = dfb_config->mode.format;
+ else
+ config->pixelformat = dfb_pixelformat_for_depth( default_mode->bpp );
+
+ return DFB_OK;
+}
+
+static DFBResult
+primarySetColorAdjustment( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ DFBColorAdjustment *adjustment )
+{
+ struct fb_cmap *cmap = &dfb_fbdev->shared->current_cmap;
+ struct fb_cmap *temp = &dfb_fbdev->shared->temp_cmap;
+ int contrast = adjustment->contrast >> 8;
+ int brightness = (adjustment->brightness >> 8) - 128;
+ int saturation = adjustment->saturation >> 8;
+ int r, g, b, i;
+
+ if (dfb_fbdev->shared->fix.visual != FB_VISUAL_DIRECTCOLOR)
+ return DFB_UNIMPLEMENTED;
+
+ /* Use gamma ramp to set color attributes */
+ for (i = 0; i < (int)cmap->len; i++) {
+ r = cmap->red[i];
+ g = cmap->green[i];
+ b = cmap->blue[i];
+ r >>= 8;
+ g >>= 8;
+ b >>= 8;
+
+ /*
+ * Brightness Adjustment: Increase/Decrease each color channels
+ * by a constant amount as specified by value of brightness.
+ */
+ if (adjustment->flags & DCAF_BRIGHTNESS) {
+ r += brightness;
+ g += brightness;
+ b += brightness;
+
+ r = CLAMP( r, 0, 255 );
+ g = CLAMP( g, 0, 255 );
+ b = CLAMP( b, 0, 255 );
+ }
+
+ /*
+ * Contrast Adjustment: We increase/decrease the "separation"
+ * between colors in proportion to the value specified by the
+ * contrast control. Decreasing the contrast has a side effect
+ * of decreasing the brightness.
+ */
+
+ if (adjustment->flags & DCAF_CONTRAST) {
+ /* Increase contrast */
+ if (contrast > 128) {
+ int c = contrast - 128;
+
+ r = ((r + c/2)/c) * c;
+ g = ((g + c/2)/c) * c;
+ b = ((b + c/2)/c) * c;
+ }
+ /* Decrease contrast */
+ else if (contrast < 127) {
+ r = (r * contrast) >> 7;
+ g = (g * contrast) >> 7;
+ b = (b * contrast) >> 7;
+ }
+
+ r = CLAMP( r, 0, 255 );
+ g = CLAMP( g, 0, 255 );
+ b = CLAMP( b, 0, 255 );
+ }
+
+ /*
+ * Saturation Adjustment: This is is a better implementation.
+ * Saturation is implemented by "mixing" a proportion of medium
+ * gray to the color value. On the other side, "removing"
+ * a proportion of medium gray oversaturates the color.
+ */
+ if (adjustment->flags & DCAF_SATURATION) {
+ if (saturation > 128) {
+ int gray = saturation - 128;
+ int color = 128 - gray;
+
+ r = ((r - gray) << 7) / color;
+ g = ((g - gray) << 7) / color;
+ b = ((b - gray) << 7) / color;
+ }
+ else if (saturation < 128) {
+ int color = saturation;
+ int gray = 128 - color;
+
+ r = ((r * color) >> 7) + gray;
+ g = ((g * color) >> 7) + gray;
+ b = ((b * color) >> 7) + gray;
+ }
+
+ r = CLAMP( r, 0, 255 );
+ g = CLAMP( g, 0, 255 );
+ b = CLAMP( b, 0, 255 );
+ }
+ r |= r << 8;
+ g |= g << 8;
+ b |= b << 8;
+
+ temp->red[i] = (unsigned short)r;
+ temp->green[i] = (unsigned short)g;
+ temp->blue[i] = (unsigned short)b;
+ }
+
+ temp->len = cmap->len;
+ temp->start = cmap->start;
+ if (FBDEV_IOCTL( FBIOPUTCMAP, temp ) < 0) {
+ D_PERROR( "DirectFB/FBDev: Could not set the palette!\n" );
+
+ return errno2result(errno);
+ }
+
+ return DFB_OK;
+}
+
+const VideoMode *
+dfb_fbdev_find_mode( int width, int height )
+{
+ FBDevShared *shared = dfb_fbdev->shared;
+ const VideoMode *videomode = shared->modes;
+ const VideoMode *highest = NULL;
+
+ while (videomode) {
+ if (videomode->xres == width && videomode->yres == height) {
+ if (!highest || highest->priority < videomode->priority)
+ highest = videomode;
+ }
+
+ videomode = videomode->next;
+ }
+
+ if (!highest)
+ D_ERROR( "FBDev/Mode: No mode found for %dx%d!\n", width, height );
+
+ return highest;
+}
+
+static DFBResult
+primaryTestRegion( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ CoreLayerRegionConfig *config,
+ CoreLayerRegionConfigFlags *failed )
+{
+ FBDevShared *shared = dfb_fbdev->shared;
+ CoreLayerRegionConfigFlags fail = CLRCF_NONE;
+ const VideoMode *mode;
+
+ D_DEBUG_AT( FBDev_Mode, "%s( %dx%d, %s )\n", __FUNCTION__,
+ config->source.w, config->source.h, dfb_pixelformat_name(config->format) );
+
+ mode = dfb_fbdev_find_mode( config->source.w, config->source.h );
+
+ if (!mode || dfb_fbdev_test_mode( mode, config ))
+ fail |= CLRCF_WIDTH | CLRCF_HEIGHT | CLRCF_FORMAT | CLRCF_BUFFERMODE;
+
+ if (config->options)
+ fail |= CLRCF_OPTIONS;
+
+ if ((config->source.x && !shared->fix.xpanstep) ||
+ (config->source.y && !shared->fix.ypanstep && !shared->fix.ywrapstep))
+ fail |= CLRCF_SOURCE;
+
+ if (failed)
+ *failed = fail;
+
+ if (fail)
+ return DFB_UNSUPPORTED;
+
+ return DFB_OK;
+}
+
+static DFBResult
+primaryAddRegion( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ void *region_data,
+ CoreLayerRegionConfig *config )
+{
+ return DFB_OK;
+}
+
+static DFBResult
+primarySetRegion( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ void *region_data,
+ CoreLayerRegionConfig *config,
+ CoreLayerRegionConfigFlags updated,
+ CoreSurface *surface,
+ CorePalette *palette,
+ CoreSurfaceBufferLock *lock )
+{
+ DFBResult ret;
+ FBDevShared *shared = dfb_fbdev->shared;
+
+ if (updated & CLRCF_SOURCE) {
+ if (config->source.w == shared->current_var.xres && config->source.h == shared->current_var.yres) {
+ ret = dfb_fbdev_pan( config->source.x, lock->offset / lock->pitch + config->source.y, true );
+ if (ret)
+ return ret;
+ }
+ else {
+ const VideoMode *mode;
+
+ D_INFO( "FBDev/Mode: Setting %dx%d %s\n", config->source.w, config->source.h,
+ dfb_pixelformat_name( surface->config.format ) );
+
+ mode = dfb_fbdev_find_mode( config->source.w, config->source.h );
+ if (!mode)
+ return DFB_UNSUPPORTED;
+
+ ret = dfb_fbdev_set_mode( mode, surface, config->source.x,
+ lock->offset / lock->pitch + config->source.y );
+ if (ret)
+ return ret;
+ }
+ }
+
+ if ((updated & CLRCF_PALETTE) && palette)
+ dfb_fbdev_set_palette( palette );
+
+ /* remember configuration */
+ shared->config = *config;
+
+ return DFB_OK;
+}
+
+static DFBResult
+primaryRemoveRegion( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ void *region_data )
+{
+ return DFB_OK;
+}
+
+static DFBResult
+primaryFlipRegion( CoreLayer *layer,
+ void *driver_data,
+ void *layer_data,
+ void *region_data,
+ CoreSurface *surface,
+ DFBSurfaceFlipFlags flags,
+ CoreSurfaceBufferLock *lock )
+{
+ DFBResult ret;
+ CoreLayerRegionConfig *config = &dfb_fbdev->shared->config;
+
+ if (((flags & DSFLIP_WAITFORSYNC) == DSFLIP_WAITFORSYNC) &&
+ !dfb_config->pollvsync_after)
+ dfb_screen_wait_vsync( dfb_screens_at(DSCID_PRIMARY) );
+
+ ret = dfb_fbdev_pan( config->source.x,
+ lock->offset / lock->pitch + config->source.y,
+ (flags & DSFLIP_WAITFORSYNC) == DSFLIP_ONSYNC );
+ if (ret)
+ return ret;
+
+ 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 );
+
+ return DFB_OK;
+}
+
+/** fbdev internal **/
+
+static void
+dfb_fbdev_var_to_mode( const struct fb_var_screeninfo *var,
+ VideoMode *mode )
+{
+ mode->xres = var->xres;
+ mode->yres = var->yres;
+ mode->bpp = var->bits_per_pixel;
+ mode->hsync_len = var->hsync_len;
+ mode->vsync_len = var->vsync_len;
+ mode->left_margin = var->left_margin;
+ mode->right_margin = var->right_margin;
+ mode->upper_margin = var->upper_margin;
+ mode->lower_margin = var->lower_margin;
+ mode->pixclock = var->pixclock;
+ mode->hsync_high = (var->sync & FB_SYNC_HOR_HIGH_ACT) ? 1 : 0;
+ mode->vsync_high = (var->sync & FB_SYNC_VERT_HIGH_ACT) ? 1 : 0;
+ mode->csync_high = (var->sync & FB_SYNC_COMP_HIGH_ACT) ? 1 : 0;
+ mode->sync_on_green = (var->sync & FB_SYNC_ON_GREEN) ? 1 : 0;
+ mode->external_sync = (var->sync & FB_SYNC_EXT) ? 1 : 0;
+ mode->broadcast = (var->sync & FB_SYNC_BROADCAST) ? 1 : 0;
+ mode->laced = (var->vmode & FB_VMODE_INTERLACED) ? 1 : 0;
+ mode->doubled = (var->vmode & FB_VMODE_DOUBLE) ? 1 : 0;
+}
+
+#if 0
+static int dfb_fbdev_compatible_format( struct fb_var_screeninfo *var,
+ int al, int rl, int gl, int bl,
+ int ao, int ro, int go, int bo )
+{
+ int ah, rh, gh, bh;
+ int vah, vrh, vgh, vbh;
+
+ ah = al + ao - 1;
+ rh = rl + ro - 1;
+ gh = gl + go - 1;
+ bh = bl + bo - 1;
+
+ vah = var->transp.length + var->transp.offset - 1;
+ vrh = var->red.length + var->red.offset - 1;
+ vgh = var->green.length + var->green.offset - 1;
+ vbh = var->blue.length + var->blue.offset - 1;
+
+ if ((!al || (ah == vah && al >= (int)var->transp.length)) &&
+ (!rl || (rh == vrh && rl >= (int)var->red.length)) &&
+ (!gl || (gh == vgh && gl >= (int)var->green.length)) &&
+ (!bl || (bh == vbh && bl >= (int)var->blue.length)))
+ return 1;
+
+ return 0;
+}
+
+static DFBSurfacePixelFormat dfb_fbdev_get_pixelformat( struct fb_var_screeninfo *var )
+{
+ switch (var->bits_per_pixel) {
+
+ case 8:
+/*
+ This check is omitted, since we want to use RGB332 even if the
+ hardware uses a palette (in that case we initialize a calculated
+ one to have correct colors)
+
+ if (fbdev_compatible_format( var, 0, 3, 3, 2, 0, 5, 2, 0 ))*/
+
+ return DSPF_RGB332;
+
+ case 15:
+ if (dfb_fbdev_compatible_format( var, 0, 5, 5, 5, 0, 10, 5, 0 ))
+ return DSPF_RGB555;
+
+ if(dfb_fbdev_compatible_format( var, 1, 5, 5, 5, 15, 10, 5, 0 ))
+ return DSPF_ARGB1555;
+
+ if (dfb_fbdev_compatible_format( var, 0, 5, 5, 5, 0, 0, 5, 10 ))
+ return DSPF_BGR555;
+
+ break;
+
+ case 16:
+ if (dfb_fbdev_compatible_format( var, 0, 5, 5, 5, 0, 10, 5, 0 ))
+ return DSPF_RGB555;
+
+ if(dfb_fbdev_compatible_format( var, 1, 5, 5, 5, 15, 10, 5, 0 ))
+ return DSPF_ARGB1555;
+
+ if (dfb_fbdev_compatible_format( var, 4, 4, 4, 4, 12, 8, 4, 0 ))
+ return DSPF_ARGB4444;
+
+ if (dfb_fbdev_compatible_format( var, 4, 4, 4, 4, 0, 12, 8, 4 ))
+ return DSPF_RGBA4444;
+
+ if (dfb_fbdev_compatible_format( var, 0, 4, 4, 4, 0, 8, 4, 0 ))
+ return DSPF_RGB444;
+
+ if (dfb_fbdev_compatible_format( var, 0, 5, 6, 5, 0, 11, 5, 0 ))
+ return DSPF_RGB16;
+
+ if (dfb_fbdev_compatible_format( var, 0, 5, 5, 5, 0, 0, 5, 10 ))
+ return DSPF_BGR555;
+
+ break;
+
+ case 18:
+ if (dfb_fbdev_compatible_format( var, 1, 6, 6, 6, 18, 12, 6, 0 ))
+ return DSPF_ARGB1666;
+
+ if (dfb_fbdev_compatible_format( var, 6, 6, 6, 6, 18, 12, 6, 0 ))
+ return DSPF_ARGB6666;
+
+ if (dfb_fbdev_compatible_format( var, 0, 6, 6, 6, 0, 12, 6, 0 ))
+ return DSPF_RGB18;
+ break;
+
+ case 24:
+ if (dfb_fbdev_compatible_format( var, 0, 8, 8, 8, 0, 16, 8, 0 ))
+ return DSPF_RGB24;
+
+ if (dfb_fbdev_compatible_format( var, 6, 6, 6, 6, 18, 12, 6, 0 ))
+ return DSPF_ARGB6666;
+ break;
+
+ case 32:
+ if (dfb_fbdev_compatible_format( var, 0, 8, 8, 8, 0, 16, 8, 0 ))
+ return DSPF_RGB32;
+
+ if (dfb_fbdev_compatible_format( var, 8, 8, 8, 8, 24, 16, 8, 0 ))
+ return DSPF_ARGB;
+
+ break;
+ }
+
+ D_ERROR( "DirectFB/FBDev: Unsupported pixelformat: "
+ "rgba %d/%d, %d/%d, %d/%d, %d/%d (%dbit)\n",
+ var->red.length, var->red.offset,
+ var->green.length, var->green.offset,
+ var->blue.length, var->blue.offset,
+ var->transp.length, var->transp.offset,
+ var->bits_per_pixel );
+
+ return DSPF_UNKNOWN;
+}
+#endif
+
+/*
+ * pans display (flips buffer) using fbdev ioctl
+ */
+static DFBResult
+dfb_fbdev_pan( int xoffset, int yoffset, bool onsync )
+{
+// DFBResult ret;
+ int result;
+ struct fb_var_screeninfo *var;
+ FBDevShared *shared = dfb_fbdev->shared;
+
+ if (!shared->fix.xpanstep && !shared->fix.ypanstep && !shared->fix.ywrapstep)
+ return DFB_OK;
+
+ var = &shared->current_var;
+
+ if (var->xres_virtual < xoffset + var->xres) {
+ D_ERROR( "DirectFB/FBDev: xres %d, vxres %d, xoffset %d\n",
+ var->xres, var->xres_virtual, xoffset );
+ D_BUG( "panning buffer out of range" );
+ return DFB_BUG;
+ }
+
+ if (var->yres_virtual < yoffset + var->yres) {
+ D_ERROR( "DirectFB/FBDev: yres %d, vyres %d, offset %d\n",
+ var->yres, var->yres_virtual, yoffset );
+ D_BUG( "panning buffer out of range" );
+ return DFB_BUG;
+ }
+
+ if (shared->fix.xpanstep)
+ var->xoffset = xoffset - (xoffset % shared->fix.xpanstep);
+ else
+ var->xoffset = 0;
+
+ if (shared->fix.ywrapstep) {
+ var->yoffset = yoffset - (yoffset % shared->fix.ywrapstep);
+ var->vmode |= FB_VMODE_YWRAP;
+ }
+ else if (shared->fix.ypanstep) {
+ var->yoffset = yoffset - (yoffset % shared->fix.ypanstep);
+ var->vmode &= ~FB_VMODE_YWRAP;
+ }
+ else {
+ var->yoffset = 0;
+ }
+
+ var->activate = onsync ? FB_ACTIVATE_VBL : FB_ACTIVATE_NOW;
+
+#if 0
+ ret = fusion_call_execute( &shared->fbdev_ioctl, FCEF_NONE, FBIOPAN_DISPLAY, var, &result );
+ if (ret)
+ return DFB_FUSION;
+
+ if (result) {
+ errno = result;
+#else
+ if (ioctl( dfb_fbdev->fd, FBIOPAN_DISPLAY, var ) < 0) {
+ result = errno;
+#endif
+ D_PERROR( "DirectFB/FBDev: Panning display failed (x=%u y=%u ywrap=%d vbl=%d)!\n",
+ var->xoffset, var->yoffset,
+ (var->vmode & FB_VMODE_YWRAP) ? 1 : 0,
+ (var->activate & FB_ACTIVATE_VBL) ? 1 : 0);
+
+ return errno2result(result);
+ }
+
+ return DFB_OK;
+}
+
+/*
+ * blanks display using fbdev ioctl
+ */
+static DFBResult
+dfb_fbdev_blank( int level )
+{
+ if (ioctl( dfb_fbdev->fd, FBIOBLANK, level ) < 0) {
+ D_PERROR( "DirectFB/FBDev: Display blanking failed!\n" );
+
+ return errno2result( errno );
+ }
+
+ return DFB_OK;
+}
+
+static DFBResult
+dfb_fbdev_mode_to_var( const VideoMode *mode,
+ DFBSurfacePixelFormat pixelformat,
+ unsigned int vxres,
+ unsigned int vyres,
+ unsigned int xoffset,
+ unsigned int yoffset,
+ DFBDisplayLayerBufferMode buffermode,
+ struct fb_var_screeninfo *ret_var )
+{
+ struct fb_var_screeninfo var;
+ FBDevShared *shared = dfb_fbdev->shared;
+
+ D_DEBUG_AT( FBDev_Mode, "%s( mode: %p )\n", __FUNCTION__, mode );
+
+ D_ASSERT( mode != NULL );
+ D_ASSERT( ret_var != NULL );
+
+ D_DEBUG_AT( FBDev_Mode, " -> resolution %dx%d\n", mode->xres, mode->yres );
+ D_DEBUG_AT( FBDev_Mode, " -> virtual %dx%d\n", vxres, vyres );
+ D_DEBUG_AT( FBDev_Mode, " -> pixelformat %s\n", dfb_pixelformat_name(pixelformat) );
+ D_DEBUG_AT( FBDev_Mode, " -> buffermode %s\n",
+ buffermode == DLBM_FRONTONLY ? "FRONTONLY" :
+ buffermode == DLBM_BACKVIDEO ? "BACKVIDEO" :
+ buffermode == DLBM_BACKSYSTEM ? "BACKSYSTEM" :
+ buffermode == DLBM_TRIPLE ? "TRIPLE" : "invalid!" );
+
+ /* Start from current information */
+ var = shared->current_var;
+ var.activate = FB_ACTIVATE_NOW;
+
+ /* Set timings */
+ var.pixclock = mode->pixclock;
+ var.left_margin = mode->left_margin;
+ var.right_margin = mode->right_margin;
+ var.upper_margin = mode->upper_margin;
+ var.lower_margin = mode->lower_margin;
+ var.hsync_len = mode->hsync_len;
+ var.vsync_len = mode->vsync_len;
+
+ /* Set resolution */
+ var.xres = mode->xres;
+ var.yres = mode->yres;
+ var.xres_virtual = vxres;
+ var.yres_virtual = vyres;
+
+ if (shared->fix.xpanstep)
+ var.xoffset = xoffset - (xoffset % shared->fix.xpanstep);
+ else
+ var.xoffset = 0;
+
+ if (shared->fix.ywrapstep)
+ var.yoffset = yoffset - (yoffset % shared->fix.ywrapstep);
+ else if (shared->fix.ypanstep)
+ var.yoffset = yoffset - (yoffset % shared->fix.ypanstep);
+ else
+ var.yoffset = 0;
+
+ /* Set buffer mode */
+ switch (buffermode) {
+ case DLBM_TRIPLE:
+ if (shared->fix.ypanstep == 0 && shared->fix.ywrapstep == 0)
+ return DFB_UNSUPPORTED;
+
+ var.yres_virtual *= 3;
+ break;
+
+ case DLBM_BACKVIDEO:
+ if (shared->fix.ypanstep == 0 && shared->fix.ywrapstep == 0)
+ return DFB_UNSUPPORTED;
+
+ var.yres_virtual *= 2;
+ break;
+
+ case DLBM_BACKSYSTEM:
+ case DLBM_FRONTONLY:
+ break;
+
+ default:
+ return DFB_UNSUPPORTED;
+ }
+
+ /* Set pixel format */
+ var.bits_per_pixel = DFB_BITS_PER_PIXEL(pixelformat);
+ var.transp.length = var.transp.offset = 0;
+
+ switch (pixelformat) {
+ case DSPF_ARGB1555:
+ var.transp.length = 1;
+ var.red.length = 5;
+ var.green.length = 5;
+ var.blue.length = 5;
+ var.transp.offset = 15;
+ var.red.offset = 10;
+ var.green.offset = 5;
+ var.blue.offset = 0;
+ break;
+
+ case DSPF_RGB555:
+ var.red.length = 5;
+ var.green.length = 5;
+ var.blue.length = 5;
+ var.red.offset = 10;
+ var.green.offset = 5;
+ var.blue.offset = 0;
+ break;
+
+ case DSPF_ARGB4444:
+ var.transp.length = 4;
+ var.red.length = 4;
+ var.green.length = 4;
+ var.blue.length = 4;
+ var.transp.offset = 12;
+ var.red.offset = 8;
+ var.green.offset = 4;
+ var.blue.offset = 0;
+ break;
+
+ case DSPF_RGBA4444:
+ var.transp.length = 4;
+ var.red.length = 4;
+ var.green.length = 4;
+ var.blue.length = 4;
+ var.transp.offset = 0;
+ var.red.offset = 12;
+ var.green.offset = 8;
+ var.blue.offset = 4;
+ break;
+
+ case DSPF_RGB444:
+ var.red.length = 4;
+ var.green.length = 4;
+ var.blue.length = 4;
+ var.red.offset = 8;
+ var.green.offset = 4;
+ var.blue.offset = 0;
+ break;
+
+ case DSPF_RGB32:
+ var.red.length = 8;
+ var.green.length = 8;
+ var.blue.length = 8;
+ var.red.offset = 16;
+ var.green.offset = 8;
+ var.blue.offset = 0;
+ break;
+
+ case DSPF_RGB16:
+ var.red.length = 5;
+ var.green.length = 6;
+ var.blue.length = 5;
+ var.red.offset = 11;
+ var.green.offset = 5;
+ var.blue.offset = 0;
+ break;
+
+ case DSPF_ARGB:
+ case DSPF_AiRGB:
+ var.transp.length = 8;
+ var.red.length = 8;
+ var.green.length = 8;
+ var.blue.length = 8;
+ var.transp.offset = 24;
+ var.red.offset = 16;
+ var.green.offset = 8;
+ var.blue.offset = 0;
+ break;
+
+ case DSPF_LUT8:
+ case DSPF_RGB24:
+ case DSPF_RGB332:
+ break;
+
+ case DSPF_ARGB1666:
+ var.transp.length = 1;
+ var.red.length = 6;
+ var.green.length = 6;
+ var.blue.length = 6;
+ var.transp.offset = 18;
+ var.red.offset = 12;
+ var.green.offset = 6;
+ var.blue.offset = 0;
+ break;
+
+ case DSPF_ARGB6666:
+ var.transp.length = 6;
+ var.red.length = 6;
+ var.green.length = 6;
+ var.blue.length = 6;
+ var.transp.offset = 18;
+ var.red.offset = 12;
+ var.green.offset = 6;
+ var.blue.offset = 0;
+ break;
+
+ case DSPF_RGB18:
+ var.red.length = 6;
+ var.green.length = 6;
+ var.blue.length = 6;
+ var.red.offset = 12;
+ var.green.offset = 6;
+ var.blue.offset = 0;
+ break;
+
+ default:
+ return DFB_UNSUPPORTED;
+ }
+
+ /* Set sync options */
+ var.sync = 0;
+ if (mode->hsync_high)
+ var.sync |= FB_SYNC_HOR_HIGH_ACT;
+ if (mode->vsync_high)
+ var.sync |= FB_SYNC_VERT_HIGH_ACT;
+ if (mode->csync_high)
+ var.sync |= FB_SYNC_COMP_HIGH_ACT;
+ if (mode->sync_on_green)
+ var.sync |= FB_SYNC_ON_GREEN;
+ if (mode->external_sync)
+ var.sync |= FB_SYNC_EXT;
+ if (mode->broadcast)
+ var.sync |= FB_SYNC_BROADCAST;
+
+ /* Set interlace/linedouble */
+ var.vmode = 0;
+ if (mode->laced)
+ var.vmode |= FB_VMODE_INTERLACED;
+ if (mode->doubled)
+ var.vmode |= FB_VMODE_DOUBLE;
+
+ *ret_var = var;
+
+ return DFB_OK;
+}
+
+DFBResult
+dfb_fbdev_test_mode( const VideoMode *mode,
+ const CoreLayerRegionConfig *config )
+{
+ DFBResult ret;
+ struct fb_var_screeninfo var;
+ FBDevShared *shared = dfb_fbdev->shared;
+ const DFBRectangle *source = &config->source;
+
+ D_DEBUG_AT( FBDev_Mode, "%s( mode: %p, config: %p )\n", __FUNCTION__, mode, config );
+
+ D_ASSERT( mode != NULL );
+ D_ASSERT( config != NULL );
+
+ /* Is panning supported? */
+ if (source->w != mode->xres && shared->fix.xpanstep == 0)
+ return DFB_UNSUPPORTED;
+ if (source->h != mode->yres && shared->fix.ypanstep == 0 && shared->fix.ywrapstep == 0)
+ return DFB_UNSUPPORTED;
+
+ ret = dfb_fbdev_mode_to_var( mode, config->format, config->width, config->height,
+ 0, 0, config->buffermode, &var );
+ if (ret)
+ return ret;
+
+ /* Enable test mode */
+ var.activate = FB_ACTIVATE_TEST;
+
+
+ dfb_gfxcard_lock( GDLF_WAIT | GDLF_SYNC | GDLF_RESET | GDLF_INVALIDATE );
+
+ if (FBDEV_IOCTL( FBIOPUT_VSCREENINFO, &var ) < 0) {
+ int erno = errno;
+ dfb_gfxcard_unlock();
+ D_DEBUG_AT( FBDev_Mode, " => FAILED!\n" );
+ return errno2result( erno );
+ }
+
+ dfb_gfxcard_unlock();
+
+ D_DEBUG_AT( FBDev_Mode, " => SUCCESS\n" );
+
+ return DFB_OK;
+}
+
+DFBResult
+dfb_fbdev_test_mode_simple( const VideoMode *mode )
+{
+ DFBResult ret;
+ struct fb_var_screeninfo var;
+
+ D_DEBUG_AT( FBDev_Mode, "%s( mode: %p )\n", __FUNCTION__, mode );
+
+ D_ASSERT( mode != NULL );
+
+ ret = dfb_fbdev_mode_to_var( mode, dfb_pixelformat_for_depth(mode->bpp), mode->xres, mode->yres,
+ 0, 0, DLBM_FRONTONLY, &var );
+ if (ret)
+ return ret;
+
+ /* Enable test mode */
+ var.activate = FB_ACTIVATE_TEST;
+
+ if (FBDEV_IOCTL( FBIOPUT_VSCREENINFO, &var ) < 0) {
+ D_DEBUG_AT( FBDev_Mode, " => FAILED!\n" );
+ return errno2result( errno );
+ }
+
+ D_DEBUG_AT( FBDev_Mode, " => SUCCESS\n" );
+
+ return DFB_OK;
+}
+
+static int num_video_buffers( CoreSurface *surface )
+{
+ int i;
+
+ for (i = 0; i < surface->num_buffers; i++) {
+ if (surface->buffers[i]->policy == CSP_SYSTEMONLY)
+ break;
+ }
+
+ return i;
+}
+
+DFBResult
+dfb_fbdev_set_mode( const VideoMode *mode,
+ CoreSurface *surface,
+ unsigned int xoffset,
+ unsigned int yoffset )
+{
+ DFBResult ret;
+ struct fb_var_screeninfo var;
+ FBDevShared *shared = dfb_fbdev->shared;
+ DFBDisplayLayerBufferMode buffermode = DLBM_FRONTONLY;
+ const CoreSurfaceConfig *config = &surface->config ;
+
+ D_DEBUG_AT( FBDev_Mode, "%s( mode: %p, config: %p )\n", __FUNCTION__, mode, config );
+
+ D_ASSERT( mode != NULL );
+ D_ASSERT( config != NULL );
+
+ switch (num_video_buffers( surface )) {
+ case 3:
+ buffermode = DLBM_TRIPLE;
+ break;
+ case 2:
+ buffermode = DLBM_BACKVIDEO;
+ break;
+ case 1:
+ buffermode = DLBM_FRONTONLY;
+ break;
+ default:
+ D_BUG( "dfb_fbdev_set_mode() called with %d video buffers!", num_video_buffers( surface ) );
+ return DFB_BUG;
+ }
+
+ ret = dfb_fbdev_mode_to_var( mode, config->format, config->size.w, config->size.h,
+ xoffset, yoffset, buffermode, &var );
+ if (ret) {
+ D_ERROR( "FBDev/Mode: Failed to switch to %dx%d %s (buffermode %d)\n",
+ config->size.w, config->size.h, dfb_pixelformat_name(config->format), buffermode );
+ return ret;
+ }
+
+
+ dfb_gfxcard_lock( GDLF_WAIT | GDLF_SYNC | GDLF_RESET | GDLF_INVALIDATE );
+
+ if (FBDEV_IOCTL( FBIOPUT_VSCREENINFO, &var ) < 0) {
+ int erno = errno;
+
+ dfb_gfxcard_unlock();
+
+ D_DEBUG_AT( FBDev_Mode, " => FAILED!\n" );
+
+ D_ERROR( "FBDev/Mode: Failed to switched to %dx%d (virtual %dx%d) at %d bit (%s)!\n",
+ var.xres, var.yres, var.xres_virtual, var.yres_virtual, var.bits_per_pixel,
+ dfb_pixelformat_name(config->format) );
+
+ return errno2result( erno );
+ }
+
+ D_DEBUG_AT( FBDev_Mode, " => SUCCESS\n" );
+
+ shared->current_var = var;
+ dfb_fbdev_var_to_mode( &var, &shared->current_mode );
+
+ /* To get the new pitch */
+ FBDEV_IOCTL( FBIOGET_FSCREENINFO, &shared->fix );
+
+ D_INFO( "FBDev/Mode: Switched to %dx%d (virtual %dx%d) at %d bit (%s), pitch %d\n",
+ var.xres, var.yres, var.xres_virtual, var.yres_virtual, var.bits_per_pixel,
+ dfb_pixelformat_name(config->format), shared->fix.line_length );
+
+ if (config->format == DSPF_RGB332)
+ dfb_fbdev_set_rgb332_palette();
+ else
+ dfb_fbdev_set_gamma_ramp( config->format );
+
+ /* invalidate original pan offset */
+ shared->orig_var.xoffset = 0;
+ shared->orig_var.yoffset = 0;
+
+ dfb_surfacemanager_adjust_heap_offset( dfb_fbdev->shared->manager,
+ var.yres_virtual * shared->fix.line_length );
+
+ dfb_gfxcard_after_set_var();
+
+ dfb_gfxcard_unlock();
+
+ return DFB_OK;
+}
+
+
+#if 0
+DFBResult
+dfb_fbdev_set_mode( CoreSurface *surface,
+ VideoMode *mode,
+ CoreLayerRegionConfig *config )
+{
+ unsigned int vxres, vyres;
+ struct fb_var_screeninfo var;
+ FBDevShared *shared = dfb_fbdev->shared;
+ DFBSurfacePixelFormat format;
+
+ D_DEBUG("DirectFB/FBDev: dfb_fbdev_set_mode (surface: %p, "
+ "mode: %p, buffermode: %d)\n", surface, mode,
+ config ? config->buffermode : DLBM_FRONTONLY);
+
+ if (!mode)
+ mode = &shared->current_mode;
+
+ var = shared->current_var;
+
+ if (config) {
+ DFBRectangle *source = &config->source;
+
+ /* Is panning supported? */
+ if (source->w != mode->xres && shared->fix.xpanstep == 0)
+ return DFB_UNSUPPORTED;
+ if (source->h != mode->yres && shared->fix.ypanstep == 0 && shared->fix.ywrapstep == 0)
+ return DFB_UNSUPPORTED;
+
+ vxres = config->width;
+ vyres = config->height;
+
+ var.xoffset = source->x;
+ var.yoffset = source->y;
+
+ switch (config->buffermode) {
+ case DLBM_TRIPLE:
+ if (shared->fix.ypanstep == 0 && shared->fix.ywrapstep == 0)
+ return DFB_UNSUPPORTED;
+ vyres *= 3;
+ break;
+
+ case DLBM_BACKVIDEO:
+ if (shared->fix.ypanstep == 0 && shared->fix.ywrapstep == 0)
+ return DFB_UNSUPPORTED;
+ vyres *= 2;
+ break;
+
+ case DLBM_BACKSYSTEM:
+ case DLBM_FRONTONLY:
+ break;
+
+ default:
+ return DFB_UNSUPPORTED;
+ }
+
+ var.bits_per_pixel = DFB_BYTES_PER_PIXEL(config->format) * 8;
+
+ var.transp.length = var.transp.offset = 0;
+
+ switch (config->format) {
+ case DSPF_ARGB1555:
+ var.transp.length = 1;
+ var.red.length = 5;
+ var.green.length = 5;
+ var.blue.length = 5;
+ var.transp.offset = 15;
+ var.red.offset = 10;
+ var.green.offset = 5;
+ var.blue.offset = 0;
+ break;
+
+ case DSPF_RGB555:
+ var.red.length = 5;
+ var.green.length = 5;
+ var.blue.length = 5;
+ var.red.offset = 10;
+ var.green.offset = 5;
+ var.blue.offset = 0;
+ break;
+
+ case DSPF_BGR555:
+ var.red.length = 5;
+ var.green.length = 5;
+ var.blue.length = 5;
+ var.red.offset = 0;
+ var.green.offset = 5;
+ var.blue.offset = 10;
+ break;
+
+ case DSPF_ARGB4444:
+ var.transp.length = 4;
+ var.red.length = 4;
+ var.green.length = 4;
+ var.blue.length = 4;
+ var.transp.offset = 12;
+ var.red.offset = 8;
+ var.green.offset = 4;
+ var.blue.offset = 0;
+ break;
+
+ case DSPF_RGBA4444:
+ var.transp.length = 4;
+ var.red.length = 4;
+ var.green.length = 4;
+ var.blue.length = 4;
+ var.transp.offset = 0;
+ var.red.offset = 12;
+ var.green.offset = 8;
+ var.blue.offset = 4;
+ break;
+
+ case DSPF_RGB444:
+ var.red.length = 4;
+ var.green.length = 4;
+ var.blue.length = 4;
+ var.red.offset = 8;
+ var.green.offset = 4;
+ var.blue.offset = 0;
+ break;
+
+ case DSPF_RGB32:
+ var.red.length = 8;
+ var.green.length = 8;
+ var.blue.length = 8;
+ var.red.offset = 16;
+ var.green.offset = 8;
+ var.blue.offset = 0;
+ break;
+
+ case DSPF_RGB16:
+ var.red.length = 5;
+ var.green.length = 6;
+ var.blue.length = 5;
+ var.red.offset = 11;
+ var.green.offset = 5;
+ var.blue.offset = 0;
+ break;
+
+ case DSPF_ARGB:
+ case DSPF_AiRGB:
+ var.transp.length = 8;
+ var.red.length = 8;
+ var.green.length = 8;
+ var.blue.length = 8;
+ var.transp.offset = 24;
+ var.red.offset = 16;
+ var.green.offset = 8;
+ var.blue.offset = 0;
+ break;
+
+ case DSPF_LUT8:
+ case DSPF_RGB24:
+ case DSPF_RGB332:
+ break;
+
+ case DSPF_ARGB1666:
+ var.transp.length = 1;
+ var.red.length = 6;
+ var.green.length = 6;
+ var.blue.length = 6;
+ var.transp.offset = 18;
+ var.red.offset = 12;
+ var.green.offset = 6;
+ var.blue.offset = 0;
+ break;
+
+ case DSPF_ARGB6666:
+ var.transp.length = 6;
+ var.red.length = 6;
+ var.green.length = 6;
+ var.blue.length = 6;
+ var.transp.offset = 18;
+ var.red.offset = 12;
+ var.green.offset = 6;
+ var.blue.offset = 0;
+ break;
+
+ case DSPF_RGB18:
+ var.red.length = 6;
+ var.green.length = 6;
+ var.blue.length = 6;
+ var.red.offset = 12;
+ var.green.offset = 6;
+ var.blue.offset = 0;
+ break;
+
+ default:
+ return DFB_UNSUPPORTED;
+ }
+ }
+ else {
+ vxres = mode->xres;
+ vyres = mode->yres;
+
+ var.xoffset = 0;
+ var.yoffset = 0;
+
+ var.bits_per_pixel = mode->bpp;
+ }
+
+ var.activate = surface ? FB_ACTIVATE_NOW : FB_ACTIVATE_TEST;
+
+ var.xres = mode->xres;
+ var.yres = mode->yres;
+ var.xres_virtual = vxres;
+ var.yres_virtual = vyres;
+
+ var.pixclock = mode->pixclock;
+ var.left_margin = mode->left_margin;
+ var.right_margin = mode->right_margin;
+ var.upper_margin = mode->upper_margin;
+ var.lower_margin = mode->lower_margin;
+ var.hsync_len = mode->hsync_len;
+ var.vsync_len = mode->vsync_len;
+
+ var.sync = 0;
+ if (mode->hsync_high)
+ var.sync |= FB_SYNC_HOR_HIGH_ACT;
+ if (mode->vsync_high)
+ var.sync |= FB_SYNC_VERT_HIGH_ACT;
+ if (mode->csync_high)
+ var.sync |= FB_SYNC_COMP_HIGH_ACT;
+ if (mode->sync_on_green)
+ var.sync |= FB_SYNC_ON_GREEN;
+ if (mode->external_sync)
+ var.sync |= FB_SYNC_EXT;
+ if (mode->broadcast)
+ var.sync |= FB_SYNC_BROADCAST;
+
+ var.vmode = 0;
+ if (mode->laced)
+ var.vmode |= FB_VMODE_INTERLACED;
+ if (mode->doubled)
+ var.vmode |= FB_VMODE_DOUBLE;
+
+ dfb_gfxcard_lock( GDLF_WAIT | GDLF_SYNC | GDLF_RESET | GDLF_INVALIDATE );
+
+ if (FBDEV_IOCTL( FBIOPUT_VSCREENINFO, &var ) < 0) {
+ int erno = errno;
+
+ if (surface)
+ D_PERROR( "DirectFB/FBDev: "
+ "Could not set video mode (FBIOPUT_VSCREENINFO)!\n" );
+
+ dfb_gfxcard_unlock();
+
+ return errno2result( erno );
+ }
+
+ /*
+ * the video mode was set successfully, check if there is enough
+ * video ram (for buggy framebuffer drivers)
+ */
+
+ if (shared->fix.smem_len < (var.yres_virtual *
+ var.xres_virtual *
+ var.bits_per_pixel >> 3)
+ || (var.xres_virtual < vxres)
+ || (var.yres_virtual < vyres))
+ {
+ if (surface) {
+ D_PERROR( "DirectFB/FBDev: "
+ "Could not set video mode (not enough video ram)!\n" );
+
+ /* restore mode */
+ FBDEV_IOCTL( FBIOPUT_VSCREENINFO, &shared->current_var );
+ }
+
+ dfb_gfxcard_unlock();
+
+ return DFB_INVARG;
+ }
+
+ /* If surface is NULL the mode was only tested, otherwise apply changes. */
+ if (surface) {
+ struct fb_fix_screeninfo fix;
+
+ FBDEV_IOCTL( FBIOGET_VSCREENINFO, &var );
+
+ vxres = var.xres_virtual;
+ switch (config->buffermode) {
+ case DLBM_TRIPLE:
+ vyres = var.yres_virtual / 3;
+ break;
+ case DLBM_BACKVIDEO:
+ vyres = var.yres_virtual / 2;
+ break;
+ default:
+ vyres = var.yres_virtual;
+ break;
+ }
+
+ format = dfb_fbdev_get_pixelformat( &var );
+ if (format == DSPF_UNKNOWN) {
+ D_WARN( "unknown format" );
+
+ /* restore mode */
+ FBDEV_IOCTL( FBIOPUT_VSCREENINFO, &shared->current_var );
+
+ dfb_gfxcard_unlock();
+
+ return DFB_UNSUPPORTED;
+ }
+
+ if (!config) {
+ dfb_gfxcard_unlock();
+
+ return DFB_OK;
+ }
+
+ if (format != config->format) {
+ if (DFB_BYTES_PER_PIXEL(format) == 1 ||
+ (format == DSPF_RGB32 && config->format == DSPF_ARGB) ||
+ (format == DSPF_RGB32 && config->format == DSPF_AiRGB) ||
+ (format == DSPF_ARGB && config->format == DSPF_AiRGB))
+ format = config->format;
+ }
+
+ if (config->format == DSPF_RGB332)
+ dfb_fbdev_set_rgb332_palette();
+ else
+ dfb_fbdev_set_gamma_ramp( config->format );
+
+ shared->current_var = var;
+ dfb_fbdev_var_to_mode( &var, &shared->current_mode );
+
+ /* invalidate original pan offset */
+ shared->orig_var.xoffset = 0;
+ shared->orig_var.yoffset = 0;
+
+ surface->config.size.w = vxres;
+ surface->config.size.h = vyres;
+ surface->config.format = format;
+
+ /* To get the new pitch */
+ FBDEV_IOCTL( FBIOGET_FSCREENINFO, &fix );
+
+ D_INFO( "FBDev/Mode: Switched to %dx%d (%dx%d) at %d bit %s (wanted %s).\n",
+ var.xres, var.yres, var.xres_virtual, var.yres_virtual, var.bits_per_pixel,
+ dfb_pixelformat_name(format), dfb_pixelformat_name(config->format) );
+
+ /* ++Tony: Other information (such as visual formats) will also change */
+ shared->fix = fix;
+
+ dfb_surfacemanager_adjust_heap_offset( dfb_fbdev->shared->manager,
+ var.yres_virtual * fix.line_length );
+
+ if (shared->fix.xpanstep || shared->fix.ypanstep || shared->fix.ywrapstep)
+ dfb_fbdev_pan( var.xoffset, var.yoffset, false );
+
+ dfb_gfxcard_after_set_var();
+
+ dfb_surface_notify( surface,
+ CSNF_SIZEFORMAT | CSNF_FLIP |
+ CSNF_VIDEO | CSNF_SYSTEM );
+ }
+
+ dfb_gfxcard_unlock();
+
+ return DFB_OK;
+}
+#endif
+
+/*
+ * parses video modes in /etc/fb.modes and stores them in dfb_fbdev->shared->modes
+ * (to be replaced by DirectFB's own config system
+ */
+static DFBResult
+dfb_fbdev_read_modes( void )
+{
+ FILE *fp;
+ char line[80],label[32],value[16];
+ int geometry=0, timings=0;
+ int dummy;
+ VideoMode temp_mode;
+ FBDevShared *shared = dfb_fbdev->shared;
+ VideoMode *prev = shared->modes;
+
+ D_DEBUG_AT( FBDev_Mode, "%s()\n", __FUNCTION__ );
+
+ if (!(fp = fopen("/etc/fb.modes","r")))
+ return errno2result( errno );
+
+ while (fgets(line,79,fp)) {
+ if (sscanf(line, "mode \"%31[^\"]\"",label) == 1) {
+ memset( &temp_mode, 0, sizeof(VideoMode) );
+
+ geometry = 0;
+ timings = 0;
+
+ while (fgets(line,79,fp) && !(strstr(line,"endmode"))) {
+ if (5 == sscanf(line," geometry %d %d %d %d %d", &temp_mode.xres, &temp_mode.yres, &dummy, &dummy, &temp_mode.bpp)) {
+ geometry = 1;
+ }
+ else if (7 == sscanf(line," timings %d %d %d %d %d %d %d", &temp_mode.pixclock, &temp_mode.left_margin, &temp_mode.right_margin,
+ &temp_mode.upper_margin, &temp_mode.lower_margin, &temp_mode.hsync_len, &temp_mode.vsync_len)) {
+ timings = 1;
+ }
+ else if (1 == sscanf(line, " hsync %15s",value) && 0 == strcasecmp(value,"high")) {
+ temp_mode.hsync_high = 1;
+ }
+ else if (1 == sscanf(line, " vsync %15s",value) && 0 == strcasecmp(value,"high")) {
+ temp_mode.vsync_high = 1;
+ }
+ else if (1 == sscanf(line, " csync %15s",value) && 0 == strcasecmp(value,"high")) {
+ temp_mode.csync_high = 1;
+ }
+ else if (1 == sscanf(line, " laced %15s",value) && 0 == strcasecmp(value,"true")) {
+ temp_mode.laced = 1;
+ }
+ else if (1 == sscanf(line, " double %15s",value) && 0 == strcasecmp(value,"true")) {
+ temp_mode.doubled = 1;
+ }
+ else if (1 == sscanf(line, " gsync %15s",value) && 0 == strcasecmp(value,"true")) {
+ temp_mode.sync_on_green = 1;
+ }
+ else if (1 == sscanf(line, " extsync %15s",value) && 0 == strcasecmp(value,"true")) {
+ temp_mode.external_sync = 1;
+ }
+ else if (1 == sscanf(line, " bcast %15s",value) && 0 == strcasecmp(value,"true")) {
+ temp_mode.broadcast = 1;
+ }
+ }
+
+ if (geometry && timings && !dfb_fbdev_test_mode_simple(&temp_mode)) {
+ VideoMode *mode = SHCALLOC( shared->shmpool, 1, sizeof(VideoMode) );
+ if (!mode) {
+ D_OOSHM();
+ continue;
+ }
+
+ if (!prev)
+ shared->modes = mode;
+ else
+ prev->next = mode;
+
+ direct_memcpy (mode, &temp_mode, sizeof(VideoMode));
+
+ prev = mode;
+
+ D_DEBUG_AT( FBDev_Mode, " +-> %16s %4dx%4d %s%s\n", label, temp_mode.xres, temp_mode.yres,
+ temp_mode.laced ? "interlaced " : "", temp_mode.doubled ? "doublescan" : "" );
+ }
+ }
+ }
+
+ fclose (fp);
+
+ return DFB_OK;
+}
+
+/*
+ * some fbdev drivers use the palette as gamma ramp in >8bpp modes, to have
+ * correct colors, the gamme ramp has to be initialized.
+ */
+
+static u16
+dfb_fbdev_calc_gamma(int n, int max)
+{
+ int ret = 65535 * n / max;
+ return CLAMP( ret, 0, 65535 );
+}
+
+static DFBResult
+dfb_fbdev_set_gamma_ramp( DFBSurfacePixelFormat format )
+{
+ int i;
+
+ int red_size = 0;
+ int green_size = 0;
+ int blue_size = 0;
+ int red_max = 0;
+ int green_max = 0;
+ int blue_max = 0;
+
+ struct fb_cmap *cmap;
+
+ if (!dfb_fbdev) {
+ D_BUG( "dfb_fbdev_set_gamma_ramp() called while dfb_fbdev == NULL!" );
+
+ return DFB_BUG;
+ }
+
+ switch (format) {
+ case DSPF_ARGB1555:
+ case DSPF_RGB555:
+ case DSPF_BGR555:
+ red_size = 32;
+ green_size = 32;
+ blue_size = 32;
+ break;
+ case DSPF_ARGB4444:
+ case DSPF_RGBA4444:
+ case DSPF_RGB444:
+ case DSPF_RGB16:
+ red_size = 32;
+ green_size = 64;
+ blue_size = 32;
+ break;
+ case DSPF_RGB24:
+ case DSPF_RGB32:
+ case DSPF_ARGB:
+ red_size = 256;
+ green_size = 256;
+ blue_size = 256;
+ break;
+ default:
+ return DFB_OK;
+ }
+
+ /*
+ * ++Tony: The gamma ramp must be set differently if in DirectColor,
+ * ie, to mimic TrueColor, index == color[index].
+ */
+ if (dfb_fbdev->shared->fix.visual == FB_VISUAL_DIRECTCOLOR) {
+ red_max = 65536 / (256/red_size);
+ green_max = 65536 / (256/green_size);
+ blue_max = 65536 / (256/blue_size);
+ }
+ else {
+ red_max = red_size;
+ green_max = green_size;
+ blue_max = blue_size;
+ }
+
+ cmap = &dfb_fbdev->shared->current_cmap;
+
+ /* assume green to have most weight */
+ cmap->len = green_size;
+
+ for (i = 0; i < red_size; i++)
+ cmap->red[i] = dfb_fbdev_calc_gamma( i, red_max );
+
+ for (i = 0; i < green_size; i++)
+ cmap->green[i] = dfb_fbdev_calc_gamma( i, green_max );
+
+ for (i = 0; i < blue_size; i++)
+ cmap->blue[i] = dfb_fbdev_calc_gamma( i, blue_max );
+
+ /* ++Tony: Some drivers use the upper byte, some use the lower */
+ if (dfb_fbdev->shared->fix.visual == FB_VISUAL_DIRECTCOLOR) {
+ for (i = 0; i < red_size; i++)
+ cmap->red[i] |= cmap->red[i] << 8;
+
+ for (i = 0; i < green_size; i++)
+ cmap->green[i] |= cmap->green[i] << 8;
+
+ for (i = 0; i < blue_size; i++)
+ cmap->blue[i] |= cmap->blue[i] << 8;
+ }
+
+ if (FBDEV_IOCTL( FBIOPUTCMAP, cmap ) < 0) {
+ D_PERROR( "DirectFB/FBDev: "
+ "Could not set gamma ramp" );
+
+ return errno2result(errno);
+ }
+
+ return DFB_OK;
+}
+
+static DFBResult
+dfb_fbdev_set_palette( CorePalette *palette )
+{
+ int i;
+ struct fb_cmap *cmap = &dfb_fbdev->shared->current_cmap;
+
+ D_ASSERT( palette != NULL );
+
+ cmap->len = palette->num_entries <= 256 ? palette->num_entries : 256;
+
+ for (i = 0; i < (int)cmap->len; i++) {
+ cmap->red[i] = palette->entries[i].r;
+ cmap->green[i] = palette->entries[i].g;
+ cmap->blue[i] = palette->entries[i].b;
+ cmap->transp[i] = 0xff - palette->entries[i].a;
+
+ cmap->red[i] |= cmap->red[i] << 8;
+ cmap->green[i] |= cmap->green[i] << 8;
+ cmap->blue[i] |= cmap->blue[i] << 8;
+ cmap->transp[i] |= cmap->transp[i] << 8;
+ }
+
+ if (FBDEV_IOCTL( FBIOPUTCMAP, cmap ) < 0) {
+ D_PERROR( "DirectFB/FBDev: Could not set the palette!\n" );
+
+ return errno2result(errno);
+ }
+
+ return DFB_OK;
+}
+
+static DFBResult
+dfb_fbdev_set_rgb332_palette( void )
+{
+ DFBResult ret = DFB_OK;
+ int red_val;
+ int green_val;
+ int blue_val;
+ int i = 0;
+ FusionSHMPoolShared *pool = dfb_fbdev->shared->shmpool_data;
+
+ struct fb_cmap cmap;
+
+ if (!dfb_fbdev) {
+ D_BUG( "dfb_fbdev_set_rgb332_palette() called while dfb_fbdev == NULL!" );
+
+ return DFB_BUG;
+ }
+
+ cmap.start = 0;
+ cmap.len = 256;
+ cmap.red = (u16*)SHMALLOC( pool, 2 * 256 );
+ if (!cmap.red) {
+ return D_OOSHM();
+ }
+ cmap.green = (u16*)SHMALLOC( pool, 2 * 256 );
+ if (!cmap.green) {
+ ret = D_OOSHM();
+ goto free_red;
+ }
+ cmap.blue = (u16*)SHMALLOC( pool, 2 * 256 );
+ if (!cmap.blue) {
+ ret = D_OOSHM();
+ goto free_green;
+ }
+ cmap.transp = (u16*)SHMALLOC( pool, 2 * 256 );
+ if (!cmap.transp) {
+ ret = D_OOSHM();
+ goto free_blue;
+ }
+
+ for (red_val = 0; red_val < 8 ; red_val++) {
+ for (green_val = 0; green_val < 8 ; green_val++) {
+ for (blue_val = 0; blue_val < 4 ; blue_val++) {
+ cmap.red[i] = dfb_fbdev_calc_gamma( red_val, 7 );
+ cmap.green[i] = dfb_fbdev_calc_gamma( green_val, 7 );
+ cmap.blue[i] = dfb_fbdev_calc_gamma( blue_val, 3 );
+ cmap.transp[i] = (i ? 0x2000 : 0xffff);
+ i++;
+ }
+ }
+ }
+
+ if (FBDEV_IOCTL( FBIOPUTCMAP, &cmap ) < 0) {
+ D_PERROR( "DirectFB/FBDev: "
+ "Could not set rgb332 palette" );
+ ret = errno2result(errno);
+ goto free_transp;
+ }
+
+ free_transp:
+ SHFREE( pool, cmap.transp );
+ free_blue:
+ SHFREE( pool, cmap.blue );
+ free_green:
+ SHFREE( pool, cmap.green );
+ free_red:
+ SHFREE( pool, cmap.red );
+
+ return ret;
+}
+
+static FusionCallHandlerResult
+fbdev_ioctl_call_handler( int caller,
+ int call_arg,
+ void *call_ptr,
+ void *ctx,
+ unsigned int serial,
+ int *ret_val )
+{
+ int ret;
+ const char cursoroff_str[] = "\033[?1;0;0c";
+ const char blankoff_str[] = "\033[9;0]";
+
+ if (dfb_config->vt) {
+ if (!dfb_config->kd_graphics && call_arg == FBIOPUT_VSCREENINFO)
+ ioctl( dfb_fbdev->vt->fd, KDSETMODE, KD_GRAPHICS );
+ }
+
+ ret = ioctl( dfb_fbdev->fd, call_arg, call_ptr );
+ if (ret)
+ ret = errno;
+
+ if (dfb_config->vt) {
+ if (call_arg == FBIOPUT_VSCREENINFO) {
+ if (!dfb_config->kd_graphics) {
+ ioctl( dfb_fbdev->vt->fd, KDSETMODE, KD_TEXT );
+ write( dfb_fbdev->vt->fd, cursoroff_str, strlen(cursoroff_str) );
+ write( dfb_fbdev->vt->fd, blankoff_str, strlen(blankoff_str) );
+ }
+ }
+ }
+
+ *ret_val = ret;
+
+ return FCHR_RETURN;
+}
+
+static int
+fbdev_ioctl( int request, void *arg, int arg_size )
+{
+ int ret;
+ int erno;
+ void *tmp_shm = NULL;
+ FBDevShared *shared;
+
+ D_ASSERT( dfb_fbdev != NULL );
+
+ shared = dfb_fbdev->shared;
+
+ D_ASSERT( shared != NULL );
+
+ if (dfb_core_is_master( dfb_fbdev->core )) {
+ fbdev_ioctl_call_handler( 1, request, arg, NULL, 0, &ret );
+ errno = ret;
+ return errno ? -1 : 0;
+ }
+
+ if (arg) {
+ if (!fusion_is_shared( dfb_core_world(dfb_fbdev->core), arg )) {
+ tmp_shm = SHMALLOC( shared->shmpool, arg_size );
+ if (!tmp_shm) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ direct_memcpy( tmp_shm, arg, arg_size );
+ }
+ }
+
+ ret = fusion_call_execute( &shared->fbdev_ioctl, FCEF_NONE,
+ request, tmp_shm ? tmp_shm : arg, &erno );
+
+ if (tmp_shm) {
+ direct_memcpy( arg, tmp_shm, arg_size );
+ SHFREE( shared->shmpool, tmp_shm );
+ }
+
+ errno = erno;
+
+ return errno ? -1 : 0;
+}
+
diff --git a/Source/DirectFB/systems/fbdev/fbdev.h b/Source/DirectFB/systems/fbdev/fbdev.h
new file mode 100755
index 0000000..a90a76b
--- /dev/null
+++ b/Source/DirectFB/systems/fbdev/fbdev.h
@@ -0,0 +1,142 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __CORE__FBDEV_H__
+#define __CORE__FBDEV_H__
+
+#include <asm/types.h> /* Needs to be included before dfb_types.h */
+
+#include <core/coretypes.h>
+
+#include <core/layers_internal.h>
+
+#include <core/system.h>
+
+#include <fusion/call.h>
+#include <fusion/reactor.h>
+
+#include "agp.h"
+#include "fb.h"
+#include "surfacemanager.h"
+#include "vt.h"
+
+#ifndef FBIO_WAITFORVSYNC
+#define FBIO_WAITFORVSYNC _IOW('F', 0x20, u_int32_t)
+#endif
+
+
+typedef struct {
+ /* fbdev fixed screeninfo, contains infos about memory and type of card */
+ struct fb_fix_screeninfo fix;
+
+ VideoMode *modes; /* linked list of valid
+ video modes */
+ VideoMode current_mode; /* current video mode */
+
+ struct fb_var_screeninfo current_var; /* fbdev variable screeninfo
+ set by DirectFB */
+ struct fb_var_screeninfo orig_var; /* fbdev variable screeninfo
+ before DirectFB was started */
+
+ void *orig_cmap_memory;
+ void *temp_cmap_memory;
+ void *current_cmap_memory;
+
+ struct fb_cmap orig_cmap; /* original palette */
+
+ struct fb_cmap current_cmap; /* our copy of the cmap */
+
+ struct fb_cmap temp_cmap; /* scratch */
+
+ FusionCall fbdev_ioctl; /* ioctl rpc */
+
+ unsigned long page_mask; /* PAGE_SIZE - 1 */
+
+ CoreSurfacePool *pool;
+
+ struct {
+ int bus;
+ int dev;
+ int func;
+ } pci; /* PCI Bus ID of graphics device */
+
+ struct {
+ unsigned short vendor; /* Graphics device vendor id */
+ unsigned short model; /* Graphics device model id */
+ } device;
+
+ AGPShared *agp;
+
+ FusionSHMPoolShared *shmpool;
+ FusionSHMPoolShared *shmpool_data;
+
+ CoreLayerRegionConfig config;
+
+ SurfaceManager *manager;
+} FBDevShared;
+
+typedef struct {
+ FBDevShared *shared;
+
+ CoreDFB *core;
+
+ /* virtual framebuffer address */
+ void *framebuffer_base;
+
+ int fd; /* file descriptor for /dev/fb */
+
+ VirtualTerminal *vt;
+
+ AGPDevice *agp;
+} FBDev;
+
+/*
+ * core init function, opens /dev/fb, get fbdev screeninfo
+ * disables font acceleration, reads mode list
+ */
+DFBResult dfb_fbdev_initialize( void );
+DFBResult dfb_fbdev_join( void );
+
+/*
+ * deinitializes DirectFB fbdev stuff and restores fbdev settings
+ */
+DFBResult dfb_fbdev_shutdown( bool emergency );
+DFBResult dfb_fbdev_leave ( bool emergency );
+
+const VideoMode *dfb_fbdev_find_mode( int width,
+ int height );
+DFBResult dfb_fbdev_test_mode ( const VideoMode *mode,
+ const CoreLayerRegionConfig *config );
+DFBResult dfb_fbdev_test_mode_simple( const VideoMode *mode );
+
+DFBResult dfb_fbdev_set_mode ( const VideoMode *mode,
+ CoreSurface *surface,
+ unsigned int xoffset,
+ unsigned int yoffset );
+
+#endif
diff --git a/Source/DirectFB/systems/fbdev/fbdev_surface_pool.c b/Source/DirectFB/systems/fbdev/fbdev_surface_pool.c
new file mode 100755
index 0000000..c5454a6
--- /dev/null
+++ b/Source/DirectFB/systems/fbdev/fbdev_surface_pool.c
@@ -0,0 +1,423 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <asm/types.h>
+
+#include <config.h>
+
+#include <direct/debug.h>
+#include <direct/mem.h>
+
+#include <core/surface_pool.h>
+
+#include <gfx/convert.h>
+
+#include "fbdev.h"
+#include "surfacemanager.h"
+
+extern FBDev *dfb_fbdev;
+
+D_DEBUG_DOMAIN( FBDev_Surfaces, "FBDev/Surfaces", "FBDev Framebuffer Surface Pool" );
+D_DEBUG_DOMAIN( FBDev_SurfLock, "FBDev/SurfLock", "FBDev Framebuffer Surface Pool Locks" );
+
+/**********************************************************************************************************************/
+
+typedef struct {
+ int magic;
+
+ SurfaceManager *manager;
+} FBDevPoolData;
+
+typedef struct {
+ int magic;
+
+ CoreDFB *core;
+} FBDevPoolLocalData;
+
+typedef struct {
+ int magic;
+
+ int offset;
+ int pitch;
+ int size;
+
+ Chunk *chunk;
+} FBDevAllocationData;
+
+/**********************************************************************************************************************/
+
+static int
+fbdevPoolDataSize( void )
+{
+ return sizeof(FBDevPoolData);
+}
+
+static int
+fbdevPoolLocalDataSize( void )
+{
+ return sizeof(FBDevPoolLocalData);
+}
+
+static int
+fbdevAllocationDataSize( void )
+{
+ return sizeof(FBDevAllocationData);
+}
+
+static DFBResult
+fbdevInitPool( CoreDFB *core,
+ CoreSurfacePool *pool,
+ void *pool_data,
+ void *pool_local,
+ void *system_data,
+ CoreSurfacePoolDescription *ret_desc )
+{
+ DFBResult ret;
+ FBDevPoolData *data = pool_data;
+ FBDevPoolLocalData *local = pool_local;
+
+ D_DEBUG_AT( FBDev_Surfaces, "%s()\n", __FUNCTION__ );
+
+ D_ASSERT( core != NULL );
+ D_MAGIC_ASSERT( pool, CoreSurfacePool );
+ D_ASSERT( data != NULL );
+ D_ASSERT( local != NULL );
+ D_ASSERT( ret_desc != NULL );
+
+ ret = dfb_surfacemanager_create( core, dfb_fbdev->shared->fix.smem_len, &data->manager );
+ if (ret)
+ return ret;
+
+ 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->priority = CSPP_DEFAULT;
+
+ /* 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;
+
+ snprintf( ret_desc->name, DFB_SURFACE_POOL_DESC_NAME_LENGTH, "Frame Buffer Memory" );
+
+ local->core = core;
+
+ D_MAGIC_SET( data, FBDevPoolData );
+ D_MAGIC_SET( local, FBDevPoolLocalData );
+
+
+ D_ASSERT( dfb_fbdev != NULL );
+ D_ASSERT( dfb_fbdev->shared != NULL );
+
+ dfb_fbdev->shared->manager = data->manager;
+
+ return DFB_OK;
+}
+
+static DFBResult
+fbdevJoinPool( CoreDFB *core,
+ CoreSurfacePool *pool,
+ void *pool_data,
+ void *pool_local,
+ void *system_data )
+{
+ FBDevPoolData *data = pool_data;
+ FBDevPoolLocalData *local = pool_local;
+
+ D_DEBUG_AT( FBDev_Surfaces, "%s()\n", __FUNCTION__ );
+
+ D_ASSERT( core != NULL );
+ D_MAGIC_ASSERT( pool, CoreSurfacePool );
+ D_MAGIC_ASSERT( data, FBDevPoolData );
+ D_ASSERT( local != NULL );
+
+ (void) data;
+
+ local->core = core;
+
+ D_MAGIC_SET( local, FBDevPoolLocalData );
+
+ return DFB_OK;
+}
+
+static DFBResult
+fbdevDestroyPool( CoreSurfacePool *pool,
+ void *pool_data,
+ void *pool_local )
+{
+ FBDevPoolData *data = pool_data;
+ FBDevPoolLocalData *local = pool_local;
+
+ D_DEBUG_AT( FBDev_Surfaces, "%s()\n", __FUNCTION__ );
+
+ D_MAGIC_ASSERT( pool, CoreSurfacePool );
+ D_MAGIC_ASSERT( data, FBDevPoolData );
+ D_MAGIC_ASSERT( local, FBDevPoolLocalData );
+
+ dfb_surfacemanager_destroy( data->manager );
+
+ D_MAGIC_CLEAR( data );
+ D_MAGIC_CLEAR( local );
+
+ return DFB_OK;
+}
+
+static DFBResult
+fbdevLeavePool( CoreSurfacePool *pool,
+ void *pool_data,
+ void *pool_local )
+{
+ FBDevPoolData *data = pool_data;
+ FBDevPoolLocalData *local = pool_local;
+
+ D_DEBUG_AT( FBDev_Surfaces, "%s()\n", __FUNCTION__ );
+
+ D_MAGIC_ASSERT( pool, CoreSurfacePool );
+ D_MAGIC_ASSERT( data, FBDevPoolData );
+ D_MAGIC_ASSERT( local, FBDevPoolLocalData );
+
+ (void) data;
+
+ D_MAGIC_CLEAR( local );
+
+ return DFB_OK;
+}
+
+static DFBResult
+fbdevTestConfig( CoreSurfacePool *pool,
+ void *pool_data,
+ void *pool_local,
+ CoreSurfaceBuffer *buffer,
+ const CoreSurfaceConfig *config )
+{
+ DFBResult ret;
+ CoreSurface *surface;
+ FBDevPoolData *data = pool_data;
+ FBDevPoolLocalData *local = pool_local;
+
+ D_DEBUG_AT( FBDev_Surfaces, "%s( %p )\n", __FUNCTION__, buffer );
+
+ D_MAGIC_ASSERT( pool, CoreSurfacePool );
+ D_MAGIC_ASSERT( data, FBDevPoolData );
+ D_MAGIC_ASSERT( local, FBDevPoolLocalData );
+ D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );
+
+ surface = buffer->surface;
+ D_MAGIC_ASSERT( surface, CoreSurface );
+
+ if ((surface->type & CSTF_LAYER) && surface->resource_id == DLID_PRIMARY)
+ return DFB_OK;
+
+ ret = dfb_surfacemanager_allocate( local->core, data->manager, buffer, NULL, NULL );
+
+ D_DEBUG_AT( FBDev_Surfaces, " -> %s\n", DirectFBErrorString(ret) );
+
+ return ret;
+}
+
+static DFBResult
+fbdevAllocateBuffer( CoreSurfacePool *pool,
+ void *pool_data,
+ void *pool_local,
+ CoreSurfaceBuffer *buffer,
+ CoreSurfaceAllocation *allocation,
+ void *alloc_data )
+{
+ DFBResult ret;
+ CoreSurface *surface;
+ FBDevPoolData *data = pool_data;
+ FBDevPoolLocalData *local = pool_local;
+ FBDevAllocationData *alloc = alloc_data;
+
+ D_DEBUG_AT( FBDev_Surfaces, "%s( %p )\n", __FUNCTION__, buffer );
+
+ D_MAGIC_ASSERT( pool, CoreSurfacePool );
+ D_MAGIC_ASSERT( data, FBDevPoolData );
+ D_MAGIC_ASSERT( local, FBDevPoolLocalData );
+ D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );
+
+ surface = buffer->surface;
+ D_MAGIC_ASSERT( surface, CoreSurface );
+
+ if ((surface->type & CSTF_LAYER) && surface->resource_id == DLID_PRIMARY) {
+ FBDevShared *shared = dfb_fbdev->shared;
+ int index = dfb_surface_buffer_index( buffer );
+
+ D_DEBUG_AT( FBDev_Surfaces, " -> primary layer buffer (index %d)\n", index );
+
+ if (index == 0) {
+ const VideoMode *highest;
+ /* FIXME: this should use source.w/source.h from layer region config! */
+ unsigned int width = surface->config.size.w;
+ unsigned int height = surface->config.size.h;
+
+ D_INFO( "FBDev/Mode: Setting %dx%d %s\n", width, height, dfb_pixelformat_name(surface->config.format) );
+
+ highest = dfb_fbdev_find_mode( width, height );
+ if (!highest)
+ return DFB_UNSUPPORTED;
+
+ ret = dfb_fbdev_set_mode( highest, surface, 0, 0 );
+ if (ret)
+ return ret;
+ }
+
+ alloc->pitch = shared->fix.line_length;
+ alloc->size = surface->config.size.h * alloc->pitch;
+ alloc->offset = index * alloc->size;
+
+ D_INFO( "FBDev/Surface: Allocated %dx%d %d bit %s buffer (index %d) at offset %d and pitch %d.\n",
+ surface->config.size.w, surface->config.size.h, shared->current_var.bits_per_pixel,
+ dfb_pixelformat_name(buffer->format), index, alloc->offset, alloc->pitch );
+ }
+ else {
+ Chunk *chunk;
+
+ ret = dfb_surfacemanager_allocate( local->core, data->manager, buffer, allocation, &chunk );
+ if (ret)
+ return ret;
+
+ D_MAGIC_ASSERT( chunk, Chunk );
+
+ alloc->offset = chunk->offset;
+ alloc->pitch = chunk->pitch;
+ alloc->size = chunk->length;
+
+ alloc->chunk = chunk;
+ }
+
+ D_DEBUG_AT( FBDev_Surfaces, " -> offset %d, pitch %d, size %d\n", alloc->offset, alloc->pitch, alloc->size );
+
+ allocation->size = alloc->size;
+ allocation->offset = alloc->offset;
+
+ D_MAGIC_SET( alloc, FBDevAllocationData );
+
+ return DFB_OK;
+}
+
+static DFBResult
+fbdevDeallocateBuffer( CoreSurfacePool *pool,
+ void *pool_data,
+ void *pool_local,
+ CoreSurfaceBuffer *buffer,
+ CoreSurfaceAllocation *allocation,
+ void *alloc_data )
+{
+ FBDevPoolData *data = pool_data;
+ FBDevAllocationData *alloc = alloc_data;
+
+ D_DEBUG_AT( FBDev_Surfaces, "%s( %p )\n", __FUNCTION__, buffer );
+
+ D_MAGIC_ASSERT( pool, CoreSurfacePool );
+ D_MAGIC_ASSERT( data, FBDevPoolData );
+ D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );
+ D_MAGIC_ASSERT( alloc, FBDevAllocationData );
+
+ if (alloc->chunk)
+ dfb_surfacemanager_deallocate( data->manager, alloc->chunk );
+
+ D_MAGIC_CLEAR( alloc );
+
+ return DFB_OK;
+}
+
+static DFBResult
+fbdevLock( CoreSurfacePool *pool,
+ void *pool_data,
+ void *pool_local,
+ CoreSurfaceAllocation *allocation,
+ void *alloc_data,
+ CoreSurfaceBufferLock *lock )
+{
+ FBDevAllocationData *alloc = alloc_data;
+
+ D_MAGIC_ASSERT( pool, CoreSurfacePool );
+ D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation );
+ D_MAGIC_ASSERT( alloc, FBDevAllocationData );
+ D_MAGIC_ASSERT( lock, CoreSurfaceBufferLock );
+
+ D_DEBUG_AT( FBDev_SurfLock, "%s( %p )\n", __FUNCTION__, lock->buffer );
+
+ lock->pitch = alloc->pitch;
+ lock->offset = alloc->offset;
+ lock->addr = dfb_fbdev->framebuffer_base + alloc->offset;
+ lock->phys = dfb_fbdev->shared->fix.smem_start + alloc->offset;
+
+ D_DEBUG_AT( FBDev_SurfLock, " -> offset %lu, pitch %d, addr %p, phys 0x%08lx\n",
+ lock->offset, lock->pitch, lock->addr, lock->phys );
+
+ return DFB_OK;
+}
+
+static DFBResult
+fbdevUnlock( CoreSurfacePool *pool,
+ void *pool_data,
+ void *pool_local,
+ CoreSurfaceAllocation *allocation,
+ void *alloc_data,
+ CoreSurfaceBufferLock *lock )
+{
+ FBDevAllocationData *alloc = alloc_data;
+
+ D_MAGIC_ASSERT( pool, CoreSurfacePool );
+ D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation );
+ D_MAGIC_ASSERT( alloc, FBDevAllocationData );
+ D_MAGIC_ASSERT( lock, CoreSurfaceBufferLock );
+
+ D_DEBUG_AT( FBDev_SurfLock, "%s( %p )\n", __FUNCTION__, lock->buffer );
+
+ (void) alloc;
+
+ return DFB_OK;
+}
+
+const SurfacePoolFuncs fbdevSurfacePoolFuncs = {
+ .PoolDataSize = fbdevPoolDataSize,
+ .PoolLocalDataSize = fbdevPoolLocalDataSize,
+ .AllocationDataSize = fbdevAllocationDataSize,
+
+ .InitPool = fbdevInitPool,
+ .JoinPool = fbdevJoinPool,
+ .DestroyPool = fbdevDestroyPool,
+ .LeavePool = fbdevLeavePool,
+
+ .TestConfig = fbdevTestConfig,
+ .AllocateBuffer = fbdevAllocateBuffer,
+ .DeallocateBuffer = fbdevDeallocateBuffer,
+
+ .Lock = fbdevLock,
+ .Unlock = fbdevUnlock,
+};
+
diff --git a/Source/DirectFB/systems/fbdev/surfacemanager.c b/Source/DirectFB/systems/fbdev/surfacemanager.c
new file mode 100755
index 0000000..811288b
--- /dev/null
+++ b/Source/DirectFB/systems/fbdev/surfacemanager.c
@@ -0,0 +1,617 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+
+#include <fusion/shmalloc.h>
+
+#include <directfb.h>
+#include <directfb_util.h>
+
+#include <core/core.h>
+
+#include <core/gfxcard.h>
+#include <core/surface.h>
+#include <core/surface_buffer.h>
+
+#include <direct/debug.h>
+#include <direct/messages.h>
+#include <direct/util.h>
+
+#include <gfx/convert.h>
+
+#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 );
+}
+
+DFBResult dfb_surfacemanager_adjust_heap_offset( SurfaceManager *manager,
+ int offset )
+{
+ D_MAGIC_ASSERT( manager, SurfaceManager );
+ D_ASSERT( offset >= 0 );
+
+ D_DEBUG_AT( SurfMan, "%s( %p, %d )\n", __FUNCTION__, manager, offset );
+
+/*FIXME_SC_2 if (manager->limits.surface_byteoffset_alignment > 1) {
+ offset += manager->limits.surface_byteoffset_alignment - 1;
+ offset -= offset % manager->limits.surface_byteoffset_alignment;
+ }
+*/
+ /*
+ * Adjust the offset of the heap.
+ */
+ if (manager->chunks->buffer == NULL) {
+ /* first chunk is free */
+ if (offset <= manager->chunks->offset + manager->chunks->length) {
+ /* ok, just recalculate offset and length */
+ manager->chunks->length = manager->chunks->offset +
+ manager->chunks->length - offset;
+ manager->chunks->offset = offset;
+ }
+ else {
+ D_WARN("unable to adjust heap offset");
+ /* more space needed than free at the beginning */
+ /* TODO: move/destroy instances */
+ }
+ }
+ else {
+ D_WARN("unable to adjust heap offset");
+ /* very rare case that the first chunk is occupied */
+ /* TODO: move/destroy instances */
+ }
+
+ manager->avail -= offset - manager->offset;
+ manager->offset = offset;
+
+ return DFB_OK;
+}
+
+/** 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 )
+{
+ 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\n", pitch, length );
+
+ if (manager->avail < length)
+ return DFB_TEMPUNAVAIL;
+
+ /* examine chunks */
+ c = manager->chunks;
+ D_MAGIC_ASSERT( c, Chunk );
+
+ /* FIXME_SC_2 Workaround creation happening before graphics driver initialization. */
+ if (!c->next) {
+ int length = dfb_gfxcard_memory_length();
+
+ if (c->length != length - manager->offset) {
+ D_WARN( "workaround" );
+
+ 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 );
+
+ 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;
+
+ 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 );
+
+ if (other->locked) {
+ D_DEBUG_AT( SurfMan, " ++ %7d locked %dx\n", allocation->size, other->locked );
+ 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_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;
+ }
+ else {
+ D_DEBUG_AT( SurfMan, "Deallocating %d bytes at offset %d.\n", chunk->length, chunk->offset );
+ }
+
+ if (chunk->buffer->policy == CSP_VIDEOONLY)
+ manager->avail += chunk->length;
+
+ 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, "Allocating %d bytes at offset %d.\n", chunk->length, chunk->offset );
+
+ chunk->allocation = allocation;
+ chunk->buffer = allocation->buffer;
+ chunk->pitch = pitch;
+
+ manager->min_toleration++;
+
+ return chunk;
+}
+
diff --git a/Source/DirectFB/systems/fbdev/surfacemanager.h b/Source/DirectFB/systems/fbdev/surfacemanager.h
new file mode 100755
index 0000000..f7812d1
--- /dev/null
+++ b/Source/DirectFB/systems/fbdev/surfacemanager.h
@@ -0,0 +1,117 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __SURFACEMANAGER_H__
+#define __SURFACEMANAGER_H__
+
+#include <directfb.h>
+
+#include <core/coretypes.h>
+
+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 );
+
+/*
+ * adjust the offset within the framebuffer for surface storage,
+ * needs to be called after a resolution switch
+ */
+DFBResult dfb_surfacemanager_adjust_heap_offset( SurfaceManager *manager,
+ int offset );
+
+/*
+ * 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 );
+
+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/Source/DirectFB/systems/fbdev/vt.c b/Source/DirectFB/systems/fbdev/vt.c
new file mode 100755
index 0000000..02bad77
--- /dev/null
+++ b/Source/DirectFB/systems/fbdev/vt.c
@@ -0,0 +1,675 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <config.h>
+
+#include <asm/types.h> /* Needs to be included before dfb_types.h */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/vt.h>
+#include <sys/kd.h>
+#include <errno.h>
+#include <pthread.h>
+
+#include <directfb.h>
+
+#include <misc/conf.h>
+#include <misc/util.h>
+
+#include <direct/debug.h>
+#include <direct/mem.h>
+#include <direct/messages.h>
+#include <direct/thread.h>
+#include <direct/util.h>
+
+#include <core/core.h>
+#include <core/coredefs.h>
+#include <core/coretypes.h>
+#include <core/gfxcard.h>
+
+#include "fbdev.h"
+#include "fb.h"
+#include "vt.h"
+
+D_DEBUG_DOMAIN( VT, "FBDev/VT", "FBDev 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 FBDev *dfb_fbdev;
+
+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_fbdev->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 )
+{
+ const char cursoron_str[] = "\033[?0;0;0c";
+ const char blankon_str[] = "\033[9;10]";
+
+ 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 {
+ write( dfb_vt->fd, blankon_str, sizeof(blankon_str) );
+ }
+ 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_fbdev->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_fbdev->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_fbdev->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];
+
+ 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;
+ }
+
+ 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 {
+ 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_fbdev->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_fbdev->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_fbdev->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)
+ break;
+
+ tcflush( dfb_vt->fd, TCIFLUSH );
+ }
+
+ return NULL;
+}
diff --git a/Source/DirectFB/systems/fbdev/vt.h b/Source/DirectFB/systems/fbdev/vt.h
new file mode 100755
index 0000000..d9b1019
--- /dev/null
+++ b/Source/DirectFB/systems/fbdev/vt.h
@@ -0,0 +1,83 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __VT_H__
+#define __VT_H__
+
+#include <signal.h>
+#include <termios.h>
+#include <unistd.h>
+#include <linux/vt.h>
+
+#include <directfb.h>
+
+typedef struct {
+ int fd0; /* file descriptor of /dev/tty0 */
+ int fd; /* file descriptor of /dev/ttyN
+ where N is the number of the allocated VT,
+ may be equal to 'fd0' if VT allocation
+ is disabled by "--no-vt-switch" */
+
+ int num; /* number of vt where DirectFB runs */
+ int prev; /* number of vt DirectFB was started from */
+
+ int old_fb; /* original fb mapped to vt */
+
+ struct sigaction sig_usr1; /* previous signal handler for USR1 */
+ struct sigaction sig_usr2; /* previous signal handler for USR2 */
+
+ struct vt_mode vt_mode; /* previous VT mode */
+
+ DirectThread *thread;
+ pthread_mutex_t lock;
+ pthread_cond_t wait;
+
+ int vt_sig;
+ struct termios old_ts;
+
+ bool flush;
+ DirectThread *flush_thread;
+} VirtualTerminal;
+
+/*
+ * allocates and switches to a new virtual terminal
+ */
+DFBResult dfb_vt_initialize( void );
+DFBResult dfb_vt_join( void );
+
+/*
+ * deallocates virtual terminal
+ */
+DFBResult dfb_vt_shutdown( bool emergency );
+DFBResult dfb_vt_leave( bool emergency );
+
+DFBResult dfb_vt_detach( bool force );
+
+bool dfb_vt_switch( int num );
+
+#endif