From 7fe60435bce6595a9c58a9bfd8244d74b5320e96 Mon Sep 17 00:00:00 2001 From: Benjamin Franzke Date: Tue, 15 Jan 2013 08:46:13 +0100 Subject: Import DirectFB141_2k11R3_beta5 --- Source/DirectFB/systems/x11/Makefile.am | 63 ++ Source/DirectFB/systems/x11/Makefile.in | 624 +++++++++++++++ Source/DirectFB/systems/x11/README | 11 + Source/DirectFB/systems/x11/glx_surface_pool.c | 838 +++++++++++++++++++++ Source/DirectFB/systems/x11/glx_surface_pool.h | 79 ++ Source/DirectFB/systems/x11/primary.c | 664 ++++++++++++++++ Source/DirectFB/systems/x11/primary.h | 39 + Source/DirectFB/systems/x11/surfacemanager.c | 559 ++++++++++++++ Source/DirectFB/systems/x11/surfacemanager.h | 110 +++ Source/DirectFB/systems/x11/vpsmem_surface_pool.c | 421 +++++++++++ Source/DirectFB/systems/x11/vpsmem_surface_pool.h | 37 + Source/DirectFB/systems/x11/x11.c | 570 ++++++++++++++ Source/DirectFB/systems/x11/x11.h | 116 +++ Source/DirectFB/systems/x11/x11_surface_pool.c | 369 +++++++++ Source/DirectFB/systems/x11/x11_surface_pool.h | 47 ++ .../DirectFB/systems/x11/x11_surface_pool_bridge.c | 331 ++++++++ .../DirectFB/systems/x11/x11_surface_pool_bridge.h | 37 + Source/DirectFB/systems/x11/x11image.c | 231 ++++++ Source/DirectFB/systems/x11/x11image.h | 76 ++ Source/DirectFB/systems/x11/x11input.c | 768 +++++++++++++++++++ Source/DirectFB/systems/x11/x11types.h | 35 + Source/DirectFB/systems/x11/xwindow.c | 294 ++++++++ Source/DirectFB/systems/x11/xwindow.h | 77 ++ 23 files changed, 6396 insertions(+) create mode 100755 Source/DirectFB/systems/x11/Makefile.am create mode 100755 Source/DirectFB/systems/x11/Makefile.in create mode 100755 Source/DirectFB/systems/x11/README create mode 100755 Source/DirectFB/systems/x11/glx_surface_pool.c create mode 100755 Source/DirectFB/systems/x11/glx_surface_pool.h create mode 100755 Source/DirectFB/systems/x11/primary.c create mode 100755 Source/DirectFB/systems/x11/primary.h create mode 100755 Source/DirectFB/systems/x11/surfacemanager.c create mode 100755 Source/DirectFB/systems/x11/surfacemanager.h create mode 100755 Source/DirectFB/systems/x11/vpsmem_surface_pool.c create mode 100755 Source/DirectFB/systems/x11/vpsmem_surface_pool.h create mode 100755 Source/DirectFB/systems/x11/x11.c create mode 100755 Source/DirectFB/systems/x11/x11.h create mode 100755 Source/DirectFB/systems/x11/x11_surface_pool.c create mode 100755 Source/DirectFB/systems/x11/x11_surface_pool.h create mode 100755 Source/DirectFB/systems/x11/x11_surface_pool_bridge.c create mode 100755 Source/DirectFB/systems/x11/x11_surface_pool_bridge.h create mode 100755 Source/DirectFB/systems/x11/x11image.c create mode 100755 Source/DirectFB/systems/x11/x11image.h create mode 100755 Source/DirectFB/systems/x11/x11input.c create mode 100755 Source/DirectFB/systems/x11/x11types.h create mode 100755 Source/DirectFB/systems/x11/xwindow.c create mode 100755 Source/DirectFB/systems/x11/xwindow.h (limited to 'Source/DirectFB/systems/x11') diff --git a/Source/DirectFB/systems/x11/Makefile.am b/Source/DirectFB/systems/x11/Makefile.am new file mode 100755 index 0000000..23c0b88 --- /dev/null +++ b/Source/DirectFB/systems/x11/Makefile.am @@ -0,0 +1,63 @@ +# Makefile.am for DirectFB/systems/x11 + +INCLUDES = \ + -I$(top_srcdir)/include \ + -I$(top_builddir)/include \ + -I$(top_builddir)/lib \ + -I$(top_srcdir)/lib \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/gfxdrivers \ + $(X11_CFLAGS) + + +systemsdir = $(MODULEDIR)/systems + +if BUILD_STATIC +systems_DATA = libdirectfb_x11.o +endif + +systems_LTLIBRARIES = libdirectfb_x11.la + +libdirectfb_x11_la_LDFLAGS = \ + $(X11_LIBS) \ + -avoid-version \ + -module + +if GFX_GLX +libdirectfb_x11_la_LDFLAGS += -lGL +endif + +libdirectfb_x11_la_SOURCES = \ + primary.c \ + primary.h \ + surfacemanager.c \ + surfacemanager.h \ + vpsmem_surface_pool.c \ + vpsmem_surface_pool.h \ + x11.c \ + x11.h \ + x11image.c \ + x11image.h \ + x11input.c \ + x11_surface_pool.c \ + x11_surface_pool.h \ + x11types.h \ + xwindow.h \ + xwindow.c + +if GFX_GLX +libdirectfb_x11_la_SOURCES += \ + glx_surface_pool.c \ + glx_surface_pool.h \ + x11_surface_pool_bridge.c \ + x11_surface_pool_bridge.h +endif + +libdirectfb_x11_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/x11/Makefile.in b/Source/DirectFB/systems/x11/Makefile.in new file mode 100755 index 0000000..e25aa5b --- /dev/null +++ b/Source/DirectFB/systems/x11/Makefile.in @@ -0,0 +1,624 @@ +# 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@ + +# Makefile.am for DirectFB/systems/x11 + + +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@ +@GFX_GLX_TRUE@am__append_1 = -lGL +@GFX_GLX_TRUE@am__append_2 = \ +@GFX_GLX_TRUE@ glx_surface_pool.c \ +@GFX_GLX_TRUE@ glx_surface_pool.h \ +@GFX_GLX_TRUE@ x11_surface_pool_bridge.c \ +@GFX_GLX_TRUE@ x11_surface_pool_bridge.h + +DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(top_srcdir)/rules/libobject.make +subdir = systems/x11 +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)" +systemsLTLIBRARIES_INSTALL = $(INSTALL) +LTLIBRARIES = $(systems_LTLIBRARIES) +libdirectfb_x11_la_DEPENDENCIES = \ + $(top_builddir)/lib/direct/libdirect.la \ + $(top_builddir)/lib/fusion/libfusion.la \ + $(top_builddir)/src/libdirectfb.la +am__libdirectfb_x11_la_SOURCES_DIST = primary.c primary.h \ + surfacemanager.c surfacemanager.h vpsmem_surface_pool.c \ + vpsmem_surface_pool.h x11.c x11.h x11image.c x11image.h \ + x11input.c x11_surface_pool.c x11_surface_pool.h x11types.h \ + xwindow.h xwindow.c glx_surface_pool.c glx_surface_pool.h \ + x11_surface_pool_bridge.c x11_surface_pool_bridge.h +@GFX_GLX_TRUE@am__objects_1 = glx_surface_pool.lo \ +@GFX_GLX_TRUE@ x11_surface_pool_bridge.lo +am_libdirectfb_x11_la_OBJECTS = primary.lo surfacemanager.lo \ + vpsmem_surface_pool.lo x11.lo x11image.lo x11input.lo \ + x11_surface_pool.lo xwindow.lo $(am__objects_1) +libdirectfb_x11_la_OBJECTS = $(am_libdirectfb_x11_la_OBJECTS) +libdirectfb_x11_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libdirectfb_x11_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_x11_la_SOURCES) +DIST_SOURCES = $(am__libdirectfb_x11_la_SOURCES_DIST) +systemsDATA_INSTALL = $(INSTALL_DATA) +DATA = $(systems_DATA) +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 \ + -I$(top_srcdir)/gfxdrivers \ + $(X11_CFLAGS) + +systemsdir = $(MODULEDIR)/systems +@BUILD_STATIC_TRUE@systems_DATA = libdirectfb_x11.o +systems_LTLIBRARIES = libdirectfb_x11.la +libdirectfb_x11_la_LDFLAGS = $(X11_LIBS) -avoid-version -module \ + $(am__append_1) +libdirectfb_x11_la_SOURCES = primary.c primary.h surfacemanager.c \ + surfacemanager.h vpsmem_surface_pool.c vpsmem_surface_pool.h \ + x11.c x11.h x11image.c x11image.h x11input.c \ + x11_surface_pool.c x11_surface_pool.h x11types.h xwindow.h \ + xwindow.c $(am__append_2) +libdirectfb_x11_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/x11/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu systems/x11/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_x11.la: $(libdirectfb_x11_la_OBJECTS) $(libdirectfb_x11_la_DEPENDENCIES) + $(libdirectfb_x11_la_LINK) -rpath $(systemsdir) $(libdirectfb_x11_la_OBJECTS) $(libdirectfb_x11_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/glx_surface_pool.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/primary.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/surfacemanager.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vpsmem_surface_pool.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/x11.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/x11_surface_pool.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/x11_surface_pool_bridge.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/x11image.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/x11input.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xwindow.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 + +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) +installdirs: + for dir in "$(DESTDIR)$(systemsdir)" "$(DESTDIR)$(systemsdir)"; 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-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-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-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-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/x11/README b/Source/DirectFB/systems/x11/README new file mode 100755 index 0000000..7258175 --- /dev/null +++ b/Source/DirectFB/systems/x11/README @@ -0,0 +1,11 @@ +This is an X11 system in very early stages, it is not really usable yet. +Tested with RGB16, ARGB1555 and ARGB mode. + +BUGS +- occasional segfault during startup +- does not work with multi-application core + +TODO +- support for RGB32 +- test RGB24, RGB332, and palette mode +- code cleanup diff --git a/Source/DirectFB/systems/x11/glx_surface_pool.c b/Source/DirectFB/systems/x11/glx_surface_pool.c new file mode 100755 index 0000000..98b909d --- /dev/null +++ b/Source/DirectFB/systems/x11/glx_surface_pool.c @@ -0,0 +1,838 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +//#define DIRECT_ENABLE_DEBUG + +#include + +#include + +#include +#include +#include + +#include + +#include + +#include +#include + +#include "x11.h" + +#include "glx_surface_pool.h" +#include "x11_surface_pool.h" + +D_DEBUG_DOMAIN( GLX_Surfaces, "GLX/Surfaces", "GLX Surface Pool" ); +D_DEBUG_DOMAIN( GLX_Pixmaps, "GLX/Pixmaps", "GLX Surface Pool Pixmaps" ); + +/**********************************************************************************************************************/ + +typedef void (*GLXBindTexImageEXTProc) ( Display *dpy, GLXDrawable drawable, int buffer, const int *attrib_list ); +typedef void (*GLXReleaseTexImageEXTProc)( Display *dpy, GLXDrawable drawable, int buffer ); + +typedef struct { + int magic; + + Display *display; + + GLXFBConfig *configs; + int num_configs; + + GLXFBConfig config24; + Visual *visual24; + + GLXFBConfig config32; + Visual *visual32; + + GLXBindTexImageEXTProc BindTexImageEXT; + GLXReleaseTexImageEXTProc ReleaseTexImageEXT; + + DirectHash *pixmaps; + + /* Every thread needs its own context! */ + pthread_key_t context_key; + pthread_key_t context_key2; +} glxPoolLocalData; + +typedef struct { +} glxPoolData; + +/**********************************************************************************************************************/ + +static void +destroy_context( void *arg ) +{ + ThreadContext *ctx = arg; + + XLockDisplay( ctx->display ); + + glXDestroyContext( ctx->display, ctx->context ); + + XUnlockDisplay( ctx->display ); + + D_FREE( ctx ); +} + +/**********************************************************************************************************************/ + +static DFBResult +InitLocal( glxPoolLocalData *local, + DFBX11 *x11 ) +{ + DFBResult ret; + + int i; + int attribs[] = { + GLX_DOUBLEBUFFER, + False, + + GLX_DRAWABLE_TYPE, + GLX_PIXMAP_BIT, + + GLX_X_RENDERABLE, + True, + + GLX_RED_SIZE, + 8, + + GLX_GREEN_SIZE, + 8, + + GLX_BLUE_SIZE, + 8, + + GLX_ALPHA_SIZE, + 8, + + GLX_DEPTH_SIZE, + 8, + + GLX_X_VISUAL_TYPE, + GLX_TRUE_COLOR, + + None + }; + + + local->display = x11->display; + + local->BindTexImageEXT = (GLXBindTexImageEXTProc) glXGetProcAddress( (unsigned char*) "glXBindTexImageEXT" ); + if (!local->BindTexImageEXT) { + D_ERROR( "glXGetProcAddress( 'glXBindTexImageEXT' ) failed!\n" ); + return DFB_UNSUPPORTED; + } + + local->ReleaseTexImageEXT = (GLXReleaseTexImageEXTProc) glXGetProcAddress( (unsigned char*) "glXReleaseTexImageEXT" ); + if (!local->ReleaseTexImageEXT) { + D_ERROR( "glXGetProcAddress( 'glXReleaseTexImageEXT' ) failed!\n" ); + return DFB_UNSUPPORTED; + } + + + ret = direct_hash_create( 7, &local->pixmaps ); + if (ret) + return ret; + + + XLockDisplay( local->display ); + + + local->configs = glXChooseFBConfig( local->display, DefaultScreen(local->display), attribs, &local->num_configs ); + + D_DEBUG_AT( GLX_Surfaces, " -> found %d configs\n", local->num_configs ); + + for (i=0; inum_configs; i++) { + int depth; + XVisualInfo *info = glXGetVisualFromFBConfig( local->display, local->configs[i] ); + + glXGetFBConfigAttrib( local->display, local->configs[i], GLX_DEPTH_SIZE, &depth ); + + D_DEBUG_AT( GLX_Surfaces, " [%2d] ID 0x%02lx, depth %d, RGB 0x%06lx/0x%06lx/0x%06lx {%d}, class %d, z %d\n", + i, info->visualid, info->depth, + info->red_mask, info->green_mask, info->blue_mask, + info->bits_per_rgb, info->class, depth ); + + if (depth >= 8 && info->class == TrueColor) { + switch (info->depth) { + case 32: + local->config32 = local->configs[i]; + local->visual32 = info->visual; + break; + + case 24: + local->config24 = local->configs[i]; + local->visual24 = info->visual; + break; + } + } + } + + if (!local->config24 || !local->config32) { + D_ERROR( "GLX/Surfaces: Could not find useful visuals!\n" ); + direct_hash_destroy( local->pixmaps ); + XUnlockDisplay( local->display ); + return DFB_UNSUPPORTED; + } + + XVisualInfo *info24 = glXGetVisualFromFBConfig( local->display, local->config24 ); + XVisualInfo *info32 = glXGetVisualFromFBConfig( local->display, local->config32 ); + + D_INFO( "GLX/Surfaces: Using visual 0x%02lx (24bit) and 0x%02lx (32bit)\n", info24->visualid, info32->visualid ); + + XUnlockDisplay( local->display ); + + + pthread_key_create( &local->context_key, destroy_context ); + pthread_key_create( &local->context_key2, destroy_context ); + + D_MAGIC_SET( local, glxPoolLocalData ); + + return DFB_OK; +} + +static DFBResult +GetLocalPixmap( glxPoolLocalData *local, + glxAllocationData *alloc, + CoreSurfaceAllocation *allocation, + LocalPixmap **ret_pixmap ) +{ + LocalPixmap *pixmap; + CoreSurface *surface; + CoreSurfaceBuffer *buffer; + + surface = allocation->surface; + D_MAGIC_ASSERT( surface, CoreSurface ); + + buffer = allocation->buffer; + D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); + + pixmap = direct_hash_lookup( local->pixmaps, alloc->pixmap ); + if (!pixmap) { + pixmap = D_CALLOC( 1, sizeof(LocalPixmap) ); + if (!pixmap) + return D_OOM(); + + pixmap->pixmap = alloc->pixmap; + pixmap->config = (alloc->depth == 24) ? local->config24 : local->config32; + + /* + * Create a GLXPixmap + */ + int attribs[] = { + GLX_TEXTURE_FORMAT_EXT, (alloc->depth == 24) ? GLX_TEXTURE_FORMAT_RGB_EXT : GLX_TEXTURE_FORMAT_RGBA_EXT, + GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_RECTANGLE_EXT, + None + }; + + + XLockDisplay( local->display ); + + pixmap->drawable = glXCreatePixmap( local->display, pixmap->config, alloc->pixmap, attribs ); + if (!pixmap->drawable) { + D_ERROR( "GLX/Surfaces: Could not create %dx%d (depth %d) GLXPixmap!\n", + surface->config.size.w, surface->config.size.h, alloc->depth ); + XUnlockDisplay( local->display ); + D_FREE( pixmap ); + return DFB_FAILURE; + } + + D_DEBUG_AT( GLX_Surfaces, " -> drawable 0x%lx\n", pixmap->drawable ); + + /* + * Create a GC (for writing to pixmap) + */ + pixmap->gc = XCreateGC( local->display, alloc->pixmap, 0, NULL ); + + D_DEBUG_AT( GLX_Surfaces, " -> gc 0x%lx\n", pixmap->drawable ); + + XUnlockDisplay( local->display ); + + + /* + * Create a texture object + */ + glGenTextures( 1, &pixmap->buffer.texture ); + + + D_DEBUG_AT( GLX_Pixmaps, " NEW GLXPixmap 0x%lx for 0x%lx [%4dx%4d] %-10s\n", pixmap->drawable, alloc->pixmap, + surface->config.size.w, surface->config.size.h, dfb_pixelformat_name(buffer->format) ); + D_DEBUG_AT( GLX_Surfaces, " -> GLXPixmap 0x%lx [%4dx%4d] %-10s (%u)\n", pixmap->drawable, + surface->config.size.w, surface->config.size.h, dfb_pixelformat_name(buffer->format), + pixmap->buffer.texture ); + + D_MAGIC_SET( pixmap, LocalPixmap ); + D_MAGIC_SET( &pixmap->buffer, GLBufferData ); + + direct_hash_insert( local->pixmaps, alloc->pixmap, pixmap ); + } + else + D_MAGIC_ASSERT( pixmap, LocalPixmap ); + + *ret_pixmap = pixmap; + + return DFB_OK; +} + +static void +ReleasePixmap( glxPoolLocalData *local, + LocalPixmap *pixmap ) +{ + D_MAGIC_ASSERT( local, glxPoolLocalData ); + D_MAGIC_ASSERT( pixmap, LocalPixmap ); + + if (pixmap->bound) { + D_DEBUG_AT( GLX_Pixmaps, " RELEASE 0x%08lx from %p\n", pixmap->drawable, pixmap->bound ); + + local->ReleaseTexImageEXT( local->display, pixmap->drawable, GLX_FRONT_EXT ); + + pixmap->bound = NULL; + } +} + +static void +DestroyPixmap( glxPoolLocalData *local, + LocalPixmap *pixmap ) +{ + D_MAGIC_ASSERT( local, glxPoolLocalData ); + D_MAGIC_ASSERT( pixmap, LocalPixmap ); + + D_DEBUG_AT( GLX_Pixmaps, " DESTROY 0x%08lx (%d)\n", pixmap->drawable, pixmap->buffer.texture ); + + glXWaitGL(); + + ReleasePixmap( local, pixmap ); + + glXWaitX(); + + glDeleteTextures( 1, &pixmap->buffer.texture ); + + XFreeGC( local->display, pixmap->gc ); + + glXDestroyPixmap( local->display, pixmap->drawable ); + + direct_hash_remove( local->pixmaps, pixmap->pixmap ); + + D_MAGIC_CLEAR( pixmap ); + D_MAGIC_CLEAR( &pixmap->buffer ); + + D_FREE( pixmap ); +} + +/**********************************************************************************************************************/ + +static int +glxPoolDataSize( void ) +{ + return sizeof(glxPoolData); +} + +static int +glxPoolLocalDataSize( void ) +{ + return sizeof(glxPoolLocalData); +} + +static int +glxAllocationDataSize( void ) +{ + return sizeof(glxAllocationData); +} + +static DFBResult +glxInitPool( CoreDFB *core, + CoreSurfacePool *pool, + void *pool_data, + void *pool_local, + void *system_data, + CoreSurfacePoolDescription *ret_desc ) +{ + glxPoolLocalData *local = pool_local; + DFBX11 *x11 = system_data; + + D_DEBUG_AT( GLX_Surfaces, "%s()\n", __FUNCTION__ ); + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + D_ASSERT( ret_desc != NULL ); + + ret_desc->caps = CSPCAPS_NONE; + ret_desc->access[CSAID_GPU] = CSAF_READ | CSAF_WRITE; + ret_desc->types = CSTF_LAYER | CSTF_WINDOW | CSTF_CURSOR | CSTF_FONT | CSTF_SHARED | CSTF_EXTERNAL; + ret_desc->priority = CSPP_DEFAULT; + + /* For showing our X11 window */ + ret_desc->access[CSAID_LAYER0] = CSAF_READ; + + /* For user contexts via DirectFBGL */ + ret_desc->access[CSAID_ACCEL1] = CSAF_READ | CSAF_WRITE; + + snprintf( ret_desc->name, DFB_SURFACE_POOL_DESC_NAME_LENGTH, "GLX Drawables" ); + + + return InitLocal( local, x11 ); +} + +static DFBResult +glxJoinPool( CoreDFB *core, + CoreSurfacePool *pool, + void *pool_data, + void *pool_local, + void *system_data ) +{ + glxPoolLocalData *local = pool_local; + DFBX11 *x11 = system_data; + + D_DEBUG_AT( GLX_Surfaces, "%s()\n", __FUNCTION__ ); + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + + + return InitLocal( local, x11 ); +} + +static DFBResult +glxDestroyPool( CoreSurfacePool *pool, + void *pool_data, + void *pool_local ) +{ + D_DEBUG_AT( GLX_Surfaces, "%s()\n", __FUNCTION__ ); + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + + return DFB_OK; +} + +static DFBResult +glxLeavePool( CoreSurfacePool *pool, + void *pool_data, + void *pool_local ) +{ + D_DEBUG_AT( GLX_Surfaces, "%s()\n", __FUNCTION__ ); + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + + return DFB_OK; +} + +static DFBResult +glxTestConfig( CoreSurfacePool *pool, + void *pool_data, + void *pool_local, + CoreSurfaceBuffer *buffer, + const CoreSurfaceConfig *config ) +{ + glxPoolLocalData *local = pool_local; + + D_MAGIC_ASSERT( local, glxPoolLocalData ); + + if (!local->configs) + return DFB_UNSUPPORTED; + + return DFB_OK; +} + +static DFBResult +glxAllocateBuffer( CoreSurfacePool *pool, + void *pool_data, + void *pool_local, + CoreSurfaceBuffer *buffer, + CoreSurfaceAllocation *allocation, + void *alloc_data ) +{ + CoreSurface *surface; + glxPoolLocalData *local = pool_local; + glxAllocationData *alloc = alloc_data; + + D_DEBUG_AT( GLX_Surfaces, "%s()\n", __FUNCTION__ ); + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + D_MAGIC_ASSERT( local, glxPoolLocalData ); + D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); + + surface = buffer->surface; + D_MAGIC_ASSERT( surface, CoreSurface ); + + XLockDisplay( local->display ); + + alloc->depth = DFB_COLOR_BITS_PER_PIXEL( buffer->format ) + DFB_ALPHA_BITS_PER_PIXEL( buffer->format ); + + /* + * Create a pixmap + */ + alloc->pixmap = XCreatePixmap( local->display, DefaultRootWindow( local->display ), + surface->config.size.w, surface->config.size.h, alloc->depth ); + if (!alloc->pixmap) { + D_ERROR( "GLX/Surfaces: Could not create %dx%d (depth %d) pixmap!\n", + surface->config.size.w, surface->config.size.h, alloc->depth ); + + XUnlockDisplay( local->display ); + + return DFB_FAILURE; + } + + D_DEBUG_AT( GLX_Surfaces, " -> pixmap 0x%lx\n", alloc->pixmap ); + + D_DEBUG_AT( GLX_Pixmaps, " NEW Pixmap 0x%lx [%4dx%4d] %-10s\n", alloc->pixmap, + surface->config.size.w, surface->config.size.h, dfb_pixelformat_name(buffer->format) ); + + XUnlockDisplay( local->display ); + + + /* Pseudo calculation */ + dfb_surface_calc_buffer_size( surface, 8, 2, NULL, &allocation->size ); + + D_MAGIC_SET( alloc, glxAllocationData ); + + return DFB_OK; +} + +static DFBResult +glxDeallocateBuffer( CoreSurfacePool *pool, + void *pool_data, + void *pool_local, + CoreSurfaceBuffer *buffer, + CoreSurfaceAllocation *allocation, + void *alloc_data ) +{ + LocalPixmap *pixmap; + glxPoolLocalData *local = pool_local; + glxAllocationData *alloc = alloc_data; + + D_DEBUG_AT( GLX_Surfaces, "%s()\n", __FUNCTION__ ); + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + D_MAGIC_ASSERT( local, glxPoolLocalData ); + D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); + D_MAGIC_ASSERT( alloc, glxAllocationData ); + + CORE_SURFACE_ALLOCATION_ASSERT( allocation ); + + XLockDisplay( local->display ); + + pixmap = direct_hash_lookup( local->pixmaps, alloc->pixmap ); + if (pixmap) + DestroyPixmap( local, pixmap ); + + XFreePixmap( local->display, alloc->pixmap ); + + XUnlockDisplay( local->display ); + + D_MAGIC_CLEAR( alloc ); + + return DFB_OK; +} + +static DFBResult +glxLock( CoreSurfacePool *pool, + void *pool_data, + void *pool_local, + CoreSurfaceAllocation *allocation, + void *alloc_data, + CoreSurfaceBufferLock *lock ) +{ + DFBResult ret; + LocalPixmap *pixmap; + glxPoolLocalData *local = pool_local; + glxAllocationData *alloc = alloc_data; + + D_DEBUG_AT( GLX_Surfaces, "%s( %p )\n", __FUNCTION__, allocation ); + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + D_MAGIC_ASSERT( local, glxPoolLocalData ); + D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation ); + D_MAGIC_ASSERT( alloc, glxAllocationData ); + D_MAGIC_ASSERT( lock, CoreSurfaceBufferLock ); + + ret = GetLocalPixmap( local, alloc, allocation, &pixmap ); + if (ret) + return ret; + + if (lock->accessor == CSAID_GPU || lock->accessor == CSAID_ACCEL1) { + ThreadContext *ctx; + + ctx = pthread_getspecific( (lock->accessor == CSAID_GPU) ? local->context_key : local->context_key2 ); + if (!ctx) { + ctx = D_CALLOC( 1, sizeof(ThreadContext) ); + if (!ctx) + return D_OOM(); + + ctx->display = local->display; + + XLockDisplay( local->display ); + + ctx->context = glXCreateNewContext( local->display, pixmap->config, GLX_RGBA_TYPE, NULL, GL_TRUE ); + if (!ctx->context) { + D_ERROR( "GLX: Could not create GLXContext!\n" ); + XUnlockDisplay( local->display ); + D_FREE( ctx ); + return DFB_FAILURE; + } + + XUnlockDisplay( local->display ); + + pthread_setspecific( (lock->accessor == CSAID_GPU) ? local->context_key : local->context_key2, ctx ); + + D_DEBUG_AT( GLX_Surfaces, " -> NEW CONTEXT %p\n", ctx->context ); + } + + if (lock->access & CSAF_WRITE) { + if (ctx->context != glXGetCurrentContext() || ctx->drawable != pixmap->drawable) { + D_DEBUG_AT( GLX_Surfaces, " -> MAKE CURRENT 0x%08lx <- 0x%08lx\n", pixmap->drawable, glXGetCurrentDrawable() ); + + if (ctx->drawable != pixmap->drawable) { + ctx->drawable = pixmap->drawable; + + pixmap->buffer.flags |= GLBF_UPDATE_TARGET; + } + + XLockDisplay( local->display ); + + glXMakeContextCurrent( local->display, pixmap->drawable, pixmap->drawable, ctx->context ); + pixmap->current = ctx->context; + + ReleasePixmap( local, pixmap ); + + XUnlockDisplay( local->display ); + } + } + else { + if (pixmap->bound != ctx->context) { + D_DEBUG_AT( GLX_Surfaces, " -> BIND TEXTURE 0x%08lx (%d)\n", pixmap->drawable, pixmap->buffer.texture ); + + XLockDisplay( local->display ); + + ReleasePixmap( local, pixmap ); + + glEnable( GL_TEXTURE_RECTANGLE_ARB ); + glBindTexture( GL_TEXTURE_RECTANGLE_ARB, pixmap->buffer.texture ); + + local->BindTexImageEXT( local->display, pixmap->drawable, GLX_FRONT_EXT, NULL ); + pixmap->bound = ctx->context; + + XUnlockDisplay( local->display ); + + pixmap->buffer.flags |= GLBF_UPDATE_TEXTURE; + } + } + + lock->handle = &pixmap->buffer; + } + else + lock->handle = pixmap; + + return DFB_OK; +} + +static DFBResult +glxUnlock( CoreSurfacePool *pool, + void *pool_data, + void *pool_local, + CoreSurfaceAllocation *allocation, + void *alloc_data, + CoreSurfaceBufferLock *lock ) +{ +#if 0 + DFBResult ret; + LocalPixmap *pixmap; + glxPoolLocalData *local = pool_local; + glxAllocationData *alloc = alloc_data; + + D_DEBUG_AT( GLX_Surfaces, "%s( %p )\n", __FUNCTION__, allocation ); + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + D_MAGIC_ASSERT( local, glxPoolLocalData ); + D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation ); + D_MAGIC_ASSERT( alloc, glxAllocationData ); + D_MAGIC_ASSERT( lock, CoreSurfaceBufferLock ); + + ret = GetLocalPixmap( local, alloc, allocation, &pixmap ); + if (ret) + return ret; + + if (lock->accessor == CSAID_GPU) { + XLockDisplay( local->display ); + + if (lock->access & CSAF_WRITE) { +// D_DEBUG_AT( GLX_Surfaces, " -> UNMAKE CURRENT 0x%08lx <- 0x%08lx\n", pixmap->drawable, glXGetCurrentDrawable() ); + +// glXMakeContextCurrent( local->display, None, None, NULL ); +// pixmap->current = NULL; + } + else { + D_DEBUG_AT( GLX_Surfaces, " -> UNBIND TEXTURE 0x%08lx (%d)\n", pixmap->drawable, pixmap->buffer.texture ); + + ReleasePixmap( local, pixmap ); + } + + XUnlockDisplay( local->display ); + } + +#endif + return DFB_OK; +} + +static DFBResult +glxRead( CoreSurfacePool *pool, + void *pool_data, + void *pool_local, + CoreSurfaceAllocation *allocation, + void *alloc_data, + void *destination, + int pitch, + const DFBRectangle *rect ) +{ + XImage *image; + XImage *sub; + glxPoolLocalData *local = pool_local; + glxAllocationData *alloc = alloc_data; + + D_DEBUG_AT( GLX_Surfaces, "%s( %p )\n", __FUNCTION__, allocation ); + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + D_MAGIC_ASSERT( local, glxPoolLocalData ); + D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation ); + D_MAGIC_ASSERT( alloc, glxAllocationData ); + D_ASSERT( destination != NULL ); + D_ASSERT( pitch >= 0 ); + DFB_RECTANGLE_ASSERT( rect ); + + D_DEBUG_AT( GLX_Surfaces, " => %p 0x%08lx [%4d,%4d-%4dx%4d]\n", alloc, alloc->pixmap, DFB_RECTANGLE_VALS(rect) ); + + XLockDisplay( local->display ); + + image = XCreateImage( local->display, (alloc->depth == 24) ? local->visual24 : local->visual32, + alloc->depth, ZPixmap, 0, destination, rect->w, rect->h, 32, pitch ); + if (!image) { + D_ERROR( "GLX/Surfaces: XCreateImage( %dx%d, depth %d ) failed!\n", rect->w, rect->h, alloc->depth ); + XUnlockDisplay( local->display ); + return DFB_FAILURE; + } + + glXWaitGL(); + + sub = XGetSubImage( local->display, alloc->pixmap, rect->x, rect->y, rect->w, rect->h, ~0, ZPixmap, image, 0, 0 ); + + glXWaitX(); + + /* FIXME: Why the X-hell is XDestroyImage() freeing *MY* data? */ + image->data = NULL; + XDestroyImage( image ); + + XUnlockDisplay( local->display ); + + if (!sub) { + D_ERROR( "GLX/Surfaces: XGetSubImage( %d,%d-%dx%d ) failed!\n", DFB_RECTANGLE_VALS(rect) ); + return DFB_FAILURE; + } + + return DFB_OK; +} + +static DFBResult +glxWrite( CoreSurfacePool *pool, + void *pool_data, + void *pool_local, + CoreSurfaceAllocation *allocation, + void *alloc_data, + const void *source, + int pitch, + const DFBRectangle *rect ) +{ + DFBResult ret; + LocalPixmap *pixmap; + CoreSurface *surface; + XImage *image; + glxPoolLocalData *local = pool_local; + glxAllocationData *alloc = alloc_data; + + D_DEBUG_AT( GLX_Surfaces, "%s( %p )\n", __FUNCTION__, allocation ); + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + D_MAGIC_ASSERT( local, glxPoolLocalData ); + D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation ); + D_MAGIC_ASSERT( alloc, glxAllocationData ); + D_ASSERT( source != NULL ); + D_ASSERT( pitch >= 0 ); + DFB_RECTANGLE_ASSERT( rect ); + + D_DEBUG_AT( GLX_Surfaces, " <= %p 0x%08lx [%4d,%4d-%4dx%4d]\n", alloc, alloc->pixmap, DFB_RECTANGLE_VALS(rect) ); + + surface = allocation->surface; + D_MAGIC_ASSERT( surface, CoreSurface ); + + ret = GetLocalPixmap( local, alloc, allocation, &pixmap ); + if (ret) + return ret; + + XLockDisplay( local->display ); + + image = XCreateImage( local->display, (alloc->depth == 24) ? local->visual24 : local->visual32, + alloc->depth, ZPixmap, 0, (void*) source, rect->w, rect->h, 32, pitch ); + if (!image) { + D_ERROR( "GLX/Surfaces: XCreateImage( %dx%d, depth %d ) failed!\n", rect->w, rect->h, alloc->depth ); + XUnlockDisplay( local->display ); + return DFB_FAILURE; + } + + glXWaitGL(); + + XPutImage( local->display, alloc->pixmap, pixmap->gc, image, 0, 0, rect->x, rect->y, rect->w, rect->h ); + + glXWaitX(); + + /* FIXME: Why the X-hell is XDestroyImage() freeing *MY* data? */ + image->data = NULL; + XDestroyImage( image ); + + XUnlockDisplay( local->display ); + + return DFB_OK; +} + +const SurfacePoolFuncs glxSurfacePoolFuncs = { + .PoolDataSize = glxPoolDataSize, + .PoolLocalDataSize = glxPoolLocalDataSize, + .AllocationDataSize = glxAllocationDataSize, + + .InitPool = glxInitPool, + .JoinPool = glxJoinPool, + .DestroyPool = glxDestroyPool, + .LeavePool = glxLeavePool, + + .TestConfig = glxTestConfig, + + .AllocateBuffer = glxAllocateBuffer, + .DeallocateBuffer = glxDeallocateBuffer, + + .Lock = glxLock, + .Unlock = glxUnlock, + + .Read = glxRead, + .Write = glxWrite, +}; + diff --git a/Source/DirectFB/systems/x11/glx_surface_pool.h b/Source/DirectFB/systems/x11/glx_surface_pool.h new file mode 100755 index 0000000..d244526 --- /dev/null +++ b/Source/DirectFB/systems/x11/glx_surface_pool.h @@ -0,0 +1,79 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __X11SYSTEM__GLX_SURFACE_POOL_H__ +#define __X11SYSTEM__GLX_SURFACE_POOL_H__ + + +#include + +#include + +#include + +extern const SurfacePoolFuncs glxSurfacePoolFuncs; + + +typedef struct { + int magic; + + /* Shared resource */ + Pixmap pixmap; + int depth; +} glxAllocationData; + +typedef struct { + int magic; + + GLBufferData buffer; + + /* Shared resource */ + Pixmap pixmap; + + /* Process local data */ + GC gc; + + GLXFBConfig config; + GLXDrawable drawable; + + /* Bound to a thread's context? */ + GLXContext current; + GLXContext bound; +} LocalPixmap; + +typedef struct { + Display *display; + + /* Thread local data */ + GLXContext context; + + GLXDrawable drawable; +} ThreadContext; + +#endif + diff --git a/Source/DirectFB/systems/x11/primary.c b/Source/DirectFB/systems/x11/primary.c new file mode 100755 index 0000000..2e12d8a --- /dev/null +++ b/Source/DirectFB/systems/x11/primary.c @@ -0,0 +1,664 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +//#define DIRECT_ENABLE_DEBUG + +#include + +#include + +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include + +#include +#include + +#ifdef USE_GLX +#include +#include "glx_surface_pool.h" +#endif + +#include "xwindow.h" +#include "x11.h" +#include "primary.h" + + +D_DEBUG_DOMAIN( X11_Layer, "X11/Layer", "X11 Layer" ); +D_DEBUG_DOMAIN( X11_Update, "X11/Update", "X11 Update" ); + +/**********************************************************************************************************************/ + +static DFBResult +dfb_x11_create_window( DFBX11 *x11, const CoreLayerRegionConfig *config ) +{ + int ret; + DFBX11Shared *shared = x11->shared; + + D_ASSERT( config != NULL ); + + shared->setmode.config = *config; + + if (fusion_call_execute( &shared->call, FCEF_NONE, X11_CREATE_WINDOW, &shared->setmode, &ret )) + return DFB_FUSION; + + return ret; +} + +static DFBResult +dfb_x11_destroy_window( DFBX11 *x11 ) +{ + int ret; + DFBX11Shared *shared = x11->shared; + + if (fusion_call_execute( &shared->call, FCEF_NONE, X11_DESTROY_WINDOW, NULL, &ret )) + return DFB_FUSION; + + return ret; +} + +static DFBResult +dfb_x11_update_screen( DFBX11 *x11, const DFBRegion *region, CoreSurfaceBufferLock *lock ) +{ + int ret; + DFBX11Shared *shared = x11->shared; + + DFB_REGION_ASSERT( region ); + D_ASSERT( lock != NULL ); + + /* FIXME: Just a hot fix! */ + while (shared->update.lock) + usleep( 10000 ); + + shared->update.region = *region; + shared->update.lock = lock; + + if (fusion_call_execute( &shared->call, FCEF_NODIRECT, X11_UPDATE_SCREEN, &shared->update, &ret )) + return DFB_FUSION; + + return ret; +} + +static DFBResult +dfb_x11_set_palette( DFBX11 *x11, CorePalette *palette ) +{ + int ret; + DFBX11Shared *shared = x11->shared; + + D_ASSERT( palette != NULL ); + + if (fusion_call_execute( &shared->call, FCEF_NONE, X11_SET_PALETTE, palette, &ret )) + return DFB_FUSION; + + return ret; +} + +/**********************************************************************************************************************/ + +static DFBResult +primaryInitScreen( CoreScreen *screen, + CoreGraphicsDevice *device, + void *driver_data, + void *screen_data, + DFBScreenDescription *description ) +{ + D_DEBUG_AT( X11_Layer, "%s()\n", __FUNCTION__ ); + + /* Set the screen capabilities. */ + description->caps = DSCCAPS_NONE; + + /* Set the screen name. */ + snprintf( description->name, + DFB_SCREEN_DESC_NAME_LENGTH, "X11 Primary Screen" ); + + return DFB_OK; +} + +static DFBResult +primaryGetScreenSize( CoreScreen *screen, + void *driver_data, + void *screen_data, + int *ret_width, + int *ret_height ) +{ + DFBX11 *x11 = driver_data; + DFBX11Shared *shared = x11->shared; + + D_DEBUG_AT( X11_Layer, "%s()\n", __FUNCTION__ ); + + *ret_width = shared->screen_size.w; + *ret_height = shared->screen_size.h; + + return DFB_OK; +} + +ScreenFuncs x11PrimaryScreenFuncs = { + .InitScreen = primaryInitScreen, + .GetScreenSize = primaryGetScreenSize, +}; + +/******************************************************************************/ + +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 ) +{ + DFBX11 *x11 = driver_data; + DFBX11Shared *shared = x11->shared; + + D_DEBUG_AT( X11_Layer, "%s()\n", __FUNCTION__ ); + + /* set capabilities and type */ + description->caps = DLCAPS_SURFACE; + description->type = DLTF_GRAPHICS; + + /* set name */ + snprintf( description->name, + DFB_DISPLAY_LAYER_DESC_NAME_LENGTH, "X11 Primary Layer" ); + + /* fill out the default configuration */ + config->flags = DLCONF_WIDTH | DLCONF_HEIGHT | + DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE; + config->buffermode = DLBM_FRONTONLY; + + if (dfb_config->mode.width) + config->width = dfb_config->mode.width; + else + config->width = shared->screen_size.w; + + if (dfb_config->mode.height) + config->height = dfb_config->mode.height; + else + config->height = shared->screen_size.h; + + if (dfb_config->mode.format != DSPF_UNKNOWN) + config->pixelformat = dfb_config->mode.format; + else if (dfb_config->mode.depth > 0) + config->pixelformat = dfb_pixelformat_for_depth( dfb_config->mode.depth ); + else { + int depth = DefaultDepthOfScreen( x11->screenptr ); + + switch (depth) { + case 15: + config->pixelformat = DSPF_RGB555; + break; + case 16: + config->pixelformat = DSPF_RGB16; + break; + case 24: + config->pixelformat = DSPF_RGB32; + break; + case 32: + config->pixelformat = DSPF_ARGB; + break; + default: + printf(" Unsupported X11 screen depth %d \n",depth); + return DFB_UNSUPPORTED; + } + } + + return DFB_OK; +} + +static DFBResult +primaryTestRegion( CoreLayer *layer, + void *driver_data, + void *layer_data, + CoreLayerRegionConfig *config, + CoreLayerRegionConfigFlags *failed ) +{ + CoreLayerRegionConfigFlags fail = 0; + + D_DEBUG_AT( X11_Layer, "%s()\n", __FUNCTION__ ); + + switch (config->buffermode) { + case DLBM_FRONTONLY: + case DLBM_BACKSYSTEM: + case DLBM_BACKVIDEO: + case DLBM_TRIPLE: + break; + + default: + fail |= CLRCF_BUFFERMODE; + break; + } + + switch (config->format) { + case DSPF_RGB16: + case DSPF_NV16: + case DSPF_RGB444: + case DSPF_ARGB4444: + case DSPF_RGBA4444: + case DSPF_RGB555: + case DSPF_ARGB1555: + case DSPF_BGR555: + case DSPF_RGB24: + case DSPF_RGB32: + case DSPF_ARGB: + case DSPF_AYUV: + break; + + default: + fail |= CLRCF_FORMAT; + break; + } + + if (config->options) + fail |= CLRCF_OPTIONS; + + 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; + DFBX11 *x11 = driver_data; + + D_DEBUG_AT( X11_Layer, "%s()\n", __FUNCTION__ ); + + ret = dfb_x11_create_window( x11, config ); + if (ret) + return ret; + + if (palette) + dfb_x11_set_palette( x11, palette ); + + return DFB_OK; +} + +static DFBResult +primaryRemoveRegion( CoreLayer *layer, + void *driver_data, + void *layer_data, + void *region_data ) +{ + DFBX11 *x11 = driver_data; + + D_DEBUG_AT( X11_Layer, "%s()\n", __FUNCTION__ ); + + dfb_x11_destroy_window( x11 ); + + return DFB_OK; +} + +static DFBResult +primaryFlipRegion( CoreLayer *layer, + void *driver_data, + void *layer_data, + void *region_data, + CoreSurface *surface, + DFBSurfaceFlipFlags flags, + CoreSurfaceBufferLock *lock ) +{ + DFBX11 *x11 = driver_data; + DFBRegion region = DFB_REGION_INIT_FROM_DIMENSION( &surface->config.size ); + + D_DEBUG_AT( X11_Layer, "%s()\n", __FUNCTION__ ); + + dfb_surface_flip( surface, false ); + + return dfb_x11_update_screen( x11, ®ion, lock ); +} + +static DFBResult +primaryUpdateRegion( CoreLayer *layer, + void *driver_data, + void *layer_data, + void *region_data, + CoreSurface *surface, + const DFBRegion *update, + CoreSurfaceBufferLock *lock ) +{ + DFBX11 *x11 = driver_data; + DFBRegion region = DFB_REGION_INIT_FROM_DIMENSION( &surface->config.size ); + + D_DEBUG_AT( X11_Layer, "%s()\n", __FUNCTION__ ); + + if (update && !dfb_region_region_intersect( ®ion, update )) + return DFB_OK; + + return dfb_x11_update_screen( x11, ®ion, lock ); +} + +DisplayLayerFuncs x11PrimaryLayerFuncs = { + .LayerDataSize = primaryLayerDataSize, + .RegionDataSize = primaryRegionDataSize, + .InitLayer = primaryInitLayer, + + .TestRegion = primaryTestRegion, + .AddRegion = primaryAddRegion, + .SetRegion = primarySetRegion, + .RemoveRegion = primaryRemoveRegion, + .FlipRegion = primaryFlipRegion, + .UpdateRegion = primaryUpdateRegion, +}; + +/******************************************************************************/ + +static DFBResult +update_screen( DFBX11 *x11, const DFBRectangle *clip, CoreSurfaceBufferLock *lock ) +{ + void *dst; + void *src; + unsigned int offset = 0; + XWindow *xw; + XImage *ximage; + CoreSurface *surface; + CoreSurfaceAllocation *allocation; + DFBX11Shared *shared; + DFBRectangle rect; + bool direct = false; + + D_ASSERT( x11 != NULL ); + DFB_RECTANGLE_ASSERT( clip ); + + D_DEBUG_AT( X11_Update, "%s( %4d,%4d-%4dx%4d )\n", __FUNCTION__, DFB_RECTANGLE_VALS( clip ) ); + + CORE_SURFACE_BUFFER_LOCK_ASSERT( lock ); + + shared = x11->shared; + D_ASSERT( shared != NULL ); + + XLockDisplay( x11->display ); + + xw = shared->xw; + if (!xw) { + XUnlockDisplay( x11->display ); + return DFB_OK; + } + + allocation = lock->allocation; + CORE_SURFACE_ALLOCATION_ASSERT( allocation ); + + surface = allocation->surface; + D_ASSERT( surface != NULL ); + + + rect.x = rect.y = 0; + rect.w = xw->width; + rect.h = xw->height; + + if (!dfb_rectangle_intersect( &rect, clip )) { + XUnlockDisplay( x11->display ); + return DFB_OK; + } + + D_DEBUG_AT( X11_Update, " -> %4d,%4d-%4dx%4d\n", DFB_RECTANGLE_VALS( &rect ) ); + +#ifdef USE_GLX + /* Check for GLX allocation... */ + if (allocation->pool == shared->glx_pool && lock->handle) { + LocalPixmap *pixmap = lock->handle; + + D_MAGIC_ASSERT( pixmap, LocalPixmap ); + + /* ...and just call SwapBuffers... */ + //D_DEBUG_AT( X11_Update, " -> Calling glXSwapBuffers( 0x%lx )...\n", alloc->drawable ); + //glXSwapBuffers( x11->display, alloc->drawable ); + + + D_DEBUG_AT( X11_Update, " -> Copying from GLXPixmap...\n" ); + + glXWaitGL(); + + XCopyArea( x11->display, pixmap->pixmap, xw->window, xw->gc, + rect.x, rect.y, rect.w, rect.h, rect.x, rect.y ); + + glXWaitX(); + + XUnlockDisplay( x11->display ); + + return DFB_OK; + } +#endif + + /* Check for our special native allocation... */ + if (allocation->pool == shared->x11image_pool && lock->handle) { + x11Image *image = lock->handle; + + D_MAGIC_ASSERT( image, x11Image ); + + /* ...and directly XShmPutImage from that. */ + ximage = image->ximage; + + direct = true; + } + else { + /* ...or copy or convert into XShmImage or XImage allocated with the XWindow. */ + ximage = xw->ximage; + offset = xw->ximage_offset; + + xw->ximage_offset = (offset ? 0 : ximage->height / 2); + + dst = xw->virtualscreen + rect.x * xw->bpp + (rect.y + offset) * ximage->bytes_per_line; + src = lock->addr + DFB_BYTES_PER_LINE( surface->config.format, rect.x ) + rect.y * lock->pitch; + + switch (xw->depth) { + case 32: + dfb_convert_to_argb( surface->config.format, src, lock->pitch, + surface->config.size.h, dst, ximage->bytes_per_line, rect.w, rect.h ); + break; + + case 24: + dfb_convert_to_rgb32( surface->config.format, src, lock->pitch, + surface->config.size.h, dst, ximage->bytes_per_line, rect.w, rect.h ); + break; + + case 16: + dfb_convert_to_rgb16( surface->config.format, src, lock->pitch, + surface->config.size.h, dst, ximage->bytes_per_line, rect.w, rect.h ); + break; + + case 15: + dfb_convert_to_rgb555( surface->config.format, src, lock->pitch, + surface->config.size.h, dst, ximage->bytes_per_line, rect.w, rect.h ); + break; + + default: + D_ONCE( "unsupported depth %d", xw->depth ); + } + } + + D_ASSERT( ximage != NULL ); + + + /* Wait for previous data to be processed... */ + XSync( x11->display, False ); + + /* ...and immediately queue or send the next! */ + if (x11->use_shm) { + /* Just queue the command, it's XShm :) */ + XShmPutImage( xw->display, xw->window, xw->gc, ximage, + rect.x, rect.y + offset, rect.x, rect.y, rect.w, rect.h, False ); + + /* Make sure the queue has really happened! */ + XFlush( x11->display ); + } + else + /* Initiate transfer of buffer... */ + XPutImage( xw->display, xw->window, xw->gc, ximage, + rect.x, rect.y + offset, rect.x, rect.y, rect.w, rect.h ); + + /* Wait for display if single buffered and not converted... */ + if (direct && !(surface->config.caps & DSCAPS_FLIPPING)) + XSync( x11->display, False ); + + XUnlockDisplay( x11->display ); + + return DFB_OK; +} + +/******************************************************************************/ + +DFBResult +dfb_x11_create_window_handler( DFBX11 *x11, CoreLayerRegionConfig *config ) +{ + XWindow *xw; + DFBX11Shared *shared = x11->shared; + + D_DEBUG_AT( X11_Layer, "%s( %p )\n", __FUNCTION__, config ); + + D_DEBUG_AT( X11_Layer, " -> %4dx%4d %s\n", config->width, config->height, dfb_pixelformat_name(config->format) ); + + XLockDisplay( x11->display ); + + xw = shared->xw; + if (xw != NULL) { + if (xw->width == config->width && xw->height == config->height) { + XUnlockDisplay( x11->display ); + return DFB_OK; + } + + shared->xw = NULL; + dfb_x11_close_window( x11, xw ); + } + + bool bSucces = dfb_x11_open_window( x11, &xw, 0, 0, config->width, config->height, config->format ); + + /* Set video mode */ + if ( !bSucces ) { + D_ERROR( "DirectFB/X11: Couldn't open %dx%d window!\n", config->width, config->height ); + + XUnlockDisplay( x11->display ); + return DFB_FAILURE; + } + else + shared->xw = xw; + + XUnlockDisplay( x11->display ); + return DFB_OK; +} + +DFBResult +dfb_x11_destroy_window_handler( DFBX11 *x11 ) +{ + DFBX11Shared *shared = x11->shared; + + D_DEBUG_AT( X11_Layer, "%s()\n", __FUNCTION__ ); + + XLockDisplay( x11->display ); + + if (shared->xw) { + XWindow *xw = shared->xw; + + shared->xw = NULL; + + dfb_x11_close_window( x11, xw ); + } + + XSync( x11->display, False ); + + XUnlockDisplay( x11->display ); + + return DFB_OK; +} + +DFBResult +dfb_x11_update_screen_handler( DFBX11 *x11, UpdateScreenData *data ) +{ + DFBRectangle rect; + + D_DEBUG_AT( X11_Update, "%s( %p )\n", __FUNCTION__, data ); + + rect = DFB_RECTANGLE_INIT_FROM_REGION( &data->region ); + + if (data->lock) + update_screen( x11, &rect, data->lock ); + + data->lock = NULL; + + return DFB_OK; +} + +DFBResult +dfb_x11_set_palette_handler( DFBX11 *x11, CorePalette *palette ) +{ + return DFB_OK; +} + diff --git a/Source/DirectFB/systems/x11/primary.h b/Source/DirectFB/systems/x11/primary.h new file mode 100755 index 0000000..a145d83 --- /dev/null +++ b/Source/DirectFB/systems/x11/primary.h @@ -0,0 +1,39 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __X11__PRIMARY_H__ +#define __X11__PRIMARY_H__ + +#include +#include + +extern ScreenFuncs x11PrimaryScreenFuncs; +extern DisplayLayerFuncs x11PrimaryLayerFuncs; + +#endif // __X11__PRIMARY_H__ + diff --git a/Source/DirectFB/systems/x11/surfacemanager.c b/Source/DirectFB/systems/x11/surfacemanager.c new file mode 100755 index 0000000..e9f697a --- /dev/null +++ b/Source/DirectFB/systems/x11/surfacemanager.c @@ -0,0 +1,559 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include + +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include + +#include + +#include "surfacemanager.h" + +D_DEBUG_DOMAIN( SurfMan, "SurfaceManager", "DirectFB Surface Manager" ); + + +static Chunk *split_chunk ( SurfaceManager *manager, + Chunk *chunk, + int length ); + +static Chunk *free_chunk ( SurfaceManager *manager, + Chunk *chunk ); + +static Chunk *occupy_chunk( SurfaceManager *manager, + Chunk *chunk, + CoreSurfaceAllocation *allocation, + int length, + int pitch ); + + +DFBResult +dfb_surfacemanager_create( CoreDFB *core, + unsigned int length, + SurfaceManager **ret_manager ) +{ + FusionSHMPoolShared *pool; + SurfaceManager *manager; + Chunk *chunk; + + D_DEBUG_AT( SurfMan, "%s( %p, %d )\n", __FUNCTION__, core, length ); + + D_ASSERT( core != NULL ); + D_ASSERT( ret_manager != NULL ); + + pool = dfb_core_shmpool( core ); + + manager = SHCALLOC( pool, 1, sizeof(SurfaceManager) ); + if (!manager) + return D_OOSHM(); + + chunk = SHCALLOC( pool, 1, sizeof(Chunk) ); + if (!chunk) { + D_OOSHM(); + SHFREE( pool, manager ); + return DFB_NOSHAREDMEMORY; + } + + manager->shmpool = pool; + manager->chunks = chunk; + manager->offset = 0; + manager->length = length; + manager->avail = manager->length - manager->offset; + + D_MAGIC_SET( manager, SurfaceManager ); + + chunk->offset = manager->offset; + chunk->length = manager->avail; + + D_MAGIC_SET( chunk, Chunk ); + + D_DEBUG_AT( SurfMan, " -> %p\n", manager ); + + *ret_manager = manager; + + return DFB_OK; +} + +void +dfb_surfacemanager_destroy( SurfaceManager *manager ) +{ + Chunk *chunk; + void *next; + + D_DEBUG_AT( SurfMan, "%s( %p )\n", __FUNCTION__, manager ); + + D_MAGIC_ASSERT( manager, SurfaceManager ); + + /* Deallocate all video chunks. */ + chunk = manager->chunks; + while (chunk) { + next = chunk->next; + + D_MAGIC_CLEAR( chunk ); + + SHFREE( manager->shmpool, chunk ); + + chunk = next; + } + + D_MAGIC_CLEAR( manager ); + + /* Deallocate manager struct. */ + SHFREE( manager->shmpool, manager ); +} + +/** public functions NOT locking the surfacemanger theirself, + to be called between lock/unlock of surfacemanager **/ + +DFBResult dfb_surfacemanager_allocate( CoreDFB *core, + SurfaceManager *manager, + CoreSurfaceBuffer *buffer, + CoreSurfaceAllocation *allocation, + Chunk **ret_chunk ) +{ + 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 ); + + 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 ); + + 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/x11/surfacemanager.h b/Source/DirectFB/systems/x11/surfacemanager.h new file mode 100755 index 0000000..e6136c5 --- /dev/null +++ b/Source/DirectFB/systems/x11/surfacemanager.h @@ -0,0 +1,110 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __SURFACEMANAGER_H__ +#define __SURFACEMANAGER_H__ + +#include + +#include + +typedef struct _SurfaceManager SurfaceManager; +typedef struct _Chunk Chunk; + +/* + * initially there is one big free chunk, + * chunks are splitted into a free and an occupied chunk if memory is allocated, + * two chunks are merged to one free chunk if memory is deallocated + */ +struct _Chunk { + int magic; + + int offset; /* offset in memory, + is greater or equal to the heap offset */ + int length; /* length of this chunk in bytes */ + + int pitch; + + CoreSurfaceBuffer *buffer; /* pointer to surface buffer occupying + this chunk, or NULL if chunk is free */ + CoreSurfaceAllocation *allocation; + + int tolerations; /* number of times this chunk was scanned + occupied, resetted in assure_video */ + + Chunk *prev; + Chunk *next; +}; + +struct _SurfaceManager { + int magic; + + FusionSHMPoolShared *shmpool; + + Chunk *chunks; + + int offset; + int length; /* length of the heap in bytes */ + int avail; /* amount of available memory in bytes */ + + int min_toleration; + + bool suspended; +}; + + +DFBResult dfb_surfacemanager_create ( CoreDFB *core, + unsigned int length, + SurfaceManager **ret_manager ); + +void dfb_surfacemanager_destroy( SurfaceManager *manager ); + +/* + * finds and allocates one for the surface or fails, + * after success the video health is CSH_RESTORE. + * NOTE: this does not notify the listeners + */ +DFBResult dfb_surfacemanager_allocate( CoreDFB *core, + SurfaceManager *manager, + CoreSurfaceBuffer *buffer, + CoreSurfaceAllocation *allocation, + Chunk **ret_chunk ); + +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/x11/vpsmem_surface_pool.c b/Source/DirectFB/systems/x11/vpsmem_surface_pool.c new file mode 100755 index 0000000..0cf505d --- /dev/null +++ b/Source/DirectFB/systems/x11/vpsmem_surface_pool.c @@ -0,0 +1,421 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include +#include + +#include + +#include +#include + +#include + +#include + +#include "x11.h" +#include "surfacemanager.h" + +D_DEBUG_DOMAIN( VPSMem_Surfaces, "VPSMem/Surfaces", "VPSMem Framebuffer Surface Pool" ); +D_DEBUG_DOMAIN( VPSMem_SurfLock, "VPSMem/SurfLock", "VPSMem Framebuffer Surface Pool Locks" ); + +/**********************************************************************************************************************/ + +typedef struct { + int magic; + + SurfaceManager *manager; + + void *mem; + unsigned int length; +} VPSMemPoolData; + +typedef struct { + int magic; + + CoreDFB *core; +} VPSMemPoolLocalData; + +typedef struct { + int magic; + + int offset; + int pitch; + int size; + + Chunk *chunk; +} VPSMemAllocationData; + +/**********************************************************************************************************************/ + +static int +vpsmemPoolDataSize( void ) +{ + return sizeof(VPSMemPoolData); +} + +static int +vpsmemPoolLocalDataSize( void ) +{ + return sizeof(VPSMemPoolLocalData); +} + +static int +vpsmemAllocationDataSize( void ) +{ + return sizeof(VPSMemAllocationData); +} + +static DFBResult +vpsmemInitPool( CoreDFB *core, + CoreSurfacePool *pool, + void *pool_data, + void *pool_local, + void *system_data, + CoreSurfacePoolDescription *ret_desc ) +{ + DFBResult ret; + VPSMemPoolData *data = pool_data; + VPSMemPoolLocalData *local = pool_local; + DFBX11 *x11 = system_data; + DFBX11Shared *shared = x11->shared; + + D_DEBUG_AT( VPSMem_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 ); + + data->mem = SHMALLOC( shared->data_shmpool, shared->vpsmem_length ); + if (!data->mem) { + shared->vpsmem_length = 0; + return D_OOSHM(); + } + + data->length = shared->vpsmem_length; + + ret = dfb_surfacemanager_create( core, data->length, &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->types = CSTF_LAYER | CSTF_WINDOW | CSTF_CURSOR | CSTF_FONT | CSTF_SHARED | CSTF_EXTERNAL; + ret_desc->priority = CSPP_DEFAULT; + ret_desc->size = data->length; + + /* For testing... */ + ret_desc->access[CSAID_ACCEL1] = CSAF_READ | CSAF_WRITE | CSAF_SHARED; + ret_desc->access[CSAID_ACCEL2] = CSAF_READ | CSAF_WRITE | CSAF_SHARED; + ret_desc->access[CSAID_ACCEL3] = CSAF_READ | CSAF_WRITE | CSAF_SHARED; + ret_desc->access[CSAID_ACCEL4] = CSAF_READ | CSAF_WRITE | CSAF_SHARED; + + snprintf( ret_desc->name, DFB_SURFACE_POOL_DESC_NAME_LENGTH, "Virtual Physical" ); + + local->core = core; + + D_MAGIC_SET( data, VPSMemPoolData ); + D_MAGIC_SET( local, VPSMemPoolLocalData ); + + return DFB_OK; +} + +static DFBResult +vpsmemJoinPool( CoreDFB *core, + CoreSurfacePool *pool, + void *pool_data, + void *pool_local, + void *system_data ) +{ + VPSMemPoolData *data = pool_data; + VPSMemPoolLocalData *local = pool_local; + + D_DEBUG_AT( VPSMem_Surfaces, "%s()\n", __FUNCTION__ ); + + D_ASSERT( core != NULL ); + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + D_MAGIC_ASSERT( data, VPSMemPoolData ); + D_ASSERT( local != NULL ); + + (void) data; + + local->core = core; + + D_MAGIC_SET( local, VPSMemPoolLocalData ); + + return DFB_OK; +} + +static DFBResult +vpsmemDestroyPool( CoreSurfacePool *pool, + void *pool_data, + void *pool_local ) +{ + VPSMemPoolData *data = pool_data; + VPSMemPoolLocalData *local = pool_local; + + D_DEBUG_AT( VPSMem_Surfaces, "%s()\n", __FUNCTION__ ); + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + D_MAGIC_ASSERT( data, VPSMemPoolData ); + D_MAGIC_ASSERT( local, VPSMemPoolLocalData ); + + dfb_surfacemanager_destroy( data->manager ); + + D_MAGIC_CLEAR( data ); + D_MAGIC_CLEAR( local ); + + return DFB_OK; +} + +static DFBResult +vpsmemLeavePool( CoreSurfacePool *pool, + void *pool_data, + void *pool_local ) +{ + VPSMemPoolData *data = pool_data; + VPSMemPoolLocalData *local = pool_local; + + D_DEBUG_AT( VPSMem_Surfaces, "%s()\n", __FUNCTION__ ); + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + D_MAGIC_ASSERT( data, VPSMemPoolData ); + D_MAGIC_ASSERT( local, VPSMemPoolLocalData ); + + (void) data; + + D_MAGIC_CLEAR( local ); + + return DFB_OK; +} + +static DFBResult +vpsmemTestConfig( CoreSurfacePool *pool, + void *pool_data, + void *pool_local, + CoreSurfaceBuffer *buffer, + const CoreSurfaceConfig *config ) +{ + DFBResult ret; + CoreSurface *surface; + VPSMemPoolData *data = pool_data; + VPSMemPoolLocalData *local = pool_local; + + D_DEBUG_AT( VPSMem_Surfaces, "%s( %p )\n", __FUNCTION__, buffer ); + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + D_MAGIC_ASSERT( data, VPSMemPoolData ); + D_MAGIC_ASSERT( local, VPSMemPoolLocalData ); + D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); + + surface = buffer->surface; + D_MAGIC_ASSERT( surface, CoreSurface ); + + ret = dfb_surfacemanager_allocate( local->core, data->manager, buffer, NULL, NULL ); + + D_DEBUG_AT( VPSMem_Surfaces, " -> %s\n", DirectFBErrorString(ret) ); + + return ret; +} + +static DFBResult +vpsmemAllocateBuffer( CoreSurfacePool *pool, + void *pool_data, + void *pool_local, + CoreSurfaceBuffer *buffer, + CoreSurfaceAllocation *allocation, + void *alloc_data ) +{ + DFBResult ret; + Chunk *chunk; + CoreSurface *surface; + VPSMemPoolData *data = pool_data; + VPSMemPoolLocalData *local = pool_local; + VPSMemAllocationData *alloc = alloc_data; + + D_DEBUG_AT( VPSMem_Surfaces, "%s( %p )\n", __FUNCTION__, buffer ); + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + D_MAGIC_ASSERT( data, VPSMemPoolData ); + D_MAGIC_ASSERT( local, VPSMemPoolLocalData ); + D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); + + surface = buffer->surface; + D_MAGIC_ASSERT( surface, CoreSurface ); + + 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 = surface->config.size.h * alloc->pitch; + + alloc->chunk = chunk; + + D_DEBUG_AT( VPSMem_Surfaces, " -> offset %d, pitch %d, size %d (%d)\n", + alloc->offset, alloc->pitch, alloc->size, chunk->length ); + + D_ASSERT( chunk->length >= alloc->size ); + + alloc->size = chunk->length; + + allocation->size = alloc->size; + allocation->offset = alloc->offset; + + D_MAGIC_SET( alloc, VPSMemAllocationData ); + + return DFB_OK; +} + +static DFBResult +vpsmemDeallocateBuffer( CoreSurfacePool *pool, + void *pool_data, + void *pool_local, + CoreSurfaceBuffer *buffer, + CoreSurfaceAllocation *allocation, + void *alloc_data ) +{ + VPSMemPoolData *data = pool_data; + VPSMemAllocationData *alloc = alloc_data; + + D_DEBUG_AT( VPSMem_Surfaces, "%s( %p )\n", __FUNCTION__, buffer ); + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + D_MAGIC_ASSERT( data, VPSMemPoolData ); + D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); + D_MAGIC_ASSERT( alloc, VPSMemAllocationData ); + + dfb_surfacemanager_deallocate( data->manager, alloc->chunk ); + + D_MAGIC_CLEAR( alloc ); + + return DFB_OK; +} + +static DFBResult +vpsmemMuckOut( CoreSurfacePool *pool, + void *pool_data, + void *pool_local, + CoreSurfaceBuffer *buffer ) +{ + CoreSurface *surface; + VPSMemPoolData *data = pool_data; + VPSMemPoolLocalData *local = pool_local; + + D_DEBUG_AT( VPSMem_Surfaces, "%s( %p )\n", __FUNCTION__, buffer ); + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + D_MAGIC_ASSERT( data, VPSMemPoolData ); + D_MAGIC_ASSERT( local, VPSMemPoolLocalData ); + D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); + + surface = buffer->surface; + D_MAGIC_ASSERT( surface, CoreSurface ); + + return dfb_surfacemanager_displace( local->core, data->manager, buffer ); +} + +static DFBResult +vpsmemLock( CoreSurfacePool *pool, + void *pool_data, + void *pool_local, + CoreSurfaceAllocation *allocation, + void *alloc_data, + CoreSurfaceBufferLock *lock ) +{ + VPSMemPoolData *data = pool_data; + VPSMemAllocationData *alloc = alloc_data; + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + D_MAGIC_ASSERT( data, VPSMemPoolData ); + D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation ); + D_MAGIC_ASSERT( alloc, VPSMemAllocationData ); + D_MAGIC_ASSERT( lock, CoreSurfaceBufferLock ); + + D_DEBUG_AT( VPSMem_SurfLock, "%s( %p )\n", __FUNCTION__, lock->buffer ); + + lock->pitch = alloc->pitch; + lock->offset = alloc->offset; + lock->addr = data->mem + alloc->offset; + lock->phys = dfb_config->video_phys + alloc->offset; + + D_DEBUG_AT( VPSMem_SurfLock, " -> offset %lu, pitch %d, addr %p, phys 0x%08lx\n", + lock->offset, lock->pitch, lock->addr, lock->phys ); + + return DFB_OK; +} + +static DFBResult +vpsmemUnlock( CoreSurfacePool *pool, + void *pool_data, + void *pool_local, + CoreSurfaceAllocation *allocation, + void *alloc_data, + CoreSurfaceBufferLock *lock ) +{ + VPSMemAllocationData *alloc = alloc_data; + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation ); + D_MAGIC_ASSERT( alloc, VPSMemAllocationData ); + D_MAGIC_ASSERT( lock, CoreSurfaceBufferLock ); + + D_DEBUG_AT( VPSMem_SurfLock, "%s( %p )\n", __FUNCTION__, lock->buffer ); + + (void) alloc; + + return DFB_OK; +} + +const SurfacePoolFuncs vpsmemSurfacePoolFuncs = { + .PoolDataSize = vpsmemPoolDataSize, + .PoolLocalDataSize = vpsmemPoolLocalDataSize, + .AllocationDataSize = vpsmemAllocationDataSize, + + .InitPool = vpsmemInitPool, + .JoinPool = vpsmemJoinPool, + .DestroyPool = vpsmemDestroyPool, + .LeavePool = vpsmemLeavePool, + + .TestConfig = vpsmemTestConfig, + .AllocateBuffer = vpsmemAllocateBuffer, + .DeallocateBuffer = vpsmemDeallocateBuffer, + + .MuckOut = vpsmemMuckOut, + + .Lock = vpsmemLock, + .Unlock = vpsmemUnlock, +}; + diff --git a/Source/DirectFB/systems/x11/vpsmem_surface_pool.h b/Source/DirectFB/systems/x11/vpsmem_surface_pool.h new file mode 100755 index 0000000..915469b --- /dev/null +++ b/Source/DirectFB/systems/x11/vpsmem_surface_pool.h @@ -0,0 +1,37 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __X11SYSTEM__VPSMEM_SURFACE_POOL_H__ +#define __X11SYSTEM__VPSMEM_SURFACE_POOL_H__ + +#include + +extern const SurfacePoolFuncs vpsmemSurfacePoolFuncs; + +#endif + diff --git a/Source/DirectFB/systems/x11/x11.c b/Source/DirectFB/systems/x11/x11.c new file mode 100755 index 0000000..62d329c --- /dev/null +++ b/Source/DirectFB/systems/x11/x11.c @@ -0,0 +1,570 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include + +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include + + +#include "primary.h" +#include "xwindow.h" +#include "x11.h" +#include "x11_surface_pool.h" +#include "x11_surface_pool_bridge.h" + +#ifdef USE_GLX +#include "glx_surface_pool.h" +#endif + +#include "vpsmem_surface_pool.h" + +#include + +D_DEBUG_DOMAIN( X11_Core, "X11/Core", "Main X11 system functions" ); + +DFB_CORE_SYSTEM( x11 ) + + +static VideoMode modes[] = { + { .xres = 320, .yres = 200 }, + { .xres = 320, .yres = 240 }, + { .xres = 512, .yres = 384 }, + { .xres = 640, .yres = 480 }, + { .xres = 768, .yres = 576 }, + + { .xres = 1024, .yres = 576 }, // 16:9 + { .xres = 1024, .yres = 600 }, // Where does that mode come from? :-) + { .xres = 1024, .yres = 768 }, // 4:3 + + { .xres = 1280, .yres = 720 }, // 16:9 + { .xres = 1280, .yres = 960 }, // 4:3 + { .xres = 1280, .yres = 1024 }, // 5:4 + + { .xres = 1440, .yres = 810 }, // 16:9 + { .xres = 1440, .yres = 1080 }, // 4:3 + + { .xres = 1600, .yres = 900 }, // 16:9, obviously :) + { .xres = 1600, .yres = 1200 }, // 4:3 + + { .xres = 1920, .yres = 1080 }, // 16:9 + { .xres = 1920, .yres = 1200 }, // 16:10 + + { .xres = 0, .yres = 0 } +}; + +/**********************************************************************************************************************/ + +static FusionCallHandlerResult call_handler( int caller, + int call_arg, + void *call_ptr, + void *ctx, + unsigned int serial, + int *ret_val ); + +/**********************************************************************************************************************/ + +static DFBResult +InitLocal( DFBX11 *x11, DFBX11Shared *shared, CoreDFB *core ) +{ + int i, n; + + XInitThreads(); + + x11->shared = shared; + x11->core = core; + + x11->display = XOpenDisplay(getenv("DISPLAY")); + if (!x11->display) { + D_ERROR("X11: Error in XOpenDisplay for '%s'\n", getenv("DISPLAY")); + return DFB_INIT; + } + + x11->screenptr = DefaultScreenOfDisplay(x11->display); + x11->screennum = DefaultScreen(x11->display); + + for (i=0; iscreenptr->ndepths; i++) { + const Depth *depth = &x11->screenptr->depths[i]; + + for (n=0; nnvisuals; n++) { + Visual *visual = &depth->visuals[n]; + + D_DEBUG_AT( X11_Core, "[Visual %d] ID 0x%02lx, depth %d, RGB 0x%06lx/0x%06lx/0x%06lx, %d bpRGB, %d entr.\n", + n, visual->visualid, depth->depth, + visual->red_mask, visual->green_mask, visual->blue_mask, + visual->bits_per_rgb, visual->map_entries ); + + switch (depth->depth) { + case 32: + if (visual->red_mask == 0xff0000 && + visual->green_mask == 0x00ff00 && + visual->blue_mask == 0x0000ff && + !x11->visuals[DFB_PIXELFORMAT_INDEX(DSPF_ARGB)]) + x11->visuals[DFB_PIXELFORMAT_INDEX(DSPF_ARGB)] = visual; + break; + + case 24: + if (visual->red_mask == 0xff0000 && + visual->green_mask == 0x00ff00 && + visual->blue_mask == 0x0000ff && + !x11->visuals[DFB_PIXELFORMAT_INDEX(DSPF_RGB32)]) + x11->visuals[DFB_PIXELFORMAT_INDEX(DSPF_RGB32)] = visual; + break; + + case 16: + if (visual->red_mask == 0xf800 && + visual->green_mask == 0x07e0 && + visual->blue_mask == 0x001f && + !x11->visuals[DFB_PIXELFORMAT_INDEX(DSPF_RGB16)]) + x11->visuals[DFB_PIXELFORMAT_INDEX(DSPF_RGB16)] = visual; + break; + + case 15: + if (visual->red_mask == 0x7c00 && + visual->green_mask == 0x03e0 && + visual->blue_mask == 0x001f && + !x11->visuals[DFB_PIXELFORMAT_INDEX(DSPF_RGB555)]) + x11->visuals[DFB_PIXELFORMAT_INDEX(DSPF_RGB555)] = visual; + break; + } + } + } + + if (XShmQueryExtension( x11->display )) + XShmQueryVersion( x11->display, &x11->xshm_major, &x11->xshm_minor, &x11->use_shm ); + + + x11->screen = dfb_screens_register( NULL, x11, &x11PrimaryScreenFuncs ); + + dfb_layers_register( x11->screen, x11, &x11PrimaryLayerFuncs ); + + return DFB_OK; +} + +/**********************************************************************************************************************/ + +static void +system_get_info( CoreSystemInfo *info ) +{ + info->type = CORE_X11; + info->caps = CSCAPS_ACCELERATION; + + D_DEBUG_AT( X11_Core, "%s()\n", __FUNCTION__ ); + + snprintf( info->name, DFB_CORE_SYSTEM_INFO_NAME_LENGTH, "X11" ); +} + +DFBX11 *dfb_x11 = NULL; + +static DFBResult +system_initialize( CoreDFB *core, void **data ) +{ + DFBResult ret; + DFBX11 *x11; + DFBX11Shared *shared; + + D_DEBUG_AT( X11_Core, "%s()\n", __FUNCTION__ ); + + x11 = D_CALLOC( 1, sizeof(DFBX11) ); + if (!x11) + return D_OOM(); + + shared = SHCALLOC( dfb_core_shmpool( core ), 1, sizeof(DFBX11Shared) ); + if (!shared) { + D_FREE( x11 ); + return D_OOSHM(); + } + + + /* + * Local init (master and slave) + */ + ret = InitLocal( x11, shared, core ); + if (ret) { + SHFREE( dfb_core_shmpool( core ), shared ); + D_FREE( x11 ); + return ret; + } + + + /* + * Shared init (master only) + */ + shared->data_shmpool = dfb_core_shmpool_data( core ); + + shared->screen_size.w = x11->screenptr->width; + shared->screen_size.h = x11->screenptr->height; + + fusion_skirmish_init( &shared->lock, "X11 System", dfb_core_world(core) ); + + fusion_call_init( &shared->call, call_handler, x11, dfb_core_world(core) ); + + + /* + * Must be set before initializing the pools! + */ + *data = x11; + + dfb_x11 = x11; + + /* + * Master init + */ + dfb_surface_pool_initialize( core, &x11SurfacePoolFuncs, &shared->x11image_pool ); + +#ifdef USE_GLX + dfb_surface_pool_initialize( core, &glxSurfacePoolFuncs, &shared->glx_pool ); +#endif + + if (dfb_config->video_length) { + shared->vpsmem_length = dfb_config->video_length; + + dfb_surface_pool_initialize( core, &vpsmemSurfacePoolFuncs, &shared->vpsmem_pool ); + } + +#ifdef USE_GLX + dfb_surface_pool_bridge_initialize( core, &x11SurfacePoolBridgeFuncs, x11, &shared->x11_pool_bridge ); +#endif + + fusion_arena_add_shared_field( dfb_core_arena( core ), "x11", shared ); + + return DFB_OK; +} + +static DFBResult +system_join( CoreDFB *core, void **data ) +{ + DFBResult ret; + void *ptr; + DFBX11 *x11; + DFBX11Shared *shared; + + D_DEBUG_AT( X11_Core, "%s()\n", __FUNCTION__ ); + + x11 = D_CALLOC( 1, sizeof(DFBX11) ); + if (!x11) + return D_OOM(); + + fusion_arena_get_shared_field( dfb_core_arena( core ), "x11", &ptr ); + shared = ptr; + + + /* + * Local init (master and slave) + */ + ret = InitLocal( x11, shared, core ); + if (ret) { + D_FREE( x11 ); + return ret; + } + + + /* + * Must be set before joining the pools! + */ + *data = x11; + + + /* + * Slave init + */ + if (shared->x11image_pool) + dfb_surface_pool_join( core, shared->x11image_pool, &x11SurfacePoolFuncs ); + +#ifdef USE_GLX + if (shared->glx_pool) + dfb_surface_pool_join( core, shared->glx_pool, &glxSurfacePoolFuncs ); +#endif + + if (shared->vpsmem_pool) + dfb_surface_pool_join( core, shared->vpsmem_pool, &vpsmemSurfacePoolFuncs ); + +#ifdef USE_GLX + if (shared->x11_pool_bridge) + dfb_surface_pool_bridge_join( core, shared->x11_pool_bridge, &x11SurfacePoolBridgeFuncs, x11 ); +#endif + + return DFB_OK; +} + +static DFBResult +system_shutdown( bool emergency ) +{ + DFBX11 *x11 = dfb_system_data(); + DFBX11Shared *shared = x11->shared; + + D_DEBUG_AT( X11_Core, "%s()\n", __FUNCTION__ ); + + /* + * Master deinit + */ + if (shared->x11_pool_bridge) + dfb_surface_pool_bridge_destroy( shared->x11_pool_bridge ); + + if (shared->vpsmem_pool) + dfb_surface_pool_destroy( shared->vpsmem_pool ); + + if (shared->glx_pool) + dfb_surface_pool_destroy( shared->glx_pool ); + + if (shared->x11image_pool) + dfb_surface_pool_destroy( shared->x11image_pool ); + + + /* + * Shared deinit (master only) + */ + fusion_call_destroy( &shared->call ); + + fusion_skirmish_prevail( &shared->lock ); + + if (shared->xw) + dfb_x11_close_window( x11, shared->xw ); + + fusion_skirmish_destroy( &shared->lock ); + + + SHFREE( dfb_core_shmpool( x11->core ), shared ); + + + /* + * Local deinit (master and slave) + */ + if (x11->display) + XCloseDisplay( x11->display ); + + D_FREE( x11 ); + + return DFB_OK; +} + +static DFBResult +system_leave( bool emergency ) +{ + DFBX11 *x11 = dfb_system_data(); + DFBX11Shared *shared = x11->shared; + + D_DEBUG_AT( X11_Core, "%s()\n", __FUNCTION__ ); + + /* + * Slave deinit + */ + if (shared->x11_pool_bridge) + dfb_surface_pool_bridge_leave( shared->x11_pool_bridge ); + + if (shared->vpsmem_pool) + dfb_surface_pool_leave( shared->vpsmem_pool ); + + if (shared->glx_pool) + dfb_surface_pool_leave( shared->glx_pool ); + + if (shared->x11image_pool) + dfb_surface_pool_leave( shared->x11image_pool ); + + + /* + * Local deinit (master and slave) + */ + if (x11->display) + XCloseDisplay( x11->display ); + + D_FREE( x11 ); + + return DFB_OK; +} + +static DFBResult +system_suspend( void ) +{ + return DFB_UNIMPLEMENTED; +} + +static DFBResult +system_resume( void ) +{ + return DFB_UNIMPLEMENTED; +} + +static volatile void * +system_map_mmio( unsigned int offset, + int length ) +{ + return NULL; +} + +static void +system_unmap_mmio( volatile void *addr, + int length ) +{ +} + +static int +system_get_accelerator( void ) +{ + return dfb_config->accelerator; +} + +static VideoMode * +system_get_modes( void ) +{ + return modes; +} + +static VideoMode * +system_get_current_mode( void ) +{ + return &modes[0]; /* FIXME */ +} + +static DFBResult +system_thread_init( void ) +{ + return DFB_OK; +} + +static bool +system_input_filter( CoreInputDevice *device, + DFBInputEvent *event ) +{ + return false; +} + +static unsigned long +system_video_memory_physical( unsigned int offset ) +{ + return 0; +} + +static void * +system_video_memory_virtual( unsigned int offset ) +{ + return NULL; +} + +static unsigned int +system_videoram_length( void ) +{ + return 0; +} + +static unsigned long +system_aux_memory_physical( unsigned int offset ) +{ + return 0; +} + +static void * +system_aux_memory_virtual( unsigned int offset ) +{ + return NULL; +} + +static unsigned int +system_auxram_length( void ) +{ + return 0; +} + +static void +system_get_busid( int *ret_bus, int *ret_dev, int *ret_func ) +{ +} + +static void +system_get_deviceid( unsigned int *ret_vendor_id, + unsigned int *ret_device_id ) +{ +} + +static FusionCallHandlerResult +call_handler( int caller, + int call_arg, + void *call_ptr, + void *ctx, + unsigned int serial, + int *ret_val ) +{ + DFBX11 *x11 = ctx; + + switch (call_arg) { + case X11_CREATE_WINDOW: + *ret_val = dfb_x11_create_window_handler( x11, call_ptr ); + break; + + case X11_DESTROY_WINDOW: + *ret_val = dfb_x11_destroy_window_handler( x11 ); + break; + + case X11_UPDATE_SCREEN: + *ret_val = dfb_x11_update_screen_handler( x11, call_ptr ); + break; + + case X11_SET_PALETTE: + *ret_val = dfb_x11_set_palette_handler( x11, call_ptr ); + break; + + case X11_IMAGE_INIT: + *ret_val = dfb_x11_image_init_handler( x11, call_ptr ); + break; + + case X11_IMAGE_DESTROY: + *ret_val = dfb_x11_image_destroy_handler( x11, call_ptr ); + break; + + default: + D_BUG( "unknown call" ); + *ret_val = DFB_BUG; + break; + } + + return FCHR_RETURN; +} + diff --git a/Source/DirectFB/systems/x11/x11.h b/Source/DirectFB/systems/x11/x11.h new file mode 100755 index 0000000..4743f1a --- /dev/null +++ b/Source/DirectFB/systems/x11/x11.h @@ -0,0 +1,116 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __X11SYSTEM__X11_H__ +#define __X11SYSTEM__X11_H__ + +#include +#include +#include +#include +#include +#include + +#include "x11image.h" +#include "xwindow.h" + +typedef struct { + CoreLayerRegionConfig config; +} SetModeData; + +typedef struct { + DFBRegion region; + + CoreSurfaceBufferLock *lock; +} UpdateScreenData; + + +typedef struct { + UpdateScreenData update; + SetModeData setmode; + + FusionSkirmish lock; + FusionCall call; + + FusionSHMPoolShared *data_shmpool; + + CoreSurfacePool *x11image_pool; + + CoreSurfacePool *glx_pool; /* only used for GL */ + + CoreSurfacePool *vpsmem_pool; + unsigned int vpsmem_length; + + CoreSurfacePoolBridge *x11_pool_bridge; + +// CoreSurface *primary; + DFBDimension screen_size; + + XWindow *xw; +} DFBX11Shared; + +struct __DFB_X11 { + DFBX11Shared *shared; + + CoreDFB *core; + CoreScreen *screen; + + Bool use_shm; + int xshm_major; + int xshm_minor; + + Display *display; + Screen *screenptr; + int screennum; + + Visual *visuals[DFB_NUM_PIXELFORMATS]; +}; + +typedef enum { + X11_CREATE_WINDOW, + X11_UPDATE_SCREEN, + X11_SET_PALETTE, + X11_IMAGE_INIT, + X11_IMAGE_DESTROY, + X11_DESTROY_WINDOW, +} DFBX11Call; + + + +DFBResult dfb_x11_create_window_handler ( DFBX11 *x11, CoreLayerRegionConfig *config ); +DFBResult dfb_x11_destroy_window_handler( DFBX11 *x11 ); + +DFBResult dfb_x11_update_screen_handler ( DFBX11 *x11, UpdateScreenData *data ); +DFBResult dfb_x11_set_palette_handler ( DFBX11 *x11, CorePalette *palette ); + +DFBResult dfb_x11_image_init_handler ( DFBX11 *x11, x11Image *image ); +DFBResult dfb_x11_image_destroy_handler ( DFBX11 *x11, x11Image *image ); + + +#endif //__X11SYSTEM__X11_H__ + diff --git a/Source/DirectFB/systems/x11/x11_surface_pool.c b/Source/DirectFB/systems/x11/x11_surface_pool.c new file mode 100755 index 0000000..4936f2a --- /dev/null +++ b/Source/DirectFB/systems/x11/x11_surface_pool.c @@ -0,0 +1,369 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +//#define DIRECT_ENABLE_DEBUG + +#include + +#include +#include +#include + +#include + +#include + +#include "x11.h" +#include "x11image.h" +#include "x11_surface_pool.h" + +D_DEBUG_DOMAIN( X11_Surfaces, "X11/Surfaces", "X11 System Surface Pool" ); + +/**********************************************************************************************************************/ + +typedef struct { +} x11PoolData; + +typedef struct { + pthread_mutex_t lock; + DirectHash *hash; + + DFBX11 *x11; +} x11PoolLocalData; + +/**********************************************************************************************************************/ + +static int +x11PoolDataSize( void ) +{ + return sizeof(x11PoolData); +} + +static int +x11PoolLocalDataSize( void ) +{ + return sizeof(x11PoolLocalData); +} + +static int +x11AllocationDataSize( void ) +{ + return sizeof(x11AllocationData); +} + +static DFBResult +x11InitPool( CoreDFB *core, + CoreSurfacePool *pool, + void *pool_data, + void *pool_local, + void *system_data, + CoreSurfacePoolDescription *ret_desc ) +{ + DFBResult ret; + x11PoolLocalData *local = pool_local; + DFBX11 *x11 = system_data; + + D_DEBUG_AT( X11_Surfaces, "%s()\n", __FUNCTION__ ); + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + D_ASSERT( ret_desc != NULL ); + + local->x11 = x11; + + ret_desc->caps = CSPCAPS_VIRTUAL; + ret_desc->access[CSAID_CPU] = 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_ULTIMATE; + + /* For showing our X11 window */ + ret_desc->access[CSAID_LAYER0] = CSAF_READ; + + snprintf( ret_desc->name, DFB_SURFACE_POOL_DESC_NAME_LENGTH, "X11 Shm Images" ); + + ret = direct_hash_create( 7, &local->hash ); + if (ret) { + D_DERROR( ret, "X11/Surfaces: Could not create local hash table!\n" ); + return ret; + } + + pthread_mutex_init( &local->lock, NULL ); + + return DFB_OK; +} + +static DFBResult +x11JoinPool( CoreDFB *core, + CoreSurfacePool *pool, + void *pool_data, + void *pool_local, + void *system_data ) +{ + DFBResult ret; + x11PoolLocalData *local = pool_local; + DFBX11 *x11 = system_data; + + D_DEBUG_AT( X11_Surfaces, "%s()\n", __FUNCTION__ ); + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + + local->x11 = x11; + + ret = direct_hash_create( 7, &local->hash ); + if (ret) { + D_DERROR( ret, "X11/Surfaces: Could not create local hash table!\n" ); + return ret; + } + + pthread_mutex_init( &local->lock, NULL ); + + return DFB_OK; +} + +static DFBResult +x11DestroyPool( CoreSurfacePool *pool, + void *pool_data, + void *pool_local ) +{ + x11PoolLocalData *local = pool_local; + + D_DEBUG_AT( X11_Surfaces, "%s()\n", __FUNCTION__ ); + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + + pthread_mutex_destroy( &local->lock ); + + direct_hash_destroy( local->hash ); + + return DFB_OK; +} + +static DFBResult +x11LeavePool( CoreSurfacePool *pool, + void *pool_data, + void *pool_local ) +{ + x11PoolLocalData *local = pool_local; + + D_DEBUG_AT( X11_Surfaces, "%s()\n", __FUNCTION__ ); + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + + pthread_mutex_destroy( &local->lock ); + + direct_hash_destroy( local->hash ); + + return DFB_OK; +} + +static DFBResult +x11TestConfig( CoreSurfacePool *pool, + void *pool_data, + void *pool_local, + CoreSurfaceBuffer *buffer, + const CoreSurfaceConfig *config ) +{ + x11PoolLocalData *local = pool_local; + DFBX11 *x11 = local->x11; + DFBX11Shared *shared = x11->shared; + + /* Provide a fallback only if no virtual physical pool is allocated... */ + if (!shared->vpsmem_length) + return DFB_OK; + + /* Pass NULL image for probing */ + return x11ImageInit( x11, NULL, config->size.w, config->size.h, config->format ); +} + +static DFBResult +x11AllocateBuffer( CoreSurfacePool *pool, + void *pool_data, + void *pool_local, + CoreSurfaceBuffer *buffer, + CoreSurfaceAllocation *allocation, + void *alloc_data ) +{ + CoreSurface *surface; + x11AllocationData *alloc = alloc_data; + x11PoolLocalData *local = pool_local; + DFBX11 *x11 = local->x11; + + D_DEBUG_AT( X11_Surfaces, "%s()\n", __FUNCTION__ ); + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); + + surface = buffer->surface; + D_MAGIC_ASSERT( surface, CoreSurface ); + + if (x11ImageInit( x11, &alloc->image, surface->config.size.w, surface->config.size.h, surface->config.format ) == DFB_OK) { + alloc->real = true; + alloc->pitch = alloc->image.pitch; + + allocation->size = surface->config.size.h * alloc->image.pitch; + } + else + dfb_surface_calc_buffer_size( surface, 8, 2, &alloc->pitch, &allocation->size ); + + return DFB_OK; +} + +static DFBResult +x11DeallocateBuffer( CoreSurfacePool *pool, + void *pool_data, + void *pool_local, + CoreSurfaceBuffer *buffer, + CoreSurfaceAllocation *allocation, + void *alloc_data ) +{ + x11AllocationData *alloc = alloc_data; + x11PoolLocalData *local = pool_local; + DFBX11 *x11 = local->x11; + DFBX11Shared *shared = x11->shared; + + D_DEBUG_AT( X11_Surfaces, "%s()\n", __FUNCTION__ ); + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); + + CORE_SURFACE_ALLOCATION_ASSERT( allocation ); + + if (alloc->real) + return x11ImageDestroy( x11, &alloc->image ); + + if (alloc->ptr) + SHFREE( shared->data_shmpool, alloc->ptr ); + + return DFB_OK; +} + +static DFBResult +x11Lock( CoreSurfacePool *pool, + void *pool_data, + void *pool_local, + CoreSurfaceAllocation *allocation, + void *alloc_data, + CoreSurfaceBufferLock *lock ) +{ + DFBResult ret; + x11PoolLocalData *local = pool_local; + x11AllocationData *alloc = alloc_data; + DFBX11 *x11 = local->x11; + DFBX11Shared *shared = x11->shared; + CoreSurfaceBuffer *buffer; + CoreSurface *surface; + + D_DEBUG_AT( X11_Surfaces, "%s( %p )\n", __FUNCTION__, allocation ); + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation ); + D_MAGIC_ASSERT( lock, CoreSurfaceBufferLock ); + + buffer = allocation->buffer; + D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer ); + + surface = buffer->surface; + D_MAGIC_ASSERT( surface, CoreSurface ); + + D_ASSERT( local->hash != NULL ); + + pthread_mutex_lock( &local->lock ); + + if (alloc->real) { + void *addr = direct_hash_lookup( local->hash, alloc->image.seginfo.shmid ); + + if (!addr) { + ret = x11ImageAttach( &alloc->image, &addr ); + if (ret) { + D_DERROR( ret, "X11/Surfaces: x11ImageAttach() failed!\n" ); + pthread_mutex_unlock( &local->lock ); + return ret; + } + + direct_hash_insert( local->hash, alloc->image.seginfo.shmid, addr ); + + /* FIXME: When to remove/detach? */ + } + + lock->addr = addr; + lock->handle = &alloc->image; + } + else { + if (!alloc->ptr) { + alloc->ptr = SHCALLOC( shared->data_shmpool, 1, allocation->size ); + if (!alloc->ptr) + return D_OOSHM(); + } + + lock->addr = alloc->ptr; + } + + lock->pitch = alloc->pitch; + + pthread_mutex_unlock( &local->lock ); + + return DFB_OK; +} + +static DFBResult +x11Unlock( CoreSurfacePool *pool, + void *pool_data, + void *pool_local, + CoreSurfaceAllocation *allocation, + void *alloc_data, + CoreSurfaceBufferLock *lock ) +{ + D_DEBUG_AT( X11_Surfaces, "%s( %p )\n", __FUNCTION__, allocation ); + + D_MAGIC_ASSERT( pool, CoreSurfacePool ); + D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation ); + D_MAGIC_ASSERT( lock, CoreSurfaceBufferLock ); + + /* FIXME: Check overhead of attach/detach per lock/unlock. */ + + return DFB_OK; +} + +const SurfacePoolFuncs x11SurfacePoolFuncs = { + .PoolDataSize = x11PoolDataSize, + .PoolLocalDataSize = x11PoolLocalDataSize, + .AllocationDataSize = x11AllocationDataSize, + + .InitPool = x11InitPool, + .JoinPool = x11JoinPool, + .DestroyPool = x11DestroyPool, + .LeavePool = x11LeavePool, + + .TestConfig = x11TestConfig, + + .AllocateBuffer = x11AllocateBuffer, + .DeallocateBuffer = x11DeallocateBuffer, + + .Lock = x11Lock, + .Unlock = x11Unlock, +}; + diff --git a/Source/DirectFB/systems/x11/x11_surface_pool.h b/Source/DirectFB/systems/x11/x11_surface_pool.h new file mode 100755 index 0000000..b660931 --- /dev/null +++ b/Source/DirectFB/systems/x11/x11_surface_pool.h @@ -0,0 +1,47 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __X11SYSTEM__X11_SURFACE_POOL_H__ +#define __X11SYSTEM__X11_SURFACE_POOL_H__ + +#include + +#include "x11image.h" + +extern const SurfacePoolFuncs x11SurfacePoolFuncs; + +typedef struct { + bool real; + x11Image image; + + void *ptr; + int pitch; +} x11AllocationData; + +#endif + diff --git a/Source/DirectFB/systems/x11/x11_surface_pool_bridge.c b/Source/DirectFB/systems/x11/x11_surface_pool_bridge.c new file mode 100755 index 0000000..ce2537e --- /dev/null +++ b/Source/DirectFB/systems/x11/x11_surface_pool_bridge.c @@ -0,0 +1,331 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +//#define DIRECT_ENABLE_DEBUG + +#include + +#include +#include +#include + +#include + +#include + +#include "x11.h" +#include "x11image.h" +#include "glx_surface_pool.h" +#include "x11_surface_pool.h" + +D_DEBUG_DOMAIN( X11_Bridge, "X11/Bridge", "X11 System Surface Pool Bridge" ); + +/**********************************************************************************************************************/ + +typedef struct { +} x11PoolBridgeData; + +typedef struct { + DFBX11 *x11; + Display *display; +} x11PoolBridgeLocalData; + +typedef struct { +} x11PoolTransferData; + +/**********************************************************************************************************************/ + +static int +x11PoolBridgeDataSize( void ) +{ + return sizeof(x11PoolBridgeData); +} + +static int +x11PoolBridgeLocalDataSize( void ) +{ + return sizeof(x11PoolBridgeLocalData); +} + +static int +x11PoolTransferDataSize( void ) +{ + return sizeof(x11PoolTransferData); +} + +static DFBResult +x11InitPoolBridge( CoreDFB *core, + CoreSurfacePoolBridge *bridge, + void *bridge_data, + void *bridge_local, + void *context, + CoreSurfacePoolBridgeDescription *ret_desc ) +{ + x11PoolBridgeLocalData *local = bridge_local; + DFBX11 *x11 = context; + + D_DEBUG_AT( X11_Bridge, "%s()\n", __FUNCTION__ ); + + D_MAGIC_ASSERT( bridge, CoreSurfacePoolBridge ); + D_ASSERT( bridge_local != NULL ); + D_ASSERT( context != NULL ); + D_ASSERT( ret_desc != NULL ); + + local->x11 = x11; + local->display = x11->display; + + ret_desc->caps = CSPBCAPS_NONE; + + snprintf( ret_desc->name, DFB_SURFACE_POOL_BRIDGE_DESC_NAME_LENGTH, "X11 Pool Bridge" ); + + return DFB_OK; +} + +static DFBResult +x11JoinPoolBridge( CoreDFB *core, + CoreSurfacePoolBridge *bridge, + void *bridge_data, + void *bridge_local, + void *context ) +{ + x11PoolBridgeLocalData *local = bridge_local; + DFBX11 *x11 = context; + + D_DEBUG_AT( X11_Bridge, "%s()\n", __FUNCTION__ ); + + D_MAGIC_ASSERT( bridge, CoreSurfacePoolBridge ); + D_ASSERT( bridge_local != NULL ); + D_ASSERT( context != NULL ); + + local->x11 = x11; + local->display = x11->display; + + return DFB_OK; +} + +static DFBResult +x11DestroyPoolBridge( CoreSurfacePoolBridge *bridge, + void *bridge_data, + void *bridge_local ) +{ + D_DEBUG_AT( X11_Bridge, "%s()\n", __FUNCTION__ ); + + D_MAGIC_ASSERT( bridge, CoreSurfacePoolBridge ); + + return DFB_OK; +} + +static DFBResult +x11LeavePoolBridge( CoreSurfacePoolBridge *bridge, + void *bridge_data, + void *bridge_local ) +{ + D_DEBUG_AT( X11_Bridge, "%s()\n", __FUNCTION__ ); + + D_MAGIC_ASSERT( bridge, CoreSurfacePoolBridge ); + + return DFB_OK; +} + +static DFBResult +x11CheckTransfer( CoreSurfacePoolBridge *bridge, + void *bridge_data, + void *bridge_local, + CoreSurfaceBuffer *buffer, + CoreSurfaceAllocation *from, + CoreSurfaceAllocation *to ) +{ + x11PoolBridgeLocalData *local = bridge_local; + DFBX11 *x11 = local->x11; + DFBX11Shared *shared = x11->shared; + + D_DEBUG_AT( X11_Bridge, "%s()\n", __FUNCTION__ ); + + if (from->pool == shared->x11image_pool && to->pool == shared->glx_pool) { + x11AllocationData *alloc = from->data; + + if (alloc->real) { + /* ARGB does not work (BadMatch) */ + if (buffer->format == DSPF_RGB32) + return DFB_OK; + } + } + else if (from->pool == shared->glx_pool && to->pool == shared->x11image_pool) { + x11AllocationData *alloc = to->data; + + if (alloc->real) { + /* ARGB does not work (BadMatch) */ + if (buffer->format == DSPF_RGB32) + return DFB_OK; + } + } + + return DFB_UNSUPPORTED; +} + +static DFBResult +x11StartTransfer( CoreSurfacePoolBridge *bridge, + void *bridge_data, + void *bridge_local, + CoreSurfacePoolTransfer *transfer, + void *transfer_data ) +{ + DFBResult ret; + int i; + CoreSurfaceBufferLock lock; + LocalPixmap *pixmap; + x11PoolBridgeLocalData *local = bridge_local; + DFBX11 *x11 = local->x11; + DFBX11Shared *shared = x11->shared; + CoreSurfaceAllocation *from = transfer->from; + CoreSurfaceAllocation *to = transfer->to; + + D_DEBUG_AT( X11_Bridge, "%s()\n", __FUNCTION__ ); + + if (from->pool == shared->x11image_pool && to->pool == shared->glx_pool) { + x11AllocationData *alloc = from->data; + + D_ASSERT( alloc->real ); + + dfb_surface_buffer_lock_init( &lock, CSAID_ANY, CSAF_WRITE ); + + ret = dfb_surface_pool_lock( to->pool, to, &lock ); + if (ret) { + dfb_surface_buffer_lock_deinit( &lock ); + return ret; + } + + pixmap = lock.handle; + D_MAGIC_ASSERT( pixmap, LocalPixmap ); + + + XLockDisplay( local->display ); + + for (i=0; inum_rects; i++) { + const DFBRectangle *rect = &transfer->rects[i]; + + D_DEBUG_AT( X11_Bridge, " -> XCopyArea( %4d,%4d-%4dx%4d )\n", rect->x, rect->y, rect->w, rect->h ); + + XCopyArea( local->display, alloc->image.pixmap, pixmap->pixmap, pixmap->gc, + rect->x, rect->y, rect->w, rect->h, rect->x, rect->y ); + } + + XFlush( local->display ); + + XUnlockDisplay( local->display ); + + + dfb_surface_pool_unlock( to->pool, to, &lock ); + + dfb_surface_buffer_lock_deinit( &lock ); + + return DFB_OK; + } + + if (from->pool == shared->glx_pool && to->pool == shared->x11image_pool) { + x11AllocationData *alloc = to->data; + + D_ASSERT( alloc->real ); + + dfb_surface_buffer_lock_init( &lock, CSAID_ANY, CSAF_READ ); + + ret = dfb_surface_pool_lock( from->pool, from, &lock ); + if (ret) { + dfb_surface_buffer_lock_deinit( &lock ); + return ret; + } + + pixmap = lock.handle; + D_MAGIC_ASSERT( pixmap, LocalPixmap ); + + + XLockDisplay( local->display ); + + glFinish(); + + for (i=0; inum_rects; i++) { + const DFBRectangle *rect = &transfer->rects[i]; + + D_DEBUG_AT( X11_Bridge, " -> XCopyArea( %4d,%4d-%4dx%4d )\n", rect->x, rect->y, rect->w, rect->h ); + + XCopyArea( local->display, pixmap->pixmap, alloc->image.pixmap, alloc->image.gc, + rect->x, rect->y, rect->w, rect->h, rect->x, rect->y ); + } + + XFlush( local->display ); + + XUnlockDisplay( local->display ); + + + dfb_surface_pool_unlock( from->pool, from, &lock ); + + dfb_surface_buffer_lock_deinit( &lock ); + + return DFB_OK; + } + + return DFB_BUG; +} + +static DFBResult +x11FinishTransfer( CoreSurfacePoolBridge *bridge, + void *bridge_data, + void *bridge_local, + CoreSurfacePoolTransfer *transfer, + void *transfer_data ) +{ + x11PoolBridgeLocalData *local = bridge_local; + + D_DEBUG_AT( X11_Bridge, "%s()\n", __FUNCTION__ ); + + XLockDisplay( local->display ); + + XSync( local->display, False ); + + XUnlockDisplay( local->display ); + + return DFB_OK; +} + + +const SurfacePoolBridgeFuncs x11SurfacePoolBridgeFuncs = { + .PoolBridgeDataSize = x11PoolBridgeDataSize, + .PoolBridgeLocalDataSize = x11PoolBridgeLocalDataSize, + .PoolTransferDataSize = x11PoolTransferDataSize, + + .InitPoolBridge = x11InitPoolBridge, + .JoinPoolBridge = x11JoinPoolBridge, + .DestroyPoolBridge = x11DestroyPoolBridge, + .LeavePoolBridge = x11LeavePoolBridge, + + .CheckTransfer = x11CheckTransfer, + + .StartTransfer = x11StartTransfer, + .FinishTransfer = x11FinishTransfer, +}; + diff --git a/Source/DirectFB/systems/x11/x11_surface_pool_bridge.h b/Source/DirectFB/systems/x11/x11_surface_pool_bridge.h new file mode 100755 index 0000000..cebb5dc --- /dev/null +++ b/Source/DirectFB/systems/x11/x11_surface_pool_bridge.h @@ -0,0 +1,37 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __X11SYSTEM__X11_SURFACE_POOL_BRIDGE_H__ +#define __X11SYSTEM__X11_SURFACE_POOL_BRIDGE_H__ + +#include + +extern const SurfacePoolBridgeFuncs x11SurfacePoolBridgeFuncs; + +#endif + diff --git a/Source/DirectFB/systems/x11/x11image.c b/Source/DirectFB/systems/x11/x11image.c new file mode 100755 index 0000000..acf36f0 --- /dev/null +++ b/Source/DirectFB/systems/x11/x11image.c @@ -0,0 +1,231 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include +#include +#include + +#include "x11.h" +#include "x11image.h" + +/**********************************************************************************************************************/ + +DFBResult x11ImageInit( DFBX11 *x11, + x11Image *image, + int width, + int height, + DFBSurfacePixelFormat format ) +{ + int ret; + Visual *visual; + DFBX11Shared *shared = x11->shared; + + if (!x11->use_shm) + return DFB_UNSUPPORTED; + + /* Lookup visual. */ + visual = x11->visuals[DFB_PIXELFORMAT_INDEX(format)]; + if (!visual) + return DFB_UNSUPPORTED; + + /* For probing. */ + if (!image) + return DFB_OK; + + image->width = width; + image->height = height; + image->format = format; + image->depth = DFB_COLOR_BITS_PER_PIXEL( format ); + + D_MAGIC_SET( image, x11Image ); + + if (fusion_call_execute( &shared->call, FCEF_NONE, X11_IMAGE_INIT, image, &ret )) { + D_MAGIC_CLEAR( image ); + return DFB_FUSION; + } + + if (ret) { + D_DERROR( ret, "X11/Image: X11_IMAGE_INIT call failed!\n" ); + D_MAGIC_CLEAR( image ); + return ret; + } + + return DFB_OK; +} + +DFBResult +x11ImageDestroy( DFBX11 *x11, + x11Image *image ) +{ + int ret; + DFBX11Shared *shared = x11->shared; + + D_MAGIC_ASSERT( image, x11Image ); + + if (fusion_call_execute( &shared->call, FCEF_NONE, X11_IMAGE_DESTROY, image, &ret )) + return DFB_FUSION; + + if (ret) { + D_DERROR( ret, "X11/Image: X11_IMAGE_DESTROY call failed!\n" ); + return ret; + } + + D_MAGIC_CLEAR( image ); + + return DFB_OK; +} + +DFBResult +x11ImageAttach( x11Image *image, + void **ret_addr ) +{ + void *addr; + + D_MAGIC_ASSERT( image, x11Image ); + D_ASSERT( ret_addr != NULL ); + + /* FIXME: We also need to DETACH! */ + + addr = shmat( image->seginfo.shmid, NULL, 0 ); + if (!addr) { + int erno = errno; + + D_PERROR( "X11/Image: shmat( %d ) failed!\n", image->seginfo.shmid ); + + return errno2result( erno ); + } + + *ret_addr = addr; + + return DFB_OK; +} + +/**********************************************************************************************************************/ + +DFBResult +dfb_x11_image_init_handler( DFBX11 *x11, x11Image *image ) +{ + Visual *visual; + XImage *ximage; + + D_MAGIC_ASSERT( image, x11Image ); + + if (!x11->use_shm) + return DFB_UNSUPPORTED; + + /* Lookup visual. */ + visual = x11->visuals[DFB_PIXELFORMAT_INDEX(image->format)]; + if (!visual) + return DFB_UNSUPPORTED; + + image->visual = visual; + + XLockDisplay( x11->display ); + + ximage = XShmCreateImage( x11->display, image->visual, image->depth, + ZPixmap, NULL, &image->seginfo, image->width, image->height ); + if (!ximage) { + D_ERROR( "X11/ShmImage: Error creating shared image (XShmCreateImage)!\n"); + XUnlockDisplay( x11->display ); + return DFB_FAILURE; + } + + /* we firstly create our shared memory segment with the size we need, and + correct permissions for the owner, the group and the world --> 0777 */ + image->seginfo.shmid = shmget( IPC_PRIVATE, + ximage->bytes_per_line * ximage->height, + IPC_CREAT | 0777 ); + if (image->seginfo.shmid < 0) + goto error; + + /* Then, we have to attach the segment to our process, and we let the + function search the correct memory place --> NULL. It's safest ! */ + image->seginfo.shmaddr = shmat( image->seginfo.shmid, NULL, 0 ); + if (!image->seginfo.shmaddr) + goto error_shmat; + + ximage->data = image->seginfo.shmaddr; + + /* We set the buffer in Read and Write mode */ + image->seginfo.readOnly = False; + + if (!XShmAttach( x11->display, &image->seginfo )) + goto error_xshmattach; + + image->ximage = ximage; + image->pitch = ximage->bytes_per_line; + + image->pixmap = XShmCreatePixmap( x11->display, DefaultRootWindow(x11->display), ximage->data, + &image->seginfo, image->width, image->height, image->depth ); + + image->gc = XCreateGC( x11->display, image->pixmap, 0, NULL ); + + XUnlockDisplay( x11->display ); + + return DFB_OK; + + +error_xshmattach: + shmdt( image->seginfo.shmaddr ); + +error_shmat: + shmctl( image->seginfo.shmid, IPC_RMID, NULL ); + +error: + XDestroyImage( ximage ); + + XUnlockDisplay( x11->display ); + + return DFB_FAILURE; +} + +DFBResult +dfb_x11_image_destroy_handler( DFBX11 *x11, x11Image *image ) +{ + D_MAGIC_ASSERT( image, x11Image ); + + XLockDisplay( x11->display ); + + XFreeGC( x11->display, image->gc ); + XFreePixmap( x11->display, image->pixmap ); + + XShmDetach( x11->display, &image->seginfo ); + + XDestroyImage( image->ximage ); + + XUnlockDisplay( x11->display ); + + shmdt( image->seginfo.shmaddr ); + + shmctl( image->seginfo.shmid, IPC_RMID, NULL ); + + return DFB_OK; +} + diff --git a/Source/DirectFB/systems/x11/x11image.h b/Source/DirectFB/systems/x11/x11image.h new file mode 100755 index 0000000..3872ef7 --- /dev/null +++ b/Source/DirectFB/systems/x11/x11image.h @@ -0,0 +1,76 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __X11SYSTEM__X11IMAGE_H__ +#define __X11SYSTEM__X11IMAGE_H__ + +#include /* fundamentals X datas structures */ +#include /* datas definitions for various functions */ +#include /* for a perfect use of keyboard events */ + +#include +#include +#include + +#include "x11types.h" + + +typedef struct { + int magic; + + int width; + int height; + DFBSurfacePixelFormat format; + + int depth; + Visual* visual; + + XImage* ximage; + int pitch; + + XShmSegmentInfo seginfo; + + Pixmap pixmap; + GC gc; +} x11Image; + + +DFBResult x11ImageInit ( DFBX11 *x11, + x11Image *image, + int width, + int height, + DFBSurfacePixelFormat format ); + +DFBResult x11ImageDestroy( DFBX11 *x11, + x11Image *image ); + +DFBResult x11ImageAttach ( x11Image *image, + void **ret_addr ); + +#endif /* __X11SYSTEM__X11IMAGE_H__ */ + diff --git a/Source/DirectFB/systems/x11/x11input.c b/Source/DirectFB/systems/x11/x11input.c new file mode 100755 index 0000000..0b711e0 --- /dev/null +++ b/Source/DirectFB/systems/x11/x11input.c @@ -0,0 +1,768 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include + +#include +#include +#include + +#include + +#include +#include +#include + + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "xwindow.h" + +#include "primary.h" +#include "x11.h" + +#define DFB_INPUTDRIVER_HAS_SENSITIVITY + +#include + +D_DEBUG_DOMAIN( X11_Input, "X11/Input", "X11 Input/Key/Mouse handling" ); + +DFB_INPUT_DRIVER( x11input ) + + +extern DFBX11 *dfb_x11; + +/* + * declaration of private data + */ +typedef struct { + CoreInputDevice* device; + DirectThread* thread; + DFBX11* x11; + bool stop; +} X11InputData; + + +static DFBInputEvent motionX = { + .type = DIET_UNKNOWN, + .axisabs = 0, +}; + +static DFBInputEvent motionY = { + .type = DIET_UNKNOWN, + .axisabs = 0, +}; + +static void +motion_compress( int x, int y, const XEvent *xEvent ) +{ + if (motionX.axisabs != x) { + motionX.type = DIET_AXISMOTION; + motionX.flags = DIEF_AXISABS | DIEF_TIMESTAMP; + motionX.axis = DIAI_X; + motionX.axisabs = x; + + motionX.timestamp.tv_sec = xEvent->xmotion.time / 1000; + motionX.timestamp.tv_usec = (xEvent->xmotion.time % 1000) * 1000; + } + + if (motionY.axisabs != y) { + motionY.type = DIET_AXISMOTION; + motionY.flags = DIEF_AXISABS | DIEF_TIMESTAMP; + motionY.axis = DIAI_Y; + motionY.axisabs = y; + + motionY.timestamp.tv_sec = xEvent->xmotion.time / 1000; + motionY.timestamp.tv_usec = (xEvent->xmotion.time % 1000) * 1000; + } +} + +static void +motion_realize( X11InputData *data ) +{ + if (motionX.type != DIET_UNKNOWN) { + if (motionY.type != DIET_UNKNOWN) + motionX.flags |= DIEF_FOLLOW; + + if (dfb_x11->shared->xw) { + motionX.flags |= DIEF_MIN | DIEF_MAX; + motionX.min = 0; + motionX.max = dfb_x11->shared->xw->width - 1; + } + + dfb_input_dispatch( data->device, &motionX ); + + motionX.type = DIET_UNKNOWN; + } + + if (motionY.type != DIET_UNKNOWN) { + if (dfb_x11->shared->xw) { + motionY.flags |= DIEF_MIN | DIEF_MAX; + motionY.min = 0; + motionY.max = dfb_x11->shared->xw->height - 1; + } + + dfb_input_dispatch( data->device, &motionY ); + + motionY.type = DIET_UNKNOWN; + } +} + +static DFBInputDeviceKeyIdentifier +xsymbol_to_id( KeySym xKeySymbol ) +{ + switch (xKeySymbol) { + case XK_a : return DIKI_A; + case XK_b : return DIKI_B; + case XK_c : return DIKI_C; + case XK_d : return DIKI_D; + case XK_e : return DIKI_E; + case XK_f : return DIKI_F; + case XK_g : return DIKI_G; + case XK_h : return DIKI_H; + case XK_i : return DIKI_I; + case XK_j : return DIKI_J; + case XK_k : return DIKI_K; + case XK_l : return DIKI_L; + case XK_m : return DIKI_M; + case XK_n : return DIKI_N; + case XK_o : return DIKI_O; + case XK_p : return DIKI_P; + case XK_q : return DIKI_Q; + case XK_r : return DIKI_R; + case XK_s : return DIKI_S; + case XK_t : return DIKI_T; + case XK_u : return DIKI_U; + case XK_v : return DIKI_V; + case XK_w : return DIKI_W; + case XK_x : return DIKI_X; + case XK_y : return DIKI_Y; + case XK_z : return DIKI_Z; + case XK_0 : return DIKI_0; + case XK_1 : return DIKI_1; + case XK_2 : return DIKI_2; + case XK_3 : return DIKI_3; + case XK_4 : return DIKI_4; + case XK_5 : return DIKI_5; + case XK_6 : return DIKI_6; + case XK_7 : return DIKI_7; + case XK_8 : return DIKI_8; + case XK_9 : return DIKI_9; + case XK_F1 : return DIKI_F1; + case XK_F2 : return DIKI_F2; + case XK_F3 : return DIKI_F3; + case XK_F4 : return DIKI_F4; + case XK_F5 : return DIKI_F5; + case XK_F6 : return DIKI_F6; + case XK_F7 : return DIKI_F7; + case XK_F8 : return DIKI_F8; + case XK_F9 : return DIKI_F9; + case XK_F10 : return DIKI_F10; + case XK_F11 : return DIKI_F11; + case XK_F12 : return DIKI_F12; + + case XK_Shift_L : return DIKI_SHIFT_L; + case XK_Shift_R : return DIKI_SHIFT_R; + case XK_Control_L : return DIKI_CONTROL_L; + case XK_Control_R : return DIKI_CONTROL_R; + case XK_Alt_L : return DIKI_ALT_L; + case XK_Alt_R : return DIKI_ALT_R; + case XK_Meta_L : return DIKI_META_L; + case XK_Meta_R : return DIKI_META_R; + case XK_Super_L : return DIKI_SUPER_L; + case XK_Super_R : return DIKI_SUPER_R; + case XK_Hyper_L : return DIKI_HYPER_L; + case XK_Hyper_R : return DIKI_HYPER_R; + case XK_Mode_switch : return DIKI_ALT_R; + + case XK_Caps_Lock : return DIKI_CAPS_LOCK; + case XK_Num_Lock : return DIKI_NUM_LOCK; + case XK_Scroll_Lock : return DIKI_SCROLL_LOCK; + + case XK_Escape : return DIKI_ESCAPE; + case XK_Left : return DIKI_LEFT; + case XK_Right : return DIKI_RIGHT; + case XK_Up : return DIKI_UP; + case XK_Down : return DIKI_DOWN; + + case XK_Tab : return DIKI_TAB; + case XK_ISO_Left_Tab : return DIKI_TAB; + case XK_Return : return DIKI_ENTER; + case XK_space : return DIKI_SPACE; + case XK_BackSpace : return DIKI_BACKSPACE; + case XK_Insert : return DIKI_INSERT; + case XK_Delete : return DIKI_DELETE; + case XK_Home : return DIKI_HOME; + case XK_End : return DIKI_END; + case XK_Page_Up : return DIKI_PAGE_UP; + case XK_Page_Down : return DIKI_PAGE_DOWN; + case XK_Print : return DIKI_PRINT; + case XK_Pause : return DIKI_PAUSE; + + /* The labels on these keys depend on the type of keyboard. + * We've choosen the names from a US keyboard layout. The + * comments refer to the ISO 9995 terminology. + */ + case XK_quoteleft : return DIKI_QUOTE_LEFT; /* TLDE */ + case XK_minus : return DIKI_MINUS_SIGN; /* AE11 */ + case XK_equal : return DIKI_EQUALS_SIGN; /* AE12 */ + case XK_bracketleft : return DIKI_BRACKET_LEFT; /* AD11 */ + case XK_bracketright : return DIKI_BRACKET_RIGHT;/* AD12 */ + case XK_backslash : return DIKI_BACKSLASH; /* BKSL */ + case XK_semicolon : return DIKI_SEMICOLON; /* AC10 */ + case XK_quoteright : return DIKI_QUOTE_RIGHT; /* AC11 */ + case XK_comma : return DIKI_COMMA; /* AB08 */ + case XK_period : return DIKI_PERIOD; /* AB09 */ + case XK_slash : return DIKI_SLASH; /* AB10 */ + case XK_less : return DIKI_LESS_SIGN; /* 103rd */ + + case XK_KP_Divide : return DIKI_KP_DIV; + case XK_KP_Multiply : return DIKI_KP_MULT; + case XK_KP_Subtract : return DIKI_KP_MINUS; + case XK_KP_Add : return DIKI_KP_PLUS; + case XK_KP_Enter : return DIKI_KP_ENTER; + case XK_KP_Space : return DIKI_KP_SPACE; + case XK_KP_Tab : return DIKI_KP_TAB; + case XK_KP_F1 : return DIKI_KP_F1; + case XK_KP_F2 : return DIKI_KP_F2; + case XK_KP_F3 : return DIKI_KP_F3; + case XK_KP_F4 : return DIKI_KP_F4; + case XK_KP_Equal : return DIKI_KP_EQUAL; + case XK_KP_Separator : return DIKI_KP_SEPARATOR; + + case XK_KP_Delete : return DIKI_KP_DECIMAL; + case XK_KP_Insert : return DIKI_KP_0; + case XK_KP_End : return DIKI_KP_1; + case XK_KP_Down : return DIKI_KP_2; + case XK_KP_Page_Down : return DIKI_KP_3; + case XK_KP_Left : return DIKI_KP_4; + case XK_KP_Begin : return DIKI_KP_5; + case XK_KP_Right : return DIKI_KP_6; + case XK_KP_Home : return DIKI_KP_7; + case XK_KP_Up : return DIKI_KP_8; + case XK_KP_Page_Up : return DIKI_KP_9; + + case XK_KP_Decimal : return DIKI_KP_DECIMAL; + case XK_KP_0 : return DIKI_KP_0; + case XK_KP_1 : return DIKI_KP_1; + case XK_KP_2 : return DIKI_KP_2; + case XK_KP_3 : return DIKI_KP_3; + case XK_KP_4 : return DIKI_KP_4; + case XK_KP_5 : return DIKI_KP_5; + case XK_KP_6 : return DIKI_KP_6; + case XK_KP_7 : return DIKI_KP_7; + case XK_KP_8 : return DIKI_KP_8; + case XK_KP_9 : return DIKI_KP_9; + + case 0 : break; + + default: + D_DEBUG_AT( X11_Input, "Unknown key symbol 0x%lx\n", xKeySymbol); + } + + return DIKI_UNKNOWN; +} + +static DFBInputDeviceKeySymbol +xsymbol_to_symbol( KeySym xKeySymbol ) +{ + if (xKeySymbol >= 0x20 && xKeySymbol <= 0xff) + return xKeySymbol; + + if (xKeySymbol >= XK_F1 && xKeySymbol <= XK_F35) + return DFB_FUNCTION_KEY( xKeySymbol - XK_F1 + 1 ); + + switch (xKeySymbol) { + case XK_Shift_L : return DIKS_SHIFT; + case XK_Shift_R : return DIKS_SHIFT; + case XK_Control_L : return DIKS_CONTROL; + case XK_Control_R : return DIKS_CONTROL; + case XK_Alt_L : return DIKS_ALT; + case XK_Alt_R : return DIKS_ALT; + case XK_Meta_L : return DIKS_META; + case XK_Meta_R : return DIKS_META; + case XK_Super_L : return DIKS_SUPER; + case XK_Super_R : return DIKS_SUPER; + case XK_Hyper_L : return DIKS_HYPER; + case XK_Hyper_R : return DIKS_HYPER; + case XK_Mode_switch : return DIKS_ALTGR; + + case XK_Caps_Lock : return DIKS_CAPS_LOCK; + case XK_Num_Lock : return DIKS_NUM_LOCK; + case XK_Scroll_Lock : return DIKS_SCROLL_LOCK; + + case XK_Escape : return DIKS_ESCAPE; + case XK_Left : return DIKS_CURSOR_LEFT; + case XK_Right : return DIKS_CURSOR_RIGHT; + case XK_Up : return DIKS_CURSOR_UP; + case XK_Down : return DIKS_CURSOR_DOWN; + + case XK_Tab : return DIKS_TAB; + case XK_ISO_Left_Tab : return DIKS_TAB; + case XK_Return : return DIKS_ENTER; + case XK_space : return DIKS_SPACE; + case XK_BackSpace : return DIKS_BACKSPACE; + case XK_Insert : return DIKS_INSERT; + case XK_Delete : return DIKS_DELETE; + case XK_Home : return DIKS_HOME; + case XK_End : return DIKS_END; + case XK_Page_Up : return DIKS_PAGE_UP; + case XK_Page_Down : return DIKS_PAGE_DOWN; + case XK_Print : return DIKS_PRINT; + case XK_Pause : return DIKS_PAUSE; + + case XK_KP_Divide : return DIKS_SLASH; + case XK_KP_Multiply : return DIKS_ASTERISK; + case XK_KP_Subtract : return DIKS_MINUS_SIGN; + case XK_KP_Add : return DIKS_PLUS_SIGN; + case XK_KP_Enter : return DIKS_ENTER; + case XK_KP_Space : return DIKS_SPACE; + case XK_KP_Tab : return DIKS_TAB; + case XK_KP_F1 : return DIKS_F1; + case XK_KP_F2 : return DIKS_F2; + case XK_KP_F3 : return DIKS_F3; + case XK_KP_F4 : return DIKS_F4; + case XK_KP_Equal : return DIKS_EQUALS_SIGN; + case XK_KP_Separator : return DIKS_COLON; /* FIXME: what is a separator */ + + case XK_KP_Delete : return DIKS_DELETE; + case XK_KP_Insert : return DIKS_INSERT; + case XK_KP_End : return DIKS_END; + case XK_KP_Down : return DIKS_CURSOR_DOWN; + case XK_KP_Page_Down : return DIKS_PAGE_DOWN; + case XK_KP_Left : return DIKS_CURSOR_LEFT; + case XK_KP_Begin : return DIKS_BEGIN; + case XK_KP_Right : return DIKS_CURSOR_RIGHT; + case XK_KP_Home : return DIKS_HOME; + case XK_KP_Up : return DIKS_CURSOR_UP; + case XK_KP_Page_Up : return DIKS_PAGE_UP; + + case XK_KP_Decimal : return DIKS_PERIOD; + case XK_KP_0 : return DIKS_0; + case XK_KP_1 : return DIKS_1; + case XK_KP_2 : return DIKS_2; + case XK_KP_3 : return DIKS_3; + case XK_KP_4 : return DIKS_4; + case XK_KP_5 : return DIKS_5; + case XK_KP_6 : return DIKS_6; + case XK_KP_7 : return DIKS_7; + case XK_KP_8 : return DIKS_8; + case XK_KP_9 : return DIKS_9; + + case 0 : break; + + default: + D_DEBUG("X11: Unknown key symbol 0x%lx\n", xKeySymbol); + } + + return DIKS_NULL; +} + + + +static void handleMouseEvent(XEvent* pXEvent, X11InputData* pData) +{ + static int iMouseEventCount = 0; + DFBInputEvent dfbEvent; + if (pXEvent->type == MotionNotify) { + motion_compress( pXEvent->xmotion.x, pXEvent->xmotion.y, pXEvent ); + ++iMouseEventCount; + } + + if ( pXEvent->type == ButtonPress || pXEvent->type == ButtonRelease ) { + if ( pXEvent->type == ButtonPress ) + dfbEvent.type = DIET_BUTTONPRESS; + else + dfbEvent.type = DIET_BUTTONRELEASE; + + dfbEvent.flags = DIEF_TIMESTAMP; + + /* Get pressed button */ + switch ( pXEvent->xbutton.button ) { + case 1: + dfbEvent.button = DIBI_LEFT; + break; + case 2: + dfbEvent.button = DIBI_MIDDLE; + break; + case 3: + dfbEvent.button = DIBI_RIGHT; + break; + //Wheel events + case 4: /*up*/ + case 5: /*down*/ + case 6: /*left*/ + case 7: /*right*/ + if (pXEvent->type == ButtonPress) { + dfbEvent.type = DIET_AXISMOTION; + dfbEvent.flags = DIEF_AXISREL; + dfbEvent.axis = DIAI_Z; + /*SCROLL UP*/ + if ( pXEvent->xbutton.button == 4 ) { + dfbEvent.axisrel = -1; + } + /*SCROLL DOWN */ + else if (pXEvent->xbutton.button == 5) { + dfbEvent.axisrel = 1; + } + /*SCROLL LEFT*/ + else if (pXEvent->xbutton.button == 6) { + dfbEvent.axis = DIAI_X; + dfbEvent.axisrel = -1; + } + /*SCROLL RIGHT*/ + else if (pXEvent->xbutton.button == 7 ) { + dfbEvent.axis = DIAI_X; + dfbEvent.axisrel = 1; + } + } + else + return; + break; + default: + break; + } + + dfbEvent.timestamp.tv_sec = pXEvent->xbutton.time / 1000; + dfbEvent.timestamp.tv_usec = (pXEvent->xbutton.time % 1000) * 1000; + + dfb_input_dispatch( pData->device, &dfbEvent ); + ++iMouseEventCount; + } +} + +static void +handle_expose( const XExposeEvent *expose ) +{ + CoreLayer *layer = dfb_layer_at( DLID_PRIMARY ); + const DisplayLayerFuncs *funcs = layer->funcs; + CoreLayerContext *context; + + D_ASSERT( funcs != NULL ); + D_ASSERT( funcs->UpdateRegion != NULL ); + + /* Get the currently active context. */ + if (dfb_layer_get_active_context( layer, &context ) == DFB_OK) { + CoreLayerRegion *region; + + /* Get the first region. */ + if (dfb_layer_context_get_primary_region( context, + false, ®ion ) == DFB_OK) + { + /* Lock the region to avoid tearing due to concurrent updates. */ + dfb_layer_region_lock( region ); + + /* Get the surface of the region. */ + if (region->surface && region->surface_lock.buffer) { + DFBRegion update = { expose->x, expose->y, + expose->x + expose->width - 1, + expose->y + expose->height - 1 }; + + funcs->UpdateRegion( layer, layer->driver_data, layer->layer_data, + region->region_data, region->surface, &update, ®ion->surface_lock ); + } + + /* Unlock the region. */ + dfb_layer_region_unlock( region ); + + /* Release the region. */ + dfb_layer_region_unref( region ); + } + + /* Release the context. */ + dfb_layer_context_unref( context ); + } +} + +/* + * Input thread reading from device. + * Generates events on incoming data. + */ +static void* +x11EventThread( DirectThread *thread, void *driver_data ) +{ + X11InputData *data = driver_data; + DFBX11 *x11 = data->x11; + DFBX11Shared *shared = x11->shared; + + while (!data->stop) { + unsigned int pull = 23; + XEvent xEvent; + DFBInputEvent dfbEvent; + + /* FIXME: Detect key repeats, we're receiving KeyPress, KeyRelease, KeyPress, KeyRelease... !!?? */ + + if (!shared->xw || !shared->xw->window) { + /* no window, so no event */ + usleep( 50000 ); + continue; + } + + usleep( 10000 ); + + XLockDisplay( x11->display ); + + while (!data->stop && pull-- && XPending( x11->display )) { + XNextEvent( x11->display, &xEvent ); + + XUnlockDisplay( x11->display ); + + D_DEBUG_AT( X11_Input, "Event received: %d\n", xEvent.type ); + + switch (xEvent.type) { + case ButtonPress: + case ButtonRelease: + motion_realize( data ); + case MotionNotify: + handleMouseEvent( &xEvent, data ); // crash ??? + break; + + case KeyPress: + case KeyRelease: { + motion_realize( data ); + + dfbEvent.type = (xEvent.type == KeyPress) ? DIET_KEYPRESS : DIET_KEYRELEASE; + dfbEvent.flags = DIEF_KEYCODE | DIEF_TIMESTAMP; + dfbEvent.key_code = xEvent.xkey.keycode; + + dfbEvent.timestamp.tv_sec = xEvent.xkey.time / 1000; + dfbEvent.timestamp.tv_usec = (xEvent.xkey.time % 1000) * 1000; + + dfb_input_dispatch( data->device, &dfbEvent ); + break; + } + + case Expose: + handle_expose( &xEvent.xexpose ); + break; + + case DestroyNotify: + /* this event is mainly to unblock XNextEvent. */ + break; + + default: + break; + } + + XLockDisplay( x11->display ); + } + + XUnlockDisplay( x11->display ); + + if (!data->stop) + motion_realize( data ); + } + + return NULL; +} + +/* exported symbols */ + +/* + * Return the number of available devices. + * Called once during initialization of DirectFB. + */ +static int +driver_get_available( void ) +{ + return dfb_system_type() == CORE_X11; +} + +/* + * Fill out general information about this driver. + * Called once during initialization of DirectFB. + */ +static void +driver_get_info( InputDriverInfo *info ) +{ + /* fill driver info structure */ + snprintf ( info->name, DFB_INPUT_DRIVER_INFO_NAME_LENGTH, "X11 Input Driver" ); + snprintf ( info->vendor, DFB_INPUT_DRIVER_INFO_VENDOR_LENGTH, "directfb.org" ); + + info->version.major = 0; + info->version.minor = 1; +} + +/* + * Open the device, fill out information about it, + * allocate and fill private data, start input thread. + * Called during initialization, resuming or taking over mastership. + */ +static DFBResult +driver_open_device( CoreInputDevice *device, + unsigned int number, + InputDeviceInfo *info, + void **driver_data ) +{ + X11InputData *data; + DFBX11 *x11 = dfb_system_data(); + DFBX11Shared *shared = x11->shared; + + D_DEBUG_AT( X11_Input, "%s()\n", __FUNCTION__ ); + + fusion_skirmish_prevail( &shared->lock ); + + fusion_skirmish_dismiss( &shared->lock ); + + /* set device vendor and name */ + snprintf( info->desc.vendor, DFB_INPUT_DEVICE_DESC_VENDOR_LENGTH, "XServer" ); + snprintf( info->desc.name, DFB_INPUT_DEVICE_DESC_NAME_LENGTH, "X11 Input" ); + + /* set one of the primary input device IDs */ + info->prefered_id = DIDID_KEYBOARD; + + /* set type flags */ + info->desc.type = DIDTF_JOYSTICK | DIDTF_KEYBOARD | DIDTF_MOUSE; + + /* set capabilities */ + info->desc.caps = DICAPS_ALL; + + /* enable translation of fake raw hardware keycodes */ + info->desc.min_keycode = 8; + info->desc.max_keycode = 255; + + + /* allocate and fill private data */ + data = D_CALLOC( 1, sizeof(X11InputData) ); + + data->device = device; + data->x11 = x11; + + /* start input thread */ + data->thread = direct_thread_create( DTT_INPUT, x11EventThread, data, "X11 Input" ); + + /* set private data pointer */ + *driver_data = data; + + return DFB_OK; +} + +/* + * Fetch one entry from the device's keymap if supported. + * this does a fake mapping based on the orginal DFB code + */ +static DFBResult +driver_get_keymap_entry( CoreInputDevice *device, + void *driver_data, + DFBInputDeviceKeymapEntry *entry ) +{ + int i; + X11InputData *data = driver_data; + DFBX11 *x11 = data->x11; + + XLockDisplay( x11->display ); + + for (i=0; i<4; i++) { + KeySym xSymbol = XKeycodeToKeysym( x11->display, entry->code, i ); + + if (i == 0) + entry->identifier = xsymbol_to_id( xSymbol ); + + entry->symbols[i] = xsymbol_to_symbol( xSymbol ); + } + + XUnlockDisplay( x11->display ); + + /* is CapsLock effective? */ + if (entry->identifier >= DIKI_A && entry->identifier <= DIKI_Z) + entry->locks |= DILS_CAPS; + + /* is NumLock effective? */ + if (entry->identifier >= DIKI_KP_DECIMAL && entry->identifier <= DIKI_KP_9) + entry->locks |= DILS_NUM; + + return DFB_OK; +} + +/* + * End thread, close device and free private data. + */ +static DFBResult +driver_set_sensitivity( CoreInputDevice *device, + void *driver_data, + int sensitivity ) +{ + D_DEBUG_AT( X11_Input, "%s( %d )\n", __FUNCTION__, sensitivity ); + + return DFB_OK; +} + +/* + * End thread, close device and free private data. + */ +static void +driver_close_device( void *driver_data ) +{ + X11InputData *data = driver_data; + DFBX11 *x11 = data->x11; + DFBX11Shared *shared = x11->shared; + + D_DEBUG_AT( X11_Input, "%s()\n", __FUNCTION__ ); + + /* stop input thread */ + data->stop = true; + + XLockDisplay( x11->display ); + + if (shared->xw) { + XWindow *xw = shared->xw; + + shared->xw = NULL; + + /* the window must generate an event, otherwise the input thread will not end */ + dfb_x11_close_window( x11, xw ); + } + + XSync( x11->display, False ); + + XUnlockDisplay( x11->display ); + + /* it is possible that this "close" function is called from the same + * thread that the input device is actually running on. + * This happens when you e.g. click the close box with your mouse. + * As a fix, we check if we are this thread. */ + if (data->thread != direct_thread_self()) { + direct_thread_join( data->thread ); + direct_thread_destroy( data->thread ); + } + + /* free private data */ + D_FREE ( data ); +} + diff --git a/Source/DirectFB/systems/x11/x11types.h b/Source/DirectFB/systems/x11/x11types.h new file mode 100755 index 0000000..872f9db --- /dev/null +++ b/Source/DirectFB/systems/x11/x11types.h @@ -0,0 +1,35 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __SYSTEMS_X11TYPES_H__ +#define __SYSTEMS_X11TYPES_H__ + +typedef struct __DFB_X11 DFBX11; + +#endif /* __SYSTEMS_X11TYPES_H__ */ + diff --git a/Source/DirectFB/systems/x11/xwindow.c b/Source/DirectFB/systems/x11/xwindow.c new file mode 100755 index 0000000..ce5e1fe --- /dev/null +++ b/Source/DirectFB/systems/x11/xwindow.c @@ -0,0 +1,294 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include + +#include +#include +#include + +#include + +#include + +#include "x11.h" + +D_DEBUG_DOMAIN( X11_Window, "X11/Window", "X11 Window handling" ); + +static bool use_shm = true; + +static int +error_handler_shm( Display *display, XErrorEvent *event ) +{ + if (use_shm) { + D_INFO( "X11/Display: Error! Disabling XShm.\n" ); + + use_shm = false; + } + + return 0; +} + + +static int error_code = 0; + +static int +error_handler( Display *display, XErrorEvent *event ) +{ + char buf[512]; + + D_DEBUG_AT( X11_Window, "%s()\n", __FUNCTION__ ); + + XGetErrorText( display, event->error_code, buf, sizeof(buf) ); + + D_ERROR( "X11/Window: Error! %s\n", buf ); + + error_code = event->error_code; + + return 0; +} + +Bool +dfb_x11_open_window( DFBX11 *x11, XWindow** ppXW, int iXPos, int iYPos, int iWidth, int iHeight, DFBSurfacePixelFormat format ) +{ + XWindow *xw; + XSetWindowAttributes attr = { .background_pixmap = 0 }; + + D_DEBUG_AT( X11_Window, "Creating %4dx%4d %s window...\n", iWidth, iHeight, dfb_pixelformat_name(format) ); + + xw = D_CALLOC( 1, sizeof(XWindow) ); + if (!xw) + return D_OOM(); + + /* We set the structure as needed for our window */ + xw->width = iWidth; + xw->height = iHeight; + xw->display = x11->display; + + xw->screenptr = DefaultScreenOfDisplay(xw->display); + xw->screennum = DefaultScreen(xw->display); + xw->depth = DefaultDepthOfScreen(xw->screenptr); + xw->visual = DefaultVisualOfScreen(xw->screenptr); + + attr.event_mask = + ButtonPressMask + | ButtonReleaseMask + | PointerMotionMask + | KeyPressMask + | KeyReleaseMask + | ExposureMask + | StructureNotifyMask; + + XLockDisplay( x11->display ); + + XSetErrorHandler( error_handler ); + + error_code = 0; + + xw->window = XCreateWindow( xw->display, + RootWindowOfScreen(xw->screenptr), + iXPos, iYPos, iWidth, iHeight, 0, xw->depth, InputOutput, + xw->visual, CWEventMask, &attr ); + XSync( xw->display, False ); + if (!xw->window || error_code) { + D_FREE( xw ); + XUnlockDisplay( x11->display ); + return False; + } + + + XSizeHints Hints; + + /* + * Here we inform the function of what we are going to change for the + * window (there's also PPosition but it's obsolete) + */ + Hints.flags = PSize | PMinSize | PMaxSize; + + /* + * Now we set the structure to the values we need for width & height. + * For esthetic reasons we set Width=MinWidth=MaxWidth. + * The same goes for Height. You can try whith differents values, or + * let's use Hints.flags=Psize; and resize your window.. + */ + Hints.min_width = Hints.max_width = Hints.base_width = xw->width; + Hints.min_height = Hints.max_height = Hints.base_height = xw->height; + + /* Now we can set the size hints for the specified window */ + XSetWMNormalHints(xw->display,xw->window,&Hints); + + /* We change the title of the window (default:Untitled) */ + XStoreName(xw->display,xw->window,"DFB X11 system window"); + + xw->gc = XCreateGC(xw->display, xw->window, 0, NULL); + + // Create a null cursor + XColor fore; + XColor back; + char zero = 0; + + xw->pixmp1 = XCreateBitmapFromData( xw->display, xw->window, &zero, 1, 1 ); + xw->pixmp2 = XCreateBitmapFromData( xw->display, xw->window, &zero, 1, 1 ); + + xw->NullCursor = XCreatePixmapCursor( xw->display, xw->pixmp1, xw->pixmp2, &fore, &back, 0, 0 ); + + XDefineCursor( xw->display, xw->window, xw->NullCursor ); + + + /* maps the window and raises it to the top of the stack */ + XMapRaised( xw->display, xw->window ); + + + if (x11->use_shm) { + // Shared memory + xw->shmseginfo=(XShmSegmentInfo *)D_CALLOC(1, sizeof(XShmSegmentInfo)); + if (!xw->shmseginfo) { + x11->use_shm = false; + goto no_shm; + } + + xw->ximage=XShmCreateImage(xw->display, xw->visual, xw->depth, ZPixmap, + NULL,xw->shmseginfo, xw->width, xw->height * 2); + XSync( xw->display, False ); + if (!xw->ximage || error_code) { + D_ERROR("X11: Error creating shared image (XShmCreateImage) \n"); + x11->use_shm = false; + D_FREE(xw->shmseginfo); + error_code = 0; + goto no_shm; + } + + xw->bpp = (xw->ximage->bits_per_pixel + 7) / 8; + + /* we firstly create our shared memory segment with the size we need, and + correct permissions for the owner, the group and the world --> 0777 */ + xw->shmseginfo->shmid=shmget(IPC_PRIVATE, + xw->ximage->bytes_per_line * xw->ximage->height * 2, + IPC_CREAT|0777); + + if (xw->shmseginfo->shmid<0) { + x11->use_shm = false; + XDestroyImage(xw->ximage); + D_FREE(xw->shmseginfo); + goto no_shm; + } + + /* Then, we have to attach the segment to our process, and we let the + function search the correct memory place --> NULL. It's safest ! */ + xw->shmseginfo->shmaddr = shmat( xw->shmseginfo->shmid, NULL, 0 ); + if (!xw->shmseginfo->shmaddr) { + x11->use_shm = false; + shmctl(xw->shmseginfo->shmid,IPC_RMID,NULL); + XDestroyImage(xw->ximage); + D_FREE(xw->shmseginfo); + goto no_shm; + } + + /* We set the buffer in Read and Write mode */ + xw->shmseginfo->readOnly=False; + + xw->virtualscreen= xw->ximage->data = xw->shmseginfo->shmaddr; + + + XSetErrorHandler( error_handler_shm ); + + XShmAttach(x11->display,xw->shmseginfo); + + XShmPutImage(x11->display, xw->window, xw->gc, xw->ximage, + 0, 0, 0, 0, 1, 1, False); + + XSync(x11->display, False); + + XSetErrorHandler( error_handler ); + + if (!x11->use_shm) { + shmdt(xw->shmseginfo->shmaddr); + shmctl(xw->shmseginfo->shmid,IPC_RMID,NULL); + XDestroyImage(xw->ximage); + D_FREE(xw->shmseginfo); + } + } + +no_shm: + if (!x11->use_shm) { + int pitch; + + xw->bpp = (xw->depth > 16) ? 4 : + (xw->depth > 8) ? 2 : 1; + + pitch = (xw->bpp * xw->width + 3) & ~3; + + /* Use malloc(), not D_MALLOC() here, because XCreateImage() + * will call free() on this data. + */ + xw->virtualscreen = malloc ( 2 * xw->height * pitch ); + + xw->ximage = XCreateImage( xw->display, xw->visual, xw->depth, ZPixmap, 0, + xw->virtualscreen, xw->width, xw->height * 2, 32, pitch ); + XSync( xw->display, False ); + if (!xw->ximage || error_code) { + D_ERROR( "X11/Window: XCreateImage( Visual %02lu, depth %d, size %dx%d, buffer %p [%d] ) failed!\n", + xw->visual->visualid, xw->depth, xw->width, xw->height * 2, xw->virtualscreen, pitch ); + XFreeGC(xw->display,xw->gc); + XDestroyWindow(xw->display,xw->window); + XSetErrorHandler( NULL ); + XUnlockDisplay( x11->display ); + D_FREE( xw ); + return False; + } + } + + XSetErrorHandler( NULL ); + + XUnlockDisplay( x11->display ); + + D_INFO( "X11/Display: %ssing XShm.\n", x11->use_shm ? "U" : "Not u" ); + + (*ppXW) = xw; + + return True; +} + +void +dfb_x11_close_window( DFBX11 *x11, XWindow* xw ) +{ + if (x11->use_shm) { + XShmDetach(xw->display, xw->shmseginfo); + shmdt(xw->shmseginfo->shmaddr); + shmctl(xw->shmseginfo->shmid,IPC_RMID,NULL); + D_FREE(xw->shmseginfo); + } + + XDestroyImage(xw->ximage); + + XFreeGC(xw->display,xw->gc); + XDestroyWindow(xw->display,xw->window); + + D_FREE(xw); +} + diff --git a/Source/DirectFB/systems/x11/xwindow.h b/Source/DirectFB/systems/x11/xwindow.h new file mode 100755 index 0000000..9eddfd7 --- /dev/null +++ b/Source/DirectFB/systems/x11/xwindow.h @@ -0,0 +1,77 @@ +/* + (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org) + (c) Copyright 2000-2004 Convergence (integrated media) GmbH + + All rights reserved. + + Written by Denis Oliver Kropp , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#ifndef __SYSTEMS_XWINDOW_H__ +#define __SYSTEMS_XWINDOW_H__ + +#include /* fundamentals X datas structures */ +#include /* datas definitions for various functions */ +#include /* for a perfect use of keyboard events */ + +#include +#include +#include + +#include "x11types.h" + + +typedef struct { + Display* display; + Window window; + Screen* screenptr; + int screennum; + Visual* visual; + GC gc; + XImage* ximage; + int ximage_offset; + Colormap colormap; + + XShmSegmentInfo* shmseginfo; + unsigned char* videomemory; + + char* virtualscreen; + int videoaccesstype; + + int width; + int height; + int depth; + int bpp; + + /* (Null) cursor stuff*/ + Pixmap pixmp1; + Pixmap pixmp2; + Cursor NullCursor; +} XWindow; + +Bool dfb_x11_open_window ( DFBX11 *x11, XWindow** ppXW, int iXPos, int iYPos, int iWidth, int iHeight, DFBSurfacePixelFormat format ); +void dfb_x11_close_window( DFBX11 *x11, XWindow* pXW ); + + + +#endif /* __SYSTEMS_XWINDOW_H__ */ + -- cgit