diff options
34 files changed, 1409 insertions, 498 deletions
diff --git a/compare.bat b/compare.bat index 90fe65d84..90fe65d84 100644..100755 --- a/compare.bat +++ b/compare.bat diff --git a/fontconfig/configure.ac b/fontconfig/configure.ac index a2b1c72f4..aeb151331 100644 --- a/fontconfig/configure.ac +++ b/fontconfig/configure.ac @@ -161,35 +161,37 @@ AC_LINK_IFELSE([AC_LANG_SOURCE([[ AC_MSG_RESULT([yes]) AC_DEFINE([HAVE_POSIX_FADVISE], [1], [Define to 1 if you have the 'posix_fadvise' function.]) ],[AC_MSG_RESULT([no])]) -AC_MSG_CHECKING([for scandir]) -AC_LINK_IFELSE([AC_LANG_SOURCE([[ - #include <dirent.h> - int comp(const struct dirent **, const struct dirent **); - int comp(const struct dirent **a, const struct dirent **b) { return 0; } - int main(void) { - struct dirent **d; - return scandir(".", &d, 0, &comp) >= 0; - } - ]])],[ - AC_MSG_RESULT([yes]) - AC_DEFINE([HAVE_SCANDIR], [1], [Define to 1 if you have the 'scandir' function.]) - ],[ - AC_LINK_IFELSE([AC_LANG_SOURCE([[ - #include <dirent.h> - int comp(const void *, const void *); - int comp(const void *a, const void *b) { return 0; } - int main(void) { - struct dirent **d; - return scandir(".", &d, 0, &comp) >= 0; - } +if test "$os_win32" = "no"; then + AC_MSG_CHECKING([for scandir]) + AC_LINK_IFELSE([AC_LANG_SOURCE([[ + #include <dirent.h> + int comp(const struct dirent **, const struct dirent **); + int comp(const struct dirent **a, const struct dirent **b) { return 0; } + int main(void) { + struct dirent **d; + return scandir(".", &d, 0, &comp) >= 0; + } ]])],[ AC_MSG_RESULT([yes]) - AC_DEFINE([HAVE_SCANDIR_VOID_P], [1], [Define to 1 if you have the 'scandir' function with int (* compar)(const void *, const void *)]) + AC_DEFINE([HAVE_SCANDIR], [1], [Define to 1 if you have the 'scandir' function.]) ],[ - AC_MSG_ERROR([ + AC_LINK_IFELSE([AC_LANG_SOURCE([[ + #include <dirent.h> + int comp(const void *, const void *); + int comp(const void *a, const void *b) { return 0; } + int main(void) { + struct dirent **d; + return scandir(".", &d, 0, &comp) >= 0; + } + ]])],[ + AC_MSG_RESULT([yes]) + AC_DEFINE([HAVE_SCANDIR_VOID_P], [1], [Define to 1 if you have the 'scandir' function with int (* compar)(const void *, const void *)]) + ],[ + AC_MSG_ERROR([ *** No scandir function available.]) + ]) ]) - ]) +fi CFLAGS="$fc_saved_CFLAGS" # diff --git a/fontconfig/src/fccfg.c b/fontconfig/src/fccfg.c index 9c0be24a3..7ea94b846 100644 --- a/fontconfig/src/fccfg.c +++ b/fontconfig/src/fccfg.c @@ -214,10 +214,8 @@ FcSubstDestroy (FcSubst *s) while (s) { n = s->next; - if (s->test) - FcTestDestroy (s->test); - if (s->edit) - FcEditDestroy (s->edit); + if (s->rule) + FcRuleDestroy (s->rule); free (s); s = n; } @@ -226,20 +224,20 @@ FcSubstDestroy (FcSubst *s) FcExpr * FcConfigAllocExpr (FcConfig *config) { - if (!config->expr_pool || config->expr_pool->next == config->expr_pool->end) - { - FcExprPage *new_page; + if (!config->expr_pool || config->expr_pool->next == config->expr_pool->end) + { + FcExprPage *new_page; - new_page = malloc (sizeof (FcExprPage)); - if (!new_page) - return 0; + new_page = malloc (sizeof (FcExprPage)); + if (!new_page) + return 0; - new_page->next_page = config->expr_pool; - new_page->next = new_page->exprs; - config->expr_pool = new_page; - } + new_page->next_page = config->expr_pool; + new_page->next = new_page->exprs; + config->expr_pool = new_page; + } - return config->expr_pool->next++; + return config->expr_pool->next++; } FcConfig * @@ -644,15 +642,13 @@ FcConfigSetRescanInverval (FcConfig *config, int rescanInterval) return FcConfigSetRescanInterval (config, rescanInterval); } - FcBool -FcConfigAddEdit (FcConfig *config, - FcTest *test, - FcEdit *edit, +FcConfigAddRule (FcConfig *config, + FcRule *rule, FcMatchKind kind) { FcSubst *subst, **prev; - FcTest *t; + FcRule *r; int num; switch (kind) { @@ -673,15 +669,18 @@ FcConfigAddEdit (FcConfig *config, return FcFalse; for (; *prev; prev = &(*prev)->next); *prev = subst; - subst->next = 0; - subst->test = test; - subst->edit = edit; + subst->next = NULL; + subst->rule = rule; num = 0; - for (t = test; t; t = t->next) + for (r = rule; r; r = r->next) { - if (t->kind == FcMatchDefault) - t->kind = kind; - num++; + if (r->type == FcRuleTest) + { + if (r->u.test && + r->u.test->kind == FcMatchDefault) + r->u.test->kind = kind; + num++; + } } if (config->maxObjects < num) config->maxObjects = num; @@ -1486,13 +1485,12 @@ FcConfigSubstituteWithPat (FcConfig *config, { FcValue v; FcSubst *s; - FcSubState *st; - int i; - FcTest *t; - FcEdit *e; - FcValueList *l; + FcRule *r; + FcValueList *l, *value = NULL; FcPattern *m; FcStrSet *strs; + FcPatternElt *elt = NULL; + FcObject object = FC_INVALID_OBJECT; if (!config) { @@ -1537,10 +1535,6 @@ FcConfigSubstituteWithPat (FcConfig *config, return FcFalse; } - st = (FcSubState *) malloc (config->maxObjects * sizeof (FcSubState)); - if (!st && config->maxObjects) - return FcFalse; - if (FcDebug () & FC_DBG_EDIT) { printf ("FcConfigSubstitute "); @@ -1548,194 +1542,174 @@ FcConfigSubstituteWithPat (FcConfig *config, } for (; s; s = s->next) { - /* - * Check the tests to see if - * they all match the pattern - */ - for (t = s->test, i = 0; t; t = t->next, i++) + r = s->rule; + for (; r; r = r->next) { - if (FcDebug () & FC_DBG_EDIT) - { - printf ("FcConfigSubstitute test "); - FcTestPrint (t); - } - st[i].elt = 0; - if (kind == FcMatchFont && t->kind == FcMatchPattern) - m = p_pat; - else - m = p; - if (m) - st[i].elt = FcPatternObjectFindElt (m, t->object); - else - st[i].elt = 0; - /* - * If there's no such field in the font, - * then FcQualAll matches while FcQualAny does not - */ - if (!st[i].elt) - { - if (t->qual == FcQualAll) + switch (r->type) { + case FcRuleUnknown: + /* shouldn't be reached */ + break; + case FcRuleTest: + /* + * Check the tests to see if + * they all match the pattern + */ + if (FcDebug () & FC_DBG_EDIT) { - st[i].value = 0; - continue; + printf ("FcConfigSubstitute test "); + FcTestPrint (r->u.test); } + if (kind == FcMatchFont && r->u.test->kind == FcMatchPattern) + m = p_pat; else - break; - } - /* - * Check to see if there is a match, mark the location - * to apply match-relative edits - */ - st[i].value = FcConfigMatchValueList (m, p_pat, kind, t, st[i].elt->values); - if (!st[i].value) - break; - if (t->qual == FcQualFirst && st[i].value != st[i].elt->values) - break; - if (t->qual == FcQualNotFirst && st[i].value == st[i].elt->values) - break; - } - if (t) - { - if (FcDebug () & FC_DBG_EDIT) - printf ("No match\n"); - continue; - } - if (FcDebug () & FC_DBG_EDIT) - { - printf ("Substitute "); - FcSubstPrint (s); - } - for (e = s->edit; e; e = e->next) - { - /* - * Evaluate the list of expressions - */ - l = FcConfigValues (p, p_pat,kind, e->expr, e->binding); - /* - * Locate any test associated with this field, skipping - * tests associated with the pattern when substituting in - * the font - */ - for (t = s->test, i = 0; t; t = t->next, i++) - { - if ((t->kind == FcMatchFont || kind == FcMatchPattern) && - t->object == e->object) + m = p; + if (m) + elt = FcPatternObjectFindElt (m, r->u.test->object); + else + elt = NULL; + /* + * If there's no such field in the font, + * then FcQualAll matches while FcQualAny does not + */ + if (!elt) { - /* - * KLUDGE - the pattern may have been reallocated or - * things may have been inserted or deleted above - * this element by other edits. Go back and find - * the element again - */ - if (e != s->edit && st[i].elt) - st[i].elt = FcPatternObjectFindElt (p, t->object); - if (!st[i].elt) - t = 0; - break; + if (r->u.test->qual == FcQualAll) + { + value = NULL; + continue; + } + else + { + if (FcDebug () & FC_DBG_EDIT) + printf ("No match\n"); + goto bail; + } } - } - switch (FC_OP_GET_OP (e->op)) { - case FcOpAssign: /* - * If there was a test, then replace the matched - * value with the new list of values + * Check to see if there is a match, mark the location + * to apply match-relative edits */ - if (t) + value = FcConfigMatchValueList (m, p_pat, kind, r->u.test, elt->values); + if (!value || + (r->u.test->qual == FcQualFirst && value != elt->values) || + (r->u.test->qual == FcQualNotFirst && value == elt->values)) { - FcValueList *thisValue = st[i].value; - FcValueList *nextValue = thisValue; - + if (FcDebug () & FC_DBG_EDIT) + printf ("No match\n"); + goto bail; + } + object = r->u.test->object; + break; + case FcRuleEdit: + if (FcDebug () & FC_DBG_EDIT) + { + printf ("Substitute "); + FcEditPrint (r->u.edit); + printf ("\n\n"); + } + /* + * Evaluate the list of expressions + */ + l = FcConfigValues (p, p_pat,kind, r->u.edit->expr, r->u.edit->binding); + /* + * Locate any test associated with this field, skipping + * tests associated with the pattern when substituting in + * the font + */ + if (object != r->u.edit->object) + value = NULL; + + switch (FC_OP_GET_OP (r->u.edit->op)) { + case FcOpAssign: /* - * Append the new list of values after the current value + * If there was a test, then replace the matched + * value with the new list of values */ - FcConfigAdd (&st[i].elt->values, thisValue, FcTrue, l, e->object); + if (value) + { + FcValueList *thisValue = value; + FcValueList *nextValue = thisValue; + + /* + * Append the new list of values after the current value + */ + FcConfigAdd (&elt->values, thisValue, FcTrue, l, r->u.edit->object); + /* + * Delete the marked value + */ + if (thisValue) + FcConfigDel (&elt->values, thisValue); + /* + * Adjust a pointer into the value list to ensure + * future edits occur at the same place + */ + value = nextValue; + break; + } + /* fall through ... */ + case FcOpAssignReplace: /* - * Delete the marked value + * Delete all of the values and insert + * the new set */ - if (thisValue) - FcConfigDel (&st[i].elt->values, thisValue); + FcConfigPatternDel (p, r->u.edit->object); + FcConfigPatternAdd (p, r->u.edit->object, l, FcTrue); /* - * Adjust any pointers into the value list to ensure - * future edits occur at the same place + * Adjust a pointer into the value list as they no + * longer point to anything valid */ - for (t = s->test, i = 0; t; t = t->next, i++) + value = NULL; + break; + case FcOpPrepend: + if (value) { - if (st[i].value == thisValue) - st[i].value = nextValue; + FcConfigAdd (&elt->values, value, FcFalse, l, r->u.edit->object); + break; } + /* fall through ... */ + case FcOpPrependFirst: + FcConfigPatternAdd (p, r->u.edit->object, l, FcFalse); break; - } - /* fall through ... */ - case FcOpAssignReplace: - /* - * Delete all of the values and insert - * the new set - */ - FcConfigPatternDel (p, e->object); - FcConfigPatternAdd (p, e->object, l, FcTrue); - /* - * Adjust any pointers into the value list as they no - * longer point to anything valid - */ - if (t) - { - FcPatternElt *thisElt = st[i].elt; - for (t = s->test, i = 0; t; t = t->next, i++) + case FcOpAppend: + if (value) { - if (st[i].elt == thisElt) - st[i].value = 0; + FcConfigAdd (&elt->values, value, FcTrue, l, r->u.edit->object); + break; } - } - break; - case FcOpPrepend: - if (t) - { - FcConfigAdd (&st[i].elt->values, st[i].value, FcFalse, l, e->object); + /* fall through ... */ + case FcOpAppendLast: + FcConfigPatternAdd (p, r->u.edit->object, l, FcTrue); break; - } - /* fall through ... */ - case FcOpPrependFirst: - FcConfigPatternAdd (p, e->object, l, FcFalse); - break; - case FcOpAppend: - if (t) - { - FcConfigAdd (&st[i].elt->values, st[i].value, FcTrue, l, e->object); + case FcOpDelete: + if (value) + { + FcConfigDel (&elt->values, value); + break; + } + /* fall through ... */ + case FcOpDeleteAll: + FcConfigPatternDel (p, r->u.edit->object); + break; + default: + FcValueListDestroy (l); break; } - /* fall through ... */ - case FcOpAppendLast: - FcConfigPatternAdd (p, e->object, l, FcTrue); - break; - case FcOpDelete: - if (t) + /* + * Now go through the pattern and eliminate + * any properties without data + */ + FcConfigPatternCanon (p, r->u.edit->object); + + if (FcDebug () & FC_DBG_EDIT) { - FcConfigDel (&st[i].elt->values, st[i].value); - break; + printf ("FcConfigSubstitute edit"); + FcPatternPrint (p); } - /* fall through ... */ - case FcOpDeleteAll: - FcConfigPatternDel (p, e->object); - break; - default: - FcValueListDestroy (l); break; } } - /* - * Now go through the pattern and eliminate - * any properties without data - */ - for (e = s->edit; e; e = e->next) - FcConfigPatternCanon (p, e->object); - - if (FcDebug () & FC_DBG_EDIT) - { - printf ("FcConfigSubstitute edit"); - FcPatternPrint (p); - } + bail:; } - free (st); if (FcDebug () & FC_DBG_EDIT) { printf ("FcConfigSubstitute done"); diff --git a/fontconfig/src/fcdbg.c b/fontconfig/src/fcdbg.c index ce642140c..d74bc2769 100644 --- a/fontconfig/src/fcdbg.c +++ b/fontconfig/src/fcdbg.c @@ -427,21 +427,38 @@ FcEditPrint (const FcEdit *edit) void FcSubstPrint (const FcSubst *subst) { - FcEdit *e; - FcTest *t; + FcRule *r; + FcRuleType last_type = FcRuleUnknown; printf ("match\n"); - for (t = subst->test; t; t = t->next) - { - printf ("\t"); - FcTestPrint (t); - } - printf ("edit\n"); - for (e = subst->edit; e; e = e->next) + for (r = subst->rule; r; r = r->next) { + if (last_type != r->type) + { + switch (r->type) { + case FcRuleTest: + printf ("[test]\n"); + break; + case FcRuleEdit: + printf ("[edit]\n"); + break; + default: + break; + } + last_type = r->type; + } printf ("\t"); - FcEditPrint (e); - printf (";\n"); + switch (r->type) { + case FcRuleTest: + FcTestPrint (r->u.test); + break; + case FcRuleEdit: + FcEditPrint (r->u.edit); + printf (";\n"); + break; + default: + break; + } } printf ("\n"); } diff --git a/fontconfig/src/fcint.h b/fontconfig/src/fcint.h index 0137deeb4..fe523fb7c 100644 --- a/fontconfig/src/fcint.h +++ b/fontconfig/src/fcint.h @@ -37,6 +37,7 @@ #include <ctype.h> #include <assert.h> #include <errno.h> +#include <limits.h> #include <unistd.h> #include <stddef.h> #include <sys/types.h> @@ -85,7 +86,7 @@ extern pfnSHGetFolderPathA pSHGetFolderPathA; #define FC_DBG_CONFIG 1024 #define FC_DBG_LANGSET 2048 -#define _FC_ASSERT_STATIC1(_line, _cond) typedef int _static_assert_on_line_##_line##_failed[(_cond)?1:-1] +#define _FC_ASSERT_STATIC1(_line, _cond) typedef int _static_assert_on_line_##_line##_failed[(_cond)?1:-1] FC_UNUSED #define _FC_ASSERT_STATIC0(_line, _cond) _FC_ASSERT_STATIC1 (_line, (_cond)) #define FC_ASSERT_STATIC(_cond) _FC_ASSERT_STATIC0 (__LINE__, (_cond)) @@ -109,7 +110,7 @@ FC_ASSERT_STATIC (sizeof (FcRef) == sizeof (int)); typedef enum _FcValueBinding { FcValueBindingWeak, FcValueBindingStrong, FcValueBindingSame, /* to make sure sizeof (FcValueBinding) == 4 even with -fshort-enums */ - FcValueBindingEnd = 0xffffffff + FcValueBindingEnd = INT_MAX } FcValueBinding; #define FcStrdup(s) ((FcChar8 *) strdup ((const char *) (s))) @@ -273,7 +274,6 @@ typedef enum _FcQual { #define FcMatchDefault ((FcMatchKind) -1) typedef struct _FcTest { - struct _FcTest *next; FcMatchKind kind; FcQual qual; FcObject object; @@ -282,17 +282,28 @@ typedef struct _FcTest { } FcTest; typedef struct _FcEdit { - struct _FcEdit *next; FcObject object; FcOp op; FcExpr *expr; FcValueBinding binding; } FcEdit; +typedef enum _FcRuleType { + FcRuleUnknown, FcRuleTest, FcRuleEdit +} FcRuleType; + +typedef struct _FcRule { + struct _FcRule *next; + FcRuleType type; + union { + FcTest *test; + FcEdit *edit; + } u; +} FcRule; + typedef struct _FcSubst { struct _FcSubst *next; - FcTest *test; - FcEdit *edit; + FcRule *rule; } FcSubst; typedef struct _FcCharLeaf { @@ -612,10 +623,9 @@ FcPrivate FcBool FcConfigAddBlank (FcConfig *config, FcChar32 blank); -FcPrivate FcBool -FcConfigAddEdit (FcConfig *config, - FcTest *test, - FcEdit *edit, +FcBool +FcConfigAddRule (FcConfig *config, + FcRule *rule, FcMatchKind kind); FcPrivate void @@ -842,6 +852,9 @@ FcTestDestroy (FcTest *test); FcPrivate void FcEditDestroy (FcEdit *e); +void +FcRuleDestroy (FcRule *rule); + /* fclang.c */ FcPrivate FcLangSet * FcFreeTypeLangSet (const FcCharSet *charset, diff --git a/fontconfig/src/fcxml.c b/fontconfig/src/fcxml.c index 7e0323064..61dc6300b 100644 --- a/fontconfig/src/fcxml.c +++ b/fontconfig/src/fcxml.c @@ -62,12 +62,28 @@ FcExprDestroy (FcExpr *e); void FcTestDestroy (FcTest *test) { - if (test->next) - FcTestDestroy (test->next); FcExprDestroy (test->expr); free (test); } +void +FcRuleDestroy (FcRule *rule) +{ + if (rule->next) + FcRuleDestroy (rule->next); + switch (rule->type) { + case FcRuleTest: + FcTestDestroy (rule->u.test); + break; + case FcRuleEdit: + FcEditDestroy (rule->u.edit); + break; + default: + break; + } + free (rule); +} + static FcExpr * FcExprCreateInteger (FcConfig *config, int i) { @@ -300,8 +316,6 @@ FcExprDestroy (FcExpr *e) void FcEditDestroy (FcEdit *e) { - if (e->next) - FcEditDestroy (e->next); if (e->expr) FcExprDestroy (e->expr); free (e); @@ -714,7 +728,6 @@ FcTestCreate (FcConfigParse *parse, { const FcObjectType *o; - test->next = 0; test->kind = kind; test->qual = qual; test->object = FcObjectFromName ((const char *) field); @@ -740,7 +753,6 @@ FcEditCreate (FcConfigParse *parse, { const FcObjectType *o; - e->next = 0; e->object = object; e->op = op; e->expr = expr; @@ -752,6 +764,34 @@ FcEditCreate (FcConfigParse *parse, return e; } +static FcRule * +FcRuleCreate (FcRuleType type, + void *p) +{ + FcRule *r = (FcRule *) malloc (sizeof (FcRule)); + + if (!r) + return NULL; + + r->next = NULL; + r->type = type; + switch (type) + { + case FcRuleTest: + r->u.test = (FcTest *) p; + break; + case FcRuleEdit: + r->u.edit = (FcEdit *) p; + break; + default: + free (r); + r = NULL; + break; + } + + return r; +} + static FcVStack * FcVStackCreateAndPush (FcConfigParse *parse) { @@ -1657,9 +1697,9 @@ static void FcParseAlias (FcConfigParse *parse) { FcExpr *family = 0, *accept = 0, *prefer = 0, *def = 0, *new = 0; - FcEdit *edit = 0, *next; + FcEdit *edit = 0; FcVStack *vstack; - FcTest *test = NULL; + FcRule *rule = NULL, *r; FcValueBinding binding; if (!FcConfigLexBinding (parse, FcConfigGetAttribute (parse, "binding"), &binding)) @@ -1704,8 +1744,14 @@ FcParseAlias (FcConfigParse *parse) vstack->tag = FcVStackNone; break; case FcVStackTest: - vstack->u.test->next = test; - test = vstack->u.test; + if (rule) + { + r = FcRuleCreate (FcRuleTest, vstack->u.test); + r->next = rule; + rule = r; + } + else + rule = FcRuleCreate (FcRuleTest, vstack->u.test); vstack->tag = FcVStackNone; break; default: @@ -1723,8 +1769,35 @@ FcParseAlias (FcConfigParse *parse) FcExprDestroy (accept); if (def) FcExprDestroy (def); + if (rule) + FcRuleDestroy (rule); return; } + if (!prefer && + !accept && + !def) + { + FcExprDestroy (family); + return; + } + else + { + FcTest *t = FcTestCreate (parse, FcMatchPattern, + FcQualAny, + (FcChar8 *) FC_FAMILY, + FC_OP (FcOpEqual, FcOpFlagIgnoreBlanks), + family); + if (rule) + { + for (r = rule; r->next; r = r->next); + r->next = FcRuleCreate (FcRuleTest, t); + r = r->next; + } + else + { + r = rule = FcRuleCreate (FcRuleTest, t); + } + } if (prefer) { edit = FcEditCreate (parse, @@ -1732,60 +1805,46 @@ FcParseAlias (FcConfigParse *parse) FcOpPrepend, prefer, binding); - if (edit) - edit->next = 0; - else + if (!edit) FcExprDestroy (prefer); + else + { + r->next = FcRuleCreate (FcRuleEdit, edit); + r = r->next; + } } if (accept) { - next = edit; edit = FcEditCreate (parse, FC_FAMILY_OBJECT, FcOpAppend, accept, binding); - if (edit) - edit->next = next; - else + if (!edit) FcExprDestroy (accept); + else + { + r->next = FcRuleCreate (FcRuleEdit, edit); + r = r->next; + } } if (def) { - next = edit; edit = FcEditCreate (parse, FC_FAMILY_OBJECT, FcOpAppendLast, def, binding); - if (edit) - edit->next = next; - else + if (!edit) FcExprDestroy (def); - } - if (edit) - { - FcTest *t = FcTestCreate (parse, FcMatchPattern, - FcQualAny, - (FcChar8 *) FC_FAMILY, - FC_OP (FcOpEqual, FcOpFlagIgnoreBlanks), - family); - if (test) + else { - FcTest *p = test; - - while (p->next) - p = p->next; - p->next = t; + r->next = FcRuleCreate (FcRuleEdit, edit); + r = r->next; } - else - test = t; - if (test) - if (!FcConfigAddEdit (parse->config, test, edit, FcMatchPattern)) - FcTestDestroy (test); } - else - FcExprDestroy (family); + if (!FcConfigAddRule (parse->config, rule, FcMatchPattern)) + FcRuleDestroy (rule); } static FcExpr * @@ -2386,22 +2445,14 @@ FcParseEdit (FcConfigParse *parse) FcEditDestroy (edit); } -typedef struct FcSubstStack { - FcTest *test; - FcEdit *edit; -} FcSubstStack; - static void FcParseMatch (FcConfigParse *parse) { const FcChar8 *kind_name; FcMatchKind kind; - FcTest *test = 0; FcEdit *edit = 0; FcVStack *vstack; - FcBool tested = FcFalse; - FcSubstStack *sstack = NULL; - int len, pos = 0; + FcRule *rule = NULL, *r; kind_name = FcConfigGetAttribute (parse, "target"); if (!kind_name) @@ -2420,48 +2471,29 @@ FcParseMatch (FcConfigParse *parse) return; } } - len = FcVStackElements(parse); - if (len > 0) - { - sstack = malloc (sizeof (FcSubstStack) * (len + 1)); - if (!sstack) - { - FcConfigMessage (parse, FcSevereError, "out of memory"); - return; - } - } while ((vstack = FcVStackPeek (parse))) { switch ((int) vstack->tag) { case FcVStackTest: - vstack->u.test->next = test; - test = vstack->u.test; + r = FcRuleCreate (FcRuleTest, vstack->u.test); + if (rule) + r->next = rule; + rule = r; vstack->tag = FcVStackNone; - tested = FcTrue; break; case FcVStackEdit: - /* due to the reverse traversal, <edit> node appears faster than - * <test> node if any. so we have to deal with it here rather than - * the above in FcVStackTest, and put recipes in reverse order. - */ - if (tested) - { - sstack[pos].test = test; - sstack[pos].edit = edit; - pos++; - test = NULL; - edit = NULL; - tested = FcFalse; - } - vstack->u.edit->next = edit; - edit = vstack->u.edit; - vstack->tag = FcVStackNone; - if (kind == FcMatchScan && edit->object > FC_MAX_BASE_OBJECT) + if (kind == FcMatchScan && vstack->u.edit->object > FC_MAX_BASE_OBJECT) { FcConfigMessage (parse, FcSevereError, "<match target=\"scan\"> cannot edit user-defined object \"%s\"", FcObjectName(edit->object)); + break; } + r = FcRuleCreate (FcRuleEdit, vstack->u.edit); + if (rule) + r->next = rule; + rule = r; + vstack->tag = FcVStackNone; break; default: FcConfigMessage (parse, FcSevereWarning, "invalid match element"); @@ -2469,22 +2501,8 @@ FcParseMatch (FcConfigParse *parse) } FcVStackPopAndDestroy (parse); } - if (!FcConfigAddEdit (parse->config, test, edit, kind)) + if (!FcConfigAddRule (parse->config, rule, kind)) FcConfigMessage (parse, FcSevereError, "out of memory"); - if (sstack) - { - int i; - - for (i = 0; i < pos; i++) - { - if (!FcConfigAddEdit (parse->config, sstack[pos - i - 1].test, sstack[pos - i - 1].edit, kind)) - { - FcConfigMessage (parse, FcSevereError, "out of memory"); - return; - } - } - free (sstack); - } } static void diff --git a/libxcb/tests/Makefile.am b/libxcb/tests/Makefile.am index 077681e51..20bdc7217 100644 --- a/libxcb/tests/Makefile.am +++ b/libxcb/tests/Makefile.am @@ -12,9 +12,6 @@ TESTS = check_all check_PROGRAMS = check_all check_all_SOURCES = check_all.c check_suites.h check_public.c -all-local:: - $(RM) CheckLog*.xml - check-local: check-TESTS $(RM) CheckLog.html if test x$(HTML_CHECK_RESULT) = xtrue; then \ diff --git a/libxcb/xcb-proto/src/sync.xml b/libxcb/xcb-proto/src/sync.xml index 516d149ab..8a5194752 100644 --- a/libxcb/xcb-proto/src/sync.xml +++ b/libxcb/xcb-proto/src/sync.xml @@ -134,16 +134,66 @@ for licensing information. <request name="CreateAlarm" opcode="8"> <field type="ALARM" name="id" /> - <valueparam value-mask-type="CARD32" - value-mask-name="value_mask" - value-list-name="value_list" /> + <field type="CARD32" name="value_mask" mask="CA" /> + <switch name="value_list"> + <fieldref>value_mask</fieldref> + <bitcase> + <enumref ref="CA">Counter</enumref> + <field type="COUNTER" name="counter" /> + </bitcase> + <bitcase> + <enumref ref="CA">ValueType</enumref> + <field type="CARD32" name="valueType" mask="VALUETYPE" /> + </bitcase> + <bitcase> + <enumref ref="CA">Value</enumref> + <field type="INT64" name="value" /> + </bitcase> + <bitcase> + <enumref ref="CA">TestType</enumref> + <field type="CARD32" name="testType" mask="TESTTYPE" /> + </bitcase> + <bitcase> + <enumref ref="CA">Delta</enumref> + <field type="INT64" name="delta" /> + </bitcase> + <bitcase> + <enumref ref="CA">Events</enumref> + <field type="CARD32" name="events" /> + </bitcase> + </switch> </request> <request name="ChangeAlarm" opcode="9"> <field type="ALARM" name="id" /> - <valueparam value-mask-type="CARD32" - value-mask-name="value_mask" - value-list-name="value_list" /> + <field type="CARD32" name="value_mask" mask="CA" /> + <switch name="value_list"> + <fieldref>value_mask</fieldref> + <bitcase> + <enumref ref="CA">Counter</enumref> + <field type="COUNTER" name="counter" /> + </bitcase> + <bitcase> + <enumref ref="CA">ValueType</enumref> + <field type="CARD32" name="valueType" mask="VALUETYPE" /> + </bitcase> + <bitcase> + <enumref ref="CA">Value</enumref> + <field type="INT64" name="value" /> + </bitcase> + <bitcase> + <enumref ref="CA">TestType</enumref> + <field type="CARD32" name="testType" mask="TESTTYPE" /> + </bitcase> + <bitcase> + <enumref ref="CA">Delta</enumref> + <field type="INT64" name="delta" /> + </bitcase> + <bitcase> + <enumref ref="CA">Events</enumref> + <field type="CARD32" name="events" /> + </bitcase> + </switch> </request> <request name="DestroyAlarm" opcode="11"> diff --git a/mesalib/configure.ac b/mesalib/configure.ac index 6832b0d89..3a0cd7791 100644 --- a/mesalib/configure.ac +++ b/mesalib/configure.ac @@ -1490,6 +1490,13 @@ AC_SUBST([EGL_NATIVE_PLATFORM]) AC_SUBST([EGL_PLATFORMS]) AC_SUBST([EGL_CFLAGS]) +# If we don't have the X11 platform, set this define so we don't try to include +# the X11 headers. +if ! echo "$egl_platforms" | grep -q 'x11'; then + DEFINES="$DEFINES -DMESA_EGL_NO_X11_HEADERS" + GL_PC_CFLAGS="$GL_PC_CFLAGS -DMESA_EGL_NO_X11_HEADERS" +fi + AC_ARG_WITH([egl-driver-dir], [AS_HELP_STRING([--with-egl-driver-dir=DIR], [directory for EGL drivers [[default=${libdir}/egl]]])], diff --git a/mesalib/docs/index.html b/mesalib/docs/index.html index be095820c..d85081d50 100644 --- a/mesalib/docs/index.html +++ b/mesalib/docs/index.html @@ -16,6 +16,12 @@ <h1>News</h1> +<h2>July 1, 2013</h2> +<p> +<a href="relnotes/9.1.4.html">Mesa 9.1.4</a> is released. +This is a bug fix release. +</p> + <h2>May 21, 2013</h2> <p> <a href="relnotes/9.1.3.html">Mesa 9.1.3</a> is released. diff --git a/mesalib/docs/relnotes.html b/mesalib/docs/relnotes.html index 04eea158a..bc5ad3c20 100644 --- a/mesalib/docs/relnotes.html +++ b/mesalib/docs/relnotes.html @@ -22,6 +22,7 @@ The release notes summarize what's new or changed in each Mesa release. <ul> <li><a href="relnotes/9.2.html">9.2 release notes</a> +<li><a href="relnotes/9.1.4.html">9.1.4 release notes</a> <li><a href="relnotes/9.1.3.html">9.1.3 release notes</a> <li><a href="relnotes/9.1.2.html">9.1.2 release notes</a> <li><a href="relnotes/9.1.1.html">9.1.1 release notes</a> diff --git a/mesalib/docs/relnotes/9.1.4.html b/mesalib/docs/relnotes/9.1.4.html new file mode 100644 index 000000000..f3e45eace --- /dev/null +++ b/mesalib/docs/relnotes/9.1.4.html @@ -0,0 +1,321 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> +<html lang="en"> +<head> + <meta http-equiv="content-type" content="text/html; charset=utf-8"> + <title>Mesa Release Notes</title> + <link rel="stylesheet" type="text/css" href="../mesa.css"> +</head> +<body> + +<div class="header"> + <h1>The Mesa 3D Graphics Library</h1> +</div> + +<iframe src="../contents.html"></iframe> +<div class="content"> + +<h1>Mesa 9.1.4 Release Notes / July 1st, 2013</h1> + +<p> +Mesa 9.1.4 is a bug fix release which fixes bugs found since the 9.1.3 release. +</p> +<p> +Mesa 9.1 implements the OpenGL 3.1 API, but the version reported by +glGetString(GL_VERSION) or glGetIntegerv(GL_MAJOR_VERSION) / +glGetIntegerv(GL_MINOR_VERSION) depends on the particular driver being used. +Some drivers don't support all the features required in OpenGL 3.1. OpenGL +3.1 is <strong>only</strong> available if requested at context creation +because GL_ARB_compatibility is not supported. +</p> + +<h2>MD5 checksums</h2> +<pre> +a2c4e25d0e27918bc67f61bae04d0cb8 MesaLib-9.1.4.tar.bz2 +8c7e9ce5b05cb2223f0587396dd9dc08 MesaLib-9.1.4.tar.gz +020459c5793d4279bdcb2daa1f7dd9f6 MesaLib-9.1.4.zip +</pre> + +<h2>New features</h2> +<p>None.</p> + +<h2>Bug fixes</h2> + +<p>This list is likely incomplete.</p> + +<ul> + +<li><a href="https://bugs.freedesktop.org/show_bug.cgi?id=37871">Bug 37871</a> - [bisected i965] Bus error (core dumped) on oglc texdecaltile</li> + +<li><a href="https://bugs.freedesktop.org/show_bug.cgi?id=42182">Bug 42182</a> - egl/opengles1/tri_x11 renders wrong</li> + +<li><a href="https://bugs.freedesktop.org/show_bug.cgi?id=44958">Bug 44958</a> - [SNB IVB HSW] mesa demo test texleak bus error</li> + +<li><a href="https://bugs.freedesktop.org/show_bug.cgi?id=53494">Bug 53494</a> - [snb] crash in texsubimage to a large atlas in clutter</li> + +<li><a href="https://bugs.freedesktop.org/show_bug.cgi?id=60518">Bug 60518</a> - glDrawElements segfault when compiled into display list</li> + +<li><a href="https://bugs.freedesktop.org/show_bug.cgi?id=61821">Bug 61821</a> - src/mesa/drivers/dri/common/xmlpool.h:96:29: fatal error: xmlpool/options.h</li> + +<li><a href="https://bugs.freedesktop.org/show_bug.cgi?id=63520">Bug 63520</a> - r300g regression (RV380): Strange rendering of light sources in Penumbra (bisected)</li> + +<li><a href="https://bugs.freedesktop.org/show_bug.cgi?id=63701">Bug 63701</a> - [HSW] support new haswell graphics [8086:0a2e]</li> + +<li><a href="https://bugs.freedesktop.org/show_bug.cgi?id=64727">Bug 64727</a> - [gm45, bisected] some piglit glsl 1.10 built-in-functions tests crash</li> + +<li><a href="https://bugs.freedesktop.org/show_bug.cgi?id=64745">Bug 64745</a> - [llvmpipe] SIGSEGV src/gallium/state_trackers/glx/xlib/glx_api.c:1374</li> + +<li><a href="https://bugs.freedesktop.org/show_bug.cgi?id=64934">Bug 64934</a> - [llvmpipe] SIGSEGV src/gallium/state_trackers/glx/xlib/glx_api.c:1363</li> + +<li><a href="https://bugs.freedesktop.org/show_bug.cgi?id=65173">Bug 65173</a> - segfault in _mesa_get_format_datatype and _mesa_get_color_read_type when state dumping with glretrace</li> + +</ul> + +<h2>Changes</h2> +<p>The full set of changes can be viewed by using the following GIT command:</p> + +<pre> + git log mesa-9.1.3..mesa-9.1.4 +</pre> + +<p>Alan Coopersmith (2):</p> +<ul> + <li>integer overflow in XF86DRIOpenConnection() [CVE-2013-1993 1/2]</li> + <li>integer overflow in XF86DRIGetClientDriverName() [CVE-2013-1993 2/2]</li> +</ul> + +<p>Alex Deucher (3):</p> +<ul> + <li>radeonsi: add support for hainan chips</li> + <li>radeonsi: add Hainan pci ids</li> + <li>winsys/radeon: add env var to disable VM on Cayman/Trinity</li> +</ul> +pp +<p>Andreas Boll (1):</p> +<ul> + <li>glapi: Add some missing static_dispatch="false" annotations to es_EXT.xml</li> +</ul> + +<p>Anuj Phogat (1):</p> +<ul> + <li>intel: Add a null pointer check before dereferencing the pointer</li> +</ul> + +<p>Armin K (1):</p> +<ul> + <li>gallivm: Fix build with LLVM 3.3</li> +</ul> + +<p>Brian Paul (9):</p> +<ul> + <li>mesa: fix the compressed TexSubImage size checking code</li> + <li>st/mesa: generate GL_OUT_OF_MEMORY if we can't create the index buffer</li> + <li>mesa: fix error checking of DXT sRGB formats in _mesa_base_tex_format()</li> + <li>st/glx/xlib: check for null ctx pointer in glXIsDirect()</li> + <li>xlib: check for null ctx pointer in glXIsDirect()</li> + <li>st/glx: add null ctx check in glXDestroyContext()</li> + <li>xlib: add null ctx check in glXDestroyContext()</li> + <li>meta: move vertex array enables for mipmap generation</li> + <li>mesa: handle missing read buffer in _mesa_get_color_read_format/type()</li> +</ul> + +<p>Bryan Cain (1):</p> +<ul> + <li>nv50: initialize kick_notify callback in nv50_create</li> +</ul> + +<p>Chad Versace (3):</p> +<ul> + <li>egl/android: Fix error condition for EGL_ANDROID_image_native_buffer</li> + <li>i965: Fix glColorPointer(GL_FIXED)</li> + <li>intel: Return early if miptree allocation fails</li> +</ul> + +<p>Chia-I Wu (1):</p> +<ul> + <li>u_vbuf: fix index buffer leak</li> +</ul> + +<p>Chris Forbes (8):</p> +<ul> + <li>mesa: add accessor for effective stencil ref</li> + <li>intel: Use accessor for stencil reference values</li> + <li>nouveau: Use accessor for stencil reference values</li> + <li>radeon: Use accessor for stencil reference values</li> + <li>st: Use accessor for stencil reference values</li> + <li>swrast: Use accessor for stencil reference values</li> + <li>mesa: Stop clamping stencil reference value at specification time</li> + <li>mesa: Use accessor for stencil reference values in glGet</li> +</ul> + +<p>Chí-Thanh Christopher Nguyễn (1):</p> +<ul> + <li>targets/dri-i915: Force c++ linker in all cases</li> +</ul> + +<p>Daniel Martin (1):</p> +<ul> + <li>Fix build of swrast only without libdrm</li> +</ul> + +<p>Dave Airlie (1):</p> +<ul> + <li>i965: fix problem with constant out of bounds access (v3)</li> +</ul> + +<p>Eric Anholt (10):</p> +<ul> + <li>mesa: Make core Mesa allocate the texture renderbuffer wrapper.</li> + <li>mesa: Make gl_renderbuffers backed by EGL images use FinishRenderTexture.</li> + <li>i965/fs: Bake regs_written into the IR instead of recomputing it later.</li> + <li>i965/vs: Fix implied_mrf_writes() for integer division pre-gen6.</li> + <li>intel: Add support for writing to our linear-temporary-CPU-map case.</li> + <li>intel: Do temporary CPU maps of textures that are too big to GTT map.</li> + <li>intel: Avoid making tiled miptrees we won't be able to blit.</li> + <li>intel: Fix MRT handling of glBitmap().</li> + <li>intel: Fix format handling of blit glBitmap()</li> + <li>i965: Shut up the last release build warning.</li> +</ul> + +<p>Fabian Bieler (2):</p> +<ul> + <li>mesa/st: Don't copy propagate from swizzles.</li> + <li>mesa/program: Don't copy propagate from swizzles.</li> +</ul> + +<p>Frank Henigman (1):</p> +<ul> + <li>intel: initialize fs_visitor::params_remap in constructor</li> +</ul> + +<p>Ian Romanick (2):</p> +<ul> + <li>docs: Add 9.1.3 release md5sums</li> + <li>mesa: Bump version to 9.1.4</li> +</ul> + +<p>José Fonseca (1):</p> +<ul> + <li>scons: Fix implicit python dependency discovery on Windows.</li> +</ul> + +<p>Kenneth Graunke (17):</p> +<ul> + <li>mesa: Add i965 varying index patches to .cherry-ignore.</li> + <li>i965: Turn brw->urb.vs_size and gs_size into local variables.</li> + <li>i965: Use a variable for the push constant size in kB.</li> + <li>i965: Update URB partitioning code for Haswell's GT3 variant.</li> + <li>i965: Add chipset limits for the Haswell GT3 variant.</li> + <li>i965: Enable the Bay Trail platform.</li> + <li>mesa: Add a reverted commit to cherry-ignore.</li> + <li>vbo: Ignore PRIMITIVE_RESTART_FIXED_INDEX for glDrawArrays().</li> + <li>mesa: Add a helper function for determining the restart index.</li> + <li>vbo: Use the new primitive restart index helper function.</li> + <li>i965: Use the correct restart index for fixed index mode on Haswell.</li> + <li>mesa: Cherry-ignore a patch that got picked but squashed.</li> + <li>i965: Fix can_cut_index_handle_restart_index() for byte/short types.</li> + <li>st/mesa: Go back to using ctx->Array.RestartIndex, not _RestartIndex.</li> + <li>mesa: Ignore fixed-index primitive restart in ArrayElement().</li> + <li>mesa: Delete the ctx->Array._RestartIndex derived state.</li> + <li>glsl: Bail on parsing if the #version directive is bogus.</li> +</ul> + +<p>Lauri Kasanen (1):</p> +<ul> + <li>r600g: Correctly initialize the shader key, v2</li> +</ul> + +<p>Maarten Lankhorst (4):</p> +<ul> + <li>nvc0: fix up video buffer alignment requirements</li> + <li>nvc0: kill assert in ppp code</li> + <li>nvc0: set rsvd_kick correctly</li> + <li>nvc0: allow frame dropping in h264</li> +</ul> + +<p>Marek Olšák (7):</p> +<ul> + <li>radeonsi: increase array size for shader inputs and outputs</li> + <li>vbo: fix possible use-after-free segfault after a VAO is deleted</li> + <li>glsl: fix the value of gl_MaxFragmentUniformVectors</li> + <li>st/mesa: initialize all program constants and UBO limits</li> + <li>st/mesa: initialize Const.MaxColorAttachments</li> + <li>st/mesa: fix a couple of issues in st_bind_ubos</li> + <li>mesa: declare UniformBufferBindings as an array with a static size</li> +</ul> + +<p>Matt Turner (3):</p> +<ul> + <li>configure.ac: Remove redundant checks of enable_dri.</li> + <li>configure.ac: Build dricommon for DRI gallium drivers</li> + <li>i965: NULL check depth_mt to quiet static analysis.</li> +</ul> + +<p>Michel Dänzer (3):</p> +<ul> + <li>radeonsi: Fix handling of TGSI_SEMANTIC_PSIZE</li> + <li>radeonsi: Fix user clip planes</li> + <li>mesa: Note that two radeonsi fixes cannot be backported after all</li> +</ul> + +<p>Mike Stroyan (1):</p> +<ul> + <li>configure.ac: Build dricommon for gallium swrast</li> +</ul> + +<p>Naohiro Aota (1):</p> +<ul> + <li>xmlpool/build: Make sure to set mo properly</li> +</ul> + +<p>Paul Berry (2):</p> +<ul> + <li>glsl: Fix error checking on "flat" keyword to match GLSL ES 3.00, GLSL 1.50.</li> + <li>i965/gen7.5: Allow HW primitive restart for all primitive types.</li> +</ul> + +<p>Paulo Zanoni (1):</p> +<ul> + <li>i965: make GT3 machines work as GT3 instead of GT2</li> +</ul> + +<p>Rodrigo Vivi (2):</p> +<ul> + <li>i965: Add missing Haswell GT3 Desktop to IS_HSW_GT3 check.</li> + <li>i965: Adding more reserved PCI IDs for Haswell.</li> +</ul> + +<p>Roland Scheidegger (1):</p> +<ul> + <li>gallivm: fix out-of-bounds access with mirror_clamp_to_edge address mode</li> +</ul> + +<p>Stéphane Marchesin (2):</p> +<ul> + <li>st/xlib: Fix upside down coordinates for CopySubBuffer</li> + <li>st/xlib: Flush the front buffer before doing CopySubBuffer</li> +</ul> + +<p>Sven Joachim (1):</p> +<ul> + <li>mesa: Fix ieee fp on Alpha</li> +</ul> + +<p>Tapani Pälli (1):</p> +<ul> + <li>mesa: fix type comparison errors in sub-texture error checking code</li> +</ul> + +<p>Tom Stellard (2):</p> +<ul> + <li>gallivm: Fix build with LLVM >= r180063</li> + <li>r300g/compiler: Prevent regalloc from swizzling texture operands v2</li> +</ul> + +<p>Vinson Lee (1):</p> +<ul> + <li>radeon: Initialize variables in radeon_llvm_context_init.</li> +</ul> + +</div> +</body> +</html> diff --git a/mesalib/docs/relnotes/9.2.html b/mesalib/docs/relnotes/9.2.html index 1f4919114..680950687 100644 --- a/mesalib/docs/relnotes/9.2.html +++ b/mesalib/docs/relnotes/9.2.html @@ -68,6 +68,9 @@ Note: some of the new features are only available with certain drivers. 2007.</li> <li>Removed GL_MESA_resize_buffers because it was only really implemented by the (unsupported) GDI driver.</li> +<li>GL_EXT_separate_shader_objects has been removed from all Gallium drivers, + because it disallows a critical GLSL shader optimization. + GL_ARB_separate_shader_objects doesn't have this issue. </ul> </div> diff --git a/mesalib/include/EGL/eglplatform.h b/mesalib/include/EGL/eglplatform.h index 17fdc6114..21b18fe73 100644 --- a/mesalib/include/EGL/eglplatform.h +++ b/mesalib/include/EGL/eglplatform.h @@ -109,8 +109,8 @@ typedef void *EGLNativeDisplayType; #ifdef MESA_EGL_NO_X11_HEADERS typedef void *EGLNativeDisplayType; -typedef khronos_uint32_t EGLNativePixmapType; -typedef khronos_uint32_t EGLNativeWindowType; +typedef khronos_uintptr_t EGLNativePixmapType; +typedef khronos_uintptr_t EGLNativeWindowType; #else diff --git a/mesalib/src/gallium/auxiliary/Makefile.sources b/mesalib/src/gallium/auxiliary/Makefile.sources index 20ff5ba73..47517626d 100644 --- a/mesalib/src/gallium/auxiliary/Makefile.sources +++ b/mesalib/src/gallium/auxiliary/Makefile.sources @@ -163,6 +163,7 @@ GENERATED_SOURCES := \ GALLIVM_SOURCES := \ gallivm/lp_bld_arit.c \ + gallivm/lp_bld_arit_overflow.c \ gallivm/lp_bld_assert.c \ gallivm/lp_bld_bitarit.c \ gallivm/lp_bld_const.c \ diff --git a/mesalib/src/gallium/auxiliary/util/u_vbuf.c b/mesalib/src/gallium/auxiliary/util/u_vbuf.c index 5936f74a0..52b360ed7 100644 --- a/mesalib/src/gallium/auxiliary/util/u_vbuf.c +++ b/mesalib/src/gallium/auxiliary/util/u_vbuf.c @@ -403,13 +403,13 @@ u_vbuf_translate_buffers(struct u_vbuf *mgr, struct translate_key *key, switch (ib->index_size) { case 4: - tr->run_elts(tr, (unsigned*)map, num_indices, 0, out_map); + tr->run_elts(tr, (unsigned*)map, num_indices, 0, 0, out_map); break; case 2: - tr->run_elts16(tr, (uint16_t*)map, num_indices, 0, out_map); + tr->run_elts16(tr, (uint16_t*)map, num_indices, 0, 0, out_map); break; case 1: - tr->run_elts8(tr, map, num_indices, 0, out_map); + tr->run_elts8(tr, map, num_indices, 0, 0, out_map); break; } @@ -428,7 +428,7 @@ u_vbuf_translate_buffers(struct u_vbuf *mgr, struct translate_key *key, out_offset -= key->output_stride * start_vertex; - tr->run(tr, 0, num_vertices, 0, out_map); + tr->run(tr, 0, num_vertices, 0, 0, out_map); } /* Unmap all buffers. */ diff --git a/mesalib/src/glsl/Makefile.sources b/mesalib/src/glsl/Makefile.sources index acd19d1ff..979c4165f 100644 --- a/mesalib/src/glsl/Makefile.sources +++ b/mesalib/src/glsl/Makefile.sources @@ -82,6 +82,7 @@ LIBGLSL_FILES = \ $(GLSL_SRCDIR)/opt_constant_variable.cpp \ $(GLSL_SRCDIR)/opt_copy_propagation.cpp \ $(GLSL_SRCDIR)/opt_copy_propagation_elements.cpp \ + $(GLSL_SRCDIR)/opt_dead_builtin_varyings.cpp \ $(GLSL_SRCDIR)/opt_dead_code.cpp \ $(GLSL_SRCDIR)/opt_dead_code_local.cpp \ $(GLSL_SRCDIR)/opt_dead_functions.cpp \ diff --git a/mesalib/src/glsl/ir_optimization.h b/mesalib/src/glsl/ir_optimization.h index d38d5e303..fad6f1bfe 100644 --- a/mesalib/src/glsl/ir_optimization.h +++ b/mesalib/src/glsl/ir_optimization.h @@ -76,6 +76,10 @@ bool do_constant_variable_unlinked(exec_list *instructions); bool do_copy_propagation(exec_list *instructions); bool do_copy_propagation_elements(exec_list *instructions); bool do_constant_propagation(exec_list *instructions); +void do_dead_builtin_varyings(struct gl_context *ctx, + exec_list *producer, exec_list *consumer, + unsigned num_tfeedback_decls, + class tfeedback_decl *tfeedback_decls); bool do_dead_code(exec_list *instructions, bool uniform_locations_assigned); bool do_dead_code_local(exec_list *instructions); bool do_dead_code_unlinked(exec_list *instructions); diff --git a/mesalib/src/glsl/link_varyings.cpp b/mesalib/src/glsl/link_varyings.cpp index 4fdbdc199..51cbdaa0e 100644 --- a/mesalib/src/glsl/link_varyings.cpp +++ b/mesalib/src/glsl/link_varyings.cpp @@ -1113,16 +1113,12 @@ assign_varying_locations(struct gl_context *ctx, } } - unsigned varying_vectors = 0; - if (consumer) { foreach_list(node, consumer->ir) { ir_variable *const var = ((ir_instruction *) node)->as_variable(); - if ((var == NULL) || (var->mode != ir_var_shader_in)) - continue; - - if (var->is_unmatched_generic_inout) { + if (var && var->mode == ir_var_shader_in && + var->is_unmatched_generic_inout) { if (prog->Version <= 120) { /* On page 25 (page 31 of the PDF) of the GLSL 1.20 spec: * @@ -1148,45 +1144,46 @@ assign_varying_locations(struct gl_context *ctx, * value is written by the previous stage. */ var->mode = ir_var_auto; - } else if (is_varying_var(consumer->Type, var)) { - /* The packing rules are used for vertex shader inputs are also - * used for fragment shader inputs. - */ - varying_vectors += count_attribute_slots(var->type); } } } + return true; +} + +bool +check_against_varying_limit(struct gl_context *ctx, + struct gl_shader_program *prog, + gl_shader *consumer) +{ + unsigned varying_vectors = 0; + + foreach_list(node, consumer->ir) { + ir_variable *const var = ((ir_instruction *) node)->as_variable(); + + if (var && var->mode == ir_var_shader_in && + is_varying_var(consumer->Type, var)) { + /* The packing rules used for vertex shader inputs are also + * used for fragment shader inputs. + */ + varying_vectors += count_attribute_slots(var->type); + } + } + if (ctx->API == API_OPENGLES2 || prog->IsES) { if (varying_vectors > ctx->Const.MaxVarying) { - if (ctx->Const.GLSLSkipStrictMaxVaryingLimitCheck) { - linker_warning(prog, "shader uses too many varying vectors " - "(%u > %u), but the driver will try to optimize " - "them out; this is non-portable out-of-spec " - "behavior\n", - varying_vectors, ctx->Const.MaxVarying); - } else { - linker_error(prog, "shader uses too many varying vectors " - "(%u > %u)\n", - varying_vectors, ctx->Const.MaxVarying); - return false; - } + linker_error(prog, "shader uses too many varying vectors " + "(%u > %u)\n", + varying_vectors, ctx->Const.MaxVarying); + return false; } } else { const unsigned float_components = varying_vectors * 4; if (float_components > ctx->Const.MaxVarying * 4) { - if (ctx->Const.GLSLSkipStrictMaxVaryingLimitCheck) { - linker_warning(prog, "shader uses too many varying components " - "(%u > %u), but the driver will try to optimize " - "them out; this is non-portable out-of-spec " - "behavior\n", - float_components, ctx->Const.MaxVarying * 4); - } else { - linker_error(prog, "shader uses too many varying components " - "(%u > %u)\n", - float_components, ctx->Const.MaxVarying * 4); - return false; - } + linker_error(prog, "shader uses too many varying components " + "(%u > %u)\n", + float_components, ctx->Const.MaxVarying * 4); + return false; } } diff --git a/mesalib/src/glsl/link_varyings.h b/mesalib/src/glsl/link_varyings.h index ee1010a7b..7f7be353b 100644 --- a/mesalib/src/glsl/link_varyings.h +++ b/mesalib/src/glsl/link_varyings.h @@ -125,6 +125,10 @@ public: return this->vector_elements * this->matrix_columns * this->size; } + unsigned get_location() const { + return this->location; + } + private: /** * The name that was supplied to glTransformFeedbackVaryings. Used for @@ -232,4 +236,9 @@ assign_varying_locations(struct gl_context *ctx, unsigned num_tfeedback_decls, tfeedback_decl *tfeedback_decls); +bool +check_against_varying_limit(struct gl_context *ctx, + struct gl_shader_program *prog, + gl_shader *consumer); + #endif /* GLSL_LINK_VARYINGS_H */ diff --git a/mesalib/src/glsl/linker.cpp b/mesalib/src/glsl/linker.cpp index c168e47e0..ba97ade25 100644 --- a/mesalib/src/glsl/linker.cpp +++ b/mesalib/src/glsl/linker.cpp @@ -1514,31 +1514,31 @@ static bool check_resources(struct gl_context *ctx, struct gl_shader_program *prog) { static const char *const shader_names[MESA_SHADER_TYPES] = { - "vertex", "fragment", "geometry" + "vertex", "geometry", "fragment" }; const unsigned max_samplers[MESA_SHADER_TYPES] = { ctx->Const.VertexProgram.MaxTextureImageUnits, - ctx->Const.FragmentProgram.MaxTextureImageUnits, - ctx->Const.GeometryProgram.MaxTextureImageUnits + ctx->Const.GeometryProgram.MaxTextureImageUnits, + ctx->Const.FragmentProgram.MaxTextureImageUnits }; const unsigned max_default_uniform_components[MESA_SHADER_TYPES] = { ctx->Const.VertexProgram.MaxUniformComponents, - ctx->Const.FragmentProgram.MaxUniformComponents, - ctx->Const.GeometryProgram.MaxUniformComponents + ctx->Const.GeometryProgram.MaxUniformComponents, + ctx->Const.FragmentProgram.MaxUniformComponents }; const unsigned max_combined_uniform_components[MESA_SHADER_TYPES] = { ctx->Const.VertexProgram.MaxCombinedUniformComponents, - ctx->Const.FragmentProgram.MaxCombinedUniformComponents, - ctx->Const.GeometryProgram.MaxCombinedUniformComponents + ctx->Const.GeometryProgram.MaxCombinedUniformComponents, + ctx->Const.FragmentProgram.MaxCombinedUniformComponents }; const unsigned max_uniform_blocks[MESA_SHADER_TYPES] = { ctx->Const.VertexProgram.MaxUniformBlocks, - ctx->Const.FragmentProgram.MaxUniformBlocks, ctx->Const.GeometryProgram.MaxUniformBlocks, + ctx->Const.FragmentProgram.MaxUniformBlocks }; for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) { @@ -1836,9 +1836,9 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) goto done; } - unsigned prev; - for (prev = 0; prev < MESA_SHADER_TYPES; prev++) { - if (prog->_LinkedShaders[prev] != NULL) + unsigned first; + for (first = 0; first < MESA_SHADER_TYPES; first++) { + if (prog->_LinkedShaders[first] != NULL) break; } @@ -1850,7 +1850,7 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) * non-zero, but the program object has no vertex or geometry * shader; */ - if (prev >= MESA_SHADER_FRAGMENT) { + if (first >= MESA_SHADER_FRAGMENT) { linker_error(prog, "Transform feedback varyings specified, but " "no vertex or geometry shader is present."); goto done; @@ -1864,69 +1864,90 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) goto done; } - for (unsigned i = prev + 1; i < MESA_SHADER_TYPES; i++) { - if (prog->_LinkedShaders[i] == NULL) - continue; - - if (!assign_varying_locations( - ctx, mem_ctx, prog, prog->_LinkedShaders[prev], prog->_LinkedShaders[i], - i == MESA_SHADER_FRAGMENT ? num_tfeedback_decls : 0, - tfeedback_decls)) - goto done; - - prev = i; + /* Linking the stages in the opposite order (from fragment to vertex) + * ensures that inter-shader outputs written to in an earlier stage are + * eliminated if they are (transitively) not used in a later stage. + */ + int last, next; + for (last = MESA_SHADER_TYPES-1; last >= 0; last--) { + if (prog->_LinkedShaders[last] != NULL) + break; } - if (prev != MESA_SHADER_FRAGMENT && num_tfeedback_decls != 0) { - /* There was no fragment shader, but we still have to assign varying - * locations for use by transform feedback. - */ - if (!assign_varying_locations( - ctx, mem_ctx, prog, prog->_LinkedShaders[prev], NULL, num_tfeedback_decls, - tfeedback_decls)) - goto done; - } + if (last >= 0 && last < MESA_SHADER_FRAGMENT) { + gl_shader *const sh = prog->_LinkedShaders[last]; - if (!store_tfeedback_info(ctx, prog, num_tfeedback_decls, tfeedback_decls)) - goto done; + if (num_tfeedback_decls != 0) { + /* There was no fragment shader, but we still have to assign varying + * locations for use by transform feedback. + */ + if (!assign_varying_locations(ctx, mem_ctx, prog, + sh, NULL, + num_tfeedback_decls, tfeedback_decls)) + goto done; + } - if (prog->_LinkedShaders[MESA_SHADER_VERTEX] != NULL) { - demote_shader_inputs_and_outputs(prog->_LinkedShaders[MESA_SHADER_VERTEX], - ir_var_shader_out); + do_dead_builtin_varyings(ctx, sh->ir, NULL, + num_tfeedback_decls, tfeedback_decls); - /* Eliminate code that is now dead due to unused vertex outputs being - * demoted. + demote_shader_inputs_and_outputs(sh, ir_var_shader_out); + + /* Eliminate code that is now dead due to unused outputs being demoted. */ - while (do_dead_code(prog->_LinkedShaders[MESA_SHADER_VERTEX]->ir, false)) - ; + while (do_dead_code(sh->ir, false)) + ; } + else if (first == MESA_SHADER_FRAGMENT) { + /* If the program only contains a fragment shader... + */ + gl_shader *const sh = prog->_LinkedShaders[first]; - if (prog->_LinkedShaders[MESA_SHADER_GEOMETRY] != NULL) { - gl_shader *const sh = prog->_LinkedShaders[MESA_SHADER_GEOMETRY]; + do_dead_builtin_varyings(ctx, NULL, sh->ir, + num_tfeedback_decls, tfeedback_decls); demote_shader_inputs_and_outputs(sh, ir_var_shader_in); - demote_shader_inputs_and_outputs(sh, ir_var_shader_out); - /* Eliminate code that is now dead due to unused geometry outputs being - * demoted. - */ - while (do_dead_code(prog->_LinkedShaders[MESA_SHADER_GEOMETRY]->ir, false)) - ; + while (do_dead_code(sh->ir, false)) + ; } - if (prog->_LinkedShaders[MESA_SHADER_FRAGMENT] != NULL) { - gl_shader *const sh = prog->_LinkedShaders[MESA_SHADER_FRAGMENT]; + next = last; + for (int i = next - 1; i >= 0; i--) { + if (prog->_LinkedShaders[i] == NULL) + continue; - demote_shader_inputs_and_outputs(sh, ir_var_shader_in); + gl_shader *const sh_i = prog->_LinkedShaders[i]; + gl_shader *const sh_next = prog->_LinkedShaders[next]; + + if (!assign_varying_locations(ctx, mem_ctx, prog, sh_i, sh_next, + next == MESA_SHADER_FRAGMENT ? num_tfeedback_decls : 0, + tfeedback_decls)) + goto done; - /* Eliminate code that is now dead due to unused fragment inputs being - * demoted. This shouldn't actually do anything other than remove - * declarations of the (now unused) global variables. + do_dead_builtin_varyings(ctx, sh_i->ir, sh_next->ir, + next == MESA_SHADER_FRAGMENT ? num_tfeedback_decls : 0, + tfeedback_decls); + + demote_shader_inputs_and_outputs(sh_i, ir_var_shader_out); + demote_shader_inputs_and_outputs(sh_next, ir_var_shader_in); + + /* Eliminate code that is now dead due to unused outputs being demoted. */ - while (do_dead_code(prog->_LinkedShaders[MESA_SHADER_FRAGMENT]->ir, false)) - ; + while (do_dead_code(sh_i->ir, false)) + ; + while (do_dead_code(sh_next->ir, false)) + ; + + /* This must be done after all dead varyings are eliminated. */ + if (!check_against_varying_limit(ctx, prog, sh_next)) + goto done; + + next = i; } + if (!store_tfeedback_info(ctx, prog, num_tfeedback_decls, tfeedback_decls)) + goto done; + update_array_sizes(prog); link_assign_uniform_locations(prog); store_fragdepth_layout(prog); diff --git a/mesalib/src/glsl/opt_dead_builtin_varyings.cpp b/mesalib/src/glsl/opt_dead_builtin_varyings.cpp new file mode 100644 index 000000000..2e813d24e --- /dev/null +++ b/mesalib/src/glsl/opt_dead_builtin_varyings.cpp @@ -0,0 +1,477 @@ +/* + * Copyright © 2013 Marek Olšák <maraeo@gmail.com> + * + * 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. + */ + +/** + * \file opt_dead_builtin_varyings.cpp + * + * This eliminates the built-in shader outputs which are either not written + * at all or not used by the next stage. It also eliminates unused elements + * of gl_TexCoord inputs, which reduces the overall varying usage. + * The varyings handled here are the primary and secondary color, the fog, + * and the texture coordinates (gl_TexCoord). + * + * This pass is necessary, because the Mesa GLSL linker cannot eliminate + * built-in varyings like it eliminates user-defined varyings, because + * the built-in varyings have pre-assigned locations. Also, the elimination + * of unused gl_TexCoord elements requires its own lowering pass anyway. + * + * It's implemented by replacing all occurences of dead varyings with + * temporary variables, which creates dead code. It is recommended to run + * a dead-code elimination pass after this. + * + * If any texture coordinate slots can be eliminated, the gl_TexCoord array is + * broken down into separate vec4 variables with locations equal to + * VARYING_SLOT_TEX0 + i. + */ + +#include "main/imports.h" /* for snprintf */ +#include "ir.h" +#include "ir_rvalue_visitor.h" +#include "ir_optimization.h" +#include "ir_print_visitor.h" +#include "glsl_types.h" +#include "link_varyings.h" + + +/** + * This obtains detailed information about built-in varyings from shader code. + */ +class varying_info_visitor : public ir_hierarchical_visitor { +public: + /* "mode" can be either ir_var_shader_in or ir_var_shader_out */ + varying_info_visitor(ir_variable_mode mode) + : lower_texcoord_array(true), + texcoord_array(NULL), + texcoord_usage(0), + color_usage(0), + tfeedback_color_usage(0), + fog(NULL), + has_fog(false), + tfeedback_has_fog(false), + mode(mode) + { + memset(color, 0, sizeof(color)); + memset(backcolor, 0, sizeof(backcolor)); + } + + virtual ir_visitor_status visit_enter(ir_dereference_array *ir) + { + ir_variable *var = ir->variable_referenced(); + + if (var && var->mode == this->mode && + var->location == VARYING_SLOT_TEX0) { + this->texcoord_array = var; + + ir_constant *index = ir->array_index->as_constant(); + if (index == NULL) { + /* There is variable indexing, we can't lower the texcoord array. + */ + this->texcoord_usage |= (1 << var->type->array_size()) - 1; + this->lower_texcoord_array = false; + } + else { + this->texcoord_usage |= 1 << index->get_uint_component(0); + } + + /* Don't visit the leaves of ir_dereference_array. */ + return visit_continue_with_parent; + } + + return visit_continue; + } + + virtual ir_visitor_status visit(ir_dereference_variable *ir) + { + ir_variable *var = ir->variable_referenced(); + + if (var->mode == this->mode && var->type->is_array() && + var->location == VARYING_SLOT_TEX0) { + /* This is a whole array dereference like "gl_TexCoord = x;", + * there's probably no point in lowering that. + */ + this->texcoord_usage |= (1 << var->type->array_size()) - 1; + this->lower_texcoord_array = false; + } + return visit_continue; + } + + virtual ir_visitor_status visit(ir_variable *var) + { + if (var->mode != this->mode) + return visit_continue; + + /* Handle colors and fog. */ + switch (var->location) { + case VARYING_SLOT_COL0: + this->color[0] = var; + this->color_usage |= 1; + break; + case VARYING_SLOT_COL1: + this->color[1] = var; + this->color_usage |= 2; + break; + case VARYING_SLOT_BFC0: + this->backcolor[0] = var; + this->color_usage |= 1; + break; + case VARYING_SLOT_BFC1: + this->backcolor[1] = var; + this->color_usage |= 2; + break; + case VARYING_SLOT_FOGC: + this->fog = var; + this->has_fog = true; + break; + } + + return visit_continue; + } + + void get(exec_list *ir, + unsigned num_tfeedback_decls, + tfeedback_decl *tfeedback_decls) + { + /* Handle the transform feedback varyings. */ + for (unsigned i = 0; i < num_tfeedback_decls; i++) { + if (!tfeedback_decls[i].is_varying()) + continue; + + unsigned location = tfeedback_decls[i].get_location(); + + switch (location) { + case VARYING_SLOT_COL0: + case VARYING_SLOT_BFC0: + this->tfeedback_color_usage |= 1; + break; + case VARYING_SLOT_COL1: + case VARYING_SLOT_BFC1: + this->tfeedback_color_usage |= 2; + break; + case VARYING_SLOT_FOGC: + this->tfeedback_has_fog = true; + break; + default: + if (location >= VARYING_SLOT_TEX0 && + location <= VARYING_SLOT_TEX7) { + this->lower_texcoord_array = false; + } + } + } + + /* Process the shader. */ + visit_list_elements(this, ir); + + if (!this->texcoord_array) { + this->lower_texcoord_array = false; + } + } + + bool lower_texcoord_array; + ir_variable *texcoord_array; + unsigned texcoord_usage; /* bitmask */ + + ir_variable *color[2]; + ir_variable *backcolor[2]; + unsigned color_usage; /* bitmask */ + unsigned tfeedback_color_usage; /* bitmask */ + + ir_variable *fog; + bool has_fog; + bool tfeedback_has_fog; + + ir_variable_mode mode; +}; + + +/** + * This replaces unused varyings with temporary variables. + * + * If "ir" is the producer, the "external" usage should come from + * the consumer. It also works the other way around. If either one is + * missing, set the "external" usage to a full mask. + */ +class replace_varyings_visitor : public ir_rvalue_visitor { +public: + replace_varyings_visitor(exec_list *ir, + const varying_info_visitor *info, + unsigned external_texcoord_usage, + unsigned external_color_usage, + bool external_has_fog) + : info(info), new_fog(NULL) + { + void *const ctx = ir; + + memset(this->new_texcoord, 0, sizeof(this->new_texcoord)); + memset(this->new_color, 0, sizeof(this->new_color)); + memset(this->new_backcolor, 0, sizeof(this->new_backcolor)); + + const char *mode_str = + info->mode == ir_var_shader_in ? "in" : "out"; + + /* Handle texcoord outputs. + * + * We're going to break down the gl_TexCoord array into separate + * variables. First, add declarations of the new variables all + * occurences of gl_TexCoord will be replaced with. + */ + if (info->lower_texcoord_array) { + for (int i = MAX_TEXTURE_COORD_UNITS-1; i >= 0; i--) { + if (info->texcoord_usage & (1 << i)) { + char name[32]; + + if (!(external_texcoord_usage & (1 << i))) { + /* This varying is unused in the next stage. Declare + * a temporary instead of an output. */ + snprintf(name, 32, "gl_%s_TexCoord%i_dummy", mode_str, i); + this->new_texcoord[i] = + new (ctx) ir_variable(glsl_type::vec4_type, name, + ir_var_temporary); + } + else { + snprintf(name, 32, "gl_%s_TexCoord%i", mode_str, i); + this->new_texcoord[i] = + new(ctx) ir_variable(glsl_type::vec4_type, name, + info->mode); + this->new_texcoord[i]->location = VARYING_SLOT_TEX0 + i; + this->new_texcoord[i]->explicit_location = true; + this->new_texcoord[i]->explicit_index = 0; + } + + ir->head->insert_before(new_texcoord[i]); + } + } + } + + /* Create dummy variables which will replace set-but-unused color and + * fog outputs. + */ + external_color_usage |= info->tfeedback_color_usage; + + for (int i = 0; i < 2; i++) { + char name[32]; + + if (!(external_color_usage & (1 << i))) { + if (info->color[i]) { + snprintf(name, 32, "gl_%s_FrontColor%i_dummy", mode_str, i); + this->new_color[i] = + new (ctx) ir_variable(glsl_type::vec4_type, name, + ir_var_temporary); + } + + if (info->backcolor[i]) { + snprintf(name, 32, "gl_%s_BackColor%i_dummy", mode_str, i); + this->new_backcolor[i] = + new (ctx) ir_variable(glsl_type::vec4_type, name, + ir_var_temporary); + } + } + } + + if (!external_has_fog && !info->tfeedback_has_fog && + info->fog) { + char name[32]; + + snprintf(name, 32, "gl_%s_FogFragCoord_dummy", mode_str); + this->new_fog = new (ctx) ir_variable(glsl_type::float_type, name, + ir_var_temporary); + } + + /* Now do the replacing. */ + visit_list_elements(this, ir); + } + + virtual ir_visitor_status visit(ir_variable *var) + { + /* Remove the gl_TexCoord array. */ + if (this->info->lower_texcoord_array && + var == this->info->texcoord_array) { + var->remove(); + } + + /* Replace set-but-unused color and fog outputs with dummy variables. */ + for (int i = 0; i < 2; i++) { + if (var == this->info->color[i] && this->new_color[i]) { + var->replace_with(this->new_color[i]); + } + if (var == this->info->backcolor[i] && + this->new_backcolor[i]) { + var->replace_with(this->new_backcolor[i]); + } + } + + if (var == this->info->fog && this->new_fog) { + var->replace_with(this->new_fog); + } + + return visit_continue; + } + + virtual void handle_rvalue(ir_rvalue **rvalue) + { + if (!*rvalue) + return; + + void *ctx = ralloc_parent(*rvalue); + + /* Replace an array dereference gl_TexCoord[i] with a single + * variable dereference representing gl_TexCoord[i]. + */ + if (this->info->lower_texcoord_array) { + /* gl_TexCoord[i] occurence */ + ir_dereference_array *const da = (*rvalue)->as_dereference_array(); + + if (da && da->variable_referenced() == + this->info->texcoord_array) { + unsigned i = da->array_index->as_constant()->get_uint_component(0); + + *rvalue = new(ctx) ir_dereference_variable(this->new_texcoord[i]); + return; + } + } + + /* Replace set-but-unused color and fog outputs with dummy variables. */ + ir_dereference_variable *const dv = (*rvalue)->as_dereference_variable(); + if (!dv) + return; + + ir_variable *var = dv->variable_referenced(); + + for (int i = 0; i < 2; i++) { + if (var == this->info->color[i] && this->new_color[i]) { + *rvalue = new(ctx) ir_dereference_variable(this->new_color[i]); + return; + } + if (var == this->info->backcolor[i] && + this->new_backcolor[i]) { + *rvalue = new(ctx) ir_dereference_variable(this->new_backcolor[i]); + return; + } + } + + if (var == this->info->fog && this->new_fog) { + *rvalue = new(ctx) ir_dereference_variable(this->new_fog); + } + } + + virtual ir_visitor_status visit_leave(ir_assignment *ir) + { + handle_rvalue(&ir->rhs); + handle_rvalue(&ir->condition); + + /* We have to use set_lhs when changing the LHS of an assignment. */ + ir_rvalue *lhs = ir->lhs; + + handle_rvalue(&lhs); + if (lhs != ir->lhs) { + ir->set_lhs(lhs); + } + + return visit_continue; + } + +private: + const varying_info_visitor *info; + struct ir_variable *new_texcoord[MAX_TEXTURE_COORD_UNITS]; + struct ir_variable *new_color[2]; + struct ir_variable *new_backcolor[2]; + struct ir_variable *new_fog; +}; + + +static void +lower_texcoord_array(exec_list *ir, const varying_info_visitor *info) +{ + replace_varyings_visitor(ir, info, + (1 << MAX_TEXTURE_COORD_UNITS) - 1, + 1 | 2, true); +} + + +void +do_dead_builtin_varyings(struct gl_context *ctx, + exec_list *producer, exec_list *consumer, + unsigned num_tfeedback_decls, + tfeedback_decl *tfeedback_decls) +{ + /* This optimization has no effect with the core context and GLES2, because + * the built-in varyings we're eliminating here are not available there. + * + * EXT_separate_shader_objects doesn't allow this optimization, + * because a program object can be bound partially (e.g. only one + * stage of a program object can be bound). + */ + if (ctx->API == API_OPENGL_CORE || + ctx->API == API_OPENGLES2 || + ctx->Extensions.EXT_separate_shader_objects) { + return; + } + + /* Information about built-in varyings. */ + varying_info_visitor producer_info(ir_var_shader_out); + varying_info_visitor consumer_info(ir_var_shader_in); + + if (producer) { + producer_info.get(producer, num_tfeedback_decls, tfeedback_decls); + + if (!consumer) { + /* At least eliminate unused gl_TexCoord elements. */ + if (producer_info.lower_texcoord_array) { + lower_texcoord_array(producer, &producer_info); + } + return; + } + } + + if (consumer) { + consumer_info.get(consumer, 0, NULL); + + if (!producer) { + /* At least eliminate unused gl_TexCoord elements. */ + if (consumer_info.lower_texcoord_array) { + lower_texcoord_array(consumer, &consumer_info); + } + return; + } + } + + /* Eliminate the varyings unused by the other shader. */ + if (producer_info.lower_texcoord_array || + producer_info.color_usage || + producer_info.has_fog) { + replace_varyings_visitor(producer, + &producer_info, + consumer_info.texcoord_usage, + consumer_info.color_usage, + consumer_info.has_fog); + } + + if (consumer_info.lower_texcoord_array || + consumer_info.color_usage || + consumer_info.has_fog) { + replace_varyings_visitor(consumer, + &consumer_info, + producer_info.texcoord_usage, + producer_info.color_usage, + producer_info.has_fog); + } +} diff --git a/mesalib/src/mapi/glapi/gen/SConscript b/mesalib/src/mapi/glapi/gen/SConscript index 18158ff8b..e4abe906a 100644 --- a/mesalib/src/mapi/glapi/gen/SConscript +++ b/mesalib/src/mapi/glapi/gen/SConscript @@ -44,6 +44,20 @@ env.CodeGenerate( env.CodeGenerate( target = '../../../mesa/main/remap_helper.h', script = 'remap_helper.py', - source = 'gl_and_es_API.xml', + source = sources, + command = python_cmd + ' $SCRIPT -f $SOURCE > $TARGET' + ) + +env.CodeGenerate( + target = '../../../mesa/main/enums.c', + script = 'gl_enums.py', + source = sources, + command = python_cmd + ' $SCRIPT -f $SOURCE > $TARGET' + ) + +env.CodeGenerate( + target = '../../../mesa/main/api_exec.c', + script = 'gl_genexec.py', + source = sources, command = python_cmd + ' $SCRIPT -f $SOURCE > $TARGET' ) diff --git a/mesalib/src/mesa/SConscript b/mesalib/src/mesa/SConscript index 0f1543802..d328fc13c 100644 --- a/mesalib/src/mesa/SConscript +++ b/mesalib/src/mesa/SConscript @@ -417,23 +417,6 @@ if (env['gcc'] or env['clang']) and \ env.Append(CPPPATH = [matypes[0].dir]) -# The enums.c file is generated from the GL/ES API.xml file -env.CodeGenerate( - target = 'main/enums.c', - script = GLAPI + 'gen/gl_enums.py', - source = GLAPI + 'gen/gl_and_es_API.xml', - command = python_cmd + ' $SCRIPT -f $SOURCE > $TARGET' - ) - -# The api_exec.c file is generated from the GL/ES API.xml file -env.CodeGenerate( - target = 'main/api_exec.c', - script = GLAPI + 'gen/gl_genexec.py', - source = GLAPI + 'gen/gl_and_es_API.xml', - command = python_cmd + ' $SCRIPT -f $SOURCE > $TARGET' - ) - - def write_git_sha1_h_file(filename): """Mesa looks for a git_sha1.h file at compile time in order to display the current git hash id in the GL_VERSION string. This function tries diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h index 1f62e2c9c..2f7cce7ba 100644 --- a/mesalib/src/mesa/main/mtypes.h +++ b/mesalib/src/mesa/main/mtypes.h @@ -2173,13 +2173,16 @@ struct gl_shader /** * Shader stages. Note that these will become 5 with tessellation. - * These MUST have the same values as gallium's PIPE_SHADER_* + * + * The order must match how shaders are ordered in the pipeline. + * The GLSL linker assumes that if i<j, then the j-th shader is + * executed later than the i-th shader. */ typedef enum { MESA_SHADER_VERTEX = 0, - MESA_SHADER_FRAGMENT = 1, - MESA_SHADER_GEOMETRY = 2, + MESA_SHADER_GEOMETRY = 1, + MESA_SHADER_FRAGMENT = 2, MESA_SHADER_TYPES = 3 } gl_shader_type; @@ -2922,12 +2925,11 @@ struct gl_constants GLboolean StripTextureBorder; /** - * For drivers which can do a better job at eliminating unused varyings - * and uniforms than the GLSL compiler. + * For drivers which can do a better job at eliminating unused uniforms + * than the GLSL compiler. * * XXX Remove these as soon as a better solution is available. */ - GLboolean GLSLSkipStrictMaxVaryingLimitCheck; GLboolean GLSLSkipStrictMaxUniformLimitCheck; /** diff --git a/mesalib/src/mesa/main/shaderobj.h b/mesalib/src/mesa/main/shaderobj.h index 5ce85cfde..de1c9fcaf 100644 --- a/mesalib/src/mesa/main/shaderobj.h +++ b/mesalib/src/mesa/main/shaderobj.h @@ -123,8 +123,8 @@ _mesa_shader_index_to_type(GLuint i) { static const GLenum enums[MESA_SHADER_TYPES] = { GL_VERTEX_SHADER, - GL_FRAGMENT_SHADER, - GL_GEOMETRY_SHADER , + GL_GEOMETRY_SHADER, + GL_FRAGMENT_SHADER }; if (i >= MESA_SHADER_TYPES) return 0; diff --git a/mesalib/src/mesa/program/ir_to_mesa.cpp b/mesalib/src/mesa/program/ir_to_mesa.cpp index 35a9b8437..4af1c8241 100644 --- a/mesalib/src/mesa/program/ir_to_mesa.cpp +++ b/mesalib/src/mesa/program/ir_to_mesa.cpp @@ -3073,12 +3073,6 @@ _mesa_ir_link_shader(struct gl_context *ctx, struct gl_shader_program *prog) linked_prog = get_mesa_program(ctx, prog, prog->_LinkedShaders[i]); if (linked_prog) { - static const GLenum targets[] = { - GL_VERTEX_PROGRAM_ARB, - GL_FRAGMENT_PROGRAM_ARB, - GL_GEOMETRY_PROGRAM_NV - }; - if (i == MESA_SHADER_VERTEX) { ((struct gl_vertex_program *)linked_prog)->UsesClipDistance = prog->Vert.UsesClipDistance; @@ -3086,7 +3080,9 @@ _mesa_ir_link_shader(struct gl_context *ctx, struct gl_shader_program *prog) _mesa_reference_program(ctx, &prog->_LinkedShaders[i]->Program, linked_prog); - if (!ctx->Driver.ProgramStringNotify(ctx, targets[i], linked_prog)) { + if (!ctx->Driver.ProgramStringNotify(ctx, + _mesa_program_index_to_target(i), + linked_prog)) { return GL_FALSE; } } diff --git a/mesalib/src/mesa/program/program.h b/mesalib/src/mesa/program/program.h index ecda59b58..f28983894 100644 --- a/mesalib/src/mesa/program/program.h +++ b/mesalib/src/mesa/program/program.h @@ -205,8 +205,8 @@ _mesa_program_index_to_target(GLuint i) { static const GLenum enums[MESA_SHADER_TYPES] = { GL_VERTEX_PROGRAM_ARB, - GL_FRAGMENT_PROGRAM_ARB, GL_GEOMETRY_PROGRAM_NV, + GL_FRAGMENT_PROGRAM_ARB }; if(i >= MESA_SHADER_TYPES) return 0; diff --git a/mesalib/src/mesa/state_tracker/st_context.c b/mesalib/src/mesa/state_tracker/st_context.c index 7d18c2521..80393cff7 100644 --- a/mesalib/src/mesa/state_tracker/st_context.c +++ b/mesalib/src/mesa/state_tracker/st_context.c @@ -221,11 +221,6 @@ struct st_context *st_create_context(gl_api api, struct pipe_context *pipe, struct gl_context *shareCtx = share ? share->ctx : NULL; struct dd_function_table funcs; - /* Sanity checks */ - STATIC_ASSERT(MESA_SHADER_VERTEX == PIPE_SHADER_VERTEX); - STATIC_ASSERT(MESA_SHADER_FRAGMENT == PIPE_SHADER_FRAGMENT); - STATIC_ASSERT(MESA_SHADER_GEOMETRY == PIPE_SHADER_GEOMETRY); - memset(&funcs, 0, sizeof(funcs)); st_init_driver_functions(&funcs); diff --git a/mesalib/src/mesa/state_tracker/st_extensions.c b/mesalib/src/mesa/state_tracker/st_extensions.c index 83e8e2e96..32348ef73 100644 --- a/mesalib/src/mesa/state_tracker/st_extensions.c +++ b/mesalib/src/mesa/state_tracker/st_extensions.c @@ -68,7 +68,7 @@ void st_init_limits(struct st_context *st) { struct pipe_screen *screen = st->pipe->screen; struct gl_constants *c = &st->ctx->Const; - gl_shader_type sh; + unsigned sh; boolean can_ubo = TRUE; c->MaxTextureLevels @@ -149,23 +149,25 @@ void st_init_limits(struct st_context *st) can_ubo = FALSE; } - for (sh = 0; sh < MESA_SHADER_TYPES; ++sh) { - struct gl_shader_compiler_options *options = - &st->ctx->ShaderCompilerOptions[sh]; + for (sh = 0; sh < PIPE_SHADER_TYPES; ++sh) { + struct gl_shader_compiler_options *options; struct gl_program_constants *pc; switch (sh) { case PIPE_SHADER_FRAGMENT: pc = &c->FragmentProgram; + options = &st->ctx->ShaderCompilerOptions[MESA_SHADER_FRAGMENT]; break; case PIPE_SHADER_VERTEX: pc = &c->VertexProgram; + options = &st->ctx->ShaderCompilerOptions[MESA_SHADER_VERTEX]; break; case PIPE_SHADER_GEOMETRY: pc = &c->GeometryProgram; + options = &st->ctx->ShaderCompilerOptions[MESA_SHADER_GEOMETRY]; break; default: - assert(0); + /* compute shader, etc. */ continue; } @@ -274,9 +276,6 @@ void st_init_limits(struct st_context *st) c->GLSLSkipStrictMaxUniformLimitCheck = screen->get_param(screen, PIPE_CAP_TGSI_CAN_COMPACT_CONSTANTS); - c->GLSLSkipStrictMaxVaryingLimitCheck = - screen->get_param(screen, PIPE_CAP_TGSI_CAN_COMPACT_VARYINGS); - if (can_ubo) { st->ctx->Extensions.ARB_uniform_buffer_object = GL_TRUE; c->UniformBufferOffsetAlignment = @@ -552,7 +551,14 @@ void st_init_extensions(struct st_context *st) ctx->Extensions.EXT_pixel_buffer_object = GL_TRUE; ctx->Extensions.EXT_point_parameters = GL_TRUE; ctx->Extensions.EXT_provoking_vertex = GL_TRUE; - ctx->Extensions.EXT_separate_shader_objects = GL_TRUE; + + /* IMPORTANT: + * Don't enable EXT_separate_shader_objects. It disallows a certain + * optimization in the GLSL compiler and therefore is considered + * harmful. + */ + ctx->Extensions.EXT_separate_shader_objects = GL_FALSE; + ctx->Extensions.EXT_texture_env_dot3 = GL_TRUE; ctx->Extensions.EXT_vertex_array_bgra = GL_TRUE; diff --git a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp index 32bc2b37b..64e0a8a46 100644 --- a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp +++ b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp @@ -5271,15 +5271,11 @@ st_link_shader(struct gl_context *ctx, struct gl_shader_program *prog) linked_prog = get_mesa_program(ctx, prog, prog->_LinkedShaders[i]); if (linked_prog) { - static const GLenum targets[] = { - GL_VERTEX_PROGRAM_ARB, - GL_FRAGMENT_PROGRAM_ARB, - GL_GEOMETRY_PROGRAM_NV - }; - _mesa_reference_program(ctx, &prog->_LinkedShaders[i]->Program, linked_prog); - if (!ctx->Driver.ProgramStringNotify(ctx, targets[i], linked_prog)) { + if (!ctx->Driver.ProgramStringNotify(ctx, + _mesa_program_index_to_target(i), + linked_prog)) { _mesa_reference_program(ctx, &prog->_LinkedShaders[i]->Program, NULL); _mesa_reference_program(ctx, &linked_prog, NULL); diff --git a/sync.bat b/sync.bat index 4cdcf4fe0..4cdcf4fe0 100644..100755 --- a/sync.bat +++ b/sync.bat diff --git a/synchronise.py b/synchronise.py index 8951f1e85..8951f1e85 100644..100755 --- a/synchronise.py +++ b/synchronise.py diff --git a/updategit.bat b/updategit.bat index 91dfb584a..91dfb584a 100644..100755 --- a/updategit.bat +++ b/updategit.bat |