Since binutils refuses to link objects that are compiled with different -march flags, pixman-mmx.c is compiled with varying -march flags into separate shared objects, which are dlopened at runtime.
AC_LINK_IFELSE is used to confirm that linking works, since for example an object built with -march=loongson2e cannot be linked with libc.so built with -march=loongson2f. I expect binary distributions' libcs to be built with generic flags, and in such case all three loongson march values can be built. If libc is built with a particular -march=loongson* flag, the linking test will fail and only the -march value matching the C library will be built. If only one -march value is built, avoid dlopen and simply build the code into libpixman-1 like before. Unfortunately, two internal pixman symbols are needed by pixman-mmx.c: _pixman_image_get_solid _pixman_implementation_create They are annotated with PIXMAN_EXPORT, but only in the dlopen case. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=51451 --- An alternative would be to move the code that creates the implementation record from pixman-mmx.c to pixman-mips.c and use dlsym to get the function pointers for the fast paths table. This seemed like a lot more work for the benefit of not exposing two private symbols on a platform almost no one cares about, and only on binary distributions at that. configure.ac | 135 +++++++++++++++++++++++++++++++++++------ pixman/Makefile.am | 60 ++++++++++++++++-- pixman/pixman-image.c | 3 + pixman/pixman-implementation.c | 3 + pixman/pixman-mips.c | 60 +++++++++++++++++- pixman/pixman-mmx.c | 3 + pixman/pixman-private.h | 6 ++ 7 files changed, 244 insertions(+), 26 deletions(-) diff --git a/configure.ac b/configure.ac index 515e312..bf10344 100644 --- a/configure.ac +++ b/configure.ac @@ -270,21 +270,26 @@ PIXMAN_CHECK_CFLAG([-xldscope=hidden], [dnl dnl =========================================================================== dnl Check for Loongson Multimedia Instructions -if test "x$LS_CFLAGS" = "x" ; then - LS_CFLAGS="-march=loongson2f" +if test "x$LS2E_CFLAGS" = "x" ; then + LS2E_CFLAGS="-march=loongson2e" +fi +if test "x$LS2F_CFLAGS" = "x" ; then + LS2F_CFLAGS="-march=loongson2f" +fi +if test "x$LS3A_CFLAGS" = "x" ; then + LS3A_CFLAGS="-march=loongson3a" fi -have_loongson_mmi=no AC_MSG_CHECKING(whether to use Loongson MMI assembler) -xserver_save_CFLAGS=$CFLAGS -CFLAGS=" $LS_CFLAGS $CFLAGS -I$srcdir" -AC_COMPILE_IFELSE([AC_LANG_SOURCE([[ +save_CFLAGS=$CFLAGS +CFLAGS=" $CFLAGS $LS2E_CFLAGS -I$srcdir" +AC_LINK_IFELSE([AC_LANG_SOURCE([[ #ifndef __mips_loongson_vector_rev #error "Loongson Multimedia Instructions are only available on Loongson" #endif #if defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 4)) -#error "Need GCC >= 4.4 for Loongson MMI compilation" +#error "Need GCC >= 4.4 for Loongson 2e/f MMI compilation" #endif #include "pixman/loongson-mmintrin.h" int main () { @@ -295,30 +300,120 @@ int main () { int b = 4; __m64 c = _mm_srli_pi16 (a.v, b); return 0; -}]])], have_loongson_mmi=yes) -CFLAGS=$xserver_save_CFLAGS +}]])], have_loongson2e_mmi=yes) +CFLAGS=$save_CFLAGS + +save_CFLAGS=$CFLAGS +CFLAGS=" $CFLAGS $LS2F_CFLAGS -I$srcdir" +AC_LINK_IFELSE([AC_LANG_SOURCE([[ +#ifndef __mips_loongson_vector_rev +#error "Loongson Multimedia Instructions are only available on Loongson" +#endif +#if defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 4)) +#error "Need GCC >= 4.4 for Loongson 2e/f MMI compilation" +#endif +#include "pixman/loongson-mmintrin.h" +int main () { + union { + __m64 v; + char c[8]; + } a = { .c = {1, 2, 3, 4, 5, 6, 7, 8} }; + int b = 4; + __m64 c = _mm_srli_pi16 (a.v, b); + return 0; +}]])], have_loongson2f_mmi=yes) +CFLAGS=$save_CFLAGS + +save_CFLAGS=$CFLAGS +CFLAGS=" $CFLAGS $LS3A_CFLAGS -I$srcdir" +AC_LINK_IFELSE([AC_LANG_SOURCE([[ +#ifndef __mips_loongson_vector_rev +#error "Loongson Multimedia Instructions are only available on Loongson" +#endif +#if defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6)) +#error "Need GCC >= 4.6 for Loongson 3A MMI compilation" +#endif +#include "pixman/loongson-mmintrin.h" +int main () { + union { + __m64 v; + char c[8]; + } a = { .c = {1, 2, 3, 4, 5, 6, 7, 8} }; + int b = 4; + __m64 c = _mm_srli_pi16 (a.v, b); + return 0; +}]])], have_loongson3a_mmi=yes) +CFLAGS=$save_CFLAGS AC_ARG_ENABLE(loongson-mmi, [AC_HELP_STRING([--disable-loongson-mmi], [disable Loongson MMI fast paths])], [enable_loongson_mmi=$enableval], [enable_loongson_mmi=auto]) - -if test $enable_loongson_mmi = no ; then - have_loongson_mmi=disabled -fi - -if test $have_loongson_mmi = yes ; then +AC_ARG_ENABLE(loongson2e-mmi, + [AC_HELP_STRING([--disable-loongson2e-mmi], + [do not build Loongson MMI fast paths for 2e])], + [enable_loongson2e_mmi=$enableval], [enable_loongson2e_mmi=auto]) +AC_ARG_ENABLE(loongson2f-mmi, + [AC_HELP_STRING([--disable-loongson2f-mmi], + [do not build Loongson MMI fast paths for 2f])], + [enable_loongson2f_mmi=$enableval], [enable_loongson2f_mmi=auto]) +AC_ARG_ENABLE(loongson3a-mmi, + [AC_HELP_STRING([--disable-loongson3a-mmi], + [do not build Loongson MMI fast paths for 3a])], + [enable_loongson3a_mmi=$enableval], [enable_loongson3a_mmi=auto]) + +test "x$enable_loongson2e_mmi" = xno && have_loongson2e_mmi=disabled +test "x$enable_loongson2f_mmi" = xno && have_loongson2f_mmi=disabled +test "x$enable_loongson3a_mmi" = xno && have_loongson3a_mmi=disabled + +if test "x$have_loongson2e_mmi" = xyes -o \ + "x$have_loongson2f_mmi" = xyes -o \ + "x$have_loongson3a_mmi" = xyes ; then + loongson_msg="yes:" AC_DEFINE(USE_LOONGSON_MMI, 1, [use Loongson Multimedia Instructions]) + if test "x$have_loongson2e_mmi" = xyes ; then + loongson_msg="$loongson_msg 2e" + AC_DEFINE(HAVE_LOONGSON2E_MMI, 1, [use Loongson 2e Multimedia Instructions]) + fi + if test "x$have_loongson2f_mmi" = xyes ; then + loongson_msg="$loongson_msg 2f" + AC_DEFINE(HAVE_LOONGSON2F_MMI, 1, [use Loongson 2f Multimedia Instructions]) + fi + if test "x$have_loongson3a_mmi" = xyes ; then + loongson_msg="$loongson_msg 3a" + AC_DEFINE(HAVE_LOONGSON3A_MMI, 1, [use Loongson 3a Multimedia Instructions]) + fi else - LS_CFLAGS= + loongson_msg="no" fi -AC_MSG_RESULT($have_loongson_mmi) -if test $enable_loongson_mmi = yes && test $have_loongson_mmi = no ; then - AC_MSG_ERROR([Loongson MMI not detected]) +AC_MSG_RESULT($loongson_msg) +case "x$have_loongson2e_mmi$have_loongson2f_mmi$have_loongson3a_mmi" in + x*yes*yes*) + dnl If multiple Loongson architectures are selected, we have to + dnl dlopen() them instead of building them into pixman directly. + AC_SEARCH_LIBS([dlopen], [dl], + [have_dlopen_loongson_mmi=yes], + [AC_MSG_ERROR([unable to find the dlopen() function])] + ) + ;; +esac + +if test "x$have_dlopen_loongson_mmi" = xyes ; then + AC_DEFINE(DLOPEN_LOONGSON_MMI, 1, [use dlopen() to load Loongson MMI]) + AC_SUBST(DLOPEN_LIBS, "-ldl") fi -AM_CONDITIONAL(USE_LOONGSON_MMI, test $have_loongson_mmi = yes) +AC_SUBST([LS2E_CFLAGS]) +AC_SUBST([LS2F_CFLAGS]) +AC_SUBST([LS3A_CFLAGS]) +AM_CONDITIONAL(DLOPEN_LOONGSON_MMI, test "x$have_dlopen_loongson_mmi" = xyes) +AM_CONDITIONAL(USE_LOONGSON_MMI, test "x$have_loongson2e_mmi" = xyes -o \ + "x$have_loongson2f_mmi" = xyes -o \ + "x$have_loongson3a_mmi" = xyes) +AM_CONDITIONAL(HAVE_LOONGSON2E, test "x$have_loongson2e_mmi" = xyes) +AM_CONDITIONAL(HAVE_LOONGSON2F, test "x$have_loongson2f_mmi" = xyes) +AM_CONDITIONAL(HAVE_LOONGSON3A, test "x$have_loongson3a_mmi" = xyes) dnl =========================================================================== dnl Check for MMX diff --git a/pixman/Makefile.am b/pixman/Makefile.am index beebdd0..55ad460 100644 --- a/pixman/Makefile.am +++ b/pixman/Makefile.am @@ -114,11 +114,61 @@ endif # loongson code if USE_LOONGSON_MMI -noinst_LTLIBRARIES += libpixman-loongson-mmi.la -libpixman_loongson_mmi_la_SOURCES = pixman-mmx.c loongson-mmintrin.h -libpixman_loongson_mmi_la_CFLAGS = $(LS_CFLAGS) -libpixman_1_la_LDFLAGS += $(LS_LDFLAGS) -libpixman_1_la_LIBADD += libpixman-loongson-mmi.la +if DLOPEN_LOONGSON_MMI +libpixman_1_la_LIBADD += $(DLOPEN_LIBS) +endif + +if HAVE_LOONGSON2E +if DLOPEN_LOONGSON_MMI +lib_LTLIBRARIES += libpixman-1-loongson2e-mmi.la +libpixman_1_loongson2e_mmi_la_LDFLAGS = -avoid-version -module +libpixman_1_loongson2e_mmi_la_CPPFLAGS = -DUSE_LOONGSON2E_MMI +else +noinst_LTLIBRARIES += libpixman-1-loongson2e-mmi.la +libpixman_1_loongson2e_mmi_la_LDFLAGS = -avoid-version +libpixman_1_la_LIBADD += libpixman-1-loongson2e-mmi.la +endif +libpixman_1_loongson2e_mmi_la_SOURCES = pixman-mmx.c loongson-mmintrin.h + +LS2E_LO = libpixman_1_loongson2e_mmi_la-pixman-mmx.lo +$(LS2E_LO): pixman-mmx.c loongson-mmintrin.h + @$(MAKE) libpixman_1_loongson2e_mmi_la-pixman-mmx.lo CFLAGS="$(CFLAGS) $(LS2E_CFLAGS)" LS2E_LO=dummy-libpixman_1_loongson2e_mmi_la-pixman-mmx.lo +endif + +if HAVE_LOONGSON2F +if DLOPEN_LOONGSON_MMI +lib_LTLIBRARIES += libpixman-1-loongson2f-mmi.la +libpixman_1_loongson2f_mmi_la_LDFLAGS = -avoid-version -module +libpixman_1_loongson2f_mmi_la_CPPFLAGS = -DUSE_LOONGSON2F_MMI +else +noinst_LTLIBRARIES += libpixman-1-loongson2f-mmi.la +libpixman_1_loongson2f_mmi_la_LDFLAGS = -avoid-version +libpixman_1_la_LIBADD += libpixman-1-loongson2f-mmi.la +endif +libpixman_1_loongson2f_mmi_la_SOURCES = pixman-mmx.c loongson-mmintrin.h + +LS2F_LO = libpixman_1_loongson2f_mmi_la-pixman-mmx.lo +$(LS2F_LO): pixman-mmx.c loongson-mmintrin.h + @$(MAKE) libpixman_1_loongson2f_mmi_la-pixman-mmx.lo CFLAGS="$(CFLAGS) $(LS2F_CFLAGS)" LS2F_LO=dummy-libpixman_1_loongson2f_mmi_la-pixman-mmx.lo +endif + +if HAVE_LOONGSON3A +if DLOPEN_LOONGSON_MMI +lib_LTLIBRARIES += libpixman-1-loongson3a-mmi.la +libpixman_1_loongson3a_mmi_la_LDFLAGS = -avoid-version -module +libpixman_1_loongson3a_mmi_la_CPPFLAGS = -DUSE_LOONGSON3A_MMI +else +noinst_LTLIBRARIES += libpixman-1-loongson3a-mmi.la +libpixman_1_loongson3a_mmi_la_LDFLAGS = -avoid-version +libpixman_1_la_LIBADD += libpixman-1-loongson3a-mmi.la +endif +libpixman_1_loongson3a_mmi_la_SOURCES = pixman-mmx.c loongson-mmintrin.h + +LS3A_LO = libpixman_1_loongson3a_mmi_la-pixman-mmx.lo +$(LS3A_LO): pixman-mmx.c loongson-mmintrin.h + @$(MAKE) libpixman_1_loongson3a_mmi_la-pixman-mmx.lo CFLAGS="$(CFLAGS) $(LS3A_CFLAGS)" LS3A_LO=dummy-libpixman_1_loongson3a_mmi_la-pixman-mmx.lo +endif + endif .c.s : $(libpixmaninclude_HEADERS) diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c index 65041b4..3db070d 100644 --- a/pixman/pixman-image.c +++ b/pixman/pixman-image.c @@ -891,6 +891,9 @@ pixman_image_get_format (pixman_image_t *image) return PIXMAN_null; } +#ifdef DLOPEN_LOONGSON_MMI +PIXMAN_EXPORT +#endif uint32_t _pixman_image_get_solid (pixman_implementation_t *imp, pixman_image_t * image, diff --git a/pixman/pixman-implementation.c b/pixman/pixman-implementation.c index ec467a6..171488b 100644 --- a/pixman/pixman-implementation.c +++ b/pixman/pixman-implementation.c @@ -27,6 +27,9 @@ #include <stdlib.h> #include "pixman-private.h" +#ifdef DLOPEN_LOONGSON_MMI +PIXMAN_EXPORT +#endif pixman_implementation_t * _pixman_implementation_create (pixman_implementation_t *fallback, const pixman_fast_path_t *fast_paths) diff --git a/pixman/pixman-mips.c b/pixman/pixman-mips.c index 3048813..77bef5c 100644 --- a/pixman/pixman-mips.c +++ b/pixman/pixman-mips.c @@ -27,6 +27,10 @@ #if defined(USE_MIPS_DSPR2) || defined(USE_LOONGSON_MMI) +#ifdef DLOPEN_LOONGSON_MMI +#include <dlfcn.h> +#endif + #include <string.h> #include <stdlib.h> @@ -69,10 +73,64 @@ pixman_implementation_t * _pixman_mips_get_implementations (pixman_implementation_t *imp) { #ifdef USE_LOONGSON_MMI + void *mmi_handle = NULL; +#ifdef DLOPEN_LOONGSON_MMI + pixman_implementation_t *(*_pixman_implementation_create_mmx) (pixman_implementation_t *); +#endif /* I really don't know if some Loongson CPUs don't have MMI. */ - if (!_pixman_disabled ("loongson-mmi") && have_feature ("Loongson")) +#ifdef HAVE_LOONGSON2E_MMI + if (!mmi_handle && !_pixman_disabled ("loongson-mmi") + && have_feature ("Loongson") && have_feature ("-2e")) + { +#ifdef DLOPEN_LOONGSON_MMI + mmi_handle = dlopen("libpixman-1-loongson2e-mmi.so", RTLD_LAZY | RTLD_LOCAL); +#else + imp = _pixman_implementation_create_mmx (imp); +#endif + } +#endif +#ifdef HAVE_LOONGSON2F_MMI + if (!mmi_handle && !_pixman_disabled ("loongson-mmi") + && have_feature ("Loongson") && have_feature ("-2f")) + { +#ifdef DLOPEN_LOONGSON_MMI + mmi_handle = dlopen("libpixman-1-loongson2f-mmi.so", RTLD_LAZY | RTLD_LOCAL); +#else + imp = _pixman_implementation_create_mmx (imp); +#endif + } +#endif +#ifdef HAVE_LOONGSON3A_MMI + if (!mmi_handle && !_pixman_disabled ("loongson-mmi") + && have_feature ("Loongson-3A")) + { +#ifdef DLOPEN_LOONGSON_MMI + mmi_handle = dlopen("libpixman-1-loongson3a-mmi.so", RTLD_LAZY | RTLD_LOCAL); +#else imp = _pixman_implementation_create_mmx (imp); #endif + } +#endif + +#ifdef DLOPEN_LOONGSON_MMI + if (mmi_handle) + { + _pixman_implementation_create_mmx = dlsym(mmi_handle, "_pixman_implementation_create_mmx"); + if (_pixman_implementation_create_mmx) + { + imp = _pixman_implementation_create_mmx (imp); + } + else + { + puts(dlerror()); + } + } + else + { + puts(dlerror()); + } +#endif +#endif #ifdef USE_MIPS_DSPR2 if (!_pixman_disabled ("mips-dspr2")) diff --git a/pixman/pixman-mmx.c b/pixman/pixman-mmx.c index ca2ac83..280e9c4 100644 --- a/pixman/pixman-mmx.c +++ b/pixman/pixman-mmx.c @@ -4044,6 +4044,9 @@ static const pixman_fast_path_t mmx_fast_paths[] = { PIXMAN_OP_NONE }, }; +#ifdef DLOPEN_LOONGSON_MMI +PIXMAN_EXPORT +#endif pixman_implementation_t * _pixman_implementation_create_mmx (pixman_implementation_t *fallback) { diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h index e5ab873..af8e8d1 100644 --- a/pixman/pixman-private.h +++ b/pixman/pixman-private.h @@ -488,11 +488,17 @@ struct pixman_implementation_t pixman_combine_float_func_t combine_float_ca[PIXMAN_N_OPERATORS]; }; +#ifdef DLOPEN_LOONGSON_MMI +PIXMAN_EXPORT +#endif uint32_t _pixman_image_get_solid (pixman_implementation_t *imp, pixman_image_t * image, pixman_format_code_t format); +#ifdef DLOPEN_LOONGSON_MMI +PIXMAN_EXPORT +#endif pixman_implementation_t * _pixman_implementation_create (pixman_implementation_t *fallback, const pixman_fast_path_t *fast_paths); -- 1.8.1.1 _______________________________________________ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman