diff options
author | marha <marha@users.sourceforge.net> | 2013-08-19 09:07:37 +0200 |
---|---|---|
committer | marha <marha@users.sourceforge.net> | 2013-08-19 09:07:37 +0200 |
commit | 2d042f719910c5aa1ba9f4a47b21009c729c345e (patch) | |
tree | 2b20d89d5f1ca342ca6f1d817c18b324adf7086f | |
parent | c3d3ea464f7f4e53e8fe3e11ecada36cb209ba4d (diff) | |
parent | 854ec4da20ddff9b830be0a7d5b81d8cb4774132 (diff) | |
download | vcxsrv-2d042f719910c5aa1ba9f4a47b21009c729c345e.tar.gz vcxsrv-2d042f719910c5aa1ba9f4a47b21009c729c345e.tar.bz2 vcxsrv-2d042f719910c5aa1ba9f4a47b21009c729c345e.zip |
Merge remote-tracking branch 'origin/released'
* origin/released:
fontconfig libX11 libXdmcp libxcb xkeyboard-config mesa pixman xserver git update 19 aug 2013
Conflicts:
fontconfig/src/fccache.c
156 files changed, 3589 insertions, 634 deletions
diff --git a/fontconfig/src/fccache.c b/fontconfig/src/fccache.c index fab2c1f2c..e02d49e8f 100644 --- a/fontconfig/src/fccache.c +++ b/fontconfig/src/fccache.c @@ -830,34 +830,6 @@ bail1: return NULL; } - -#ifdef _WIN32 -#undef mkdir -#define mkdir(path,mode) _mkdir(path) -#endif - -static FcBool -FcMakeDirectory (const FcChar8 *dir) -{ - FcChar8 *parent; - FcBool ret; - - if (strlen ((char *) dir) == 0) - return FcFalse; - - parent = FcStrDirname (dir); - if (!parent) - return FcFalse; - if (access ((char *) parent, F_OK) == 0) - ret = mkdir ((char *) dir, 0755) == 0 && chmod ((char *) dir, 0755) == 0; - else if (access ((char *) parent, F_OK) == -1) - ret = FcMakeDirectory (parent) && (mkdir ((char *) dir, 0755) == 0) && chmod ((char *) dir, 0755) == 0; - else - ret = FcFalse; - FcStrFree (parent); - return ret; -} - /* write serialized state to the cache file */ FcBool FcDirCacheWrite (FcCache *cache, FcConfig *config) diff --git a/fontconfig/src/fccfg.c b/fontconfig/src/fccfg.c index 7ea94b846..be738d53d 100644 --- a/fontconfig/src/fccfg.c +++ b/fontconfig/src/fccfg.c @@ -674,12 +674,21 @@ FcConfigAddRule (FcConfig *config, num = 0; for (r = rule; r; r = r->next) { - if (r->type == FcRuleTest) + switch (r->type) { + case FcRuleTest: if (r->u.test && r->u.test->kind == FcMatchDefault) r->u.test->kind = kind; - num++; + if (r->u.test->object > FC_MAX_BASE_OBJECT) + num++; + break; + case FcRuleEdit: + if (r->u.edit->object > FC_MAX_BASE_OBJECT) + num++; + break; + default: + break; } } if (config->maxObjects < num) @@ -1486,11 +1495,15 @@ FcConfigSubstituteWithPat (FcConfig *config, FcValue v; FcSubst *s; FcRule *r; - FcValueList *l, *value = NULL; + FcValueList *l, **value = NULL; FcPattern *m; FcStrSet *strs; - FcPatternElt *elt = NULL; FcObject object = FC_INVALID_OBJECT; + FcPatternElt **elt = NULL; + int i, nobjs; + FcBool retval = FcTrue; + +#define FC_OBJ_ID(_n_) ((_n_) > FC_MAX_BASE_OBJECT ? ((_n_) - FC_EXT_OBJ_INDEX) : (_n_)) if (!config) { @@ -1535,6 +1548,20 @@ FcConfigSubstituteWithPat (FcConfig *config, return FcFalse; } + nobjs = FC_MAX_BASE_OBJECT + config->maxObjects + 2; + value = (FcValueList **) malloc (SIZEOF_VOID_P * nobjs); + if (!value) + { + retval = FcFalse; + goto bail1; + } + elt = (FcPatternElt **) malloc (SIZEOF_VOID_P * nobjs); + if (!elt) + { + retval = FcFalse; + goto bail1; + } + if (FcDebug () & FC_DBG_EDIT) { printf ("FcConfigSubstitute "); @@ -1543,6 +1570,11 @@ FcConfigSubstituteWithPat (FcConfig *config, for (; s; s = s->next) { r = s->rule; + for (i = 0; i < nobjs; i++) + { + elt[i] = NULL; + value[i] = NULL; + } for (; r; r = r->next) { switch (r->type) { @@ -1550,6 +1582,7 @@ FcConfigSubstituteWithPat (FcConfig *config, /* shouldn't be reached */ break; case FcRuleTest: + object = FC_OBJ_ID (r->u.test->object); /* * Check the tests to see if * they all match the pattern @@ -1564,18 +1597,16 @@ FcConfigSubstituteWithPat (FcConfig *config, else m = p; if (m) - elt = FcPatternObjectFindElt (m, r->u.test->object); - else - elt = NULL; + elt[object] = FcPatternObjectFindElt (m, r->u.test->object); /* * If there's no such field in the font, * then FcQualAll matches while FcQualAny does not */ - if (!elt) + if (!elt[object]) { if (r->u.test->qual == FcQualAll) { - value = NULL; + value[object] = NULL; continue; } else @@ -1589,18 +1620,18 @@ FcConfigSubstituteWithPat (FcConfig *config, * Check to see if there is a match, mark the location * to apply match-relative edits */ - 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)) + value[object] = FcConfigMatchValueList (m, p_pat, kind, r->u.test, elt[object]->values); + if (!value[object] || + (r->u.test->qual == FcQualFirst && value[object] != elt[object]->values) || + (r->u.test->qual == FcQualNotFirst && value[object] == elt[object]->values)) { if (FcDebug () & FC_DBG_EDIT) printf ("No match\n"); goto bail; } - object = r->u.test->object; break; case FcRuleEdit: + object = FC_OBJ_ID (r->u.edit->object); if (FcDebug () & FC_DBG_EDIT) { printf ("Substitute "); @@ -1611,13 +1642,6 @@ FcConfigSubstituteWithPat (FcConfig *config, * 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: @@ -1625,25 +1649,25 @@ FcConfigSubstituteWithPat (FcConfig *config, * If there was a test, then replace the matched * value with the new list of values */ - if (value) + if (value[object]) { - FcValueList *thisValue = value; - FcValueList *nextValue = thisValue; + FcValueList *thisValue = value[object]; + FcValueList *nextValue = l; /* * Append the new list of values after the current value */ - FcConfigAdd (&elt->values, thisValue, FcTrue, l, r->u.edit->object); + FcConfigAdd (&elt[object]->values, thisValue, FcTrue, l, r->u.edit->object); /* * Delete the marked value */ if (thisValue) - FcConfigDel (&elt->values, thisValue); + FcConfigDel (&elt[object]->values, thisValue); /* * Adjust a pointer into the value list to ensure * future edits occur at the same place */ - value = nextValue; + value[object] = nextValue; break; } /* fall through ... */ @@ -1658,12 +1682,12 @@ FcConfigSubstituteWithPat (FcConfig *config, * Adjust a pointer into the value list as they no * longer point to anything valid */ - value = NULL; + value[object] = NULL; break; case FcOpPrepend: - if (value) + if (value[object]) { - FcConfigAdd (&elt->values, value, FcFalse, l, r->u.edit->object); + FcConfigAdd (&elt[object]->values, value[object], FcFalse, l, r->u.edit->object); break; } /* fall through ... */ @@ -1671,9 +1695,9 @@ FcConfigSubstituteWithPat (FcConfig *config, FcConfigPatternAdd (p, r->u.edit->object, l, FcFalse); break; case FcOpAppend: - if (value) + if (value[object]) { - FcConfigAdd (&elt->values, value, FcTrue, l, r->u.edit->object); + FcConfigAdd (&elt[object]->values, value[object], FcTrue, l, r->u.edit->object); break; } /* fall through ... */ @@ -1681,9 +1705,9 @@ FcConfigSubstituteWithPat (FcConfig *config, FcConfigPatternAdd (p, r->u.edit->object, l, FcTrue); break; case FcOpDelete: - if (value) + if (value[object]) { - FcConfigDel (&elt->values, value); + FcConfigDel (&elt[object]->values, value[object]); break; } /* fall through ... */ @@ -1715,7 +1739,15 @@ FcConfigSubstituteWithPat (FcConfig *config, printf ("FcConfigSubstitute done"); FcPatternPrint (p); } - return FcTrue; +bail1: + if (elt) + free (elt); + if (value) + free (value); + +#undef FC_OBJ_ID + + return retval; } FcBool diff --git a/fontconfig/src/fccompat.c b/fontconfig/src/fccompat.c index a2171607c..d4f88c83f 100644 --- a/fontconfig/src/fccompat.c +++ b/fontconfig/src/fccompat.c @@ -219,3 +219,30 @@ FcRandom(void) return result; } + +#ifdef _WIN32 +#include <direct.h> +#define mkdir(path,mode) _mkdir(path) +#endif + +FcBool +FcMakeDirectory (const FcChar8 *dir) +{ + FcChar8 *parent; + FcBool ret; + + if (strlen ((char *) dir) == 0) + return FcFalse; + + parent = FcStrDirname (dir); + if (!parent) + return FcFalse; + if (access ((char *) parent, F_OK) == 0) + ret = mkdir ((char *) dir, 0755) == 0 && chmod ((char *) dir, 0755) == 0; + else if (access ((char *) parent, F_OK) == -1) + ret = FcMakeDirectory (parent) && (mkdir ((char *) dir, 0755) == 0) && chmod ((char *) dir, 0755) == 0; + else + ret = FcFalse; + FcStrFree (parent); + return ret; +} diff --git a/fontconfig/src/fcdir.c b/fontconfig/src/fcdir.c index dc580bb6f..b040a285a 100644 --- a/fontconfig/src/fcdir.c +++ b/fontconfig/src/fcdir.c @@ -49,6 +49,16 @@ FcFileIsLink (const FcChar8 *file) #endif } +FcBool +FcFileIsFile (const FcChar8 *file) +{ + struct stat statb; + + if (FcStat (file, &statb) != 0) + return FcFalse; + return S_ISREG (statb.st_mode); +} + static FcBool FcFileScanFontConfig (FcFontSet *set, FcBlanks *blanks, diff --git a/fontconfig/src/fcint.h b/fontconfig/src/fcint.h index fe523fb7c..ec0c67470 100644 --- a/fontconfig/src/fcint.h +++ b/fontconfig/src/fcint.h @@ -174,6 +174,11 @@ typedef struct _FcValueList { typedef int FcObject; +/* The 1000 is to leave some room for future added internal objects, such + * that caches from newer fontconfig can still be used with older fontconfig + * without getting confused. */ +#define FC_EXT_OBJ_INDEX 1000 + typedef struct _FcPatternElt *FcPatternEltPtr; /* @@ -742,6 +747,9 @@ FcMakeTempfile (char *template); FcPrivate int32_t FcRandom (void); +FcPrivate FcBool +FcMakeDirectory (const FcChar8 *dir); + /* fcdbg.c */ FcPrivate void @@ -800,6 +808,9 @@ FcPrivate FcBool FcFileIsLink (const FcChar8 *file); FcPrivate FcBool +FcFileIsFile (const FcChar8 *file); + +FcPrivate FcBool FcFileScanConfig (FcFontSet *set, FcStrSet *dirs, FcBlanks *blanks, diff --git a/fontconfig/src/fcmatch.c b/fontconfig/src/fcmatch.c index 10976d6e8..dec92b9cf 100644 --- a/fontconfig/src/fcmatch.c +++ b/fontconfig/src/fcmatch.c @@ -245,6 +245,8 @@ typedef enum _FcMatcherPriorityDummy { typedef enum _FcMatcherPriority { PRI1(HASH), PRI1(FILE), + PRI1(FONTFORMAT), + PRI1(SCALABLE), PRI1(FOUNDRY), PRI1(CHARSET), PRI_FAMILY_STRONG, diff --git a/fontconfig/src/fcobjs.c b/fontconfig/src/fcobjs.c index 1d3af73be..bad9824d4 100644 --- a/fontconfig/src/fcobjs.c +++ b/fontconfig/src/fcobjs.c @@ -37,7 +37,7 @@ FcObjectTypeLookup (register const char *str, register unsigned int len); /* The 1000 is to leave some room for future added internal objects, such * that caches from newer fontconfig can still be used with older fontconfig * without getting confused. */ -static fc_atomic_int_t next_id = FC_MAX_BASE_OBJECT + 1000; +static fc_atomic_int_t next_id = FC_MAX_BASE_OBJECT + FC_EXT_OBJ_INDEX; struct FcObjectOtherTypeInfo { struct FcObjectOtherTypeInfo *next; FcObjectType object; diff --git a/fontconfig/src/fcobjs.h b/fontconfig/src/fcobjs.h index 682fe6ad3..87c7319e3 100644 --- a/fontconfig/src/fcobjs.h +++ b/fontconfig/src/fcobjs.h @@ -23,7 +23,7 @@ FC_OBJECT (FILE, FcTypeString, FcCompareFilename) FC_OBJECT (INDEX, FcTypeInteger, NULL) FC_OBJECT (RASTERIZER, FcTypeString, FcCompareString) FC_OBJECT (OUTLINE, FcTypeBool, FcCompareBool) -FC_OBJECT (SCALABLE, FcTypeBool, NULL) +FC_OBJECT (SCALABLE, FcTypeBool, FcCompareBool) FC_OBJECT (DPI, FcTypeDouble, NULL) FC_OBJECT (RGBA, FcTypeInteger, NULL) FC_OBJECT (SCALE, FcTypeDouble, NULL) @@ -35,7 +35,7 @@ FC_OBJECT (CHARSET, FcTypeCharSet, FcCompareCharSet) FC_OBJECT (LANG, FcTypeLangSet, FcCompareLang) FC_OBJECT (FONTVERSION, FcTypeInteger, FcCompareNumber) FC_OBJECT (CAPABILITY, FcTypeString, NULL) -FC_OBJECT (FONTFORMAT, FcTypeString, NULL) +FC_OBJECT (FONTFORMAT, FcTypeString, FcCompareString) FC_OBJECT (EMBOLDEN, FcTypeBool, NULL) FC_OBJECT (EMBEDDED_BITMAP, FcTypeBool, NULL) FC_OBJECT (DECORATIVE, FcTypeBool, FcCompareBool) diff --git a/fontconfig/src/fcxml.c b/fontconfig/src/fcxml.c index 1cac9a8b3..eb8d26ac0 100644 --- a/fontconfig/src/fcxml.c +++ b/fontconfig/src/fcxml.c @@ -2183,6 +2183,8 @@ FcParseInclude (FcConfigParse *parse) FcBool ignore_missing = FcFalse; FcBool deprecated = FcFalse; FcChar8 *prefix = NULL, *p; + static FcChar8 *userdir = NULL; + static FcChar8 *userconf = NULL; s = FcStrBufDoneStatic (&parse->pstack->str); if (!s) @@ -2215,23 +2217,78 @@ FcParseInclude (FcConfigParse *parse) memcpy (&prefix[plen + 1], s, dlen); prefix[plen + 1 + dlen] = 0; s = prefix; + if (FcFileIsDir (s)) + { + userdir: + if (!userdir) + userdir = FcStrdup (s); + } + else if (FcFileIsFile (s)) + { + userconf: + if (!userconf) + userconf = FcStrdup (s); + } + else + { + /* No config dir nor file on the XDG directory spec compliant place + * so need to guess what it is supposed to be. + */ + FcChar8 *parent = FcStrDirname (s); + + if (!FcFileIsDir (parent)) + FcMakeDirectory (parent); + FcStrFree (parent); + if (FcStrStr (s, (const FcChar8 *)"conf.d") != NULL) + goto userdir; + else + goto userconf; + } } if (!FcConfigParseAndLoad (parse->config, s, !ignore_missing)) parse->error = FcTrue; +#ifndef _WIN32 else { FcChar8 *filename; + static FcBool warn_conf = FcFalse, warn_confd = FcFalse; filename = FcConfigFilename(s); if (deprecated == FcTrue && filename != NULL && !FcFileIsLink (filename)) { - FcConfigMessage (parse, FcSevereWarning, "reading configurations from %s is deprecated.", s); + if (FcFileIsDir (filename)) + { + if (FcFileIsDir (userdir) || + rename ((const char *)filename, (const char *)userdir) != 0 || + symlink ((const char *)userdir, (const char *)filename) != 0) + { + if (!warn_confd) + { + FcConfigMessage (parse, FcSevereWarning, "reading configurations from %s is deprecated. please move it to %s manually", s, userdir); + warn_confd = FcTrue; + } + } + } + else + { + if (FcFileIsFile (userconf) || + rename ((const char *)filename, (const char *)userconf) != 0 || + symlink ((const char *)userconf, (const char *)filename) != 0) + { + if (!warn_conf) + { + FcConfigMessage (parse, FcSevereWarning, "reading configurations from %s is deprecated. please move it to %s manually", s, userconf); + warn_conf = FcTrue; + } + } + } } if(filename) FcStrFree(filename); } +#endif FcStrBufDestroy (&parse->pstack->str); bail: diff --git a/libX11/configure.ac b/libX11/configure.ac index ff04f8a3e..d3becda9f 100644 --- a/libX11/configure.ac +++ b/libX11/configure.ac @@ -438,9 +438,9 @@ locales="\ iso8859-1 iso8859-10 iso8859-11 iso8859-13 iso8859-14 iso8859-15 \ iso8859-2 iso8859-3 iso8859-4 iso8859-5 iso8859-6 iso8859-7 \ iso8859-8 iso8859-9 iso8859-9e ja ja.JIS ja_JP.UTF-8\ - ja.SJIS ko koi8-c koi8-r \ - koi8-u ko_KR.UTF-8 microsoft-cp1251 microsoft-cp1255 \ - microsoft-cp1256 mulelao-1 nokhchi-1 pt_BR.UTF-8 ru_RU.UTF-8 \ + ja.SJIS km_KH.UTF-8 ko koi8-c koi8-r koi8-u \ + ko_KR.UTF-8 microsoft-cp1251 microsoft-cp1255 microsoft-cp1256 \ + mulelao-1 nokhchi-1 pt_BR.UTF-8 ru_RU.UTF-8 sr_CS.UTF-8 \ tatar-cyr th_TH th_TH.UTF-8 tscii-0 vi_VN.tcvn vi_VN.viscii \ zh_CN zh_CN.gb18030 zh_CN.gbk zh_CN.UTF-8 zh_HK.big5 \ zh_HK.big5hkscs zh_HK.UTF-8 zh_TW zh_TW.big5 zh_TW.UTF-8" diff --git a/libX11/modules/im/ximcp/imDefIc.c b/libX11/modules/im/ximcp/imDefIc.c index 3b5fa4147..f7e484789 100644 --- a/libX11/modules/im/ximcp/imDefIc.c +++ b/libX11/modules/im/ximcp/imDefIc.c @@ -927,6 +927,30 @@ _XimProtoDestroyIC( return; } +/* + * Some functions require the request queue from the server to be flushed + * so that the ordering of client initiated status changes and those requested + * by the server is well defined. + * _XimSync() would be the function of choice here as it should get a + * XIM_SYNC_REPLY back from the server. + * This however isn't implemented in the piece of junk that is used by most + * input servers as the server side protocol if to XIM. + * Since this code is not shipped as a library together with the client side + * XIM code but is duplicated by every input server around the world there + * is no easy fix to this but this ugly hack below. + * Obtaining an IC value from the server sends a request and empties out the + * event/server request queue until the answer to this request is found. + * Thus it is guaranteed that any pending server side request gets processed. + * This is what the hack below is doing. + */ + +static void +BrokenSyncWithServer(XIC xic) +{ + CARD32 dummy; + XGetICValues(xic, XNFilterEvents, &dummy, NULL); +} + static void _XimProtoSetFocus( XIC xic) @@ -957,6 +981,7 @@ _XimProtoSetFocus( } } #endif /* XIM_CONNECTABLE */ + BrokenSyncWithServer(xic); buf_s[0] = im->private.proto.imid; /* imid */ buf_s[1] = ic->private.proto.icid; /* icid */ @@ -1003,6 +1028,8 @@ _XimProtoUnsetFocus( } #endif /* XIM_CONNECTABLE */ + BrokenSyncWithServer(xic); + buf_s[0] = im->private.proto.imid; /* imid */ buf_s[1] = ic->private.proto.icid; /* icid */ diff --git a/libX11/modules/im/ximcp/imDefLkup.c b/libX11/modules/im/ximcp/imDefLkup.c index 0a9553a41..b4315894f 100644 --- a/libX11/modules/im/ximcp/imDefLkup.c +++ b/libX11/modules/im/ximcp/imDefLkup.c @@ -269,6 +269,8 @@ _XimForwardEventCore( int ret_code; INT16 len; + bzero(buf32, sizeof(buf32)); /* valgrind noticed uninitialized memory use! */ + if (!(len = _XimSetEventToWire(ev, (xEvent *)&buf_s[4]))) return False; /* X event */ @@ -704,7 +706,11 @@ _XimCommitRecv( (void)_XimRespSyncReply(ic, flag); - MARK_FABRICATED(im); + if (ic->private.proto.registed_filter_event + & (KEYPRESS_MASK | KEYRELEASE_MASK)) + MARK_FABRICATED(im); + + bzero(&ev, sizeof(ev)); /* uninitialized : found when running kterm under valgrind */ ev.type = KeyPress; ev.send_event = False; @@ -713,6 +719,15 @@ _XimCommitRecv( ev.keycode = 0; ev.state = 0; + ev.time = 0L; + ev.serial = LastKnownRequestProcessed(im->core.display); + /* FIXME : + I wish there were COMMENTs (!) about the data passed around. + */ +#if 0 + fprintf(stderr,"%s,%d: putback k press FIXED ev.time=0 ev.serial=%lu\n", __FILE__, __LINE__, ev.serial); +#endif + XPutBackEvent(im->core.display, (XEvent *)&ev); return True; diff --git a/libX11/modules/im/ximcp/imTrans.c b/libX11/modules/im/ximcp/imTrans.c index 75a05f2b1..1e3702ea7 100644 --- a/libX11/modules/im/ximcp/imTrans.c +++ b/libX11/modules/im/ximcp/imTrans.c @@ -224,12 +224,20 @@ _XimTransInternalConnection( if (spec->is_putback) return; + + bzero(&ev, sizeof(ev)); /* FIXME: other fields may be accessed, too. */ kev = (XKeyEvent *)&ev; kev->type = KeyPress; kev->send_event = False; kev->display = im->core.display; kev->window = spec->window; kev->keycode = 0; + kev->time = 0L; + kev->serial = LastKnownRequestProcessed(im->core.display); +#if 0 + fprintf(stderr,"%s,%d: putback FIXED kev->time=0 kev->serial=%lu\n", __FILE__, __LINE__, kev->serial); +#endif + XPutBackEvent(im->core.display, &ev); XFlush(im->core.display); spec->is_putback = True; diff --git a/libXdmcp/Key.c b/libXdmcp/Key.c index 995ec2ae6..bdefe2b71 100644 --- a/libXdmcp/Key.c +++ b/libXdmcp/Key.c @@ -32,6 +32,11 @@ in this Software without prior written authorization from The Open Group. #include <X11/Xmd.h> #include <X11/Xdmcp.h> +#ifdef HAVE_LIBBSD +#include <bsd/stdlib.h> /* for arc4random_buf() */ +#endif + +#ifndef HAVE_ARC4RANDOM_BUF static void getbits (long data, unsigned char *dst) { @@ -40,6 +45,7 @@ getbits (long data, unsigned char *dst) dst[2] = (data >> 16) & 0xff; dst[3] = (data >> 24) & 0xff; } +#endif #define Time_t time_t @@ -53,6 +59,7 @@ getbits (long data, unsigned char *dst) void XdmcpGenerateKey (XdmAuthKeyPtr key) { +#ifndef HAVE_ARC4RANDOM_BUF long lowbits, highbits; srandom ((int)getpid() ^ time((Time_t *)0)); @@ -60,6 +67,9 @@ XdmcpGenerateKey (XdmAuthKeyPtr key) highbits = random (); getbits (lowbits, key->data); getbits (highbits, key->data + 4); +#else + arc4random_buf(key->data, 8); +#endif } int diff --git a/libXdmcp/configure.ac b/libXdmcp/configure.ac index 08c046ae0..d8ddfae93 100644 --- a/libXdmcp/configure.ac +++ b/libXdmcp/configure.ac @@ -53,7 +53,8 @@ AC_PROG_LN_S AC_SEARCH_LIBS([recvfrom],[socket]) # Checks for library functions. -AC_CHECK_FUNCS([srand48 lrand48]) +AC_CHECK_LIB([bsd], [arc4random_buf]) +AC_CHECK_FUNCS([srand48 lrand48 arc4random_buf]) # Obtain compiler/linker options for depedencies PKG_CHECK_MODULES(XDMCP, xproto) diff --git a/libxcb/configure.ac b/libxcb/configure.ac index 736438305..482f85b2b 100644 --- a/libxcb/configure.ac +++ b/libxcb/configure.ac @@ -128,12 +128,12 @@ xcbincludedir='${includedir}/xcb' AC_SUBST(xcbincludedir) if test "x$GCC" = xyes ; then - CWARNFLAGS="-Wall -pedantic -Wpointer-arith \ + CWARNFLAGS="-Wall -pedantic -Wpointer-arith -Wold-style-definition \ -Wstrict-prototypes -Wmissing-declarations -Wnested-externs" else AC_CHECK_DECL([__SUNPRO_C], [SUNCC="yes"], [SUNCC="no"]) if test "x$SUNCC" = "xyes"; then - CWARNFLAGS="-v" + CWARNFLAGS="-v -fd" fi fi AC_SUBST(CWARNFLAGS) @@ -192,7 +192,7 @@ XCB_EXTENSION(XFixes, "yes") XCB_EXTENSION(XFree86-DRI, "yes") XCB_EXTENSION(Xinerama, "yes") XCB_EXTENSION(XInput, "no") -XCB_EXTENSION(XKB, "no") +XCB_EXTENSION(XKB, "yes") XCB_EXTENSION(Xprint, "yes") XCB_EXTENSION(SELinux, "no") XCB_EXTENSION(XTest, "yes") diff --git a/libxcb/src/xcb_list.c b/libxcb/src/xcb_list.c index 6f5c61190..129540bc4 100644 --- a/libxcb/src/xcb_list.c +++ b/libxcb/src/xcb_list.c @@ -47,7 +47,7 @@ struct _xcb_map { /* Private interface */ -_xcb_map *_xcb_map_new() +_xcb_map *_xcb_map_new(void) { _xcb_map *list; list = malloc(sizeof(_xcb_map)); diff --git a/mesalib/Makefile.am b/mesalib/Makefile.am index ce391c409..343badef4 100644 --- a/mesalib/Makefile.am +++ b/mesalib/Makefile.am @@ -52,12 +52,6 @@ EXTRA_FILES = \ src/glsl/glcpp/glcpp-lex.c \ src/glsl/glcpp/glcpp-parse.c \ src/glsl/glcpp/glcpp-parse.h \ - src/mesa/main/api_exec_es1.c \ - src/mesa/main/api_exec_es1_dispatch.h \ - src/mesa/main/api_exec_es1_remap_helper.h \ - src/mesa/main/api_exec_es2.c \ - src/mesa/main/api_exec_es2_dispatch.h \ - src/mesa/main/api_exec_es2_remap_helper.h \ src/mesa/program/lex.yy.c \ src/mesa/program/program_parse.tab.c \ src/mesa/program/program_parse.tab.h \ diff --git a/mesalib/configure.ac b/mesalib/configure.ac index 62d06e035..0dcd2a51f 100644 --- a/mesalib/configure.ac +++ b/mesalib/configure.ac @@ -1617,6 +1617,10 @@ if test "x$enable_gallium_llvm" = xyes; then if $LLVM_CONFIG --components | grep -qw 'irreader'; then LLVM_COMPONENTS="${LLVM_COMPONENTS} irreader" fi + # LLVM 3.4 requires Option + if $LLVM_CONFIG --components | grep -qw 'option'; then + LLVM_COMPONENTS="${LLVM_COMPONENTS} option" + fi fi DEFINES="${DEFINES} -DHAVE_LLVM=0x0$LLVM_VERSION_INT" MESA_LLVM=1 diff --git a/mesalib/docs/devinfo.html b/mesalib/docs/devinfo.html index bf7725961..4c1099c5e 100644 --- a/mesalib/docs/devinfo.html +++ b/mesalib/docs/devinfo.html @@ -36,7 +36,7 @@ To add a new GL extension to Mesa you have to do at least the following. </pre> </li> <li> - In the src/mesa/glapi/ directory, add the new extension functions and + In the src/mapi/glapi/gen/ directory, add the new extension functions and enums to the gl_API.xml file. Then, a bunch of source files must be regenerated by executing the corresponding Python scripts. diff --git a/mesalib/docs/index.html b/mesalib/docs/index.html index f0c51703f..30f58ab42 100644 --- a/mesalib/docs/index.html +++ b/mesalib/docs/index.html @@ -16,6 +16,12 @@ <h1>News</h1> +<h2>August 1, 2013</h2> +<p> +<a href="relnotes/9.1.6.html">Mesa 9.1.6</a> is released. +This is a bug fix release. +</p> + <h2>July 17, 2013</h2> <p> <a href="relnotes/9.1.5.html">Mesa 9.1.5</a> is released. diff --git a/mesalib/docs/relnotes.html b/mesalib/docs/relnotes.html index 3d391c061..e33835abc 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.6.html">9.1.6 release notes</a> <li><a href="relnotes/9.1.5.html">9.1.5 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> diff --git a/mesalib/docs/relnotes/9.1.5.html b/mesalib/docs/relnotes/9.1.5.html index fcc47c4f4..05f35e825 100644 --- a/mesalib/docs/relnotes/9.1.5.html +++ b/mesalib/docs/relnotes/9.1.5.html @@ -30,7 +30,9 @@ because GL_ARB_compatibility is not supported. <h2>MD5 checksums</h2> <pre> -TBD +4ed2af5943141a85a21869053a2fc2eb MesaLib-9.1.5.tar.bz2 +47181066acf3231d74e027b2033f9455 MesaLib-9.1.5.tar.gz +4c9c6615bd99215325250f87ed34058f MesaLib-9.1.5.zip </pre> <h2>New features</h2> diff --git a/mesalib/docs/relnotes/9.1.6.html b/mesalib/docs/relnotes/9.1.6.html new file mode 100644 index 000000000..c27b0a619 --- /dev/null +++ b/mesalib/docs/relnotes/9.1.6.html @@ -0,0 +1,168 @@ +<!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.6 Release Notes / August 1, 2013</h1> + +<p> +Mesa 9.1.6 is a bug fix release which fixes bugs found since the 9.1.5 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> +443a2a352667294b53d56cb1a74114e9 MesaLib-9.1.6.tar.bz2 +08d3069cccd6821e5f33e0840bca0718 MesaLib-9.1.6.tar.gz +90aa7a6d9878cdbfcb055312f356d6b9 MesaLib-9.1.6.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=47824">Bug 47824</a> - osmesa using --enable-shared-glapi depends on libgl</li> + +<li><a href="https://bugs.freedesktop.org/show_bug.cgi?id=62362">Bug 62362</a> - Crash when using Wayland EGL platform</li> + +<li><a href="https://bugs.freedesktop.org/show_bug.cgi?id=63435">Bug 63435</a> - [Regression since 9.0] Flickering in EGL OpenGL full-screen window with swap interval 1</li> + +<li><a href="https://bugs.freedesktop.org/show_bug.cgi?id=64087">Bug 64087</a> - Webgl conformance shader-with-non-reserved-words crash when mesa is compiled without --enable-debug</li> + +<li><a href="https://bugs.freedesktop.org/show_bug.cgi?id=64330">Bug 64330</a> - WebGL snake demo crash in loop_analysis.cpp:506: bool is_loop_terminator(ir_if*): assertion „inst != __null“ failed.</li> + +<li><a href="https://bugs.freedesktop.org/show_bug.cgi?id=65236">Bug 65236</a> - [i965] Rendering artifacts in VDrift/GL2</li> + +<li><a href="https://bugs.freedesktop.org/show_bug.cgi?id=66558">Bug 66558</a> - RS690: 3D artifacts when playing SuperTuxKart</li> + +<li><a href="https://bugs.freedesktop.org/show_bug.cgi?id=66847">Bug 66847</a> - compilation broken with llvm 3.3</li> + +<li><a href="https://bugs.freedesktop.org/show_bug.cgi?id=66850">Bug 66850</a> - glGenerateMipmap crashes when using GL_TEXTURE_2D_ARRAY with compressed internal format</li> + +<li><a href="https://bugs.freedesktop.org/show_bug.cgi?id=66921">Bug 66921</a> - [r300g] Heroes of Newerth: HiZ related corruption</li> + +<li><a href="https://bugs.freedesktop.org/show_bug.cgi?id=67283">Bug 67283</a> - VDPAU doesn't work on hybrid laptop through DRI_PRIME</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.5..mesa-9.1.6 +</pre> + +<p>Andreas Boll (1):</p> +<ul> + <li>configure.ac: Require llvm-3.2 for r600g/radeonsi llvm backends</li> +</ul> + +<p>Brian Paul (4):</p> +<ul> + <li>mesa: handle 2D texture arrays in get_tex_rgba_compressed()</li> + <li>meta: handle 2D texture arrays in decompress_texture_image()</li> + <li>mesa: implement mipmap generation for compressed 2D array textures</li> + <li>mesa: improve free() cleanup in generate_mipmap_compressed()</li> +</ul> + +<p>Carl Worth (7):</p> +<ul> + <li>docs: Add 9.1.5 release md5sums</li> + <li>Merge 'origin/9.1' into stable</li> + <li>cherry-ignore: Drop 13 patches from the pick list</li> + <li>get-pick-list.sh: Include commits mentionining "CC: mesa-stable..." in pick list</li> + <li>get-pick-list: Allow for non-whitespace between "CC:" and "mesa-stable"</li> + <li>get-pick-list: Ignore commits which CC mesa-stable unless they say "9.1"</li> + <li>Bump version to 9.1.6</li> +</ul> + +<p>Chris Forbes (5):</p> +<ul> + <li>i965/Gen4: Zero extra coordinates for ir_tex</li> + <li>i965/vs: Fix flaky texture swizzling</li> + <li>i965/vs: set up sampler state pointer for Gen4/5.</li> + <li>i965/vs: Put lod parameter in the correct place for Gen4</li> + <li>i965/vs: Gen4/5: enable front colors if back colors are written</li> +</ul> + +<p>Christoph Bumiller (1):</p> +<ul> + <li>nv50,nvc0: s/uint16/uint32 for constant buffer offset</li> +</ul> + +<p>Dave Airlie (1):</p> +<ul> + <li>gallium/vl: add prime support</li> +</ul> + +<p>Eric Anholt (1):</p> +<ul> + <li>egl: Restore "bogus" DRI2 invalidate event code.</li> +</ul> + +<p>Jeremy Huddleston Sequoia (1):</p> +<ul> + <li>Apple: glFlush() is not needed with CGLFlushDrawable()</li> +</ul> + +<p>Kenneth Graunke (1):</p> +<ul> + <li>glsl: Classify "layout" like other identifiers.</li> +</ul> + +<p>Kristian Høgsberg (1):</p> +<ul> + <li>egl-wayland: Fix left-over wl_display_roundtrip() usage</li> +</ul> + +<p>Maarten Lankhorst (2):</p> +<ul> + <li>osmesa: link against static libglapi library too to get the gl exports</li> + <li>nvc0: force use of correct firmware file</li> +</ul> + +<p>Marek Olšák (4):</p> +<ul> + <li>r300g/swtcl: fix geometry corruption by uploading indices to a buffer</li> + <li>r300g/swtcl: fix a lockup in MSAA resolve</li> + <li>Revert "r300g: allow HiZ with a 16-bit zbuffer"</li> + <li>r600g: increase array size for shader inputs and outputs</li> +</ul> + +<p>Matt Turner (2):</p> +<ul> + <li>i965: NULL check prog on shader compilation failure.</li> + <li>i965/vs: Print error if vertex shader fails to compile.</li> +</ul> + +<p>Paul Berry (1):</p> +<ul> + <li>glsl: Handle empty if statement encountered during loop analysis.</li> +</ul> + +</div> +</body> +</html> diff --git a/mesalib/docs/relnotes/9.2.html b/mesalib/docs/relnotes/9.2.html index 4e419f166..1f93b8963 100644 --- a/mesalib/docs/relnotes/9.2.html +++ b/mesalib/docs/relnotes/9.2.html @@ -53,6 +53,7 @@ Note: some of the new features are only available with certain drivers. <li>Added new freedreno gallium driver</li> <li>OSMesa interface for gallium llvmpipe/softpipe drivers</li> <li>Gallium Heads-Up Display (HUD) feature for performance monitoring</li> +<li>Added support for UVD (2.2 and 3.0) video decoding on r600g and radeonsi through VDPAU (requires Kernel 3.10 or later)</li> </ul> @@ -71,7 +72,8 @@ Note: some of the new features are only available with certain drivers. 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. + GL_ARB_separate_shader_objects doesn't have this issue.</li> +<li>i965 Gen6+ requires Kernel 3.6 or later. (92d2f5a)</li> </ul> </div> diff --git a/mesalib/docs/sourcetree.html b/mesalib/docs/sourcetree.html index 530c333c4..a6868d398 100644 --- a/mesalib/docs/sourcetree.html +++ b/mesalib/docs/sourcetree.html @@ -59,7 +59,6 @@ each directory. <li><b>osmesa</b> - off-screen software driver <li>XXX more </ul> - <li><b>es</b> - OpenGL ES overlay, parallelly buildable with the core Mesa <li><b>math</b> - vertex array translation and transformation code (not used with Gallium) <li><b>program</b> - Vertex/fragment shader and GLSL compiler code @@ -135,7 +134,6 @@ each directory. <li><b>clover</b> - OpenCL state tracker <li><b>dri</b> - Meta state tracker for DRI drivers <li><b>egl</b> - Meta state tracker for EGL drivers - <li><b>es</b> - OpenGL ES 1.x and 2.x state trackers <li><b>glx</b> - Meta state tracker for GLX <li><b>vdpau</b> - VDPAU state tracker <li><b>vega</b> - OpenVG 1.x state tracker diff --git a/mesalib/docs/specs/WL_bind_wayland_display.spec b/mesalib/docs/specs/WL_bind_wayland_display.spec index 02bd6ea21..8f0083c24 100644 --- a/mesalib/docs/specs/WL_bind_wayland_display.spec +++ b/mesalib/docs/specs/WL_bind_wayland_display.spec @@ -17,7 +17,7 @@ Status Version - Version 1, March 1, 2011 + Version 5, July 16, 2013 Number @@ -57,7 +57,7 @@ New Procedures and Functions struct wl_display *display); EGLBoolean eglQueryWaylandBufferWL(EGLDisplay dpy, - struct wl_buffer *buffer, + struct wl_resource *buffer, EGLint attribute, EGLint *value); New Tokens @@ -173,3 +173,7 @@ Revision History Use EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGB, and EGL_TEXTURE_RGBA, and just define the new YUV texture formats. Add support for EGL_WIDTH and EGL_HEIGHT in the query attributes (Kristian Høgsberg) + Version 5, July 16, 2013 + Change eglQueryWaylandBufferWL to take a resource pointer to the + buffer instead of a pointer to a struct wl_buffer, as the latter has + been deprecated. (Ander Conselvan de Oliveira) diff --git a/mesalib/include/EGL/eglmesaext.h b/mesalib/include/EGL/eglmesaext.h index d476d18a2..e0eae281f 100644 --- a/mesalib/include/EGL/eglmesaext.h +++ b/mesalib/include/EGL/eglmesaext.h @@ -120,15 +120,15 @@ typedef EGLDisplay (EGLAPIENTRYP PFNEGLGETDRMDISPLAYMESA) (int fd); #define EGL_TEXTURE_Y_XUXV_WL 0x31D9 struct wl_display; -struct wl_buffer; +struct wl_resource; #ifdef EGL_EGLEXT_PROTOTYPES EGLAPI EGLBoolean EGLAPIENTRY eglBindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display); EGLAPI EGLBoolean EGLAPIENTRY eglUnbindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display); -EGLAPI EGLBoolean EGLAPIENTRY eglQueryWaylandBufferWL(EGLDisplay dpy, struct wl_buffer *buffer, EGLint attribute, EGLint *value); +EGLAPI EGLBoolean EGLAPIENTRY eglQueryWaylandBufferWL(EGLDisplay dpy, struct wl_resource *buffer, EGLint attribute, EGLint *value); #endif typedef EGLBoolean (EGLAPIENTRYP PFNEGLBINDWAYLANDDISPLAYWL) (EGLDisplay dpy, struct wl_display *display); typedef EGLBoolean (EGLAPIENTRYP PFNEGLUNBINDWAYLANDDISPLAYWL) (EGLDisplay dpy, struct wl_display *display); -typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYWAYLANDBUFFERWL) (EGLDisplay dpy, struct wl_buffer *buffer, EGLint attribute, EGLint *value); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYWAYLANDBUFFERWL) (EGLDisplay dpy, struct wl_resource *buffer, EGLint attribute, EGLint *value); #endif diff --git a/mesalib/include/GL/internal/dri_interface.h b/mesalib/include/GL/internal/dri_interface.h index 279e9f003..a89a696b1 100644 --- a/mesalib/include/GL/internal/dri_interface.h +++ b/mesalib/include/GL/internal/dri_interface.h @@ -944,7 +944,7 @@ struct __DRIdri2ExtensionRec { * extensions. */ #define __DRI_IMAGE "DRI_IMAGE" -#define __DRI_IMAGE_VERSION 7 +#define __DRI_IMAGE_VERSION 8 /** * These formats correspond to the similarly named MESA_FORMAT_* @@ -1031,6 +1031,25 @@ struct __DRIdri2ExtensionRec { * 7+. Each query will return a * new fd. */ +enum __DRIYUVColorSpace { + __DRI_YUV_COLOR_SPACE_UNDEFINED = 0, + __DRI_YUV_COLOR_SPACE_ITU_REC601 = 0x327F, + __DRI_YUV_COLOR_SPACE_ITU_REC709 = 0x3280, + __DRI_YUV_COLOR_SPACE_ITU_REC2020 = 0x3281 +}; + +enum __DRISampleRange { + __DRI_YUV_RANGE_UNDEFINED = 0, + __DRI_YUV_FULL_RANGE = 0x3282, + __DRI_YUV_NARROW_RANGE = 0x3283 +}; + +enum __DRIChromaSiting { + __DRI_YUV_CHROMA_SITING_UNDEFINED = 0, + __DRI_YUV_CHROMA_SITING_0 = 0x3284, + __DRI_YUV_CHROMA_SITING_0_5 = 0x3285 +}; + /** * \name Reasons that __DRIimageExtensionRec::createImageFromTexture might fail */ @@ -1136,6 +1155,24 @@ struct __DRIimageExtensionRec { int *fds, int num_fds, int *strides, int *offsets, void *loaderPrivate); + + /** + * Like createImageFromFds, but takes additional attributes. + * + * For EGL_EXT_image_dma_buf_import. + * + * \since 8 + */ + __DRIimage *(*createImageFromDmaBufs)(__DRIscreen *screen, + int width, int height, int fourcc, + int *fds, int num_fds, + int *strides, int *offsets, + enum __DRIYUVColorSpace color_space, + enum __DRISampleRange sample_range, + enum __DRIChromaSiting horiz_siting, + enum __DRIChromaSiting vert_siting, + unsigned *error, + void *loaderPrivate); }; diff --git a/mesalib/src/Makefile.am b/mesalib/src/Makefile.am index b3dc44d6f..76280a0c0 100644 --- a/mesalib/src/Makefile.am +++ b/mesalib/src/Makefile.am @@ -29,6 +29,10 @@ if HAVE_DRI_GLX SUBDIRS += glx endif +if HAVE_EGL_PLATFORM_WAYLAND +SUBDIRS += egl/wayland +endif + if HAVE_GBM SUBDIRS += gbm endif diff --git a/mesalib/src/gallium/auxiliary/util/u_cpu_detect.c b/mesalib/src/gallium/auxiliary/util/u_cpu_detect.c index 588fc7c72..87ad78095 100644 --- a/mesalib/src/gallium/auxiliary/util/u_cpu_detect.c +++ b/mesalib/src/gallium/auxiliary/util/u_cpu_detect.c @@ -230,8 +230,28 @@ static INLINE uint64_t xgetbv(void) #else return 0; #endif +} + +#if defined(PIPE_ARCH_X86) +static INLINE boolean sse2_has_daz(void) +{ + struct { + uint32_t pad1[7]; + uint32_t mxcsr_mask; + uint32_t pad2[128-8]; + } PIPE_ALIGN_VAR(16) fxarea; + + fxarea.mxcsr_mask = 0; +#if (defined(PIPE_CC_GCC) || defined(PIPE_CC_SUNPRO)) + __asm __volatile ("fxsave %0" : "+m" (fxarea)); +#elif (defined(PIPE_CC_MSVC) || defined(PIPE_CC_ICL)) + _fxsave(&fxarea); +#endif + return !!(fxarea.mxcsr_mask & (1 << 6)); } +#endif + #endif /* X86 or X86_64 */ void @@ -310,6 +330,12 @@ util_cpu_detect(void) ((xgetbv() & 6) == 6); // XMM & YMM util_cpu_caps.has_f16c = (regs2[2] >> 29) & 1; util_cpu_caps.has_mmx2 = util_cpu_caps.has_sse; /* SSE cpus supports mmxext too */ +#if defined(PIPE_ARCH_X86_64) + util_cpu_caps.has_daz = 1; +#else + util_cpu_caps.has_daz = util_cpu_caps.has_sse3 || + (util_cpu_caps.has_sse2 && sse2_has_daz()); +#endif cacheline = ((regs2[1] >> 8) & 0xFF) * 8; if (cacheline > 0) @@ -368,9 +394,12 @@ util_cpu_detect(void) debug_printf("util_cpu_caps.has_sse4_1 = %u\n", util_cpu_caps.has_sse4_1); debug_printf("util_cpu_caps.has_sse4_2 = %u\n", util_cpu_caps.has_sse4_2); debug_printf("util_cpu_caps.has_avx = %u\n", util_cpu_caps.has_avx); + debug_printf("util_cpu_caps.has_f16c = %u\n", util_cpu_caps.has_f16c); + debug_printf("util_cpu_caps.has_popcnt = %u\n", util_cpu_caps.has_popcnt); debug_printf("util_cpu_caps.has_3dnow = %u\n", util_cpu_caps.has_3dnow); debug_printf("util_cpu_caps.has_3dnow_ext = %u\n", util_cpu_caps.has_3dnow_ext); debug_printf("util_cpu_caps.has_altivec = %u\n", util_cpu_caps.has_altivec); + debug_printf("util_cpu_caps.has_daz = %u\n", util_cpu_caps.has_daz); } #endif diff --git a/mesalib/src/gallium/auxiliary/util/u_cpu_detect.h b/mesalib/src/gallium/auxiliary/util/u_cpu_detect.h index f9cd6475e..cc3e0ce03 100644 --- a/mesalib/src/gallium/auxiliary/util/u_cpu_detect.h +++ b/mesalib/src/gallium/auxiliary/util/u_cpu_detect.h @@ -68,6 +68,7 @@ struct util_cpu_caps { unsigned has_3dnow:1; unsigned has_3dnow_ext:1; unsigned has_altivec:1; + unsigned has_daz:1; }; extern struct util_cpu_caps diff --git a/mesalib/src/gallium/auxiliary/util/u_format_srgb.h b/mesalib/src/gallium/auxiliary/util/u_format_srgb.h index 82ed9575d..740a91974 100644 --- a/mesalib/src/gallium/auxiliary/util/u_format_srgb.h +++ b/mesalib/src/gallium/auxiliary/util/u_format_srgb.h @@ -39,6 +39,7 @@ #include "pipe/p_compiler.h" +#include "u_pack_color.h" #include "u_math.h" @@ -51,23 +52,58 @@ util_format_srgb_to_linear_8unorm_table[256]; extern const uint8_t util_format_linear_to_srgb_8unorm_table[256]; +extern const unsigned +util_format_linear_to_srgb_helper_table[104]; + /** * Convert a unclamped linear float to srgb value in the [0,255]. - * XXX this hasn't been tested (render to srgb surface). - * XXX this needs optimization. */ static INLINE uint8_t util_format_linear_float_to_srgb_8unorm(float x) { - if (x >= 1.0f) - return 255; - else if (x >= 0.0031308f) - return float_to_ubyte(1.055f * powf(x, 0.41666f) - 0.055f); - else if (x > 0.0f) - return float_to_ubyte(12.92f * x); - else - return 0; + /* this would be exact but (probably much) slower */ + if (0) { + if (x >= 1.0f) + return 255; + else if (x >= 0.0031308f) + return float_to_ubyte(1.055f * powf(x, 0.41666666f) - 0.055f); + else if (x > 0.0f) + return float_to_ubyte(12.92f * x); + else + return 0; + } + else { + /* + * This is taken from https://gist.github.com/rygorous/2203834 + * Use LUT and do linear interpolation. + */ + union fi almostone, minval, f; + unsigned tab, bias, scale, t; + + almostone.ui = 0x3f7fffff; + minval.ui = (127-13) << 23; + + /* + * Clamp to [2^(-13), 1-eps]; these two values map to 0 and 1, respectively. + * The tests are carefully written so that NaNs map to 0, same as in the + * reference implementation. + */ + if (!(x > minval.f)) + x = minval.f; + if (x > almostone.f) + x = almostone.f; + + /* Do the table lookup and unpack bias, scale */ + f.f = x; + tab = util_format_linear_to_srgb_helper_table[(f.ui - minval.ui) >> 20]; + bias = (tab >> 16) << 9; + scale = tab & 0xffff; + + /* Grab next-highest mantissa bits and perform linear interpolation */ + t = (f.ui >> 12) & 0xff; + return (uint8_t) ((bias + scale*t) >> 16); + } } diff --git a/mesalib/src/gallium/auxiliary/util/u_format_srgb.py b/mesalib/src/gallium/auxiliary/util/u_format_srgb.py index cd63ae789..c6c02f053 100644 --- a/mesalib/src/gallium/auxiliary/util/u_format_srgb.py +++ b/mesalib/src/gallium/auxiliary/util/u_format_srgb.py @@ -40,6 +40,7 @@ CopyRight = ''' import math +import struct def srgb_to_linear(x): @@ -51,10 +52,11 @@ def srgb_to_linear(x): def linear_to_srgb(x): if x >= 0.0031308: - return 1.055 * math.pow(x, 0.41666) - 0.055 + return 1.055 * math.pow(x, 0.41666666) - 0.055 else: return 12.92 * x + def generate_srgb_tables(): print 'const float' print 'util_format_srgb_8unorm_to_linear_float_table[256] = {' @@ -84,6 +86,59 @@ def generate_srgb_tables(): print '};' print +# calculate the table interpolation values used in float linear to unorm8 srgb + numexp = 13 + mantissa_msb = 3 +# stepshift is just used to only use every x-th float to make things faster, +# 5 is largest value which still gives exact same table as 0 + stepshift = 5 + nbuckets = numexp << mantissa_msb + bucketsize = (1 << (23 - mantissa_msb)) >> stepshift + mantshift = 12 + valtable = [] + sum_aa = float(bucketsize) + sum_ab = 0.0 + sum_bb = 0.0 + for i in range(0, bucketsize): + j = (i << stepshift) >> mantshift + sum_ab += j + sum_bb += j*j + inv_det = 1.0 / (sum_aa * sum_bb - sum_ab * sum_ab) + + for bucket in range(0, nbuckets): + start = ((127 - numexp) << 23) + bucket*(bucketsize << stepshift) + sum_a = 0.0 + sum_b = 0.0 + + for i in range(0, bucketsize): + j = (i << stepshift) >> mantshift + fint = start + (i << stepshift) + ffloat = struct.unpack('f', struct.pack('I', fint))[0] + val = linear_to_srgb(ffloat) * 255.0 + 0.5 + sum_a += val + sum_b += j*val + + solved_a = inv_det * (sum_bb*sum_a - sum_ab*sum_b) + solved_b = inv_det * (sum_aa*sum_b - sum_ab*sum_a) + + scaled_a = solved_a * 65536.0 / 512.0 + scaled_b = solved_b * 65536.0 + + int_a = int(scaled_a + 0.5) + int_b = int(scaled_b + 0.5) + + valtable.append((int_a << 16) + int_b) + + print 'const unsigned' + print 'util_format_linear_to_srgb_helper_table[104] = {' + + for j in range(0, nbuckets, 4): + print ' ', + for i in range(j, j + 4): + print '0x%08x,' % (valtable[i],), + print + print '};' + print def main(): print '/* This file is autogenerated by u_format_srgb.py. Do not edit directly. */' diff --git a/mesalib/src/gallium/auxiliary/util/u_math.c b/mesalib/src/gallium/auxiliary/util/u_math.c index f3fe392ba..6981ee939 100644 --- a/mesalib/src/gallium/auxiliary/util/u_math.c +++ b/mesalib/src/gallium/auxiliary/util/u_math.c @@ -111,7 +111,7 @@ util_fpstate_set_denorms_to_zero(unsigned current_mxcsr) if (util_cpu_caps.has_sse) { /* Enable flush to zero mode */ current_mxcsr |= _MM_FLUSH_ZERO_MASK; - if (util_cpu_caps.has_sse3) { + if (util_cpu_caps.has_daz) { /* Enable denormals are zero mode */ current_mxcsr |= _MM_DENORMALS_ZERO_MASK; } diff --git a/mesalib/src/glsl/ast.h b/mesalib/src/glsl/ast.h index 5f2d5b1e4..2cf86e797 100644 --- a/mesalib/src/glsl/ast.h +++ b/mesalib/src/glsl/ast.h @@ -439,6 +439,12 @@ struct ast_type_qualifier { unsigned column_major:1; unsigned row_major:1; /** \} */ + + /** \name Layout qualifiers for GLSL 1.50 geometry shaders */ + /** \{ */ + unsigned prim_type:1; + unsigned max_vertices:1; + /** \} */ } /** \brief Set of flags, accessed by name. */ q; @@ -465,6 +471,12 @@ struct ast_type_qualifier { */ int index; + /** Maximum output vertices in GLSL 1.50 geometry shaders. */ + int max_vertices; + + /** Input or output primitive type in GLSL 1.50 geometry shaders */ + GLenum prim_type; + /** * Binding specified via GL_ARB_shading_language_420pack's "binding" keyword. * @@ -899,12 +911,14 @@ public: class ast_interface_block : public ast_node { public: ast_interface_block(ast_type_qualifier layout, - const char *instance_name, - ast_expression *array_size) + const char *instance_name, + bool is_array, + ast_expression *array_size) : layout(layout), block_name(NULL), instance_name(instance_name), - array_size(array_size) + is_array(is_array), array_size(array_size) { - /* empty */ + if (!is_array) + assert(array_size == NULL); } virtual ir_rvalue *hir(exec_list *instructions, @@ -925,16 +939,44 @@ public: exec_list declarations; /** - * Declared array size of the block instance - * - * If the block is not declared as an array, this field will be \c NULL. + * True if the block is declared as an array * * \note * A block can only be an array if it also has an instance name. If this - * field is not \c NULL, ::instance_name must also not be \c NULL. + * field is true, ::instance_name must also not be \c NULL. + */ + bool is_array; + + /** + * Declared array size of the block instance + * + * If the block is not declared as an array or if the block instance array + * is unsized, this field will be \c NULL. */ ast_expression *array_size; }; + + +/** + * AST node representing a declaration of the input layout for geometry + * shaders. + */ +class ast_gs_input_layout : public ast_node +{ +public: + ast_gs_input_layout(const struct YYLTYPE &locp, GLenum prim_type) + : prim_type(prim_type) + { + set_location(locp); + } + + virtual ir_rvalue *hir(exec_list *instructions, + struct _mesa_glsl_parse_state *state); + +private: + const GLenum prim_type; +}; + /*@}*/ extern void diff --git a/mesalib/src/glsl/ast_array_index.cpp b/mesalib/src/glsl/ast_array_index.cpp index 4baeb6f9d..51f6b10f3 100644 --- a/mesalib/src/glsl/ast_array_index.cpp +++ b/mesalib/src/glsl/ast_array_index.cpp @@ -117,7 +117,8 @@ _mesa_ast_array_index_to_hir(void *mem_ctx, } else if (const_index == NULL && array->type->is_array()) { if (array->type->array_size() == 0) { _mesa_glsl_error(&loc, state, "unsized array index must be constant"); - } else if (array->type->fields.array->is_interface()) { + } else if (array->type->fields.array->is_interface() + && array->variable_referenced()->mode == ir_var_uniform) { /* Page 46 in section 4.3.7 of the OpenGL ES 3.00 spec says: * * "All indexes used to index a uniform block array must be diff --git a/mesalib/src/glsl/ast_to_hir.cpp b/mesalib/src/glsl/ast_to_hir.cpp index 598da92f8..04b16c8aa 100644 --- a/mesalib/src/glsl/ast_to_hir.cpp +++ b/mesalib/src/glsl/ast_to_hir.cpp @@ -72,6 +72,8 @@ _mesa_ast_to_hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) state->toplevel_ir = instructions; + state->gs_input_prim_type_specified = false; + /* Section 4.2 of the GLSL 1.20 specification states: * "The built-in functions are scoped in a scope outside the global scope * users declare global variables in. That is, a shader's global scope, @@ -1771,12 +1773,6 @@ process_array_type(YYLTYPE *loc, const glsl_type *base, ast_node *array_size, } } } - } else if (state->es_shader) { - /* Section 10.17 of the GLSL ES 1.00 specification states that unsized - * array declarations have been removed from the language. - */ - _mesa_glsl_error(loc, state, "unsized array declarations are not " - "allowed in GLSL ES 1.00"); } const glsl_type *array_type = glsl_type::get_array_instance(base, length); @@ -1936,6 +1932,8 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, bool ubo_qualifiers_valid, bool is_parameter) { + STATIC_ASSERT(sizeof(qual->flags.q) <= sizeof(qual->flags.i)); + if (qual->flags.q.invariant) { if (var->used) { _mesa_glsl_error(loc, state, @@ -1963,6 +1961,21 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, _mesa_glsl_shader_target_name(state->target)); } + /* Section 6.1.1 (Function Calling Conventions) of the GLSL 1.10 spec says: + * + * "However, the const qualifier cannot be used with out or inout." + * + * The same section of the GLSL 4.40 spec further clarifies this saying: + * + * "The const qualifier cannot be used with out or inout, or a + * compile-time error results." + */ + if (is_parameter && qual->flags.q.constant && qual->flags.q.out) { + _mesa_glsl_error(loc, state, + "`const' may not be applied to `out' or `inout' " + "function parameters"); + } + /* If there is no qualifier that changes the mode of the variable, leave * the setting alone. */ @@ -2055,13 +2068,24 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, else var->interpolation = INTERP_QUALIFIER_NONE; - if (var->interpolation != INTERP_QUALIFIER_NONE && - !(state->target == vertex_shader && var->mode == ir_var_shader_out) && - !(state->target == fragment_shader && var->mode == ir_var_shader_in)) { - _mesa_glsl_error(loc, state, - "interpolation qualifier `%s' can only be applied to " - "vertex shader outputs and fragment shader inputs", - var->interpolation_string()); + if (var->interpolation != INTERP_QUALIFIER_NONE) { + ir_variable_mode mode = (ir_variable_mode) var->mode; + + if (mode != ir_var_shader_in && mode != ir_var_shader_out) { + _mesa_glsl_error(loc, state, + "interpolation qualifier `%s' can only be applied to " + "shader inputs or outputs.", + var->interpolation_string()); + + } + + if ((state->target == vertex_shader && mode == ir_var_shader_in) || + (state->target == fragment_shader && mode == ir_var_shader_out)) { + _mesa_glsl_error(loc, state, + "interpolation qualifier `%s' cannot be applied to " + "vertex shader inputs or fragment shader outputs", + var->interpolation_string()); + } } var->pixel_center_integer = qual->flags.q.pixel_center_integer; @@ -2317,7 +2341,8 @@ get_variable_being_redeclared(ir_variable *var, ast_declaration *decl, earlier->type = var->type; delete var; var = NULL; - } else if (state->ARB_fragment_coord_conventions_enable + } else if ((state->ARB_fragment_coord_conventions_enable || + state->is_version(150, 0)) && strcmp(var->name, "gl_FragCoord") == 0 && earlier->type == var->type && earlier->mode == var->mode) { @@ -2519,6 +2544,81 @@ process_initializer(ir_variable *var, ast_declaration *decl, return result; } + +/** + * Do additional processing necessary for geometry shader input declarations + * (this covers both interface blocks arrays and bare input variables). + */ +static void +handle_geometry_shader_input_decl(struct _mesa_glsl_parse_state *state, + YYLTYPE loc, ir_variable *var) +{ + unsigned num_vertices = 0; + if (state->gs_input_prim_type_specified) { + num_vertices = vertices_per_prim(state->gs_input_prim_type); + } + + /* Geometry shader input variables must be arrays. Caller should have + * reported an error for this. + */ + if (!var->type->is_array()) { + assert(state->error); + + /* To avoid cascading failures, short circuit the checks below. */ + return; + } + + if (var->type->length == 0) { + /* Section 4.3.8.1 (Input Layout Qualifiers) of the GLSL 1.50 spec says: + * + * All geometry shader input unsized array declarations will be + * sized by an earlier input layout qualifier, when present, as per + * the following table. + * + * Followed by a table mapping each allowed input layout qualifier to + * the corresponding input length. + */ + if (num_vertices != 0) + var->type = glsl_type::get_array_instance(var->type->fields.array, + num_vertices); + } else { + /* Section 4.3.8.1 (Input Layout Qualifiers) of the GLSL 1.50 spec + * includes the following examples of compile-time errors: + * + * // code sequence within one shader... + * in vec4 Color1[]; // size unknown + * ...Color1.length()...// illegal, length() unknown + * in vec4 Color2[2]; // size is 2 + * ...Color1.length()...// illegal, Color1 still has no size + * in vec4 Color3[3]; // illegal, input sizes are inconsistent + * layout(lines) in; // legal, input size is 2, matching + * in vec4 Color4[3]; // illegal, contradicts layout + * ... + * + * To detect the case illustrated by Color3, we verify that the size of + * an explicitly-sized array matches the size of any previously declared + * explicitly-sized array. To detect the case illustrated by Color4, we + * verify that the size of an explicitly-sized array is consistent with + * any previously declared input layout. + */ + if (num_vertices != 0 && var->type->length != num_vertices) { + _mesa_glsl_error(&loc, state, + "geometry shader input size contradicts previously" + " declared layout (size is %u, but layout requires a" + " size of %u)", var->type->length, num_vertices); + } else if (state->gs_input_size != 0 && + var->type->length != state->gs_input_size) { + _mesa_glsl_error(&loc, state, + "geometry shader input sizes are " + "inconsistent (size is %u, but a previous " + "declaration has size %u)", + var->type->length, state->gs_input_size); + } else { + state->gs_input_size = var->type->length; + } + } +} + ir_rvalue * ast_declarator_list::hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) @@ -2605,6 +2705,11 @@ ast_declarator_list::hir(exec_list *instructions, * name of a known structure type. This is both invalid and weird. * Emit an error. * + * - The program text contained something like 'mediump float;' + * when the programmer probably meant 'precision mediump + * float;' Emit a warning with a description of what they + * probably meant to do. + * * Note that if decl_type is NULL and there is a structure involved, * there must have been some sort of error with the structure. In this * case we assume that an error was already generated on this line of @@ -2613,20 +2718,33 @@ ast_declarator_list::hir(exec_list *instructions, */ assert(this->type->specifier->structure == NULL || decl_type != NULL || state->error); - if (this->type->specifier->structure == NULL) { - if (decl_type != NULL) { - _mesa_glsl_warning(&loc, state, "empty declaration"); - } else { - _mesa_glsl_error(&loc, state, - "invalid type `%s' in empty declaration", - type_name); - } - } - if (this->type->qualifier.precision != ast_precision_none && - this->type->specifier->structure != NULL) { - _mesa_glsl_error(&loc, state, "precision qualifiers can't be applied " - "to structures"); + if (decl_type == NULL) { + _mesa_glsl_error(&loc, state, + "invalid type `%s' in empty declaration", + type_name); + } else if (this->type->qualifier.precision != ast_precision_none) { + if (this->type->specifier->structure != NULL) { + _mesa_glsl_error(&loc, state, + "precision qualifiers can't be applied " + "to structures"); + } else { + static const char *const precision_names[] = { + "highp", + "highp", + "mediump", + "lowp" + }; + + _mesa_glsl_warning(&loc, state, + "empty declaration with precision qualifier, " + "to set the default precision, use " + "`precision %s %s;'", + precision_names[this->type->qualifier.precision], + type_name); + } + } else { + _mesa_glsl_warning(&loc, state, "empty declaration"); } } @@ -2662,6 +2780,26 @@ ast_declarator_list::hir(exec_list *instructions, var = new(ctx) ir_variable(var_type, decl->identifier, ir_var_auto); + /* The 'varying in' and 'varying out' qualifiers can only be used with + * ARB_geometry_shader4 and EXT_geometry_shader4, which we don't support + * yet. + */ + if (this->type->qualifier.flags.q.varying) { + if (this->type->qualifier.flags.q.in) { + _mesa_glsl_error(& loc, state, + "`varying in' qualifier in declaration of " + "`%s' only valid for geometry shaders using " + "ARB_geometry_shader4 or EXT_geometry_shader4", + decl->identifier); + } else if (this->type->qualifier.flags.q.out) { + _mesa_glsl_error(& loc, state, + "`varying out' qualifier in declaration of " + "`%s' only valid for geometry shaders using " + "ARB_geometry_shader4 or EXT_geometry_shader4", + decl->identifier); + } + } + /* From page 22 (page 28 of the PDF) of the GLSL 1.10 specification; * * "Global variables can only use the qualifiers const, @@ -2796,7 +2934,22 @@ ast_declarator_list::hir(exec_list *instructions, "cannot have array type")) { error_emitted = true; } - } + } else if (state->target == geometry_shader) { + /* From section 4.3.4 (Inputs) of the GLSL 1.50 spec: + * + * Geometry shader input variables get the per-vertex values + * written out by vertex shader output variables of the same + * names. Since a geometry shader operates on a set of + * vertices, each input varying variable (or input block, see + * interface blocks below) needs to be declared as an array. + */ + if (!var->type->is_array()) { + _mesa_glsl_error(&loc, state, + "geometry shader inputs must be arrays"); + } + + handle_geometry_shader_input_decl(state, loc, var); + } } /* Integer fragment inputs must be qualified with 'flat'. In GLSL ES, @@ -2906,7 +3059,7 @@ ast_declarator_list::hir(exec_list *instructions, } break; default: - assert(0); + break; } } @@ -3015,6 +3168,33 @@ ast_declarator_list::hir(exec_list *instructions, decl->identifier); } + if (state->es_shader) { + const glsl_type *const t = (earlier == NULL) + ? var->type : earlier->type; + + if (t->is_array() && t->length == 0) + /* Section 10.17 of the GLSL ES 1.00 specification states that + * unsized array declarations have been removed from the language. + * Arrays that are sized using an initializer are still explicitly + * sized. However, GLSL ES 1.00 does not allow array + * initializers. That is only allowed in GLSL ES 3.00. + * + * Section 4.1.9 (Arrays) of the GLSL ES 3.00 spec says: + * + * "An array type can also be formed without specifying a size + * if the definition includes an initializer: + * + * float x[] = float[2] (1.0, 2.0); // declares an array of size 2 + * float y[] = float[] (1.0, 2.0, 3.0); // declares an array of size 3 + * + * float a[5]; + * float b[] = a;" + */ + _mesa_glsl_error(& loc, state, + "unsized array declarations are not allowed in " + "GLSL ES"); + } + /* If the declaration is not a redeclaration, there are a few additional * semantic checks that must be applied. In addition, variable that was * created for the declaration should be added to the IR stream. @@ -3323,6 +3503,18 @@ ast_function::hir(exec_list *instructions, "function `%s' return type has qualifiers", name); } + /* Section 6.1 (Function Definitions) of the GLSL 1.20 spec says: + * + * "Arrays are allowed as arguments and as the return type. In both + * cases, the array must be explicitly sized." + */ + if (return_type->is_array() && return_type->length == 0) { + YYLTYPE loc = this->get_location(); + _mesa_glsl_error(& loc, state, + "function `%s' return type array must be explicitly " + "sized", name); + } + /* From page 17 (page 23 of the PDF) of the GLSL 1.20 spec: * * "[Sampler types] can only be declared as function parameters @@ -4362,6 +4554,19 @@ ast_interface_block::hir(exec_list *instructions, */ assert(declared_variables.is_empty()); + /* From section 4.3.4 (Inputs) of the GLSL 1.50 spec: + * + * Geometry shader input variables get the per-vertex values written + * out by vertex shader output variables of the same names. Since a + * geometry shader operates on a set of vertices, each input varying + * variable (or input block, see interface blocks below) needs to be + * declared as an array. + */ + if (state->target == geometry_shader && !this->is_array && + var_mode == ir_var_shader_in) { + _mesa_glsl_error(&loc, state, "geometry shader inputs must be arrays"); + } + /* Page 39 (page 45 of the PDF) of section 4.3.7 in the GLSL ES 3.00 spec * says: * @@ -4372,7 +4577,34 @@ ast_interface_block::hir(exec_list *instructions, if (this->instance_name) { ir_variable *var; - if (this->array_size != NULL) { + if (this->is_array) { + /* Section 4.3.7 (Interface Blocks) of the GLSL 1.50 spec says: + * + * For uniform blocks declared an array, each individual array + * element corresponds to a separate buffer object backing one + * instance of the block. As the array size indicates the number + * of buffer objects needed, uniform block array declarations + * must specify an array size. + * + * And a few paragraphs later: + * + * Geometry shader input blocks must be declared as arrays and + * follow the array declaration and linking rules for all + * geometry shader inputs. All other input and output block + * arrays must specify an array size. + * + * The upshot of this is that the only circumstance where an + * interface array size *doesn't* need to be specified is on a + * geometry shader input. + */ + if (this->array_size == NULL && + (state->target != geometry_shader || !this->layout.flags.q.in)) { + _mesa_glsl_error(&loc, state, + "only geometry shader inputs may be unsized " + "instance block arrays"); + + } + const glsl_type *block_array_type = process_array_type(&loc, block_type, this->array_size, state); @@ -4386,13 +4618,15 @@ ast_interface_block::hir(exec_list *instructions, } var->interface_type = block_type; + if (state->target == geometry_shader && var_mode == ir_var_shader_in) + handle_geometry_shader_input_decl(state, loc, var); state->symbols->add_variable(var); instructions->push_tail(var); } else { /* In order to have an array size, the block must also be declared with * an instane name. */ - assert(this->array_size == NULL); + assert(!this->is_array); for (unsigned i = 0; i < num_variables; i++) { ir_variable *var = @@ -4416,6 +4650,72 @@ ast_interface_block::hir(exec_list *instructions, return NULL; } + +ir_rvalue * +ast_gs_input_layout::hir(exec_list *instructions, + struct _mesa_glsl_parse_state *state) +{ + YYLTYPE loc = this->get_location(); + + /* If any geometry input layout declaration preceded this one, make sure it + * was consistent with this one. + */ + if (state->gs_input_prim_type_specified && + state->gs_input_prim_type != this->prim_type) { + _mesa_glsl_error(&loc, state, + "geometry shader input layout does not match" + " previous declaration"); + return NULL; + } + + /* If any shader inputs occurred before this declaration and specified an + * array size, make sure the size they specified is consistent with the + * primitive type. + */ + unsigned num_vertices = vertices_per_prim(this->prim_type); + if (state->gs_input_size != 0 && state->gs_input_size != num_vertices) { + _mesa_glsl_error(&loc, state, + "this geometry shader input layout implies %u vertices" + " per primitive, but a previous input is declared" + " with size %u", num_vertices, state->gs_input_size); + return NULL; + } + + state->gs_input_prim_type_specified = true; + state->gs_input_prim_type = this->prim_type; + + /* If any shader inputs occurred before this declaration and did not + * specify an array size, their size is determined now. + */ + foreach_list (node, instructions) { + ir_variable *var = ((ir_instruction *) node)->as_variable(); + if (var == NULL || var->mode != ir_var_shader_in) + continue; + + /* Note: gl_PrimitiveIDIn has mode ir_var_shader_in, but it's not an + * array; skip it. + */ + if (!var->type->is_array()) + continue; + + if (var->type->length == 0) { + if (var->max_array_access >= num_vertices) { + _mesa_glsl_error(&loc, state, + "this geometry shader input layout implies %u" + " vertices, but an access to element %u of input" + " `%s' already exists", num_vertices, + var->max_array_access, var->name); + } else { + var->type = glsl_type::get_array_instance(var->type->fields.array, + num_vertices); + } + } + } + + return NULL; +} + + static void detect_conflicting_assignments(struct _mesa_glsl_parse_state *state, exec_list *instructions) diff --git a/mesalib/src/glsl/ast_type.cpp b/mesalib/src/glsl/ast_type.cpp index 38c3f8eb0..ce6b6a771 100644 --- a/mesalib/src/glsl/ast_type.cpp +++ b/mesalib/src/glsl/ast_type.cpp @@ -133,6 +133,25 @@ ast_type_qualifier::merge_qualifier(YYLTYPE *loc, return false; } + if (q.flags.q.prim_type) { + if (this->flags.q.prim_type && this->prim_type != q.prim_type) { + _mesa_glsl_error(loc, state, + "conflicting primitive type qualifiers used"); + return false; + } + this->prim_type = q.prim_type; + } + + if (q.flags.q.max_vertices) { + if (this->flags.q.max_vertices && this->max_vertices != q.max_vertices) { + _mesa_glsl_error(loc, state, + "geometry shader set conflicting max_vertices " + "(%d and %d)", this->max_vertices, q.max_vertices); + return false; + } + this->max_vertices = q.max_vertices; + } + if ((q.flags.i & ubo_mat_mask.flags.i) != 0) this->flags.i &= ~ubo_mat_mask.flags.i; if ((q.flags.i & ubo_layout_mask.flags.i) != 0) diff --git a/mesalib/src/glsl/builtin_variables.cpp b/mesalib/src/glsl/builtin_variables.cpp index 1e88b6a73..6a808c072 100644 --- a/mesalib/src/glsl/builtin_variables.cpp +++ b/mesalib/src/glsl/builtin_variables.cpp @@ -686,8 +686,11 @@ builtin_variable_generator::generate_gs_special_vars() * the specific case of gl_PrimitiveIDIn. So we don't need to treat * gl_PrimitiveIDIn as an {ARB,EXT}_geometry_shader4-only variable. */ - add_input(VARYING_SLOT_PRIMITIVE_ID, int_t, "gl_PrimitiveIDIn"); - add_output(VARYING_SLOT_PRIMITIVE_ID, int_t, "gl_PrimitiveID"); + ir_variable *var; + var = add_input(VARYING_SLOT_PRIMITIVE_ID, int_t, "gl_PrimitiveIDIn"); + var->interpolation = INTERP_QUALIFIER_FLAT; + var = add_output(VARYING_SLOT_PRIMITIVE_ID, int_t, "gl_PrimitiveID"); + var->interpolation = INTERP_QUALIFIER_FLAT; } @@ -702,6 +705,12 @@ builtin_variable_generator::generate_fs_special_vars() if (state->is_version(120, 100)) add_input(VARYING_SLOT_PNTC, vec2_t, "gl_PointCoord"); + if (state->is_version(150, 0)) { + ir_variable *var = + add_input(VARYING_SLOT_PRIMITIVE_ID, int_t, "gl_PrimitiveID"); + var->interpolation = INTERP_QUALIFIER_FLAT; + } + /* gl_FragColor and gl_FragData were deprecated starting in desktop GLSL * 1.30, and were relegated to the compatibility profile in GLSL 4.20. * They were removed from GLSL ES 3.00. diff --git a/mesalib/src/glsl/glsl_parser.yy b/mesalib/src/glsl/glsl_parser.yy index fcc5620cd..e3a57ea02 100644 --- a/mesalib/src/glsl/glsl_parser.yy +++ b/mesalib/src/glsl/glsl_parser.yy @@ -254,6 +254,7 @@ _mesa_glsl_lex(YYSTYPE *val, YYLTYPE *loc, _mesa_glsl_parse_state *state) %type <node> for_init_statement %type <for_rest_statement> for_rest_statement %type <n> integer_constant +%type <node> layout_defaults %right THEN ELSE %% @@ -1157,7 +1158,8 @@ layout_qualifier_id: memset(& $$, 0, sizeof($$)); /* Layout qualifiers for ARB_fragment_coord_conventions. */ - if (!$$.flags.i && state->ARB_fragment_coord_conventions_enable) { + if (!$$.flags.i && (state->ARB_fragment_coord_conventions_enable || + state->is_version(150, 0))) { if (strcmp($1, "origin_upper_left") == 0) { $$.flags.q.origin_upper_left = 1; } else if (strcmp($1, "pixel_center_integer") == 0) { @@ -1222,6 +1224,34 @@ layout_qualifier_id: } } + /* Layout qualifiers for GLSL 1.50 geometry shaders. */ + if (!$$.flags.i) { + struct { + const char *s; + GLenum e; + } map[] = { + { "points", GL_POINTS }, + { "lines", GL_LINES }, + { "lines_adjacency", GL_LINES_ADJACENCY }, + { "line_strip", GL_LINE_STRIP }, + { "triangles", GL_TRIANGLES }, + { "triangles_adjacency", GL_TRIANGLES_ADJACENCY }, + { "triangle_strip", GL_TRIANGLE_STRIP }, + }; + for (unsigned i = 0; i < Elements(map); i++) { + if (strcmp($1, map[i].s) == 0) { + $$.flags.q.prim_type = 1; + $$.prim_type = map[i].e; + break; + } + } + + if ($$.flags.i && !state->is_version(150, 0)) { + _mesa_glsl_error(& @1, state, "#version 150 layout " + "qualifier `%s' used", $1); + } + } + if (!$$.flags.i) { _mesa_glsl_error(& @1, state, "unrecognized layout identifier " "`%s'", $1); @@ -1264,6 +1294,23 @@ layout_qualifier_id: $$.binding = $3; } + if (strcmp("max_vertices", $1) == 0) { + $$.flags.q.max_vertices = 1; + + if ($3 < 0) { + _mesa_glsl_error(& @3, state, + "invalid max_vertices %d specified", $3); + YYERROR; + } else { + $$.max_vertices = $3; + if (!state->is_version(150, 0)) { + _mesa_glsl_error(& @3, state, + "#version 150 max_vertices qualifier " + "specified", $3); + } + } + } + /* If the identifier didn't match any known layout identifiers, * emit an error. */ @@ -2046,7 +2093,7 @@ external_declaration: function_definition { $$ = $1; } | declaration { $$ = $1; } | pragma_statement { $$ = NULL; } - | layout_defaults { $$ = NULL; } + | layout_defaults { $$ = $1; } ; function_definition: @@ -2197,25 +2244,22 @@ instance_name_opt: /* empty */ { $$ = new(state) ast_interface_block(*state->default_uniform_qualifier, - NULL, NULL); + NULL, false, NULL); } | NEW_IDENTIFIER { $$ = new(state) ast_interface_block(*state->default_uniform_qualifier, - $1, NULL); + $1, false, NULL); } | NEW_IDENTIFIER '[' constant_expression ']' { $$ = new(state) ast_interface_block(*state->default_uniform_qualifier, - $1, $3); + $1, true, $3); } | NEW_IDENTIFIER '[' ']' { - _mesa_glsl_error(& @1, state, - "instance block arrays must be explicitly sized"); - $$ = new(state) ast_interface_block(*state->default_uniform_qualifier, - $1, NULL); + $1, true, NULL); } ; @@ -2263,4 +2307,32 @@ layout_defaults: if (!state->default_uniform_qualifier->merge_qualifier(& @1, state, $1)) { YYERROR; } + $$ = NULL; + } + + | layout_qualifier IN_TOK ';' + { + void *ctx = state; + if (state->target != geometry_shader) { + _mesa_glsl_error(& @1, state, + "input layout qualifiers only valid in " + "geometry shaders"); + } else if (!$1.flags.q.prim_type) { + _mesa_glsl_error(& @1, state, + "input layout qualifiers must specify a primitive" + " type"); + } + $$ = new(ctx) ast_gs_input_layout(@1, $1.prim_type); + } + + | layout_qualifier OUT_TOK ';' + { + if (state->target != geometry_shader) { + _mesa_glsl_error(& @1, state, + "out layout qualifiers only valid in " + "geometry shaders"); + } else if (!state->out_qualifier->merge_qualifier(& @1, state, $1)) { + YYERROR; + } + $$ = NULL; } diff --git a/mesalib/src/glsl/glsl_parser_extras.cpp b/mesalib/src/glsl/glsl_parser_extras.cpp index a5bc20c23..88f048365 100644 --- a/mesalib/src/glsl/glsl_parser_extras.cpp +++ b/mesalib/src/glsl/glsl_parser_extras.cpp @@ -159,6 +159,10 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx, this->default_uniform_qualifier = new(this) ast_type_qualifier(); this->default_uniform_qualifier->flags.q.shared = 1; this->default_uniform_qualifier->flags.q.column_major = 1; + + this->gs_input_prim_type_specified = false; + this->gs_input_prim_type = GL_POINTS; + this->out_qualifier = new(this) ast_type_qualifier(); } /** @@ -1410,6 +1414,34 @@ ast_struct_specifier::ast_struct_specifier(const char *identifier, is_declaration = true; } +static void +set_shader_inout_layout(struct gl_shader *shader, + struct _mesa_glsl_parse_state *state) +{ + if (shader->Type != GL_GEOMETRY_SHADER) { + /* Should have been prevented by the parser. */ + assert(!state->gs_input_prim_type_specified); + assert(!state->out_qualifier->flags.i); + return; + } + + shader->Geom.VerticesOut = 0; + if (state->out_qualifier->flags.q.max_vertices) + shader->Geom.VerticesOut = state->out_qualifier->max_vertices; + + if (state->gs_input_prim_type_specified) { + shader->Geom.InputType = state->gs_input_prim_type; + } else { + shader->Geom.InputType = PRIM_UNKNOWN; + } + + if (state->out_qualifier->flags.q.prim_type) { + shader->Geom.OutputType = state->out_qualifier->prim_type; + } else { + shader->Geom.OutputType = PRIM_UNKNOWN; + } +} + extern "C" { void @@ -1485,6 +1517,9 @@ _mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *shader, shader->UniformBlocks = state->uniform_blocks; ralloc_steal(shader, shader->UniformBlocks); + if (!state->error) + set_shader_inout_layout(shader, state); + /* Retain any live IR, but trash the rest. */ reparent_ir(shader->ir, shader->ir); diff --git a/mesalib/src/glsl/glsl_parser_extras.h b/mesalib/src/glsl/glsl_parser_extras.h index 45f5246f7..7e5a77fa6 100644 --- a/mesalib/src/glsl/glsl_parser_extras.h +++ b/mesalib/src/glsl/glsl_parser_extras.h @@ -170,6 +170,24 @@ struct _mesa_glsl_parse_state { struct ast_type_qualifier *default_uniform_qualifier; /** + * True if a geometry shader input primitive type was specified using a + * layout directive. + * + * Note: this value is computed at ast_to_hir time rather than at parse + * time. + */ + bool gs_input_prim_type_specified; + + /** + * If gs_input_prim_type_specified is true, the primitive type that was + * specified. Otherwise ignored. + */ + GLenum gs_input_prim_type; + + /** Output layout qualifiers from GLSL 1.50. (geometry shader controls)*/ + struct ast_type_qualifier *out_qualifier; + + /** * Printable list of GLSL versions supported by the current context * * \note @@ -302,6 +320,15 @@ struct _mesa_glsl_parse_state { /** Shaders containing built-in functions that are used for linking. */ struct gl_shader *builtins_to_link[16]; unsigned num_builtins_to_link; + + /** + * For geometry shaders, size of the most recently seen input declaration + * that was a sized array, or 0 if no sized input array declarations have + * been seen. + * + * Unused for other shader types. + */ + unsigned gs_input_size; }; # define YYLLOC_DEFAULT(Current, Rhs, N) \ diff --git a/mesalib/src/glsl/glsl_types.cpp b/mesalib/src/glsl/glsl_types.cpp index 8324b8ade..0c7e8eb11 100644 --- a/mesalib/src/glsl/glsl_types.cpp +++ b/mesalib/src/glsl/glsl_types.cpp @@ -828,3 +828,58 @@ glsl_type::std140_size(bool row_major) const assert(!"not reached"); return -1; } + + +unsigned +glsl_type::count_attribute_slots() const +{ + /* From page 31 (page 37 of the PDF) of the GLSL 1.50 spec: + * + * "A scalar input counts the same amount against this limit as a vec4, + * so applications may want to consider packing groups of four + * unrelated float inputs together into a vector to better utilize the + * capabilities of the underlying hardware. A matrix input will use up + * multiple locations. The number of locations used will equal the + * number of columns in the matrix." + * + * The spec does not explicitly say how arrays are counted. However, it + * should be safe to assume the total number of slots consumed by an array + * is the number of entries in the array multiplied by the number of slots + * consumed by a single element of the array. + * + * The spec says nothing about how structs are counted, because vertex + * attributes are not allowed to be (or contain) structs. However, Mesa + * allows varying structs, the number of varying slots taken up by a + * varying struct is simply equal to the sum of the number of slots taken + * up by each element. + */ + switch (this->base_type) { + case GLSL_TYPE_UINT: + case GLSL_TYPE_INT: + case GLSL_TYPE_FLOAT: + case GLSL_TYPE_BOOL: + return this->matrix_columns; + + case GLSL_TYPE_STRUCT: + case GLSL_TYPE_INTERFACE: { + unsigned size = 0; + + for (unsigned i = 0; i < this->length; i++) + size += this->fields.structure[i].type->count_attribute_slots(); + + return size; + } + + case GLSL_TYPE_ARRAY: + return this->length * this->fields.array->count_attribute_slots(); + + case GLSL_TYPE_SAMPLER: + case GLSL_TYPE_VOID: + case GLSL_TYPE_ERROR: + break; + } + + assert(!"Unexpected type in count_attribute_slots()"); + + return 0; +} diff --git a/mesalib/src/glsl/glsl_types.h b/mesalib/src/glsl/glsl_types.h index 8172309a7..647867a23 100644 --- a/mesalib/src/glsl/glsl_types.h +++ b/mesalib/src/glsl/glsl_types.h @@ -253,6 +253,18 @@ struct glsl_type { unsigned component_slots() const; /** + * Calculate the number of attribute slots required to hold this type + * + * This implements the language rules of GLSL 1.50 for counting the number + * of slots used by a vertex attribute. It also determines the number of + * varying slots the type will use up in the absence of varying packing + * (and thus, it can be used to measure the number of varying slots used by + * the varyings that are generated by lower_packed_varyings). + */ + unsigned count_attribute_slots() const; + + + /** * Alignment in bytes of the start of this type in a std140 uniform * block. */ diff --git a/mesalib/src/glsl/ir.cpp b/mesalib/src/glsl/ir.cpp index dad58deeb..99dceacf8 100644 --- a/mesalib/src/glsl/ir.cpp +++ b/mesalib/src/glsl/ir.cpp @@ -1778,3 +1778,24 @@ ir_rvalue::as_rvalue_to_saturate() return NULL; } + + +unsigned +vertices_per_prim(GLenum prim) +{ + switch (prim) { + case GL_POINTS: + return 1; + case GL_LINES: + return 2; + case GL_TRIANGLES: + return 3; + case GL_LINES_ADJACENCY: + return 4; + case GL_TRIANGLES_ADJACENCY: + return 6; + default: + assert(!"Bad primitive"); + return 3; + } +} diff --git a/mesalib/src/glsl/ir.h b/mesalib/src/glsl/ir.h index 7ac291cf4..62e3b27ca 100644 --- a/mesalib/src/glsl/ir.h +++ b/mesalib/src/glsl/ir.h @@ -81,6 +81,8 @@ enum ir_node_type { ir_type_return, ir_type_swizzle, ir_type_texture, + ir_type_emit_vertex, + ir_type_end_primitive, ir_type_max /**< maximum ir_type enum number, for validation */ }; @@ -519,6 +521,8 @@ public: * * - Vertex shader input: one of the values from \c gl_vert_attrib. * - Vertex shader output: one of the values from \c gl_varying_slot. + * - Geometry shader input: one of the values from \c gl_varying_slot. + * - Geometry shader output: one of the values from \c gl_varying_slot. * - Fragment shader input: one of the values from \c gl_varying_slot. * - Fragment shader output: one of the values from \c gl_frag_result. * - Uniforms: Per-stage uniform slot number for default uniform block. @@ -1992,6 +1996,53 @@ private: /*@}*/ /** + * IR instruction to emit a vertex in a geometry shader. + */ +class ir_emit_vertex : public ir_instruction { +public: + ir_emit_vertex() + { + ir_type = ir_type_emit_vertex; + } + + virtual void accept(ir_visitor *v) + { + v->visit(this); + } + + virtual ir_emit_vertex *clone(void *mem_ctx, struct hash_table *) const + { + return new(mem_ctx) ir_emit_vertex(); + } + + virtual ir_visitor_status accept(ir_hierarchical_visitor *); +}; + +/** + * IR instruction to complete the current primitive and start a new one in a + * geometry shader. + */ +class ir_end_primitive : public ir_instruction { +public: + ir_end_primitive() + { + ir_type = ir_type_end_primitive; + } + + virtual void accept(ir_visitor *v) + { + v->visit(this); + } + + virtual ir_end_primitive *clone(void *mem_ctx, struct hash_table *) const + { + return new(mem_ctx) ir_end_primitive(); + } + + virtual ir_visitor_status accept(ir_hierarchical_visitor *); +}; + +/** * Apply a visitor to each IR node in a list */ void @@ -2061,7 +2112,7 @@ ir_has_call(ir_instruction *ir); extern void do_set_program_inouts(exec_list *instructions, struct gl_program *prog, - bool is_fragment_shader); + GLenum shader_type); extern char * prototype_string(const glsl_type *return_type, const char *name, @@ -2077,4 +2128,7 @@ extern void _mesa_print_ir(struct exec_list *instructions, } /* extern "C" */ #endif +unsigned +vertices_per_prim(GLenum prim); + #endif /* IR_H */ diff --git a/mesalib/src/glsl/ir_builder.cpp b/mesalib/src/glsl/ir_builder.cpp index 8fb30a02a..7d9cf5e47 100644 --- a/mesalib/src/glsl/ir_builder.cpp +++ b/mesalib/src/glsl/ir_builder.cpp @@ -219,6 +219,12 @@ saturate(operand a) new(mem_ctx) ir_constant(0.0f)); } +ir_expression * +abs(operand a) +{ + return expr(ir_unop_abs, a); +} + ir_expression* equal(operand a, operand b) { @@ -226,6 +232,12 @@ equal(operand a, operand b) } ir_expression* +nequal(operand a, operand b) +{ + return expr(ir_binop_nequal, a, b); +} + +ir_expression* less(operand a, operand b) { return expr(ir_binop_less, a, b); @@ -304,12 +316,24 @@ f2i(operand a) } ir_expression* +bitcast_f2i(operand a) +{ + return expr(ir_unop_bitcast_f2i, a); +} + +ir_expression* i2f(operand a) { return expr(ir_unop_i2f, a); } ir_expression* +bitcast_i2f(operand a) +{ + return expr(ir_unop_bitcast_i2f, a); +} + +ir_expression* i2u(operand a) { return expr(ir_unop_i2u, a); @@ -328,11 +352,35 @@ f2u(operand a) } ir_expression* +bitcast_f2u(operand a) +{ + return expr(ir_unop_bitcast_f2u, a); +} + +ir_expression* u2f(operand a) { return expr(ir_unop_u2f, a); } +ir_expression* +bitcast_u2f(operand a) +{ + return expr(ir_unop_bitcast_u2f, a); +} + +ir_expression* +i2b(operand a) +{ + return expr(ir_unop_i2b, a); +} + +ir_expression* +b2i(operand a) +{ + return expr(ir_unop_b2i, a); +} + ir_if* if_tree(operand condition, ir_instruction *then_branch) diff --git a/mesalib/src/glsl/ir_builder.h b/mesalib/src/glsl/ir_builder.h index 690ac74eb..7049476a1 100644 --- a/mesalib/src/glsl/ir_builder.h +++ b/mesalib/src/glsl/ir_builder.h @@ -133,8 +133,10 @@ ir_expression *round_even(operand a); ir_expression *dot(operand a, operand b); ir_expression *clamp(operand a, operand b, operand c); ir_expression *saturate(operand a); +ir_expression *abs(operand a); ir_expression *equal(operand a, operand b); +ir_expression *nequal(operand a, operand b); ir_expression *less(operand a, operand b); ir_expression *greater(operand a, operand b); ir_expression *lequal(operand a, operand b); @@ -151,11 +153,17 @@ ir_expression *lshift(operand a, operand b); ir_expression *rshift(operand a, operand b); ir_expression *f2i(operand a); +ir_expression *bitcast_f2i(operand a); ir_expression *i2f(operand a); +ir_expression *bitcast_i2f(operand a); ir_expression *f2u(operand a); +ir_expression *bitcast_f2u(operand a); ir_expression *u2f(operand a); +ir_expression *bitcast_u2f(operand a); ir_expression *i2u(operand a); ir_expression *u2i(operand a); +ir_expression *b2i(operand a); +ir_expression *i2b(operand a); /** * Swizzle away later components, but preserve the ordering. diff --git a/mesalib/src/glsl/ir_hierarchical_visitor.cpp b/mesalib/src/glsl/ir_hierarchical_visitor.cpp index f24414046..2e606dda4 100644 --- a/mesalib/src/glsl/ir_hierarchical_visitor.cpp +++ b/mesalib/src/glsl/ir_hierarchical_visitor.cpp @@ -69,6 +69,24 @@ ir_hierarchical_visitor::visit(ir_loop_jump *ir) } ir_visitor_status +ir_hierarchical_visitor::visit(ir_emit_vertex *ir) +{ + if (this->callback != NULL) + this->callback(ir, this->data); + + return visit_continue; +} + +ir_visitor_status +ir_hierarchical_visitor::visit(ir_end_primitive *ir) +{ + if (this->callback != NULL) + this->callback(ir, this->data); + + return visit_continue; +} + +ir_visitor_status ir_hierarchical_visitor::visit(ir_dereference_variable *ir) { if (this->callback != NULL) diff --git a/mesalib/src/glsl/ir_hierarchical_visitor.h b/mesalib/src/glsl/ir_hierarchical_visitor.h index 1988ad091..647d2e002 100644 --- a/mesalib/src/glsl/ir_hierarchical_visitor.h +++ b/mesalib/src/glsl/ir_hierarchical_visitor.h @@ -87,6 +87,8 @@ public: virtual ir_visitor_status visit(class ir_variable *); virtual ir_visitor_status visit(class ir_constant *); virtual ir_visitor_status visit(class ir_loop_jump *); + virtual ir_visitor_status visit(class ir_emit_vertex *); + virtual ir_visitor_status visit(class ir_end_primitive *); /** * ir_dereference_variable isn't technically a leaf, but it is treated as a diff --git a/mesalib/src/glsl/ir_hv_accept.cpp b/mesalib/src/glsl/ir_hv_accept.cpp index 559b71af3..76a607d17 100644 --- a/mesalib/src/glsl/ir_hv_accept.cpp +++ b/mesalib/src/glsl/ir_hv_accept.cpp @@ -415,3 +415,16 @@ ir_if::accept(ir_hierarchical_visitor *v) return v->visit_leave(this); } + +ir_visitor_status +ir_emit_vertex::accept(ir_hierarchical_visitor *v) +{ + return v->visit(this); +} + + +ir_visitor_status +ir_end_primitive::accept(ir_hierarchical_visitor *v) +{ + return v->visit(this); +} diff --git a/mesalib/src/glsl/ir_optimization.h b/mesalib/src/glsl/ir_optimization.h index 2c1479ff4..b79c2b787 100644 --- a/mesalib/src/glsl/ir_optimization.h +++ b/mesalib/src/glsl/ir_optimization.h @@ -77,7 +77,7 @@ 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, + gl_shader *producer, gl_shader *consumer, unsigned num_tfeedback_decls, class tfeedback_decl *tfeedback_decls); bool do_dead_code(exec_list *instructions, bool uniform_locations_assigned); @@ -112,7 +112,7 @@ bool lower_packing_builtins(exec_list *instructions, int op_mask); void lower_ubo_reference(struct gl_shader *shader, exec_list *instructions); void lower_packed_varyings(void *mem_ctx, unsigned location_base, unsigned locations_used, ir_variable_mode mode, - gl_shader *shader); + unsigned gs_input_vertices, gl_shader *shader); bool lower_vector_insert(exec_list *instructions, bool lower_nonconstant_index); void lower_named_interface_blocks(void *mem_ctx, gl_shader *shader); bool optimize_redundant_jumps(exec_list *instructions); diff --git a/mesalib/src/glsl/ir_print_visitor.cpp b/mesalib/src/glsl/ir_print_visitor.cpp index ca973a5f3..541231a33 100644 --- a/mesalib/src/glsl/ir_print_visitor.cpp +++ b/mesalib/src/glsl/ir_print_visitor.cpp @@ -539,3 +539,15 @@ ir_print_visitor::visit(ir_loop_jump *ir) { printf("%s", ir->is_break() ? "break" : "continue"); } + +void +ir_print_visitor::visit(ir_emit_vertex *ir) +{ + printf("(emit-vertex)"); +} + +void +ir_print_visitor::visit(ir_end_primitive *ir) +{ + printf("(end-primitive)"); +} diff --git a/mesalib/src/glsl/ir_print_visitor.h b/mesalib/src/glsl/ir_print_visitor.h index a84056d16..865376fe0 100644 --- a/mesalib/src/glsl/ir_print_visitor.h +++ b/mesalib/src/glsl/ir_print_visitor.h @@ -69,6 +69,8 @@ public: virtual void visit(ir_if *); virtual void visit(ir_loop *); virtual void visit(ir_loop_jump *); + virtual void visit(ir_emit_vertex *); + virtual void visit(ir_end_primitive *); /*@}*/ private: diff --git a/mesalib/src/glsl/ir_reader.cpp b/mesalib/src/glsl/ir_reader.cpp index 51534ca7c..f263fe810 100644 --- a/mesalib/src/glsl/ir_reader.cpp +++ b/mesalib/src/glsl/ir_reader.cpp @@ -59,6 +59,8 @@ private: ir_swizzle *read_swizzle(s_expression *); ir_constant *read_constant(s_expression *); ir_texture *read_texture(s_expression *); + ir_emit_vertex *read_emit_vertex(s_expression *); + ir_end_primitive *read_end_primitive(s_expression *); ir_dereference *read_dereference(s_expression *); ir_dereference_variable *read_var_ref(s_expression *); @@ -355,6 +357,10 @@ ir_reader::read_instruction(s_expression *expr, ir_loop *loop_ctx) inst = read_return(list); } else if (strcmp(tag->value(), "function") == 0) { inst = read_function(list, false); + } else if (strcmp(tag->value(), "emit-vertex") == 0) { + inst = read_emit_vertex(list); + } else if (strcmp(tag->value(), "end-primitive") == 0) { + inst = read_end_primitive(list); } else { inst = read_rvalue(list); if (inst == NULL) @@ -1065,3 +1071,27 @@ ir_reader::read_texture(s_expression *expr) }; return tex; } + +ir_emit_vertex * +ir_reader::read_emit_vertex(s_expression *expr) +{ + s_pattern pat[] = { "emit-vertex" }; + + if (MATCH(expr, pat)) { + return new(mem_ctx) ir_emit_vertex(); + } + ir_read_error(NULL, "when reading emit-vertex"); + return NULL; +} + +ir_end_primitive * +ir_reader::read_end_primitive(s_expression *expr) +{ + s_pattern pat[] = { "end-primitive" }; + + if (MATCH(expr, pat)) { + return new(mem_ctx) ir_end_primitive(); + } + ir_read_error(NULL, "when reading end-primitive"); + return NULL; +} diff --git a/mesalib/src/glsl/ir_set_program_inouts.cpp b/mesalib/src/glsl/ir_set_program_inouts.cpp index 91a8b4526..6196d6a64 100644 --- a/mesalib/src/glsl/ir_set_program_inouts.cpp +++ b/mesalib/src/glsl/ir_set_program_inouts.cpp @@ -44,11 +44,10 @@ class ir_set_program_inouts_visitor : public ir_hierarchical_visitor { public: - ir_set_program_inouts_visitor(struct gl_program *prog, - bool is_fragment_shader) + ir_set_program_inouts_visitor(struct gl_program *prog, GLenum shader_type) { this->prog = prog; - this->is_fragment_shader = is_fragment_shader; + this->shader_type = shader_type; } ~ir_set_program_inouts_visitor() { @@ -60,8 +59,12 @@ public: virtual ir_visitor_status visit_enter(ir_discard *); virtual ir_visitor_status visit(ir_dereference_variable *); +private: + void mark_whole_variable(ir_variable *var); + bool try_mark_partial_variable(ir_variable *var, ir_rvalue *index); + struct gl_program *prog; - bool is_fragment_shader; + GLenum shader_type; }; static inline bool @@ -104,6 +107,23 @@ mark(struct gl_program *prog, ir_variable *var, int offset, int len, } } +/** + * Mark an entire variable as used. Caller must ensure that the variable + * represents a shader input or output. + */ +void +ir_set_program_inouts_visitor::mark_whole_variable(ir_variable *var) +{ + const glsl_type *type = var->type; + if (this->shader_type == GL_GEOMETRY_SHADER && + var->mode == ir_var_shader_in && type->is_array()) { + type = type->fields.array; + } + + mark(this->prog, var, 0, type->count_attribute_slots(), + this->shader_type == GL_FRAGMENT_SHADER); +} + /* Default handler: Mark all the locations in the variable as used. */ ir_visitor_status ir_set_program_inouts_visitor::visit(ir_dereference_variable *ir) @@ -111,43 +131,154 @@ ir_set_program_inouts_visitor::visit(ir_dereference_variable *ir) if (!is_shader_inout(ir->var)) return visit_continue; - if (ir->type->is_array()) { - mark(this->prog, ir->var, 0, - ir->type->length * ir->type->fields.array->matrix_columns, - this->is_fragment_shader); - } else { - mark(this->prog, ir->var, 0, ir->type->matrix_columns, - this->is_fragment_shader); - } + mark_whole_variable(ir->var); return visit_continue; } -ir_visitor_status -ir_set_program_inouts_visitor::visit_enter(ir_dereference_array *ir) +/** + * Try to mark a portion of the given variable as used. Caller must ensure + * that the variable represents a shader input or output which can be indexed + * into in array fashion (an array or matrix). For the purpose of geometry + * shader inputs (which are always arrays*), this means that the array element + * must be something that can be indexed into in array fashion. + * + * *Except gl_PrimitiveIDIn, as noted below. + * + * If the index can't be interpreted as a constant, or some other problem + * occurs, then nothing will be marked and false will be returned. + */ +bool +ir_set_program_inouts_visitor::try_mark_partial_variable(ir_variable *var, + ir_rvalue *index) { - ir_dereference_variable *deref_var; - ir_constant *index = ir->array_index->as_constant(); - deref_var = ir->array->as_dereference_variable(); - ir_variable *var = deref_var ? deref_var->var : NULL; + const glsl_type *type = var->type; - /* Check that we're dereferencing a shader in or out */ - if (!var || !is_shader_inout(var)) - return visit_continue; + if (this->shader_type == GL_GEOMETRY_SHADER && + var->mode == ir_var_shader_in) { + /* The only geometry shader input that is not an array is + * gl_PrimitiveIDIn, and in that case, this code will never be reached, + * because gl_PrimitiveIDIn can't be indexed into in array fashion. + */ + assert(type->is_array()); + type = type->fields.array; + } - if (index) { - int width = 1; + /* The code below only handles: + * + * - Indexing into matrices + * - Indexing into arrays of (matrices, vectors, or scalars) + * + * All other possibilities are either prohibited by GLSL (vertex inputs and + * fragment outputs can't be structs) or should have been eliminated by + * lowering passes (do_vec_index_to_swizzle() gets rid of indexing into + * vectors, and lower_packed_varyings() gets rid of structs that occur in + * varyings). + */ + if (!(type->is_matrix() || + (type->is_array() && + (type->fields.array->is_numeric() || + type->fields.array->is_boolean())))) { + assert(!"Unexpected indexing in ir_set_program_inouts"); - if (deref_var->type->is_array() && - deref_var->type->fields.array->is_matrix()) { - width = deref_var->type->fields.array->matrix_columns; - } + /* For safety in release builds, in case we ever encounter unexpected + * indexing, give up and let the caller mark the whole variable as used. + */ + return false; + } + + ir_constant *index_as_constant = index->as_constant(); + if (!index_as_constant) + return false; + + unsigned elem_width; + unsigned num_elems; + if (type->is_array()) { + num_elems = type->length; + if (type->fields.array->is_matrix()) + elem_width = type->fields.array->matrix_columns; + else + elem_width = 1; + } else { + num_elems = type->matrix_columns; + elem_width = 1; + } - mark(this->prog, var, index->value.i[0] * width, width, - this->is_fragment_shader); - return visit_continue_with_parent; + if (index_as_constant->value.u[0] >= num_elems) { + /* Constant index outside the bounds of the matrix/array. This could + * arise as a result of constant folding of a legal GLSL program. + * + * Even though the spec says that indexing outside the bounds of a + * matrix/array results in undefined behaviour, we don't want to pass + * out-of-range values to mark() (since this could result in slots that + * don't exist being marked as used), so just let the caller mark the + * whole variable as used. + */ + return false; } + mark(this->prog, var, index_as_constant->value.u[0] * elem_width, + elem_width, this->shader_type == GL_FRAGMENT_SHADER); + return true; +} + +ir_visitor_status +ir_set_program_inouts_visitor::visit_enter(ir_dereference_array *ir) +{ + /* Note: for geometry shader inputs, lower_named_interface_blocks may + * create 2D arrays, so we need to be able to handle those. 2D arrays + * shouldn't be able to crop up for any other reason. + */ + if (ir_dereference_array * const inner_array = + ir->array->as_dereference_array()) { + /* ir => foo[i][j] + * inner_array => foo[i] + */ + if (ir_dereference_variable * const deref_var = + inner_array->array->as_dereference_variable()) { + if (this->shader_type == GL_GEOMETRY_SHADER && + deref_var->var->mode == ir_var_shader_in) { + /* foo is a geometry shader input, so i is the vertex, and j the + * part of the input we're accessing. + */ + if (try_mark_partial_variable(deref_var->var, ir->array_index)) + { + /* We've now taken care of foo and j, but i might contain a + * subexpression that accesses shader inputs. So manually + * visit i and then continue with the parent. + */ + inner_array->array_index->accept(this); + return visit_continue_with_parent; + } + } + } + } else if (ir_dereference_variable * const deref_var = + ir->array->as_dereference_variable()) { + /* ir => foo[i], where foo is a variable. */ + if (this->shader_type == GL_GEOMETRY_SHADER && + deref_var->var->mode == ir_var_shader_in) { + /* foo is a geometry shader input, so i is the vertex, and we're + * accessing the entire input. + */ + mark_whole_variable(deref_var->var); + /* We've now taken care of foo, but i might contain a subexpression + * that accesses shader inputs. So manually visit i and then + * continue with the parent. + */ + ir->array_index->accept(this); + return visit_continue_with_parent; + } else if (is_shader_inout(deref_var->var)) { + /* foo is a shader input/output, but not a geometry shader input, + * so i is the part of the input we're accessing. + */ + if (try_mark_partial_variable(deref_var->var, ir->array_index)) + return visit_continue_with_parent; + } + } + + /* The expression is something we don't recognize. Just visit its + * subexpressions. + */ return visit_continue; } @@ -164,7 +295,8 @@ ir_set_program_inouts_visitor::visit_enter(ir_function_signature *ir) ir_visitor_status ir_set_program_inouts_visitor::visit_enter(ir_expression *ir) { - if (is_fragment_shader && ir->operation == ir_unop_dFdy) { + if (this->shader_type == GL_FRAGMENT_SHADER && + ir->operation == ir_unop_dFdy) { gl_fragment_program *fprog = (gl_fragment_program *) prog; fprog->UsesDFdy = true; } @@ -175,7 +307,7 @@ ir_visitor_status ir_set_program_inouts_visitor::visit_enter(ir_discard *) { /* discards are only allowed in fragment shaders. */ - assert(is_fragment_shader); + assert(this->shader_type == GL_FRAGMENT_SHADER); gl_fragment_program *fprog = (gl_fragment_program *) prog; fprog->UsesKill = true; @@ -185,14 +317,14 @@ ir_set_program_inouts_visitor::visit_enter(ir_discard *) void do_set_program_inouts(exec_list *instructions, struct gl_program *prog, - bool is_fragment_shader) + GLenum shader_type) { - ir_set_program_inouts_visitor v(prog, is_fragment_shader); + ir_set_program_inouts_visitor v(prog, shader_type); prog->InputsRead = 0; prog->OutputsWritten = 0; prog->SystemValuesRead = 0; - if (is_fragment_shader) { + if (shader_type == GL_FRAGMENT_SHADER) { gl_fragment_program *fprog = (gl_fragment_program *) prog; memset(fprog->InterpQualifier, 0, sizeof(fprog->InterpQualifier)); fprog->IsCentroid = 0; diff --git a/mesalib/src/glsl/ir_visitor.h b/mesalib/src/glsl/ir_visitor.h index bd47ef7d5..40f96ffbc 100644 --- a/mesalib/src/glsl/ir_visitor.h +++ b/mesalib/src/glsl/ir_visitor.h @@ -63,6 +63,8 @@ public: virtual void visit(class ir_if *) = 0; virtual void visit(class ir_loop *) = 0; virtual void visit(class ir_loop_jump *) = 0; + virtual void visit(class ir_emit_vertex *) = 0; + virtual void visit(class ir_end_primitive *) = 0; /*@}*/ }; @@ -81,6 +83,8 @@ public: virtual void visit(class ir_assignment *) {} virtual void visit(class ir_constant *) {} virtual void visit(class ir_call *) {} + virtual void visit(class ir_emit_vertex *) {} + virtual void visit(class ir_end_primitive *) {} }; #endif /* __cplusplus */ diff --git a/mesalib/src/glsl/link_varyings.cpp b/mesalib/src/glsl/link_varyings.cpp index 2c7e4514e..4ceb1d33e 100644 --- a/mesalib/src/glsl/link_varyings.cpp +++ b/mesalib/src/glsl/link_varyings.cpp @@ -68,6 +68,10 @@ cross_validate_outputs_to_inputs(struct gl_shader_program *prog, /* Find all shader inputs in the "consumer" stage. Any variables that have * matching outputs already in the symbol table must have the same type and * qualifiers. + * + * Exception: if the consumer is the geometry shader, then the inputs + * should be arrays and the type of the array element should match the type + * of the corresponding producer output. */ foreach_list(node, consumer->ir) { ir_variable *const input = ((ir_instruction *) node)->as_variable(); @@ -79,7 +83,12 @@ cross_validate_outputs_to_inputs(struct gl_shader_program *prog, if (output != NULL) { /* Check that the types match between stages. */ - if (input->type != output->type) { + const glsl_type *type_to_match = input->type; + if (consumer->Type == GL_GEOMETRY_SHADER) { + assert(type_to_match->is_array()); /* Enforced by ast_to_hir */ + type_to_match = type_to_match->element_type(); + } + if (type_to_match != output->type) { /* There is a bit of a special case for gl_TexCoord. This * built-in is unsized by default. Applications that variable * access it must redeclare it with a size. There is some @@ -973,6 +982,9 @@ private: * each of these objects that matches one of the outputs of the * producer. * + * \param gs_input_vertices: if \c consumer is a geometry shader, this is the + * number of input vertices it accepts. Otherwise zero. + * * When num_tfeedback_decls is nonzero, it is permissible for the consumer to * be NULL. In this case, varying locations are assigned solely based on the * requirements of transform feedback. @@ -983,7 +995,8 @@ assign_varying_locations(struct gl_context *ctx, struct gl_shader_program *prog, gl_shader *producer, gl_shader *consumer, unsigned num_tfeedback_decls, - tfeedback_decl *tfeedback_decls) + tfeedback_decl *tfeedback_decls, + unsigned gs_input_vertices) { const unsigned producer_base = VARYING_SLOT_VAR0; const unsigned consumer_base = VARYING_SLOT_VAR0; @@ -1104,10 +1117,10 @@ assign_varying_locations(struct gl_context *ctx, assert(!ctx->Extensions.EXT_transform_feedback); } else { lower_packed_varyings(mem_ctx, producer_base, slots_used, - ir_var_shader_out, producer); + ir_var_shader_out, 0, producer); if (consumer) { lower_packed_varyings(mem_ctx, consumer_base, slots_used, - ir_var_shader_in, consumer); + ir_var_shader_in, gs_input_vertices, consumer); } } @@ -1164,7 +1177,7 @@ check_against_varying_limit(struct gl_context *ctx, /* The packing rules used for vertex shader inputs are also * used for fragment shader inputs. */ - varying_vectors += count_attribute_slots(var->type); + varying_vectors += var->type->count_attribute_slots(); } } diff --git a/mesalib/src/glsl/link_varyings.h b/mesalib/src/glsl/link_varyings.h index cfc6e474f..302ab5c26 100644 --- a/mesalib/src/glsl/link_varyings.h +++ b/mesalib/src/glsl/link_varyings.h @@ -234,7 +234,8 @@ assign_varying_locations(struct gl_context *ctx, struct gl_shader_program *prog, gl_shader *producer, gl_shader *consumer, unsigned num_tfeedback_decls, - tfeedback_decl *tfeedback_decls); + tfeedback_decl *tfeedback_decls, + unsigned gs_input_vertices); bool check_against_varying_limit(struct gl_context *ctx, diff --git a/mesalib/src/glsl/linker.cpp b/mesalib/src/glsl/linker.cpp index 942f90615..f87ae0eec 100644 --- a/mesalib/src/glsl/linker.cpp +++ b/mesalib/src/glsl/linker.cpp @@ -73,11 +73,15 @@ #include "linker.h" #include "link_varyings.h" #include "ir_optimization.h" +#include "ir_rvalue_visitor.h" extern "C" { #include "main/shaderobj.h" +#include "main/enums.h" } +void linker_error(gl_shader_program *, const char *, ...); + /** * Visitor that determines whether or not a variable is ever written. */ @@ -174,6 +178,77 @@ private: }; +class geom_array_resize_visitor : public ir_hierarchical_visitor { +public: + unsigned num_vertices; + gl_shader_program *prog; + + geom_array_resize_visitor(unsigned num_vertices, gl_shader_program *prog) + { + this->num_vertices = num_vertices; + this->prog = prog; + } + + virtual ~geom_array_resize_visitor() + { + /* empty */ + } + + virtual ir_visitor_status visit(ir_variable *var) + { + if (!var->type->is_array() || var->mode != ir_var_shader_in) + return visit_continue; + + unsigned size = var->type->length; + + /* Generate a link error if the shader has declared this array with an + * incorrect size. + */ + if (size && size != this->num_vertices) { + linker_error(this->prog, "size of array %s declared as %u, " + "but number of input vertices is %u\n", + var->name, size, this->num_vertices); + return visit_continue; + } + + /* Generate a link error if the shader attempts to access an input + * array using an index too large for its actual size assigned at link + * time. + */ + if (var->max_array_access >= this->num_vertices) { + linker_error(this->prog, "geometry shader accesses element %i of " + "%s, but only %i input vertices\n", + var->max_array_access, var->name, this->num_vertices); + return visit_continue; + } + + var->type = glsl_type::get_array_instance(var->type->element_type(), + this->num_vertices); + var->max_array_access = this->num_vertices - 1; + + return visit_continue; + } + + /* Dereferences of input variables need to be updated so that their type + * matches the newly assigned type of the variable they are accessing. */ + virtual ir_visitor_status visit(ir_dereference_variable *ir) + { + ir->type = ir->var->type; + return visit_continue; + } + + /* Dereferences of 2D input arrays need to be updated so that their type + * matches the newly assigned type of the array they are accessing. */ + virtual ir_visitor_status visit_leave(ir_dereference_array *ir) + { + const glsl_type *const vt = ir->array->type; + if (vt->is_array()) + ir->type = vt->element_type(); + return visit_continue; + } +}; + + void linker_error(gl_shader_program *prog, const char *fmt, ...) { @@ -298,41 +373,6 @@ link_invalidate_variable_locations(gl_shader *sh, int input_base, /** - * Determine the number of attribute slots required for a particular type - * - * This code is here because it implements the language rules of a specific - * GLSL version. Since it's a property of the language and not a property of - * types in general, it doesn't really belong in glsl_type. - */ -unsigned -count_attribute_slots(const glsl_type *t) -{ - /* From page 31 (page 37 of the PDF) of the GLSL 1.50 spec: - * - * "A scalar input counts the same amount against this limit as a vec4, - * so applications may want to consider packing groups of four - * unrelated float inputs together into a vector to better utilize the - * capabilities of the underlying hardware. A matrix input will use up - * multiple locations. The number of locations used will equal the - * number of columns in the matrix." - * - * The spec does not explicitly say how arrays are counted. However, it - * should be safe to assume the total number of slots consumed by an array - * is the number of entries in the array multiplied by the number of slots - * consumed by a single element of the array. - */ - - if (t->is_array()) - return t->array_size() * count_attribute_slots(t->element_type()); - - if (t->is_matrix()) - return t->matrix_columns; - - return 1; -} - - -/** * Verify that a vertex shader executable meets all semantic requirements. * * Also sets prog->Vert.UsesClipDistance and prog->Vert.ClipDistanceArraySize @@ -437,6 +477,24 @@ validate_fragment_shader_executable(struct gl_shader_program *prog, } } +/** + * Verify that a geometry shader executable meets all semantic requirements + * + * Also sets prog->Geom.VerticesIn as a side effect. + * + * \param shader Geometry shader executable to be verified + */ +void +validate_geometry_shader_executable(struct gl_shader_program *prog, + struct gl_shader *shader) +{ + if (shader == NULL) + return; + + unsigned num_vertices = vertices_per_prim(prog->Geom.InputType); + prog->Geom.VerticesIn = num_vertices; +} + /** * Generate a string describing the mode of a variable @@ -931,6 +989,99 @@ public: }; /** + * Performs the cross-validation of geometry shader max_vertices and + * primitive type layout qualifiers for the attached geometry shaders, + * and propagates them to the linked GS and linked shader program. + */ +static void +link_gs_inout_layout_qualifiers(struct gl_shader_program *prog, + struct gl_shader *linked_shader, + struct gl_shader **shader_list, + unsigned num_shaders) +{ + linked_shader->Geom.VerticesOut = 0; + linked_shader->Geom.InputType = PRIM_UNKNOWN; + linked_shader->Geom.OutputType = PRIM_UNKNOWN; + + /* No in/out qualifiers defined for anything but GLSL 1.50+ + * geometry shaders so far. + */ + if (linked_shader->Type != GL_GEOMETRY_SHADER || prog->Version < 150) + return; + + /* From the GLSL 1.50 spec, page 46: + * + * "All geometry shader output layout declarations in a program + * must declare the same layout and same value for + * max_vertices. There must be at least one geometry output + * layout declaration somewhere in a program, but not all + * geometry shaders (compilation units) are required to + * declare it." + */ + + for (unsigned i = 0; i < num_shaders; i++) { + struct gl_shader *shader = shader_list[i]; + + if (shader->Geom.InputType != PRIM_UNKNOWN) { + if (linked_shader->Geom.InputType != PRIM_UNKNOWN && + linked_shader->Geom.InputType != shader->Geom.InputType) { + linker_error(prog, "geometry shader defined with conflicting " + "input types\n"); + return; + } + linked_shader->Geom.InputType = shader->Geom.InputType; + } + + if (shader->Geom.OutputType != PRIM_UNKNOWN) { + if (linked_shader->Geom.OutputType != PRIM_UNKNOWN && + linked_shader->Geom.OutputType != shader->Geom.OutputType) { + linker_error(prog, "geometry shader defined with conflicting " + "output types\n"); + return; + } + linked_shader->Geom.OutputType = shader->Geom.OutputType; + } + + if (shader->Geom.VerticesOut != 0) { + if (linked_shader->Geom.VerticesOut != 0 && + linked_shader->Geom.VerticesOut != shader->Geom.VerticesOut) { + linker_error(prog, "geometry shader defined with conflicting " + "output vertex count (%d and %d)\n", + linked_shader->Geom.VerticesOut, + shader->Geom.VerticesOut); + return; + } + linked_shader->Geom.VerticesOut = shader->Geom.VerticesOut; + } + } + + /* Just do the intrastage -> interstage propagation right now, + * since we already know we're in the right type of shader program + * for doing it. + */ + if (linked_shader->Geom.InputType == PRIM_UNKNOWN) { + linker_error(prog, + "geometry shader didn't declare primitive input type\n"); + return; + } + prog->Geom.InputType = linked_shader->Geom.InputType; + + if (linked_shader->Geom.OutputType == PRIM_UNKNOWN) { + linker_error(prog, + "geometry shader didn't declare primitive output type\n"); + return; + } + prog->Geom.OutputType = linked_shader->Geom.OutputType; + + if (linked_shader->Geom.VerticesOut == 0) { + linker_error(prog, + "geometry shader didn't declare max_vertices\n"); + return; + } + prog->Geom.VerticesOut = linked_shader->Geom.VerticesOut; +} + +/** * Combine a group of shaders for a single stage to generate a linked shader * * \note @@ -1034,6 +1185,8 @@ link_intrastage_shaders(void *mem_ctx, linked->NumUniformBlocks = num_uniform_blocks; ralloc_steal(linked, linked->UniformBlocks); + link_gs_inout_layout_qualifiers(prog, linked, shader_list, num_shaders); + populate_symbol_table(linked); /* The a pointer to the main function in the final linked shader (i.e., the @@ -1080,7 +1233,8 @@ link_intrastage_shaders(void *mem_ctx, if (!link_function_calls(prog, linked, linking_shaders, num_linking_shaders)) { ctx->Driver.DeleteShader(ctx, linked); - linked = NULL; + free(linking_shaders); + return NULL; } free(linking_shaders); @@ -1088,18 +1242,24 @@ link_intrastage_shaders(void *mem_ctx, /* At this point linked should contain all of the linked IR, so * validate it to make sure nothing went wrong. */ - if (linked) - validate_ir_tree(linked->ir); + validate_ir_tree(linked->ir); + + /* Set the size of geometry shader input arrays */ + if (linked->Type == GL_GEOMETRY_SHADER) { + unsigned num_vertices = vertices_per_prim(prog->Geom.InputType); + geom_array_resize_visitor input_resize_visitor(num_vertices, prog); + foreach_iter(exec_list_iterator, iter, *linked->ir) { + ir_instruction *ir = (ir_instruction *)iter.get(); + ir->accept(&input_resize_visitor); + } + } /* Make a pass over all variable declarations to ensure that arrays with * unspecified sizes have a size specified. The size is inferred from the * max_array_access field. */ - if (linked != NULL) { - array_sizing_visitor v; - - v.run(linked->ir); - } + array_sizing_visitor v; + v.run(linked->ir); return linked; } @@ -1129,9 +1289,7 @@ update_array_sizes(struct gl_shader_program *prog) foreach_list(node, prog->_LinkedShaders[i]->ir) { ir_variable *const var = ((ir_instruction *) node)->as_variable(); - if ((var == NULL) || (var->mode != ir_var_uniform && - var->mode != ir_var_shader_in && - var->mode != ir_var_shader_out) || + if ((var == NULL) || (var->mode != ir_var_uniform) || !var->type->is_array()) continue; @@ -1334,7 +1492,7 @@ assign_attribute_or_color_locations(gl_shader_program *prog, * that it doesn't collide with other assigned locations. Otherwise, * add it to the list of variables that need linker-assigned locations. */ - const unsigned slots = count_attribute_slots(var->type); + const unsigned slots = var->type->count_attribute_slots(); if (var->location != -1) { if (var->location >= generic_base && var->index < 1) { /* From page 61 of the OpenGL 4.0 spec: @@ -1650,10 +1808,15 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) unsigned num_vert_shaders = 0; struct gl_shader **frag_shader_list; unsigned num_frag_shaders = 0; + struct gl_shader **geom_shader_list; + unsigned num_geom_shaders = 0; vert_shader_list = (struct gl_shader **) - calloc(2 * prog->NumShaders, sizeof(struct gl_shader *)); - frag_shader_list = &vert_shader_list[prog->NumShaders]; + calloc(prog->NumShaders, sizeof(struct gl_shader *)); + frag_shader_list = (struct gl_shader **) + calloc(prog->NumShaders, sizeof(struct gl_shader *)); + geom_shader_list = (struct gl_shader **) + calloc(prog->NumShaders, sizeof(struct gl_shader *)); unsigned min_version = UINT_MAX; unsigned max_version = 0; @@ -1679,8 +1842,8 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) num_frag_shaders++; break; case GL_GEOMETRY_SHADER: - /* FINISHME: Support geometry shaders. */ - assert(prog->Shaders[i]->Type != GL_GEOMETRY_SHADER); + geom_shader_list[num_geom_shaders] = prog->Shaders[i]; + num_geom_shaders++; break; } } @@ -1701,6 +1864,14 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) prog->Version = max_version; prog->IsES = is_es_prog; + /* Geometry shaders have to be linked with vertex shaders. + */ + if (num_geom_shaders > 0 && num_vert_shaders == 0) { + linker_error(prog, "Geometry shader must be linked with " + "vertex shader\n"); + goto done; + } + for (unsigned int i = 0; i < MESA_SHADER_TYPES; i++) { if (prog->_LinkedShaders[i] != NULL) ctx->Driver.DeleteShader(ctx, prog->_LinkedShaders[i]); @@ -1742,6 +1913,22 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) sh); } + if (num_geom_shaders > 0) { + gl_shader *const sh = + link_intrastage_shaders(mem_ctx, ctx, prog, geom_shader_list, + num_geom_shaders); + + if (!prog->LinkStatus) + goto done; + + validate_geometry_shader_executable(prog, sh); + if (!prog->LinkStatus) + goto done; + + _mesa_reference_shader(ctx, &prog->_LinkedShaders[MESA_SHADER_GEOMETRY], + sh); + } + /* Here begins the inter-stage linking phase. Some initial validation is * performed, then locations are assigned for uniforms, attributes, and * varyings. @@ -1828,7 +2015,11 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) prog->_LinkedShaders[MESA_SHADER_VERTEX], VERT_ATTRIB_GENERIC0, VARYING_SLOT_VAR0); } - /* FINISHME: Geometry shaders not implemented yet */ + if (prog->_LinkedShaders[MESA_SHADER_GEOMETRY] != NULL) { + link_invalidate_variable_locations( + prog->_LinkedShaders[MESA_SHADER_GEOMETRY], + VARYING_SLOT_VAR0, VARYING_SLOT_VAR0); + } if (prog->_LinkedShaders[MESA_SHADER_FRAGMENT] != NULL) { link_invalidate_variable_locations( prog->_LinkedShaders[MESA_SHADER_FRAGMENT], @@ -1862,7 +2053,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 (first >= 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; @@ -1895,11 +2086,12 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) */ if (!assign_varying_locations(ctx, mem_ctx, prog, sh, NULL, - num_tfeedback_decls, tfeedback_decls)) + num_tfeedback_decls, tfeedback_decls, + 0)) goto done; } - do_dead_builtin_varyings(ctx, sh->ir, NULL, + do_dead_builtin_varyings(ctx, sh, NULL, num_tfeedback_decls, tfeedback_decls); demote_shader_inputs_and_outputs(sh, ir_var_shader_out); @@ -1914,7 +2106,7 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) */ gl_shader *const sh = prog->_LinkedShaders[first]; - do_dead_builtin_varyings(ctx, NULL, sh->ir, + do_dead_builtin_varyings(ctx, NULL, sh, num_tfeedback_decls, tfeedback_decls); demote_shader_inputs_and_outputs(sh, ir_var_shader_in); @@ -1930,13 +2122,15 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) gl_shader *const sh_i = prog->_LinkedShaders[i]; gl_shader *const sh_next = prog->_LinkedShaders[next]; + unsigned gs_input_vertices = + next == MESA_SHADER_GEOMETRY ? prog->Geom.VerticesIn : 0; if (!assign_varying_locations(ctx, mem_ctx, prog, sh_i, sh_next, next == MESA_SHADER_FRAGMENT ? num_tfeedback_decls : 0, - tfeedback_decls)) + tfeedback_decls, gs_input_vertices)) goto done; - do_dead_builtin_varyings(ctx, sh_i->ir, sh_next->ir, + do_dead_builtin_varyings(ctx, sh_i, sh_next, next == MESA_SHADER_FRAGMENT ? num_tfeedback_decls : 0, tfeedback_decls); @@ -1985,6 +2179,8 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) done: free(vert_shader_list); + free(frag_shader_list); + free(geom_shader_list); for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) { if (prog->_LinkedShaders[i] == NULL) diff --git a/mesalib/src/glsl/linker.h b/mesalib/src/glsl/linker.h index 0ce747d6c..64a683d15 100644 --- a/mesalib/src/glsl/linker.h +++ b/mesalib/src/glsl/linker.h @@ -155,7 +155,4 @@ linker_error(gl_shader_program *prog, const char *fmt, ...); void linker_warning(gl_shader_program *prog, const char *fmt, ...); -unsigned -count_attribute_slots(const glsl_type *t); - #endif /* GLSL_LINKER_H */ diff --git a/mesalib/src/glsl/lower_output_reads.cpp b/mesalib/src/glsl/lower_output_reads.cpp index b93e254ec..5ba9720d0 100644 --- a/mesalib/src/glsl/lower_output_reads.cpp +++ b/mesalib/src/glsl/lower_output_reads.cpp @@ -50,6 +50,7 @@ public: output_read_remover(); ~output_read_remover(); virtual ir_visitor_status visit(class ir_dereference_variable *); + virtual ir_visitor_status visit(class ir_emit_vertex *); virtual ir_visitor_status visit_leave(class ir_return *); virtual ir_visitor_status visit_leave(class ir_function_signature *); }; @@ -117,7 +118,9 @@ copy(void *ctx, ir_variable *output, ir_variable *temp) return new(ctx) ir_assignment(lhs, rhs); } -/** Insert a copy-back assignment before a "return" statement */ +/** Insert a copy-back assignment before a "return" statement or a call to + * EmitVertex(). + */ static void emit_return_copy(const void *key, void *data, void *closure) { @@ -141,6 +144,14 @@ output_read_remover::visit_leave(ir_return *ir) } ir_visitor_status +output_read_remover::visit(ir_emit_vertex *ir) +{ + hash_table_call_foreach(replacements, emit_return_copy, ir); + hash_table_clear(replacements); + return visit_continue; +} + +ir_visitor_status output_read_remover::visit_leave(ir_function_signature *sig) { if (strcmp(sig->function_name(), "main") != 0) diff --git a/mesalib/src/glsl/lower_packed_varyings.cpp b/mesalib/src/glsl/lower_packed_varyings.cpp index cdf2289b4..31a50bba5 100644 --- a/mesalib/src/glsl/lower_packed_varyings.cpp +++ b/mesalib/src/glsl/lower_packed_varyings.cpp @@ -74,6 +74,74 @@ * This lowering pass also handles varyings whose type is a struct or an array * of struct. Structs are packed in order and with no gaps, so there may be a * performance penalty due to structure elements being double-parked. + * + * Lowering of geometry shader inputs is slightly more complex, since geometry + * inputs are always arrays, so we need to lower arrays to arrays. For + * example, the following input: + * + * in struct Foo { + * float f; + * vec3 v; + * vec2 a[2]; + * } arr[3]; // location=4, location_frac=0 + * + * Would get lowered like this if it occurred in a fragment shader: + * + * struct Foo { + * float f; + * vec3 v; + * vec2 a[2]; + * } arr[3]; + * in vec4 packed4; // location=4, location_frac=0 + * in vec4 packed5; // location=5, location_frac=0 + * in vec4 packed6; // location=6, location_frac=0 + * in vec4 packed7; // location=7, location_frac=0 + * in vec4 packed8; // location=8, location_frac=0 + * in vec4 packed9; // location=9, location_frac=0 + * + * main() + * { + * arr[0].f = packed4.x; + * arr[0].v = packed4.yzw; + * arr[0].a[0] = packed5.xy; + * arr[0].a[1] = packed5.zw; + * arr[1].f = packed6.x; + * arr[1].v = packed6.yzw; + * arr[1].a[0] = packed7.xy; + * arr[1].a[1] = packed7.zw; + * arr[2].f = packed8.x; + * arr[2].v = packed8.yzw; + * arr[2].a[0] = packed9.xy; + * arr[2].a[1] = packed9.zw; + * ... + * } + * + * But it would get lowered like this if it occurred in a geometry shader: + * + * struct Foo { + * float f; + * vec3 v; + * vec2 a[2]; + * } arr[3]; + * in vec4 packed4[3]; // location=4, location_frac=0 + * in vec4 packed5[3]; // location=5, location_frac=0 + * + * main() + * { + * arr[0].f = packed4[0].x; + * arr[0].v = packed4[0].yzw; + * arr[0].a[0] = packed5[0].xy; + * arr[0].a[1] = packed5[0].zw; + * arr[1].f = packed4[1].x; + * arr[1].v = packed4[1].yzw; + * arr[1].a[0] = packed5[1].xy; + * arr[1].a[1] = packed5[1].zw; + * arr[2].f = packed4[2].x; + * arr[2].v = packed4[2].yzw; + * arr[2].a[0] = packed5[2].xy; + * arr[2].a[1] = packed5[2].zw; + * ... + * } */ #include "glsl_symbol_table.h" @@ -93,7 +161,8 @@ public: lower_packed_varyings_visitor(void *mem_ctx, unsigned location_base, unsigned locations_used, ir_variable_mode mode, - exec_list *main_instructions); + unsigned gs_input_vertices, + exec_list *out_instructions); void run(exec_list *instructions); @@ -101,13 +170,16 @@ private: ir_assignment *bitwise_assign_pack(ir_rvalue *lhs, ir_rvalue *rhs); ir_assignment *bitwise_assign_unpack(ir_rvalue *lhs, ir_rvalue *rhs); unsigned lower_rvalue(ir_rvalue *rvalue, unsigned fine_location, - ir_variable *unpacked_var, const char *name); + ir_variable *unpacked_var, const char *name, + bool gs_input_toplevel, unsigned vertex_index); unsigned lower_arraylike(ir_rvalue *rvalue, unsigned array_size, unsigned fine_location, - ir_variable *unpacked_var, const char *name); - ir_variable *get_packed_varying(unsigned location, - ir_variable *unpacked_var, - const char *name); + ir_variable *unpacked_var, const char *name, + bool gs_input_toplevel, unsigned vertex_index); + ir_dereference *get_packed_varying_deref(unsigned location, + ir_variable *unpacked_var, + const char *name, + unsigned vertex_index); bool needs_lowering(ir_variable *var); /** @@ -145,15 +217,23 @@ private: const ir_variable_mode mode; /** - * List of instructions corresponding to the main() function. This is - * where we add instructions to pack or unpack the varyings. + * If we are currently lowering geometry shader inputs, the number of input + * vertices the geometry shader accepts. Otherwise zero. */ - exec_list *main_instructions; + const unsigned gs_input_vertices; + + /** + * Exec list into which the visitor should insert the packing instructions. + * Caller provides this list; it should insert the instructions into the + * appropriate place in the shader once the visitor has finished running. + */ + exec_list *out_instructions; }; lower_packed_varyings_visitor::lower_packed_varyings_visitor( void *mem_ctx, unsigned location_base, unsigned locations_used, - ir_variable_mode mode, exec_list *main_instructions) + ir_variable_mode mode, unsigned gs_input_vertices, + exec_list *out_instructions) : mem_ctx(mem_ctx), location_base(location_base), locations_used(locations_used), @@ -161,7 +241,8 @@ lower_packed_varyings_visitor::lower_packed_varyings_visitor( rzalloc_array_size(mem_ctx, sizeof(*packed_varyings), locations_used)), mode(mode), - main_instructions(main_instructions) + gs_input_vertices(gs_input_vertices), + out_instructions(out_instructions) { } @@ -195,7 +276,7 @@ lower_packed_varyings_visitor::run(exec_list *instructions) /* Recursively pack or unpack it. */ this->lower_rvalue(deref, var->location * 4 + var->location_frac, var, - var->name); + var->name, this->gs_input_vertices != 0, 0); } } @@ -277,6 +358,15 @@ lower_packed_varyings_visitor::bitwise_assign_unpack(ir_rvalue *lhs, * in multiples of a float, rather than multiples of a vec4 as is used * elsewhere in Mesa. * + * \param gs_input_toplevel should be set to true if we are lowering geometry + * shader inputs, and we are currently lowering the whole input variable + * (i.e. we are lowering the array whose index selects the vertex). + * + * \param vertex_index: if we are lowering geometry shader inputs, and the + * level of the array that we are currently lowering is *not* the top level, + * then this indicates which vertex we are currently lowering. Otherwise it + * is ignored. + * * \return the location where the next constituent vector (after this one) * should be packed. */ @@ -284,8 +374,15 @@ unsigned lower_packed_varyings_visitor::lower_rvalue(ir_rvalue *rvalue, unsigned fine_location, ir_variable *unpacked_var, - const char *name) + const char *name, + bool gs_input_toplevel, + unsigned vertex_index) { + /* When gs_input_toplevel is set, we should be looking at a geometry shader + * input array. + */ + assert(!gs_input_toplevel || rvalue->type->is_array()); + if (rvalue->type->is_record()) { for (unsigned i = 0; i < rvalue->type->length; i++) { if (i != 0) @@ -296,7 +393,8 @@ lower_packed_varyings_visitor::lower_rvalue(ir_rvalue *rvalue, char *deref_name = ralloc_asprintf(this->mem_ctx, "%s.%s", name, field_name); fine_location = this->lower_rvalue(dereference_record, fine_location, - unpacked_var, deref_name); + unpacked_var, deref_name, false, + vertex_index); } return fine_location; } else if (rvalue->type->is_array()) { @@ -304,13 +402,15 @@ lower_packed_varyings_visitor::lower_rvalue(ir_rvalue *rvalue, * sequence. */ return this->lower_arraylike(rvalue, rvalue->type->array_size(), - fine_location, unpacked_var, name); + fine_location, unpacked_var, name, + gs_input_toplevel, vertex_index); } else if (rvalue->type->is_matrix()) { /* Matrices are packed/unpacked by considering each column vector in * sequence. */ return this->lower_arraylike(rvalue, rvalue->type->matrix_columns, - fine_location, unpacked_var, name); + fine_location, unpacked_var, name, + false, vertex_index); } else if (rvalue->type->vector_elements + fine_location % 4 > 4) { /* This vector is going to be "double parked" across two varying slots, * so handle it as two separate assignments. @@ -340,9 +440,10 @@ lower_packed_varyings_visitor::lower_rvalue(ir_rvalue *rvalue, char *right_name = ralloc_asprintf(this->mem_ctx, "%s.%s", name, right_swizzle_name); fine_location = this->lower_rvalue(left_swizzle, fine_location, - unpacked_var, left_name); + unpacked_var, left_name, false, + vertex_index); return this->lower_rvalue(right_swizzle, fine_location, unpacked_var, - right_name); + right_name, false, vertex_index); } else { /* No special handling is necessary; pack the rvalue into the * varying. @@ -353,19 +454,19 @@ lower_packed_varyings_visitor::lower_rvalue(ir_rvalue *rvalue, unsigned location_frac = fine_location % 4; for (unsigned i = 0; i < components; ++i) swizzle_values[i] = i + location_frac; - ir_dereference_variable *packed_deref = new(this->mem_ctx) - ir_dereference_variable(this->get_packed_varying(location, - unpacked_var, name)); + ir_dereference *packed_deref = + this->get_packed_varying_deref(location, unpacked_var, name, + vertex_index); ir_swizzle *swizzle = new(this->mem_ctx) ir_swizzle(packed_deref, swizzle_values, components); if (this->mode == ir_var_shader_out) { ir_assignment *assignment = this->bitwise_assign_pack(swizzle, rvalue); - this->main_instructions->push_tail(assignment); + this->out_instructions->push_tail(assignment); } else { ir_assignment *assignment = this->bitwise_assign_unpack(rvalue, swizzle); - this->main_instructions->push_head(assignment); + this->out_instructions->push_tail(assignment); } return fine_location + components; } @@ -376,13 +477,24 @@ lower_packed_varyings_visitor::lower_rvalue(ir_rvalue *rvalue, * constituent elements, accessing each one using an ir_dereference_array. * This takes care of both arrays and matrices, since ir_dereference_array * treats a matrix like an array of its column vectors. + * + * \param gs_input_toplevel should be set to true if we are lowering geometry + * shader inputs, and we are currently lowering the whole input variable + * (i.e. we are lowering the array whose index selects the vertex). + * + * \param vertex_index: if we are lowering geometry shader inputs, and the + * level of the array that we are currently lowering is *not* the top level, + * then this indicates which vertex we are currently lowering. Otherwise it + * is ignored. */ unsigned lower_packed_varyings_visitor::lower_arraylike(ir_rvalue *rvalue, unsigned array_size, unsigned fine_location, ir_variable *unpacked_var, - const char *name) + const char *name, + bool gs_input_toplevel, + unsigned vertex_index) { for (unsigned i = 0; i < array_size; i++) { if (i != 0) @@ -392,8 +504,20 @@ lower_packed_varyings_visitor::lower_arraylike(ir_rvalue *rvalue, ir_dereference_array(rvalue, constant); char *subscripted_name = ralloc_asprintf(this->mem_ctx, "%s[%d]", name, i); - fine_location = this->lower_rvalue(dereference_array, fine_location, - unpacked_var, subscripted_name); + if (gs_input_toplevel) { + /* Geometry shader inputs are a special case. Instead of storing + * each element of the array at a different location, all elements + * are at the same location, but with a different vertex index. + */ + (void) this->lower_rvalue(dereference_array, fine_location, + unpacked_var, subscripted_name, + false, i); + } else { + fine_location = + this->lower_rvalue(dereference_array, fine_location, + unpacked_var, subscripted_name, + false, vertex_index); + } } return fine_location; } @@ -406,11 +530,14 @@ lower_packed_varyings_visitor::lower_arraylike(ir_rvalue *rvalue, * The newly created varying inherits its interpolation parameters from \c * unpacked_var. Its base type is ivec4 if we are lowering a flat varying, * vec4 otherwise. + * + * \param vertex_index: if we are lowering geometry shader inputs, then this + * indicates which vertex we are currently lowering. Otherwise it is ignored. */ -ir_variable * -lower_packed_varyings_visitor::get_packed_varying(unsigned location, - ir_variable *unpacked_var, - const char *name) +ir_dereference * +lower_packed_varyings_visitor::get_packed_varying_deref( + unsigned location, ir_variable *unpacked_var, const char *name, + unsigned vertex_index) { unsigned slot = location - this->location_base; assert(slot < locations_used); @@ -421,18 +548,44 @@ lower_packed_varyings_visitor::get_packed_varying(unsigned location, packed_type = glsl_type::ivec4_type; else packed_type = glsl_type::vec4_type; + if (this->gs_input_vertices != 0) { + packed_type = + glsl_type::get_array_instance(packed_type, + this->gs_input_vertices); + } ir_variable *packed_var = new(this->mem_ctx) ir_variable(packed_type, packed_name, this->mode); + if (this->gs_input_vertices != 0) { + /* Prevent update_array_sizes() from messing with the size of the + * array. + */ + packed_var->max_array_access = this->gs_input_vertices - 1; + } packed_var->centroid = unpacked_var->centroid; packed_var->interpolation = unpacked_var->interpolation; packed_var->location = location; unpacked_var->insert_before(packed_var); this->packed_varyings[slot] = packed_var; } else { - ralloc_asprintf_append((char **) &this->packed_varyings[slot]->name, - ",%s", name); + /* For geometry shader inputs, only update the packed variable name the + * first time we visit each component. + */ + if (this->gs_input_vertices == 0 || vertex_index == 0) { + ralloc_asprintf_append((char **) &this->packed_varyings[slot]->name, + ",%s", name); + } + } + + ir_dereference *deref = new(this->mem_ctx) + ir_dereference_variable(this->packed_varyings[slot]); + if (this->gs_input_vertices != 0) { + /* When lowering GS inputs, the packed variable is an array, so we need + * to dereference it using vertex_index. + */ + ir_constant *constant = new(this->mem_ctx) ir_constant(vertex_index); + deref = new(this->mem_ctx) ir_dereference_array(deref, constant); } - return this->packed_varyings[slot]; + return deref; } bool @@ -440,6 +593,10 @@ lower_packed_varyings_visitor::needs_lowering(ir_variable *var) { /* Things composed of vec4's don't need lowering. Everything else does. */ const glsl_type *type = var->type; + if (this->gs_input_vertices != 0) { + assert(type->is_array()); + type = type->element_type(); + } if (type->is_array()) type = type->fields.array; if (type->vector_elements == 4) @@ -447,19 +604,81 @@ lower_packed_varyings_visitor::needs_lowering(ir_variable *var) return true; } + +/** + * Visitor that splices varying packing code before every use of EmitVertex() + * in a geometry shader. + */ +class lower_packed_varyings_gs_splicer : public ir_hierarchical_visitor +{ +public: + explicit lower_packed_varyings_gs_splicer(void *mem_ctx, + const exec_list *instructions); + + virtual ir_visitor_status visit(ir_emit_vertex *ev); + +private: + /** + * Memory context used to allocate new instructions for the shader. + */ + void * const mem_ctx; + + /** + * Instructions that should be spliced into place before each EmitVertex() + * call. + */ + const exec_list *instructions; +}; + + +lower_packed_varyings_gs_splicer::lower_packed_varyings_gs_splicer( + void *mem_ctx, const exec_list *instructions) + : mem_ctx(mem_ctx), instructions(instructions) +{ +} + + +ir_visitor_status +lower_packed_varyings_gs_splicer::visit(ir_emit_vertex *ev) +{ + foreach_list(node, this->instructions) { + ir_instruction *ir = (ir_instruction *) node; + ev->insert_before(ir->clone(this->mem_ctx, NULL)); + } + return visit_continue; +} + + void lower_packed_varyings(void *mem_ctx, unsigned location_base, unsigned locations_used, ir_variable_mode mode, - gl_shader *shader) + unsigned gs_input_vertices, gl_shader *shader) { exec_list *instructions = shader->ir; ir_function *main_func = shader->symbols->get_function("main"); exec_list void_parameters; ir_function_signature *main_func_sig = main_func->matching_signature(&void_parameters); - exec_list *main_instructions = &main_func_sig->body; + exec_list new_instructions; lower_packed_varyings_visitor visitor(mem_ctx, location_base, locations_used, mode, - main_instructions); + gs_input_vertices, &new_instructions); visitor.run(instructions); + if (mode == ir_var_shader_out) { + if (shader->Type == GL_GEOMETRY_SHADER) { + /* For geometry shaders, outputs need to be lowered before each call + * to EmitVertex() + */ + lower_packed_varyings_gs_splicer splicer(mem_ctx, &new_instructions); + splicer.run(instructions); + } else { + /* For other shader types, outputs need to be lowered at the end of + * main() + */ + main_func_sig->body.append_list(&new_instructions); + } + } else { + /* Shader inputs need to be lowered at the beginning of main() */ + main_func_sig->body.head->insert_before(&new_instructions); + } } diff --git a/mesalib/src/glsl/opt_dead_builtin_varyings.cpp b/mesalib/src/glsl/opt_dead_builtin_varyings.cpp index 2e813d24e..6745d5c64 100644 --- a/mesalib/src/glsl/opt_dead_builtin_varyings.cpp +++ b/mesalib/src/glsl/opt_dead_builtin_varyings.cpp @@ -409,7 +409,7 @@ lower_texcoord_array(exec_list *ir, const varying_info_visitor *info) void do_dead_builtin_varyings(struct gl_context *ctx, - exec_list *producer, exec_list *consumer, + gl_shader *producer, gl_shader *consumer, unsigned num_tfeedback_decls, tfeedback_decl *tfeedback_decls) { @@ -431,44 +431,55 @@ do_dead_builtin_varyings(struct gl_context *ctx, varying_info_visitor consumer_info(ir_var_shader_in); if (producer) { - producer_info.get(producer, num_tfeedback_decls, tfeedback_decls); + producer_info.get(producer->ir, 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); + lower_texcoord_array(producer->ir, &producer_info); } return; } } if (consumer) { - consumer_info.get(consumer, 0, NULL); + consumer_info.get(consumer->ir, 0, NULL); if (!producer) { /* At least eliminate unused gl_TexCoord elements. */ if (consumer_info.lower_texcoord_array) { - lower_texcoord_array(consumer, &consumer_info); + lower_texcoord_array(consumer->ir, &consumer_info); } return; } } - /* Eliminate the varyings unused by the other shader. */ + /* Eliminate the outputs unused by the consumer. */ if (producer_info.lower_texcoord_array || producer_info.color_usage || producer_info.has_fog) { - replace_varyings_visitor(producer, + replace_varyings_visitor(producer->ir, &producer_info, consumer_info.texcoord_usage, consumer_info.color_usage, consumer_info.has_fog); } + /* The gl_TexCoord fragment shader inputs can be initialized + * by GL_COORD_REPLACE, so we can't eliminate them. + * + * This doesn't prevent elimination of the gl_TexCoord elements which + * are not read by the fragment shader. We want to eliminate those anyway. + */ + if (consumer->Type == GL_FRAGMENT_SHADER) { + producer_info.texcoord_usage = (1 << MAX_TEXTURE_COORD_UNITS) - 1; + } + + /* Eliminate the inputs uninitialized by the producer. */ if (consumer_info.lower_texcoord_array || consumer_info.color_usage || consumer_info.has_fog) { - replace_varyings_visitor(consumer, + replace_varyings_visitor(consumer->ir, &consumer_info, producer_info.texcoord_usage, producer_info.color_usage, diff --git a/mesalib/src/glsl/opt_dead_code_local.cpp b/mesalib/src/glsl/opt_dead_code_local.cpp index 8c31802a6..42a30b3d8 100644 --- a/mesalib/src/glsl/opt_dead_code_local.cpp +++ b/mesalib/src/glsl/opt_dead_code_local.cpp @@ -114,6 +114,23 @@ public: return visit_continue_with_parent; } + virtual ir_visitor_status visit(ir_emit_vertex *ir) + { + /* For the purpose of dead code elimination, emitting a vertex counts as + * "reading" all of the currently assigned output variables. + */ + foreach_iter(exec_list_iterator, iter, *this->assignments) { + assignment_entry *entry = (assignment_entry *)iter.get(); + if (entry->lhs->mode == ir_var_shader_out) { + if (debug) + printf("kill %s\n", entry->lhs->name); + entry->remove(); + } + } + + return visit_continue; + } + private: exec_list *assignments; }; diff --git a/mesalib/src/mapi/glapi/gen/EXT_framebuffer_object.xml b/mesalib/src/mapi/glapi/gen/EXT_framebuffer_object.xml index 16c82a4a2..2cf75bc67 100644 --- a/mesalib/src/mapi/glapi/gen/EXT_framebuffer_object.xml +++ b/mesalib/src/mapi/glapi/gen/EXT_framebuffer_object.xml @@ -78,7 +78,7 @@ <return type="GLboolean"/> </function> - <function name="BindRenderbufferEXT" offset="assign"> + <function name="BindRenderbufferEXT" offset="assign" deprecated="3.1"> <param name="target" type="GLenum"/> <param name="renderbuffer" type="GLuint"/> <glx rop="4316"/> @@ -112,7 +112,7 @@ <return type="GLboolean"/> </function> - <function name="BindFramebufferEXT" offset="assign"> + <function name="BindFramebufferEXT" offset="assign" deprecated="3.1"> <param name="target" type="GLenum"/> <param name="framebuffer" type="GLuint"/> <glx rop="4319"/> diff --git a/mesalib/src/mesa/drivers/common/meta.c b/mesalib/src/mesa/drivers/common/meta.c index 4a3497c9a..60157af98 100644 --- a/mesalib/src/mesa/drivers/common/meta.c +++ b/mesalib/src/mesa/drivers/common/meta.c @@ -704,9 +704,14 @@ _mesa_meta_begin(struct gl_context *ctx, GLbitfield state) _mesa_LoadIdentity(); _mesa_MatrixMode(GL_PROJECTION); _mesa_LoadIdentity(); - _mesa_Ortho(0.0, ctx->DrawBuffer->Width, - 0.0, ctx->DrawBuffer->Height, - -1.0, 1.0); + + /* glOrtho with width = 0 or height = 0 generates GL_INVALID_VALUE. + * This can occur when there is no draw buffer. + */ + if (ctx->DrawBuffer->Width != 0 && ctx->DrawBuffer->Height != 0) + _mesa_Ortho(0.0, ctx->DrawBuffer->Width, + 0.0, ctx->DrawBuffer->Height, + -1.0, 1.0); } if (state & MESA_META_CLIP) { @@ -956,7 +961,7 @@ _mesa_meta_end(struct gl_context *ctx) if (ctx->Extensions.ARB_vertex_shader) _mesa_use_shader_program(ctx, GL_VERTEX_SHADER, save->VertexShader); - if (ctx->Extensions.ARB_geometry_shader4) + if (_mesa_has_geometry_shaders(ctx)) _mesa_use_shader_program(ctx, GL_GEOMETRY_SHADER_ARB, save->GeometryShader); @@ -1879,19 +1884,24 @@ _mesa_meta_BlitFramebuffer(struct gl_context *ctx, const GLenum rb_base_format = _mesa_base_tex_format(ctx, colorReadRb->InternalFormat); - newTex = alloc_texture(tex, srcW, srcH, rb_base_format); - setup_copypix_texture(ctx, tex, newTex, srcX, srcY, srcW, srcH, + /* Using the exact source rectangle to create the texture does incorrect + * linear filtering along the edges. So, allocate the texture extended along + * edges by one pixel in x, y directions. + */ + newTex = alloc_texture(tex, srcW + 2, srcH + 2, rb_base_format); + setup_copypix_texture(ctx, tex, newTex, + srcX - 1, srcY - 1, srcW + 2, srcH + 2, rb_base_format, filter); /* texcoords (after texture allocation!) */ { - verts[0].s = 0.0F; - verts[0].t = 0.0F; - verts[1].s = tex->Sright; - verts[1].t = 0.0F; - verts[2].s = tex->Sright; - verts[2].t = tex->Ttop; - verts[3].s = 0.0F; - verts[3].t = tex->Ttop; + verts[0].s = 1.0F; + verts[0].t = 1.0F; + verts[1].s = tex->Sright - 1.0F; + verts[1].t = 1.0F; + verts[2].s = tex->Sright - 1.0F; + verts[2].t = tex->Ttop - 1.0F; + verts[3].s = 1.0F; + verts[3].t = tex->Ttop - 1.0F; /* upload new vertex data */ _mesa_BufferSubData(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts); diff --git a/mesalib/src/mesa/drivers/dri/common/dri_util.c b/mesalib/src/mesa/drivers/dri/common/dri_util.c index 9ed9df4b3..fa520ea90 100644 --- a/mesalib/src/mesa/drivers/dri/common/dri_util.c +++ b/mesalib/src/mesa/drivers/dri/common/dri_util.c @@ -52,8 +52,6 @@ PUBLIC const char __dri2ConfigOptions[] = DRI_CONF_SECTION_END DRI_CONF_END; -static const uint __dri2NConfigOptions = 1; - /*****************************************************************/ /** \name Screen handling functions */ /*****************************************************************/ @@ -112,7 +110,7 @@ dri2CreateNewScreen(int scrn, int fd, return NULL; } - driParseOptionInfo(&psp->optionInfo, __dri2ConfigOptions, __dri2NConfigOptions); + driParseOptionInfo(&psp->optionInfo, __dri2ConfigOptions); driParseConfigFiles(&psp->optionCache, &psp->optionInfo, psp->myNum, "dri2"); return psp; diff --git a/mesalib/src/mesa/drivers/dri/common/xmlconfig.c b/mesalib/src/mesa/drivers/dri/common/xmlconfig.c index 5c97c20fc..b95e452f1 100644 --- a/mesalib/src/mesa/drivers/dri/common/xmlconfig.c +++ b/mesalib/src/mesa/drivers/dri/common/xmlconfig.c @@ -132,16 +132,6 @@ static GLuint findOption (const driOptionCache *cache, const char *name) { return hash; } -/** \brief Count the real number of options in an option cache */ -static GLuint countOptions (const driOptionCache *cache) { - GLuint size = 1 << cache->tableSize; - GLuint i, count = 0; - for (i = 0; i < size; ++i) - if (cache->info[i].name) - count++; - return count; -} - /** \brief Like strdup but using malloc and with error checking. */ #define XSTRDUP(dest,source) do { \ GLuint len = strlen (source); \ @@ -685,25 +675,18 @@ static void optInfoEndElem (void *userData, const XML_Char *name) { } } -void driParseOptionInfo (driOptionCache *info, - const char *configOptions, GLuint nConfigOptions) { +void driParseOptionInfo (driOptionCache *info, const char *configOptions) { XML_Parser p; int status; struct OptInfoData userData; struct OptInfoData *data = &userData; - GLuint realNoptions; - - /* determine hash table size and allocate memory: - * 3/2 of the number of options, rounded up, so there remains always - * at least one free entry. This is needed for detecting undefined - * options in configuration files without getting a hash table overflow. - * Round this up to a power of two. */ - GLuint minSize = (nConfigOptions*3 + 1) / 2; - GLuint size, log2size; - for (size = 1, log2size = 0; size < minSize; size <<= 1, ++log2size); - info->tableSize = log2size; - info->info = calloc(size, sizeof (driOptionInfo)); - info->values = calloc(size, sizeof (driOptionValue)); + + /* Make the hash table big enough to fit more than the maximum number of + * config options we've ever seen in a driver. + */ + info->tableSize = 6; + info->info = calloc(1 << info->tableSize, sizeof (driOptionInfo)); + info->values = calloc(1 << info->tableSize, sizeof (driOptionValue)); if (info->info == NULL || info->values == NULL) { fprintf (stderr, "%s: %d: out of memory.\n", __FILE__, __LINE__); abort(); @@ -728,17 +711,6 @@ void driParseOptionInfo (driOptionCache *info, XML_FATAL ("%s.", XML_ErrorString(XML_GetErrorCode(p))); XML_ParserFree (p); - - /* Check if the actual number of options matches nConfigOptions. - * A mismatch is not fatal (a hash table overflow would be) but we - * want the driver developer's attention anyway. */ - realNoptions = countOptions (info); - if (realNoptions != nConfigOptions) { - fprintf (stderr, - "Error: nConfigOptions (%u) does not match the actual number of options in\n" - " __driConfigOptions (%u).\n", - nConfigOptions, realNoptions); - } } /** \brief Parser context for configuration files. */ diff --git a/mesalib/src/mesa/drivers/dri/common/xmlconfig.h b/mesalib/src/mesa/drivers/dri/common/xmlconfig.h index c363af764..d0ad42c19 100644 --- a/mesalib/src/mesa/drivers/dri/common/xmlconfig.h +++ b/mesalib/src/mesa/drivers/dri/common/xmlconfig.h @@ -76,7 +76,6 @@ typedef struct driOptionCache { GLuint tableSize; /**< \brief Size of the arrays * - * Depending on the hash function this may differ from __driNConfigOptions. * In the current implementation it's not actually a size but log2(size). * The value is the same in the screen and all contexts. */ } driOptionCache; @@ -87,14 +86,13 @@ typedef struct driOptionCache { * * \param info pointer to a driOptionCache that will store the option info * \param configOptions XML document describing available configuration opts - * \param nConfigOptions number of options, used to choose a hash table size * * For the option information to be available to external configuration tools * it must be a public symbol __driConfigOptions. It is also passed as a * parameter to driParseOptionInfo in order to avoid driver-independent code * depending on symbols in driver-specific code. */ void driParseOptionInfo (driOptionCache *info, - const char *configOptions, GLuint nConfigOptions); + const char *configOptions); /** \brief Initialize option cache from info and parse configuration files * * To be called in <driver>CreateContext. screenNum and driverName select diff --git a/mesalib/src/mesa/main/api_validate.c b/mesalib/src/mesa/main/api_validate.c index 7ab8e305d..243bb89d1 100644 --- a/mesalib/src/mesa/main/api_validate.c +++ b/mesalib/src/mesa/main/api_validate.c @@ -222,7 +222,7 @@ _mesa_is_valid_prim_mode(struct gl_context *ctx, GLenum mode) case GL_LINE_STRIP_ADJACENCY: case GL_TRIANGLES_ADJACENCY: case GL_TRIANGLE_STRIP_ADJACENCY: - return _mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_geometry_shader4; + return _mesa_has_geometry_shaders(ctx); default: return false; } @@ -245,6 +245,74 @@ _mesa_valid_prim_mode(struct gl_context *ctx, GLenum mode, const char *name) return GL_FALSE; } + /* From the ARB_geometry_shader4 spec: + * + * The error INVALID_OPERATION is generated if Begin, or any command that + * implicitly calls Begin, is called when a geometry shader is active and: + * + * * the input primitive type of the current geometry shader is + * POINTS and <mode> is not POINTS, + * + * * the input primitive type of the current geometry shader is + * LINES and <mode> is not LINES, LINE_STRIP, or LINE_LOOP, + * + * * the input primitive type of the current geometry shader is + * TRIANGLES and <mode> is not TRIANGLES, TRIANGLE_STRIP or + * TRIANGLE_FAN, + * + * * the input primitive type of the current geometry shader is + * LINES_ADJACENCY_ARB and <mode> is not LINES_ADJACENCY_ARB or + * LINE_STRIP_ADJACENCY_ARB, or + * + * * the input primitive type of the current geometry shader is + * TRIANGLES_ADJACENCY_ARB and <mode> is not + * TRIANGLES_ADJACENCY_ARB or TRIANGLE_STRIP_ADJACENCY_ARB. + * + */ + if (ctx->Shader.CurrentGeometryProgram) { + const GLenum geom_mode = + ctx->Shader.CurrentGeometryProgram->Geom.InputType; + switch (mode) { + case GL_POINTS: + valid_enum = (geom_mode == GL_POINTS); + break; + case GL_LINES: + case GL_LINE_LOOP: + case GL_LINE_STRIP: + valid_enum = (geom_mode == GL_LINES); + break; + case GL_TRIANGLES: + case GL_TRIANGLE_STRIP: + case GL_TRIANGLE_FAN: + valid_enum = (geom_mode == GL_TRIANGLES); + break; + case GL_QUADS: + case GL_QUAD_STRIP: + case GL_POLYGON: + valid_enum = false; + break; + case GL_LINES_ADJACENCY: + case GL_LINE_STRIP_ADJACENCY: + valid_enum = (geom_mode == GL_LINES_ADJACENCY); + break; + case GL_TRIANGLES_ADJACENCY: + case GL_TRIANGLE_STRIP_ADJACENCY: + valid_enum = (geom_mode == GL_TRIANGLES_ADJACENCY); + break; + default: + valid_enum = false; + break; + } + if (!valid_enum) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(mode=%s vs geometry shader input %s)", + name, + _mesa_lookup_prim_by_nr(mode), + _mesa_lookup_prim_by_nr(geom_mode)); + return GL_FALSE; + } + } + /* From the GL_EXT_transform_feedback spec: * * "The error INVALID_OPERATION is generated if Begin, or any command diff --git a/mesalib/src/mesa/main/context.h b/mesalib/src/mesa/main/context.h index 8872be1f4..792ab4cd5 100644 --- a/mesalib/src/mesa/main/context.h +++ b/mesalib/src/mesa/main/context.h @@ -312,6 +312,17 @@ _mesa_is_gles3(const struct gl_context *ctx) } +/** + * Checks if the context supports geometry shaders. + */ +static inline GLboolean +_mesa_has_geometry_shaders(const struct gl_context *ctx) +{ + return _mesa_is_desktop_gl(ctx) && + (ctx->Version >= 32 || ctx->Extensions.ARB_geometry_shader4); +} + + #ifdef __cplusplus } #endif diff --git a/mesalib/src/mesa/main/fbobject.c b/mesalib/src/mesa/main/fbobject.c index bf7e85c88..1034c7a71 100644 --- a/mesalib/src/mesa/main/fbobject.c +++ b/mesalib/src/mesa/main/fbobject.c @@ -343,6 +343,28 @@ _mesa_remove_attachment(struct gl_context *ctx, } /** + * Verify a couple error conditions that will lead to an incomplete FBO and + * may cause problems for the driver's RenderTexture path. + */ +static bool +driver_RenderTexture_is_safe(const struct gl_renderbuffer_attachment *att) +{ + const struct gl_texture_image *const texImage = + att->Texture->Image[att->CubeMapFace][att->TextureLevel]; + + if (texImage->Width == 0 || texImage->Height == 0 || texImage->Depth == 0) + return false; + + if ((texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY + && att->Zoffset >= texImage->Height) + || (texImage->TexObject->Target != GL_TEXTURE_1D_ARRAY + && att->Zoffset >= texImage->Depth)) + return false; + + return true; +} + +/** * Create a renderbuffer which will be set up by the driver to wrap the * texture image slice. * @@ -363,8 +385,6 @@ _mesa_update_texture_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb; texImage = att->Texture->Image[att->CubeMapFace][att->TextureLevel]; - if (!texImage) - return; rb = att->Renderbuffer; if (!rb) { @@ -383,6 +403,9 @@ _mesa_update_texture_renderbuffer(struct gl_context *ctx, rb->NeedsFinishRenderTexture = ctx->Driver.FinishRenderTexture != NULL; } + if (!texImage) + return; + rb->_BaseFormat = texImage->_BaseFormat; rb->Format = texImage->TexFormat; rb->InternalFormat = texImage->InternalFormat; @@ -391,7 +414,8 @@ _mesa_update_texture_renderbuffer(struct gl_context *ctx, rb->NumSamples = texImage->NumSamples; rb->TexImage = texImage; - ctx->Driver.RenderTexture(ctx, fb, att); + if (driver_RenderTexture_is_safe(att)) + ctx->Driver.RenderTexture(ctx, fb, att); } /** @@ -703,15 +727,39 @@ test_attachment_completeness(const struct gl_context *ctx, GLenum format, } if (texImage->Width < 1 || texImage->Height < 1) { att_incomplete("teximage width/height=0"); - printf("texobj = %u\n", texObj->Name); - printf("level = %d\n", att->TextureLevel); att->Complete = GL_FALSE; return; } - if (texObj->Target == GL_TEXTURE_3D && att->Zoffset >= texImage->Depth) { - att_incomplete("bad z offset"); - att->Complete = GL_FALSE; - return; + + switch (texObj->Target) { + case GL_TEXTURE_3D: + if (att->Zoffset >= texImage->Depth) { + att_incomplete("bad z offset"); + att->Complete = GL_FALSE; + return; + } + break; + case GL_TEXTURE_1D_ARRAY: + if (att->Zoffset >= texImage->Height) { + att_incomplete("bad 1D-array layer"); + att->Complete = GL_FALSE; + return; + } + break; + case GL_TEXTURE_2D_ARRAY: + if (att->Zoffset >= texImage->Depth) { + att_incomplete("bad 2D-array layer"); + att->Complete = GL_FALSE; + return; + } + break; + case GL_TEXTURE_CUBE_MAP_ARRAY: + if (att->Zoffset >= texImage->Depth) { + att_incomplete("bad cube-array layer"); + att->Complete = GL_FALSE; + return; + } + break; } baseFormat = _mesa_get_format_base_format(texImage->TexFormat); @@ -1104,8 +1152,8 @@ _mesa_IsRenderbuffer(GLuint renderbuffer) } -void GLAPIENTRY -_mesa_BindRenderbuffer(GLenum target, GLuint renderbuffer) +static void +bind_renderbuffer(GLenum target, GLuint renderbuffer, bool allow_user_names) { struct gl_renderbuffer *newRb; GET_CURRENT_CONTEXT(ctx); @@ -1125,9 +1173,7 @@ _mesa_BindRenderbuffer(GLenum target, GLuint renderbuffer) /* ID was reserved, but no real renderbuffer object made yet */ newRb = NULL; } - else if (!newRb - && _mesa_is_desktop_gl(ctx) - && ctx->Extensions.ARB_framebuffer_object) { + else if (!newRb && !allow_user_names) { /* All RB IDs must be Gen'd */ _mesa_error(ctx, GL_INVALID_OPERATION, "glBindRenderbuffer(buffer)"); return; @@ -1154,32 +1200,68 @@ _mesa_BindRenderbuffer(GLenum target, GLuint renderbuffer) _mesa_reference_renderbuffer(&ctx->CurrentRenderbuffer, newRb); } +void GLAPIENTRY +_mesa_BindRenderbuffer(GLenum target, GLuint renderbuffer) +{ + GET_CURRENT_CONTEXT(ctx); + + /* OpenGL ES glBindRenderbuffer and glBindRenderbufferOES use this same + * entry point, but they allow the use of user-generated names. + */ + bind_renderbuffer(target, renderbuffer, _mesa_is_gles(ctx)); +} void GLAPIENTRY _mesa_BindRenderbufferEXT(GLenum target, GLuint renderbuffer) { - _mesa_BindRenderbuffer(target, renderbuffer); + /* This function should not be in the dispatch table for core profile / + * OpenGL 3.1, so execution should never get here in those cases -- no + * need for an explicit test. + */ + bind_renderbuffer(target, renderbuffer, true); } /** - * If the given renderbuffer is anywhere attached to the framebuffer, detach - * the renderbuffer. - * This is used when a renderbuffer object is deleted. - * The spec calls for unbinding. + * Remove the specified renderbuffer or texture from any attachment point in + * the framebuffer. + * + * \returns + * \c true if the renderbuffer was detached from an attachment point. \c + * false otherwise. */ -static void -detach_renderbuffer(struct gl_context *ctx, - struct gl_framebuffer *fb, - struct gl_renderbuffer *rb) +bool +_mesa_detach_renderbuffer(struct gl_context *ctx, + struct gl_framebuffer *fb, + const void *att) { - GLuint i; + unsigned i; + bool progress = false; + for (i = 0; i < BUFFER_COUNT; i++) { - if (fb->Attachment[i].Renderbuffer == rb) { + if (fb->Attachment[i].Texture == att + || fb->Attachment[i].Renderbuffer == att) { _mesa_remove_attachment(ctx, &fb->Attachment[i]); + progress = true; } } - invalidate_framebuffer(fb); + + /* Section 4.4.4 (Framebuffer Completeness), subsection "Whole Framebuffer + * Completeness," of the OpenGL 3.1 spec says: + * + * "Performing any of the following actions may change whether the + * framebuffer is considered complete or incomplete: + * + * ... + * + * - Deleting, with DeleteTextures or DeleteRenderbuffers, an object + * containing an image that is attached to a framebuffer object + * that is bound to the framebuffer." + */ + if (progress) + invalidate_framebuffer(fb); + + return progress; } @@ -1203,12 +1285,29 @@ _mesa_DeleteRenderbuffers(GLsizei n, const GLuint *renderbuffers) _mesa_BindRenderbuffer(GL_RENDERBUFFER_EXT, 0); } + /* Section 4.4.2 (Attaching Images to Framebuffer Objects), + * subsection "Attaching Renderbuffer Images to a Framebuffer," of + * the OpenGL 3.1 spec says: + * + * "If a renderbuffer object is deleted while its image is + * attached to one or more attachment points in the currently + * bound framebuffer, then it is as if FramebufferRenderbuffer + * had been called, with a renderbuffer of 0, for each + * attachment point to which this image was attached in the + * currently bound framebuffer. In other words, this + * renderbuffer image is first detached from all attachment + * points in the currently bound framebuffer. Note that the + * renderbuffer image is specifically not detached from any + * non-bound framebuffers. Detaching the image from any + * non-bound framebuffers is the responsibility of the + * application. + */ if (_mesa_is_user_fbo(ctx->DrawBuffer)) { - detach_renderbuffer(ctx, ctx->DrawBuffer, rb); + _mesa_detach_renderbuffer(ctx, ctx->DrawBuffer, rb); } if (_mesa_is_user_fbo(ctx->ReadBuffer) && ctx->ReadBuffer != ctx->DrawBuffer) { - detach_renderbuffer(ctx, ctx->ReadBuffer, rb); + _mesa_detach_renderbuffer(ctx, ctx->ReadBuffer, rb); } /* Remove from hash table immediately, to free the ID. @@ -1875,7 +1974,8 @@ check_begin_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb) for (i = 0; i < BUFFER_COUNT; i++) { struct gl_renderbuffer_attachment *att = fb->Attachment + i; - if (att->Texture && att->Renderbuffer->TexImage) { + if (att->Texture && att->Renderbuffer->TexImage + && driver_RenderTexture_is_safe(att)) { ctx->Driver.RenderTexture(ctx, fb, att); } } @@ -1906,8 +2006,8 @@ check_end_texture_render(struct gl_context *ctx, struct gl_framebuffer *fb) } -void GLAPIENTRY -_mesa_BindFramebuffer(GLenum target, GLuint framebuffer) +static void +bind_framebuffer(GLenum target, GLuint framebuffer, bool allow_user_names) { struct gl_framebuffer *newDrawFb, *newReadFb; struct gl_framebuffer *oldDrawFb, *oldReadFb; @@ -1953,9 +2053,7 @@ _mesa_BindFramebuffer(GLenum target, GLuint framebuffer) /* ID was reserved, but no real framebuffer object made yet */ newDrawFb = NULL; } - else if (!newDrawFb - && _mesa_is_desktop_gl(ctx) - && ctx->Extensions.ARB_framebuffer_object) { + else if (!newDrawFb && !allow_user_names) { /* All FBO IDs must be Gen'd */ _mesa_error(ctx, GL_INVALID_OPERATION, "glBindFramebuffer(buffer)"); return; @@ -2033,12 +2131,25 @@ _mesa_BindFramebuffer(GLenum target, GLuint framebuffer) } void GLAPIENTRY -_mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer) +_mesa_BindFramebuffer(GLenum target, GLuint framebuffer) { - _mesa_BindFramebuffer(target, framebuffer); -} + GET_CURRENT_CONTEXT(ctx); + /* OpenGL ES glBindFramebuffer and glBindFramebufferOES use this same entry + * point, but they allow the use of user-generated names. + */ + bind_framebuffer(target, framebuffer, _mesa_is_gles(ctx)); +} +void GLAPIENTRY +_mesa_BindFramebufferEXT(GLenum target, GLuint framebuffer) +{ + /* This function should not be in the dispatch table for core profile / + * OpenGL 3.1, so execution should never get here in those cases -- no + * need for an explicit test. + */ + bind_framebuffer(target, framebuffer, true); +} void GLAPIENTRY _mesa_DeleteFramebuffers(GLsizei n, const GLuint *framebuffers) @@ -2476,7 +2587,7 @@ _mesa_FramebufferTexture(GLenum target, GLenum attachment, { GET_CURRENT_CONTEXT(ctx); - if (ctx->Version >= 32 || ctx->Extensions.ARB_geometry_shader4) { + if (_mesa_has_geometry_shaders(ctx)) { framebuffer_texture(ctx, "Layer", target, attachment, 0, texture, level, 0, GL_TRUE); } else { diff --git a/mesalib/src/mesa/main/fbobject.h b/mesalib/src/mesa/main/fbobject.h index 0a2a5cc59..ab138cfff 100644 --- a/mesalib/src/mesa/main/fbobject.h +++ b/mesalib/src/mesa/main/fbobject.h @@ -28,6 +28,7 @@ #include "compiler.h" #include "glheader.h" +#include <stdbool.h> struct gl_context; struct gl_texture_object; @@ -113,6 +114,11 @@ _mesa_is_legal_color_format(const struct gl_context *ctx, GLenum baseFormat); extern GLenum _mesa_base_fbo_format(struct gl_context *ctx, GLenum internalFormat); +extern bool +_mesa_detach_renderbuffer(struct gl_context *ctx, + struct gl_framebuffer *fb, + const void *att); + extern GLboolean GLAPIENTRY _mesa_IsRenderbuffer(GLuint renderbuffer); diff --git a/mesalib/src/mesa/main/get.c b/mesalib/src/mesa/main/get.c index 0b33fa49b..09b008a07 100644 --- a/mesalib/src/mesa/main/get.c +++ b/mesalib/src/mesa/main/get.c @@ -989,7 +989,7 @@ check_extra(struct gl_context *ctx, const char *func, const struct value_desc *d case EXTRA_EXT_UBO_GS4: api_check = GL_TRUE; api_found = (ctx->Extensions.ARB_uniform_buffer_object && - ctx->Extensions.ARB_geometry_shader4); + _mesa_has_geometry_shaders(ctx)); break; case EXTRA_END: break; diff --git a/mesalib/src/mesa/main/lines.c b/mesalib/src/mesa/main/lines.c index 0df9d66b0..3c08ed2e7 100644 --- a/mesalib/src/mesa/main/lines.c +++ b/mesalib/src/mesa/main/lines.c @@ -62,7 +62,8 @@ _mesa_LineWidth( GLfloat width ) */ if (ctx->API == API_OPENGL_CORE && ((ctx->Const.ContextFlags & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT) - != 0)) { + != 0) + && width > 1.0) { _mesa_error( ctx, GL_INVALID_VALUE, "glLineWidth" ); return; } diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h index 5bb680745..5f9b7f983 100644 --- a/mesalib/src/mesa/main/mtypes.h +++ b/mesalib/src/mesa/main/mtypes.h @@ -1152,31 +1152,32 @@ struct gl_sampler_object */ struct gl_texture_object { - _glthread_Mutex Mutex; /**< for thread safety */ - GLint RefCount; /**< reference count */ - GLuint Name; /**< the user-visible texture object ID */ - GLenum Target; /**< GL_TEXTURE_1D, GL_TEXTURE_2D, etc. */ + _glthread_Mutex Mutex; /**< for thread safety */ + GLint RefCount; /**< reference count */ + GLuint Name; /**< the user-visible texture object ID */ + GLenum Target; /**< GL_TEXTURE_1D, GL_TEXTURE_2D, etc. */ struct gl_sampler_object Sampler; - GLenum DepthMode; /**< GL_ARB_depth_texture */ - - GLfloat Priority; /**< in [0,1] */ - GLint BaseLevel; /**< min mipmap level, OpenGL 1.2 */ - GLint MaxLevel; /**< max mipmap level, OpenGL 1.2 */ - GLint ImmutableLevels; /**< ES 3.0 / ARB_texture_view */ - GLint _MaxLevel; /**< actual max mipmap level (q in the spec) */ - GLfloat _MaxLambda; /**< = _MaxLevel - BaseLevel (q - b in spec) */ - GLint CropRect[4]; /**< GL_OES_draw_texture */ - GLenum Swizzle[4]; /**< GL_EXT_texture_swizzle */ - GLuint _Swizzle; /**< same as Swizzle, but SWIZZLE_* format */ - GLboolean GenerateMipmap; /**< GL_SGIS_generate_mipmap */ - GLboolean _BaseComplete; /**< Is the base texture level valid? */ - GLboolean _MipmapComplete; /**< Is the whole mipmap valid? */ - GLboolean _IsIntegerFormat; /**< Does the texture store integer values? */ - GLboolean _RenderToTexture; /**< Any rendering to this texture? */ - GLboolean Purgeable; /**< Is the buffer purgeable under memory pressure? */ - GLboolean Immutable; /**< GL_ARB_texture_storage */ + GLenum DepthMode; /**< GL_ARB_depth_texture */ + + GLfloat Priority; /**< in [0,1] */ + GLint BaseLevel; /**< min mipmap level, OpenGL 1.2 */ + GLint MaxLevel; /**< max mipmap level, OpenGL 1.2 */ + GLint ImmutableLevels; /**< ES 3.0 / ARB_texture_view */ + GLint _MaxLevel; /**< actual max mipmap level (q in the spec) */ + GLfloat _MaxLambda; /**< = _MaxLevel - BaseLevel (q - p in spec) */ + GLint CropRect[4]; /**< GL_OES_draw_texture */ + GLenum Swizzle[4]; /**< GL_EXT_texture_swizzle */ + GLuint _Swizzle; /**< same as Swizzle, but SWIZZLE_* format */ + GLboolean GenerateMipmap; /**< GL_SGIS_generate_mipmap */ + GLboolean _BaseComplete; /**< Is the base texture level valid? */ + GLboolean _MipmapComplete; /**< Is the whole mipmap valid? */ + GLboolean _IsIntegerFormat; /**< Does the texture store integer values? */ + GLboolean _RenderToTexture; /**< Any rendering to this texture? */ + GLboolean Purgeable; /**< Is the buffer purgeable under memory + pressure? */ + GLboolean Immutable; /**< GL_ARB_texture_storage */ /** Actual texture images, indexed by [cube face] and [mipmap level] */ struct gl_texture_image *Image[MAX_FACES][MAX_TEXTURE_LEVELS]; @@ -1851,7 +1852,7 @@ struct gl_program GLuint Id; GLubyte *String; /**< Null-terminated program text */ GLint RefCount; - GLenum Target; /**< GL_VERTEX/FRAGMENT_PROGRAM_ARB */ + GLenum Target; /**< GL_VERTEX/FRAGMENT_PROGRAM_ARB, GL_GEOMETRY_PROGRAM_NV */ GLenum Format; /**< String encoding format */ struct prog_instruction *Instructions; @@ -1918,6 +1919,7 @@ struct gl_geometry_program { struct gl_program Base; /**< base class */ + GLint VerticesIn; GLint VerticesOut; GLenum InputType; /**< GL_POINTS, GL_LINES, GL_LINES_ADJACENCY_ARB, GL_TRIANGLES, or GL_TRIANGLES_ADJACENCY_ARB */ @@ -2169,6 +2171,24 @@ struct gl_shader /** Shaders containing built-in functions that are used for linking. */ struct gl_shader *builtins_to_link[16]; unsigned num_builtins_to_link; + + /** + * Geometry shader state from GLSL 1.50 layout qualifiers. + */ + struct { + GLint VerticesOut; + /** + * GL_POINTS, GL_LINES, GL_LINES_ADJACENCY, GL_TRIANGLES, or + * GL_TRIANGLES_ADJACENCY, or PRIM_UNKNOWN if it's not set in this + * shader. + */ + GLenum InputType; + /** + * GL_POINTS, GL_LINE_STRIP or GL_TRIANGLE_STRIP, or PRIM_UNKNOWN if + * it's not set in this shader. + */ + GLenum OutputType; + } Geom; }; @@ -2318,17 +2338,25 @@ struct gl_shader_program /** Post-link gl_FragDepth layout for ARB_conservative_depth. */ enum gl_frag_depth_layout FragDepthLayout; - /** Geometry shader state - copied into gl_geometry_program at link time */ + /** + * Geometry shader state - copied into gl_geometry_program by + * _mesa_copy_linked_program_data(). + */ struct { + GLint VerticesIn; GLint VerticesOut; GLenum InputType; /**< GL_POINTS, GL_LINES, GL_LINES_ADJACENCY_ARB, GL_TRIANGLES, or GL_TRIANGLES_ADJACENCY_ARB */ GLenum OutputType; /**< GL_POINTS, GL_LINE_STRIP or GL_TRIANGLE_STRIP */ } Geom; - /** Vertex shader state - copied into gl_vertex_program at link time */ + /** Vertex shader state */ struct { - GLboolean UsesClipDistance; /**< True if gl_ClipDistance is written to. */ + /** + * True if gl_ClipDistance is written to. Copied into gl_vertex_program + * by _mesa_copy_linked_program_data(). + */ + GLboolean UsesClipDistance; GLuint ClipDistanceArraySize; /**< Size of the gl_ClipDistance array, or 0 if not present. */ } Vert; diff --git a/mesalib/src/mesa/main/shaderapi.c b/mesalib/src/mesa/main/shaderapi.c index c349b0cb5..d184b114c 100644 --- a/mesalib/src/mesa/main/shaderapi.c +++ b/mesalib/src/mesa/main/shaderapi.c @@ -179,7 +179,7 @@ validate_shader_target(const struct gl_context *ctx, GLenum type) case GL_VERTEX_SHADER: return ctx->Extensions.ARB_vertex_shader; case GL_GEOMETRY_SHADER_ARB: - return _mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_geometry_shader4; + return _mesa_has_geometry_shaders(ctx); default: return false; } @@ -478,8 +478,7 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname, GLint *param /* Are geometry shaders available in this context? */ - const bool has_gs = - _mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_geometry_shader4; + const bool has_gs = _mesa_has_geometry_shaders(ctx); /* Are uniform buffer objects available in this context? */ @@ -743,6 +742,12 @@ compile_shader(struct gl_context *ctx, GLuint shaderObj) if (!sh) return; + /* Geometry shaders are not yet fully supported, so issue a warning message + * if we're compiling one. + */ + if (sh->Type == GL_GEOMETRY_SHADER) + printf("WARNING: Geometry shader support is currently experimental.\n"); + options = &ctx->ShaderCompilerOptions[_mesa_shader_type_to_index(sh->Type)]; /* set default pragma state for shader */ @@ -1635,10 +1640,10 @@ _mesa_ProgramParameteri(GLuint program, GLenum pname, GLint value) if (!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_geometry_shader4) break; - if (value < 1 || + if (value < 0 || (unsigned) value > ctx->Const.MaxGeometryOutputVertices) { _mesa_error(ctx, GL_INVALID_VALUE, - "glProgramParameteri(GL_GEOMETRY_VERTICES_OUT_ARB=%d", + "glProgramParameteri(GL_GEOMETRY_VERTICES_OUT_ARB=%d)", value); return; } @@ -1658,7 +1663,7 @@ _mesa_ProgramParameteri(GLuint program, GLenum pname, GLint value) break; default: _mesa_error(ctx, GL_INVALID_VALUE, - "glProgramParameteri(geometry input type = %s", + "glProgramParameteri(geometry input type = %s)", _mesa_lookup_enum_by_nr(value)); return; } @@ -1675,7 +1680,7 @@ _mesa_ProgramParameteri(GLuint program, GLenum pname, GLint value) break; default: _mesa_error(ctx, GL_INVALID_VALUE, - "glProgramParameteri(geometry output type = %s", + "glProgramParameteri(geometry output type = %s)", _mesa_lookup_enum_by_nr(value)); return; } @@ -1843,3 +1848,32 @@ _mesa_CreateShaderProgramEXT(GLenum type, const GLchar *string) return program; } + + +/** + * Copy program-specific data generated by linking from the gl_shader_program + * object to a specific gl_program object. + */ +void +_mesa_copy_linked_program_data(gl_shader_type type, + const struct gl_shader_program *src, + struct gl_program *dst) +{ + switch (type) { + case MESA_SHADER_VERTEX: { + struct gl_vertex_program *dst_vp = (struct gl_vertex_program *) dst; + dst_vp->UsesClipDistance = src->Vert.UsesClipDistance; + } + break; + case MESA_SHADER_GEOMETRY: { + struct gl_geometry_program *dst_gp = (struct gl_geometry_program *) dst; + dst_gp->VerticesIn = src->Geom.VerticesIn; + dst_gp->VerticesOut = src->Geom.VerticesOut; + dst_gp->InputType = src->Geom.InputType; + dst_gp->OutputType = src->Geom.OutputType; + } + break; + default: + break; + } +} diff --git a/mesalib/src/mesa/main/shaderapi.h b/mesalib/src/mesa/main/shaderapi.h index 1cd4ffcea..fe58e7de9 100644 --- a/mesalib/src/mesa/main/shaderapi.h +++ b/mesalib/src/mesa/main/shaderapi.h @@ -210,6 +210,11 @@ _mesa_ActiveProgramEXT(GLuint program); extern GLuint GLAPIENTRY _mesa_CreateShaderProgramEXT(GLenum type, const GLchar *string); +extern void +_mesa_copy_linked_program_data(gl_shader_type type, + const struct gl_shader_program *src, + struct gl_program *dst); + #ifdef __cplusplus } diff --git a/mesalib/src/mesa/main/shared.c b/mesalib/src/mesa/main/shared.c index 5ef88098f..2f73cf3ca 100644 --- a/mesalib/src/mesa/main/shared.c +++ b/mesalib/src/mesa/main/shared.c @@ -218,7 +218,8 @@ delete_shader_cb(GLuint id, void *data, void *userData) { struct gl_context *ctx = (struct gl_context *) userData; struct gl_shader *sh = (struct gl_shader *) data; - if (sh->Type == GL_FRAGMENT_SHADER || sh->Type == GL_VERTEX_SHADER) { + if (sh->Type == GL_FRAGMENT_SHADER || sh->Type == GL_VERTEX_SHADER || + sh->Type == GL_GEOMETRY_SHADER) { ctx->Driver.DeleteShader(ctx, sh); } else { diff --git a/mesalib/src/mesa/main/texobj.c b/mesalib/src/mesa/main/texobj.c index 334dee77b..7c8f04db9 100644 --- a/mesalib/src/mesa/main/texobj.c +++ b/mesalib/src/mesa/main/texobj.c @@ -548,12 +548,13 @@ _mesa_test_texobj_completeness( const struct gl_context *ctx, ASSERT(maxLevels > 0); - t->_MaxLevel = - baseLevel + baseImage->MaxNumLevels - 1; /* 'p' in the GL spec */ - t->_MaxLevel = MIN2(t->_MaxLevel, t->MaxLevel); - t->_MaxLevel = MIN2(t->_MaxLevel, maxLevels - 1); /* 'q' in the GL spec */ + t->_MaxLevel = MIN3(t->MaxLevel, + /* 'p' in the GL spec */ + baseLevel + baseImage->MaxNumLevels - 1, + /* 'q' in the GL spec */ + maxLevels - 1); - /* Compute _MaxLambda = q - b (see the 1.2 spec) used during mipmapping */ + /* Compute _MaxLambda = q - p in the spec used during mipmapping */ t->_MaxLambda = (GLfloat) (t->_MaxLevel - baseLevel); if (t->Immutable) { @@ -1040,23 +1041,35 @@ static void unbind_texobj_from_fbo(struct gl_context *ctx, struct gl_texture_object *texObj) { - const GLuint n = (ctx->DrawBuffer == ctx->ReadBuffer) ? 1 : 2; - GLuint i; + bool progress = false; - for (i = 0; i < n; i++) { - struct gl_framebuffer *fb = (i == 0) ? ctx->DrawBuffer : ctx->ReadBuffer; - if (_mesa_is_user_fbo(fb)) { - GLuint j; - for (j = 0; j < BUFFER_COUNT; j++) { - if (fb->Attachment[j].Type == GL_TEXTURE && - fb->Attachment[j].Texture == texObj) { - /* Vertices are already flushed by _mesa_DeleteTextures */ - ctx->NewState |= _NEW_BUFFERS; - _mesa_remove_attachment(ctx, fb->Attachment + j); - } - } - } + /* Section 4.4.2 (Attaching Images to Framebuffer Objects), subsection + * "Attaching Texture Images to a Framebuffer," of the OpenGL 3.1 spec + * says: + * + * "If a texture object is deleted while its image is attached to one + * or more attachment points in the currently bound framebuffer, then + * it is as if FramebufferTexture* had been called, with a texture of + * zero, for each attachment point to which this image was attached in + * the currently bound framebuffer. In other words, this texture image + * is first detached from all attachment points in the currently bound + * framebuffer. Note that the texture image is specifically not + * detached from any other framebuffer objects. Detaching the texture + * image from any other framebuffer objects is the responsibility of + * the application." + */ + if (_mesa_is_user_fbo(ctx->DrawBuffer)) { + progress = _mesa_detach_renderbuffer(ctx, ctx->DrawBuffer, texObj); } + if (_mesa_is_user_fbo(ctx->ReadBuffer) + && ctx->ReadBuffer != ctx->DrawBuffer) { + progress = _mesa_detach_renderbuffer(ctx, ctx->ReadBuffer, texObj) + || progress; + } + + if (progress) + /* Vertices are already flushed by _mesa_DeleteTextures */ + ctx->NewState |= _NEW_BUFFERS; } diff --git a/mesalib/src/mesa/main/texparam.c b/mesalib/src/mesa/main/texparam.c index 32109951c..757ae80ec 100644 --- a/mesalib/src/mesa/main/texparam.c +++ b/mesalib/src/mesa/main/texparam.c @@ -386,7 +386,13 @@ set_tex_parameteri(struct gl_context *ctx, return GL_FALSE; } incomplete(ctx, texObj); - texObj->BaseLevel = params[0]; + + /** See note about ARB_texture_storage below */ + if (texObj->Immutable) + texObj->BaseLevel = MIN2(texObj->ImmutableLevels - 1, params[0]); + else + texObj->BaseLevel = params[0]; + return GL_TRUE; case GL_TEXTURE_MAX_LEVEL: @@ -399,7 +405,19 @@ set_tex_parameteri(struct gl_context *ctx, return GL_FALSE; } incomplete(ctx, texObj); - texObj->MaxLevel = params[0]; + + /** From ARB_texture_storage: + * However, if TEXTURE_IMMUTABLE_FORMAT is TRUE, then level_base is + * clamped to the range [0, <levels> - 1] and level_max is then clamped to + * the range [level_base, <levels> - 1], where <levels> is the parameter + * passed the call to TexStorage* for the texture object. + */ + if (texObj->Immutable) + texObj->MaxLevel = CLAMP(params[0], texObj->BaseLevel, + texObj->ImmutableLevels - 1); + else + texObj->MaxLevel = params[0]; + return GL_TRUE; case GL_GENERATE_MIPMAP_SGIS: diff --git a/mesalib/src/mesa/main/texstate.c b/mesalib/src/mesa/main/texstate.c index afff01359..dad69a8f6 100644 --- a/mesalib/src/mesa/main/texstate.c +++ b/mesalib/src/mesa/main/texstate.c @@ -528,6 +528,7 @@ update_texture_state( struct gl_context *ctx ) GLuint unit; struct gl_program *fprog = NULL; struct gl_program *vprog = NULL; + struct gl_program *gprog = NULL; GLbitfield enabledFragUnits = 0x0; if (ctx->Shader.CurrentVertexProgram && @@ -535,6 +536,11 @@ update_texture_state( struct gl_context *ctx ) vprog = ctx->Shader.CurrentVertexProgram->_LinkedShaders[MESA_SHADER_VERTEX]->Program; } + if (ctx->Shader.CurrentGeometryProgram && + ctx->Shader.CurrentGeometryProgram->LinkStatus) { + gprog = ctx->Shader.CurrentGeometryProgram->_LinkedShaders[MESA_SHADER_GEOMETRY]->Program; + } + if (ctx->Shader.CurrentFragmentProgram && ctx->Shader.CurrentFragmentProgram->LinkStatus) { fprog = ctx->Shader.CurrentFragmentProgram->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program; @@ -543,10 +549,6 @@ update_texture_state( struct gl_context *ctx ) fprog = &ctx->FragmentProgram.Current->Base; } - /* FINISHME: Geometry shader texture accesses should also be considered - * FINISHME: here. - */ - /* TODO: only set this if there are actual changes */ ctx->NewState |= _NEW_TEXTURE; @@ -562,6 +564,7 @@ update_texture_state( struct gl_context *ctx ) struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; GLbitfield enabledVertTargets = 0x0; GLbitfield enabledFragTargets = 0x0; + GLbitfield enabledGeomTargets = 0x0; GLbitfield enabledTargets = 0x0; GLuint texIndex; @@ -575,6 +578,10 @@ update_texture_state( struct gl_context *ctx ) enabledVertTargets |= vprog->TexturesUsed[unit]; } + if (gprog) { + enabledGeomTargets |= gprog->TexturesUsed[unit]; + } + if (fprog) { enabledFragTargets |= fprog->TexturesUsed[unit]; } @@ -583,7 +590,8 @@ update_texture_state( struct gl_context *ctx ) enabledFragTargets |= texUnit->Enabled; } - enabledTargets = enabledVertTargets | enabledFragTargets; + enabledTargets = enabledVertTargets | enabledFragTargets | + enabledGeomTargets; texUnit->_ReallyEnabled = 0x0; diff --git a/mesalib/src/mesa/main/varray.c b/mesalib/src/mesa/main/varray.c index 529d93324..dee476abb 100644 --- a/mesalib/src/mesa/main/varray.c +++ b/mesalib/src/mesa/main/varray.c @@ -196,6 +196,16 @@ update_array(struct gl_context *ctx, if (ctx->Extensions.EXT_vertex_array_bgra && sizeMax == BGRA_OR_4 && size == GL_BGRA) { + /* Page 298 of the PDF of the OpenGL 4.3 (Core Profile) spec says: + * + * "An INVALID_OPERATION error is generated under any of the following + * conditions: + * ... + * • size is BGRA and type is not UNSIGNED_BYTE, INT_2_10_10_10_REV + * or UNSIGNED_INT_2_10_10_10_REV; + * ... + * • size is BGRA and normalized is FALSE;" + */ GLboolean bgra_error = GL_FALSE; if (ctx->Extensions.ARB_vertex_type_2_10_10_10_rev) { @@ -207,9 +217,17 @@ update_array(struct gl_context *ctx, bgra_error = GL_TRUE; if (bgra_error) { - _mesa_error(ctx, GL_INVALID_VALUE, "%s(GL_BGRA/GLubyte)", func); + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(size=GL_BGRA and type=%s)", + func, _mesa_lookup_enum_by_nr(type)); return; } + + if (!normalized) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(size=GL_BGRA and normalized=GL_FALSE)", func); + return; + } + format = GL_BGRA; size = 4; } diff --git a/mesalib/src/mesa/main/version.c b/mesalib/src/mesa/main/version.c index abcf90eec..ee77947b4 100644 --- a/mesalib/src/mesa/main/version.c +++ b/mesalib/src/mesa/main/version.c @@ -262,7 +262,6 @@ compute_version(struct gl_context *ctx) ctx->Extensions.ARB_depth_clamp && ctx->Extensions.ARB_draw_elements_base_vertex && ctx->Extensions.ARB_fragment_coord_conventions && - ctx->Extensions.ARB_geometry_shader4 && ctx->Extensions.EXT_provoking_vertex && ctx->Extensions.ARB_seamless_cube_map && ctx->Extensions.ARB_sync && diff --git a/mesalib/src/mesa/program/ir_to_mesa.cpp b/mesalib/src/mesa/program/ir_to_mesa.cpp index f0fc1b9b1..f612f41ba 100644 --- a/mesalib/src/mesa/program/ir_to_mesa.cpp +++ b/mesalib/src/mesa/program/ir_to_mesa.cpp @@ -265,6 +265,8 @@ public: virtual void visit(ir_discard *); virtual void visit(ir_texture *); virtual void visit(ir_if *); + virtual void visit(ir_emit_vertex *); + virtual void visit(ir_end_primitive *); /*@}*/ src_reg result; @@ -2252,6 +2254,18 @@ ir_to_mesa_visitor::visit(ir_if *ir) if_inst = emit(ir->condition, OPCODE_ENDIF); } +void +ir_to_mesa_visitor::visit(ir_emit_vertex *ir) +{ + assert(!"Geometry shaders not supported."); +} + +void +ir_to_mesa_visitor::visit(ir_end_primitive *ir) +{ + assert(!"Geometry shaders not supported."); +} + ir_to_mesa_visitor::ir_to_mesa_visitor() { result.file = PROGRAM_UNDEFINED; @@ -2961,7 +2975,7 @@ get_mesa_program(struct gl_context *ctx, */ mesa_instructions = NULL; - do_set_program_inouts(shader->ir, prog, shader->Type == GL_FRAGMENT_SHADER); + do_set_program_inouts(shader->ir, prog, shader->Type); prog->SamplersUsed = shader->active_samplers; prog->ShadowSamplers = shader->shadow_samplers; @@ -3073,10 +3087,7 @@ _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) { - if (i == MESA_SHADER_VERTEX) { - ((struct gl_vertex_program *)linked_prog)->UsesClipDistance - = prog->Vert.UsesClipDistance; - } + _mesa_copy_linked_program_data((gl_shader_type) i, prog, linked_prog); _mesa_reference_program(ctx, &prog->_LinkedShaders[i]->Program, linked_prog); 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 3dfd5e5b3..4e29e4500 100644 --- a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp +++ b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp @@ -369,6 +369,8 @@ public: virtual void visit(ir_discard *); virtual void visit(ir_texture *); virtual void visit(ir_if *); + virtual void visit(ir_emit_vertex *); + virtual void visit(ir_end_primitive *); /*@}*/ st_src_reg result; @@ -418,8 +420,6 @@ public: void emit_scalar(ir_instruction *ir, unsigned op, st_dst_reg dst, st_src_reg src0, st_src_reg src1); - void try_emit_float_set(ir_instruction *ir, unsigned op, st_dst_reg dst); - void emit_arl(ir_instruction *ir, st_dst_reg dst, st_src_reg src0); void emit_scs(ir_instruction *ir, unsigned op, @@ -592,9 +592,6 @@ glsl_to_tgsi_visitor::emit(ir_instruction *ir, unsigned op, this->instructions.push_tail(inst); - if (native_integers) - try_emit_float_set(ir, op, dst); - return inst; } @@ -620,25 +617,6 @@ glsl_to_tgsi_visitor::emit(ir_instruction *ir, unsigned op) return emit(ir, op, undef_dst, undef_src, undef_src, undef_src); } - /** - * Emits the code to convert the result of float SET instructions to integers. - */ -void -glsl_to_tgsi_visitor::try_emit_float_set(ir_instruction *ir, unsigned op, - st_dst_reg dst) -{ - if ((op == TGSI_OPCODE_SEQ || - op == TGSI_OPCODE_SNE || - op == TGSI_OPCODE_SGE || - op == TGSI_OPCODE_SLT)) - { - st_src_reg src = st_src_reg(dst); - src.negate = ~src.negate; - dst.type = GLSL_TYPE_FLOAT; - emit(ir, TGSI_OPCODE_F2I, dst, src); - } -} - /** * Determines whether to use an integer, unsigned integer, or float opcode * based on the operands and input opcode, then emits the result. @@ -662,14 +640,30 @@ glsl_to_tgsi_visitor::get_opcode(ir_instruction *ir, unsigned op, #define case4(c, f, i, u) \ case TGSI_OPCODE_##c: \ - if (type == GLSL_TYPE_INT) op = TGSI_OPCODE_##i; \ - else if (type == GLSL_TYPE_UINT) op = TGSI_OPCODE_##u; \ - else op = TGSI_OPCODE_##f; \ + if (type == GLSL_TYPE_INT) \ + op = TGSI_OPCODE_##i; \ + else if (type == GLSL_TYPE_UINT) \ + op = TGSI_OPCODE_##u; \ + else \ + op = TGSI_OPCODE_##f; \ break; + #define case3(f, i, u) case4(f, f, i, u) #define case2fi(f, i) case4(f, f, i, i) #define case2iu(i, u) case4(i, LAST, i, u) - + +#define casecomp(c, f, i, u) \ + case TGSI_OPCODE_##c: \ + if (type == GLSL_TYPE_INT) \ + op = TGSI_OPCODE_##i; \ + else if (type == GLSL_TYPE_UINT) \ + op = TGSI_OPCODE_##u; \ + else if (native_integers) \ + op = TGSI_OPCODE_##f; \ + else \ + op = TGSI_OPCODE_##c; \ + break; + switch(op) { case2fi(ADD, UADD); case2fi(MUL, UMUL); @@ -678,12 +672,12 @@ glsl_to_tgsi_visitor::get_opcode(ir_instruction *ir, unsigned op, case3(MAX, IMAX, UMAX); case3(MIN, IMIN, UMIN); case2iu(MOD, UMOD); - - case2fi(SEQ, USEQ); - case2fi(SNE, USNE); - case3(SGE, ISGE, USGE); - case3(SLT, ISLT, USLT); - + + casecomp(SEQ, FSEQ, USEQ, USEQ); + casecomp(SNE, FSNE, USNE, USNE); + casecomp(SGE, FSGE, ISGE, USGE); + casecomp(SLT, FSLT, ISLT, USLT); + case2iu(ISHR, USHR); case2fi(SSG, ISSG); @@ -3015,6 +3009,18 @@ glsl_to_tgsi_visitor::visit(ir_if *ir) if_inst = emit(ir->condition, TGSI_OPCODE_ENDIF); } +void +glsl_to_tgsi_visitor::visit(ir_emit_vertex *ir) +{ + assert(!"Geometry shaders not supported."); +} + +void +glsl_to_tgsi_visitor::visit(ir_end_primitive *ir) +{ + assert(!"Geometry shaders not supported."); +} + glsl_to_tgsi_visitor::glsl_to_tgsi_visitor() { result.file = PROGRAM_UNDEFINED; @@ -5121,7 +5127,7 @@ get_mesa_program(struct gl_context *ctx, prog->Instructions = NULL; prog->NumInstructions = 0; - do_set_program_inouts(shader->ir, prog, shader->Type == GL_FRAGMENT_SHADER); + do_set_program_inouts(shader->ir, prog, shader->Type); count_resources(v, prog); _mesa_reference_program(ctx, &shader->Program, prog); diff --git a/mesalib/src/mesa/vbo/vbo_exec_array.c b/mesalib/src/mesa/vbo/vbo_exec_array.c index 75831faf9..bd05cd0c3 100644 --- a/mesalib/src/mesa/vbo/vbo_exec_array.c +++ b/mesalib/src/mesa/vbo/vbo_exec_array.c @@ -442,41 +442,77 @@ recalculate_input_bindings(struct gl_context *ctx) break; case VP_ARB: - /* GL_ARB_vertex_program or GLSL vertex shader - Only the generic[0] + /* There are no shaders in OpenGL ES 1.x, so this code path should be + * impossible to reach. The meta code is careful to not use shaders in + * ES1. + */ + assert(ctx->API != API_OPENGLES); + + /* In the compatibility profile of desktop OpenGL, the generic[0] * attribute array aliases and overrides the legacy position array. - * * Otherwise, legacy attributes available in the legacy slots, * generic attributes in the generic slots and materials are not * available as per-vertex attributes. + * + * In all other APIs, only the generic attributes exist, and none of the + * slots are considered "magic." */ - if (vertexAttrib[VERT_ATTRIB_GENERIC0].Enabled) - inputs[0] = &vertexAttrib[VERT_ATTRIB_GENERIC0]; - else if (vertexAttrib[VERT_ATTRIB_POS].Enabled) - inputs[0] = &vertexAttrib[VERT_ATTRIB_POS]; - else { - inputs[0] = &vbo->currval[VBO_ATTRIB_POS]; - const_inputs |= VERT_BIT_POS; - } + if (ctx->API == API_OPENGL_COMPAT) { + if (vertexAttrib[VERT_ATTRIB_GENERIC0].Enabled) + inputs[0] = &vertexAttrib[VERT_ATTRIB_GENERIC0]; + else if (vertexAttrib[VERT_ATTRIB_POS].Enabled) + inputs[0] = &vertexAttrib[VERT_ATTRIB_POS]; + else { + inputs[0] = &vbo->currval[VBO_ATTRIB_POS]; + const_inputs |= VERT_BIT_POS; + } - for (i = 1; i < VERT_ATTRIB_FF_MAX; i++) { - if (vertexAttrib[VERT_ATTRIB_FF(i)].Enabled) - inputs[i] = &vertexAttrib[VERT_ATTRIB_FF(i)]; - else { - inputs[i] = &vbo->currval[VBO_ATTRIB_POS+i]; + for (i = 1; i < VERT_ATTRIB_FF_MAX; i++) { + if (vertexAttrib[VERT_ATTRIB_FF(i)].Enabled) + inputs[i] = &vertexAttrib[VERT_ATTRIB_FF(i)]; + else { + inputs[i] = &vbo->currval[VBO_ATTRIB_POS+i]; + const_inputs |= VERT_BIT_FF(i); + } + } + + for (i = 1; i < VERT_ATTRIB_GENERIC_MAX; i++) { + if (vertexAttrib[VERT_ATTRIB_GENERIC(i)].Enabled) + inputs[VERT_ATTRIB_GENERIC(i)] = + &vertexAttrib[VERT_ATTRIB_GENERIC(i)]; + else { + inputs[VERT_ATTRIB_GENERIC(i)] = + &vbo->currval[VBO_ATTRIB_GENERIC0+i]; + const_inputs |= VERT_BIT_GENERIC(i); + } + } + + inputs[VERT_ATTRIB_GENERIC0] = inputs[0]; + } else { + /* Other parts of the code assume that inputs[0] through + * inputs[VERT_ATTRIB_FF_MAX] will be non-NULL. However, in OpenGL + * ES 2.0+ or OpenGL core profile, none of these arrays should ever + * be enabled. + */ + for (i = 0; i < VERT_ATTRIB_FF_MAX; i++) { + assert(!vertexAttrib[VERT_ATTRIB_FF(i)].Enabled); + + inputs[i] = &vbo->currval[VBO_ATTRIB_POS+i]; const_inputs |= VERT_BIT_FF(i); } - } - for (i = 1; i < VERT_ATTRIB_GENERIC_MAX; i++) { - if (vertexAttrib[VERT_ATTRIB_GENERIC(i)].Enabled) - inputs[VERT_ATTRIB_GENERIC(i)] = &vertexAttrib[VERT_ATTRIB_GENERIC(i)]; - else { - inputs[VERT_ATTRIB_GENERIC(i)] = &vbo->currval[VBO_ATTRIB_GENERIC0+i]; - const_inputs |= VERT_BIT_GENERIC(i); + for (i = 0; i < VERT_ATTRIB_GENERIC_MAX; i++) { + if (vertexAttrib[VERT_ATTRIB_GENERIC(i)].Enabled) + inputs[VERT_ATTRIB_GENERIC(i)] = + &vertexAttrib[VERT_ATTRIB_GENERIC(i)]; + else { + inputs[VERT_ATTRIB_GENERIC(i)] = + &vbo->currval[VBO_ATTRIB_GENERIC0+i]; + const_inputs |= VERT_BIT_GENERIC(i); + } } } - inputs[VERT_ATTRIB_GENERIC0] = inputs[0]; break; } diff --git a/pixman/RELEASING b/pixman/RELEASING index fbe15813d..657857de2 100644 --- a/pixman/RELEASING +++ b/pixman/RELEASING @@ -55,3 +55,5 @@ Here are the steps to follow to create a new pixman release: You must use "--tags" here; otherwise the new tag will not be pushed out. +8) Change the topic of the #cairo IRC channel on freenode to advertise + the new version. diff --git a/pixman/pixman/pixman-fast-path.c b/pixman/pixman/pixman-fast-path.c index 3982dce8b..2608268d9 100644 --- a/pixman/pixman/pixman-fast-path.c +++ b/pixman/pixman/pixman-fast-path.c @@ -2261,6 +2261,237 @@ fast_write_back_r5g6b5 (pixman_iter_t *iter) } } +typedef struct +{ + int y; + uint64_t * buffer; +} line_t; + +typedef struct +{ + line_t line0; + line_t line1; + pixman_fixed_t y; + pixman_fixed_t x; + uint64_t data[1]; +} bilinear_info_t; + +static void +fetch_horizontal (bits_image_t *image, line_t *line, + int y, pixman_fixed_t x, pixman_fixed_t ux, int n) +{ + uint32_t *bits = image->bits + y * image->rowstride; + int i; + + for (i = 0; i < n; ++i) + { + int x0 = pixman_fixed_to_int (x); + int x1 = x0 + 1; + int32_t dist_x; + + uint32_t left = *(bits + x0); + uint32_t right = *(bits + x1); + + dist_x = pixman_fixed_to_bilinear_weight (x); + dist_x <<= (8 - BILINEAR_INTERPOLATION_BITS); + +#if SIZEOF_LONG <= 4 + { + uint32_t lag, rag, ag; + uint32_t lrb, rrb, rb; + + lag = (left & 0xff00ff00) >> 8; + rag = (right & 0xff00ff00) >> 8; + ag = (lag << 8) + dist_x * (rag - lag); + + lrb = (left & 0x00ff00ff); + rrb = (right & 0x00ff00ff); + rb = (lrb << 8) + dist_x * (rrb - lrb); + + *((uint32_t *)(line->buffer + i)) = ag; + *((uint32_t *)(line->buffer + i) + 1) = rb; + } +#else + { + uint64_t lagrb, ragrb; + uint32_t lag, rag; + uint32_t lrb, rrb; + + lag = (left & 0xff00ff00); + lrb = (left & 0x00ff00ff); + rag = (right & 0xff00ff00); + rrb = (right & 0x00ff00ff); + lagrb = (((uint64_t)lag) << 24) | lrb; + ragrb = (((uint64_t)rag) << 24) | rrb; + + line->buffer[i] = (lagrb << 8) + dist_x * (ragrb - lagrb); + } +#endif + + x += ux; + } + + line->y = y; +} + +static uint32_t * +fast_fetch_bilinear_cover (pixman_iter_t *iter, const uint32_t *mask) +{ + pixman_fixed_t fx, ux; + bilinear_info_t *info = iter->data; + line_t *line0, *line1; + int y0, y1; + int32_t dist_y; + int i; + + fx = info->x; + ux = iter->image->common.transform->matrix[0][0]; + + y0 = pixman_fixed_to_int (info->y); + y1 = y0 + 1; + dist_y = pixman_fixed_to_bilinear_weight (info->y); + dist_y <<= (8 - BILINEAR_INTERPOLATION_BITS); + + line0 = &info->line0; + line1 = &info->line1; + + if (line0->y != y0 || line1->y != y1) + { + if (line0->y == y1 || line1->y == y0) + { + line_t tmp = *line0; + *line0 = *line1; + *line1 = tmp; + } + + if (line0->y != y0) + { + fetch_horizontal ( + &iter->image->bits, line0, y0, fx, ux, iter->width); + } + + if (line1->y != y1) + { + fetch_horizontal ( + &iter->image->bits, line1, y1, fx, ux, iter->width); + } + } + + for (i = 0; i < iter->width; ++i) + { +#if SIZEOF_LONG <= 4 + uint32_t ta, tr, tg, tb; + uint32_t ba, br, bg, bb; + uint32_t tag, trb; + uint32_t bag, brb; + uint32_t a, r, g, b; + + tag = *((uint32_t *)(line0->buffer + i)); + trb = *((uint32_t *)(line0->buffer + i) + 1); + bag = *((uint32_t *)(line1->buffer + i)); + brb = *((uint32_t *)(line1->buffer + i) + 1); + + ta = tag >> 16; + ba = bag >> 16; + a = (ta << 8) + dist_y * (ba - ta); + + tr = trb >> 16; + br = brb >> 16; + r = (tr << 8) + dist_y * (br - tr); + + tg = tag & 0xffff; + bg = bag & 0xffff; + g = (tg << 8) + dist_y * (bg - tg); + + tb = trb & 0xffff; + bb = brb & 0xffff; + b = (tb << 8) + dist_y * (bb - tb); + + a = (a << 8) & 0xff000000; + r = (r << 0) & 0x00ff0000; + g = (g >> 8) & 0x0000ff00; + b = (b >> 16) & 0x000000ff; +#else + uint64_t top = line0->buffer[i]; + uint64_t bot = line1->buffer[i]; + uint64_t tar = (top & 0xffff0000ffff0000ULL) >> 16; + uint64_t bar = (bot & 0xffff0000ffff0000ULL) >> 16; + uint64_t tgb = (top & 0x0000ffff0000ffffULL); + uint64_t bgb = (bot & 0x0000ffff0000ffffULL); + uint64_t ar, gb; + uint32_t a, r, g, b; + + ar = (tar << 8) + dist_y * (bar - tar); + gb = (tgb << 8) + dist_y * (bgb - tgb); + + a = ((ar >> 24) & 0xff000000); + r = ((ar >> 0) & 0x00ff0000); + g = ((gb >> 40) & 0x0000ff00); + b = ((gb >> 16) & 0x000000ff); +#endif + + iter->buffer[i] = a | r | g | b; + } + + info->y += iter->image->common.transform->matrix[1][1]; + + return iter->buffer; +} + +static void +bilinear_cover_iter_fini (pixman_iter_t *iter) +{ + free (iter->data); +} + +static void +fast_bilinear_cover_iter_init (pixman_iter_t *iter, const pixman_iter_info_t *iter_info) +{ + int width = iter->width; + bilinear_info_t *info; + pixman_vector_t v; + + /* Reference point is the center of the pixel */ + v.vector[0] = pixman_int_to_fixed (iter->x) + pixman_fixed_1 / 2; + v.vector[1] = pixman_int_to_fixed (iter->y) + pixman_fixed_1 / 2; + v.vector[2] = pixman_fixed_1; + + if (!pixman_transform_point_3d (iter->image->common.transform, &v)) + goto fail; + + info = malloc (sizeof (*info) + (2 * width - 1) * sizeof (uint64_t)); + if (!info) + goto fail; + + info->x = v.vector[0] - pixman_fixed_1 / 2; + info->y = v.vector[1] - pixman_fixed_1 / 2; + + /* It is safe to set the y coordinates to -1 initially + * because COVER_CLIP_BILINEAR ensures that we will only + * be asked to fetch lines in the [0, height) interval + */ + info->line0.y = -1; + info->line0.buffer = &(info->data[0]); + info->line1.y = -1; + info->line1.buffer = &(info->data[width]); + + iter->get_scanline = fast_fetch_bilinear_cover; + iter->fini = bilinear_cover_iter_fini; + + iter->data = info; + return; + +fail: + /* Something went wrong, either a bad matrix or OOM; in such cases, + * we don't guarantee any particular rendering. + */ + _pixman_log_error ( + FUNC, "Allocation failure or bad matrix, skipping rendering\n"); + + iter->get_scanline = _pixman_iter_get_scanline_noop; + iter->fini = bilinear_cover_iter_fini; +} + #define IMAGE_FLAGS \ (FAST_PATH_STANDARD_FLAGS | FAST_PATH_ID_TRANSFORM | \ FAST_PATH_BITS_IMAGE | FAST_PATH_SAMPLES_COVER_CLIP_NEAREST) @@ -2280,6 +2511,16 @@ static const pixman_iter_info_t fast_iters[] = _pixman_iter_init_bits_stride, fast_dest_fetch_noop, fast_write_back_r5g6b5 }, + { PIXMAN_a8r8g8b8, + (FAST_PATH_STANDARD_FLAGS | + FAST_PATH_SCALE_TRANSFORM | + FAST_PATH_BILINEAR_FILTER | + FAST_PATH_SAMPLES_COVER_CLIP_BILINEAR), + ITER_NARROW | ITER_SRC, + fast_bilinear_cover_iter_init, + NULL, NULL + }, + { PIXMAN_null }, }; diff --git a/pixman/pixman/pixman-general.c b/pixman/pixman/pixman-general.c index 4da5da5e2..6310bff9d 100644 --- a/pixman/pixman/pixman-general.c +++ b/pixman/pixman/pixman-general.c @@ -208,6 +208,13 @@ general_composite_rect (pixman_implementation_t *imp, dest_iter.write_back (&dest_iter); } + if (src_iter.fini) + src_iter.fini (&src_iter); + if (mask_iter.fini) + mask_iter.fini (&mask_iter); + if (dest_iter.fini) + dest_iter.fini (&dest_iter); + if (scanline_buffer != (uint8_t *) stack_scanline_buffer) free (scanline_buffer); } diff --git a/pixman/pixman/pixman-image.c b/pixman/pixman/pixman-image.c index 4f9c2f966..1ff1a4974 100644 --- a/pixman/pixman/pixman-image.c +++ b/pixman/pixman/pixman-image.c @@ -926,6 +926,9 @@ _pixman_image_get_solid (pixman_implementation_t *imp, ITER_NARROW | ITER_SRC, image->common.flags); result = *iter.get_scanline (&iter, NULL); + + if (iter.fini) + iter.fini (&iter); } /* If necessary, convert RGB <--> BGR. */ diff --git a/pixman/pixman/pixman-implementation.c b/pixman/pixman/pixman-implementation.c index 7f1332abf..f82c915dc 100644 --- a/pixman/pixman/pixman-implementation.c +++ b/pixman/pixman/pixman-implementation.c @@ -313,6 +313,7 @@ _pixman_implementation_iter_init (pixman_implementation_t *imp, iter->height = height; iter->iter_flags = iter_flags; iter->image_flags = image_flags; + iter->fini = NULL; if (!iter->image) { diff --git a/pixman/pixman/pixman-private.h b/pixman/pixman/pixman-private.h index af4a0b6e0..964660508 100644 --- a/pixman/pixman/pixman-private.h +++ b/pixman/pixman/pixman-private.h @@ -209,6 +209,7 @@ union pixman_image typedef struct pixman_iter_t pixman_iter_t; typedef uint32_t *(* pixman_iter_get_scanline_t) (pixman_iter_t *iter, const uint32_t *mask); typedef void (* pixman_iter_write_back_t) (pixman_iter_t *iter); +typedef void (* pixman_iter_fini_t) (pixman_iter_t *iter); typedef enum { @@ -255,6 +256,7 @@ struct pixman_iter_t /* These function pointers are initialized by the implementation */ pixman_iter_get_scanline_t get_scanline; pixman_iter_write_back_t write_back; + pixman_iter_fini_t fini; /* These fields are scratch data that implementations can use */ void * data; diff --git a/pixman/test/Makefile.sources b/pixman/test/Makefile.sources index b5fc740f3..2fabdb574 100644 --- a/pixman/test/Makefile.sources +++ b/pixman/test/Makefile.sources @@ -33,6 +33,7 @@ OTHERPROGRAMS = \ lowlevel-blt-bench \ radial-perf-test \ check-formats \ + scaling-bench \ $(NULL) # Utility functions diff --git a/pixman/test/alpha-loop.c b/pixman/test/alpha-loop.c index eca761537..4d4384d00 100644 --- a/pixman/test/alpha-loop.c +++ b/pixman/test/alpha-loop.c @@ -8,6 +8,7 @@ int main (int argc, char **argv) { + pixman_image_t *a, *d, *s; uint8_t *alpha; uint32_t *src, *dest; @@ -17,9 +18,9 @@ main (int argc, char **argv) src = (uint32_t *)make_random_bytes (WIDTH * HEIGHT * 4); dest = (uint32_t *)make_random_bytes (WIDTH * HEIGHT * 4); - pixman_image_t *a = pixman_image_create_bits (PIXMAN_a8, WIDTH, HEIGHT, (uint32_t *)alpha, WIDTH); - pixman_image_t *d = pixman_image_create_bits (PIXMAN_a8r8g8b8, WIDTH, HEIGHT, dest, WIDTH * 4); - pixman_image_t *s = pixman_image_create_bits (PIXMAN_a2r10g10b10, WIDTH, HEIGHT, src, WIDTH * 4); + a = pixman_image_create_bits (PIXMAN_a8, WIDTH, HEIGHT, (uint32_t *)alpha, WIDTH); + d = pixman_image_create_bits (PIXMAN_a8r8g8b8, WIDTH, HEIGHT, dest, WIDTH * 4); + s = pixman_image_create_bits (PIXMAN_a2r10g10b10, WIDTH, HEIGHT, src, WIDTH * 4); fail_after (5, "Infinite loop detected: 5 seconds without progress\n"); diff --git a/pixman/test/matrix-test.c b/pixman/test/matrix-test.c index 8437dd291..0a5f203f5 100644 --- a/pixman/test/matrix-test.c +++ b/pixman/test/matrix-test.c @@ -70,6 +70,53 @@ pixman_bool_t does_it_fit_fixed_48_16 (__float128 x) #endif +static inline uint32_t +byteswap32 (uint32_t x) +{ + return ((x & ((uint32_t)0xFF << 24)) >> 24) | + ((x & ((uint32_t)0xFF << 16)) >> 8) | + ((x & ((uint32_t)0xFF << 8)) << 8) | + ((x & ((uint32_t)0xFF << 0)) << 24); +} + +static inline uint64_t +byteswap64 (uint64_t x) +{ + return ((x & ((uint64_t)0xFF << 56)) >> 56) | + ((x & ((uint64_t)0xFF << 48)) >> 40) | + ((x & ((uint64_t)0xFF << 40)) >> 24) | + ((x & ((uint64_t)0xFF << 32)) >> 8) | + ((x & ((uint64_t)0xFF << 24)) << 8) | + ((x & ((uint64_t)0xFF << 16)) << 24) | + ((x & ((uint64_t)0xFF << 8)) << 40) | + ((x & ((uint64_t)0xFF << 0)) << 56); +} + +static void +byteswap_transform (pixman_transform_t *t) +{ + int i, j; + + if (is_little_endian ()) + return; + + for (i = 0; i < 3; i++) + for (j = 0; j < 3; j++) + t->matrix[i][j] = byteswap32 (t->matrix[i][j]); +} + +static void +byteswap_vector_48_16 (pixman_vector_48_16_t *v) +{ + int i; + + if (is_little_endian ()) + return; + + for (i = 0; i < 3; i++) + v->v[i] = byteswap64 (v->v[i]); +} + uint32_t test_matrix (int testnum, int verbose) { @@ -90,6 +137,8 @@ test_matrix (int testnum, int verbose) #endif prng_randmemset (&ti, sizeof(ti), 0); prng_randmemset (&vi, sizeof(vi), 0); + byteswap_transform (&ti); + byteswap_vector_48_16 (&vi); for (j = 0; j < 3; j++) { @@ -132,8 +181,6 @@ test_matrix (int testnum, int verbose) else transform_ok = pixman_transform_point_31_16 (&ti, &vi, &result_i); - crc32 = compute_crc32 (crc32, &result_i, sizeof(result_i)); - #ifdef HAVE_FLOAT128 /* compare with a reference 128-bit floating point implementation */ for (j = 0; j < 3; j++) @@ -173,6 +220,8 @@ test_matrix (int testnum, int verbose) } } #endif + byteswap_vector_48_16 (&result_i); + crc32 = compute_crc32 (crc32, &result_i, sizeof (result_i)); } return crc32; } diff --git a/pixman/test/scaling-bench.c b/pixman/test/scaling-bench.c new file mode 100644 index 000000000..b39adeff5 --- /dev/null +++ b/pixman/test/scaling-bench.c @@ -0,0 +1,69 @@ +#include <stdlib.h> +#include "utils.h" + +#define SOURCE_WIDTH 320 +#define SOURCE_HEIGHT 240 + +static pixman_image_t * +make_source (void) +{ + size_t n_bytes = (SOURCE_WIDTH + 2) * (SOURCE_HEIGHT + 2) * 4; + uint32_t *data = malloc (n_bytes); + pixman_image_t *source; + + prng_randmemset (data, n_bytes, 0); + + source = pixman_image_create_bits ( + PIXMAN_a8r8g8b8, SOURCE_WIDTH + 2, SOURCE_HEIGHT + 2, + data, + (SOURCE_WIDTH + 2) * 4); + + pixman_image_set_filter (source, PIXMAN_FILTER_BILINEAR, NULL, 0); + + return source; +} + +int +main () +{ + double scale; + pixman_image_t *src; + + prng_srand (23874); + + src = make_source (); + printf ("# %-6s %-22s %-14s %-12s\n", + "ratio", + "resolutions", + "time / ms", + "time per pixel / ns"); + for (scale = 0.1; scale < 10.005; scale += 0.01) + { + int dest_width = SOURCE_WIDTH * scale + 0.5; + int dest_height = SOURCE_HEIGHT * scale + 0.5; + pixman_fixed_t s = (1 / scale) * 65536.0 + 0.5; + pixman_transform_t transform; + pixman_image_t *dest; + double t1, t2; + + pixman_transform_init_scale (&transform, s, s); + pixman_image_set_transform (src, &transform); + + dest = pixman_image_create_bits ( + PIXMAN_a8r8g8b8, dest_width, dest_height, NULL, -1); + + t1 = gettime(); + pixman_image_composite ( + PIXMAN_OP_OVER, src, NULL, dest, + scale, scale, 0, 0, 0, 0, dest_width, dest_height); + t2 = gettime(); + + printf ("%6.2f : %4dx%-4d => %4dx%-4d : %12.4f : %12.4f\n", + scale, SOURCE_WIDTH, SOURCE_HEIGHT, dest_width, dest_height, + (t2 - t1) * 1000, ((t2 - t1) / (dest_width * dest_height)) * 1000000000); + + pixman_image_unref (dest); + } + + return 0; +} diff --git a/xorg-server/.dir-locals.el b/xorg-server/.dir-locals.el new file mode 100644 index 000000000..6aceae3a6 --- /dev/null +++ b/xorg-server/.dir-locals.el @@ -0,0 +1 @@ +((c-mode . ((c-basic-offset . 4) (indent-tabs-mode . nil))))
\ No newline at end of file diff --git a/xorg-server/configure.ac b/xorg-server/configure.ac index c6ecba418..d27ca2392 100644 --- a/xorg-server/configure.ac +++ b/xorg-server/configure.ac @@ -215,7 +215,7 @@ AC_SUBST(DLOPEN_LIBS) dnl Checks for library functions. AC_CHECK_FUNCS([backtrace ffs geteuid getuid issetugid getresuid \ getdtablesize getifaddrs getpeereid getpeerucred getzoneid \ - mmap shmctl64 strncasecmp vasprintf vsnprintf walkcontext]) + mmap seteuid shmctl64 strncasecmp vasprintf vsnprintf walkcontext]) AC_REPLACE_FUNCS([strcasecmp strcasestr strlcat strlcpy strndup]) dnl Find the math libary, then check for cbrt function in it. diff --git a/xorg-server/dix/window.c b/xorg-server/dix/window.c index 2e31292d5..c97d04293 100644 --- a/xorg-server/dix/window.c +++ b/xorg-server/dix/window.c @@ -126,6 +126,7 @@ Equipment Corporation. #ifdef COMPOSITE #include "compint.h" #endif +#include "selection.h" #include "privates.h" #include "xace.h" diff --git a/xorg-server/exa/Makefile.am b/xorg-server/exa/Makefile.am index 8b759cd76..c1f1e8638 100644 --- a/xorg-server/exa/Makefile.am +++ b/xorg-server/exa/Makefile.am @@ -8,7 +8,7 @@ if XORG sdk_HEADERS = exa.h endif -INCLUDES = \ +AM_CPPFLAGS = \ $(XORG_INCS) \ -I$(srcdir)/../miext/cw diff --git a/xorg-server/glx/Makefile.am b/xorg-server/glx/Makefile.am index 591c4ac66..d1c203dc9 100644 --- a/xorg-server/glx/Makefile.am +++ b/xorg-server/glx/Makefile.am @@ -15,7 +15,7 @@ AM_CFLAGS = \ # none yet #sdk_HEADERS = -INCLUDES = \ +AM_CPPFLAGS = \ -I$(top_srcdir)/hw/xfree86/os-support \ -I$(top_srcdir)/hw/xfree86/os-support/bus \ -I$(top_srcdir)/hw/xfree86/common \ @@ -23,7 +23,7 @@ INCLUDES = \ -I$(top_srcdir)/mi if DRI2_AIGLX -INCLUDES += -I$(top_srcdir)/hw/xfree86/dri2 +AM_CPPFLAGS += -I$(top_srcdir)/hw/xfree86/dri2 endif glapi_sources = \ diff --git a/xorg-server/hw/kdrive/ephyr/Makefile.am b/xorg-server/hw/kdrive/ephyr/Makefile.am index 2e0613a7c..ab024373c 100644 --- a/xorg-server/hw/kdrive/ephyr/Makefile.am +++ b/xorg-server/hw/kdrive/ephyr/Makefile.am @@ -1,6 +1,6 @@ SUBDIRS = man -INCLUDES = \ +AM_CPPFLAGS = \ @KDRIVE_INCS@ \ @KDRIVE_CFLAGS@ \ @XEPHYR_INCS@ \ diff --git a/xorg-server/hw/kdrive/fake/Makefile.am b/xorg-server/hw/kdrive/fake/Makefile.am index 6d3ed056e..14c99c3cc 100644 --- a/xorg-server/hw/kdrive/fake/Makefile.am +++ b/xorg-server/hw/kdrive/fake/Makefile.am @@ -1,4 +1,4 @@ -INCLUDES = \ +AM_CPPFLAGS = \ @KDRIVE_INCS@ \ @KDRIVE_CFLAGS@ diff --git a/xorg-server/hw/kdrive/fbdev/Makefile.am b/xorg-server/hw/kdrive/fbdev/Makefile.am index ec9df95e0..7e8ba024c 100644 --- a/xorg-server/hw/kdrive/fbdev/Makefile.am +++ b/xorg-server/hw/kdrive/fbdev/Makefile.am @@ -1,4 +1,4 @@ -INCLUDES = \ +AM_CPPFLAGS = \ @KDRIVE_INCS@ \ @KDRIVE_CFLAGS@ diff --git a/xorg-server/hw/kdrive/linux/Makefile.am b/xorg-server/hw/kdrive/linux/Makefile.am index 93e5d2f9f..1362cd9d8 100644 --- a/xorg-server/hw/kdrive/linux/Makefile.am +++ b/xorg-server/hw/kdrive/linux/Makefile.am @@ -1,4 +1,4 @@ -INCLUDES = \ +AM_CPPFLAGS = \ @KDRIVE_INCS@ \ @KDRIVE_CFLAGS@ diff --git a/xorg-server/hw/kdrive/src/Makefile.am b/xorg-server/hw/kdrive/src/Makefile.am index 51375b950..5799ddbdb 100644 --- a/xorg-server/hw/kdrive/src/Makefile.am +++ b/xorg-server/hw/kdrive/src/Makefile.am @@ -1,4 +1,4 @@ -INCLUDES = \ +AM_CPPFLAGS = \ @KDRIVE_INCS@ \ @KDRIVE_CFLAGS@ diff --git a/xorg-server/hw/xfree86/Makefile.am b/xorg-server/hw/xfree86/Makefile.am index c3899b577..d568e0d7e 100644 --- a/xorg-server/hw/xfree86/Makefile.am +++ b/xorg-server/hw/xfree86/Makefile.am @@ -39,7 +39,7 @@ bin_PROGRAMS = Xorg nodist_Xorg_SOURCES = sdksyms.c AM_CFLAGS = $(DIX_CFLAGS) @XORG_CFLAGS@ -INCLUDES = $(XORG_INCS) -I$(srcdir)/parser -I$(top_srcdir)/miext/cw \ +AM_CPPFLAGS = $(XORG_INCS) -I$(srcdir)/parser -I$(top_srcdir)/miext/cw \ -I$(srcdir)/ddc -I$(srcdir)/i2c -I$(srcdir)/modes -I$(srcdir)/ramdac \ -I$(srcdir)/dri -I$(srcdir)/dri2 @@ -115,7 +115,7 @@ CLEANFILES = sdksyms.c sdksyms.dep EXTRA_DIST += sdksyms.sh sdksyms.dep sdksyms.c: sdksyms.sh - $(AM_V_GEN)CPP='$(CPP)' AWK='$(AWK)' $(SHELL) $(srcdir)/sdksyms.sh $(top_srcdir) $(CFLAGS) $(AM_CFLAGS) $(INCLUDES) + $(AM_V_GEN)CPP='$(CPP)' AWK='$(AWK)' $(SHELL) $(srcdir)/sdksyms.sh $(top_srcdir) $(CFLAGS) $(AM_CFLAGS) $(AM_CPPFLAGS) SDKSYMS_DEP = sdksyms.dep include $(SDKSYMS_DEP) diff --git a/xorg-server/hw/xfree86/common/Makefile.am b/xorg-server/hw/xfree86/common/Makefile.am index 532d87bbe..7a2b4bc1e 100644 --- a/xorg-server/hw/xfree86/common/Makefile.am +++ b/xorg-server/hw/xfree86/common/Makefile.am @@ -53,7 +53,7 @@ libcommon_la_SOURCES = xf86Configure.c xf86Bus.c xf86Config.c \ nodist_libcommon_la_SOURCES = xf86DefModeSet.c xf86Build.h libcommon_la_LIBADD = $(top_builddir)/config/libconfig.la -INCLUDES = $(XORG_INCS) -I$(srcdir)/../ddc -I$(srcdir)/../i2c \ +AM_CPPFLAGS = $(XORG_INCS) -I$(srcdir)/../ddc -I$(srcdir)/../i2c \ -I$(srcdir)/../loader -I$(srcdir)/../parser \ -I$(srcdir)/../vbe -I$(srcdir)/../int10 \ -I$(srcdir)/../vgahw -I$(srcdir)/../dixmods/extmod \ diff --git a/xorg-server/hw/xfree86/ddc/Makefile.am b/xorg-server/hw/xfree86/ddc/Makefile.am index 93ea4a2a5..a7b84adcd 100644 --- a/xorg-server/hw/xfree86/ddc/Makefile.am +++ b/xorg-server/hw/xfree86/ddc/Makefile.am @@ -4,7 +4,7 @@ noinst_LTLIBRARIES = libddc.la libddc_la_SOURCES = ddc.c interpret_edid.c print_edid.c ddcProperty.c -INCLUDES = $(XORG_INCS) -I$(srcdir)/../i2c +AM_CPPFLAGS = $(XORG_INCS) -I$(srcdir)/../i2c AM_CFLAGS = $(DIX_CFLAGS) $(XORG_CFLAGS) diff --git a/xorg-server/hw/xfree86/dixmods/Makefile.am b/xorg-server/hw/xfree86/dixmods/Makefile.am index f161db60a..9933bc88d 100644 --- a/xorg-server/hw/xfree86/dixmods/Makefile.am +++ b/xorg-server/hw/xfree86/dixmods/Makefile.am @@ -12,7 +12,7 @@ extsmoduledir = $(moduledir)/extensions extsmodule_LTLIBRARIES = $(GLXMODS) AM_CFLAGS = @XORG_CFLAGS@ @DIX_CFLAGS@ -INCLUDES = @XORG_INCS@ \ +AM_CPPFLAGS = @XORG_INCS@ \ -I$(top_srcdir)/hw/xfree86/loader \ -I$(top_srcdir)/miext/shadow \ -I$(top_srcdir)/glx diff --git a/xorg-server/hw/xfree86/exa/Makefile.am b/xorg-server/hw/xfree86/exa/Makefile.am index 433908411..1e42cdacd 100644 --- a/xorg-server/hw/xfree86/exa/Makefile.am +++ b/xorg-server/hw/xfree86/exa/Makefile.am @@ -4,7 +4,7 @@ module_LTLIBRARIES = libexa.la libexa_la_LDFLAGS = -module -avoid-version $(LD_NO_UNDEFINED_FLAG) -INCLUDES = \ +AM_CPPFLAGS = \ $(XORG_INCS) \ -I$(srcdir)/../../../exa \ -I$(srcdir)/../../../miext/cw diff --git a/xorg-server/hw/xfree86/fbdevhw/Makefile.am b/xorg-server/hw/xfree86/fbdevhw/Makefile.am index ee5577a86..37cd88c0e 100644 --- a/xorg-server/hw/xfree86/fbdevhw/Makefile.am +++ b/xorg-server/hw/xfree86/fbdevhw/Makefile.am @@ -10,7 +10,7 @@ else libfbdevhw_la_SOURCES = fbdevhwstub.c endif -INCLUDES = $(XORG_INCS) -I$(srcdir)/../i2c -I$(srcdir)/../modes -I$(srcdir)/../ddc -I$(srcdir)/../parser +AM_CPPFLAGS = $(XORG_INCS) -I$(srcdir)/../i2c -I$(srcdir)/../modes -I$(srcdir)/../ddc -I$(srcdir)/../parser AM_CFLAGS = $(DIX_CFLAGS) $(XORG_CFLAGS) diff --git a/xorg-server/hw/xfree86/i2c/Makefile.am b/xorg-server/hw/xfree86/i2c/Makefile.am index cb18db188..c31159196 100644 --- a/xorg-server/hw/xfree86/i2c/Makefile.am +++ b/xorg-server/hw/xfree86/i2c/Makefile.am @@ -12,7 +12,7 @@ multimedia_LTLIBRARIES = \ libi2c_la_SOURCES = xf86i2c.c -INCLUDES = $(XORG_INCS) +AM_CPPFLAGS = $(XORG_INCS) AM_CFLAGS = $(DIX_CFLAGS) $(XORG_CFLAGS) diff --git a/xorg-server/hw/xfree86/int10/Makefile.am b/xorg-server/hw/xfree86/int10/Makefile.am index f5ece69ef..66cb14d46 100644 --- a/xorg-server/hw/xfree86/int10/Makefile.am +++ b/xorg-server/hw/xfree86/int10/Makefile.am @@ -17,9 +17,10 @@ if I386_VIDEO I386_VIDEO_CFLAGS = -D_PC endif +AM_CPPFLAGS = $(XORG_INCS) + if INT10_VM86 AM_CFLAGS = $(I386_VIDEO_CFLAGS) -D_VM86_LINUX $(DIX_CFLAGS) $(XORG_CFLAGS) $(EXTRA_CFLAGS) -INCLUDES = $(XORG_INCS) libint10_la_SOURCES = \ $(COMMON_SOURCES) \ $(srcdir)/../os-support/linux/int10/vm86/linux_vm86.c \ @@ -29,7 +30,7 @@ endif if INT10_X86EMU AM_CFLAGS = $(I386_VIDEO_CFLAGS) -D_X86EMU -DNO_SYS_HEADERS \ $(XORG_CFLAGS) $(EXTRA_CFLAGS) $(DIX_CFLAGS) -INCLUDES = $(XORG_INCS) -I$(srcdir)/../x86emu +AM_CPPFLAGS += -I$(srcdir)/../x86emu libint10_la_SOURCES = \ $(COMMON_SOURCES) \ xf86x86emu.c \ @@ -39,7 +40,6 @@ endif if INT10_STUB AM_CFLAGS = $(I386_VIDEO_CFLAGS) -D_VM86_LINUX $(DIX_CFLAGS) $(XORG_CFLAGS) $(EXTRA_CFLAGS) -INCLUDES = $(XORG_INCS) libint10_la_SOURCES = stub.c xf86int10module.c endif diff --git a/xorg-server/hw/xfree86/loader/Makefile.am b/xorg-server/hw/xfree86/loader/Makefile.am index bd47a635b..a658ca50f 100644 --- a/xorg-server/hw/xfree86/loader/Makefile.am +++ b/xorg-server/hw/xfree86/loader/Makefile.am @@ -1,6 +1,6 @@ noinst_LTLIBRARIES = libloader.la -INCLUDES = $(XORG_INCS) -I$(srcdir)/../parser -I$(top_srcdir)/miext/cw \ +AM_CPPFLAGS = $(XORG_INCS) -I$(srcdir)/../parser -I$(top_srcdir)/miext/cw \ -I$(srcdir)/../ddc -I$(srcdir)/../i2c -I$(srcdir)/../modes \ -I$(srcdir)/../ramdac -I$(srcdir)/../dri -I$(srcdir)/../dri2 diff --git a/xorg-server/hw/xfree86/modes/Makefile.am b/xorg-server/hw/xfree86/modes/Makefile.am index 7e33ebb17..220643f7b 100644 --- a/xorg-server/hw/xfree86/modes/Makefile.am +++ b/xorg-server/hw/xfree86/modes/Makefile.am @@ -19,7 +19,7 @@ libxf86modes_la_SOURCES = \ xf86Rotate.c \ $(DGA_SRCS) -INCLUDES = $(XORG_INCS) -I$(srcdir)/../ddc -I$(srcdir)/../i2c \ +AM_CPPFLAGS = $(XORG_INCS) -I$(srcdir)/../ddc -I$(srcdir)/../i2c \ -I$(srcdir)/../loader -I$(srcdir)/../rac -I$(srcdir)/../parser \ -I$(srcdir)/../vbe -I$(srcdir)/../int10 \ -I$(srcdir)/../vgahw -I$(srcdir)/../ramdac \ diff --git a/xorg-server/hw/xfree86/os-support/bsd/Makefile.am b/xorg-server/hw/xfree86/os-support/bsd/Makefile.am index b6ecdf1d1..7133c0f21 100644 --- a/xorg-server/hw/xfree86/os-support/bsd/Makefile.am +++ b/xorg-server/hw/xfree86/os-support/bsd/Makefile.am @@ -54,7 +54,7 @@ endif # FIXME: NetBSD Aperture defines (configure.ac) AM_CFLAGS = -DUSESTDRES $(XORG_CFLAGS) $(DIX_CFLAGS) -INCLUDES = $(XORG_INCS) +AM_CPPFLAGS = $(XORG_INCS) libbsd_la_SOURCES = \ $(srcdir)/../shared/posix_tty.c \ diff --git a/xorg-server/hw/xfree86/os-support/bus/Makefile.am b/xorg-server/hw/xfree86/os-support/bus/Makefile.am index e09d4d21f..eebb3aed6 100644 --- a/xorg-server/hw/xfree86/os-support/bus/Makefile.am +++ b/xorg-server/hw/xfree86/os-support/bus/Makefile.am @@ -17,7 +17,7 @@ endif libbus_la_SOURCES = $(PCI_SOURCES) $(PLATFORM_SOURCES) nobus.c -INCLUDES = $(XORG_INCS) +AM_CPPFLAGS = $(XORG_INCS) AM_CFLAGS = $(XORG_CFLAGS) $(DIX_CFLAGS) diff --git a/xorg-server/hw/xfree86/os-support/hurd/Makefile.am b/xorg-server/hw/xfree86/os-support/hurd/Makefile.am index 3e8224753..f228c1ce4 100644 --- a/xorg-server/hw/xfree86/os-support/hurd/Makefile.am +++ b/xorg-server/hw/xfree86/os-support/hurd/Makefile.am @@ -12,4 +12,4 @@ libhurd_la_SOURCES = hurd_bell.c hurd_init.c hurd_mmap.c \ AM_CFLAGS = -DUSESTDRES -DHAVE_SYSV_IPC $(XORG_CFLAGS) $(DIX_CFLAGS) -INCLUDES = $(XORG_INCS) +AM_CPPFLAGS = $(XORG_INCS) diff --git a/xorg-server/hw/xfree86/os-support/linux/Makefile.am b/xorg-server/hw/xfree86/os-support/linux/Makefile.am index 61175b386..83e7e0027 100644 --- a/xorg-server/hw/xfree86/os-support/linux/Makefile.am +++ b/xorg-server/hw/xfree86/os-support/linux/Makefile.am @@ -34,7 +34,7 @@ liblinux_la_SOURCES = lnx_init.c lnx_video.c \ AM_CFLAGS = -DUSESTDRES -DHAVE_SYSV_IPC $(DIX_CFLAGS) $(XORG_CFLAGS) $(PLATFORM_DEFINES) -INCLUDES = $(XORG_INCS) $(PLATFORM_INCLUDES) $(LIBDRM_CFLAGS) +AM_CPPFLAGS = $(XORG_INCS) $(PLATFORM_INCLUDES) $(LIBDRM_CFLAGS) EXTRA_DIST = \ $(srcdir)/../shared/xf86Axp.h diff --git a/xorg-server/hw/xfree86/os-support/misc/Makefile.am b/xorg-server/hw/xfree86/os-support/misc/Makefile.am index 4bd3fc3e1..0265aecd4 100644 --- a/xorg-server/hw/xfree86/os-support/misc/Makefile.am +++ b/xorg-server/hw/xfree86/os-support/misc/Makefile.am @@ -5,7 +5,7 @@ libmisc_la_SOURCES = SlowBcopy.c #AM_LDFLAGS = -r -INCLUDES = $(XORG_INCS) +AM_CPPFLAGS = $(XORG_INCS) AM_CFLAGS = $(XORG_CFLAGS) $(DIX_CFLAGS) diff --git a/xorg-server/hw/xfree86/os-support/solaris/Makefile.am b/xorg-server/hw/xfree86/os-support/solaris/Makefile.am index 5163f4423..6cda4b361 100644 --- a/xorg-server/hw/xfree86/os-support/solaris/Makefile.am +++ b/xorg-server/hw/xfree86/os-support/solaris/Makefile.am @@ -31,7 +31,7 @@ nodist_sdk_HEADERS = solaris-@SOLARIS_INOUT_ARCH@.il AM_CFLAGS = -DUSESTDRES -DHAVE_SYSV_IPC $(XORG_CFLAGS) $(DIX_CFLAGS) -INCLUDES = $(XORG_INCS) +AM_CPPFLAGS = $(XORG_INCS) EXTRA_DIST = solaris-amd64.S solaris-ia32.S solaris-sparcv8plus.S \ apSolaris.shar sun_inout.s diff --git a/xorg-server/hw/xfree86/os-support/stub/Makefile.am b/xorg-server/hw/xfree86/os-support/stub/Makefile.am index a1156ef1b..a39e17d55 100644 --- a/xorg-server/hw/xfree86/os-support/stub/Makefile.am +++ b/xorg-server/hw/xfree86/os-support/stub/Makefile.am @@ -2,7 +2,7 @@ noinst_LTLIBRARIES = libstub.la AM_CFLAGS = $(XORG_CFLAGS) $(DIX_CFLAGS) -INCLUDES = $(XORG_INCS) +AM_CPPFLAGS = $(XORG_INCS) libstub_la_SOURCES = \ $(srcdir)/../shared/VTsw_noop.c \ diff --git a/xorg-server/hw/xfree86/parser/Makefile.am b/xorg-server/hw/xfree86/parser/Makefile.am index 002cfbf5c..3bf62e8af 100644 --- a/xorg-server/hw/xfree86/parser/Makefile.am +++ b/xorg-server/hw/xfree86/parser/Makefile.am @@ -51,4 +51,4 @@ sdk_HEADERS = \ xf86Parser.h \ xf86Optrec.h -INCLUDES = -I$(srcdir)/../common +AM_CPPFLAGS = -I$(srcdir)/../common diff --git a/xorg-server/hw/xfree86/parser/write.c b/xorg-server/hw/xfree86/parser/write.c index 9c706a062..26739b933 100644 --- a/xorg-server/hw/xfree86/parser/write.c +++ b/xorg-server/hw/xfree86/parser/write.c @@ -55,6 +55,7 @@ #include <xorg-config.h> #endif +#include "os.h" #include "xf86Parser.h" #include "xf86tokens.h" #include "Configint.h" @@ -65,7 +66,7 @@ #include <signal.h> #include <errno.h> -#if defined(SVR4) || defined(__linux__) || defined(CSRG_BASED) +#if defined(HAVE_SETEUID) && defined(_POSIX_SAVED_IDS) && _POSIX_SAVED_IDS > 0 #define HAS_SAVED_IDS_AND_SETEUID #endif #if defined(WIN32) diff --git a/xorg-server/hw/xfree86/ramdac/Makefile.am b/xorg-server/hw/xfree86/ramdac/Makefile.am index 346af4ccc..a3d77628c 100644 --- a/xorg-server/hw/xfree86/ramdac/Makefile.am +++ b/xorg-server/hw/xfree86/ramdac/Makefile.am @@ -9,4 +9,4 @@ EXTRA_DIST = BTPriv.h IBMPriv.h TIPriv.h xf86CursorPriv.h xf86RamDacPriv.h \ CURSOR.NOTES AM_CFLAGS = $(DIX_CFLAGS) $(XORG_CFLAGS) -INCLUDES = $(XORG_INCS) +AM_CPPFLAGS = $(XORG_INCS) diff --git a/xorg-server/hw/xfree86/shadowfb/Makefile.am b/xorg-server/hw/xfree86/shadowfb/Makefile.am index 5756fca3b..22f7ada2a 100644 --- a/xorg-server/hw/xfree86/shadowfb/Makefile.am +++ b/xorg-server/hw/xfree86/shadowfb/Makefile.am @@ -5,6 +5,6 @@ libshadowfb_la_LIBADD = $(PIXMAN_LIBS) sdk_HEADERS = shadowfb.h -INCLUDES = $(XORG_INCS) +AM_CPPFLAGS = $(XORG_INCS) AM_CFLAGS = $(DIX_CFLAGS) $(XORG_CFLAGS) diff --git a/xorg-server/hw/xfree86/utils/cvt/Makefile.am b/xorg-server/hw/xfree86/utils/cvt/Makefile.am index 754606e8e..26abeb40b 100644 --- a/xorg-server/hw/xfree86/utils/cvt/Makefile.am +++ b/xorg-server/hw/xfree86/utils/cvt/Makefile.am @@ -22,7 +22,7 @@ bin_PROGRAMS = cvt -INCLUDES = $(XORG_INCS) \ +AM_CPPFLAGS = $(XORG_INCS) \ -I$(top_srcdir)/hw/xfree86/ddc \ -I$(top_srcdir)/hw/xfree86/modes \ -I$(top_srcdir)/hw/xfree86/parser diff --git a/xorg-server/hw/xfree86/vbe/Makefile.am b/xorg-server/hw/xfree86/vbe/Makefile.am index 1720eb93b..041b47a9f 100644 --- a/xorg-server/hw/xfree86/vbe/Makefile.am +++ b/xorg-server/hw/xfree86/vbe/Makefile.am @@ -9,6 +9,6 @@ sdk_HEADERS = vbe.h vbeModes.h AM_CFLAGS = $(DIX_CFLAGS) $(XORG_CFLAGS) -INCLUDES = $(XORG_INCS) -I$(srcdir)/../ddc -I$(srcdir)/../i2c \ +AM_CPPFLAGS = $(XORG_INCS) -I$(srcdir)/../ddc -I$(srcdir)/../i2c \ -I$(srcdir)/../modes -I$(srcdir)/../parser \ -I$(srcdir)/../int10 diff --git a/xorg-server/hw/xfree86/vgahw/Makefile.am b/xorg-server/hw/xfree86/vgahw/Makefile.am index f48e46a11..f0b65740c 100644 --- a/xorg-server/hw/xfree86/vgahw/Makefile.am +++ b/xorg-server/hw/xfree86/vgahw/Makefile.am @@ -1,7 +1,7 @@ module_LTLIBRARIES = libvgahw.la libvgahw_la_LDFLAGS = -avoid-version libvgahw_la_SOURCES = vgaHW.c vgaHWmodule.c -INCLUDES = $(XORG_INCS) -I$(srcdir)/../ddc -I$(srcdir)/../i2c +AM_CPPFLAGS = $(XORG_INCS) -I$(srcdir)/../ddc -I$(srcdir)/../i2c AM_CFLAGS = $(DIX_CFLAGS) $(XORG_CFLAGS) sdk_HEADERS = vgaHW.h diff --git a/xorg-server/hw/xfree86/x86emu/Makefile.am b/xorg-server/hw/xfree86/x86emu/Makefile.am index df9697767..2a55d6353 100644 --- a/xorg-server/hw/xfree86/x86emu/Makefile.am +++ b/xorg-server/hw/xfree86/x86emu/Makefile.am @@ -11,7 +11,7 @@ libx86emu_la_SOURCES = debug.c \ sys.c \ x86emu.h -INCLUDES = +AM_CPPFLAGS = AM_CFLAGS = $(DIX_CFLAGS) $(XORG_CFLAGS) diff --git a/xorg-server/hw/xwin/Makefile.am b/xorg-server/hw/xwin/Makefile.am index 3f27b4dd2..89bff5bca 100644 --- a/xorg-server/hw/xwin/Makefile.am +++ b/xorg-server/hw/xwin/Makefile.am @@ -151,7 +151,7 @@ SRCS = InitInput.c \ XWin_SOURCES = $(SRCS) -INCLUDES = -I$(top_srcdir)/miext/rootless +AM_CPPFLAGS = -I$(top_srcdir)/miext/rootless XWIN_SYS_LIBS += -ldxguid diff --git a/xorg-server/hw/xwin/glx/Makefile.am b/xorg-server/hw/xwin/glx/Makefile.am index f969af277..067ee5b3c 100644 --- a/xorg-server/hw/xwin/glx/Makefile.am +++ b/xorg-server/hw/xwin/glx/Makefile.am @@ -23,7 +23,7 @@ endif DEFS = $(DEFS_MULTIWINDOW) $(DEFS_MULTIWINDOWEXTWM) $(DEFS_GLX_WINDOWS) -INCLUDES = -I$(top_srcdir)/miext/rootless +AM_CPPFLAGS = -I$(top_srcdir)/miext/rootless AM_CFLAGS = -DHAVE_XWIN_CONFIG_H $(DIX_CFLAGS) \ $(XWINMODULES_CFLAGS) \ diff --git a/xorg-server/include/xorg-config.h.in b/xorg-server/include/xorg-config.h.in index a71b25d72..0df31aeb2 100644 --- a/xorg-server/include/xorg-config.h.in +++ b/xorg-server/include/xorg-config.h.in @@ -139,4 +139,7 @@ /* Have X server platform bus support */ #undef XSERVER_PLATFORM_BUS +/* Define to 1 if you have the `seteuid' function. */ +#undef HAVE_SETEUID + #endif /* _XORG_CONFIG_H_ */ diff --git a/xorg-server/mi/miinitext.c b/xorg-server/mi/miinitext.c index 38d19bc2f..b1ceaa4dc 100644 --- a/xorg-server/mi/miinitext.c +++ b/xorg-server/mi/miinitext.c @@ -157,7 +157,7 @@ static ExtensionToggle ExtensionToggleList[] = { #ifdef XF86BIGFONT {"XFree86-Bigfont", &noXFree86BigfontExtension}, #endif -#ifdef XorgLoader +#ifdef XORGSERVER #ifdef XFreeXDGA {"XFree86-DGA", &noXFree86DGAExtension}, #endif diff --git a/xorg-server/miext/damage/Makefile.am b/xorg-server/miext/damage/Makefile.am index 767a65aee..a7f432a61 100644 --- a/xorg-server/miext/damage/Makefile.am +++ b/xorg-server/miext/damage/Makefile.am @@ -2,7 +2,7 @@ noinst_LTLIBRARIES = libdamage.la AM_CFLAGS = $(DIX_CFLAGS) -INCLUDES = -I$(srcdir)/../cw +AM_CPPFLAGS = -I$(srcdir)/../cw if XORG sdk_HEADERS = damage.h damagestr.h diff --git a/xorg-server/miext/sync/Makefile.am b/xorg-server/miext/sync/Makefile.am index 36b2816d7..9aa1ba5d5 100644 --- a/xorg-server/miext/sync/Makefile.am +++ b/xorg-server/miext/sync/Makefile.am @@ -2,7 +2,7 @@ noinst_LTLIBRARIES = libsync.la AM_CFLAGS = $(DIX_CFLAGS) -INCLUDES = +AM_CPPFLAGS = if XORG sdk_HEADERS = misync.h misyncstr.h diff --git a/xorg-server/test/Makefile.am b/xorg-server/test/Makefile.am index 34f53fc1e..eff0c9d81 100644 --- a/xorg-server/test/Makefile.am +++ b/xorg-server/test/Makefile.am @@ -13,9 +13,9 @@ TESTS=$(noinst_PROGRAMS) TESTS_ENVIRONMENT = $(XORG_MALLOC_DEBUG_ENV) AM_CFLAGS = $(DIX_CFLAGS) @XORG_CFLAGS@ -INCLUDES = $(XORG_INCS) -I$(top_srcdir)/miext/cw +AM_CPPFLAGS = $(XORG_INCS) -I$(top_srcdir)/miext/cw if XORG -INCLUDES += -I$(top_srcdir)/hw/xfree86/parser \ +AM_CPPFLAGS += -I$(top_srcdir)/hw/xfree86/parser \ -I$(top_srcdir)/hw/xfree86/ddc \ -I$(top_srcdir)/hw/xfree86/i2c -I$(top_srcdir)/hw/xfree86/modes \ -I$(top_srcdir)/hw/xfree86/ramdac -I$(top_srcdir)/hw/xfree86/dri \ diff --git a/xorg-server/test/hashtabletest.c b/xorg-server/test/hashtabletest.c index 64c7091fc..6af14a8e6 100644 --- a/xorg-server/test/hashtabletest.c +++ b/xorg-server/test/hashtabletest.c @@ -1,3 +1,7 @@ +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + #include <misc.h> #include <stdlib.h> #include <stdio.h> diff --git a/xorg-server/test/xi2/Makefile.am b/xorg-server/test/xi2/Makefile.am index 9de7abf5d..bfddfef13 100644 --- a/xorg-server/test/xi2/Makefile.am +++ b/xorg-server/test/xi2/Makefile.am @@ -17,7 +17,7 @@ TESTS=$(noinst_PROGRAMS) TESTS_ENVIRONMENT = $(XORG_MALLOC_DEBUG_ENV) AM_CFLAGS = $(DIX_CFLAGS) @XORG_CFLAGS@ -INCLUDES = @XORG_INCS@ +AM_CPPFLAGS = @XORG_INCS@ TEST_LDADD=../libxservertest.la $(XORG_SYS_LIBS) $(XSERVER_SYS_LIBS) $(GLX_SYS_LIBS) COMMON_SOURCES=protocol-common.h protocol-common.c diff --git a/xorg-server/xkeyboard-config/compat/level5 b/xorg-server/xkeyboard-config/compat/level5 index 8d28051c1..8e0cc9c38 100644 --- a/xorg-server/xkeyboard-config/compat/level5 +++ b/xorg-server/xkeyboard-config/compat/level5 @@ -20,6 +20,7 @@ default partial xkb_compatibility "default" { }; interpret ISO_Level5_Latch+Any { + useModMapMods= level1; virtualModifier= LevelFive; action= LatchMods(modifiers=LevelFive); }; @@ -29,6 +30,7 @@ default partial xkb_compatibility "default" { }; interpret ISO_Level5_Lock+Any { + useModMapMods= level1; virtualModifier= LevelFive; action= LockMods(modifiers=LevelFive); }; diff --git a/xorg-server/xkeyboard-config/rules/base.extras.xml.in b/xorg-server/xkeyboard-config/rules/base.extras.xml.in index 4647bec16..4b3c6234e 100644 --- a/xorg-server/xkeyboard-config/rules/base.extras.xml.in +++ b/xorg-server/xkeyboard-config/rules/base.extras.xml.in @@ -301,7 +301,7 @@ </variant> <variant> <configItem> - <name>type6</name> + <name>sun_type6</name> <_description>Polish (Sun Type 6/7)</_description> </configItem> </variant> @@ -333,7 +333,7 @@ </variant> <variant> <configItem> - <name>type6</name> + <name>sun_type6</name> <_description>Romanian (Sun Type 6/7)</_description> </configItem> </variant> @@ -381,7 +381,7 @@ </variant> <variant> <configItem> - <name>type6</name> + <name>sun_type6</name> <_description>Russian (Sun Type 6/7)</_description> </configItem> </variant> diff --git a/xorg-server/xkeyboard-config/rules/base.xml.in b/xorg-server/xkeyboard-config/rules/base.xml.in index 450154bb5..51c4ca59e 100644 --- a/xorg-server/xkeyboard-config/rules/base.xml.in +++ b/xorg-server/xkeyboard-config/rules/base.xml.in @@ -1414,7 +1414,7 @@ <variant> <configItem> <name>olpc2</name> - <_description>English (layout toggle on multiply/divide key)</_description> + <_description>English (the divide/multiply keys toggle the layout)</_description> </configItem> </variant> <variant> @@ -1724,7 +1724,7 @@ <variant> <configItem> <name>oss_latin9</name> - <_description>Belgian (alternative, latin-9 only)</_description> + <_description>Belgian (alternative, Latin-9 only)</_description> </configItem> </variant> <variant> @@ -1882,6 +1882,17 @@ </variant> <variant> <configItem> + <name>kan-kagapa</name> + <!-- Keyboard indicator for Kannada layouts --> + <_shortDescription>kn</_shortDescription> + <_description>Kannada (KaGaPa phonetic)</_description> + <languageList> + <iso639Id>kan</iso639Id> + </languageList> + </configItem> + </variant> + <variant> + <configItem> <name>mal</name> <!-- Keyboard indicator for Malayalam layouts --> <_shortDescription>ml</_shortDescription> @@ -1990,6 +2001,17 @@ </variant> <variant> <configItem> + <name>tel-kagapa</name> + <!-- Keyboard indicator for Telugu layouts --> + <_shortDescription>te</_shortDescription> + <_description>Telugu (KaGaPa phonetic)</_description> + <languageList> + <iso639Id>tel</iso639Id> + </languageList> + </configItem> + </variant> + <variant> + <configItem> <name>urd-phonetic</name> <!-- Keyboard indicator for Urdu layouts --> <_shortDescription>ur</_shortDescription> @@ -2045,6 +2067,39 @@ </variant> <variant> <configItem> + <name>hin-kagapa</name> + <!-- Keyboard indicator for Hindi layouts --> + <_shortDescription>hi</_shortDescription> + <_description>Hindi (KaGaPa phonetic)</_description> + <languageList> + <iso639Id>hin</iso639Id> + </languageList> + </configItem> + </variant> + <variant> + <configItem> + <name>san-kagapa</name> + <!-- Keyboard indicator for Sanskrit layouts --> + <_shortDescription>sa</_shortDescription> + <_description>Sanskrit (KaGaPa phonetic)</_description> + <languageList> + <iso639Id>san</iso639Id> + </languageList> + </configItem> + </variant> + <variant> + <configItem> + <name>mar-kagapa</name> + <!-- Keyboard indicator for Marathi layouts --> + <_shortDescription>mr</_shortDescription> + <_description>Marathi (KaGaPa phonetic)</_description> + <languageList> + <iso639Id>mar</iso639Id> + </languageList> + </configItem> + </variant> + <variant> + <configItem> <name>eng</name> <!-- Keyboard indicator for English layouts --> <_shortDescription>en</_shortDescription> @@ -2125,7 +2180,7 @@ <variant> <configItem> <name>nativo-us</name> - <_description>Portuguese (Brazil, nativo for USA keyboards)</_description> + <_description>Portuguese (Brazil, nativo for US keyboards)</_description> </configItem> </variant> <variant> @@ -2880,7 +2935,7 @@ <variant> <configItem> <name>oss_latin9</name> - <_description>French (alternative, latin-9 only)</_description> + <_description>French (alternative, Latin-9 only)</_description> </configItem> </variant> <variant> @@ -2922,7 +2977,7 @@ <variant> <configItem> <name>bepo_latin9</name> - <_description>French (Bepo, ergonomic, Dvorak way, latin-9 only)</_description> + <_description>French (Bepo, ergonomic, Dvorak way, Latin-9 only)</_description> </configItem> </variant> <variant> @@ -4087,7 +4142,7 @@ <variant> <configItem> <name>nativo-us</name> - <_description>Portuguese (Nativo for USA keyboards)</_description> + <_description>Portuguese (Nativo for US keyboards)</_description> </configItem> </variant> <variant> @@ -5869,7 +5924,7 @@ <option> <configItem> <name>lv3:ralt_switch_multikey</name> - <_description>Right Alt, Shift+Right Alt key is Multi_Key</_description> + <_description>Right Alt, Shift+Right Alt key is Compose</_description> </configItem> </option> <option> @@ -6086,7 +6141,7 @@ <option> <configItem> <name>kpdl:dotoss_latin9</name> - <_description>Four-level key with dot, latin-9 restriction</_description> + <_description>Four-level key with dot, Latin-9 only</_description> </configItem> </option> <option> @@ -6112,7 +6167,7 @@ <option> <configItem> <name>kpdl:semi</name> - <_description>Semi-colon on third level</_description> + <_description>Semicolon on third level</_description> </configItem> </option> </group> @@ -6193,7 +6248,7 @@ <option> <configItem> <name>caps:shiftlock</name> - <_description>Caps Lock toggles Shift so all keys are affected</_description> + <_description>Caps Lock toggles ShiftLock (affects all keys)</_description> </configItem> </option> <option> @@ -6447,25 +6502,25 @@ <option> <configItem> <name>shift:both_capslock</name> - <_description>Both Shift-Keys together toggle Caps Lock</_description> + <_description>Both Shift keys together toggle Caps Lock</_description> </configItem> </option> <option> <configItem> <name>shift:both_capslock_cancel</name> - <_description>Both Shift-Keys together activate Caps Lock, one Shift-Key deactivates</_description> + <_description>Both Shift keys together activate Caps Lock, one Shift key deactivates</_description> </configItem> </option> <option> <configItem> <name>shift:both_shiftlock</name> - <_description>Both Shift-Keys together toggle ShiftLock</_description> + <_description>Both Shift keys together toggle ShiftLock</_description> </configItem> </option> <option> <configItem> <name>keypad:pointerkeys</name> - <_description>Toggle PointerKeys with Shift + NumLock.</_description> + <_description>Shift + NumLock toggles PointerKeys</_description> </configItem> </option> <option> @@ -6710,18 +6765,18 @@ <group allowMultipleSelection="false"> <configItem> <name>esperanto</name> - <_description>Adding Esperanto circumflexes (supersigno)</_description> + <_description>Adding Esperanto supersigned letters</_description> </configItem> <option> <configItem> <name>esperanto:qwerty</name> - <_description>To the corresponding key in a Qwerty keyboard.</_description> + <_description>To the corresponding key in a Qwerty layout</_description> </configItem> </option> <option> <configItem> <name>esperanto:dvorak</name> - <_description>To the corresponding key in a Dvorak keyboard.</_description> + <_description>To the corresponding key in a Dvorak layout</_description> </configItem> </option> </group> diff --git a/xorg-server/xkeyboard-config/symbols/be b/xorg-server/xkeyboard-config/symbols/be index cf8e06871..286e9289e 100644 --- a/xorg-server/xkeyboard-config/symbols/be +++ b/xorg-server/xkeyboard-config/symbols/be @@ -110,7 +110,7 @@ xkb_symbols "oss_latin9" { include "be(oss_frbe)" include "keypad(oss_latin9)" - name[Group1]="Belgian (alternative, latin-9 only)"; + name[Group1]="Belgian (alternative, Latin-9 only)"; // First row key <TLDE> { [ twosuperior, threesuperior, onesuperior, less ] }; // ² ³ ¹ < diff --git a/xorg-server/xkeyboard-config/symbols/br b/xorg-server/xkeyboard-config/symbols/br index dee718860..b75ffc98c 100644 --- a/xorg-server/xkeyboard-config/symbols/br +++ b/xorg-server/xkeyboard-config/symbols/br @@ -283,7 +283,7 @@ partial alphanumeric_keys xkb_symbols "nativo-us" { include "br(nativo)" - name[Group1]="Portuguese (Brazil, nativo for USA keyboards)"; + name[Group1]="Portuguese (Brazil, nativo for US keyboards)"; // Lower row key <AB01> { [ y, Y, ccedilla, Ccedilla ] }; diff --git a/xorg-server/xkeyboard-config/symbols/de b/xorg-server/xkeyboard-config/symbols/de index 20689af30..adc60ed36 100644 --- a/xorg-server/xkeyboard-config/symbols/de +++ b/xorg-server/xkeyboard-config/symbols/de @@ -107,8 +107,6 @@ xkb_symbols "deadacute" { partial alphanumeric_keys xkb_symbols "T3" { - include "latin(type4)" - name[Group1]="German (T3)"; key.type[Group1] = "EIGHT_LEVEL"; @@ -151,7 +149,7 @@ xkb_symbols "T3" { key <AC05> { [ g, G, seconds, NoSymbol, eng, ENG, dead_belowmacron, NoSymbol ] }; key <AC06> { [ h, H, U1E9E, NoSymbol, U0272, U019D, U0332, NoSymbol ] }; key <AC07> { [ j, J, dead_cedilla, NoSymbol, U0133, U0132, dead_belowring, NoSymbol ] }; - key <AC08> { [ k, K, dead_belowcomma, NoSymbol, kra, dead_belowcomma, U0335, NoSymbol ] }; + key <AC08> { [ k, K, dead_belowcomma, NoSymbol, kra, dead_belowcomma, dead_stroke, NoSymbol ] }; key <AC09> { [ l, L, dead_ogonek, NoSymbol, lstroke, Lstroke, U0338, NoSymbol ] }; key <AC10> { [ odiaeresis, Odiaeresis, dead_belowdot, NoSymbol, dead_acute, dead_doubleacute, degree, NoSymbol ] }; key <AC11> { [ adiaeresis, Adiaeresis, dead_stroke, NoSymbol, U019B, U1E9E, minutes, NoSymbol ] }; @@ -176,10 +174,12 @@ xkb_symbols "T3" { include "kpdl(comma)" - // We do not support the correct level selection mechanism yet, this is - //just for testing: - include "level5(rctrl_switch)" - include "level3(ralt_switch)" + include "level5(modifier_mapping)" + include "level3(modifier_mapping)" + key.type[Group1] = "THREE_LEVEL"; + key <LFSH> { [ Shift_L, Shift_L, ISO_Level5_Latch ] }; + key <RTSH> { [ Shift_R, Shift_R, ISO_Level5_Latch ] }; + key <RALT> { [ ISO_Level3_Latch, ISO_Level5_Latch, ISO_Level5_Latch ] }; }; partial alphanumeric_keys diff --git a/xorg-server/xkeyboard-config/symbols/es b/xorg-server/xkeyboard-config/symbols/es index 5adf1a2bb..ea4a28b1f 100644 --- a/xorg-server/xkeyboard-config/symbols/es +++ b/xorg-server/xkeyboard-config/symbols/es @@ -200,7 +200,7 @@ xkb_symbols "olpcm" { // See: http://wiki.laptop.org/go/OLPC_Spanish_Non-membrane_Keyboard include "us(basic)" - name[Group1]="Spain"; + name[Group1]="Spanish"; key <AE00> { [ questiondown, exclamdown, backslash ] }; key <AE01> { [ 1, exclam, bar ] }; diff --git a/xorg-server/xkeyboard-config/symbols/fr b/xorg-server/xkeyboard-config/symbols/fr index 0d1d13de8..418ff5200 100644 --- a/xorg-server/xkeyboard-config/symbols/fr +++ b/xorg-server/xkeyboard-config/symbols/fr @@ -200,7 +200,7 @@ xkb_symbols "oss_latin9" { include "fr(oss)" include "keypad(oss_latin9)" - name[Group1]="French (alternative, latin-9 only)"; + name[Group1]="French (alternative, Latin-9 only)"; // First row key <AE01> { [ ampersand, 1, dead_caron, dead_cedilla ] }; // & 1 ˇ ¸ @@ -547,7 +547,7 @@ xkb_symbols "bepo_latin9" { include "fr(bepo)" include "keypad(oss_latin9)" - name[Group1]="French (Bepo, ergonomic, Dvorak way, latin-9 only)"; + name[Group1]="French (Bepo, ergonomic, Dvorak way, Latin-9 only)"; key <TLDE> { [ dollar, numbersign, dollar, paragraph ] }; // $ # $ ¶ diff --git a/xorg-server/xkeyboard-config/symbols/in b/xorg-server/xkeyboard-config/symbols/in index b995fbb98..64c3ea1dd 100644 --- a/xorg-server/xkeyboard-config/symbols/in +++ b/xorg-server/xkeyboard-config/symbols/in @@ -1,9 +1,10 @@ // This layout includes all Indian layouts, including: +// - Devanagari (Hindi, Marathi, Sanskrit) // - Bengali -// - Gujarati -// - Kannada +// - Gujarati +// - Kannada // - Malayalam -// - Oriya +// - Oriya // - Tamil // - Telugu // - Urdu @@ -1753,3 +1754,266 @@ xkb_symbols "mal_enhanced" { }; + +// ---- BEGIN Hindi KaGaPa phonetic ---- +// Name: KaGaPa phonetic +// Brief: Devanagari layout (Hindi, Sanskrit, Nepali, Marathi, etc.) +// Diagram: (Original)[http://baraha.com/help/Keyboards/dev_brhkbd.htm] +// (This layout)[http://bdsatish.in/lang/dev-kagapa.png] +// +// Description: Based on KaGaPa layout (also called Baraha layout or Nudi layout) +// which is a modified layout of the specification by Dr. K. P. Rao. +// This is a phonetic layout with the following features: +// [1] All letters are mapped to phonetically-similar English keys +// as much as possible. +// [2] The independent vowel (svara) and its dependent vowel (maatra) +// use the same key (depending upon SHIFT, ALTGR or ALTGR + SHIFT). +// [3] Consonant conjuncts are produced by explicitly invoking the +// 'viraama' (key f). The 'short a' maatra is implicit in all +// consonants. +// [4] Zero width non-joiner and joiner are on keys 6 and 7 +// respectively. These are absolutely essential for alternative +// glyph renderings of consonant half-forms. +// [5] Rigvedic accent marks, visarga variants. +// +// Author: Satish BD <bdsatish@gmail.com> +// +partial alphanumeric_keys +xkb_symbols "hin-kagapa" { + name[Group1] = "Hindi (KaGaPa phonetic)"; + key.type="FOUR_LEVEL"; + + //Top Alphanumeric row + // Roman digits + key <TLDE> { [ apostrophe, asciitilde, U201C ] }; // U201C: left double quotation mark + key <AE01> { [ 1, exclam, U0967 ] }; + key <AE02> { [ 2, at, U0968, U20A8 ] }; // U20A8: generic rupee sign (Rs) + key <AE03> { [ 3, numbersign, U0969 ] }; + key <AE04> { [ 4, dollar, U096A, U20B9 ] }; // U20B9: new Indian Rupee sign + key <AE05> { [ 5, percent, U096B ] }; + key <AE06> { [ 6, asciicircum, U096C, U200C ] }; // ZWNJ + key <AE07> { [ 7, ampersand, U096D, U200D ] }; // ZWJ + key <AE08> { [ 8, asterisk, U096E, U0901 ] }; // U0901: Devanagari candrabindu + key <AE09> { [ 9, parenleft, U096F ] }; + key <AE10> { [ 0, parenright, U0966, U0970 ] }; // U0970: Devanagari abbreviation sign + key <AE11> { [ minus, underscore, U0952 ] }; // U0952: Devanagari stress sign anudatta + key <AE12> { [ equal, plus ] }; + key <BKSL> { [ U005C, U007C, U0964, U0965 ] }; // backslash, pipe, danda, double danda + + //Q Row + key <AD01> { [ U091F, U0920 ] }; // Q: retroflex Ta, Tha + key <AD02> { [ U0921, U0922, U095C, U095D ] }; // W: retroflex Da, Dha, Da-nukta, Dha-nukta + key <AD03> { [ U0946, U0947, U090E, U090F ] }; // E: matras, short E, long E + key <AD04> { [ U0930, U0943, U090B, U0931 ] }; // R: ra, vocalic R matra, vocalic R, ra-nukta + key <AD05> { [ U0924, U0925 ] }; // T: dental ta, tha + key <AD06> { [ U092F, U0948, U0910, U095F ] }; // Y: ya, ai matra, ai, ya-nukta + key <AD07> { [ U0941, U0942, U0909, U090A ] }; // U: matras, u, uu + key <AD08> { [ U093F, U0940, U0907, U0908 ] }; // I: matras, i, ii + key <AD09> { [ U094A, U094B, U0912, U0913 ] }; // O: matras, short o, long o + key <AD10> { [ U092A, U092B, U095E ] }; // P: pa, pha, pha-nukta + key <AD11> { [ bracketleft, braceleft ] }; + key <AD12> { [ bracketright, braceright ] }; + + //A Row + key <AC01> { [ U093E, U0906, U0905, U0972 ] }; // A: aa matra, aa, short a, candra a + key <AC02> { [ U0938, U0936 ] }; // S: sa, sha + key <AC03> { [ U0926, U0927 ] }; // D: dental da, dha + key <AC04> { [ U094D, U0944, U0960 ] }; // F: virama, vocalic RR matra, vocalic RR + key <AC05> { [ U0917, U0918, U095A ] }; // G: ga, gha, ga-nukta + key <AC06> { [ U0939, U0903, U1CF5, U1CF6 ] }; // H: ha, visarga, jihvamuliya, upadhmaniya + key <AC07> { [ U091C, U091D, U095B ] }; // J: ja, jha, ja-nukta + key <AC08> { [ U0915, U0916, U0958, U0959 ] }; // K: ka, kha, ka-nukta, kha-nukta + key <AC09> { [ U0932, U0933, U0962, U090C ] }; // L: la, lla, vocalic L matra, vocalic L + key <AC10> { [ semicolon, colon, U1CF2, U1CF3 ] }; // U1CF2/3: ardhavisarga/rotated ardhavisarga + key <AC11> { [ apostrophe, quotedbl, U0951, U201D ] }; // U0951: Devanagari stress sign udatta + // U201D: Right double quotation mark + + //Z Row + key <AB01> { [ U091E, U0919 ] }; // Z: nya, nga + key <AB02> { [ U0937, U093C, U0934 ] }; // X: ssa, nukta below, lla-nukta + key <AB03> { [ U091A, U091B ] }; // C: ca, cha + key <AB04> { [ U0935, U094C, U0914 ] }; // V: va, matra au, au + key <AB05> { [ U092C, U092D ] }; // B: ba, bha + key <AB06> { [ U0928, U0923, U0929 ] }; // N: na, nna, nnna + key <AB07> { [ U092E, U0902, U093D, U0950 ] }; // M: ma, anusvara, avagraha, Devanagari OM + key <AB08> { [ comma, U003C, U0945, U090D ] }; // comma: comma, less than, matra, candra e + key <AB09> { [ period, U003E, U0949, U0911 ] }; // period: period, greater than, matra, candra o + key <AB10> { [ slash, question ] }; + + include "level3(ralt_switch)" +}; +// ---- END Hindi KaGaPa ---- + +// Sanskrit uses Devanagari layout of Hindi +partial alphanumeric_keys +xkb_symbols "san-kagapa" { + name[Group1] = "Sanskrit (KaGaPa phonetic)"; + include "in(hin-kagapa)" + +}; + +// Marathi uses Devanagari layout of Hindi +partial alphanumeric_keys +xkb_symbols "mar-kagapa" { + name[Group1] = "Marathi (KaGaPa phonetic)"; + include "in(hin-kagapa)" + +}; + + +// ---- BEGIN Kannada KaGaPa phonetic ---- +// Name: Kannada KaGaPa phonetic +// Diagram: (Original)[http://www.baraha.com/help/Keyboards/kan_brhkbd.htm] +// (This layout)[http://bdsatish.in/lang/kan-kagapa.png] +// +// Description: Based on KaGaPa layout (also called Baraha layout or Nudi layout). +// See the description to "hin-kagapa" above. +// Certain punctuation characters from Devanagari block are +// retained for compatibility. +// +// Author: Satish BD <bdsatish@gmail.com> +// +partial alphanumeric_keys +xkb_symbols "kan-kagapa" { + name[Group1] = "Kannada (KaGaPa phonetic)"; + key.type="FOUR_LEVEL"; + + //Top Alphanumeric row + // Roman digits + key <TLDE> { [ apostrophe, asciitilde, U201C ] }; // U201C: left double quotation mark + key <AE01> { [ 1, exclam, U0CE7 ] }; + key <AE02> { [ 2, at, U0CE8, U20A8 ] }; // U20A8: generic rupee sign (Rs) + key <AE03> { [ 3, numbersign, U0CE9 ] }; + key <AE04> { [ 4, dollar, U0CEA, U20B9 ] }; // U20B9: new Indian Rupee sign + key <AE05> { [ 5, percent, U0CEB ] }; + key <AE06> { [ 6, asciicircum, U0CEC, U200C ] }; // ZWNJ + key <AE07> { [ 7, ampersand, U0CED, U200D ] }; // ZWJ + key <AE08> { [ 8, asterisk, U0CEE, U0901 ] }; // U0901: Devanagari candrabindu + key <AE09> { [ 9, parenleft, U0CEF ] }; + key <AE10> { [ 0, parenright, U0CE6 ] }; + key <AE11> { [ minus, underscore, U0952 ] }; // U0952: Devanagari stress sign anudatta + key <AE12> { [ equal, plus ] }; + key <BKSL> { [ U005C, U007C, U0964, U0965 ] }; // backslash, pipe, danda, double danda + + //Q Row + key <AD01> { [ U0C9F, U0CA0 ] }; // Q: retroflex Ta, Tha + key <AD02> { [ U0CA1, U0CA2 ] }; // W: retroflex Da, Dha + key <AD03> { [ U0CC6, U0CC7, U0C8E, U0C8F ] }; // E: matras, short E, long E + key <AD04> { [ U0CB0, U0CC3, U0C8B, U0CB1 ] }; // R: ra, vocalic R matra, vocalic R, RRA + key <AD05> { [ U0CA4, U0CA5 ] }; // T: dental ta, tha + key <AD06> { [ U0CAF, U0CC8, U0C90 ] }; // Y: ya, ai matra, ai + key <AD07> { [ U0CC1, U0CC2, U0C89, U0C8A ] }; // U: matras, u, uu + key <AD08> { [ U0CBF, U0CC0, U0C87, U0C88 ] }; // I: matras, i, ii + key <AD09> { [ U0CCA, U0CCB, U0C92, U0C93 ] }; // O: matras, short o, long o + key <AD10> { [ U0CAA, U0CAB ] }; // P: pa, pha + key <AD11> { [ bracketleft, braceleft ] }; + key <AD12> { [ bracketright, braceright ] }; + + //A Row + key <AC01> { [ U0CBE, U0C86, U0C85 ] }; // A: aa matra, aa, short a + key <AC02> { [ U0CB8, U0CB6 ] }; // S: sa, sha + key <AC03> { [ U0CA6, U0CA7 ] }; // D: dental da, dha + key <AC04> { [ U0CCD, U0CC4, U0CE0 ] }; // F: virama, vocalic RR matra, vocalic RR + key <AC05> { [ U0C97, U0C98 ] }; // G: ga, gha + key <AC06> { [ U0CB9, U0C83, U0CF1, U0CF2 ] }; // H: ha, visarga, jihvanuliya, upadhmaniya + key <AC07> { [ U0C9C, U0C9D ] }; // J: ja, jha + key <AC08> { [ U0C95, U0C96 ] }; // K: ka, kha + key <AC09> { [ U0CB2, U0CB3, U0CE2, U0C8C ] }; // L: la, lla, vocalic L matra, vocalic L + key <AC10> { [ semicolon, colon ] }; + key <AC11> { [ apostrophe, quotedbl, U0951, U201D ] }; // U0951: Devanagari stress sign udatta + // U201D: Right double quotation mark + + //Z Row + key <AB01> { [ U0C9E, U0C99 ] }; // Z: nya, nga + key <AB02> { [ U0CB7, U0CBC, U0CDE ] }; // X: ssa, nukta below, LLLA + key <AB03> { [ U0C9A, U0C9B ] }; // C: ca, cha + key <AB04> { [ U0CB5, U0CCC, U0C94 ] }; // V: va, matra au, au + key <AB05> { [ U0CAC, U0CAD ] }; // B: ba, bha + key <AB06> { [ U0CA8, U0CA3 ] }; // N: na, nna + key <AB07> { [ U0CAE, U0C82, U0CBD, U0950 ] }; // M: ma, anusvara, avagraha, Devanagari OM + key <AB08> { [ comma, U003C, U0CB1 ] }; // comma: comma, less than, RRA + key <AB09> { [ period, U003E, U0CDE ] }; // period: period, greater than, LLLA + key <AB10> { [ slash, question ] }; + + include "level3(ralt_switch)" +}; +// ---- END Kannada KaGaPa ---- + + +// ---- BEGIN Telugu KaGaPa phonetic ---- +// Name: Telugu KaGaPa phonetic +// Diagram: (Original)[http://www.baraha.com/help/Keyboards/tel_brhkbd.htm] +// (This layout)[http://bdsatish.in/lang/tel-kagapa.png] +// +// Description: Based on KaGaPa layout (also called Baraha layout or Nudi layout). +// See the description to "hin-kagapa" above. +// Certain punctuation characters from Devanagari block are +// retained for compatibility. +// +// Author: Satish BD <bdsatish@gmail.com> +// +partial alphanumeric_keys +xkb_symbols "tel-kagapa" { + name[Group1] = "Telugu (KaGaPa phonetic)"; + key.type="FOUR_LEVEL"; + + //Top Alphanumeric row + // Roman digits + key <TLDE> { [ apostrophe, asciitilde, U201C ] }; // U201C: left double quotation mark + key <AE01> { [ 1, exclam, U0C67 ] }; + key <AE02> { [ 2, at, U0C68, U20A8 ] }; // U20A8: generic rupee sign (Rs) + key <AE03> { [ 3, numbersign, U0C69 ] }; + key <AE04> { [ 4, dollar, U0C6A, U20B9 ] }; // U20B9: new Indian Rupee sign + key <AE05> { [ 5, percent, U0C6B ] }; + key <AE06> { [ 6, asciicircum, U0C6C, U200C ] }; // ZWNJ + key <AE07> { [ 7, ampersand, U0C6D, U200D ] }; // ZWJ + key <AE08> { [ 8, asterisk, U0C6E, U0C01 ] }; // U0C01: Telugu arasunna + key <AE09> { [ 9, parenleft, U0C6F ] }; + key <AE10> { [ 0, parenright, U0C66 ] }; + key <AE11> { [ minus, underscore, U0952 ] }; // U0952: Devanagari stress sign anudatta + key <AE12> { [ equal, plus ] }; + key <BKSL> { [ U005C, U007C, U0964, U0965 ] }; // backslash, pipe, danda, double danda + + //Q Row + key <AD01> { [ U0C1F, U0C20 ] }; // Q: retroflex Ta, Tha + key <AD02> { [ U0C21, U0C22 ] }; // W: retroflex Da, Dha + key <AD03> { [ U0C46, U0C47, U0C0E, U0C0F ] }; // E: matras, short E, long E + key <AD04> { [ U0C30, U0C43, U0C0B, U0C31 ] }; // R: ra, vocalic R matra, vocalic R, RRA + key <AD05> { [ U0C24, U0C25 ] }; // T: dental ta, tha + key <AD06> { [ U0C2F, U0C48, U0C10 ] }; // Y: ya, ai matra, ai + key <AD07> { [ U0C41, U0C42, U0C09, U0C0A ] }; // U: matras, u, uu + key <AD08> { [ U0C3F, U0C40, U0C07, U0C08 ] }; // I: matras, i, ii + key <AD09> { [ U0C4A, U0C4B, U0C12, U0C13 ] }; // O: matras, short o, long o + key <AD10> { [ U0C2A, U0C2B ] }; // P: pa, pha + key <AD11> { [ bracketleft, braceleft ] }; + key <AD12> { [ bracketright, braceright ] }; + + //A Row + key <AC01> { [ U0C3E, U0C06, U0C05 ] }; // A: aa matra, aa, short a + key <AC02> { [ U0C38, U0C36 ] }; // S: sa, sha + key <AC03> { [ U0C26, U0C27 ] }; // D: dental da, dha + key <AC04> { [ U0C4D, U0C44, U0C60 ] }; // F: virama, vocalic RR matra, vocalic RR + key <AC05> { [ U0C17, U0C18 ] }; // G: ga, gha + key <AC06> { [ U0C39, U0C03 ] }; // H: ha, visarga + key <AC07> { [ U0C1C, U0C1D ] }; // J: ja, jha + key <AC08> { [ U0C15, U0C16 ] }; // K: ka, kha + key <AC09> { [ U0C32, U0C33, U0C62, U0C0C ] }; // L: la, lla, vocalic L matra, vocalic L + key <AC10> { [ semicolon, colon ] }; + key <AC11> { [ apostrophe, quotedbl, U0951, U201D ] }; // U0951: Devanagari stress sign udatta + // U201D: Right double quotation mark + + //Z Row + key <AB01> { [ U0C1E, U0C19 ] }; // Z: nya, nga + key <AB02> { [ U0C37 ] }; // X: ssa + key <AB03> { [ U0C1A, U0C1B ] }; // C: ca, cha + key <AB04> { [ U0C35, U0C4C, U0C14 ] }; // V: va, matra au, au + key <AB05> { [ U0C2C, U0C2D ] }; // B: ba, bha + key <AB06> { [ U0C28, U0C23 ] }; // N: na, nna + key <AB07> { [ U0C2E, U0C02, U0C3D, U0950 ] }; // M: ma, anusvara, avagraha, Devanagari OM + key <AB08> { [ comma, U003C, U0C58 ] }; // comma: comma, less than, TSA + key <AB09> { [ period, U003E, U0C59 ] }; // period: period, greater than, DZA + key <AB10> { [ slash, question ] }; + + include "level3(ralt_switch)" +}; +// ---- END Telugu KaGaPa ---- diff --git a/xorg-server/xkeyboard-config/symbols/latin b/xorg-server/xkeyboard-config/symbols/latin index 424768ead..8cabe73e3 100644 --- a/xorg-server/xkeyboard-config/symbols/latin +++ b/xorg-server/xkeyboard-config/symbols/latin @@ -105,7 +105,7 @@ xkb_symbols "type3" { key <AC05> { [ g, G, bracketright, ENG ] }; key <AC08> { [ k, K, lstroke, ampersand ] }; - key <AB01> { [ y, Y, guillemotleft, less ] }; + key <AB01> { [ y, Y, guillemotleft, less ] }; key <AB04> { [ v, V, at, grave ] }; key <AB05> { [ b, B, braceleft, apostrophe ] }; key <AB06> { [ n, N, braceright, braceright ] }; @@ -114,9 +114,9 @@ xkb_symbols "type3" { key <AB09> { [ period, colon, greater, division ] }; }; -// Another one Latin common layout +// Another common Latin layout // (German, Estonian, Spanish, Icelandic, Italian, Latin American, Portuguese) - + partial xkb_symbols "type4" { @@ -150,7 +150,7 @@ xkb_symbols "nodeadkeys" { partial xkb_symbols "type2_nodeadkeys" { - + include "latin(nodeadkeys)" key <AD11> { [ aring, Aring, diaeresis, degree ] }; @@ -162,13 +162,13 @@ xkb_symbols "type2_nodeadkeys" { partial xkb_symbols "type3_nodeadkeys" { - + include "latin(nodeadkeys)" }; partial xkb_symbols "type4_nodeadkeys" { - + include "latin(nodeadkeys)" key <AB10> { [ minus, underscore, dead_belowdot, abovedot ] }; @@ -178,12 +178,12 @@ xkb_symbols "type4_nodeadkeys" { // See http://marcinwolinski.pl/keyboard/ for a description. // Used by pl(intl) // -// ┌────┐ -// │ 2 4│ 2 = Shift, 4 = Level3 + Shift -// │ 1 3│ 1 = Normal, 3 = Level3 -// └────┘ +// ┌─────┐ +// │ 2 4 │ 2 = Shift, 4 = Level3 + Shift +// │ 1 3 │ 1 = Normal, 3 = Level3 +// └─────┘ // ┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┲━━━━━━━━━┓ -// │ ~ ~ │ ! ' │ @ " │ # ˝ │ $ ¸ │ % ˇ │ ^ ^ │ & ˘ │ * ˙ │ ( ̣ │ ) ° │ _ ¯ │ + ˛ ┃ ⌫ Back ┃ +// │ ~ ~ │ ! ' │ @ " │ # ˝ │ $ ¸ │ % ˇ │ ^ ^ │ & ˘ │ * ̇ │ ( ̣ │ ) ° │ _ ¯ │ + ˛ ┃ ⌫ Back- ┃ // │ ` ` │ 1 ¡ │ 2 © │ 3 • │ 4 § │ 5 € │ 6 ¢ │ 7 − │ 8 × │ 9 ÷ │ 0 ° │ - – │ = — ┃ space ┃ // ┢━━━━━┷━┱───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┺━┳━━━━━━━┫ // ┃ ┃ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │ { « │ } » ┃ Enter ┃ @@ -198,7 +198,7 @@ xkb_symbols "type4_nodeadkeys" { // ┃ ┃ ┃ ┃ ␣ ⍽ ┃ ┃ ┃ ┃ // ┃Ctrl ┃Meta ┃Alt ┃ ␣ Space ⍽ ┃AltGr ⇮┃Menu ┃Ctrl ┃ // ┗━━━━━━━┻━━━━━━━┻━━━━━━━┹───────────────────────────────────┺━━━━━━━┻━━━━━━━┻━━━━━━━┛ - + partial xkb_symbols "intl" { diff --git a/xorg-server/xkeyboard-config/symbols/pt b/xorg-server/xkeyboard-config/symbols/pt index e42b40808..b2e0b1255 100644 --- a/xorg-server/xkeyboard-config/symbols/pt +++ b/xorg-server/xkeyboard-config/symbols/pt @@ -186,7 +186,7 @@ partial alphanumeric_keys xkb_symbols "nativo-us" { include "pt(nativo)" - name[Group1]="Portuguese (Nativo for USA keyboards)"; + name[Group1]="Portuguese (Nativo for US keyboards)"; // Lower row key <AB01> { [ y, Y, ccedilla, Ccedilla ] }; diff --git a/xorg-server/xkeyboard-config/symbols/us b/xorg-server/xkeyboard-config/symbols/us index b34bedc0f..5ad2ae072 100644 --- a/xorg-server/xkeyboard-config/symbols/us +++ b/xorg-server/xkeyboard-config/symbols/us @@ -853,7 +853,7 @@ xkb_symbols "altgr-intl" { partial alphanumeric_keys xkb_symbols "classmate" { include "us(basic)" - name[Group1]= "USA - ClassmatePC"; + name[Group1]= "English (US)"; key <LSGT> { [ backslash, bar, backslash, bar ] }; @@ -1052,14 +1052,14 @@ xkb_symbols "olpc" { partial alphanumeric_keys xkb_symbols "olpc2" { include "us(olpc)" - name[Group1]= "English (layout toggle on multiply/divide key)"; + name[Group1]= "English (the divide/multiply keys toggle the layout)"; include "group(olpc)" }; xkb_symbols "olpcm" { include "us(basic)" - name[Group1]= "USA"; + name[Group1]= "English (US)"; // Mechanical (non-membrane) OLPC int'l US English keyboard layout. // See: http://wiki.laptop.org/go/OLPC_English_Non-membrane_Keyboard diff --git a/xorg-server/xkeyboard-config/tests/genLists4Comparizon.sh b/xorg-server/xkeyboard-config/tests/genLists4Comparizon.sh index 90981a939..5756d3ff2 100644 --- a/xorg-server/xkeyboard-config/tests/genLists4Comparizon.sh +++ b/xorg-server/xkeyboard-config/tests/genLists4Comparizon.sh @@ -13,7 +13,9 @@ F1b=${F1}base F1e=${F1}extras xsltproc $ROOT/xslt/reg2ll.xsl $ROOT/rules/base.xml > $F1b -xsltproc $ROOT/xslt/reg2ll.xsl $ROOT/rules/base.extras.xml > $F1e +xsltproc $ROOT/xslt/reg2ll.xsl $ROOT/rules/base.extras.xml | \ + grep -v "sun_type" > $F1e + cat $F1b $F1e | sort | uniq > $F1 rm -f $F1e $F1e @@ -39,7 +41,7 @@ for i in $ROOT/symbols/*; do } else { name=$2; - if (variant == "olpc" || variant == "htcdream") + if (variant == "olpc" || variant == "htcdream" || variant == "olpcm" || variant == "classmate") printf "%s:\"%s\"\n", id, name; else printf "%s(%s):\"%s\"\n", id, variant, name; |