From 5e6fff7ac4a4e0d06d394391f6e2dd2eb6ff8aee Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Sun, 19 Jul 2009 09:22:31 +0200 Subject: svga: Do the gallium intel configure trick for svga as well Since the drivers we produce on systems where we use configure depend on none stable kernel API the driver deliverables should not be built by default in the mesa 7.7 release. People wishing to shoot them self in the foot have to pull the trigger themself, we just hand them the gun. --- configure.ac | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'configure.ac') diff --git a/configure.ac b/configure.ac index 25e4321510..e15e1f60c4 100644 --- a/configure.ac +++ b/configure.ac @@ -1200,13 +1200,15 @@ dnl dnl Gallium SVGA configuration dnl AC_ARG_ENABLE([gallium-svga], - [AS_HELP_STRING([--disable-gallium-svga], - [build gallium SVGA @<:@default=enabled@:>@])], + [AS_HELP_STRING([--enable-gallium-svga], + [build gallium SVGA @<:@default=disabled@:>@])], [enable_gallium_svga="$enableval"], - [enable_gallium_svga=yes]) + [enable_gallium_svga=auto]) if test "x$enable_gallium_svga" = xyes; then GALLIUM_WINSYS_DRM_DIRS="$GALLIUM_WINSYS_DRM_DIRS vmware" GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS svga" +elif test "x$enable_gallium_svga" = xauto; then + GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS svga" fi dnl -- cgit v1.2.3 From ce4f23aab9e10675a569bab92d0edcbca7399d33 Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Wed, 4 Nov 2009 23:02:13 +0000 Subject: i965g: Build with configure --- configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'configure.ac') diff --git a/configure.ac b/configure.ac index 910c0b1a4b..11887edc52 100644 --- a/configure.ac +++ b/configure.ac @@ -1191,8 +1191,8 @@ AC_ARG_ENABLE([gallium-intel], [enable_gallium_intel="$enableval"], [enable_gallium_intel=yes]) if test "x$enable_gallium_intel" = xyes; then - GALLIUM_WINSYS_DRM_DIRS="$GALLIUM_WINSYS_DRM_DIRS intel" - GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS i915" + GALLIUM_WINSYS_DRM_DIRS="$GALLIUM_WINSYS_DRM_DIRS intel i965" + GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS i915 i965" fi dnl -- cgit v1.2.3 From 60769b232c8eedddc24f25ab91f35bcb6973dded Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Thu, 12 Nov 2009 01:28:26 +0100 Subject: svga: Build svga driver --- SConstruct | 8 ++++---- configs/default | 2 +- configs/linux-dri | 2 +- configure.ac | 13 +++++++++++++ src/gallium/winsys/drm/SConscript | 5 +++++ 5 files changed, 24 insertions(+), 6 deletions(-) (limited to 'configure.ac') diff --git a/SConstruct b/SConstruct index d53f4401e5..f43c10cecb 100644 --- a/SConstruct +++ b/SConstruct @@ -32,10 +32,10 @@ import common default_statetrackers = 'mesa' if common.default_platform in ('linux', 'freebsd', 'darwin'): - default_drivers = 'softpipe,failover,i915,trace,identity,llvmpipe' + default_drivers = 'softpipe,failover,svga,i915,trace,identity,llvmpipe' default_winsys = 'xlib' elif common.default_platform in ('winddk',): - default_drivers = 'softpipe,i915,trace,identity' + default_drivers = 'softpipe,svga,i915,trace,identity' default_winsys = 'all' else: default_drivers = 'all' @@ -46,9 +46,9 @@ common.AddOptions(opts) opts.Add(ListVariable('statetrackers', 'state trackers to build', default_statetrackers, ['mesa', 'python', 'xorg'])) opts.Add(ListVariable('drivers', 'pipe drivers to build', default_drivers, - ['softpipe', 'failover', 'i915', 'cell', 'trace', 'r300', 'identity', 'llvmpipe'])) + ['softpipe', 'failover', 'svga', 'i915', 'cell', 'trace', 'r300', 'identity', 'llvmpipe'])) opts.Add(ListVariable('winsys', 'winsys drivers to build', default_winsys, - ['xlib', 'intel', 'gdi', 'radeon'])) + ['xlib', 'vmware', 'intel', 'gdi', 'radeon'])) opts.Add(EnumVariable('MSVS_VERSION', 'MS Visual C++ version', None, allowed_values=('7.1', '8.0', '9.0'))) diff --git a/configs/default b/configs/default index c3bb47e70d..9af816cf9b 100644 --- a/configs/default +++ b/configs/default @@ -96,7 +96,7 @@ EGL_DRIVERS_DIRS = demo GALLIUM_DIRS = auxiliary drivers state_trackers GALLIUM_AUXILIARY_DIRS = rbug draw translate cso_cache pipebuffer tgsi sct rtasm util indices vl GALLIUM_AUXILIARIES = $(foreach DIR,$(GALLIUM_AUXILIARY_DIRS),$(TOP)/src/gallium/auxiliary/$(DIR)/lib$(DIR).a) -GALLIUM_DRIVERS_DIRS = softpipe i915 failover trace identity +GALLIUM_DRIVERS_DIRS = softpipe failover svga i915 trace identity GALLIUM_DRIVERS = $(foreach DIR,$(GALLIUM_DRIVERS_DIRS),$(TOP)/src/gallium/drivers/$(DIR)/lib$(DIR).a) GALLIUM_WINSYS_DIRS = xlib egl_xlib GALLIUM_WINSYS_DRM_DIRS = diff --git a/configs/linux-dri b/configs/linux-dri index 6c3c0ab921..0802543347 100644 --- a/configs/linux-dri +++ b/configs/linux-dri @@ -60,7 +60,7 @@ EGL_DRIVERS_DIRS = demo glx DRIVER_DIRS = dri WINDOW_SYSTEM = dri GALLIUM_WINSYS_DIRS = drm -GALLIUM_WINSYS_DRM_DIRS = intel +GALLIUM_WINSYS_DRM_DIRS = vmware intel GALLIUM_STATE_TRACKERS_DIRS = egl DRI_DIRS = i810 i915 i965 mach64 mga r128 r200 r300 radeon \ diff --git a/configure.ac b/configure.ac index cc588d5fab..f9476a46dd 100644 --- a/configure.ac +++ b/configure.ac @@ -1189,6 +1189,19 @@ AC_ARG_WITH([max-height], [AC_MSG_WARN([Large framebuffer: see s_tritemp.h comments.])])] ) +dnl +dnl Gallium SVGA configuration +dnl +AC_ARG_ENABLE([gallium-svga], + [AS_HELP_STRING([--disable-gallium-svga], + [build gallium SVGA @<:@default=enabled@:>@])], + [enable_gallium_svga="$enableval"], + [enable_gallium_svga=yes]) +if test "x$enable_gallium_svga" = xyes; then + GALLIUM_WINSYS_DRM_DIRS="$GALLIUM_WINSYS_DRM_DIRS vmware" + GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS svga" +fi + dnl dnl Gallium Intel configuration dnl diff --git a/src/gallium/winsys/drm/SConscript b/src/gallium/winsys/drm/SConscript index a9e9f2682a..9f7b383d2d 100644 --- a/src/gallium/winsys/drm/SConscript +++ b/src/gallium/winsys/drm/SConscript @@ -48,6 +48,11 @@ if env['dri']: # $(INSTALL) -d $(DRI_DRIVER_INSTALL_DIR) # $(INSTALL) -m 755 $(LIBNAME) $(DRI_DRIVER_INSTALL_DIR) + if 'vmware' in env['winsys']: + SConscript([ + 'vmware/SConscript', + ]) + if 'intel' in env['winsys']: SConscript([ 'intel/SConscript', -- cgit v1.2.3 From 8ac2503397c0618db9caec1c702622830e1268ff Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Fri, 4 Dec 2009 16:01:41 +0000 Subject: i915g: Do not build winsys and binaries by default Using a hack in the configure script the gallium intel drivers have 3 options. Off, nothing is built. On, the driver and binaries are built. Auto, only the driver but not the binaries and winsys is built. Since the i915g driver builds everywhere its can enable the driver per default, so we can get build coverage. But building the binaries per default is a pain for distributions and testers since they conflict on the install target with the old mesa drivers. Which are more stable/faster/better. So this change gives us the best of both worlds. --- configure.ac | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'configure.ac') diff --git a/configure.ac b/configure.ac index f9476a46dd..054857d559 100644 --- a/configure.ac +++ b/configure.ac @@ -1206,13 +1206,15 @@ dnl dnl Gallium Intel configuration dnl AC_ARG_ENABLE([gallium-intel], - [AS_HELP_STRING([--disable-gallium-intel], - [build gallium intel @<:@default=enabled@:>@])], + [AS_HELP_STRING([--enable-gallium-intel], + [build gallium intel @<:@default=disabled@:>@])], [enable_gallium_intel="$enableval"], - [enable_gallium_intel=yes]) + [enable_gallium_intel=auto]) if test "x$enable_gallium_intel" = xyes; then GALLIUM_WINSYS_DRM_DIRS="$GALLIUM_WINSYS_DRM_DIRS intel" GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS i915" +elif test "x$enable_gallium_intel" = xauto; then + GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS i915" fi dnl -- cgit v1.2.3 From bc0532b0ed3c6dca3a198c64384636d96b2056ef Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Fri, 4 Dec 2009 18:50:29 +0000 Subject: gallium: DRI drivers enabled by default, Xorg drivers auto by default. This change enabled gallium dri drivers by default under the configure build system. Xorg drivers are built automaticaly if a Xorg dev enviroment is installed and the Xorg version is higher then 1.6.0. --- configure.ac | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'configure.ac') diff --git a/configure.ac b/configure.ac index 054857d559..25e4321510 100644 --- a/configure.ac +++ b/configure.ac @@ -1143,7 +1143,14 @@ yes) GALLIUM_STATE_TRACKERS_DIRS=glx ;; dri) - test "x$enable_egl" = xyes && GALLIUM_STATE_TRACKERS_DIRS=egl + GALLIUM_STATE_TRACKERS_DIRS="dri" + if test "x$enable_egl" = xyes; then + GALLIUM_STATE_TRACKERS_DIRS="$GALLIUM_STATE_TRACKERS_DIRS egl" + fi + # Have only tested st/xorg on 1.6.0 servers + PKG_CHECK_MODULES(XORG, [xorg-server >= 1.6.0], + HAVE_XORG="yes"; GALLIUM_STATE_TRACKERS_DIRS="$GALLIUM_STATE_TRACKERS_DIRS xorg", + HAVE_XORG="no") ;; esac ;; -- cgit v1.2.3 From 2f127e5236ca3c53bfe25fc4ffcfe16ae55ed42b Mon Sep 17 00:00:00 2001 From: Sedat Dilek Date: Thu, 17 Dec 2009 19:14:53 +0100 Subject: configure.ac: Add glsl to SRC_DIRS Signed-off-by: Brian Paul --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'configure.ac') diff --git a/configure.ac b/configure.ac index 25e4321510..6fa0a605e0 100644 --- a/configure.ac +++ b/configure.ac @@ -413,7 +413,7 @@ esac dnl dnl Driver specific build directories dnl -SRC_DIRS="mesa glew" +SRC_DIRS="glsl mesa glew" GLU_DIRS="sgi" WINDOW_SYSTEM="" GALLIUM_DIRS="auxiliary drivers state_trackers" -- cgit v1.2.3 From ae1c0a06e81b8c6f015a3b64616a5d3a989f9373 Mon Sep 17 00:00:00 2001 From: Fabio Pedretti Date: Tue, 22 Dec 2009 10:43:35 +1000 Subject: configure.ac: fix for libdrm_radeon API changes. --- configure.ac | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'configure.ac') diff --git a/configure.ac b/configure.ac index 6fa0a605e0..944108b08e 100644 --- a/configure.ac +++ b/configure.ac @@ -19,6 +19,7 @@ AC_CANONICAL_HOST dnl Versions for external dependencies LIBDRM_REQUIRED=2.4.15 +LIBDRM_RADEON_REQUIRED=2.4.17 DRI2PROTO_REQUIRED=1.99.3 dnl Check for progs @@ -577,7 +578,7 @@ dri) GL_PC_REQ_PRIV="libdrm >= $LIBDRM_REQUIRED dri2proto >= $DRI2PROTO_REQUIRED" DRI_PC_REQ_PRIV="libdrm >= $LIBDRM_REQUIRED" - PKG_CHECK_MODULES([LIBDRM_RADEON], [libdrm_radeon], HAVE_LIBDRM_RADEON=yes, HAVE_LIBDRM_RADEON=no) + PKG_CHECK_MODULES([LIBDRM_RADEON], [libdrm_radeon libdrm >= $LIBDRM_RADEON_REQUIRED], HAVE_LIBDRM_RADEON=yes, HAVE_LIBDRM_RADEON=no) if test "$HAVE_LIBDRM_RADEON" = yes; then RADEON_CFLAGS="-DHAVE_LIBDRM_RADEON=1 $LIBDRM_RADEON_CFLAGS" -- cgit v1.2.3 From bf064ce0c31abb036fc035c59fdc1134705a5e3f Mon Sep 17 00:00:00 2001 From: Fabio Pedretti Date: Tue, 22 Dec 2009 10:43:35 +1000 Subject: configure.ac: fix for libdrm_radeon API changes. --- configure.ac | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'configure.ac') diff --git a/configure.ac b/configure.ac index e15e1f60c4..a15ca111e2 100644 --- a/configure.ac +++ b/configure.ac @@ -19,6 +19,7 @@ AC_CANONICAL_HOST dnl Versions for external dependencies LIBDRM_REQUIRED=2.4.15 +LIBDRM_RADEON_REQUIRED=2.4.17 DRI2PROTO_REQUIRED=1.99.3 dnl Check for progs @@ -577,7 +578,7 @@ dri) GL_PC_REQ_PRIV="libdrm >= $LIBDRM_REQUIRED dri2proto >= $DRI2PROTO_REQUIRED" DRI_PC_REQ_PRIV="libdrm >= $LIBDRM_REQUIRED" - PKG_CHECK_MODULES([LIBDRM_RADEON], [libdrm_radeon], HAVE_LIBDRM_RADEON=yes, HAVE_LIBDRM_RADEON=no) + PKG_CHECK_MODULES([LIBDRM_RADEON], [libdrm_radeon libdrm >= $LIBDRM_RADEON_REQUIRED], HAVE_LIBDRM_RADEON=yes, HAVE_LIBDRM_RADEON=no) if test "$HAVE_LIBDRM_RADEON" = yes; then RADEON_CFLAGS="-DHAVE_LIBDRM_RADEON=1 $LIBDRM_RADEON_CFLAGS" -- cgit v1.2.3 From c978ab017d103e60e7e69b6a7857a70baca29e7b Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Sat, 2 Jan 2010 20:22:52 +0000 Subject: gallium: Hunt down all references to GALLIUM_AUXILIARY_DIRS. --- configs/autoconf.in | 1 - configs/default | 1 - configs/linux-llvm | 2 -- configure.ac | 3 --- 4 files changed, 7 deletions(-) (limited to 'configure.ac') diff --git a/configs/autoconf.in b/configs/autoconf.in index 241ac99463..b94d9bce46 100644 --- a/configs/autoconf.in +++ b/configs/autoconf.in @@ -66,7 +66,6 @@ SRC_DIRS = @SRC_DIRS@ GLU_DIRS = @GLU_DIRS@ DRIVER_DIRS = @DRIVER_DIRS@ GALLIUM_DIRS = @GALLIUM_DIRS@ -GALLIUM_AUXILIARY_DIRS = @GALLIUM_AUXILIARY_DIRS@ GALLIUM_DRIVERS_DIRS = @GALLIUM_DRIVERS_DIRS@ GALLIUM_WINSYS_DIRS = @GALLIUM_WINSYS_DIRS@ GALLIUM_WINSYS_DRM_DIRS = @GALLIUM_WINSYS_DRM_DIRS@ diff --git a/configs/default b/configs/default index d745d5bc57..94beca4fa6 100644 --- a/configs/default +++ b/configs/default @@ -94,7 +94,6 @@ EGL_DRIVERS_DIRS = demo # Gallium directories and GALLIUM_DIRS = auxiliary drivers state_trackers -GALLIUM_AUXILIARY_DIRS = rbug draw translate cso_cache pipebuffer tgsi rtasm util indices vl GALLIUM_AUXILIARIES = $(TOP)/src/gallium/auxiliary/libgallium.a GALLIUM_DRIVERS_DIRS = softpipe failover svga i915 i965 trace identity GALLIUM_DRIVERS = $(foreach DIR,$(GALLIUM_DRIVERS_DIRS),$(TOP)/src/gallium/drivers/$(DIR)/lib$(DIR).a) diff --git a/configs/linux-llvm b/configs/linux-llvm index 19b53cc546..dbf7e3ed7a 100644 --- a/configs/linux-llvm +++ b/configs/linux-llvm @@ -6,8 +6,6 @@ include $(TOP)/configs/linux CONFIG_NAME = linux-llvm -#GALLIUM_AUXILIARY_DIRS += gallivm - # Add llvmpipe driver GALLIUM_DRIVERS_DIRS += llvmpipe diff --git a/configure.ac b/configure.ac index d83dd4315b..72afabcf9e 100644 --- a/configure.ac +++ b/configure.ac @@ -420,7 +420,6 @@ WINDOW_SYSTEM="" GALLIUM_DIRS="auxiliary drivers state_trackers" GALLIUM_WINSYS_DIRS="" GALLIUM_WINSYS_DRM_DIRS="" -GALLIUM_AUXILIARY_DIRS="rbug draw translate cso_cache pipebuffer tgsi sct rtasm util indices vl" GALLIUM_DRIVERS_DIRS="softpipe failover trace identity" GALLIUM_STATE_TRACKERS_DIRS="" @@ -447,7 +446,6 @@ AC_SUBST([GALLIUM_DIRS]) AC_SUBST([GALLIUM_WINSYS_DIRS]) AC_SUBST([GALLIUM_WINSYS_DRM_DIRS]) AC_SUBST([GALLIUM_DRIVERS_DIRS]) -AC_SUBST([GALLIUM_AUXILIARY_DIRS]) AC_SUBST([GALLIUM_STATE_TRACKERS_DIRS]) AC_SUBST([RADEON_CFLAGS]) AC_SUBST([RADEON_LDFLAGS]) @@ -1306,7 +1304,6 @@ if echo "$SRC_DIRS" | grep 'gallium' >/dev/null 2>&1; then echo " Gallium dirs: $GALLIUM_DIRS" echo " Winsys dirs: $GALLIUM_WINSYS_DIRS" echo " Winsys drm dirs:$GALLIUM_WINSYS_DRM_DIRS" - echo " Auxiliary dirs: $GALLIUM_AUXILIARY_DIRS" echo " Driver dirs: $GALLIUM_DRIVERS_DIRS" echo " Trackers dirs: $GALLIUM_STATE_TRACKERS_DIRS" else -- cgit v1.2.3 From e388d62b4712bcd75cecad53f5ca20a2bb6f89b1 Mon Sep 17 00:00:00 2001 From: Kristian Høgsberg Date: Sat, 2 Jan 2010 18:59:54 -0500 Subject: Compile with -fvisibility-hidden by default We have all functions that need to be visible marked with PUBLIC and this is trimming around 4% off the DRI driver .so size. --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'configure.ac') diff --git a/configure.ac b/configure.ac index 72afabcf9e..b2a969bc8c 100644 --- a/configure.ac +++ b/configure.ac @@ -95,7 +95,7 @@ esac dnl Add flags for gcc and g++ if test "x$GCC" = xyes; then - CFLAGS="$CFLAGS -Wall -Wmissing-prototypes -std=c99 -ffast-math" + CFLAGS="$CFLAGS -Wall -Wmissing-prototypes -std=c99 -ffast-math -fvisibility=hidden" # Work around aliasing bugs - developers should comment this out CFLAGS="$CFLAGS -fno-strict-aliasing" -- cgit v1.2.3 From 8616cec5c9889e6166839b33baa8db52f04d409c Mon Sep 17 00:00:00 2001 From: Kristian Høgsberg Date: Fri, 1 Jan 2010 17:03:33 -0500 Subject: Check for libdrm_$chipset.pc when needed This adds missing pkg-config lookup for intel and moves the radeon lookup into a case...esac so it's only looked up when one or more of the radeon drivers are enabled. --- configs/autoconf.in | 2 ++ configure.ac | 30 +++++++++++++++++++++--------- src/mesa/drivers/dri/i915/Makefile | 3 ++- src/mesa/drivers/dri/i965/Makefile | 3 ++- 4 files changed, 27 insertions(+), 11 deletions(-) (limited to 'configure.ac') diff --git a/configs/autoconf.in b/configs/autoconf.in index b94d9bce46..f63618ebea 100644 --- a/configs/autoconf.in +++ b/configs/autoconf.in @@ -22,6 +22,8 @@ LDFLAGS = @LDFLAGS@ EXTRA_LIB_PATH = @EXTRA_LIB_PATH@ RADEON_CFLAGS = @RADEON_CFLAGS@ RADEON_LDFLAGS = @RADEON_LDFLAGS@ +INTEL_LIBS = @INTEL_LIBS@ +INTEL_CFLAGS = @INTEL_CFLAGS@ # Assembler MESA_ASM_SOURCES = @MESA_ASM_SOURCES@ diff --git a/configure.ac b/configure.ac index b2a969bc8c..d3fbd02713 100644 --- a/configure.ac +++ b/configure.ac @@ -447,8 +447,6 @@ AC_SUBST([GALLIUM_WINSYS_DIRS]) AC_SUBST([GALLIUM_WINSYS_DRM_DIRS]) AC_SUBST([GALLIUM_DRIVERS_DIRS]) AC_SUBST([GALLIUM_STATE_TRACKERS_DIRS]) -AC_SUBST([RADEON_CFLAGS]) -AC_SUBST([RADEON_LDFLAGS]) dnl dnl User supplied program configuration @@ -576,13 +574,6 @@ dri) GL_PC_REQ_PRIV="libdrm >= $LIBDRM_REQUIRED dri2proto >= $DRI2PROTO_REQUIRED" DRI_PC_REQ_PRIV="libdrm >= $LIBDRM_REQUIRED" - PKG_CHECK_MODULES([LIBDRM_RADEON], [libdrm_radeon libdrm >= $LIBDRM_RADEON_REQUIRED], HAVE_LIBDRM_RADEON=yes, HAVE_LIBDRM_RADEON=no) - - if test "$HAVE_LIBDRM_RADEON" = yes; then - RADEON_CFLAGS="-DHAVE_LIBDRM_RADEON=1 $LIBDRM_RADEON_CFLAGS" - RADEON_LDFLAGS=$LIBDRM_RADEON_LIBS - fi - # find the DRI deps for libGL if test "$x11_pkgconfig" = yes; then # add xcb modules if necessary @@ -802,6 +793,27 @@ AC_SUBST([DRI_DIRS]) AC_SUBST([EXPAT_INCLUDES]) AC_SUBST([DRI_LIB_DEPS]) +case $DRI_DIRS in +*i915*|*i965*) + PKG_CHECK_MODULES([INTEL], [libdrm_intel]) + ;; + +*radeon*|*r200*|*r300*|*r600*) + PKG_CHECK_MODULES([LIBDRM_RADEON], + [libdrm_radeon libdrm >= $LIBDRM_RADEON_REQUIRED], + HAVE_LIBDRM_RADEON=yes, + HAVE_LIBDRM_RADEON=no) + + if test "$HAVE_LIBDRM_RADEON" = yes; then + RADEON_CFLAGS="-DHAVE_LIBDRM_RADEON=1 $LIBDRM_RADEON_CFLAGS" + RADEON_LDFLAGS=$LIBDRM_RADEON_LIBS + fi + ;; +esac +AC_SUBST([RADEON_CFLAGS]) +AC_SUBST([RADEON_LDFLAGS]) + + dnl dnl OSMesa configuration dnl diff --git a/src/mesa/drivers/dri/i915/Makefile b/src/mesa/drivers/dri/i915/Makefile index 37f15aa767..788e78654e 100644 --- a/src/mesa/drivers/dri/i915/Makefile +++ b/src/mesa/drivers/dri/i915/Makefile @@ -64,7 +64,8 @@ DRIVER_DEFINES = -I../intel -I../intel/server -DI915 \ $(shell pkg-config libdrm --atleast-version=2.3.1 \ && echo "-DDRM_VBLANK_FLIP=DRM_VBLANK_FLIP") -DRI_LIB_DEPS += -ldrm_intel +INCLUDES += $(INTEL_CFLAGS) +DRI_LIB_DEPS += $(INTEL_LIBS) include ../Makefile.template diff --git a/src/mesa/drivers/dri/i965/Makefile b/src/mesa/drivers/dri/i965/Makefile index 7a55333e89..7cdbdc7071 100644 --- a/src/mesa/drivers/dri/i965/Makefile +++ b/src/mesa/drivers/dri/i965/Makefile @@ -96,7 +96,8 @@ ASM_SOURCES = DRIVER_DEFINES = -I../intel -I../intel/server -DRI_LIB_DEPS += -ldrm_intel +INCLUDES += $(INTEL_CFLAGS) +DRI_LIB_DEPS += $(INTEL_LIBS) include ../Makefile.template -- cgit v1.2.3 From 27fe7a7303d93bc38df1f3c2861d07af3e82546d Mon Sep 17 00:00:00 2001 From: Kristian Høgsberg Date: Thu, 7 Jan 2010 10:29:29 -0500 Subject: configure: Fix matching for dri driver to actually work The shell case statement obviously only evaluates the first matching block. Thanks to Julien Cristau for spotting the bug. --- configure.ac | 2 ++ 1 file changed, 2 insertions(+) (limited to 'configure.ac') diff --git a/configure.ac b/configure.ac index d3fbd02713..d8af5ea9ef 100644 --- a/configure.ac +++ b/configure.ac @@ -797,7 +797,9 @@ case $DRI_DIRS in *i915*|*i965*) PKG_CHECK_MODULES([INTEL], [libdrm_intel]) ;; +esac +case $DRI_DIRS in *radeon*|*r200*|*r300*|*r600*) PKG_CHECK_MODULES([LIBDRM_RADEON], [libdrm_radeon libdrm >= $LIBDRM_RADEON_REQUIRED], -- cgit v1.2.3 From a35f6bb207efe3c959bbd16a37f2049e5aceeea9 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Fri, 17 Jul 2009 03:30:29 -0400 Subject: DRI2: add SwapBuffers support Support the new DRI2 protocol request, DRI2SwapBuffers, in both direct and indirect rendering context. This request allows the display server to optimize back->front swaps (e.g. through page flipping) and allows us to more easily support other GLX features like swap interval and the OML sync extension in DRI2. Signed-off-by: Jesse Barnes --- configure.ac | 2 +- include/GL/internal/dri_interface.h | 14 +++++++++++++- src/glx/x11/dri2.c | 16 ++++++++++++++++ src/glx/x11/dri2.h | 3 +++ src/glx/x11/dri2_glx.c | 32 +++++++++++++++++++++++++++++++- src/mesa/drivers/dri/common/dri_util.c | 1 + src/mesa/drivers/dri/common/dri_util.h | 2 ++ 7 files changed, 67 insertions(+), 3 deletions(-) (limited to 'configure.ac') diff --git a/configure.ac b/configure.ac index b2a969bc8c..fd300504bf 100644 --- a/configure.ac +++ b/configure.ac @@ -20,7 +20,7 @@ AC_CANONICAL_HOST dnl Versions for external dependencies LIBDRM_REQUIRED=2.4.15 LIBDRM_RADEON_REQUIRED=2.4.17 -DRI2PROTO_REQUIRED=1.99.3 +DRI2PROTO_REQUIRED=2.2 dnl Check for progs AC_PROG_CPP diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h index 910c9166b5..ec6238f873 100644 --- a/include/GL/internal/dri_interface.h +++ b/include/GL/internal/dri_interface.h @@ -262,10 +262,22 @@ struct __DRItexBufferExtensionRec { * Used by drivers that implement DRI2 */ #define __DRI2_FLUSH "DRI2_Flush" -#define __DRI2_FLUSH_VERSION 1 +#define __DRI2_FLUSH_VERSION 2 struct __DRI2flushExtensionRec { __DRIextension base; void (*flush)(__DRIdrawable *drawable); + + /** + * Flush all rendering queue in the driver to the drm and + * invalidate all buffers. The driver will call out to + * getBuffers/getBuffersWithFormat before it starts rendering + * again. + * + * \param drawable the drawable to flush and invalidate + * + * \since 2 + */ + void (*flushInvalidate)(__DRIdrawable *drawable); }; diff --git a/src/glx/x11/dri2.c b/src/glx/x11/dri2.c index dad04470a0..a0f8901d42 100644 --- a/src/glx/x11/dri2.c +++ b/src/glx/x11/dri2.c @@ -380,4 +380,20 @@ DRI2CopyRegion(Display * dpy, XID drawable, XserverRegion region, SyncHandle(); } +void DRI2SwapBuffers(Display *dpy, XID drawable) +{ + XExtDisplayInfo *info = DRI2FindDisplay(dpy); + xDRI2SwapBuffersReq *req; + + XextSimpleCheckExtension (dpy, info, dri2ExtensionName); + + LockDisplay(dpy); + GetReq(DRI2SwapBuffers, req); + req->reqType = info->codes->major_opcode; + req->dri2ReqType = X_DRI2SwapBuffers; + req->drawable = drawable; + UnlockDisplay(dpy); + SyncHandle(); +} + #endif /* GLX_DIRECT_RENDERING */ diff --git a/src/glx/x11/dri2.h b/src/glx/x11/dri2.h index a6fe66e136..ba6eff5e4f 100644 --- a/src/glx/x11/dri2.h +++ b/src/glx/x11/dri2.h @@ -85,4 +85,7 @@ DRI2CopyRegion(Display * dpy, XID drawable, XserverRegion region, CARD32 dest, CARD32 src); +extern void +DRI2SwapBuffers(Display *dpy, XID drawable); + #endif diff --git a/src/glx/x11/dri2_glx.c b/src/glx/x11/dri2_glx.c index 89efe3ab29..114cad2ae7 100644 --- a/src/glx/x11/dri2_glx.c +++ b/src/glx/x11/dri2_glx.c @@ -35,6 +35,7 @@ #include #include #include +#include "glapi.h" #include "glxclient.h" #include "glcontextmodes.h" #include "xf86dri.h" @@ -64,6 +65,7 @@ struct __GLXDRIdisplayPrivateRec int driMajor; int driMinor; int driPatch; + int swapAvailable; }; struct __GLXDRIcontextPrivateRec @@ -240,7 +242,7 @@ dri2SwapBuffers(__GLXDRIdrawable * pdraw) } static void -dri2WaitX(__GLXDRIdrawable * pdraw) +dri2WaitX(__GLXDRIdrawable *pdraw) { __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw; XRectangle xrect; @@ -342,6 +344,31 @@ process_buffers(__GLXDRIdrawablePrivate * pdraw, DRI2Buffer * buffers, } +static void dri2SwapBuffers(__GLXDRIdrawable *pdraw) +{ + __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw; + __GLXdisplayPrivate *dpyPriv = __glXInitialize(priv->base.psc->dpy); + __GLXDRIdisplayPrivate *pdp = + (__GLXDRIdisplayPrivate *)dpyPriv->dri2Display; + __GLXscreenConfigs *psc = pdraw->psc; + +#ifdef __DRI2_FLUSH + if (pdraw->psc->f) + (*pdraw->psc->f->flush)(pdraw->driDrawable); +#endif + + /* Old servers can't handle swapbuffers */ + if (!pdp->swapAvailable) + return dri2CopySubBuffer(pdraw, 0, 0, priv->width, priv->height); + + DRI2SwapBuffers(pdraw->psc->dpy, pdraw->drawable); + +#if __DRI2_FLUSH_VERSION >= 2 + if (pdraw->psc->f) + (*pdraw->psc->f->flushInvalidate)(pdraw->driDrawable); +#endif +} + static __DRIbuffer * dri2GetBuffers(__DRIdrawable * driDrawable, int *width, int *height, @@ -559,6 +586,9 @@ dri2CreateDisplay(Display * dpy) } pdp->driPatch = 0; + pdp->swapAvailable = 0; + if (pdp->driMinor >= 2) + pdp->swapAvailable = 1; pdp->base.destroyDisplay = dri2DestroyDisplay; pdp->base.createScreen = dri2CreateScreen; diff --git a/src/mesa/drivers/dri/common/dri_util.c b/src/mesa/drivers/dri/common/dri_util.c index 547f18a009..cd271ede09 100644 --- a/src/mesa/drivers/dri/common/dri_util.c +++ b/src/mesa/drivers/dri/common/dri_util.c @@ -454,6 +454,7 @@ driCreateNewDrawable(__DRIscreen *psp, const __DRIconfig *config, pdp->driScreenPriv = psp; pdp->driContextPriv = &psp->dummyContextPriv; + pdp->validBuffers = GL_FALSE; if (!(*psp->DriverAPI.CreateBuffer)(psp, pdp, &config->modes, renderType == GLX_PIXMAP_BIT)) { diff --git a/src/mesa/drivers/dri/common/dri_util.h b/src/mesa/drivers/dri/common/dri_util.h index c95a5c8299..c3046d6b18 100644 --- a/src/mesa/drivers/dri/common/dri_util.h +++ b/src/mesa/drivers/dri/common/dri_util.h @@ -380,6 +380,8 @@ struct __DRIdrawableRec { * GLX_MESA_swap_control. */ unsigned int swap_interval; + + GLboolean validBuffers; }; /** -- cgit v1.2.3 From d4c1ee05345e1e185ac15a3cd3552d9bb0d61bc3 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Mon, 21 Dec 2009 11:13:18 +0800 Subject: egl: Clean up the Makefile rules. This allows libEGL to be built as a static library and removes libX11 from the dependencies. Signed-off-by: Chia-I Wu --- configs/autoconf.in | 3 +++ configs/default | 5 ++++- configure.ac | 18 ++++++++++-------- src/egl/main/Makefile | 25 ++++++++++++++----------- 4 files changed, 31 insertions(+), 20 deletions(-) (limited to 'configure.ac') diff --git a/configs/autoconf.in b/configs/autoconf.in index f63618ebea..49c009052b 100644 --- a/configs/autoconf.in +++ b/configs/autoconf.in @@ -54,6 +54,7 @@ GLU_LIB_NAME = @GLU_LIB_NAME@ GLUT_LIB_NAME = @GLUT_LIB_NAME@ GLW_LIB_NAME = @GLW_LIB_NAME@ OSMESA_LIB_NAME = @OSMESA_LIB_NAME@ +EGL_LIB_NAME = @EGL_LIB_NAME@ # Globs used to install the lib and all symlinks GL_LIB_GLOB = @GL_LIB_GLOB@ @@ -61,12 +62,14 @@ GLU_LIB_GLOB = @GLU_LIB_GLOB@ GLUT_LIB_GLOB = @GLUT_LIB_GLOB@ GLW_LIB_GLOB = @GLW_LIB_GLOB@ OSMESA_LIB_GLOB = @OSMESA_LIB_GLOB@ +EGL_LIB_GLOB = @EGL_LIB_GLOB@ # Directories to build LIB_DIR = @LIB_DIR@ SRC_DIRS = @SRC_DIRS@ GLU_DIRS = @GLU_DIRS@ DRIVER_DIRS = @DRIVER_DIRS@ +EGL_DRIVERS_DIRS = @EGL_DRIVERS_DIRS@ GALLIUM_DIRS = @GALLIUM_DIRS@ GALLIUM_DRIVERS_DIRS = @GALLIUM_DRIVERS_DIRS@ GALLIUM_WINSYS_DIRS = @GALLIUM_WINSYS_DIRS@ diff --git a/configs/default b/configs/default index 94beca4fa6..f5a4bc195f 100644 --- a/configs/default +++ b/configs/default @@ -55,6 +55,7 @@ GLUT_LIB = glut GLEW_LIB = GLEW GLW_LIB = GLw OSMESA_LIB = OSMesa +EGL_LIB = EGL # Library names (actual file names) @@ -64,6 +65,7 @@ GLUT_LIB_NAME = lib$(GLUT_LIB).so GLEW_LIB_NAME = lib$(GLEW_LIB).a GLW_LIB_NAME = lib$(GLW_LIB).so OSMESA_LIB_NAME = lib$(OSMESA_LIB).so +EGL_LIB_NAME = lib$(EGL_LIB).so # globs used to install the lib and all symlinks GL_LIB_GLOB = $(GL_LIB_NAME)* @@ -71,6 +73,7 @@ GLU_LIB_GLOB = $(GLU_LIB_NAME)* GLUT_LIB_GLOB = $(GLUT_LIB_NAME)* GLW_LIB_GLOB = $(GLW_LIB_NAME)* OSMESA_LIB_GLOB = $(OSMESA_LIB_NAME)* +EGL_LIB_GLOB = $(EGL_LIB_NAME)* # Optional assembly language optimization files for libGL MESA_ASM_SOURCES = @@ -89,7 +92,7 @@ DRIVER_DIRS = x11 osmesa # Which subdirs under $(TOP)/progs/ to enter: PROGRAM_DIRS = demos redbook samples glsl objviewer xdemos -# EGL directories +# EGL drivers to build EGL_DRIVERS_DIRS = demo # Gallium directories and diff --git a/configure.ac b/configure.ac index d8af5ea9ef..43069de1ea 100644 --- a/configure.ac +++ b/configure.ac @@ -243,24 +243,28 @@ GLU_LIB_NAME='lib$(GLU_LIB).'${LIB_EXTENSION} GLUT_LIB_NAME='lib$(GLUT_LIB).'${LIB_EXTENSION} GLW_LIB_NAME='lib$(GLW_LIB).'${LIB_EXTENSION} OSMESA_LIB_NAME='lib$(OSMESA_LIB).'${LIB_EXTENSION} +EGL_LIB_NAME='lib$(EGL_LIB).'${LIB_EXTENSION} GL_LIB_GLOB='lib$(GL_LIB).*'${LIB_EXTENSION}'*' GLU_LIB_GLOB='lib$(GLU_LIB).*'${LIB_EXTENSION}'*' GLUT_LIB_GLOB='lib$(GLUT_LIB).*'${LIB_EXTENSION}'*' GLW_LIB_GLOB='lib$(GLW_LIB).*'${LIB_EXTENSION}'*' OSMESA_LIB_GLOB='lib$(OSMESA_LIB).*'${LIB_EXTENSION}'*' +EGL_LIB_GLOB='lib$(EGL_LIB).*'${LIB_EXTENSION}'*' AC_SUBST([GL_LIB_NAME]) AC_SUBST([GLU_LIB_NAME]) AC_SUBST([GLUT_LIB_NAME]) AC_SUBST([GLW_LIB_NAME]) AC_SUBST([OSMESA_LIB_NAME]) +AC_SUBST([EGL_LIB_NAME]) AC_SUBST([GL_LIB_GLOB]) AC_SUBST([GLU_LIB_GLOB]) AC_SUBST([GLUT_LIB_GLOB]) AC_SUBST([GLW_LIB_GLOB]) AC_SUBST([OSMESA_LIB_GLOB]) +AC_SUBST([EGL_LIB_GLOB]) dnl dnl Arch/platform-specific settings @@ -900,17 +904,15 @@ AC_ARG_ENABLE([egl], [enable_egl=yes]) if test "x$enable_egl" = xyes; then SRC_DIRS="$SRC_DIRS egl" - - if test "$x11_pkgconfig" = yes; then - PKG_CHECK_MODULES([EGL], [x11]) - EGL_LIB_DEPS="$EGL_LIBS" - else - # should check these... - EGL_LIB_DEPS="$X_LIBS -lX11" + EGL_LIB_DEPS="$DLOPEN_LIBS -lpthread" + EGL_DRIVERS_DIRS="" + if test "$enable_static" != yes && test "$mesa_driver" != osmesa; then + # build egl_glx when libGL is built + EGL_DRIVERS_DIRS="glx" fi - EGL_LIB_DEPS="$EGL_LIB_DEPS $DLOPEN_LIBS" fi AC_SUBST([EGL_LIB_DEPS]) +AC_SUBST([EGL_DRIVERS_DIRS]) dnl dnl GLU configuration diff --git a/src/egl/main/Makefile b/src/egl/main/Makefile index c951b070f1..ec326a845d 100644 --- a/src/egl/main/Makefile +++ b/src/egl/main/Makefile @@ -4,7 +4,10 @@ TOP = ../../.. include $(TOP)/configs/current -INCLUDE_DIRS = -I$(TOP)/include -I$(TOP)/src/mesa/glapi $(X11_INCLUDES) +EGL_MAJOR = 1 +EGL_MINOR = 0 + +INCLUDE_DIRS = -I$(TOP)/include HEADERS = \ eglcompiler.h \ @@ -43,7 +46,7 @@ SOURCES = \ OBJECTS = $(SOURCES:.c=.o) -# Undefined for now +# use dl*() to load drivers LOCAL_CFLAGS = -D_EGL_PLATFORM_X=1 @@ -56,21 +59,21 @@ default: depend library # EGL Library -library: $(TOP)/$(LIB_DIR)/libEGL.so +library: $(TOP)/$(LIB_DIR)/$(EGL_LIB_NAME) -$(TOP)/$(LIB_DIR)/libEGL.so: $(OBJECTS) - $(MKLIB) -o EGL -linker '$(CC)' -ldflags '$(LDFLAGS)' \ - -major 1 -minor 0 \ - -install $(TOP)/$(LIB_DIR) \ +$(TOP)/$(LIB_DIR)/$(EGL_LIB_NAME): $(OBJECTS) + $(MKLIB) -o $(EGL_LIB) -linker '$(CC)' -ldflags '$(LDFLAGS)' \ + -major $(EGL_MAJOR) -minor $(EGL_MINOR) \ + -install $(TOP)/$(LIB_DIR) $(MKLIB_OPTIONS) \ $(EGL_LIB_DEPS) $(OBJECTS) install: default $(INSTALL) -d $(DESTDIR)$(INSTALL_LIB_DIR) - $(MINSTALL) $(TOP)/$(LIB_DIR)/libEGL.so* $(DESTDIR)$(INSTALL_LIB_DIR) + $(MINSTALL) $(TOP)/$(LIB_DIR)/$(EGL_LIB_GLOB) \ + $(DESTDIR)$(INSTALL_LIB_DIR) clean: - -rm -f *.o *.so* - -rm -f core.* + -rm -f *.o -rm -f depend depend.bak @@ -82,5 +85,5 @@ depend: $(SOURCES) $(HEADERS) $(SOURCES) $(HEADERS) > /dev/null 2>/dev/null -include depend +-include depend # DO NOT DELETE -- cgit v1.2.3 From f2f83d9a7891428ea7c784a75bd9e2968fdf00ae Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Mon, 11 Jan 2010 17:28:10 -0500 Subject: GLX: check glproto version This was a silent dependency before, but now we really need 1.4.11 for INTEL_swap_event support, so check for it. Signed-off-by: Jesse Barnes --- configure.ac | 2 ++ 1 file changed, 2 insertions(+) (limited to 'configure.ac') diff --git a/configure.ac b/configure.ac index 33437f54f8..b388723113 100644 --- a/configure.ac +++ b/configure.ac @@ -21,6 +21,7 @@ dnl Versions for external dependencies LIBDRM_REQUIRED=2.4.15 LIBDRM_RADEON_REQUIRED=2.4.17 DRI2PROTO_REQUIRED=2.2 +GLPROTO_REQUIRED=1.4.11 dnl Check for progs AC_PROG_CPP @@ -577,6 +578,7 @@ dri) PKG_CHECK_MODULES([DRI2PROTO], [dri2proto >= $DRI2PROTO_REQUIRED]) GL_PC_REQ_PRIV="libdrm >= $LIBDRM_REQUIRED dri2proto >= $DRI2PROTO_REQUIRED" DRI_PC_REQ_PRIV="libdrm >= $LIBDRM_REQUIRED" + PKG_CHECK_MODULES([GLPROTO], [glproto >= $GLPROTO_REQUIRED]) # find the DRI deps for libGL if test "$x11_pkgconfig" = yes; then -- cgit v1.2.3 From 49381d63e61c724b156b76068058df1c01a906c2 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Mon, 11 Jan 2010 01:23:01 +0800 Subject: st/egl_g3d: New EGL state tracker that uses Gallium. This new (intermediate) EGL state tracker is the base work for EGL drivers that uses Gallium. It makes it easier to support new window systems. Currently, there is support only for X11. This driver supports multiple APIs (OpenVG, OpenGL, ...) and supports hardware acceleration through winsys/drm. Signed-off-by: Chia-I Wu --- configs/autoconf.in | 1 + configs/default | 2 + configure.ac | 29 + src/gallium/state_trackers/egl_g3d/Makefile | 72 ++ .../state_trackers/egl_g3d/common/egl_g3d.c | 921 +++++++++++++++++++++ .../state_trackers/egl_g3d/common/egl_g3d.h | 113 +++ src/gallium/state_trackers/egl_g3d/common/egl_st.c | 131 +++ src/gallium/state_trackers/egl_g3d/common/egl_st.h | 73 ++ src/gallium/state_trackers/egl_g3d/common/native.h | 168 ++++ .../state_trackers/egl_g3d/common/st_public_tmp.h | 20 + src/gallium/state_trackers/egl_g3d/x11/glxinit.c | 573 +++++++++++++ src/gallium/state_trackers/egl_g3d/x11/glxinit.h | 14 + .../state_trackers/egl_g3d/x11/native_dri2.c | 693 ++++++++++++++++ .../state_trackers/egl_g3d/x11/native_x11.c | 73 ++ .../state_trackers/egl_g3d/x11/native_x11.h | 41 + .../state_trackers/egl_g3d/x11/native_ximage.c | 680 +++++++++++++++ src/gallium/state_trackers/egl_g3d/x11/sw_winsys.c | 231 ++++++ src/gallium/state_trackers/egl_g3d/x11/sw_winsys.h | 40 + .../state_trackers/egl_g3d/x11/x11_screen.c | 402 +++++++++ .../state_trackers/egl_g3d/x11/x11_screen.h | 99 +++ 20 files changed, 4376 insertions(+) create mode 100644 src/gallium/state_trackers/egl_g3d/Makefile create mode 100644 src/gallium/state_trackers/egl_g3d/common/egl_g3d.c create mode 100644 src/gallium/state_trackers/egl_g3d/common/egl_g3d.h create mode 100644 src/gallium/state_trackers/egl_g3d/common/egl_st.c create mode 100644 src/gallium/state_trackers/egl_g3d/common/egl_st.h create mode 100644 src/gallium/state_trackers/egl_g3d/common/native.h create mode 100644 src/gallium/state_trackers/egl_g3d/common/st_public_tmp.h create mode 100644 src/gallium/state_trackers/egl_g3d/x11/glxinit.c create mode 100644 src/gallium/state_trackers/egl_g3d/x11/glxinit.h create mode 100644 src/gallium/state_trackers/egl_g3d/x11/native_dri2.c create mode 100644 src/gallium/state_trackers/egl_g3d/x11/native_x11.c create mode 100644 src/gallium/state_trackers/egl_g3d/x11/native_x11.h create mode 100644 src/gallium/state_trackers/egl_g3d/x11/native_ximage.c create mode 100644 src/gallium/state_trackers/egl_g3d/x11/sw_winsys.c create mode 100644 src/gallium/state_trackers/egl_g3d/x11/sw_winsys.h create mode 100644 src/gallium/state_trackers/egl_g3d/x11/x11_screen.c create mode 100644 src/gallium/state_trackers/egl_g3d/x11/x11_screen.h (limited to 'configure.ac') diff --git a/configs/autoconf.in b/configs/autoconf.in index 49c009052b..c6d315e4d2 100644 --- a/configs/autoconf.in +++ b/configs/autoconf.in @@ -84,6 +84,7 @@ PROGRAM_DIRS = @PROGRAM_DIRS@ # Driver specific build vars DRI_DIRS = @DRI_DIRS@ WINDOW_SYSTEM = @WINDOW_SYSTEM@ +EGL_DISPLAYS = @EGL_DISPLAYS@ USING_EGL = @USING_EGL@ # Dependencies diff --git a/configs/default b/configs/default index f5a4bc195f..8b4557d26a 100644 --- a/configs/default +++ b/configs/default @@ -104,6 +104,8 @@ GALLIUM_WINSYS_DIRS = xlib egl_xlib GALLIUM_WINSYS_DRM_DIRS = GALLIUM_STATE_TRACKERS_DIRS = glx +# native displays EGL should support +EGL_DISPLAYS = x11 # Library dependencies #EXTRA_LIB_PATH ?= diff --git a/configure.ac b/configure.ac index b388723113..8a8919b137 100644 --- a/configure.ac +++ b/configure.ac @@ -1191,6 +1191,35 @@ yes) ;; esac +AC_ARG_WITH([egl-displays], + [AS_HELP_STRING([--with-egl-displays@<:@=DIRS...@:>@], + [comma delimited native displays libEGL supports, e.g. + "x11" @<:@default=auto@:>@])], + [with_egl_displays="$withval"], + [with_egl_displays=yes]) + +EGL_DISPLAYS="" +case "$with_egl_displays" in +yes) + if test "x$enable_egl" = xyes && test "x$mesa_driver" != xosmesa; then + EGL_DISPLAYS="x11" + fi + ;; +*) + if test "x$enable_egl" != xyes; then + AC_MSG_ERROR([cannot build egl state tracker without EGL library]) + fi + # verify the requested driver directories exist + egl_displays=`IFS=', '; echo $with_egl_displays` + for dpy in $egl_displays; do + test -d "$srcdir/src/gallium/state_trackers/egl_g3d/$dpy" || \ + AC_MSG_ERROR([EGL display '$dpy' does't exist]) + done + EGL_DISPLAYS="$egl_displays" + ;; +esac +AC_SUBST([EGL_DISPLAYS]) + AC_ARG_WITH([xorg-driver-dir], [AS_HELP_STRING([--with-xorg-driver-dir=DIR], [Default xorg driver directory[[default=${libdir}/xorg/modules/drivers]]])], diff --git a/src/gallium/state_trackers/egl_g3d/Makefile b/src/gallium/state_trackers/egl_g3d/Makefile new file mode 100644 index 0000000000..213eb3e815 --- /dev/null +++ b/src/gallium/state_trackers/egl_g3d/Makefile @@ -0,0 +1,72 @@ +TOP = ../../../.. +include $(TOP)/configs/current + +common_INCLUDES = \ + -I. \ + -I$(TOP)/src/gallium/include \ + -I$(TOP)/src/gallium/auxiliary \ + -I$(TOP)/src/egl/main \ + -I$(TOP)/include + +common_SOURCES = $(wildcard common/*.c) +common_OBJECTS = $(common_SOURCES:.c=.o) + + +x11_INCLUDES = \ + -I$(TOP)/src/gallium/drivers \ + -I$(TOP)/src/glx/x11 \ + -I$(TOP)/src/mesa \ + $(shell pkg-config --cflags-only-I libdrm) + +x11_SOURCES = $(wildcard x11/*.c) $(TOP)/src/glx/x11/dri2.c +x11_OBJECTS = $(x11_SOURCES:.c=.o) + + +kms_INCLUDES = $(shell pkg-config --cflags-only-I libdrm) +kms_SOURCES = $(wildcard kms/*.c) +kms_OBJECTS = $(kms_SOURCES:.c=.o) + + +ALL_INCLUDES = $(common_INCLUDES) $(x11_INCLUDES) $(kms_INCLUDES) +ALL_SOURCES = $(common_SOURCES) $(x11_SOURCES) $(kms_SOURCES) +ALL_OBJECTS = $(common_OBJECTS) $(x11_OBJECTS) $(kms_OBJECTS) + +##### TARGETS ##### + +EGL_DISPLAYS_MODS = $(foreach dpy, $(EGL_DISPLAYS), libegl$(dpy).a) + +default: depend $(EGL_DISPLAYS_MODS) + + +libeglx11.a: $(x11_OBJECTS) $(common_OBJECTS) Makefile + $(MKLIB) -o eglx11 -static $(x11_OBJECTS) $(common_OBJECTS) + +libeglkms.a: $(kms_OBJECTS) $(common_OBJECTS) Makefile + $(MKLIB) -o eglkms -static $(kms_OBJECTS) $(common_OBJECTS) + +depend: + rm -f depend + touch depend + $(MKDEP) $(MKDEP_OPTIONS) $(ALL_INCLUDES) $(ALL_SOURCES) 2> /dev/null + +clean: + rm -f $(ALL_OBJECTS) + rm -f $(EGL_DISPLAYS_MODS) + rm -f depend depend.bak + +# Dummy target +install: + @echo -n "" + +##### RULES ##### + +$(common_OBJECTS): %.o: %.c + $(CC) -c $(common_INCLUDES) $(DEFINES) $(CFLAGS) $< -o $@ + +$(x11_OBJECTS): %.o: %.c + $(CC) -c $(common_INCLUDES) $(x11_INCLUDES) $(DEFINES) $(CFLAGS) $< -o $@ + +$(kms_OBJECTS): %.o: %.c + $(CC) -c $(common_INCLUDES) $(kms_INCLUDES) $(DEFINES) $(CFLAGS) $< -o $@ + +sinclude depend diff --git a/src/gallium/state_trackers/egl_g3d/common/egl_g3d.c b/src/gallium/state_trackers/egl_g3d/common/egl_g3d.c new file mode 100644 index 0000000000..f4a58f77eb --- /dev/null +++ b/src/gallium/state_trackers/egl_g3d/common/egl_g3d.c @@ -0,0 +1,921 @@ +/* + * Mesa 3-D graphics library + * Version: 7.8 + * + * Copyright (C) 2009-2010 Chia-I Wu + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include "util/u_memory.h" +#include "egldriver.h" +#include "eglcurrent.h" +#include "eglconfigutil.h" +#include "egllog.h" + +#include "native.h" +#include "egl_g3d.h" +#include "egl_st.h" + +/** + * Validate the draw/read surfaces of the context. + */ +static void +egl_g3d_validate_context(_EGLDisplay *dpy, _EGLContext *ctx) +{ + struct egl_g3d_display *gdpy = egl_g3d_display(dpy); + struct pipe_screen *screen = gdpy->native->screen; + struct egl_g3d_context *gctx = egl_g3d_context(ctx); + EGLint num_surfaces; + EGLint s, i; + + /* validate draw and/or read buffers */ + num_surfaces = (gctx->base.ReadSurface == gctx->base.DrawSurface) ? 1 : 2; + for (s = 0; s < num_surfaces; s++) { + struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS]; + struct egl_g3d_surface *gsurf; + struct egl_g3d_buffer *gbuf; + + if (s == 0) { + gsurf = egl_g3d_surface(gctx->base.DrawSurface); + gbuf = &gctx->draw; + } + else { + gsurf = egl_g3d_surface(gctx->base.ReadSurface); + gbuf = &gctx->read; + } + + if (!gctx->force_validate) { + EGLint cur_w, cur_h; + + cur_w = gsurf->base.Width; + cur_h = gsurf->base.Height; + gsurf->native->validate(gsurf->native, + gbuf->native_atts, gbuf->num_atts, + NULL, + &gsurf->base.Width, &gsurf->base.Height); + /* validate only when the geometry changed */ + if (gsurf->base.Width == cur_w && gsurf->base.Height == cur_h) + continue; + } + + gsurf->native->validate(gsurf->native, + gbuf->native_atts, gbuf->num_atts, + (struct pipe_texture **) textures, + &gsurf->base.Width, &gsurf->base.Height); + for (i = 0; i < gbuf->num_atts; i++) { + struct pipe_texture *pt = textures[i]; + struct pipe_surface *ps; + + if (pt) { + ps = screen->get_tex_surface(screen, pt, 0, 0, 0, + PIPE_BUFFER_USAGE_GPU_READ | + PIPE_BUFFER_USAGE_GPU_WRITE); + gctx->stapi->st_set_framebuffer_surface(gbuf->st_fb, + gbuf->st_atts[i], ps); + + if (gbuf->native_atts[i] == gsurf->render_att) + pipe_surface_reference(&gsurf->render_surface, ps); + + pipe_surface_reference(&ps, NULL); + pipe_texture_reference(&pt, NULL); + } + } + + gctx->stapi->st_resize_framebuffer(gbuf->st_fb, + gsurf->base.Width, gsurf->base.Height); + } + + gctx->force_validate = EGL_FALSE; + +} + +/** + * Create a st_framebuffer. + */ +static struct st_framebuffer * +create_framebuffer(_EGLContext *ctx, _EGLSurface *surf) +{ + struct egl_g3d_context *gctx = egl_g3d_context(ctx); + struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); + struct egl_g3d_config *gconf = egl_g3d_config(gsurf->base.Config); + + return gctx->stapi->st_create_framebuffer(&gconf->native->mode, + gconf->native->color_format, gconf->native->depth_format, + gconf->native->stencil_format, + gsurf->base.Width, gsurf->base.Height, &gsurf->base); +} + +/** + * Update the attachments of draw/read surfaces. + */ +static void +egl_g3d_route_context(_EGLDisplay *dpy, _EGLContext *ctx) +{ + struct egl_g3d_context *gctx = egl_g3d_context(ctx); + const uint st_att_map[NUM_NATIVE_ATTACHMENTS] = { + ST_SURFACE_FRONT_LEFT, + ST_SURFACE_BACK_LEFT, + ST_SURFACE_FRONT_RIGHT, + ST_SURFACE_BACK_RIGHT, + }; + EGLint s, i; + + /* route draw and read buffers' attachments */ + for (s = 0; s < 2; s++) { + struct egl_g3d_surface *gsurf; + struct egl_g3d_buffer *gbuf; + + if (s == 0) { + gsurf = egl_g3d_surface(gctx->base.DrawSurface); + gbuf = &gctx->draw; + } + else { + gsurf = egl_g3d_surface(gctx->base.ReadSurface); + gbuf = &gctx->read; + } + + gbuf->native_atts[0] = gsurf->render_att; + gbuf->num_atts = 1; + + for (i = 0; i < gbuf->num_atts; i++) + gbuf->st_atts[i] = st_att_map[gbuf->native_atts[i]]; + + /* FIXME OpenGL defaults to draw the front or back buffer when the + * context is single-buffered or double-buffered respectively. In EGL, + * however, the buffer to be drawn is determined by the surface, instead + * of the context. As a result, rendering to a pixmap surface with a + * double-buffered context does not work as expected. + * + * gctx->stapi->st_draw_front_buffer(gctx->st_ctx, natt == + * NATIVE_ATTACHMENT_FRONT_LEFT); + */ + + /* + * FIXME If the back buffer is asked for here, and the front buffer is + * later needed by the client API (e.g. glDrawBuffer is called to draw + * the front buffer), it will create a new pipe texture and draw there. + * One fix is to ask for both buffers here, but it would be a waste if + * the front buffer is never used. A better fix is to add a callback to + * the pipe screen with context private (just like flush_frontbuffer). + */ + } +} + +/** + * Reallocate the context's framebuffers after draw/read surfaces change. + */ +static EGLBoolean +egl_g3d_realloc_context(_EGLDisplay *dpy, _EGLContext *ctx) +{ + struct egl_g3d_context *gctx = egl_g3d_context(ctx); + struct egl_g3d_surface *gdraw = egl_g3d_surface(gctx->base.DrawSurface); + struct egl_g3d_surface *gread = egl_g3d_surface(gctx->base.ReadSurface); + + /* unreference the old framebuffers */ + if (gctx->draw.st_fb) { + EGLBoolean is_equal = (gctx->draw.st_fb == gctx->read.st_fb); + void *priv; + + priv = gctx->stapi->st_framebuffer_private(gctx->draw.st_fb); + if (!gdraw || priv != (void *) &gdraw->base) { + gctx->stapi->st_unreference_framebuffer(gctx->draw.st_fb); + gctx->draw.st_fb = NULL; + gctx->draw.num_atts = 0; + } + + if (is_equal) { + gctx->read.st_fb = NULL; + gctx->draw.num_atts = 0; + } + else { + priv = gctx->stapi->st_framebuffer_private(gctx->read.st_fb); + if (!gread || priv != (void *) &gread->base) { + gctx->stapi->st_unreference_framebuffer(gctx->read.st_fb); + gctx->read.st_fb = NULL; + gctx->draw.num_atts = 0; + } + } + } + + if (!gdraw) + return EGL_TRUE; + + /* create the draw fb */ + if (!gctx->draw.st_fb) { + gctx->draw.st_fb = create_framebuffer(&gctx->base, &gdraw->base); + if (!gctx->draw.st_fb) + return EGL_FALSE; + } + + /* create the read fb */ + if (!gctx->read.st_fb) { + if (gread != gdraw) { + gctx->read.st_fb = create_framebuffer(&gctx->base, &gread->base); + if (!gctx->read.st_fb) { + gctx->stapi->st_unreference_framebuffer(gctx->draw.st_fb); + gctx->draw.st_fb = NULL; + return EGL_FALSE; + } + } + else { + /* there is no st_reference_framebuffer... */ + gctx->read.st_fb = gctx->draw.st_fb; + } + } + + egl_g3d_route_context(dpy, &gctx->base); + gctx->force_validate = EGL_TRUE; + + return EGL_TRUE; +} + +/** + * Return the current context of the given API. + */ +static struct egl_g3d_context * +egl_g3d_get_current_context(EGLint api) +{ + _EGLThreadInfo *t = _eglGetCurrentThread(); + EGLint api_index = _eglConvertApiToIndex(api); + return egl_g3d_context(t->CurrentContexts[api_index]); +} + +/** + * Return the state tracker for the given context. + */ +static const struct egl_g3d_st * +egl_g3d_choose_st(_EGLDriver *drv, _EGLContext *ctx) +{ + struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); + const struct egl_g3d_st *stapi; + EGLint idx = -1; + + switch (ctx->ClientAPI) { + case EGL_OPENGL_ES_API: + switch (ctx->ClientVersion) { + case 1: + idx = EGL_G3D_ST_OPENGL_ES; + break; + case 2: + idx = EGL_G3D_ST_OPENGL_ES2; + break; + default: + _eglLog(_EGL_WARNING, "unknown client version %d", + ctx->ClientVersion); + break; + } + break; + case EGL_OPENVG_API: + idx = EGL_G3D_ST_OPENVG; + break; + case EGL_OPENGL_API: + idx = EGL_G3D_ST_OPENGL; + break; + default: + _eglLog(_EGL_WARNING, "unknown client API 0x%04x", ctx->ClientAPI); + break; + } + + stapi = (idx >= 0) ? gdrv->stapis[idx] : NULL; + return stapi; +} + +/** + * Return an API mask that consists of the state trackers that supports the + * given mode. + * + * FIXME add st_is_mode_supported()? + */ +static EGLint +get_mode_api_mask(const __GLcontextModes *mode, EGLint api_mask) +{ + EGLint check; + + /* OpenGL ES 1.x and 2.x are checked together */ + check = EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT; + if (api_mask & check) { + /* this is required by EGL, not by OpenGL ES */ + if (mode->drawableType & GLX_WINDOW_BIT && !mode->doubleBufferMode) + api_mask &= ~check; + } + + check = EGL_OPENVG_BIT; + if (api_mask & check) { + /* vega st needs the depth/stencil rb */ + if (!mode->depthBits && !mode->stencilBits) + api_mask &= ~check; + } + + return api_mask; +} + +/** + * Add configs to display and return the next config ID. + */ +static EGLint +egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint id) +{ + struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); + struct egl_g3d_display *gdpy = egl_g3d_display(dpy); + const struct native_config **native_configs; + int num_configs, i; + + native_configs = gdpy->native->get_configs(gdpy->native, + &num_configs); + if (!num_configs) { + if (native_configs) + free(native_configs); + return id; + } + + for (i = 0; i < num_configs; i++) { + EGLint api_mask; + struct egl_g3d_config *gconf; + EGLBoolean valid; + + api_mask = get_mode_api_mask(&native_configs[i]->mode, gdrv->api_mask); + if (!api_mask) { + _eglLog(_EGL_DEBUG, "no state tracker supports config 0x%x", + native_configs[i]->mode.visualID); + continue; + } + + gconf = CALLOC_STRUCT(egl_g3d_config); + if (!gconf) + continue; + + _eglInitConfig(&gconf->base, id); + valid = _eglConfigFromContextModesRec(&gconf->base, + &native_configs[i]->mode, api_mask, api_mask); + if (valid) + valid = _eglValidateConfig(&gconf->base, EGL_FALSE); + if (!valid) { + _eglLog(_EGL_DEBUG, "skip invalid config 0x%x", + native_configs[i]->mode.visualID); + free(gconf); + continue; + } + + gconf->native = native_configs[i]; + _eglAddConfig(dpy, &gconf->base); + id++; + } + + free(native_configs); + return id; +} + +/** + * Flush the front buffer of the context's draw surface. + */ +static void +egl_g3d_flush_frontbuffer(void *dummy, struct pipe_surface *surf, + void *context_private) +{ + struct egl_g3d_context *gctx = egl_g3d_context(context_private); + struct egl_g3d_surface *gsurf = egl_g3d_surface(gctx->base.DrawSurface); + + if (gsurf) { + gsurf->native->flush_frontbuffer(gsurf->native); + egl_g3d_validate_context(gctx->base.Display, &gctx->base); + } +} + +static EGLBoolean +egl_g3d_terminate(_EGLDriver *drv, _EGLDisplay *dpy) +{ + struct egl_g3d_display *gdpy = egl_g3d_display(dpy); + + _eglReleaseDisplayResources(drv, dpy); + _eglCleanupDisplay(dpy); + + if (gdpy->native) + gdpy->native->destroy(gdpy->native); + + free(gdpy); + dpy->DriverData = NULL; + + return EGL_TRUE; +} + +static EGLBoolean +egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy, + EGLint *major, EGLint *minor) +{ + struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); + struct egl_g3d_display *gdpy; + + gdpy = CALLOC_STRUCT(egl_g3d_display); + if (!gdpy) { + _eglError(EGL_BAD_ALLOC, "eglInitialize"); + goto fail; + } + dpy->DriverData = gdpy; + + gdpy->native = + native_create_display(dpy->NativeDisplay, egl_g3d_flush_frontbuffer); + if (!gdpy->native) { + _eglError(EGL_NOT_INITIALIZED, "eglInitialize(no usable display)"); + goto fail; + } + + dpy->ClientAPIsMask = gdrv->api_mask; + + if (egl_g3d_add_configs(drv, dpy, 1) == 1) { + _eglError(EGL_NOT_INITIALIZED, "eglInitialize(unable to add configs)"); + goto fail; + } + + *major = 1; + *minor = 4; + + return EGL_TRUE; + +fail: + if (gdpy) + egl_g3d_terminate(drv, dpy); + return EGL_FALSE; +} + +static _EGLContext * +egl_g3d_create_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, + _EGLContext *share, const EGLint *attribs) +{ + struct egl_g3d_display *gdpy = egl_g3d_display(dpy); + struct egl_g3d_context *xshare = egl_g3d_context(share); + struct egl_g3d_config *gconf = egl_g3d_config(conf); + struct egl_g3d_context *gctx; + const __GLcontextModes *mode; + + gctx = CALLOC_STRUCT(egl_g3d_context); + if (!gctx) { + _eglError(EGL_BAD_ALLOC, "eglCreateContext"); + return NULL; + } + + if (!_eglInitContext(drv, &gctx->base, conf, attribs)) { + free(gctx); + return NULL; + } + + gctx->stapi = egl_g3d_choose_st(drv, &gctx->base); + if (!gctx->stapi) { + free(gctx); + return NULL; + } + + mode = &gconf->native->mode; + gctx->pipe = + gdpy->native->create_context(gdpy->native, (void *) &gctx->base); + gctx->st_ctx = gctx->stapi->st_create_context(gctx->pipe, mode, + (xshare) ? xshare->st_ctx : NULL); + + return &gctx->base; +} + +static EGLBoolean +egl_g3d_destroy_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx) +{ + struct egl_g3d_context *gctx = egl_g3d_context(ctx); + + if (_eglIsContextBound(&gctx->base)) + return EGL_TRUE; + + egl_g3d_realloc_context(dpy, &gctx->base); + + /* it will destroy pipe context */ + gctx->stapi->st_destroy_context(gctx->st_ctx); + + free(gctx); + + return EGL_TRUE; +} + +static _EGLSurface * +egl_g3d_create_window_surface(_EGLDriver *drv, _EGLDisplay *dpy, + _EGLConfig *conf, EGLNativeWindowType win, + const EGLint *attribs) +{ + struct egl_g3d_display *gdpy = egl_g3d_display(dpy); + struct egl_g3d_config *gconf = egl_g3d_config(conf); + struct egl_g3d_surface *gsurf; + + gsurf = CALLOC_STRUCT(egl_g3d_surface); + if (!gsurf) { + _eglError(EGL_BAD_ALLOC, "eglCreateWindowSurface"); + return NULL; + } + + if (!_eglInitSurface(drv, &gsurf->base, EGL_WINDOW_BIT, conf, attribs)) { + free(gsurf); + return NULL; + } + + gsurf->native = + gdpy->native->create_window_surface(gdpy->native, win, gconf->native); + if (!gsurf->native) { + free(gsurf); + return NULL; + } + + if (!gsurf->native->validate(gsurf->native, NULL, 0, NULL, + &gsurf->base.Width, &gsurf->base.Height)) { + gsurf->native->destroy(gsurf->native); + free(gsurf); + return NULL; + } + + gsurf->render_att = (gsurf->base.RenderBuffer == EGL_SINGLE_BUFFER || + !gconf->native->mode.doubleBufferMode) ? + NATIVE_ATTACHMENT_FRONT_LEFT : NATIVE_ATTACHMENT_BACK_LEFT; + + return &gsurf->base; +} + +static _EGLSurface * +egl_g3d_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *dpy, + _EGLConfig *conf, EGLNativePixmapType pix, + const EGLint *attribs) +{ + struct egl_g3d_display *gdpy = egl_g3d_display(dpy); + struct egl_g3d_config *gconf = egl_g3d_config(conf); + struct egl_g3d_surface *gsurf; + + gsurf = CALLOC_STRUCT(egl_g3d_surface); + if (!gsurf) { + _eglError(EGL_BAD_ALLOC, "eglCreatePixmapSurface"); + return NULL; + } + + if (!_eglInitSurface(drv, &gsurf->base, EGL_PIXMAP_BIT, conf, attribs)) { + free(gsurf); + return NULL; + } + + gsurf->native = + gdpy->native->create_pixmap_surface(gdpy->native, pix, gconf->native); + if (!gsurf->native) { + free(gsurf); + return NULL; + } + + if (!gsurf->native->validate(gsurf->native, NULL, 0, NULL, + &gsurf->base.Width, &gsurf->base.Height)) { + gsurf->native->destroy(gsurf->native); + free(gsurf); + return NULL; + } + + gsurf->render_att = NATIVE_ATTACHMENT_FRONT_LEFT; + + return &gsurf->base; +} + +static _EGLSurface * +egl_g3d_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *dpy, + _EGLConfig *conf, const EGLint *attribs) +{ + struct egl_g3d_display *gdpy = egl_g3d_display(dpy); + struct egl_g3d_config *gconf = egl_g3d_config(conf); + struct egl_g3d_surface *gsurf; + + gsurf = CALLOC_STRUCT(egl_g3d_surface); + if (!gsurf) { + _eglError(EGL_BAD_ALLOC, "eglCreatePbufferSurface"); + return NULL; + } + + if (!_eglInitSurface(drv, &gsurf->base, EGL_PBUFFER_BIT, conf, attribs)) { + free(gsurf); + return NULL; + } + + gsurf->native = + gdpy->native->create_pbuffer_surface(gdpy->native, gconf->native, + gsurf->base.Width, gsurf->base.Height); + if (!gsurf->native) { + free(gsurf); + return NULL; + } + + gsurf->render_att = (!gconf->native->mode.doubleBufferMode) ? + NATIVE_ATTACHMENT_FRONT_LEFT : NATIVE_ATTACHMENT_BACK_LEFT; + + return &gsurf->base; +} + +static EGLBoolean +egl_g3d_destroy_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf) +{ + struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); + + if (_eglIsSurfaceBound(&gsurf->base)) + return EGL_TRUE; + + pipe_surface_reference(&gsurf->render_surface, NULL); + gsurf->native->destroy(gsurf->native); + free(gsurf); + return EGL_TRUE; +} + +static EGLBoolean +egl_g3d_make_current(_EGLDriver *drv, _EGLDisplay *dpy, + _EGLSurface *draw, _EGLSurface *read, _EGLContext *ctx) +{ + struct egl_g3d_context *gctx = egl_g3d_context(ctx); + struct egl_g3d_context *old_gctx; + EGLint api; + EGLBoolean ok = EGL_TRUE; + + /* find the old context */ + api = (gctx) ? gctx->base.ClientAPI : eglQueryAPI(); + old_gctx = egl_g3d_get_current_context(api); + if (old_gctx && !_eglIsContextLinked(&old_gctx->base)) + old_gctx = NULL; + + if (!_eglMakeCurrent(drv, dpy, draw, read, ctx)) + return EGL_FALSE; + + if (old_gctx) { + /* flush old context */ + old_gctx->stapi->st_flush(old_gctx->st_ctx, + PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL); + + /* + * The old context is no longer current, and egl_g3d_realloc_context() + * should be called to destroy the framebuffers. However, it is possible + * that it will be made current again with the same draw/read surfaces. + * It might be better to keep it around. + */ + } + + if (gctx) { + struct egl_g3d_surface *gdraw = egl_g3d_surface(draw); + + ok = egl_g3d_realloc_context(dpy, &gctx->base); + if (ok) { + ok = gctx->stapi->st_make_current(gctx->st_ctx, + gctx->draw.st_fb, gctx->read.st_fb); + if (ok) { + egl_g3d_validate_context(dpy, &gctx->base); + if (gdraw->base.Type == EGL_WINDOW_BIT) { + gctx->base.WindowRenderBuffer = + (gdraw->render_att == NATIVE_ATTACHMENT_FRONT_LEFT) ? + EGL_SINGLE_BUFFER : EGL_BACK_BUFFER; + } + } + } + } + else if (old_gctx) { + ok = old_gctx->stapi->st_make_current(NULL, NULL, NULL); + old_gctx->base.WindowRenderBuffer = EGL_NONE; + } + + return ok; +} + +static EGLBoolean +egl_g3d_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf) +{ + struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); + _EGLContext *ctx = _eglGetCurrentContext(); + struct egl_g3d_context *gctx = NULL; + + /* no-op for pixmap or pbuffer surface */ + if (gsurf->base.Type == EGL_PIXMAP_BIT || + gsurf->base.Type == EGL_PBUFFER_BIT) + return EGL_TRUE; + + /* or when the surface is single-buffered */ + if (gsurf->render_att == NATIVE_ATTACHMENT_FRONT_LEFT) + return EGL_TRUE; + + if (ctx && ctx->DrawSurface == surf) + gctx = egl_g3d_context(ctx); + + /* flush if the surface is current */ + if (gctx) + gctx->stapi->st_notify_swapbuffers(gctx->draw.st_fb); + + /* + * We drew on the back buffer, unless there was no back buffer. + * In that case, we drew on the front buffer. Either case, we call + * swap_buffers. + */ + if (!gsurf->native->swap_buffers(gsurf->native)) + return EGL_FALSE; + + if (gctx) { + struct egl_g3d_config *gconf = egl_g3d_config(gsurf->base.Config); + + /* force validation if the swap method is not copy */ + if (gconf->native->mode.swapMethod != GLX_SWAP_COPY_OML) + gctx->force_validate = EGL_TRUE; + egl_g3d_validate_context(dpy, &gctx->base); + } + + return EGL_TRUE; +} + +static EGLBoolean +egl_g3d_wait_client(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx) +{ + struct egl_g3d_context *gctx = egl_g3d_context(ctx); + gctx->stapi->st_finish(gctx->st_ctx); + return EGL_TRUE; +} + +static EGLBoolean +egl_g3d_wait_native(_EGLDriver *drv, _EGLDisplay *dpy, EGLint engine) +{ + _EGLSurface *surf = _eglGetCurrentSurface(EGL_DRAW); + struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); + + if (engine != EGL_CORE_NATIVE_ENGINE) + return _eglError(EGL_BAD_PARAMETER, "eglWaitNative"); + + if (gsurf) + gsurf->native->wait(gsurf->native); + + return EGL_TRUE; +} + +static _EGLProc +egl_g3d_get_proc_address(const char *procname) +{ + /* FIXME how come _EGLDriver is not passed? */ + const struct egl_g3d_st *stapi; + _EGLProc proc; + EGLint i; + + for (i = 0; i < NUM_EGL_G3D_STS; i++) { + stapi = egl_g3d_get_st(i); + if (stapi) { + proc = (_EGLProc) stapi->st_get_proc_address(procname); + if (proc) + return proc; + } + } + + return (_EGLProc) NULL; +} + +static EGLBoolean +egl_g3d_bind_tex_image(_EGLDriver *drv, _EGLDisplay *dpy, + _EGLSurface *surf, EGLint buffer) +{ + struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); + struct egl_g3d_context *gctx; + enum pipe_format target_format; + int target; + + if (!gsurf || gsurf->base.Type != EGL_PBUFFER_BIT) + return _eglError(EGL_BAD_SURFACE, "eglBindTexImage"); + if (buffer != EGL_BACK_BUFFER) + return _eglError(EGL_BAD_PARAMETER, "eglBindTexImage"); + if (gsurf->base.BoundToTexture) + return _eglError(EGL_BAD_ACCESS, "eglBindTexImage"); + + switch (gsurf->base.TextureFormat) { + case EGL_TEXTURE_RGB: + target_format = PIPE_FORMAT_R8G8B8_UNORM; + break; + case EGL_TEXTURE_RGBA: + target_format = PIPE_FORMAT_A8R8G8B8_UNORM; + break; + default: + return _eglError(EGL_BAD_MATCH, "eglBindTexImage"); + } + + switch (gsurf->base.TextureTarget) { + case EGL_TEXTURE_2D: + target = ST_TEXTURE_2D; + break; + default: + return _eglError(EGL_BAD_MATCH, "eglBindTexImage"); + } + + /* flush properly if the surface is bound */ + if (gsurf->base.Binding) { + gctx = egl_g3d_context(gsurf->base.Binding); + gctx->stapi->st_flush(gctx->st_ctx, + PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL); + } + + /* XXX change to EGL_OPENGL_ES_API once OpenGL ES is merged */ + gctx = egl_g3d_get_current_context(EGL_OPENGL_API); + if (gctx) { + if (!gsurf->render_surface) + return EGL_FALSE; + + gctx->stapi->st_bind_texture_surface(gsurf->render_surface, + target, gsurf->base.MipmapLevel, target_format); + gsurf->base.BoundToTexture = EGL_TRUE; + } + + return EGL_TRUE; +} + +static EGLBoolean +egl_g3d_release_tex_image(_EGLDriver *drv, _EGLDisplay *dpy, + _EGLSurface *surf, EGLint buffer) +{ + struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); + + if (!gsurf || gsurf->base.Type != EGL_PBUFFER_BIT || + !gsurf->base.BoundToTexture) + return _eglError(EGL_BAD_SURFACE, "eglReleaseTexImage"); + if (buffer != EGL_BACK_BUFFER) + return _eglError(EGL_BAD_PARAMETER, "eglReleaseTexImage"); + + if (gsurf->render_surface) { + _EGLThreadInfo *t = _eglGetCurrentThread(); + /* XXX change to EGL_OPENGL_ES_API once OpenGL ES is merged */ + struct egl_g3d_context *gctx = egl_g3d_context( + t->CurrentContexts[_eglConvertApiToIndex(EGL_OPENGL_API)]); + + /* what if the context the surface binds to is no longer current? */ + if (gctx) + gctx->stapi->st_unbind_texture_surface(gsurf->render_surface, + ST_TEXTURE_2D, gsurf->base.MipmapLevel); + } + + gsurf->base.BoundToTexture = EGL_FALSE; + + return EGL_TRUE; +} + +static void +egl_g3d_unload(_EGLDriver *drv) +{ + struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); + free(gdrv); +} + +_EGLDriver * +_eglMain(const char *args) +{ + static char driver_name[64]; + struct egl_g3d_driver *gdrv; + EGLint i; + + snprintf(driver_name, sizeof(driver_name), + "Gallium/%s", native_get_name()); + + gdrv = CALLOC_STRUCT(egl_g3d_driver); + if (!gdrv) + return NULL; + + _eglInitDriverFallbacks(&gdrv->base); + + gdrv->base.API.Initialize = egl_g3d_initialize; + gdrv->base.API.Terminate = egl_g3d_terminate; + gdrv->base.API.CreateContext = egl_g3d_create_context; + gdrv->base.API.DestroyContext = egl_g3d_destroy_context; + gdrv->base.API.CreateWindowSurface = egl_g3d_create_window_surface; + gdrv->base.API.CreatePixmapSurface = egl_g3d_create_pixmap_surface; + gdrv->base.API.CreatePbufferSurface = egl_g3d_create_pbuffer_surface; + gdrv->base.API.DestroySurface = egl_g3d_destroy_surface; + gdrv->base.API.MakeCurrent = egl_g3d_make_current; + gdrv->base.API.SwapBuffers = egl_g3d_swap_buffers; + gdrv->base.API.WaitClient = egl_g3d_wait_client; + gdrv->base.API.WaitNative = egl_g3d_wait_native; + gdrv->base.API.GetProcAddress = egl_g3d_get_proc_address; + + gdrv->base.API.BindTexImage = egl_g3d_bind_tex_image; + gdrv->base.API.ReleaseTexImage = egl_g3d_release_tex_image; + + gdrv->base.Name = driver_name; + gdrv->base.Unload = egl_g3d_unload; + + for (i = 0; i < NUM_EGL_G3D_STS; i++) { + gdrv->stapis[i] = egl_g3d_get_st(i); + if (gdrv->stapis[i]) + gdrv->api_mask |= gdrv->stapis[i]->api_bit; + } + + if (gdrv->api_mask) + _eglLog(_EGL_DEBUG, "Driver API mask: 0x%x", gdrv->api_mask); + else + _eglLog(_EGL_WARNING, "No supported client API"); + + return &gdrv->base; +} diff --git a/src/gallium/state_trackers/egl_g3d/common/egl_g3d.h b/src/gallium/state_trackers/egl_g3d/common/egl_g3d.h new file mode 100644 index 0000000000..525bb488e2 --- /dev/null +++ b/src/gallium/state_trackers/egl_g3d/common/egl_g3d.h @@ -0,0 +1,113 @@ +/* + * Mesa 3-D graphics library + * Version: 7.8 + * + * Copyright (C) 2009-2010 Chia-I Wu + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef _EGL_G3D_H_ +#define _EGL_G3D_H_ + +#include "pipe/p_compiler.h" +#include "pipe/p_screen.h" +#include "pipe/p_context.h" +#include "pipe/p_format.h" +#include "egldriver.h" +#include "egldisplay.h" +#include "eglcontext.h" +#include "eglsurface.h" +#include "eglconfig.h" + +#include "native.h" +#include "egl_st.h" + +struct egl_g3d_driver { + _EGLDriver base; + const struct egl_g3d_st *stapis[NUM_EGL_G3D_STS]; + EGLint api_mask; +}; + +struct egl_g3d_display { + struct native_display *native; +}; + +struct egl_g3d_buffer { + struct st_framebuffer *st_fb; + EGLint num_atts; + enum native_attachment native_atts[NUM_NATIVE_ATTACHMENTS]; + uint st_atts[NUM_NATIVE_ATTACHMENTS]; +}; + +struct egl_g3d_context { + _EGLContext base; + + const struct egl_g3d_st *stapi; + struct pipe_context *pipe; + + struct st_context *st_ctx; + EGLBoolean force_validate; + struct egl_g3d_buffer draw, read; +}; + +struct egl_g3d_surface { + _EGLSurface base; + struct native_surface *native; + enum native_attachment render_att; + struct pipe_surface *render_surface; +}; + +struct egl_g3d_config { + _EGLConfig base; + const struct native_config *native; +}; + + +static INLINE struct egl_g3d_driver * +egl_g3d_driver(_EGLDriver *drv) +{ + return (struct egl_g3d_driver *) drv; +} + +static INLINE struct egl_g3d_display * +egl_g3d_display(_EGLDisplay *dpy) +{ + /* note that it is not direct casting */ + return (struct egl_g3d_display *) dpy->DriverData; +} + +static INLINE struct egl_g3d_context * +egl_g3d_context(_EGLContext *ctx) +{ + return (struct egl_g3d_context *) ctx; +} + +static INLINE struct egl_g3d_surface * +egl_g3d_surface(_EGLSurface *surf) +{ + return (struct egl_g3d_surface *) surf; +} + +static INLINE struct egl_g3d_config * +egl_g3d_config(_EGLConfig *conf) +{ + return (struct egl_g3d_config *) conf; +} + +#endif /* _EGL_G3D_H_ */ diff --git a/src/gallium/state_trackers/egl_g3d/common/egl_st.c b/src/gallium/state_trackers/egl_g3d/common/egl_st.c new file mode 100644 index 0000000000..a88ff911cd --- /dev/null +++ b/src/gallium/state_trackers/egl_g3d/common/egl_st.c @@ -0,0 +1,131 @@ +/* + * Mesa 3-D graphics library + * Version: 7.8 + * + * Copyright (C) 2009-2010 Chia-I Wu + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "pipe/p_compiler.h" +#include "util/u_memory.h" +#include "egllog.h" +#include "EGL/egl.h" /* for EGL_api_BIT */ + +#include "egl_st.h" + +#ifndef HAVE_DLADDR +#define HAVE_DLADDR 1 +#endif + +#if HAVE_DLADDR + +static const char * +egl_g3d_st_names[] = { +#define ST_PUBLIC(name, ...) #name, +#include "st_public_tmp.h" + NULL +}; + +static boolean +egl_g3d_fill_st(struct egl_g3d_st *stapi, void *sym) +{ + st_proc *procs = (st_proc *) stapi; + void *handle; + Dl_info info; + const char **name; + + if (!dladdr(sym, &info)) + return FALSE; + handle = dlopen(info.dli_fname, RTLD_LAZY | RTLD_LOCAL | RTLD_NODELETE); + if (!handle) + return FALSE; + + for (name = egl_g3d_st_names; *name; name++) { + st_proc proc = (st_proc) dlsym(handle, *name); + if (!proc) { + _eglLog(_EGL_WARNING, "%s is missing in %s", *name, info.dli_fname); + memset(stapi, 0, sizeof(*stapi)); + dlclose(handle); + return FALSE; + } + *procs++ = proc; + } + + dlclose(handle); + return TRUE; +} + +#else /* HAVE_DLADDR */ + +static boolean +egl_g3d_fill_st(struct egl_g3d_st *stapi, void *sym) +{ +#define ST_PUBLIC(name, ...) stapi->name = name; +#include "st_public_tmp.h" + return TRUE; +} + +#endif /* HAVE_DLADDR */ + +static boolean +egl_g3d_init_st(struct egl_g3d_st *stapi, const char *api) +{ + void *handle, *sym; + boolean res = FALSE; + + /* already initialized */ + if (stapi->st_notify_swapbuffers != NULL) + return TRUE; + + handle = dlopen(NULL, RTLD_LAZY | RTLD_LOCAL); + if (!handle) + return FALSE; + + sym = dlsym(handle, api); + if (sym && egl_g3d_fill_st(stapi, sym)) + res = TRUE; + + dlclose(handle); + return res; +} + +static struct { + const char *symbol; + EGLint api_bit; +} egl_g3d_st_info[NUM_EGL_G3D_STS] = { + { "st_api_OpenGL_ES1", EGL_OPENGL_ES_BIT }, + { "st_api_OpenVG", EGL_OPENVG_BIT }, + { "st_api_OpenGL_ES2", EGL_OPENGL_ES2_BIT }, + { "st_api_OpenGL", EGL_OPENGL_BIT }, +}; + +const struct egl_g3d_st * +egl_g3d_get_st(enum egl_g3d_st_api api) +{ + static struct egl_g3d_st all_trackers[NUM_EGL_G3D_STS]; + + if (egl_g3d_init_st(&all_trackers[api], egl_g3d_st_info[api].symbol)) { + all_trackers[api].api_bit = egl_g3d_st_info[api].api_bit; + return &all_trackers[api]; + } + else { + return NULL; + } +} diff --git a/src/gallium/state_trackers/egl_g3d/common/egl_st.h b/src/gallium/state_trackers/egl_g3d/common/egl_st.h new file mode 100644 index 0000000000..8fb464bd3d --- /dev/null +++ b/src/gallium/state_trackers/egl_g3d/common/egl_st.h @@ -0,0 +1,73 @@ +/* + * Mesa 3-D graphics library + * Version: 7.8 + * + * Copyright (C) 2009-2010 Chia-I Wu + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef _EGL_ST_H_ +#define _EGL_ST_H_ + +#include "GL/gl.h" /* for GL types */ +#include "GL/internal/glcore.h" /* for __GLcontextModes */ + +#include "pipe/p_compiler.h" +#include "pipe/p_format.h" +#include "pipe/p_context.h" + +/* avoid calling st functions directly */ +#if 1 + +#define ST_SURFACE_FRONT_LEFT 0 +#define ST_SURFACE_BACK_LEFT 1 +#define ST_SURFACE_FRONT_RIGHT 2 +#define ST_SURFACE_BACK_RIGHT 3 + +#define ST_TEXTURE_2D 0x2 + +struct st_context; +struct st_framebuffer; +typedef void (*st_proc)(); + +#else +#include "state_tracker/st_public.h" +#endif + +/* remember to update egl_g3d_get_st() when update the enums */ +enum egl_g3d_st_api { + EGL_G3D_ST_OPENGL_ES = 0, + EGL_G3D_ST_OPENVG, + EGL_G3D_ST_OPENGL_ES2, + EGL_G3D_ST_OPENGL, + + NUM_EGL_G3D_STS +}; + +struct egl_g3d_st { +#define ST_PUBLIC(name, ret, ...) ret (*name)(__VA_ARGS__); +#include "st_public_tmp.h" + /* fields must be added here */ + EGLint api_bit; +}; + +const struct egl_g3d_st * +egl_g3d_get_st(enum egl_g3d_st_api api); + +#endif /* _EGL_ST_H_ */ diff --git a/src/gallium/state_trackers/egl_g3d/common/native.h b/src/gallium/state_trackers/egl_g3d/common/native.h new file mode 100644 index 0000000000..34abd86a31 --- /dev/null +++ b/src/gallium/state_trackers/egl_g3d/common/native.h @@ -0,0 +1,168 @@ +/* + * Mesa 3-D graphics library + * Version: 7.8 + * + * Copyright (C) 2009-2010 Chia-I Wu + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef _NATIVE_H_ +#define _NATIVE_H_ + +#include "EGL/egl.h" /* for EGL native types */ +#include "GL/gl.h" /* for GL types needed by __GLcontextModes */ +#include "GL/internal/glcore.h" /* for __GLcontextModes */ + +#include "pipe/p_compiler.h" +#include "pipe/p_screen.h" +#include "pipe/p_context.h" +#include "pipe/p_state.h" + +/** + * Only color buffers are listed. The others are allocated privately through, + * for example, st_renderbuffer_alloc_storage(). + */ +enum native_attachment { + NATIVE_ATTACHMENT_FRONT_LEFT, + NATIVE_ATTACHMENT_BACK_LEFT, + NATIVE_ATTACHMENT_FRONT_RIGHT, + NATIVE_ATTACHMENT_BACK_RIGHT, + + NUM_NATIVE_ATTACHMENTS +}; + +struct native_surface { + void (*destroy)(struct native_surface *nsurf); + + /** + * Swap the front and back buffers so that the back buffer is visible. It + * is no-op if the surface is single-buffered. The contents of the back + * buffer after swapping may or may not be preserved. + */ + boolean (*swap_buffers)(struct native_surface *nsurf); + + /** + * Make the front buffer visible. In some native displays, changes to the + * front buffer might not be visible immediately and require manual flush. + */ + boolean (*flush_frontbuffer)(struct native_surface *nsurf); + + /** + * Validate the buffers of the surface. Those not listed in the attachments + * will be destroyed. The returned textures are owned by the caller. + */ + boolean (*validate)(struct native_surface *nsurf, + const enum native_attachment *natts, + unsigned num_natts, + struct pipe_texture **textures, + int *width, int *height); + + /** + * Wait until all native commands affecting the surface has been executed. + */ + void (*wait)(struct native_surface *nsurf); +}; + +struct native_config { + __GLcontextModes mode; + enum pipe_format color_format; + enum pipe_format depth_format; + enum pipe_format stencil_format; +}; + +/** + * A pipe winsys abstracts the OS. A pipe screen abstracts the graphcis + * hardware. A native display consists of a pipe winsys, a pipe screen, and + * the native display server. + */ +struct native_display { + struct pipe_screen *screen; + void (*destroy)(struct native_display *ndpy); + + /** + * Get the supported configs. The configs are owned by the display, but + * the returned array should be free()ed. + * + * The configs will be converted to EGL config by + * _eglConfigFromContextModesRec and validated by _eglValidateConfig. + * Those failing to pass the test will be skipped. + */ + const struct native_config **(*get_configs)(struct native_display *ndpy, + int *num_configs); + + /** + * Create a pipe context. + */ + struct pipe_context *(*create_context)(struct native_display *ndpy, + void *context_private); + + /** + * Create a window surface. Required unless no config has GLX_WINDOW_BIT + * set. + */ + struct native_surface *(*create_window_surface)(struct native_display *ndpy, + EGLNativeWindowType win, + const struct native_config *nconf); + + /** + * Create a pixmap surface. Required unless no config has GLX_PIXMAP_BIT + * set. + */ + struct native_surface *(*create_pixmap_surface)(struct native_display *ndpy, + EGLNativePixmapType pix, + const struct native_config *nconf); + + /** + * Create a pbuffer surface. Required unless no config has GLX_PBUFFER_BIT + * set. + */ + struct native_surface *(*create_pbuffer_surface)(struct native_display *ndpy, + const struct native_config *nconf, + uint width, uint height); + +#if 0 + struct native_mode *(*get_modes)(struct native_display *ndpy, + int *num_modes); + + /** + * Create a screen surface. + */ + struct native_surface *(*create_screen_surface)(struct native_display *ndpy, + const struct native_config *nconf, + uint width, uint height); + + boolean (*set_mode)(struct native_display *ndpy, + const struct native_mode *nmode, + struct native_surface *nsurf); +#endif +}; + + +typedef void (*native_flush_frontbuffer)(void *dummy, + struct pipe_surface *surf, + void *context_private); + +const char * +native_get_name(void); + +struct native_display * +native_create_display(EGLNativeDisplayType dpy, + native_flush_frontbuffer flush_frontbuffer); + +#endif /* _NATIVE_H_ */ diff --git a/src/gallium/state_trackers/egl_g3d/common/st_public_tmp.h b/src/gallium/state_trackers/egl_g3d/common/st_public_tmp.h new file mode 100644 index 0000000000..507a0ec402 --- /dev/null +++ b/src/gallium/state_trackers/egl_g3d/common/st_public_tmp.h @@ -0,0 +1,20 @@ +ST_PUBLIC(st_create_context, struct st_context *, struct pipe_context *pipe, const __GLcontextModes *visual, struct st_context *share) +ST_PUBLIC(st_destroy_context, void, struct st_context *st) +ST_PUBLIC(st_copy_context_state, void, struct st_context *dst, struct st_context *src, uint mask) +ST_PUBLIC(st_create_framebuffer, struct st_framebuffer *, const __GLcontextModes *visual, enum pipe_format colorFormat, enum pipe_format depthFormat, enum pipe_format stencilFormat, uint width, uint height, void *privateData) +ST_PUBLIC(st_resize_framebuffer, void, struct st_framebuffer *stfb, uint width, uint height) +ST_PUBLIC(st_set_framebuffer_surface, void, struct st_framebuffer *stfb, uint surfIndex, struct pipe_surface *surf) +ST_PUBLIC(st_get_framebuffer_dimensions, void, struct st_framebuffer *stfb, uint *width, uint *height) +ST_PUBLIC(st_get_framebuffer_surface, int, struct st_framebuffer *stfb, uint surfIndex, struct pipe_surface **surface) +ST_PUBLIC(st_get_framebuffer_texture, int, struct st_framebuffer *stfb, uint surfIndex, struct pipe_texture **texture) +ST_PUBLIC(st_framebuffer_private, void *, struct st_framebuffer *stfb) +ST_PUBLIC(st_unreference_framebuffer, void, struct st_framebuffer *stfb) +ST_PUBLIC(st_make_current, GLboolean, struct st_context *st, struct st_framebuffer *draw, struct st_framebuffer *read) +ST_PUBLIC(st_get_current, struct st_context *, void) +ST_PUBLIC(st_flush, void, struct st_context *st, uint pipeFlushFlags, struct pipe_fence_handle **fence) +ST_PUBLIC(st_finish, void, struct st_context *st) +ST_PUBLIC(st_notify_swapbuffers, void, struct st_framebuffer *stfb) +ST_PUBLIC(st_bind_texture_surface, int, struct pipe_surface *ps, int target, int level, enum pipe_format format) +ST_PUBLIC(st_unbind_texture_surface, int, struct pipe_surface *ps, int target, int level) +ST_PUBLIC(st_get_proc_address, st_proc, const char *procname) +#undef ST_PUBLIC diff --git a/src/gallium/state_trackers/egl_g3d/x11/glxinit.c b/src/gallium/state_trackers/egl_g3d/x11/glxinit.c new file mode 100644 index 0000000000..c955a908b9 --- /dev/null +++ b/src/gallium/state_trackers/egl_g3d/x11/glxinit.c @@ -0,0 +1,573 @@ +/** + * GLX initialization. Code based on glxext.c, glx_query.c, and + * glcontextmodes.c under src/glx/x11/. The major difference is that no DRI + * related code here. + * + */ + +#include +#include +#include +#include +#include +#include + +#include "x11_screen.h" +#include "glxinit.h" + +typedef struct GLXGenericGetString +{ + CARD8 reqType; + CARD8 glxCode; + CARD16 length B16; + CARD32 for_whom B32; + CARD32 name B32; +} xGLXGenericGetStringReq; + +#define sz_xGLXGenericGetStringReq 12 +#define X_GLXGenericGetString 0 + +/* Extension required boiler plate */ + +static char *__glXExtensionName = GLX_EXTENSION_NAME; +static XExtensionInfo *__glXExtensionInfo = NULL; + +static /* const */ XExtensionHooks __glXExtensionHooks = { NULL }; +static +XEXT_GENERATE_FIND_DISPLAY(__glXFindDisplay, __glXExtensionInfo, + __glXExtensionName, &__glXExtensionHooks, + __GLX_NUMBER_EVENTS, NULL) + +static GLint +_gl_convert_from_x_visual_type(int visualType) +{ +#define NUM_VISUAL_TYPES 6 + static const int glx_visual_types[NUM_VISUAL_TYPES] = { + GLX_STATIC_GRAY, GLX_GRAY_SCALE, + GLX_STATIC_COLOR, GLX_PSEUDO_COLOR, + GLX_TRUE_COLOR, GLX_DIRECT_COLOR + }; + + return ((unsigned) visualType < NUM_VISUAL_TYPES) + ? glx_visual_types[visualType] : GLX_NONE; +} + +_X_HIDDEN char * +__glXQueryServerString(Display * dpy, int opcode, CARD32 screen, CARD32 name) +{ + xGLXGenericGetStringReq *req; + xGLXSingleReply reply; + int length; + int numbytes; + char *buf; + CARD32 for_whom = screen; + CARD32 glxCode = X_GLXQueryServerString; + + + LockDisplay(dpy); + + + /* All of the GLX protocol requests for getting a string from the server + * look the same. The exact meaning of the for_whom field is usually + * either the screen number (for glXQueryServerString) or the context tag + * (for GLXSingle). + */ + + GetReq(GLXGenericGetString, req); + req->reqType = opcode; + req->glxCode = glxCode; + req->for_whom = for_whom; + req->name = name; + + _XReply(dpy, (xReply *) & reply, 0, False); + + length = reply.length * 4; + numbytes = reply.size; + + buf = (char *) Xmalloc(numbytes); + if (buf != NULL) { + _XRead(dpy, buf, numbytes); + length -= numbytes; + } + + _XEatData(dpy, length); + + UnlockDisplay(dpy); + SyncHandle(); + + return buf; +} + +/************************************************************************/ +/* +** Free the per screen configs data as well as the array of +** __glXScreenConfigs. +*/ +static void +FreeScreenConfigs(__GLXdisplayPrivate * priv) +{ + __GLXscreenConfigs *psc; + GLint i, screens; + + /* Free screen configuration information */ + psc = priv->screenConfigs; + screens = ScreenCount(priv->dpy); + for (i = 0; i < screens; i++, psc++) { + if (psc->configs) { + x11_context_modes_destroy(psc->configs); + psc->configs = NULL; /* NOTE: just for paranoia */ + } + if (psc->visuals) { + x11_context_modes_destroy(psc->visuals); + psc->visuals = NULL; /* NOTE: just for paranoia */ + } + Xfree((char *) psc->serverGLXexts); + } + XFree((char *) priv->screenConfigs); + priv->screenConfigs = NULL; +} + +/************************************************************************/ + +/* +** Query the version of the GLX extension. This procedure works even if +** the client extension is not completely set up. +*/ +static Bool +QueryVersion(Display * dpy, int opcode, int *major, int *minor) +{ + xGLXQueryVersionReq *req; + xGLXQueryVersionReply reply; + + /* Send the glXQueryVersion request */ + LockDisplay(dpy); + GetReq(GLXQueryVersion, req); + req->reqType = opcode; + req->glxCode = X_GLXQueryVersion; + req->majorVersion = GLX_MAJOR_VERSION; + req->minorVersion = GLX_MINOR_VERSION; + _XReply(dpy, (xReply *) & reply, 0, False); + UnlockDisplay(dpy); + SyncHandle(); + + if (reply.majorVersion != GLX_MAJOR_VERSION) { + /* + ** The server does not support the same major release as this + ** client. + */ + return GL_FALSE; + } + *major = reply.majorVersion; + *minor = min(reply.minorVersion, GLX_MINOR_VERSION); + return GL_TRUE; +} + +_X_HIDDEN void +__glXInitializeVisualConfigFromTags(__GLcontextModes * config, int count, + const INT32 * bp, Bool tagged_only, + Bool fbconfig_style_tags) +{ + int i; + + if (!tagged_only) { + /* Copy in the first set of properties */ + config->visualID = *bp++; + + config->visualType = _gl_convert_from_x_visual_type(*bp++); + + config->rgbMode = *bp++; + + config->redBits = *bp++; + config->greenBits = *bp++; + config->blueBits = *bp++; + config->alphaBits = *bp++; + config->accumRedBits = *bp++; + config->accumGreenBits = *bp++; + config->accumBlueBits = *bp++; + config->accumAlphaBits = *bp++; + + config->doubleBufferMode = *bp++; + config->stereoMode = *bp++; + + config->rgbBits = *bp++; + config->depthBits = *bp++; + config->stencilBits = *bp++; + config->numAuxBuffers = *bp++; + config->level = *bp++; + + count -= __GLX_MIN_CONFIG_PROPS; + } + + /* + ** Additional properties may be in a list at the end + ** of the reply. They are in pairs of property type + ** and property value. + */ + +#define FETCH_OR_SET(tag) \ + config-> tag = ( fbconfig_style_tags ) ? *bp++ : 1 + + for (i = 0; i < count; i += 2) { + switch (*bp++) { + case GLX_RGBA: + FETCH_OR_SET(rgbMode); + break; + case GLX_BUFFER_SIZE: + config->rgbBits = *bp++; + break; + case GLX_LEVEL: + config->level = *bp++; + break; + case GLX_DOUBLEBUFFER: + FETCH_OR_SET(doubleBufferMode); + break; + case GLX_STEREO: + FETCH_OR_SET(stereoMode); + break; + case GLX_AUX_BUFFERS: + config->numAuxBuffers = *bp++; + break; + case GLX_RED_SIZE: + config->redBits = *bp++; + break; + case GLX_GREEN_SIZE: + config->greenBits = *bp++; + break; + case GLX_BLUE_SIZE: + config->blueBits = *bp++; + break; + case GLX_ALPHA_SIZE: + config->alphaBits = *bp++; + break; + case GLX_DEPTH_SIZE: + config->depthBits = *bp++; + break; + case GLX_STENCIL_SIZE: + config->stencilBits = *bp++; + break; + case GLX_ACCUM_RED_SIZE: + config->accumRedBits = *bp++; + break; + case GLX_ACCUM_GREEN_SIZE: + config->accumGreenBits = *bp++; + break; + case GLX_ACCUM_BLUE_SIZE: + config->accumBlueBits = *bp++; + break; + case GLX_ACCUM_ALPHA_SIZE: + config->accumAlphaBits = *bp++; + break; + case GLX_VISUAL_CAVEAT_EXT: + config->visualRating = *bp++; + break; + case GLX_X_VISUAL_TYPE: + config->visualType = *bp++; + break; + case GLX_TRANSPARENT_TYPE: + config->transparentPixel = *bp++; + break; + case GLX_TRANSPARENT_INDEX_VALUE: + config->transparentIndex = *bp++; + break; + case GLX_TRANSPARENT_RED_VALUE: + config->transparentRed = *bp++; + break; + case GLX_TRANSPARENT_GREEN_VALUE: + config->transparentGreen = *bp++; + break; + case GLX_TRANSPARENT_BLUE_VALUE: + config->transparentBlue = *bp++; + break; + case GLX_TRANSPARENT_ALPHA_VALUE: + config->transparentAlpha = *bp++; + break; + case GLX_VISUAL_ID: + config->visualID = *bp++; + break; + case GLX_DRAWABLE_TYPE: + config->drawableType = *bp++; + break; + case GLX_RENDER_TYPE: + config->renderType = *bp++; + break; + case GLX_X_RENDERABLE: + config->xRenderable = *bp++; + break; + case GLX_FBCONFIG_ID: + config->fbconfigID = *bp++; + break; + case GLX_MAX_PBUFFER_WIDTH: + config->maxPbufferWidth = *bp++; + break; + case GLX_MAX_PBUFFER_HEIGHT: + config->maxPbufferHeight = *bp++; + break; + case GLX_MAX_PBUFFER_PIXELS: + config->maxPbufferPixels = *bp++; + break; + case GLX_OPTIMAL_PBUFFER_WIDTH_SGIX: + config->optimalPbufferWidth = *bp++; + break; + case GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX: + config->optimalPbufferHeight = *bp++; + break; + case GLX_VISUAL_SELECT_GROUP_SGIX: + config->visualSelectGroup = *bp++; + break; + case GLX_SWAP_METHOD_OML: + config->swapMethod = *bp++; + break; + case GLX_SAMPLE_BUFFERS_SGIS: + config->sampleBuffers = *bp++; + break; + case GLX_SAMPLES_SGIS: + config->samples = *bp++; + break; + case GLX_BIND_TO_TEXTURE_RGB_EXT: + config->bindToTextureRgb = *bp++; + break; + case GLX_BIND_TO_TEXTURE_RGBA_EXT: + config->bindToTextureRgba = *bp++; + break; + case GLX_BIND_TO_MIPMAP_TEXTURE_EXT: + config->bindToMipmapTexture = *bp++; + break; + case GLX_BIND_TO_TEXTURE_TARGETS_EXT: + config->bindToTextureTargets = *bp++; + break; + case GLX_Y_INVERTED_EXT: + config->yInverted = *bp++; + break; + case None: + i = count; + break; + default: + break; + } + } + + config->renderType = + (config->rgbMode) ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT; + + config->haveAccumBuffer = ((config->accumRedBits + + config->accumGreenBits + + config->accumBlueBits + + config->accumAlphaBits) > 0); + config->haveDepthBuffer = (config->depthBits > 0); + config->haveStencilBuffer = (config->stencilBits > 0); +} + +static __GLcontextModes * +createConfigsFromProperties(Display * dpy, int nvisuals, int nprops, + int screen, GLboolean tagged_only) +{ + INT32 buf[__GLX_TOTAL_CONFIG], *props; + unsigned prop_size; + __GLcontextModes *modes, *m; + int i; + + if (nprops == 0) + return NULL; + + /* FIXME: Is the __GLX_MIN_CONFIG_PROPS test correct for FBconfigs? */ + + /* Check number of properties */ + if (nprops < __GLX_MIN_CONFIG_PROPS || nprops > __GLX_MAX_CONFIG_PROPS) + return NULL; + + /* Allocate memory for our config structure */ + modes = x11_context_modes_create(nvisuals); + if (!modes) + return NULL; + + prop_size = nprops * __GLX_SIZE_INT32; + if (prop_size <= sizeof(buf)) + props = buf; + else + props = Xmalloc(prop_size); + + /* Read each config structure and convert it into our format */ + m = modes; + for (i = 0; i < nvisuals; i++) { + _XRead(dpy, (char *) props, prop_size); + /* Older X servers don't send this so we default it here. */ + m->drawableType = GLX_WINDOW_BIT; + __glXInitializeVisualConfigFromTags(m, nprops, props, + tagged_only, GL_TRUE); + m->screen = screen; + m = m->next; + } + + if (props != buf) + Xfree(props); + + return modes; +} + +static GLboolean +getVisualConfigs(Display * dpy, __GLXdisplayPrivate * priv, int screen) +{ + xGLXGetVisualConfigsReq *req; + __GLXscreenConfigs *psc; + xGLXGetVisualConfigsReply reply; + + LockDisplay(dpy); + + psc = priv->screenConfigs + screen; + psc->visuals = NULL; + GetReq(GLXGetVisualConfigs, req); + req->reqType = priv->majorOpcode; + req->glxCode = X_GLXGetVisualConfigs; + req->screen = screen; + + if (!_XReply(dpy, (xReply *) & reply, 0, False)) + goto out; + + psc->visuals = createConfigsFromProperties(dpy, + reply.numVisuals, + reply.numProps, + screen, GL_FALSE); + + out: + UnlockDisplay(dpy); + return psc->visuals != NULL; +} + +static GLboolean +getFBConfigs(Display * dpy, __GLXdisplayPrivate * priv, int screen) +{ + xGLXGetFBConfigsReq *fb_req; + xGLXGetFBConfigsSGIXReq *sgi_req; + xGLXVendorPrivateWithReplyReq *vpreq; + xGLXGetFBConfigsReply reply; + __GLXscreenConfigs *psc; + + psc = priv->screenConfigs + screen; + psc->serverGLXexts = + __glXQueryServerString(dpy, priv->majorOpcode, screen, GLX_EXTENSIONS); + + LockDisplay(dpy); + + psc->configs = NULL; + if (atof(priv->serverGLXversion) >= 1.3) { + GetReq(GLXGetFBConfigs, fb_req); + fb_req->reqType = priv->majorOpcode; + fb_req->glxCode = X_GLXGetFBConfigs; + fb_req->screen = screen; + } + else if (strstr(psc->serverGLXexts, "GLX_SGIX_fbconfig") != NULL) { + GetReqExtra(GLXVendorPrivateWithReply, + sz_xGLXGetFBConfigsSGIXReq + + sz_xGLXVendorPrivateWithReplyReq, vpreq); + sgi_req = (xGLXGetFBConfigsSGIXReq *) vpreq; + sgi_req->reqType = priv->majorOpcode; + sgi_req->glxCode = X_GLXVendorPrivateWithReply; + sgi_req->vendorCode = X_GLXvop_GetFBConfigsSGIX; + sgi_req->screen = screen; + } + else + goto out; + + if (!_XReply(dpy, (xReply *) & reply, 0, False)) + goto out; + + psc->configs = createConfigsFromProperties(dpy, + reply.numFBConfigs, + reply.numAttribs * 2, + screen, GL_TRUE); + + out: + UnlockDisplay(dpy); + return psc->configs != NULL; +} + +static GLboolean +AllocAndFetchScreenConfigs(Display * dpy, __GLXdisplayPrivate * priv) +{ + __GLXscreenConfigs *psc; + GLint i, screens; + + /* + ** First allocate memory for the array of per screen configs. + */ + screens = ScreenCount(dpy); + psc = (__GLXscreenConfigs *) Xmalloc(screens * sizeof(__GLXscreenConfigs)); + if (!psc) { + return GL_FALSE; + } + memset(psc, 0, screens * sizeof(__GLXscreenConfigs)); + priv->screenConfigs = psc; + + priv->serverGLXversion = + __glXQueryServerString(dpy, priv->majorOpcode, 0, GLX_VERSION); + if (priv->serverGLXversion == NULL) { + FreeScreenConfigs(priv); + return GL_FALSE; + } + + for (i = 0; i < screens; i++, psc++) { + getFBConfigs(dpy, priv, i); + getVisualConfigs(dpy, priv, i); + psc->scr = i; + psc->dpy = dpy; + } + + SyncHandle(); + + return GL_TRUE; +} + +_X_HIDDEN void +__glXRelease(__GLXdisplayPrivate *dpyPriv) +{ + FreeScreenConfigs(dpyPriv); + + if (dpyPriv->serverGLXvendor) { + Xfree((char *) dpyPriv->serverGLXvendor); + dpyPriv->serverGLXvendor = NULL; + } + if (dpyPriv->serverGLXversion) { + Xfree((char *) dpyPriv->serverGLXversion); + dpyPriv->serverGLXversion = NULL; + } + + Xfree(dpyPriv); +} + +_X_HIDDEN __GLXdisplayPrivate * +__glXInitialize(Display * dpy) +{ + XExtDisplayInfo *info = __glXFindDisplay(dpy); + __GLXdisplayPrivate *dpyPriv; + int major, minor; + + if (!XextHasExtension(info)) + return NULL; + + /* See if the versions are compatible */ + if (!QueryVersion(dpy, info->codes->major_opcode, &major, &minor)) + return NULL; + + dpyPriv = (__GLXdisplayPrivate *) Xcalloc(1, sizeof(__GLXdisplayPrivate)); + if (!dpyPriv) + return NULL; + + /* + ** Init the display private and then read in the screen config + ** structures from the server. + */ + dpyPriv->majorOpcode = info->codes->major_opcode; + dpyPriv->majorVersion = major; + dpyPriv->minorVersion = minor; + dpyPriv->dpy = dpy; + + dpyPriv->serverGLXvendor = NULL; + dpyPriv->serverGLXversion = NULL; + + if (!AllocAndFetchScreenConfigs(dpy, dpyPriv)) { + Xfree(dpyPriv); + return NULL; + } + + return dpyPriv; +} diff --git a/src/gallium/state_trackers/egl_g3d/x11/glxinit.h b/src/gallium/state_trackers/egl_g3d/x11/glxinit.h new file mode 100644 index 0000000000..515a825222 --- /dev/null +++ b/src/gallium/state_trackers/egl_g3d/x11/glxinit.h @@ -0,0 +1,14 @@ +#ifndef GLXINIT_INCLUDED +#define GLXINIT_INCLUDED + +#include + +#ifndef GLX_DIRECT_RENDERING +#define GLX_DIRECT_RENDERING +#endif +#include "glxclient.h" + +extern void +__glXRelease(__GLXdisplayPrivate *dpyPriv); + +#endif /* GLXINIT_INCLUDED */ diff --git a/src/gallium/state_trackers/egl_g3d/x11/native_dri2.c b/src/gallium/state_trackers/egl_g3d/x11/native_dri2.c new file mode 100644 index 0000000000..0dda786bbd --- /dev/null +++ b/src/gallium/state_trackers/egl_g3d/x11/native_dri2.c @@ -0,0 +1,693 @@ +/* + * Mesa 3-D graphics library + * Version: 7.8 + * + * Copyright (C) 2009-2010 Chia-I Wu + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "util/u_memory.h" +#include "util/u_math.h" +#include "util/u_format.h" +#include "pipe/p_compiler.h" +#include "pipe/p_screen.h" +#include "pipe/p_context.h" +#include "pipe/p_state.h" +#include "state_tracker/drm_api.h" +#include "egllog.h" + +#include "native_x11.h" +#include "x11_screen.h" + +enum dri2_surface_type { + DRI2_SURFACE_TYPE_WINDOW, + DRI2_SURFACE_TYPE_PIXMAP, + DRI2_SURFACE_TYPE_PBUFFER +}; + +struct dri2_display { + struct native_display base; + Display *dpy; + boolean own_dpy; + + struct drm_api *api; + struct x11_screen *xscr; + int xscr_number; + + struct dri2_config *configs; + int num_configs; +}; + +struct dri2_surface { + struct native_surface base; + Drawable drawable; + enum dri2_surface_type type; + enum pipe_format color_format; + struct dri2_display *dri2dpy; + + struct pipe_texture *pbuffer_textures[NUM_NATIVE_ATTACHMENTS]; + boolean have_back, have_fake; + int width, height; +}; + +struct dri2_config { + struct native_config base; +}; + +static INLINE struct dri2_display * +dri2_display(const struct native_display *ndpy) +{ + return (struct dri2_display *) ndpy; +} + +static INLINE struct dri2_surface * +dri2_surface(const struct native_surface *nsurf) +{ + return (struct dri2_surface *) nsurf; +} + +static INLINE struct dri2_config * +dri2_config(const struct native_config *nconf) +{ + return (struct dri2_config *) nconf; +} + +static boolean +dri2_surface_flush_frontbuffer(struct native_surface *nsurf) +{ + struct dri2_surface *dri2surf = dri2_surface(nsurf); + struct dri2_display *dri2dpy = dri2surf->dri2dpy; + + /* pbuffer is private */ + if (dri2surf->type == DRI2_SURFACE_TYPE_PBUFFER) + return TRUE; + + /* copy to real front buffer */ + if (dri2surf->have_fake) + x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable, + 0, 0, dri2surf->width, dri2surf->height, + DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft); + + return TRUE; +} + +static boolean +dri2_surface_swap_buffers(struct native_surface *nsurf) +{ + struct dri2_surface *dri2surf = dri2_surface(nsurf); + struct dri2_display *dri2dpy = dri2surf->dri2dpy; + + /* pbuffer is private */ + if (dri2surf->type == DRI2_SURFACE_TYPE_PBUFFER) + return TRUE; + + /* copy to front buffer */ + if (dri2surf->have_back) + x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable, + 0, 0, dri2surf->width, dri2surf->height, + DRI2BufferBackLeft, DRI2BufferFrontLeft); + + /* and update fake front buffer */ + if (dri2surf->have_fake) + x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable, + 0, 0, dri2surf->width, dri2surf->height, + DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft); + + return TRUE; +} + +static boolean +dri2_surface_validate(struct native_surface *nsurf, + const enum native_attachment *natts, + unsigned num_natts, + struct pipe_texture **textures, + int *width, int *height) +{ + struct dri2_surface *dri2surf = dri2_surface(nsurf); + struct dri2_display *dri2dpy = dri2surf->dri2dpy; + unsigned int dri2atts[NUM_NATIVE_ATTACHMENTS]; + EGLint texture_indices[NUM_NATIVE_ATTACHMENTS]; + struct pipe_texture templ; + struct x11_drawable_buffer *xbufs; + int num_ins, num_outs, i; + + if (num_natts) { + memset(&templ, 0, sizeof(templ)); + templ.target = PIPE_TEXTURE_2D; + templ.last_level = 0; + templ.width0 = dri2surf->width; + templ.height0 = dri2surf->height; + templ.depth0 = 1; + templ.format = dri2surf->color_format; + templ.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET; + + if (textures) + memset(textures, 0, sizeof(*textures) * num_natts); + } + + /* create textures for pbuffer */ + if (dri2surf->type == DRI2_SURFACE_TYPE_PBUFFER) { + struct pipe_screen *screen = dri2dpy->base.screen; + + for (i = 0; i < num_natts; i++) { + enum native_attachment natt = natts[i]; + struct pipe_texture *ptex = dri2surf->pbuffer_textures[natt]; + + if (!ptex) { + ptex = screen->texture_create(screen, &templ); + dri2surf->pbuffer_textures[natt] = ptex; + } + + if (textures) + pipe_texture_reference(&textures[i], ptex); + } + + if (width) + *width = dri2surf->width; + if (height) + *height = dri2surf->height; + + return TRUE; + } + + for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) + texture_indices[i] = -1; + + /* prepare the attachments */ + num_ins = num_natts; + for (i = 0; i < num_natts; i++) { + unsigned int dri2att; + + switch (natts[i]) { + case NATIVE_ATTACHMENT_FRONT_LEFT: + dri2att = DRI2BufferFrontLeft; + break; + case NATIVE_ATTACHMENT_BACK_LEFT: + dri2att = DRI2BufferBackLeft; + break; + case NATIVE_ATTACHMENT_FRONT_RIGHT: + dri2att = DRI2BufferFrontRight; + break; + case NATIVE_ATTACHMENT_BACK_RIGHT: + dri2att = DRI2BufferBackRight; + break; + default: + assert(0); + dri2att = 0; + break; + } + dri2atts[i] = dri2att; + texture_indices[natts[i]] = i; + } + + dri2surf->have_back = FALSE; + dri2surf->have_fake = FALSE; + + xbufs = x11_drawable_get_buffers(dri2dpy->xscr, dri2surf->drawable, + &dri2surf->width, &dri2surf->height, + dri2atts, FALSE, num_ins, &num_outs); + if (!xbufs) + return FALSE; + + /* update width and height */ + templ.width0 = dri2surf->width; + templ.height0 = dri2surf->height; + + for (i = 0; i < num_outs; i++) { + struct x11_drawable_buffer *xbuf = &xbufs[i]; + const char *desc; + enum native_attachment natt; + + switch (xbuf->attachment) { + case DRI2BufferFrontLeft: + natt = NATIVE_ATTACHMENT_FRONT_LEFT; + desc = "DRI2 Front Buffer"; + break; + case DRI2BufferFakeFrontLeft: + natt = NATIVE_ATTACHMENT_FRONT_LEFT; + desc = "DRI2 Fake Front Buffer"; + dri2surf->have_fake = TRUE; + break; + case DRI2BufferBackLeft: + natt = NATIVE_ATTACHMENT_BACK_LEFT; + desc = "DRI2 Back Buffer"; + dri2surf->have_back = TRUE; + break; + default: + desc = NULL; + break; + } + + if (!desc || texture_indices[natt] < 0 || + (textures && textures[texture_indices[natt]])) { + if (!desc) + _eglLog(_EGL_WARNING, "unknown buffer %d", xbuf->attachment); + else if (texture_indices[natt] < 0) + _eglLog(_EGL_WARNING, "unexpected buffer %d", xbuf->attachment); + else if (textures && textures[texture_indices[natt]]) + _eglLog(_EGL_WARNING, "both real and fake front buffers are listed"); + continue; + } + + if (textures) { + struct pipe_texture *ptex = + dri2dpy->api->texture_from_shared_handle(dri2dpy->api, + dri2dpy->base.screen, &templ, + desc, xbuf->pitch, xbuf->name); + if (ptex) { + /* the caller owns the textures */ + textures[texture_indices[natt]] = ptex; + } + } + } + + free(xbufs); + + if (width) + *width = dri2surf->width; + if (height) + *height = dri2surf->height; + + return TRUE; +} + +static void +dri2_surface_wait(struct native_surface *nsurf) +{ + struct dri2_surface *dri2surf = dri2_surface(nsurf); + struct dri2_display *dri2dpy = dri2surf->dri2dpy; + + if (dri2surf->have_fake) { + x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable, + 0, 0, dri2surf->width, dri2surf->height, + DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft); + } +} + +static void +dri2_surface_destroy(struct native_surface *nsurf) +{ + struct dri2_surface *dri2surf = dri2_surface(nsurf); + int i; + + for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) { + struct pipe_texture *ptex = dri2surf->pbuffer_textures[i]; + pipe_texture_reference(&ptex, NULL); + } + + if (dri2surf->drawable) + x11_drawable_enable_dri2(dri2surf->dri2dpy->xscr, + dri2surf->drawable, FALSE); + free(dri2surf); +} + +static struct dri2_surface * +dri2_display_create_surface(struct native_display *ndpy, + enum dri2_surface_type type, + Drawable drawable, + const struct native_config *nconf) +{ + struct dri2_display *dri2dpy = dri2_display(ndpy); + struct dri2_config *dri2conf = dri2_config(nconf); + struct dri2_surface *dri2surf; + + dri2surf = CALLOC_STRUCT(dri2_surface); + if (!dri2surf) + return NULL; + + if (drawable) + x11_drawable_enable_dri2(dri2dpy->xscr, drawable, TRUE); + + dri2surf->dri2dpy = dri2dpy; + dri2surf->type = type; + dri2surf->drawable = drawable; + dri2surf->color_format = dri2conf->base.color_format; + + dri2surf->base.destroy = dri2_surface_destroy; + dri2surf->base.swap_buffers = dri2_surface_swap_buffers; + dri2surf->base.flush_frontbuffer = dri2_surface_flush_frontbuffer; + dri2surf->base.validate = dri2_surface_validate; + dri2surf->base.wait = dri2_surface_wait; + + return dri2surf; +} + +static struct native_surface * +dri2_display_create_window_surface(struct native_display *ndpy, + EGLNativeWindowType win, + const struct native_config *nconf) +{ + struct dri2_surface *dri2surf; + + dri2surf = dri2_display_create_surface(ndpy, DRI2_SURFACE_TYPE_WINDOW, + (Drawable) win, nconf); + return (dri2surf) ? &dri2surf->base : NULL; +} + +static struct native_surface * +dri2_display_create_pixmap_surface(struct native_display *ndpy, + EGLNativePixmapType pix, + const struct native_config *nconf) +{ + struct dri2_surface *dri2surf; + + dri2surf = dri2_display_create_surface(ndpy, DRI2_SURFACE_TYPE_PIXMAP, + (Drawable) pix, nconf); + return (dri2surf) ? &dri2surf->base : NULL; +} + +static struct native_surface * +dri2_display_create_pbuffer_surface(struct native_display *ndpy, + const struct native_config *nconf, + uint width, uint height) +{ + struct dri2_surface *dri2surf; + + dri2surf = dri2_display_create_surface(ndpy, DRI2_SURFACE_TYPE_PBUFFER, + (Drawable) None, nconf); + if (dri2surf) { + dri2surf->width = width; + dri2surf->height = height; + } + return (dri2surf) ? &dri2surf->base : NULL; +} + +static struct pipe_context * +dri2_display_create_context(struct native_display *ndpy, void *context_private) +{ + struct dri2_display *dri2dpy = dri2_display(ndpy); + struct pipe_context *pctx; + + pctx = dri2dpy->api->create_context(dri2dpy->api, dri2dpy->base.screen); + if (pctx) + pctx->priv = context_private; + return pctx; +} + +static int +choose_color_format(const __GLcontextModes *mode, enum pipe_format formats[32]) +{ + int count = 0; + + switch (mode->rgbBits) { + case 32: + formats[count++] = PIPE_FORMAT_A8R8G8B8_UNORM; + formats[count++] = PIPE_FORMAT_B8G8R8A8_UNORM; + break; + case 24: + formats[count++] = PIPE_FORMAT_X8R8G8B8_UNORM; + formats[count++] = PIPE_FORMAT_B8G8R8X8_UNORM; + formats[count++] = PIPE_FORMAT_A8R8G8B8_UNORM; + formats[count++] = PIPE_FORMAT_B8G8R8A8_UNORM; + break; + case 16: + formats[count++] = PIPE_FORMAT_R5G6B5_UNORM; + break; + default: + break; + } + + return count; +} + +static int +choose_depth_stencil_format(const __GLcontextModes *mode, + enum pipe_format formats[32]) +{ + int count = 0; + + switch (mode->depthBits) { + case 32: + formats[count++] = PIPE_FORMAT_Z32_UNORM; + break; + case 24: + if (mode->stencilBits) { + formats[count++] = PIPE_FORMAT_S8Z24_UNORM; + formats[count++] = PIPE_FORMAT_Z24S8_UNORM; + } + else { + formats[count++] = PIPE_FORMAT_X8Z24_UNORM; + formats[count++] = PIPE_FORMAT_Z24X8_UNORM; + } + break; + case 16: + formats[count++] = PIPE_FORMAT_Z16_UNORM; + break; + default: + break; + } + + return count; +} + +static boolean +is_format_supported(struct pipe_screen *screen, + enum pipe_format fmt, boolean is_color) +{ + return screen->is_format_supported(screen, fmt, PIPE_TEXTURE_2D, + (is_color) ? PIPE_TEXTURE_USAGE_RENDER_TARGET : + PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0); +} + +static boolean +dri2_display_convert_config(struct native_display *ndpy, + const __GLcontextModes *mode, + struct native_config *nconf) +{ + enum pipe_format formats[32]; + int num_formats, i; + + if (!(mode->renderType & GLX_RGBA_BIT) || !mode->rgbMode) + return FALSE; + + /* skip single-buffered configs */ + if (!mode->doubleBufferMode) + return FALSE; + + nconf->mode = *mode; + nconf->mode.renderType = GLX_RGBA_BIT; + nconf->mode.rgbMode = TRUE; + /* pbuffer is allocated locally and is always supported */ + nconf->mode.drawableType |= GLX_PBUFFER_BIT; + /* the swap method is always copy */ + nconf->mode.swapMethod = GLX_SWAP_COPY_OML; + + /* fix up */ + nconf->mode.rgbBits = + nconf->mode.redBits + nconf->mode.greenBits + + nconf->mode.blueBits + nconf->mode.alphaBits; + if (!(nconf->mode.drawableType & GLX_WINDOW_BIT)) { + nconf->mode.visualID = 0; + nconf->mode.visualType = GLX_NONE; + } + if (!(nconf->mode.drawableType & GLX_PBUFFER_BIT)) { + nconf->mode.bindToTextureRgb = FALSE; + nconf->mode.bindToTextureRgba = FALSE; + } + + nconf->color_format = PIPE_FORMAT_NONE; + nconf->depth_format = PIPE_FORMAT_NONE; + nconf->stencil_format = PIPE_FORMAT_NONE; + + /* choose color format */ + num_formats = choose_color_format(mode, formats); + for (i = 0; i < num_formats; i++) { + if (is_format_supported(ndpy->screen, formats[i], TRUE)) { + nconf->color_format = formats[i]; + break; + } + } + if (nconf->color_format == PIPE_FORMAT_NONE) + return FALSE; + + /* choose depth/stencil format */ + num_formats = choose_depth_stencil_format(mode, formats); + for (i = 0; i < num_formats; i++) { + if (is_format_supported(ndpy->screen, formats[i], FALSE)) { + nconf->depth_format = formats[i]; + nconf->stencil_format = formats[i]; + break; + } + } + if ((nconf->mode.depthBits && nconf->depth_format == PIPE_FORMAT_NONE) || + (nconf->mode.stencilBits && nconf->stencil_format == PIPE_FORMAT_NONE)) + return FALSE; + + return TRUE; +} + +static const struct native_config ** +dri2_display_get_configs(struct native_display *ndpy, int *num_configs) +{ + struct dri2_display *dri2dpy = dri2_display(ndpy); + const struct native_config **configs; + int i; + + /* first time */ + if (!dri2dpy->configs) { + const __GLcontextModes *modes; + int num_modes, count; + + modes = x11_screen_get_glx_configs(dri2dpy->xscr); + if (!modes) + return NULL; + num_modes = x11_context_modes_count(modes); + + dri2dpy->configs = calloc(num_modes, sizeof(*dri2dpy->configs)); + if (!dri2dpy->configs) + return NULL; + + count = 0; + for (i = 0; i < num_modes; i++) { + struct native_config *nconf = &dri2dpy->configs[count].base; + if (dri2_display_convert_config(&dri2dpy->base, modes, nconf)) + count++; + modes = modes->next; + } + + dri2dpy->num_configs = count; + } + + configs = malloc(dri2dpy->num_configs * sizeof(*configs)); + if (configs) { + for (i = 0; i < dri2dpy->num_configs; i++) + configs[i] = (const struct native_config *) &dri2dpy->configs[i]; + if (num_configs) + *num_configs = dri2dpy->num_configs; + } + + return configs; +} + +static void +dri2_display_destroy(struct native_display *ndpy) +{ + struct dri2_display *dri2dpy = dri2_display(ndpy); + + if (dri2dpy->configs) + free(dri2dpy->configs); + + if (dri2dpy->base.screen) + dri2dpy->base.screen->destroy(dri2dpy->base.screen); + + if (dri2dpy->xscr) + x11_screen_destroy(dri2dpy->xscr); + if (dri2dpy->own_dpy) + XCloseDisplay(dri2dpy->dpy); + if (dri2dpy->api && dri2dpy->api->destroy) + dri2dpy->api->destroy(dri2dpy->api); + free(dri2dpy); +} + +/** + * Initialize DRI2 and pipe screen. + */ +static boolean +dri2_display_init_screen(struct native_display *ndpy) +{ + struct dri2_display *dri2dpy = dri2_display(ndpy); + const char *driver = dri2dpy->api->name; + struct drm_create_screen_arg arg; + int fd; + + if (!x11_screen_support(dri2dpy->xscr, X11_SCREEN_EXTENSION_DRI2) || + !x11_screen_support(dri2dpy->xscr, X11_SCREEN_EXTENSION_GLX)) { + _eglLog(_EGL_WARNING, "GLX/DRI2 is not supported"); + return FALSE; + } + + fd = x11_screen_enable_dri2(dri2dpy->xscr, driver); + if (fd < 0) + return FALSE; + + memset(&arg, 0, sizeof(arg)); + arg.mode = DRM_CREATE_NORMAL; + dri2dpy->base.screen = dri2dpy->api->create_screen(dri2dpy->api, fd, &arg); + if (!dri2dpy->base.screen) { + _eglLog(_EGL_WARNING, "failed to create DRM screen"); + return FALSE; + } + + return TRUE; +} + +static void +dri2_display_flush_frontbuffer(void *dummy, struct pipe_surface *surf, + void *context_private) +{ + /* TODO get native surface from context private, and remove the callback */ + _eglLog(_EGL_WARNING, "flush_frontbuffer is not supplied"); +} + +struct native_display * +x11_create_dri2_display(EGLNativeDisplayType dpy, + struct drm_api *api, + native_flush_frontbuffer flush_frontbuffer) +{ + struct dri2_display *dri2dpy; + + dri2dpy = CALLOC_STRUCT(dri2_display); + if (!dri2dpy) + return NULL; + + dri2dpy->api = api; + if (!dri2dpy->api) { + _eglLog(_EGL_WARNING, "failed to create DRM API"); + free(dri2dpy); + return NULL; + } + + dri2dpy->dpy = dpy; + if (!dri2dpy->dpy) { + dri2dpy->dpy = XOpenDisplay(NULL); + if (!dri2dpy->dpy) { + dri2_display_destroy(&dri2dpy->base); + return NULL; + } + dri2dpy->own_dpy = TRUE; + } + + dri2dpy->xscr_number = DefaultScreen(dri2dpy->dpy); + dri2dpy->xscr = x11_screen_create(dri2dpy->dpy, dri2dpy->xscr_number); + if (!dri2dpy->xscr) { + dri2_display_destroy(&dri2dpy->base); + return NULL; + } + + if (!dri2_display_init_screen(&dri2dpy->base)) { + dri2_display_destroy(&dri2dpy->base); + return NULL; + } + + if (!flush_frontbuffer) + flush_frontbuffer = dri2_display_flush_frontbuffer; + + dri2dpy->base.screen->flush_frontbuffer = + (void (*)(struct pipe_screen *, struct pipe_surface *, void *)) + flush_frontbuffer; + + dri2dpy->base.destroy = dri2_display_destroy; + dri2dpy->base.get_configs = dri2_display_get_configs; + dri2dpy->base.create_context = dri2_display_create_context; + dri2dpy->base.create_window_surface = dri2_display_create_window_surface; + dri2dpy->base.create_pixmap_surface = dri2_display_create_pixmap_surface; + dri2dpy->base.create_pbuffer_surface = dri2_display_create_pbuffer_surface; + + return &dri2dpy->base; +} diff --git a/src/gallium/state_trackers/egl_g3d/x11/native_x11.c b/src/gallium/state_trackers/egl_g3d/x11/native_x11.c new file mode 100644 index 0000000000..a4f36e9dec --- /dev/null +++ b/src/gallium/state_trackers/egl_g3d/x11/native_x11.c @@ -0,0 +1,73 @@ +/* + * Mesa 3-D graphics library + * Version: 7.8 + * + * Copyright (C) 2009-2010 Chia-I Wu + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "util/u_debug.h" +#include "state_tracker/drm_api.h" +#include "egllog.h" + +#include "native_x11.h" + +static struct drm_api *api; + +const char * +native_get_name(void) +{ + static char x11_name[32]; + + if (!api) + api = drm_api_create(); + + if (api) + snprintf(x11_name, sizeof(x11_name), "X11/%s", api->name); + else + snprintf(x11_name, sizeof(x11_name), "X11"); + + return x11_name; +} + +struct native_display * +native_create_display(EGLNativeDisplayType dpy, + native_flush_frontbuffer flush_frontbuffer) +{ + struct native_display *ndpy = NULL; + boolean force_sw; + + if (!api) + api = drm_api_create(); + + force_sw = debug_get_bool_option("EGL_SOFTWARE", FALSE); + if (api && !force_sw) { + ndpy = x11_create_dri2_display(dpy, api, flush_frontbuffer); + } + + if (!ndpy) { + EGLint level = (force_sw) ? _EGL_INFO : _EGL_WARNING; + + _eglLog(level, "use software fallback"); + ndpy = x11_create_ximage_display(dpy, TRUE, flush_frontbuffer); + } + + return ndpy; +} diff --git a/src/gallium/state_trackers/egl_g3d/x11/native_x11.h b/src/gallium/state_trackers/egl_g3d/x11/native_x11.h new file mode 100644 index 0000000000..9217eb6252 --- /dev/null +++ b/src/gallium/state_trackers/egl_g3d/x11/native_x11.h @@ -0,0 +1,41 @@ +/* + * Mesa 3-D graphics library + * Version: 7.8 + * + * Copyright (C) 2009-2010 Chia-I Wu + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef _NATIVE_X11_H_ +#define _NATIVE_X11_H_ + +#include "state_tracker/drm_api.h" +#include "common/native.h" + +struct native_display * +x11_create_ximage_display(EGLNativeDisplayType dpy, + boolean use_xshm, + native_flush_frontbuffer flush_frontbuffer); + +struct native_display * +x11_create_dri2_display(EGLNativeDisplayType dpy, + struct drm_api *api, + native_flush_frontbuffer flush_frontbuffer); + +#endif /* _NATIVE_X11_H_ */ diff --git a/src/gallium/state_trackers/egl_g3d/x11/native_ximage.c b/src/gallium/state_trackers/egl_g3d/x11/native_ximage.c new file mode 100644 index 0000000000..e02faa9b7b --- /dev/null +++ b/src/gallium/state_trackers/egl_g3d/x11/native_ximage.c @@ -0,0 +1,680 @@ +/* + * Mesa 3-D graphics library + * Version: 7.8 + * + * Copyright (C) 2009-2010 Chia-I Wu + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "util/u_memory.h" +#include "util/u_math.h" +#include "util/u_format.h" +#include "pipe/p_compiler.h" +#include "pipe/internal/p_winsys_screen.h" +#include "softpipe/sp_winsys.h" +#include "egllog.h" + +#include "sw_winsys.h" +#include "native_x11.h" +#include "x11_screen.h" + +enum ximage_surface_type { + XIMAGE_SURFACE_TYPE_WINDOW, + XIMAGE_SURFACE_TYPE_PIXMAP, + XIMAGE_SURFACE_TYPE_PBUFFER +}; + +struct ximage_display { + struct native_display base; + Display *dpy; + boolean own_dpy; + + struct x11_screen *xscr; + int xscr_number; + + boolean use_xshm; + + struct pipe_winsys *winsys; + struct ximage_config *configs; + int num_configs; +}; + +struct ximage_buffer { + XImage *ximage; + + struct pipe_texture *texture; + struct pipe_transfer *transfer; + XShmSegmentInfo *shm_info; + boolean xshm_attached; +}; + +struct ximage_surface { + struct native_surface base; + Drawable drawable; + enum ximage_surface_type type; + enum pipe_format color_format; + XVisualInfo visual; + struct ximage_display *xdpy; + + int width, height; + GC gc; + + struct ximage_buffer buffers[NUM_NATIVE_ATTACHMENTS]; +}; + +struct ximage_config { + struct native_config base; + const XVisualInfo *visual; +}; + +static INLINE struct ximage_display * +ximage_display(const struct native_display *ndpy) +{ + return (struct ximage_display *) ndpy; +} + +static INLINE struct ximage_surface * +ximage_surface(const struct native_surface *nsurf) +{ + return (struct ximage_surface *) nsurf; +} + +static INLINE struct ximage_config * +ximage_config(const struct native_config *nconf) +{ + return (struct ximage_config *) nconf; +} + +static void +ximage_surface_free_buffer(struct native_surface *nsurf, + enum native_attachment which) +{ + struct ximage_surface *xsurf = ximage_surface(nsurf); + struct ximage_buffer *xbuf = &xsurf->buffers[which]; + struct pipe_screen *screen = xsurf->xdpy->base.screen; + + if (xbuf->transfer) { + screen->tex_transfer_destroy(xbuf->transfer); + xbuf->transfer = NULL; + } + pipe_texture_reference(&xbuf->texture, NULL); + + if (xbuf->shm_info) { + if (xbuf->xshm_attached) + XShmDetach(xsurf->xdpy->dpy, xbuf->shm_info); + if (xbuf->shm_info->shmaddr != (void *) -1) + shmdt(xbuf->shm_info->shmaddr); + if (xbuf->shm_info->shmid != -1) + shmctl(xbuf->shm_info->shmid, IPC_RMID, 0); + + xbuf->shm_info->shmaddr = (void *) -1; + xbuf->shm_info->shmid = -1; + } +} + +static boolean +ximage_surface_alloc_buffer(struct native_surface *nsurf, + enum native_attachment which) +{ + struct ximage_surface *xsurf = ximage_surface(nsurf); + struct ximage_buffer *xbuf = &xsurf->buffers[which]; + struct pipe_screen *screen = xsurf->xdpy->base.screen; + struct pipe_texture templ; + + /* free old data */ + if (xbuf->texture) + ximage_surface_free_buffer(&xsurf->base, which); + + memset(&templ, 0, sizeof(templ)); + templ.target = PIPE_TEXTURE_2D; + templ.format = xsurf->color_format; + templ.width0 = xsurf->width; + templ.height0 = xsurf->height; + templ.depth0 = 1; + templ.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET; + + if (xbuf->shm_info) { + struct pipe_buffer *pbuf; + unsigned stride, size; + void *addr = NULL; + + stride = util_format_get_stride(xsurf->color_format, xsurf->width); + /* alignment should depend on visual? */ + stride = align(stride, 4); + size = stride * xsurf->height; + + /* create and attach shm object */ + xbuf->shm_info->shmid = shmget(IPC_PRIVATE, size, 0755); + if (xbuf->shm_info->shmid != -1) { + xbuf->shm_info->shmaddr = + shmat(xbuf->shm_info->shmid, NULL, 0); + if (xbuf->shm_info->shmaddr != (void *) -1) { + if (XShmAttach(xsurf->xdpy->dpy, xbuf->shm_info)) { + addr = xbuf->shm_info->shmaddr; + xbuf->xshm_attached = TRUE; + } + } + } + + if (addr) { + pbuf = screen->user_buffer_create(screen, addr, size); + if (pbuf) { + xbuf->texture = + screen->texture_blanket(screen, &templ, &stride, pbuf); + pipe_buffer_reference(&pbuf, NULL); + } + } + } + else { + xbuf->texture = screen->texture_create(screen, &templ); + } + + if (xbuf->texture) { + xbuf->transfer = screen->get_tex_transfer(screen, xbuf->texture, + 0, 0, 0, PIPE_TRANSFER_READ, 0, 0, xsurf->width, xsurf->height); + if (!xbuf->transfer) + pipe_texture_reference(&xbuf->texture, NULL); + } + + /* clean up the buffer if allocation failed */ + if (!xbuf->texture) + ximage_surface_free_buffer(&xsurf->base, which); + + return (xbuf->texture != NULL); +} + +static boolean +ximage_surface_draw_buffer(struct native_surface *nsurf, + enum native_attachment which) +{ + struct ximage_surface *xsurf = ximage_surface(nsurf); + struct ximage_buffer *xbuf = &xsurf->buffers[which]; + struct pipe_screen *screen = xsurf->xdpy->base.screen; + + if (xsurf->type == XIMAGE_SURFACE_TYPE_PBUFFER) + return TRUE; + + assert(xsurf->drawable && xbuf->ximage && xbuf->texture); + + xbuf->ximage->data = screen->transfer_map(screen, xbuf->transfer); + + if (xbuf->shm_info) + XShmPutImage(xsurf->xdpy->dpy, xsurf->drawable, xsurf->gc, + xbuf->ximage, 0, 0, 0, 0, xsurf->width, xsurf->height, False); + else + XPutImage(xsurf->xdpy->dpy, xsurf->drawable, xsurf->gc, + xbuf->ximage, 0, 0, 0, 0, xsurf->width, xsurf->height); + + xbuf->ximage->data = NULL; + screen->transfer_unmap(screen, xbuf->transfer); + + XSync(xsurf->xdpy->dpy, FALSE); + + return TRUE; +} + +static boolean +ximage_surface_flush_frontbuffer(struct native_surface *nsurf) +{ + return ximage_surface_draw_buffer(nsurf, NATIVE_ATTACHMENT_FRONT_LEFT); +} + +static boolean +ximage_surface_swap_buffers(struct native_surface *nsurf) +{ + struct ximage_surface *xsurf = ximage_surface(nsurf); + struct ximage_buffer *xfront, *xback, xtmp; + + xfront = &xsurf->buffers[NATIVE_ATTACHMENT_FRONT_LEFT]; + xback = &xsurf->buffers[NATIVE_ATTACHMENT_BACK_LEFT]; + + /* draw the back buffer directly if there is no front buffer */ + if (!xfront->texture) + return ximage_surface_draw_buffer(nsurf, NATIVE_ATTACHMENT_BACK_LEFT); + + /* swap the buffers */ + xtmp = *xfront; + *xfront = *xback; + *xback = xtmp; + + return ximage_surface_draw_buffer(nsurf, NATIVE_ATTACHMENT_FRONT_LEFT); +} + +static void +ximage_surface_update_geometry(struct native_surface *nsurf) +{ + struct ximage_surface *xsurf = ximage_surface(nsurf); + Status ok; + Window root; + int x, y; + unsigned int w, h, border, depth; + + /* pbuffer has fixed geometry */ + if (xsurf->type == XIMAGE_SURFACE_TYPE_PBUFFER) + return; + + ok = XGetGeometry(xsurf->xdpy->dpy, xsurf->drawable, + &root, &x, &y, &w, &h, &border, &depth); + if (ok) { + xsurf->width = w; + xsurf->height = h; + } +} + +static boolean +ximage_surface_validate(struct native_surface *nsurf, + const enum native_attachment *natts, + unsigned num_natts, + struct pipe_texture **textures, + int *width, int *height) +{ + struct ximage_surface *xsurf = ximage_surface(nsurf); + boolean error = FALSE; + unsigned i; + + ximage_surface_update_geometry(&xsurf->base); + + if (textures) + memset(textures, 0, sizeof(*textures) * num_natts); + + for (i = 0; i < num_natts; i++) { + enum native_attachment natt = natts[i]; + struct ximage_buffer *xbuf = &xsurf->buffers[natt]; + + if (!xbuf) + continue; + + /* reallocate the texture */ + if (!xbuf->texture || + xsurf->width != xbuf->texture->width0 || + xsurf->height != xbuf->texture->height0) { + if (ximage_surface_alloc_buffer(&xsurf->base, natt)) { + /* update ximage */ + if (xbuf->ximage) { + xbuf->ximage->width = xbuf->transfer->width; + xbuf->ximage->height = xbuf->transfer->height; + xbuf->ximage->bytes_per_line = xbuf->transfer->stride; + } + } + } + + /* allocation failed */ + if (!xbuf->texture) { + unsigned j; + for (j = 0; j < i; j++) + pipe_texture_reference(&textures[j], NULL); + for (j = i; j < num_natts; j++) + textures[j] = NULL; + error = TRUE; + break; + } + + if (textures) + pipe_texture_reference(&textures[i], xbuf->texture); + } + + if (width) + *width = xsurf->width; + if (height) + *height = xsurf->height; + + return !error; +} + +static void +ximage_surface_wait(struct native_surface *nsurf) +{ + struct ximage_surface *xsurf = ximage_surface(nsurf); + XSync(xsurf->xdpy->dpy, FALSE); + /* TODO XGetImage and update the front texture */ +} + +static void +ximage_surface_destroy(struct native_surface *nsurf) +{ + struct ximage_surface *xsurf = ximage_surface(nsurf); + int i; + + for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) { + struct ximage_buffer *xbuf = &xsurf->buffers[i]; + ximage_surface_free_buffer(&xsurf->base, i); + /* xbuf->shm_info is owned by xbuf->ximage? */ + if (xbuf->ximage) { + XDestroyImage(xbuf->ximage); + xbuf->ximage = NULL; + } + } + + if (xsurf->type != XIMAGE_SURFACE_TYPE_PBUFFER) + XFreeGC(xsurf->xdpy->dpy, xsurf->gc); + free(xsurf); +} + +static struct ximage_surface * +ximage_display_create_surface(struct native_display *ndpy, + enum ximage_surface_type type, + Drawable drawable, + const struct native_config *nconf) +{ + struct ximage_display *xdpy = ximage_display(ndpy); + struct ximage_config *xconf = ximage_config(nconf); + struct ximage_surface *xsurf; + int i; + + xsurf = CALLOC_STRUCT(ximage_surface); + if (!xsurf) + return NULL; + + xsurf->xdpy = xdpy; + xsurf->type = type; + xsurf->color_format = xconf->base.color_format; + xsurf->drawable = drawable; + + if (xsurf->type != XIMAGE_SURFACE_TYPE_PBUFFER) { + xsurf->drawable = drawable; + xsurf->visual = *xconf->visual; + + xsurf->gc = XCreateGC(xdpy->dpy, xsurf->drawable, 0, NULL); + if (!xsurf->gc) { + free(xsurf); + return NULL; + } + + for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) { + struct ximage_buffer *xbuf = &xsurf->buffers[i]; + + if (xdpy->use_xshm) { + xbuf->shm_info = calloc(1, sizeof(*xbuf->shm_info)); + if (xbuf->shm_info) { + /* initialize shm info */ + xbuf->shm_info->shmid = -1; + xbuf->shm_info->shmaddr = (void *) -1; + xbuf->shm_info->readOnly = TRUE; + + xbuf->ximage = XShmCreateImage(xsurf->xdpy->dpy, + xsurf->visual.visual, + xsurf->visual.depth, + ZPixmap, NULL, + xbuf->shm_info, + 0, 0); + } + } + else { + xbuf->ximage = XCreateImage(xsurf->xdpy->dpy, + xsurf->visual.visual, + xsurf->visual.depth, + ZPixmap, 0, /* format, offset */ + NULL, /* data */ + 0, 0, /* size */ + 8, /* bitmap_pad */ + 0); /* bytes_per_line */ + } + + if (!xbuf->ximage) { + XFreeGC(xdpy->dpy, xsurf->gc); + free(xsurf); + return NULL; + } + } + } + + xsurf->base.destroy = ximage_surface_destroy; + xsurf->base.swap_buffers = ximage_surface_swap_buffers; + xsurf->base.flush_frontbuffer = ximage_surface_flush_frontbuffer; + xsurf->base.validate = ximage_surface_validate; + xsurf->base.wait = ximage_surface_wait; + + return xsurf; +} + +static struct native_surface * +ximage_display_create_window_surface(struct native_display *ndpy, + EGLNativeWindowType win, + const struct native_config *nconf) +{ + struct ximage_surface *xsurf; + + xsurf = ximage_display_create_surface(ndpy, XIMAGE_SURFACE_TYPE_WINDOW, + (Drawable) win, nconf); + return (xsurf) ? &xsurf->base : NULL; +} + +static struct native_surface * +ximage_display_create_pixmap_surface(struct native_display *ndpy, + EGLNativePixmapType pix, + const struct native_config *nconf) +{ + struct ximage_surface *xsurf; + + xsurf = ximage_display_create_surface(ndpy, XIMAGE_SURFACE_TYPE_PIXMAP, + (Drawable) pix, nconf); + return (xsurf) ? &xsurf->base : NULL; +} + +static struct native_surface * +ximage_display_create_pbuffer_surface(struct native_display *ndpy, + const struct native_config *nconf, + uint width, uint height) +{ + struct ximage_surface *xsurf; + + xsurf = ximage_display_create_surface(ndpy, XIMAGE_SURFACE_TYPE_PBUFFER, + (Drawable) None, nconf); + if (xsurf) { + xsurf->width = width; + xsurf->height = height; + } + return (xsurf) ? &xsurf->base : NULL; +} + +static struct pipe_context * +ximage_display_create_context(struct native_display *ndpy, + void *context_private) +{ + struct pipe_context *pctx = softpipe_create(ndpy->screen); + if (pctx) + pctx->priv = context_private; + return pctx; +} + +static enum pipe_format +choose_format(const XVisualInfo *vinfo) +{ + enum pipe_format fmt; + /* TODO elaborate the formats */ + switch (vinfo->depth) { + case 32: + fmt = PIPE_FORMAT_A8R8G8B8_UNORM; + break; + case 24: + fmt = PIPE_FORMAT_X8R8G8B8_UNORM; + break; + case 16: + fmt = PIPE_FORMAT_R5G6B5_UNORM; + break; + default: + fmt = PIPE_FORMAT_NONE; + break; + } + + return fmt; +} + +static const struct native_config ** +ximage_display_get_configs(struct native_display *ndpy, int *num_configs) +{ + struct ximage_display *xdpy = ximage_display(ndpy); + const struct native_config **configs; + int i; + + /* first time */ + if (!xdpy->configs) { + const XVisualInfo *visuals; + int num_visuals, count, j; + + visuals = x11_screen_get_visuals(xdpy->xscr, &num_visuals); + if (!visuals) + return NULL; + + /* + * Create two configs for each visual. + * One with depth/stencil buffer; one without + */ + xdpy->configs = calloc(num_visuals * 2, sizeof(*xdpy->configs)); + if (!xdpy->configs) + return NULL; + + count = 0; + for (i = 0; i < num_visuals; i++) { + for (j = 0; j < 2; j++) { + struct ximage_config *xconf = &xdpy->configs[count]; + __GLcontextModes *mode = &xconf->base.mode; + + xconf->visual = &visuals[i]; + xconf->base.color_format = choose_format(xconf->visual); + if (xconf->base.color_format == PIPE_FORMAT_NONE) + continue; + + x11_screen_convert_visual(xdpy->xscr, xconf->visual, mode); + /* support double buffer mode */ + mode->doubleBufferMode = TRUE; + + xconf->base.depth_format = PIPE_FORMAT_NONE; + xconf->base.stencil_format = PIPE_FORMAT_NONE; + /* create the second config with depth/stencil buffer */ + if (j == 1) { + xconf->base.depth_format = PIPE_FORMAT_S8Z24_UNORM; + xconf->base.stencil_format = PIPE_FORMAT_S8Z24_UNORM; + mode->depthBits = 24; + mode->stencilBits = 8; + mode->haveDepthBuffer = TRUE; + mode->haveStencilBuffer = TRUE; + } + + mode->maxPbufferWidth = 4096; + mode->maxPbufferHeight = 4096; + mode->maxPbufferPixels = 4096 * 4096; + mode->drawableType = + GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT; + mode->swapMethod = GLX_SWAP_EXCHANGE_OML; + + if (mode->alphaBits) + mode->bindToTextureRgba = TRUE; + else + mode->bindToTextureRgb = TRUE; + + count++; + } + } + + xdpy->num_configs = count; + } + + configs = malloc(xdpy->num_configs * sizeof(*configs)); + if (configs) { + for (i = 0; i < xdpy->num_configs; i++) + configs[i] = (const struct native_config *) &xdpy->configs[i]; + if (num_configs) + *num_configs = xdpy->num_configs; + } + return configs; +} + +static void +ximage_display_destroy(struct native_display *ndpy) +{ + struct ximage_display *xdpy = ximage_display(ndpy); + + if (xdpy->configs) + free(xdpy->configs); + + xdpy->base.screen->destroy(xdpy->base.screen); + free(xdpy->winsys); + + x11_screen_destroy(xdpy->xscr); + if (xdpy->own_dpy) + XCloseDisplay(xdpy->dpy); + free(xdpy); +} + +static void +ximage_display_flush_frontbuffer(void *dummy, struct pipe_surface *surf, + void *context_private) +{ + /* TODO get native surface from context private, and remove the callback */ + _eglLog(_EGL_WARNING, "flush_frontbuffer is not supplied"); +} + +struct native_display * +x11_create_ximage_display(EGLNativeDisplayType dpy, + boolean use_xshm, + native_flush_frontbuffer flush_frontbuffer) +{ + struct ximage_display *xdpy; + + xdpy = CALLOC_STRUCT(ximage_display); + if (!xdpy) + return NULL; + + xdpy->dpy = dpy; + if (!xdpy->dpy) { + xdpy->dpy = XOpenDisplay(NULL); + if (!xdpy->dpy) { + free(xdpy); + return NULL; + } + xdpy->own_dpy = TRUE; + } + + xdpy->xscr_number = DefaultScreen(xdpy->dpy); + xdpy->xscr = x11_screen_create(xdpy->dpy, xdpy->xscr_number); + if (!xdpy->xscr) { + free(xdpy); + return NULL; + } + + xdpy->use_xshm = + (use_xshm && x11_screen_support(xdpy->xscr, X11_SCREEN_EXTENSION_XSHM)); + + xdpy->winsys = create_sw_winsys(); + if (!flush_frontbuffer) + flush_frontbuffer = ximage_display_flush_frontbuffer; + xdpy->winsys->flush_frontbuffer = + (void (*)(struct pipe_winsys *, struct pipe_surface *, void *)) + flush_frontbuffer; + + xdpy->base.screen = softpipe_create_screen(xdpy->winsys); + + xdpy->base.destroy = ximage_display_destroy; + + xdpy->base.get_configs = ximage_display_get_configs; + xdpy->base.create_context = ximage_display_create_context; + xdpy->base.create_window_surface = ximage_display_create_window_surface; + xdpy->base.create_pixmap_surface = ximage_display_create_pixmap_surface; + xdpy->base.create_pbuffer_surface = ximage_display_create_pbuffer_surface; + + return &xdpy->base; +} diff --git a/src/gallium/state_trackers/egl_g3d/x11/sw_winsys.c b/src/gallium/state_trackers/egl_g3d/x11/sw_winsys.c new file mode 100644 index 0000000000..6ee3ede38c --- /dev/null +++ b/src/gallium/state_trackers/egl_g3d/x11/sw_winsys.c @@ -0,0 +1,231 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/** + * Totally software-based winsys layer. + * Note that the one winsys function that we can't implement here + * is flush_frontbuffer(). + * Whoever uses this code will have to provide that. + * + * Authors: Brian Paul + */ + + +#include "pipe/internal/p_winsys_screen.h" +#include "pipe/p_state.h" +#include "pipe/p_inlines.h" +#include "util/u_format.h" +#include "util/u_math.h" +#include "util/u_memory.h" + +#include "sw_winsys.h" + + + +/** Subclass of pipe_winsys */ +struct sw_pipe_winsys +{ + struct pipe_winsys Base; + /* no extra fields for now */ +}; + + +/** subclass of pipe_buffer */ +struct sw_pipe_buffer +{ + struct pipe_buffer Base; + boolean UserBuffer; /** Is this a user-space buffer? */ + void *Data; + void *Mapped; +}; + + +/** cast wrapper */ +static INLINE struct sw_pipe_buffer * +sw_pipe_buffer(struct pipe_buffer *b) +{ + return (struct sw_pipe_buffer *) b; +} + + +static const char * +get_name(struct pipe_winsys *pws) +{ + return "software"; +} + + +/** Create new pipe_buffer and allocate storage of given size */ +static struct pipe_buffer * +buffer_create(struct pipe_winsys *pws, + unsigned alignment, + unsigned usage, + unsigned size) +{ + struct sw_pipe_buffer *buffer = CALLOC_STRUCT(sw_pipe_buffer); + if (!buffer) + return NULL; + + pipe_reference_init(&buffer->Base.reference, 1); + buffer->Base.alignment = alignment; + buffer->Base.usage = usage; + buffer->Base.size = size; + + /* align to 16-byte multiple for Cell */ + buffer->Data = align_malloc(size, MAX2(alignment, 16)); + + return &buffer->Base; +} + + +/** + * Create buffer which wraps user-space data. + */ +static struct pipe_buffer * +user_buffer_create(struct pipe_winsys *pws, void *ptr, unsigned bytes) +{ + struct sw_pipe_buffer *buffer = CALLOC_STRUCT(sw_pipe_buffer); + if (!buffer) + return NULL; + + pipe_reference_init(&buffer->Base.reference, 1); + buffer->Base.size = bytes; + buffer->UserBuffer = TRUE; + buffer->Data = ptr; + + return &buffer->Base; +} + + +static void * +buffer_map(struct pipe_winsys *pws, struct pipe_buffer *buf, unsigned flags) +{ + struct sw_pipe_buffer *buffer = sw_pipe_buffer(buf); + buffer->Mapped = buffer->Data; + return buffer->Mapped; +} + + +static void +buffer_unmap(struct pipe_winsys *pws, struct pipe_buffer *buf) +{ + struct sw_pipe_buffer *buffer = sw_pipe_buffer(buf); + buffer->Mapped = NULL; +} + + +static void +buffer_destroy(struct pipe_buffer *buf) +{ + struct sw_pipe_buffer *buffer = sw_pipe_buffer(buf); + + if (buffer->Data && !buffer->UserBuffer) { + align_free(buffer->Data); + buffer->Data = NULL; + } + + free(buffer); +} + + +static struct pipe_buffer * +surface_buffer_create(struct pipe_winsys *winsys, + unsigned width, unsigned height, + enum pipe_format format, + unsigned usage, + unsigned tex_usage, + unsigned *stride) +{ + const unsigned alignment = 64; + unsigned nblocksy; + + nblocksy = util_format_get_nblocksy(format, height); + *stride = align(util_format_get_stride(format, width), alignment); + + return winsys->buffer_create(winsys, alignment, + usage, + *stride * nblocksy); +} + + +static void +fence_reference(struct pipe_winsys *sws, struct pipe_fence_handle **ptr, + struct pipe_fence_handle *fence) +{ + /* no-op */ +} + + +static int +fence_signalled(struct pipe_winsys *sws, struct pipe_fence_handle *fence, + unsigned flag) +{ + /* no-op */ + return 0; +} + + +static int +fence_finish(struct pipe_winsys *sws, struct pipe_fence_handle *fence, + unsigned flag) +{ + /* no-op */ + return 0; +} + + +/** + * Create/return a new pipe_winsys object. + */ +struct pipe_winsys * +create_sw_winsys(void) +{ + struct sw_pipe_winsys *ws = CALLOC_STRUCT(sw_pipe_winsys); + if (!ws) + return NULL; + + /* Fill in this struct with callbacks that pipe will need to + * communicate with the window system, buffer manager, etc. + */ + ws->Base.buffer_create = buffer_create; + ws->Base.user_buffer_create = user_buffer_create; + ws->Base.buffer_map = buffer_map; + ws->Base.buffer_unmap = buffer_unmap; + ws->Base.buffer_destroy = buffer_destroy; + + ws->Base.surface_buffer_create = surface_buffer_create; + + ws->Base.fence_reference = fence_reference; + ws->Base.fence_signalled = fence_signalled; + ws->Base.fence_finish = fence_finish; + + ws->Base.flush_frontbuffer = NULL; /* not implemented here! */ + + ws->Base.get_name = get_name; + + return &ws->Base; +} diff --git a/src/gallium/state_trackers/egl_g3d/x11/sw_winsys.h b/src/gallium/state_trackers/egl_g3d/x11/sw_winsys.h new file mode 100644 index 0000000000..f96c5a14b0 --- /dev/null +++ b/src/gallium/state_trackers/egl_g3d/x11/sw_winsys.h @@ -0,0 +1,40 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + +#ifndef SW_WINSYS_H +#define SW_WINSYS_H + + +struct pipe_winsys; + + +extern struct pipe_winsys * +create_sw_winsys(void); + + +#endif /* SW_WINSYS_H */ diff --git a/src/gallium/state_trackers/egl_g3d/x11/x11_screen.c b/src/gallium/state_trackers/egl_g3d/x11/x11_screen.c new file mode 100644 index 0000000000..1e98943242 --- /dev/null +++ b/src/gallium/state_trackers/egl_g3d/x11/x11_screen.c @@ -0,0 +1,402 @@ +/* + * Mesa 3-D graphics library + * Version: 7.8 + * + * Copyright (C) 2009-2010 Chia-I Wu + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include "util/u_memory.h" +#include "util/u_math.h" +#include "xf86drm.h" +#include "egllog.h" + +#include "x11_screen.h" +#include "dri2.h" +#include "glxinit.h" + +struct x11_screen { + Display *dpy; + int number; + + __GLXdisplayPrivate *glx_dpy; + + int dri_major, dri_minor; + char *dri_driver; + char *dri_device; + int dri_fd; + + XVisualInfo *visuals; + int num_visuals; +}; + + +/** + * Create a X11 screen. + */ +struct x11_screen * +x11_screen_create(Display *dpy, int screen) +{ + struct x11_screen *xscr; + + if (screen >= ScreenCount(dpy)) + return NULL; + + xscr = CALLOC_STRUCT(x11_screen); + if (xscr) { + xscr->dpy = dpy; + xscr->number = screen; + + xscr->dri_major = -1; + xscr->dri_fd = -1; + } + return xscr; +} + +/** + * Destroy a X11 screen. + */ +void +x11_screen_destroy(struct x11_screen *xscr) +{ + if (xscr->dri_fd >= 0) + close(xscr->dri_fd); + if (xscr->dri_driver) + Xfree(xscr->dri_driver); + if (xscr->dri_device) + Xfree(xscr->dri_device); + + if (xscr->glx_dpy) + __glXRelease(xscr->glx_dpy); + if (xscr->visuals) + XFree(xscr->visuals); + free(xscr); +} + +static boolean +x11_screen_init_dri2(struct x11_screen *xscr) +{ + if (xscr->dri_major < 0) { + int eventBase, errorBase; + + if (!DRI2QueryExtension(xscr->dpy, &eventBase, &errorBase) || + !DRI2QueryVersion(xscr->dpy, &xscr->dri_major, &xscr->dri_minor)) + xscr->dri_major = -1; + } + return (xscr->dri_major >= 0); +} + +static boolean +x11_screen_init_glx(struct x11_screen *xscr) +{ + if (!xscr->glx_dpy) + xscr->glx_dpy = __glXInitialize(xscr->dpy); + return (xscr->glx_dpy != NULL); +} + +/** + * Return true if the screen supports the extension. + */ +boolean +x11_screen_support(struct x11_screen *xscr, enum x11_screen_extension ext) +{ + boolean supported = FALSE; + + switch (ext) { + case X11_SCREEN_EXTENSION_XSHM: + supported = XShmQueryExtension(xscr->dpy); + break; + case X11_SCREEN_EXTENSION_GLX: + supported = x11_screen_init_glx(xscr); + break; + case X11_SCREEN_EXTENSION_DRI2: + supported = x11_screen_init_dri2(xscr); + break; + default: + break; + } + + return supported; +} + +/** + * Return the X visuals. + */ +const XVisualInfo * +x11_screen_get_visuals(struct x11_screen *xscr, int *num_visuals) +{ + if (!xscr->visuals) { + XVisualInfo vinfo_template; + vinfo_template.screen = xscr->number; + xscr->visuals = XGetVisualInfo(xscr->dpy, VisualScreenMask, + &vinfo_template, &xscr->num_visuals); + } + + if (num_visuals) + *num_visuals = xscr->num_visuals; + return xscr->visuals; +} + +void +x11_screen_convert_visual(struct x11_screen *xscr, const XVisualInfo *visual, + __GLcontextModes *mode) +{ + int r, g, b, a; + int visual_type; + + r = util_bitcount(visual->red_mask); + g = util_bitcount(visual->green_mask); + b = util_bitcount(visual->blue_mask); + a = visual->depth - (r + g + b); +#if defined(__cplusplus) || defined(c_plusplus) + visual_type = visual->c_class; +#else + visual_type = visual->class; +#endif + + /* convert to GLX visual type */ + switch (visual_type) { + case TrueColor: + visual_type = GLX_TRUE_COLOR; + break; + case DirectColor: + visual_type = GLX_DIRECT_COLOR; + break; + case PseudoColor: + visual_type = GLX_PSEUDO_COLOR; + break; + case StaticColor: + visual_type = GLX_STATIC_COLOR; + break; + case GrayScale: + visual_type = GLX_GRAY_SCALE; + break; + case StaticGray: + visual_type = GLX_STATIC_GRAY; + break; + default: + visual_type = GLX_NONE; + break; + } + + mode->rgbBits = r + g + b + a; + mode->redBits = r; + mode->greenBits = g; + mode->blueBits = b; + mode->alphaBits = a; + mode->visualID = visual->visualid; + mode->visualType = visual_type; + + /* sane defaults */ + mode->renderType = GLX_RGBA_BIT; + mode->rgbMode = TRUE; + mode->visualRating = GLX_SLOW_CONFIG; + mode->xRenderable = TRUE; +} + +/** + * Return the GLX fbconfigs. + */ +const __GLcontextModes * +x11_screen_get_glx_configs(struct x11_screen *xscr) +{ + return (x11_screen_init_glx(xscr)) + ? xscr->glx_dpy->screenConfigs[xscr->number].configs + : NULL; +} + +/** + * Return the GLX visuals. + */ +const __GLcontextModes * +x11_screen_get_glx_visuals(struct x11_screen *xscr) +{ + return (x11_screen_init_glx(xscr)) + ? xscr->glx_dpy->screenConfigs[xscr->number].visuals + : NULL; +} + +static boolean +x11_screen_is_driver_equal(struct x11_screen *xscr, const char *driver) +{ + return (strcmp(xscr->dri_driver, driver) == 0); +} + +/** + * Enable DRI2 and returns the file descriptor of the DRM device. The file + * descriptor will be closed automatically when the screen is destoryed. + */ +int +x11_screen_enable_dri2(struct x11_screen *xscr, const char *driver) +{ + if (xscr->dri_fd < 0) { + int fd; + drm_magic_t magic; + + /* get the driver name and the device name first */ + if (!xscr->dri_driver) { + if (!DRI2Connect(xscr->dpy, RootWindow(xscr->dpy, xscr->number), + &xscr->dri_driver, &xscr->dri_device)) { + xscr->dri_driver = xscr->dri_device = NULL; + return -1; + } + } + + if (!x11_screen_is_driver_equal(xscr, driver)) { + _eglLog(_EGL_WARNING, "Driver mismatch: %s != %s", + xscr->dri_driver, driver); + return -1; + } + + fd = open(xscr->dri_device, O_RDWR); + if (fd < 0) { + _eglLog(_EGL_WARNING, "failed to open %s", xscr->dri_device); + return -1; + } + + memset(&magic, 0, sizeof(magic)); + if (drmGetMagic(fd, &magic)) { + _eglLog(_EGL_WARNING, "failed to get magic"); + close(fd); + return -1; + } + + if (!DRI2Authenticate(xscr->dpy, + RootWindow(xscr->dpy, xscr->number), magic)) { + _eglLog(_EGL_WARNING, "failed to authenticate magic"); + close(fd); + return -1; + } + + xscr->dri_fd = fd; + } + + return xscr->dri_fd; +} + +/** + * Create/Destroy the DRI drawable. + */ +void +x11_drawable_enable_dri2(struct x11_screen *xscr, + Drawable drawable, boolean on) +{ + if (on) + DRI2CreateDrawable(xscr->dpy, drawable); + else + DRI2DestroyDrawable(xscr->dpy, drawable); +} + +/** + * Copy between buffers of the DRI2 drawable. + */ +void +x11_drawable_copy_buffers(struct x11_screen *xscr, Drawable drawable, + int x, int y, int width, int height, + int src_buf, int dst_buf) +{ + XRectangle rect; + XserverRegion region; + + rect.x = x; + rect.y = y; + rect.width = width; + rect.height = height; + + region = XFixesCreateRegion(xscr->dpy, &rect, 1); + DRI2CopyRegion(xscr->dpy, drawable, region, dst_buf, src_buf); + XFixesDestroyRegion(xscr->dpy, region); +} + +/** + * Get the buffers of the DRI2 drawable. The returned array should be freed. + */ +struct x11_drawable_buffer * +x11_drawable_get_buffers(struct x11_screen *xscr, Drawable drawable, + int *width, int *height, unsigned int *attachments, + boolean with_format, int num_ins, int *num_outs) +{ + DRI2Buffer *dri2bufs; + + if (with_format) + dri2bufs = DRI2GetBuffersWithFormat(xscr->dpy, drawable, width, height, + attachments, num_ins, num_outs); + else + dri2bufs = DRI2GetBuffers(xscr->dpy, drawable, width, height, + attachments, num_ins, num_outs); + + return (struct x11_drawable_buffer *) dri2bufs; +} + +/** + * Create a mode list of the given size. + */ +__GLcontextModes * +x11_context_modes_create(unsigned count) +{ + const size_t size = sizeof(__GLcontextModes); + __GLcontextModes *base = NULL; + __GLcontextModes **next; + unsigned i; + + next = &base; + for (i = 0; i < count; i++) { + *next = (__GLcontextModes *) calloc(1, size); + if (*next == NULL) { + x11_context_modes_destroy(base); + base = NULL; + break; + } + next = &((*next)->next); + } + + return base; +} + +/** + * Destroy a mode list. + */ +void +x11_context_modes_destroy(__GLcontextModes *modes) +{ + while (modes != NULL) { + __GLcontextModes *next = modes->next; + free(modes); + modes = next; + } +} + +/** + * Return the number of the modes in the mode list. + */ +unsigned +x11_context_modes_count(const __GLcontextModes *modes) +{ + const __GLcontextModes *mode; + int count = 0; + for (mode = modes; mode; mode = mode->next) + count++; + return count; +} diff --git a/src/gallium/state_trackers/egl_g3d/x11/x11_screen.h b/src/gallium/state_trackers/egl_g3d/x11/x11_screen.h new file mode 100644 index 0000000000..86e8e0501a --- /dev/null +++ b/src/gallium/state_trackers/egl_g3d/x11/x11_screen.h @@ -0,0 +1,99 @@ +/* + * Mesa 3-D graphics library + * Version: 7.8 + * + * Copyright (C) 2009-2010 Chia-I Wu + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef _X11_SCREEN_H_ +#define _X11_SCREEN_H_ + +#include +#include +#include +#include "pipe/p_compiler.h" +#include "common/native.h" + +enum x11_screen_extension { + X11_SCREEN_EXTENSION_XSHM, + X11_SCREEN_EXTENSION_GLX, + X11_SCREEN_EXTENSION_DRI2, +}; + +/* the same as DRI2Buffer */ +struct x11_drawable_buffer { + unsigned int attachment; + unsigned int name; + unsigned int pitch; + unsigned int cpp; + unsigned int flags; +}; + +struct x11_screen; + +struct x11_screen * +x11_screen_create(Display *dpy, int screen); + +void +x11_screen_destroy(struct x11_screen *xscr); + +boolean +x11_screen_support(struct x11_screen *xscr, enum x11_screen_extension ext); + +const XVisualInfo * +x11_screen_get_visuals(struct x11_screen *xscr, int *num_visuals); + +void +x11_screen_convert_visual(struct x11_screen *xscr, const XVisualInfo *visual, + __GLcontextModes *mode); + +const __GLcontextModes * +x11_screen_get_glx_configs(struct x11_screen *xscr); + +const __GLcontextModes * +x11_screen_get_glx_visuals(struct x11_screen *xscr); + +int +x11_screen_enable_dri2(struct x11_screen *xscr, const char *driver); + +__GLcontextModes * +x11_context_modes_create(unsigned count); + +void +x11_context_modes_destroy(__GLcontextModes *modes); + +unsigned +x11_context_modes_count(const __GLcontextModes *modes); + +void +x11_drawable_enable_dri2(struct x11_screen *xscr, + Drawable drawable, boolean on); + +void +x11_drawable_copy_buffers(struct x11_screen *xscr, Drawable drawable, + int x, int y, int width, int height, + int src_buf, int dst_buf); + +struct x11_drawable_buffer * +x11_drawable_get_buffers(struct x11_screen *xscr, Drawable drawable, + int *width, int *height, unsigned int *attachments, + boolean with_format, int num_ins, int *num_outs); + +#endif /* _X11_SCREEN_H_ */ -- cgit v1.2.3 From a68b51deb2ea4f3cb51f2753b1b879e5677db225 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Sun, 3 Jan 2010 19:24:04 +0800 Subject: st/egl_g3d: Add support for KMS native display. The KMS native display implements the modeset interface using DRM modesetting. Signed-off-by: Chia-I Wu --- configure.ac | 2 +- .../state_trackers/egl_g3d/kms/native_kms.c | 866 +++++++++++++++++++++ .../state_trackers/egl_g3d/kms/native_kms.h | 138 ++++ 3 files changed, 1005 insertions(+), 1 deletion(-) create mode 100644 src/gallium/state_trackers/egl_g3d/kms/native_kms.c create mode 100644 src/gallium/state_trackers/egl_g3d/kms/native_kms.h (limited to 'configure.ac') diff --git a/configure.ac b/configure.ac index 8a8919b137..5fea166c67 100644 --- a/configure.ac +++ b/configure.ac @@ -1194,7 +1194,7 @@ esac AC_ARG_WITH([egl-displays], [AS_HELP_STRING([--with-egl-displays@<:@=DIRS...@:>@], [comma delimited native displays libEGL supports, e.g. - "x11" @<:@default=auto@:>@])], + "x11,kms" @<:@default=auto@:>@])], [with_egl_displays="$withval"], [with_egl_displays=yes]) diff --git a/src/gallium/state_trackers/egl_g3d/kms/native_kms.c b/src/gallium/state_trackers/egl_g3d/kms/native_kms.c new file mode 100644 index 0000000000..0e0babdb14 --- /dev/null +++ b/src/gallium/state_trackers/egl_g3d/kms/native_kms.c @@ -0,0 +1,866 @@ +/* + * Mesa 3-D graphics library + * Version: 7.8 + * + * Copyright (C) 2010 Chia-I Wu + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include + +#include "pipe/p_screen.h" +#include "pipe/p_context.h" +#include "util/u_debug.h" +#include "util/u_memory.h" +#include "egllog.h" + +#include "native_kms.h" + +static boolean +kms_surface_validate(struct native_surface *nsurf, + const enum native_attachment *natts, + unsigned num_natts, + struct pipe_texture **textures, + int *width, int *height) +{ + struct kms_surface *ksurf = kms_surface(nsurf); + struct kms_display *kdpy = ksurf->kdpy; + struct pipe_screen *screen = kdpy->base.screen; + struct pipe_texture templ, *ptex; + int i; + + if (num_natts) { + if (textures) + memset(textures, 0, sizeof(*textures) * num_natts); + + memset(&templ, 0, sizeof(templ)); + templ.target = PIPE_TEXTURE_2D; + templ.last_level = 0; + templ.width0 = ksurf->width; + templ.height0 = ksurf->height; + templ.depth0 = 1; + templ.format = ksurf->color_format; + templ.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET; + if (ksurf->type == KMS_SURFACE_TYPE_SCANOUT) + templ.tex_usage |= PIPE_TEXTURE_USAGE_PRIMARY; + } + + /* create textures */ + for (i = 0; i < num_natts; i++) { + enum native_attachment natt = natts[i]; + + ptex = ksurf->textures[natt]; + if (!ptex) { + ptex = screen->texture_create(screen, &templ); + ksurf->textures[natt] = ptex; + } + + if (textures) + pipe_texture_reference(&textures[i], ptex); + } + + if (width) + *width = ksurf->width; + if (height) + *height = ksurf->height; + + return TRUE; +} + +/** + * Add textures as DRM framebuffers. + */ +static boolean +kms_surface_init_framebuffers(struct native_surface *nsurf, boolean need_back) +{ + struct kms_surface *ksurf = kms_surface(nsurf); + struct kms_display *kdpy = ksurf->kdpy; + int num_framebuffers = (need_back) ? 2 : 1; + int i, err; + + for (i = 0; i < num_framebuffers; i++) { + struct kms_framebuffer *fb; + enum native_attachment natt; + unsigned int handle, stride; + uint block_bits; + + if (i == 0) { + fb = &ksurf->front_fb; + natt = NATIVE_ATTACHMENT_FRONT_LEFT; + } + else { + fb = &ksurf->back_fb; + natt = NATIVE_ATTACHMENT_BACK_LEFT; + } + + if (!fb->texture) { + /* make sure the texture has been allocated */ + kms_surface_validate(&ksurf->base, &natt, 1, NULL, NULL, NULL); + if (!ksurf->textures[natt]) + return FALSE; + + pipe_texture_reference(&fb->texture, ksurf->textures[natt]); + } + + /* already initialized */ + if (fb->buffer_id) + continue; + + /* TODO detect the real value */ + fb->is_passive = TRUE; + + if (!kdpy->api->local_handle_from_texture(kdpy->api, + kdpy->base.screen, fb->texture, &stride, &handle)) + return FALSE; + + block_bits = util_format_get_blocksizebits(ksurf->color_format); + err = drmModeAddFB(kdpy->fd, ksurf->width, ksurf->height, + block_bits, block_bits, stride, handle, &fb->buffer_id); + if (err) { + fb->buffer_id = 0; + return FALSE; + } + } + + return TRUE; +} + +static boolean +kms_surface_flush_frontbuffer(struct native_surface *nsurf) +{ +#ifdef DRM_MODE_FEATURE_DIRTYFB + struct kms_surface *ksurf = kms_surface(nsurf); + struct kms_display *kdpy = ksurf->kdpy; + + /* pbuffer is private */ + if (ksurf->type == KMS_SURFACE_TYPE_PBUFFER) + return TRUE; + + if (ksurf->front_fb.is_passive) + drmModeDirtyFB(kdpy->fd, ksurf->front_fb.buffer_id, NULL, 0); +#endif + + return TRUE; +} + +static boolean +kms_surface_swap_buffers(struct native_surface *nsurf) +{ + struct kms_surface *ksurf = kms_surface(nsurf); + struct kms_crtc *kcrtc = &ksurf->current_crtc; + struct kms_display *kdpy = ksurf->kdpy; + struct kms_framebuffer tmp_fb; + struct pipe_texture *tmp_texture; + int err; + + /* pbuffer is private */ + if (ksurf->type == KMS_SURFACE_TYPE_PBUFFER) + return TRUE; + + if (!ksurf->back_fb.buffer_id) { + if (!kms_surface_init_framebuffers(&ksurf->base, TRUE)) + return FALSE; + } + + if (ksurf->is_shown && kcrtc->crtc) { + err = drmModeSetCrtc(kdpy->fd, kcrtc->crtc->crtc_id, + ksurf->back_fb.buffer_id, kcrtc->crtc->x, kcrtc->crtc->y, + kcrtc->connectors, kcrtc->num_connectors, &kcrtc->crtc->mode); + if (err) + return FALSE; + } + + /* swap the buffers */ + tmp_fb = ksurf->front_fb; + ksurf->front_fb = ksurf->back_fb; + ksurf->back_fb = tmp_fb; + + tmp_texture = ksurf->textures[NATIVE_ATTACHMENT_FRONT_LEFT]; + ksurf->textures[NATIVE_ATTACHMENT_FRONT_LEFT] = + ksurf->textures[NATIVE_ATTACHMENT_BACK_LEFT]; + ksurf->textures[NATIVE_ATTACHMENT_BACK_LEFT] = tmp_texture; + + return TRUE; +} + +static void +kms_surface_wait(struct native_surface *nsurf) +{ + /* no-op */ +} + +static void +kms_surface_destroy(struct native_surface *nsurf) +{ + struct kms_surface *ksurf = kms_surface(nsurf); + int i; + + if (ksurf->current_crtc.crtc) + drmModeFreeCrtc(ksurf->current_crtc.crtc); + + if (ksurf->front_fb.buffer_id) + drmModeRmFB(ksurf->kdpy->fd, ksurf->front_fb.buffer_id); + pipe_texture_reference(&ksurf->front_fb.texture, NULL); + + if (ksurf->back_fb.buffer_id) + drmModeRmFB(ksurf->kdpy->fd, ksurf->back_fb.buffer_id); + pipe_texture_reference(&ksurf->back_fb.texture, NULL); + + for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) { + struct pipe_texture *ptex = ksurf->textures[i]; + pipe_texture_reference(&ptex, NULL); + } + + free(ksurf); +} + +static struct kms_surface * +kms_display_create_surface(struct native_display *ndpy, + enum kms_surface_type type, + const struct native_config *nconf, + uint width, uint height) +{ + struct kms_display *kdpy = kms_display(ndpy); + struct kms_config *kconf = kms_config(nconf); + struct kms_surface *ksurf; + + ksurf = CALLOC_STRUCT(kms_surface); + if (!ksurf) + return NULL; + + ksurf->kdpy = kdpy; + ksurf->type = type; + ksurf->color_format = kconf->base.color_format; + ksurf->width = width; + ksurf->height = height; + + ksurf->base.destroy = kms_surface_destroy; + ksurf->base.swap_buffers = kms_surface_swap_buffers; + ksurf->base.flush_frontbuffer = kms_surface_flush_frontbuffer; + ksurf->base.validate = kms_surface_validate; + ksurf->base.wait = kms_surface_wait; + + return ksurf; +} + +/** + * Choose a CRTC that supports all given connectors. + */ +static uint32_t +kms_display_choose_crtc(struct native_display *ndpy, + uint32_t *connectors, int num_connectors) +{ + struct kms_display *kdpy = kms_display(ndpy); + int idx; + + for (idx = 0; idx < kdpy->resources->count_crtcs; idx++) { + boolean found_crtc = TRUE; + int i, j; + + for (i = 0; i < num_connectors; i++) { + drmModeConnectorPtr connector; + int encoder_idx = -1; + + connector = drmModeGetConnector(kdpy->fd, connectors[i]); + if (!connector) { + found_crtc = FALSE; + break; + } + + /* find an encoder the CRTC supports */ + for (j = 0; j < connector->count_encoders; j++) { + drmModeEncoderPtr encoder = + drmModeGetEncoder(kdpy->fd, connector->encoders[j]); + if (encoder->possible_crtcs & (1 << idx)) { + encoder_idx = j; + break; + } + drmModeFreeEncoder(encoder); + } + + drmModeFreeConnector(connector); + if (encoder_idx < 0) { + found_crtc = FALSE; + break; + } + } + + if (found_crtc) + break; + } + + if (idx >= kdpy->resources->count_crtcs) { + _eglLog(_EGL_WARNING, + "failed to find a CRTC that supports the given %d connectors", + num_connectors); + return 0; + } + + return kdpy->resources->crtcs[idx]; +} + +/** + * Remember the original CRTC status and set the CRTC + */ +static boolean +kms_display_set_crtc(struct native_display *ndpy, int crtc_idx, + uint32_t buffer_id, uint32_t x, uint32_t y, + uint32_t *connectors, int num_connectors, + drmModeModeInfoPtr mode) +{ + struct kms_display *kdpy = kms_display(ndpy); + struct kms_crtc *kcrtc = &kdpy->saved_crtcs[crtc_idx]; + uint32_t crtc_id; + int err; + + if (kcrtc->crtc) { + crtc_id = kcrtc->crtc->crtc_id; + } + else { + int count = 0, i; + + /* + * Choose the CRTC once. It could be more dynamic, but let's keep it + * simple for now. + */ + crtc_id = kms_display_choose_crtc(&kdpy->base, + connectors, num_connectors); + + /* save the original CRTC status */ + kcrtc->crtc = drmModeGetCrtc(kdpy->fd, crtc_id); + if (!kcrtc->crtc) + return FALSE; + + for (i = 0; i < kdpy->num_connectors; i++) { + struct kms_connector *kconn = &kdpy->connectors[i]; + drmModeConnectorPtr connector = kconn->connector; + drmModeEncoderPtr encoder; + + encoder = drmModeGetEncoder(kdpy->fd, connector->encoder_id); + if (encoder) { + if (encoder->crtc_id == crtc_id) { + kcrtc->connectors[count++] = connector->connector_id; + if (count >= Elements(kcrtc->connectors)) + break; + } + drmModeFreeEncoder(encoder); + } + } + + kcrtc->num_connectors = count; + } + + err = drmModeSetCrtc(kdpy->fd, crtc_id, buffer_id, x, y, + connectors, num_connectors, mode); + if (err) { + drmModeFreeCrtc(kcrtc->crtc); + kcrtc->crtc = NULL; + kcrtc->num_connectors = 0; + + return FALSE; + } + + return TRUE; +} + +static boolean +kms_display_program(struct native_display *ndpy, int crtc_idx, + struct native_surface *nsurf, uint x, uint y, + const struct native_connector **nconns, int num_nconns, + const struct native_mode *nmode) +{ + struct kms_display *kdpy = kms_display(ndpy); + struct kms_surface *ksurf = kms_surface(nsurf); + const struct kms_mode *kmode = kms_mode(nmode); + uint32_t connector_ids[32]; + uint32_t buffer_id; + drmModeModeInfo mode_tmp, *mode; + int i; + + if (num_nconns > Elements(connector_ids)) { + _eglLog(_EGL_WARNING, "too many connectors (%d)", num_nconns); + num_nconns = Elements(connector_ids); + } + + if (ksurf) { + if (!kms_surface_init_framebuffers(&ksurf->base, FALSE)) + return FALSE; + + buffer_id = ksurf->front_fb.buffer_id; + /* the mode argument of drmModeSetCrtc is not constified */ + mode_tmp = kmode->mode; + mode = &mode_tmp; + } + else { + /* disable the CRTC */ + buffer_id = 0; + mode = NULL; + num_nconns = 0; + } + + for (i = 0; i < num_nconns; i++) { + struct kms_connector *kconn = kms_connector(nconns[i]); + connector_ids[i] = kconn->connector->connector_id; + } + + if (!kms_display_set_crtc(&kdpy->base, crtc_idx, buffer_id, x, y, + connector_ids, num_nconns, mode)) { + _eglLog(_EGL_WARNING, "failed to set CRTC %d", crtc_idx); + + return FALSE; + } + + if (kdpy->shown_surfaces[crtc_idx]) + kdpy->shown_surfaces[crtc_idx]->is_shown = FALSE; + kdpy->shown_surfaces[crtc_idx] = ksurf; + + /* remember the settings for buffer swapping */ + if (ksurf) { + uint32_t crtc_id = kdpy->saved_crtcs[crtc_idx].crtc->crtc_id; + struct kms_crtc *kcrtc = &ksurf->current_crtc; + + if (kcrtc->crtc) + drmModeFreeCrtc(kcrtc->crtc); + kcrtc->crtc = drmModeGetCrtc(kdpy->fd, crtc_id); + + assert(num_nconns < Elements(kcrtc->connectors)); + memcpy(kcrtc->connectors, connector_ids, + sizeof(*connector_ids) * num_nconns); + kcrtc->num_connectors = num_nconns; + + ksurf->is_shown = TRUE; + } + + return TRUE; +} + +static const struct native_mode ** +kms_display_get_modes(struct native_display *ndpy, + const struct native_connector *nconn, + int *num_modes) +{ + struct kms_display *kdpy = kms_display(ndpy); + struct kms_connector *kconn = kms_connector(nconn); + const struct native_mode **nmodes_return; + int count, i; + + /* delete old data */ + if (kconn->connector) { + drmModeFreeConnector(kconn->connector); + free(kconn->kms_modes); + + kconn->connector = NULL; + kconn->kms_modes = NULL; + kconn->num_modes = 0; + } + + /* detect again */ + kconn->connector = drmModeGetConnector(kdpy->fd, kconn->connector_id); + if (!kconn->connector) + return NULL; + + count = kconn->connector->count_modes; + kconn->kms_modes = calloc(count, sizeof(*kconn->kms_modes)); + if (!kconn->kms_modes) { + drmModeFreeConnector(kconn->connector); + kconn->connector = NULL; + + return NULL; + } + + for (i = 0; i < count; i++) { + struct kms_mode *kmode = &kconn->kms_modes[i]; + drmModeModeInfoPtr mode = &kconn->connector->modes[i]; + + kmode->mode = *mode; + + kmode->base.desc = kmode->mode.name; + kmode->base.width = kmode->mode.hdisplay; + kmode->base.height = kmode->mode.vdisplay; + kmode->base.refresh_rate = kmode->mode.vrefresh / 1000; + } + + nmodes_return = malloc(count * sizeof(*nmodes_return)); + if (nmodes_return) { + for (i = 0; i < count; i++) + nmodes_return[i] = &kconn->kms_modes[i].base; + if (num_modes) + *num_modes = count; + } + + return nmodes_return; +} + +static const struct native_connector ** +kms_display_get_connectors(struct native_display *ndpy, int *num_connectors, + int *num_crtc) +{ + struct kms_display *kdpy = kms_display(ndpy); + const struct native_connector **connectors; + int i; + + if (!kdpy->connectors) { + kdpy->connectors = + calloc(kdpy->resources->count_connectors, sizeof(*kdpy->connectors)); + if (!kdpy->connectors) + return NULL; + + for (i = 0; i < kdpy->resources->count_connectors; i++) { + struct kms_connector *kconn = &kdpy->connectors[i]; + + kconn->connector_id = kdpy->resources->connectors[i]; + /* kconn->connector is allocated when the modes are asked */ + } + + kdpy->num_connectors = kdpy->resources->count_connectors; + } + + connectors = malloc(kdpy->num_connectors * sizeof(*connectors)); + if (connectors) { + for (i = 0; i < kdpy->num_connectors; i++) + connectors[i] = &kdpy->connectors[i].base; + if (num_connectors) + *num_connectors = kdpy->num_connectors; + } + + if (num_crtc) + *num_crtc = kdpy->resources->count_crtcs; + + return connectors; +} + +static struct native_surface * +kms_display_create_scanout_surface(struct native_display *ndpy, + const struct native_config *nconf, + uint width, uint height) +{ + struct kms_surface *ksurf; + + ksurf = kms_display_create_surface(ndpy, + KMS_SURFACE_TYPE_SCANOUT, nconf, width, height); + return &ksurf->base; +} + +static struct native_surface * +kms_display_create_pbuffer_surface(struct native_display *ndpy, + const struct native_config *nconf, + uint width, uint height) +{ + struct kms_surface *ksurf; + + ksurf = kms_display_create_surface(ndpy, + KMS_SURFACE_TYPE_PBUFFER, nconf, width, height); + return &ksurf->base; +} + +static struct pipe_context * +kms_display_create_context(struct native_display *ndpy, void *context_private) +{ + struct kms_display *kdpy = kms_display(ndpy); + struct pipe_context *pctx; + + pctx = kdpy->api->create_context(kdpy->api, kdpy->base.screen); + if (pctx) + pctx->priv = context_private; + return pctx; +} + +static boolean +kms_display_is_format_supported(struct native_display *ndpy, + enum pipe_format fmt, boolean is_color) +{ + return ndpy->screen->is_format_supported(ndpy->screen, + fmt, PIPE_TEXTURE_2D, + (is_color) ? PIPE_TEXTURE_USAGE_RENDER_TARGET : + PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0); +} + +static const struct native_config ** +kms_display_get_configs(struct native_display *ndpy, int *num_configs) +{ + struct kms_display *kdpy = kms_display(ndpy); + const struct native_config **configs; + + /* first time */ + if (!kdpy->config) { + struct native_config *nconf; + enum pipe_format format; + + kdpy->config = calloc(1, sizeof(*kdpy->config)); + if (!kdpy->config) + return NULL; + + nconf = &kdpy->config->base; + + /* always double-buffered */ + nconf->mode.doubleBufferMode = TRUE; + + format = PIPE_FORMAT_A8R8G8B8_UNORM; + if (!kms_display_is_format_supported(&kdpy->base, format, TRUE)) { + format = PIPE_FORMAT_B8G8R8A8_UNORM; + if (!kms_display_is_format_supported(&kdpy->base, format, TRUE)) + format = PIPE_FORMAT_NONE; + } + if (format == PIPE_FORMAT_NONE) + return NULL; + + nconf->color_format = format; + nconf->mode.redBits = 8; + nconf->mode.greenBits = 8; + nconf->mode.blueBits = 8; + nconf->mode.alphaBits = 8; + nconf->mode.rgbBits = 32; + + format = PIPE_FORMAT_S8Z24_UNORM; + if (!kms_display_is_format_supported(&kdpy->base, format, FALSE)) { + format = PIPE_FORMAT_Z24S8_UNORM; + if (!kms_display_is_format_supported(&kdpy->base, format, FALSE)) + format = PIPE_FORMAT_NONE; + } + if (format != PIPE_FORMAT_NONE) { + nconf->depth_format = format; + nconf->stencil_format = format; + + nconf->mode.depthBits = 24; + nconf->mode.stencilBits = 8; + nconf->mode.haveDepthBuffer = TRUE; + nconf->mode.haveStencilBuffer = TRUE; + } + + nconf->scanout_bit = TRUE; + nconf->mode.drawableType = GLX_PBUFFER_BIT; + nconf->mode.swapMethod = GLX_SWAP_EXCHANGE_OML; + + nconf->mode.visualID = 0; + nconf->mode.visualType = EGL_NONE; + + nconf->mode.renderType = GLX_RGBA_BIT; + nconf->mode.rgbMode = TRUE; + nconf->mode.xRenderable = FALSE; + } + + configs = malloc(sizeof(*configs)); + if (configs) { + configs[0] = &kdpy->config->base; + if (num_configs) + *num_configs = 1; + } + + return configs; +} + +static void +kms_display_destroy(struct native_display *ndpy) +{ + struct kms_display *kdpy = kms_display(ndpy); + int i; + + if (kdpy->config) + free(kdpy->config); + + if (kdpy->connectors) { + for (i = 0; i < kdpy->num_connectors; i++) { + struct kms_connector *kconn = &kdpy->connectors[i]; + if (kconn->connector) { + drmModeFreeConnector(kconn->connector); + free(kconn->kms_modes); + } + } + free(kdpy->connectors); + } + + if (kdpy->shown_surfaces) + free(kdpy->shown_surfaces); + + if (kdpy->saved_crtcs) { + for (i = 0; i < kdpy->resources->count_crtcs; i++) { + struct kms_crtc *kcrtc = &kdpy->saved_crtcs[i]; + + if (kcrtc->crtc) { + /* restore crtc */ + drmModeSetCrtc(kdpy->fd, kcrtc->crtc->crtc_id, + kcrtc->crtc->buffer_id, kcrtc->crtc->x, kcrtc->crtc->y, + kcrtc->connectors, kcrtc->num_connectors, + &kcrtc->crtc->mode); + + drmModeFreeCrtc(kcrtc->crtc); + } + } + free(kdpy->saved_crtcs); + } + + if (kdpy->resources) + drmModeFreeResources(kdpy->resources); + + if (kdpy->base.screen) + kdpy->base.screen->destroy(kdpy->base.screen); + + if (kdpy->fd >= 0) + drmClose(kdpy->fd); + + if (kdpy->api) + kdpy->api->destroy(kdpy->api); + free(kdpy); +} + +/** + * Initialize KMS and pipe screen. + */ +static boolean +kms_display_init_screen(struct native_display *ndpy) +{ + struct kms_display *kdpy = kms_display(ndpy); + struct drm_create_screen_arg arg; + int fd; + + fd = drmOpen(kdpy->api->name, NULL); + if (fd < 0) { + _eglLog(_EGL_WARNING, "failed to open DRM device"); + return FALSE; + } + +#if 0 + if (drmSetMaster(fd)) { + _eglLog(_EGL_WARNING, "failed to become DRM master"); + return FALSE; + } +#endif + + memset(&arg, 0, sizeof(arg)); + arg.mode = DRM_CREATE_NORMAL; + kdpy->base.screen = kdpy->api->create_screen(kdpy->api, fd, &arg); + if (!kdpy->base.screen) { + _eglLog(_EGL_WARNING, "failed to create DRM screen"); + drmClose(fd); + return FALSE; + } + + kdpy->fd = fd; + + return TRUE; +} + +static struct native_display_modeset kms_display_modeset = { + .get_connectors = kms_display_get_connectors, + .get_modes = kms_display_get_modes, + .create_scanout_surface = kms_display_create_scanout_surface, + .program = kms_display_program +}; + +static struct native_display * +kms_create_display(EGLNativeDisplayType dpy, struct drm_api *api, + native_flush_frontbuffer flush_frontbuffer) +{ + struct kms_display *kdpy; + + kdpy = CALLOC_STRUCT(kms_display); + if (!kdpy) + return NULL; + + kdpy->api = api; + if (!kdpy->api) { + _eglLog(_EGL_WARNING, "failed to create DRM API"); + free(kdpy); + return NULL; + } + + kdpy->fd = -1; + if (!kms_display_init_screen(&kdpy->base)) { + kms_display_destroy(&kdpy->base); + return NULL; + } + + /* resources are fixed, unlike crtc, connector, or encoder */ + kdpy->resources = drmModeGetResources(kdpy->fd); + if (!kdpy->resources) { + kms_display_destroy(&kdpy->base); + return NULL; + } + + kdpy->saved_crtcs = + calloc(kdpy->resources->count_crtcs, sizeof(*kdpy->saved_crtcs)); + if (!kdpy->saved_crtcs) { + kms_display_destroy(&kdpy->base); + return NULL; + } + + kdpy->shown_surfaces = + calloc(kdpy->resources->count_crtcs, sizeof(*kdpy->shown_surfaces)); + if (!kdpy->shown_surfaces) { + kms_display_destroy(&kdpy->base); + return NULL; + } + + kdpy->base.screen->flush_frontbuffer = + (void (*)(struct pipe_screen *, struct pipe_surface *, void *)) + flush_frontbuffer; + + kdpy->base.destroy = kms_display_destroy; + kdpy->base.get_configs = kms_display_get_configs; + kdpy->base.create_context = kms_display_create_context; + kdpy->base.create_pbuffer_surface = kms_display_create_pbuffer_surface; + + kdpy->base.modeset = &kms_display_modeset; + + return &kdpy->base; +} + +static void +dummy_flush_frontbuffer(void *dummy, struct pipe_surface *surf, + void *context_private) +{ + _eglLog(_EGL_WARNING, "flush_frontbuffer is not supplied"); +} + +/* the api is destroyed with the native display */ +static struct drm_api *drm_api; + +const char * +native_get_name(void) +{ + static char kms_name[32]; + + if (!drm_api) + drm_api = drm_api_create(); + + if (drm_api) + snprintf(kms_name, sizeof(kms_name), "KMS/%s", drm_api->name); + else + snprintf(kms_name, sizeof(kms_name), "KMS"); + + return kms_name; +} + +struct native_display * +native_create_display(EGLNativeDisplayType dpy, + native_flush_frontbuffer flush_frontbuffer) +{ + struct native_display *ndpy = NULL; + + if (!drm_api) + drm_api = drm_api_create(); + + if (!flush_frontbuffer) + flush_frontbuffer = dummy_flush_frontbuffer; + + if (drm_api) + ndpy = kms_create_display(dpy, drm_api, flush_frontbuffer); + + return ndpy; +} diff --git a/src/gallium/state_trackers/egl_g3d/kms/native_kms.h b/src/gallium/state_trackers/egl_g3d/kms/native_kms.h new file mode 100644 index 0000000000..3f869b25ac --- /dev/null +++ b/src/gallium/state_trackers/egl_g3d/kms/native_kms.h @@ -0,0 +1,138 @@ +/* + * Mesa 3-D graphics library + * Version: 7.8 + * + * Copyright (C) 2010 Chia-I Wu + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef _NATIVE_KMS_H_ +#define _NATIVE_KMS_H_ + +#include +#include + +#include "pipe/p_compiler.h" +#include "util/u_format.h" +#include "pipe/p_state.h" +#include "state_tracker/drm_api.h" + +#include "common/native.h" + +enum kms_surface_type { + KMS_SURFACE_TYPE_PBUFFER, + KMS_SURFACE_TYPE_SCANOUT +}; + +struct kms_config; +struct kms_connector; +struct kms_mode; + +struct kms_crtc { + drmModeCrtcPtr crtc; + uint32_t connectors[32]; + int num_connectors; +}; + +struct kms_display { + struct native_display base; + + int fd; + struct drm_api *api; + drmModeResPtr resources; + struct kms_config *config; + + struct kms_connector *connectors; + int num_connectors; + + struct kms_surface **shown_surfaces; + /* save the original settings of the CRTCs */ + struct kms_crtc *saved_crtcs; +}; + +struct kms_framebuffer { + struct pipe_texture *texture; + boolean is_passive; + + uint32_t buffer_id; +}; + +struct kms_surface { + struct native_surface base; + enum kms_surface_type type; + enum pipe_format color_format; + struct kms_display *kdpy; + int width, height; + + struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS]; + struct kms_framebuffer front_fb, back_fb; + + boolean is_shown; + struct kms_crtc current_crtc; +}; + +struct kms_config { + struct native_config base; +}; + +struct kms_connector { + struct native_connector base; + + uint32_t connector_id; + drmModeConnectorPtr connector; + struct kms_mode *kms_modes; + int num_modes; +}; + +struct kms_mode { + struct native_mode base; + drmModeModeInfo mode; +}; + +static INLINE struct kms_display * +kms_display(const struct native_display *ndpy) +{ + return (struct kms_display *) ndpy; +} + +static INLINE struct kms_surface * +kms_surface(const struct native_surface *nsurf) +{ + return (struct kms_surface *) nsurf; +} + +static INLINE struct kms_config * +kms_config(const struct native_config *nconf) +{ + return (struct kms_config *) nconf; +} + +static INLINE struct kms_connector * +kms_connector(const struct native_connector *nconn) +{ + return (struct kms_connector *) nconn; +} + +static INLINE struct kms_mode * +kms_mode(const struct native_mode *nmode) +{ + return (struct kms_mode *) nmode; +} + +#endif /* _NATIVE_KMS_H_ */ -- cgit v1.2.3 From 077d6dd7508af88509dd0499c5dfbdaa186b4015 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Sun, 10 Jan 2010 23:08:39 +0800 Subject: winsys/drm: Use egl_g3d to build EGL drivers. The new EGL drivers use egl_g3d and respect EGL_DISPLAYS. They are named after the display supported and the DRM name. Signed-off-by: Chia-I Wu --- configure.ac | 2 +- src/gallium/winsys/drm/Makefile.egl_g3d | 64 +++++++++++++++++++++++++ src/gallium/winsys/drm/i965/egl_g3d/Makefile | 14 ++++++ src/gallium/winsys/drm/i965/egl_g3d/dummy.c | 1 + src/gallium/winsys/drm/intel/egl_g3d/Makefile | 14 ++++++ src/gallium/winsys/drm/intel/egl_g3d/dummy.c | 1 + src/gallium/winsys/drm/nouveau/egl_g3d/Makefile | 19 ++++++++ src/gallium/winsys/drm/nouveau/egl_g3d/dummy.c | 1 + src/gallium/winsys/drm/radeon/egl_g3d/Makefile | 14 ++++++ src/gallium/winsys/drm/radeon/egl_g3d/dummy.c | 1 + src/gallium/winsys/drm/vmware/egl_g3d/Makefile | 14 ++++++ src/gallium/winsys/drm/vmware/egl_g3d/dummy.c | 1 + 12 files changed, 145 insertions(+), 1 deletion(-) create mode 100644 src/gallium/winsys/drm/Makefile.egl_g3d create mode 100644 src/gallium/winsys/drm/i965/egl_g3d/Makefile create mode 100644 src/gallium/winsys/drm/i965/egl_g3d/dummy.c create mode 100644 src/gallium/winsys/drm/intel/egl_g3d/Makefile create mode 100644 src/gallium/winsys/drm/intel/egl_g3d/dummy.c create mode 100644 src/gallium/winsys/drm/nouveau/egl_g3d/Makefile create mode 100644 src/gallium/winsys/drm/nouveau/egl_g3d/dummy.c create mode 100644 src/gallium/winsys/drm/radeon/egl_g3d/Makefile create mode 100644 src/gallium/winsys/drm/radeon/egl_g3d/dummy.c create mode 100644 src/gallium/winsys/drm/vmware/egl_g3d/Makefile create mode 100644 src/gallium/winsys/drm/vmware/egl_g3d/dummy.c (limited to 'configure.ac') diff --git a/configure.ac b/configure.ac index 5fea166c67..23bce96ca6 100644 --- a/configure.ac +++ b/configure.ac @@ -1162,7 +1162,7 @@ yes) dri) GALLIUM_STATE_TRACKERS_DIRS="dri" if test "x$enable_egl" = xyes; then - GALLIUM_STATE_TRACKERS_DIRS="$GALLIUM_STATE_TRACKERS_DIRS egl" + GALLIUM_STATE_TRACKERS_DIRS="$GALLIUM_STATE_TRACKERS_DIRS egl egl_g3d" fi # Have only tested st/xorg on 1.6.0 servers PKG_CHECK_MODULES(XORG, [xorg-server >= 1.6.0], diff --git a/src/gallium/winsys/drm/Makefile.egl_g3d b/src/gallium/winsys/drm/Makefile.egl_g3d new file mode 100644 index 0000000000..3ce2725852 --- /dev/null +++ b/src/gallium/winsys/drm/Makefile.egl_g3d @@ -0,0 +1,64 @@ +# src/gallium/winsys/drm/Makefile.egl_g3d + +# The driver Makefile should define +# +# EGL_DRIVER_NAME, the name of the driver +# EGL_DRIVER_SOURCES, the sources of the driver +# EGL_DRIVER_LIBS, extra libraries needed by the driver +# EGL_DRIVER_PIPES, the pipe drivers of the driver +# +# before including this file. + +EGL_DRIVER_OBJECTS = $(EGL_DRIVER_SOURCES:.c=.o) + +common_LIBS = -ldrm -lm -ldl + +x11_ST = $(TOP)/src/gallium/state_trackers/egl_g3d/libeglx11.a +x11_LIBS = $(common_LIBS) -lX11 -lXext -lXfixes + +kms_ST = $(TOP)/src/gallium/state_trackers/egl_g3d/libeglkms.a +kms_LIBS = $(common_LIBS) + +##### RULES ##### + +.c.o: + $(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@ + + +##### TARGETS ##### + +EGL_DISPLAY_DRIVERS = $(foreach dpy, $(EGL_DISPLAYS), egl_$(dpy)_$(EGL_DRIVER_NAME).so) + +LIB_GALLIUM_DIR = $(TOP)/$(LIB_DIR)/gallium +EGL_DISPLAY_LIBS = $(foreach drv, $(EGL_DISPLAY_DRIVERS), $(LIB_GALLIUM_DIR)/$(drv)) + +default: $(EGL_DISPLAY_LIBS) + +$(EGL_DISPLAY_LIBS): $(LIB_GALLIUM_DIR)/%.so: %.so + @mkdir -p $(LIB_GALLIUM_DIR) + $(INSTALL) $^ $(LIB_GALLIUM_DIR) + +define mklib-egl +$(MKLIB) -noprefix -o $@ $(EGL_DRIVER_OBJECTS) \ + -Wl,--whole-archive $($(1)_ST) -Wl,--no-whole-archive \ + $(EGL_DRIVER_PIPES) $(GALLIUM_AUXILIARIES) $($(1)_LIBS) $(EGL_DRIVER_LIBS) +endef + +egl_x11_$(EGL_DRIVER_NAME).so: $(EGL_DRIVER_OBJECTS) $(x11_ST) $(EGL_DRIVER_PIPES) $(GALLIUM_AUXILIARIES) Makefile + $(call mklib-egl,x11) + +egl_kms_$(EGL_DRIVER_NAME).so: $(EGL_DRIVER_OBJECTS) $(kms_ST) $(EGL_DRIVER_PIPES) $(GALLIUM_AUXILIARIES) Makefile + $(call mklib-egl,kms) + +clean: + -rm -f $(EGL_DRIVER_OBJECTS) + -rm -f $(EGL_DISPLAY_DRIVERS) + +install: $(EGL_DISPLAY_LIBS) + @$(INSTALL) -d $(DESTDIR)$(DRI_DRIVER_INSTALL_DIR) + @echo "Install $(EGL_DISPLAY_DRIVERS)" + @for lib in "$(EGL_DISPLAY_LIBS)"; do \ + $(MINSTALL) -m 755 "$$lib" $(DESTDIR)$(DRI_DRIVER_INSTALL_DIR); \ + done + +depend: diff --git a/src/gallium/winsys/drm/i965/egl_g3d/Makefile b/src/gallium/winsys/drm/i965/egl_g3d/Makefile new file mode 100644 index 0000000000..dd2efe2485 --- /dev/null +++ b/src/gallium/winsys/drm/i965/egl_g3d/Makefile @@ -0,0 +1,14 @@ +TOP = ../../../../../.. +include $(TOP)/configs/current + +EGL_DRIVER_NAME = i965 +EGL_DRIVER_SOURCES = dummy.c +EGL_DRIVER_LIBS = -ldrm_intel + +EGL_DRIVER_PIPES = \ + $(TOP)/src/gallium/winsys/drm/i965/gem/libi965drm.a \ + $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \ + $(TOP)/src/gallium/drivers/trace/libtrace.a \ + $(TOP)/src/gallium/drivers/i965/libi965.a + +include ../../Makefile.egl_g3d diff --git a/src/gallium/winsys/drm/i965/egl_g3d/dummy.c b/src/gallium/winsys/drm/i965/egl_g3d/dummy.c new file mode 100644 index 0000000000..4a1bc28b0b --- /dev/null +++ b/src/gallium/winsys/drm/i965/egl_g3d/dummy.c @@ -0,0 +1 @@ +/* mklib expects at least one object file */ diff --git a/src/gallium/winsys/drm/intel/egl_g3d/Makefile b/src/gallium/winsys/drm/intel/egl_g3d/Makefile new file mode 100644 index 0000000000..cdbb680773 --- /dev/null +++ b/src/gallium/winsys/drm/intel/egl_g3d/Makefile @@ -0,0 +1,14 @@ +TOP = ../../../../../.. +include $(TOP)/configs/current + +EGL_DRIVER_NAME = i915 +EGL_DRIVER_SOURCES = dummy.c +EGL_DRIVER_LIBS = -ldrm_intel + +EGL_DRIVER_PIPES = \ + $(TOP)/src/gallium/winsys/drm/intel/gem/libinteldrm.a \ + $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \ + $(TOP)/src/gallium/drivers/trace/libtrace.a \ + $(TOP)/src/gallium/drivers/i915/libi915.a + +include ../../Makefile.egl_g3d diff --git a/src/gallium/winsys/drm/intel/egl_g3d/dummy.c b/src/gallium/winsys/drm/intel/egl_g3d/dummy.c new file mode 100644 index 0000000000..4a1bc28b0b --- /dev/null +++ b/src/gallium/winsys/drm/intel/egl_g3d/dummy.c @@ -0,0 +1 @@ +/* mklib expects at least one object file */ diff --git a/src/gallium/winsys/drm/nouveau/egl_g3d/Makefile b/src/gallium/winsys/drm/nouveau/egl_g3d/Makefile new file mode 100644 index 0000000000..865a5d56a9 --- /dev/null +++ b/src/gallium/winsys/drm/nouveau/egl_g3d/Makefile @@ -0,0 +1,19 @@ +TOP = ../../../../../.. +include $(TOP)/configs/current + +EGL_DRIVER_NAME = nouveau +EGL_DRIVER_SOURCES = dummy.c +EGL_DRIVER_LIBS = -ldrm_nouveau + +EGL_DRIVER_PIPES = \ + $(TOP)/src/gallium/winsys/drm/nouveau/drm/libnouveaudrm.a \ + $(TOP)/src/gallium/drivers/nv04/libnv04.a \ + $(TOP)/src/gallium/drivers/nv10/libnv10.a \ + $(TOP)/src/gallium/drivers/nv20/libnv20.a \ + $(TOP)/src/gallium/drivers/nv30/libnv30.a \ + $(TOP)/src/gallium/drivers/nv40/libnv40.a \ + $(TOP)/src/gallium/drivers/nv50/libnv50.a \ + $(TOP)/src/gallium/drivers/nouveau/libnouveau.a \ + $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a + +include ../../Makefile.egl_g3d diff --git a/src/gallium/winsys/drm/nouveau/egl_g3d/dummy.c b/src/gallium/winsys/drm/nouveau/egl_g3d/dummy.c new file mode 100644 index 0000000000..4a1bc28b0b --- /dev/null +++ b/src/gallium/winsys/drm/nouveau/egl_g3d/dummy.c @@ -0,0 +1 @@ +/* mklib expects at least one object file */ diff --git a/src/gallium/winsys/drm/radeon/egl_g3d/Makefile b/src/gallium/winsys/drm/radeon/egl_g3d/Makefile new file mode 100644 index 0000000000..9027a5ff46 --- /dev/null +++ b/src/gallium/winsys/drm/radeon/egl_g3d/Makefile @@ -0,0 +1,14 @@ +TOP = ../../../../../.. +include $(TOP)/configs/current + +EGL_DRIVER_NAME = r300 +EGL_DRIVER_SOURCES = dummy.c +EGL_DRIVER_LIBS = -ldrm_radeon + +EGL_DRIVER_PIPES = \ + $(TOP)/src/gallium/winsys/drm/radeon/core/libradeonwinsys.a \ + $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \ + $(TOP)/src/gallium/drivers/trace/libtrace.a \ + $(TOP)/src/gallium/drivers/r300/libr300.a + +include ../../Makefile.egl_g3d diff --git a/src/gallium/winsys/drm/radeon/egl_g3d/dummy.c b/src/gallium/winsys/drm/radeon/egl_g3d/dummy.c new file mode 100644 index 0000000000..4a1bc28b0b --- /dev/null +++ b/src/gallium/winsys/drm/radeon/egl_g3d/dummy.c @@ -0,0 +1 @@ +/* mklib expects at least one object file */ diff --git a/src/gallium/winsys/drm/vmware/egl_g3d/Makefile b/src/gallium/winsys/drm/vmware/egl_g3d/Makefile new file mode 100644 index 0000000000..3cf79924e0 --- /dev/null +++ b/src/gallium/winsys/drm/vmware/egl_g3d/Makefile @@ -0,0 +1,14 @@ +TOP = ../../../../../.. +include $(TOP)/configs/current + +EGL_DRIVER_NAME = vmwgfx +EGL_DRIVER_SOURCES = dummy.c +EGL_DRIVER_LIBS = + +EGL_DRIVER_PIPES = \ + $(TOP)/src/gallium/winsys/drm/vmware/core/libsvgadrm.a \ + $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \ + $(TOP)/src/gallium/drivers/trace/libtrace.a \ + $(TOP)/src/gallium/drivers/svga/libsvga.a + +include ../../Makefile.egl_g3d diff --git a/src/gallium/winsys/drm/vmware/egl_g3d/dummy.c b/src/gallium/winsys/drm/vmware/egl_g3d/dummy.c new file mode 100644 index 0000000000..4a1bc28b0b --- /dev/null +++ b/src/gallium/winsys/drm/vmware/egl_g3d/dummy.c @@ -0,0 +1 @@ +/* mklib expects at least one object file */ -- cgit v1.2.3