From 080d1527a5358dd66ac927acbe0ec61cba7aa7e1 Mon Sep 17 00:00:00 2001 From: marha Date: Mon, 11 Jun 2012 08:22:24 +0200 Subject: fontconfig glproto mesa pixman git update 11 Jun 2012 --- fontconfig/doc/fclangset.fncs | 9 + fontconfig/fc-lang/fc-lang.c | 6 + fontconfig/fontconfig/fontconfig.h | 3 + fontconfig/src/fccfg.c | 17 + fontconfig/src/fcdefault.c | 106 ++--- fontconfig/src/fcfreetype.c | 15 +- fontconfig/src/fcint.h | 6 + fontconfig/src/fclang.c | 159 +++++++ fontconfig/src/fcstr.c | 44 ++ gl/glxtokens.h | 4 +- mesalib/src/glsl/glcpp/.gitignore | 3 - mesalib/src/glsl/ir.h | 10 + mesalib/src/glsl/ir_constant_expression.cpp | 7 +- mesalib/src/mapi/glapi/.gitignore | 11 - mesalib/src/mesa/main/bufferobj.c | 20 +- pixman/configure.ac | 22 +- pixman/pixman/Makefile.am | 18 +- pixman/pixman/Makefile.sources | 1 + pixman/pixman/pixman-compiler.h | 4 + pixman/pixman/pixman-glyph.c | 672 ++++++++++++++++++++++++++++ pixman/pixman/pixman-image.c | 33 +- pixman/pixman/pixman-private.h | 70 +++ pixman/pixman/pixman-utils.c | 31 +- pixman/pixman/pixman.c | 42 +- pixman/pixman/pixman.h | 59 +++ pixman/test/Makefile.sources | 1 + pixman/test/blitters-test.c | 31 +- pixman/test/glyph-test.c | 331 ++++++++++++++ pixman/test/utils.c | 101 +++++ pixman/test/utils.h | 7 +- 30 files changed, 1663 insertions(+), 180 deletions(-) create mode 100644 pixman/pixman/pixman-glyph.c create mode 100644 pixman/test/glyph-test.c diff --git a/fontconfig/doc/fclangset.fncs b/fontconfig/doc/fclangset.fncs index 0a44b38c2..e2a40b854 100644 --- a/fontconfig/doc/fclangset.fncs +++ b/fontconfig/doc/fclangset.fncs @@ -153,6 +153,15 @@ function returns FcLangDifferentTerritory. If ls has no matching language, this function returns FcLangDifferentLang. @@ +@RET@ FcStrSet * +@FUNC@ FcGetDefaultLangs +@TYPE1@ void +@PURPOSE@ Get the default languages list +@DESC@ +Returns a string set of the default languages according to the environment variables on the system. +This function looks for them in order of FC_LANG, LC_ALL, LC_CTYPE and LANG then. +If there are no valid values in those environment variables, "en" will be set as fallback. + @RET@ FcStrSet * @FUNC@ FcLangSetGetLangs @TYPE1@ const FcLangSet * @ARG1@ ls diff --git a/fontconfig/fc-lang/fc-lang.c b/fontconfig/fc-lang/fc-lang.c index 51717f952..93200c4e0 100644 --- a/fontconfig/fc-lang/fc-lang.c +++ b/fontconfig/fc-lang/fc-lang.c @@ -57,6 +57,12 @@ FcCacheObjectDereference (void *object) { } +FcPrivate FcChar8 * +FcLangNormalize (const FcChar8 *lang) +{ + return NULL; +} + int FcDebugVal; FcChar8 * diff --git a/fontconfig/fontconfig/fontconfig.h b/fontconfig/fontconfig/fontconfig.h index 2671da78d..21a476a02 100644 --- a/fontconfig/fontconfig/fontconfig.h +++ b/fontconfig/fontconfig/fontconfig.h @@ -497,6 +497,9 @@ FcPublic void FcFontSetPrint (const FcFontSet *s); /* fcdefault.c */ +FcPublic FcStrSet * +FcGetDefaultLangs (void); + FcPublic void FcDefaultSubstitute (FcPattern *pattern); diff --git a/fontconfig/src/fccfg.c b/fontconfig/src/fccfg.c index b45d74a23..3f1fa73df 100644 --- a/fontconfig/src/fccfg.c +++ b/fontconfig/src/fccfg.c @@ -1407,6 +1407,7 @@ FcConfigSubstituteWithPat (FcConfig *config, FcEdit *e; FcValueList *l; FcPattern *m; + FcStrSet *strs; if (!config) { @@ -1418,6 +1419,22 @@ FcConfigSubstituteWithPat (FcConfig *config, switch (kind) { case FcMatchPattern: s = config->substPattern; + strs = FcGetDefaultLangs (); + if (strs) + { + FcStrList *l = FcStrListCreate (strs); + FcChar8 *lang; + FcValue v; + + FcStrSetDestroy (strs); + while (l && (lang = FcStrListNext (l))) + { + v.type = FcTypeString; + v.u.s = lang; + FcPatternObjectAddWithBinding (p, FC_LANG_OBJECT, v, FcValueBindingWeak, FcTrue); + } + FcStrListDone (l); + } break; case FcMatchFont: s = config->substFont; diff --git a/fontconfig/src/fcdefault.c b/fontconfig/src/fcdefault.c index 170a8a4d8..c6b5669ed 100644 --- a/fontconfig/src/fcdefault.c +++ b/fontconfig/src/fcdefault.c @@ -23,7 +23,7 @@ */ #include "fcint.h" -#include +#include static const struct { FcObject field; @@ -39,81 +39,45 @@ static const struct { #define NUM_FC_BOOL_DEFAULTS (int) (sizeof FcBoolDefaults / sizeof FcBoolDefaults[0]) -FcChar8 * -FcGetDefaultLang (void) +FcStrSet * +FcGetDefaultLangs (void) { - static char lang_local [128] = {0}; - char *ctype; - char *territory; - char *after; - int lang_len, territory_len; - - if (lang_local [0]) - return (FcChar8 *) lang_local; - - ctype = setlocale (LC_CTYPE, NULL); - - /* - * Check if setlocale (LC_ALL, "") has been called - */ - if (!ctype || !strcmp (ctype, "C")) + FcStrSet *result = FcStrSetCreate (); + char *langs; + + langs = getenv ("FC_LANG"); + if (!langs || !langs[0]) + langs = getenv ("LC_ALL"); + if (!langs || !langs[0]) + langs = getenv ("LC_CTYPE"); + if (!langs || !langs[0]) + langs = getenv ("LANG"); + if (langs && langs[0]) { - ctype = getenv ("LC_ALL"); - if (!ctype) - { - ctype = getenv ("LC_CTYPE"); - if (!ctype) - ctype = getenv ("LANG"); - } + if (!FcStrSetAddLangs (result, langs)) + FcStrSetAdd (result, (const FcChar8 *) "en"); } + else + FcStrSetAdd (result, (const FcChar8 *) "en"); - /* ignore missing or empty ctype */ - if (ctype && *ctype != '\0') + return result; +} + +FcChar8 * +FcGetDefaultLang (void) +{ + static FcChar8 lang_local[128] = {0}; + FcStrSet *langs; + + if (!lang_local[0]) { - territory = strchr (ctype, '_'); - if (territory) - { - lang_len = territory - ctype; - territory = territory + 1; - after = strchr (territory, '.'); - if (!after) - { - after = strchr (territory, '@'); - if (!after) - after = territory + strlen (territory); - } - territory_len = after - territory; - if (lang_len + 1 + territory_len + 1 <= (int) sizeof (lang_local)) - { - strncpy (lang_local, ctype, lang_len); - lang_local[lang_len] = '-'; - strncpy (lang_local + lang_len + 1, territory, territory_len); - lang_local[lang_len + 1 + territory_len] = '\0'; - } - } - else - { - after = strchr (ctype, '.'); - if (!after) - { - after = strchr (ctype, '@'); - if (!after) - after = ctype + strlen (ctype); - } - lang_len = after - ctype; - if (lang_len + 1 <= (int) sizeof (lang_local)) - { - strncpy (lang_local, ctype, lang_len); - lang_local[lang_len] = '\0'; - } - } + langs = FcGetDefaultLangs (); + strncpy ((char *)lang_local, (const char *)langs->strs[0], 127); + lang_local[127] = 0; + FcStrSetDestroy (langs); } - /* set default lang to en */ - if (!lang_local [0]) - strcpy (lang_local, "en"); - - return (FcChar8 *) lang_local; + return lang_local; } void @@ -162,10 +126,6 @@ FcDefaultSubstitute (FcPattern *pattern) FcPatternObjectAddDouble (pattern, FC_PIXEL_SIZE_OBJECT, size); } - if (FcPatternObjectGet (pattern, FC_LANG_OBJECT, 0, &v) == FcResultNoMatch) - { - FcPatternObjectAddString (pattern, FC_LANG_OBJECT, FcGetDefaultLang ()); - } if (FcPatternObjectGet (pattern, FC_FONTVERSION_OBJECT, 0, &v) == FcResultNoMatch) { FcPatternObjectAddInteger (pattern, FC_FONTVERSION_OBJECT, 0x7fffffff); diff --git a/fontconfig/src/fcfreetype.c b/fontconfig/src/fcfreetype.c index ce7dc836c..fb2b0f2f9 100644 --- a/fontconfig/src/fcfreetype.c +++ b/fontconfig/src/fcfreetype.c @@ -1179,10 +1179,11 @@ FcFreeTypeQueryFace (const FT_Face face, for (snamei = 0; snamei < snamec; snamei++) { - FcChar8 *utf8; + FcChar8 *utf8, *pp; const FcChar8 *lang; const char *elt = 0, *eltlang = 0; int *np = 0, *nlangp = 0; + size_t len; if (FT_Get_Sfnt_Name (face, snamei, &sname) != 0) continue; @@ -1253,6 +1254,18 @@ FcFreeTypeQueryFace (const FT_Face face, #endif case TT_NAME_ID_PREFERRED_SUBFAMILY: case TT_NAME_ID_FONT_SUBFAMILY: + if (utf8) + { + pp = utf8; + while (*pp == ' ') + pp++; + len = strlen ((const char *) pp); + memmove (utf8, pp, len + 1); + pp = utf8 + len - 1; + while (*pp == ' ') + pp--; + *(pp + 1) = 0; + } if (FcDebug () & FC_DBG_SCANV) printf ("found style (n %2d p %d e %d l 0x%04x) %s\n", sname.name_id, sname.platform_id, diff --git a/fontconfig/src/fcint.h b/fontconfig/src/fcint.h index 3d06fc6eb..7cc4ed2d8 100644 --- a/fontconfig/src/fcint.h +++ b/fontconfig/src/fcint.h @@ -816,6 +816,9 @@ FcPrivate FcLangSet * FcFreeTypeLangSet (const FcCharSet *charset, const FcChar8 *exclusiveLang); +FcPrivate FcChar8 * +FcLangNormalize (const FcChar8 *lang); + FcPrivate FcLangResult FcLangCompare (const FcChar8 *s1, const FcChar8 *s2); @@ -1039,6 +1042,9 @@ FcPrivate FcBool FcIsFsMtimeBroken (const FcChar8 *dir); /* fcstr.c */ +FcPrivate FcBool +FcStrSetAddLangs (FcStrSet *strs, const char *languages); + FcPrivate void FcStrSetSort (FcStrSet * set); diff --git a/fontconfig/src/fclang.c b/fontconfig/src/fclang.c index be42b58c4..b7e70fcfb 100644 --- a/fontconfig/src/fclang.c +++ b/fontconfig/src/fclang.c @@ -22,6 +22,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ +#include #include "fcint.h" #include "fcftint.h" @@ -43,6 +44,9 @@ struct _FcLangSet { FcChar32 map[NUM_LANG_SET_MAP]; }; +static int FcLangSetIndex (const FcChar8 *lang); + + static void FcLangSetBitSet (FcLangSet *ls, unsigned int id) @@ -173,6 +177,161 @@ FcFreeTypeLangSet (const FcCharSet *charset, return ls; } +FcChar8 * +FcLangNormalize (const FcChar8 *lang) +{ + FcChar8 *result = NULL, *s, *orig; + char *territory, *encoding, *modifier; + size_t llen, tlen = 0, mlen = 0; + + if (!lang || !*lang) + return NULL; + + if (FcStrCmpIgnoreCase (lang, (const FcChar8 *)"C") == 0 || + FcStrCmpIgnoreCase (lang, (const FcChar8 *)"POSIX") == 0) + { + result = FcStrCopy ((const FcChar8 *)"en"); + goto bail; + } + + s = FcStrCopy (lang); + if (!s) + goto bail; + + /* from the comments in glibc: + * + * LOCALE can consist of up to four recognized parts for the XPG syntax: + * + * language[_territory[.codeset]][@modifier] + * + * Beside the first all of them are allowed to be missing. If the + * full specified locale is not found, the less specific one are + * looked for. The various part will be stripped off according to + * the following order: + * (1) codeset + * (2) normalized codeset + * (3) territory + * (4) modifier + * + * So since we don't take care of the codeset part here, what patterns + * we need to deal with is: + * + * 1. language_territory@modifier + * 2. language@modifier + * 3. language + * + * then. and maybe no need to try language_territory here. + */ + modifier = strchr ((const char *) s, '@'); + if (modifier) + { + *modifier = 0; + modifier++; + mlen = strlen (modifier); + } + encoding = strchr ((const char *) s, '.'); + if (encoding) + { + *encoding = 0; + encoding++; + if (modifier) + { + memmove (encoding, modifier, mlen + 1); + modifier = encoding; + } + } + territory = strchr ((const char *) s, '_'); + if (!territory) + territory = strchr ((const char *) s, '-'); + if (territory) + { + *territory = 0; + territory++; + tlen = strlen (territory); + } + llen = strlen ((const char *) s); + if (llen < 2 || llen > 3) + { + fprintf (stderr, "Fontconfig warning: ignoring %s: not a valid language tag\n", + lang); + goto bail0; + } + if (territory && (tlen < 2 || tlen > 3)) + { + fprintf (stderr, "Fontconfig warning: ignoring %s: not a valid region tag\n", + lang); + goto bail0; + } + if (territory) + territory[-1] = '-'; + if (modifier) + modifier[-1] = '@'; + orig = FcStrDowncase (s); + if (!orig) + goto bail0; + if (territory) + { + if (FcDebug () & FC_DBG_LANGSET) + printf("Checking the existence of %s.orth\n", s); + if (FcLangSetIndex (s) < 0) + { + memmove (territory - 1, territory + tlen, (mlen > 0 ? mlen + 1 : 0) + 1); + if (modifier) + modifier = territory; + } + else + { + result = s; + s = NULL; + goto bail1; + } + } + if (modifier) + { + if (FcDebug () & FC_DBG_LANGSET) + printf("Checking the existence of %s.orth\n", s); + if (FcLangSetIndex (s) < 0) + modifier[-1] = 0; + else + { + result = s; + s = NULL; + goto bail1; + } + } + if (FcDebug () & FC_DBG_LANGSET) + printf("Checking the existence of %s.orth\n", s); + if (FcLangSetIndex (s) < 0) + { + /* there seems no languages matched in orth. + * add the language as is for fallback. + */ + result = orig; + orig = NULL; + } + else + { + result = s; + s = NULL; + } + bail1: + if (orig) + free (orig); + bail0: + if (s) + free (s); + bail: + if (FcDebug () & FC_DBG_LANGSET) + { + if (result) + printf ("normalized: %s -> %s\n", lang, result); + else + printf ("Unable to normalize %s\n", lang); + } + + return result; +} + #define FcLangEnd(c) ((c) == '-' || (c) == '\0') FcLangResult diff --git a/fontconfig/src/fcstr.c b/fontconfig/src/fcstr.c index e372af080..c446bcd8e 100644 --- a/fontconfig/src/fcstr.c +++ b/fontconfig/src/fcstr.c @@ -1176,6 +1176,50 @@ FcStrSetAddFilename (FcStrSet *set, const FcChar8 *s) return FcTrue; } +FcBool +FcStrSetAddLangs (FcStrSet *strs, const char *languages) +{ + const char *p = languages, *next; + FcChar8 lang[128] = {0}, *normalized_lang; + size_t len; + FcBool ret = FcFalse; + + if (!languages) + return FcFalse; + + while ((next = strchr (p, ':'))) + { + len = next - p; + len = FC_MIN (len, 128); + strncpy ((char *) lang, p, len); + lang[len] = 0; + /* ignore an empty item */ + if (*lang) + { + normalized_lang = FcLangNormalize ((const FcChar8 *) lang); + if (normalized_lang) + { + FcStrSetAdd (strs, normalized_lang); + free (normalized_lang); + ret = FcTrue; + } + } + p = next + 1; + } + if (*p) + { + normalized_lang = FcLangNormalize ((const FcChar8 *) p); + if (normalized_lang) + { + FcStrSetAdd (strs, normalized_lang); + free (normalized_lang); + ret = FcTrue; + } + } + + return ret; +} + FcBool FcStrSetDel (FcStrSet *set, const FcChar8 *s) { diff --git a/gl/glxtokens.h b/gl/glxtokens.h index 1ed2fd3e4..5e6bbea11 100644 --- a/gl/glxtokens.h +++ b/gl/glxtokens.h @@ -286,6 +286,7 @@ extern "C" { /* * GLX_ARB_create_context * GLX_ARB_create_context_profile + * GLX_EXT_create_context_es2_profile */ #define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091 #define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092 @@ -297,6 +298,7 @@ extern "C" { #define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x0001 #define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x0002 +#define GLX_CONTEXT_ES2_PROFILE_BIT_EXT 0x0004 /* * GLX_ARB_create_context_robustness @@ -304,7 +306,7 @@ extern "C" { #define GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x0004 #define GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256 #define GLX_NO_RESET_NOTIFICATION_ARB 0x8261 -#define GLX_LOST_CONTEXT_ON_RESET_ARB 0x8252 +#define GLX_LOSE_CONTEXT_ON_RESET_ARB 0x8252 #ifdef __cplusplus } #endif diff --git a/mesalib/src/glsl/glcpp/.gitignore b/mesalib/src/glsl/glcpp/.gitignore index 41b34bb30..24a7119ca 100644 --- a/mesalib/src/glsl/glcpp/.gitignore +++ b/mesalib/src/glsl/glcpp/.gitignore @@ -3,7 +3,4 @@ glcpp-lex.c glcpp-parse.output glcpp-parse.c glcpp-parse.h -*.o -*.lo -*~ tests/*.out diff --git a/mesalib/src/glsl/ir.h b/mesalib/src/glsl/ir.h index 2c4723627..a3f9f0588 100644 --- a/mesalib/src/glsl/ir.h +++ b/mesalib/src/glsl/ir.h @@ -89,6 +89,16 @@ class ir_instruction : public exec_node { public: enum ir_node_type ir_type; + /** + * GCC 4.7+ and clang warn when deleting an ir_instruction unless + * there's a virtual destructor present. Because we almost + * universally use ralloc for our memory management of + * ir_instructions, the destructor doesn't need to do any work. + */ + virtual ~ir_instruction() + { + } + /** ir_print_visitor helper for debugging. */ void print(void) const; diff --git a/mesalib/src/glsl/ir_constant_expression.cpp b/mesalib/src/glsl/ir_constant_expression.cpp index 7a4d15f43..38a1ed96c 100644 --- a/mesalib/src/glsl/ir_constant_expression.cpp +++ b/mesalib/src/glsl/ir_constant_expression.cpp @@ -1322,8 +1322,11 @@ ir_function_signature::constant_expression_value(exec_list *actual_parameters, s foreach_list(n, actual_parameters) { ir_constant *constant = ((ir_rvalue *) n)->constant_expression_value(variable_context); - if (constant == NULL) - return NULL; + if (constant == NULL) { + hash_table_dtor(deref_hash); + return NULL; + } + ir_variable *var = (ir_variable *)parameter_info; hash_table_insert(deref_hash, constant, var); diff --git a/mesalib/src/mapi/glapi/.gitignore b/mesalib/src/mapi/glapi/.gitignore index 21edf4f58..ecae56a3f 100644 --- a/mesalib/src/mapi/glapi/.gitignore +++ b/mesalib/src/mapi/glapi/.gitignore @@ -1,14 +1,3 @@ -.cvsignore -glX_proto_common.pyo -glX_proto_common.pyc -typeexpr.pyo -typeexpr.pyc -license.pyo -license.pyc -gl_XML.pyo -gl_XML.pyc -glX_XML.pyo -glX_XML.pyc glapi_gentable.c glapi_gentable.h glapi_mapi_tmp.h diff --git a/mesalib/src/mesa/main/bufferobj.c b/mesalib/src/mesa/main/bufferobj.c index 36a761986..541566509 100644 --- a/mesalib/src/mesa/main/bufferobj.c +++ b/mesalib/src/mesa/main/bufferobj.c @@ -546,7 +546,7 @@ _mesa_buffer_unmap( struct gl_context *ctx, struct gl_buffer_object *bufObj ) /** * Default fallback for \c dd_function_table::CopyBufferSubData(). - * Called via glCopyBuffserSubData(). + * Called via glCopyBufferSubData(). */ static void _mesa_copy_buffer_subdata(struct gl_context *ctx, @@ -1328,48 +1328,48 @@ _mesa_CopyBufferSubData(GLenum readTarget, GLenum writeTarget, struct gl_buffer_object *src, *dst; ASSERT_OUTSIDE_BEGIN_END(ctx); - src = get_buffer(ctx, "glCopyBuffserSubData", readTarget); + src = get_buffer(ctx, "glCopyBufferSubData", readTarget); if (!src) return; - dst = get_buffer(ctx, "glCopyBuffserSubData", writeTarget); + dst = get_buffer(ctx, "glCopyBufferSubData", writeTarget); if (!dst) return; if (_mesa_bufferobj_mapped(src)) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glCopyBuffserSubData(readBuffer is mapped)"); + "glCopyBufferSubData(readBuffer is mapped)"); return; } if (_mesa_bufferobj_mapped(dst)) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glCopyBuffserSubData(writeBuffer is mapped)"); + "glCopyBufferSubData(writeBuffer is mapped)"); return; } if (readOffset < 0) { _mesa_error(ctx, GL_INVALID_VALUE, - "glCopyBuffserSubData(readOffset = %d)", (int) readOffset); + "glCopyBufferSubData(readOffset = %d)", (int) readOffset); return; } if (writeOffset < 0) { _mesa_error(ctx, GL_INVALID_VALUE, - "glCopyBuffserSubData(writeOffset = %d)", (int) writeOffset); + "glCopyBufferSubData(writeOffset = %d)", (int) writeOffset); return; } if (readOffset + size > src->Size) { _mesa_error(ctx, GL_INVALID_VALUE, - "glCopyBuffserSubData(readOffset + size = %d)", + "glCopyBufferSubData(readOffset + size = %d)", (int) (readOffset + size)); return; } if (writeOffset + size > dst->Size) { _mesa_error(ctx, GL_INVALID_VALUE, - "glCopyBuffserSubData(writeOffset + size = %d)", + "glCopyBufferSubData(writeOffset + size = %d)", (int) (writeOffset + size)); return; } @@ -1384,7 +1384,7 @@ _mesa_CopyBufferSubData(GLenum readTarget, GLenum writeTarget, else { /* overlapping src/dst is illegal */ _mesa_error(ctx, GL_INVALID_VALUE, - "glCopyBuffserSubData(overlapping src/dst)"); + "glCopyBufferSubData(overlapping src/dst)"); return; } } diff --git a/pixman/configure.ac b/pixman/configure.ac index 5c60b13c9..2b9d1ba20 100644 --- a/pixman/configure.ac +++ b/pixman/configure.ac @@ -607,14 +607,27 @@ fi dnl =========================================================================== dnl Check for IWMMXT +AC_ARG_ENABLE(arm-iwmmxt, + [AC_HELP_STRING([--disable-arm-iwmmxt], + [disable ARM IWMMXT fast paths])], + [enable_iwmmxt=$enableval], [enable_iwmmxt=auto]) + +AC_ARG_ENABLE(arm-iwmmxt2, + [AC_HELP_STRING([--disable-arm-iwmmxt2], + [build ARM IWMMXT fast paths with -march=iwmmxt instead of -march=iwmmxt2])], + [enable_iwmmxt2=$enableval], [enable_iwmmxt2=auto]) + if test "x$IWMMXT_CFLAGS" = "x" ; then - IWMMXT_CFLAGS="-march=iwmmxt -flax-vector-conversions -Winline" + IWMMXT_CFLAGS="-flax-vector-conversions -Winline -march=iwmmxt" + if test $enable_iwmmxt2 != no ; then + IWMMXT_CFLAGS+="2" + fi fi have_iwmmxt_intrinsics=no AC_MSG_CHECKING(whether to use ARM IWMMXT intrinsics) xserver_save_CFLAGS=$CFLAGS -CFLAGS="$IWMMXT_CFLAGS $CFLAGS" +CFLAGS="$CFLAGS $IWMMXT_CFLAGS" AC_COMPILE_IFELSE([AC_LANG_SOURCE([[ #ifndef __arm__ #error "IWMMXT is only available on ARM" @@ -636,11 +649,6 @@ int main () { }]])], have_iwmmxt_intrinsics=yes) CFLAGS=$xserver_save_CFLAGS -AC_ARG_ENABLE(arm-iwmmxt, - [AC_HELP_STRING([--disable-arm-iwmmxt], - [disable ARM IWMMXT fast paths])], - [enable_iwmmxt=$enableval], [enable_iwmmxt=auto]) - if test $enable_iwmmxt = no ; then have_iwmmxt_intrinsics=disabled fi diff --git a/pixman/pixman/Makefile.am b/pixman/pixman/Makefile.am index b320a5838..1b232ad0f 100644 --- a/pixman/pixman/Makefile.am +++ b/pixman/pixman/Makefile.am @@ -93,13 +93,21 @@ endif # iwmmxt code if USE_ARM_IWMMXT noinst_LTLIBRARIES += libpixman-iwmmxt.la -libpixman_iwmmxt_la_SOURCES = pixman-mmx.c -libpixman_iwmmxt_la_CFLAGS = $(DEP_CFLAGS) $(IWMMXT_CFLAGS) -libpixman_iwmmxt_la_LIBADD = $(DEP_LIBS) -libpixman_1_la_LDFLAGS += $(IWMMXT_LDFLAGS) libpixman_1_la_LIBADD += libpixman-iwmmxt.la -ASM_CFLAGS_IWMMXT=$(IWMMXT_CFLAGS) +libpixman_iwmmxt_la-pixman-mmx.lo: pixman-mmx.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(CFLAGS) $(IWMMXT_CFLAGS) -MT libpixman_iwmmxt_la-pixman-mmx.lo -MD -MP -MF $(DEPDIR)/libpixman_iwmmxt_la-pixman-mmx.Tpo -c -o libpixman_iwmmxt_la-pixman-mmx.lo `test -f 'pixman-mmx.c' || echo '$(srcdir)/'`pixman-mmx.c + $(AM_V_at)$(am__mv) $(DEPDIR)/libpixman_iwmmxt_la-pixman-mmx.Tpo $(DEPDIR)/libpixman_iwmmxt_la-pixman-mmx.Plo + +libpixman_iwmmxt_la_DEPENDENCIES = $(am__DEPENDENCIES_1) +libpixman_iwmmxt_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(CFLAGS) $(IWMMXT_CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +libpixman_iwmmxt_la_LIBADD = $(DEP_LIBS) + +libpixman-iwmmxt.la: libpixman_iwmmxt_la-pixman-mmx.lo $(libpixman_iwmmxt_la_DEPENDENCIES) + $(AM_V_CCLD)$(libpixman_iwmmxt_la_LINK) libpixman_iwmmxt_la-pixman-mmx.lo $(libpixman_iwmmxt_la_LIBADD) $(LIBS) endif # mips dspr2 code diff --git a/pixman/pixman/Makefile.sources b/pixman/pixman/Makefile.sources index ca3f001db..11f959d97 100644 --- a/pixman/pixman/Makefile.sources +++ b/pixman/pixman/Makefile.sources @@ -10,6 +10,7 @@ libpixman_sources = \ pixman-edge.c \ pixman-edge-accessors.c \ pixman-fast-path.c \ + pixman-glyph.c \ pixman-general.c \ pixman-gradient-walker.c \ pixman-image.c \ diff --git a/pixman/pixman/pixman-compiler.h b/pixman/pixman/pixman-compiler.h index ffd51720e..a978accfd 100644 --- a/pixman/pixman/pixman-compiler.h +++ b/pixman/pixman/pixman-compiler.h @@ -89,6 +89,10 @@ # define PIXMAN_EXPORT #endif +/* member offsets */ +#define CONTAINER_OF(type, member, data) \ + ((type *)(((uint8_t *)data) - offsetof (type, member))) + /* TLS */ #if defined(PIXMAN_NO_TLS) diff --git a/pixman/pixman/pixman-glyph.c b/pixman/pixman/pixman-glyph.c new file mode 100644 index 000000000..921eff158 --- /dev/null +++ b/pixman/pixman/pixman-glyph.c @@ -0,0 +1,672 @@ +/* + * Copyright 2010, 2012, Soren Sandmann + * Copyright 2010, 2011, 2012, Red Hat, Inc + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (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 NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS 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. + * + * Author: Soren Sandmann + */ +#include +#include +#include "pixman-private.h" + +typedef struct glyph_metrics_t glyph_metrics_t; +typedef struct glyph_t glyph_t; + +#define TOMBSTONE ((glyph_t *)0x1) + +/* XXX: These numbers are arbitrary---we've never done any measurements. + */ +#define N_GLYPHS_HIGH_WATER (16384) +#define N_GLYPHS_LOW_WATER (8192) +#define HASH_SIZE (2 * N_GLYPHS_HIGH_WATER) +#define HASH_MASK (HASH_SIZE - 1) + +struct glyph_t +{ + void * font_key; + void * glyph_key; + int origin_x; + int origin_y; + pixman_image_t * image; + pixman_link_t mru_link; +}; + +struct pixman_glyph_cache_t +{ + int n_glyphs; + int n_tombstones; + int freeze_count; + pixman_list_t mru; + glyph_t * glyphs[HASH_SIZE]; +}; + +static void +free_glyph (glyph_t *glyph) +{ + pixman_list_unlink (&glyph->mru_link); + pixman_image_unref (glyph->image); + free (glyph); +} + +static unsigned int +hash (const void *font_key, const void *glyph_key) +{ + size_t key = (size_t)font_key + (size_t)glyph_key; + + /* This hash function is based on one found on Thomas Wang's + * web page at + * + * http://www.concentric.net/~Ttwang/tech/inthash.htm + * + */ + key = (key << 15) - key - 1; + key = key ^ (key >> 12); + key = key + (key << 2); + key = key ^ (key >> 4); + key = key + (key << 3) + (key << 11); + key = key ^ (key >> 16); + + return key; +} + +static glyph_t * +lookup_glyph (pixman_glyph_cache_t *cache, + void *font_key, + void *glyph_key) +{ + unsigned idx; + glyph_t *g; + + idx = hash (font_key, glyph_key); + while ((g = cache->glyphs[idx++ & HASH_MASK])) + { + if (g != TOMBSTONE && + g->font_key == font_key && + g->glyph_key == glyph_key) + { + return g; + } + } + + return NULL; +} + +static void +insert_glyph (pixman_glyph_cache_t *cache, + glyph_t *glyph) +{ + unsigned idx; + glyph_t **loc; + + idx = hash (glyph->font_key, glyph->glyph_key); + + /* Note: we assume that there is room in the table. If there isn't, + * this will be an infinite loop. + */ + do + { + loc = &cache->glyphs[idx++ & HASH_MASK]; + } while (*loc && *loc != TOMBSTONE); + + if (*loc == TOMBSTONE) + cache->n_tombstones--; + cache->n_glyphs++; + + *loc = glyph; +} + +static void +remove_glyph (pixman_glyph_cache_t *cache, + glyph_t *glyph) +{ + unsigned idx; + + idx = hash (glyph->font_key, glyph->glyph_key); + while (cache->glyphs[idx & HASH_MASK] != glyph) + idx++; + + cache->glyphs[idx & HASH_MASK] = TOMBSTONE; + cache->n_tombstones++; + cache->n_glyphs--; + + /* Eliminate tombstones if possible */ + if (cache->glyphs[(idx + 1) & HASH_MASK] == NULL) + { + while (cache->glyphs[idx & HASH_MASK] == TOMBSTONE) + { + cache->glyphs[idx & HASH_MASK] = NULL; + cache->n_tombstones--; + idx--; + } + } +} + +static void +clear_table (pixman_glyph_cache_t *cache) +{ + int i; + + for (i = 0; i < HASH_SIZE; ++i) + { + glyph_t *glyph = cache->glyphs[i]; + + if (glyph && glyph != TOMBSTONE) + free_glyph (glyph); + + cache->glyphs[i] = NULL; + } + + cache->n_glyphs = 0; + cache->n_tombstones = 0; +} + +PIXMAN_EXPORT pixman_glyph_cache_t * +pixman_glyph_cache_create (void) +{ + pixman_glyph_cache_t *cache; + + if (!(cache = malloc (sizeof *cache))) + return NULL; + + memset (cache->glyphs, 0, sizeof (cache->glyphs)); + cache->n_glyphs = 0; + cache->n_tombstones = 0; + cache->freeze_count = 0; + + pixman_list_init (&cache->mru); + + return cache; +} + +PIXMAN_EXPORT void +pixman_glyph_cache_destroy (pixman_glyph_cache_t *cache) +{ + return_if_fail (cache->freeze_count == 0); + + clear_table (cache); + + free (cache); +} + +PIXMAN_EXPORT void +pixman_glyph_cache_freeze (pixman_glyph_cache_t *cache) +{ + cache->freeze_count++; +} + +PIXMAN_EXPORT void +pixman_glyph_cache_thaw (pixman_glyph_cache_t *cache) +{ + if (--cache->freeze_count == 0 && + cache->n_glyphs + cache->n_tombstones > N_GLYPHS_HIGH_WATER) + { + if (cache->n_tombstones > N_GLYPHS_HIGH_WATER) + { + /* More than half the entries are + * tombstones. Just dump the whole table. + */ + clear_table (cache); + } + + while (cache->n_glyphs > N_GLYPHS_LOW_WATER) + { + glyph_t *glyph = CONTAINER_OF (glyph_t, mru_link, cache->mru.tail); + + remove_glyph (cache, glyph); + free_glyph (glyph); + } + } +} + +PIXMAN_EXPORT const void * +pixman_glyph_cache_lookup (pixman_glyph_cache_t *cache, + void *font_key, + void *glyph_key) +{ + return lookup_glyph (cache, font_key, glyph_key); +} + +PIXMAN_EXPORT const void * +pixman_glyph_cache_insert (pixman_glyph_cache_t *cache, + void *font_key, + void *glyph_key, + int origin_x, + int origin_y, + pixman_image_t *image) +{ + glyph_t *glyph; + int32_t width, height; + + return_val_if_fail (cache->freeze_count > 0, NULL); + return_val_if_fail (image->type == BITS, NULL); + + width = image->bits.width; + height = image->bits.height; + + if (cache->n_glyphs >= HASH_SIZE) + return NULL; + + if (!(glyph = malloc (sizeof *glyph))) + return NULL; + + glyph->font_key = font_key; + glyph->glyph_key = glyph_key; + glyph->origin_x = origin_x; + glyph->origin_y = origin_y; + + if (!(glyph->image = pixman_image_create_bits ( + image->bits.format, width, height, NULL, -1))) + { + free (glyph); + return NULL; + } + + pixman_image_composite32 (PIXMAN_OP_SRC, + image, NULL, glyph->image, 0, 0, 0, 0, 0, 0, + width, height); + + if (PIXMAN_FORMAT_A (glyph->image->bits.format) != 0 && + PIXMAN_FORMAT_RGB (glyph->image->bits.format) != 0) + { + pixman_image_set_component_alpha (glyph->image, TRUE); + } + + pixman_list_prepend (&cache->mru, &glyph->mru_link); + + _pixman_image_validate (glyph->image); + insert_glyph (cache, glyph); + + return glyph; +} + +PIXMAN_EXPORT void +pixman_glyph_cache_remove (pixman_glyph_cache_t *cache, + void *font_key, + void *glyph_key) +{ + glyph_t *glyph; + + if ((glyph = lookup_glyph (cache, font_key, glyph_key))) + { + remove_glyph (cache, glyph); + + free_glyph (glyph); + } +} + +PIXMAN_EXPORT void +pixman_glyph_get_extents (pixman_glyph_cache_t *cache, + int n_glyphs, + pixman_glyph_t *glyphs, + pixman_box32_t *extents) +{ + int i; + + extents->x1 = extents->y1 = INT32_MAX; + extents->x2 = extents->y2 = INT32_MIN; + + for (i = 0; i < n_glyphs; ++i) + { + glyph_t *glyph = (glyph_t *)glyphs[i].glyph; + int x1, y1, x2, y2; + + x1 = glyphs[i].x - glyph->origin_x; + y1 = glyphs[i].y - glyph->origin_y; + x2 = glyphs[i].x - glyph->origin_x + glyph->image->bits.width; + y2 = glyphs[i].y - glyph->origin_y + glyph->image->bits.height; + + if (x1 < extents->x1) + extents->x1 = x1; + if (y1 < extents->y1) + extents->y1 = y1; + if (x2 > extents->x2) + extents->x2 = x2; + if (y2 > extents->y2) + extents->y2 = y2; + } +} + +/* This function returns a format that is suitable for use as a mask for the + * set of glyphs in question. + */ +PIXMAN_EXPORT pixman_format_code_t +pixman_glyph_get_mask_format (pixman_glyph_cache_t *cache, + int n_glyphs, + pixman_glyph_t * glyphs) +{ + pixman_format_code_t format = PIXMAN_a1; + int i; + + for (i = 0; i < n_glyphs; ++i) + { + const glyph_t *glyph = glyphs[i].glyph; + pixman_format_code_t glyph_format = glyph->image->bits.format; + + if (PIXMAN_FORMAT_TYPE (glyph_format) == PIXMAN_TYPE_A) + { + if (PIXMAN_FORMAT_A (glyph_format) > PIXMAN_FORMAT_A (format)) + format = glyph_format; + } + else + { + return PIXMAN_a8r8g8b8; + } + } + + return format; +} + +static pixman_bool_t +box32_intersect (pixman_box32_t *dest, + const pixman_box32_t *box1, + const pixman_box32_t *box2) +{ + dest->x1 = MAX (box1->x1, box2->x1); + dest->y1 = MAX (box1->y1, box2->y1); + dest->x2 = MIN (box1->x2, box2->x2); + dest->y2 = MIN (box1->y2, box2->y2); + + return dest->x2 > dest->x1 && dest->y2 > dest->y1; +} + +PIXMAN_EXPORT void +pixman_composite_glyphs_no_mask (pixman_op_t op, + pixman_image_t *src, + pixman_image_t *dest, + int32_t src_x, + int32_t src_y, + int32_t dest_x, + int32_t dest_y, + pixman_glyph_cache_t *cache, + int n_glyphs, + pixman_glyph_t *glyphs) +{ + pixman_region32_t region; + pixman_format_code_t glyph_format = PIXMAN_null; + uint32_t glyph_flags = 0; + pixman_format_code_t dest_format; + uint32_t dest_flags; + pixman_composite_func_t func = NULL; + pixman_implementation_t *implementation = NULL; + pixman_composite_info_t info; + int i; + + _pixman_image_validate (src); + _pixman_image_validate (dest); + + dest_format = dest->common.extended_format_code; + dest_flags = dest->common.flags; + + pixman_region32_init (®ion); + if (!_pixman_compute_composite_region32 ( + ®ion, + src, NULL, dest, + src_x - dest_x, src_y - dest_y, 0, 0, 0, 0, + dest->bits.width, dest->bits.height)) + { + goto out; + } + + info.op = op; + info.src_image = src; + info.dest_image = dest; + info.src_flags = src->common.flags; + info.dest_flags = dest->common.flags; + + for (i = 0; i < n_glyphs; ++i) + { + glyph_t *glyph = (glyph_t *)glyphs[i].glyph; + pixman_image_t *glyph_img = glyph->image; + pixman_box32_t glyph_box; + pixman_box32_t *pbox; + uint32_t extra = FAST_PATH_SAMPLES_COVER_CLIP_NEAREST; + pixman_box32_t composite_box; + int n; + + glyph_box.x1 = dest_x + glyphs[i].x - glyph->origin_x; + glyph_box.y1 = dest_y + glyphs[i].y - glyph->origin_y; + glyph_box.x2 = glyph_box.x1 + glyph->image->bits.width; + glyph_box.y2 = glyph_box.y1 + glyph->image->bits.height; + + pbox = pixman_region32_rectangles (®ion, &n); + + info.mask_image = glyph_img; + + while (n--) + { + if (box32_intersect (&composite_box, pbox, &glyph_box)) + { + if (glyph_img->common.extended_format_code != glyph_format || + glyph_img->common.flags != glyph_flags) + { + glyph_format = glyph_img->common.extended_format_code; + glyph_flags = glyph_img->common.flags; + + _pixman_lookup_composite_function ( + get_implementation(), op, + src->common.extended_format_code, src->common.flags, + glyph_format, glyph_flags | extra, + dest_format, dest_flags, + &implementation, &func); + + if (!func) + goto out; + } + + info.src_x = src_x + composite_box.x1 - dest_x; + info.src_y = src_y + composite_box.y1 - dest_y; + info.mask_x = composite_box.x1 - (dest_x + glyphs[i].x - glyph->origin_x); + info.mask_y = composite_box.y1 - (dest_y + glyphs[i].y - glyph->origin_y); + info.dest_x = composite_box.x1; + info.dest_y = composite_box.y1; + info.width = composite_box.x2 - composite_box.x1; + info.height = composite_box.y2 - composite_box.y1; + + info.mask_flags = glyph_flags; + + func (implementation, &info); + } + + pbox++; + } + pixman_list_move_to_front (&cache->mru, &glyph->mru_link); + } + +out: + pixman_region32_fini (®ion); +} + +static void +add_glyphs (pixman_glyph_cache_t *cache, + pixman_image_t *dest, + int off_x, int off_y, + int n_glyphs, pixman_glyph_t *glyphs) +{ + pixman_format_code_t glyph_format = PIXMAN_null; + uint32_t glyph_flags = 0; + pixman_composite_func_t func = NULL; + pixman_implementation_t *implementation = NULL; + uint32_t dest_format; + uint32_t dest_flags; + pixman_box32_t dest_box; + pixman_composite_info_t info; + pixman_image_t *white_img = NULL; + pixman_bool_t white_src = FALSE; + int i; + + _pixman_image_validate (dest); + + dest_format = dest->common.extended_format_code; + dest_flags = dest->common.flags; + + info.op = PIXMAN_OP_ADD; + info.dest_image = dest; + info.src_x = 0; + info.src_y = 0; + info.dest_flags = dest_flags; + + dest_box.x1 = 0; + dest_box.y1 = 0; + dest_box.x2 = dest->bits.width; + dest_box.y2 = dest->bits.height; + + for (i = 0; i < n_glyphs; ++i) + { + glyph_t *glyph = (glyph_t *)glyphs[i].glyph; + pixman_image_t *glyph_img = glyph->image; + pixman_box32_t glyph_box; + pixman_box32_t composite_box; + + if (glyph_img->common.extended_format_code != glyph_format || + glyph_img->common.flags != glyph_flags) + { + pixman_format_code_t src_format, mask_format; + + glyph_format = glyph_img->common.extended_format_code; + glyph_flags = glyph_img->common.flags; + + if (glyph_format == dest->bits.format) + { + src_format = glyph_format; + mask_format = PIXMAN_null; + info.src_flags = glyph_flags | FAST_PATH_SAMPLES_COVER_CLIP_NEAREST; + info.mask_flags = FAST_PATH_IS_OPAQUE; + info.mask_image = NULL; + white_src = FALSE; + } + else + { + if (!white_img) + { + pixman_color_t white = { 0xffff, 0xffff, 0xffff, 0xffff }; + + if (!(white_img = pixman_image_create_solid_fill (&white))) + goto out; + + _pixman_image_validate (white_img); + } + + src_format = PIXMAN_solid; + mask_format = glyph_format; + info.src_flags = white_img->common.flags; + info.mask_flags = glyph_flags | FAST_PATH_SAMPLES_COVER_CLIP_NEAREST; + info.src_image = white_img; + white_src = TRUE; + } + + _pixman_lookup_composite_function ( + get_implementation(), PIXMAN_OP_ADD, + src_format, info.src_flags, + mask_format, info.mask_flags, + dest_format, dest_flags, + &implementation, &func); + + if (!func) + goto out; + } + + glyph_box.x1 = glyphs[i].x - glyph->origin_x + off_x; + glyph_box.y1 = glyphs[i].y - glyph->origin_y + off_y; + glyph_box.x2 = glyph_box.x1 + glyph->image->bits.width; + glyph_box.y2 = glyph_box.y1 + glyph->image->bits.height; + + if (box32_intersect (&composite_box, &glyph_box, &dest_box)) + { + int src_x = composite_box.x1 - glyph_box.x1; + int src_y = composite_box.y1 - glyph_box.y1; + + if (white_src) + info.mask_image = glyph_img; + else + info.src_image = glyph_img; + + info.mask_x = info.src_x = src_x; + info.mask_y = info.src_y = src_y; + info.dest_x = composite_box.x1; + info.dest_y = composite_box.y1; + info.width = composite_box.x2 - composite_box.x1; + info.height = composite_box.y2 - composite_box.y1; + + func (implementation, &info); + + pixman_list_move_to_front (&cache->mru, &glyph->mru_link); + } + } + +out: + if (white_img) + pixman_image_unref (white_img); +} + +/* Conceptually, for each glyph, (white IN glyph) is PIXMAN_OP_ADDed to an + * infinitely big mask image at the position such that the glyph origin point + * is positioned at the (glyphs[i].x, glyphs[i].y) point. + * + * Then (mask_x, mask_y) in the infinite mask and (src_x, src_y) in the source + * image are both aligned with (dest_x, dest_y) in the destination image. Then + * these three images are composited within the + * + * (dest_x, dest_y, dst_x + width, dst_y + height) + * + * rectangle. + * + * TODO: + * - Trim the mask to the destination clip/image? + * - Trim composite region based on sources, when the op ignores 0s. + */ +PIXMAN_EXPORT void +pixman_composite_glyphs (pixman_op_t op, + pixman_image_t *src, + pixman_image_t *dest, + pixman_format_code_t mask_format, + int32_t src_x, + int32_t src_y, + int32_t mask_x, + int32_t mask_y, + int32_t dest_x, + int32_t dest_y, + int32_t width, + int32_t height, + pixman_glyph_cache_t *cache, + int n_glyphs, + pixman_glyph_t *glyphs) +{ + pixman_image_t *mask; + + if (!(mask = pixman_image_create_bits (mask_format, width, height, NULL, -1))) + return; + + if (PIXMAN_FORMAT_A (mask_format) != 0 && + PIXMAN_FORMAT_RGB (mask_format) != 0) + { + pixman_image_set_component_alpha (mask, TRUE); + } + + add_glyphs (cache, mask, - mask_x, - mask_y, n_glyphs, glyphs); + + pixman_image_composite32 (op, src, mask, dest, + src_x, src_y, + 0, 0, + dest_x, dest_y, + width, height); + + pixman_image_unref (mask); +} diff --git a/pixman/pixman/pixman-image.c b/pixman/pixman/pixman-image.c index 6a965e462..8b634a7dc 100644 --- a/pixman/pixman/pixman-image.c +++ b/pixman/pixman/pixman-image.c @@ -879,13 +879,34 @@ _pixman_image_get_solid (pixman_implementation_t *imp, pixman_format_code_t format) { uint32_t result; - pixman_iter_t iter; - _pixman_implementation_src_iter_init ( - imp, &iter, image, 0, 0, 1, 1, - (uint8_t *)&result, ITER_NARROW, image->common.flags); - - result = *iter.get_scanline (&iter, NULL); + if (image->type == SOLID) + { + result = image->solid.color_32; + } + else if (image->type == BITS) + { + if (image->bits.format == PIXMAN_a8r8g8b8) + result = image->bits.bits[0]; + else if (image->bits.format == PIXMAN_x8r8g8b8) + result = image->bits.bits[0] | 0xff000000; + else if (image->bits.format == PIXMAN_a8) + result = (*(uint8_t *)image->bits.bits) << 24; + else + goto otherwise; + } + else + { + pixman_iter_t iter; + + otherwise: + _pixman_implementation_src_iter_init ( + imp, &iter, image, 0, 0, 1, 1, + (uint8_t *)&result, + ITER_NARROW, image->common.flags); + + result = *iter.get_scanline (&iter, NULL); + } /* If necessary, convert RGB <--> BGR. */ if (PIXMAN_FORMAT_TYPE (format) != PIXMAN_TYPE_ARGB) diff --git a/pixman/pixman/pixman-private.h b/pixman/pixman/pixman-private.h index f4ca63216..873f3218f 100644 --- a/pixman/pixman/pixman-private.h +++ b/pixman/pixman/pixman-private.h @@ -13,6 +13,7 @@ #include #include #include +#include #include "pixman-compiler.h" @@ -580,6 +581,19 @@ _pixman_choose_implementation (void); /* * Utilities */ +pixman_bool_t +_pixman_compute_composite_region32 (pixman_region32_t * region, + pixman_image_t * src_image, + pixman_image_t * mask_image, + pixman_image_t * dest_image, + int32_t src_x, + int32_t src_y, + int32_t mask_x, + int32_t mask_y, + int32_t dest_x, + int32_t dest_y, + int32_t width, + int32_t height); uint32_t * _pixman_iter_get_scanline_noop (pixman_iter_t *iter, const uint32_t *mask); @@ -687,6 +701,18 @@ _pixman_iter_get_scanline_noop (pixman_iter_t *iter, const uint32_t *mask); dest, FAST_PATH_STD_DEST_FLAGS, \ func) } +extern pixman_implementation_t *global_implementation; + +static force_inline pixman_implementation_t * +get_implementation (void) +{ +#ifndef TOOLCHAIN_SUPPORTS_ATTRIBUTE_CONSTRUCTOR + if (!global_implementation) + global_implementation = _pixman_choose_implementation (); +#endif + return global_implementation; +} + /* Memory allocation helpers */ void * pixman_malloc_ab (unsigned int n, unsigned int b); @@ -736,6 +762,50 @@ pixman_bool_t pixman_region16_copy_from_region32 (pixman_region16_t *dst, pixman_region32_t *src); +/* Doubly linked lists */ +typedef struct pixman_link_t pixman_link_t; +struct pixman_link_t +{ + pixman_link_t *next; + pixman_link_t *prev; +}; + +typedef struct pixman_list_t pixman_list_t; +struct pixman_list_t +{ + pixman_link_t *head; + pixman_link_t *tail; +}; + +static force_inline void +pixman_list_init (pixman_list_t *list) +{ + list->head = (pixman_link_t *)list; + list->tail = (pixman_link_t *)list; +} + +static force_inline void +pixman_list_prepend (pixman_list_t *list, pixman_link_t *link) +{ + link->next = list->head; + link->prev = (pixman_link_t *)list; + list->head->prev = link; + list->head = link; +} + +static force_inline void +pixman_list_unlink (pixman_link_t *link) +{ + link->prev->next = link->next; + link->next->prev = link->prev; +} + +static force_inline void +pixman_list_move_to_front (pixman_list_t *list, pixman_link_t *link) +{ + pixman_list_unlink (link); + pixman_list_prepend (list, link); +} /* Misc macros */ diff --git a/pixman/pixman/pixman-utils.c b/pixman/pixman/pixman-utils.c index 2ec2594e1..93c061ad2 100644 --- a/pixman/pixman/pixman-utils.c +++ b/pixman/pixman/pixman-utils.c @@ -183,6 +183,22 @@ pixman_malloc_abc (unsigned int a, return malloc (a * b * c); } +static void +unorm_to_unorm_params (int in_width, int out_width, uint32_t *factor, int *shift) +{ + int w = 0; + + *factor = 0; + while (in_width != 0 && w < out_width) + { + *factor |= 1 << w; + w += in_width; + } + + /* Did we generate too many bits? */ + *shift = w - out_width; +} + /* * This function expands images from ARGB8 format to ARGB16. To preserve * precision, it needs to know the original source format. For example, if the @@ -212,8 +228,15 @@ pixman_expand (uint64_t * dst, r_mask = ~(~0 << r_size), g_mask = ~(~0 << g_size), b_mask = ~(~0 << b_size); + uint32_t au_factor, ru_factor, gu_factor, bu_factor; + int au_shift, ru_shift, gu_shift, bu_shift; int i; + unorm_to_unorm_params (a_size, 16, &au_factor, &au_shift); + unorm_to_unorm_params (r_size, 16, &ru_factor, &ru_shift); + unorm_to_unorm_params (g_size, 16, &gu_factor, &gu_shift); + unorm_to_unorm_params (b_size, 16, &bu_factor, &bu_shift); + /* Start at the end so that we can do the expansion in place * when src == dst */ @@ -226,7 +249,7 @@ pixman_expand (uint64_t * dst, if (a_size) { a = (pixel >> a_shift) & a_mask; - a16 = unorm_to_unorm (a, a_size, 16); + a16 = a * au_factor >> au_shift; } else { @@ -238,9 +261,9 @@ pixman_expand (uint64_t * dst, r = (pixel >> r_shift) & r_mask; g = (pixel >> g_shift) & g_mask; b = (pixel >> b_shift) & b_mask; - r16 = unorm_to_unorm (r, r_size, 16); - g16 = unorm_to_unorm (g, g_size, 16); - b16 = unorm_to_unorm (b, b_size, 16); + r16 = r * ru_factor >> ru_shift; + g16 = g * gu_factor >> gu_shift; + b16 = b * bu_factor >> bu_shift; } else { diff --git a/pixman/pixman/pixman.c b/pixman/pixman/pixman.c index 8fb53568f..0137c3cab 100644 --- a/pixman/pixman/pixman.c +++ b/pixman/pixman/pixman.c @@ -30,7 +30,7 @@ #include -static pixman_implementation_t *global_implementation; +pixman_implementation_t *global_implementation; #ifdef TOOLCHAIN_SUPPORTS_ATTRIBUTE_CONSTRUCTOR static void __attribute__((constructor)) @@ -40,16 +40,6 @@ pixman_constructor (void) } #endif -static force_inline pixman_implementation_t * -get_implementation (void) -{ -#ifndef TOOLCHAIN_SUPPORTS_ATTRIBUTE_CONSTRUCTOR - if (!global_implementation) - global_implementation = _pixman_choose_implementation (); -#endif - return global_implementation; -} - typedef struct operator_info_t operator_info_t; struct operator_info_t @@ -234,19 +224,19 @@ clip_source_image (pixman_region32_t * region, * returns FALSE if the final region is empty. Indistinguishable from * an allocation failure, but rendering ignores those anyways. */ -static pixman_bool_t -pixman_compute_composite_region32 (pixman_region32_t * region, - pixman_image_t * src_image, - pixman_image_t * mask_image, - pixman_image_t * dest_image, - int32_t src_x, - int32_t src_y, - int32_t mask_x, - int32_t mask_y, - int32_t dest_x, - int32_t dest_y, - int32_t width, - int32_t height) +pixman_bool_t +_pixman_compute_composite_region32 (pixman_region32_t * region, + pixman_image_t * src_image, + pixman_image_t * mask_image, + pixman_image_t * dest_image, + int32_t src_x, + int32_t src_y, + int32_t mask_x, + int32_t mask_y, + int32_t dest_x, + int32_t dest_y, + int32_t width, + int32_t height) { region->extents.x1 = dest_x; region->extents.x2 = dest_x + width; @@ -625,7 +615,7 @@ pixman_image_composite32 (pixman_op_t op, pixman_region32_init (®ion); - if (!pixman_compute_composite_region32 ( + if (!_pixman_compute_composite_region32 ( ®ion, src, mask, dest, src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height)) { @@ -1124,7 +1114,7 @@ pixman_compute_composite_region (pixman_region16_t * region, pixman_region32_init (&r32); - retval = pixman_compute_composite_region32 ( + retval = _pixman_compute_composite_region32 ( &r32, src_image, mask_image, dest_image, src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height); diff --git a/pixman/pixman/pixman.h b/pixman/pixman/pixman.h index 18d951312..7233ceb8a 100644 --- a/pixman/pixman/pixman.h +++ b/pixman/pixman/pixman.h @@ -867,6 +867,65 @@ void pixman_image_composite32 (pixman_op_t op, */ void pixman_disable_out_of_bounds_workaround (void); +/* + * Glyphs + */ +typedef struct pixman_glyph_cache_t pixman_glyph_cache_t; +typedef struct +{ + int x, y; + const void *glyph; +} pixman_glyph_t; + +pixman_glyph_cache_t *pixman_glyph_cache_create (void); +void pixman_glyph_cache_destroy (pixman_glyph_cache_t *cache); +void pixman_glyph_cache_freeze (pixman_glyph_cache_t *cache); +void pixman_glyph_cache_thaw (pixman_glyph_cache_t *cache); +const void * pixman_glyph_cache_lookup (pixman_glyph_cache_t *cache, + void *font_key, + void *glyph_key); +const void * pixman_glyph_cache_insert (pixman_glyph_cache_t *cache, + void *font_key, + void *glyph_key, + int origin_x, + int origin_y, + pixman_image_t *glyph_image); +void pixman_glyph_cache_remove (pixman_glyph_cache_t *cache, + void *font_key, + void *glyph_key); +void pixman_glyph_get_extents (pixman_glyph_cache_t *cache, + int n_glyphs, + pixman_glyph_t *glyphs, + pixman_box32_t *extents); +pixman_format_code_t pixman_glyph_get_mask_format (pixman_glyph_cache_t *cache, + int n_glyphs, + pixman_glyph_t * glyphs); +void pixman_composite_glyphs (pixman_op_t op, + pixman_image_t *src, + pixman_image_t *dest, + pixman_format_code_t mask_format, + int32_t src_x, + int32_t src_y, + int32_t mask_x, + int32_t mask_y, + int32_t dest_x, + int32_t dest_y, + int32_t width, + int32_t height, + pixman_glyph_cache_t *cache, + int n_glyphs, + pixman_glyph_t *glyphs); +void pixman_composite_glyphs_no_mask (pixman_op_t op, + pixman_image_t *src, + pixman_image_t *dest, + int32_t src_x, + int32_t src_y, + int32_t dest_x, + int32_t dest_y, + pixman_glyph_cache_t *cache, + int n_glyphs, + pixman_glyph_t *glyphs); + /* * Trapezoids */ diff --git a/pixman/test/Makefile.sources b/pixman/test/Makefile.sources index 99eb705af..fad8c6f69 100644 --- a/pixman/test/Makefile.sources +++ b/pixman/test/Makefile.sources @@ -16,6 +16,7 @@ TESTPROGRAMS = \ stress-test \ composite-traps-test \ blitters-test \ + glyph-test \ scaling-test \ affine-test \ composite \ diff --git a/pixman/test/blitters-test.c b/pixman/test/blitters-test.c index feea308c2..6a3cc8649 100644 --- a/pixman/test/blitters-test.c +++ b/pixman/test/blitters-test.c @@ -83,39 +83,10 @@ free_random_image (uint32_t initcrc, pixman_format_code_t fmt) { uint32_t crc32 = 0; - int stride = pixman_image_get_stride (img); uint32_t *data = pixman_image_get_data (img); - int height = pixman_image_get_height (img); if (fmt != PIXMAN_null) - { - /* mask unused 'x' part */ - if (PIXMAN_FORMAT_BPP (fmt) - PIXMAN_FORMAT_DEPTH (fmt) && - PIXMAN_FORMAT_DEPTH (fmt) != 0) - { - int i; - uint32_t *data = pixman_image_get_data (img); - uint32_t mask = (1 << PIXMAN_FORMAT_DEPTH (fmt)) - 1; - - if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_BGRA || - PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_RGBA) - { - mask <<= (PIXMAN_FORMAT_BPP (fmt) - PIXMAN_FORMAT_DEPTH (fmt)); - } - - for (i = 0; i * PIXMAN_FORMAT_BPP (fmt) < 32; i++) - mask |= mask << (i * PIXMAN_FORMAT_BPP (fmt)); - - for (i = 0; i < stride * height / 4; i++) - data[i] &= mask; - } - - /* swap endiannes in order to provide identical results on both big - * and litte endian systems - */ - image_endian_swap (img); - crc32 = compute_crc32 (initcrc, data, stride * height); - } + crc32 = compute_crc32_for_image (initcrc, img); pixman_image_unref (img); free (data); diff --git a/pixman/test/glyph-test.c b/pixman/test/glyph-test.c new file mode 100644 index 000000000..9ff2a2bd4 --- /dev/null +++ b/pixman/test/glyph-test.c @@ -0,0 +1,331 @@ +#include +#include "utils.h" + +static const pixman_format_code_t glyph_formats[] = +{ + PIXMAN_a8r8g8b8, + PIXMAN_a8, + PIXMAN_a4, + PIXMAN_a1, + PIXMAN_x8r8g8b8, + PIXMAN_r3g3b2, + PIXMAN_null, +}; + +static const pixman_format_code_t formats[] = +{ + PIXMAN_a8r8g8b8, + PIXMAN_a8b8g8r8, + PIXMAN_x8r8g8b8, + PIXMAN_x8b8g8r8, + PIXMAN_r5g6b5, + PIXMAN_b5g6r5, + PIXMAN_a8, + PIXMAN_a1, + PIXMAN_r3g3b2, + PIXMAN_b8g8r8a8, + PIXMAN_b8g8r8x8, + PIXMAN_r8g8b8a8, + PIXMAN_r8g8b8x8, + PIXMAN_x14r6g6b6, + PIXMAN_r8g8b8, + PIXMAN_b8g8r8, + PIXMAN_x2r10g10b10, + PIXMAN_a2r10g10b10, + PIXMAN_x2b10g10r10, + PIXMAN_a2b10g10r10, + PIXMAN_a1r5g5b5, + PIXMAN_x1r5g5b5, + PIXMAN_a1b5g5r5, + PIXMAN_x1b5g5r5, + PIXMAN_a4r4g4b4, + PIXMAN_x4r4g4b4, + PIXMAN_a4b4g4r4, + PIXMAN_x4b4g4r4, + PIXMAN_r3g3b2, + PIXMAN_b2g3r3, + PIXMAN_a2r2g2b2, + PIXMAN_a2b2g2r2, + PIXMAN_x4a4, + PIXMAN_a4, + PIXMAN_r1g2b1, + PIXMAN_b1g2r1, + PIXMAN_a1r1g1b1, + PIXMAN_a1b1g1r1, + PIXMAN_null, +}; + +static const pixman_op_t operators[] = +{ + PIXMAN_OP_SRC, + PIXMAN_OP_OVER, + PIXMAN_OP_ADD, + PIXMAN_OP_CLEAR, + PIXMAN_OP_SRC, + PIXMAN_OP_DST, + PIXMAN_OP_OVER, + PIXMAN_OP_OVER_REVERSE, + PIXMAN_OP_IN, + PIXMAN_OP_IN_REVERSE, + PIXMAN_OP_OUT, + PIXMAN_OP_OUT_REVERSE, + PIXMAN_OP_ATOP, + PIXMAN_OP_ATOP_REVERSE, + PIXMAN_OP_XOR, + PIXMAN_OP_ADD +}; + +enum +{ + ALLOW_CLIPPED = (1 << 0), + ALLOW_ALPHA_MAP = (1 << 1), + ALLOW_SOURCE_CLIPPING = (1 << 2), + ALLOW_REPEAT = (1 << 3), + ALLOW_SOLID = (1 << 4), + ALLOW_FENCED_MEMORY = (1 << 5), +}; + +static void +destroy_fenced (pixman_image_t *image, void *data) +{ + fence_free (data); +} + +static void +destroy_malloced (pixman_image_t *image, void *data) +{ + free (data); +} + +static pixman_format_code_t +random_format (const pixman_format_code_t *formats) +{ + int i; + i = 0; + while (formats[i] != PIXMAN_null) + ++i; + return formats[lcg_rand_n (i)]; +} + +static pixman_image_t * +create_image (int max_size, const pixman_format_code_t *formats, uint32_t flags) +{ + int width, height; + pixman_image_t *image; + pixman_format_code_t format; + uint32_t *data; + int bpp; + int stride; + int i; + pixman_image_destroy_func_t destroy; + + if ((flags & ALLOW_SOLID) && lcg_rand_n (4) == 0) + { + pixman_color_t color; + + color.alpha = lcg_rand_u32(); + color.red = lcg_rand_u32(); + color.green = lcg_rand_u32(); + color.blue = lcg_rand_u32(); + + return pixman_image_create_solid_fill (&color); + } + + width = lcg_rand_n (max_size) + 1; + height = lcg_rand_n (max_size) + 1; + format = random_format (formats); + + bpp = PIXMAN_FORMAT_BPP (format); + stride = (width * bpp + 7) / 8 + lcg_rand_n (17); + stride = (stride + 3) & ~3; + + if (lcg_rand_n (64) == 0) + { + if (!(data = (uint32_t *)make_random_bytes (stride * height))) + { + fprintf (stderr, "Out of memory\n"); + abort (); + } + destroy = destroy_fenced; + } + else + { + data = malloc (stride * height); + for (i = 0; i < height * stride / 4; ++i) + data[i] = lcg_rand_u32(); + + destroy = destroy_malloced; + } + + image = pixman_image_create_bits (format, width, height, data, stride); + pixman_image_set_destroy_function (image, destroy, data); + + if ((flags & ALLOW_CLIPPED) && lcg_rand_n (8) == 0) + { + pixman_box16_t clip_boxes[8]; + pixman_region16_t clip; + int n = lcg_rand_n (8) + 1; + + for (i = 0; i < n; i++) + { + clip_boxes[i].x1 = lcg_rand_n (width); + clip_boxes[i].y1 = lcg_rand_n (height); + clip_boxes[i].x2 = + clip_boxes[i].x1 + lcg_rand_n (width - clip_boxes[i].x1); + clip_boxes[i].y2 = + clip_boxes[i].y1 + lcg_rand_n (height - clip_boxes[i].y1); + } + + pixman_region_init_rects (&clip, clip_boxes, n); + pixman_image_set_clip_region (image, &clip); + pixman_region_fini (&clip); + } + + if ((flags & ALLOW_SOURCE_CLIPPING) && lcg_rand_n (4) == 0) + { + pixman_image_set_source_clipping (image, TRUE); + pixman_image_set_has_client_clip (image, TRUE); + } + + if ((flags & ALLOW_ALPHA_MAP) && lcg_rand_n (16) == 0) + { + pixman_image_t *alpha_map; + int alpha_x, alpha_y; + + alpha_x = lcg_rand_n (width); + alpha_y = lcg_rand_n (height); + alpha_map = + create_image (max_size, formats, (flags & ~ALLOW_ALPHA_MAP)); + pixman_image_set_alpha_map (image, alpha_map, alpha_x, alpha_y); + pixman_image_unref (alpha_map); + } + + if ((flags & ALLOW_REPEAT) && lcg_rand_n (2) == 0) + pixman_image_set_repeat (image, lcg_rand_n (4)); + + image_endian_swap (image); + + return image; +} + +#define KEY1(p) ((void *)(((unsigned long)p) ^ (0xa7e23dfaUL))) +#define KEY2(p) ((void *)(((unsigned long)p) ^ (0xabcd9876UL))) + +#define MAX_GLYPHS 32 + +uint32_t +test_glyphs (int testnum, int verbose) +{ + pixman_image_t *glyph_images[MAX_GLYPHS]; + pixman_glyph_t glyphs[4 * MAX_GLYPHS]; + uint32_t crc32 = 0; + pixman_image_t *source, *dest; + int n_glyphs, i; + pixman_glyph_cache_t *cache; + + lcg_srand (testnum); + + cache = pixman_glyph_cache_create (); + + source = create_image (300, formats, + ALLOW_CLIPPED | ALLOW_ALPHA_MAP | + ALLOW_SOURCE_CLIPPING | + ALLOW_REPEAT | ALLOW_SOLID); + + dest = create_image (128, formats, + ALLOW_CLIPPED | ALLOW_ALPHA_MAP | + ALLOW_SOURCE_CLIPPING); + + pixman_glyph_cache_freeze (cache); + + n_glyphs = lcg_rand_n (MAX_GLYPHS); + for (i = 0; i < n_glyphs; ++i) + glyph_images[i] = create_image (32, glyph_formats, 0); + + for (i = 0; i < 4 * n_glyphs; ++i) + { + int g = lcg_rand_n (n_glyphs); + pixman_image_t *glyph_img = glyph_images[g]; + void *key1 = KEY1 (glyph_img); + void *key2 = KEY2 (glyph_img); + const void *glyph; + + if (!(glyph = pixman_glyph_cache_lookup (cache, key1, key2))) + { + glyph = + pixman_glyph_cache_insert (cache, key1, key2, 5, 8, glyph_img); + } + + glyphs[i].glyph = glyph; + glyphs[i].x = lcg_rand_n (128); + glyphs[i].y = lcg_rand_n (128); + } + + if (lcg_rand_n (2) == 0) + { + int src_x = lcg_rand_n (300) - 150; + int src_y = lcg_rand_n (300) - 150; + int mask_x = lcg_rand_n (64) - 32; + int mask_y = lcg_rand_n (64) - 32; + int dest_x = lcg_rand_n (64) - 32; + int dest_y = lcg_rand_n (64) - 32; + int width = lcg_rand_n (64); + int height = lcg_rand_n (64); + pixman_op_t op = operators[lcg_rand_n (ARRAY_LENGTH (operators))]; + pixman_format_code_t format = random_format (glyph_formats); + + pixman_composite_glyphs ( + op, + source, dest, format, + src_x, src_y, + mask_x, mask_y, + dest_x, dest_y, + width, height, + cache, 4 * n_glyphs, glyphs); + } + else + { + pixman_op_t op = operators[lcg_rand_n (ARRAY_LENGTH (operators))]; + int src_x = lcg_rand_n (300) - 150; + int src_y = lcg_rand_n (300) - 150; + int dest_x = lcg_rand_n (64) - 32; + int dest_y = lcg_rand_n (64) - 32; + + pixman_composite_glyphs_no_mask ( + op, source, dest, + src_x, src_y, + dest_x, dest_y, + cache, 4 * n_glyphs, glyphs); + } + + pixman_glyph_cache_thaw (cache); + + for (i = 0; i < n_glyphs; ++i) + { + pixman_image_t *img = glyph_images[i]; + void *key1, *key2; + + key1 = KEY1 (img); + key2 = KEY2 (img); + + pixman_glyph_cache_remove (cache, key1, key2); + pixman_image_unref (glyph_images[i]); + } + + crc32 = compute_crc32_for_image (0, dest); + + pixman_image_unref (source); + pixman_image_unref (dest); + + pixman_glyph_cache_destroy (cache); + + return crc32; +} + +int +main (int argc, const char *argv[]) +{ + return fuzzer_test_main ("glyph", 30000, + 0xA2B67F99, + test_glyphs, argc, argv); +} diff --git a/pixman/test/utils.c b/pixman/test/utils.c index c1bf6dc2c..0abc32c66 100644 --- a/pixman/test/utils.c +++ b/pixman/test/utils.c @@ -135,6 +135,107 @@ compute_crc32 (uint32_t in_crc32, return (crc32 ^ 0xFFFFFFFF); } +static uint32_t +compute_crc32_for_image_internal (uint32_t crc32, + pixman_image_t *img, + pixman_bool_t remove_alpha, + pixman_bool_t remove_rgb) +{ + pixman_format_code_t fmt = pixman_image_get_format (img); + uint32_t *data = pixman_image_get_data (img); + int stride = pixman_image_get_stride (img); + int height = pixman_image_get_height (img); + uint32_t mask = 0xffffffff; + int i; + + /* mask unused 'x' part */ + if (PIXMAN_FORMAT_BPP (fmt) - PIXMAN_FORMAT_DEPTH (fmt) && + PIXMAN_FORMAT_DEPTH (fmt) != 0) + { + uint32_t m = (1 << PIXMAN_FORMAT_DEPTH (fmt)) - 1; + + if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_BGRA || + PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_RGBA) + { + m <<= (PIXMAN_FORMAT_BPP (fmt) - PIXMAN_FORMAT_DEPTH (fmt)); + } + + mask &= m; + } + + /* mask alpha channel */ + if (remove_alpha && PIXMAN_FORMAT_A (fmt)) + { + uint32_t m; + + if (PIXMAN_FORMAT_BPP (fmt) == 32) + m = 0xffffffff; + else + m = (1 << PIXMAN_FORMAT_BPP (fmt)) - 1; + + m >>= PIXMAN_FORMAT_A (fmt); + + if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_BGRA || + PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_RGBA || + PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_A) + { + /* Alpha is at the bottom of the pixel */ + m <<= PIXMAN_FORMAT_A (fmt); + } + + mask &= m; + } + + /* mask rgb channels */ + if (remove_rgb && PIXMAN_FORMAT_RGB (fmt)) + { + uint32_t m = ((uint32_t)~0) >> (32 - PIXMAN_FORMAT_BPP (fmt)); + uint32_t size = PIXMAN_FORMAT_R (fmt) + PIXMAN_FORMAT_G (fmt) + PIXMAN_FORMAT_B (fmt); + + m &= ~((1 << size) - 1); + + if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_BGRA || + PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_RGBA) + { + /* RGB channels are at the top of the pixel */ + m >>= size; + } + + mask &= m; + } + + for (i = 0; i * PIXMAN_FORMAT_BPP (fmt) < 32; i++) + mask |= mask << (i * PIXMAN_FORMAT_BPP (fmt)); + + for (i = 0; i < stride * height / 4; i++) + data[i] &= mask; + + /* swap endiannes in order to provide identical results on both big + * and litte endian systems + */ + image_endian_swap (img); + + return compute_crc32 (crc32, data, stride * height); +} + +uint32_t +compute_crc32_for_image (uint32_t crc32, + pixman_image_t *img) +{ + if (img->common.alpha_map) + { + crc32 = compute_crc32_for_image_internal (crc32, img, TRUE, FALSE); + crc32 = compute_crc32_for_image_internal ( + crc32, (pixman_image_t *)img->common.alpha_map, FALSE, TRUE); + } + else + { + crc32 = compute_crc32_for_image_internal (crc32, img, FALSE, FALSE); + } + + return crc32; +} + pixman_bool_t is_little_endian (void) { diff --git a/pixman/test/utils.h b/pixman/test/utils.h index 01af316d2..ac2decd11 100644 --- a/pixman/test/utils.h +++ b/pixman/test/utils.h @@ -63,7 +63,12 @@ compute_crc32 (uint32_t in_crc32, const void *buf, size_t buf_len); -/* Returns TRUE if running on a little endian system */ +uint32_t +compute_crc32_for_image (uint32_t in_crc32, + pixman_image_t *image); + +/* Returns TRUE if running on a little endian system + */ pixman_bool_t is_little_endian (void); -- cgit v1.2.3