diff options
author | marha <marha@users.sourceforge.net> | 2012-04-30 10:36:15 +0200 |
---|---|---|
committer | marha <marha@users.sourceforge.net> | 2012-04-30 10:36:15 +0200 |
commit | 762b7fde3d57d3a151f98535fd31516b7e823bc0 (patch) | |
tree | 11c32921b96808f2aab11a86863534fb28b274f6 | |
parent | b68922d51f52ca6ab9daa0105ef5c57f35bfbdcf (diff) | |
download | vcxsrv-762b7fde3d57d3a151f98535fd31516b7e823bc0.tar.gz vcxsrv-762b7fde3d57d3a151f98535fd31516b7e823bc0.tar.bz2 vcxsrv-762b7fde3d57d3a151f98535fd31516b7e823bc0.zip |
fontconfig libX11 libfontenc mesa pixman xserver git update 30 Apr 2012
68 files changed, 2119 insertions, 1020 deletions
diff --git a/fontconfig/configure.in b/fontconfig/configure.in index 62bc25e4a..b77c52a29 100644 --- a/fontconfig/configure.in +++ b/fontconfig/configure.in @@ -123,7 +123,7 @@ dnl ========================================================================== # Checks for header files. AC_HEADER_DIRENT AC_HEADER_STDC -AC_CHECK_HEADERS([fcntl.h regex.h stdlib.h string.h unistd.h]) +AC_CHECK_HEADERS([fcntl.h regex.h stdlib.h string.h unistd.h sys/vfs.h sys/statfs.h sys/param.h sys/mount.h]) # Checks for typedefs, structures, and compiler characteristics. AC_C_CONST @@ -133,9 +133,29 @@ AC_TYPE_PID_T # Checks for library functions. AC_FUNC_VPRINTF AC_FUNC_MMAP -AC_CHECK_FUNCS([geteuid getuid link memmove memset mkstemp strchr strrchr strtol getopt getopt_long sysconf ftruncate chsize rand random lrand48 random_r rand_r regcomp regerror regexec regfree posix_fadvise]) +AC_CHECK_FUNCS([geteuid getuid link memmove memset mkstemp strchr strrchr strtol getopt getopt_long sysconf ftruncate chsize rand random lrand48 random_r rand_r regcomp regerror regexec regfree posix_fadvise fstatvfs fstatfs]) # +if test "x$ac_cv_func_fstatvfs" = "xyes"; then + AC_CHECK_MEMBERS([struct statvfs.f_basetype, struct statvfs.f_fstypename],,, + [#include <sys/statvfs.h>]) +fi +if test "x$ac_cv_func_fstatfs" = "xyes"; then + AC_CHECK_MEMBERS([struct statfs.f_flags, struct statfs.f_fstypename],,, [ +#ifdef HAVE_SYS_VFS_H +#include <sys/vfs.h> +#endif +#ifdef HAVE_SYS_STATFS_H +#include <sys/statfs.h> +#endif +#ifdef HAVE_SYS_PARAM_H +#include <sys/param.h> +#endif +#ifdef HAVE_SYS_MOUNT_H +#include <sys/mount.h> +#endif]) +fi +# # regex # if test "x$ac_cv_func_regcomp" = "xyes" -a "x$ac_cv_func_regerror" = "xyes" -a "x$ac_cv_func_regexec" = "xyes" -a "x$ac_cv_func_regfree"; then @@ -145,6 +165,10 @@ fi # # Checks for iconv # +AC_ARG_ENABLE(iconv, + [AC_HELP_STRING([--enable-iconv], + [Use iconv to support non-Unicode SFNT name])], + ,enable_iconv=no) AC_ARG_WITH(libiconv, [AC_HELP_STRING([--with-libiconv=DIR], [Use libiconv in DIR])], @@ -186,38 +210,39 @@ if test "x$libiconv_cflags" != "x"; then fi use_iconv=0 -AC_MSG_CHECKING([for a usable iconv]) -if test "x$libiconv_cflags" != "x" -o "x$libiconv_libs" != "x"; then - iconvsaved_CFLAGS="$CFLAGS" - iconvsaved_LIBS="$LIBS" - CFLAGS="$CFLAGS $libiconv_cflags" - LIBS="$LIBS $libiconv_libs" - - AC_TRY_LINK([#include <iconv.h>], - [iconv_open ("from", "to");], - [iconv_type="libiconv" - use_iconv=1], - [use_iconv=0]) - - CFLAGS="$iconvsaved_CFLAGS" - LIBS="$iconvsaved_LIBS" - ICONV_CFLAGS="$libiconv_cflags" - ICONV_LIBS="$libiconv_libs" -fi -if test "x$use_iconv" = "x0"; then - AC_TRY_LINK([#include <iconv.h>], - [iconv_open ("from", "to");], - [iconv_type="libc" - use_iconv=1], - [iconv_type="not found" - use_iconv=0]) -fi +if test "x$enable_iconv" != "xno"; then + AC_MSG_CHECKING([for a usable iconv]) + if test "x$libiconv_cflags" != "x" -o "x$libiconv_libs" != "x"; then + iconvsaved_CFLAGS="$CFLAGS" + iconvsaved_LIBS="$LIBS" + CFLAGS="$CFLAGS $libiconv_cflags" + LIBS="$LIBS $libiconv_libs" + + AC_TRY_LINK([#include <iconv.h>], + [iconv_open ("from", "to");], + [iconv_type="libiconv" + use_iconv=1], + [use_iconv=0]) + + CFLAGS="$iconvsaved_CFLAGS" + LIBS="$iconvsaved_LIBS" + ICONV_CFLAGS="$libiconv_cflags" + ICONV_LIBS="$libiconv_libs" + fi + if test "x$use_iconv" = "x0"; then + AC_TRY_LINK([#include <iconv.h>], + [iconv_open ("from", "to");], + [iconv_type="libc" + use_iconv=1], + [iconv_type="not found" + use_iconv=0]) + fi -AC_MSG_RESULT([$iconv_type]) -AC_SUBST(ICONV_CFLAGS) -AC_SUBST(ICONV_LIBS) + AC_MSG_RESULT([$iconv_type]) + AC_SUBST(ICONV_CFLAGS) + AC_SUBST(ICONV_LIBS) +fi AC_DEFINE_UNQUOTED(USE_ICONV,$use_iconv,[Use iconv.]) - # # Checks for FreeType # diff --git a/fontconfig/doc/fontconfig-devel.sgml b/fontconfig/doc/fontconfig-devel.sgml index 87339511c..ab390925d 100644 --- a/fontconfig/doc/fontconfig-devel.sgml +++ b/fontconfig/doc/fontconfig-devel.sgml @@ -190,6 +190,9 @@ convenience for the application's rendering mechanism. the font embolden FC_EMBOLDEN Bool Rasterizer should synthetically embolden the font + namelang FC_NAMELANG String Language name to be used for the + default value of familylang, + stylelang and fullnamelang </programlisting> </sect2> </sect1> diff --git a/fontconfig/doc/fontconfig-user.sgml b/fontconfig/doc/fontconfig-user.sgml index 14fdc79aa..86f2b3299 100644 --- a/fontconfig/doc/fontconfig-user.sgml +++ b/fontconfig/doc/fontconfig-user.sgml @@ -224,7 +224,7 @@ values as the font name is read. </para> </refsect2> </refsect1> -<refsect1><title>Debugging Applications</title> +<refsect1 id="debug"><title>Debugging Applications</title> <para> To help diagnose font and applications problems, fontconfig is built with a large amount of internal debugging left enabled. It is controlled by means @@ -692,6 +692,24 @@ is the conventional repository of font information that isn't found in the per-directory caches. This file is automatically maintained by fontconfig. </para> </refsect1> +<refsect1><title>Environment variables</title> + <para> +<emphasis>FONTCONFIG_FILE</emphasis> +is used to override the default configuration file. + </para> + <para> +<emphasis>FONTCONFIG_PATH</emphasis> +is used to override the default configuration directory. + </para> + <para> +<emphasis>FC_DEBUG</emphasis> +is used to output the detailed debugging messages. see <link linkend="debug">Debugging Applications</link> section for more details. + </para> + <para> +<emphasis>FONTCONFIG_USE_MMAP</emphasis> +is used to control the use of mmap(2) for the cache files if available. this take a boolean value. fontconfig will checks if the cache files are stored on the filesystem that is safe to use mmap(2). explicitly setting this environment variable will causes skipping this check and enforce to use or not use mmap(2) anyway. + </para> +</refsect1> <refsect1><title>See Also</title> <para> fc-cat(1), fc-cache(1), fc-list(1), fc-match(1), fc-query(1) diff --git a/fontconfig/fontconfig/fontconfig.h b/fontconfig/fontconfig/fontconfig.h index e4d57088d..2671da78d 100644 --- a/fontconfig/fontconfig/fontconfig.h +++ b/fontconfig/fontconfig/fontconfig.h @@ -111,6 +111,7 @@ typedef int FcBool; #define FC_EMBEDDED_BITMAP "embeddedbitmap" /* Bool - true to enable embedded bitmaps */ #define FC_DECORATIVE "decorative" /* Bool - true if style is a decorative variant */ #define FC_LCD_FILTER "lcdfilter" /* Int */ +#define FC_NAMELANG "namelang" /* String RFC 3866 langs */ #define FC_CACHE_SUFFIX ".cache-" FC_CACHE_VERSION #define FC_DIR_CACHE_FILE "fonts.cache-" FC_CACHE_VERSION diff --git a/fontconfig/src/fccache.c b/fontconfig/src/fccache.c index fbe2d5c01..882dd3eb5 100644 --- a/fontconfig/src/fccache.c +++ b/fontconfig/src/fccache.c @@ -37,6 +37,21 @@ # include <unistd.h> # include <sys/mman.h> #endif +#ifdef HAVE_SYS_VFS_H +#include <sys/vfs.h> +#endif +#ifdef HAVE_SYS_STATFS_H +#include <sys/statfs.h> +#endif +#ifdef HAVE_SYS_PARAM_H +#include <sys/param.h> +#endif +#ifdef HAVE_SYS_MOUNT_H +#include <sys/mount.h> +#endif +#ifdef HAVE_MNTENT_H +#include <mntent.h> +#endif #ifndef O_BINARY #define O_BINARY 0 @@ -144,6 +159,64 @@ FcStat (const FcChar8 *file, struct stat *statb) #endif +static FcBool +FcCacheIsMmapSafe (int fd) +{ + FcBool retval = FcTrue; + static FcBool is_initialized = FcFalse; + static FcBool is_env_available = FcFalse; + static FcBool use_mmap = FcFalse; + + if (!is_initialized) + { + const char *env; + + env = getenv ("FONTCONFIG_USE_MMAP"); + if (env) + { + if (FcNameBool ((const FcChar8 *)env, &use_mmap)) + is_env_available = FcTrue; + } + is_initialized = FcTrue; + } + if (is_env_available) + return use_mmap; +#if defined(HAVE_FSTATVFS) && (defined(HAVE_STRUCT_STATVFS_F_BASETYPE) || defined(HAVE_STRUCT_STATVFS_F_FSTYPENAME)) + struct statvfs buf; + + if (fstatvfs (fd, &buf) == 0) + { + const char *p; +#if defined(HAVE_STRUCT_STATVFS_F_BASETYPE) + p = buf.f_basetype; +#elif defined(HAVE_STRUCT_STATVFS_F_FSTYPENAME) + p = buf.f_fstypename; +#endif + + if (strcmp (p, "nfs") == 0) + retval = FcFalse; + } +#elif defined(HAVE_FSTATFS) && (defined(HAVE_STRUCT_STATFS_F_FLAGS) || defined(HAVE_STRUCT_STATFS_F_FSTYPENAME) || defined(__linux__)) + struct statfs buf; + + if (fstatfs (fd, &buf) == 0) + { +# if defined(HAVE_STRUCT_STATFS_F_FLAGS) && defined(MNT_LOCAL) + if (!(buf.f_flags & MNT_LOCAL)) +# elif defined(HAVE_STRUCT_STATFS_F_FSTYPENAME) + if (strcmp (buf.f_fstypename, "nfs") == 0) +# elif defined(__linux__) + if (buf.f_type == 0x6969) /* nfs */ +# else +# error "BUG: No way to figure out with fstatfs()" +# endif + retval = FcFalse; + } +#endif + + return retval; +} + static const char bin2hex[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', @@ -602,10 +675,10 @@ FcDirCacheMapFd (int fd, struct stat *fd_stat, struct stat *dir_stat) } /* - * Lage cache files are mmap'ed, smaller cache files are read. This + * Large cache files are mmap'ed, smaller cache files are read. This * balances the system cost of mmap against per-process memory usage. */ - if (fd_stat->st_size >= FC_CACHE_MIN_MMAP) + if (FcCacheIsMmapSafe (fd) && fd_stat->st_size >= FC_CACHE_MIN_MMAP) { #if defined(HAVE_MMAP) || defined(__CYGWIN__) cache = mmap (0, fd_stat->st_size, PROT_READ, MAP_SHARED, fd, 0); diff --git a/fontconfig/src/fcdefault.c b/fontconfig/src/fcdefault.c index a9165facd..170a8a4d8 100644 --- a/fontconfig/src/fcdefault.c +++ b/fontconfig/src/fcdefault.c @@ -119,7 +119,7 @@ FcGetDefaultLang (void) void FcDefaultSubstitute (FcPattern *pattern) { - FcValue v; + FcValue v, namelang, v2; int i; if (FcPatternObjectGet (pattern, FC_WEIGHT_OBJECT, 0, &v) == FcResultNoMatch ) @@ -175,6 +175,41 @@ FcDefaultSubstitute (FcPattern *pattern) { FcPatternObjectAddInteger (pattern, FC_HINT_STYLE_OBJECT, FC_HINT_FULL); } + if (FcPatternObjectGet (pattern, FC_NAMELANG_OBJECT, 0, &v) == FcResultNoMatch) + { + FcPatternObjectAddString (pattern, FC_NAMELANG_OBJECT, FcGetDefaultLang ()); + } + /* shouldn't be failed. */ + FcPatternObjectGet (pattern, FC_NAMELANG_OBJECT, 0, &namelang); + /* Add a fallback to ensure the english name when the requested language + * isn't available. this would helps for the fonts that have non-English + * name at the beginning. + */ + /* Set "en-us" instead of "en" to avoid giving higher score to "en". + * This is a hack for the case that the orth is not like ll-cc, because, + * if no namelang isn't explicitly set, it will has something like ll-cc + * according to current locale. which may causes FcLangDifferentTerritory + * at FcLangCompare(). thus, the English name is selected so that + * exact matched "en" has higher score than ll-cc. + */ + v2.type = FcTypeString; + v2.u.s = FcSharedStr ((FcChar8 *)"en-us"); + if (FcPatternObjectGet (pattern, FC_FAMILYLANG_OBJECT, 0, &v) == FcResultNoMatch) + { + FcPatternObjectAdd (pattern, FC_FAMILYLANG_OBJECT, namelang, FcTrue); + FcPatternObjectAddWithBinding (pattern, FC_FAMILYLANG_OBJECT, v2, FcValueBindingWeak, FcTrue); + } + if (FcPatternObjectGet (pattern, FC_STYLELANG_OBJECT, 0, &v) == FcResultNoMatch) + { + FcPatternObjectAdd (pattern, FC_STYLELANG_OBJECT, namelang, FcTrue); + FcPatternObjectAddWithBinding (pattern, FC_STYLELANG_OBJECT, v2, FcValueBindingWeak, FcTrue); + } + if (FcPatternObjectGet (pattern, FC_FULLNAMELANG_OBJECT, 0, &v) == FcResultNoMatch) + { + FcPatternObjectAdd (pattern, FC_FULLNAMELANG_OBJECT, namelang, FcTrue); + FcPatternObjectAddWithBinding (pattern, FC_FULLNAMELANG_OBJECT, v2, FcValueBindingWeak, FcTrue); + } + FcSharedStrFree (v2.u.s); } #define __fcdefault__ #include "fcaliastail.h" diff --git a/fontconfig/src/fcint.h b/fontconfig/src/fcint.h index bada32550..fb4a64b9d 100644 --- a/fontconfig/src/fcint.h +++ b/fontconfig/src/fcint.h @@ -858,7 +858,8 @@ FcListPatternMatchAny (const FcPattern *p, #define FC_EMBEDDED_BITMAP_OBJECT 39 #define FC_DECORATIVE_OBJECT 40 #define FC_LCD_FILTER_OBJECT 41 -#define FC_MAX_BASE_OBJECT FC_LCD_FILTER_OBJECT +#define FC_NAMELANG_OBJECT 42 +#define FC_MAX_BASE_OBJECT FC_NAMELANG_OBJECT FcPrivate FcBool FcNameBool (const FcChar8 *v, FcBool *result); diff --git a/fontconfig/src/fclist.c b/fontconfig/src/fclist.c index 88025e900..331352cd8 100644 --- a/fontconfig/src/fclist.c +++ b/fontconfig/src/fclist.c @@ -221,7 +221,18 @@ FcListPatternMatchAny (const FcPattern *p, for (i = 0; i < p->num; i++) { FcPatternElt *pe = &FcPatternElts(p)[i]; - FcPatternElt *fe = FcPatternObjectFindElt (font, pe->object); + FcPatternElt *fe; + + if (pe->object == FC_NAMELANG_OBJECT) + { + /* "namelang" object is the alias object to change "familylang", + * "stylelang" and "fullnamelang" object alltogether. it won't be + * available on the font pattern. so checking its availability + * causes no results. we should ignore it here. + */ + continue; + } + fe = FcPatternObjectFindElt (font, pe->object); if (!fe) return FcFalse; if (!FcListValueListMatchAny (FcPatternEltValues(pe), /* pat elts */ @@ -340,13 +351,13 @@ FcListHashTableCleanup (FcListHashTable *table) } static int -FcGetDefaultObjectLangIndex (FcPattern *font, FcObject object) +FcGetDefaultObjectLangIndex (FcPattern *font, FcObject object, const FcChar8 *lang) { - FcChar8 *lang = FcGetDefaultLang (); FcPatternElt *e = FcPatternObjectFindElt (font, object); FcValueListPtr v; FcValue value; int idx = -1; + int defidx = -1; int i; if (e) @@ -363,17 +374,27 @@ FcGetDefaultObjectLangIndex (FcPattern *font, FcObject object) if (res == FcLangDifferentCountry && idx < 0) idx = i; + if (defidx < 0) + { + /* workaround for fonts that has non-English value + * at the head of values. + */ + res = FcLangCompare (value.u.s, (FcChar8 *)"en"); + if (res == FcLangEqual) + defidx = i; + } } } } - return (idx > 0) ? idx : 0; + return (idx > 0) ? idx : (defidx > 0) ? defidx : 0; } static FcBool FcListAppend (FcListHashTable *table, FcPattern *font, - FcObjectSet *os) + FcObjectSet *os, + const FcChar8 *lang) { int o; FcPatternElt *e; @@ -409,19 +430,19 @@ FcListAppend (FcListHashTable *table, if (!strcmp (os->objects[o], FC_FAMILY) || !strcmp (os->objects[o], FC_FAMILYLANG)) { if (familyidx < 0) - familyidx = FcGetDefaultObjectLangIndex (font, FC_FAMILYLANG_OBJECT); + familyidx = FcGetDefaultObjectLangIndex (font, FC_FAMILYLANG_OBJECT, lang); defidx = familyidx; } else if (!strcmp (os->objects[o], FC_FULLNAME) || !strcmp (os->objects[o], FC_FULLNAMELANG)) { if (fullnameidx < 0) - fullnameidx = FcGetDefaultObjectLangIndex (font, FC_FULLNAMELANG_OBJECT); + fullnameidx = FcGetDefaultObjectLangIndex (font, FC_FULLNAMELANG_OBJECT, lang); defidx = fullnameidx; } else if (!strcmp (os->objects[o], FC_STYLE) || !strcmp (os->objects[o], FC_STYLELANG)) { if (styleidx < 0) - styleidx = FcGetDefaultObjectLangIndex (font, FC_STYLELANG_OBJECT); + styleidx = FcGetDefaultObjectLangIndex (font, FC_STYLELANG_OBJECT, lang); defidx = styleidx; } else @@ -499,8 +520,16 @@ FcFontSetList (FcConfig *config, for (f = 0; f < s->nfont; f++) if (FcListPatternMatchAny (p, /* pattern */ s->fonts[f])) /* font */ - if (!FcListAppend (&table, s->fonts[f], os)) + { + FcChar8 *lang; + + if (FcPatternObjectGetString (p, FC_NAMELANG_OBJECT, 0, &lang) != FcResultMatch) + { + lang = FcGetDefaultLang (); + } + if (!FcListAppend (&table, s->fonts[f], os, lang)) goto bail1; + } } #if 0 { diff --git a/fontconfig/src/fcmatch.c b/fontconfig/src/fcmatch.c index 655e62cf5..623538bd3 100644 --- a/fontconfig/src/fcmatch.c +++ b/fontconfig/src/fcmatch.c @@ -240,7 +240,8 @@ static const FcMatcher _FcMatchers [] = { #define NUM_MATCH_VALUES 17 static const FcMatcher* -FcObjectToMatcher (FcObject object) +FcObjectToMatcher (FcObject object, + FcBool include_lang) { int i; @@ -278,6 +279,16 @@ FcObjectToMatcher (FcObject object) i = MATCH_OUTLINE; break; case FC_DECORATIVE_OBJECT: i = MATCH_DECORATIVE; break; + default: + if (include_lang) + { + switch (object) { + case FC_FAMILYLANG_OBJECT: + case FC_STYLELANG_OBJECT: + case FC_FULLNAMELANG_OBJECT: + i = MATCH_LANG; break; + } + } } if (i < 0) @@ -287,22 +298,25 @@ FcObjectToMatcher (FcObject object) } static FcBool -FcCompareValueList (FcObject object, - FcValueListPtr v1orig, /* pattern */ - FcValueListPtr v2orig, /* target */ - FcValue *bestValue, - double *value, - FcResult *result) +FcCompareValueList (FcObject object, + const FcMatcher *match, + FcValueListPtr v1orig, /* pattern */ + FcValueListPtr v2orig, /* target */ + FcValue *bestValue, + double *value, + int *n, + FcResult *result) { FcValueListPtr v1, v2; double v, best, bestStrong, bestWeak; - int j; - const FcMatcher *match = FcObjectToMatcher(object); + int j, k, pos = 0; if (!match) { if (bestValue) *bestValue = FcValueCanonicalize(&v2orig->value); + if (n) + *n = 0; return FcTrue; } @@ -312,7 +326,7 @@ FcCompareValueList (FcObject object, j = 1; for (v1 = v1orig; v1; v1 = FcValueListNext(v1)) { - for (v2 = v2orig; v2; v2 = FcValueListNext(v2)) + for (v2 = v2orig, k = 0; v2; v2 = FcValueListNext(v2), k++) { v = (match->compare) (&v1->value, &v2->value); if (v < 0) @@ -326,6 +340,7 @@ FcCompareValueList (FcObject object, if (bestValue) *bestValue = FcValueCanonicalize(&v2->value); best = v; + pos = k; } if (v1->binding == FcValueBindingStrong) { @@ -360,6 +375,9 @@ FcCompareValueList (FcObject object, value[strong] += bestStrong; } } + if (n) + *n = pos; + return FcTrue; } @@ -393,10 +411,11 @@ FcCompare (FcPattern *pat, i1++; else { - if (!FcCompareValueList (elt_i1->object, + const FcMatcher *match = FcObjectToMatcher (elt_i1->object, FcFalse); + if (!FcCompareValueList (elt_i1->object, match, FcPatternEltValues(elt_i1), FcPatternEltValues(elt_i2), - 0, value, result)) + NULL, value, NULL, result)) return FcFalse; i1++; i2++; @@ -412,8 +431,8 @@ FcFontRenderPrepare (FcConfig *config, { FcPattern *new; int i; - FcPatternElt *fe, *pe; - FcValue v; + FcPatternElt *fe, *pe, *fel, *pel; + FcValue v, vl; FcResult result; assert (pat != NULL); @@ -425,19 +444,81 @@ FcFontRenderPrepare (FcConfig *config, for (i = 0; i < font->num; i++) { fe = &FcPatternElts(font)[i]; + if (fe->object == FC_FAMILYLANG_OBJECT || + fe->object == FC_STYLELANG_OBJECT || + fe->object == FC_FULLNAMELANG_OBJECT) + { + /* ignore those objects. we need to deal with them + * another way */ + continue; + } + if (fe->object == FC_FAMILY_OBJECT || + fe->object == FC_STYLE_OBJECT || + fe->object == FC_FULLNAME_OBJECT) + { + FC_ASSERT_STATIC ((FC_FAMILY_OBJECT + 1) == FC_FAMILYLANG_OBJECT); + FC_ASSERT_STATIC ((FC_STYLE_OBJECT + 1) == FC_STYLELANG_OBJECT); + FC_ASSERT_STATIC ((FC_FULLNAME_OBJECT + 1) == FC_FULLNAMELANG_OBJECT); + + fel = FcPatternObjectFindElt (font, fe->object + 1); + pel = FcPatternObjectFindElt (pat, fe->object + 1); + } + else + { + fel = NULL; + pel = NULL; + } pe = FcPatternObjectFindElt (pat, fe->object); if (pe) { - if (!FcCompareValueList (pe->object, FcPatternEltValues(pe), - FcPatternEltValues(fe), &v, 0, &result)) + const FcMatcher *match = FcObjectToMatcher (pe->object, FcFalse); + + if (!FcCompareValueList (pe->object, match, + FcPatternEltValues(pe), + FcPatternEltValues(fe), &v, NULL, NULL, &result)) { FcPatternDestroy (new); return 0; } + if (fel && pel) + { + int n = 1, j; + + match = FcObjectToMatcher (pel->object, FcTrue); + if (!FcCompareValueList (pel->object, match, + FcPatternEltValues (pel), + FcPatternEltValues (fel), &vl, NULL, &n, &result)) + { + FcPatternDestroy (new); + return NULL; + } + else + { + FcValueListPtr l; + + for (j = 0, l = FcPatternEltValues (fe); + j < n && l != NULL; + j++, l = FcValueListNext (l)); + if (l) + v = FcValueCanonicalize (&l->value); + else + v = FcValueCanonicalize (&FcPatternEltValues (fe)->value); + } + } + else if (fel) + { + vl = FcValueCanonicalize (&FcPatternEltValues (fel)->value); + } } else + { v = FcValueCanonicalize(&FcPatternEltValues (fe)->value); + if (fel) + vl = FcValueCanonicalize (&FcPatternEltValues (fel)->value); + } FcPatternObjectAdd (new, fe->object, v, FcFalse); + if (fel) + FcPatternObjectAdd (new, fel->object, vl, FcFalse); } for (i = 0; i < pat->num; i++) { diff --git a/fontconfig/src/fcname.c b/fontconfig/src/fcname.c index d0b1ca84c..d51307bec 100644 --- a/fontconfig/src/fcname.c +++ b/fontconfig/src/fcname.c @@ -76,6 +76,7 @@ static const FcObjectType _FcBaseObjectTypes[] = { { FC_EMBEDDED_BITMAP, FcTypeBool }, { FC_DECORATIVE, FcTypeBool }, { FC_LCD_FILTER, FcTypeInteger }, /* 41 */ + { FC_NAMELANG, FcTypeString }, /* 42 */ }; #define NUM_OBJECT_TYPES (sizeof _FcBaseObjectTypes / sizeof _FcBaseObjectTypes[0]) diff --git a/libX11/specs/XKB/acknowledgement.xml b/libX11/specs/XKB/acknowledgement.xml index 2977999c4..4ecb798c1 100644 --- a/libX11/specs/XKB/acknowledgement.xml +++ b/libX11/specs/XKB/acknowledgement.xml @@ -24,12 +24,20 @@ not only for the quality of this document, but for the quality of the Keyboard extension itself. </para> <para> +<literallayout> Matt Landau -</para> -<para> Manager, X Window System +X Consortium Inc. +</literallayout> </para> +<simplesect> +<title>X Version 11, Release 7 addendum</title> <para> -X Consortium Inc. +This document is made available to you in modern formats such as HTML and PDF +thanks to the efforts of Matt Dew, who converted the original troff sources to +DocBook/XML and edited them into shape; Fernando Carrijo, who converted the +images to SVG format; and Gaetan Nadon, who set up the formatting machinery in +the libX11 builds and performed further editing of the DocBook markup. </para> +</simplesect> </preface> diff --git a/libX11/specs/i18n/localedb/localedb.xml b/libX11/specs/i18n/localedb/localedb.xml index caacd82d5..ed9000769 100644 --- a/libX11/specs/i18n/localedb/localedb.xml +++ b/libX11/specs/i18n/localedb/localedb.xml @@ -422,7 +422,7 @@ for this fontset. The format of value is; <para> For detail definition of CHARSET_REGISTRY-CHARSET_ENCODING, refer -"X Logical Font Descriptions" document. +to the <olink targetdoc='xlfd' targetptr='xlfd'><citetitle>X Logical Font Description Conventions</citetitle></olink> document. </para> <literallayout> example: @@ -778,7 +778,7 @@ END XLC_XLOCALE [1] <emphasis remap='I'>ISO/IEC 9899:1990 C Language Standard</emphasis> </para> <para> -[2] <emphasis remap='I'>X Logical Font Descriptions</emphasis> +[2] <olink targetdoc='xlfd' targetptr='xlfd'><citetitle>X Logical Font Description Conventions</citetitle></olink> </para> </sect1> diff --git a/libX11/specs/libX11/AppD.xml b/libX11/specs/libX11/AppD.xml index f3c0e2f6a..fdea46894 100644 --- a/libX11/specs/libX11/AppD.xml +++ b/libX11/specs/libX11/AppD.xml @@ -361,7 +361,7 @@ The next two functions set and read the <property>WM_ZOOM_HINTS</property> prope To set the zoom hints for a window, use <xref linkend='XSetZoomHints' xrefstyle='select: title'/>. This function is no longer supported by the -<emphasis remap='I'>Inter-Client Communication Conventions Manual</emphasis>. +<citetitle>Inter-Client Communication Conventions Manual</citetitle>. </para> <indexterm significance="preferred"><primary>XSetZoomHints</primary></indexterm> <!-- .sM --> @@ -431,7 +431,7 @@ errors. To read the zoom hints for a window, use <xref linkend='XGetZoomHints' xrefstyle='select: title'/>. This function is no longer supported by the -<emphasis remap='I'>Inter-Client Communication Conventions Manual</emphasis>. +<citetitle>Inter-Client Communication Conventions Manual</citetitle>. </para> <indexterm significance="preferred"><primary>XGetZoomHints</primary></indexterm> <!-- .sM --> diff --git a/libX11/specs/libX11/CH01.xml b/libX11/specs/libX11/CH01.xml index 081e80c46..67744cfa2 100644 --- a/libX11/specs/libX11/CH01.xml +++ b/libX11/specs/libX11/CH01.xml @@ -685,7 +685,7 @@ What you do inside of your top-level window, however, is up to your application. For further information, see <link linkend='Inter_Client_Communication_Functions'>chapter 14</link> -and the <citetitle>Inter-Client Communication Conventions Manual</citetitle>. +and the <olink targetdoc='icccm' targetptr='icccm'><citetitle>Inter-Client Communication Conventions Manual</citetitle></olink>. </para> </listitem> </itemizedlist> diff --git a/libX11/specs/libX11/CH03.xml b/libX11/specs/libX11/CH03.xml index e2468580d..7d2b20e52 100644 --- a/libX11/specs/libX11/CH03.xml +++ b/libX11/specs/libX11/CH03.xml @@ -1214,7 +1214,7 @@ you should set these properties for top-level windows before mapping them. <!-- .LP --> For further information, see <link linkend='Inter_Client_Communication_Functions'>chapter 14</link> and -the <emphasis remap='I'>Inter-Client Communication Conventions Manual</emphasis>. +the <olink targetdoc='icccm' targetptr='icccm'><citetitle>Inter-Client Communication Conventions Manual</citetitle></olink>. </para> <para> <!-- .LP --> diff --git a/libX11/specs/libX11/CH04.xml b/libX11/specs/libX11/CH04.xml index a3f47d543..9cdfd1a7f 100644 --- a/libX11/specs/libX11/CH04.xml +++ b/libX11/specs/libX11/CH04.xml @@ -893,8 +893,8 @@ see <link linkend='Inter_Client_Communication_Functions'>chapter 14</link>. <!-- .LP --> The core protocol imposes no semantics on these property names, but semantics are specified in other X Consortium standards, -such as the <emphasis remap='I'>Inter-Client Communication Conventions Manual</emphasis> -and the <emphasis remap='I'>X Logical Font Description Conventions</emphasis>. +such as the <olink targetdoc='icccm' targetptr='icccm'><citetitle>Inter-Client Communication Conventions Manual</citetitle></olink> +and the <olink targetdoc='xlfd' targetptr='xlfd'><citetitle>X Logical Font Description Conventions</citetitle></olink>. </para> <para> <!-- .LP --> diff --git a/libX11/specs/libX11/CH06.xml b/libX11/specs/libX11/CH06.xml index 1a6709cd7..b84ce95cc 100644 --- a/libX11/specs/libX11/CH06.xml +++ b/libX11/specs/libX11/CH06.xml @@ -7109,8 +7109,9 @@ a class of output devices. <indexterm><primary>Device Color Characterization</primary></indexterm> For details about how color characterization data is stored in root window properties, -see the section on Device Color Characterization in the -<emphasis remap='I'>Inter-Client Communication Conventions Manual</emphasis>. +see <olink targetdoc='icccm' targetptr='Device_Color_Characterization'>the +section on Device Color Characterization in the +<citetitle>Inter-Client Communication Conventions Manual</citetitle></olink>. The LINEAR_RGB function set is provided by Xlib and will support most color monitors. Function sets may require data that differs diff --git a/libX11/specs/libX11/CH08.xml b/libX11/specs/libX11/CH08.xml index b2348b5ae..e4afa37fa 100644 --- a/libX11/specs/libX11/CH08.xml +++ b/libX11/specs/libX11/CH08.xml @@ -2995,7 +2995,7 @@ A font is not guaranteed to have any properties. The interpretation of the property value (for example, long or unsigned long) must be derived from <emphasis remap='I'>a priori</emphasis> knowledge of the property. A basic set of font properties is specified in the X Consortium standard -<emphasis remap='I'>X Logical Font Description Conventions</emphasis>. +<olink targetdoc='xlfd' targetptr='xlfd'><citetitle>X Logical Font Description Conventions</citetitle></olink>. </para> <sect2 id="Loading_and_Freeing_Fonts"> <title>Loading and Freeing Fonts</title> @@ -3067,7 +3067,7 @@ In the pattern, the ``?'' character will match any single character, and the ``*'' character will match any number of characters. A structured format for font names is specified in the X Consortium standard -<emphasis remap='I'>X Logical Font Description Conventions</emphasis>. +<olink targetdoc='xlfd' targetptr='xlfd'><citetitle>X Logical Font Description Conventions</citetitle></olink>. If <xref linkend='XLoadFont' xrefstyle='select: title'/> was unsuccessful at loading the specified font, diff --git a/libX11/specs/libX11/CH10.xml b/libX11/specs/libX11/CH10.xml index 2024592b5..9c12ef710 100644 --- a/libX11/specs/libX11/CH10.xml +++ b/libX11/specs/libX11/CH10.xml @@ -4632,8 +4632,10 @@ The owner should convert the selection based on the specified target type and send a <symbol>SelectionNotify</symbol> event back to the requestor. -A complete specification for using selections is given in the X Consortium -standard <emphasis remap='I'>Inter-Client Communication Conventions Manual</emphasis>. +A <olink targetdoc='icccm' +targetptr='Peer_to_Peer_Communication_by_Means_of_Selections'>complete +specification for using selections</olink> is given in the X Consortium +standard <citetitle>Inter-Client Communication Conventions Manual</citetitle>. </para> </sect2> <sect2 id="SelectionNotify_Events"> diff --git a/libX11/specs/libX11/CH12.xml b/libX11/specs/libX11/CH12.xml index ae8017b2b..cc14fe649 100644 --- a/libX11/specs/libX11/CH12.xml +++ b/libX11/specs/libX11/CH12.xml @@ -1926,7 +1926,7 @@ error. Xlib provides functions that you can use to set and get the input focus. The input focus is a shared resource, and cooperation among clients is required for correct interaction. See the -<emphasis remap='I'>Inter-Client Communication Conventions Manual</emphasis> +<olink targetdoc='icccm' targetptr='Input_Focus'><citetitle>Inter-Client Communication Conventions Manual</citetitle></olink> for input focus policy. </para> <para> diff --git a/libX11/specs/libX11/CH14.xml b/libX11/specs/libX11/CH14.xml index ee14b95ee..6dc947a9c 100644 --- a/libX11/specs/libX11/CH14.xml +++ b/libX11/specs/libX11/CH14.xml @@ -4,11 +4,12 @@ <chapter id='Inter_Client_Communication_Functions'> <title>Inter-Client Communication Functions</title> <para> -The Inter-Client Communication Conventions Manual, hereafter referred to as the <acronym>ICCCM</acronym>, +The <citetitle>Inter-Client Communication Conventions Manual</citetitle>, +hereafter referred to as the <acronym>ICCCM</acronym>, details the X Consortium approved conventions that govern inter-client communications. These conventions ensure peer-to-peer client cooperation in the use of selections, cut buffers, and shared resources as well as client cooperation with window and session managers. For further information, -see the Inter-Client Communication Conventions Manual. +see the <olink targetdoc='icccm' targetptr='icccm'><citetitle>Inter-Client Communication Conventions Manual</citetitle></olink>. </para> <para> Xlib provides a number of standard properties and programming interfaces that are <acronym>ICCCM</acronym> @@ -313,8 +314,9 @@ function sends a <property>WM_CHANGE_STATE</property> <symbol>ClientMessage</symbol> event with a format of 32 and a first data element of <symbol>IconicState</symbol> -(as described in section 4.1.4 of the -<emphasis remap='I'>Inter-Client Communication Conventions Manual</emphasis>) +(as described in <olink targetdoc='icccm' targetptr='Changing_Window_State' +>section 4.1.4 of the +<citetitle>Inter-Client Communication Conventions Manual</citetitle></olink>) and a window of w to the root window of the specified screen with an event mask set to diff --git a/libX11/specs/libX11/credits.xml b/libX11/specs/libX11/credits.xml index c8fdfecb4..c3d1f7383 100644 --- a/libX11/specs/libX11/credits.xml +++ b/libX11/specs/libX11/credits.xml @@ -224,4 +224,14 @@ Massachusetts Institute of Technology </literallayout> </para> </simplesect> +<simplesect> +<title>Release 7</title> +<para> +This document is made available to you in modern formats such as HTML and PDF +thanks to the efforts of Matt Dew, who converted the original troff sources to +DocBook/XML and edited them into shape; along with Gaetan Nadon and +Alan Coopersmith, who set up the formatting machinery in the libX11 builds and +performed further editing of the DocBook markup. +</para> +</simplesect> </preface> diff --git a/libX11/specs/libX11/glossary.xml b/libX11/specs/libX11/glossary.xml index 51fa30293..14ad2e2dd 100644 --- a/libX11/specs/libX11/glossary.xml +++ b/libX11/specs/libX11/glossary.xml @@ -1689,8 +1689,8 @@ see the <glossterm linkend="glossary:Host_Portable_Character_Encoding">Host Port <indexterm significance="preferred"><primary><acronym>XLFD</acronym></primary></indexterm> <glossdef> <para> -The X Logical Font Description Conventions that define a standard syntax -for structured font names. +The <olink targetdoc='xlfd' targetptr='xlfd'><citetitle>X Logical Font Description Conventions</citetitle></olink> +that define a standard syntax for structured font names. </para> </glossdef> </glossentry> diff --git a/libX11/src/XlibInt.c b/libX11/src/XlibInt.c index a8f5d0844..2827c106a 100644 --- a/libX11/src/XlibInt.c +++ b/libX11/src/XlibInt.c @@ -886,7 +886,7 @@ void _XEnq( extension = ((xGenericEvent*)event)->extension; qelt->event.type = type; - /* If an extension has registerd a generic_event_vec handler, then + /* If an extension has registered a generic_event_vec handler, then * it can handle event cookies. Otherwise, proceed with the normal * event handlers. * diff --git a/libfontenc/src/fontenc.c b/libfontenc/src/fontenc.c index fb56ff173..4cfa1e59b 100644 --- a/libfontenc/src/fontenc.c +++ b/libfontenc/src/fontenc.c @@ -250,7 +250,8 @@ iso8859_6_to_unicode(unsigned isocode, void *client_data) if(isocode<=0xA0 || isocode==0xA4 || isocode==0xAD) return isocode; else if(isocode==0xAC || isocode==0xBB || - (isocode>=0xBF && isocode<=0xDA) || + isocode==0xBF || + (isocode>=0xC1 && isocode<=0xDA) || (isocode>=0xE0 && isocode<=0xEF) || (isocode>=0xF0 && isocode<=0xF2)) return isocode-0xA0+0x0600; @@ -278,6 +279,8 @@ iso8859_7_to_unicode(unsigned isocode, void *client_data) return 0x02BC; else if(isocode==0xAF) return 0x2015; + else if(isocode==0xD2) /* unassigned */ + return 0; else if(isocode>=0xB4) return isocode-0xA0+0x0370; else diff --git a/mesalib/bin/mklib b/mesalib/bin/mklib index 56e0b36d1..9bac29ea8 100644 --- a/mesalib/bin/mklib +++ b/mesalib/bin/mklib @@ -334,7 +334,9 @@ case $ARCH in # environment. If so, pass -m32 flag to linker. set ${OBJECTS} ABI32=`file $1 | grep 32-bit` - if [ "${ABI32}" -a `uname -m` = "x86_64" ] ; then + ARM=`file $1 | grep ARM` + # Do not add "-m32" option for arm. + if [ -z "$ARM" -a "${ABI32}" -a `uname -m` = "x86_64" ] ; then OPTS="-m32 ${OPTS}" fi @@ -391,7 +393,9 @@ case $ARCH in # environment. If so, pass -m32 flag to linker. set ${OBJECTS} ABI32=`file $1 | grep 32-bit` - if [ "${ABI32}" -a `uname -m` = "x86_64" ] ; then + ARM=`file $1 | grep ARM` + # Do not add "-m32" option for arm. + if [ -z "$ARM" -a "${ABI32}" -a `uname -m` = "x86_64" ] ; then OPTS="-m32 ${OPTS}" fi if [ "${ALTOPTS}" ] ; then diff --git a/mesalib/configs/autoconf.in b/mesalib/configs/autoconf.in index ec3f3194e..eb6713ddf 100644 --- a/mesalib/configs/autoconf.in +++ b/mesalib/configs/autoconf.in @@ -217,9 +217,5 @@ WAYLAND_LIBS = @WAYLAND_LIBS@ MESA_LLVM = @MESA_LLVM@ LLVM_VERSION = @LLVM_VERSION@ -ifneq ($(LLVM_VERSION),) - HAVE_LLVM := 0x0$(subst .,0,$(LLVM_VERSION:svn=)) - DEFINES += -DHAVE_LLVM=$(HAVE_LLVM) -endif HAVE_XF86VIDMODE = @HAVE_XF86VIDMODE@ diff --git a/mesalib/configs/darwin b/mesalib/configs/darwin index 721fbc780..12e6e3a06 100644 --- a/mesalib/configs/darwin +++ b/mesalib/configs/darwin @@ -52,10 +52,10 @@ OSMESA_LIB_DEPS = $(EXTRA_LDFLAGS) GLU_LIB_DEPS = -L$(TOP)/$(LIB_DIR) -l$(GL_LIB) $(EXTRA_LDFLAGS) GLW_LIB_DEPS = -L$(TOP)/$(LIB_DIR) -l$(GL_LIB) -L$(INSTALL_DIR)/$(LIB_DIR) -L$(X11_DIR)/$(LIB_DIR) -lX11 -lXt $(EXTRA_LDFLAGS) -SRC_DIRS = glsl mapi/glapi mapi/vgapi glx/apple mesa gallium glu +SRC_DIRS = glsl mapi/glapi mapi/vgapi glx/apple mesa glu GLU_DIRS = sgi DRIVER_DIRS = osmesa #DRIVER_DIRS = dri DRI_DIRS = swrast -GALLIUM_DRIVERS_DIRS = softpipe trace rbug noop identity galahad +#GALLIUM_DRIVERS_DIRS = softpipe trace rbug noop identity galahad #GALLIUM_DRIVERS_DIRS += llvmpipe diff --git a/mesalib/configure.ac b/mesalib/configure.ac index 1b571b95c..3bc59ca3e 100644 --- a/mesalib/configure.ac +++ b/mesalib/configure.ac @@ -16,7 +16,7 @@ AC_INIT([Mesa],[mesa_version], [https://bugs.freedesktop.org/enter_bug.cgi?product=Mesa]) AC_CONFIG_AUX_DIR([bin]) AC_CANONICAL_HOST -AM_INIT_AUTOMAKE([foreign]) +AM_INIT_AUTOMAKE([foreign -Wall]) dnl http://people.gnome.org/~walters/docs/build-api.txt dnl We don't support srcdir != builddir. @@ -637,6 +637,12 @@ AC_ARG_ENABLE([gallium_gbm], [enable_gallium_gbm="$enableval"], [enable_gallium_gbm=auto]) +AC_ARG_ENABLE([r600-llvm-compiler], + [AS_HELP_STRING([--enable-r600-llvm-compilerl], + [Enable experimental LLVM backend for graphics shaders @<:default=disable@:>@])], + [enable_r600_llvm="$enableval"], + [enable_r600_llvm=no]) + # Option for Gallium drivers GALLIUM_DRIVERS_DEFAULT="r300,r600,svga,swrast" @@ -1805,7 +1811,7 @@ if test "x$enable_gallium_llvm" = xyes; then LLVM_BINDIR=`$LLVM_CONFIG --bindir` LLVM_CXXFLAGS=`$LLVM_CONFIG --cxxflags` LLVM_INCLUDEDIR=`$LLVM_CONFIG --includedir` - DEFINES="$DEFINES -D__STDC_CONSTANT_MACROS" + DEFINES="${DEFINES} -DHAVE_LLVM=`echo $LLVM_VERSION | sed -e 's/\([[0-9]]\)\.\([[0-9]]\)/0x0\10\2/g'`" MESA_LLVM=1 else MESA_LLVM=0 @@ -1906,6 +1912,13 @@ if test "x$with_gallium_drivers" != x; then xr600) PKG_CHECK_MODULES([RADEON], [libdrm_radeon >= $LIBDRM_RADEON_REQUIRED]) GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS r600" + if test "x$enable_r600_llvm" = xyes; then + if test "x$LLVM_VERSION" != "x3.1"; then + AC_MSG_ERROR([LLVM 3.1 is required for the r600 llvm compiler.]) + fi + NEED_RADEON_GALLIUM=yes; + USE_R600_LLVM_COMPILER=yes; + fi gallium_check_st "radeon/drm" "dri-r600" "xorg-r600" "" "xvmc-r600" "vdpau-r600" "va-r600" ;; xradeonsi) @@ -1976,6 +1989,7 @@ AM_CONDITIONAL(HAVE_GALAHAD_GALLIUM, test x$HAVE_GALAHAD_GALLIUM = xyes) AM_CONDITIONAL(HAVE_IDENTITY_GALLIUM, test x$HAVE_IDENTITY_GALLIUM = xyes) AM_CONDITIONAL(HAVE_NOOP_GALLIUM, test x$HAVE_NOOP_GALLIUM = xyes) AM_CONDITIONAL(NEED_RADEON_GALLIUM, test x$NEED_RADEON_GALLIUM = xyes) +AM_CONDITIONAL(USE_R600_LLVM_COMPILER, test x$USE_R600_LLVM_COMPILER = xyes) AC_SUBST([GALLIUM_MAKE_DIRS]) dnl prepend CORE_DIRS to SRC_DIRS diff --git a/mesalib/scons/source_list.py b/mesalib/scons/source_list.py index fbd3ef7dc..1d5166ba1 100644 --- a/mesalib/scons/source_list.py +++ b/mesalib/scons/source_list.py @@ -3,7 +3,7 @@ The syntax of a source list file is a very small subset of GNU Make. These features are supported - operators: +=, := + operators: =, +=, := line continuation non-nested variable expansion comment @@ -62,17 +62,18 @@ class SourceListParser(object): if op_pos < 0: self._error('not a variable definition') - if op_pos > 0 and line[op_pos - 1] in [':', '+']: - op_pos -= 1 + if op_pos > 0: + if line[op_pos - 1] in [':', '+']: + op_pos -= 1 else: - self._error('only := and += are supported') + self._error('only =, :=, and += are supported') # set op, sym, and val op = line[op_pos:op_end] sym = line[:op_pos].strip() val = self._expand_value(line[op_end:].lstrip()) - if op == ':=': + if op in ('=', ':='): self.symbol_table[sym] = val elif op == '+=': self.symbol_table[sym] += ' ' + val diff --git a/mesalib/src/gallium/auxiliary/util/u_blitter.c b/mesalib/src/gallium/auxiliary/util/u_blitter.c index 6a9141209..d0b9187d1 100644 --- a/mesalib/src/gallium/auxiliary/util/u_blitter.c +++ b/mesalib/src/gallium/auxiliary/util/u_blitter.c @@ -733,6 +733,7 @@ static void blitter_draw(struct blitter_context_priv *ctx, u_upload_unmap(ctx->upload); util_draw_vertex_buffer(ctx->base.pipe, NULL, buf, offset, PIPE_PRIM_TRIANGLE_FAN, 4, 2); + pipe_resource_reference(&buf, NULL); } static void blitter_draw_rectangle(struct blitter_context *blitter, diff --git a/mesalib/src/gallium/auxiliary/util/u_draw_quad.c b/mesalib/src/gallium/auxiliary/util/u_draw_quad.c index 371fefb9e..590fa0c36 100644 --- a/mesalib/src/gallium/auxiliary/util/u_draw_quad.c +++ b/mesalib/src/gallium/auxiliary/util/u_draw_quad.c @@ -1,135 +1,134 @@ -/**************************************************************************
- *
- * 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.
- *
- **************************************************************************/
-
-
-#include "pipe/p_context.h"
-#include "pipe/p_defines.h"
-#include "util/u_inlines.h"
-#include "util/u_draw_quad.h"
-#include "util/u_memory.h"
-#include "cso_cache/cso_context.h"
-
-
-/**
- * Draw a simple vertex buffer / primitive.
- * Limited to float[4] vertex attribs, tightly packed.
- */
-void
-util_draw_vertex_buffer(struct pipe_context *pipe,
- struct cso_context *cso,
- struct pipe_resource *vbuf,
- uint offset,
- uint prim_type,
- uint num_verts,
- uint num_attribs)
-{
- struct pipe_vertex_buffer vbuffer;
-
- assert(num_attribs <= PIPE_MAX_ATTRIBS);
-
- /* tell pipe about the vertex buffer */
- memset(&vbuffer, 0, sizeof(vbuffer));
- vbuffer.buffer = vbuf;
- vbuffer.stride = num_attribs * 4 * sizeof(float); /* vertex size */
- vbuffer.buffer_offset = offset;
-
- if (cso) {
- cso_set_vertex_buffers(cso, 1, &vbuffer);
- } else {
- pipe->set_vertex_buffers(pipe, 1, &vbuffer);
- }
-
- /* note: vertex elements already set by caller */
-
- /* draw */
- util_draw_arrays(pipe, prim_type, 0, num_verts);
-}
-
-
-
-/**
- * Draw screen-aligned textured quad.
- * Note: this isn't especially efficient.
- */
-void
-util_draw_texquad(struct pipe_context *pipe, struct cso_context *cso,
- float x0, float y0, float x1, float y1, float z)
-{
- uint numAttribs = 2, i, j;
- uint vertexBytes = 4 * (4 * numAttribs * sizeof(float));
- struct pipe_resource *vbuf = NULL;
- float *v = NULL;
-
- v = MALLOC(vertexBytes);
- if (v == NULL)
- goto out;
-
- /*
- * Load vertex buffer
- */
- for (i = j = 0; i < 4; i++) {
- v[j + 2] = z; /* z */
- v[j + 3] = 1.0; /* w */
- v[j + 6] = 0.0; /* r */
- v[j + 7] = 1.0; /* q */
- j += 8;
- }
-
- v[0] = x0;
- v[1] = y0;
- v[4] = 0.0; /*s*/
- v[5] = 0.0; /*t*/
-
- v[8] = x1;
- v[9] = y0;
- v[12] = 1.0;
- v[13] = 0.0;
-
- v[16] = x1;
- v[17] = y1;
- v[20] = 1.0;
- v[21] = 1.0;
-
- v[24] = x0;
- v[25] = y1;
- v[28] = 0.0;
- v[29] = 1.0;
-
- vbuf = pipe_user_buffer_create(pipe->screen, v, vertexBytes,
- PIPE_BIND_VERTEX_BUFFER);
- if (!vbuf)
- goto out;
-
- util_draw_vertex_buffer(pipe, cso, vbuf, 0, PIPE_PRIM_TRIANGLE_FAN, 4, 2);
-
-out:
- if (vbuf)
- pipe_resource_reference(&vbuf, NULL);
-
- if (v)
- FREE(v);
-}
+/************************************************************************** + * + * 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. + * + **************************************************************************/ + + +#include "pipe/p_context.h" +#include "pipe/p_defines.h" +#include "util/u_inlines.h" +#include "util/u_draw_quad.h" +#include "util/u_memory.h" +#include "cso_cache/cso_context.h" + + +/** + * Draw a simple vertex buffer / primitive. + * Limited to float[4] vertex attribs, tightly packed. + */ +void +util_draw_vertex_buffer(struct pipe_context *pipe, + struct cso_context *cso, + struct pipe_resource *vbuf, + uint offset, + uint prim_type, + uint num_verts, + uint num_attribs) +{ + struct pipe_vertex_buffer vbuffer; + + assert(num_attribs <= PIPE_MAX_ATTRIBS); + + /* tell pipe about the vertex buffer */ + memset(&vbuffer, 0, sizeof(vbuffer)); + vbuffer.buffer = vbuf; + vbuffer.stride = num_attribs * 4 * sizeof(float); /* vertex size */ + vbuffer.buffer_offset = offset; + + /* note: vertex elements already set by caller */ + + if (cso) { + cso_set_vertex_buffers(cso, 1, &vbuffer); + cso_draw_arrays(cso, prim_type, 0, num_verts); + } else { + pipe->set_vertex_buffers(pipe, 1, &vbuffer); + util_draw_arrays(pipe, prim_type, 0, num_verts); + } +} + + + +/** + * Draw screen-aligned textured quad. + * Note: this isn't especially efficient. + */ +void +util_draw_texquad(struct pipe_context *pipe, struct cso_context *cso, + float x0, float y0, float x1, float y1, float z) +{ + uint numAttribs = 2, i, j; + uint vertexBytes = 4 * (4 * numAttribs * sizeof(float)); + struct pipe_resource *vbuf = NULL; + float *v = NULL; + + v = MALLOC(vertexBytes); + if (v == NULL) + goto out; + + /* + * Load vertex buffer + */ + for (i = j = 0; i < 4; i++) { + v[j + 2] = z; /* z */ + v[j + 3] = 1.0; /* w */ + v[j + 6] = 0.0; /* r */ + v[j + 7] = 1.0; /* q */ + j += 8; + } + + v[0] = x0; + v[1] = y0; + v[4] = 0.0; /*s*/ + v[5] = 0.0; /*t*/ + + v[8] = x1; + v[9] = y0; + v[12] = 1.0; + v[13] = 0.0; + + v[16] = x1; + v[17] = y1; + v[20] = 1.0; + v[21] = 1.0; + + v[24] = x0; + v[25] = y1; + v[28] = 0.0; + v[29] = 1.0; + + vbuf = pipe_user_buffer_create(pipe->screen, v, vertexBytes, + PIPE_BIND_VERTEX_BUFFER); + if (!vbuf) + goto out; + + util_draw_vertex_buffer(pipe, cso, vbuf, 0, PIPE_PRIM_TRIANGLE_FAN, 4, 2); + +out: + if (vbuf) + pipe_resource_reference(&vbuf, NULL); + + if (v) + FREE(v); +} diff --git a/mesalib/src/gallium/auxiliary/util/u_vbuf.c b/mesalib/src/gallium/auxiliary/util/u_vbuf.c index 50c35afd5..401c8a4a8 100644 --- a/mesalib/src/gallium/auxiliary/util/u_vbuf.c +++ b/mesalib/src/gallium/auxiliary/util/u_vbuf.c @@ -52,9 +52,23 @@ struct u_vbuf_elements { /* This might mean two things: * - src_format != native_format, as discussed above. * - src_offset % 4 != 0 (if the caps don't allow such an offset). */ - boolean incompatible_layout; - /* Per-element flags. */ - boolean incompatible_layout_elem[PIPE_MAX_ATTRIBS]; + uint32_t incompatible_elem_mask; /* each bit describes a corresp. attrib */ + /* Which buffer has at least one vertex element referencing it + * incompatible. */ + uint32_t incompatible_vb_mask_any; + /* Which buffer has all vertex elements referencing it incompatible. */ + uint32_t incompatible_vb_mask_all; + /* Which buffer has at least one vertex element referencing it + * compatible. */ + uint32_t compatible_vb_mask_any; + /* Which buffer has all vertex elements referencing it compatible. */ + uint32_t compatible_vb_mask_all; + + /* Which buffer has at least one vertex element referencing it + * non-instanced. */ + uint32_t noninstance_vb_mask_any; + + void *driver_cso; }; enum { @@ -64,101 +78,128 @@ enum { VB_NUM = 3 }; -struct u_vbuf_priv { - struct u_vbuf b; +struct u_vbuf { + struct u_vbuf_caps caps; + struct pipe_context *pipe; struct translate_cache *translate_cache; struct cso_cache *cso_cache; + struct u_upload_mgr *uploader; - /* Vertex element state bound by the state tracker. */ - void *saved_ve; - /* and its associated helper structure for this module. */ - struct u_vbuf_elements *ve; + /* This is what was set in set_vertex_buffers. + * May contain user buffers. */ + struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS]; + unsigned nr_vertex_buffers; + + /* Saved vertex buffers. */ + struct pipe_vertex_buffer vertex_buffer_saved[PIPE_MAX_ATTRIBS]; + unsigned nr_vertex_buffers_saved; + + /* Vertex buffers for the driver. + * There are no user buffers. */ + struct pipe_vertex_buffer real_vertex_buffer[PIPE_MAX_ATTRIBS]; + int nr_real_vertex_buffers; + boolean vertex_buffers_dirty; + + /* The index buffer. */ + struct pipe_index_buffer index_buffer; + + /* Vertex elements. */ + struct u_vbuf_elements *ve, *ve_saved; /* Vertex elements used for the translate fallback. */ struct pipe_vertex_element fallback_velems[PIPE_MAX_ATTRIBS]; /* If non-NULL, this is a vertex element state used for the translate * fallback and therefore used for rendering too. */ - void *fallback_ve; + boolean using_translate; /* The vertex buffer slot index where translated vertices have been * stored in. */ unsigned fallback_vbs[VB_NUM]; - /* When binding the fallback vertex element state, we don't want to - * change saved_ve and ve. This is set to TRUE in such cases. */ - boolean ve_binding_lock; - - /* Whether there is any user buffer. */ - boolean any_user_vbs; - /* Whether there is a buffer with a non-native layout. */ - boolean incompatible_vb_layout; - /* Per-buffer flags. */ - boolean incompatible_vb[PIPE_MAX_ATTRIBS]; + + /* Which buffer is a user buffer. */ + uint32_t user_vb_mask; /* each bit describes a corresp. buffer */ + /* Which buffer is incompatible (unaligned). */ + uint32_t incompatible_vb_mask; /* each bit describes a corresp. buffer */ + /* Which buffer has a non-zero stride. */ + uint32_t nonzero_stride_vb_mask; /* each bit describes a corresp. buffer */ }; -static void u_vbuf_init_format_caps(struct u_vbuf_priv *mgr) -{ - struct pipe_screen *screen = mgr->pipe->screen; +static void * +u_vbuf_create_vertex_elements(struct u_vbuf *mgr, unsigned count, + const struct pipe_vertex_element *attribs); +static void u_vbuf_delete_vertex_elements(struct u_vbuf *mgr, void *cso); - mgr->b.caps.format_fixed32 = + +void u_vbuf_get_caps(struct pipe_screen *screen, struct u_vbuf_caps *caps) +{ + caps->format_fixed32 = screen->is_format_supported(screen, PIPE_FORMAT_R32_FIXED, PIPE_BUFFER, 0, PIPE_BIND_VERTEX_BUFFER); - mgr->b.caps.format_float16 = + caps->format_float16 = screen->is_format_supported(screen, PIPE_FORMAT_R16_FLOAT, PIPE_BUFFER, 0, PIPE_BIND_VERTEX_BUFFER); - mgr->b.caps.format_float64 = + caps->format_float64 = screen->is_format_supported(screen, PIPE_FORMAT_R64_FLOAT, PIPE_BUFFER, 0, PIPE_BIND_VERTEX_BUFFER); - mgr->b.caps.format_norm32 = + caps->format_norm32 = screen->is_format_supported(screen, PIPE_FORMAT_R32_UNORM, PIPE_BUFFER, 0, PIPE_BIND_VERTEX_BUFFER) && screen->is_format_supported(screen, PIPE_FORMAT_R32_SNORM, PIPE_BUFFER, 0, PIPE_BIND_VERTEX_BUFFER); - mgr->b.caps.format_scaled32 = + caps->format_scaled32 = screen->is_format_supported(screen, PIPE_FORMAT_R32_USCALED, PIPE_BUFFER, 0, PIPE_BIND_VERTEX_BUFFER) && screen->is_format_supported(screen, PIPE_FORMAT_R32_SSCALED, PIPE_BUFFER, 0, PIPE_BIND_VERTEX_BUFFER); + + caps->buffer_offset_unaligned = + !screen->get_param(screen, + PIPE_CAP_VERTEX_BUFFER_OFFSET_4BYTE_ALIGNED_ONLY); + + caps->buffer_stride_unaligned = + !screen->get_param(screen, + PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY); + + caps->velem_src_offset_unaligned = + !screen->get_param(screen, + PIPE_CAP_VERTEX_ELEMENT_SRC_OFFSET_4BYTE_ALIGNED_ONLY); + + caps->user_vertex_buffers = + screen->get_param(screen, PIPE_CAP_USER_VERTEX_BUFFERS); } struct u_vbuf * u_vbuf_create(struct pipe_context *pipe, - unsigned upload_buffer_size, - unsigned upload_buffer_alignment, - unsigned upload_buffer_bind, - enum u_fetch_alignment fetch_alignment) + struct u_vbuf_caps *caps) { - struct u_vbuf_priv *mgr = CALLOC_STRUCT(u_vbuf_priv); + struct u_vbuf *mgr = CALLOC_STRUCT(u_vbuf); + mgr->caps = *caps; mgr->pipe = pipe; mgr->cso_cache = cso_cache_create(); mgr->translate_cache = translate_cache_create(); memset(mgr->fallback_vbs, ~0, sizeof(mgr->fallback_vbs)); - mgr->b.uploader = u_upload_create(pipe, upload_buffer_size, - upload_buffer_alignment, - upload_buffer_bind); - - mgr->b.caps.fetch_dword_unaligned = - fetch_alignment == U_VERTEX_FETCH_BYTE_ALIGNED; - - u_vbuf_init_format_caps(mgr); + mgr->uploader = u_upload_create(pipe, 1024 * 1024, 4, + PIPE_BIND_VERTEX_BUFFER); - return &mgr->b; + return mgr; } -/* XXX I had to fork this off of cso_context. */ -static void * -u_vbuf_pipe_set_vertex_elements(struct u_vbuf_priv *mgr, - unsigned count, - const struct pipe_vertex_element *states) +/* u_vbuf uses its own caching for vertex elements, because it needs to keep + * its own preprocessed state per vertex element CSO. */ +static struct u_vbuf_elements * +u_vbuf_set_vertex_elements_internal(struct u_vbuf *mgr, unsigned count, + const struct pipe_vertex_element *states) { + struct pipe_context *pipe = mgr->pipe; unsigned key_size, hash_key; struct cso_hash_iter iter; - void *handle; + struct u_vbuf_elements *ve; struct cso_velems_state velems_state; /* need to include the count into the stored state data too. */ @@ -173,47 +214,52 @@ u_vbuf_pipe_set_vertex_elements(struct u_vbuf_priv *mgr, if (cso_hash_iter_is_null(iter)) { struct cso_velements *cso = MALLOC_STRUCT(cso_velements); memcpy(&cso->state, &velems_state, key_size); - cso->data = - mgr->pipe->create_vertex_elements_state(mgr->pipe, count, - &cso->state.velems[0]); - cso->delete_state = - (cso_state_callback)mgr->pipe->delete_vertex_elements_state; - cso->context = mgr->pipe; + cso->data = u_vbuf_create_vertex_elements(mgr, count, states); + cso->delete_state = (cso_state_callback)u_vbuf_delete_vertex_elements; + cso->context = (void*)mgr; iter = cso_insert_state(mgr->cso_cache, hash_key, CSO_VELEMENTS, cso); - handle = cso->data; + ve = cso->data; } else { - handle = ((struct cso_velements *)cso_hash_iter_data(iter))->data; + ve = ((struct cso_velements *)cso_hash_iter_data(iter))->data; } - mgr->pipe->bind_vertex_elements_state(mgr->pipe, handle); - return handle; + assert(ve); + pipe->bind_vertex_elements_state(pipe, ve->driver_cso); + return ve; +} + +void u_vbuf_set_vertex_elements(struct u_vbuf *mgr, unsigned count, + const struct pipe_vertex_element *states) +{ + mgr->ve = u_vbuf_set_vertex_elements_internal(mgr, count, states); } -void u_vbuf_destroy(struct u_vbuf *mgrb) +void u_vbuf_destroy(struct u_vbuf *mgr) { - struct u_vbuf_priv *mgr = (struct u_vbuf_priv*)mgrb; unsigned i; - for (i = 0; i < mgr->b.nr_vertex_buffers; i++) { - pipe_resource_reference(&mgr->b.vertex_buffer[i].buffer, NULL); + mgr->pipe->set_vertex_buffers(mgr->pipe, 0, NULL); + + for (i = 0; i < mgr->nr_vertex_buffers; i++) { + pipe_resource_reference(&mgr->vertex_buffer[i].buffer, NULL); } - for (i = 0; i < mgr->b.nr_real_vertex_buffers; i++) { - pipe_resource_reference(&mgr->b.real_vertex_buffer[i].buffer, NULL); + for (i = 0; i < mgr->nr_real_vertex_buffers; i++) { + pipe_resource_reference(&mgr->real_vertex_buffer[i].buffer, NULL); } translate_cache_destroy(mgr->translate_cache); - u_upload_destroy(mgr->b.uploader); + u_upload_destroy(mgr->uploader); cso_cache_delete(mgr->cso_cache); FREE(mgr); } static void -u_vbuf_translate_buffers(struct u_vbuf_priv *mgr, struct translate_key *key, +u_vbuf_translate_buffers(struct u_vbuf *mgr, struct translate_key *key, unsigned vb_mask, unsigned out_vb, int start_vertex, unsigned num_vertices, int start_index, unsigned num_indices, int min_index, - bool unroll_indices) + boolean unroll_indices) { struct translate *tr; struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS] = {0}; @@ -225,14 +271,14 @@ u_vbuf_translate_buffers(struct u_vbuf_priv *mgr, struct translate_key *key, tr = translate_cache_find(mgr->translate_cache, key); /* Map buffers we want to translate. */ - for (i = 0; i < mgr->b.nr_vertex_buffers; i++) { + for (i = 0; i < mgr->nr_vertex_buffers; i++) { if (vb_mask & (1 << i)) { - struct pipe_vertex_buffer *vb = &mgr->b.vertex_buffer[i]; + struct pipe_vertex_buffer *vb = &mgr->vertex_buffer[i]; unsigned offset = vb->buffer_offset + vb->stride * start_vertex; uint8_t *map; - if (u_vbuf_resource(vb->buffer)->user_ptr) { - map = u_vbuf_resource(vb->buffer)->user_ptr + offset; + if (vb->buffer->user_ptr) { + map = vb->buffer->user_ptr + offset; } else { unsigned size = vb->stride ? num_vertices * vb->stride : sizeof(double)*4; @@ -256,15 +302,15 @@ u_vbuf_translate_buffers(struct u_vbuf_priv *mgr, struct translate_key *key, /* Translate. */ if (unroll_indices) { - struct pipe_index_buffer *ib = &mgr->b.index_buffer; + struct pipe_index_buffer *ib = &mgr->index_buffer; struct pipe_transfer *transfer = NULL; unsigned offset = ib->offset + start_index * ib->index_size; uint8_t *map; assert(ib->buffer && ib->index_size); - if (u_vbuf_resource(ib->buffer)->user_ptr) { - map = u_vbuf_resource(ib->buffer)->user_ptr + offset; + if (ib->buffer->user_ptr) { + map = ib->buffer->user_ptr + offset; } else { map = pipe_buffer_map_range(mgr->pipe, ib->buffer, offset, num_indices * ib->index_size, @@ -272,7 +318,7 @@ u_vbuf_translate_buffers(struct u_vbuf_priv *mgr, struct translate_key *key, } /* Create and map the output buffer. */ - u_upload_alloc(mgr->b.uploader, 0, + u_upload_alloc(mgr->uploader, 0, key->output_stride * num_indices, &out_offset, &out_buffer, (void**)&out_map); @@ -294,7 +340,7 @@ u_vbuf_translate_buffers(struct u_vbuf_priv *mgr, struct translate_key *key, } } else { /* Create and map the output buffer. */ - u_upload_alloc(mgr->b.uploader, + u_upload_alloc(mgr->uploader, key->output_stride * start_vertex, key->output_stride * num_vertices, &out_offset, &out_buffer, @@ -306,64 +352,52 @@ u_vbuf_translate_buffers(struct u_vbuf_priv *mgr, struct translate_key *key, } /* Unmap all buffers. */ - for (i = 0; i < mgr->b.nr_vertex_buffers; i++) { + for (i = 0; i < mgr->nr_vertex_buffers; i++) { if (vb_transfer[i]) { pipe_buffer_unmap(mgr->pipe, vb_transfer[i]); } } /* Setup the new vertex buffer. */ - mgr->b.real_vertex_buffer[out_vb].buffer_offset = out_offset; - mgr->b.real_vertex_buffer[out_vb].stride = key->output_stride; + mgr->real_vertex_buffer[out_vb].buffer_offset = out_offset; + mgr->real_vertex_buffer[out_vb].stride = key->output_stride; /* Move the buffer reference. */ pipe_resource_reference( - &mgr->b.real_vertex_buffer[out_vb].buffer, NULL); - mgr->b.real_vertex_buffer[out_vb].buffer = out_buffer; + &mgr->real_vertex_buffer[out_vb].buffer, NULL); + mgr->real_vertex_buffer[out_vb].buffer = out_buffer; } static boolean -u_vbuf_translate_find_free_vb_slots(struct u_vbuf_priv *mgr, +u_vbuf_translate_find_free_vb_slots(struct u_vbuf *mgr, unsigned mask[VB_NUM]) { - unsigned i, type; - unsigned nr = mgr->ve->count; - boolean used_vb[PIPE_MAX_ATTRIBS] = {0}; + unsigned type; unsigned fallback_vbs[VB_NUM]; + /* Set the bit for each buffer which is incompatible, or isn't set. */ + uint32_t unused_vb_mask = + mgr->ve->incompatible_vb_mask_all | mgr->incompatible_vb_mask | + ~((1 << mgr->nr_vertex_buffers) - 1); memset(fallback_vbs, ~0, sizeof(fallback_vbs)); - /* Mark used vertex buffers as... used. */ - for (i = 0; i < nr; i++) { - if (!mgr->ve->incompatible_layout_elem[i]) { - unsigned index = mgr->ve->ve[i].vertex_buffer_index; - - if (!mgr->incompatible_vb[index]) { - used_vb[index] = TRUE; - } - } - } - /* Find free slots for each type if needed. */ - i = 0; for (type = 0; type < VB_NUM; type++) { if (mask[type]) { - for (; i < PIPE_MAX_ATTRIBS; i++) { - if (!used_vb[i]) { - /*printf("found slot=%i for type=%i\n", i, type);*/ - fallback_vbs[type] = i; - i++; - if (i > mgr->b.nr_real_vertex_buffers) { - mgr->b.nr_real_vertex_buffers = i; - } - break; - } - } - if (i == PIPE_MAX_ATTRIBS) { + uint32_t index; + + if (!unused_vb_mask) { /* fail, reset the number to its original value */ - mgr->b.nr_real_vertex_buffers = mgr->b.nr_vertex_buffers; + mgr->nr_real_vertex_buffers = mgr->nr_vertex_buffers; return FALSE; } + + index = ffs(unused_vb_mask) - 1; + fallback_vbs[type] = index; + if (index >= mgr->nr_real_vertex_buffers) { + mgr->nr_real_vertex_buffers = index + 1; + } + /*printf("found slot=%i for type=%i\n", index, type);*/ } } @@ -372,11 +406,11 @@ u_vbuf_translate_find_free_vb_slots(struct u_vbuf_priv *mgr, } static boolean -u_vbuf_translate_begin(struct u_vbuf_priv *mgr, +u_vbuf_translate_begin(struct u_vbuf *mgr, int start_vertex, unsigned num_vertices, int start_instance, unsigned num_instances, int start_index, unsigned num_indices, int min_index, - bool unroll_indices) + boolean unroll_indices) { unsigned mask[VB_NUM] = {0}; struct translate_key key[VB_NUM]; @@ -403,22 +437,22 @@ u_vbuf_translate_begin(struct u_vbuf_priv *mgr, for (i = 0; i < mgr->ve->count; i++) { unsigned vb_index = mgr->ve->ve[i].vertex_buffer_index; - if (!mgr->b.vertex_buffer[vb_index].stride) { - if (!mgr->ve->incompatible_layout_elem[i] && - !mgr->incompatible_vb[vb_index]) { + if (!mgr->vertex_buffer[vb_index].stride) { + if (!(mgr->ve->incompatible_elem_mask & (1 << i)) && + !(mgr->incompatible_vb_mask & (1 << vb_index))) { continue; } mask[VB_CONST] |= 1 << vb_index; } else if (mgr->ve->ve[i].instance_divisor) { - if (!mgr->ve->incompatible_layout_elem[i] && - !mgr->incompatible_vb[vb_index]) { + if (!(mgr->ve->incompatible_elem_mask & (1 << i)) && + !(mgr->incompatible_vb_mask & (1 << vb_index))) { continue; } mask[VB_INSTANCE] |= 1 << vb_index; } else { if (!unroll_indices && - !mgr->ve->incompatible_layout_elem[i] && - !mgr->incompatible_vb[vb_index]) { + !(mgr->ve->incompatible_elem_mask & (1 << i)) && + !(mgr->incompatible_vb_mask & (1 << vb_index))) { continue; } mask[VB_VERTEX] |= 1 << vb_index; @@ -439,8 +473,8 @@ u_vbuf_translate_begin(struct u_vbuf_priv *mgr, unsigned bit, vb_index = mgr->ve->ve[i].vertex_buffer_index; bit = 1 << vb_index; - if (!mgr->ve->incompatible_layout_elem[i] && - !mgr->incompatible_vb[vb_index] && + if (!(mgr->ve->incompatible_elem_mask & (1 << i)) && + !(mgr->incompatible_vb_mask & (1 << vb_index)) && (!unroll_indices || !(mask[VB_VERTEX] & bit))) { continue; } @@ -484,7 +518,7 @@ u_vbuf_translate_begin(struct u_vbuf_priv *mgr, /* Fixup the stride for constant attribs. */ if (type == VB_CONST) { - mgr->b.real_vertex_buffer[mgr->fallback_vbs[VB_CONST]].stride = 0; + mgr->real_vertex_buffer[mgr->fallback_vbs[VB_CONST]].stride = 0; } } } @@ -512,55 +546,48 @@ u_vbuf_translate_begin(struct u_vbuf_priv *mgr, } } - /* Preserve saved_ve. */ - mgr->ve_binding_lock = TRUE; - mgr->fallback_ve = u_vbuf_pipe_set_vertex_elements(mgr, mgr->ve->count, - mgr->fallback_velems); - mgr->ve_binding_lock = FALSE; + u_vbuf_set_vertex_elements_internal(mgr, mgr->ve->count, + mgr->fallback_velems); + mgr->using_translate = TRUE; return TRUE; } -static void u_vbuf_translate_end(struct u_vbuf_priv *mgr) +static void u_vbuf_translate_end(struct u_vbuf *mgr) { unsigned i; /* Restore vertex elements. */ - /* Note that saved_ve will be overwritten in bind_vertex_elements_state. */ - mgr->pipe->bind_vertex_elements_state(mgr->pipe, mgr->saved_ve); - mgr->fallback_ve = NULL; + mgr->pipe->bind_vertex_elements_state(mgr->pipe, mgr->ve->driver_cso); + mgr->using_translate = FALSE; /* Unreference the now-unused VBOs. */ for (i = 0; i < VB_NUM; i++) { unsigned vb = mgr->fallback_vbs[i]; if (vb != ~0) { - pipe_resource_reference(&mgr->b.real_vertex_buffer[vb].buffer, NULL); + pipe_resource_reference(&mgr->real_vertex_buffer[vb].buffer, NULL); mgr->fallback_vbs[i] = ~0; } } - mgr->b.nr_real_vertex_buffers = mgr->b.nr_vertex_buffers; + mgr->nr_real_vertex_buffers = mgr->nr_vertex_buffers; } #define FORMAT_REPLACE(what, withwhat) \ case PIPE_FORMAT_##what: format = PIPE_FORMAT_##withwhat; break -struct u_vbuf_elements * -u_vbuf_create_vertex_elements(struct u_vbuf *mgrb, - unsigned count, - const struct pipe_vertex_element *attribs, - struct pipe_vertex_element *native_attribs) +static void * +u_vbuf_create_vertex_elements(struct u_vbuf *mgr, unsigned count, + const struct pipe_vertex_element *attribs) { - struct u_vbuf_priv *mgr = (struct u_vbuf_priv*)mgrb; + struct pipe_context *pipe = mgr->pipe; unsigned i; + struct pipe_vertex_element driver_attribs[PIPE_MAX_ATTRIBS]; struct u_vbuf_elements *ve = CALLOC_STRUCT(u_vbuf_elements); + uint32_t used_buffers = 0; ve->count = count; - if (!count) { - return ve; - } - memcpy(ve->ve, attribs, sizeof(struct pipe_vertex_element) * count); - memcpy(native_attribs, attribs, sizeof(struct pipe_vertex_element) * count); + memcpy(driver_attribs, attribs, sizeof(struct pipe_vertex_element) * count); /* Set the best native format in case the original format is not * supported. */ @@ -569,10 +596,16 @@ u_vbuf_create_vertex_elements(struct u_vbuf *mgrb, ve->src_format_size[i] = util_format_get_blocksize(format); + used_buffers |= 1 << ve->ve[i].vertex_buffer_index; + + if (!ve->ve[i].instance_divisor) { + ve->noninstance_vb_mask_any |= 1 << ve->ve[i].vertex_buffer_index; + } + /* Choose a native format. * For now we don't care about the alignment, that's going to * be sorted out later. */ - if (!mgr->b.caps.format_fixed32) { + if (!mgr->caps.format_fixed32) { switch (format) { FORMAT_REPLACE(R32_FIXED, R32_FLOAT); FORMAT_REPLACE(R32G32_FIXED, R32G32_FLOAT); @@ -581,7 +614,7 @@ u_vbuf_create_vertex_elements(struct u_vbuf *mgrb, default:; } } - if (!mgr->b.caps.format_float16) { + if (!mgr->caps.format_float16) { switch (format) { FORMAT_REPLACE(R16_FLOAT, R32_FLOAT); FORMAT_REPLACE(R16G16_FLOAT, R32G32_FLOAT); @@ -590,7 +623,7 @@ u_vbuf_create_vertex_elements(struct u_vbuf *mgrb, default:; } } - if (!mgr->b.caps.format_float64) { + if (!mgr->caps.format_float64) { switch (format) { FORMAT_REPLACE(R64_FLOAT, R32_FLOAT); FORMAT_REPLACE(R64G64_FLOAT, R32G32_FLOAT); @@ -599,7 +632,7 @@ u_vbuf_create_vertex_elements(struct u_vbuf *mgrb, default:; } } - if (!mgr->b.caps.format_norm32) { + if (!mgr->caps.format_norm32) { switch (format) { FORMAT_REPLACE(R32_UNORM, R32_FLOAT); FORMAT_REPLACE(R32G32_UNORM, R32G32_FLOAT); @@ -612,7 +645,7 @@ u_vbuf_create_vertex_elements(struct u_vbuf *mgrb, default:; } } - if (!mgr->b.caps.format_scaled32) { + if (!mgr->caps.format_scaled32) { switch (format) { FORMAT_REPLACE(R32_USCALED, R32_FLOAT); FORMAT_REPLACE(R32G32_USCALED, R32G32_FLOAT); @@ -626,115 +659,106 @@ u_vbuf_create_vertex_elements(struct u_vbuf *mgrb, } } - native_attribs[i].src_format = format; + driver_attribs[i].src_format = format; ve->native_format[i] = format; ve->native_format_size[i] = util_format_get_blocksize(ve->native_format[i]); - ve->incompatible_layout_elem[i] = - ve->ve[i].src_format != ve->native_format[i] || - (!mgr->b.caps.fetch_dword_unaligned && ve->ve[i].src_offset % 4 != 0); - ve->incompatible_layout = - ve->incompatible_layout || - ve->incompatible_layout_elem[i]; + if (ve->ve[i].src_format != format || + (!mgr->caps.velem_src_offset_unaligned && + ve->ve[i].src_offset % 4 != 0)) { + ve->incompatible_elem_mask |= 1 << i; + ve->incompatible_vb_mask_any |= 1 << ve->ve[i].vertex_buffer_index; + } else { + ve->compatible_vb_mask_any |= 1 << ve->ve[i].vertex_buffer_index; + } } + ve->compatible_vb_mask_all = ~ve->incompatible_vb_mask_any & used_buffers; + ve->incompatible_vb_mask_all = ~ve->compatible_vb_mask_any & used_buffers; + /* Align the formats to the size of DWORD if needed. */ - if (!mgr->b.caps.fetch_dword_unaligned) { + if (!mgr->caps.velem_src_offset_unaligned) { for (i = 0; i < count; i++) { ve->native_format_size[i] = align(ve->native_format_size[i], 4); } } + ve->driver_cso = + pipe->create_vertex_elements_state(pipe, count, driver_attribs); return ve; } -void u_vbuf_bind_vertex_elements(struct u_vbuf *mgrb, - void *cso, - struct u_vbuf_elements *ve) +static void u_vbuf_delete_vertex_elements(struct u_vbuf *mgr, void *cso) { - struct u_vbuf_priv *mgr = (struct u_vbuf_priv*)mgrb; - - if (!cso) { - return; - } - - if (!mgr->ve_binding_lock) { - mgr->saved_ve = cso; - mgr->ve = ve; - } -} + struct pipe_context *pipe = mgr->pipe; + struct u_vbuf_elements *ve = cso; -void u_vbuf_destroy_vertex_elements(struct u_vbuf *mgr, - struct u_vbuf_elements *ve) -{ + pipe->delete_vertex_elements_state(pipe, ve->driver_cso); FREE(ve); } -void u_vbuf_set_vertex_buffers(struct u_vbuf *mgrb, - unsigned count, +void u_vbuf_set_vertex_buffers(struct u_vbuf *mgr, unsigned count, const struct pipe_vertex_buffer *bufs) { - struct u_vbuf_priv *mgr = (struct u_vbuf_priv*)mgrb; unsigned i; - mgr->any_user_vbs = FALSE; - mgr->incompatible_vb_layout = FALSE; - memset(mgr->incompatible_vb, 0, sizeof(mgr->incompatible_vb)); - - if (!mgr->b.caps.fetch_dword_unaligned) { - /* Check if the strides and offsets are aligned to the size of DWORD. */ - for (i = 0; i < count; i++) { - if (bufs[i].buffer) { - if (bufs[i].stride % 4 != 0 || - bufs[i].buffer_offset % 4 != 0) { - mgr->incompatible_vb_layout = TRUE; - mgr->incompatible_vb[i] = TRUE; - } - } - } - } + mgr->user_vb_mask = 0; + mgr->incompatible_vb_mask = 0; + mgr->nonzero_stride_vb_mask = 0; for (i = 0; i < count; i++) { const struct pipe_vertex_buffer *vb = &bufs[i]; + struct pipe_vertex_buffer *orig_vb = &mgr->vertex_buffer[i]; + struct pipe_vertex_buffer *real_vb = &mgr->real_vertex_buffer[i]; - pipe_resource_reference(&mgr->b.vertex_buffer[i].buffer, vb->buffer); + pipe_resource_reference(&orig_vb->buffer, vb->buffer); - mgr->b.real_vertex_buffer[i].buffer_offset = - mgr->b.vertex_buffer[i].buffer_offset = vb->buffer_offset; + real_vb->buffer_offset = orig_vb->buffer_offset = vb->buffer_offset; + real_vb->stride = orig_vb->stride = vb->stride; - mgr->b.real_vertex_buffer[i].stride = - mgr->b.vertex_buffer[i].stride = vb->stride; + if (vb->stride) { + mgr->nonzero_stride_vb_mask |= 1 << i; + } + + if (!vb->buffer) { + pipe_resource_reference(&real_vb->buffer, NULL); + continue; + } - if (!vb->buffer || - mgr->incompatible_vb[i]) { - pipe_resource_reference(&mgr->b.real_vertex_buffer[i].buffer, NULL); + if ((!mgr->caps.buffer_offset_unaligned && vb->buffer_offset % 4 != 0) || + (!mgr->caps.buffer_stride_unaligned && vb->stride % 4 != 0)) { + mgr->incompatible_vb_mask |= 1 << i; + pipe_resource_reference(&real_vb->buffer, NULL); continue; } - if (u_vbuf_resource(vb->buffer)->user_ptr) { - pipe_resource_reference(&mgr->b.real_vertex_buffer[i].buffer, NULL); - mgr->any_user_vbs = TRUE; + if (!mgr->caps.user_vertex_buffers && vb->buffer->user_ptr) { + mgr->user_vb_mask |= 1 << i; + pipe_resource_reference(&real_vb->buffer, NULL); continue; } - pipe_resource_reference(&mgr->b.real_vertex_buffer[i].buffer, vb->buffer); + pipe_resource_reference(&real_vb->buffer, vb->buffer); } - for (i = count; i < mgr->b.nr_vertex_buffers; i++) { - pipe_resource_reference(&mgr->b.vertex_buffer[i].buffer, NULL); + for (i = count; i < mgr->nr_vertex_buffers; i++) { + pipe_resource_reference(&mgr->vertex_buffer[i].buffer, NULL); } - for (i = count; i < mgr->b.nr_real_vertex_buffers; i++) { - pipe_resource_reference(&mgr->b.real_vertex_buffer[i].buffer, NULL); + for (i = count; i < mgr->nr_real_vertex_buffers; i++) { + pipe_resource_reference(&mgr->real_vertex_buffer[i].buffer, NULL); } - mgr->b.nr_vertex_buffers = count; - mgr->b.nr_real_vertex_buffers = count; + mgr->nr_vertex_buffers = count; + mgr->nr_real_vertex_buffers = count; + mgr->vertex_buffers_dirty = TRUE; } void u_vbuf_set_index_buffer(struct u_vbuf *mgr, const struct pipe_index_buffer *ib) { + struct pipe_context *pipe = mgr->pipe; + if (ib && ib->buffer) { assert(ib->offset % ib->index_size == 0); pipe_resource_reference(&mgr->index_buffer.buffer, ib->buffer); @@ -743,18 +767,20 @@ void u_vbuf_set_index_buffer(struct u_vbuf *mgr, } else { pipe_resource_reference(&mgr->index_buffer.buffer, NULL); } + + pipe->set_index_buffer(pipe, ib); } static void -u_vbuf_upload_buffers(struct u_vbuf_priv *mgr, +u_vbuf_upload_buffers(struct u_vbuf *mgr, int start_vertex, unsigned num_vertices, int start_instance, unsigned num_instances) { unsigned i; unsigned nr_velems = mgr->ve->count; - unsigned nr_vbufs = mgr->b.nr_vertex_buffers; + unsigned nr_vbufs = mgr->nr_vertex_buffers; struct pipe_vertex_element *velems = - mgr->fallback_ve ? mgr->fallback_velems : mgr->ve->ve; + mgr->using_translate ? mgr->fallback_velems : mgr->ve->ve; unsigned start_offset[PIPE_MAX_ATTRIBS]; unsigned end_offset[PIPE_MAX_ATTRIBS] = {0}; @@ -762,7 +788,7 @@ u_vbuf_upload_buffers(struct u_vbuf_priv *mgr, for (i = 0; i < nr_velems; i++) { struct pipe_vertex_element *velem = &velems[i]; unsigned index = velem->vertex_buffer_index; - struct pipe_vertex_buffer *vb = &mgr->b.vertex_buffer[index]; + struct pipe_vertex_buffer *vb = &mgr->vertex_buffer[index]; unsigned instance_div, first, size; /* Skip the buffers generated by translate. */ @@ -774,7 +800,7 @@ u_vbuf_upload_buffers(struct u_vbuf_priv *mgr, assert(vb->buffer); - if (!u_vbuf_resource(vb->buffer)->user_ptr) { + if (!vb->buffer->user_ptr) { continue; } @@ -820,129 +846,35 @@ u_vbuf_upload_buffers(struct u_vbuf_priv *mgr, start = start_offset[i]; assert(start < end); - real_vb = &mgr->b.real_vertex_buffer[i]; - ptr = u_vbuf_resource(mgr->b.vertex_buffer[i].buffer)->user_ptr; + real_vb = &mgr->real_vertex_buffer[i]; + ptr = mgr->vertex_buffer[i].buffer->user_ptr; - u_upload_data(mgr->b.uploader, start, end - start, ptr + start, + u_upload_data(mgr->uploader, start, end - start, ptr + start, &real_vb->buffer_offset, &real_vb->buffer); real_vb->buffer_offset -= start; } } -unsigned u_vbuf_draw_max_vertex_count(struct u_vbuf *mgrb) -{ - struct u_vbuf_priv *mgr = (struct u_vbuf_priv*)mgrb; - unsigned i, nr = mgr->ve->count; - struct pipe_vertex_element *velems = - mgr->fallback_ve ? mgr->fallback_velems : mgr->ve->ve; - unsigned result = ~0; - - for (i = 0; i < nr; i++) { - struct pipe_vertex_buffer *vb = - &mgr->b.real_vertex_buffer[velems[i].vertex_buffer_index]; - unsigned size, max_count, value; - - /* We're not interested in constant and per-instance attribs. */ - if (!vb->buffer || - !vb->stride || - velems[i].instance_divisor) { - continue; - } - - size = vb->buffer->width0; - - /* Subtract buffer_offset. */ - value = vb->buffer_offset; - if (value >= size) { - return 0; - } - size -= value; - - /* Subtract src_offset. */ - value = velems[i].src_offset; - if (value >= size) { - return 0; - } - size -= value; - - /* Subtract format_size. */ - value = mgr->ve->native_format_size[i]; - if (value >= size) { - return 0; - } - size -= value; - - /* Compute the max count. */ - max_count = 1 + size / vb->stride; - result = MIN2(result, max_count); - } - return result; -} - -static boolean u_vbuf_need_minmax_index(struct u_vbuf_priv *mgr) +static boolean u_vbuf_need_minmax_index(struct u_vbuf *mgr) { - unsigned i, nr = mgr->ve->count; - - for (i = 0; i < nr; i++) { - struct pipe_vertex_buffer *vb; - unsigned index; - - /* Per-instance attribs don't need min/max_index. */ - if (mgr->ve->ve[i].instance_divisor) { - continue; - } - - index = mgr->ve->ve[i].vertex_buffer_index; - vb = &mgr->b.vertex_buffer[index]; - - /* Constant attribs don't need min/max_index. */ - if (!vb->stride) { - continue; - } - - /* Per-vertex attribs need min/max_index. */ - if (u_vbuf_resource(vb->buffer)->user_ptr || - mgr->ve->incompatible_layout_elem[i] || - mgr->incompatible_vb[index]) { - return TRUE; - } - } - - return FALSE; + /* See if there are any per-vertex attribs which will be uploaded or + * translated. Use bitmasks to get the info instead of looping over vertex + * elements. */ + return ((mgr->user_vb_mask | mgr->incompatible_vb_mask | + mgr->ve->incompatible_vb_mask_any) & + mgr->ve->noninstance_vb_mask_any & mgr->nonzero_stride_vb_mask) != 0; } -static boolean u_vbuf_mapping_vertex_buffer_blocks(struct u_vbuf_priv *mgr) +static boolean u_vbuf_mapping_vertex_buffer_blocks(struct u_vbuf *mgr) { - unsigned i, nr = mgr->ve->count; - - for (i = 0; i < nr; i++) { - struct pipe_vertex_buffer *vb; - unsigned index; - - /* Per-instance attribs are not per-vertex data. */ - if (mgr->ve->ve[i].instance_divisor) { - continue; - } - - index = mgr->ve->ve[i].vertex_buffer_index; - vb = &mgr->b.vertex_buffer[index]; - - /* Constant attribs are not per-vertex data. */ - if (!vb->stride) { - continue; - } - - /* Return true for the hw buffers which don't need to be translated. */ - /* XXX we could use some kind of a is-busy query. */ - if (!u_vbuf_resource(vb->buffer)->user_ptr && - !mgr->ve->incompatible_layout_elem[i] && - !mgr->incompatible_vb[index]) { - return TRUE; - } - } - - return FALSE; + /* Return true if there are hw buffers which don't need to be translated. + * + * We could query whether each buffer is busy, but that would + * be way more costly than this. */ + return (~mgr->user_vb_mask & ~mgr->incompatible_vb_mask & + mgr->ve->compatible_vb_mask_all & mgr->ve->noninstance_vb_mask_any & + mgr->nonzero_stride_vb_mask) != 0; } static void u_vbuf_get_minmax_index(struct pipe_context *pipe, @@ -956,8 +888,8 @@ static void u_vbuf_get_minmax_index(struct pipe_context *pipe, unsigned i; unsigned restart_index = info->restart_index; - if (u_vbuf_resource(ib->buffer)->user_ptr) { - indices = u_vbuf_resource(ib->buffer)->user_ptr + + if (ib->buffer->user_ptr) { + indices = ib->buffer->user_ptr + ib->offset + info->start * ib->index_size; } else { indices = pipe_buffer_map_range(pipe, ib->buffer, @@ -1044,38 +976,42 @@ static void u_vbuf_get_minmax_index(struct pipe_context *pipe, } } -enum u_vbuf_return_flags -u_vbuf_draw_begin(struct u_vbuf *mgrb, - struct pipe_draw_info *info) +void u_vbuf_draw_vbo(struct u_vbuf *mgr, const struct pipe_draw_info *info) { - struct u_vbuf_priv *mgr = (struct u_vbuf_priv*)mgrb; + struct pipe_context *pipe = mgr->pipe; int start_vertex, min_index; unsigned num_vertices; - bool unroll_indices = false; + boolean unroll_indices = FALSE; + uint32_t user_vb_mask = mgr->user_vb_mask; + + /* Normal draw. No fallback and no user buffers. */ + if (!mgr->incompatible_vb_mask && + !mgr->ve->incompatible_elem_mask && + !user_vb_mask) { + /* Set vertex buffers if needed. */ + if (mgr->vertex_buffers_dirty) { + pipe->set_vertex_buffers(pipe, mgr->nr_real_vertex_buffers, + mgr->real_vertex_buffer); + mgr->vertex_buffers_dirty = FALSE; + } - if (!mgr->incompatible_vb_layout && - !mgr->ve->incompatible_layout && - !mgr->any_user_vbs) { - return 0; + pipe->draw_vbo(pipe, info); + return; } if (info->indexed) { - int max_index; - bool index_bounds_valid = false; - - if (info->max_index != ~0) { - min_index = info->min_index; - max_index = info->max_index; - index_bounds_valid = true; - } else if (u_vbuf_need_minmax_index(mgr)) { - u_vbuf_get_minmax_index(mgr->pipe, &mgr->b.index_buffer, info, - &min_index, &max_index); - index_bounds_valid = true; - } + /* See if anything needs to be done for per-vertex attribs. */ + if (u_vbuf_need_minmax_index(mgr)) { + int max_index; + + if (info->max_index != ~0) { + min_index = info->min_index; + max_index = info->max_index; + } else { + u_vbuf_get_minmax_index(mgr->pipe, &mgr->index_buffer, info, + &min_index, &max_index); + } - /* If the index bounds are valid, it means some upload or translation - * of per-vertex attribs will be performed. */ - if (index_bounds_valid) { assert(min_index <= max_index); start_vertex = min_index + info->index_bias; @@ -1090,7 +1026,9 @@ u_vbuf_draw_begin(struct u_vbuf *mgrb, num_vertices-info->count > 32 && !u_vbuf_mapping_vertex_buffer_blocks(mgr)) { /*printf("num_vertices=%i count=%i\n", num_vertices, info->count);*/ - unroll_indices = true; + unroll_indices = TRUE; + user_vb_mask &= ~(mgr->nonzero_stride_vb_mask & + mgr->ve->noninstance_vb_mask_any); } } else { /* Nothing to do for per-vertex attribs. */ @@ -1106,17 +1044,20 @@ u_vbuf_draw_begin(struct u_vbuf *mgrb, /* Translate vertices with non-native layouts or formats. */ if (unroll_indices || - mgr->incompatible_vb_layout || - mgr->ve->incompatible_layout) { + mgr->incompatible_vb_mask || + mgr->ve->incompatible_elem_mask) { /* XXX check the return value */ u_vbuf_translate_begin(mgr, start_vertex, num_vertices, info->start_instance, info->instance_count, info->start, info->count, min_index, unroll_indices); + + user_vb_mask &= ~(mgr->incompatible_vb_mask | + mgr->ve->incompatible_vb_mask_all); } /* Upload user buffers. */ - if (mgr->any_user_vbs) { + if (user_vb_mask) { u_vbuf_upload_buffers(mgr, start_vertex, num_vertices, info->start_instance, info->instance_count); } @@ -1130,34 +1071,75 @@ u_vbuf_draw_begin(struct u_vbuf *mgrb, } unsigned i; - for (i = 0; i < mgr->b.nr_vertex_buffers; i++) { + for (i = 0; i < mgr->nr_vertex_buffers; i++) { printf("input %i: ", i); - util_dump_vertex_buffer(stdout, mgr->b.vertex_buffer+i); + util_dump_vertex_buffer(stdout, mgr->vertex_buffer+i); printf("\n"); } - for (i = 0; i < mgr->b.nr_real_vertex_buffers; i++) { + for (i = 0; i < mgr->nr_real_vertex_buffers; i++) { printf("real %i: ", i); - util_dump_vertex_buffer(stdout, mgr->b.real_vertex_buffer+i); + util_dump_vertex_buffer(stdout, mgr->real_vertex_buffer+i); printf("\n"); } */ - if (unroll_indices) { - info->indexed = FALSE; - info->index_bias = 0; - info->min_index = 0; - info->max_index = info->count - 1; - info->start = 0; + u_upload_unmap(mgr->uploader); + pipe->set_vertex_buffers(pipe, mgr->nr_real_vertex_buffers, + mgr->real_vertex_buffer); + + if (unlikely(unroll_indices)) { + struct pipe_draw_info new_info = *info; + new_info.indexed = FALSE; + new_info.index_bias = 0; + new_info.min_index = 0; + new_info.max_index = info->count - 1; + new_info.start = 0; + + pipe->draw_vbo(pipe, &new_info); + } else { + pipe->draw_vbo(pipe, info); + } + + if (mgr->using_translate) { + u_vbuf_translate_end(mgr); } + mgr->vertex_buffers_dirty = TRUE; +} - return U_VBUF_BUFFERS_UPDATED; +void u_vbuf_save_vertex_elements(struct u_vbuf *mgr) +{ + assert(!mgr->ve_saved); + mgr->ve_saved = mgr->ve; } -void u_vbuf_draw_end(struct u_vbuf *mgrb) +void u_vbuf_restore_vertex_elements(struct u_vbuf *mgr) { - struct u_vbuf_priv *mgr = (struct u_vbuf_priv*)mgrb; + if (mgr->ve != mgr->ve_saved) { + struct pipe_context *pipe = mgr->pipe; - if (mgr->fallback_ve) { - u_vbuf_translate_end(mgr); + mgr->ve = mgr->ve_saved; + pipe->bind_vertex_elements_state(pipe, + mgr->ve ? mgr->ve->driver_cso : NULL); + } + mgr->ve_saved = NULL; +} + +void u_vbuf_save_vertex_buffers(struct u_vbuf *mgr) +{ + util_copy_vertex_buffers(mgr->vertex_buffer_saved, + &mgr->nr_vertex_buffers_saved, + mgr->vertex_buffer, + mgr->nr_vertex_buffers); +} + +void u_vbuf_restore_vertex_buffers(struct u_vbuf *mgr) +{ + unsigned i; + + u_vbuf_set_vertex_buffers(mgr, mgr->nr_vertex_buffers_saved, + mgr->vertex_buffer_saved); + for (i = 0; i < mgr->nr_vertex_buffers_saved; i++) { + pipe_resource_reference(&mgr->vertex_buffer_saved[i].buffer, NULL); } + mgr->nr_vertex_buffers_saved = 0; } diff --git a/mesalib/src/gallium/auxiliary/util/u_vbuf.h b/mesalib/src/gallium/auxiliary/util/u_vbuf.h index 3669c9b87..59eb59a11 100644 --- a/mesalib/src/gallium/auxiliary/util/u_vbuf.h +++ b/mesalib/src/gallium/auxiliary/util/u_vbuf.h @@ -25,8 +25,8 @@ * **************************************************************************/ -#ifndef U_VBUF_MGR_H -#define U_VBUF_MGR_H +#ifndef U_VBUF_H +#define U_VBUF_H /* This module builds upon u_upload_mgr and translate_cache and takes care of * user buffer uploads and vertex format fallbacks. It's designed @@ -35,7 +35,9 @@ #include "pipe/p_context.h" #include "pipe/p_state.h" -#include "util/u_transfer.h" + +struct cso_context; +struct u_vbuf; /* Hardware vertex fetcher limitations can be described by this structure. */ struct u_vbuf_caps { @@ -47,99 +49,38 @@ struct u_vbuf_caps { unsigned format_norm32:1; /* PIPE_FORMAT_*32*NORM */ unsigned format_scaled32:1; /* PIPE_FORMAT_*32*SCALED */ - /* Whether vertex fetches don't have to be dword-aligned. */ + /* Whether vertex fetches don't have to be 4-byte-aligned. */ /* TRUE if hardware supports it. */ - unsigned fetch_dword_unaligned:1; -}; - -/* The manager. - * This structure should also be used to access vertex buffers - * from a driver. */ -struct u_vbuf { - /* This is what was set in set_vertex_buffers. - * May contain user buffers. */ - struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS]; - unsigned nr_vertex_buffers; - - /* Contains only real vertex buffers. - * Hardware drivers should use real_vertex_buffers[i] - * instead of vertex_buffers[i].buffer. */ - struct pipe_vertex_buffer real_vertex_buffer[PIPE_MAX_ATTRIBS]; - int nr_real_vertex_buffers; - - /* The index buffer. */ - struct pipe_index_buffer index_buffer; - - /* This uploader can optionally be used by the driver. - * - * Allowed functions: - * - u_upload_alloc - * - u_upload_data - * - u_upload_buffer - * - u_upload_flush */ - struct u_upload_mgr *uploader; - - struct u_vbuf_caps caps; -}; - -struct u_vbuf_resource { - struct u_resource b; - uint8_t *user_ptr; -}; + unsigned buffer_offset_unaligned:1; + unsigned buffer_stride_unaligned:1; + unsigned velem_src_offset_unaligned:1; -/* Opaque type containing information about vertex elements for the manager. */ -struct u_vbuf_elements; - -enum u_fetch_alignment { - U_VERTEX_FETCH_BYTE_ALIGNED, - U_VERTEX_FETCH_DWORD_ALIGNED + /* Whether the driver supports user vertex buffers. */ + unsigned user_vertex_buffers:1; }; -enum u_vbuf_return_flags { - U_VBUF_BUFFERS_UPDATED = 1 -}; +void u_vbuf_get_caps(struct pipe_screen *screen, struct u_vbuf_caps *caps); struct u_vbuf * u_vbuf_create(struct pipe_context *pipe, - unsigned upload_buffer_size, - unsigned upload_buffer_alignment, - unsigned upload_buffer_bind, - enum u_fetch_alignment fetch_alignment); + struct u_vbuf_caps *caps); void u_vbuf_destroy(struct u_vbuf *mgr); -struct u_vbuf_elements * -u_vbuf_create_vertex_elements(struct u_vbuf *mgr, - unsigned count, - const struct pipe_vertex_element *attrs, - struct pipe_vertex_element *native_attrs); - -void u_vbuf_bind_vertex_elements(struct u_vbuf *mgr, - void *cso, - struct u_vbuf_elements *ve); - -void u_vbuf_destroy_vertex_elements(struct u_vbuf *mgr, - struct u_vbuf_elements *ve); - -void u_vbuf_set_vertex_buffers(struct u_vbuf *mgr, - unsigned count, +/* State and draw functions. */ +void u_vbuf_set_vertex_elements(struct u_vbuf *mgr, unsigned count, + const struct pipe_vertex_element *states); +void u_vbuf_set_vertex_buffers(struct u_vbuf *mgr, unsigned count, const struct pipe_vertex_buffer *bufs); - void u_vbuf_set_index_buffer(struct u_vbuf *mgr, const struct pipe_index_buffer *ib); +void u_vbuf_draw_vbo(struct u_vbuf *mgr, const struct pipe_draw_info *info); -enum u_vbuf_return_flags u_vbuf_draw_begin(struct u_vbuf *mgr, - struct pipe_draw_info *info); - -unsigned u_vbuf_draw_max_vertex_count(struct u_vbuf *mgr); - -void u_vbuf_draw_end(struct u_vbuf *mgr); - - -static INLINE struct u_vbuf_resource *u_vbuf_resource(struct pipe_resource *r) -{ - return (struct u_vbuf_resource*)r; -} +/* Save/restore functionality. */ +void u_vbuf_save_vertex_elements(struct u_vbuf *mgr); +void u_vbuf_restore_vertex_elements(struct u_vbuf *mgr); +void u_vbuf_save_vertex_buffers(struct u_vbuf *mgr); +void u_vbuf_restore_vertex_buffers(struct u_vbuf *mgr); #endif diff --git a/mesalib/src/glsl/Makefile b/mesalib/src/glsl/Makefile index f6c722997..7c80c95d8 100644 --- a/mesalib/src/glsl/Makefile +++ b/mesalib/src/glsl/Makefile @@ -165,7 +165,7 @@ glcpp/glcpp-parse.c: glcpp/glcpp-parse.y builtin_compiler: $(GLSL2_OBJECTS) $(OBJECTS) builtin_stubs.o $(APP_CXX) $(INCLUDES) $(CXXFLAGS) $(LDFLAGS) $(OBJECTS) $(GLSL2_OBJECTS) builtin_stubs.o -o $@ -builtin_function.cpp: builtins/profiles/* builtins/ir/* builtins/tools/generate_builtins.py builtins/tools/texture_builtins.py builtin_compiler +builtin_function.cpp: builtins/profiles/* builtins/ir/* builtins/glsl/* builtins/tools/generate_builtins.py builtins/tools/texture_builtins.py builtin_compiler @echo Regenerating builtin_function.cpp... $(PYTHON2) $(PYTHON_FLAGS) builtins/tools/generate_builtins.py ./builtin_compiler > builtin_function.cpp || rm -f builtin_function.cpp diff --git a/mesalib/src/glsl/ir_reader.cpp b/mesalib/src/glsl/ir_reader.cpp index 7ce683ef7..03dbb67c3 100644 --- a/mesalib/src/glsl/ir_reader.cpp +++ b/mesalib/src/glsl/ir_reader.cpp @@ -407,6 +407,8 @@ ir_reader::read_declaration(s_expression *expr) var->mode = ir_var_out; } else if (strcmp(qualifier->value(), "inout") == 0) { var->mode = ir_var_inout; + } else if (strcmp(qualifier->value(), "temporary") == 0) { + var->mode = ir_var_temporary; } else if (strcmp(qualifier->value(), "smooth") == 0) { var->interpolation = INTERP_QUALIFIER_SMOOTH; } else if (strcmp(qualifier->value(), "flat") == 0) { diff --git a/mesalib/src/glsl/main.cpp b/mesalib/src/glsl/main.cpp index 3231b1be9..64c2496eb 100644 --- a/mesalib/src/glsl/main.cpp +++ b/mesalib/src/glsl/main.cpp @@ -22,6 +22,15 @@ */ #include <getopt.h> +/** @file main.cpp + * + * This file is the main() routine and scaffolding for producing + * builtin_compiler (which doesn't include builtins itself and is used + * to generate the profile information for builtin_function.cpp), and + * for glsl_compiler (which does include builtins and can be used to + * offline compile GLSL code and examine the resulting GLSL IR. + */ + #include "ast.h" #include "glsl_parser_extras.h" #include "ir_optimization.h" diff --git a/mesalib/src/glsl/opt_dead_functions.cpp b/mesalib/src/glsl/opt_dead_functions.cpp index 017a28639..f50349395 100644 --- a/mesalib/src/glsl/opt_dead_functions.cpp +++ b/mesalib/src/glsl/opt_dead_functions.cpp @@ -62,8 +62,6 @@ public: signature_entry *get_signature_entry(ir_function_signature *var); - bool (*predicate)(ir_instruction *ir); - /* List of signature_entry */ exec_list signature_list; void *mem_ctx; diff --git a/mesalib/src/glsl/opt_structure_splitting.cpp b/mesalib/src/glsl/opt_structure_splitting.cpp index 6dd228e4e..a21238dd0 100644 --- a/mesalib/src/glsl/opt_structure_splitting.cpp +++ b/mesalib/src/glsl/opt_structure_splitting.cpp @@ -201,7 +201,6 @@ public: variable_entry2 *get_splitting_entry(ir_variable *var); exec_list *variable_list; - void *mem_ctx; }; variable_entry2 * diff --git a/mesalib/src/mesa/main/version.c b/mesalib/src/mesa/main/version.c index 82cc54b44..607230b5e 100644 --- a/mesalib/src/mesa/main/version.c +++ b/mesalib/src/mesa/main/version.c @@ -124,6 +124,7 @@ compute_version(struct gl_context *ctx) ctx->Extensions.EXT_texture_sRGB); const GLboolean ver_3_0 = (ver_2_1 && ctx->Const.GLSLVersion >= 130 && + ctx->Const.MaxSamples >= 4 && ctx->Extensions.ARB_color_buffer_float && ctx->Extensions.ARB_depth_buffer_float && ctx->Extensions.ARB_half_float_pixel && diff --git a/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c b/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c index 5e078a85e..9a3f22465 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c +++ b/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c @@ -1509,7 +1509,15 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy, readY = srcy; readW = width; readH = height; - _mesa_clip_readpixels(ctx, &readX, &readY, &readW, &readH, &pack); + if (!_mesa_clip_readpixels(ctx, &readX, &readY, &readW, &readH, &pack)) { + /* The source region is completely out of bounds. Do nothing. + * The GL spec says "Results of copies from outside the window, + * or from regions of the window that are not exposed, are + * hardware dependent and undefined." + */ + return; + } + readW = MAX2(0, readW); readH = MAX2(0, readH); diff --git a/mesalib/src/mesa/state_tracker/st_context.c b/mesalib/src/mesa/state_tracker/st_context.c index 0245fd92b..19d9da131 100644 --- a/mesalib/src/mesa/state_tracker/st_context.c +++ b/mesalib/src/mesa/state_tracker/st_context.c @@ -65,6 +65,7 @@ #include "util/u_inlines.h" #include "util/u_upload_mgr.h" #include "cso_cache/cso_context.h" +#include "util/u_vbuf.h" DEBUG_GET_ONCE_BOOL_OPTION(mesa_mvp_dp4, "MESA_MVP_DP4", FALSE) @@ -111,6 +112,29 @@ st_get_msaa(void) } +static void st_init_vbuf(struct st_context *st) +{ + struct u_vbuf_caps caps; + + u_vbuf_get_caps(st->pipe->screen, &caps); + + /* Create u_vbuf if there is anything unsupported. */ + if (!caps.buffer_offset_unaligned || + !caps.buffer_stride_unaligned || + !caps.velem_src_offset_unaligned || + !caps.format_fixed32 || + !caps.format_float16 || + !caps.format_float64 || + !caps.format_norm32 || + !caps.format_scaled32 || + !caps.user_vertex_buffers) { + /* XXX user vertex buffers are always uploaded regardless of the CAP. */ + st->vbuf = u_vbuf_create(st->pipe, &caps); + cso_install_vbuf(st->cso_context, st->vbuf); + } +} + + static struct st_context * st_create_context_priv( struct gl_context *ctx, struct pipe_context *pipe ) { @@ -134,6 +158,7 @@ st_create_context_priv( struct gl_context *ctx, struct pipe_context *pipe ) st->uploader = u_upload_create(st->pipe, 65536, 4, PIPE_BIND_VERTEX_BUFFER); st->cso_context = cso_create_context(pipe); + st_init_vbuf(st); st_init_atoms( st ); st_init_bitmap(st); st_init_clear(st); @@ -245,6 +270,7 @@ static void st_destroy_context_priv( struct st_context *st ) void st_destroy_context( struct st_context *st ) { struct pipe_context *pipe = st->pipe; + struct u_vbuf *vbuf = st->vbuf; struct cso_context *cso = st->cso_context; struct gl_context *ctx = st->ctx; GLuint i; @@ -275,7 +301,13 @@ void st_destroy_context( struct st_context *st ) _mesa_free_context_data(ctx); + /* This will free the st_context too, so 'st' must not be accessed + * afterwards. */ st_destroy_context_priv(st); + st = NULL; + + if (vbuf) + u_vbuf_destroy(vbuf); cso_destroy_context(cso); diff --git a/mesalib/src/mesa/state_tracker/st_context.h b/mesalib/src/mesa/state_tracker/st_context.h index e3d65d97a..3ec98ada1 100644 --- a/mesalib/src/mesa/state_tracker/st_context.h +++ b/mesalib/src/mesa/state_tracker/st_context.h @@ -41,6 +41,7 @@ struct gen_mipmap_state; struct st_context; struct st_fragment_program; struct u_upload_mgr; +struct u_vbuf; #define ST_NEW_MESA (1 << 0) /* Mesa state has changed */ @@ -73,6 +74,8 @@ struct st_context struct pipe_context *pipe; struct u_upload_mgr *uploader; + struct u_vbuf *vbuf; + struct draw_context *draw; /**< For selection/feedback/rastpos only */ struct draw_stage *feedback_stage; /**< For GL_FEEDBACK rendermode */ struct draw_stage *selection_stage; /**< For GL_SELECT rendermode */ diff --git a/mesalib/src/mesa/state_tracker/st_draw.c b/mesalib/src/mesa/state_tracker/st_draw.c index 0a35ab2be..edab76bf5 100644 --- a/mesalib/src/mesa/state_tracker/st_draw.c +++ b/mesalib/src/mesa/state_tracker/st_draw.c @@ -795,7 +795,8 @@ find_sub_primitives(const void *elements, unsigned element_size, * sub-primitives. */ static void -handle_fallback_primitive_restart(struct pipe_context *pipe, +handle_fallback_primitive_restart(struct cso_context *cso, + struct pipe_context *pipe, const struct _mesa_index_buffer *ib, struct pipe_index_buffer *ibuffer, struct pipe_draw_info *orig_info) @@ -851,7 +852,7 @@ handle_fallback_primitive_restart(struct pipe_context *pipe, info.start = sub_prims[i].start; info.count = sub_prims[i].count; if (u_trim_pipe_prim(info.mode, &info.count)) { - pipe->draw_vbo(pipe, &info); + cso_draw_vbo(cso, &info); } } } @@ -1075,7 +1076,7 @@ st_draw_vbo(struct gl_context *ctx, } setup_index_buffer(ctx, ib, &ibuffer); - pipe->set_index_buffer(pipe, &ibuffer); + cso_set_index_buffer(st->cso_context, &ibuffer); util_draw_init_info(&info); if (ib) { @@ -1110,20 +1111,21 @@ st_draw_vbo(struct gl_context *ctx, } if (info.count_from_stream_output) { - pipe->draw_vbo(pipe, &info); + cso_draw_vbo(st->cso_context, &info); } else if (info.primitive_restart) { if (st->sw_primitive_restart) { /* Handle primitive restart for drivers that doesn't support it */ - handle_fallback_primitive_restart(pipe, ib, &ibuffer, &info); + handle_fallback_primitive_restart(st->cso_context, pipe, ib, + &ibuffer, &info); } else { /* don't trim, restarts might be inside index list */ - pipe->draw_vbo(pipe, &info); + cso_draw_vbo(st->cso_context, &info); } } else if (u_trim_pipe_prim(info.mode, &info.count)) - pipe->draw_vbo(pipe, &info); + cso_draw_vbo(st->cso_context, &info); } pipe_resource_reference(&ibuffer.buffer, NULL); diff --git a/mesalib/src/mesa/state_tracker/st_extensions.c b/mesalib/src/mesa/state_tracker/st_extensions.c index 34e0329be..1b4bca681 100644 --- a/mesalib/src/mesa/state_tracker/st_extensions.c +++ b/mesalib/src/mesa/state_tracker/st_extensions.c @@ -459,12 +459,6 @@ void st_init_extensions(struct st_context *st) /* Required: vertex fetch support. */ static const struct st_extension_format_mapping vertex_mapping[] = { - { { o(ARB_ES2_compatibility) }, - { PIPE_FORMAT_R32G32B32A32_FIXED } }, - - { { o(ARB_half_float_vertex) }, - { PIPE_FORMAT_R16G16B16A16_FLOAT } }, - { { o(ARB_vertex_type_2_10_10_10_rev) }, { PIPE_FORMAT_R10G10B10A2_UNORM, PIPE_FORMAT_B10G10R10A2_UNORM, @@ -479,6 +473,7 @@ void st_init_extensions(struct st_context *st) /* * Extensions that are supported by all Gallium drivers: */ + ctx->Extensions.ARB_ES2_compatibility = GL_TRUE; ctx->Extensions.ARB_copy_buffer = GL_TRUE; ctx->Extensions.ARB_draw_elements_base_vertex = GL_TRUE; ctx->Extensions.ARB_explicit_attrib_location = GL_TRUE; @@ -486,6 +481,7 @@ void st_init_extensions(struct st_context *st) ctx->Extensions.ARB_fragment_program = GL_TRUE; ctx->Extensions.ARB_fragment_shader = GL_TRUE; ctx->Extensions.ARB_half_float_pixel = GL_TRUE; + ctx->Extensions.ARB_half_float_vertex = GL_TRUE; ctx->Extensions.ARB_map_buffer_range = GL_TRUE; ctx->Extensions.ARB_sampler_objects = GL_TRUE; ctx->Extensions.ARB_shader_objects = GL_TRUE; diff --git a/mesalib/src/mesa/vbo/vbo_exec.h b/mesalib/src/mesa/vbo/vbo_exec.h index 5cdf5ced9..be9f3d78d 100644 --- a/mesalib/src/mesa/vbo/vbo_exec.h +++ b/mesalib/src/mesa/vbo/vbo_exec.h @@ -189,7 +189,8 @@ static inline void vbo_draw_method(struct vbo_exec_context *exec, enum draw_method method) { if (exec->last_draw_method != method) { - exec->ctx->NewState |= _NEW_ARRAY; + struct gl_context *ctx = exec->ctx; + ctx->Driver.UpdateState(ctx, _NEW_ARRAY); exec->last_draw_method = method; } } diff --git a/mesalib/src/mesa/vbo/vbo_exec_array.c b/mesalib/src/mesa/vbo/vbo_exec_array.c index f95e062fb..2dcfb8e5b 100644 --- a/mesalib/src/mesa/vbo/vbo_exec_array.c +++ b/mesalib/src/mesa/vbo/vbo_exec_array.c @@ -438,14 +438,6 @@ recalculate_input_bindings(struct gl_context *ctx) inputs[VERT_ATTRIB_GENERIC(i)] = &vbo->currval[VBO_ATTRIB_GENERIC0+i]; const_inputs |= VERT_BIT_GENERIC(i); } - - /* There is no need to make _NEW_ARRAY dirty here for the TnL program, - * because it already takes care of invalidating the state necessary - * to revalidate vertex arrays. Not marking the state as dirty also - * improves performance (quite significantly in some apps). - */ - if (!ctx->VertexProgram._MaintainTnlProgram) - ctx->NewState |= _NEW_ARRAY; break; case VP_NV: @@ -472,8 +464,6 @@ recalculate_input_bindings(struct gl_context *ctx) inputs[VERT_ATTRIB_GENERIC(i)] = &vbo->currval[VBO_ATTRIB_GENERIC0+i]; const_inputs |= VERT_BIT_GENERIC(i); } - - ctx->NewState |= _NEW_ARRAY; break; case VP_ARB: @@ -512,11 +502,11 @@ recalculate_input_bindings(struct gl_context *ctx) } inputs[VERT_ATTRIB_GENERIC0] = inputs[0]; - ctx->NewState |= _NEW_ARRAY; break; } _mesa_set_varying_vp_inputs( ctx, VERT_BIT_ALL & (~const_inputs) ); + ctx->Driver.UpdateState(ctx, _NEW_ARRAY); } @@ -640,11 +630,11 @@ vbo_exec_DrawArrays(GLenum mode, GLint start, GLsizei count) _mesa_debug(ctx, "glDrawArrays(%s, %d, %d)\n", _mesa_lookup_enum_by_nr(mode), start, count); + FLUSH_CURRENT(ctx, 0); + if (!_mesa_validate_DrawArrays( ctx, mode, start, count )) return; - FLUSH_CURRENT( ctx, 0 ); - if (0) check_draw_arrays_data(ctx, start, count); @@ -669,11 +659,11 @@ vbo_exec_DrawArraysInstanced(GLenum mode, GLint start, GLsizei count, _mesa_debug(ctx, "glDrawArraysInstanced(%s, %d, %d, %d)\n", _mesa_lookup_enum_by_nr(mode), start, count, numInstances); + FLUSH_CURRENT(ctx, 0); + if (!_mesa_validate_DrawArraysInstanced(ctx, mode, start, count, numInstances)) return; - FLUSH_CURRENT( ctx, 0 ); - if (0) check_draw_arrays_data(ctx, start, count); @@ -761,8 +751,6 @@ vbo_validated_drawrangeelements(struct gl_context *ctx, GLenum mode, struct _mesa_index_buffer ib; struct _mesa_prim prim[1]; - FLUSH_CURRENT( ctx, 0 ); - vbo_bind_arrays(ctx); ib.count = count; @@ -838,6 +826,8 @@ vbo_exec_DrawRangeElementsBaseVertex(GLenum mode, _mesa_lookup_enum_by_nr(mode), start, end, count, _mesa_lookup_enum_by_nr(type), indices, basevertex); + FLUSH_CURRENT(ctx, 0); + if (!_mesa_validate_DrawRangeElements( ctx, mode, start, end, count, type, indices, basevertex )) return; @@ -936,6 +926,8 @@ vbo_exec_DrawElements(GLenum mode, GLsizei count, GLenum type, _mesa_lookup_enum_by_nr(mode), count, _mesa_lookup_enum_by_nr(type), indices); + FLUSH_CURRENT(ctx, 0); + if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices, 0 )) return; @@ -958,6 +950,8 @@ vbo_exec_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type, _mesa_lookup_enum_by_nr(mode), count, _mesa_lookup_enum_by_nr(type), indices, basevertex); + FLUSH_CURRENT(ctx, 0); + if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices, basevertex )) return; @@ -981,6 +975,8 @@ vbo_exec_DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, _mesa_lookup_enum_by_nr(mode), count, _mesa_lookup_enum_by_nr(type), indices, numInstances); + FLUSH_CURRENT(ctx, 0); + if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, indices, numInstances, 0)) return; @@ -1005,6 +1001,8 @@ vbo_exec_DrawElementsInstancedBaseVertex(GLenum mode, GLsizei count, GLenum type _mesa_lookup_enum_by_nr(type), indices, numInstances, basevertex); + FLUSH_CURRENT(ctx, 0); + if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, indices, numInstances, basevertex)) return; @@ -1037,8 +1035,6 @@ vbo_validated_multidrawelements(struct gl_context *ctx, GLenum mode, if (primcount == 0) return; - FLUSH_CURRENT( ctx, 0 ); - prim = calloc(1, primcount * sizeof(*prim)); if (prim == NULL) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMultiDrawElements"); @@ -1226,12 +1222,12 @@ vbo_exec_DrawTransformFeedback(GLenum mode, GLuint name) _mesa_debug(ctx, "glDrawTransformFeedback(%s, %d)\n", _mesa_lookup_enum_by_nr(mode), name); + FLUSH_CURRENT(ctx, 0); + if (!_mesa_validate_DrawTransformFeedback(ctx, mode, obj)) { return; } - FLUSH_CURRENT(ctx, 0); - vbo_draw_transform_feedback(ctx, mode, obj, 1); } diff --git a/mesalib/src/mesa/vbo/vbo_exec_draw.c b/mesalib/src/mesa/vbo/vbo_exec_draw.c index 5cc6586b3..da5ca695e 100644 --- a/mesalib/src/mesa/vbo/vbo_exec_draw.c +++ b/mesalib/src/mesa/vbo/vbo_exec_draw.c @@ -253,11 +253,11 @@ vbo_exec_bind_arrays( struct gl_context *ctx ) arrays[attr]._MaxElement = count; /* ??? */ varying_inputs |= VERT_BIT(attr); - ctx->NewState |= _NEW_ARRAY; } } _mesa_set_varying_vp_inputs( ctx, varying_inputs ); + ctx->Driver.UpdateState(ctx, _NEW_ARRAY); } diff --git a/mesalib/src/mesa/vbo/vbo_save_draw.c b/mesalib/src/mesa/vbo/vbo_save_draw.c index 57186de64..88a9a7e34 100644 --- a/mesalib/src/mesa/vbo/vbo_save_draw.c +++ b/mesalib/src/mesa/vbo/vbo_save_draw.c @@ -209,11 +209,11 @@ static void vbo_bind_vertex_list(struct gl_context *ctx, buffer_offset += node_attrsz[src] * sizeof(GLfloat); varying_inputs |= VERT_BIT(attr); - ctx->NewState |= _NEW_ARRAY; } } _mesa_set_varying_vp_inputs( ctx, varying_inputs ); + ctx->Driver.UpdateState(ctx, _NEW_ARRAY); } diff --git a/pixman/configure.ac b/pixman/configure.ac index b8d59f625..54787342e 100644 --- a/pixman/configure.ac +++ b/pixman/configure.ac @@ -271,6 +271,59 @@ PIXMAN_CHECK_CFLAG([-xldscope=hidden], [dnl ]) dnl =========================================================================== +dnl Check for Loongson Multimedia Instructions + +if test "x$LS_CFLAGS" = "x" ; then + LS_CFLAGS="-march=loongson2f" +fi + +have_loongson_mmi=no +AC_MSG_CHECKING(whether to use Loongson MMI) + +xserver_save_CFLAGS=$CFLAGS +CFLAGS=" $CFLAGS $LS_CFLAGS" +AC_COMPILE_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" +#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_loongson_mmi=yes) +CFLAGS=$xserver_save_CFLAGS + +AC_ARG_ENABLE(loongson, + [AC_HELP_STRING([--disable-loongson], + [disable Loongson fast paths])], + [enable_loongson=$enableval], [enable_loongson=auto]) + +if test $enable_loongson = no ; then + have_loongson_mmi=disabled +fi + +if test $have_loongson_mmi = yes ; then + AC_DEFINE(USE_LOONGSON_MMI, 1, [use Loongson Multimedia Instructions]) +else + LS_CFLAGS= +fi + +AC_MSG_RESULT($have_loongson_mmi) +if test $enable_loongson = yes && test $have_loongson_mmi = no ; then + AC_MSG_ERROR([Loongson MMI not detected]) +fi + +AM_CONDITIONAL(USE_LOONGSON_MMI, test $have_loongson_mmi = yes) + +dnl =========================================================================== dnl Check for MMX if test "x$MMX_CFLAGS" = "x" ; then @@ -416,6 +469,7 @@ case $host_os in ;; esac +AC_SUBST(LS_CFLAGS) AC_SUBST(IWMMXT_CFLAGS) AC_SUBST(MMX_CFLAGS) AC_SUBST(MMX_LDFLAGS) diff --git a/pixman/pixman/Makefile.am b/pixman/pixman/Makefile.am index fb7e04723..b320a5838 100644 --- a/pixman/pixman/Makefile.am +++ b/pixman/pixman/Makefile.am @@ -118,5 +118,17 @@ libpixman_1_la_LIBADD += libpixman-mips-dspr2.la ASM_CFLAGS_mips_dspr2= 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 = $(DEP_CFLAGS) $(LS_CFLAGS) +libpixman_loongson_mmi_la_LIBADD = $(DEP_LIBS) +libpixman_1_la_LDFLAGS += $(LS_LDFLAGS) +libpixman_1_la_LIBADD += libpixman-loongson-mmi.la + +ASM_CFLAGS_ls=$(LS_CFLAGS) +endif + .c.s : $(libpixmaninclude_HEADERS) $(BUILT_SOURCES) $(CC) $(CFLAGS) $(ASM_CFLAGS_$(@:pixman-%.s=%)) $(ASM_CFLAGS_$(@:pixman-arm-%.s=arm_%)) -DHAVE_CONFIG_H -I$(srcdir) -I$(builddir) -I$(top_builddir) -S -o $@ $< diff --git a/pixman/pixman/loongson-mmintrin.h b/pixman/pixman/loongson-mmintrin.h new file mode 100644 index 000000000..8295ba01c --- /dev/null +++ b/pixman/pixman/loongson-mmintrin.h @@ -0,0 +1,273 @@ +/* The gcc-provided loongson intrinsic functions are way too fucking broken + * to be of any use, otherwise I'd use them. + * + * - The hardware instructions are very similar to MMX or iwMMXt. Certainly + * close enough that they could have implemented the _mm_*-style intrinsic + * interface and had a ton of optimized code available to them. Instead they + * implemented something much, much worse. + * + * - pshuf takes a dead first argument, causing extra instructions to be + * generated. + * + * - There are no 64-bit shift or logical intrinsics, which means you have + * to implement them with inline assembly, but this is a nightmare because + * gcc doesn't understand that the integer vector datatypes are actually in + * floating-point registers, so you end up with braindead code like + * + * punpcklwd $f9,$f9,$f5 + * dmtc1 v0,$f8 + * punpcklwd $f19,$f19,$f5 + * dmfc1 t9,$f9 + * dmtc1 v0,$f9 + * dmtc1 t9,$f20 + * dmfc1 s0,$f19 + * punpcklbh $f20,$f20,$f2 + * + * where crap just gets copied back and forth between integer and floating- + * point registers ad nauseum. + * + * Instead of trying to workaround the problems from these crap intrinsics, I + * just implement the _mm_* intrinsics needed for pixman-mmx.c using inline + * assembly. + */ + +#include <stdint.h> + +/* vectors are stored in 64-bit floating-point registers */ +typedef double __m64; +/* having a 32-bit datatype allows us to use 32-bit loads in places like load8888 */ +typedef float __m32; + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_setzero_si64 (void) +{ + return 0.0; +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_adds_pu16 (__m64 __m1, __m64 __m2) +{ + __m64 ret; + asm("paddush %0, %1, %2\n\t" + : "=f" (ret) + : "f" (__m1), "f" (__m2) + ); + return ret; +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_adds_pu8 (__m64 __m1, __m64 __m2) +{ + __m64 ret; + asm("paddusb %0, %1, %2\n\t" + : "=f" (ret) + : "f" (__m1), "f" (__m2) + ); + return ret; +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_and_si64 (__m64 __m1, __m64 __m2) +{ + __m64 ret; + asm("and %0, %1, %2\n\t" + : "=f" (ret) + : "f" (__m1), "f" (__m2) + ); + return ret; +} + +extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_empty (void) +{ + +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_madd_pi16 (__m64 __m1, __m64 __m2) +{ + __m64 ret; + asm("pmaddhw %0, %1, %2\n\t" + : "=f" (ret) + : "f" (__m1), "f" (__m2) + ); + return ret; +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mulhi_pu16 (__m64 __m1, __m64 __m2) +{ + __m64 ret; + asm("pmulhuh %0, %1, %2\n\t" + : "=f" (ret) + : "f" (__m1), "f" (__m2) + ); + return ret; +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_mullo_pi16 (__m64 __m1, __m64 __m2) +{ + __m64 ret; + asm("pmullh %0, %1, %2\n\t" + : "=f" (ret) + : "f" (__m1), "f" (__m2) + ); + return ret; +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_or_si64 (__m64 __m1, __m64 __m2) +{ + __m64 ret; + asm("or %0, %1, %2\n\t" + : "=f" (ret) + : "f" (__m1), "f" (__m2) + ); + return ret; +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_packs_pu16 (__m64 __m1, __m64 __m2) +{ + __m64 ret; + asm("packushb %0, %1, %2\n\t" + : "=f" (ret) + : "f" (__m1), "f" (__m2) + ); + return ret; +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_shuffle_pi16 (__m64 __m, int64_t __n) +{ + __m64 ret; + asm("pshufh %0, %1, %2\n\t" + : "=f" (ret) + : "f" (__m), "f" (*(__m64 *)&__n) + ); + return ret; +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_slli_si64 (__m64 __m, int64_t __count) +{ + __m64 ret; + asm("dsll %0, %1, %2\n\t" + : "=f" (ret) + : "f" (__m), "f" (*(__m64 *)&__count) + ); + return ret; +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_srli_pi16 (__m64 __m, int64_t __count) +{ + __m64 ret; + asm("psrlh %0, %1, %2\n\t" + : "=f" (ret) + : "f" (__m), "f" (*(__m64 *)&__count) + ); + return ret; +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_srli_si64 (__m64 __m, int64_t __count) +{ + __m64 ret; + asm("dsrl %0, %1, %2\n\t" + : "=f" (ret) + : "f" (__m), "f" (*(__m64 *)&__count) + ); + return ret; +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_unpackhi_pi8 (__m64 __m1, __m64 __m2) +{ + __m64 ret; + asm("punpckhbh %0, %1, %2\n\t" + : "=f" (ret) + : "f" (__m1), "f" (__m2) + ); + return ret; +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_unpackhi_pi16 (__m64 __m1, __m64 __m2) +{ + __m64 ret; + asm("punpckhhw %0, %1, %2\n\t" + : "=f" (ret) + : "f" (__m1), "f" (__m2) + ); + return ret; +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_unpacklo_pi8 (__m64 __m1, __m64 __m2) +{ + __m64 ret; + asm("punpcklbh %0, %1, %2\n\t" + : "=f" (ret) + : "f" (__m1), "f" (__m2) + ); + return ret; +} + +/* Since punpcklbh doesn't care about the high 32-bits, we use the __m32 datatype which + * allows load8888 to use 32-bit loads */ +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_unpacklo_pi8_f (__m32 __m1, __m64 __m2) +{ + __m64 ret; + asm("punpcklbh %0, %1, %2\n\t" + : "=f" (ret) + : "f" (__m1), "f" (__m2) + ); + return ret; +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_unpacklo_pi16 (__m64 __m1, __m64 __m2) +{ + __m64 ret; + asm("punpcklhw %0, %1, %2\n\t" + : "=f" (ret) + : "f" (__m1), "f" (__m2) + ); + return ret; +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_xor_si64 (__m64 __m1, __m64 __m2) +{ + __m64 ret; + asm("xor %0, %1, %2\n\t" + : "=f" (ret) + : "f" (__m1), "f" (__m2) + ); + return ret; +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +loongson_extract_pi16 (__m64 __m, int64_t __pos) +{ + __m64 ret; + asm("pextrh %0, %1, %2\n\t" + : "=f" (ret) + : "f" (__m), "f" (*(__m64 *)&__pos) + ); + return ret; +} + +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +loongson_insert_pi16 (__m64 __m1, __m64 __m2, int64_t __pos) +{ + __m64 ret; + asm("pinsrh_%3 %0, %1, %2\n\t" + : "=f" (ret) + : "f" (__m1), "f" (__m2), "i" (__pos) + ); + return ret; +} diff --git a/pixman/pixman/pixman-cpu.c b/pixman/pixman/pixman-cpu.c index 1060f4776..aa9036fa2 100644 --- a/pixman/pixman/pixman-cpu.c +++ b/pixman/pixman/pixman-cpu.c @@ -427,22 +427,19 @@ pixman_have_arm_iwmmxt (void) #endif /* USE_ARM_SIMD || USE_ARM_NEON || USE_ARM_IWMMXT */ -#if defined(USE_MIPS_DSPR2) +#if defined(USE_MIPS_DSPR2) || defined(USE_LOONGSON_MMI) #if defined (__linux__) /* linux ELF */ -pixman_bool_t -pixman_have_mips_dspr2 (void) +static pixman_bool_t +pixman_have_mips_feature (const char *search_string) { - const char *search_string = "MIPS 74K"; const char *file_name = "/proc/cpuinfo"; - /* Simple detection of MIPS DSP ASE (revision 2) at runtime for Linux. + /* Simple detection of MIPS features at runtime for Linux. * It is based on /proc/cpuinfo, which reveals hardware configuration * to user-space applications. According to MIPS (early 2010), no similar * facility is universally available on the MIPS architectures, so it's up * to individual OSes to provide such. - * - * Only currently available MIPS core that supports DSPr2 is 74K. */ char cpuinfo_line[256]; @@ -467,13 +464,32 @@ pixman_have_mips_dspr2 (void) return FALSE; } +#if defined(USE_MIPS_DSPR2) +pixman_bool_t +pixman_have_mips_dspr2 (void) +{ + /* Only currently available MIPS core that supports DSPr2 is 74K. */ + return pixman_have_mips_feature ("MIPS 74K"); +} +#endif + +#if defined(USE_LOONGSON_MMI) +pixman_bool_t +pixman_have_loongson_mmi (void) +{ + /* I really don't know if some Loongson CPUs don't have MMI. */ + return pixman_have_mips_feature ("Loongson"); +} +#endif + #else /* linux ELF */ #define pixman_have_mips_dspr2() FALSE +#define pixman_have_loongson_mmi() FALSE #endif /* linux ELF */ -#endif /* USE_MIPS_DSPR2 */ +#endif /* USE_MIPS_DSPR2 || USE_LOONGSON_MMI */ #if defined(USE_X86_MMX) || defined(USE_SSE2) /* The CPU detection code needs to be in a file not compiled with @@ -773,7 +789,10 @@ _pixman_choose_implementation (void) if (!disabled ("arm-iwmmxt") && pixman_have_arm_iwmmxt ()) imp = _pixman_implementation_create_mmx (imp); #endif - +#ifdef USE_LOONGSON_MMI + if (!disabled ("loongson-mmi") && pixman_have_loongson_mmi ()) + imp = _pixman_implementation_create_mmx (imp); +#endif #ifdef USE_ARM_NEON if (!disabled ("arm-neon") && pixman_have_arm_neon ()) imp = _pixman_implementation_create_arm_neon (imp); diff --git a/pixman/pixman/pixman-mmx.c b/pixman/pixman/pixman-mmx.c index 9fd1a76f9..b14201a4e 100644 --- a/pixman/pixman/pixman-mmx.c +++ b/pixman/pixman/pixman-mmx.c @@ -33,9 +33,13 @@ #include <config.h> #endif -#if defined USE_X86_MMX || defined USE_ARM_IWMMXT +#if defined USE_X86_MMX || defined USE_ARM_IWMMXT || defined USE_LOONGSON_MMI +#ifdef USE_LOONGSON_MMI +#include <loongson-mmintrin.h> +#else #include <mmintrin.h> +#endif #include "pixman-private.h" #include "pixman-combine32.h" @@ -63,6 +67,19 @@ _mm_empty (void) /* We have to compile with -msse to use xmmintrin.h, but that causes SSE * instructions to be generated that we don't want. Just duplicate the * functions we want to use. */ +extern __inline int __attribute__((__gnu_inline__, __always_inline__, __artificial__)) +_mm_movemask_pi8 (__m64 __A) +{ + int ret; + + asm ("pmovmskb %1, %0\n\t" + : "=r" (ret) + : "y" (__A) + ); + + return ret; +} + extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm_mulhi_pu16 (__m64 __A, __m64 __B) { @@ -125,11 +142,14 @@ _mm_shuffle_pi16 (__m64 __A, int8_t const __N) * uint64_t and __m64 values, then define USE_CVT_INTRINSICS. * If __m64 and uint64_t values can just be cast to each other directly, * then define USE_M64_CASTS. + * If __m64 is a double datatype, then define USE_M64_DOUBLE. */ #ifdef _MSC_VER # define M64_MEMBER m64_u64 #elif defined(__ICC) # define USE_CVT_INTRINSICS +#elif defined(USE_LOONGSON_MMI) +# define USE_M64_DOUBLE #elif defined(__GNUC__) # define USE_M64_CASTS #elif defined(__SUNPRO_C) @@ -147,7 +167,7 @@ _mm_shuffle_pi16 (__m64 __A, int8_t const __N) # endif #endif -#if defined(USE_M64_CASTS) || defined(USE_CVT_INTRINSICS) +#if defined(USE_M64_CASTS) || defined(USE_CVT_INTRINSICS) || defined(USE_M64_DOUBLE) typedef uint64_t mmxdatafield; #else typedef __m64 mmxdatafield; @@ -159,15 +179,21 @@ typedef struct mmxdatafield mmx_4x0080; mmxdatafield mmx_565_rgb; mmxdatafield mmx_565_unpack_multiplier; + mmxdatafield mmx_565_pack_multiplier; mmxdatafield mmx_565_r; mmxdatafield mmx_565_g; mmxdatafield mmx_565_b; + mmxdatafield mmx_packed_565_rb; + mmxdatafield mmx_packed_565_g; +#ifndef USE_LOONGSON_MMI mmxdatafield mmx_mask_0; mmxdatafield mmx_mask_1; mmxdatafield mmx_mask_2; mmxdatafield mmx_mask_3; +#endif mmxdatafield mmx_full_alpha; mmxdatafield mmx_4x0101; + mmxdatafield mmx_ff000000; } mmx_data_t; #if defined(_MSC_VER) @@ -184,21 +210,29 @@ static const mmx_data_t c = MMXDATA_INIT (.mmx_4x0080, 0x0080008000800080), MMXDATA_INIT (.mmx_565_rgb, 0x000001f0003f001f), MMXDATA_INIT (.mmx_565_unpack_multiplier, 0x0000008404100840), + MMXDATA_INIT (.mmx_565_pack_multiplier, 0x2000000420000004), MMXDATA_INIT (.mmx_565_r, 0x000000f800000000), MMXDATA_INIT (.mmx_565_g, 0x0000000000fc0000), MMXDATA_INIT (.mmx_565_b, 0x00000000000000f8), + MMXDATA_INIT (.mmx_packed_565_rb, 0x00f800f800f800f8), + MMXDATA_INIT (.mmx_packed_565_g, 0x0000fc000000fc00), +#ifndef USE_LOONGSON_MMI MMXDATA_INIT (.mmx_mask_0, 0xffffffffffff0000), MMXDATA_INIT (.mmx_mask_1, 0xffffffff0000ffff), MMXDATA_INIT (.mmx_mask_2, 0xffff0000ffffffff), MMXDATA_INIT (.mmx_mask_3, 0x0000ffffffffffff), +#endif MMXDATA_INIT (.mmx_full_alpha, 0x00ff000000000000), MMXDATA_INIT (.mmx_4x0101, 0x0101010101010101), + MMXDATA_INIT (.mmx_ff000000, 0xff000000ff000000), }; #ifdef USE_CVT_INTRINSICS # define MC(x) to_m64 (c.mmx_ ## x) #elif defined(USE_M64_CASTS) # define MC(x) ((__m64)c.mmx_ ## x) +#elif defined(USE_M64_DOUBLE) +# define MC(x) (*(__m64 *)&c.mmx_ ## x) #else # define MC(x) c.mmx_ ## x #endif @@ -213,6 +247,8 @@ to_m64 (uint64_t x) res.M64_MEMBER = x; return res; +#elif defined USE_M64_DOUBLE + return *(__m64 *)&x; #else /* USE_M64_CASTS */ return (__m64)x; #endif @@ -226,6 +262,8 @@ to_uint64 (__m64 x) #elif defined M64_MEMBER /* __m64 is a struct, not an integral type */ uint64_t res = x.M64_MEMBER; return res; +#elif defined USE_M64_DOUBLE + return *(uint64_t *)&x; #else /* USE_M64_CASTS */ return (uint64_t)x; #endif @@ -324,7 +362,7 @@ in_over (__m64 src, __m64 srca, __m64 mask, __m64 dest) /* Elemental unaligned loads */ -static force_inline __m64 ldq_u(uint64_t *p) +static force_inline __m64 ldq_u(__m64 *p) { #ifdef USE_X86_MMX /* x86's alignment restrictions are very relaxed. */ @@ -337,7 +375,7 @@ static force_inline __m64 ldq_u(uint64_t *p) aligned_p = (__m64 *)((uintptr_t)p & ~7); return (__m64) _mm_align_si64 (aligned_p[0], aligned_p[1], align); #else - struct __una_u64 { uint64_t x __attribute__((packed)); }; + struct __una_u64 { __m64 x __attribute__((packed)); }; const struct __una_u64 *ptr = (const struct __una_u64 *) p; return (__m64) ptr->x; #endif @@ -356,16 +394,35 @@ static force_inline uint32_t ldl_u(const uint32_t *p) } static force_inline __m64 +load (const uint32_t *v) +{ +#ifdef USE_LOONGSON_MMI + __m64 ret; + asm ("lwc1 %0, %1\n\t" + : "=f" (ret) + : "m" (*v) + ); + return ret; +#else + return _mm_cvtsi32_si64 (*v); +#endif +} + +static force_inline __m64 load8888 (const uint32_t *v) { - return _mm_unpacklo_pi8 (_mm_cvtsi32_si64 (*v), _mm_setzero_si64 ()); +#ifdef USE_LOONGSON_MMI + return _mm_unpacklo_pi8_f (*(__m32 *)v, _mm_setzero_si64 ()); +#else + return _mm_unpacklo_pi8 (load (v), _mm_setzero_si64 ()); +#endif } static force_inline __m64 load8888u (const uint32_t *v) { - uint32_t l = ldl_u(v); - return load8888(&l); + uint32_t l = ldl_u (v); + return load8888 (&l); } static force_inline __m64 @@ -375,10 +432,52 @@ pack8888 (__m64 lo, __m64 hi) } static force_inline void -store8888 (uint32_t *dest, __m64 v) +store (uint32_t *dest, __m64 v) { - v = pack8888 (v, _mm_setzero_si64()); +#ifdef USE_LOONGSON_MMI + asm ("swc1 %1, %0\n\t" + : "=m" (*dest) + : "f" (v) + : "memory" + ); +#else *dest = _mm_cvtsi64_si32 (v); +#endif +} + +static force_inline void +store8888 (uint32_t *dest, __m64 v) +{ + v = pack8888 (v, _mm_setzero_si64 ()); + store (dest, v); +} + +static force_inline pixman_bool_t +is_equal (__m64 a, __m64 b) +{ +#ifdef USE_LOONGSON_MMI + /* __m64 is double, we can compare directly. */ + return a == b; +#else + return _mm_movemask_pi8 (_mm_cmpeq_pi8 (a, b)) == 0xff; +#endif +} + +static force_inline pixman_bool_t +is_opaque (__m64 v) +{ +#ifdef USE_LOONGSON_MMI + return is_equal (_mm_and_si64 (v, MC (full_alpha)), MC (full_alpha)); +#else + __m64 ffs = _mm_cmpeq_pi8 (v, v); + return (_mm_movemask_pi8 (_mm_cmpeq_pi8 (v, ffs)) & 0x40); +#endif +} + +static force_inline pixman_bool_t +is_zero (__m64 v) +{ + return is_equal (v, _mm_setzero_si64 ()); } /* Expand 16 bits positioned at @pos (0-3) of a mmx register into @@ -402,7 +501,11 @@ expand565 (__m64 pixel, int pos) __m64 t1, t2; /* move pixel to low 16 bit and zero the rest */ +#ifdef USE_LOONGSON_MMI + p = loongson_extract_pi16 (p, pos); +#else p = shift (shift (p, (3 - pos) * 16), -48); +#endif t1 = shift (p, 36 - 11); t2 = shift (p, 16 - 5); @@ -441,6 +544,15 @@ pack_565 (__m64 pixel, __m64 target, int pos) g = _mm_and_si64 (p, MC (565_g)); b = _mm_and_si64 (p, MC (565_b)); +#ifdef USE_LOONGSON_MMI + r = shift (r, -(32 - 8)); + g = shift (g, -(16 - 3)); + b = shift (b, -(0 + 3)); + + p = _mm_or_si64 (r, g); + p = _mm_or_si64 (p, b); + return loongson_insert_pi16 (t, p, pos); +#else r = shift (r, -(32 - 8) + pos * 16); g = shift (g, -(16 - 3) + pos * 16); b = shift (b, -(0 + 3) + pos * 16); @@ -458,6 +570,32 @@ pack_565 (__m64 pixel, __m64 target, int pos) p = _mm_or_si64 (g, p); return _mm_or_si64 (b, p); +#endif +} + +static force_inline __m64 +pack_4xpacked565 (__m64 a, __m64 b) +{ + __m64 rb0 = _mm_and_si64 (a, MC (packed_565_rb)); + __m64 rb1 = _mm_and_si64 (b, MC (packed_565_rb)); + + __m64 t0 = _mm_madd_pi16 (rb0, MC (565_pack_multiplier)); + __m64 t1 = _mm_madd_pi16 (rb1, MC (565_pack_multiplier)); + + __m64 g0 = _mm_and_si64 (a, MC (packed_565_g)); + __m64 g1 = _mm_and_si64 (b, MC (packed_565_g)); + + t0 = _mm_or_si64 (t0, g0); + t1 = _mm_or_si64 (t1, g1); + + t0 = shift(t0, -5); +#ifdef USE_ARM_IWMMXT + t1 = shift(t1, -5); + return _mm_packs_pu32 (t0, t1); +#else + t1 = shift(t1, -5 + 16); + return _mm_shuffle_pi16 (_mm_or_si64 (t0, t1), _MM_SHUFFLE (3, 1, 2, 0)); +#endif } #ifndef _MSC_VER @@ -482,23 +620,20 @@ pix_add_mul (__m64 x, __m64 a, __m64 y, __m64 b) /* --------------- MMX code patch for fbcompose.c --------------------- */ -static force_inline uint32_t +static force_inline __m64 combine (const uint32_t *src, const uint32_t *mask) { - uint32_t ssrc = *src; + __m64 vsrc = load8888 (src); if (mask) { __m64 m = load8888 (mask); - __m64 s = load8888 (&ssrc); m = expand_alpha (m); - s = pix_multiply (s, m); - - store8888 (&ssrc, s); + vsrc = pix_multiply (vsrc, m); } - return ssrc; + return vsrc; } static void @@ -513,19 +648,16 @@ mmx_combine_over_u (pixman_implementation_t *imp, while (dest < end) { - uint32_t ssrc = combine (src, mask); - uint32_t a = ssrc >> 24; + __m64 vsrc = combine (src, mask); - if (a == 0xff) + if (is_opaque (vsrc)) { - *dest = ssrc; + store8888 (dest, vsrc); } - else if (ssrc) + else if (!is_zero (vsrc)) { - __m64 s, sa; - s = load8888 (&ssrc); - sa = expand_alpha (s); - store8888 (dest, over (s, sa, load8888 (dest))); + __m64 sa = expand_alpha (vsrc); + store8888 (dest, over (vsrc, sa, load8888 (dest))); } ++dest; @@ -549,11 +681,11 @@ mmx_combine_over_reverse_u (pixman_implementation_t *imp, while (dest < end) { __m64 d, da; - uint32_t s = combine (src, mask); + __m64 s = combine (src, mask); d = load8888 (dest); da = expand_alpha (d); - store8888 (dest, over (d, da, load8888 (&s))); + store8888 (dest, over (d, da, s)); ++dest; ++src; @@ -575,10 +707,9 @@ mmx_combine_in_u (pixman_implementation_t *imp, while (dest < end) { - __m64 x, a; - uint32_t ssrc = combine (src, mask); + __m64 a; + __m64 x = combine (src, mask); - x = load8888 (&ssrc); a = load8888 (dest); a = expand_alpha (a); x = pix_multiply (x, a); @@ -605,11 +736,10 @@ mmx_combine_in_reverse_u (pixman_implementation_t *imp, while (dest < end) { - __m64 x, a; - uint32_t ssrc = combine (src, mask); + __m64 a = combine (src, mask); + __m64 x; x = load8888 (dest); - a = load8888 (&ssrc); a = expand_alpha (a); x = pix_multiply (x, a); store8888 (dest, x); @@ -634,10 +764,9 @@ mmx_combine_out_u (pixman_implementation_t *imp, while (dest < end) { - __m64 x, a; - uint32_t ssrc = combine (src, mask); + __m64 a; + __m64 x = combine (src, mask); - x = load8888 (&ssrc); a = load8888 (dest); a = expand_alpha (a); a = negate (a); @@ -664,11 +793,10 @@ mmx_combine_out_reverse_u (pixman_implementation_t *imp, while (dest < end) { - __m64 x, a; - uint32_t ssrc = combine (src, mask); + __m64 a = combine (src, mask); + __m64 x; x = load8888 (dest); - a = load8888 (&ssrc); a = expand_alpha (a); a = negate (a); x = pix_multiply (x, a); @@ -695,10 +823,9 @@ mmx_combine_atop_u (pixman_implementation_t *imp, while (dest < end) { - __m64 s, da, d, sia; - uint32_t ssrc = combine (src, mask); + __m64 da, d, sia; + __m64 s = combine (src, mask); - s = load8888 (&ssrc); d = load8888 (dest); sia = expand_alpha (s); sia = negate (sia); @@ -728,10 +855,9 @@ mmx_combine_atop_reverse_u (pixman_implementation_t *imp, while (dest < end) { - __m64 s, dia, d, sa; - uint32_t ssrc = combine (src, mask); + __m64 dia, d, sa; + __m64 s = combine (src, mask); - s = load8888 (&ssrc); d = load8888 (dest); sa = expand_alpha (s); dia = expand_alpha (d); @@ -759,10 +885,9 @@ mmx_combine_xor_u (pixman_implementation_t *imp, while (dest < end) { - __m64 s, dia, d, sia; - uint32_t ssrc = combine (src, mask); + __m64 dia, d, sia; + __m64 s = combine (src, mask); - s = load8888 (&ssrc); d = load8888 (dest); sia = expand_alpha (s); dia = expand_alpha (d); @@ -791,10 +916,9 @@ mmx_combine_add_u (pixman_implementation_t *imp, while (dest < end) { - __m64 s, d; - uint32_t ssrc = combine (src, mask); + __m64 d; + __m64 s = combine (src, mask); - s = load8888 (&ssrc); d = load8888 (dest); s = pix_add (s, d); store8888 (dest, s); @@ -819,12 +943,14 @@ mmx_combine_saturate_u (pixman_implementation_t *imp, while (dest < end) { - uint32_t s = combine (src, mask); + uint32_t s, sa, da; uint32_t d = *dest; - __m64 ms = load8888 (&s); - __m64 md = load8888 (&d); - uint32_t sa = s >> 24; - uint32_t da = ~d >> 24; + __m64 ms = combine (src, mask); + __m64 md = load8888 (dest); + + store8888(&s, ms); + da = ~d >> 24; + sa = s >> 24; if (sa > da) { @@ -1440,7 +1566,7 @@ mmx_composite_over_8888_n_8888 (pixman_implementation_t *imp, while (w >= 2) { - __m64 vs = ldq_u((uint64_t *)src); + __m64 vs = ldq_u ((__m64 *)src); __m64 vd = *(__m64 *)dst; __m64 vsrc0 = expand8888 (vs, 0); __m64 vsrc1 = expand8888 (vs, 1); @@ -1522,14 +1648,14 @@ mmx_composite_over_x888_n_8888 (pixman_implementation_t *imp, __m64 vd6 = *(__m64 *)(dst + 12); __m64 vd7 = *(__m64 *)(dst + 14); - __m64 vs0 = ldq_u((uint64_t *)(src + 0)); - __m64 vs1 = ldq_u((uint64_t *)(src + 2)); - __m64 vs2 = ldq_u((uint64_t *)(src + 4)); - __m64 vs3 = ldq_u((uint64_t *)(src + 6)); - __m64 vs4 = ldq_u((uint64_t *)(src + 8)); - __m64 vs5 = ldq_u((uint64_t *)(src + 10)); - __m64 vs6 = ldq_u((uint64_t *)(src + 12)); - __m64 vs7 = ldq_u((uint64_t *)(src + 14)); + __m64 vs0 = ldq_u ((__m64 *)(src + 0)); + __m64 vs1 = ldq_u ((__m64 *)(src + 2)); + __m64 vs2 = ldq_u ((__m64 *)(src + 4)); + __m64 vs3 = ldq_u ((__m64 *)(src + 6)); + __m64 vs4 = ldq_u ((__m64 *)(src + 8)); + __m64 vs5 = ldq_u ((__m64 *)(src + 10)); + __m64 vs6 = ldq_u ((__m64 *)(src + 12)); + __m64 vs7 = ldq_u ((__m64 *)(src + 14)); vd0 = pack8888 ( in_over (expandx888 (vs0, 0), srca, vmask, expand8888 (vd0, 0)), @@ -1996,6 +2122,60 @@ pixman_fill_mmx (uint32_t *bits, } static void +mmx_composite_src_x888_0565 (pixman_implementation_t *imp, + pixman_composite_info_t *info) +{ + PIXMAN_COMPOSITE_ARGS (info); + uint16_t *dst_line, *dst; + uint32_t *src_line, *src, s; + int dst_stride, src_stride; + int32_t w; + + PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1); + PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint16_t, dst_stride, dst_line, 1); + + while (height--) + { + dst = dst_line; + dst_line += dst_stride; + src = src_line; + src_line += src_stride; + w = width; + + while (w && (unsigned long)dst & 7) + { + s = *src++; + *dst = CONVERT_8888_TO_0565 (s); + dst++; + w--; + } + + while (w >= 4) + { + __m64 vdest; + __m64 vsrc0 = ldq_u ((__m64 *)(src + 0)); + __m64 vsrc1 = ldq_u ((__m64 *)(src + 2)); + + vdest = pack_4xpacked565 (vsrc0, vsrc1); + + *(__m64 *)dst = vdest; + + w -= 4; + src += 4; + dst += 4; + } + + while (w) + { + s = *src++; + *dst = CONVERT_8888_TO_0565 (s); + dst++; + w--; + } + } +} + +static void mmx_composite_src_n_8_8888 (pixman_implementation_t *imp, pixman_composite_info_t *info) { @@ -2123,7 +2303,7 @@ mmx_composite_over_n_8_0565 (pixman_implementation_t *imp, int dst_stride, mask_stride; int32_t w; __m64 vsrc, vsrca, tmp; - uint64_t srcsrcsrcsrc, src16; + __m64 srcsrcsrcsrc; CHECKPOINT (); @@ -2140,11 +2320,7 @@ mmx_composite_over_n_8_0565 (pixman_implementation_t *imp, vsrca = expand_alpha (vsrc); tmp = pack_565 (vsrc, _mm_setzero_si64 (), 0); - src16 = to_uint64 (tmp); - - srcsrcsrcsrc = - (uint64_t)src16 << 48 | (uint64_t)src16 << 32 | - (uint64_t)src16 << 16 | (uint64_t)src16; + srcsrcsrcsrc = expand_alpha_rev (tmp); while (height--) { @@ -2188,7 +2364,7 @@ mmx_composite_over_n_8_0565 (pixman_implementation_t *imp, if (srca == 0xff && (m0 & m1 & m2 & m3) == 0xff) { - *(uint64_t *)dst = srcsrcsrcsrc; + *(__m64 *)dst = srcsrcsrcsrc; } else if (m0 | m1 | m2 | m3) { @@ -2809,7 +2985,7 @@ mmx_composite_add_8_8 (pixman_implementation_t *imp, while (w >= 8) { - *(__m64*)dst = _mm_adds_pu8 (ldq_u((uint64_t *)src), *(__m64*)dst); + *(__m64*)dst = _mm_adds_pu8 (ldq_u ((__m64 *)src), *(__m64*)dst); dst += 8; src += 8; w -= 8; @@ -2837,7 +3013,6 @@ mmx_composite_add_8888_8888 (pixman_implementation_t *imp, pixman_composite_info_t *info) { PIXMAN_COMPOSITE_ARGS (info); - __m64 dst64; uint32_t *dst_line, *dst; uint32_t *src_line, *src; int dst_stride, src_stride; @@ -2858,8 +3033,8 @@ mmx_composite_add_8888_8888 (pixman_implementation_t *imp, while (w && (unsigned long)dst & 7) { - *dst = _mm_cvtsi64_si32 (_mm_adds_pu8 (_mm_cvtsi32_si64 (*src), - _mm_cvtsi32_si64 (*dst))); + store (dst, _mm_adds_pu8 (load ((const uint32_t *)src), + load ((const uint32_t *)dst))); dst++; src++; w--; @@ -2867,8 +3042,7 @@ mmx_composite_add_8888_8888 (pixman_implementation_t *imp, while (w >= 2) { - dst64 = _mm_adds_pu8 (ldq_u((uint64_t *)src), *(__m64*)dst); - *(uint64_t*)dst = to_uint64 (dst64); + *(__m64 *)dst = _mm_adds_pu8 (ldq_u ((__m64 *)src), *(__m64*)dst); dst += 2; src += 2; w -= 2; @@ -2876,8 +3050,8 @@ mmx_composite_add_8888_8888 (pixman_implementation_t *imp, if (w) { - *dst = _mm_cvtsi64_si32 (_mm_adds_pu8 (_mm_cvtsi32_si64 (*src), - _mm_cvtsi32_si64 (*dst))); + store (dst, _mm_adds_pu8 (load ((const uint32_t *)src), + load ((const uint32_t *)dst))); } } @@ -2958,7 +3132,7 @@ pixman_blt_mmx (uint32_t *src_bits, while (w >= 4 && ((unsigned long)d & 7)) { - *(uint32_t *)d = ldl_u((uint32_t *)s); + *(uint32_t *)d = ldl_u ((uint32_t *)s); w -= 4; s += 4; @@ -2992,14 +3166,14 @@ pixman_blt_mmx (uint32_t *src_bits, "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7"); #else - __m64 v0 = ldq_u((uint64_t *)(s + 0)); - __m64 v1 = ldq_u((uint64_t *)(s + 8)); - __m64 v2 = ldq_u((uint64_t *)(s + 16)); - __m64 v3 = ldq_u((uint64_t *)(s + 24)); - __m64 v4 = ldq_u((uint64_t *)(s + 32)); - __m64 v5 = ldq_u((uint64_t *)(s + 40)); - __m64 v6 = ldq_u((uint64_t *)(s + 48)); - __m64 v7 = ldq_u((uint64_t *)(s + 56)); + __m64 v0 = ldq_u ((__m64 *)(s + 0)); + __m64 v1 = ldq_u ((__m64 *)(s + 8)); + __m64 v2 = ldq_u ((__m64 *)(s + 16)); + __m64 v3 = ldq_u ((__m64 *)(s + 24)); + __m64 v4 = ldq_u ((__m64 *)(s + 32)); + __m64 v5 = ldq_u ((__m64 *)(s + 40)); + __m64 v6 = ldq_u ((__m64 *)(s + 48)); + __m64 v7 = ldq_u ((__m64 *)(s + 56)); *(__m64 *)(d + 0) = v0; *(__m64 *)(d + 8) = v1; *(__m64 *)(d + 16) = v2; @@ -3016,7 +3190,7 @@ pixman_blt_mmx (uint32_t *src_bits, } while (w >= 4) { - *(uint32_t *)d = ldl_u((uint32_t *)s); + *(uint32_t *)d = ldl_u ((uint32_t *)s); w -= 4; s += 4; @@ -3109,6 +3283,190 @@ mmx_composite_over_x888_8_8888 (pixman_implementation_t *imp, _mm_empty (); } +static uint32_t * +mmx_fetch_x8r8g8b8 (pixman_iter_t *iter, const uint32_t *mask) +{ + int w = iter->width; + uint32_t *dst = iter->buffer; + uint32_t *src = (uint32_t *)iter->bits; + + iter->bits += iter->stride; + + while (w && ((unsigned long)dst) & 7) + { + *dst++ = (*src++) | 0xff000000; + w--; + } + + while (w >= 8) + { + __m64 vsrc1 = ldq_u ((__m64 *)(src + 0)); + __m64 vsrc2 = ldq_u ((__m64 *)(src + 2)); + __m64 vsrc3 = ldq_u ((__m64 *)(src + 4)); + __m64 vsrc4 = ldq_u ((__m64 *)(src + 6)); + + *(__m64 *)(dst + 0) = _mm_or_si64 (vsrc1, MC (ff000000)); + *(__m64 *)(dst + 2) = _mm_or_si64 (vsrc2, MC (ff000000)); + *(__m64 *)(dst + 4) = _mm_or_si64 (vsrc3, MC (ff000000)); + *(__m64 *)(dst + 6) = _mm_or_si64 (vsrc4, MC (ff000000)); + + dst += 8; + src += 8; + w -= 8; + } + + while (w) + { + *dst++ = (*src++) | 0xff000000; + w--; + } + + return iter->buffer; +} + +static uint32_t * +mmx_fetch_r5g6b5 (pixman_iter_t *iter, const uint32_t *mask) +{ + int w = iter->width; + uint32_t *dst = iter->buffer; + uint16_t *src = (uint16_t *)iter->bits; + + iter->bits += iter->stride; + + while (w && ((unsigned long)dst) & 0x0f) + { + uint16_t s = *src++; + + *dst++ = CONVERT_0565_TO_8888 (s); + w--; + } + + while (w >= 4) + { + __m64 vsrc = ldq_u ((__m64 *)src); + + __m64 mm0 = expand565 (vsrc, 0); + __m64 mm1 = expand565 (vsrc, 1); + __m64 mm2 = expand565 (vsrc, 2); + __m64 mm3 = expand565 (vsrc, 3); + + *(__m64 *)(dst + 0) = _mm_or_si64 (pack8888 (mm0, mm1), MC (ff000000)); + *(__m64 *)(dst + 2) = _mm_or_si64 (pack8888 (mm2, mm3), MC (ff000000)); + + dst += 4; + src += 4; + w -= 4; + } + + while (w) + { + uint16_t s = *src++; + + *dst++ = CONVERT_0565_TO_8888 (s); + w--; + } + + return iter->buffer; +} + +static uint32_t * +mmx_fetch_a8 (pixman_iter_t *iter, const uint32_t *mask) +{ + int w = iter->width; + uint32_t *dst = iter->buffer; + uint8_t *src = iter->bits; + + iter->bits += iter->stride; + + while (w && (((unsigned long)dst) & 15)) + { + *dst++ = *(src++) << 24; + w--; + } + + while (w >= 8) + { + __m64 mm0 = ldq_u ((__m64 *)src); + + __m64 mm1 = _mm_unpacklo_pi8 (_mm_setzero_si64(), mm0); + __m64 mm2 = _mm_unpackhi_pi8 (_mm_setzero_si64(), mm0); + __m64 mm3 = _mm_unpacklo_pi16 (_mm_setzero_si64(), mm1); + __m64 mm4 = _mm_unpackhi_pi16 (_mm_setzero_si64(), mm1); + __m64 mm5 = _mm_unpacklo_pi16 (_mm_setzero_si64(), mm2); + __m64 mm6 = _mm_unpackhi_pi16 (_mm_setzero_si64(), mm2); + + *(__m64 *)(dst + 0) = mm3; + *(__m64 *)(dst + 2) = mm4; + *(__m64 *)(dst + 4) = mm5; + *(__m64 *)(dst + 6) = mm6; + + dst += 8; + src += 8; + w -= 8; + } + + while (w) + { + *dst++ = *(src++) << 24; + w--; + } + + return iter->buffer; +} + +typedef struct +{ + pixman_format_code_t format; + pixman_iter_get_scanline_t get_scanline; +} fetcher_info_t; + +static const fetcher_info_t fetchers[] = +{ + { PIXMAN_x8r8g8b8, mmx_fetch_x8r8g8b8 }, + { PIXMAN_r5g6b5, mmx_fetch_r5g6b5 }, + { PIXMAN_a8, mmx_fetch_a8 }, + { PIXMAN_null } +}; + +static void +mmx_src_iter_init (pixman_implementation_t *imp, pixman_iter_t *iter) +{ + pixman_image_t *image = iter->image; + int x = iter->x; + int y = iter->y; + int width = iter->width; + int height = iter->height; + +#define FLAGS \ + (FAST_PATH_STANDARD_FLAGS | FAST_PATH_ID_TRANSFORM | FAST_PATH_BITS_IMAGE) + + if ((iter->flags & ITER_NARROW) && + (image->common.flags & FLAGS) == FLAGS && + x >= 0 && y >= 0 && + x + width <= image->bits.width && + y + height <= image->bits.height) + { + const fetcher_info_t *f; + + for (f = &fetchers[0]; f->format != PIXMAN_null; f++) + { + if (image->common.extended_format_code == f->format) + { + uint8_t *b = (uint8_t *)image->bits.bits; + int s = image->bits.rowstride * 4; + + iter->bits = b + s * iter->y + x * PIXMAN_FORMAT_BPP (f->format) / 8; + iter->stride = s; + + iter->get_scanline = f->get_scanline; + return; + } + } + } + + imp->delegate->src_iter_init (imp->delegate, iter); +} + static const pixman_fast_path_t mmx_fast_paths[] = { PIXMAN_STD_FAST_PATH (OVER, solid, a8, r5g6b5, mmx_composite_over_n_8_0565 ), @@ -3160,6 +3518,10 @@ static const pixman_fast_path_t mmx_fast_paths[] = PIXMAN_STD_FAST_PATH (ADD, a8, null, a8, mmx_composite_add_8_8 ), PIXMAN_STD_FAST_PATH (ADD, solid, a8, a8, mmx_composite_add_n_8_8 ), + PIXMAN_STD_FAST_PATH (SRC, a8r8g8b8, null, r5g6b5, mmx_composite_src_x888_0565 ), + PIXMAN_STD_FAST_PATH (SRC, a8b8g8r8, null, b5g6r5, mmx_composite_src_x888_0565 ), + PIXMAN_STD_FAST_PATH (SRC, x8r8g8b8, null, r5g6b5, mmx_composite_src_x888_0565 ), + PIXMAN_STD_FAST_PATH (SRC, x8b8g8r8, null, b5g6r5, mmx_composite_src_x888_0565 ), PIXMAN_STD_FAST_PATH (SRC, solid, a8, a8r8g8b8, mmx_composite_src_n_8_8888 ), PIXMAN_STD_FAST_PATH (SRC, solid, a8, x8r8g8b8, mmx_composite_src_n_8_8888 ), PIXMAN_STD_FAST_PATH (SRC, solid, a8, a8b8g8r8, mmx_composite_src_n_8_8888 ), @@ -3260,7 +3622,9 @@ _pixman_implementation_create_mmx (pixman_implementation_t *fallback) imp->blt = mmx_blt; imp->fill = mmx_fill; + imp->src_iter_init = mmx_src_iter_init; + return imp; } -#endif /* USE_X86_MMX || USE_ARM_IWMMXT */ +#endif /* USE_X86_MMX || USE_ARM_IWMMXT || USE_LOONGSON_MMI */ diff --git a/pixman/pixman/pixman-private.h b/pixman/pixman/pixman-private.h index 0cba2e962..f456bbd33 100644 --- a/pixman/pixman/pixman-private.h +++ b/pixman/pixman/pixman-private.h @@ -539,7 +539,7 @@ _pixman_implementation_create_fast_path (pixman_implementation_t *fallback); pixman_implementation_t * _pixman_implementation_create_noop (pixman_implementation_t *fallback); -#if defined USE_X86_MMX || defined USE_ARM_IWMMXT +#if defined USE_X86_MMX || defined USE_ARM_IWMMXT || defined USE_LOONGSON_MMI pixman_implementation_t * _pixman_implementation_create_mmx (pixman_implementation_t *fallback); #endif diff --git a/xorg-server/Xext/xres.c b/xorg-server/Xext/xres.c index ecef0c032..dbefeebdb 100644 --- a/xorg-server/Xext/xres.c +++ b/xorg-server/Xext/xres.c @@ -29,7 +29,10 @@ #include <string.h> #include "hashtable.h" #include "picturestr.h" + +#ifdef COMPOSITE #include "compint.h" +#endif /** @brief Holds fragments of responses for ConstructClientIds. * diff --git a/xorg-server/glx/glapi_gentable.c b/xorg-server/glx/glapi_gentable.c index 1fb143100..4b2801547 100644 --- a/xorg-server/glx/glapi_gentable.c +++ b/xorg-server/glx/glapi_gentable.c @@ -113,7 +113,7 @@ __glapi_gentable_set_remaining_noop(struct _glapi_table *disp) struct _glapi_table * _glapi_create_table_from_handle(void *handle, const char *symbol_prefix) { - struct _glapi_table *disp = calloc(1, sizeof(struct _glapi_table)); + struct _glapi_table *disp = calloc(_glapi_get_dispatch_table_size(), sizeof(void*)); char symboln[512]; if (!disp) diff --git a/xorg-server/hw/xfree86/modes/xf86Rotate.c b/xorg-server/hw/xfree86/modes/xf86Rotate.c index 85d75573d..cbc868735 100644 --- a/xorg-server/hw/xfree86/modes/xf86Rotate.c +++ b/xorg-server/hw/xfree86/modes/xf86Rotate.c @@ -290,14 +290,19 @@ xf86RotateDestroy(xf86CrtcPtr crtc) * Clean up damage structures when no crtcs are rotated */ if (xf86_config->rotation_damage) { + DrawablePtr screenDrawable = NULL; + if (pScreen && pScreen->root) + screenDrawable = &pScreen->root->drawable; /* Free damage structure */ if (xf86_config->rotation_damage_registered) { - DamageUnregister(&pScreen->root->drawable, - xf86_config->rotation_damage); + if (screenDrawable) + DamageUnregister(screenDrawable, + xf86_config->rotation_damage); xf86_config->rotation_damage_registered = FALSE; DisableLimitedSchedulingLatency(); } - DamageDestroy(xf86_config->rotation_damage); + if (screenDrawable) + DamageDestroy(xf86_config->rotation_damage); xf86_config->rotation_damage = NULL; } } diff --git a/xorg-server/hw/xfree86/sdksyms.sh b/xorg-server/hw/xfree86/sdksyms.sh index 3815525fa..f6c3f2244 100644 --- a/xorg-server/hw/xfree86/sdksyms.sh +++ b/xorg-server/hw/xfree86/sdksyms.sh @@ -251,8 +251,9 @@ cat > sdksyms.c << EOF #include "exa.h" */ - +#ifdef COMPOSITE #include "compositeext.h" +#endif /* xfixes/Makefile.am */ #include "xfixes.h" diff --git a/xorg-server/hw/xquartz/X11Application.m b/xorg-server/hw/xquartz/X11Application.m index a203f7807..0c3283ed0 100644 --- a/xorg-server/hw/xquartz/X11Application.m +++ b/xorg-server/hw/xquartz/X11Application.m @@ -215,9 +215,8 @@ message_kit_thread(SEL selector, NSObject *arg) if (state) { if (bgMouseLocationUpdated) { DarwinSendPointerEvents(darwinPointer, MotionNotify, 0, - bgMouseLocation.x, bgMouseLocation.y, 0.0, - 0.0, - 0.0); + bgMouseLocation.x, bgMouseLocation.y, + 0.0, 0.0); bgMouseLocationUpdated = FALSE; } DarwinSendDDXEvent(kXquartzActivate, 0); @@ -1549,9 +1548,9 @@ handle_mouse: if ([e isEnteringProximity]) needsProximityIn = YES; else - DarwinSendProximityEvents(darwinTabletCurrent, ProximityOut, - location.x, location.y, pressure, - tilt.x, tilt.y); + DarwinSendTabletEvents(darwinTabletCurrent, ProximityOut, 0, + location.x, location.y, pressure, + tilt.x, tilt.y); return; } @@ -1563,9 +1562,9 @@ handle_mouse: pDev = darwinTabletCurrent; if (needsProximityIn) { - DarwinSendProximityEvents(darwinTabletCurrent, ProximityIn, - location.x, location.y, pressure, - tilt.x, tilt.y); + DarwinSendTabletEvents(darwinTabletCurrent, ProximityIn, 0, + location.x, location.y, pressure, + tilt.x, tilt.y); needsProximityIn = NO; } @@ -1596,14 +1595,22 @@ handle_mouse: if (bgMouseLocationUpdated) { if (!(ev_type == MotionNotify && ev_button == 0)) { - DarwinSendPointerEvents(pDev, MotionNotify, 0, location.x, - location.y, pressure, tilt.x, tilt.y); + DarwinSendPointerEvents(darwinPointer, MotionNotify, 0, + location.x, location.y, + 0.0, 0.0); } bgMouseLocationUpdated = FALSE; } - DarwinSendPointerEvents(pDev, ev_type, ev_button, location.x, - location.y, pressure, tilt.x, tilt.y); + if (pDev == darwinPointer) { + DarwinSendPointerEvents(pDev, ev_type, ev_button, + location.x, location.y, + [e deltaX], [e deltaY]); + } else { + DarwinSendTabletEvents(pDev, ev_type, ev_button, + location.x, location.y, pressure, + tilt.x, tilt.y); + } break; @@ -1627,15 +1634,35 @@ handle_mouse: if ([e isEnteringProximity]) needsProximityIn = YES; else - DarwinSendProximityEvents(darwinTabletCurrent, ProximityOut, - location.x, location.y, pressure, - tilt.x, tilt.y); + DarwinSendTabletEvents(darwinTabletCurrent, ProximityOut, 0, + location.x, location.y, pressure, + tilt.x, tilt.y); break; case NSScrollWheel: { - float deltaX = [e deltaX]; - float deltaY = [e deltaY]; + CGFloat deltaX = [e deltaX]; + CGFloat deltaY = [e deltaY]; + CGEventRef cge = [e CGEvent]; + BOOL isContinuous = + CGEventGetIntegerValueField(cge, kCGScrollWheelEventIsContinuous); + +#if 0 + /* Scale the scroll value by line height */ + CGEventSourceRef source = CGEventCreateSourceFromEvent(cge); + if (source) { + double lineHeight = CGEventSourceGetPixelsPerLine(source); + CFRelease(source); + + /* There's no real reason for the 1/5 ratio here other than that + * it feels like a good ratio after some testing. + */ + + deltaX *= lineHeight / 5.0; + deltaY *= lineHeight / 5.0; + } +#endif + #if !defined(XPLUGIN_VERSION) || XPLUGIN_VERSION == 0 /* If we're in the background, we need to send a MotionNotify event * first, since we aren't getting them on background mouse motion @@ -1643,8 +1670,8 @@ handle_mouse: if (!XQuartzServerVisible && noTestExtensions) { bgMouseLocationUpdated = FALSE; DarwinSendPointerEvents(darwinPointer, MotionNotify, 0, - location.x, location.y, pressure, - tilt.x, tilt.y); + location.x, location.y, + 0.0, 0.0); } #endif #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 @@ -1656,6 +1683,93 @@ handle_mouse: deltaY *= -1; } #endif + /* This hack is in place to better deal with "clicky" scroll wheels: + * http://xquartz.macosforge.org/trac/ticket/562 + */ + if (!isContinuous) { + static NSTimeInterval lastScrollTime = 0.0; + + /* These store how much extra we have already scrolled. + * ie, this is how much we ignore on the next event. + */ + static double deficit_x = 0.0; + static double deficit_y = 0.0; + + /* If we have past a second since the last scroll, wipe the slate + * clean + */ + if ([e timestamp] - lastScrollTime > 1.0) { + deficit_x = deficit_y = 0.0; + } + lastScrollTime = [e timestamp]; + + if (deltaX != 0.0) { + /* If we changed directions, wipe the slate clean */ + if ((deficit_x < 0.0 && deltaX > 0.0) || + (deficit_x > 0.0 && deltaX < 0.0)) { + deficit_x = 0.0; + } + + /* Eat up the deficit, but ensure that something is + * always sent + */ + if (fabs(deltaX) > fabs(deficit_x)) { + deltaX -= deficit_x; + + if (deltaX > 0.0) { + deficit_x = ceil(deltaX) - deltaX; + deltaX = ceil(deltaX); + } else { + deficit_x = floor(deltaX) - deltaX; + deltaX = floor(deltaX); + } + } else { + deficit_x -= deltaX; + + if (deltaX > 0.0) { + deltaX = 1.0; + } else { + deltaX = -1.0; + } + + deficit_x += deltaX; + } + } + + if (deltaY != 0.0) { + /* If we changed directions, wipe the slate clean */ + if ((deficit_y < 0.0 && deltaY > 0.0) || + (deficit_y > 0.0 && deltaY < 0.0)) { + deficit_y = 0.0; + } + + /* Eat up the deficit, but ensure that something is + * always sent + */ + if (fabs(deltaY) > fabs(deficit_y)) { + deltaY -= deficit_y; + + if (deltaY > 0.0) { + deficit_y = ceil(deltaY) - deltaY; + deltaY = ceil(deltaY); + } else { + deficit_y = floor(deltaY) - deltaY; + deltaY = floor(deltaY); + } + } else { + deficit_y -= deltaY; + + if (deltaY > 0.0) { + deltaY = 1.0; + } else { + deltaY = -1.0; + } + + deficit_y += deltaY; + } + } + } + DarwinSendScrollEvents(deltaX, deltaY); break; } diff --git a/xorg-server/hw/xquartz/console_redirect.c b/xorg-server/hw/xquartz/console_redirect.c index 7b92eca39..1e0e56bad 100644 --- a/xorg-server/hw/xquartz/console_redirect.c +++ b/xorg-server/hw/xquartz/console_redirect.c @@ -336,7 +336,7 @@ xq_asl_log_fd(aslclient asl, aslmsg msg, int level, int fd) { /* Reallocate if we need more space */ if (fd >= n_redirect_fds) { - size_t new_n = 1 << (ffs(fd) + 1); + size_t new_n = 1 << (fls(fd) + 1); asl_redirect *new_array = realloc(redirect_fds, new_n * sizeof(*redirect_fds)); diff --git a/xorg-server/hw/xquartz/darwin.c b/xorg-server/hw/xquartz/darwin.c index 03030ad22..41db72af8 100644 --- a/xorg-server/hw/xquartz/darwin.c +++ b/xorg-server/hw/xquartz/darwin.c @@ -309,7 +309,7 @@ static int DarwinMouseProc(DeviceIntPtr pPointer, int what) { #define NBUTTONS 3 -#define NAXES 4 +#define NAXES 6 // 3 buttons: left, middle, right CARD8 map[NBUTTONS + 1] = { 0, 1, 2, 3}; Atom btn_labels[NBUTTONS] = { 0 }; @@ -323,10 +323,12 @@ DarwinMouseProc(DeviceIntPtr pPointer, int what) btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE); btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT); - axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X); - axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y); - axes_labels[2] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_WHEEL); - axes_labels[3] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_HWHEEL); + axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_X); + axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_Y); + axes_labels[2] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X); + axes_labels[3] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y); + axes_labels[4] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_WHEEL); + axes_labels[5] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_HWHEEL); // Set button map. InitPointerDeviceStruct((DevicePtr)pPointer, map, NBUTTONS, @@ -334,21 +336,27 @@ DarwinMouseProc(DeviceIntPtr pPointer, int what) (PtrCtrlProcPtr)NoopDDA, GetMotionHistorySize(), NAXES, axes_labels); - InitValuatorAxisStruct(pPointer, 0, axes_labels[0], + InitValuatorAxisStruct(pPointer, 0, axes_labels[0], NO_AXIS_LIMITS, NO_AXIS_LIMITS, - 1, 0, 1, Relative); - InitValuatorAxisStruct(pPointer, 1, axes_labels[1], + 0, 0, 0, Absolute); + InitValuatorAxisStruct(pPointer, 1, axes_labels[1], NO_AXIS_LIMITS, NO_AXIS_LIMITS, - 1, 0, 1, Relative); + 0, 0, 0, Absolute); InitValuatorAxisStruct(pPointer, 2, axes_labels[2], NO_AXIS_LIMITS, NO_AXIS_LIMITS, 1, 0, 1, Relative); InitValuatorAxisStruct(pPointer, 3, axes_labels[3], NO_AXIS_LIMITS, NO_AXIS_LIMITS, 1, 0, 1, Relative); + InitValuatorAxisStruct(pPointer, 4, axes_labels[4], + NO_AXIS_LIMITS, NO_AXIS_LIMITS, + 1, 0, 1, Relative); + InitValuatorAxisStruct(pPointer, 5, axes_labels[5], + NO_AXIS_LIMITS, NO_AXIS_LIMITS, + 1, 0, 1, Relative); - SetScrollValuator(pPointer, 2, SCROLL_TYPE_VERTICAL, -1.0, SCROLL_FLAG_PREFERRED); - SetScrollValuator(pPointer, 3, SCROLL_TYPE_HORIZONTAL, -1.0, SCROLL_FLAG_NONE); + SetScrollValuator(pPointer, 4, SCROLL_TYPE_VERTICAL, -1.0, SCROLL_FLAG_PREFERRED); + SetScrollValuator(pPointer, 5, SCROLL_TYPE_HORIZONTAL, -1.0, SCROLL_FLAG_NONE); break; case DEVICE_ON: @@ -399,23 +407,24 @@ DarwinTabletProc(DeviceIntPtr pPointer, int what) axes_labels); InitProximityClassDeviceStruct(pPointer); - InitValuatorAxisStruct(pPointer, 0, axes_labels[0], 0, - XQUARTZ_VALUATOR_LIMIT, 1, 0, 1, - Absolute); - InitValuatorAxisStruct(pPointer, 1, axes_labels[1], 0, - XQUARTZ_VALUATOR_LIMIT, 1, 0, 1, - Absolute); - InitValuatorAxisStruct(pPointer, 2, axes_labels[2], 0, - XQUARTZ_VALUATOR_LIMIT, 1, 0, 1, - Absolute); + InitValuatorAxisStruct(pPointer, 0, axes_labels[0], + 0, XQUARTZ_VALUATOR_LIMIT, + 1, 0, 1, Absolute); + InitValuatorAxisStruct(pPointer, 1, axes_labels[1], + 0, XQUARTZ_VALUATOR_LIMIT, + 1, 0, 1, Absolute); + InitValuatorAxisStruct(pPointer, 2, axes_labels[2], + 0, XQUARTZ_VALUATOR_LIMIT, + 1, 0, 1, Absolute); InitValuatorAxisStruct(pPointer, 3, axes_labels[3], -XQUARTZ_VALUATOR_LIMIT, - XQUARTZ_VALUATOR_LIMIT, 1, 0, 1, - Absolute); + XQUARTZ_VALUATOR_LIMIT, + 1, 0, 1, Absolute); InitValuatorAxisStruct(pPointer, 4, axes_labels[4], -XQUARTZ_VALUATOR_LIMIT, - XQUARTZ_VALUATOR_LIMIT, 1, 0, 1, - Absolute); + XQUARTZ_VALUATOR_LIMIT, + 1, 0, 1, Absolute); + // pPointer->use = IsXExtensionDevice; break; diff --git a/xorg-server/hw/xquartz/darwinEvents.c b/xorg-server/hw/xquartz/darwinEvents.c index c62dd4484..b41c6fdac 100644 --- a/xorg-server/hw/xquartz/darwinEvents.c +++ b/xorg-server/hw/xquartz/darwinEvents.c @@ -44,19 +44,20 @@ #include <dix-config.h> #endif -#include <X11/X.h> -#include <X11/Xmd.h> -#include <X11/Xproto.h> -#include "misc.h" -#include "windowstr.h" -#include "pixmapstr.h" -#include "inputstr.h" -#include "inpututils.h" -#include "eventstr.h" -#include "mi.h" -#include "scrnintstr.h" -#include "mipointer.h" -#include "os.h" +#include <X11/X.h> +#include <X11/Xmd.h> +#include <X11/Xproto.h> +#include "misc.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "inputstr.h" +#include "inpututils.h" +#include "eventstr.h" +#include "mi.h" +#include "scrnintstr.h" +#include "mipointer.h" +#include "os.h" +#include "exglobals.h" #include "darwin.h" #include "quartz.h" @@ -73,12 +74,6 @@ #include <IOKit/hidsystem/IOLLEvent.h> -/* Fake button press/release for scroll wheel move. */ -#define SCROLLWHEELUPFAKE 4 -#define SCROLLWHEELDOWNFAKE 5 -#define SCROLLWHEELLEFTFAKE 6 -#define SCROLLWHEELRIGHTFAKE 7 - #include <X11/extensions/applewmconst.h> #include "applewmExt.h" @@ -442,56 +437,6 @@ DarwinPokeEQ(void) write(darwinEventWriteFD, &nullbyte, sizeof(nullbyte)); } -/* Convert from Appkit pointer input values to X input values: - * Note: pointer_x and pointer_y are relative to the upper-left of primary - * display. - */ -static void -DarwinPrepareValuators(DeviceIntPtr pDev, ValuatorMask *pmask, - ScreenPtr screen, - double pointer_x, double pointer_y, - double pressure, double tilt_x, - double tilt_y) -{ - - valuator_mask_zero(pmask); - - /* Fix offset between darwin and X screens */ - pointer_x -= darwinMainScreenX + screen->x; - pointer_y -= darwinMainScreenY + screen->y; - - if (pointer_x < 0.0) - pointer_x = 0.0; - - if (pointer_y < 0.0) - pointer_y = 0.0; - - if (pDev == darwinPointer) { - valuator_mask_set_double(pmask, 0, pointer_x); - valuator_mask_set_double(pmask, 1, pointer_y); - } - else { - valuator_mask_set_double(pmask, 0, XQUARTZ_VALUATOR_LIMIT * - (pointer_x / - (double)screenInfo.screens[0]->width)); - valuator_mask_set_double(pmask, 1, XQUARTZ_VALUATOR_LIMIT * - (pointer_y / - (double)screenInfo.screens[0]->height)); - valuator_mask_set_double(pmask, 2, XQUARTZ_VALUATOR_LIMIT * pressure); - valuator_mask_set_double(pmask, 3, XQUARTZ_VALUATOR_LIMIT * tilt_x); - valuator_mask_set_double(pmask, 4, XQUARTZ_VALUATOR_LIMIT * tilt_y); - DEBUG_LOG("Pointer (%lf, %lf), Valuators: {%lf,%lf,%lf,%lf,%lf}\n", - pointer_x, pointer_y, - valuator_mask_get_double(pmask, - 0), - valuator_mask_get_double(pmask, 1), - valuator_mask_get_double(pmask, - 2), - valuator_mask_get_double(pmask, 3), - valuator_mask_get_double(pmask, 4)); - } -} - void DarwinInputReleaseButtonsAndKeys(DeviceIntPtr pDev) { @@ -521,27 +466,73 @@ DarwinInputReleaseButtonsAndKeys(DeviceIntPtr pDev) } void +DarwinSendTabletEvents(DeviceIntPtr pDev, int ev_type, int ev_button, + double pointer_x, double pointer_y, + double pressure, double tilt_x, + double tilt_y) +{ + ScreenPtr screen; + ValuatorMask valuators; + + if (!darwinEvents) { + DEBUG_LOG("%s called before darwinEvents was initialized\n", + __FUNCTION__); + return; + } + + screen = miPointerGetScreen(pDev); + if (!screen) { + DEBUG_LOG("%s called before screen was initialized\n", + __FUNCTION__); + return; + } + + /* Fix offset between darwin and X screens */ + pointer_x -= darwinMainScreenX + screen->x; + pointer_y -= darwinMainScreenY + screen->y; + + /* Adjust our pointer location to the [0,1] range */ + pointer_x = pointer_x / (double)screenInfo.width; + pointer_y = pointer_y / (double)screenInfo.height; + + valuator_mask_zero(&valuators); + valuator_mask_set_double(&valuators, 0, XQUARTZ_VALUATOR_LIMIT * pointer_x); + valuator_mask_set_double(&valuators, 1, XQUARTZ_VALUATOR_LIMIT * pointer_y); + valuator_mask_set_double(&valuators, 2, XQUARTZ_VALUATOR_LIMIT * pressure); + valuator_mask_set_double(&valuators, 3, XQUARTZ_VALUATOR_LIMIT * tilt_x); + valuator_mask_set_double(&valuators, 4, XQUARTZ_VALUATOR_LIMIT * tilt_y); + + darwinEvents_lock(); + { + if (ev_type == ProximityIn || ev_type == ProximityOut) { + QueueProximityEvents(pDev, ev_type, &valuators); + } else { + QueuePointerEvents(pDev, ev_type, ev_button, POINTER_ABSOLUTE, + &valuators); + } + DarwinPokeEQ(); + } darwinEvents_unlock(); +} + +void DarwinSendPointerEvents(DeviceIntPtr pDev, int ev_type, int ev_button, double pointer_x, double pointer_y, - double pressure, double tilt_x, - double tilt_y) + double pointer_dx, double pointer_dy) { static int darwinFakeMouseButtonDown = 0; ScreenPtr screen; ValuatorMask valuators; - //DEBUG_LOG("x=%f, y=%f, p=%f, tx=%f, ty=%f\n", pointer_x, pointer_y, pressure, tilt_x, tilt_y); - if (!darwinEvents) { - DEBUG_LOG( - "DarwinSendPointerEvents called before darwinEvents was initialized\n"); + DEBUG_LOG("%s called before darwinEvents was initialized\n", + __FUNCTION__); return; } screen = miPointerGetScreen(pDev); if (!screen) { - DEBUG_LOG( - "DarwinSendPointerEvents called before screen was initialized\n"); + DEBUG_LOG("%s called before screen was initialized\n", + __FUNCTION__); return; } @@ -550,9 +541,8 @@ DarwinSendPointerEvents(DeviceIntPtr pDev, int ev_type, int ev_button, if (darwinFakeMouseButtonDown != 0) { /* We're currently "down" with another button, so release it first */ DarwinSendPointerEvents(pDev, ButtonRelease, - darwinFakeMouseButtonDown, pointer_x, - pointer_y, pressure, tilt_x, - tilt_y); + darwinFakeMouseButtonDown, + pointer_x, pointer_y, 0.0, 0.0); darwinFakeMouseButtonDown = 0; } if (darwin_all_modifier_flags & darwinFakeMouse2Mask) { @@ -586,15 +576,27 @@ DarwinSendPointerEvents(DeviceIntPtr pDev, int ev_type, int ev_button, darwinFakeMouseButtonDown = 0; } - DarwinPrepareValuators(pDev, &valuators, screen, pointer_x, pointer_y, - pressure, tilt_x, - tilt_y); + /* Fix offset between darwin and X screens */ + pointer_x -= darwinMainScreenX + screen->x; + pointer_y -= darwinMainScreenY + screen->y; + + valuator_mask_zero(&valuators); + valuator_mask_set_double(&valuators, 0, pointer_x); + valuator_mask_set_double(&valuators, 1, pointer_y); + + if (ev_type == MotionNotify) { + if (pointer_dx != 0.0) + valuator_mask_set_double(&valuators, 2, pointer_dx); + if (pointer_dy != 0.0) + valuator_mask_set_double(&valuators, 3, pointer_dy); + } + darwinEvents_lock(); { QueuePointerEvents(pDev, ev_type, ev_button, POINTER_ABSOLUTE, &valuators); DarwinPokeEQ(); - } darwinEvents_unlock(); + } darwinEvents_unlock(); } void @@ -615,42 +617,6 @@ DarwinSendKeyboardEvents(int ev_type, int keycode) } darwinEvents_unlock(); } -void -DarwinSendProximityEvents(DeviceIntPtr pDev, int ev_type, double pointer_x, - double pointer_y, - double pressure, double tilt_x, - double tilt_y) -{ - ScreenPtr screen; - ValuatorMask valuators; - - DEBUG_LOG("DarwinSendProximityEvents: %d l:%f,%f p:%f t:%f,%f\n", ev_type, - pointer_x, pointer_y, pressure, tilt_x, - tilt_y); - - if (!darwinEvents) { - DEBUG_LOG( - "DarwinSendProximityEvents called before darwinEvents was initialized\n"); - return; - } - - screen = miPointerGetScreen(pDev); - if (!screen) { - DEBUG_LOG( - "DarwinSendPointerEvents called before screen was initialized\n"); - return; - } - - DarwinPrepareValuators(pDev, &valuators, screen, pointer_x, pointer_y, - pressure, tilt_x, - tilt_y); - darwinEvents_lock(); - { - QueueProximityEvents(pDev, ev_type, &valuators); - DarwinPokeEQ(); - } darwinEvents_unlock(); -} - /* Send the appropriate number of button clicks to emulate scroll wheel */ void DarwinSendScrollEvents(double scroll_x, double scroll_y) { @@ -671,8 +637,8 @@ DarwinSendScrollEvents(double scroll_x, double scroll_y) { } valuator_mask_zero(&valuators); - valuator_mask_set_double(&valuators, 2, scroll_y); - valuator_mask_set_double(&valuators, 3, scroll_x); + valuator_mask_set_double(&valuators, 4, scroll_y); + valuator_mask_set_double(&valuators, 5, scroll_x); darwinEvents_lock(); { diff --git a/xorg-server/hw/xquartz/darwinEvents.h b/xorg-server/hw/xquartz/darwinEvents.h index 61ace6ee3..448e730bc 100644 --- a/xorg-server/hw/xquartz/darwinEvents.h +++ b/xorg-server/hw/xquartz/darwinEvents.h @@ -44,14 +44,13 @@ DarwinEQSwitchScreen(ScreenPtr pScreen, Bool fromDIX); void DarwinInputReleaseButtonsAndKeys(DeviceIntPtr pDev); void -DarwinSendPointerEvents(DeviceIntPtr pDev, int ev_type, int ev_button, - double pointer_x, double pointer_y, double pressure, - double tilt_x, - double tilt_y); +DarwinSendTabletEvents(DeviceIntPtr pDev, int ev_type, int ev_button, + double pointer_x, double pointer_y, double pressure, + double tilt_x, double tilt_y); void -DarwinSendProximityEvents(DeviceIntPtr pDev, int ev_type, double pointer_x, - double pointer_y, double pressure, double tilt_x, - double tilt_y); +DarwinSendPointerEvents(DeviceIntPtr pDev, int ev_type, int ev_button, + double pointer_x, double pointer_y, + double pointer_dx, double pointer_dy); void DarwinSendKeyboardEvents(int ev_type, int keycode); void diff --git a/xorg-server/hw/xquartz/mach-startup/bundle-main.c b/xorg-server/hw/xquartz/mach-startup/bundle-main.c index d1ad6f7e3..cabdf1eab 100644 --- a/xorg-server/hw/xquartz/mach-startup/bundle-main.c +++ b/xorg-server/hw/xquartz/mach-startup/bundle-main.c @@ -78,7 +78,7 @@ FatalError(const char *f, ...) _X_ATTRIBUTE_PRINTF(1, 2) _X_NORETURN; extern int noPanoramiXExtension; #define DEFAULT_CLIENT X11BINDIR "/xterm" -#define DEFAULT_STARTX X11BINDIR "/startx" +#define DEFAULT_STARTX X11BINDIR "/startx -- " X11BINDIR "/Xquartz" #define DEFAULT_SHELL "/bin/sh" #ifndef BUILD_DATE diff --git a/xorg-server/hw/xquartz/xpr/xprFrame.c b/xorg-server/hw/xquartz/xpr/xprFrame.c index 4c7aac42b..01f1def20 100644 --- a/xorg-server/hw/xquartz/xpr/xprFrame.c +++ b/xorg-server/hw/xquartz/xpr/xprFrame.c @@ -212,7 +212,7 @@ xprCreateFrame(RootlessWindowPtr pFrame, ScreenPtr pScreen, #else pthread_rwlock_wrlock(&window_hash_rwlock); x_hash_table_insert(window_hash, pFrame->wid, pFrame); - pthread_rwlock_wrlock(&window_hash_rwlock); + pthread_rwlock_unlock(&window_hash_rwlock); #endif xprSetNativeProperty(pFrame); diff --git a/xorg-server/include/os.h b/xorg-server/include/os.h index 166c60cd8..276eb5213 100644 --- a/xorg-server/include/os.h +++ b/xorg-server/include/os.h @@ -321,7 +321,8 @@ extern _X_EXPORT void OsCleanup(Bool); extern _X_EXPORT void -OsVendorFatalError(const char *f, va_list args); +OsVendorFatalError(const char *f, va_list args) +_X_ATTRIBUTE_PRINTF(1, 0); extern _X_EXPORT void OsVendorInit(void); diff --git a/xorg-server/test/Makefile.am b/xorg-server/test/Makefile.am index 8c7e412c3..85823977b 100644 --- a/xorg-server/test/Makefile.am +++ b/xorg-server/test/Makefile.am @@ -54,8 +54,6 @@ libxservertest_la_LIBADD += \ $(top_builddir)/hw/xfree86/dixmods/libxorgxkb.la \ @XORG_LIBS@ -EXTRA_DIST = ddxstubs.c - else nodist_libxservertest_la_SOURCES = \ ddxstubs.c \ @@ -111,3 +109,6 @@ endif libxservertest_la_DEPENDENCIES = $(libxservertest_la_LIBADD) endif + +EXTRA_DIST = ddxstubs.c + |