diff options
author | marha <marha@users.sourceforge.net> | 2012-12-10 08:55:36 +0100 |
---|---|---|
committer | marha <marha@users.sourceforge.net> | 2012-12-10 08:55:36 +0100 |
commit | a0124a5e8e70979d2c24ef55285da989fdad766a (patch) | |
tree | 5cea5c9804a8edf67bc7260e0851a20d21324547 | |
parent | 514b4afb64ccbf8e954270105ed5064272a2be68 (diff) | |
parent | 0328076efb5ff6e62152c09e38d0d11f7931d07b (diff) | |
download | vcxsrv-a0124a5e8e70979d2c24ef55285da989fdad766a.tar.gz vcxsrv-a0124a5e8e70979d2c24ef55285da989fdad766a.tar.bz2 vcxsrv-a0124a5e8e70979d2c24ef55285da989fdad766a.zip |
Merge remote-tracking branch 'origin/released'
* origin/released:
fontconfig libX11 mesa pixman git update 10 dec 2012
Conflicts:
fontconfig/src/fcxml.c
138 files changed, 7086 insertions, 1766 deletions
diff --git a/fontconfig/conf.d/50-user.conf b/fontconfig/conf.d/50-user.conf index 2f1040898..07c9182e7 100644 --- a/fontconfig/conf.d/50-user.conf +++ b/fontconfig/conf.d/50-user.conf @@ -1,7 +1,12 @@ <?xml version="1.0"?> <!DOCTYPE fontconfig SYSTEM "fonts.dtd"> <fontconfig> - <!-- Load per-user customization file --> + <!-- + Load per-user customization files where stored on XDG Base Directory + specification compliant places. it should be usually: + $HOME/.config/fontconfig/conf.d + $HOME/.config/fontconfig/fonts.conf + --> <include ignore_missing="yes" prefix="xdg">fontconfig/conf.d</include> <include ignore_missing="yes" prefix="xdg">fontconfig/fonts.conf</include> <!-- the following elements will be removed in the future --> diff --git a/fontconfig/configure.ac b/fontconfig/configure.ac index 6d5ce7e77..5657bb5d1 100644 --- a/fontconfig/configure.ac +++ b/fontconfig/configure.ac @@ -137,7 +137,7 @@ AC_TYPE_PID_T # Checks for library functions. AC_FUNC_VPRINTF AC_FUNC_MMAP -AC_CHECK_FUNCS([geteuid getuid link memmove memset mkstemp strchr strrchr strtol getopt getopt_long sysconf ftruncate chsize rand random lrand48 random_r rand_r regcomp regerror regexec regfree fstatvfs fstatfs]) +AC_CHECK_FUNCS([geteuid getuid link memmove memset mkstemp strchr strrchr strtol getopt getopt_long sysconf ftruncate chsize rand random lrand48 random_r rand_r regcomp regerror regexec regfree fstatvfs fstatfs lstat]) dnl AC_CHECK_FUNCS doesn't check for header files. dnl posix_fadvise() may be not available in older libc. diff --git a/fontconfig/src/fccfg.c b/fontconfig/src/fccfg.c index d3752e552..45b486945 100644 --- a/fontconfig/src/fccfg.c +++ b/fontconfig/src/fccfg.c @@ -1743,6 +1743,8 @@ FcConfigFileExists (const FcChar8 *dir, const FcChar8 *file) #else if ((!path[0] || path[strlen((char *) path)-1] != '/') && file[0] != '/') strcat ((char *) path, "/"); + else + osize--; #endif strcat ((char *) path, (char *) file); diff --git a/fontconfig/src/fcdir.c b/fontconfig/src/fcdir.c index 2b476e8b9..6869ea179 100644 --- a/fontconfig/src/fcdir.c +++ b/fontconfig/src/fcdir.c @@ -35,6 +35,20 @@ FcFileIsDir (const FcChar8 *file) return S_ISDIR(statb.st_mode); } +FcBool +FcFileIsLink (const FcChar8 *file) +{ +#if HAVE_LSTAT + struct stat statb; + + if (lstat ((const char *)file, &statb) != 0) + return FcFalse; + return S_ISLNK (statb.st_mode); +#else + return FcFalse; +#endif +} + static FcBool FcFileScanFontConfig (FcFontSet *set, FcBlanks *blanks, diff --git a/fontconfig/src/fcinit.c b/fontconfig/src/fcinit.c index ab6401215..606483d8d 100644 --- a/fontconfig/src/fcinit.c +++ b/fontconfig/src/fcinit.c @@ -72,7 +72,7 @@ FcInitLoadConfig (void) if (config->cacheDirs && config->cacheDirs->num == 0) { - FcChar8 *prefix; + FcChar8 *prefix, *p; size_t plen; fprintf (stderr, @@ -81,12 +81,15 @@ FcInitLoadConfig (void) "Fontconfig warning: adding <cachedir>%s</cachedir>\n", FC_CACHEDIR); prefix = FcConfigXdgCacheHome (); - plen = prefix ? strlen ((const char *)prefix) : 0; if (!prefix) goto bail; - prefix = realloc (prefix, plen + 12); - if (!prefix) + plen = strlen ((const char *)prefix); + p = realloc (prefix, plen + 12); + if (!p) goto bail; + prefix = p; + FcMemFree (FC_MEM_STRING, plen + 1); + FcMemAlloc (FC_MEM_STRING, plen + 12); memcpy (&prefix[plen], FC_DIR_SEPARATOR_S "fontconfig", 11); prefix[plen + 11] = 0; fprintf (stderr, @@ -98,11 +101,12 @@ FcInitLoadConfig (void) bail: fprintf (stderr, "Fontconfig error: out of memory"); - free (prefix); + if (prefix) + FcStrFree (prefix); FcConfigDestroy (config); return FcInitFallbackConfig (); } - free (prefix); + FcStrFree (prefix); } return config; diff --git a/fontconfig/src/fcint.h b/fontconfig/src/fcint.h index 7125f2e5e..87c7b9a9f 100644 --- a/fontconfig/src/fcint.h +++ b/fontconfig/src/fcint.h @@ -764,6 +764,9 @@ FcGetDefaultLang (void); /* fcdir.c */ FcPrivate FcBool +FcFileIsLink (const FcChar8 *file); + +FcPrivate FcBool FcFileScanConfig (FcFontSet *set, FcStrSet *dirs, FcBlanks *blanks, diff --git a/fontconfig/src/fclang.c b/fontconfig/src/fclang.c index b7e70fcfb..65d22a932 100644 --- a/fontconfig/src/fclang.c +++ b/fontconfig/src/fclang.c @@ -182,7 +182,7 @@ FcLangNormalize (const FcChar8 *lang) { FcChar8 *result = NULL, *s, *orig; char *territory, *encoding, *modifier; - size_t llen, tlen = 0, mlen = 0; + size_t llen, tlen = 0, mlen = 0, ssize; if (!lang || !*lang) return NULL; @@ -197,6 +197,10 @@ FcLangNormalize (const FcChar8 *lang) s = FcStrCopy (lang); if (!s) goto bail; + /* store the original length of 's' here to let FcMemFree know + * the correct size since we breaks 's' from now on. + */ + ssize = strlen ((const char *)s) + 1; /* from the comments in glibc: * @@ -282,6 +286,11 @@ FcLangNormalize (const FcChar8 *lang) else { result = s; + /* we'll miss the opportunity to reduce the correct size + * of the allocated memory for the string after that. + */ + FcMemFree (FC_MEM_STRING, ssize); + FcMemAlloc (FC_MEM_STRING, strlen((const char *)s) + 1); s = NULL; goto bail1; } @@ -295,6 +304,11 @@ FcLangNormalize (const FcChar8 *lang) else { result = s; + /* we'll miss the opportunity to reduce the correct size + * of the allocated memory for the string after that. + */ + FcMemFree (FC_MEM_STRING, ssize); + FcMemAlloc (FC_MEM_STRING, strlen((const char *)s) + 1); s = NULL; goto bail1; } @@ -312,14 +326,22 @@ FcLangNormalize (const FcChar8 *lang) else { result = s; + /* we'll miss the opportunity to reduce the correct size + * of the allocated memory for the string after that. + */ + FcMemFree (FC_MEM_STRING, ssize); + FcMemAlloc (FC_MEM_STRING, strlen((const char *)s) + 1); s = NULL; } bail1: if (orig) - free (orig); + FcStrFree (orig); bail0: if (s) + { free (s); + FcMemFree (FC_MEM_STRING, ssize); + } bail: if (FcDebug () & FC_DBG_LANGSET) { diff --git a/fontconfig/src/fcstr.c b/fontconfig/src/fcstr.c index 037960d2f..99b59da0a 100644 --- a/fontconfig/src/fcstr.c +++ b/fontconfig/src/fcstr.c @@ -38,7 +38,6 @@ FcStrCopy (const FcChar8 *s) { int len; FcChar8 *r; - if (!s) return 0; len = strlen ((char *) s) + 1; @@ -1204,7 +1203,7 @@ FcStrSetAddLangs (FcStrSet *strs, const char *languages) if (normalized_lang) { FcStrSetAdd (strs, normalized_lang); - free (normalized_lang); + FcStrFree (normalized_lang); ret = FcTrue; } } @@ -1216,7 +1215,7 @@ FcStrSetAddLangs (FcStrSet *strs, const char *languages) if (normalized_lang) { FcStrSetAdd (strs, normalized_lang); - free (normalized_lang); + FcStrFree (normalized_lang); ret = FcTrue; } } diff --git a/fontconfig/src/fcxml.c b/fontconfig/src/fcxml.c index 7d1d6f1ad..0c8c80561 100644..100755 --- a/fontconfig/src/fcxml.c +++ b/fontconfig/src/fcxml.c @@ -1850,7 +1850,7 @@ FcParseDir (FcConfigParse *parse) { const FcChar8 *attr; FcChar8 *data; - FcChar8 *prefix = NULL; + FcChar8 *prefix = NULL, *p; #ifdef _WIN32 FcChar8 buffer[1000]; #endif @@ -1869,13 +1869,14 @@ FcParseDir (FcConfigParse *parse) size_t plen = strlen ((const char *)prefix); size_t dlen = strlen ((const char *)data); - FcMemFree (FC_MEM_STRING, plen + 1); - prefix = realloc (prefix, plen + 1 + dlen + 1); - if (!prefix) + p = realloc (prefix, plen + 1 + dlen + 1); + if (!p) { FcConfigMessage (parse, FcSevereError, "out of memory"); goto bail; } + prefix = p; + FcMemFree (FC_MEM_STRING, plen + 1); FcMemAlloc (FC_MEM_STRING, plen + 1 + dlen + 1); prefix[plen] = FC_DIR_SEPARATOR; memcpy (&prefix[plen + 1], data, dlen); @@ -1948,7 +1949,7 @@ static void FcParseCacheDir (FcConfigParse *parse) { const FcChar8 *attr; - FcChar8 *prefix = NULL, *data; + FcChar8 *prefix = NULL, *p, *data; attr = FcConfigGetAttribute (parse, "prefix"); if (attr && FcStrCmp (attr, (const FcChar8 *)"xdg") == 0) @@ -1964,13 +1965,15 @@ FcParseCacheDir (FcConfigParse *parse) size_t plen = strlen ((const char *)prefix); size_t dlen = strlen ((const char *)data); - FcMemFree (FC_MEM_STRING, plen + 1); - prefix = realloc (prefix, plen + 1 + dlen + 1); - if (!prefix) + p = realloc (prefix, plen + 1 + dlen + 1); + if (!p) { FcConfigMessage (parse, FcSevereError, "out of memory"); + data = prefix; goto bail; } + prefix = p; + FcMemFree (FC_MEM_STRING, plen + 1); FcMemAlloc (FC_MEM_STRING, plen + 1 + dlen + 1); prefix[plen] = FC_DIR_SEPARATOR; memcpy (&prefix[plen + 1], data, dlen); @@ -2044,7 +2047,7 @@ FcParseInclude (FcConfigParse *parse) const FcChar8 *attr; FcBool ignore_missing = FcFalse; FcBool deprecated = FcFalse; - FcChar8 *prefix = NULL; + FcChar8 *prefix = NULL, *p; s = FcStrBufDoneStatic (&parse->pstack->str); if (!s) @@ -2066,13 +2069,14 @@ FcParseInclude (FcConfigParse *parse) size_t plen = strlen ((const char *)prefix); size_t dlen = strlen ((const char *)s); - FcMemFree (FC_MEM_STRING, plen + 1); - prefix = realloc (prefix, plen + 1 + dlen + 1); - if (!prefix) + p = realloc (prefix, plen + 1 + dlen + 1); + if (!p) { FcConfigMessage (parse, FcSevereError, "out of memory"); goto bail; } + prefix = p; + FcMemFree (FC_MEM_STRING, plen + 1); FcMemAlloc (FC_MEM_STRING, plen + 1 + dlen + 1); prefix[plen] = FC_DIR_SEPARATOR; memcpy (&prefix[plen + 1], s, dlen); @@ -2086,8 +2090,10 @@ FcParseInclude (FcConfigParse *parse) FcChar8 *filename; filename = FcConfigFilename(s); - if ((deprecated == FcTrue) && filename) - { + if (deprecated == FcTrue && + filename != NULL && + !FcFileIsLink (filename)) + { FcConfigMessage (parse, FcSevereWarning, "reading configurations from %s is deprecated.", s); } if(filename) diff --git a/libX11/configure.ac b/libX11/configure.ac index a45f9d956..fe3179948 100644 --- a/libX11/configure.ac +++ b/libX11/configure.ac @@ -439,7 +439,7 @@ 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.S90 ja.SJIS ja.U90 ko koi8-c koi8-r \ + 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 \ tatar-cyr th_TH th_TH.UTF-8 tscii-0 vi_VN.tcvn vi_VN.viscii \ diff --git a/libX11/nls/compose.dir.pre b/libX11/nls/compose.dir.pre index 14a2fa987..ef9a519bc 100644 --- a/libX11/nls/compose.dir.pre +++ b/libX11/nls/compose.dir.pre @@ -7,6 +7,7 @@ XCOMM iso8859-1/Compose: C iso8859-1/Compose: af_ZA.ISO8859-1 iso8859-6/Compose: ar_AA.ISO8859-6 +iso8859-6/Compose: ar_AE.ISO8859-6 iso8859-6/Compose: ar_BH.ISO8859-6 iso8859-6/Compose: ar_DZ.ISO8859-6 iso8859-6/Compose: ar_EG.ISO8859-6 @@ -19,13 +20,17 @@ iso8859-6/Compose: ar_MA.ISO8859-6 iso8859-6/Compose: ar_OM.ISO8859-6 iso8859-6/Compose: ar_QA.ISO8859-6 iso8859-6/Compose: ar_SA.ISO8859-6 +iso8859-6/Compose: ar_SD.ISO8859-6 +iso8859-6/Compose: ar_SY.ISO8859-6 iso8859-6/Compose: ar_TN.ISO8859-6 iso8859-6/Compose: ar_YE.ISO8859-6 iso8859-9e/Compose: az_AZ.ISO8859-9E -koi8-c/Compose: a3_AZ.KOI8-C +koi8-c/Compose: az_AZ.KOI8-C microsoft-cp1251/Compose: be_BY.CP1251 +iso8859-5/Compose: be_BY.ISO8859-5 iso8859-5/Compose: bg_BG.ISO8859-5 microsoft-cp1251/Compose: bg_BG.CP1251 +koi8-r/Compose: bg_BG.KOI8-R iso8859-1/Compose: br_FR.ISO8859-1 iso8859-14/Compose: br_FR.ISO8859-14 iso8859-15/Compose: br_FR.ISO8859-15 @@ -46,6 +51,8 @@ iso8859-1/Compose: da_DK.ISO8859-1 iso8859-15/Compose: da_DK.ISO8859-15 iso8859-1/Compose: de_AT.ISO8859-1 iso8859-15/Compose: de_AT.ISO8859-15 +iso8859-1/Compose: de_BE.ISO8859-1 +iso8859-15/Compose: de_BE.ISO8859-15 iso8859-1/Compose: de_CH.ISO8859-1 iso8859-15/Compose: de_CH.ISO8859-15 iso8859-1/Compose: de_DE.ISO8859-1 @@ -54,16 +61,26 @@ iso8859-1/Compose: de_LI.ISO8859-1 iso8859-15/Compose: de_LI.ISO8859-15 iso8859-1/Compose: de_LU.ISO8859-1 iso8859-15/Compose: de_LU.ISO8859-15 +iso8859-4/Compose: ee_EE.ISO8859-4 iso8859-7/Compose: el_GR.ISO8859-7 +iso8859-15/Compose: el_GR.ISO8859-15 iso8859-1/Compose: en_AU.ISO8859-1 +iso8859-1/Compose: en_BE.ISO8859-1 +iso8859-15/Compose: en_BE.ISO8859-15 +iso8859-1/Compose: en_BW.ISO8859-1 iso8859-1/Compose: en_BZ.ISO8859-1 iso8859-1/Compose: en_CA.ISO8859-1 +iso8859-1/Compose: en_EN.ISO8859-1 iso8859-1/Compose: en_GB.ISO8859-1 iso8859-15/Compose: en_GB.ISO8859-15 +iso8859-1/Compose: en_HK.ISO8859-1 iso8859-1/Compose: en_IE.ISO8859-1 iso8859-15/Compose: en_IE.ISO8859-15 +iso8859-15/Compose: en_IN.ISO8859-15 iso8859-1/Compose: en_JM.ISO8859-1 iso8859-1/Compose: en_NZ.ISO8859-1 +iso8859-1/Compose: en_PH.ISO8859-1 +iso8859-1/Compose: en_SG.ISO8859-1 iso8859-1/Compose: en_TT.ISO8859-1 iso8859-1/Compose: en_UK.ISO8859-1 iso8859-15/Compose: en_UK.ISO8859-15 @@ -71,6 +88,8 @@ iso8859-1/Compose: en_US.ISO8859-1 iso8859-15/Compose: en_US.ISO8859-15 iso8859-1/Compose: en_ZA.ISO8859-1 iso8859-15/Compose: en_ZA.ISO8859-15 +iso8859-1/Compose: en_ZW.ISO8859-1 +iso8859-3/Compose: eo_EO.ISO8859-3 iso8859-3/Compose: eo_XX.ISO8859-3 iso8859-1/Compose: es_AR.ISO8859-1 iso8859-1/Compose: es_BO.ISO8859-1 @@ -86,12 +105,19 @@ iso8859-1/Compose: es_HN.ISO8859-1 iso8859-1/Compose: es_MX.ISO8859-1 iso8859-1/Compose: es_NI.ISO8859-1 iso8859-1/Compose: es_PA.ISO8859-1 +iso8859-15/Compose: es_PA.ISO8859-15 iso8859-1/Compose: es_PE.ISO8859-1 +iso8859-15/Compose: es_PE.ISO8859-15 iso8859-1/Compose: es_PR.ISO8859-1 iso8859-1/Compose: es_PY.ISO8859-1 +iso8859-15/Compose: es_PY.ISO8859-15 iso8859-1/Compose: es_SV.ISO8859-1 +iso8859-15/Compose: es_SV.ISO8859-15 +iso8859-1/Compose: es_US.ISO8859-1 iso8859-1/Compose: es_UY.ISO8859-1 +iso8859-15/Compose: es_UY.ISO8859-15 iso8859-1/Compose: es_VE.ISO8859-1 +iso8859-15/Compose: es_VE.ISO8859-15 iso8859-1/Compose: et_EE.ISO8859-1 iso8859-4/Compose: et_EE.ISO8859-4 iso8859-13/Compose: et_EE.ISO8859-13 @@ -151,14 +177,12 @@ iso8859-15/Compose: kw_GB.ISO8859-15 ko/Compose: ko_KR.eucKR ibm-cp1133/Compose: lo_LA.IBM-CP1133 mulelao-1/Compose: lo_LA.MULELAO-1 -iso8859-1/Compose: lt_LN.ISO8859-1 iso8859-4/Compose: lt_LT.ISO8859-4 iso8859-13/Compose: lt_LT.ISO8859-13 iso8859-4/Compose: lv_LV.ISO8859-4 iso8859-13/Compose: lv_LV.ISO8859-13 iso8859-13/Compose: mi_NZ.ISO8859-13 iso8859-5/Compose: mk_MK.ISO8859-5 -XCOMM mk_MK.UTF-8/Compose: mk_MK.UTF-8 microsoft-cp1251/Compose: mk_MK.CP1251 iso8859-1/Compose: ms_MY.ISO8859-1 iso8859-3/Compose: mt_MT.ISO8859-3 @@ -179,7 +203,9 @@ iso8859-15/Compose: ny_NO.ISO8859-15 iso8859-1/Compose: oc_FR.ISO8859-1 iso8859-15/Compose: oc_FR.ISO8859-15 iso8859-1/Compose: pd_DE.ISO8859-1 +iso8859-15/Compose: pd_DE.ISO8859-15 iso8859-1/Compose: pd_US.ISO8859-1 +iso8859-15/Compose: pd_US.ISO8859-15 iso8859-1/Compose: ph_PH.ISO8859-1 iso8859-2/Compose: pl_PL.ISO8859-2 iso8859-1/Compose: pp_AN.ISO8859-1 @@ -191,16 +217,17 @@ iso8859-2/Compose: ro_RO.ISO8859-2 koi8-r/Compose: ru_RU.KOI8-R iso8859-5/Compose: ru_RU.ISO8859-5 microsoft-cp1251/Compose: ru_RU.CP1251 +microsoft-cp1251/Compose: ru_UA.CP1251 koi8-u/Compose: ru_UA.KOI8-U iso8859-1/Compose: rw_RW.ISO8859-1 iso8859-2/Compose: sh_YU.ISO8859-2 iso8859-2/Compose: sk_SK.ISO8859-2 -iso8859-2/Compose: sl_CS.ISO8859-2 iso8859-2/Compose: sl_SI.ISO8859-2 iso8859-2/Compose: sq_AL.ISO8859-2 iso8859-2/Compose: sr_CS.ISO8859-2 iso8859-5/Compose: sr_CS.ISO8859-5 iso8859-2/Compose: sr_YU.ISO8859-2 +microsoft-cp1251/Compose: sr_YU.CP1251 iso8859-5/Compose: sr_YU.ISO8859-5 iso8859-1/Compose: ss_ZA.ISO8859-1 iso8859-1/Compose: st_ZA.ISO8859-1 @@ -211,34 +238,39 @@ iso8859-15/Compose: sv_SE.ISO8859-15 tscii-0/Compose: ta_IN.TSCII-0 koi8-c/Compose: tg_TJ.KOI8-C iso8859-1/Compose: tl_PH.ISO8859-1 +iso8859-11/Compose: th_TH.ISO8859-11 +th_TH/Compose: th_TH.TIS620 iso8859-15/Compose: tn_ZA.ISO8859-15 iso8859-9/Compose: tr_TR.ISO8859-9 iso8859-1/Compose: ts_ZA.ISO8859-1 tatar-cyr/Compose: tt_RU.TATAR-CYR +microsoft-cp1251/Compose: uk_UA.CP1251 koi8-c/Compose: tt_RU.KOI8-C koi8-u/Compose: uk_UA.KOI8-U +iso8859-5/Compose: uk_UA.ISO8859-5 microsoft-cp1256/Compose: ur_PK.CP1256 +iso8859-1/Compose: uz_UZ.ISO8859-1 vi_VN.viscii/Compose: vi_VN.VISCII vi_VN.tcvn/Compose: vi_VN.TCVN iso8859-1/Compose: wa_BE.ISO8859-1 +iso8859-15/Compose: wa_BE.ISO8859-15 iso8859-1/Compose: xh_ZA.ISO8859-1 -microsoft-cp1255/Compose: yi_US.CP1256 +microsoft-cp1255/Compose: yi_US.CP1255 zh_CN/Compose: zh_CN.eucCN -zh_CN/Compose: zh_CN.GB2312 -zh_CN.gbk/Compose: zh_CN.GBK -zh_CN.gb18030/Compose: zh_CN.GB18030 +zh_CN/Compose: zh_CN.gb2312 +zh_CN.gbk/Compose: zh_CN.gbk +zh_CN.gb18030/Compose: zh_CN.gb18030 zh_HK.big5/Compose: zh_HK.big5 -zh_HK.big5/Compose: zh_HK.Big5 zh_HK.big5hkscs/Compose: zh_HK.big5hkscs -zh_HK.big5hkscs/Compose: zh_HK.Big5HKSCS zh_TW.big5/Compose: zh_TW.big5 -zh_TW.big5/Compose: zh_TW.Big5 zh_TW/Compose: zh_TW.eucTW iso8859-1/Compose: zu_ZA.ISO8859-1 XCOMM XCOMM en_US.UTF-8/Compose: af_ZA.UTF-8 +am_ET.UTF-8/Compose: am_ET.UTF-8 en_US.UTF-8/Compose: ar_AA.UTF-8 +en_US.UTF-8/Compose: ar_AE.UTF-8 en_US.UTF-8/Compose: ar_BH.UTF-8 en_US.UTF-8/Compose: ar_DZ.UTF-8 en_US.UTF-8/Compose: ar_EG.UTF-8 @@ -252,23 +284,26 @@ en_US.UTF-8/Compose: ar_MA.UTF-8 en_US.UTF-8/Compose: ar_OM.UTF-8 en_US.UTF-8/Compose: ar_QA.UTF-8 en_US.UTF-8/Compose: ar_SA.UTF-8 +en_US.UTF-8/Compose: ar_SD.UTF-8 +en_US.UTF-8/Compose: ar_SY.UTF-8 en_US.UTF-8/Compose: ar_TN.UTF-8 en_US.UTF-8/Compose: ar_YE.UTF-8 +en_US.UTF-8/Compose: as_IN.UTF-8 en_US.UTF-8/Compose: bo_IN.UTF-8 en_US.UTF-8/Compose: bs_BA.UTF-8 en_US.UTF-8/Compose: az_AZ.UTF-8 -en_US.UTF-8/Compose: a3_AZ.UTF-8 en_US.UTF-8/Compose: be_BY.UTF-8 en_US.UTF-8/Compose: bg_BG.UTF-8 en_US.UTF-8/Compose: bn_IN.UTF-8 +en_US.UTF-8/Compose: bn_BD.UTF-8 en_US.UTF-8/Compose: br_FR.UTF-8 +en_US.UTF-8/Compose: bs_BA.UTF-8 en_US.UTF-8/Compose: ca_AD.UTF-8 en_US.UTF-8/Compose: ca_ES.UTF-8 en_US.UTF-8/Compose: ca_FR.UTF-8 en_US.UTF-8/Compose: ca_IT.UTF-8 en_US.UTF-8/Compose: cs_CZ.UTF-8 en_US.UTF-8/Compose: cy_GB.UTF-8 -en_US.UTF-8/Compose: cz_CZ.UTF-8 en_US.UTF-8/Compose: da_DK.UTF-8 en_US.UTF-8/Compose: de_AT.UTF-8 en_US.UTF-8/Compose: de_BE.UTF-8 @@ -279,17 +314,27 @@ en_US.UTF-8/Compose: de_LU.UTF-8 el_GR.UTF-8/Compose: el_CY.UTF-8 el_GR.UTF-8/Compose: el_GR.UTF-8 en_US.UTF-8/Compose: en_AU.UTF-8 +en_US.UTF-8/Compose: en_BE.UTF-8 +en_US.UTF-8/Compose: en_BW.UTF-8 en_US.UTF-8/Compose: en_BZ.UTF-8 +en_US.UTF-8/Compose: en_DK.UTF-8 en_US.UTF-8/Compose: en_CA.UTF-8 en_US.UTF-8/Compose: en_GB.UTF-8 +en_US.UTF-8/Compose: en_EN.UTF-8 +en_US.UTF-8/Compose: en_HK.UTF-8 en_US.UTF-8/Compose: en_IE.UTF-8 +en_US.UTF-8/Compose: en_IN.UTF-8 en_US.UTF-8/Compose: en_JM.UTF-8 en_US.UTF-8/Compose: en_MT.UTF-8 en_US.UTF-8/Compose: en_NZ.UTF-8 +en_US.UTF-8/Compose: en_PH.UTF-8 +en_US.UTF-8/Compose: en_SG.UTF-8 en_US.UTF-8/Compose: en_TT.UTF-8 en_US.UTF-8/Compose: en_UK.UTF-8 en_US.UTF-8/Compose: en_US.UTF-8 en_US.UTF-8/Compose: en_ZA.UTF-8 +en_US.UTF-8/Compose: en_ZW.UTF-8 +en_US.UTF-8/Compose: eo_EO.UTF-8 en_US.UTF-8/Compose: eo_XX.UTF-8 en_US.UTF-8/Compose: es_AR.UTF-8 en_US.UTF-8/Compose: es_BO.UTF-8 @@ -337,12 +382,13 @@ en_US.UTF-8/Compose: is_IS.UTF-8 en_US.UTF-8/Compose: it_CH.UTF-8 en_US.UTF-8/Compose: it_IT.UTF-8 en_US.UTF-8/Compose: iu_CA.UTF-8 -en_US.UTF-8/Compose: ja_JP.UTF-8 +ja_JP.UTF-8/Compose: ja_JP.UTF-8 en_US.UTF-8/Compose: ka_GE.UTF-8 -en_US.UTF-8/Compose: kl_GL.UTF-8 en_US.UTF-8/Compose: kk_KZ.UTF-8 +en_US.UTF-8/Compose: kl_GL.UTF-8 +km_KH.UTF-8/Compose: mk_KH.UTF-8 en_US.UTF-8/Compose: kn_IN.UTF-8 -en_US.UTF-8/Compose: ko_KR.UTF-8 +ko_KR.UTF-8/Compose: ko_KR.UTF-8 en_US.UTF-8/Compose: ks_IN.UTF-8 en_US.UTF-8/Compose: ks_IN@devanagari.UTF-8 en_US.UTF-8/Compose: kw_GB.UTF-8 @@ -357,6 +403,7 @@ en_US.UTF-8/Compose: ml_IN.UTF-8 en_US.UTF-8/Compose: mr_IN.UTF-8 en_US.UTF-8/Compose: ms_MY.UTF-8 en_US.UTF-8/Compose: mt_MT.UTF-8 +en_US.UTF-8/Compose: ne_NP.UTF-8 en_US.UTF-8/Compose: nl_BE.UTF-8 en_US.UTF-8/Compose: nl_NL.UTF-8 en_US.UTF-8/Compose: nn_NO.UTF-8 @@ -377,18 +424,20 @@ en_US.UTF-8/Compose: pp_AN.UTF-8 pt_BR.UTF-8/Compose: pt_BR.UTF-8 en_US.UTF-8/Compose: pt_PT.UTF-8 en_US.UTF-8/Compose: ro_RO.UTF-8 -en_US.UTF-8/Compose: ru_RU.UTF-8 +ru_RU.UTF-8/Compose: ru_RU.UTF-8 en_US.UTF-8/Compose: ru_UA.UTF-8 en_US.UTF-8/Compose: rw_RW.UTF-8 en_US.UTF-8/Compose: sa_IN.UTF-8 en_US.UTF-8/Compose: sd_IN.UTF-8 en_US.UTF-8/Compose: sd_IN@devanagari.UTF-8 +en_US.UTF-8/Compose: se_NO.UTF-8 en_US.UTF-8/Compose: sh_BA.UTF-8 +en_US.UTF-8/Compose: sh_YU.UTF-8 en_US.UTF-8/Compose: si_LK.UTF-8 en_US.UTF-8/Compose: sk_SK.UTF-8 en_US.UTF-8/Compose: sl_SI.UTF-8 en_US.UTF-8/Compose: sq_AL.UTF-8 -en_US.UTF-8/Compose: sr_CS.UTF-8 +sr_CS.UTF-8/Compose: sr_CS.UTF-8 en_US.UTF-8/Compose: sr_ME.UTF-8 en_US.UTF-8/Compose: sr_RS.UTF-8 en_US.UTF-8/Compose: sr_YU.UTF-8 @@ -399,7 +448,9 @@ en_US.UTF-8/Compose: sv_SE.UTF-8 en_US.UTF-8/Compose: ta_IN.UTF-8 en_US.UTF-8/Compose: te_IN.UTF-8 en_US.UTF-8/Compose: tg_TJ.UTF-8 -en_US.UTF-8/Compose: th_TH.UTF-8 +th_TH.UTF-8/Compose: th_TH.UTF-8 +en_US.UTF-8/Compose: ti_ER.UTF-8 +en_US.UTF-8/Compose: ti_ET.UTF-8 en_US.UTF-8/Compose: tl_PH.UTF-8 en_US.UTF-8/Compose: tn_ZA.UTF-8 en_US.UTF-8/Compose: tr_TR.UTF-8 @@ -407,14 +458,15 @@ en_US.UTF-8/Compose: ts_ZA.UTF-8 en_US.UTF-8/Compose: tt_RU.UTF-8 en_US.UTF-8/Compose: uk_UA.UTF-8 en_US.UTF-8/Compose: ur_PK.UTF-8 +en_US.UTF-8/Compose: ur_IN.UTF-8 en_US.UTF-8/Compose: uz_UZ.UTF-8 en_US.UTF-8/Compose: ve_ZA.UTF-8 en_US.UTF-8/Compose: vi_VN.UTF-8 en_US.UTF-8/Compose: wa_BE.UTF-8 en_US.UTF-8/Compose: yi_US.UTF-8 en_US.UTF-8/Compose: xh_ZA.UTF-8 -en_US.UTF-8/Compose: zh_TW.UTF-8 +zh_CN.UTF-8/Compose: zh_CN.UTF-8 +zh_HK.UTF-8/Compose: zh_HK.UTF-8 +zh_TW.UTF-8/Compose: zh_TW.UTF-8 en_US.UTF-8/Compose: zu_ZA.UTF-8 -en_US.UTF-8/Compose: bs_BA.UTF-8 -en_US.UTF-8/Compose: ne_NP.UTF-8 - +en_US.UTF-8/Compose: zh_SG.UTF-8 diff --git a/libX11/nls/ja.S90/XI18N_OBJS b/libX11/nls/ja.S90/XI18N_OBJS deleted file mode 100644 index d8f0fdd99..000000000 --- a/libX11/nls/ja.S90/XI18N_OBJS +++ /dev/null @@ -1,7 +0,0 @@ -# CATEGORY(XLC|XIM|OM) SHARED_LIBRARY_NAME FUNCTION_NAME -# -# XI18N objects table for ja.S90 locale -# -XLC common/xlibi18n _XlcGenericLoader # XLC_open -XIM common/ximcp _XimOpenIM _XimRegisterIMInstantiateCallback _XimUnRegisterIMInstantiateCallback # XIM_open XIM_register XIM_unregister -XOM common/xomGeneric _XomGenericOpenOM # XOM_open diff --git a/libX11/nls/ja.S90/XLC_LOCALE.pre b/libX11/nls/ja.S90/XLC_LOCALE.pre deleted file mode 100644 index cb4e49d13..000000000 --- a/libX11/nls/ja.S90/XLC_LOCALE.pre +++ /dev/null @@ -1,150 +0,0 @@ -XCOMM Copyright 1995 by FUJITSU LIMITED -XCOMM This is source code modified by FUJITSU LIMITED under the Joint -XCOMM Development Agreement for the CDEnext PST. -XCOMM This is unpublished proprietary source code of FUJITSU LIMITED -XCOMM -XCOMM NLS-DB for ja_JP.S90 - -XCOMM -XCOMM XLC_CHARSET_DEFINE category -XCOMM -XLC_CHARSET_DEFINE -csd0 { - charset_name u90x03.1991-0 - side GL - length 2 - gc_number 94 - string_encoding False - sequence \x1b\x25\x28\x32 - encoding_name fujitsu.U90X03 -} - -csd1 { - charset_name u90x03.1991-0 - side GR - length 2 - gc_number 94 - string_encoding False - sequence \x1b\x25\x2f\x32 - encoding_name fujitsu.U90X03 -} -END XLC_CHARSET_DEFINE - -XCOMM -XCOMM XLC_FONTSET category -XCOMM -XLC_FONTSET -XCOMM fs0 class (7 bit ASCII) -fs0 { - charset { - name JISX0201.1976-0:GL - } - font { - primary JISX0201.1976-0:GL - substitute ISO8859-1:GL - vertical_rotate all - } -} -XCOMM fs1 class (Kanji) -fs1 { - charset { - name JISX0208.1983-0:GL - udc_area \x7521,\x7e7e - } - font { - primary fujitsu.u90x01.1991-0:GL,[\x2121,\x747e];\ - fujitsu.u90x03.1991-0:GL,[\x7521,\x7e7e]->\x6521 - substitute u90x01.1991-0:GL;\ - JISX0208.1983-0:GL; JISX0208.1983-0:GR;\ - JISX0208.1983-1:GL; JISX0208.1983-1:GR;\ - JISX0208.1990-0:GL; JISX0208.1990-0:GR - vertical_map u90x01.1991-0.2:GL,\ - [\x2122,\x2125]->\x7d21,[\x2131,\x2132]->\x7d25,\ - [\x213c,\x213e]->\x7d27,[\x2141,\x215b]->\x7d2a,\ - [\x2421,\x2421]->\x7d45,[\x2423,\x2423]->\x7d46,\ - [\x2425,\x2425]->\x7d47,[\x2427,\x2427]->\x7d48,\ - [\x2429,\x2429]->\x7d49,[\x2443,\x2443]->\x7d4a,\ - [\x2463,\x2463]->\x7d4b,[\x2465,\x2465]->\x7d4c,\ - [\x2467,\x2467]->\x7d4d,[\x246e,\x246e]->\x7d4e,\ - [\x2521,\x2521]->\x7d4f,[\x2523,\x2523]->\x7d50,\ - [\x2525,\x2525]->\x7d51,[\x2527,\x2527]->\x7d52,\ - [\x2529,\x2529]->\x7d53,[\x2543,\x2543]->\x7d54,\ - [\x2563,\x2563]->\x7d55,[\x2565,\x2565]->\x7d56,\ - [\x2567,\x2567]->\x7d57,[\x256e,\x256e]->\x7d58,\ - [\x2575,\x2576]->\x7d59,[\x2475,\x2476]->\x7d5b - } -} -XCOMM fs2 class (Half Kana) -fs2 { - charset { - name JISX0201.1976-0:GR - } - font { - primary JISX0201.1976-0:GR - vertical_rotate all - } -} -XCOMM fs3 class (JEF Kanji + User Defined Character) -fs3 { - charset { - name u90x03.1991-0:GR; u90x03.1991-0:GL - udc_area \x6521,\x787e - } - font { - primary fujitsu.u90x03.1991-0:GL - substitute u90x03.1991-0:GL;\ - JISX0208.1983-0:GL; JISX0208.1983-0:GR;\ - JISX0208.1983-1:GL; JISX0208.1983-1:GR;\ - JISX0208.1990-0:GL; JISX0208.1990-0:GR - } -} -END XLC_FONTSET - -XCOMM -XCOMM XLC_XLOCALE category -XCOMM -XLC_XLOCALE - -XCOMM encoding_name ja.euc -encoding_name ja_JP.S90 -mb_cur_max 3 -state_depend_encoding False - -wc_encoding_mask \x30000000 -wc_shift_bits 7 - - -XCOMM cs0 class -cs0 { - side GL:Default - length 1 - wc_encoding \x00000000 - ct_encoding JISX0201.1976-0:GL; ISO8859-1:GL -} - -XCOMM cs1 class -cs1 { - side GR:Default - length 2 - wc_encoding \x30000000 - ct_encoding JISX0208.1983-0:GL; JISX0208.1983-0:GR;\ - JISX0208.1983-1:GL; JISX0208.1983-1:GR -} - -XCOMM cs2 class -cs2 { - side GR - length 1 - mb_encoding <SS> \x8e - wc_encoding \x10000000 - ct_encoding JISX0201.1976-0:GR -} -XCOMM cs3 class -cs3 { - side GR - length 2 - mb_encoding <SS> \x8f - wc_encoding \x20000000 - ct_encoding u90x03.1991-0:GR; u90x03.1991-0:GL -} -END XLC_XLOCALE diff --git a/libX11/nls/ja.U90/XI18N_OBJS b/libX11/nls/ja.U90/XI18N_OBJS deleted file mode 100644 index 8c766a958..000000000 --- a/libX11/nls/ja.U90/XI18N_OBJS +++ /dev/null @@ -1,7 +0,0 @@ -# CATEGORY(XLC|XIM|OM) SHARED_LIBRARY_NAME FUNCTION_NAME -# -# XI18N objects table for ja.U90 locale -# -XLC common/xlibi18n _XlcGenericLoader # XLC_open -XIM common/ximcp _XimOpenIM _XimRegisterIMInstantiateCallback _XimUnRegisterIMInstantiateCallback # XIM_open XIM_register XIM_unregister -XOM common/xomGeneric _XomGenericOpenOM # XOM_open diff --git a/libX11/nls/ja.U90/XLC_LOCALE.pre b/libX11/nls/ja.U90/XLC_LOCALE.pre deleted file mode 100644 index 5d8fd3c0a..000000000 --- a/libX11/nls/ja.U90/XLC_LOCALE.pre +++ /dev/null @@ -1,151 +0,0 @@ -XCOMM Copyright 1995 by FUJITSU LIMITED -XCOMM This is source code modified by FUJITSU LIMITED under the Joint -XCOMM Development Agreement for the CDEnext PST. -XCOMM This is unpublished proprietary source code of FUJITSU LIMITED -XCOMM -XCOMM NLS-DB for ja_JP.U90 - -XCOMM -XCOMM XLC_CHARSET_DEFINE category -XCOMM -XLC_CHARSET_DEFINE -csd0 { - charset_name u90x03.1991-0 - side GL - length 2 - gc_number 94 - string_encoding False - sequence \x1b\x25\x28\x32 - encoding_name fujitsu.U90X03 -} - -csd1 { - charset_name u90x03.1991-0 - side GR - length 2 - gc_number 94 - string_encoding False - sequence \x1b\x25\x2f\x32 - encoding_name fujitsu.U90X03 -} -END XLC_CHARSET_DEFINE - -XCOMM -XCOMM XLC_FONTSET category -XCOMM -XLC_FONTSET -XCOMM fs0 class (7 bit ASCII) -fs0 { - charset { - name JISX0201.1976-0:GL - } - font { - primary JISX0201.1976-0:GL - substitute ISO8859-1:GL - vertical_rotate all - } -} -XCOMM fs1 class (Kanji) -fs1 { - charset { - name JISX0208.1983-0:GL - } - font { - primary fujitsu.u90x01.1991-0:GL -XCOMM primary JISX0208.1983-0:GL - substitute JISX0208.1983-0:GL; JISX0208.1983-0:GR;\ - JISX0208.1983-1:GL; JISX0208.1983-1:GR;\ - JISX0208.1990-0:GL; JISX0208.1990-0:GR;\ - u90x01.1991-0:GL - vertical_map u90x01.1991-0.2:GL,\ - [\x2122,\x2125]->\x7d21,[\x2131,\x2132]->\x7d25,\ - [\x213c,\x213e]->\x7d27,[\x2141,\x215b]->\x7d2a,\ - [\x2421,\x2421]->\x7d45,[\x2423,\x2423]->\x7d46,\ - [\x2425,\x2425]->\x7d47,[\x2427,\x2427]->\x7d48,\ - [\x2429,\x2429]->\x7d49,[\x2443,\x2443]->\x7d4a,\ - [\x2463,\x2463]->\x7d4b,[\x2465,\x2465]->\x7d4c,\ - [\x2467,\x2467]->\x7d4d,[\x246e,\x246e]->\x7d4e,\ - [\x2521,\x2521]->\x7d4f,[\x2523,\x2523]->\x7d50,\ - [\x2525,\x2525]->\x7d51,[\x2527,\x2527]->\x7d52,\ - [\x2529,\x2529]->\x7d53,[\x2543,\x2543]->\x7d54,\ - [\x2563,\x2563]->\x7d55,[\x2565,\x2565]->\x7d56,\ - [\x2567,\x2567]->\x7d57,[\x256e,\x256e]->\x7d58,\ - [\x2575,\x2576]->\x7d59,[\x2475,\x2476]->\x7d5b - } -} -XCOMM fs2 class (Half Kana) -fs2 { - charset { - name JISX0201.1976-0:GR - } - font { - primary JISX0201.1976-0:GR - vertical_rotate all - } -} -XCOMM fs3 class (JEF Kanji + User Defined Character) -fs3 { - charset { - name u90x03.1991-0:GR; u90x03.1991-0:GL - udc_area \x6521,\x787e - } - font { - primary fujitsu.u90x03.1991-0:GL - substitute u90x03.1991-0:GL;\ - JISX0208.1983-0:GL; JISX0208.1983-0:GR;\ - JISX0208.1983-1:GL; JISX0208.1983-1:GR;\ - JISX0208.1990-0:GL; JISX0208.1990-0:GR - } -} -END XLC_FONTSET - -XCOMM -XCOMM XLC_XLOCALE category -XCOMM -XLC_XLOCALE - -XCOMM encoding_name ja.euc -encoding_name ja_JP.U90 -mb_cur_max 3 -state_depend_encoding False - -wc_encoding_mask \x30000000 -wc_shift_bits 7 - - -XCOMM cs0 class -cs0 { - side GL:Default - length 1 - wc_encoding \x00000000 - ct_encoding JISX0201.1976-0:GL; ISO8859-1:GL -} - -XCOMM cs1 class -cs1 { - side GR:Default - length 2 - wc_encoding \x30000000 - ct_encoding JISX0208.1983-0:GL; JISX0208.1983-0:GR;\ - JISX0208.1983-1:GL; JISX0208.1983-1:GR -} - -XCOMM cs2 class -cs2 { - side GR - length 1 - mb_encoding <SS> \x8e - wc_encoding \x10000000 - ct_encoding JISX0201.1976-0:GR -} - -XCOMM cs3 class -cs3 { - side GR - length 2 - mb_encoding <SS> \x8f - wc_encoding \x20000000 - ct_encoding u90x03.1991-0:GR; u90x03.1991-0:GL -} - -END XLC_XLOCALE diff --git a/libX11/nls/ja_JP.UTF-8/Compose.pre b/libX11/nls/ja_JP.UTF-8/Compose.pre index e69de29bb..6c2c4114d 100644 --- a/libX11/nls/ja_JP.UTF-8/Compose.pre +++ b/libX11/nls/ja_JP.UTF-8/Compose.pre @@ -0,0 +1 @@ +include "X11_LOCALEDATADIR/en_US.UTF-8/Compose" diff --git a/libX11/nls/km_KH.UTF-8/Compose.pre b/libX11/nls/km_KH.UTF-8/Compose.pre new file mode 100644 index 000000000..77651d085 --- /dev/null +++ b/libX11/nls/km_KH.UTF-8/Compose.pre @@ -0,0 +1,8 @@ +include "X11_LOCALEDATADIR/en_US.UTF-8/Compose" + +# Khmer digraphs +<U17ff> : "ាំ" +<U17fe> : "ោះ" +<U17fd> : "េះ" +<U17fc> : "ុំ" +<U17fb> : "ុះ" diff --git a/libX11/nls/km_KH.UTF-8/XI18N_OBJS b/libX11/nls/km_KH.UTF-8/XI18N_OBJS new file mode 100644 index 000000000..f201bf435 --- /dev/null +++ b/libX11/nls/km_KH.UTF-8/XI18N_OBJS @@ -0,0 +1,8 @@ +# CATEGORY(XLC|XIM|OM) SHARED_LIBRARY_NAME FUNCTION_NAME +# +# XI18N objects table for euro locales +# +XLC common/xlcUTF8Load _XlcUtf8Loader # XLC_open +XOM common/xomLTRTTB _XomGenericOpenOM # XOM_open +XIM common/xiiimp _SwitchOpenIM # XIM_open +XIM common/xiiimp _XimpLocalOpenIM # XIM_open diff --git a/libX11/nls/ja.S90/Compose.pre b/libX11/nls/km_KH.UTF-8/XLC_LOCALE.pre index e69de29bb..e69de29bb 100644 --- a/libX11/nls/ja.S90/Compose.pre +++ b/libX11/nls/km_KH.UTF-8/XLC_LOCALE.pre diff --git a/libX11/nls/ko_KR.UTF-8/Compose.pre b/libX11/nls/ko_KR.UTF-8/Compose.pre index e69de29bb..6c2c4114d 100644 --- a/libX11/nls/ko_KR.UTF-8/Compose.pre +++ b/libX11/nls/ko_KR.UTF-8/Compose.pre @@ -0,0 +1 @@ +include "X11_LOCALEDATADIR/en_US.UTF-8/Compose" diff --git a/libX11/nls/locale.alias.pre b/libX11/nls/locale.alias.pre index 7b3546099..11d93f26e 100644 --- a/libX11/nls/locale.alias.pre +++ b/libX11/nls/locale.alias.pre @@ -17,9 +17,11 @@ Cextend.en: en_US.ISO8859-1 English_United-States.437: C C.UTF-8: en_US.UTF-8 XCOMM a3 is not an ISO 639 language code, but in Cyrillic, "Z" looks like "3". -a3: a3_AZ.KOI8-C -a3_AZ: a3_AZ.KOI8-C -a3_AZ.koi8c: a3_AZ.KOI8-C +a3: az_AZ.KOI8-C +a3_AZ: az_AZ.KOI8-C +a3_AZ.koi8c: az_AZ.KOI8-C +a3_AZ.KOI-C: az_AZ.KOI8-C +a3_AZ.UTF-8: az_AZ.UTF-8 af: af_ZA.ISO8859-1 af_ZA: af_ZA.ISO8859-1 af_ZA.iso88591: af_ZA.ISO8859-1 @@ -50,6 +52,7 @@ ar_EG: ar_EG.ISO8859-6 ar_EG.iso88596: ar_EG.ISO8859-6 ar_EG.ISO-8859-6: ar_EG.ISO8859-6 ar_EG.utf8: ar_EG.UTF-8 +ar_IN: ar_IN.UTF-8 ar_IN.utf8: ar_IN.UTF-8 ar_IQ: ar_IQ.ISO8859-6 ar_IQ.iso88596: ar_IQ.ISO8859-6 @@ -100,6 +103,7 @@ ar_TN.iso88596: ar_TN.ISO8859-6 ar_TN.ISO-8859-6: ar_TN.ISO8859-6 ar_TN.utf8: ar_TN.UTF-8 as: as_IN.UTF-8 +as_IN: as_IN.UTF-8 as_IN.utf8: as_IN.UTF-8 ar_YE: ar_YE.ISO8859-6 ar_YE.iso88596: ar_YE.ISO8859-6 @@ -128,7 +132,9 @@ bg_BG.iso88595: bg_BG.ISO8859-5 bg_BG.ISO-8859-5: bg_BG.ISO8859-5 bg_BG.koi8r: bg_BG.KOI8-R be_BG.utf8: bg_BG.UTF-8 +bn_IN: bn_IN.UTF-8 bn_IN.utf8: bn_IN.UTF-8 +bo_IN: bo_IN.UTF-8 bo_IN.utf8: bo_IN.UTF-8 br: br_FR.ISO8859-1 br_FR: br_FR.ISO8859-1 @@ -188,7 +194,7 @@ cs_CS: cs_CZ.ISO8859-2 cs_CS.ISO8859-2: cs_CZ.ISO8859-2 cs_CZ: cs_CZ.ISO8859-2 cs_CZ.iso88592: cs_CZ.ISO8859-2 -cs_CS.iso8859-2: cs_CS.ISO8859-2 +cs_CS.iso8859-2: cs_CZ.ISO8859-2 cs_CZ.ISO-8859-2: cs_CZ.ISO8859-2 cs_CZ.ISO_8859-2: cs_CZ.ISO8859-2 cs_CZ.utf8: cs_CZ.UTF-8 @@ -297,6 +303,7 @@ en_BE: en_BE.ISO8859-1 en_BE@euro: en_BE.ISO8859-15 en_BE.utf8: en_BE.UTF-8 en_BW: en_BW.ISO8859-1 +en_BW.utf8: en_BW.UTF-8 en_BW.iso88591: en_BW.ISO8859-1 en_BW.ISO-8859-1: en_BW.ISO8859-1 en_CA: en_CA.ISO8859-1 @@ -304,6 +311,7 @@ en_CA.iso88591: en_CA.ISO8859-1 en_CA.ISO-8859-1: en_CA.ISO8859-1 en_CA.ISO_8859-1: en_CA.ISO8859-1 en_CA.utf8: en_CA.UTF-8 +en_DL.utf8: en_DL.UTF-8 en_GB: en_GB.ISO8859-1 en_GB.88591: en_GB.ISO8859-1 en_GB.88591.en: en_GB.ISO8859-1 @@ -319,6 +327,7 @@ ENG_GB.8859.in: en_GB.ISO8859-1 en_HK: en_HK.ISO8859-1 en_HK.iso88591: en_HK.ISO8859-1 en_HK.ISO-8859-1: en_HK.ISO8859-1 +en_HK.utf8: en_HK.UTF-8 en_IE: en_IE.ISO8859-1 en_IE.iso88591: en_IE.ISO8859-1 en_IE.ISO-8859-1: en_IE.ISO8859-1 @@ -328,15 +337,18 @@ en_IE.ISO-8859-15@euro: en_IE.ISO8859-15 en_IE@euro: en_IE.ISO8859-15 en_IE.UTF-8@euro: en_IE.UTF-8 en_IE.utf8: en_IE.UTF-8 +en_IN.utf8: en_IN.UTF-8 en_IN: en_IN.ISO8859-1 en_NZ: en_NZ.ISO8859-1 en_NZ.iso88591: en_NZ.ISO8859-1 en_NZ.ISO-8859-1: en_NZ.ISO8859-1 en_NZ.utf8: en_NZ.UTF-8 en_PH: en_PH.ISO8859-1 +en_PH.utf8: en_PH.UTF-8 en_PH.iso88591: en_PH.ISO8859-1 en_PH.ISO-8859-1: en_PH.ISO8859-1 en_SG: en_SG.ISO8859-1 +en_SG.utf8: en_SG.UTF-8 en_SG.iso88591: en_SG.ISO8859-1 en_SG.ISO-8859-1: en_SG.ISO8859-1 en_US: en_US.ISO8859-1 @@ -362,6 +374,7 @@ en_ZA.iso885915: en_ZA.ISO8859-15 en_ZA.ISO-8859-15: en_ZA.ISO8859-15 en_ZA.utf8: en_ZA.UTF-8 en_ZW: en_ZW.ISO8859-1 +en_ZW.utf8: en_ZS.UTF-8 en_ZW.iso88591: en_ZW.ISO8859-1 en_ZW.ISO-8859-1: en_ZW.ISO8859-1 eo: eo_XX.ISO8859-3 @@ -602,6 +615,7 @@ gl_ES.ISO-8859-15@euro: gl_ES.ISO8859-15 gl_ES@euro: gl_ES.ISO8859-15 gl_ES.UTF-8@euro: gl_ES.UTF-8 gl_ES.utf8: gl_ES.UTF-8 +gu_IN: gu_IN.UTF-8 gu_IN.utf8: gu_IN.UTF-8 gv: gv_GB.ISO8859-1 gv_GB: gv_GB.ISO8859-1 @@ -629,6 +643,7 @@ hi_IN.isciidev: hi_IN.ISCII-DEV hi_IN.utf8: hi_IN.UTF-8 HI_IN.UTF-8: hi_IN.UTF-8 hne: hne_IN.UTF-8 +hne_IN: hne_IN.UTF-8 hne_IN.utf8: hne_IN.UTF-8 hr: hr_HR.ISO8859-2 hr_HR: hr_HR.ISO8859-2 @@ -674,6 +689,8 @@ it_IT.ISO-8859-15@euro: it_IT.ISO8859-15 it_IT@euro: it_IT.ISO8859-15 it_IT.utf8: it_IT.UTF-8 it_IT.UTF-8@euro: it_IT.UTF-8 +XCOMM NUNACOM is an encoding for the Inuktitut syllabics +XCOMM we have little else on this encoding. iu: iu_CA.NUNACOM-8 iu_CA: iu_CA.NUNACOM-8 iu_CA.nunacom8: iu_CA.NUNACOM-8 @@ -684,13 +701,7 @@ iw_IL: he_IL.ISO8859-8 Iw_IL: he_IL.ISO8859-8 iw_IL.iso88598: he_IL.ISO8859-8 iw_IL.ISO-8859-8: he_IL.ISO8859-8 -#ifndef __uxp__ ja_JP: ja_JP.eucJP -#else /* __uxp__ */ -ja_JP: ja_JP.U90 -ja_JP.U90: ja_JP.U90 -ja_JP.S90: ja_JP.S90 -#endif /* __uxp__ */ ja: ja_JP.eucJP ja.JIS: ja_JP.JIS7 ja.SJIS: ja_JP.SJIS @@ -721,7 +732,10 @@ kl_GL.iso88591: kl_GL.ISO8859-1 kl_GL.ISO-8859-1: kl_GL.ISO8859-1 kl_GL.iso885915: kl_GL.ISO8859-15 kl_GL.utf8: kl_GL.UTF-8 +km_KH: mk_KH.UTF-8 +km_KH.utf8: mk_KH.UTF-8 kn: kn_IN.UTF-8 +kn_IN: kn_IN.UTF-8 kn_IN.utf8: kn_IN.UTF-8 ko: ko_KR.eucKR ko.UTF-8: ko_KR.UTF-8 @@ -734,6 +748,7 @@ ko_KR.euckr: ko_KR.eucKR ko_KR.utf8: ko_KR.UTF-8 KO_KR.UTF-8: ko_KR.UTF-8 ks: ks_IN.UTF-8 +ks_IN: ks_IN.UTF-8 ks_IN.utf8: ks_IN.UTF-8 ks_IN@devanagari: ks_IN@devanagari.UTF-8 ks_IN@devanagari.utf8: ks_IN@devanagari.UTF-8 @@ -748,6 +763,7 @@ kw_GB.ISO-8859-15: kw_GB.ISO8859-15 ky: ky_KG.UTF-8 ky_KG: ky_KG.UTF-8 ky_KG.UTF-8: ky_KG.UTF-8 +ky_KG.utf8: ky_KG.UTF-8 lo: lo_LA.MULELAO-1 lo_LA: lo_LA.MULELAO-1 lo_LA.cp1133: lo_LA.IBM-CP1133 @@ -778,6 +794,7 @@ lv_LV.ISO-8859-13: lv_LV.ISO8859-13 lv_LV.ISO_8859-13: lv_LV.ISO8859-13 lv_LV.utf8: lv_LV.UTF-8 mai: mai_IN.UTF-8 +mai_IN: mai_IN.UTF-8 mai_IN.utf8: mai_IN.UTF-8 mi: mi_NZ.ISO8859-1 mi_NZ: mi_NZ.ISO8859-1 @@ -792,6 +809,7 @@ mk_MK.microsoft-cp1251: mk_MK.CP1251 mk_MK.MICROSOFT-CP1251: mk_MK.CP1251 mk_MK.utf8: mk_MK.UTF-8 ml: ml_IN.UTF-8 +ml_IN: ml_IN.UTF-8 ml_IN.utf8: ml_IN.UTF-8 mr: mr_IN.UTF-8 mr_IN: mr_IN.UTF-8 @@ -811,6 +829,7 @@ nb_NO.ISO-8859-1: nb_NO.ISO8859-1 nb_NO.iso885915: nb_NO.ISO8859-15 nb_NO.ISO-8859-15: nb_NO.ISO8859-15 nb_NO.utf8: nb_NO.UTF-8 +ne_NP: ne_NP.UTF-8 ne_NP.utf8: ne_NP.UTF-8 nl: nl_NL.ISO8859-1 nl.ISO8859-15: nl_NL.ISO8859-15 @@ -880,8 +899,10 @@ oc_FR.iso885915: oc_FR.ISO8859-15 oc_FR.ISO-8859-15: oc_FR.ISO8859-15 oc_FR@euro: oc_FR.ISO8859-15 or: or_IN.UTF-8 +or_IN: or_IN.UTF-8 or_IN.utf8: or_IN.UTF-8 pa: pa_IN.UTF-8 +pa_IN: pa_IN.UTF-8 pa_IN.utf8: pa_IN.UTF-8 pa_PK.utf8: pa_PK.UTF-8 pd: pd_US.ISO8859-1 @@ -961,7 +982,8 @@ rw_RW.ISO-8859-1: rw_RW.ISO8859-1 rw_RW.utf8: rw_RW.UTF-8 sd: sd_IN.UTF-8 sd_IN.utf8: sd_IN.UTF-8 -sd: sd_IN@devanagari.UTF-8 +sd@devanagari: sd_IN@devanagari.UTF-8 +sd_IN@devanagari: sd_IN@devanagari.UTF-8 sd_IN@devanagari.utf8: sd_IN@devanagari.UTF-8 se_NO: se_NO.UTF-8 se_NO.utf8: se_NO.UTF-8 @@ -1000,11 +1022,11 @@ sr@cyrillic: sr_RS.UTF-8 sr_YU@cyrillic: sr_RS.UTF-8 sr_YU.utf8: sr_RS.UTF-8 sr_YU.UTF-8@cyrillic: sr_RS.UTF-8 -sr_CS: sr_RS.UTF-8 -sr@Latn: sr_RS.UTF-8@latin -sr_CS@Latn: sr_RS.UTF-8@latin -sr_CS.utf8: sr_RS.UTF-8 -sr_CS.UTF-8@Latn: sr_RS.UTF-8@latin +sr_CS: sr_CS.UTF-8 +sr@Latn: sr_CS.UTF-8@latin +sr_CS@Latn: sr_CS.UTF-8@latin +sr_CS.utf8: sr_CS.UTF-8 +sr_CS.UTF-8@Latn: sr_CS.UTF-8@latin sr_RS: sr_RS.UTF-8 sr@latin: sr_RS.UTF-8@latin sr_RS@latin: sr_RS.UTF-8@latin @@ -1048,6 +1070,7 @@ ta_IN: ta_IN.TSCII-0 ta_IN.tscii: ta_IN.TSCII-0 ta_IN.tscii0: ta_IN.TSCII-0 te: te_IN.UTF-8 +te.UTF-8: te_IN.UTF-8 te_IN.utf8: te_IN.UTF-8 tg: tg_TJ.KOI8-C tg_TJ: tg_TJ.KOI8-C @@ -1092,6 +1115,7 @@ uk_UA.microsoft-cp1251: uk_UA.CP1251 uk_UA.MICROSOFT-CP1251: uk_UA.CP1251 uk_UA.utf8: uk_UA.UTF-8 ur: ur_IN.UTF-8 +ur_IN: ur_IN.UTF-8 ur_IN.utf8: ur_IN.UTF-8 ur: ur_PK.CP1256 ur_PK: ur_PK.CP1256 @@ -1153,6 +1177,10 @@ zh_HK.Big5_hkscs: zh_HK.big5hkscs zh_HK.Big5HKSCS: zh_HK.big5hkscs zh_HK.BIG5-HKSCS: zh_HK.big5hkscs zh_HK.BIG5_HKSCS: zh_HK.big5hkscs +zh_HK.Big5-HKSCS: zh_HK.big5hkscs +zh_HK.big5-hkscs: zh_HK.big5hkscs +zh_HK.Big5-HKSCS: zh_HK.big5hkscs +zh_HK.Big5HKSCS: zh_HK.big5hkscs zh_HK.Big5: zh_HK.big5 zh_HK.utf8: zh_HK.UTF-8 ZH_HK.UTF-8: zh_HK.UTF-8 @@ -1210,8 +1238,8 @@ german: de_DE.ISO8859-1 german.iso88591: de_CH.ISO8859-1 greek: el_GR.ISO8859-7 greek.iso88597: el_GR.ISO8859-7 -hebrew: iw_IL.ISO8859-8 -hebrew.iso88598: iw_IL.ISO8859-8 +hebrew: he_IL.ISO8859-8 +hebrew.iso88598: he_IL.ISO8859-8 hrvatski: hr_HR.ISO8859-2 hungarian: hu_HU.ISO8859-2 icelandic.iso88591: is_IS.ISO8859-1 @@ -1254,102 +1282,102 @@ iso_8859_15: en_US.ISO8859-15 #ifdef WIN32 XCOMM Microsoft Windows/NT 4.0 SP3 XCOMM parser doesn't grok embedded spaces in locale name -Afrikaans_South Africa.1252: af_ZA.iso8859-1 -Arabic_Bahrain.1256: ar_BH.iso8859-6 -Arabic_Algeria.1256: ar_DZ.iso8859-6 -Arabic_Egypt.1256: ar_EG.iso8859-6 -Arabic_Iraq.1256: ar_IQ.iso8859-6 -Arabic_Jordan.1256: ar_JO.iso8859-6 -Arabic_Kuwait.1256: ar_KW.iso8859-6 -Arabic_Lebanon.1256: ar_LB.iso8859-6 -Arabic_Libya.1256: ar_LY.iso8859-6 -Arabic_Morocco.1256: ar_MA.iso8859-6 -Arabic_Oman.1256: ar_OM.iso8859-6 -Arabic_Qatar.1256: ar_QA.iso8859-6 -Arabic_Saudi Arabia.1256: ar_SA.iso8859-6 -Arabic_Tunisia.1256: ar_TN.iso8859-6 -Arabic_Yemen.1256: ar_YE.iso8859-6 -Belarusian_Belarus.1251: be_BY.iso8859-5 -Bulgarian_Bulgaria.1251: bg_BG.iso8859-5 -Catalan_Andorra.1252: ca_AD.iso8859-1 -Catalan_Spain.1252: ca_ES.iso8859-1 -Catalan_France.1252: ca_FR.iso8859-1 -Catalan_Italy.1252: ca_IT.iso8859-1 -Czech_Czech Republic.1250: cs_CZ.iso8859-2 -Danish_Denmark.1252: da_DK.iso8859-1 -German_Austria.1252: de_AT.iso8859-1 -German_Switzerland.1252: de_CH.iso8859-1 -German_Germany.1252: de_DE.iso8859-1 -German_Liechtenstein.1252: de_LI.iso8859-1 -German_Luxembourg.1252: de_LU.iso8859-1 -Greek_Greece.1253: el_GR.iso8859-7 -English_Australia.1252: en_AU.iso8859-1 -English_Belize.1252: en_BZ.iso8859-1 -English_Canada.1252: en_CA.iso8859-1 -English_Ireland.1252: en_IE.iso8859-1 -English_Jamaica.1252: en_JM.iso8859-1 -English_New Zealand.1252: en_NZ.iso8859-1 -English_Trinidad y Tobago.1252: en_TT.iso8859-1 -English_United Kingdom.1252: en_UK.iso8859-1 -English_United States.1252: en_US.iso8859-1 -English_South Africa.1252: en_ZA.iso8859-1 -Spanish_Argentina.1252: es_AR.iso8859-1 -Spanish_Bolivia.1252: es_BO.iso8859-1 -Spanish_Chile.1252: es_CL.iso8859-1 -Spanish_Colombia.1252: es_CO.iso8859-1 -Spanish_Costa Rica.1252: es_CR.iso8859-1 -Spanish_Dominican Republic.1252: es_DO.iso8859-1 -Spanish_Ecuador.1252: es_EC.iso8859-1 -Spanish - Modern Sort_Spain.1252: es_ES.iso8859-1 -Spanish - Traditional Sort_Spain.1252: es_ES.iso8859-1 -Spanish_Guatemala.1252: es_GT.iso8859-1 -Spanish_Honduras.1252: es_HN.iso8859-1 -Spanish_Mexican.1252: es_MX.iso8859-1 -Spanish_Nicaragua.1252: es_NI.iso8859-1 -Spanish_Panama.1252: es_PA.iso8859-1 -Spanish_Paraguay.1252: es_PY.iso8859-1 -Spanish_Peru.1252: es_PE.iso8859-1 -Spanish_Puerto Rico.1252: es_PR.iso8859-1 -Spanish_El Salvador.1252: es_SV.iso8859-1 -Spanish_Uruguay.1252: es_UY.iso8859-1 -Spanish_Venezuela.1252: es_VE.iso8859-1 -Estonian_Estonia.1257: et_EE.iso8859-13 -Basque_Spain.1252: eu_ES.iso8859-1 -Finnish_Finland.1252: fi_FI.iso8859-1 -French_Belgium.1252: fr_BE.iso8859-1 -French_Canada.1252: fr_CA.iso8859-1 -French_Switzerland.1252: fr_CH.iso8859-1 -French_France.1252: fr_FR.iso8859-1 -French_Luxembourg.1252: fr_LU.iso8859-1 -Faeroese_Faeroe Islands.1252: fo_FO.iso8859-1 -Hebrew_Israel.1255: he_IL.iso8859-8 -Croatian_Croatia.1250: hr_HR.iso8859-2 -Hungarian_Hungary.1250: hu_HU.iso8859-2 -Indonesian_Indonesia.1252: id_ID.iso8859-1 -Icelandic_Iceland.1252: is_IS.iso8859-1 -Italian_Switzerland.1252: it_CH.iso8859-1 -Italian_Italy.1252: it_IT.iso8859-1 +Afrikaans_South Africa.1252: af_ZA.ISO8859-1 +Arabic_Bahrain.1256: ar_BH.ISO8859-6 +Arabic_Algeria.1256: ar_DZ.ISO8859-6 +Arabic_Egypt.1256: ar_EG.ISO8859-6 +Arabic_Iraq.1256: ar_IQ.ISO8859-6 +Arabic_Jordan.1256: ar_JO.ISO8859-6 +Arabic_Kuwait.1256: ar_KW.ISO8859-6 +Arabic_Lebanon.1256: ar_LB.ISO8859-6 +Arabic_Libya.1256: ar_LY.ISO8859-6 +Arabic_Morocco.1256: ar_MA.ISO8859-6 +Arabic_Oman.1256: ar_OM.ISO8859-6 +Arabic_Qatar.1256: ar_QA.ISO8859-6 +Arabic_Saudi Arabia.1256: ar_SA.ISO8859-6 +Arabic_Tunisia.1256: ar_TN.ISO8859-6 +Arabic_Yemen.1256: ar_YE.ISO8859-6 +Belarusian_Belarus.1251: be_BY.ISO8859-5 +Bulgarian_Bulgaria.1251: bg_BG.ISO8859-5 +Catalan_Andorra.1252: ca_AD.ISO8859-1 +Catalan_Spain.1252: ca_ES.ISO8859-1 +Catalan_France.1252: ca_FR.ISO8859-1 +Catalan_Italy.1252: ca_IT.ISO8859-1 +Czech_Czech Republic.1250: cs_CZ.ISO8859-2 +Danish_Denmark.1252: da_DK.ISO8859-1 +German_Austria.1252: de_AT.ISO8859-1 +German_Switzerland.1252: de_CH.ISO8859-1 +German_Germany.1252: de_DE.ISO8859-1 +German_Liechtenstein.1252: de_LI.ISO8859-1 +German_Luxembourg.1252: de_LU.ISO8859-1 +Greek_Greece.1253: el_GR.ISO8859-7 +English_Australia.1252: en_AU.ISO8859-1 +English_Belize.1252: en_BZ.ISO8859-1 +English_Canada.1252: en_CA.ISO8859-1 +English_Ireland.1252: en_IE.ISO8859-1 +English_Jamaica.1252: en_JM.ISO8859-1 +English_New Zealand.1252: en_NZ.ISO8859-1 +English_Trinidad y Tobago.1252: en_TT.ISO8859-1 +English_United Kingdom.1252: en_UK.ISO8859-1 +English_United States.1252: en_US.ISO8859-1 +English_South Africa.1252: en_ZA.ISO8859-1 +Spanish_Argentina.1252: es_AR.ISO8859-1 +Spanish_Bolivia.1252: es_BO.ISO8859-1 +Spanish_Chile.1252: es_CL.ISO8859-1 +Spanish_Colombia.1252: es_CO.ISO8859-1 +Spanish_Costa Rica.1252: es_CR.ISO8859-1 +Spanish_Dominican Republic.1252: es_DO.ISO8859-1 +Spanish_Ecuador.1252: es_EC.ISO8859-1 +Spanish - Modern Sort_Spain.1252: es_ES.ISO8859-1 +Spanish - Traditional Sort_Spain.1252: es_ES.ISO8859-1 +Spanish_Guatemala.1252: es_GT.ISO8859-1 +Spanish_Honduras.1252: es_HN.ISO8859-1 +Spanish_Mexican.1252: es_MX.ISO8859-1 +Spanish_Nicaragua.1252: es_NI.ISO8859-1 +Spanish_Panama.1252: es_PA.ISO8859-1 +Spanish_Paraguay.1252: es_PY.ISO8859-1 +Spanish_Peru.1252: es_PE.ISO8859-1 +Spanish_Puerto Rico.1252: es_PR.ISO8859-1 +Spanish_El Salvador.1252: es_SV.ISO8859-1 +Spanish_Uruguay.1252: es_UY.ISO8859-1 +Spanish_Venezuela.1252: es_VE.ISO8859-1 +Estonian_Estonia.1257: et_EE.ISO8859-13 +Basque_Spain.1252: eu_ES.ISO8859-1 +Finnish_Finland.1252: fi_FI.ISO8859-1 +French_Belgium.1252: fr_BE.ISO8859-1 +French_Canada.1252: fr_CA.ISO8859-1 +French_Switzerland.1252: fr_CH.ISO8859-1 +French_France.1252: fr_FR.ISO8859-1 +French_Luxembourg.1252: fr_LU.ISO8859-1 +Faeroese_Faeroe Islands.1252: fo_FO.ISO8859-1 +Hebrew_Israel.1255: he_IL.ISO8859-8 +Croatian_Croatia.1250: hr_HR.ISO8859-2 +Hungarian_Hungary.1250: hu_HU.ISO8859-2 +Indonesian_Indonesia.1252: id_ID.ISO8859-1 +Icelandic_Iceland.1252: is_IS.ISO8859-1 +Italian_Switzerland.1252: it_CH.ISO8859-1 +Italian_Italy.1252: it_IT.ISO8859-1 Japanese_Japan.932: ja_JP.SJIS Korean_Korea.949: ko_KR.EUC -Lithuanian_Lithuania.1257: lt_LT.iso8859-13 -Latvian_Latvia.1257: lv_LV.iso8859-13 -Dutch_Belgium.1252: nl_BE.iso8859-1 -Dutch_Netherlands.1252: nl_NL.iso8859-1 -Norwegian (Nynorsk)_Norway.1252: no_NO.iso8859-1 -Norwegian (Bokml)_Norway.1252: no_NO.iso8859-1 -Polish_Poland.1250: pl_PL.iso8859-2 -Portuguese_Brazil.1252: pt_BR.iso8859-1 -Portuguese_Portugal.1252: pt_PT.iso8859-1 -Romanian_Romania.1250: ro_RO.iso8859-2 -Russian_Russia.1251: ru_RU.iso8859-5 -Slovak_Slovakia.1250: sk_SK.iso8859-2 -Slovene_Slovenia.1250: sl_SI.iso8859-2 -Albanian_Albania.1250: sq_AL.iso8859-2 +Lithuanian_Lithuania.1257: lt_LT.ISO8859-13 +Latvian_Latvia.1257: lv_LV.ISO8859-13 +Dutch_Belgium.1252: nl_BE.ISO8859-1 +Dutch_Netherlands.1252: nl_NL.ISO8859-1 +Norwegian (Nynorsk)_Norway.1252: no_NO.ISO8859-1 +Norwegian (Bokml)_Norway.1252: no_NO.ISO8859-1 +Polish_Poland.1250: pl_PL.ISO8859-2 +Portuguese_Brazil.1252: pt_BR.ISO8859-1 +Portuguese_Portugal.1252: pt_PT.ISO8859-1 +Romanian_Romania.1250: ro_RO.ISO8859-2 +Russian_Russia.1251: ru_RU.ISO8859-5 +Slovak_Slovakia.1250: sk_SK.ISO8859-2 +Slovene_Slovenia.1250: sl_SI.ISO8859-2 +Albanian_Albania.1250: sq_AL.ISO8859-2 Serbian (Latin)_Serbia.1250: sr_RS.UTF-8@latin -Swedish_Finland.1252: sv_FI.iso8859-1 -Swedish_Sweden.1252: sv_SE.iso8859-1 -Turkish_Turkey.1254: tr_TR.iso8859-9 -Ukrainian_Ukraine.1251: uk_UA.iso8859-5 +Swedish_Finland.1252: sv_FI.ISO8859-1 +Swedish_Sweden.1252: sv_SE.ISO8859-1 +Turkish_Turkey.1254: tr_TR.ISO8859-9 +Ukrainian_Ukraine.1251: uk_UA.ISO8859-5 Chinese(PRC)_People's Republic of China.936: zh_CN.EUC Chinese(PRC)_Hong Kong.950: zh_HK.EUC Chinese(Singapore)_Signapore.936: zh_SG.EUC @@ -1358,9 +1386,5 @@ Chinese(Taiwan)_Taiwan.950: zh_TW.EUC XCOMM Other miscellaneous locale names ISO8859-1: en_US.ISO8859-1 ISO-8859-1: en_US.ISO8859-1 -#ifndef __uxp__ japan: ja_JP.eucJP -#else -japan: ja_JP.U90 -#endif Japanese-EUC: ja_JP.eucJP diff --git a/libX11/nls/locale.dir.pre b/libX11/nls/locale.dir.pre index e0d9ef7ef..4ec929745 100644 --- a/libX11/nls/locale.dir.pre +++ b/libX11/nls/locale.dir.pre @@ -24,6 +24,7 @@ iso8859-6/XLC_LOCALE: ar_SD.ISO8859-6 iso8859-6/XLC_LOCALE: ar_SY.ISO8859-6 iso8859-6/XLC_LOCALE: ar_TN.ISO8859-6 iso8859-6/XLC_LOCALE: ar_YE.ISO8859-6 +iso8859-6/XLC_LOCALE: ar_AE.ISO8859-6 iso8859-9e/XLC_LOCALE: az_AZ.ISO8859-9E koi8-c/XLC_LOCALE: az_AZ.KOI8-C iso8859-5/XLC_LOCALE: be_BY.ISO8859-5 @@ -47,7 +48,6 @@ iso8859-2/XLC_LOCALE: cs_CZ.ISO8859-2 iso8859-1/XLC_LOCALE: cy_GB.ISO8859-1 iso8859-14/XLC_LOCALE: cy_GB.ISO8859-14 iso8859-15/XLC_LOCALE: cy_GB.ISO8859-15 -iso8859-2/XLC_LOCALE: cz_CZ.ISO8859-2 iso8859-1/XLC_LOCALE: da_DK.ISO8859-1 iso8859-15/XLC_LOCALE: da_DK.ISO8859-15 iso8859-1/XLC_LOCALE: de_AT.ISO8859-1 @@ -59,15 +59,19 @@ iso8859-15/XLC_LOCALE: de_CH.ISO8859-15 iso8859-1/XLC_LOCALE: de_DE.ISO8859-1 iso8859-15/XLC_LOCALE: de_DE.ISO8859-15 iso8859-1/XLC_LOCALE: de_LI.ISO8859-1 +iso8859-1/XLC_LOCALE: de_LI.ISO8859-15 iso8859-1/XLC_LOCALE: de_LU.ISO8859-1 iso8859-15/XLC_LOCALE: de_LU.ISO8859-15 -iso8859-7/XLC_LOCALE: el_GR.ISO8859-7 +iso8859-7/XLC_LOCALE: el_GR.ISO8859-7 +iso8859-4/XLC_LOCALE: ee_EE.ISO8859-4 iso8859-15/XLC_LOCALE: el_GR.ISO8859-15 iso8859-1/XLC_LOCALE: en_AU.ISO8859-1 iso8859-1/XLC_LOCALE: en_BE.ISO8859-1 +iso8859-15/XLC_LOCALE: en_BE.ISO8859-15 iso8859-1/XLC_LOCALE: en_BZ.ISO8859-1 iso8859-1/XLC_LOCALE: en_BW.ISO8859-1 iso8859-1/XLC_LOCALE: en_CA.ISO8859-1 +iso8859-1/XLC_LOCALE: en_EN.ISO8859-1 iso8859-1/XLC_LOCALE: en_GB.ISO8859-1 iso8859-15/XLC_LOCALE: en_GB.ISO8859-15 iso8859-1/XLC_LOCALE: en_HK.ISO8859-1 @@ -85,6 +89,7 @@ iso8859-1/XLC_LOCALE: en_US.ISO8859-1 iso8859-15/XLC_LOCALE: en_US.ISO8859-15 iso8859-1/XLC_LOCALE: en_ZA.ISO8859-1 iso8859-15/XLC_LOCALE: en_ZA.ISO8859-15 +iso8859-1/XLC_LOCALE: en_ZW.ISO8859-1 iso8859-3/XLC_LOCALE: eo_EO.ISO8859-3 iso8859-3/XLC_LOCALE: eo_XX.ISO8859-3 iso8859-1/XLC_LOCALE: es_AR.ISO8859-1 @@ -101,13 +106,19 @@ iso8859-1/XLC_LOCALE: es_HN.ISO8859-1 iso8859-1/XLC_LOCALE: es_MX.ISO8859-1 iso8859-1/XLC_LOCALE: es_NI.ISO8859-1 iso8859-1/XLC_LOCALE: es_PA.ISO8859-1 +iso8859-15/XLC_LOCALE: es_PA.ISO8859-15 iso8859-1/XLC_LOCALE: es_PE.ISO8859-1 +iso8859-15/XLC_LOCALE: es_PE.ISO8859-15 iso8859-1/XLC_LOCALE: es_PR.ISO8859-1 iso8859-1/XLC_LOCALE: es_PY.ISO8859-1 +iso8859-15/XLC_LOCALE: es_PY.ISO8859-15 iso8859-1/XLC_LOCALE: es_SV.ISO8859-1 +iso8859-15/XLC_LOCALE: es_SV.ISO8859-15 iso8859-1/XLC_LOCALE: es_US.ISO8859-1 iso8859-1/XLC_LOCALE: es_UY.ISO8859-1 +iso8859-15/XLC_LOCALE: es_UY.ISO8859-15 iso8859-1/XLC_LOCALE: es_VE.ISO8859-1 +iso8859-15/XLC_LOCALE: es_VE.ISO8859-15 iso8859-1/XLC_LOCALE: et_EE.ISO8859-1 iso8859-4/XLC_LOCALE: et_EE.ISO8859-4 iso8859-13/XLC_LOCALE: et_EE.ISO8859-13 @@ -147,9 +158,11 @@ iso8859-2/XLC_LOCALE: hr_HR.ISO8859-2 iso8859-2/XLC_LOCALE: hu_HU.ISO8859-2 armscii-8/XLC_LOCALE: hy_AM.ARMSCII-8 iso8859-1/XLC_LOCALE: id_ID.ISO8859-1 +iso8859-1/XLC_LOCALE: id_ID.ISO8859-15 iso8859-1/XLC_LOCALE: is_IS.ISO8859-1 iso8859-15/XLC_LOCALE: is_IS.ISO8859-15 iso8859-1/XLC_LOCALE: it_CH.ISO8859-1 +iso8859-15/XLC_LOCALE: it_CH.ISO8859-15 iso8859-1/XLC_LOCALE: it_IT.ISO8859-1 iso8859-15/XLC_LOCALE: it_IT.ISO8859-15 ja/XLC_LOCALE: ja_JP.eucJP @@ -158,6 +171,7 @@ ja.JIS/XLC_LOCALE: ja_JP.JIS7 georgian-academy/XLC_LOCALE: ka_GE.GEORGIAN-ACADEMY georgian-ps/XLC_LOCALE: ka_GE.GEORGIAN-PS iso8859-1/XLC_LOCALE: kl_GL.ISO8859-1 +iso8859-15/XLC_LOCALE: kl_GL.ISO8859-15 ko/XLC_LOCALE: ko_KR.eucKR iso8859-1/XLC_LOCALE: kw_GB.ISO8859-1 iso8859-14/XLC_LOCALE: kw_GB.ISO8859-14 @@ -190,16 +204,21 @@ iso8859-1/XLC_LOCALE: ny_NO.ISO8859-15 iso8859-1/XLC_LOCALE: oc_FR.ISO8859-1 iso8859-15/XLC_LOCALE: oc_FR.ISO8859-15 iso8859-1/XLC_LOCALE: pd_DE.ISO8859-1 +iso8859-15/XLC_LOCALE: pd_DE.ISO8859-15 +iso8859-1/XLC_LOCALE: pd_US.ISO8859-1 +iso8859-15/XLC_LOCALE: pd_US.ISO8859-15 iso8859-1/XLC_LOCALE: ph_PH.ISO8859-1 iso8859-2/XLC_LOCALE: pl_PL.ISO8859-2 iso8859-1/XLC_LOCALE: pp_AN.ISO8859-1 iso8859-1/XLC_LOCALE: pt_BR.ISO8859-1 +iso8859-15/XLC_LOCALE: pt_BR.ISO8859-15 iso8859-1/XLC_LOCALE: pt_PT.ISO8859-1 iso8859-15/XLC_LOCALE: pt_PT.ISO8859-15 iso8859-2/XLC_LOCALE: ro_RO.ISO8859-2 iso8859-5/XLC_LOCALE: ru_RU.ISO8859-5 microsoft-cp1251/XLC_LOCALE: ru_RU.CP1251 koi8-r/XLC_LOCALE: ru_RU.KOI8-R +microsoft-cp1251/XLC_LOCALE: ru_UA.CP1251 koi8-u/XLC_LOCALE: ru_UA.KOI8-U iso8859-1/XLC_LOCALE: rw_RW.ISO8859-1 iso8859-2/XLC_LOCALE: sh_YU.ISO8859-2 @@ -231,6 +250,7 @@ iso8859-5/XLC_LOCALE: uk_UA.ISO8859-5 microsoft-cp1251/XLC_LOCALE: uk_UA.CP1251 koi8-u/XLC_LOCALE: uk_UA.KOI8-U microsoft-cp1256/XLC_LOCALE: ur_PK.CP1256 +iso8859-1/XLC_LOCALE: uz_UZ.ISO8859-1 vi_VN.tcvn/XLC_LOCALE: vi_VN.TCVN vi_VN.viscii/XLC_LOCALE: vi_VN.VISCII iso8859-1/XLC_LOCALE: wa_BE.ISO8859-1 @@ -242,10 +262,7 @@ zh_CN/XLC_LOCALE: zh_CN.gb2312 zh_CN.gbk/XLC_LOCALE: zh_CN.gbk zh_CN.gb18030/XLC_LOCALE: zh_CN.gb18030 zh_HK.big5/XLC_LOCALE: zh_HK.big5 -zh_HK.big5hkscs/XLC_LOCALE: zh_HK.big5-hkscs -zh_HK.big5hkscs/XLC_LOCALE: zh_HK.Big5-HKSCS zh_HK.big5hkscs/XLC_LOCALE: zh_HK.big5hkscs -zh_HK.big5hkscs/XLC_LOCALE: zh_HK.Big5HKSCS zh_TW.big5/XLC_LOCALE: zh_TW.big5 zh_TW/XLC_LOCALE: zh_TW.eucTW iso8859-1/XLC_LOCALE: zu_ZA.ISO8859-1 @@ -274,7 +291,6 @@ en_US.UTF-8/XLC_LOCALE: ar_TN.UTF-8 en_US.UTF-8/XLC_LOCALE: ar_YE.UTF-8 en_US.UTF-8/XLC_LOCALE: as_IN.UTF-8 en_US.UTF-8/XLC_LOCALE: az_AZ.UTF-8 -en_US.UTF-8/XLC_LOCALE: a3_AZ.UTF-8 en_US.UTF-8/XLC_LOCALE: be_BY.UTF-8 en_US.UTF-8/XLC_LOCALE: bg_BG.UTF-8 en_US.UTF-8/XLC_LOCALE: bn_BD.UTF-8 @@ -299,17 +315,25 @@ en_US.UTF-8/XLC_LOCALE: el_CY.UTF-8 en_US.UTF-8/XLC_LOCALE: el_GR.UTF-8 en_US.UTF-8/XLC_LOCALE: en_AU.UTF-8 en_US.UTF-8/XLC_LOCALE: en_BE.UTF-8 +en_US.UTF-8/XLC_LOCALE: en_BW.UTF-8 en_US.UTF-8/XLC_LOCALE: en_BZ.UTF-8 en_US.UTF-8/XLC_LOCALE: en_CA.UTF-8 +en_US.UTF-8/XLC_LOCALE: en_DK.UTF-8 en_US.UTF-8/XLC_LOCALE: en_GB.UTF-8 +en_US.UTF-8/XLC_LOCALE: en_EN.UTF-8 +en_US.UTF-8/XLC_LOCALE: en_HK.UTF-8 en_US.UTF-8/XLC_LOCALE: en_IE.UTF-8 +en_US.UTF-8/XLC_LOCALE: en_IN.UTF-8 en_US.UTF-8/XLC_LOCALE: en_JM.UTF-8 en_US.UTF-8/XLC_LOCALE: en_MT.UTF-8 en_US.UTF-8/XLC_LOCALE: en_NZ.UTF-8 +en_US.UTF-8/XLC_LOCALE: en_PH.UTF-8 +en_US.UTF-8/XLC_LOCALE: en_SG.UTF-8 en_US.UTF-8/XLC_LOCALE: en_TT.UTF-8 en_US.UTF-8/XLC_LOCALE: en_UK.UTF-8 en_US.UTF-8/XLC_LOCALE: en_US.UTF-8 en_US.UTF-8/XLC_LOCALE: en_ZA.UTF-8 +en_US.UTF-8/XLC_LOCALE: en_ZW.UTF-8 en_US.UTF-8/XLC_LOCALE: eo_EO.UTF-8 en_US.UTF-8/XLC_LOCALE: eo_XX.UTF-8 en_US.UTF-8/XLC_LOCALE: es_AR.UTF-8 @@ -360,8 +384,9 @@ en_US.UTF-8/XLC_LOCALE: it_IT.UTF-8 en_US.UTF-8/XLC_LOCALE: iu_CA.UTF-8 ja_JP.UTF-8/XLC_LOCALE: ja_JP.UTF-8 en_US.UTF-8/XLC_LOCALE: ka_GE.UTF-8 -en_US.UTF-8/XLC_LOCALE: kl_GL.UTF-8 en_US.UTF-8/XLC_LOCALE: kk_KZ.UTF-8 +en_US.UTF-8/XLC_LOCALE: kl_GL.UTF-8 +en_US.UTF-8/XLC_LOCALE: km_KH.UTF-8 en_US.UTF-8/XLC_LOCALE: kn_IN.UTF-8 en_US.UTF-8/XLC_LOCALE: ks_IN.UTF-8 en_US.UTF-8/XLC_LOCALE: ks_IN@devanagari.UTF-8 @@ -445,7 +470,3 @@ zh_HK.UTF-8/XLC_LOCALE: zh_HK.UTF-8 zh_CN.UTF-8/XLC_LOCALE: zh_SG.UTF-8 zh_TW.UTF-8/XLC_LOCALE: zh_TW.UTF-8 en_US.UTF-8/XLC_LOCALE: zu_ZA.UTF-8 -#ifdef __uxp__ -ja.U90/XLC_LOCALE: ja_JP.U90 -ja.S90/XLC_LOCALE: ja_JP.S90 -#endif diff --git a/libX11/nls/sr_CS.UTF-8/Compose.pre b/libX11/nls/sr_CS.UTF-8/Compose.pre new file mode 100644 index 000000000..119e23ec4 --- /dev/null +++ b/libX11/nls/sr_CS.UTF-8/Compose.pre @@ -0,0 +1,128 @@ +include "X11_LOCALEDATADIR/en_US.UTF-8/Compose" + +# Serbian accented Cyrillic +# а А - U+0430, U+0410 Cyrillic_a, Cyrillic_A +# е Е - U+0435, U+0415 Cyrillic_e, Cyrillic_E +# о О - U+043E, U+041E Cyrillic_o, Cyrillic_O +# у У - U+0443, U+0423 Cyrillic_u, Cyrillic_U +# и И - U+0438, U+0418 Cyrillic_i, Cyrillic_I +# +# ̀ - U+0300 <dead_grave>, <combining_grave>, <Multi_key> <grave> +# ́ - U+0301 <dead_acute>, <Multi_key> <acute>, <Multi_key> <apostrophe>, <combining_acute> +# ̂ - U+0302 <dead_circumflex>, <Multi_key> <asciicircum> +# ̏ - U+030F <dead_diaeresis>, <dead_doubleacute> +# ̀ - kratkouzlazni, U+0300 <dead_grave>, <combining_grave>, <Multi_key> <grave> +<dead_grave> <Cyrillic_a> : "а̀" +<combining_grave> <Cyrillic_a> : "а̀" +<Multi_key> <grave> <Cyrillic_a> : "а̀" +<dead_grave> <Cyrillic_A> : "А̀" +<combining_grave> <Cyrillic_A> : "А̀" +<Multi_key> <grave> <Cyrillic_A> : "А̀" +<dead_grave> <Cyrillic_e> : "ѐ" +<combining_grave> <Cyrillic_e> : "ѐ" +<Multi_key> <grave> <Cyrillic_e> : "ѐ" +<dead_grave> <Cyrillic_E> : "Ѐ" +<combining_grave> <Cyrillic_E> : "Ѐ" +<Multi_key> <grave> <Cyrillic_E> : "Ѐ" +<dead_grave> <Cyrillic_i> : "ѝ" +<combining_grave> <Cyrillic_i> : "ѝ" +<Multi_key> <grave> <Cyrillic_i> : "ѝ" +<dead_grave> <Cyrillic_I> : "Ѝ" +<combining_grave> <Cyrillic_I> : "Ѝ" +<Multi_key> <grave> <Cyrillic_I> : "Ѝ" +<dead_grave> <Cyrillic_o> : "о̀" +<combining_grave> <Cyrillic_o> : "о̀" +<Multi_key> <grave> <Cyrillic_o> : "о̀" +<dead_grave> <Cyrillic_O> : "О̀" +<combining_grave> <Cyrillic_O> : "О̀" +<Multi_key> <grave> <Cyrillic_O> : "О̀" +<dead_grave> <Cyrillic_u> : "у̀" +<combining_grave> <Cyrillic_u> : "у̀" +<Multi_key> <grave> <Cyrillic_u> : "у̀" +<dead_grave> <Cyrillic_U> : "У̀" +<combining_grave> <Cyrillic_U> : "У̀" +<Multi_key> <grave> <Cyrillic_U> : "У̀" +# ́ - dugouzlazni, U+0301 <dead_acute>, <Multi_key> <acute>, <Multi_key> <apostrophe>, <combining_acute> +<dead_acute> <Cyrillic_a> : "а́" +<combining_acute> <Cyrillic_a> : "а́" +<Multi_key> <acute> <Cyrillic_a> : "а́" +<Multi_key> <apostrophe> <Cyrillic_a> : "а́" +<dead_acute> <Cyrillic_A> : "А́" +<combining_acute> <Cyrillic_A> : "А́" +<Multi_key> <acute> <Cyrillic_A> : "А́" +<Multi_key> <apostrophe> <Cyrillic_A> : "А́" +<dead_acute> <Cyrillic_e> : "е́" +<combining_acute> <Cyrillic_e> : "е́" +<Multi_key> <acute> <Cyrillic_e> : "е́" +<Multi_key> <apostrophe> <Cyrillic_e> : "е́" +<dead_acute> <Cyrillic_E> : "Е́" +<combining_acute> <Cyrillic_E> : "Е́" +<Multi_key> <acute> <Cyrillic_E> : "Е́" +<Multi_key> <apostrophe> <Cyrillic_E> : "Е́" +<dead_acute> <Cyrillic_i> : "и́" +<combining_acute> <Cyrillic_i> : "и́" +<Multi_key> <acute> <Cyrillic_i> : "и́" +<Multi_key> <apostrophe> <Cyrillic_i> : "и́" +<dead_acute> <Cyrillic_I> : "И́" +<combining_acute> <Cyrillic_I> : "И́" +<Multi_key> <acute> <Cyrillic_I> : "И́" +<Multi_key> <apostrophe> <Cyrillic_I> : "И́" +<dead_acute> <Cyrillic_o> : "о́" +<combining_acute> <Cyrillic_o> : "о́" +<Multi_key> <acute> <Cyrillic_o> : "о́" +<Multi_key> <apostrophe> <Cyrillic_o> : "о́" +<dead_acute> <Cyrillic_O> : "О́" +<combining_acute> <Cyrillic_O> : "О́" +<Multi_key> <acute> <Cyrillic_O> : "О́" +<Multi_key> <apostrophe> <Cyrillic_O> : "О́" +<dead_acute> <Cyrillic_u> : "у́" +<combining_acute> <Cyrillic_u> : "у́" +<Multi_key> <acute> <Cyrillic_u> : "у́" +<Multi_key> <apostrophe> <Cyrillic_u> : "у́" +<dead_acute> <Cyrillic_U> : "У́" +<combining_acute> <Cyrillic_U> : "У́" +<Multi_key> <acute> <Cyrillic_U> : "У́" +<Multi_key> <apostrophe> <Cyrillic_U> : "У́" +# ̂ - dugosilazni, U+0302 <dead_circumflex>, <Multi_key> <asciicircum> +<dead_circumflex> <Cyrillic_a> : "а̂" +<Multi_key> <asciicircum> <Cyrillic_a> : "а̂" +<dead_circumflex> <Cyrillic_A> : "А̂" +<Multi_key> <asciicircum> <Cyrillic_A> : "А̂" +<dead_circumflex> <Cyrillic_e> : "е̂" +<Multi_key> <asciicircum> <Cyrillic_e> : "е̂" +<dead_circumflex> <Cyrillic_E> : "Е̂" +<Multi_key> <asciicircum> <Cyrillic_E> : "Е̂" +<dead_circumflex> <Cyrillic_i> : "и̂" +<Multi_key> <asciicircum> <Cyrillic_i> : "и̂" +<dead_circumflex> <Cyrillic_I> : "И̂" +<Multi_key> <asciicircum> <Cyrillic_I> : "И̂" +<dead_circumflex> <Cyrillic_o> : "о̂" +<Multi_key> <asciicircum> <Cyrillic_o> : "о̂" +<dead_circumflex> <Cyrillic_O> : "О̂" +<Multi_key> <asciicircum> <Cyrillic_O> : "О̂" +<dead_circumflex> <Cyrillic_u> : "у̂" +<Multi_key> <asciicircum> <Cyrillic_u> : "у̂" +<dead_circumflex> <Cyrillic_U> : "У̂" +<Multi_key> <asciicircum> <Cyrillic_U> : "У̂" +# ̏ - kratkosilazni, U+030F <dead_diaeresis>, <dead_doubleacute> +# there's no appropriate dead_doublegrave, so we use these two dead keys +<dead_diaeresis> <Cyrillic_a> : "а̏" +<dead_doubleacute> <Cyrillic_a> : "а̏" +<dead_diaeresis> <Cyrillic_A> : "А̏" +<dead_doubleacute> <Cyrillic_A> : "А̏" +<dead_diaeresis> <Cyrillic_e> : "е̏" +<dead_doubleacute> <Cyrillic_e> : "е̏" +<dead_diaeresis> <Cyrillic_E> : "Е̏" +<dead_doubleacute> <Cyrillic_E> : "Е̏" +<dead_diaeresis> <Cyrillic_i> : "и̏" +<dead_doubleacute> <Cyrillic_i> : "и̏" +<dead_diaeresis> <Cyrillic_I> : "И̏" +<dead_doubleacute> <Cyrillic_I> : "И̏" +<dead_diaeresis> <Cyrillic_o> : "о̏" +<dead_doubleacute> <Cyrillic_o> : "о̏" +<dead_diaeresis> <Cyrillic_O> : "О̏" +<dead_doubleacute> <Cyrillic_O> : "О̏" +<dead_diaeresis> <Cyrillic_u> : "у̏" +<dead_doubleacute> <Cyrillic_u> : "у̏" +<dead_diaeresis> <Cyrillic_U> : "У̏" +<dead_doubleacute> <Cyrillic_U> : "У̏" diff --git a/libX11/nls/sr_CS.UTF-8/XI18N_OBJS b/libX11/nls/sr_CS.UTF-8/XI18N_OBJS new file mode 100644 index 000000000..f201bf435 --- /dev/null +++ b/libX11/nls/sr_CS.UTF-8/XI18N_OBJS @@ -0,0 +1,8 @@ +# CATEGORY(XLC|XIM|OM) SHARED_LIBRARY_NAME FUNCTION_NAME +# +# XI18N objects table for euro locales +# +XLC common/xlcUTF8Load _XlcUtf8Loader # XLC_open +XOM common/xomLTRTTB _XomGenericOpenOM # XOM_open +XIM common/xiiimp _SwitchOpenIM # XIM_open +XIM common/xiiimp _XimpLocalOpenIM # XIM_open diff --git a/libX11/nls/ja.U90/Compose.pre b/libX11/nls/sr_CS.UTF-8/XLC_LOCALE.pre index e69de29bb..e69de29bb 100644 --- a/libX11/nls/ja.U90/Compose.pre +++ b/libX11/nls/sr_CS.UTF-8/XLC_LOCALE.pre diff --git a/libX11/nls/th_TH.UTF-8/Compose.pre b/libX11/nls/th_TH.UTF-8/Compose.pre index e69de29bb..6c2c4114d 100644 --- a/libX11/nls/th_TH.UTF-8/Compose.pre +++ b/libX11/nls/th_TH.UTF-8/Compose.pre @@ -0,0 +1 @@ +include "X11_LOCALEDATADIR/en_US.UTF-8/Compose" diff --git a/libX11/nls/zh_CN.UTF-8/Compose.pre b/libX11/nls/zh_CN.UTF-8/Compose.pre index e69de29bb..6c2c4114d 100644 --- a/libX11/nls/zh_CN.UTF-8/Compose.pre +++ b/libX11/nls/zh_CN.UTF-8/Compose.pre @@ -0,0 +1 @@ +include "X11_LOCALEDATADIR/en_US.UTF-8/Compose" diff --git a/libX11/nls/zh_HK.UTF-8/Compose.pre b/libX11/nls/zh_HK.UTF-8/Compose.pre index e69de29bb..6c2c4114d 100644 --- a/libX11/nls/zh_HK.UTF-8/Compose.pre +++ b/libX11/nls/zh_HK.UTF-8/Compose.pre @@ -0,0 +1 @@ +include "X11_LOCALEDATADIR/en_US.UTF-8/Compose" diff --git a/libX11/nls/zh_TW.UTF-8/Compose.pre b/libX11/nls/zh_TW.UTF-8/Compose.pre index e69de29bb..6c2c4114d 100644 --- a/libX11/nls/zh_TW.UTF-8/Compose.pre +++ b/libX11/nls/zh_TW.UTF-8/Compose.pre @@ -0,0 +1 @@ +include "X11_LOCALEDATADIR/en_US.UTF-8/Compose" diff --git a/mesalib/.dir-locals.el b/mesalib/.dir-locals.el new file mode 100644 index 000000000..4f0ad7ac8 --- /dev/null +++ b/mesalib/.dir-locals.el @@ -0,0 +1,11 @@ +((nil + (indent-tabs-mode . nil) + (tab-width . 8) + (c-basic-offset . 3) + (c-file-style . "stroustrup") + (fill-column . 78) + (eval . (progn + (c-set-offset 'innamespace '0) + (c-set-offset 'inline-open '0))) + ) + ) diff --git a/mesalib/include/GL/gl.h b/mesalib/include/GL/gl.h index e65e1bc8a..97094fc59 100644 --- a/mesalib/include/GL/gl.h +++ b/mesalib/include/GL/gl.h @@ -169,8 +169,8 @@ typedef double GLclampd; /* double precision float in [0,1] */ */ /* Boolean values */ -#define GL_FALSE 0x0 -#define GL_TRUE 0x1 +#define GL_FALSE 0 +#define GL_TRUE 1 /* Data types */ #define GL_BYTE 0x1400 @@ -370,8 +370,8 @@ typedef double GLclampd; /* double precision float in [0,1] */ #define GL_BLEND 0x0BE2 #define GL_BLEND_SRC 0x0BE1 #define GL_BLEND_DST 0x0BE0 -#define GL_ZERO 0x0 -#define GL_ONE 0x1 +#define GL_ZERO 0 +#define GL_ONE 1 #define GL_SRC_COLOR 0x0300 #define GL_ONE_MINUS_SRC_COLOR 0x0301 #define GL_SRC_ALPHA 0x0302 @@ -461,7 +461,7 @@ typedef double GLclampd; /* double precision float in [0,1] */ #define GL_DECR 0x1E03 /* Buffers, Pixel Drawing/Reading */ -#define GL_NONE 0x0 +#define GL_NONE 0 #define GL_LEFT 0x0406 #define GL_RIGHT 0x0407 /*GL_FRONT 0x0404 */ @@ -689,7 +689,7 @@ typedef double GLclampd; /* double precision float in [0,1] */ #define GL_EXTENSIONS 0x1F03 /* Errors */ -#define GL_NO_ERROR 0x0 +#define GL_NO_ERROR 0 #define GL_INVALID_ENUM 0x0500 #define GL_INVALID_VALUE 0x0501 #define GL_INVALID_OPERATION 0x0502 diff --git a/mesalib/scons/gallium.py b/mesalib/scons/gallium.py index 66ccaea73..98671f75d 100644 --- a/mesalib/scons/gallium.py +++ b/mesalib/scons/gallium.py @@ -500,7 +500,7 @@ def generate(env): libs = [] if env['platform'] in ('darwin', 'freebsd', 'linux', 'posix', 'sunos'): libs += ['m', 'pthread', 'dl'] - if env['platform'] in 'linux': + if env['platform'] in ('linux',): libs += ['rt'] env.Append(LIBS = libs) diff --git a/mesalib/src/gallium/auxiliary/Makefile.sources b/mesalib/src/gallium/auxiliary/Makefile.sources index 6258861f0..724178535 100644 --- a/mesalib/src/gallium/auxiliary/Makefile.sources +++ b/mesalib/src/gallium/auxiliary/Makefile.sources @@ -124,7 +124,6 @@ C_SOURCES := \ util/u_math.c \ util/u_mm.c \ util/u_pstipple.c \ - util/u_rect.c \ util/u_ringbuffer.c \ util/u_sampler.c \ util/u_simple_shaders.c \ diff --git a/mesalib/src/gallium/auxiliary/util/u_blitter.h b/mesalib/src/gallium/auxiliary/util/u_blitter.h index b96e68e93..99175409b 100644 --- a/mesalib/src/gallium/auxiliary/util/u_blitter.h +++ b/mesalib/src/gallium/auxiliary/util/u_blitter.h @@ -29,10 +29,14 @@ #include "util/u_framebuffer.h" #include "util/u_inlines.h" -#include "util/u_memory.h" #include "pipe/p_state.h" +/* u_memory.h conflicts with st/mesa */ +#ifndef Elements +#define Elements(x) (sizeof(x)/sizeof((x)[0])) +#endif + #ifdef __cplusplus extern "C" { diff --git a/mesalib/src/gallium/auxiliary/util/u_rect.c b/mesalib/src/gallium/auxiliary/util/u_rect.c deleted file mode 100644 index d00568f1f..000000000 --- a/mesalib/src/gallium/auxiliary/util/u_rect.c +++ /dev/null @@ -1,158 +0,0 @@ -/************************************************************************** - * - * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/** - * Rectangle-related helper functions. - */ - - -#include "util/u_format.h" -#include "util/u_rect.h" -#include "util/u_pack_color.h" - - -/** - * Copy 2D rect from one place to another. - * Position and sizes are in pixels. - * src_stride may be negative to do vertical flip of pixels from source. - */ -void -util_copy_rect(ubyte * dst, - enum pipe_format format, - unsigned dst_stride, - unsigned dst_x, - unsigned dst_y, - unsigned width, - unsigned height, - const ubyte * src, - int src_stride, - unsigned src_x, - unsigned src_y) -{ - unsigned i; - int src_stride_pos = src_stride < 0 ? -src_stride : src_stride; - int blocksize = util_format_get_blocksize(format); - int blockwidth = util_format_get_blockwidth(format); - int blockheight = util_format_get_blockheight(format); - - assert(blocksize > 0); - assert(blockwidth > 0); - assert(blockheight > 0); - - dst_x /= blockwidth; - dst_y /= blockheight; - width = (width + blockwidth - 1)/blockwidth; - height = (height + blockheight - 1)/blockheight; - src_x /= blockwidth; - src_y /= blockheight; - - dst += dst_x * blocksize; - src += src_x * blocksize; - dst += dst_y * dst_stride; - src += src_y * src_stride_pos; - width *= blocksize; - - if (width == dst_stride && width == src_stride) - memcpy(dst, src, height * width); - else { - for (i = 0; i < height; i++) { - memcpy(dst, src, width); - dst += dst_stride; - src += src_stride; - } - } -} - -void -util_fill_rect(ubyte * dst, - enum pipe_format format, - unsigned dst_stride, - unsigned dst_x, - unsigned dst_y, - unsigned width, - unsigned height, - union util_color *uc) -{ - const struct util_format_description *desc = util_format_description(format); - unsigned i, j; - unsigned width_size; - int blocksize = desc->block.bits / 8; - int blockwidth = desc->block.width; - int blockheight = desc->block.height; - - assert(blocksize > 0); - assert(blockwidth > 0); - assert(blockheight > 0); - - dst_x /= blockwidth; - dst_y /= blockheight; - width = (width + blockwidth - 1)/blockwidth; - height = (height + blockheight - 1)/blockheight; - - dst += dst_x * blocksize; - dst += dst_y * dst_stride; - width_size = width * blocksize; - - switch (blocksize) { - case 1: - if(dst_stride == width_size) - memset(dst, uc->ub, height * width_size); - else { - for (i = 0; i < height; i++) { - memset(dst, uc->ub, width_size); - dst += dst_stride; - } - } - break; - case 2: - for (i = 0; i < height; i++) { - uint16_t *row = (uint16_t *)dst; - for (j = 0; j < width; j++) - *row++ = uc->us; - dst += dst_stride; - } - break; - case 4: - for (i = 0; i < height; i++) { - uint32_t *row = (uint32_t *)dst; - for (j = 0; j < width; j++) - *row++ = uc->ui; - dst += dst_stride; - } - break; - default: - for (i = 0; i < height; i++) { - ubyte *row = dst; - for (j = 0; j < width; j++) { - memcpy(row, uc, blocksize); - row += blocksize; - } - dst += dst_stride; - } - break; - } -} diff --git a/mesalib/src/gallium/auxiliary/util/u_rect.h b/mesalib/src/gallium/auxiliary/util/u_rect.h index 8fccae8c4..10909b202 100644 --- a/mesalib/src/gallium/auxiliary/util/u_rect.h +++ b/mesalib/src/gallium/auxiliary/util/u_rect.h @@ -83,36 +83,10 @@ u_rect_possible_intersection(const struct u_rect *a, } #endif -#include "pipe/p_format.h" -#include "util/u_pack_color.h" - - -/********************************************************************** - * Pipe copy/fill rect helpers. - */ - -/* These really should move to a different file: +/* Include pipe copy/fill rect helpers declarations for backwards compatibility */ -#include "pipe/p_format.h" +#include "util/u_surface.h" -#ifdef __cplusplus -extern "C" { -#endif - -extern void -util_copy_rect(ubyte * dst, enum pipe_format format, - unsigned dst_stride, unsigned dst_x, unsigned dst_y, - unsigned width, unsigned height, const ubyte * src, - int src_stride, unsigned src_x, unsigned src_y); - -extern void -util_fill_rect(ubyte * dst, enum pipe_format format, - unsigned dst_stride, unsigned dst_x, unsigned dst_y, - unsigned width, unsigned height, union util_color *uc); - -#ifdef __cplusplus -} -#endif #endif /* U_RECT_H */ diff --git a/mesalib/src/gallium/auxiliary/util/u_surface.c b/mesalib/src/gallium/auxiliary/util/u_surface.c index 5b42afd0d..2c197c3df 100644 --- a/mesalib/src/gallium/auxiliary/util/u_surface.c +++ b/mesalib/src/gallium/auxiliary/util/u_surface.c @@ -116,6 +116,163 @@ util_create_rgba_texture(struct pipe_context *pipe, /** + * Copy 2D rect from one place to another. + * Position and sizes are in pixels. + * src_stride may be negative to do vertical flip of pixels from source. + */ +void +util_copy_rect(ubyte * dst, + enum pipe_format format, + unsigned dst_stride, + unsigned dst_x, + unsigned dst_y, + unsigned width, + unsigned height, + const ubyte * src, + int src_stride, + unsigned src_x, + unsigned src_y) +{ + unsigned i; + int src_stride_pos = src_stride < 0 ? -src_stride : src_stride; + int blocksize = util_format_get_blocksize(format); + int blockwidth = util_format_get_blockwidth(format); + int blockheight = util_format_get_blockheight(format); + + assert(blocksize > 0); + assert(blockwidth > 0); + assert(blockheight > 0); + + dst_x /= blockwidth; + dst_y /= blockheight; + width = (width + blockwidth - 1)/blockwidth; + height = (height + blockheight - 1)/blockheight; + src_x /= blockwidth; + src_y /= blockheight; + + dst += dst_x * blocksize; + src += src_x * blocksize; + dst += dst_y * dst_stride; + src += src_y * src_stride_pos; + width *= blocksize; + + if (width == dst_stride && width == src_stride) + memcpy(dst, src, height * width); + else { + for (i = 0; i < height; i++) { + memcpy(dst, src, width); + dst += dst_stride; + src += src_stride; + } + } +} + + +/** + * Copy 3D box from one place to another. + * Position and sizes are in pixels. + */ +void +util_copy_box(ubyte * dst, + enum pipe_format format, + unsigned dst_stride, unsigned dst_slice_stride, + unsigned dst_x, unsigned dst_y, unsigned dst_z, + unsigned width, unsigned height, unsigned depth, + const ubyte * src, + int src_stride, unsigned src_slice_stride, + unsigned src_x, unsigned src_y, unsigned src_z) +{ + unsigned z; + dst += dst_z * dst_slice_stride; + src += src_z * src_slice_stride; + for (z = 0; z < depth; ++z) { + util_copy_rect(dst, + format, + dst_stride, + dst_x, dst_y, + width, height, + src, + src_stride, + src_x, src_y); + + dst += dst_slice_stride; + src += src_slice_stride; + } +} + + +void +util_fill_rect(ubyte * dst, + enum pipe_format format, + unsigned dst_stride, + unsigned dst_x, + unsigned dst_y, + unsigned width, + unsigned height, + union util_color *uc) +{ + const struct util_format_description *desc = util_format_description(format); + unsigned i, j; + unsigned width_size; + int blocksize = desc->block.bits / 8; + int blockwidth = desc->block.width; + int blockheight = desc->block.height; + + assert(blocksize > 0); + assert(blockwidth > 0); + assert(blockheight > 0); + + dst_x /= blockwidth; + dst_y /= blockheight; + width = (width + blockwidth - 1)/blockwidth; + height = (height + blockheight - 1)/blockheight; + + dst += dst_x * blocksize; + dst += dst_y * dst_stride; + width_size = width * blocksize; + + switch (blocksize) { + case 1: + if(dst_stride == width_size) + memset(dst, uc->ub, height * width_size); + else { + for (i = 0; i < height; i++) { + memset(dst, uc->ub, width_size); + dst += dst_stride; + } + } + break; + case 2: + for (i = 0; i < height; i++) { + uint16_t *row = (uint16_t *)dst; + for (j = 0; j < width; j++) + *row++ = uc->us; + dst += dst_stride; + } + break; + case 4: + for (i = 0; i < height; i++) { + uint32_t *row = (uint32_t *)dst; + for (j = 0; j < width; j++) + *row++ = uc->ui; + dst += dst_stride; + } + break; + default: + for (i = 0; i < height; i++) { + ubyte *row = dst; + for (j = 0; j < width; j++) { + memcpy(row, uc, blocksize); + row += blocksize; + } + dst += dst_stride; + } + break; + } +} + + +/** * Fallback function for pipe->resource_copy_region(). * Note: (X,Y)=(0,0) is always the upper-left corner. */ @@ -133,7 +290,6 @@ util_resource_copy_region(struct pipe_context *pipe, const uint8_t *src_map; enum pipe_format src_format, dst_format; struct pipe_box dst_box; - int z; assert(src && dst); if (!src || !dst) @@ -181,19 +337,14 @@ util_resource_copy_region(struct pipe_context *pipe, assert(src_box->depth == 1); memcpy(dst_map, src_map, src_box->width); } else { - for (z = 0; z < src_box->depth; ++z) { - util_copy_rect(dst_map, - dst_format, - dst_trans->stride, - 0, 0, - src_box->width, src_box->height, - src_map, - src_trans->stride, - 0, 0); - - dst_map += dst_trans->layer_stride; - src_map += src_trans->layer_stride; - } + util_copy_box(dst_map, + dst_format, + dst_trans->stride, dst_trans->layer_stride, + 0, 0, 0, + src_box->width, src_box->height, src_box->depth, + src_map, + src_trans->stride, src_trans->layer_stride, + 0, 0, 0); } pipe->transfer_unmap(pipe, dst_trans); diff --git a/mesalib/src/gallium/auxiliary/util/u_surface.h b/mesalib/src/gallium/auxiliary/util/u_surface.h index 6bcb63f3d..dd4d5785e 100644 --- a/mesalib/src/gallium/auxiliary/util/u_surface.h +++ b/mesalib/src/gallium/auxiliary/util/u_surface.h @@ -32,6 +32,8 @@ #include "pipe/p_compiler.h" #include "pipe/p_state.h" +#include "util/u_pack_color.h" + #ifdef __cplusplus extern "C" { @@ -50,6 +52,28 @@ util_create_rgba_texture(struct pipe_context *ctx, extern void +util_copy_rect(ubyte * dst, enum pipe_format format, + unsigned dst_stride, unsigned dst_x, unsigned dst_y, + unsigned width, unsigned height, const ubyte * src, + int src_stride, unsigned src_x, unsigned src_y); + +extern void +util_copy_box(ubyte * dst, + enum pipe_format format, + unsigned dst_stride, unsigned dst_slice_stride, + unsigned dst_x, unsigned dst_y, unsigned dst_z, + unsigned width, unsigned height, unsigned depth, + const ubyte * src, + int src_stride, unsigned src_slice_stride, + unsigned src_x, unsigned src_y, unsigned src_z); + +extern void +util_fill_rect(ubyte * dst, enum pipe_format format, + unsigned dst_stride, unsigned dst_x, unsigned dst_y, + unsigned width, unsigned height, union util_color *uc); + + +extern void util_resource_copy_region(struct pipe_context *pipe, struct pipe_resource *dst, unsigned dst_level, diff --git a/mesalib/src/gallium/auxiliary/util/u_transfer.c b/mesalib/src/gallium/auxiliary/util/u_transfer.c index 8b4c36592..861682553 100644 --- a/mesalib/src/gallium/auxiliary/util/u_transfer.c +++ b/mesalib/src/gallium/auxiliary/util/u_transfer.c @@ -1,5 +1,5 @@ #include "pipe/p_context.h" -#include "util/u_rect.h" +#include "util/u_surface.h" #include "util/u_inlines.h" #include "util/u_transfer.h" #include "util/u_memory.h" @@ -47,21 +47,19 @@ void u_default_transfer_inline_write( struct pipe_context *pipe, } else { const uint8_t *src_data = data; - unsigned i; - for (i = 0; i < box->depth; i++) { - util_copy_rect(map, - resource->format, - transfer->stride, /* bytes */ - 0, 0, - box->width, - box->height, - src_data, - stride, /* bytes */ - 0, 0); - map += transfer->layer_stride; - src_data += layer_stride; - } + util_copy_box(map, + resource->format, + transfer->stride, /* bytes */ + transfer->layer_stride, /* bytes */ + 0, 0, 0, + box->width, + box->height, + box->depth, + src_data, + stride, /* bytes */ + layer_stride, /* bytes */ + 0, 0, 0); } pipe_transfer_unmap(pipe, transfer); diff --git a/mesalib/src/glsl/Makefile.am b/mesalib/src/glsl/Makefile.am index ea7617685..aff1559e0 100644 --- a/mesalib/src/glsl/Makefile.am +++ b/mesalib/src/glsl/Makefile.am @@ -49,14 +49,16 @@ libglsl_la_LIBADD = glcpp/libglcpp.la libglsl_la_LDFLAGS = glsl_compiler_SOURCES = \ - $(top_srcdir)/src/mesa/program/hash_table.c \ + $(top_srcdir)/src/mesa/main/hash_table.c \ + $(top_srcdir)/src/mesa/program/prog_hash_table.c \ $(top_srcdir)/src/mesa/program/symbol_table.c \ $(GLSL_COMPILER_CXX_FILES) glsl_compiler_LDADD = libglsl.la glsl_test_SOURCES = \ - $(top_srcdir)/src/mesa/program/hash_table.c \ + $(top_srcdir)/src/mesa/main/hash_table.c \ + $(top_srcdir)/src/mesa/program/prog_hash_table.c \ $(top_srcdir)/src/mesa/program/symbol_table.c \ $(GLSL_SRCDIR)/standalone_scaffolding.cpp \ test.cpp \ diff --git a/mesalib/src/glsl/SConscript b/mesalib/src/glsl/SConscript index 0cf25c07b..6abba2a24 100644 --- a/mesalib/src/glsl/SConscript +++ b/mesalib/src/glsl/SConscript @@ -57,14 +57,18 @@ if env['crosscompile'] and not env['embedded']: Import('builtin_glsl_function') else: # Copy these files to avoid generation object files into src/mesa/program + env.Prepend(CPPPATH = ['#src/mesa/main']) + env.Command('hash_table.c', '#src/mesa/main/hash_table.c', Copy('$TARGET', '$SOURCE')) + # Copy these files to avoid generation object files into src/mesa/program env.Prepend(CPPPATH = ['#src/mesa/program']) - env.Command('hash_table.c', '#src/mesa/program/hash_table.c', Copy('$TARGET', '$SOURCE')) + env.Command('prog_hash_table.c', '#src/mesa/program/prog_hash_table.c', Copy('$TARGET', '$SOURCE')) env.Command('symbol_table.c', '#src/mesa/program/symbol_table.c', Copy('$TARGET', '$SOURCE')) compiler_objs = env.StaticObject(source_lists['GLSL_COMPILER_CXX_FILES']) mesa_objs = env.StaticObject([ 'hash_table.c', + 'prog_hash_table.c', 'symbol_table.c', ]) diff --git a/mesalib/src/glsl/ast_function.cpp b/mesalib/src/glsl/ast_function.cpp index ea3282c5f..b56a3c723 100644 --- a/mesalib/src/glsl/ast_function.cpp +++ b/mesalib/src/glsl/ast_function.cpp @@ -275,9 +275,10 @@ generate_call(exec_list *instructions, ir_function_signature *sig, /* If the function call is a constant expression, don't generate any * instructions; just generate an ir_constant. * - * Function calls were first allowed to be constant expressions in GLSL 1.20. + * Function calls were first allowed to be constant expressions in GLSL + * 1.20 and GLSL ES 3.00. */ - if (state->language_version >= 120) { + if (state->is_version(120, 300)) { ir_constant *value = sig->constant_expression_value(actual_parameters, NULL); if (value != NULL) { return value; @@ -324,7 +325,8 @@ match_function_by_name(const char *name, goto done; /* no match */ /* Is the function hidden by a variable (impossible in 1.10)? */ - if (state->language_version != 110 && state->symbols->get_variable(name)) + if (!state->symbols->separate_function_namespace + && state->symbols->get_variable(name)) goto done; /* no match */ if (f != NULL) { @@ -1242,9 +1244,8 @@ ast_function_expression::hir(exec_list *instructions, } if (constructor_type->is_array()) { - if (state->language_version <= 110) { - _mesa_glsl_error(& loc, state, - "array constructors forbidden in GLSL 1.10"); + if (!state->check_version(120, 300, &loc, + "array constructors forbidden")) { return ir_rvalue::error_value(ctx); } @@ -1367,11 +1368,11 @@ ast_function_expression::hir(exec_list *instructions, * "It is an error to construct matrices from other matrices. This * is reserved for future use." */ - if (state->language_version == 110 && matrix_parameters > 0 - && constructor_type->is_matrix()) { - _mesa_glsl_error(& loc, state, "cannot construct `%s' from a " - "matrix in GLSL 1.10", - constructor_type->name); + if (matrix_parameters > 0 + && constructor_type->is_matrix() + && !state->check_version(120, 100, &loc, + "cannot construct `%s' from a matrix", + constructor_type->name)) { return ir_rvalue::error_value(ctx); } diff --git a/mesalib/src/glsl/ast_to_hir.cpp b/mesalib/src/glsl/ast_to_hir.cpp index d450aa1e4..94b63f682 100644 --- a/mesalib/src/glsl/ast_to_hir.cpp +++ b/mesalib/src/glsl/ast_to_hir.cpp @@ -66,7 +66,7 @@ _mesa_ast_to_hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) { _mesa_glsl_initialize_variables(instructions, state); - state->symbols->language_version = state->language_version; + state->symbols->separate_function_namespace = state->language_version == 110; state->current_function = NULL; @@ -121,7 +121,7 @@ apply_implicit_conversion(const glsl_type *to, ir_rvalue * &from, /* This conversion was added in GLSL 1.20. If the compilation mode is * GLSL 1.10, the conversion is skipped. */ - if (state->language_version < 120) + if (!state->is_version(120, 0)) return false; /* From page 27 (page 33 of the PDF) of the GLSL 1.50 spec: @@ -390,8 +390,7 @@ bit_logic_result_type(const struct glsl_type *type_a, ast_operators op, struct _mesa_glsl_parse_state *state, YYLTYPE *loc) { - if (state->language_version < 130) { - _mesa_glsl_error(loc, state, "bit operations require GLSL 1.30"); + if (!state->check_bitwise_operations_allowed(loc)) { return glsl_type::error_type; } @@ -446,10 +445,7 @@ modulus_result_type(const struct glsl_type *type_a, const struct glsl_type *type_b, struct _mesa_glsl_parse_state *state, YYLTYPE *loc) { - if (state->language_version < 130) { - _mesa_glsl_error(loc, state, - "operator '%%' is reserved in %s", - state->version_string); + if (!state->check_version(130, 300, loc, "operator '%%' is reserved")) { return glsl_type::error_type; } @@ -553,8 +549,7 @@ shift_result_type(const struct glsl_type *type_a, ast_operators op, struct _mesa_glsl_parse_state *state, YYLTYPE *loc) { - if (state->language_version < 130) { - _mesa_glsl_error(loc, state, "bit operations require GLSL 1.30"); + if (!state->check_bitwise_operations_allowed(loc)) { return glsl_type::error_type; } @@ -694,15 +689,17 @@ do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state, lhs->variable_referenced()->name); error_emitted = true; - } else if (state->language_version <= 110 && lhs->type->is_array()) { + } else if (lhs->type->is_array() && + !state->check_version(120, 300, &lhs_loc, + "whole array assignment forbidden")) { /* From page 32 (page 38 of the PDF) of the GLSL 1.10 spec: * * "Other binary or unary expressions, non-dereferenced * arrays, function names, swizzles with repeated fields, * and constants cannot be l-values." + * + * The restriction on arrays is lifted in GLSL 1.20 and GLSL ES 3.00. */ - _mesa_glsl_error(&lhs_loc, state, "whole array assignment is not " - "allowed in GLSL 1.10 or GLSL ES 1.00."); error_emitted = true; } else if (!lhs->is_lvalue()) { _mesa_glsl_error(& lhs_loc, state, "non-lvalue in assignment"); @@ -1099,9 +1096,7 @@ ast_expression::hir(exec_list *instructions, case ast_lshift: case ast_rshift: - if (state->language_version < 130) { - _mesa_glsl_error(&loc, state, "operator %s requires GLSL 1.30", - operator_string(this->oper)); + if (!state->check_bitwise_operations_allowed(&loc)) { error_emitted = true; } @@ -1155,10 +1150,9 @@ ast_expression::hir(exec_list *instructions, _mesa_glsl_error(& loc, state, "operands of `%s' must have the same " "type", (this->oper == ast_equal) ? "==" : "!="); error_emitted = true; - } else if ((state->language_version <= 110) - && (op[0]->type->is_array() || op[1]->type->is_array())) { - _mesa_glsl_error(& loc, state, "array comparisons forbidden in " - "GLSL 1.10"); + } else if ((op[0]->type->is_array() || op[1]->type->is_array()) && + !state->check_version(120, 300, &loc, + "array comparisons forbidden")) { error_emitted = true; } @@ -1185,8 +1179,7 @@ ast_expression::hir(exec_list *instructions, case ast_bit_not: op[0] = this->subexpressions[0]->hir(instructions, state); - if (state->language_version < 130) { - _mesa_glsl_error(&loc, state, "bit-wise operations require GLSL 1.30"); + if (!state->check_bitwise_operations_allowed(&loc)) { error_emitted = true; } @@ -1424,9 +1417,10 @@ ast_expression::hir(exec_list *instructions, * "The second and third expressions must be the same type, but can * be of any type other than an array." */ - if ((state->language_version <= 110) && type->is_array()) { - _mesa_glsl_error(& loc, state, "Second and third operands of ?: " - "operator must not be arrays."); + if (type->is_array() && + !state->check_version(120, 300, &loc, + "Second and third operands of ?: operator " + "cannot be arrays")) { error_emitted = true; } @@ -1660,15 +1654,18 @@ ast_expression::hir(exec_list *instructions, array->type->element_type()->is_sampler() && const_index == NULL) { - if (state->language_version == 100) { - _mesa_glsl_warning(&loc, state, - "sampler arrays indexed with non-constant " - "expressions is optional in GLSL ES 1.00"); - } else if (state->language_version < 130) { - _mesa_glsl_warning(&loc, state, - "sampler arrays indexed with non-constant " - "expressions is forbidden in GLSL 1.30 and " - "later"); + if (!state->is_version(130, 100)) { + if (state->es_shader) { + _mesa_glsl_warning(&loc, state, + "sampler arrays indexed with non-constant " + "expressions is optional in %s", + state->get_version_string()); + } else { + _mesa_glsl_warning(&loc, state, + "sampler arrays indexed with non-constant " + "expressions will be forbidden in GLSL 1.30 and " + "later"); + } } else { _mesa_glsl_error(&loc, state, "sampler arrays indexed with non-constant " @@ -2288,7 +2285,7 @@ get_variable_being_redeclared(ir_variable *var, ast_declaration *decl, * * gl_Color * * gl_SecondaryColor */ - } else if (state->language_version >= 130 + } else if (state->is_version(130, 0) && (strcmp(var->name, "gl_FrontColor") == 0 || strcmp(var->name, "gl_BackColor") == 0 || strcmp(var->name, "gl_FrontSecondaryColor") == 0 @@ -2355,10 +2352,9 @@ process_initializer(ir_variable *var, ast_declaration *decl, * directly by an application via API commands, or indirectly by * OpenGL." */ - if ((state->language_version <= 110) - && (var->mode == ir_var_uniform)) { - _mesa_glsl_error(& initializer_loc, state, - "cannot initialize uniforms in GLSL 1.10"); + if (var->mode == ir_var_uniform) { + state->check_version(120, 0, &initializer_loc, + "cannot initialize uniforms"); } if (var->type->is_sampler()) { @@ -2608,23 +2604,23 @@ ast_declarator_list::hir(exec_list *instructions, * * Local variables can only use the qualifier const." * - * This is relaxed in GLSL 1.30. It is also relaxed by any extension - * that adds the 'layout' keyword. + * This is relaxed in GLSL 1.30 and GLSL ES 3.00. It is also relaxed by + * any extension that adds the 'layout' keyword. */ - if ((state->language_version < 130) + if (!state->is_version(130, 300) && !state->ARB_explicit_attrib_location_enable && !state->ARB_fragment_coord_conventions_enable) { if (this->type->qualifier.flags.q.out) { _mesa_glsl_error(& loc, state, "`out' qualifier in declaration of `%s' " "only valid for function parameters in %s.", - decl->identifier, state->version_string); + decl->identifier, state->get_version_string()); } if (this->type->qualifier.flags.q.in) { _mesa_glsl_error(& loc, state, "`in' qualifier in declaration of `%s' " "only valid for function parameters in %s.", - decl->identifier, state->version_string); + decl->identifier, state->get_version_string()); } /* FINISHME: Test for other invalid qualifiers. */ } @@ -2703,6 +2699,13 @@ ast_declarator_list::hir(exec_list *instructions, * "The attribute qualifier can be used only with float, * floating-point vectors, and matrices. Attribute variables * cannot be declared as arrays or structures." + * + * From page 33 (page 39 of the PDF) of the GLSL ES 3.00 spec: + * + * "Vertex shader inputs can only be float, floating-point + * vectors, matrices, signed and unsigned integers and integer + * vectors. Vertex shader inputs cannot be arrays or + * structures." */ const glsl_type *check_type = var->type->is_array() ? var->type->fields.array : var->type; @@ -2712,7 +2715,7 @@ ast_declarator_list::hir(exec_list *instructions, break; case GLSL_TYPE_UINT: case GLSL_TYPE_INT: - if (state->language_version > 120) + if (state->is_version(120, 300)) break; /* FALLTHROUGH */ default: @@ -2724,11 +2727,10 @@ ast_declarator_list::hir(exec_list *instructions, error_emitted = true; } - if (!error_emitted && (state->language_version <= 130) - && var->type->is_array()) { - _mesa_glsl_error(& loc, state, - "vertex shader input / attribute cannot have " - "array type"); + if (!error_emitted && var->type->is_array() && + !state->check_version(140, 0, &loc, + "vertex shader input / attribute " + "cannot have array type")) { error_emitted = true; } } @@ -2740,8 +2742,16 @@ ast_declarator_list::hir(exec_list *instructions, * "If a vertex output is a signed or unsigned integer or integer * vector, then it must be qualified with the interpolation qualifier * flat." + * + * From section 4.3.4 of the GLSL 3.00 ES spec: + * "Fragment shader inputs that are signed or unsigned integers or + * integer vectors must be qualified with the interpolation qualifier + * flat." + * + * Since vertex outputs and fragment inputs must have matching + * qualifiers, these two requirements are equivalent. */ - if (state->language_version >= 130 + if (state->is_version(130, 300) && state->target == vertex_shader && state->current_function == NULL && var->type->is_integer() @@ -2760,8 +2770,10 @@ ast_declarator_list::hir(exec_list *instructions, * "interpolation qualifiers may only precede the qualifiers in, * centroid in, out, or centroid out in a declaration. They do not apply * to the deprecated storage qualifiers varying or centroid varying." + * + * These deprecated storage qualifiers do not exist in GLSL ES 3.00. */ - if (state->language_version >= 130 + if (state->is_version(130, 0) && this->type->qualifier.has_interpolation() && this->type->qualifier.flags.q.varying) { @@ -2786,8 +2798,14 @@ ast_declarator_list::hir(exec_list *instructions, * "Outputs from a vertex shader (out) and inputs to a fragment * shader (in) can be further qualified with one or more of these * interpolation qualifiers" + * + * From page 31 (page 37 of the PDF) of the GLSL ES 3.00 spec: + * "These interpolation qualifiers may only precede the qualifiers + * in, centroid in, out, or centroid out in a declaration. They do + * not apply to inputs into a vertex shader or outputs from a + * fragment shader." */ - if (state->language_version >= 130 + if (state->is_version(130, 300) && this->type->qualifier.has_interpolation()) { const char *i = this->type->qualifier.interpolation_string(); @@ -2816,8 +2834,12 @@ ast_declarator_list::hir(exec_list *instructions, /* From section 4.3.4 of the GLSL 1.30 spec: * "It is an error to use centroid in in a vertex shader." + * + * From section 4.3.4 of the GLSL ES 3.00 spec: + * "It is an error to use centroid in or interpolation qualifiers in + * a vertex shader input." */ - if (state->language_version >= 130 + if (state->is_version(130, 300) && this->type->qualifier.flags.q.centroid && this->type->qualifier.flags.q.in && state->target == vertex_shader) { @@ -2829,13 +2851,8 @@ ast_declarator_list::hir(exec_list *instructions, /* Precision qualifiers exists only in GLSL versions 1.00 and >= 1.30. */ - if (this->type->specifier->precision != ast_precision_none - && state->language_version != 100 - && state->language_version < 130) { - - _mesa_glsl_error(&loc, state, - "precision qualifiers are supported only in GLSL ES " - "1.00, and GLSL 1.30 and later"); + if (this->type->specifier->precision != ast_precision_none) { + state->check_precision_qualifiers_allowed(&loc); } @@ -3077,8 +3094,9 @@ ast_parameter_declarator::hir(exec_list *instructions, * allowed. This restriction is removed in GLSL 1.20, and in GLSL ES. */ if ((var->mode == ir_var_inout || var->mode == ir_var_out) - && type->is_array() && state->language_version == 110) { - _mesa_glsl_error(&loc, state, "Arrays cannot be out or inout parameters in GLSL 1.10"); + && type->is_array() + && !state->check_version(120, 100, &loc, + "Arrays cannot be out or inout parameters")) { type = glsl_type::error_type; } @@ -3161,7 +3179,8 @@ ast_function::hir(exec_list *instructions, * * Note that this language does not appear in GLSL 1.10. */ - if ((state->current_function != NULL) && (state->language_version != 110)) { + if ((state->current_function != NULL) && + state->is_version(120, 100)) { YYLTYPE loc = this->get_location(); _mesa_glsl_error(&loc, state, "declaration of function `%s' not allowed within " @@ -3872,11 +3891,7 @@ ast_type_specifier::hir(exec_list *instructions, YYLTYPE loc = this->get_location(); if (this->precision != ast_precision_none - && state->language_version != 100 - && state->language_version < 130) { - _mesa_glsl_error(&loc, state, - "precision qualifiers exist only in " - "GLSL ES 1.00, and GLSL 1.30 and later"); + && !state->check_precision_qualifiers_allowed(&loc)) { return NULL; } if (this->precision != ast_precision_none diff --git a/mesalib/src/glsl/builtin_compiler/Makefile.am b/mesalib/src/glsl/builtin_compiler/Makefile.am index d6f85a7f4..d27aca555 100644 --- a/mesalib/src/glsl/builtin_compiler/Makefile.am +++ b/mesalib/src/glsl/builtin_compiler/Makefile.am @@ -55,7 +55,8 @@ builtin_compiler_SOURCES = \ $(GLSL_BUILDDIR)/glsl_parser.cc \ $(LIBGLSL_FILES) \ $(LIBGLSL_CXX_FILES) \ - $(top_srcdir)/src/mesa/program/hash_table.c \ + $(top_srcdir)/src/mesa/main/hash_table.c \ + $(top_srcdir)/src/mesa/program/prog_hash_table.c \ $(top_srcdir)/src/mesa/program/symbol_table.c \ $(GLSL_COMPILER_CXX_FILES) \ builtin_stubs.cpp diff --git a/mesalib/src/glsl/builtin_types.h b/mesalib/src/glsl/builtin_types.h index 92427d8e7..a4c995fd1 100644 --- a/mesalib/src/glsl/builtin_types.h +++ b/mesalib/src/glsl/builtin_types.h @@ -31,6 +31,11 @@ const glsl_type glsl_type::_sampler3D_type = glsl_type(GL_SAMPLER_3D, GLSL_SAMPLER_DIM_3D, 0, 0, GLSL_TYPE_FLOAT, "sampler3D"); +const glsl_type glsl_type::_samplerCubeShadow_type = + glsl_type(GL_SAMPLER_CUBE_SHADOW, + GLSL_SAMPLER_DIM_CUBE, 1, 0, GLSL_TYPE_FLOAT, + "samplerCubeShadow"); + const glsl_type *const glsl_type::error_type = & glsl_type::_error_type; const glsl_type *const glsl_type::void_type = & glsl_type::_void_type; diff --git a/mesalib/src/glsl/builtin_variables.cpp b/mesalib/src/glsl/builtin_variables.cpp index 353805b7f..e7769419f 100644 --- a/mesalib/src/glsl/builtin_variables.cpp +++ b/mesalib/src/glsl/builtin_variables.cpp @@ -61,6 +61,17 @@ static const builtin_variable builtin_100ES_fs_variables[] = { { ir_var_in, FRAG_ATTRIB_PNTC, "vec2", "gl_PointCoord" }, }; +static const builtin_variable builtin_300ES_vs_variables[] = { + { ir_var_system_value, SYSTEM_VALUE_VERTEX_ID, "int", "gl_VertexID" }, +}; + +static const builtin_variable builtin_300ES_fs_variables[] = { + { ir_var_in, FRAG_ATTRIB_WPOS, "vec4", "gl_FragCoord" }, + { ir_var_in, FRAG_ATTRIB_FACE, "bool", "gl_FrontFacing" }, + { ir_var_out, FRAG_RESULT_DEPTH, "float", "gl_FragDepth" }, + { ir_var_in, FRAG_ATTRIB_PNTC, "vec2", "gl_PointCoord" }, +}; + static const builtin_variable builtin_110_fs_variables[] = { { ir_var_out, FRAG_RESULT_DEPTH, "float", "gl_FragDepth" }, }; @@ -499,12 +510,15 @@ add_builtin_constant(exec_list *instructions, glsl_symbol_table *symtab, return var; } -/* Several constants in GLSL ES have different names than normal desktop GLSL. +/** + * Uniforms that are common to all GLSL ES implementations. + * + * Several constants in GLSL ES have different names than normal desktop GLSL. * Therefore, this function should only be called on the ES path. */ static void -generate_100ES_uniforms(exec_list *instructions, - struct _mesa_glsl_parse_state *state) +generate_common_ES_uniforms(exec_list *instructions, + struct _mesa_glsl_parse_state *state) { glsl_symbol_table *const symtab = state->symbols; @@ -512,8 +526,6 @@ generate_100ES_uniforms(exec_list *instructions, state->Const.MaxVertexAttribs); add_builtin_constant(instructions, symtab, "gl_MaxVertexUniformVectors", state->Const.MaxVertexUniformComponents); - add_builtin_constant(instructions, symtab, "gl_MaxVaryingVectors", - state->Const.MaxVaryingFloats / 4); add_builtin_constant(instructions, symtab, "gl_MaxVertexTextureImageUnits", state->Const.MaxVertexTextureImageUnits); add_builtin_constant(instructions, symtab, "gl_MaxCombinedTextureImageUnits", @@ -528,6 +540,36 @@ generate_100ES_uniforms(exec_list *instructions, } static void +generate_100ES_uniforms(exec_list *instructions, + struct _mesa_glsl_parse_state *state) +{ + generate_common_ES_uniforms(instructions, state); + + glsl_symbol_table *const symtab = state->symbols; + + add_builtin_constant(instructions, symtab, "gl_MaxVaryingVectors", + state->Const.MaxVaryingFloats / 4); +} + +static void +generate_300ES_uniforms(exec_list *instructions, + struct _mesa_glsl_parse_state *state) +{ + generate_common_ES_uniforms(instructions, state); + + glsl_symbol_table *const symtab = state->symbols; + + add_builtin_constant(instructions, symtab, "gl_MaxVertexOutputVectors", + state->Const.MaxVaryingFloats / 4); + add_builtin_constant(instructions, symtab, "gl_MaxFragmentInputVectors", + state->Const.MaxVaryingFloats / 4); + add_builtin_constant(instructions, symtab, "gl_MinProgramTexelOffset", + state->Const.MinProgramTexelOffset); + add_builtin_constant(instructions, symtab, "gl_MaxProgramTexelOffset", + state->Const.MaxProgramTexelOffset); +} + +static void generate_110_uniforms(exec_list *instructions, struct _mesa_glsl_parse_state *state, bool add_deprecated) @@ -657,6 +699,26 @@ generate_100ES_vs_variables(exec_list *instructions, vertex_shader); } +static void +generate_300ES_vs_variables(exec_list *instructions, + struct _mesa_glsl_parse_state *state) +{ + for (unsigned i = 0; i < Elements(builtin_core_vs_variables); i++) { + add_builtin_variable(instructions, state->symbols, + & builtin_core_vs_variables[i]); + } + + for (unsigned i = 0; i < Elements(builtin_300ES_vs_variables); i++) { + add_builtin_variable(instructions, state->symbols, + & builtin_300ES_vs_variables[i]); + } + + generate_300ES_uniforms(instructions, state); + + generate_ARB_draw_buffers_variables(instructions, state, false, + vertex_shader); +} + static void generate_110_vs_variables(exec_list *instructions, @@ -760,23 +822,36 @@ static void initialize_vs_variables(exec_list *instructions, struct _mesa_glsl_parse_state *state) { - - switch (state->language_version) { - case 100: - generate_100ES_vs_variables(instructions, state); - break; - case 110: - generate_110_vs_variables(instructions, state, true); - break; - case 120: - generate_120_vs_variables(instructions, state, true); - break; - case 130: - generate_130_vs_variables(instructions, state, true); - break; - case 140: - generate_130_vs_variables(instructions, state, false); - break; + if (state->es_shader) { + switch (state->language_version) { + case 100: + generate_100ES_vs_variables(instructions, state); + break; + case 300: + generate_300ES_vs_variables(instructions, state); + break; + default: + assert(!"Unexpected language version"); + break; + } + } else { + switch (state->language_version) { + case 110: + generate_110_vs_variables(instructions, state, true); + break; + case 120: + generate_120_vs_variables(instructions, state, true); + break; + case 130: + generate_130_vs_variables(instructions, state, true); + break; + case 140: + generate_130_vs_variables(instructions, state, false); + break; + default: + assert(!"Unexpected language version"); + break; + } } generate_ARB_draw_instanced_variables(instructions, state, false, @@ -806,6 +881,25 @@ generate_100ES_fs_variables(exec_list *instructions, } static void +generate_300ES_fs_variables(exec_list *instructions, + struct _mesa_glsl_parse_state *state) +{ + /* Note: we don't add builtin_core_fs_variables, because it contains + * gl_FragColor, which is not in GLSL 3.00 ES. + */ + + for (unsigned i = 0; i < Elements(builtin_300ES_fs_variables); i++) { + add_builtin_variable(instructions, state->symbols, + & builtin_300ES_fs_variables[i]); + } + + generate_300ES_uniforms(instructions, state); + + generate_ARB_draw_buffers_variables(instructions, state, false, + fragment_shader); +} + +static void generate_110_fs_variables(exec_list *instructions, struct _mesa_glsl_parse_state *state, bool add_deprecated) @@ -865,8 +959,9 @@ generate_ARB_draw_buffers_variables(exec_list *instructions, mdb->warn_extension = "GL_ARB_draw_buffers"; /* gl_FragData is only available in the fragment shader. + * It is not present in GLSL 3.00 ES. */ - if (target == fragment_shader) { + if (target == fragment_shader && !state->is_version(0, 300)) { const glsl_type *const vec4_array_type = glsl_type::get_array_instance(glsl_type::vec4_type, state->Const.MaxDrawBuffers); @@ -903,7 +998,8 @@ generate_ARB_draw_instanced_variables(exec_list *instructions, inst->warn_extension = "GL_ARB_draw_instanced"; } - if (state->ARB_draw_instanced_enable || state->language_version >= 140) { + bool available_in_core = state->is_version(140, 300); + if (state->ARB_draw_instanced_enable || available_in_core) { /* Originally ARB_draw_instanced only specified that ARB decorated name. * Since no vendor actually implemented that behavior and some apps use * the undecorated name, the extension now specifies that both names are @@ -914,7 +1010,7 @@ generate_ARB_draw_instanced_variables(exec_list *instructions, "gl_InstanceID", glsl_type::int_type, ir_var_system_value, SYSTEM_VALUE_INSTANCE_ID); - if (state->language_version < 140 && warn) + if (!available_in_core && warn) inst->warn_extension = "GL_ARB_draw_instanced"; } } @@ -1016,23 +1112,36 @@ static void initialize_fs_variables(exec_list *instructions, struct _mesa_glsl_parse_state *state) { - - switch (state->language_version) { - case 100: - generate_100ES_fs_variables(instructions, state); - break; - case 110: - generate_110_fs_variables(instructions, state, true); - break; - case 120: - generate_120_fs_variables(instructions, state, true); - break; - case 130: - generate_130_fs_variables(instructions, state); - break; - case 140: - generate_140_fs_variables(instructions, state); - break; + if (state->es_shader) { + switch (state->language_version) { + case 100: + generate_100ES_fs_variables(instructions, state); + break; + case 300: + generate_300ES_fs_variables(instructions, state); + break; + default: + assert(!"Unexpected language version"); + break; + } + } else { + switch (state->language_version) { + case 110: + generate_110_fs_variables(instructions, state, true); + break; + case 120: + generate_120_fs_variables(instructions, state, true); + break; + case 130: + generate_130_fs_variables(instructions, state); + break; + case 140: + generate_140_fs_variables(instructions, state); + break; + default: + assert(!"Unexpected language version"); + break; + } } if (state->ARB_shader_stencil_export_enable) diff --git a/mesalib/src/glsl/glcpp/Makefile.am b/mesalib/src/glsl/glcpp/Makefile.am index 04d8cda01..d8d39d295 100644 --- a/mesalib/src/glsl/glcpp/Makefile.am +++ b/mesalib/src/glsl/glcpp/Makefile.am @@ -46,7 +46,7 @@ libglcpp_la_SOURCES = \ glcpp_SOURCES = \ ../ralloc.c \ - $(top_srcdir)/src/mesa/program/hash_table.c \ + $(top_srcdir)/src/mesa/program/prog_hash_table.c \ glcpp.c glcpp_LDADD = libglcpp.la diff --git a/mesalib/src/glsl/glcpp/glcpp-parse.y b/mesalib/src/glsl/glcpp/glcpp-parse.y index e7daf7fea..380a1d99c 100644 --- a/mesalib/src/glsl/glcpp/glcpp-parse.y +++ b/mesalib/src/glsl/glcpp/glcpp-parse.y @@ -133,6 +133,10 @@ _glcpp_parser_skip_stack_change_if (glcpp_parser_t *parser, YYLTYPE *loc, static void _glcpp_parser_skip_stack_pop (glcpp_parser_t *parser, YYLTYPE *loc); +static void +_glcpp_parser_handle_version_declaration(glcpp_parser_t *parser, intmax_t version, + const char *ident); + static int glcpp_parser_lex (YYSTYPE *yylval, YYLTYPE *yylloc, glcpp_parser_t *parser); @@ -334,25 +338,10 @@ control_line: _glcpp_parser_skip_stack_pop (parser, & @1); } NEWLINE | HASH_VERSION integer_constant NEWLINE { - macro_t *macro = hash_table_find (parser->defines, "__VERSION__"); - if (macro) { - hash_table_remove (parser->defines, "__VERSION__"); - ralloc_free (macro); - } - add_builtin_define (parser, "__VERSION__", $2); - - if ($2 == 100) - add_builtin_define (parser, "GL_ES", 1); - - /* Currently, all ES2 implementations support highp in the - * fragment shader, so we always define this macro in ES2. - * If we ever get a driver that doesn't support highp, we'll - * need to add a flag to the gl_context and check that here. - */ - if ($2 >= 130 || $2 == 100) - add_builtin_define (parser, "GL_FRAGMENT_PRECISION_HIGH", 1); - - ralloc_asprintf_rewrite_tail (&parser->output, &parser->output_length, "#version %" PRIiMAX, $2); + _glcpp_parser_handle_version_declaration(parser, $2, NULL); + } +| HASH_VERSION integer_constant IDENTIFIER NEWLINE { + _glcpp_parser_handle_version_declaration(parser, $2, $3); } | HASH NEWLINE ; @@ -2032,3 +2021,38 @@ _glcpp_parser_skip_stack_pop (glcpp_parser_t *parser, YYLTYPE *loc) parser->skip_stack = node->next; ralloc_free (node); } + +static void +_glcpp_parser_handle_version_declaration(glcpp_parser_t *parser, intmax_t version, + const char *es_identifier) +{ + /* Note: We assume that if any identifier is present, it means ES. + * The GLSL parser will double-check that the identifier is correct. + */ + bool is_es = es_identifier != NULL; + + macro_t *macro = hash_table_find (parser->defines, "__VERSION__"); + if (macro) { + hash_table_remove (parser->defines, "__VERSION__"); + ralloc_free (macro); + } + add_builtin_define (parser, "__VERSION__", version); + + if (version == 100) + is_es = true; + if (is_es) + add_builtin_define (parser, "GL_ES", 1); + + /* Currently, all ES2/ES3 implementations support highp in the + * fragment shader, so we always define this macro in ES2/ES3. + * If we ever get a driver that doesn't support highp, we'll + * need to add a flag to the gl_context and check that here. + */ + if (version >= 130 || is_es) + add_builtin_define (parser, "GL_FRAGMENT_PRECISION_HIGH", 1); + + ralloc_asprintf_rewrite_tail (&parser->output, &parser->output_length, + "#version %" PRIiMAX "%s%s", version, + es_identifier ? " " : "", + es_identifier ? es_identifier : ""); +} diff --git a/mesalib/src/glsl/glsl_lexer.ll b/mesalib/src/glsl/glsl_lexer.ll index c538d7d8e..2f66c5828 100644 --- a/mesalib/src/glsl/glsl_lexer.ll +++ b/mesalib/src/glsl/glsl_lexer.ll @@ -48,20 +48,34 @@ static int classify_identifier(struct _mesa_glsl_parse_state *, const char *); * * Certain words start out as identifiers, become reserved words in * later language revisions, and finally become language keywords. + * This may happen at different times in desktop GLSL and GLSL ES. * * For example, consider the following lexer rule: - * samplerBuffer KEYWORD(130, 140, SAMPLERBUFFER) + * samplerBuffer KEYWORD(130, 0, 140, 0, SAMPLERBUFFER) * * This means that "samplerBuffer" will be treated as: * - a keyword (SAMPLERBUFFER token) ...in GLSL >= 1.40 * - a reserved word - error ...in GLSL >= 1.30 - * - an identifier ...in GLSL < 1.30 + * - an identifier ...in GLSL < 1.30 or GLSL ES */ -#define KEYWORD(reserved_version, allowed_version, token) \ +#define KEYWORD(reserved_glsl, reserved_glsl_es, \ + allowed_glsl, allowed_glsl_es, token) \ + KEYWORD_WITH_ALT(reserved_glsl, reserved_glsl_es, \ + allowed_glsl, allowed_glsl_es, false, token) + +/** + * Like the KEYWORD macro, but the word is also treated as a keyword + * if the given boolean expression is true. + */ +#define KEYWORD_WITH_ALT(reserved_glsl, reserved_glsl_es, \ + allowed_glsl, allowed_glsl_es, \ + alt_expr, token) \ do { \ - if (yyextra->language_version >= allowed_version) { \ + if (yyextra->is_version(allowed_glsl, allowed_glsl_es) \ + || alt_expr) { \ return token; \ - } else if (yyextra->language_version >= reserved_version) { \ + } else if (yyextra->is_version(reserved_glsl, \ + reserved_glsl_es)) { \ _mesa_glsl_error(yylloc, yyextra, \ "Illegal use of reserved word `%s'", yytext); \ return ERROR_TOK; \ @@ -71,15 +85,20 @@ static int classify_identifier(struct _mesa_glsl_parse_state *, const char *); } \ } while (0) -/* The ES macro can be used in KEYWORD checks: - * - * word KEYWORD(110 || ES, 400, TOKEN) - * ...means the word is reserved in GLSL ES 1.00, while - * - * word KEYWORD(110, 130 || ES, TOKEN) - * ...means the word is a legal keyword in GLSL ES 1.00. +/** + * A macro for handling keywords that have been present in GLSL since + * its origin, but were changed into reserved words in GLSL 3.00 ES. */ -#define ES yyextra->es_shader +#define DEPRECATED_ES_KEYWORD(token) \ + do { \ + if (yyextra->is_version(0, 300)) { \ + _mesa_glsl_error(yylloc, yyextra, \ + "Illegal use of reserved word `%s'", yytext); \ + return ERROR_TOK; \ + } else { \ + return token; \ + } \ + } while (0) static int literal_integer(char *text, int len, struct _mesa_glsl_parse_state *state, @@ -103,7 +122,7 @@ literal_integer(char *text, int len, struct _mesa_glsl_parse_state *state, if (value > UINT_MAX) { /* Note that signed 0xffffffff is valid, not out of range! */ - if (state->language_version >= 130) { + if (state->is_version(130, 300)) { _mesa_glsl_error(lloc, state, "Literal value `%s' out of range", text); } else { @@ -219,12 +238,12 @@ HASH ^{SPC}#{SPC} \n { yylineno++; yycolumn = 0; } -attribute return ATTRIBUTE; +attribute DEPRECATED_ES_KEYWORD(ATTRIBUTE); const return CONST_TOK; bool return BOOL_TOK; float return FLOAT_TOK; int return INT_TOK; -uint KEYWORD(130, 130, UINT_TOK); +uint KEYWORD(130, 300, 130, 300, UINT_TOK); break return BREAK; continue return CONTINUE; @@ -242,59 +261,59 @@ bvec4 return BVEC4; ivec2 return IVEC2; ivec3 return IVEC3; ivec4 return IVEC4; -uvec2 KEYWORD(130, 130, UVEC2); -uvec3 KEYWORD(130, 130, UVEC3); -uvec4 KEYWORD(130, 130, UVEC4); +uvec2 KEYWORD(130, 300, 130, 300, UVEC2); +uvec3 KEYWORD(130, 300, 130, 300, UVEC3); +uvec4 KEYWORD(130, 300, 130, 300, UVEC4); vec2 return VEC2; vec3 return VEC3; vec4 return VEC4; mat2 return MAT2X2; mat3 return MAT3X3; mat4 return MAT4X4; -mat2x2 KEYWORD(120, 120, MAT2X2); -mat2x3 KEYWORD(120, 120, MAT2X3); -mat2x4 KEYWORD(120, 120, MAT2X4); -mat3x2 KEYWORD(120, 120, MAT3X2); -mat3x3 KEYWORD(120, 120, MAT3X3); -mat3x4 KEYWORD(120, 120, MAT3X4); -mat4x2 KEYWORD(120, 120, MAT4X2); -mat4x3 KEYWORD(120, 120, MAT4X3); -mat4x4 KEYWORD(120, 120, MAT4X4); +mat2x2 KEYWORD(120, 300, 120, 300, MAT2X2); +mat2x3 KEYWORD(120, 300, 120, 300, MAT2X3); +mat2x4 KEYWORD(120, 300, 120, 300, MAT2X4); +mat3x2 KEYWORD(120, 300, 120, 300, MAT3X2); +mat3x3 KEYWORD(120, 300, 120, 300, MAT3X3); +mat3x4 KEYWORD(120, 300, 120, 300, MAT3X4); +mat4x2 KEYWORD(120, 300, 120, 300, MAT4X2); +mat4x3 KEYWORD(120, 300, 120, 300, MAT4X3); +mat4x4 KEYWORD(120, 300, 120, 300, MAT4X4); in return IN_TOK; out return OUT_TOK; inout return INOUT_TOK; uniform return UNIFORM; -varying return VARYING; -centroid KEYWORD(120, 120, CENTROID); -invariant KEYWORD(120 || ES, 120 || ES, INVARIANT); -flat KEYWORD(130 || ES, 130, FLAT); -smooth KEYWORD(130, 130, SMOOTH); -noperspective KEYWORD(130, 130, NOPERSPECTIVE); - -sampler1D return SAMPLER1D; +varying DEPRECATED_ES_KEYWORD(VARYING); +centroid KEYWORD(120, 300, 120, 300, CENTROID); +invariant KEYWORD(120, 100, 120, 100, INVARIANT); +flat KEYWORD(130, 100, 130, 300, FLAT); +smooth KEYWORD(130, 300, 130, 300, SMOOTH); +noperspective KEYWORD(130, 300, 130, 0, NOPERSPECTIVE); + +sampler1D DEPRECATED_ES_KEYWORD(SAMPLER1D); sampler2D return SAMPLER2D; sampler3D return SAMPLER3D; samplerCube return SAMPLERCUBE; -sampler1DArray KEYWORD(130, 130, SAMPLER1DARRAY); -sampler2DArray KEYWORD(130, 130, SAMPLER2DARRAY); -sampler1DShadow return SAMPLER1DSHADOW; +sampler1DArray KEYWORD(130, 300, 130, 0, SAMPLER1DARRAY); +sampler2DArray KEYWORD(130, 300, 130, 300, SAMPLER2DARRAY); +sampler1DShadow DEPRECATED_ES_KEYWORD(SAMPLER1DSHADOW); sampler2DShadow return SAMPLER2DSHADOW; -samplerCubeShadow KEYWORD(130, 130, SAMPLERCUBESHADOW); -sampler1DArrayShadow KEYWORD(130, 130, SAMPLER1DARRAYSHADOW); -sampler2DArrayShadow KEYWORD(130, 130, SAMPLER2DARRAYSHADOW); -isampler1D KEYWORD(130, 130, ISAMPLER1D); -isampler2D KEYWORD(130, 130, ISAMPLER2D); -isampler3D KEYWORD(130, 130, ISAMPLER3D); -isamplerCube KEYWORD(130, 130, ISAMPLERCUBE); -isampler1DArray KEYWORD(130, 130, ISAMPLER1DARRAY); -isampler2DArray KEYWORD(130, 130, ISAMPLER2DARRAY); -usampler1D KEYWORD(130, 130, USAMPLER1D); -usampler2D KEYWORD(130, 130, USAMPLER2D); -usampler3D KEYWORD(130, 130, USAMPLER3D); -usamplerCube KEYWORD(130, 130, USAMPLERCUBE); -usampler1DArray KEYWORD(130, 130, USAMPLER1DARRAY); -usampler2DArray KEYWORD(130, 130, USAMPLER2DARRAY); +samplerCubeShadow KEYWORD(130, 300, 130, 300, SAMPLERCUBESHADOW); +sampler1DArrayShadow KEYWORD(130, 300, 130, 0, SAMPLER1DARRAYSHADOW); +sampler2DArrayShadow KEYWORD(130, 300, 130, 300, SAMPLER2DARRAYSHADOW); +isampler1D KEYWORD(130, 300, 130, 0, ISAMPLER1D); +isampler2D KEYWORD(130, 300, 130, 300, ISAMPLER2D); +isampler3D KEYWORD(130, 300, 130, 300, ISAMPLER3D); +isamplerCube KEYWORD(130, 300, 130, 300, ISAMPLERCUBE); +isampler1DArray KEYWORD(130, 300, 130, 0, ISAMPLER1DARRAY); +isampler2DArray KEYWORD(130, 300, 130, 300, ISAMPLER2DARRAY); +usampler1D KEYWORD(130, 300, 130, 0, USAMPLER1D); +usampler2D KEYWORD(130, 300, 130, 300, USAMPLER2D); +usampler3D KEYWORD(130, 300, 130, 300, USAMPLER3D); +usamplerCube KEYWORD(130, 300, 130, 300, USAMPLERCUBE); +usampler1DArray KEYWORD(130, 300, 130, 0, USAMPLER1DARRAY); +usampler2DArray KEYWORD(130, 300, 130, 300, USAMPLER2DARRAY); samplerCubeArray { if (yyextra->ARB_texture_cube_map_array_enable) @@ -333,7 +352,7 @@ struct return STRUCT; void return VOID_TOK; layout { - if ((yyextra->language_version >= 140) + if ((yyextra->is_version(140, 300)) || yyextra->AMD_conservative_depth_enable || yyextra->ARB_conservative_depth_enable || yyextra->ARB_explicit_attrib_location_enable @@ -411,96 +430,114 @@ false { /* Reserved words in GLSL 1.10. */ -asm KEYWORD(110 || ES, 999, ASM); -class KEYWORD(110 || ES, 999, CLASS); -union KEYWORD(110 || ES, 999, UNION); -enum KEYWORD(110 || ES, 999, ENUM); -typedef KEYWORD(110 || ES, 999, TYPEDEF); -template KEYWORD(110 || ES, 999, TEMPLATE); -this KEYWORD(110 || ES, 999, THIS); -packed KEYWORD(110 || ES, 140 || yyextra->ARB_uniform_buffer_object_enable, PACKED_TOK); -goto KEYWORD(110 || ES, 999, GOTO); -switch KEYWORD(110 || ES, 130, SWITCH); -default KEYWORD(110 || ES, 130, DEFAULT); -inline KEYWORD(110 || ES, 999, INLINE_TOK); -noinline KEYWORD(110 || ES, 999, NOINLINE); -volatile KEYWORD(110 || ES, 999, VOLATILE); -public KEYWORD(110 || ES, 999, PUBLIC_TOK); -static KEYWORD(110 || ES, 999, STATIC); -extern KEYWORD(110 || ES, 999, EXTERN); -external KEYWORD(110 || ES, 999, EXTERNAL); -interface KEYWORD(110 || ES, 999, INTERFACE); -long KEYWORD(110 || ES, 999, LONG_TOK); -short KEYWORD(110 || ES, 999, SHORT_TOK); -double KEYWORD(110 || ES, 400, DOUBLE_TOK); -half KEYWORD(110 || ES, 999, HALF); -fixed KEYWORD(110 || ES, 999, FIXED_TOK); -unsigned KEYWORD(110 || ES, 999, UNSIGNED); -input KEYWORD(110 || ES, 999, INPUT_TOK); -output KEYWORD(110 || ES, 999, OUTPUT); -hvec2 KEYWORD(110 || ES, 999, HVEC2); -hvec3 KEYWORD(110 || ES, 999, HVEC3); -hvec4 KEYWORD(110 || ES, 999, HVEC4); -dvec2 KEYWORD(110 || ES, 400, DVEC2); -dvec3 KEYWORD(110 || ES, 400, DVEC3); -dvec4 KEYWORD(110 || ES, 400, DVEC4); -fvec2 KEYWORD(110 || ES, 999, FVEC2); -fvec3 KEYWORD(110 || ES, 999, FVEC3); -fvec4 KEYWORD(110 || ES, 999, FVEC4); -sampler2DRect return SAMPLER2DRECT; -sampler3DRect KEYWORD(110 || ES, 999, SAMPLER3DRECT); -sampler2DRectShadow return SAMPLER2DRECTSHADOW; -sizeof KEYWORD(110 || ES, 999, SIZEOF); -cast KEYWORD(110 || ES, 999, CAST); -namespace KEYWORD(110 || ES, 999, NAMESPACE); -using KEYWORD(110 || ES, 999, USING); +asm KEYWORD(110, 100, 0, 0, ASM); +class KEYWORD(110, 100, 0, 0, CLASS); +union KEYWORD(110, 100, 0, 0, UNION); +enum KEYWORD(110, 100, 0, 0, ENUM); +typedef KEYWORD(110, 100, 0, 0, TYPEDEF); +template KEYWORD(110, 100, 0, 0, TEMPLATE); +this KEYWORD(110, 100, 0, 0, THIS); +packed KEYWORD_WITH_ALT(110, 100, 140, 300, yyextra->ARB_uniform_buffer_object_enable, PACKED_TOK); +goto KEYWORD(110, 100, 0, 0, GOTO); +switch KEYWORD(110, 100, 130, 300, SWITCH); +default KEYWORD(110, 100, 130, 300, DEFAULT); +inline KEYWORD(110, 100, 0, 0, INLINE_TOK); +noinline KEYWORD(110, 100, 0, 0, NOINLINE); +volatile KEYWORD(110, 100, 0, 0, VOLATILE); +public KEYWORD(110, 100, 0, 0, PUBLIC_TOK); +static KEYWORD(110, 100, 0, 0, STATIC); +extern KEYWORD(110, 100, 0, 0, EXTERN); +external KEYWORD(110, 100, 0, 0, EXTERNAL); +interface KEYWORD(110, 100, 0, 0, INTERFACE); +long KEYWORD(110, 100, 0, 0, LONG_TOK); +short KEYWORD(110, 100, 0, 0, SHORT_TOK); +double KEYWORD(110, 100, 400, 0, DOUBLE_TOK); +half KEYWORD(110, 100, 0, 0, HALF); +fixed KEYWORD(110, 100, 0, 0, FIXED_TOK); +unsigned KEYWORD(110, 100, 0, 0, UNSIGNED); +input KEYWORD(110, 100, 0, 0, INPUT_TOK); +output KEYWORD(110, 100, 0, 0, OUTPUT); +hvec2 KEYWORD(110, 100, 0, 0, HVEC2); +hvec3 KEYWORD(110, 100, 0, 0, HVEC3); +hvec4 KEYWORD(110, 100, 0, 0, HVEC4); +dvec2 KEYWORD(110, 100, 400, 0, DVEC2); +dvec3 KEYWORD(110, 100, 400, 0, DVEC3); +dvec4 KEYWORD(110, 100, 400, 0, DVEC4); +fvec2 KEYWORD(110, 100, 0, 0, FVEC2); +fvec3 KEYWORD(110, 100, 0, 0, FVEC3); +fvec4 KEYWORD(110, 100, 0, 0, FVEC4); +sampler2DRect DEPRECATED_ES_KEYWORD(SAMPLER2DRECT); +sampler3DRect KEYWORD(110, 100, 0, 0, SAMPLER3DRECT); +sampler2DRectShadow DEPRECATED_ES_KEYWORD(SAMPLER2DRECTSHADOW); +sizeof KEYWORD(110, 100, 0, 0, SIZEOF); +cast KEYWORD(110, 100, 0, 0, CAST); +namespace KEYWORD(110, 100, 0, 0, NAMESPACE); +using KEYWORD(110, 100, 0, 0, USING); /* Additional reserved words in GLSL 1.20. */ -lowp KEYWORD(120, 130 || ES, LOWP); -mediump KEYWORD(120, 130 || ES, MEDIUMP); -highp KEYWORD(120, 130 || ES, HIGHP); -precision KEYWORD(120, 130 || ES, PRECISION); +lowp KEYWORD(120, 100, 130, 100, LOWP); +mediump KEYWORD(120, 100, 130, 100, MEDIUMP); +highp KEYWORD(120, 100, 130, 100, HIGHP); +precision KEYWORD(120, 100, 130, 100, PRECISION); /* Additional reserved words in GLSL 1.30. */ -case KEYWORD(130, 130, CASE); -common KEYWORD(130, 999, COMMON); -partition KEYWORD(130, 999, PARTITION); -active KEYWORD(130, 999, ACTIVE); -superp KEYWORD(130 || ES, 999, SUPERP); -samplerBuffer KEYWORD(130, 140, SAMPLERBUFFER); -filter KEYWORD(130, 999, FILTER); -image1D KEYWORD(130, 999, IMAGE1D); -image2D KEYWORD(130, 999, IMAGE2D); -image3D KEYWORD(130, 999, IMAGE3D); -imageCube KEYWORD(130, 999, IMAGECUBE); -iimage1D KEYWORD(130, 999, IIMAGE1D); -iimage2D KEYWORD(130, 999, IIMAGE2D); -iimage3D KEYWORD(130, 999, IIMAGE3D); -iimageCube KEYWORD(130, 999, IIMAGECUBE); -uimage1D KEYWORD(130, 999, UIMAGE1D); -uimage2D KEYWORD(130, 999, UIMAGE2D); -uimage3D KEYWORD(130, 999, UIMAGE3D); -uimageCube KEYWORD(130, 999, UIMAGECUBE); -image1DArray KEYWORD(130, 999, IMAGE1DARRAY); -image2DArray KEYWORD(130, 999, IMAGE2DARRAY); -iimage1DArray KEYWORD(130, 999, IIMAGE1DARRAY); -iimage2DArray KEYWORD(130, 999, IIMAGE2DARRAY); -uimage1DArray KEYWORD(130, 999, UIMAGE1DARRAY); -uimage2DArray KEYWORD(130, 999, UIMAGE2DARRAY); -image1DShadow KEYWORD(130, 999, IMAGE1DSHADOW); -image2DShadow KEYWORD(130, 999, IMAGE2DSHADOW); -image1DArrayShadow KEYWORD(130, 999, IMAGE1DARRAYSHADOW); -image2DArrayShadow KEYWORD(130, 999, IMAGE2DARRAYSHADOW); -imageBuffer KEYWORD(130, 999, IMAGEBUFFER); -iimageBuffer KEYWORD(130, 999, IIMAGEBUFFER); -uimageBuffer KEYWORD(130, 999, UIMAGEBUFFER); -row_major KEYWORD(130, 140 || yyextra->ARB_uniform_buffer_object_enable, ROW_MAJOR); +case KEYWORD(130, 300, 130, 300, CASE); +common KEYWORD(130, 300, 0, 0, COMMON); +partition KEYWORD(130, 300, 0, 0, PARTITION); +active KEYWORD(130, 300, 0, 0, ACTIVE); +superp KEYWORD(130, 100, 0, 0, SUPERP); +samplerBuffer KEYWORD(130, 300, 140, 0, SAMPLERBUFFER); +filter KEYWORD(130, 300, 0, 0, FILTER); +image1D KEYWORD(130, 300, 0, 0, IMAGE1D); +image2D KEYWORD(130, 300, 0, 0, IMAGE2D); +image3D KEYWORD(130, 300, 0, 0, IMAGE3D); +imageCube KEYWORD(130, 300, 0, 0, IMAGECUBE); +iimage1D KEYWORD(130, 300, 0, 0, IIMAGE1D); +iimage2D KEYWORD(130, 300, 0, 0, IIMAGE2D); +iimage3D KEYWORD(130, 300, 0, 0, IIMAGE3D); +iimageCube KEYWORD(130, 300, 0, 0, IIMAGECUBE); +uimage1D KEYWORD(130, 300, 0, 0, UIMAGE1D); +uimage2D KEYWORD(130, 300, 0, 0, UIMAGE2D); +uimage3D KEYWORD(130, 300, 0, 0, UIMAGE3D); +uimageCube KEYWORD(130, 300, 0, 0, UIMAGECUBE); +image1DArray KEYWORD(130, 300, 0, 0, IMAGE1DARRAY); +image2DArray KEYWORD(130, 300, 0, 0, IMAGE2DARRAY); +iimage1DArray KEYWORD(130, 300, 0, 0, IIMAGE1DARRAY); +iimage2DArray KEYWORD(130, 300, 0, 0, IIMAGE2DARRAY); +uimage1DArray KEYWORD(130, 300, 0, 0, UIMAGE1DARRAY); +uimage2DArray KEYWORD(130, 300, 0, 0, UIMAGE2DARRAY); +image1DShadow KEYWORD(130, 300, 0, 0, IMAGE1DSHADOW); +image2DShadow KEYWORD(130, 300, 0, 0, IMAGE2DSHADOW); +image1DArrayShadow KEYWORD(130, 300, 0, 0, IMAGE1DARRAYSHADOW); +image2DArrayShadow KEYWORD(130, 300, 0, 0, IMAGE2DARRAYSHADOW); +imageBuffer KEYWORD(130, 300, 0, 0, IMAGEBUFFER); +iimageBuffer KEYWORD(130, 300, 0, 0, IIMAGEBUFFER); +uimageBuffer KEYWORD(130, 300, 0, 0, UIMAGEBUFFER); +row_major KEYWORD_WITH_ALT(130, 0, 140, 0, yyextra->ARB_uniform_buffer_object_enable, ROW_MAJOR); /* Additional reserved words in GLSL 1.40 */ -isampler2DRect KEYWORD(140, 140, ISAMPLER2DRECT); -usampler2DRect KEYWORD(140, 140, USAMPLER2DRECT); -isamplerBuffer KEYWORD(140, 140, ISAMPLERBUFFER); -usamplerBuffer KEYWORD(140, 140, USAMPLERBUFFER); +isampler2DRect KEYWORD(140, 300, 140, 0, ISAMPLER2DRECT); +usampler2DRect KEYWORD(140, 300, 140, 0, USAMPLER2DRECT); +isamplerBuffer KEYWORD(140, 300, 140, 0, ISAMPLERBUFFER); +usamplerBuffer KEYWORD(140, 300, 140, 0, USAMPLERBUFFER); + + /* Additional reserved words in GLSL ES 3.00 */ +coherent KEYWORD(0, 300, 0, 0, COHERENT); +restrict KEYWORD(0, 300, 0, 0, RESTRICT); +readonly KEYWORD(0, 300, 0, 0, READONLY); +writeonly KEYWORD(0, 300, 0, 0, WRITEONLY); +resource KEYWORD(0, 300, 0, 0, RESOURCE); +atomic_uint KEYWORD(0, 300, 0, 0, ATOMIC_UINT); +patch KEYWORD(0, 300, 0, 0, PATCH); +sample KEYWORD(0, 300, 0, 0, SAMPLE); +subroutine KEYWORD(0, 300, 0, 0, SUBROUTINE); +sampler2DMS KEYWORD(0, 300, 0, 0, SAMPLER2DMS); +isampler2DMS KEYWORD(0, 300, 0, 0, ISAMPLER2DMS); +usampler2DMS KEYWORD(0, 300, 0, 0, USAMPLER2DMS); +sampler2DMSArray KEYWORD(0, 300, 0, 0, SAMPLER2DMSARRAY); +isampler2DMSArray KEYWORD(0, 300, 0, 0, ISAMPLER2DMSARRAY); +usampler2DMSArray KEYWORD(0, 300, 0, 0, USAMPLER2DMSARRAY); + [_a-zA-Z][_a-zA-Z0-9]* { struct _mesa_glsl_parse_state *state = yyextra; diff --git a/mesalib/src/glsl/glsl_parser.yy b/mesalib/src/glsl/glsl_parser.yy index 407dbbeeb..d8494667b 100644 --- a/mesalib/src/glsl/glsl_parser.yy +++ b/mesalib/src/glsl/glsl_parser.yy @@ -137,6 +137,9 @@ static void yyerror(YYLTYPE *loc, _mesa_glsl_parse_state *st, const char *msg) %token HVEC2 HVEC3 HVEC4 DVEC2 DVEC3 DVEC4 FVEC2 FVEC3 FVEC4 %token SAMPLER3DRECT %token SIZEOF CAST NAMESPACE USING +%token COHERENT RESTRICT READONLY WRITEONLY RESOURCE ATOMIC_UINT PATCH SAMPLE +%token SUBROUTINE SAMPLER2DMS ISAMPLER2DMS USAMPLER2DMS SAMPLER2DMSARRAY +%token ISAMPLER2DMSARRAY USAMPLER2DMSARRAY %token ERROR_TOK @@ -258,54 +261,12 @@ version_statement: /* blank - no #version specified: defaults are already set */ | VERSION_TOK INTCONSTANT EOL { - bool supported = false; - - switch ($2) { - case 100: - state->es_shader = true; - supported = state->ctx->API == API_OPENGLES2 || - state->ctx->Extensions.ARB_ES2_compatibility; - break; - case 110: - case 120: - /* FINISHME: Once the OpenGL 3.0 'forward compatible' context or - * the OpenGL 3.2 Core context is supported, this logic will need - * change. Older versions of GLSL are no longer supported - * outside the compatibility contexts of 3.x. - */ - case 130: - case 140: - case 150: - case 330: - case 400: - case 410: - case 420: - supported = _mesa_is_desktop_gl(state->ctx) && - ((unsigned) $2) <= state->ctx->Const.GLSLVersion; - break; - default: - supported = false; - break; - } - - state->language_version = $2; - state->version_string = - ralloc_asprintf(state, "GLSL%s %d.%02d", - state->es_shader ? " ES" : "", - state->language_version / 100, - state->language_version % 100); - - if (!supported) { - _mesa_glsl_error(& @2, state, "%s is not supported. " - "Supported versions are: %s\n", - state->version_string, - state->supported_version_string); - } - - if (state->language_version >= 140) { - state->ARB_uniform_buffer_object_enable = true; - } + state->process_version_directive(&@2, $2, NULL); } + | VERSION_TOK INTCONSTANT any_identifier EOL + { + state->process_version_directive(&@2, $2, $3); + } ; pragma_statement: @@ -315,10 +276,11 @@ pragma_statement: | PRAGMA_OPTIMIZE_OFF EOL | PRAGMA_INVARIANT_ALL EOL { - if (state->language_version == 110) { + if (!state->is_version(120, 100)) { _mesa_glsl_warning(& @1, state, - "pragma `invariant(all)' not supported in %s", - state->version_string); + "pragma `invariant(all)' not supported in %s " + "(GLSL ES 1.00 or GLSL 1.20 required).", + state->get_version_string()); } else { state->all_invariant = true; } @@ -1126,6 +1088,7 @@ layout_qualifier_id_list: integer_constant: INTCONSTANT { $$ = $1; } | UINTCONSTANT { $$ = $1; } + ; layout_qualifier_id: any_identifier @@ -1181,6 +1144,8 @@ layout_qualifier_id: $$.flags.q.shared = 1; } else if (strcmp($1, "column_major") == 0) { $$.flags.q.column_major = 1; + } else if (strcmp($1, "row_major") == 0) { + $$.flags.q.row_major = 1; } if ($$.flags.i && state->ARB_uniform_buffer_object_warn) { @@ -1498,32 +1463,17 @@ basic_type_specifier_nonarray: precision_qualifier: HIGHP { - if (!state->es_shader && state->language_version < 130) - _mesa_glsl_error(& @1, state, - "precision qualifier forbidden " - "in %s (1.30 or later " - "required)\n", - state->version_string); + state->check_precision_qualifiers_allowed(&@1); $$ = ast_precision_high; } | MEDIUMP { - if (!state->es_shader && state->language_version < 130) - _mesa_glsl_error(& @1, state, - "precision qualifier forbidden " - "in %s (1.30 or later " - "required)\n", - state->version_string); + state->check_precision_qualifiers_allowed(&@1); $$ = ast_precision_medium; } | LOWP { - if (!state->es_shader && state->language_version < 130) - _mesa_glsl_error(& @1, state, - "precision qualifier forbidden " - "in %s (1.30 or later " - "required)\n", - state->version_string); + state->check_precision_qualifiers_allowed(&@1); $$ = ast_precision_low; } diff --git a/mesalib/src/glsl/glsl_parser_extras.cpp b/mesalib/src/glsl/glsl_parser_extras.cpp index f1fdd3a47..d36089226 100644 --- a/mesalib/src/glsl/glsl_parser_extras.cpp +++ b/mesalib/src/glsl/glsl_parser_extras.cpp @@ -37,6 +37,16 @@ extern "C" { #include "ir_optimization.h" #include "loop_analysis.h" +/** + * Format a short human-readable description of the given GLSL version. + */ +const char * +glsl_compute_version_string(void *mem_ctx, bool is_es, unsigned version) +{ + return ralloc_asprintf(mem_ctx, "GLSL%s %d.%02d", is_es ? " ES" : "", + version / 100, version % 100); +} + _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx, GLenum target, void *mem_ctx) : ctx(_ctx) @@ -82,6 +92,8 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx, this->Const.MaxCombinedTextureImageUnits = ctx->Const.MaxCombinedTextureImageUnits; this->Const.MaxTextureImageUnits = ctx->Const.MaxTextureImageUnits; this->Const.MaxFragmentUniformComponents = ctx->Const.FragmentProgram.MaxUniformComponents; + this->Const.MinProgramTexelOffset = ctx->Const.MinProgramTexelOffset; + this->Const.MaxProgramTexelOffset = ctx->Const.MaxProgramTexelOffset; this->Const.MaxDrawBuffers = ctx->Const.MaxDrawBuffers; @@ -113,6 +125,166 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx, this->default_uniform_qualifier->flags.q.column_major = 1; } +/** + * Determine whether the current GLSL version is sufficiently high to support + * a certain feature, and generate an error message if it isn't. + * + * \param required_glsl_version and \c required_glsl_es_version are + * interpreted as they are in _mesa_glsl_parse_state::is_version(). + * + * \param locp is the parser location where the error should be reported. + * + * \param fmt (and additional arguments) constitute a printf-style error + * message to report if the version check fails. Information about the + * current and required GLSL versions will be appended. So, for example, if + * the GLSL version being compiled is 1.20, and check_version(130, 300, locp, + * "foo unsupported") is called, the error message will be "foo unsupported in + * GLSL 1.20 (GLSL 1.30 or GLSL 3.00 ES required)". + */ +bool +_mesa_glsl_parse_state::check_version(unsigned required_glsl_version, + unsigned required_glsl_es_version, + YYLTYPE *locp, const char *fmt, ...) +{ + if (this->is_version(required_glsl_version, required_glsl_es_version)) + return true; + + va_list args; + va_start(args, fmt); + char *problem = ralloc_vasprintf(ctx, fmt, args); + va_end(args); + const char *glsl_version_string + = glsl_compute_version_string(ctx, false, required_glsl_version); + const char *glsl_es_version_string + = glsl_compute_version_string(ctx, true, required_glsl_es_version); + const char *requirement_string = ""; + if (required_glsl_version && required_glsl_es_version) { + requirement_string = ralloc_asprintf(ctx, " (%s or %s required)", + glsl_version_string, + glsl_es_version_string); + } else if (required_glsl_version) { + requirement_string = ralloc_asprintf(ctx, " (%s required)", + glsl_version_string); + } else if (required_glsl_es_version) { + requirement_string = ralloc_asprintf(ctx, " (%s required)", + glsl_es_version_string); + } + _mesa_glsl_error(locp, this, "%s in %s%s.", + problem, this->get_version_string(), + requirement_string); + + return false; +} + +/** + * Process a GLSL #version directive. + * + * \param version is the integer that follows the #version token. + * + * \param ident is a string identifier that follows the integer, if any is + * present. Otherwise NULL. + */ +void +_mesa_glsl_parse_state::process_version_directive(YYLTYPE *locp, int version, + const char *ident) +{ + bool es_token_present = false; + if (ident) { + if (strcmp(ident, "es") == 0) { + es_token_present = true; + } else { + _mesa_glsl_error(locp, this, + "Illegal text following version number\n"); + } + } + + bool supported = false; + + if (es_token_present) { + this->es_shader = true; + switch (version) { + case 100: + _mesa_glsl_error(locp, this, + "GLSL 1.00 ES should be selected using " + "`#version 100'\n"); + supported = this->ctx->API == API_OPENGLES2 || + this->ctx->Extensions.ARB_ES2_compatibility; + break; + case 300: + supported = _mesa_is_gles3(this->ctx) || + this->ctx->Extensions.ARB_ES3_compatibility; + break; + default: + supported = false; + break; + } + } else { + switch (version) { + case 100: + this->es_shader = true; + supported = this->ctx->API == API_OPENGLES2 || + this->ctx->Extensions.ARB_ES2_compatibility; + break; + case 110: + case 120: + /* FINISHME: Once the OpenGL 3.0 'forward compatible' context or + * the OpenGL 3.2 Core context is supported, this logic will need + * change. Older versions of GLSL are no longer supported + * outside the compatibility contexts of 3.x. + */ + case 130: + case 140: + case 150: + case 330: + case 400: + case 410: + case 420: + supported = _mesa_is_desktop_gl(this->ctx) && + ((unsigned) version) <= this->ctx->Const.GLSLVersion; + break; + default: + supported = false; + break; + } + } + + this->language_version = version; + + if (!supported) { + _mesa_glsl_error(locp, this, "%s is not supported. " + "Supported versions are: %s\n", + this->get_version_string(), + this->supported_version_string); + + /* On exit, the language_version must be set to a valid value. + * Later calls to _mesa_glsl_initialize_types will misbehave if + * the version is invalid. + */ + switch (this->ctx->API) { + case API_OPENGL_COMPAT: + case API_OPENGL_CORE: + this->language_version = this->ctx->Const.GLSLVersion; + break; + + case API_OPENGLES: + assert(!"Should not get here."); + /* FALLTHROUGH */ + + case API_OPENGLES2: + this->language_version = 100; + break; + } + } + + if (this->language_version >= 140) { + this->ARB_uniform_buffer_object_enable = true; + } + + if (this->language_version == 300 && this->es_shader) { + this->ARB_explicit_attrib_location_enable = true; + } +} + const char * _mesa_glsl_shader_target_name(enum _mesa_glsl_parser_targets target) { diff --git a/mesalib/src/glsl/glsl_parser_extras.h b/mesalib/src/glsl/glsl_parser_extras.h index 17ebc76a7..01cf6a8d9 100644 --- a/mesalib/src/glsl/glsl_parser_extras.h +++ b/mesalib/src/glsl/glsl_parser_extras.h @@ -56,6 +56,19 @@ struct glsl_switch_state { bool is_switch_innermost; // if switch stmt is closest to break, ... }; +const char * +glsl_compute_version_string(void *mem_ctx, bool is_es, unsigned version); + +typedef struct YYLTYPE { + int first_line; + int first_column; + int last_line; + int last_column; + unsigned source; +} YYLTYPE; +# define YYLTYPE_IS_DECLARED 1 +# define YYLTYPE_IS_TRIVIAL 1 + struct _mesa_glsl_parse_state { _mesa_glsl_parse_state(struct gl_context *_ctx, GLenum target, void *mem_ctx); @@ -81,6 +94,55 @@ struct _mesa_glsl_parse_state { ralloc_free(mem); } + /** + * Generate a string representing the GLSL version currently being compiled + * (useful for error messages). + */ + const char *get_version_string() + { + return glsl_compute_version_string(this, this->es_shader, + this->language_version); + } + + /** + * Determine whether the current GLSL version is sufficiently high to + * support a certain feature. + * + * \param required_glsl_version is the desktop GLSL version that is + * required to support the feature, or 0 if no version of desktop GLSL + * supports the feature. + * + * \param required_glsl_es_version is the GLSL ES version that is required + * to support the feature, or 0 if no version of GLSL ES suports the + * feature. + */ + bool is_version(unsigned required_glsl_version, + unsigned required_glsl_es_version) + { + unsigned required_version = this->es_shader ? + required_glsl_es_version : required_glsl_version; + return required_version != 0 + && this->language_version >= required_version; + } + + bool check_version(unsigned required_glsl_version, + unsigned required_glsl_es_version, + YYLTYPE *locp, const char *fmt, ...) PRINTFLIKE(5, 6); + + bool check_precision_qualifiers_allowed(YYLTYPE *locp) + { + return check_version(130, 100, locp, + "precision qualifiers are forbidden"); + } + + bool check_bitwise_operations_allowed(YYLTYPE *locp) + { + return check_version(130, 300, locp, "bit-wise operations are forbidden"); + } + + void process_version_directive(YYLTYPE *locp, int version, + const char *ident); + struct gl_context *const ctx; void *scanner; exec_list translation_unit; @@ -92,7 +154,6 @@ struct _mesa_glsl_parse_state { bool es_shader; unsigned language_version; - const char *version_string; enum _mesa_glsl_parser_targets target; /** @@ -133,6 +194,10 @@ struct _mesa_glsl_parse_state { /* ARB_draw_buffers */ unsigned MaxDrawBuffers; + + /* 3.00 ES */ + int MinProgramTexelOffset; + int MaxProgramTexelOffset; } Const; /** @@ -221,16 +286,6 @@ struct _mesa_glsl_parse_state { unsigned num_builtins_to_link; }; -typedef struct YYLTYPE { - int first_line; - int first_column; - int last_line; - int last_column; - unsigned source; -} YYLTYPE; -# define YYLTYPE_IS_DECLARED 1 -# define YYLTYPE_IS_TRIVIAL 1 - # define YYLLOC_DEFAULT(Current, Rhs, N) \ do { \ if (N) \ diff --git a/mesalib/src/glsl/glsl_symbol_table.cpp b/mesalib/src/glsl/glsl_symbol_table.cpp index 27a669b65..247aff55c 100644 --- a/mesalib/src/glsl/glsl_symbol_table.cpp +++ b/mesalib/src/glsl/glsl_symbol_table.cpp @@ -56,7 +56,7 @@ public: glsl_symbol_table::glsl_symbol_table() { - this->language_version = 120; + this->separate_function_namespace = false; this->table = _mesa_symbol_table_ctor(); this->mem_ctx = ralloc_context(NULL); } @@ -84,7 +84,7 @@ bool glsl_symbol_table::name_declared_this_scope(const char *name) bool glsl_symbol_table::add_variable(ir_variable *v) { - if (this->language_version == 110) { + if (this->separate_function_namespace) { /* In 1.10, functions and variables have separate namespaces. */ symbol_table_entry *existing = get_entry(v->name); if (name_declared_this_scope(v->name)) { @@ -124,7 +124,7 @@ bool glsl_symbol_table::add_type(const char *name, const glsl_type *t) bool glsl_symbol_table::add_function(ir_function *f) { - if (this->language_version == 110 && name_declared_this_scope(f->name)) { + if (this->separate_function_namespace && name_declared_this_scope(f->name)) { /* In 1.10, functions and variables have separate namespaces. */ symbol_table_entry *existing = get_entry(f->name); if ((existing->f == NULL) && (existing->t == NULL)) { diff --git a/mesalib/src/glsl/glsl_symbol_table.h b/mesalib/src/glsl/glsl_symbol_table.h index 1afeddb33..55baebf10 100644 --- a/mesalib/src/glsl/glsl_symbol_table.h +++ b/mesalib/src/glsl/glsl_symbol_table.h @@ -82,7 +82,8 @@ public: glsl_symbol_table(); ~glsl_symbol_table(); - unsigned int language_version; + /* In 1.10, functions and variables have separate namespaces. */ + bool separate_function_namespace; void push_scope(); void pop_scope(); diff --git a/mesalib/src/glsl/glsl_types.cpp b/mesalib/src/glsl/glsl_types.cpp index 3940a12a5..71b185027 100644 --- a/mesalib/src/glsl/glsl_types.cpp +++ b/mesalib/src/glsl/glsl_types.cpp @@ -102,11 +102,16 @@ glsl_type::glsl_type(const glsl_struct_field *fields, unsigned num_fields, static void add_types_to_symbol_table(glsl_symbol_table *symtab, const struct glsl_type *types, - unsigned num_types, bool warn) + unsigned num_types, bool warn, + bool skip_1d) { (void) warn; for (unsigned i = 0; i < num_types; i++) { + if (skip_1d && types[i].base_type == GLSL_TYPE_SAMPLER + && types[i].sampler_dimensionality == GLSL_SAMPLER_DIM_1D) + continue; + symtab->add_type(types[i].name, & types[i]); } } @@ -158,49 +163,68 @@ glsl_type::sampler_index() const void glsl_type::generate_100ES_types(glsl_symbol_table *symtab) { + bool skip_1d = false; add_types_to_symbol_table(symtab, builtin_core_types, Elements(builtin_core_types), - false); + false, skip_1d); add_types_to_symbol_table(symtab, builtin_structure_types, Elements(builtin_structure_types), - false); - add_types_to_symbol_table(symtab, void_type, 1, false); + false, skip_1d); + add_types_to_symbol_table(symtab, void_type, 1, false, skip_1d); +} + +void +glsl_type::generate_300ES_types(glsl_symbol_table *symtab) +{ + /* GLSL 3.00 ES types are the same as GLSL 1.30 types, except that 1D + * samplers are skipped, and samplerCubeShadow is added. + */ + bool add_deprecated = false; + bool skip_1d = true; + + generate_130_types(symtab, add_deprecated, skip_1d); + + add_types_to_symbol_table(symtab, &_samplerCubeShadow_type, 1, false, + skip_1d); } void -glsl_type::generate_110_types(glsl_symbol_table *symtab, bool add_deprecated) +glsl_type::generate_110_types(glsl_symbol_table *symtab, bool add_deprecated, + bool skip_1d) { generate_100ES_types(symtab); add_types_to_symbol_table(symtab, builtin_110_types, Elements(builtin_110_types), - false); - add_types_to_symbol_table(symtab, &_sampler3D_type, 1, false); + false, skip_1d); + add_types_to_symbol_table(symtab, &_sampler3D_type, 1, false, skip_1d); if (add_deprecated) { add_types_to_symbol_table(symtab, builtin_110_deprecated_structure_types, Elements(builtin_110_deprecated_structure_types), - false); + false, skip_1d); } } void -glsl_type::generate_120_types(glsl_symbol_table *symtab, bool add_deprecated) +glsl_type::generate_120_types(glsl_symbol_table *symtab, bool add_deprecated, + bool skip_1d) { - generate_110_types(symtab, add_deprecated); + generate_110_types(symtab, add_deprecated, skip_1d); add_types_to_symbol_table(symtab, builtin_120_types, - Elements(builtin_120_types), false); + Elements(builtin_120_types), false, skip_1d); } void -glsl_type::generate_130_types(glsl_symbol_table *symtab, bool add_deprecated) +glsl_type::generate_130_types(glsl_symbol_table *symtab, bool add_deprecated, + bool skip_1d) { - generate_120_types(symtab, add_deprecated); + generate_120_types(symtab, add_deprecated, skip_1d); add_types_to_symbol_table(symtab, builtin_130_types, - Elements(builtin_130_types), false); + Elements(builtin_130_types), false, skip_1d); generate_EXT_texture_array_types(symtab, false); } @@ -208,14 +232,16 @@ glsl_type::generate_130_types(glsl_symbol_table *symtab, bool add_deprecated) void glsl_type::generate_140_types(glsl_symbol_table *symtab) { - generate_130_types(symtab, false); + bool skip_1d = false; + + generate_130_types(symtab, false, skip_1d); add_types_to_symbol_table(symtab, builtin_140_types, - Elements(builtin_140_types), false); + Elements(builtin_140_types), false, skip_1d); add_types_to_symbol_table(symtab, builtin_EXT_texture_buffer_object_types, Elements(builtin_EXT_texture_buffer_object_types), - false); + false, skip_1d); } @@ -223,9 +249,11 @@ void glsl_type::generate_ARB_texture_rectangle_types(glsl_symbol_table *symtab, bool warn) { + bool skip_1d = false; + add_types_to_symbol_table(symtab, builtin_ARB_texture_rectangle_types, Elements(builtin_ARB_texture_rectangle_types), - warn); + warn, skip_1d); } @@ -233,16 +261,20 @@ void glsl_type::generate_EXT_texture_array_types(glsl_symbol_table *symtab, bool warn) { + bool skip_1d = false; + add_types_to_symbol_table(symtab, builtin_EXT_texture_array_types, Elements(builtin_EXT_texture_array_types), - warn); + warn, skip_1d); } void glsl_type::generate_OES_texture_3D_types(glsl_symbol_table *symtab, bool warn) { - add_types_to_symbol_table(symtab, &_sampler3D_type, 1, warn); + bool skip_1d = false; + + add_types_to_symbol_table(symtab, &_sampler3D_type, 1, warn, skip_1d); } @@ -250,56 +282,74 @@ void glsl_type::generate_OES_EGL_image_external_types(glsl_symbol_table *symtab, bool warn) { + bool skip_1d = false; + add_types_to_symbol_table(symtab, builtin_OES_EGL_image_external_types, Elements(builtin_OES_EGL_image_external_types), - warn); + warn, skip_1d); } void glsl_type::generate_ARB_texture_cube_map_array_types(glsl_symbol_table *symtab, bool warn) { + bool skip_1d = false; + add_types_to_symbol_table(symtab, builtin_ARB_texture_cube_map_array_types, Elements(builtin_ARB_texture_cube_map_array_types), - warn); + warn, skip_1d); } void _mesa_glsl_initialize_types(struct _mesa_glsl_parse_state *state) { - switch (state->language_version) { - case 100: - assert(state->es_shader); - glsl_type::generate_100ES_types(state->symbols); - break; - case 110: - glsl_type::generate_110_types(state->symbols, true); - break; - case 120: - glsl_type::generate_120_types(state->symbols, true); - break; - case 130: - glsl_type::generate_130_types(state->symbols, true); - break; - case 140: - glsl_type::generate_140_types(state->symbols); - break; - default: - /* error */ - break; + if (state->es_shader) { + switch (state->language_version) { + case 100: + assert(state->es_shader); + glsl_type::generate_100ES_types(state->symbols); + break; + case 300: + glsl_type::generate_300ES_types(state->symbols); + break; + default: + assert(!"Unexpected language version"); + break; + } + } else { + bool skip_1d = false; + switch (state->language_version) { + case 110: + glsl_type::generate_110_types(state->symbols, true, skip_1d); + break; + case 120: + glsl_type::generate_120_types(state->symbols, true, skip_1d); + break; + case 130: + glsl_type::generate_130_types(state->symbols, true, skip_1d); + break; + case 140: + glsl_type::generate_140_types(state->symbols); + break; + default: + assert(!"Unexpected language version"); + break; + } } if (state->ARB_texture_rectangle_enable || - state->language_version >= 140) { + state->is_version(140, 0)) { glsl_type::generate_ARB_texture_rectangle_types(state->symbols, state->ARB_texture_rectangle_warn); } - if (state->OES_texture_3D_enable && state->language_version == 100) { + if (state->OES_texture_3D_enable + && state->is_version(0, 100)) { glsl_type::generate_OES_texture_3D_types(state->symbols, state->OES_texture_3D_warn); } - if (state->EXT_texture_array_enable && state->language_version < 130) { + if (state->EXT_texture_array_enable + && !state->is_version(130, 0)) { // These are already included in 130; don't create twice. glsl_type::generate_EXT_texture_array_types(state->symbols, state->EXT_texture_array_warn); diff --git a/mesalib/src/glsl/glsl_types.h b/mesalib/src/glsl/glsl_types.h index cf954a256..d6f5c105e 100644 --- a/mesalib/src/glsl/glsl_types.h +++ b/mesalib/src/glsl/glsl_types.h @@ -510,6 +510,7 @@ private: static const glsl_type _error_type; static const glsl_type _void_type; static const glsl_type _sampler3D_type; + static const glsl_type _samplerCubeShadow_type; static const glsl_type builtin_core_types[]; static const glsl_type builtin_structure_types[]; static const glsl_type builtin_110_deprecated_structure_types[]; @@ -534,9 +535,13 @@ private: */ /*@{*/ static void generate_100ES_types(glsl_symbol_table *); - static void generate_110_types(glsl_symbol_table *, bool add_deprecated); - static void generate_120_types(glsl_symbol_table *, bool add_deprecated); - static void generate_130_types(glsl_symbol_table *, bool add_deprecated); + static void generate_300ES_types(glsl_symbol_table *); + static void generate_110_types(glsl_symbol_table *, bool add_deprecated, + bool skip_1d); + static void generate_120_types(glsl_symbol_table *, bool add_deprecated, + bool skip_1d); + static void generate_130_types(glsl_symbol_table *, bool add_deprecated, + bool skip_1d); static void generate_140_types(glsl_symbol_table *); static void generate_ARB_texture_rectangle_types(glsl_symbol_table *, bool); static void generate_EXT_texture_array_types(glsl_symbol_table *, bool); diff --git a/mesalib/src/glsl/hir_field_selection.cpp b/mesalib/src/glsl/hir_field_selection.cpp index 260b415a8..ac416d5da 100644 --- a/mesalib/src/glsl/hir_field_selection.cpp +++ b/mesalib/src/glsl/hir_field_selection.cpp @@ -72,8 +72,7 @@ _mesa_ast_field_selection_to_hir(const ast_expression *expr, } } else if (expr->subexpressions[1] != NULL) { /* Handle "method calls" in GLSL 1.20 - namely, array.length() */ - if (state->language_version < 120) - _mesa_glsl_error(&loc, state, "Methods not supported in GLSL 1.10."); + state->check_version(120, 300, &loc, "Methods not supported"); ast_expression *call = expr->subexpressions[1]; assert(call->oper == ast_function_call); diff --git a/mesalib/src/glsl/ir_variable_refcount.cpp b/mesalib/src/glsl/ir_variable_refcount.cpp index 1633a7357..923eb1a82 100644 --- a/mesalib/src/glsl/ir_variable_refcount.cpp +++ b/mesalib/src/glsl/ir_variable_refcount.cpp @@ -33,7 +33,26 @@ #include "ir_visitor.h" #include "ir_variable_refcount.h" #include "glsl_types.h" +#include "main/hash_table.h" +ir_variable_refcount_visitor::ir_variable_refcount_visitor() +{ + this->mem_ctx = ralloc_context(NULL); + this->ht = _mesa_hash_table_create(NULL, _mesa_key_pointer_equal); +} + +static void +free_entry(struct hash_entry *entry) +{ + ir_variable_refcount_entry *ivre = (ir_variable_refcount_entry *) entry->data; + delete ivre; +} + +ir_variable_refcount_visitor::~ir_variable_refcount_visitor() +{ + ralloc_free(this->mem_ctx); + _mesa_hash_table_destroy(this->ht, free_entry); +} // constructor ir_variable_refcount_entry::ir_variable_refcount_entry(ir_variable *var) @@ -50,15 +69,17 @@ ir_variable_refcount_entry * ir_variable_refcount_visitor::get_variable_entry(ir_variable *var) { assert(var); - foreach_iter(exec_list_iterator, iter, this->variable_list) { - ir_variable_refcount_entry *entry = (ir_variable_refcount_entry *)iter.get(); - if (entry->var == var) - return entry; - } - ir_variable_refcount_entry *entry = new(mem_ctx) ir_variable_refcount_entry(var); + struct hash_entry *e = _mesa_hash_table_search(this->ht, + _mesa_hash_pointer(var), + var); + if (e) + return (ir_variable_refcount_entry *)e->data; + + ir_variable_refcount_entry *entry = new ir_variable_refcount_entry(var); assert(entry->referenced_count == 0); - this->variable_list.push_tail(entry); + _mesa_hash_table_insert(this->ht, _mesa_hash_pointer(var), var, entry); + return entry; } diff --git a/mesalib/src/glsl/ir_variable_refcount.h b/mesalib/src/glsl/ir_variable_refcount.h index 51a4945a1..c15e8110d 100644 --- a/mesalib/src/glsl/ir_variable_refcount.h +++ b/mesalib/src/glsl/ir_variable_refcount.h @@ -33,7 +33,7 @@ #include "ir_visitor.h" #include "glsl_types.h" -class ir_variable_refcount_entry : public exec_node +class ir_variable_refcount_entry { public: ir_variable_refcount_entry(ir_variable *var); @@ -52,16 +52,8 @@ public: class ir_variable_refcount_visitor : public ir_hierarchical_visitor { public: - ir_variable_refcount_visitor(void) - { - this->mem_ctx = ralloc_context(NULL); - this->variable_list.make_empty(); - } - - ~ir_variable_refcount_visitor(void) - { - ralloc_free(this->mem_ctx); - } + ir_variable_refcount_visitor(void); + ~ir_variable_refcount_visitor(void); virtual ir_visitor_status visit(ir_variable *); virtual ir_visitor_status visit(ir_dereference_variable *); @@ -71,8 +63,7 @@ public: ir_variable_refcount_entry *get_variable_entry(ir_variable *var); - /* List of ir_variable_refcount_entry */ - exec_list variable_list; + struct hash_table *ht; void *mem_ctx; }; diff --git a/mesalib/src/glsl/linker.cpp b/mesalib/src/glsl/linker.cpp index 3b2ab962b..29fc5d841 100644 --- a/mesalib/src/glsl/linker.cpp +++ b/mesalib/src/glsl/linker.cpp @@ -289,8 +289,11 @@ validate_vertex_shader_executable(struct gl_shader_program *prog, * operations, if present, that operate on primitives after * vertex processing has occurred. Its value is undefined if * the vertex shader executable does not write gl_Position." + * + * GLSL ES 3.00 is similar to GLSL 1.40--failing to write to gl_Position is + * not an error. */ - if (prog->Version < 140) { + if (prog->Version < (prog->IsES ? 300 : 140)) { find_assignment_visitor find("gl_Position"); find.run(shader->ir); if (!find.variable_found()) { @@ -301,12 +304,15 @@ validate_vertex_shader_executable(struct gl_shader_program *prog, prog->Vert.ClipDistanceArraySize = 0; - if (prog->Version >= 130) { + if (!prog->IsES && prog->Version >= 130) { /* From section 7.1 (Vertex Shader Special Variables) of the * GLSL 1.30 spec: * * "It is an error for a shader to statically write both * gl_ClipVertex and gl_ClipDistance." + * + * This does not apply to GLSL ES shaders, since GLSL ES defines neither + * gl_ClipVertex nor gl_ClipDistance. */ find_assignment_visitor clip_vertex("gl_ClipVertex"); find_assignment_visitor clip_distance("gl_ClipDistance"); @@ -2144,7 +2150,7 @@ assign_varying_locations(struct gl_context *ctx, } } - if (ctx->API == API_OPENGLES2 || prog->Version == 100) { + if (ctx->API == API_OPENGLES2 || prog->IsES) { if (varying_vectors > ctx->Const.MaxVarying) { if (ctx->Const.GLSLSkipStrictMaxVaryingLimitCheck) { linker_warning(prog, "shader uses too many varying vectors " @@ -2421,10 +2427,18 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) unsigned min_version = UINT_MAX; unsigned max_version = 0; + const bool is_es_prog = + (prog->NumShaders > 0 && prog->Shaders[0]->IsES) ? true : false; for (unsigned i = 0; i < prog->NumShaders; i++) { min_version = MIN2(min_version, prog->Shaders[i]->Version); max_version = MAX2(max_version, prog->Shaders[i]->Version); + if (prog->Shaders[i]->IsES != is_es_prog) { + linker_error(prog, "all shaders must use same shading " + "language version\n"); + goto done; + } + switch (prog->Shaders[i]->Type) { case GL_VERTEX_SHADER: vert_shader_list[num_vert_shaders] = prog->Shaders[i]; @@ -2444,10 +2458,10 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) /* Previous to GLSL version 1.30, different compilation units could mix and * match shading language versions. With GLSL 1.30 and later, the versions * of all shaders must match. + * + * GLSL ES has never allowed mixing of shading language versions. */ - assert(min_version >= 100); - assert(max_version <= 140); - if ((max_version >= 130 || min_version == 100) + if ((is_es_prog || max_version >= 130) && min_version != max_version) { linker_error(prog, "all shaders must use same shading " "language version\n"); @@ -2455,6 +2469,7 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) } prog->Version = max_version; + prog->IsES = is_es_prog; for (unsigned int i = 0; i < MESA_SHADER_TYPES; i++) { if (prog->_LinkedShaders[i] != NULL) @@ -2528,8 +2543,10 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) /* Implement the GLSL 1.30+ rule for discard vs infinite loops Do * it before optimization because we want most of the checks to get * dropped thanks to constant propagation. + * + * This rule also applies to GLSL ES 3.00. */ - if (max_version >= 130) { + if (max_version >= (is_es_prog ? 300 : 130)) { struct gl_shader *sh = prog->_LinkedShaders[MESA_SHADER_FRAGMENT]; if (sh) { lower_discard_flow(sh->ir); @@ -2673,11 +2690,11 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) goto done; /* OpenGL ES requires that a vertex shader and a fragment shader both be - * present in a linked program. By checking for use of shading language - * version 1.00, we also catch the GL_ARB_ES2_compatibility case. + * present in a linked program. By checking prog->IsES, we also + * catch the GL_ARB_ES2_compatibility case. */ if (!prog->InternalSeparateShader && - (ctx->API == API_OPENGLES2 || prog->Version == 100)) { + (ctx->API == API_OPENGLES2 || prog->IsES)) { if (prog->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) { linker_error(prog, "program lacks a vertex shader\n"); } else if (prog->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL) { diff --git a/mesalib/src/glsl/lower_output_reads.cpp b/mesalib/src/glsl/lower_output_reads.cpp index 90d71b04a..a6192a517 100644 --- a/mesalib/src/glsl/lower_output_reads.cpp +++ b/mesalib/src/glsl/lower_output_reads.cpp @@ -97,6 +97,7 @@ output_read_remover::visit(ir_dereference_variable *ir) temp = new(var_ctx) ir_variable(ir->var->type, ir->var->name, ir_var_temporary); hash_table_insert(replacements, temp, ir->var); + ir->var->insert_after(temp); } /* Update the dereference to use the temporary */ diff --git a/mesalib/src/glsl/main.cpp b/mesalib/src/glsl/main.cpp index af97c545b..d21b8cd2d 100644 --- a/mesalib/src/glsl/main.cpp +++ b/mesalib/src/glsl/main.cpp @@ -59,6 +59,7 @@ initialize_context(struct gl_context *ctx, gl_api api) * everything in order to compile the built-in functions. */ ctx->Const.GLSLVersion = 140; + ctx->Extensions.ARB_ES3_compatibility = true; ctx->Const.MaxClipPlanes = 8; ctx->Const.MaxDrawBuffers = 2; @@ -201,6 +202,7 @@ compile_shader(struct gl_context *ctx, struct gl_shader *shader) shader->symbols = state->symbols; shader->CompileStatus = !state->error; shader->Version = state->language_version; + shader->IsES = state->es_shader; memcpy(shader->builtins_to_link, state->builtins_to_link, sizeof(shader->builtins_to_link[0]) * state->num_builtins_to_link); shader->num_builtins_to_link = state->num_builtins_to_link; diff --git a/mesalib/src/glsl/opt_dead_code.cpp b/mesalib/src/glsl/opt_dead_code.cpp index de8475f95..47247e20d 100644 --- a/mesalib/src/glsl/opt_dead_code.cpp +++ b/mesalib/src/glsl/opt_dead_code.cpp @@ -31,6 +31,7 @@ #include "ir_visitor.h" #include "ir_variable_refcount.h" #include "glsl_types.h" +#include "main/hash_table.h" static bool debug = false; @@ -49,8 +50,9 @@ do_dead_code(exec_list *instructions, bool uniform_locations_assigned) v.run(instructions); - foreach_iter(exec_list_iterator, iter, v.variable_list) { - ir_variable_refcount_entry *entry = (ir_variable_refcount_entry *)iter.get(); + struct hash_entry *e; + hash_table_foreach(v.ht, e) { + ir_variable_refcount_entry *entry = (ir_variable_refcount_entry *)e->data; /* Since each assignment is a reference, the refereneced count must be * greater than or equal to the assignment count. If they are equal, diff --git a/mesalib/src/glsl/standalone_scaffolding.cpp b/mesalib/src/glsl/standalone_scaffolding.cpp index 120ee9534..33d3804c6 100644 --- a/mesalib/src/glsl/standalone_scaffolding.cpp +++ b/mesalib/src/glsl/standalone_scaffolding.cpp @@ -73,6 +73,7 @@ void initialize_context_to_defaults(struct gl_context *ctx, gl_api api) ctx->Extensions.dummy_false = false; ctx->Extensions.dummy_true = true; ctx->Extensions.ARB_ES2_compatibility = true; + ctx->Extensions.ARB_ES3_compatibility = false; ctx->Extensions.ARB_draw_instanced = true; ctx->Extensions.ARB_fragment_coord_conventions = true; ctx->Extensions.EXT_texture_array = true; diff --git a/mesalib/src/mesa/Android.libmesa_glsl_utils.mk b/mesalib/src/mesa/Android.libmesa_glsl_utils.mk index 480275795..9beeda57f 100644 --- a/mesalib/src/mesa/Android.libmesa_glsl_utils.mk +++ b/mesalib/src/mesa/Android.libmesa_glsl_utils.mk @@ -36,7 +36,8 @@ include $(CLEAR_VARS) LOCAL_MODULE := libmesa_glsl_utils LOCAL_SRC_FILES := \ - program/hash_table.c \ + main/hash_table.c \ + program/prog_hash_table.c \ program/symbol_table.c include $(MESA_COMMON_MK) @@ -52,7 +53,8 @@ LOCAL_MODULE := libmesa_glsl_utils LOCAL_IS_HOST_MODULE := true LOCAL_SRC_FILES := \ - program/hash_table.c \ + main/hash_table.c \ + program/prog_hash_table.c \ program/symbol_table.c include $(MESA_COMMON_MK) diff --git a/mesalib/src/mesa/SConscript b/mesalib/src/mesa/SConscript index be1ed5f60..a2492f771 100644 --- a/mesalib/src/mesa/SConscript +++ b/mesalib/src/mesa/SConscript @@ -107,6 +107,7 @@ main_sources = [ 'main/renderbuffer.c', 'main/samplerobj.c', 'main/scissor.c', + 'main/set.c', 'main/shaderapi.c', 'main/shaderobj.c', 'main/shader_query.cpp', @@ -293,7 +294,7 @@ env.Append(CPPPATH = [Dir('.').abspath]) program_sources = [ 'program/arbprogparse.c', - 'program/hash_table.c', + 'program/prog_hash_table.c', 'program/ir_to_mesa.cpp', 'program/program.c', 'program/program_parse_extra.c', diff --git a/mesalib/src/mesa/drivers/common/meta.c b/mesalib/src/mesa/drivers/common/meta.c index d5e8af3c0..ac036eaac 100644 --- a/mesalib/src/mesa/drivers/common/meta.c +++ b/mesalib/src/mesa/drivers/common/meta.c @@ -133,6 +133,7 @@ struct save_state struct gl_vertex_program *VertexProgram; GLboolean FragmentProgramEnabled; struct gl_fragment_program *FragmentProgram; + GLboolean ATIFragmentShaderEnabled; struct gl_shader_program *VertexShader; struct gl_shader_program *GeometryShader; struct gl_shader_program *FragmentShader; @@ -594,6 +595,11 @@ _mesa_meta_begin(struct gl_context *ctx, GLbitfield state) _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, GL_FALSE); } + if (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.ATI_fragment_shader) { + save->ATIFragmentShaderEnabled = ctx->ATIFragmentShader.Enabled; + _mesa_set_enable(ctx, GL_FRAGMENT_SHADER_ATI, GL_FALSE); + } + if (ctx->Extensions.ARB_shader_objects) { _mesa_reference_shader_program(ctx, &save->VertexShader, ctx->Shader.CurrentVertexProgram); @@ -914,6 +920,11 @@ _mesa_meta_end(struct gl_context *ctx) _mesa_reference_fragprog(ctx, &save->FragmentProgram, NULL); } + if (ctx->API == API_OPENGL_COMPAT && ctx->Extensions.ATI_fragment_shader) { + _mesa_set_enable(ctx, GL_FRAGMENT_SHADER_ATI, + save->ATIFragmentShaderEnabled); + } + if (ctx->Extensions.ARB_vertex_shader) _mesa_use_shader_program(ctx, GL_VERTEX_SHADER, save->VertexShader); @@ -1844,23 +1855,8 @@ meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear) "{\n" " gl_FragColor = color;\n" "}\n"; - const char *vs_int_source = - "#version 130\n" - "in vec4 position;\n" - "void main()\n" - "{\n" - " gl_Position = position;\n" - "}\n"; - const char *fs_int_source = - "#version 130\n" - "uniform ivec4 color;\n" - "out ivec4 out_color;\n" - "\n" - "void main()\n" - "{\n" - " out_color = color;\n" - "}\n"; GLuint vs, fs; + bool has_integer_textures; if (clear->ArrayObj != 0) return; @@ -1896,9 +1892,35 @@ meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear) clear->ColorLocation = _mesa_GetUniformLocation(clear->ShaderProg, "color"); - if (_mesa_is_desktop_gl(ctx) && ctx->Const.GLSLVersion >= 130) { + has_integer_textures = _mesa_is_gles3(ctx) || + (_mesa_is_desktop_gl(ctx) && ctx->Const.GLSLVersion >= 130); + + if (has_integer_textures) { + void *shader_source_mem_ctx = ralloc_context(NULL); + const char *vs_int_source = + ralloc_asprintf(shader_source_mem_ctx, + "#version %s\n" + "in vec4 position;\n" + "void main()\n" + "{\n" + " gl_Position = position;\n" + "}\n", + _mesa_is_desktop_gl(ctx) ? "130" : "300 es"); + const char *fs_int_source = + ralloc_asprintf(shader_source_mem_ctx, + "#version %s\n" + "uniform ivec4 color;\n" + "out ivec4 out_color;\n" + "\n" + "void main()\n" + "{\n" + " out_color = color;\n" + "}\n", + _mesa_is_desktop_gl(ctx) ? "130" : "300 es"); + vs = compile_shader_with_debug(ctx, GL_VERTEX_SHADER, vs_int_source); fs = compile_shader_with_debug(ctx, GL_FRAGMENT_SHADER, fs_int_source); + ralloc_free(shader_source_mem_ctx); clear->IntegerShaderProg = _mesa_CreateProgramObjectARB(); _mesa_AttachShader(clear->IntegerShaderProg, fs); @@ -3101,18 +3123,19 @@ setup_glsl_generate_mipmap(struct gl_context *ctx, sampler->func, sampler->texcoords); } else { - vs_source = - "#version 130\n" - "in vec2 position;\n" - "in vec3 textureCoords;\n" - "out vec3 texCoords;\n" - "void main()\n" - "{\n" - " texCoords = textureCoords;\n" - " gl_Position = vec4(position, 0.0, 1.0);\n" - "}\n"; + vs_source = ralloc_asprintf(mem_ctx, + "#version %s\n" + "in vec2 position;\n" + "in vec3 textureCoords;\n" + "out vec3 texCoords;\n" + "void main()\n" + "{\n" + " texCoords = textureCoords;\n" + " gl_Position = vec4(position, 0.0, 1.0);\n" + "}\n", + _mesa_is_desktop_gl(ctx) ? "130" : "300 es"); fs_source = ralloc_asprintf(mem_ctx, - "#version 130\n" + "#version %s\n" "uniform %s texSampler;\n" "in vec3 texCoords;\n" "out vec4 out_color;\n" @@ -3121,6 +3144,7 @@ setup_glsl_generate_mipmap(struct gl_context *ctx, "{\n" " out_color = texture(texSampler, %s);\n" "}\n", + _mesa_is_desktop_gl(ctx) ? "130" : "300 es", sampler->type, sampler->texcoords); } diff --git a/mesalib/src/mesa/drivers/dri/common/drisw_util.c b/mesalib/src/mesa/drivers/dri/common/drisw_util.c index e22ae1b84..33339880b 100644 --- a/mesalib/src/mesa/drivers/dri/common/drisw_util.c +++ b/mesalib/src/mesa/drivers/dri/common/drisw_util.c @@ -127,7 +127,10 @@ driCreateContextAttribs(__DRIscreen *screen, int api, mesa_api = API_OPENGLES2; break; case __DRI_API_OPENGL_CORE: + mesa_api = API_OPENGL_CORE; + break; default: + *error = __DRI_CTX_ERROR_BAD_API; return NULL; } @@ -150,6 +153,19 @@ driCreateContextAttribs(__DRIscreen *screen, int api, } } + /* Mesa does not support the GL_ARB_compatibilty extension or the + * compatibility profile. This means that we treat a API_OPENGL_COMPAT 3.1 as + * API_OPENGL_CORE and reject API_OPENGL_COMPAT 3.2+. + */ + if (mesa_api == API_OPENGL_COMPAT && major_version == 3 && minor_version == 1) + mesa_api = API_OPENGL_CORE; + + if (mesa_api == API_OPENGL_COMPAT + && ((major_version > 3) + || (major_version == 3 && minor_version >= 2))) { + *error = __DRI_CTX_ERROR_BAD_API; + return NULL; + } /* There are no forward-compatible contexts before OpenGL 3.0. The * GLX_ARB_create_context spec says: * diff --git a/mesalib/src/mesa/main/bufferobj.c b/mesalib/src/mesa/main/bufferobj.c index dbcd0e6e6..ce873ecd7 100644 --- a/mesalib/src/mesa/main/bufferobj.c +++ b/mesalib/src/mesa/main/bufferobj.c @@ -2160,17 +2160,19 @@ _mesa_BindBufferRange(GLenum target, GLuint index, return; } - if (size <= 0) { - _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(size=%d)", - (int) size); - return; - } + if (buffer != 0) { + if (size <= 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glBindBufferRange(size=%d)", + (int) size); + return; + } - if (offset + size > bufObj->Size) { - _mesa_error(ctx, GL_INVALID_VALUE, - "glBindBufferRange(offset + size %d > buffer size %d)", - (int) (offset + size), (int) (bufObj->Size)); - return; + if (offset + size > bufObj->Size) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glBindBufferRange(offset + size %d > buffer size %d)", + (int) (offset + size), (int) (bufObj->Size)); + return; + } } switch (target) { diff --git a/mesalib/src/mesa/main/extensions.c b/mesalib/src/mesa/main/extensions.c index 150d41e04..11cbea2b4 100644 --- a/mesalib/src/mesa/main/extensions.c +++ b/mesalib/src/mesa/main/extensions.c @@ -80,6 +80,7 @@ struct extension { static const struct extension extension_table[] = { /* ARB Extensions */ { "GL_ARB_ES2_compatibility", o(ARB_ES2_compatibility), GL, 2009 }, + { "GL_ARB_ES3_compatibility", o(ARB_ES3_compatibility), GL, 2012 }, { "GL_ARB_base_instance", o(ARB_base_instance), GL, 2011 }, { "GL_ARB_blend_func_extended", o(ARB_blend_func_extended), GL, 2009 }, { "GL_ARB_color_buffer_float", o(ARB_color_buffer_float), GL, 2004 }, diff --git a/mesalib/src/mesa/main/ff_fragment_shader.cpp b/mesalib/src/mesa/main/ff_fragment_shader.cpp index 3a80ab7f3..02b4707f0 100644 --- a/mesalib/src/mesa/main/ff_fragment_shader.cpp +++ b/mesalib/src/mesa/main/ff_fragment_shader.cpp @@ -1309,6 +1309,7 @@ create_new_program(struct gl_context *ctx, struct state_key *key) p.shader_program->InternalSeparateShader = GL_TRUE; state->language_version = 130; + state->es_shader = false; if (ctx->Extensions.OES_EGL_image_external) state->OES_EGL_image_external_enable = true; _mesa_glsl_initialize_types(state); diff --git a/mesalib/src/mesa/main/format_unpack.c b/mesalib/src/mesa/main/format_unpack.c index 04fd1d698..d34a27b82 100644 --- a/mesalib/src/mesa/main/format_unpack.c +++ b/mesalib/src/mesa/main/format_unpack.c @@ -57,8 +57,8 @@ struct z32f_x24s8 * linear RGB value in [0, 1]. * Implemented with a 256-entry lookup table. */ -static inline GLfloat -nonlinear_to_linear(GLubyte cs8) +GLfloat +_mesa_nonlinear_to_linear(GLubyte cs8) { static GLfloat table[256]; static GLboolean tableReady = GL_FALSE; @@ -742,9 +742,9 @@ unpack_SRGB8(const void *src, GLfloat dst[][4], GLuint n) const GLubyte *s = (const GLubyte *) src; GLuint i; for (i = 0; i < n; i++) { - dst[i][RCOMP] = nonlinear_to_linear(s[i*3+2]); - dst[i][GCOMP] = nonlinear_to_linear(s[i*3+1]); - dst[i][BCOMP] = nonlinear_to_linear(s[i*3+0]); + dst[i][RCOMP] = _mesa_nonlinear_to_linear(s[i*3+2]); + dst[i][GCOMP] = _mesa_nonlinear_to_linear(s[i*3+1]); + dst[i][BCOMP] = _mesa_nonlinear_to_linear(s[i*3+0]); dst[i][ACOMP] = 1.0F; } } @@ -755,9 +755,9 @@ unpack_SRGBA8(const void *src, GLfloat dst[][4], GLuint n) const GLuint *s = ((const GLuint *) src); GLuint i; for (i = 0; i < n; i++) { - dst[i][RCOMP] = nonlinear_to_linear( (s[i] >> 24) ); - dst[i][GCOMP] = nonlinear_to_linear( (s[i] >> 16) & 0xff ); - dst[i][BCOMP] = nonlinear_to_linear( (s[i] >> 8) & 0xff ); + dst[i][RCOMP] = _mesa_nonlinear_to_linear( (s[i] >> 24) ); + dst[i][GCOMP] = _mesa_nonlinear_to_linear( (s[i] >> 16) & 0xff ); + dst[i][BCOMP] = _mesa_nonlinear_to_linear( (s[i] >> 8) & 0xff ); dst[i][ACOMP] = UBYTE_TO_FLOAT( s[i] & 0xff ); /* linear! */ } } @@ -768,9 +768,9 @@ unpack_SARGB8(const void *src, GLfloat dst[][4], GLuint n) const GLuint *s = ((const GLuint *) src); GLuint i; for (i = 0; i < n; i++) { - dst[i][RCOMP] = nonlinear_to_linear( (s[i] >> 16) & 0xff ); - dst[i][GCOMP] = nonlinear_to_linear( (s[i] >> 8) & 0xff ); - dst[i][BCOMP] = nonlinear_to_linear( (s[i] ) & 0xff ); + dst[i][RCOMP] = _mesa_nonlinear_to_linear( (s[i] >> 16) & 0xff ); + dst[i][GCOMP] = _mesa_nonlinear_to_linear( (s[i] >> 8) & 0xff ); + dst[i][BCOMP] = _mesa_nonlinear_to_linear( (s[i] ) & 0xff ); dst[i][ACOMP] = UBYTE_TO_FLOAT( s[i] >> 24 ); /* linear! */ } } @@ -783,7 +783,7 @@ unpack_SL8(const void *src, GLfloat dst[][4], GLuint n) for (i = 0; i < n; i++) { dst[i][RCOMP] = dst[i][GCOMP] = - dst[i][BCOMP] = nonlinear_to_linear(s[i]); + dst[i][BCOMP] = _mesa_nonlinear_to_linear(s[i]); dst[i][ACOMP] = 1.0F; } } @@ -796,7 +796,7 @@ unpack_SLA8(const void *src, GLfloat dst[][4], GLuint n) for (i = 0; i < n; i++) { dst[i][RCOMP] = dst[i][GCOMP] = - dst[i][BCOMP] = nonlinear_to_linear(s[i] & 0xff); + dst[i][BCOMP] = _mesa_nonlinear_to_linear(s[i] & 0xff); dst[i][ACOMP] = UBYTE_TO_FLOAT(s[i] >> 8); /* linear! */ } } @@ -1337,6 +1337,68 @@ unpack_ETC1_RGB8(const void *src, GLfloat dst[][4], GLuint n) } static void +unpack_ETC2_RGB8(const void *src, GLfloat dst[][4], GLuint n) +{ + /* XXX to do */ +} + +static void +unpack_ETC2_SRGB8(const void *src, GLfloat dst[][4], GLuint n) +{ + /* XXX to do */ +} + +static void +unpack_ETC2_RGBA8_EAC(const void *src, GLfloat dst[][4], GLuint n) +{ + /* XXX to do */ +} + +static void +unpack_ETC2_SRGB8_ALPHA8_EAC(const void *src, GLfloat dst[][4], GLuint n) +{ + /* XXX to do */ +} + +static void +unpack_ETC2_R11_EAC(const void *src, GLfloat dst[][4], GLuint n) +{ + /* XXX to do */ +} + +static void +unpack_ETC2_RG11_EAC(const void *src, GLfloat dst[][4], GLuint n) +{ + /* XXX to do */ +} + +static void +unpack_ETC2_SIGNED_R11_EAC(const void *src, GLfloat dst[][4], GLuint n) +{ + /* XXX to do */ +} + +static void +unpack_ETC2_SIGNED_RG11_EAC(const void *src, GLfloat dst[][4], GLuint n) +{ + /* XXX to do */ +} + +static void +unpack_ETC2_RGB8_PUNCHTHROUGH_ALPHA1(const void *src, GLfloat dst[][4], + GLuint n) +{ + /* XXX to do */ +} + +static void +unpack_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1(const void *src, GLfloat dst[][4], + GLuint n) +{ + /* XXX to do */ +} + +static void unpack_SIGNED_A8(const void *src, GLfloat dst[][4], GLuint n) { const GLbyte *s = ((const GLbyte *) src); @@ -1585,7 +1647,18 @@ get_unpack_rgba_function(gl_format format) table[MESA_FORMAT_SIGNED_LA_LATC2] = unpack_SIGNED_LA_LATC2; table[MESA_FORMAT_ETC1_RGB8] = unpack_ETC1_RGB8; - + table[MESA_FORMAT_ETC2_RGB8] = unpack_ETC2_RGB8; + table[MESA_FORMAT_ETC2_SRGB8] = unpack_ETC2_SRGB8; + table[MESA_FORMAT_ETC2_RGBA8_EAC] = unpack_ETC2_RGBA8_EAC; + table[MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC] = unpack_ETC2_SRGB8_ALPHA8_EAC; + table[MESA_FORMAT_ETC2_R11_EAC] = unpack_ETC2_R11_EAC; + table[MESA_FORMAT_ETC2_RG11_EAC] = unpack_ETC2_RG11_EAC; + table[MESA_FORMAT_ETC2_SIGNED_R11_EAC] = unpack_ETC2_SIGNED_R11_EAC; + table[MESA_FORMAT_ETC2_SIGNED_RG11_EAC] = unpack_ETC2_SIGNED_RG11_EAC; + table[MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1] = + unpack_ETC2_RGB8_PUNCHTHROUGH_ALPHA1; + table[MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1] = + unpack_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1; table[MESA_FORMAT_SIGNED_A8] = unpack_SIGNED_A8; table[MESA_FORMAT_SIGNED_L8] = unpack_SIGNED_L8; table[MESA_FORMAT_SIGNED_AL88] = unpack_SIGNED_AL88; diff --git a/mesalib/src/mesa/main/format_unpack.h b/mesalib/src/mesa/main/format_unpack.h index aad800dd1..29c526319 100644 --- a/mesalib/src/mesa/main/format_unpack.h +++ b/mesalib/src/mesa/main/format_unpack.h @@ -24,6 +24,9 @@ #ifndef FORMAT_UNPACK_H #define FORMAT_UNPACK_H +extern GLfloat +_mesa_nonlinear_to_linear(GLubyte cs8); + extern void _mesa_unpack_rgba_row(gl_format format, GLuint n, const void *src, GLfloat dst[][4]); diff --git a/mesalib/src/mesa/main/formats.c b/mesalib/src/mesa/main/formats.c index df23af1dd..47a1d6802 100644 --- a/mesalib/src/mesa/main/formats.c +++ b/mesalib/src/mesa/main/formats.c @@ -1398,6 +1398,106 @@ static struct gl_format_info format_info[MESA_FORMAT_COUNT] = 4, 4, 8 /* 8 bytes per 4x4 block */ }, + { + MESA_FORMAT_ETC2_RGB8, + "MESA_FORMAT_ETC2_RGB8", + GL_RGB, + GL_UNSIGNED_NORMALIZED, + 8, 8, 8, 0, + 0, 0, 0, 0, 0, + 4, 4, 8 /* 8 bytes per 4x4 block */ + }, + + { + MESA_FORMAT_ETC2_SRGB8, + "MESA_FORMAT_ETC2_SRGB8", + GL_RGB, + GL_UNSIGNED_NORMALIZED, + 8, 8, 8, 0, + 0, 0, 0, 0, 0, + 4, 4, 8 /* 8 bytes per 4x4 block */ + }, + + { + MESA_FORMAT_ETC2_RGBA8_EAC, + "MESA_FORMAT_ETC2_RGBA8_EAC", + GL_RGBA, + GL_UNSIGNED_NORMALIZED, + 8, 8, 8, 8, + 0, 0, 0, 0, 0, + 4, 4, 16 /* 16 bytes per 4x4 block */ + }, + + { + MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC, + "MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC", + GL_RGBA, + GL_UNSIGNED_NORMALIZED, + 8, 8, 8, 8, + 0, 0, 0, 0, 0, + 4, 4, 16 /* 16 bytes per 4x4 block */ + }, + + { + MESA_FORMAT_ETC2_R11_EAC, + "MESA_FORMAT_ETC2_R11_EAC", + GL_RED, + GL_UNSIGNED_NORMALIZED, + 11, 0, 0, 0, + 0, 0, 0, 0, 0, + 4, 4, 8 /* 8 bytes per 4x4 block */ + }, + + { + MESA_FORMAT_ETC2_RG11_EAC, + "MESA_FORMAT_ETC2_RG11_EAC", + GL_RG, + GL_UNSIGNED_NORMALIZED, + 11, 11, 0, 0, + 0, 0, 0, 0, 0, + 4, 4, 16 /* 16 bytes per 4x4 block */ + }, + + { + MESA_FORMAT_ETC2_SIGNED_R11_EAC, + "MESA_FORMAT_ETC2_SIGNED_R11_EAC", + GL_RED, + GL_SIGNED_NORMALIZED, + 11, 0, 0, 0, + 0, 0, 0, 0, 0, + 4, 4, 8 /* 8 bytes per 4x4 block */ + }, + + { + MESA_FORMAT_ETC2_SIGNED_RG11_EAC, + "MESA_FORMAT_ETC2_SIGNED_RG11_EAC", + GL_RG, + GL_SIGNED_NORMALIZED, + 11, 11, 0, 0, + 0, 0, 0, 0, 0, + 4, 4, 16 /* 16 bytes per 4x4 block */ + }, + + { + MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1, + "MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1", + GL_RGBA, + GL_UNSIGNED_NORMALIZED, + 8, 8, 8, 1, + 0, 0, 0, 0, 0, + 4, 4, 8 /* 8 bytes per 4x4 block */ + }, + + { + MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1, + "MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1", + GL_RGBA, + GL_UNSIGNED_NORMALIZED, + 8, 8, 8, 1, + 0, 0, 0, 0, 0, + 4, 4, 8 /* 8 bytes per 4x4 block */ + }, + /* Signed formats from EXT_texture_snorm that are not in GL3.1 */ { MESA_FORMAT_SIGNED_A8, @@ -1840,7 +1940,20 @@ _mesa_get_uncompressed_format(gl_format format) case MESA_FORMAT_SIGNED_LA_LATC2: return MESA_FORMAT_SIGNED_AL88; case MESA_FORMAT_ETC1_RGB8: + case MESA_FORMAT_ETC2_RGB8: + case MESA_FORMAT_ETC2_SRGB8: return MESA_FORMAT_RGB888; + case MESA_FORMAT_ETC2_RGBA8_EAC: + case MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC: + case MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1: + case MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1: + return MESA_FORMAT_RGBA8888; + case MESA_FORMAT_ETC2_R11_EAC: + case MESA_FORMAT_ETC2_SIGNED_R11_EAC: + return MESA_FORMAT_R16; + case MESA_FORMAT_ETC2_RG11_EAC: + case MESA_FORMAT_ETC2_SIGNED_RG11_EAC: + return MESA_FORMAT_RG1616; default: #ifdef DEBUG assert(!_mesa_is_format_compressed(format)); @@ -2282,6 +2395,16 @@ _mesa_format_to_type_and_comps(gl_format format, case MESA_FORMAT_LA_LATC2: case MESA_FORMAT_SIGNED_LA_LATC2: case MESA_FORMAT_ETC1_RGB8: + case MESA_FORMAT_ETC2_RGB8: + case MESA_FORMAT_ETC2_SRGB8: + case MESA_FORMAT_ETC2_RGBA8_EAC: + case MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC: + case MESA_FORMAT_ETC2_R11_EAC: + case MESA_FORMAT_ETC2_RG11_EAC: + case MESA_FORMAT_ETC2_SIGNED_R11_EAC: + case MESA_FORMAT_ETC2_SIGNED_RG11_EAC: + case MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1: + case MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1: /* XXX generate error instead? */ *datatype = GL_UNSIGNED_BYTE; *comps = 0; @@ -2912,6 +3035,16 @@ _mesa_format_matches_format_and_type(gl_format gl_format, return GL_FALSE; case MESA_FORMAT_ETC1_RGB8: + case MESA_FORMAT_ETC2_RGB8: + case MESA_FORMAT_ETC2_SRGB8: + case MESA_FORMAT_ETC2_RGBA8_EAC: + case MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC: + case MESA_FORMAT_ETC2_R11_EAC: + case MESA_FORMAT_ETC2_RG11_EAC: + case MESA_FORMAT_ETC2_SIGNED_R11_EAC: + case MESA_FORMAT_ETC2_SIGNED_RG11_EAC: + case MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1: + case MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1: return GL_FALSE; case MESA_FORMAT_SIGNED_A8: diff --git a/mesalib/src/mesa/main/formats.h b/mesalib/src/mesa/main/formats.h index 1843eb6fc..050fce96c 100644 --- a/mesalib/src/mesa/main/formats.h +++ b/mesalib/src/mesa/main/formats.h @@ -259,6 +259,16 @@ typedef enum /*@}*/ MESA_FORMAT_ETC1_RGB8, + MESA_FORMAT_ETC2_RGB8, + MESA_FORMAT_ETC2_SRGB8, + MESA_FORMAT_ETC2_RGBA8_EAC, + MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC, + MESA_FORMAT_ETC2_R11_EAC, + MESA_FORMAT_ETC2_RG11_EAC, + MESA_FORMAT_ETC2_SIGNED_R11_EAC, + MESA_FORMAT_ETC2_SIGNED_RG11_EAC, + MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1, + MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1, MESA_FORMAT_SIGNED_A8, /* AAAA AAAA */ MESA_FORMAT_SIGNED_L8, /* LLLL LLLL */ diff --git a/mesalib/src/mesa/main/glformats.c b/mesalib/src/mesa/main/glformats.c index 69caef70b..fefa9c441 100644 --- a/mesalib/src/mesa/main/glformats.c +++ b/mesalib/src/mesa/main/glformats.c @@ -570,6 +570,16 @@ _mesa_is_color_format(GLenum format) case GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT: case GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI: case GL_ETC1_RGB8_OES: + case GL_COMPRESSED_RGB8_ETC2: + case GL_COMPRESSED_SRGB8_ETC2: + case GL_COMPRESSED_RGBA8_ETC2_EAC: + case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC: + case GL_COMPRESSED_R11_EAC: + case GL_COMPRESSED_RG11_EAC: + case GL_COMPRESSED_SIGNED_R11_EAC: + case GL_COMPRESSED_SIGNED_RG11_EAC: + case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: + case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: /* generic integer formats */ case GL_RED_INTEGER_EXT: case GL_GREEN_INTEGER_EXT: @@ -829,6 +839,17 @@ _mesa_is_compressed_format(struct gl_context *ctx, GLenum format) case GL_ETC1_RGB8_OES: return _mesa_is_gles(ctx) && ctx->Extensions.OES_compressed_ETC1_RGB8_texture; + case GL_COMPRESSED_RGB8_ETC2: + case GL_COMPRESSED_SRGB8_ETC2: + case GL_COMPRESSED_RGBA8_ETC2_EAC: + case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC: + case GL_COMPRESSED_R11_EAC: + case GL_COMPRESSED_RG11_EAC: + case GL_COMPRESSED_SIGNED_R11_EAC: + case GL_COMPRESSED_SIGNED_RG11_EAC: + case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: + case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: + return _mesa_is_gles3(ctx); case GL_PALETTE4_RGB8_OES: case GL_PALETTE4_RGBA8_OES: case GL_PALETTE4_R5_G6_B5_OES: diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h index 5bfae69c8..b353e7026 100644 --- a/mesalib/src/mesa/main/mtypes.h +++ b/mesalib/src/mesa/main/mtypes.h @@ -79,6 +79,8 @@ struct st_context; struct gl_uniform_storage; struct prog_instruction; struct gl_program_parameter_list; +struct set; +struct set_entry; /*@}*/ @@ -2184,6 +2186,7 @@ struct gl_shader struct gl_sl_pragmas Pragmas; unsigned Version; /**< GLSL version used for linking */ + GLboolean IsES; /**< True if this shader uses GLSL ES */ /** * \name Sampler tracking @@ -2386,6 +2389,7 @@ struct gl_shader_program GLchar *InfoLog; unsigned Version; /**< GLSL version used for linking */ + GLboolean IsES; /**< True if this program uses GLSL ES */ /** * Per-stage shaders resulting from the first stage of linking. @@ -2509,7 +2513,7 @@ struct gl_query_state /** Sync object state */ struct gl_sync_object { - struct simple_node link; + struct set_entry *SetEntry; GLenum Type; /**< GL_SYNC_FENCE */ GLuint Name; /**< Fence name */ GLint RefCount; /**< Reference count */ @@ -2576,7 +2580,7 @@ struct gl_shared_state struct _mesa_HashTable *FrameBuffers; /* GL_ARB_sync */ - struct simple_node SyncObjects; + struct set *SyncObjects; /** GL_ARB_sampler_objects */ struct _mesa_HashTable *SamplerObjects; @@ -2939,6 +2943,7 @@ struct gl_extensions GLboolean dummy_false; /* Set false by _mesa_init_extensions(). */ GLboolean ANGLE_texture_compression_dxt; GLboolean ARB_ES2_compatibility; + GLboolean ARB_ES3_compatibility; GLboolean ARB_base_instance; GLboolean ARB_blend_func_extended; GLboolean ARB_color_buffer_float; diff --git a/mesalib/src/mesa/main/set.c b/mesalib/src/mesa/main/set.c new file mode 100644 index 000000000..736841fc9 --- /dev/null +++ b/mesalib/src/mesa/main/set.c @@ -0,0 +1,348 @@ +/* + * Copyright © 2009-2012 Intel Corporation + * Copyright © 1988-2004 Keith Packard and Bart Massey. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Except as contained in this notice, the names of the authors + * or their institutions shall not be used in advertising or + * otherwise to promote the sale, use or other dealings in this + * Software without prior written authorization from the + * authors. + * + * Authors: + * Eric Anholt <eric@anholt.net> + * Keith Packard <keithp@keithp.com> + */ + +#include <stdlib.h> + +#include "set.h" +#include "ralloc.h" + +#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0])) + +/* + * From Knuth -- a good choice for hash/rehash values is p, p-2 where + * p and p-2 are both prime. These tables are sized to have an extra 10% + * free to avoid exponential performance degradation as the hash table fills + */ + +uint32_t deleted_key_value; +const void *deleted_key = &deleted_key_value; + +static const struct { + uint32_t max_entries, size, rehash; +} hash_sizes[] = { + { 2, 5, 3 }, + { 4, 7, 5 }, + { 8, 13, 11 }, + { 16, 19, 17 }, + { 32, 43, 41 }, + { 64, 73, 71 }, + { 128, 151, 149 }, + { 256, 283, 281 }, + { 512, 571, 569 }, + { 1024, 1153, 1151 }, + { 2048, 2269, 2267 }, + { 4096, 4519, 4517 }, + { 8192, 9013, 9011 }, + { 16384, 18043, 18041 }, + { 32768, 36109, 36107 }, + { 65536, 72091, 72089 }, + { 131072, 144409, 144407 }, + { 262144, 288361, 288359 }, + { 524288, 576883, 576881 }, + { 1048576, 1153459, 1153457 }, + { 2097152, 2307163, 2307161 }, + { 4194304, 4613893, 4613891 }, + { 8388608, 9227641, 9227639 }, + { 16777216, 18455029, 18455027 }, + { 33554432, 36911011, 36911009 }, + { 67108864, 73819861, 73819859 }, + { 134217728, 147639589, 147639587 }, + { 268435456, 295279081, 295279079 }, + { 536870912, 590559793, 590559791 }, + { 1073741824, 1181116273, 1181116271 }, + { 2147483648ul, 2362232233ul, 2362232231ul } +}; + +static int +entry_is_free(struct set_entry *entry) +{ + return entry->key == NULL; +} + +static int +entry_is_deleted(struct set_entry *entry) +{ + return entry->key == deleted_key; +} + +static int +entry_is_present(struct set_entry *entry) +{ + return entry->key != NULL && entry->key != deleted_key; +} + +struct set * +_mesa_set_create(void *mem_ctx, + bool key_equals_function(const void *a, + const void *b)) +{ + struct set *ht; + + ht = ralloc(mem_ctx, struct set); + if (ht == NULL) + return NULL; + + ht->mem_ctx = mem_ctx; + ht->size_index = 0; + ht->size = hash_sizes[ht->size_index].size; + ht->rehash = hash_sizes[ht->size_index].rehash; + ht->max_entries = hash_sizes[ht->size_index].max_entries; + ht->key_equals_function = key_equals_function; + ht->table = rzalloc_array(ht, struct set_entry, ht->size); + ht->entries = 0; + ht->deleted_entries = 0; + + if (ht->table == NULL) { + ralloc_free(ht); + return NULL; + } + + return ht; +} + +/** + * Frees the given set. + * + * If delete_function is passed, it gets called on each entry present before + * freeing. + */ +void +_mesa_set_destroy(struct set *ht, void (*delete_function)(struct set_entry *entry)) +{ + if (!ht) + return; + + if (delete_function) { + struct set_entry *entry; + + set_foreach (ht, entry) { + delete_function(entry); + } + } + ralloc_free(ht->table); + ralloc_free(ht); +} + +/** + * Finds a set entry with the given key and hash of that key. + * + * Returns NULL if no entry is found. + */ +struct set_entry * +_mesa_set_search(const struct set *ht, uint32_t hash, const void *key) +{ + uint32_t hash_address; + + hash_address = hash % ht->size; + do { + uint32_t double_hash; + + struct set_entry *entry = ht->table + hash_address; + + if (entry_is_free(entry)) { + return NULL; + } else if (entry_is_present(entry) && entry->hash == hash) { + if (ht->key_equals_function(key, entry->key)) { + return entry; + } + } + + double_hash = 1 + hash % ht->rehash; + + hash_address = (hash_address + double_hash) % ht->size; + } while (hash_address != hash % ht->size); + + return NULL; +} + +static void +set_rehash(struct set *ht, int new_size_index) +{ + struct set old_ht; + struct set_entry *table, *entry; + + if (new_size_index >= ARRAY_SIZE(hash_sizes)) + return; + + table = rzalloc_array(ht, struct set_entry, + hash_sizes[new_size_index].size); + if (table == NULL) + return; + + old_ht = *ht; + + ht->table = table; + ht->size_index = new_size_index; + ht->size = hash_sizes[ht->size_index].size; + ht->rehash = hash_sizes[ht->size_index].rehash; + ht->max_entries = hash_sizes[ht->size_index].max_entries; + ht->entries = 0; + ht->deleted_entries = 0; + + for (entry = old_ht.table; + entry != old_ht.table + old_ht.size; + entry++) { + if (entry_is_present(entry)) { + _mesa_set_add(ht, entry->hash, entry->key); + } + } + + ralloc_free(old_ht.table); +} + +/** + * Inserts the key with the given hash into the table. + * + * Note that insertion may rearrange the table on a resize or rehash, + * so previously found hash_entries are no longer valid after this function. + */ +struct set_entry * +_mesa_set_add(struct set *ht, uint32_t hash, const void *key) +{ + uint32_t hash_address; + + if (ht->entries >= ht->max_entries) { + set_rehash(ht, ht->size_index + 1); + } else if (ht->deleted_entries + ht->entries >= ht->max_entries) { + set_rehash(ht, ht->size_index); + } + + hash_address = hash % ht->size; + do { + struct set_entry *entry = ht->table + hash_address; + uint32_t double_hash; + + if (!entry_is_present(entry)) { + if (entry_is_deleted(entry)) + ht->deleted_entries--; + entry->hash = hash; + entry->key = key; + ht->entries++; + return entry; + } + + /* Implement replacement when another insert happens + * with a matching key. This is a relatively common + * feature of hash tables, with the alternative + * generally being "insert the new value as well, and + * return it first when the key is searched for". + * + * Note that the hash table doesn't have a delete callback. + * If freeing of old keys is required to avoid memory leaks, + * perform a search before inserting. + */ + if (entry->hash == hash && + ht->key_equals_function(key, entry->key)) { + entry->key = key; + return entry; + } + + double_hash = 1 + hash % ht->rehash; + + hash_address = (hash_address + double_hash) % ht->size; + } while (hash_address != hash % ht->size); + + /* We could hit here if a required resize failed. An unchecked-malloc + * application could ignore this result. + */ + return NULL; +} + +/** + * This function deletes the given hash table entry. + * + * Note that deletion doesn't otherwise modify the table, so an iteration over + * the table deleting entries is safe. + */ +void +_mesa_set_remove(struct set *ht, struct set_entry *entry) +{ + if (!entry) + return; + + entry->key = deleted_key; + ht->entries--; + ht->deleted_entries++; +} + +/** + * This function is an iterator over the hash table. + * + * Pass in NULL for the first entry, as in the start of a for loop. Note that + * an iteration over the table is O(table_size) not O(entries). + */ +struct set_entry * +_mesa_set_next_entry(const struct set *ht, struct set_entry *entry) +{ + if (entry == NULL) + entry = ht->table; + else + entry = entry + 1; + + for (; entry != ht->table + ht->size; entry++) { + if (entry_is_present(entry)) { + return entry; + } + } + + return NULL; +} + +struct set_entry * +_mesa_set_random_entry(struct set *ht, + int (*predicate)(struct set_entry *entry)) +{ + struct set_entry *entry; + uint32_t i = rand() % ht->size; + + if (ht->entries == 0) + return NULL; + + for (entry = ht->table + i; entry != ht->table + ht->size; entry++) { + if (entry_is_present(entry) && + (!predicate || predicate(entry))) { + return entry; + } + } + + for (entry = ht->table; entry != ht->table + i; entry++) { + if (entry_is_present(entry) && + (!predicate || predicate(entry))) { + return entry; + } + } + + return NULL; +} + diff --git a/mesalib/src/mesa/main/set.h b/mesalib/src/mesa/main/set.h new file mode 100644 index 000000000..206d0c4d2 --- /dev/null +++ b/mesalib/src/mesa/main/set.h @@ -0,0 +1,94 @@ +/* + * Copyright © 2009-2012 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Eric Anholt <eric@anholt.net> + * + */ + +#ifndef _SET_H +#define _SET_H + +#include <inttypes.h> +#include <stdbool.h> + +#ifdef __cplusplus +extern "C" { +#endif + +struct set_entry { + uint32_t hash; + const void *key; +}; + +struct set { + void *mem_ctx; + struct set_entry *table; + bool (*key_equals_function)(const void *a, const void *b); + uint32_t size; + uint32_t rehash; + uint32_t max_entries; + uint32_t size_index; + uint32_t entries; + uint32_t deleted_entries; +}; + +struct set * +_mesa_set_create(void *mem_ctx, + bool (*key_equals_function)(const void *a, + const void *b)); +void +_mesa_set_destroy(struct set *set, + void (*delete_function)(struct set_entry *entry)); + +struct set_entry * +_mesa_set_add(struct set *set, uint32_t hash, const void *key); + +struct set_entry * +_mesa_set_search(const struct set *set, uint32_t hash, + const void *key); + +void +_mesa_set_remove(struct set *set, struct set_entry *entry); + +struct set_entry * +_mesa_set_next_entry(const struct set *set, struct set_entry *entry); + +struct set_entry * +_mesa_set_random_entry(struct set *set, + int (*predicate)(struct set_entry *entry)); + +/** + * This foreach function is safe against deletion, but not against + * insertion (which may rehash the set, making entry a dangling + * pointer). + */ +#define set_foreach(set, entry) \ + for (entry = _mesa_set_next_entry(set, NULL); \ + entry != NULL; \ + entry = _mesa_set_next_entry(set, entry)) + +#ifdef __cplusplus +} /* extern C */ +#endif + +#endif /* _SET_H */ diff --git a/mesalib/src/mesa/main/shared.c b/mesalib/src/mesa/main/shared.c index eaf9f8de1..a98a45c75 100644 --- a/mesalib/src/mesa/main/shared.c +++ b/mesalib/src/mesa/main/shared.c @@ -31,12 +31,14 @@ #include "mfeatures.h" #include "mtypes.h" #include "hash.h" +#include "hash_table.h" #include "atifragshader.h" #include "bufferobj.h" #include "shared.h" #include "program/program.h" #include "dlist.h" #include "samplerobj.h" +#include "set.h" #include "shaderobj.h" #include "syncobj.h" @@ -115,7 +117,7 @@ _mesa_alloc_shared_state(struct gl_context *ctx) shared->FrameBuffers = _mesa_NewHashTable(); shared->RenderBuffers = _mesa_NewHashTable(); - make_empty_list(& shared->SyncObjects); + shared->SyncObjects = _mesa_set_create(NULL, _mesa_key_pointer_equal); return shared; } @@ -327,13 +329,13 @@ free_shared_state(struct gl_context *ctx, struct gl_shared_state *shared) _mesa_reference_buffer_object(ctx, &shared->NullBufferObj, NULL); { - struct simple_node *node; - struct simple_node *temp; + struct set_entry *entry; - foreach_s(node, temp, & shared->SyncObjects) { - _mesa_unref_sync_object(ctx, (struct gl_sync_object *) node); + set_foreach(shared->SyncObjects, entry) { + _mesa_unref_sync_object(ctx, (struct gl_sync_object *) entry->key); } } + _mesa_set_destroy(shared->SyncObjects, NULL); _mesa_HashDeleteAll(shared->SamplerObjects, delete_sampler_object_cb, ctx); _mesa_DeleteHashTable(shared->SamplerObjects); diff --git a/mesalib/src/mesa/main/syncobj.c b/mesalib/src/mesa/main/syncobj.c index 598414596..12e325ccd 100644 --- a/mesalib/src/mesa/main/syncobj.c +++ b/mesalib/src/mesa/main/syncobj.c @@ -64,6 +64,8 @@ #include "get.h" #include "dispatch.h" #include "mtypes.h" +#include "set.h" +#include "hash_table.h" #include "syncobj.h" @@ -174,9 +176,12 @@ _mesa_free_sync_data(struct gl_context *ctx) static int -_mesa_validate_sync(struct gl_sync_object *syncObj) +_mesa_validate_sync(struct gl_context *ctx, struct gl_sync_object *syncObj) { return (syncObj != NULL) + && _mesa_set_search(ctx->Shared->SyncObjects, + _mesa_hash_pointer(syncObj), + syncObj) != NULL && (syncObj->Type == GL_SYNC_FENCE) && !syncObj->DeletePending; } @@ -197,7 +202,7 @@ _mesa_unref_sync_object(struct gl_context *ctx, struct gl_sync_object *syncObj) _glthread_LOCK_MUTEX(ctx->Shared->Mutex); syncObj->RefCount--; if (syncObj->RefCount == 0) { - remove_from_list(& syncObj->link); + _mesa_set_remove(ctx->Shared->SyncObjects, syncObj->SetEntry); _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); ctx->Driver.DeleteSyncObject(ctx, syncObj); @@ -214,7 +219,7 @@ _mesa_IsSync(GLsync sync) struct gl_sync_object *const syncObj = (struct gl_sync_object *) sync; ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); - return _mesa_validate_sync(syncObj) ? GL_TRUE : GL_FALSE; + return _mesa_validate_sync(ctx, syncObj) ? GL_TRUE : GL_FALSE; } @@ -235,8 +240,8 @@ _mesa_DeleteSync(GLsync sync) return; } - if (!_mesa_validate_sync(syncObj)) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glDeleteSync"); + if (!_mesa_validate_sync(ctx, syncObj)) { + _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteSync (not a valid sync object)"); return; } @@ -285,7 +290,9 @@ _mesa_FenceSync(GLenum condition, GLbitfield flags) ctx->Driver.FenceSync(ctx, syncObj, condition, flags); _glthread_LOCK_MUTEX(ctx->Shared->Mutex); - insert_at_tail(& ctx->Shared->SyncObjects, & syncObj->link); + syncObj->SetEntry = _mesa_set_add(ctx->Shared->SyncObjects, + _mesa_hash_pointer(syncObj), + syncObj); _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); return (GLsync) syncObj; @@ -303,8 +310,8 @@ _mesa_ClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) GLenum ret; ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_WAIT_FAILED); - if (!_mesa_validate_sync(syncObj)) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glClientWaitSync"); + if (!_mesa_validate_sync(ctx, syncObj)) { + _mesa_error(ctx, GL_INVALID_VALUE, "glClientWaitSync (not a valid sync object)"); return GL_WAIT_FAILED; } @@ -347,8 +354,8 @@ _mesa_WaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) struct gl_sync_object *const syncObj = (struct gl_sync_object *) sync; ASSERT_OUTSIDE_BEGIN_END(ctx); - if (!_mesa_validate_sync(syncObj)) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glWaitSync"); + if (!_mesa_validate_sync(ctx, syncObj)) { + _mesa_error(ctx, GL_INVALID_VALUE, "glWaitSync (not a valid sync object)"); return; } @@ -377,8 +384,8 @@ _mesa_GetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint v[1]; ASSERT_OUTSIDE_BEGIN_END(ctx); - if (!_mesa_validate_sync(syncObj)) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glGetSynciv"); + if (!_mesa_validate_sync(ctx, syncObj)) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGetSynciv (not a valid sync object)"); return; } diff --git a/mesalib/src/mesa/main/texcompress.c b/mesalib/src/mesa/main/texcompress.c index 957cc6df6..372a483fa 100644 --- a/mesalib/src/mesa/main/texcompress.c +++ b/mesalib/src/mesa/main/texcompress.c @@ -33,6 +33,7 @@ #include "glheader.h" #include "imports.h" #include "colormac.h" +#include "context.h" #include "formats.h" #include "mfeatures.h" #include "mtypes.h" @@ -77,12 +78,16 @@ _mesa_gl_compressed_format_base_format(GLenum format) { switch (format) { case GL_COMPRESSED_RED: + case GL_COMPRESSED_R11_EAC: case GL_COMPRESSED_RED_RGTC1: + case GL_COMPRESSED_SIGNED_R11_EAC: case GL_COMPRESSED_SIGNED_RED_RGTC1: return GL_RED; case GL_COMPRESSED_RG: + case GL_COMPRESSED_RG11_EAC: case GL_COMPRESSED_RG_RGTC2: + case GL_COMPRESSED_SIGNED_RG11_EAC: case GL_COMPRESSED_SIGNED_RG_RGTC2: return GL_RG; @@ -92,6 +97,8 @@ _mesa_gl_compressed_format_base_format(GLenum format) case GL_COMPRESSED_RGB_FXT1_3DFX: case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: case GL_ETC1_RGB8_OES: + case GL_COMPRESSED_RGB8_ETC2: + case GL_COMPRESSED_SRGB8_ETC2: return GL_RGB; case GL_COMPRESSED_RGBA: @@ -107,6 +114,10 @@ _mesa_gl_compressed_format_base_format(GLenum format) case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: + case GL_COMPRESSED_RGBA8_ETC2_EAC: + case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC: + case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: + case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: return GL_RGBA; case GL_COMPRESSED_ALPHA: @@ -293,6 +304,23 @@ _mesa_get_compressed_formats(struct gl_context *ctx, GLint *formats) } } + if (_mesa_is_gles3(ctx)) { + if (formats) { + formats[n++] = GL_COMPRESSED_RGB8_ETC2; + formats[n++] = GL_COMPRESSED_SRGB8_ETC2; + formats[n++] = GL_COMPRESSED_RGBA8_ETC2_EAC; + formats[n++] = GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC; + formats[n++] = GL_COMPRESSED_R11_EAC; + formats[n++] = GL_COMPRESSED_RG11_EAC; + formats[n++] = GL_COMPRESSED_SIGNED_R11_EAC; + formats[n++] = GL_COMPRESSED_SIGNED_RG11_EAC; + formats[n++] = GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2; + formats[n++] = GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2; + } + else { + n += 10; + } + } return n; } @@ -352,6 +380,26 @@ _mesa_glenum_to_compressed_format(GLenum format) case GL_ETC1_RGB8_OES: return MESA_FORMAT_ETC1_RGB8; + case GL_COMPRESSED_RGB8_ETC2: + return MESA_FORMAT_ETC2_RGB8; + case GL_COMPRESSED_SRGB8_ETC2: + return MESA_FORMAT_ETC2_SRGB8; + case GL_COMPRESSED_RGBA8_ETC2_EAC: + return MESA_FORMAT_ETC2_RGBA8_EAC; + case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC: + return MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC; + case GL_COMPRESSED_R11_EAC: + return MESA_FORMAT_ETC2_R11_EAC; + case GL_COMPRESSED_RG11_EAC: + return MESA_FORMAT_ETC2_RG11_EAC; + case GL_COMPRESSED_SIGNED_R11_EAC: + return MESA_FORMAT_ETC2_SIGNED_R11_EAC; + case GL_COMPRESSED_SIGNED_RG11_EAC: + return MESA_FORMAT_ETC2_SIGNED_RG11_EAC; + case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: + return MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1; + case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: + return MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1; default: return MESA_FORMAT_NONE; @@ -413,6 +461,26 @@ _mesa_compressed_format_to_glenum(struct gl_context *ctx, gl_format mesaFormat) case MESA_FORMAT_ETC1_RGB8: return GL_ETC1_RGB8_OES; + case MESA_FORMAT_ETC2_RGB8: + return GL_COMPRESSED_RGB8_ETC2; + case MESA_FORMAT_ETC2_SRGB8: + return GL_COMPRESSED_SRGB8_ETC2; + case MESA_FORMAT_ETC2_RGBA8_EAC: + return GL_COMPRESSED_RGBA8_ETC2_EAC; + case MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC: + return GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC; + case MESA_FORMAT_ETC2_R11_EAC: + return GL_COMPRESSED_R11_EAC; + case MESA_FORMAT_ETC2_RG11_EAC: + return GL_COMPRESSED_RG11_EAC; + case MESA_FORMAT_ETC2_SIGNED_R11_EAC: + return GL_COMPRESSED_SIGNED_R11_EAC; + case MESA_FORMAT_ETC2_SIGNED_RG11_EAC: + return GL_COMPRESSED_SIGNED_RG11_EAC; + case MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1: + return GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2; + case MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1: + return GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2; default: _mesa_problem(ctx, "Unexpected mesa texture format in" @@ -538,6 +606,38 @@ _mesa_decompress_image(gl_format format, GLuint width, GLuint height, fetch = _mesa_fetch_texel_2d_f_etc1_rgb8; break; + /* ETC2 formats */ + case MESA_FORMAT_ETC2_RGB8: + fetch = _mesa_fetch_texel_2d_f_etc2_rgb8; + break; + case MESA_FORMAT_ETC2_SRGB8: + fetch = _mesa_fetch_texel_2d_f_etc2_srgb8; + break; + case MESA_FORMAT_ETC2_RGBA8_EAC: + fetch = _mesa_fetch_texel_2d_f_etc2_rgba8_eac; + break; + case MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC: + fetch = _mesa_fetch_texel_2d_f_etc2_srgb8_alpha8_eac; + break; + case MESA_FORMAT_ETC2_R11_EAC: + fetch = _mesa_fetch_texel_2d_f_etc2_r11_eac; + break; + case MESA_FORMAT_ETC2_RG11_EAC: + fetch = _mesa_fetch_texel_2d_f_etc2_rg11_eac; + break; + case MESA_FORMAT_ETC2_SIGNED_R11_EAC: + fetch = _mesa_fetch_texel_2d_f_etc2_signed_r11_eac; + break; + case MESA_FORMAT_ETC2_SIGNED_RG11_EAC: + fetch = _mesa_fetch_texel_2d_f_etc2_signed_rg11_eac; + break; + case MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1: + fetch = _mesa_fetch_texel_2d_f_etc2_rgb8_punchthrough_alpha1; + break; + case MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1: + fetch = _mesa_fetch_texel_2d_f_etc2_srgb8_punchthrough_alpha1; + break; + default: _mesa_problem(NULL, "Unexpected format in _mesa_decompress_image()"); return; diff --git a/mesalib/src/mesa/main/texcompress_etc.c b/mesalib/src/mesa/main/texcompress_etc.c index c645f52b9..73d2fa4fe 100644 --- a/mesalib/src/mesa/main/texcompress_etc.c +++ b/mesalib/src/mesa/main/texcompress_etc.c @@ -24,24 +24,78 @@ /** * \file texcompress_etc.c * GL_OES_compressed_ETC1_RGB8_texture support. + * Supported ETC2 texture formats are: + * GL_COMPRESSED_RGB8_ETC2 + * GL_COMPRESSED_SRGB8_ETC2 + * GL_COMPRESSED_RGBA8_ETC2_EAC + * GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC + * GL_COMPRESSED_R11_EAC + * GL_COMPRESSED_RG11_EAC + * GL_COMPRESSED_SIGNED_R11_EAC + * GL_COMPRESSED_SIGNED_RG11_EAC + * MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1 + * MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1 */ - +#include <stdbool.h> #include "mfeatures.h" #include "texcompress.h" #include "texcompress_etc.h" #include "texstore.h" #include "macros.h" #include "swrast/s_context.h" +#include "format_unpack.h" -GLboolean -_mesa_texstore_etc1_rgb8(TEXSTORE_PARAMS) -{ - /* GL_ETC1_RGB8_OES is only valid in glCompressedTexImage2D */ - ASSERT(0); +struct etc2_block { + int distance; + uint64_t pixel_indices[2]; + const int *modifier_tables[2]; + bool flipped; + bool opaque; + bool is_ind_mode; + bool is_diff_mode; + bool is_t_mode; + bool is_h_mode; + bool is_planar_mode; + uint8_t base_colors[3][3]; + uint8_t paint_colors[4][3]; + uint8_t base_codeword; + uint8_t multiplier; + uint8_t table_index; +}; - return GL_FALSE; -} +static const int etc2_distance_table[8] = { + 3, 6, 11, 16, 23, 32, 41, 64 }; + +static const int etc2_modifier_tables[16][8] = { + { -3, -6, -9, -15, 2, 5, 8, 14}, + { -3, -7, -10, -13, 2, 6, 9, 12}, + { -2, -5, -8, -13, 1, 4, 7, 12}, + { -2, -4, -6, -13, 1, 3, 5, 12}, + { -3, -6, -8, -12, 2, 5, 7, 11}, + { -3, -7, -9, -11, 2, 6, 8, 10}, + { -4, -7, -8, -11, 3, 6, 7, 10}, + { -3, -5, -8, -11, 2, 4, 7, 10}, + { -2, -6, -8, -10, 1, 5, 7, 9}, + { -2, -5, -8, -10, 1, 4, 7, 9}, + { -2, -4, -8, -10, 1, 3, 7, 9}, + { -2, -5, -7, -10, 1, 4, 6, 9}, + { -3, -4, -7, -10, 2, 3, 6, 9}, + { -1, -2, -3, -10, 0, 1, 2, 9}, + { -4, -6, -8, -9, 3, 5, 7, 8}, + { -3, -5, -7, -9, 2, 4, 6, 8}, +}; + +static const int etc2_modifier_tables_non_opaque[8][4] = { + { 0, 8, 0, -8}, + { 0, 17, 0, -17}, + { 0, 29, 0, -29}, + { 0, 42, 0, -42}, + { 0, 60, 0, -60}, + { 0, 80, 0, -80}, + { 0, 106, 0, -106}, + { 0, 183, 0, -183} +}; /* define etc1_parse_block and etc. */ #define UINT8_TYPE GLubyte @@ -50,6 +104,15 @@ _mesa_texstore_etc1_rgb8(TEXSTORE_PARAMS) #undef TAG #undef UINT8_TYPE +GLboolean +_mesa_texstore_etc1_rgb8(TEXSTORE_PARAMS) +{ + /* GL_ETC1_RGB8_OES is only valid in glCompressedTexImage2D */ + ASSERT(0); + + return GL_FALSE; +} + void _mesa_fetch_texel_2d_f_etc1_rgb8(const struct swrast_texture_image *texImage, GLint i, GLint j, GLint k, GLfloat *texel) @@ -101,3 +164,1300 @@ _mesa_etc1_unpack_rgba8888(uint8_t *dst_row, src_row, src_stride, src_width, src_height); } + +static uint8_t +etc2_base_color1_t_mode(const uint8_t *in, GLuint index) +{ + uint8_t R1a = 0, x = 0; + /* base col 1 = extend_4to8bits( (R1a << 2) | R1b, G1, B1) */ + switch(index) { + case 0: + R1a = (in[0] >> 3) & 0x3; + x = ((R1a << 2) | (in[0] & 0x3)); + break; + case 1: + x = ((in[1] >> 4) & 0xf); + break; + case 2: + x = (in[1] & 0xf); + break; + default: + /* invalid index */ + break; + } + return ((x << 4) | (x & 0xf)); +} + +static uint8_t +etc2_base_color2_t_mode(const uint8_t *in, GLuint index) +{ + uint8_t x = 0; + /*extend 4to8bits(R2, G2, B2)*/ + switch(index) { + case 0: + x = ((in[2] >> 4) & 0xf ); + break; + case 1: + x = (in[2] & 0xf); + break; + case 2: + x = ((in[3] >> 4) & 0xf); + break; + default: + /* invalid index */ + break; + } + return ((x << 4) | (x & 0xf)); +} + +static uint8_t +etc2_base_color1_h_mode(const uint8_t *in, GLuint index) +{ + uint8_t x = 0; + /* base col 1 = extend 4to8bits(R1, (G1a << 1) | G1b, (B1a << 3) | B1b) */ + switch(index) { + case 0: + x = ((in[0] >> 3) & 0xf); + break; + case 1: + x = (((in[0] & 0x7) << 1) | ((in[1] >> 4) & 0x1)); + break; + case 2: + x = ((in[1] & 0x8) | + (((in[1] & 0x3) << 1) | ((in[2] >> 7) & 0x1))); + break; + default: + /* invalid index */ + break; + } + return ((x << 4) | (x & 0xf)); + } + +static uint8_t +etc2_base_color2_h_mode(const uint8_t *in, GLuint index) +{ + uint8_t x = 0; + /* base col 2 = extend 4to8bits(R2, G2, B2) */ + switch(index) { + case 0: + x = ((in[2] >> 3) & 0xf ); + break; + case 1: + x = (((in[2] & 0x7) << 1) | ((in[3] >> 7) & 0x1)); + break; + case 2: + x = ((in[3] >> 3) & 0xf); + break; + default: + /* invalid index */ + break; + } + return ((x << 4) | (x & 0xf)); + } + +static uint8_t +etc2_base_color_o_planar(const uint8_t *in, GLuint index) +{ + GLuint tmp; + switch(index) { + case 0: + tmp = ((in[0] >> 1) & 0x3f); /* RO */ + return ((tmp << 2) | (tmp >> 4)); + case 1: + tmp = (((in[0] & 0x1) << 6) | /* GO1 */ + ((in[1] >> 1) & 0x3f)); /* GO2 */ + return ((tmp << 1) | (tmp >> 6)); + case 2: + tmp = (((in[1] & 0x1) << 5) | /* BO1 */ + (in[2] & 0x18) | /* BO2 */ + (((in[2] & 0x3) << 1) | ((in[3] >> 7) & 0x1))); /* BO3 */ + return ((tmp << 2) | (tmp >> 4)); + default: + /* invalid index */ + return 0; + } +} + +static uint8_t +etc2_base_color_h_planar(const uint8_t *in, GLuint index) +{ + GLuint tmp; + switch(index) { + case 0: + tmp = (((in[3] & 0x7c) >> 1) | /* RH1 */ + (in[3] & 0x1)); /* RH2 */ + return ((tmp << 2) | (tmp >> 4)); + case 1: + tmp = (in[4] >> 1) & 0x7f; /* GH */ + return ((tmp << 1) | (tmp >> 6)); + case 2: + tmp = (((in[4] & 0x1) << 5) | + ((in[5] >> 3) & 0x1f)); /* BH */ + return ((tmp << 2) | (tmp >> 4)); + default: + /* invalid index */ + return 0; + } +} + +static uint8_t +etc2_base_color_v_planar(const uint8_t *in, GLuint index) +{ + GLuint tmp; + switch(index) { + case 0: + tmp = (((in[5] & 0x7) << 0x3) | + ((in[6] >> 5) & 0x7)); /* RV */ + return ((tmp << 2) | (tmp >> 4)); + case 1: + tmp = (((in[6] & 0x1f) << 2) | + ((in[7] >> 6) & 0x3)); /* GV */ + return ((tmp << 1) | (tmp >> 6)); + case 2: + tmp = in[7] & 0x3f; /* BV */ + return ((tmp << 2) | (tmp >> 4)); + default: + /* invalid index */ + return 0; + } +} + +static GLint +etc2_get_pixel_index(const struct etc2_block *block, int x, int y) +{ + int bit = ((3 - y) + (3 - x) * 4) * 3; + int idx = (block->pixel_indices[1] >> bit) & 0x7; + return idx; +} + +static uint8_t +etc2_clamp(int color) +{ + /* CLAMP(color, 0, 255) */ + return (uint8_t) CLAMP(color, 0, 255); +} + +static GLushort +etc2_clamp2(int color) +{ + /* CLAMP(color, 0, 2047) */ + return (GLushort) CLAMP(color, 0, 2047); +} + +static GLshort +etc2_clamp3(int color) +{ + /* CLAMP(color, -1023, 1023) */ + return (GLshort) CLAMP(color, -1023, 1023); +} + +static void +etc2_rgb8_parse_block(struct etc2_block *block, + const uint8_t *src, + GLboolean punchthrough_alpha) +{ + unsigned i; + GLboolean diffbit = false; + static const int lookup[8] = { 0, 1, 2, 3, -4, -3, -2, -1 }; + + const int R_plus_dR = (src[0] >> 3) + lookup[src[0] & 0x7]; + const int G_plus_dG = (src[1] >> 3) + lookup[src[1] & 0x7]; + const int B_plus_dB = (src[2] >> 3) + lookup[src[2] & 0x7]; + + /* Reset the mode flags */ + block->is_ind_mode = false; + block->is_diff_mode = false; + block->is_t_mode = false; + block->is_h_mode = false; + block->is_planar_mode = false; + + if (punchthrough_alpha) + block->opaque = src[3] & 0x2; + else + diffbit = src[3] & 0x2; + + if (!diffbit && !punchthrough_alpha) { + /* individual mode */ + block->is_ind_mode = true; + + for (i = 0; i < 3; i++) { + /* Texture decode algorithm is same for individual mode in etc1 + * & etc2. + */ + block->base_colors[0][i] = etc1_base_color_ind_hi(src[i]); + block->base_colors[1][i] = etc1_base_color_ind_lo(src[i]); + } + } + else if (R_plus_dR < 0 || R_plus_dR > 31){ + /* T mode */ + block->is_t_mode = true; + + for(i = 0; i < 3; i++) { + block->base_colors[0][i] = etc2_base_color1_t_mode(src, i); + block->base_colors[1][i] = etc2_base_color2_t_mode(src, i); + } + /* pick distance */ + block->distance = + etc2_distance_table[(((src[3] >> 2) & 0x3) << 1) | + (src[3] & 0x1)]; + + for (i = 0; i < 3; i++) { + block->paint_colors[0][i] = etc2_clamp(block->base_colors[0][i]); + block->paint_colors[1][i] = etc2_clamp(block->base_colors[1][i] + + block->distance); + block->paint_colors[2][i] = etc2_clamp(block->base_colors[1][i]); + block->paint_colors[3][i] = etc2_clamp(block->base_colors[1][i] - + block->distance); + } + } + else if (G_plus_dG < 0 || G_plus_dG > 31){ + int base_color_1_value, base_color_2_value; + + /* H mode */ + block->is_h_mode = true; + + for(i = 0; i < 3; i++) { + block->base_colors[0][i] = etc2_base_color1_h_mode(src, i); + block->base_colors[1][i] = etc2_base_color2_h_mode(src, i); + } + + base_color_1_value = (block->base_colors[0][0] << 16) + + (block->base_colors[0][1] << 8) + + block->base_colors[0][2]; + base_color_2_value = (block->base_colors[1][0] << 16) + + (block->base_colors[1][1] << 8) + + block->base_colors[1][2]; + /* pick distance */ + block->distance = + etc2_distance_table[(src[3] & 0x4) | + ((src[3] & 0x1) << 1) | + (base_color_1_value >= base_color_2_value)]; + + for (i = 0; i < 3; i++) { + block->paint_colors[0][i] = etc2_clamp(block->base_colors[0][i] + + block->distance); + block->paint_colors[1][i] = etc2_clamp(block->base_colors[0][i] - + block->distance); + block->paint_colors[2][i] = etc2_clamp(block->base_colors[1][i] + + block->distance); + block->paint_colors[3][i] = etc2_clamp(block->base_colors[1][i] - + block->distance); + } + } + else if (B_plus_dB < 0 || B_plus_dB > 31) { + /* Planar mode */ + block->is_planar_mode = true; + + /* opaque bit must be set in planar mode */ + if (!block->opaque) + block->opaque = true; + + for (i = 0; i < 3; i++) { + block->base_colors[0][i] = etc2_base_color_o_planar(src, i); + block->base_colors[1][i] = etc2_base_color_h_planar(src, i); + block->base_colors[2][i] = etc2_base_color_v_planar(src, i); + } + } + else if (diffbit || punchthrough_alpha) { + /* differential mode */ + block->is_diff_mode = true; + + for (i = 0; i < 3; i++) { + /* Texture decode algorithm is same for differential mode in etc1 + * & etc2. + */ + block->base_colors[0][i] = etc1_base_color_diff_hi(src[i]); + block->base_colors[1][i] = etc1_base_color_diff_lo(src[i]); + } + } + + if (block->is_ind_mode || block->is_diff_mode) { + int table1_idx = (src[3] >> 5) & 0x7; + int table2_idx = (src[3] >> 2) & 0x7; + + /* Use same modifier tables as for etc1 textures if opaque bit is set + * or if non punchthrough texture format + */ + block->modifier_tables[0] = (block->opaque || !punchthrough_alpha) ? + etc1_modifier_tables[table1_idx] : + etc2_modifier_tables_non_opaque[table1_idx]; + block->modifier_tables[1] = (block->opaque || !punchthrough_alpha) ? + etc1_modifier_tables[table2_idx] : + etc2_modifier_tables_non_opaque[table2_idx]; + + block->flipped = (src[3] & 0x1); + } + + block->pixel_indices[0] = + (src[4] << 24) | (src[5] << 16) | (src[6] << 8) | src[7]; +} + +static void +etc2_rgb8_fetch_texel(const struct etc2_block *block, + int x, int y, uint8_t *dst, + GLboolean punchthrough_alpha) +{ + const uint8_t *base_color; + int modifier, bit, idx, blk; + + /* get pixel index */ + bit = y + x * 4; + idx = ((block->pixel_indices[0] >> (15 + bit)) & 0x2) | + ((block->pixel_indices[0] >> (bit)) & 0x1); + + if (block->is_ind_mode || block->is_diff_mode) { + /* check for punchthrough_alpha format */ + if (punchthrough_alpha) { + if (!block->opaque && idx == 2) { + dst[0] = dst[1] = dst[2] = dst[3] = 0; + return; + } + else + dst[3] = 255; + } + + /* Use pixel index and subblock to get the modifier */ + blk = (block->flipped) ? (y >= 2) : (x >= 2); + base_color = block->base_colors[blk]; + modifier = block->modifier_tables[blk][idx]; + + dst[0] = etc2_clamp(base_color[0] + modifier); + dst[1] = etc2_clamp(base_color[1] + modifier); + dst[2] = etc2_clamp(base_color[2] + modifier); + } + else if (block->is_t_mode || block->is_h_mode) { + /* check for punchthrough_alpha format */ + if (punchthrough_alpha) { + if (!block->opaque && idx == 2) { + dst[0] = dst[1] = dst[2] = dst[3] = 0; + return; + } + else + dst[3] = 255; + } + + /* Use pixel index to pick one of the paint colors */ + dst[0] = block->paint_colors[idx][0]; + dst[1] = block->paint_colors[idx][1]; + dst[2] = block->paint_colors[idx][2]; + } + else if (block->is_planar_mode) { + /* {R(x, y) = clamp255((x × (RH − RO) + y × (RV − RO) + 4 × RO + 2) >> 2) + * {G(x, y) = clamp255((x × (GH − GO) + y × (GV − GO) + 4 × GO + 2) >> 2) + * {B(x, y) = clamp255((x × (BH − BO) + y × (BV − BO) + 4 × BO + 2) >> 2) + */ + int red, green, blue; + red = (x * (block->base_colors[1][0] - block->base_colors[0][0]) + + y * (block->base_colors[2][0] - block->base_colors[0][0]) + + 4 * block->base_colors[0][0] + 2) >> 2; + + green = (x * (block->base_colors[1][1] - block->base_colors[0][1]) + + y * (block->base_colors[2][1] - block->base_colors[0][1]) + + 4 * block->base_colors[0][1] + 2) >> 2; + + blue = (x * (block->base_colors[1][2] - block->base_colors[0][2]) + + y * (block->base_colors[2][2] - block->base_colors[0][2]) + + 4 * block->base_colors[0][2] + 2) >> 2; + + dst[0] = etc2_clamp(red); + dst[1] = etc2_clamp(green); + dst[2] = etc2_clamp(blue); + + /* check for punchthrough_alpha format */ + if (punchthrough_alpha) + dst[3] = 255; + } +} + +static void +etc2_alpha8_fetch_texel(const struct etc2_block *block, + int x, int y, uint8_t *dst) +{ + int modifier, alpha, idx; + /* get pixel index */ + idx = etc2_get_pixel_index(block, x, y); + modifier = etc2_modifier_tables[block->table_index][idx]; + alpha = block->base_codeword + modifier * block->multiplier; + dst[3] = etc2_clamp(alpha); +} + +static void +etc2_r11_fetch_texel(const struct etc2_block *block, + int x, int y, uint8_t *dst) +{ + GLint modifier, idx; + GLshort color; + /* Get pixel index */ + idx = etc2_get_pixel_index(block, x, y); + modifier = etc2_modifier_tables[block->table_index][idx]; + + if (block->multiplier != 0) + /* clamp2(base codeword × 8 + 4 + modifier × multiplier × 8) */ + color = etc2_clamp2(((block->base_codeword << 3) | 0x4) + + ((modifier * block->multiplier) << 3)); + else + color = etc2_clamp2(((block->base_codeword << 3) | 0x4) + modifier); + + /* Extend 11 bits color value to 16 bits. OpenGL ES 3.0 specification + * allows extending the color value to any number of bits. But, an + * implementation is not allowed to truncate the 11-bit value to less than + * 11 bits." + */ + color = (color << 5) | (color >> 6); + ((GLushort *)dst)[0] = color; +} + +static void +etc2_signed_r11_fetch_texel(const struct etc2_block *block, + int x, int y, uint8_t *dst) +{ + GLint modifier, idx; + GLshort color; + GLbyte base_codeword = (GLbyte) block->base_codeword; + + if (base_codeword == -128) + base_codeword = -127; + + /* Get pixel index */ + idx = etc2_get_pixel_index(block, x, y); + modifier = etc2_modifier_tables[block->table_index][idx]; + + if (block->multiplier != 0) + /* clamp3(base codeword × 8 + modifier × multiplier × 8) */ + color = etc2_clamp3((base_codeword << 3) + + ((modifier * block->multiplier) << 3)); + else + color = etc2_clamp3((base_codeword << 3) + modifier); + + /* Extend 11 bits color value to 16 bits. OpenGL ES 3.0 specification + * allows extending the color value to any number of bits. But, an + * implementation is not allowed to truncate the 11-bit value to less than + * 11 bits. A negative 11-bit value must first be made positive before bit + * replication, and then made negative again + */ + if (color >= 0) + color = (color << 5) | (color >> 5); + else { + color = -color; + color = (color << 5) | (color >> 5); + color = -color; + } + ((GLshort *)dst)[0] = color; +} + +static void +etc2_alpha8_parse_block(struct etc2_block *block, const uint8_t *src) +{ + block->base_codeword = src[0]; + block->multiplier = (src[1] >> 4) & 0xf; + block->table_index = src[1] & 0xf; + block->pixel_indices[1] = (((uint64_t)src[2] << 40) | + ((uint64_t)src[3] << 32) | + ((uint64_t)src[4] << 24) | + ((uint64_t)src[5] << 16) | + ((uint64_t)src[6] << 8) | + ((uint64_t)src[7])); +} + +static void +etc2_r11_parse_block(struct etc2_block *block, const uint8_t *src) +{ + /* Parsing logic remains same as for etc2_alpha8_parse_block */ + etc2_alpha8_parse_block(block, src); +} + +static void +etc2_rgba8_parse_block(struct etc2_block *block, const uint8_t *src) +{ + /* RGB component is parsed the same way as for MESA_FORMAT_ETC2_RGB8 */ + etc2_rgb8_parse_block(block, src + 8, + false /* punchthrough_alpha */); + /* Parse Alpha component */ + etc2_alpha8_parse_block(block, src); +} + +static void +etc2_rgba8_fetch_texel(const struct etc2_block *block, + int x, int y, uint8_t *dst) +{ + etc2_rgb8_fetch_texel(block, x, y, dst, + false /* punchthrough_alpha */); + etc2_alpha8_fetch_texel(block, x, y, dst); +} + +static void +etc2_unpack_rgb8(uint8_t *dst_row, + unsigned dst_stride, + const uint8_t *src_row, + unsigned src_stride, + unsigned width, + unsigned height) +{ + const unsigned bw = 4, bh = 4, bs = 8, comps = 4; + struct etc2_block block; + unsigned x, y, i, j; + + for (y = 0; y < height; y += bh) { + const uint8_t *src = src_row; + + for (x = 0; x < width; x+= bw) { + etc2_rgb8_parse_block(&block, src, + false /* punchthrough_alpha */); + + for (j = 0; j < bh; j++) { + uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps; + for (i = 0; i < bw; i++) { + etc2_rgb8_fetch_texel(&block, i, j, dst, + false /* punchthrough_alpha */); + dst[3] = 255; + dst += comps; + } + } + + src += bs; + } + + src_row += src_stride; + } +} + +static void +etc2_unpack_srgb8(uint8_t *dst_row, + unsigned dst_stride, + const uint8_t *src_row, + unsigned src_stride, + unsigned width, + unsigned height) +{ + const unsigned bw = 4, bh = 4, bs = 8, comps = 4; + struct etc2_block block; + unsigned x, y, i, j; + uint8_t tmp; + + for (y = 0; y < height; y += bh) { + const uint8_t *src = src_row; + + for (x = 0; x < width; x+= bw) { + etc2_rgb8_parse_block(&block, src, + false /* punchthrough_alpha */); + + for (j = 0; j < bh; j++) { + uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps; + for (i = 0; i < bw; i++) { + etc2_rgb8_fetch_texel(&block, i, j, dst, + false /* punchthrough_alpha */); + /* Convert to MESA_FORMAT_SARGB8 */ + tmp = dst[0]; + dst[0] = dst[2]; + dst[2] = tmp; + dst[3] = 255; + + dst += comps; + } + } + src += bs; + } + + src_row += src_stride; + } +} + +static void +etc2_unpack_rgba8(uint8_t *dst_row, + unsigned dst_stride, + const uint8_t *src_row, + unsigned src_stride, + unsigned width, + unsigned height) +{ + /* If internalformat is COMPRESSED_RGBA8_ETC2_EAC, each 4 × 4 block of + * RGBA8888 information is compressed to 128 bits. To decode a block, the + * two 64-bit integers int64bitAlpha and int64bitColor are calculated. + */ + const unsigned bw = 4, bh = 4, bs = 16, comps = 4; + struct etc2_block block; + unsigned x, y, i, j; + + for (y = 0; y < height; y += bh) { + const uint8_t *src = src_row; + + for (x = 0; x < width; x+= bw) { + etc2_rgba8_parse_block(&block, src); + + for (j = 0; j < bh; j++) { + uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps; + for (i = 0; i < bw; i++) { + etc2_rgba8_fetch_texel(&block, i, j, dst); + dst += comps; + } + } + src += bs; + } + + src_row += src_stride; + } +} + +static void +etc2_unpack_srgb8_alpha8(uint8_t *dst_row, + unsigned dst_stride, + const uint8_t *src_row, + unsigned src_stride, + unsigned width, + unsigned height) +{ + /* If internalformat is COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, each 4 × 4 block + * of RGBA8888 information is compressed to 128 bits. To decode a block, the + * two 64-bit integers int64bitAlpha and int64bitColor are calculated. + */ + const unsigned bw = 4, bh = 4, bs = 16, comps = 4; + struct etc2_block block; + unsigned x, y, i, j; + uint8_t tmp; + + for (y = 0; y < height; y += bh) { + const uint8_t *src = src_row; + + for (x = 0; x < width; x+= bw) { + etc2_rgba8_parse_block(&block, src); + + for (j = 0; j < bh; j++) { + uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps; + for (i = 0; i < bw; i++) { + etc2_rgba8_fetch_texel(&block, i, j, dst); + + /* Convert to MESA_FORMAT_SARGB8 */ + tmp = dst[0]; + dst[0] = dst[2]; + dst[2] = tmp; + dst[3] = dst[3]; + + dst += comps; + } + } + src += bs; + } + + src_row += src_stride; + } +} + +static void +etc2_unpack_r11(uint8_t *dst_row, + unsigned dst_stride, + const uint8_t *src_row, + unsigned src_stride, + unsigned width, + unsigned height) +{ + /* If internalformat is COMPRESSED_R11_EAC, each 4 × 4 block of + color information is compressed to 64 bits. + */ + const unsigned bw = 4, bh = 4, bs = 8, comps = 1, comp_size = 2; + struct etc2_block block; + unsigned x, y, i, j; + + for (y = 0; y < height; y += bh) { + const uint8_t *src = src_row; + + for (x = 0; x < width; x+= bw) { + etc2_r11_parse_block(&block, src); + + for (j = 0; j < bh; j++) { + uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps * comp_size; + for (i = 0; i < bw; i++) { + etc2_r11_fetch_texel(&block, i, j, dst); + dst += comps * comp_size; + } + } + src += bs; + } + + src_row += src_stride; + } +} + +static void +etc2_unpack_rg11(uint8_t *dst_row, + unsigned dst_stride, + const uint8_t *src_row, + unsigned src_stride, + unsigned width, + unsigned height) +{ + /* If internalformat is COMPRESSED_RG11_EAC, each 4 × 4 block of + RG color information is compressed to 128 bits. + */ + const unsigned bw = 4, bh = 4, bs = 16, comps = 2, comp_size = 2; + struct etc2_block block; + unsigned x, y, i, j; + + for (y = 0; y < height; y += bh) { + const uint8_t *src = src_row; + + for (x = 0; x < width; x+= bw) { + /* red component */ + etc2_r11_parse_block(&block, src); + + for (j = 0; j < bh; j++) { + uint8_t *dst = dst_row + (y + j) * dst_stride + + x * comps * comp_size; + for (i = 0; i < bw; i++) { + etc2_r11_fetch_texel(&block, i, j, dst); + dst += comps * comp_size; + } + } + /* green component */ + etc2_r11_parse_block(&block, src + 8); + + for (j = 0; j < bh; j++) { + uint8_t *dst = dst_row + (y + j) * dst_stride + + x * comps * comp_size; + for (i = 0; i < bw; i++) { + etc2_r11_fetch_texel(&block, i, j, dst + comp_size); + dst += comps * comp_size; + } + } + src += bs; + } + + src_row += src_stride; + } +} + +static void +etc2_unpack_signed_r11(uint8_t *dst_row, + unsigned dst_stride, + const uint8_t *src_row, + unsigned src_stride, + unsigned width, + unsigned height) +{ + /* If internalformat is COMPRESSED_SIGNED_R11_EAC, each 4 × 4 block of + red color information is compressed to 64 bits. + */ + const unsigned bw = 4, bh = 4, bs = 8, comps = 1, comp_size = 2; + struct etc2_block block; + unsigned x, y, i, j; + + for (y = 0; y < height; y += bh) { + const uint8_t *src = src_row; + + for (x = 0; x < width; x+= bw) { + etc2_r11_parse_block(&block, src); + + for (j = 0; j < bh; j++) { + uint8_t *dst = dst_row + (y + j) * dst_stride + + x * comps * comp_size; + for (i = 0; i < bw; i++) { + etc2_signed_r11_fetch_texel(&block, i, j, dst); + dst += comps * comp_size; + } + } + src += bs; + } + + src_row += src_stride; + } +} + +static void +etc2_unpack_signed_rg11(uint8_t *dst_row, + unsigned dst_stride, + const uint8_t *src_row, + unsigned src_stride, + unsigned width, + unsigned height) +{ + /* If internalformat is COMPRESSED_SIGNED_RG11_EAC, each 4 × 4 block of + RG color information is compressed to 128 bits. + */ + const unsigned bw = 4, bh = 4, bs = 16, comps = 2, comp_size = 2; + struct etc2_block block; + unsigned x, y, i, j; + + for (y = 0; y < height; y += bh) { + const uint8_t *src = src_row; + + for (x = 0; x < width; x+= bw) { + /* red component */ + etc2_r11_parse_block(&block, src); + + for (j = 0; j < bh; j++) { + uint8_t *dst = dst_row + (y + j) * dst_stride + + x * comps * comp_size; + for (i = 0; i < bw; i++) { + etc2_signed_r11_fetch_texel(&block, i, j, dst); + dst += comps * comp_size; + } + } + /* green component */ + etc2_r11_parse_block(&block, src + 8); + + for (j = 0; j < bh; j++) { + uint8_t *dst = dst_row + (y + j) * dst_stride + + x * comps * comp_size; + for (i = 0; i < bw; i++) { + etc2_signed_r11_fetch_texel(&block, i, j, dst + comp_size); + dst += comps * comp_size; + } + } + src += bs; + } + + src_row += src_stride; + } +} + +static void +etc2_unpack_rgb8_punchthrough_alpha1(uint8_t *dst_row, + unsigned dst_stride, + const uint8_t *src_row, + unsigned src_stride, + unsigned width, + unsigned height) +{ + const unsigned bw = 4, bh = 4, bs = 8, comps = 4; + struct etc2_block block; + unsigned x, y, i, j; + + for (y = 0; y < height; y += bh) { + const uint8_t *src = src_row; + + for (x = 0; x < width; x+= bw) { + etc2_rgb8_parse_block(&block, src, + true /* punchthrough_alpha */); + for (j = 0; j < bh; j++) { + uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps; + for (i = 0; i < bw; i++) { + etc2_rgb8_fetch_texel(&block, i, j, dst, + true /* punchthrough_alpha */); + dst += comps; + } + } + + src += bs; + } + + src_row += src_stride; + } +} + +static void +etc2_unpack_srgb8_punchthrough_alpha1(uint8_t *dst_row, + unsigned dst_stride, + const uint8_t *src_row, + unsigned src_stride, + unsigned width, + unsigned height) +{ + const unsigned bw = 4, bh = 4, bs = 8, comps = 4; + struct etc2_block block; + unsigned x, y, i, j; + uint8_t tmp; + + for (y = 0; y < height; y += bh) { + const uint8_t *src = src_row; + + for (x = 0; x < width; x+= bw) { + etc2_rgb8_parse_block(&block, src, + true /* punchthrough_alpha */); + for (j = 0; j < bh; j++) { + uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps; + for (i = 0; i < bw; i++) { + etc2_rgb8_fetch_texel(&block, i, j, dst, + true /* punchthrough_alpha */); + /* Convert to MESA_FORMAT_SARGB8 */ + tmp = dst[0]; + dst[0] = dst[2]; + dst[2] = tmp; + dst[3] = dst[3]; + + dst += comps; + } + } + + src += bs; + } + + src_row += src_stride; + } +} + +/* ETC2 texture formats are valid in glCompressedTexImage2D and + * glCompressedTexSubImage2D functions */ +GLboolean +_mesa_texstore_etc2_rgb8(TEXSTORE_PARAMS) +{ + ASSERT(0); + + return GL_FALSE; +} + +GLboolean +_mesa_texstore_etc2_srgb8(TEXSTORE_PARAMS) +{ + ASSERT(0); + + return GL_FALSE; +} + +GLboolean +_mesa_texstore_etc2_rgba8_eac(TEXSTORE_PARAMS) +{ + ASSERT(0); + + return GL_FALSE; +} + +GLboolean +_mesa_texstore_etc2_srgb8_alpha8_eac(TEXSTORE_PARAMS) +{ + ASSERT(0); + + return GL_FALSE; +} + +GLboolean +_mesa_texstore_etc2_r11_eac(TEXSTORE_PARAMS) +{ + ASSERT(0); + + return GL_FALSE; +} + +GLboolean +_mesa_texstore_etc2_signed_r11_eac(TEXSTORE_PARAMS) +{ + ASSERT(0); + + return GL_FALSE; +} + +GLboolean +_mesa_texstore_etc2_rg11_eac(TEXSTORE_PARAMS) +{ + ASSERT(0); + + return GL_FALSE; +} + +GLboolean +_mesa_texstore_etc2_signed_rg11_eac(TEXSTORE_PARAMS) +{ + ASSERT(0); + + return GL_FALSE; +} + +GLboolean +_mesa_texstore_etc2_rgb8_punchthrough_alpha1(TEXSTORE_PARAMS) +{ + ASSERT(0); + + return GL_FALSE; +} + +GLboolean +_mesa_texstore_etc2_srgb8_punchthrough_alpha1(TEXSTORE_PARAMS) +{ + ASSERT(0); + + return GL_FALSE; +} + +void +_mesa_fetch_texel_2d_f_etc2_rgb8(const struct swrast_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel) +{ + struct etc2_block block; + uint8_t dst[3]; + const uint8_t *src; + + src = texImage->Map + + (((texImage->RowStride + 3) / 4) * (j / 4) + (i / 4)) * 8; + + etc2_rgb8_parse_block(&block, src, + false /* punchthrough_alpha */); + etc2_rgb8_fetch_texel(&block, i % 4, j % 4, dst, + false /* punchthrough_alpha */); + + texel[RCOMP] = UBYTE_TO_FLOAT(dst[0]); + texel[GCOMP] = UBYTE_TO_FLOAT(dst[1]); + texel[BCOMP] = UBYTE_TO_FLOAT(dst[2]); + texel[ACOMP] = 1.0f; +} + +void +_mesa_fetch_texel_2d_f_etc2_srgb8(const struct swrast_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel) +{ + struct etc2_block block; + uint8_t dst[3]; + const uint8_t *src; + + src = texImage->Map + + (((texImage->RowStride + 3) / 4) * (j / 4) + (i / 4)) * 8; + + etc2_rgb8_parse_block(&block, src, + false /* punchthrough_alpha */); + etc2_rgb8_fetch_texel(&block, i % 4, j % 4, dst, + false /* punchthrough_alpha */); + + texel[RCOMP] = _mesa_nonlinear_to_linear(dst[0]); + texel[GCOMP] = _mesa_nonlinear_to_linear(dst[1]); + texel[BCOMP] = _mesa_nonlinear_to_linear(dst[2]); + texel[ACOMP] = 1.0f; +} + +void +_mesa_fetch_texel_2d_f_etc2_rgba8_eac(const struct swrast_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel) +{ + struct etc2_block block; + uint8_t dst[4]; + const uint8_t *src; + + src = texImage->Map + + (((texImage->RowStride + 3) / 4) * (j / 4) + (i / 4)) * 16; + + etc2_rgba8_parse_block(&block, src); + etc2_rgba8_fetch_texel(&block, i % 4, j % 4, dst); + + texel[RCOMP] = UBYTE_TO_FLOAT(dst[0]); + texel[GCOMP] = UBYTE_TO_FLOAT(dst[1]); + texel[BCOMP] = UBYTE_TO_FLOAT(dst[2]); + texel[ACOMP] = UBYTE_TO_FLOAT(dst[3]); +} + +void +_mesa_fetch_texel_2d_f_etc2_srgb8_alpha8_eac(const struct + swrast_texture_image *texImage, + GLint i, GLint j, + GLint k, GLfloat *texel) +{ + struct etc2_block block; + uint8_t dst[4]; + const uint8_t *src; + + src = texImage->Map + + (((texImage->RowStride + 3) / 4) * (j / 4) + (i / 4)) * 16; + + etc2_rgba8_parse_block(&block, src); + etc2_rgba8_fetch_texel(&block, i % 4, j % 4, dst); + + texel[RCOMP] = _mesa_nonlinear_to_linear(dst[0]); + texel[GCOMP] = _mesa_nonlinear_to_linear(dst[1]); + texel[BCOMP] = _mesa_nonlinear_to_linear(dst[2]); + texel[ACOMP] = UBYTE_TO_FLOAT(dst[3]); +} + +void +_mesa_fetch_texel_2d_f_etc2_r11_eac(const struct swrast_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel) +{ + struct etc2_block block; + GLushort dst; + const uint8_t *src; + + src = texImage->Map + + (((texImage->RowStride + 3) / 4) * (j / 4) + (i / 4)) * 8; + + etc2_r11_parse_block(&block, src); + etc2_r11_fetch_texel(&block, i % 4, j % 4, (uint8_t *)&dst); + + texel[RCOMP] = USHORT_TO_FLOAT(dst); + texel[GCOMP] = 0.0f; + texel[BCOMP] = 0.0f; + texel[ACOMP] = 1.0f; +} + +void +_mesa_fetch_texel_2d_f_etc2_rg11_eac(const struct + swrast_texture_image *texImage, + GLint i, GLint j, + GLint k, GLfloat *texel) +{ + struct etc2_block block; + GLushort dst[2]; + const uint8_t *src; + + src = texImage->Map + + (((texImage->RowStride + 3) / 4) * (j / 4) + (i / 4)) * 16; + + /* red component */ + etc2_r11_parse_block(&block, src); + etc2_r11_fetch_texel(&block, i % 4, j % 4, (uint8_t *)dst); + + /* green component */ + etc2_r11_parse_block(&block, src + 8); + etc2_r11_fetch_texel(&block, i % 4, j % 4, (uint8_t *)(dst + 1)); + + texel[RCOMP] = USHORT_TO_FLOAT(dst[0]); + texel[GCOMP] = USHORT_TO_FLOAT(dst[1]); + texel[BCOMP] = 0.0f; + texel[ACOMP] = 1.0f; +} + +void +_mesa_fetch_texel_2d_f_etc2_signed_r11_eac(const struct swrast_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel) +{ + struct etc2_block block; + GLushort dst; + const uint8_t *src; + + src = texImage->Map + + (((texImage->RowStride + 3) / 4) * (j / 4) + (i / 4)) * 8; + + etc2_r11_parse_block(&block, src); + etc2_signed_r11_fetch_texel(&block, i % 4, j % 4, (uint8_t *)&dst); + + texel[RCOMP] = SHORT_TO_FLOAT(dst); + texel[GCOMP] = 0.0f; + texel[BCOMP] = 0.0f; + texel[ACOMP] = 1.0f; +} + +void +_mesa_fetch_texel_2d_f_etc2_signed_rg11_eac(const struct swrast_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel) +{ + struct etc2_block block; + GLushort dst[2]; + const uint8_t *src; + + src = texImage->Map + + (((texImage->RowStride + 3) / 4) * (j / 4) + (i / 4)) * 16; + + /* red component */ + etc2_r11_parse_block(&block, src); + etc2_signed_r11_fetch_texel(&block, i % 4, j % 4, (uint8_t *)dst); + + /* green component */ + etc2_r11_parse_block(&block, src + 8); + etc2_signed_r11_fetch_texel(&block, i % 4, j % 4, (uint8_t *)(dst + 1)); + + texel[RCOMP] = SHORT_TO_FLOAT(dst[0]); + texel[GCOMP] = SHORT_TO_FLOAT(dst[1]); + texel[BCOMP] = 0.0f; + texel[ACOMP] = 1.0f; +} + +void +_mesa_fetch_texel_2d_f_etc2_rgb8_punchthrough_alpha1( + const struct swrast_texture_image *texImage, + GLint i, GLint j, + GLint k, GLfloat *texel) +{ + struct etc2_block block; + uint8_t dst[4]; + const uint8_t *src; + + src = texImage->Map + + (((texImage->RowStride + 3) / 4) * (j / 4) + (i / 4)) * 8; + + etc2_rgb8_parse_block(&block, src, + true /* punchthrough alpha */); + etc2_rgb8_fetch_texel(&block, i % 4, j % 4, dst, + true /* punchthrough alpha */); + texel[RCOMP] = UBYTE_TO_FLOAT(dst[0]); + texel[GCOMP] = UBYTE_TO_FLOAT(dst[1]); + texel[BCOMP] = UBYTE_TO_FLOAT(dst[2]); + texel[ACOMP] = UBYTE_TO_FLOAT(dst[3]); +} + +void +_mesa_fetch_texel_2d_f_etc2_srgb8_punchthrough_alpha1( + const struct swrast_texture_image *texImage, + GLint i, GLint j, + GLint k, GLfloat *texel) +{ + struct etc2_block block; + uint8_t dst[4]; + const uint8_t *src; + + src = texImage->Map + + (((texImage->RowStride + 3) / 4) * (j / 4) + (i / 4)) * 8; + + etc2_rgb8_parse_block(&block, src, + true /* punchthrough alpha */); + etc2_rgb8_fetch_texel(&block, i % 4, j % 4, dst, + true /* punchthrough alpha */); + texel[RCOMP] = _mesa_nonlinear_to_linear(dst[0]); + texel[GCOMP] = _mesa_nonlinear_to_linear(dst[1]); + texel[BCOMP] = _mesa_nonlinear_to_linear(dst[2]); + texel[ACOMP] = UBYTE_TO_FLOAT(dst[3]); +} + +/** + * Decode texture data in any one of following formats: + * `MESA_FORMAT_ETC2_RGB8` + * `MESA_FORMAT_ETC2_SRGB8` + * `MESA_FORMAT_ETC2_RGBA8_EAC` + * `MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC` + * `MESA_FORMAT_ETC2_R11_EAC` + * `MESA_FORMAT_ETC2_RG11_EAC` + * `MESA_FORMAT_ETC2_SIGNED_R11_EAC` + * `MESA_FORMAT_ETC2_SIGNED_RG11_EAC` + * `MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1` + * `MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1` + * + * The size of the source data must be a multiple of the ETC2 block size + * even if the texture image's dimensions are not aligned to 4. + * + * \param src_width in pixels + * \param src_height in pixels + * \param dst_stride in bytes + */ + +void +_mesa_unpack_etc2_format(uint8_t *dst_row, + unsigned dst_stride, + const uint8_t *src_row, + unsigned src_stride, + unsigned src_width, + unsigned src_height, + gl_format format) +{ + if (format == MESA_FORMAT_ETC2_RGB8) + etc2_unpack_rgb8(dst_row, dst_stride, + src_row, src_stride, + src_width, src_height); + else if (format == MESA_FORMAT_ETC2_SRGB8) + etc2_unpack_srgb8(dst_row, dst_stride, + src_row, src_stride, + src_width, src_height); + else if (format == MESA_FORMAT_ETC2_RGBA8_EAC) + etc2_unpack_rgba8(dst_row, dst_stride, + src_row, src_stride, + src_width, src_height); + else if (format == MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC) + etc2_unpack_srgb8_alpha8(dst_row, dst_stride, + src_row, src_stride, + src_width, src_height); + else if (format == MESA_FORMAT_ETC2_R11_EAC) + etc2_unpack_r11(dst_row, dst_stride, + src_row, src_stride, + src_width, src_height); + else if (format == MESA_FORMAT_ETC2_RG11_EAC) + etc2_unpack_rg11(dst_row, dst_stride, + src_row, src_stride, + src_width, src_height); + else if (format == MESA_FORMAT_ETC2_SIGNED_R11_EAC) + etc2_unpack_signed_r11(dst_row, dst_stride, + src_row, src_stride, + src_width, src_height); + else if (format == MESA_FORMAT_ETC2_SIGNED_RG11_EAC) + etc2_unpack_signed_rg11(dst_row, dst_stride, + src_row, src_stride, + src_width, src_height); + else if (format == MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1) + etc2_unpack_rgb8_punchthrough_alpha1(dst_row, dst_stride, + src_row, src_stride, + src_width, src_height); + else if (format == MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1) + etc2_unpack_srgb8_punchthrough_alpha1(dst_row, dst_stride, + src_row, src_stride, + src_width, src_height); +} diff --git a/mesalib/src/mesa/main/texcompress_etc.h b/mesalib/src/mesa/main/texcompress_etc.h index 411e1540d..5e086d4e7 100644 --- a/mesalib/src/mesa/main/texcompress_etc.h +++ b/mesalib/src/mesa/main/texcompress_etc.h @@ -34,16 +34,93 @@ struct swrast_texture_image; GLboolean _mesa_texstore_etc1_rgb8(TEXSTORE_PARAMS); +GLboolean +_mesa_texstore_etc2_rgb8(TEXSTORE_PARAMS); + +GLboolean +_mesa_texstore_etc2_srgb8(TEXSTORE_PARAMS); + +GLboolean +_mesa_texstore_etc2_rgba8_eac(TEXSTORE_PARAMS); + +GLboolean +_mesa_texstore_etc2_srgb8_alpha8_eac(TEXSTORE_PARAMS); + +GLboolean +_mesa_texstore_etc2_r11_eac(TEXSTORE_PARAMS); + +GLboolean +_mesa_texstore_etc2_rg11_eac(TEXSTORE_PARAMS); + +GLboolean +_mesa_texstore_etc2_signed_r11_eac(TEXSTORE_PARAMS); + +GLboolean +_mesa_texstore_etc2_signed_rg11_eac(TEXSTORE_PARAMS); + +GLboolean +_mesa_texstore_etc2_rgb8_punchthrough_alpha1(TEXSTORE_PARAMS); + +GLboolean +_mesa_texstore_etc2_srgb8_punchthrough_alpha1(TEXSTORE_PARAMS); + void _mesa_fetch_texel_2d_f_etc1_rgb8(const struct swrast_texture_image *texImage, GLint i, GLint j, GLint k, GLfloat *texel); +void +_mesa_fetch_texel_2d_f_etc2_rgb8(const struct swrast_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel); +void +_mesa_fetch_texel_2d_f_etc2_srgb8(const struct swrast_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel); void +_mesa_fetch_texel_2d_f_etc2_rgba8_eac(const struct swrast_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel); +void +_mesa_fetch_texel_2d_f_etc2_srgb8_alpha8_eac(const struct + swrast_texture_image *texImage, + GLint i, GLint j, + GLint k, GLfloat *texel); +void +_mesa_fetch_texel_2d_f_etc2_r11_eac(const struct swrast_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel); +void +_mesa_fetch_texel_2d_f_etc2_rg11_eac(const struct swrast_texture_image *texImage, + GLint i, GLint j, GLint k, GLfloat *texel); +void +_mesa_fetch_texel_2d_f_etc2_signed_r11_eac(const struct + swrast_texture_image *texImage, + GLint i, GLint j, + GLint k, GLfloat *texel); +void +_mesa_fetch_texel_2d_f_etc2_signed_rg11_eac(const struct + swrast_texture_image *texImage, + GLint i, GLint j, + GLint k, GLfloat *texel); +void +_mesa_fetch_texel_2d_f_etc2_rgb8_punchthrough_alpha1( + const struct swrast_texture_image *texImage, + GLint i, GLint j, + GLint k, GLfloat *texel); +void +_mesa_fetch_texel_2d_f_etc2_srgb8_punchthrough_alpha1( + const struct swrast_texture_image *texImage, + GLint i, GLint j, + GLint k, GLfloat *texel); +void _mesa_etc1_unpack_rgba8888(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned src_width, unsigned src_height); - +void +_mesa_unpack_etc2_format(uint8_t *dst_row, + unsigned dst_stride, + const uint8_t *src_row, + unsigned src_stride, + unsigned src_width, + unsigned src_height, + gl_format format); #endif diff --git a/mesalib/src/mesa/main/texcompress_s3tc.c b/mesalib/src/mesa/main/texcompress_s3tc.c index da7725964..476b998e0 100644 --- a/mesalib/src/mesa/main/texcompress_s3tc.c +++ b/mesalib/src/mesa/main/texcompress_s3tc.c @@ -45,6 +45,7 @@ #include "texcompress_s3tc.h" #include "texstore.h" #include "swrast/s_context.h" +#include "format_unpack.h" #if defined(_WIN32) || defined(WIN32) @@ -57,33 +58,6 @@ #define DXTN_LIBNAME "libtxc_dxtn.so" #endif -/** - * Convert an 8-bit sRGB value from non-linear space to a - * linear RGB value in [0, 1]. - * Implemented with a 256-entry lookup table. - */ -static inline GLfloat -nonlinear_to_linear(GLubyte cs8) -{ - static GLfloat table[256]; - static GLboolean tableReady = GL_FALSE; - if (!tableReady) { - /* compute lookup table now */ - GLuint i; - for (i = 0; i < 256; i++) { - const GLfloat cs = UBYTE_TO_FLOAT(i); - if (cs <= 0.04045) { - table[i] = cs / 12.92f; - } - else { - table[i] = (GLfloat) pow((cs + 0.055) / 1.055, 2.4); - } - } - tableReady = GL_TRUE; - } - return table[cs8]; -} - typedef void (*dxtFetchTexelFuncExt)( GLint srcRowstride, GLubyte *pixdata, GLint col, GLint row, GLvoid *texelOut ); static dxtFetchTexelFuncExt fetch_ext_rgb_dxt1 = NULL; @@ -476,9 +450,9 @@ _mesa_fetch_texel_srgb_dxt1(const struct swrast_texture_image *texImage, /* just sample as GLubyte and convert to float here */ GLubyte rgba[4]; fetch_texel_2d_rgb_dxt1(texImage, i, j, k, rgba); - texel[RCOMP] = nonlinear_to_linear(rgba[RCOMP]); - texel[GCOMP] = nonlinear_to_linear(rgba[GCOMP]); - texel[BCOMP] = nonlinear_to_linear(rgba[BCOMP]); + texel[RCOMP] = _mesa_nonlinear_to_linear(rgba[RCOMP]); + texel[GCOMP] = _mesa_nonlinear_to_linear(rgba[GCOMP]); + texel[BCOMP] = _mesa_nonlinear_to_linear(rgba[BCOMP]); texel[ACOMP] = UBYTE_TO_FLOAT(rgba[ACOMP]); } @@ -489,9 +463,9 @@ _mesa_fetch_texel_srgba_dxt1(const struct swrast_texture_image *texImage, /* just sample as GLubyte and convert to float here */ GLubyte rgba[4]; fetch_texel_2d_rgba_dxt1(texImage, i, j, k, rgba); - texel[RCOMP] = nonlinear_to_linear(rgba[RCOMP]); - texel[GCOMP] = nonlinear_to_linear(rgba[GCOMP]); - texel[BCOMP] = nonlinear_to_linear(rgba[BCOMP]); + texel[RCOMP] = _mesa_nonlinear_to_linear(rgba[RCOMP]); + texel[GCOMP] = _mesa_nonlinear_to_linear(rgba[GCOMP]); + texel[BCOMP] = _mesa_nonlinear_to_linear(rgba[BCOMP]); texel[ACOMP] = UBYTE_TO_FLOAT(rgba[ACOMP]); } @@ -502,9 +476,9 @@ _mesa_fetch_texel_srgba_dxt3(const struct swrast_texture_image *texImage, /* just sample as GLubyte and convert to float here */ GLubyte rgba[4]; fetch_texel_2d_rgba_dxt3(texImage, i, j, k, rgba); - texel[RCOMP] = nonlinear_to_linear(rgba[RCOMP]); - texel[GCOMP] = nonlinear_to_linear(rgba[GCOMP]); - texel[BCOMP] = nonlinear_to_linear(rgba[BCOMP]); + texel[RCOMP] = _mesa_nonlinear_to_linear(rgba[RCOMP]); + texel[GCOMP] = _mesa_nonlinear_to_linear(rgba[GCOMP]); + texel[BCOMP] = _mesa_nonlinear_to_linear(rgba[BCOMP]); texel[ACOMP] = UBYTE_TO_FLOAT(rgba[ACOMP]); } @@ -515,8 +489,8 @@ _mesa_fetch_texel_srgba_dxt5(const struct swrast_texture_image *texImage, /* just sample as GLubyte and convert to float here */ GLubyte rgba[4]; fetch_texel_2d_rgba_dxt5(texImage, i, j, k, rgba); - texel[RCOMP] = nonlinear_to_linear(rgba[RCOMP]); - texel[GCOMP] = nonlinear_to_linear(rgba[GCOMP]); - texel[BCOMP] = nonlinear_to_linear(rgba[BCOMP]); + texel[RCOMP] = _mesa_nonlinear_to_linear(rgba[RCOMP]); + texel[GCOMP] = _mesa_nonlinear_to_linear(rgba[GCOMP]); + texel[BCOMP] = _mesa_nonlinear_to_linear(rgba[BCOMP]); texel[ACOMP] = UBYTE_TO_FLOAT(rgba[ACOMP]); } diff --git a/mesalib/src/mesa/main/texformat.c b/mesalib/src/mesa/main/texformat.c index f0bc7fdb9..b3ffc6c51 100644 --- a/mesalib/src/mesa/main/texformat.c +++ b/mesalib/src/mesa/main/texformat.c @@ -972,6 +972,43 @@ _mesa_choose_tex_format(struct gl_context *ctx, GLenum target, } } + if (_mesa_is_gles3(ctx)) { + switch (internalFormat) { + case GL_COMPRESSED_RGB8_ETC2: + RETURN_IF_SUPPORTED(MESA_FORMAT_ETC2_RGB8); + break; + case GL_COMPRESSED_SRGB8_ETC2: + RETURN_IF_SUPPORTED(MESA_FORMAT_ETC2_SRGB8); + break; + case GL_COMPRESSED_RGBA8_ETC2_EAC: + RETURN_IF_SUPPORTED(MESA_FORMAT_ETC2_RGBA8_EAC); + break; + case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC: + RETURN_IF_SUPPORTED(MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC); + break; + case GL_COMPRESSED_R11_EAC: + RETURN_IF_SUPPORTED(MESA_FORMAT_ETC2_R11_EAC); + break; + case GL_COMPRESSED_RG11_EAC: + RETURN_IF_SUPPORTED(MESA_FORMAT_ETC2_RG11_EAC); + break; + case GL_COMPRESSED_SIGNED_R11_EAC: + RETURN_IF_SUPPORTED(MESA_FORMAT_ETC2_SIGNED_R11_EAC); + break; + case GL_COMPRESSED_SIGNED_RG11_EAC: + RETURN_IF_SUPPORTED(MESA_FORMAT_ETC2_SIGNED_RG11_EAC); + break; + case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: + RETURN_IF_SUPPORTED(MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1); + break; + case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: + RETURN_IF_SUPPORTED(MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1); + break; + default: + ; /* fallthrough */ + } + } + _mesa_problem(ctx, "unexpected format %s in _mesa_choose_tex_format()", _mesa_lookup_enum_by_nr(internalFormat)); return MESA_FORMAT_NONE; diff --git a/mesalib/src/mesa/main/teximage.c b/mesalib/src/mesa/main/teximage.c index a720c38b8..83b7e1488 100644 --- a/mesalib/src/mesa/main/teximage.c +++ b/mesalib/src/mesa/main/teximage.c @@ -529,6 +529,27 @@ _mesa_base_tex_format( struct gl_context *ctx, GLint internalFormat ) } } + if (_mesa_is_gles3(ctx)) { + switch (internalFormat) { + case GL_COMPRESSED_RGB8_ETC2: + case GL_COMPRESSED_SRGB8_ETC2: + return GL_RGB; + case GL_COMPRESSED_RGBA8_ETC2_EAC: + case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC: + case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: + case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: + return GL_RGBA; + case GL_COMPRESSED_R11_EAC: + case GL_COMPRESSED_SIGNED_R11_EAC: + return GL_RED; + case GL_COMPRESSED_RG11_EAC: + case GL_COMPRESSED_SIGNED_RG11_EAC: + return GL_RG; + default: + ; /* fallthrough */ + } + } + if (ctx->API == API_OPENGLES) { switch (internalFormat) { case GL_PALETTE4_RGB8_OES: diff --git a/mesalib/src/mesa/main/texstore.c b/mesalib/src/mesa/main/texstore.c index 1c088106f..26c5b6703 100644 --- a/mesalib/src/mesa/main/texstore.c +++ b/mesalib/src/mesa/main/texstore.c @@ -4124,6 +4124,18 @@ _mesa_get_texstore_func(gl_format format) table[MESA_FORMAT_LA_LATC2] = _mesa_texstore_rg_rgtc2; table[MESA_FORMAT_SIGNED_LA_LATC2] = _mesa_texstore_signed_rg_rgtc2; table[MESA_FORMAT_ETC1_RGB8] = _mesa_texstore_etc1_rgb8; + table[MESA_FORMAT_ETC2_RGB8] = _mesa_texstore_etc2_rgb8; + table[MESA_FORMAT_ETC2_SRGB8] = _mesa_texstore_etc2_srgb8; + table[MESA_FORMAT_ETC2_RGBA8_EAC] = _mesa_texstore_etc2_rgba8_eac; + table[MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC] = _mesa_texstore_etc2_srgb8_alpha8_eac; + table[MESA_FORMAT_ETC2_R11_EAC] = _mesa_texstore_etc2_r11_eac; + table[MESA_FORMAT_ETC2_RG11_EAC] = _mesa_texstore_etc2_rg11_eac; + table[MESA_FORMAT_ETC2_SIGNED_R11_EAC] = _mesa_texstore_etc2_signed_r11_eac; + table[MESA_FORMAT_ETC2_SIGNED_RG11_EAC] = _mesa_texstore_etc2_signed_rg11_eac; + table[MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1] = + _mesa_texstore_etc2_rgb8_punchthrough_alpha1; + table[MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1] = + _mesa_texstore_etc2_srgb8_punchthrough_alpha1; table[MESA_FORMAT_SIGNED_A8] = _mesa_texstore_snorm8; table[MESA_FORMAT_SIGNED_L8] = _mesa_texstore_snorm8; table[MESA_FORMAT_SIGNED_AL88] = _mesa_texstore_snorm88; diff --git a/mesalib/src/mesa/program/Android.mk b/mesalib/src/mesa/program/Android.mk index 712506129..51362e0eb 100644 --- a/mesalib/src/mesa/program/Android.mk +++ b/mesalib/src/mesa/program/Android.mk @@ -65,6 +65,9 @@ LOCAL_GENERATED_SOURCES := \ $(intermediates)/program/program_parse.tab.c: $(LOCAL_PATH)/program_parse.y $(mesa_local-y-to-c-and-h) +$(intermediates)/program/program_parse.tab.h: $(intermediates)/program/program_parse.tab.c + @ + $(intermediates)/program/lex.yy.c: $(LOCAL_PATH)/program_lexer.l $(local-l-to-c) diff --git a/mesalib/src/mesa/program/hash_table.c b/mesalib/src/mesa/program/prog_hash_table.c index f45ed46af..f45ed46af 100644 --- a/mesalib/src/mesa/program/hash_table.c +++ b/mesalib/src/mesa/program/prog_hash_table.c diff --git a/mesalib/src/mesa/sources.mak b/mesalib/src/mesa/sources.mak index 54e58c21b..8cde2c4cf 100644 --- a/mesalib/src/mesa/sources.mak +++ b/mesalib/src/mesa/sources.mak @@ -76,6 +76,7 @@ MAIN_FILES = \ $(SRCDIR)main/renderbuffer.c \ $(SRCDIR)main/samplerobj.c \ $(SRCDIR)main/scissor.c \ + $(SRCDIR)main/set.c \ $(SRCDIR)main/shaderapi.c \ $(SRCDIR)main/shaderobj.c \ $(SRCDIR)main/shader_query.cpp \ @@ -247,7 +248,7 @@ STATETRACKER_FILES = \ PROGRAM_FILES = \ $(SRCDIR)program/arbprogparse.c \ - $(SRCDIR)program/hash_table.c \ + $(SRCDIR)program/prog_hash_table.c \ $(SRCDIR)program/ir_to_mesa.cpp \ $(SRCDIR)program/program.c \ $(SRCDIR)program/program_parse_extra.c \ diff --git a/mesalib/src/mesa/state_tracker/st_atom.c b/mesalib/src/mesa/state_tracker/st_atom.c index 102fee93b..32bcc266a 100644 --- a/mesalib/src/mesa/state_tracker/st_atom.c +++ b/mesalib/src/mesa/state_tracker/st_atom.c @@ -64,6 +64,8 @@ static const struct st_tracked_state *atoms[] = &st_update_vs_constants, &st_update_gs_constants, &st_update_fs_constants, + &st_bind_vs_ubos, + &st_bind_fs_ubos, &st_update_pixel_transfer, /* this must be done after the vertex program update */ diff --git a/mesalib/src/mesa/state_tracker/st_atom.h b/mesalib/src/mesa/state_tracker/st_atom.h index 6c7d09fba..101a3a6bd 100644 --- a/mesalib/src/mesa/state_tracker/st_atom.h +++ b/mesalib/src/mesa/state_tracker/st_atom.h @@ -67,6 +67,8 @@ extern const struct st_tracked_state st_finalize_textures; extern const struct st_tracked_state st_update_fs_constants; extern const struct st_tracked_state st_update_gs_constants; extern const struct st_tracked_state st_update_vs_constants; +extern const struct st_tracked_state st_bind_fs_ubos; +extern const struct st_tracked_state st_bind_vs_ubos; extern const struct st_tracked_state st_update_pixel_transfer; diff --git a/mesalib/src/mesa/state_tracker/st_atom_constbuf.c b/mesalib/src/mesa/state_tracker/st_atom_constbuf.c index 580393e60..961fb28a9 100644 --- a/mesalib/src/mesa/state_tracker/st_atom_constbuf.c +++ b/mesalib/src/mesa/state_tracker/st_atom_constbuf.c @@ -45,7 +45,7 @@ #include "st_atom.h" #include "st_atom_constbuf.h" #include "st_program.h" - +#include "st_cb_bufferobjects.h" /** * Pass the given program parameters to the graphics pipe as a @@ -175,3 +175,69 @@ const struct st_tracked_state st_update_gs_constants = { }, update_gs_constants /* update */ }; + +static void st_bind_ubos(struct st_context *st, + struct gl_shader *shader, + unsigned shader_type) +{ + unsigned i; + struct pipe_constant_buffer cb = { 0 }; + + if (!shader) + return; + + for (i = 0; i < shader->NumUniformBlocks; i++) { + struct gl_uniform_buffer_binding *binding; + struct st_buffer_object *st_obj; + + binding = &st->ctx->UniformBufferBindings[shader->UniformBlocks[i].Binding]; + st_obj = st_buffer_object(binding->BufferObject); + pipe_resource_reference(&cb.buffer, st_obj->buffer); + + cb.buffer_size = st_obj->buffer->width0 - binding->Offset; + + st->pipe->set_constant_buffer(st->pipe, shader_type, 1 + i, &cb); + pipe_resource_reference(&cb.buffer, NULL); + } +} + +static void bind_vs_ubos(struct st_context *st) +{ + struct gl_shader_program *prog = st->ctx->Shader.CurrentVertexProgram; + + if (!prog) + return; + + st_bind_ubos(st, prog->_LinkedShaders[MESA_SHADER_VERTEX], PIPE_SHADER_VERTEX); +} + +const struct st_tracked_state st_bind_vs_ubos = { + "st_bind_vs_ubos", + { + (_NEW_PROGRAM | _NEW_BUFFER_OBJECT), + ST_NEW_VERTEX_PROGRAM, + }, + bind_vs_ubos +}; + +static void bind_fs_ubos(struct st_context *st) +{ + struct gl_shader_program *prog = st->ctx->Shader.CurrentFragmentProgram; + + if (!prog) + return; + + st_bind_ubos(st, prog->_LinkedShaders[MESA_SHADER_FRAGMENT], PIPE_SHADER_FRAGMENT); + +} + +const struct st_tracked_state st_bind_fs_ubos = { + "st_bind_fs_ubos", + { + (_NEW_PROGRAM | _NEW_BUFFER_OBJECT), + ST_NEW_FRAGMENT_PROGRAM, + }, + bind_fs_ubos +}; + + diff --git a/mesalib/src/mesa/state_tracker/st_atom_texture.c b/mesalib/src/mesa/state_tracker/st_atom_texture.c index df05e83c2..dba1d829c 100644 --- a/mesalib/src/mesa/state_tracker/st_atom_texture.c +++ b/mesalib/src/mesa/state_tracker/st_atom_texture.c @@ -215,13 +215,19 @@ update_single_texture(struct st_context *st, /* Determine the format of the texture sampler view */ st_view_format = stObj->pt->format; - { - const struct st_texture_image *firstImage = - st_texture_image(stObj->base.Image[0][stObj->base.BaseLevel]); - const gl_format texFormat = firstImage->base.TexFormat; - enum pipe_format firstImageFormat = - st_mesa_format_to_pipe_format(texFormat); + { + gl_format texFormat; + enum pipe_format firstImageFormat; + + if (texObj->Target == GL_TEXTURE_BUFFER) { + texFormat = stObj->base._BufferObjectFormat; + } else { + const struct st_texture_image *firstImage = + st_texture_image(stObj->base.Image[0][stObj->base.BaseLevel]); + texFormat = firstImage->base.TexFormat; + } + firstImageFormat = st_mesa_format_to_pipe_format(texFormat); if ((samp->sRGBDecode == GL_SKIP_DECODE_EXT) && (_mesa_get_format_color_encoding(texFormat) == GL_SRGB)) { /* Don't do sRGB->RGB conversion. Interpret the texture data as diff --git a/mesalib/src/mesa/state_tracker/st_cb_bufferobjects.c b/mesalib/src/mesa/state_tracker/st_cb_bufferobjects.c index ac38128df..cf291c1c1 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_bufferobjects.c +++ b/mesalib/src/mesa/state_tracker/st_cb_bufferobjects.c @@ -195,9 +195,15 @@ st_bufferobj_data(struct gl_context *ctx, case GL_ELEMENT_ARRAY_BUFFER_ARB: bind = PIPE_BIND_INDEX_BUFFER; break; + case GL_TEXTURE_BUFFER: + bind = PIPE_BIND_SAMPLER_VIEW; + break; case GL_TRANSFORM_FEEDBACK_BUFFER: bind = PIPE_BIND_STREAM_OUTPUT; break; + case GL_UNIFORM_BUFFER: + bind = PIPE_BIND_CONSTANT_BUFFER; + break; default: bind = 0; } diff --git a/mesalib/src/mesa/state_tracker/st_cb_texture.c b/mesalib/src/mesa/state_tracker/st_cb_texture.c index f06814f9c..ae069eb2c 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_texture.c +++ b/mesalib/src/mesa/state_tracker/st_cb_texture.c @@ -48,6 +48,7 @@ #include "state_tracker/st_cb_fbo.h" #include "state_tracker/st_cb_flush.h" #include "state_tracker/st_cb_texture.h" +#include "state_tracker/st_cb_bufferobjects.h" #include "state_tracker/st_format.h" #include "state_tracker/st_texture.h" #include "state_tracker/st_gen_mipmap.h" @@ -59,6 +60,7 @@ #include "pipe/p_shader_tokens.h" #include "util/u_tile.h" #include "util/u_blit.h" +#include "util/u_blitter.h" #include "util/u_format.h" #include "util/u_surface.h" #include "util/u_sampler.h" @@ -922,12 +924,12 @@ st_CopyTexSubImage(struct gl_context *ctx, GLuint dims, struct pipe_context *pipe = st->pipe; struct pipe_screen *screen = pipe->screen; enum pipe_format dest_format, src_format; - GLboolean matching_base_formats; - GLuint color_writemask, zs_writemask, sample_count; + GLuint color_writemask; struct pipe_surface *dest_surface = NULL; GLboolean do_flip = (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP); struct pipe_surface surf_tmpl; - unsigned int dst_usage; + unsigned dst_usage; + unsigned blit_mask; GLint srcY0, srcY1; /* make sure finalize_textures has been called? @@ -939,12 +941,6 @@ st_CopyTexSubImage(struct gl_context *ctx, GLuint dims, return; } - sample_count = strb->surface->texture->nr_samples; - /* I believe this would be legal, presumably would need to do a resolve - for color, and for depth/stencil spec says to just use one of the - depth/stencil samples per pixel? Need some transfer clarifications. */ - assert(sample_count < 2); - assert(strb); assert(strb->surface); assert(stImage->pt); @@ -952,22 +948,24 @@ st_CopyTexSubImage(struct gl_context *ctx, GLuint dims, src_format = strb->surface->format; dest_format = stImage->pt->format; - /* - * Determine if the src framebuffer and dest texture have the same - * base format. We need this to detect a case such as the framebuffer - * being GL_RGBA but the texture being GL_RGB. If the actual hardware - * texture format stores RGBA we need to set A=1 (overriding the - * framebuffer's alpha values). We can't do that with the blit or - * textured-quad paths. - */ - matching_base_formats = - (_mesa_get_format_base_format(strb->Base.Format) == - _mesa_get_format_base_format(texImage->TexFormat)); + if (do_flip) { + srcY1 = strb->Base.Height - srcY - height; + srcY0 = srcY1 + height; + } + else { + srcY0 = srcY; + srcY1 = srcY0 + height; + } if (ctx->_ImageTransferState) { goto fallback; } + /* Compressed and subsampled textures aren't supported for blitting. */ + if (!util_format_is_plain(dest_format)) { + goto fallback; + } + if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY) { /* 1D arrays might be thought of as 2D images but the actual layout * might not be that way. At some points, we convert OpenGL's 1D @@ -978,53 +976,112 @@ st_CopyTexSubImage(struct gl_context *ctx, GLuint dims, goto fallback; } - if (matching_base_formats && - src_format == dest_format && - !do_flip) { - /* use surface_copy() / blit */ - struct pipe_box src_box; - unsigned dstLevel; + /* Set the blit writemask. */ + switch (texBaseFormat) { + case GL_DEPTH_STENCIL: + switch (strb->Base._BaseFormat) { + case GL_DEPTH_STENCIL: + blit_mask = PIPE_MASK_ZS; + break; + case GL_DEPTH_COMPONENT: + blit_mask = PIPE_MASK_Z; + break; + case GL_STENCIL_INDEX: + blit_mask = PIPE_MASK_S; + break; + default: + assert(0); + return; + } + dst_usage = PIPE_BIND_DEPTH_STENCIL; + break; + + case GL_DEPTH_COMPONENT: + blit_mask = PIPE_MASK_Z; + dst_usage = PIPE_BIND_DEPTH_STENCIL; + break; - u_box_2d_zslice(srcX, srcY, strb->surface->u.tex.first_layer, - width, height, &src_box); + default: + /* Colorbuffers. + * + * Determine if the src framebuffer and dest texture have the same + * base format. We need this to detect a case such as the framebuffer + * being GL_RGBA but the texture being GL_RGB. If the actual hardware + * texture format stores RGBA we need to set A=1 (overriding the + * framebuffer's alpha values). + * + * XXX util_blit_pixels doesn't support MSAA resolve, so always use + * pipe->blit + */ + if (texBaseFormat == strb->Base._BaseFormat || + strb->texture->nr_samples > 1) { + blit_mask = PIPE_MASK_RGBA; + } + else { + blit_mask = 0; + } + dst_usage = PIPE_BIND_RENDER_TARGET; + } + /* Blit the texture. + * This supports flipping, format conversions, and downsampling. + */ + if (blit_mask) { /* If stImage->pt is an independent image (not a pointer into a full * mipmap) stImage->pt.last_level will be zero and we need to use that * as the dest level. */ - dstLevel = MIN2(stImage->base.Level, stImage->pt->last_level); - - /* for resource_copy_region(), y=0=top, always */ - pipe->resource_copy_region(pipe, - /* dest */ - stImage->pt, - dstLevel, - destX, destY, destZ + stImage->base.Face, - /* src */ - strb->texture, - strb->surface->u.tex.level, - &src_box); - return; - } + unsigned dstLevel = MIN2(stImage->base.Level, stImage->pt->last_level); + struct pipe_blit_info blit; + + memset(&blit, 0, sizeof(blit)); + blit.src.resource = strb->texture; + blit.src.format = src_format; + blit.src.level = strb->surface->u.tex.level; + blit.src.box.x = srcX; + blit.src.box.y = srcY0; + blit.src.box.z = strb->surface->u.tex.first_layer; + blit.src.box.width = width; + blit.src.box.height = srcY1 - srcY0; + blit.src.box.depth = 1; + blit.dst.resource = stImage->pt; + blit.dst.format = dest_format; + blit.dst.level = dstLevel; + blit.dst.box.x = destX; + blit.dst.box.y = destY; + blit.dst.box.z = stImage->base.Face + destZ; + blit.dst.box.width = width; + blit.dst.box.height = height; + blit.dst.box.depth = 1; + blit.mask = blit_mask; + blit.filter = PIPE_TEX_FILTER_NEAREST; + + /* try resource_copy_region in case the format is not supported + * for rendering */ + if (util_try_blit_via_copy_region(pipe, &blit)) { + return; /* done */ + } - if (texBaseFormat == GL_DEPTH_STENCIL) { - goto fallback; - } + /* check the format support */ + if (!screen->is_format_supported(screen, src_format, + PIPE_TEXTURE_2D, 0, + PIPE_BIND_SAMPLER_VIEW) || + !screen->is_format_supported(screen, dest_format, + PIPE_TEXTURE_2D, 0, + dst_usage)) { + goto fallback; + } - if (texBaseFormat == GL_DEPTH_COMPONENT) { - color_writemask = 0; - zs_writemask = BLIT_WRITEMASK_Z; - dst_usage = PIPE_BIND_DEPTH_STENCIL; - } - else { - color_writemask = compatible_src_dst_formats(ctx, &strb->Base, texImage); - zs_writemask = 0; - dst_usage = PIPE_BIND_RENDER_TARGET; + pipe->blit(pipe, &blit); + return; } - if ((!color_writemask && !zs_writemask) || + /* try u_blit */ + color_writemask = compatible_src_dst_formats(ctx, &strb->Base, texImage); + + if (!color_writemask || !screen->is_format_supported(screen, src_format, - PIPE_TEXTURE_2D, sample_count, + PIPE_TEXTURE_2D, 0, PIPE_BIND_SAMPLER_VIEW) || !screen->is_format_supported(screen, dest_format, PIPE_TEXTURE_2D, 0, @@ -1032,15 +1089,6 @@ st_CopyTexSubImage(struct gl_context *ctx, GLuint dims, goto fallback; } - if (do_flip) { - srcY1 = strb->Base.Height - srcY - height; - srcY0 = srcY1 + height; - } - else { - srcY0 = srcY; - srcY1 = srcY0 + height; - } - /* Disable conditional rendering. */ if (st->render_condition) { pipe->render_condition(pipe, NULL, 0); @@ -1065,7 +1113,7 @@ st_CopyTexSubImage(struct gl_context *ctx, GLuint dims, destX, destY, destX + width, destY + height, 0.0, PIPE_TEX_MIPFILTER_NEAREST, - color_writemask, zs_writemask); + color_writemask, 0); pipe_surface_reference(&dest_surface, NULL); /* Restore conditional rendering state. */ @@ -1182,6 +1230,20 @@ st_finalize_texture(struct gl_context *ctx, stObj->lastLevel = stObj->base._MaxLevel; } + if (tObj->Target == GL_TEXTURE_BUFFER) { + struct st_buffer_object *st_obj = st_buffer_object(tObj->BufferObject); + + if (st_obj->buffer != stObj->pt) { + pipe_resource_reference(&stObj->pt, st_obj->buffer); + pipe_sampler_view_release(st->pipe, &stObj->sampler_view); + stObj->width0 = stObj->pt->width0 / _mesa_get_format_bytes(tObj->_BufferObjectFormat); + stObj->height0 = 1; + stObj->depth0 = 1; + } + return GL_TRUE; + + } + firstImage = st_texture_image(stObj->base.Image[0][stObj->base.BaseLevel]); assert(firstImage); diff --git a/mesalib/src/mesa/state_tracker/st_extensions.c b/mesalib/src/mesa/state_tracker/st_extensions.c index 62a736bb6..93ef7a91c 100644 --- a/mesalib/src/mesa/state_tracker/st_extensions.c +++ b/mesalib/src/mesa/state_tracker/st_extensions.c @@ -70,6 +70,8 @@ void st_init_limits(struct st_context *st) struct pipe_screen *screen = st->pipe->screen; struct gl_constants *c = &st->ctx->Const; gl_shader_type sh; + boolean can_ubo = TRUE; + int max_const_buffers; c->MaxTextureLevels = _min(screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS), @@ -218,6 +220,17 @@ void st_init_limits(struct st_context *st) options->EmitNoIndirectUniform = !screen->get_shader_param(screen, sh, PIPE_SHADER_CAP_INDIRECT_CONST_ADDR); + if (pc->MaxNativeInstructions) { + if (options->EmitNoIndirectUniform) + can_ubo = FALSE; + + max_const_buffers = screen->get_shader_param(screen, sh, + PIPE_SHADER_CAP_MAX_CONST_BUFFERS); + /* we need 13 buffers - 1 constant, 12 UBO */ + if (max_const_buffers < 13) + can_ubo = FALSE; + } + if (options->EmitNoLoops) options->MaxUnrollIterations = MIN2(screen->get_shader_param(screen, sh, PIPE_SHADER_CAP_MAX_INSTRUCTIONS), 65536); else @@ -251,6 +264,9 @@ void st_init_limits(struct st_context *st) c->GLSLSkipStrictMaxVaryingLimitCheck = screen->get_param(screen, PIPE_CAP_TGSI_CAN_COMPACT_VARYINGS); + + if (can_ubo) + st->ctx->Extensions.ARB_uniform_buffer_object = GL_TRUE; } @@ -553,7 +569,12 @@ void st_init_extensions(struct st_context *st) /* Figure out GLSL support. */ glsl_feature_level = screen->get_param(screen, PIPE_CAP_GLSL_FEATURE_LEVEL); - if (glsl_feature_level >= 130) { + if (glsl_feature_level >= 140) { + if (ctx->API == API_OPENGL_CORE) + ctx->Const.GLSLVersion = 140; + else + ctx->Const.GLSLVersion = 130; + } else if (glsl_feature_level >= 130) { ctx->Const.GLSLVersion = 130; } else { ctx->Const.GLSLVersion = 120; @@ -643,4 +664,6 @@ void st_init_extensions(struct st_context *st) if (ctx->Const.MinMapBufferAlignment >= 64) { ctx->Extensions.ARB_map_buffer_alignment = GL_TRUE; } + if (screen->get_param(screen, PIPE_CAP_TEXTURE_BUFFER_OBJECTS)) + ctx->Extensions.ARB_texture_buffer_object = GL_TRUE; } diff --git a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp index c030a6b37..a4df4e5fa 100644 --- a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp +++ b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp @@ -107,6 +107,7 @@ public: else this->swizzle = SWIZZLE_XYZW; this->negate = 0; + this->index2D = 0; this->type = type ? type->base_type : GLSL_TYPE_ERROR; this->reladdr = NULL; } @@ -116,6 +117,18 @@ public: this->type = type; this->file = file; this->index = index; + this->index2D = 0; + this->swizzle = SWIZZLE_XYZW; + this->negate = 0; + this->reladdr = NULL; + } + + st_src_reg(gl_register_file file, int index, int type, int index2D) + { + this->type = type; + this->file = file; + this->index = index; + this->index2D = index2D; this->swizzle = SWIZZLE_XYZW; this->negate = 0; this->reladdr = NULL; @@ -126,6 +139,7 @@ public: this->type = GLSL_TYPE_ERROR; this->file = PROGRAM_UNDEFINED; this->index = 0; + this->index2D = 0; this->swizzle = 0; this->negate = 0; this->reladdr = NULL; @@ -135,6 +149,7 @@ public: gl_register_file file; /**< PROGRAM_* from Mesa */ int index; /**< temporary index, VERT_ATTRIB_*, FRAG_ATTRIB_*, etc. */ + int index2D; GLuint swizzle; /**< SWIZZLE_XYZWONEZERO swizzles from Mesa. */ int negate; /**< NEGATE_XYZW mask from mesa */ int type; /** GLSL_TYPE_* from GLSL IR (enum glsl_base_type) */ @@ -183,6 +198,7 @@ st_src_reg::st_src_reg(st_dst_reg reg) this->swizzle = SWIZZLE_XYZW; this->negate = 0; this->reladdr = reg.reladdr; + this->index2D = 0; } st_dst_reg::st_dst_reg(st_src_reg reg) @@ -1873,10 +1889,46 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir) assert(!"GLSL 1.30 features unsupported"); break; - case ir_binop_ubo_load: - assert(!"not yet supported"); - break; + case ir_binop_ubo_load: { + ir_constant *uniform_block = ir->operands[0]->as_constant(); + ir_constant *const_offset_ir = ir->operands[1]->as_constant(); + unsigned const_offset = const_offset_ir ? const_offset_ir->value.u[0] : 0; + st_src_reg index_reg = get_temp(glsl_type::uint_type); + st_src_reg cbuf; + + cbuf.type = glsl_type::vec4_type->base_type; + cbuf.file = PROGRAM_CONSTANT; + cbuf.index = 0; + cbuf.index2D = uniform_block->value.u[0] + 1; + cbuf.reladdr = NULL; + cbuf.negate = 0; + + assert(ir->type->is_vector() || ir->type->is_scalar()); + + if (const_offset_ir) { + index_reg = st_src_reg_for_int(const_offset / 16); + } else { + emit(ir, TGSI_OPCODE_USHR, st_dst_reg(index_reg), op[1], st_src_reg_for_int(4)); + } + cbuf.swizzle = swizzle_for_size(ir->type->vector_elements); + cbuf.swizzle += MAKE_SWIZZLE4(const_offset % 16 / 4, + const_offset % 16 / 4, + const_offset % 16 / 4, + const_offset % 16 / 4); + + cbuf.reladdr = ralloc(mem_ctx, st_src_reg); + memcpy(cbuf.reladdr, &index_reg, sizeof(index_reg)); + + if (ir->type->base_type == GLSL_TYPE_BOOL) { + emit(ir, TGSI_OPCODE_USNE, result_dst, cbuf, st_src_reg_for_int(0)); + result_src.negate = 1; + emit(ir, TGSI_OPCODE_UCMP, result_dst, result_src, st_src_reg_for_int(~0), st_src_reg_for_int(0)); + } else { + emit(ir, TGSI_OPCODE_MOV, result_dst, cbuf); + } + break; + } case ir_quadop_vector: /* This operation should have already been handled. */ @@ -2776,7 +2828,7 @@ glsl_to_tgsi_visitor::visit(ir_texture *ir) inst->tex_target = TEXTURE_RECT_INDEX; break; case GLSL_SAMPLER_DIM_BUF: - assert(!"FINISHME: Implement ARB_texture_buffer_object"); + inst->tex_target = TEXTURE_BUFFER_INDEX; break; case GLSL_SAMPLER_DIM_EXTERNAL: inst->tex_target = TEXTURE_EXTERNAL_INDEX; @@ -4061,7 +4113,7 @@ dst_register(struct st_translate *t, static struct ureg_src src_register(struct st_translate *t, gl_register_file file, - GLint index) + GLint index, GLint index2D) { switch(file) { case PROGRAM_UNDEFINED: @@ -4081,7 +4133,13 @@ src_register(struct st_translate *t, return t->constants[index]; case PROGRAM_STATE_VAR: case PROGRAM_CONSTANT: /* ie, immediate */ - if (index < 0) + if (index2D) { + struct ureg_src src; + src = ureg_src_register(TGSI_FILE_CONSTANT, 0); + src.Dimension = 1; + src.DimensionIndex = index2D; + return src; + } else if (index < 0) return ureg_DECL_constant(t->ureg, 0); else return t->constants[index]; @@ -4160,7 +4218,7 @@ translate_dst(struct st_translate *t, static struct ureg_src translate_src(struct st_translate *t, const st_src_reg *src_reg) { - struct ureg_src src = src_register(t, src_reg->file, src_reg->index); + struct ureg_src src = src_register(t, src_reg->file, src_reg->index, src_reg->index2D); src = ureg_swizzle(src, GET_SWZ(src_reg->swizzle, 0) & 0x3, @@ -4202,14 +4260,17 @@ translate_tex_offset(struct st_translate *t, const struct tgsi_texture_offset *in_offset) { struct tgsi_texture_offset offset; + struct ureg_src imm_src; assert(in_offset->File == PROGRAM_IMMEDIATE); + imm_src = t->immediates[in_offset->Index]; + offset.File = imm_src.File; + offset.Index = imm_src.Index; + offset.SwizzleX = imm_src.SwizzleX; + offset.SwizzleY = imm_src.SwizzleY; + offset.SwizzleZ = imm_src.SwizzleZ; offset.File = TGSI_FILE_IMMEDIATE; - offset.Index = in_offset->Index; - offset.SwizzleX = in_offset->SwizzleX; - offset.SwizzleY = in_offset->SwizzleY; - offset.SwizzleZ = in_offset->SwizzleZ; offset.Padding = 0; return offset; @@ -4754,6 +4815,14 @@ st_translate_program( } } } + + if (program->shader_program) { + unsigned num_ubos = program->shader_program->NumUniformBlocks; + + for (i = 0; i < num_ubos; i++) { + ureg_DECL_constant2D(t->ureg, 0, program->shader_program->UniformBlocks[i].UniformBufferSize / 4, i + 1); + } + } /* Emit immediate values. */ @@ -5060,6 +5129,8 @@ st_link_shader(struct gl_context *ctx, struct gl_shader_program *prog) do_mat_op_to_vec(ir); lower_instructions(ir, what_to_lower); + lower_ubo_reference(prog->_LinkedShaders[i], ir); + progress = do_lower_jumps(ir, true, true, options->EmitNoMainReturn, options->EmitNoCont, options->EmitNoLoops) || progress; progress = do_common_optimization(ir, true, true, @@ -5090,6 +5161,7 @@ st_link_shader(struct gl_context *ctx, struct gl_shader_program *prog) || progress; progress = do_vec_index_to_cond_assign(ir) || progress; + } while (progress); validate_ir_tree(ir); diff --git a/mesalib/src/mesa/state_tracker/st_manager.c b/mesalib/src/mesa/state_tracker/st_manager.c index 0b9add95e..b065db0ac 100644 --- a/mesalib/src/mesa/state_tracker/st_manager.c +++ b/mesalib/src/mesa/state_tracker/st_manager.c @@ -398,7 +398,7 @@ st_visual_to_context_mode(const struct st_visual *visual, UTIL_FORMAT_COLORSPACE_RGB, 3); } - if (visual->samples) { + if (visual->samples > 1) { mode->sampleBuffers = 1; mode->samples = visual->samples; } @@ -789,7 +789,7 @@ st_manager_flush_frontbuffer(struct st_context *st) /* never a dummy fb */ assert(&stfb->Base != _mesa_get_incomplete_framebuffer()); - stfb->iface->flush_front(stfb->iface, ST_ATTACHMENT_FRONT_LEFT); + stfb->iface->flush_front(&st->iface, stfb->iface, ST_ATTACHMENT_FRONT_LEFT); } /** @@ -899,7 +899,7 @@ static const struct st_api st_gl_api = { ST_PROFILE_OPENGL_ES2_MASK | #endif 0, - 0, + ST_API_FEATURE_MS_VISUALS_MASK, st_api_destroy, st_api_get_proc_address, st_api_create_context, diff --git a/mesalib/src/mesa/state_tracker/st_mesa_to_tgsi.c b/mesalib/src/mesa/state_tracker/st_mesa_to_tgsi.c index 81a870f86..e326bcc70 100644 --- a/mesalib/src/mesa/state_tracker/st_mesa_to_tgsi.c +++ b/mesalib/src/mesa/state_tracker/st_mesa_to_tgsi.c @@ -269,6 +269,7 @@ st_translate_texture_target( GLuint textarget, } switch( textarget ) { + case TEXTURE_BUFFER_INDEX: return TGSI_TEXTURE_BUFFER; case TEXTURE_1D_INDEX: return TGSI_TEXTURE_1D; case TEXTURE_2D_INDEX: return TGSI_TEXTURE_2D; case TEXTURE_3D_INDEX: return TGSI_TEXTURE_3D; diff --git a/mesalib/src/mesa/swrast/s_texfetch.c b/mesalib/src/mesa/swrast/s_texfetch.c index 7bfe3b941..86b01a0b3 100644 --- a/mesalib/src/mesa/swrast/s_texfetch.c +++ b/mesalib/src/mesa/swrast/s_texfetch.c @@ -1029,6 +1029,66 @@ texfetch_funcs[] = NULL }, { + MESA_FORMAT_ETC2_RGB8, + NULL, + _mesa_fetch_texel_2d_f_etc2_rgb8, + NULL + }, + { + MESA_FORMAT_ETC2_SRGB8, + NULL, + _mesa_fetch_texel_2d_f_etc2_srgb8, + NULL + }, + { + MESA_FORMAT_ETC2_RGBA8_EAC, + NULL, + _mesa_fetch_texel_2d_f_etc2_rgba8_eac, + NULL + }, + { + MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC, + NULL, + _mesa_fetch_texel_2d_f_etc2_srgb8_alpha8_eac, + NULL + }, + { + MESA_FORMAT_ETC2_R11_EAC, + NULL, + _mesa_fetch_texel_2d_f_etc2_r11_eac, + NULL + }, + { + MESA_FORMAT_ETC2_RG11_EAC, + NULL, + _mesa_fetch_texel_2d_f_etc2_rg11_eac, + NULL + }, + { + MESA_FORMAT_ETC2_SIGNED_R11_EAC, + NULL, + _mesa_fetch_texel_2d_f_etc2_signed_r11_eac, + NULL + }, + { + MESA_FORMAT_ETC2_SIGNED_RG11_EAC, + NULL, + _mesa_fetch_texel_2d_f_etc2_signed_rg11_eac, + NULL + }, + { + MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1, + NULL, + _mesa_fetch_texel_2d_f_etc2_rgb8_punchthrough_alpha1, + NULL + }, + { + MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1, + NULL, + _mesa_fetch_texel_2d_f_etc2_srgb8_punchthrough_alpha1, + NULL + }, + { MESA_FORMAT_SIGNED_A8, fetch_texel_1d_signed_a8, fetch_texel_2d_signed_a8, diff --git a/pixman/configure.ac b/pixman/configure.ac index 45b709dcf..81f068d9c 100644 --- a/pixman/configure.ac +++ b/pixman/configure.ac @@ -860,7 +860,7 @@ AC_CACHE_VAL(ac_cv_tls, [ #error OpenBSD has broken __thread support #endif -int $kw test;], [], ac_cv_tls=$kw) +int $kw test;], [], [ac_cv_tls=$kw; break]) done ]) AC_MSG_RESULT($ac_cv_tls) diff --git a/pixman/demos/Makefile.am b/pixman/demos/Makefile.am index f324f5f5b..3f2a3fad6 100644 --- a/pixman/demos/Makefile.am +++ b/pixman/demos/Makefile.am @@ -6,7 +6,8 @@ AM_LDFLAGS = $(OPENMP_CFLAGS) LDADD = $(top_builddir)/pixman/libpixman-1.la -lm $(GTK_LIBS) $(PNG_LIBS) INCLUDES = -I$(top_srcdir)/pixman -I$(top_builddir)/pixman $(GTK_CFLAGS) $(PNG_CFLAGS) -GTK_UTILS = gtk-utils.c gtk-utils.h ../test/utils.c ../test/utils.h +GTK_UTILS = gtk-utils.c gtk-utils.h ../test/utils.c ../test/utils.h \ + ../test/utils-prng.c ../test/utils-prng.h DEMOS = \ clip-test \ @@ -14,6 +15,7 @@ DEMOS = \ composite-test \ gradient-test \ radial-test \ + conical-test \ alpha-test \ screen-test \ convolution-test \ @@ -22,9 +24,10 @@ DEMOS = \ quad2quad \ checkerboard \ srgb-trap-test \ - srgb-test + srgb-test \ + scale -EXTRA_DIST = parrot.c parrot.jpg +EXTRA_DIST = parrot.c parrot.jpg scale.ui gradient_test_SOURCES = gradient-test.c $(GTK_UTILS) alpha_test_SOURCES = alpha-test.c $(GTK_UTILS) @@ -35,10 +38,12 @@ trap_test_SOURCES = trap-test.c $(GTK_UTILS) screen_test_SOURCES = screen-test.c $(GTK_UTILS) convolution_test_SOURCES = convolution-test.c $(GTK_UTILS) radial_test_SOURCES = radial-test.c $(GTK_UTILS) +conical_test_SOURCES = conical-test.c $(GTK_UTILS) tri_test_SOURCES = tri-test.c $(GTK_UTILS) checkerboard_SOURCES = checkerboard.c $(GTK_UTILS) srgb_test_SOURCES = srgb-test.c $(GTK_UTILS) srgb_trap_test_SOURCES = srgb-trap-test.c $(GTK_UTILS) +scale_SOURCES = scale.c $(GTK_UTILS) noinst_PROGRAMS = $(DEMOS) diff --git a/pixman/demos/conical-test.c b/pixman/demos/conical-test.c new file mode 100644 index 000000000..1e08e42f7 --- /dev/null +++ b/pixman/demos/conical-test.c @@ -0,0 +1,134 @@ +#include "../test/utils.h" +#include "gtk-utils.h" + +#define SIZE 128 +#define GRADIENTS_PER_ROW 7 +#define NUM_ROWS ((NUM_GRADIENTS + GRADIENTS_PER_ROW - 1) / GRADIENTS_PER_ROW) +#define WIDTH (SIZE * GRADIENTS_PER_ROW) +#define HEIGHT (SIZE * NUM_ROWS) +#define NUM_GRADIENTS 35 + +#define double_to_color(x) \ + (((uint32_t) ((x)*65536)) - (((uint32_t) ((x)*65536)) >> 16)) + +#define PIXMAN_STOP(offset,r,g,b,a) \ + { pixman_double_to_fixed (offset), \ + { \ + double_to_color (r), \ + double_to_color (g), \ + double_to_color (b), \ + double_to_color (a) \ + } \ + } + + +static const pixman_gradient_stop_t stops[] = { + PIXMAN_STOP (0.25, 1, 0, 0, 0.7), + PIXMAN_STOP (0.5, 1, 1, 0, 0.7), + PIXMAN_STOP (0.75, 0, 1, 0, 0.7), + PIXMAN_STOP (1.0, 0, 0, 1, 0.7) +}; + +#define NUM_STOPS (sizeof (stops) / sizeof (stops[0])) + +static pixman_image_t * +create_conical (int index) +{ + pixman_point_fixed_t c; + double angle; + + c.x = pixman_double_to_fixed (0); + c.y = pixman_double_to_fixed (0); + + angle = (0.5 / NUM_GRADIENTS + index / (double)NUM_GRADIENTS) * 720 - 180; + + return pixman_image_create_conical_gradient ( + &c, pixman_double_to_fixed (angle), stops, NUM_STOPS); +} + +#define CHECK_SIZE 25 + +static void +fill_checkerboard (pixman_image_t *image, int width, int height) +{ +#define C1 0xaaaa +#define C2 0x8888 + + pixman_color_t check1 = { C1, C1, C1, 0xffff }; + pixman_color_t check2 = { C2, C2, C2, 0xffff }; + pixman_image_t *c1, *c2; + int i, j; + + c1 = pixman_image_create_solid_fill (&check1); + c2 = pixman_image_create_solid_fill (&check2); + + for (j = 0; j < height; j += CHECK_SIZE) + { + for (i = 0; i < width; i += CHECK_SIZE) + { + pixman_image_t *src; + + if ((((i / CHECK_SIZE) ^ (j / CHECK_SIZE)) & 1) == 0) + src = c1; + else + src = c2; + + pixman_image_composite32 (PIXMAN_OP_SRC, src, NULL, image, + 0, 0, 0, 0, i, j, + CHECK_SIZE, CHECK_SIZE); + } + } +} + +int +main (int argc, char **argv) +{ + pixman_transform_t transform; + pixman_image_t *src_img, *dest_img; + int i; + + enable_divbyzero_exceptions (); + + dest_img = pixman_image_create_bits (PIXMAN_a8r8g8b8, + WIDTH, HEIGHT, + NULL, 0); + + fill_checkerboard (dest_img, WIDTH, HEIGHT); + + pixman_transform_init_identity (&transform); + + pixman_transform_translate (NULL, &transform, + pixman_double_to_fixed (0.5), + pixman_double_to_fixed (0.5)); + + pixman_transform_scale (NULL, &transform, + pixman_double_to_fixed (SIZE), + pixman_double_to_fixed (SIZE)); + pixman_transform_translate (NULL, &transform, + pixman_double_to_fixed (0.5), + pixman_double_to_fixed (0.5)); + + for (i = 0; i < NUM_GRADIENTS; i++) + { + int column = i % GRADIENTS_PER_ROW; + int row = i / GRADIENTS_PER_ROW; + + src_img = create_conical (i); + pixman_image_set_repeat (src_img, PIXMAN_REPEAT_NORMAL); + + pixman_image_set_transform (src_img, &transform); + + pixman_image_composite32 ( + PIXMAN_OP_OVER, src_img, NULL,dest_img, + 0, 0, 0, 0, column * SIZE, row * SIZE, + SIZE, SIZE); + + pixman_image_unref (src_img); + } + + show_image (dest_img); + + pixman_image_unref (dest_img); + + return 0; +} diff --git a/pixman/demos/gtk-utils.c b/pixman/demos/gtk-utils.c index 8291a1ed2..d7e946ded 100644 --- a/pixman/demos/gtk-utils.c +++ b/pixman/demos/gtk-utils.c @@ -3,6 +3,72 @@ #include "../test/utils.h" #include "gtk-utils.h" +pixman_image_t * +pixman_image_from_file (const char *filename, pixman_format_code_t format) +{ + GdkPixbuf *pixbuf; + pixman_image_t *image; + int width, height; + uint32_t *data, *d; + uint8_t *gdk_data; + int n_channels; + int j, i; + int stride; + + if (!(pixbuf = gdk_pixbuf_new_from_file (filename, NULL))) + return NULL; + + image = NULL; + + width = gdk_pixbuf_get_width (pixbuf); + height = gdk_pixbuf_get_height (pixbuf); + n_channels = gdk_pixbuf_get_n_channels (pixbuf); + gdk_data = gdk_pixbuf_get_pixels (pixbuf); + stride = gdk_pixbuf_get_rowstride (pixbuf); + + if (!(data = malloc (width * height * sizeof (uint32_t)))) + goto out; + + d = data; + for (j = 0; j < height; ++j) + { + uint8_t *gdk_line = gdk_data; + + for (i = 0; i < width; ++i) + { + int r, g, b, a; + uint32_t pixel; + + r = gdk_line[0]; + g = gdk_line[1]; + b = gdk_line[2]; + + if (n_channels == 4) + a = gdk_line[3]; + else + a = 0xff; + + r = (r * a + 127) / 255; + g = (g * a + 127) / 255; + b = (b * a + 127) / 255; + + pixel = (a << 24) | (r << 16) | (g << 8) | b; + + *d++ = pixel; + gdk_line += n_channels; + } + + gdk_data += stride; + } + + image = pixman_image_create_bits ( + format, width, height, data, width * 4); + +out: + g_object_unref (pixbuf); + return image; +} + GdkPixbuf * pixbuf_from_argb32 (uint32_t *bits, int width, diff --git a/pixman/demos/gtk-utils.h b/pixman/demos/gtk-utils.h index 55cb7018a..36be4def6 100644 --- a/pixman/demos/gtk-utils.h +++ b/pixman/demos/gtk-utils.h @@ -6,6 +6,9 @@ void show_image (pixman_image_t *image); +pixman_image_t * +pixman_image_from_file (const char *filename, pixman_format_code_t format); + GdkPixbuf *pixbuf_from_argb32 (uint32_t *bits, int width, int height, diff --git a/pixman/demos/scale.c b/pixman/demos/scale.c new file mode 100644 index 000000000..9100ff72a --- /dev/null +++ b/pixman/demos/scale.c @@ -0,0 +1,431 @@ +/* + * Copyright 2012, Red Hat, Inc. + * Copyright 2012, Soren Sandmann + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Author: Soren Sandmann <soren.sandmann@gmail.com> + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include <math.h> +#include <gtk/gtk.h> +#include <pixman.h> +#include <stdlib.h> +#include "gtk-utils.h" + +typedef struct +{ + GtkBuilder * builder; + pixman_image_t * original; + GtkAdjustment * scale_x_adjustment; + GtkAdjustment * scale_y_adjustment; + GtkAdjustment * rotate_adjustment; + int scaled_width; + int scaled_height; +} app_t; + +static GtkWidget * +get_widget (app_t *app, const char *name) +{ + GtkWidget *widget = GTK_WIDGET (gtk_builder_get_object (app->builder, name)); + + if (!widget) + g_error ("Widget %s not found\n", name); + + return widget; +} + +static double +min4 (double a, double b, double c, double d) +{ + double m1, m2; + + m1 = MIN (a, b); + m2 = MIN (c, d); + return MIN (m1, m2); +} + +static double +max4 (double a, double b, double c, double d) +{ + double m1, m2; + + m1 = MAX (a, b); + m2 = MAX (c, d); + return MAX (m1, m2); +} + +static void +compute_extents (pixman_f_transform_t *trans, double *sx, double *sy) +{ + double min_x, max_x, min_y, max_y; + pixman_f_vector_t v[4] = + { + { { 1, 1, 1 } }, + { { -1, 1, 1 } }, + { { -1, -1, 1 } }, + { { 1, -1, 1 } }, + }; + + pixman_f_transform_point (trans, &v[0]); + pixman_f_transform_point (trans, &v[1]); + pixman_f_transform_point (trans, &v[2]); + pixman_f_transform_point (trans, &v[3]); + + min_x = min4 (v[0].v[0], v[1].v[0], v[2].v[0], v[3].v[0]); + max_x = max4 (v[0].v[0], v[1].v[0], v[2].v[0], v[3].v[0]); + min_y = min4 (v[0].v[1], v[1].v[1], v[2].v[1], v[3].v[1]); + max_y = max4 (v[0].v[1], v[1].v[1], v[2].v[1], v[3].v[1]); + + *sx = (max_x - min_x) / 2.0; + *sy = (max_y - min_y) / 2.0; +} + +typedef struct +{ + char name [20]; + pixman_kernel_t value; +} named_int_t; + +static const named_int_t filters[] = +{ + { "Box", PIXMAN_KERNEL_BOX }, + { "Impulse", PIXMAN_KERNEL_IMPULSE }, + { "Linear", PIXMAN_KERNEL_LINEAR }, + { "Cubic", PIXMAN_KERNEL_CUBIC }, + { "Lanczos2", PIXMAN_KERNEL_LANCZOS2 }, + { "Lanczos3", PIXMAN_KERNEL_LANCZOS3 }, + { "Lanczos3 Stretched", PIXMAN_KERNEL_LANCZOS3_STRETCHED }, + { "Gaussian", PIXMAN_KERNEL_GAUSSIAN }, +}; + +static const named_int_t repeats[] = +{ + { "None", PIXMAN_REPEAT_NONE }, + { "Normal", PIXMAN_REPEAT_NORMAL }, + { "Reflect", PIXMAN_REPEAT_REFLECT }, + { "Pad", PIXMAN_REPEAT_PAD }, +}; + +static pixman_kernel_t +get_value (app_t *app, const named_int_t table[], const char *box_name) +{ + GtkComboBox *box = GTK_COMBO_BOX (get_widget (app, box_name)); + + return table[gtk_combo_box_get_active (box)].value; +} + +static void +copy_to_counterpart (app_t *app, GObject *object) +{ + static const char *xy_map[] = + { + "reconstruct_x_combo_box", "reconstruct_y_combo_box", + "sample_x_combo_box", "sample_y_combo_box", + "scale_x_adjustment", "scale_y_adjustment", + }; + GObject *counterpart = NULL; + int i; + + for (i = 0; i < G_N_ELEMENTS (xy_map); i += 2) + { + GObject *x = gtk_builder_get_object (app->builder, xy_map[i]); + GObject *y = gtk_builder_get_object (app->builder, xy_map[i + 1]); + + if (object == x) + counterpart = y; + if (object == y) + counterpart = x; + } + + if (!counterpart) + return; + + if (GTK_IS_COMBO_BOX (counterpart)) + { + gtk_combo_box_set_active ( + GTK_COMBO_BOX (counterpart), + gtk_combo_box_get_active ( + GTK_COMBO_BOX (object))); + } + else if (GTK_IS_ADJUSTMENT (counterpart)) + { + gtk_adjustment_set_value ( + GTK_ADJUSTMENT (counterpart), + gtk_adjustment_get_value ( + GTK_ADJUSTMENT (object))); + } +} + +static double +to_scale (double v) +{ + return pow (1.15, v); +} + +static void +rescale (GtkWidget *may_be_null, app_t *app) +{ + pixman_f_transform_t ftransform; + pixman_transform_t transform; + double new_width, new_height; + double fscale_x, fscale_y; + double rotation; + pixman_fixed_t *params; + int n_params; + double sx, sy; + + pixman_f_transform_init_identity (&ftransform); + + if (may_be_null && gtk_toggle_button_get_active ( + GTK_TOGGLE_BUTTON (get_widget (app, "lock_checkbutton")))) + { + copy_to_counterpart (app, G_OBJECT (may_be_null)); + } + + fscale_x = gtk_adjustment_get_value (app->scale_x_adjustment); + fscale_y = gtk_adjustment_get_value (app->scale_y_adjustment); + rotation = gtk_adjustment_get_value (app->rotate_adjustment); + + fscale_x = to_scale (fscale_x); + fscale_y = to_scale (fscale_y); + + new_width = pixman_image_get_width (app->original) * fscale_x; + new_height = pixman_image_get_height (app->original) * fscale_y; + + pixman_f_transform_scale (&ftransform, NULL, fscale_x, fscale_y); + + pixman_f_transform_translate (&ftransform, NULL, - new_width / 2.0, - new_height / 2.0); + + rotation = (rotation / 360.0) * 2 * M_PI; + pixman_f_transform_rotate (&ftransform, NULL, cos (rotation), sin (rotation)); + + pixman_f_transform_translate (&ftransform, NULL, new_width / 2.0, new_height / 2.0); + + pixman_f_transform_invert (&ftransform, &ftransform); + + compute_extents (&ftransform, &sx, &sy); + + pixman_transform_from_pixman_f_transform (&transform, &ftransform); + pixman_image_set_transform (app->original, &transform); + + params = pixman_filter_create_separable_convolution ( + &n_params, + sx * 65536.0 + 0.5, + sy * 65536.0 + 0.5, + get_value (app, filters, "reconstruct_x_combo_box"), + get_value (app, filters, "reconstruct_y_combo_box"), + get_value (app, filters, "sample_x_combo_box"), + get_value (app, filters, "sample_y_combo_box"), + 4, 4); + + pixman_image_set_filter (app->original, PIXMAN_FILTER_SEPARABLE_CONVOLUTION, params, n_params); + + pixman_image_set_repeat ( + app->original, get_value (app, repeats, "repeat_combo_box")); + + free (params); + + app->scaled_width = ceil (new_width); + app->scaled_height = ceil (new_height); + + gtk_widget_set_size_request ( + get_widget (app, "drawing_area"), new_width + 0.5, new_height + 0.5); + + gtk_widget_queue_draw ( + get_widget (app, "drawing_area")); +} + +static gboolean +on_expose (GtkWidget *da, GdkEvent *event, gpointer data) +{ + app_t *app = data; + GdkRectangle *area = &event->expose.area; + cairo_surface_t *surface; + pixman_image_t *tmp; + cairo_t *cr; + uint32_t *pixels; + + pixels = calloc (1, area->width * area->height * 4); + tmp = pixman_image_create_bits ( + PIXMAN_a8r8g8b8, area->width, area->height, pixels, area->width * 4); + + if (area->x < app->scaled_width && area->y < app->scaled_height) + { + pixman_image_composite ( + PIXMAN_OP_SRC, + app->original, NULL, tmp, + area->x, area->y, 0, 0, 0, 0, + app->scaled_width - area->x, app->scaled_height - area->y); + } + + surface = cairo_image_surface_create_for_data ( + (uint8_t *)pixels, CAIRO_FORMAT_ARGB32, + area->width, area->height, area->width * 4); + + cr = gdk_cairo_create (da->window); + + cairo_set_source_surface (cr, surface, area->x, area->y); + + cairo_paint (cr); + + cairo_destroy (cr); + cairo_surface_destroy (surface); + free (pixels); + pixman_image_unref (tmp); + + return TRUE; +} + +static void +set_up_combo_box (app_t *app, const char *box_name, + int n_entries, const named_int_t table[]) +{ + GtkWidget *widget = get_widget (app, box_name); + GtkListStore *model; + GtkCellRenderer *cell; + int i; + + model = gtk_list_store_new (1, G_TYPE_STRING); + + cell = gtk_cell_renderer_text_new (); + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (widget), cell, TRUE); + gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (widget), cell, + "text", 0, + NULL); + + gtk_combo_box_set_model (GTK_COMBO_BOX (widget), GTK_TREE_MODEL (model)); + + for (i = 0; i < n_entries; ++i) + { + const named_int_t *info = &(table[i]); + GtkTreeIter iter; + + gtk_list_store_append (model, &iter); + gtk_list_store_set (model, &iter, 0, info->name, -1); + } + + gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0); + + g_signal_connect (widget, "changed", G_CALLBACK (rescale), app); +} + +static void +set_up_filter_box (app_t *app, const char *box_name) +{ + set_up_combo_box (app, box_name, G_N_ELEMENTS (filters), filters); +} + +static char * +format_value (GtkWidget *widget, double value) +{ + return g_strdup_printf ("%.4f", to_scale (value)); +} + +static app_t * +app_new (pixman_image_t *original) +{ + GtkWidget *widget; + app_t *app = g_malloc (sizeof *app); + GError *err = NULL; + + app->builder = gtk_builder_new (); + app->original = original; + + if (!gtk_builder_add_from_file (app->builder, "scale.ui", &err)) + g_error ("Could not read file scale.ui: %s", err->message); + + app->scale_x_adjustment = + GTK_ADJUSTMENT (gtk_builder_get_object (app->builder, "scale_x_adjustment")); + app->scale_y_adjustment = + GTK_ADJUSTMENT (gtk_builder_get_object (app->builder, "scale_y_adjustment")); + app->rotate_adjustment = + GTK_ADJUSTMENT (gtk_builder_get_object (app->builder, "rotate_adjustment")); + + g_signal_connect (app->scale_x_adjustment, "value_changed", G_CALLBACK (rescale), app); + g_signal_connect (app->scale_y_adjustment, "value_changed", G_CALLBACK (rescale), app); + g_signal_connect (app->rotate_adjustment, "value_changed", G_CALLBACK (rescale), app); + + widget = get_widget (app, "scale_x_scale"); + gtk_scale_add_mark (GTK_SCALE (widget), 0.0, GTK_POS_LEFT, NULL); + g_signal_connect (widget, "format_value", G_CALLBACK (format_value), app); + widget = get_widget (app, "scale_y_scale"); + gtk_scale_add_mark (GTK_SCALE (widget), 0.0, GTK_POS_LEFT, NULL); + g_signal_connect (widget, "format_value", G_CALLBACK (format_value), app); + widget = get_widget (app, "rotate_scale"); + gtk_scale_add_mark (GTK_SCALE (widget), 0.0, GTK_POS_LEFT, NULL); + + widget = get_widget (app, "drawing_area"); + g_signal_connect (widget, "expose_event", G_CALLBACK (on_expose), app); + + set_up_filter_box (app, "reconstruct_x_combo_box"); + set_up_filter_box (app, "reconstruct_y_combo_box"); + set_up_filter_box (app, "sample_x_combo_box"); + set_up_filter_box (app, "sample_y_combo_box"); + + set_up_combo_box ( + app, "repeat_combo_box", G_N_ELEMENTS (repeats), repeats); + + g_signal_connect ( + gtk_builder_get_object (app->builder, "lock_checkbutton"), + "toggled", G_CALLBACK (rescale), app); + + rescale (NULL, app); + + return app; +} + +int +main (int argc, char **argv) +{ + GtkWidget *window; + pixman_image_t *image; + app_t *app; + + gtk_init (&argc, &argv); + + if (argc < 2) + { + printf ("%s <image file>\n", argv[0]); + return -1; + } + + if (!(image = pixman_image_from_file (argv[1], PIXMAN_a8r8g8b8))) + { + printf ("Could not load image \"%s\"\n", argv[1]); + return -1; + } + + app = app_new (image); + + window = get_widget (app, "main"); + + g_signal_connect (window, "delete_event", G_CALLBACK (gtk_main_quit), NULL); + + gtk_window_set_default_size (GTK_WINDOW (window), 1024, 768); + + gtk_widget_show_all (window); + + gtk_main (); + + return 0; +} diff --git a/pixman/demos/scale.ui b/pixman/demos/scale.ui new file mode 100644 index 000000000..f7c0c805f --- /dev/null +++ b/pixman/demos/scale.ui @@ -0,0 +1,302 @@ +<?xml version="1.0" encoding="UTF-8"?> +<interface> + <!-- interface-requires gtk+ 2.12 --> + <!-- interface-naming-policy toplevel-contextual --> + <object class="GtkAdjustment" id="rotate_adjustment"> + <property name="lower">-180</property> + <property name="upper">190</property> + <property name="step_increment">1</property> + <property name="page_increment">10</property> + <property name="page_size">10</property> + </object> + <object class="GtkAdjustment" id="scale_y_adjustment"> + <property name="lower">-32</property> + <property name="upper">42</property> + <property name="step_increment">1</property> + <property name="page_increment">10</property> + <property name="page_size">10</property> + </object> + <object class="GtkAdjustment" id="scale_x_adjustment"> + <property name="lower">-32</property> + <property name="upper">42</property> + <property name="step_increment">1</property> + <property name="page_increment">10</property> + <property name="page_size">10</property> + </object> + <object class="GtkWindow" id="main"> + <child> + <object class="GtkHBox" id="u"> + <property name="visible">True</property> + <property name="spacing">12</property> + <child> + <object class="GtkScrolledWindow" id="scrolledwindow1"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="shadow_type">in</property> + <child> + <object class="GtkViewport" id="viewport1"> + <property name="visible">True</property> + <child> + <object class="GtkDrawingArea" id="drawing_area"> + <property name="visible">True</property> + </object> + </child> + </object> + </child> + </object> + <packing> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkVBox" id="box1"> + <property name="visible">True</property> + <child> + <object class="GtkHBox" id="box2"> + <property name="visible">True</property> + <property name="homogeneous">True</property> + <child> + <object class="GtkVBox" id="box3"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <object class="GtkLabel" id="label1"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>Scale X</b></property> + <property name="use_markup">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkVScale" id="scale_x_scale"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="adjustment">scale_x_adjustment</property> + <property name="fill_level">32</property> + <property name="value_pos">right</property> + </object> + <packing> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkVBox" id="box4"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <object class="GtkLabel" id="label2"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>Scale Y</b></property> + <property name="use_markup">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkVScale" id="scale_y_scale"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="adjustment">scale_y_adjustment</property> + <property name="fill_level">32</property> + <property name="value_pos">right</property> + </object> + <packing> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkVBox" id="box5"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <object class="GtkLabel" id="label3"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>Rotate</b></property> + <property name="use_markup">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkVScale" id="rotate_scale"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="adjustment">rotate_adjustment</property> + <property name="fill_level">180</property> + <property name="value_pos">right</property> + </object> + <packing> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="position">2</property> + </packing> + </child> + </object> + <packing> + <property name="padding">6</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkVBox" id="box6"> + <property name="visible">True</property> + <child> + <object class="GtkCheckButton" + id="lock_checkbutton"> + <property name="label" translatable="yes">Lock X and Y Dimensions</property> + <property name="xalign">0.0</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="padding">6</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkTable" id="grid1"> + <property name="visible">True</property> + <property name="column_spacing">8</property> + <property name="row_spacing">6</property> + <child> + <object class="GtkLabel" id="label4"> + <property name="visible">True</property> + <property name="xalign">1</property> + <property name="label" translatable="yes"><b>Reconstruct X:</b></property> + <property name="use_markup">True</property> + </object> + </child> + <child> + <object class="GtkLabel" id="label5"> + <property name="visible">True</property> + <property name="xalign">1</property> + <property name="label" translatable="yes"><b>Reconstruct Y:</b></property> + <property name="use_markup">True</property> + </object> + <packing> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label6"> + <property name="visible">True</property> + <property name="xalign">1</property> + <property name="label" translatable="yes"><b>Sample X:</b></property> + <property name="use_markup">True</property> + </object> + <packing> + <property name="top_attach">2</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label7"> + <property name="visible">True</property> + <property name="xalign">1</property> + <property name="label" translatable="yes"><b>Sample Y:</b></property> + <property name="use_markup">True</property> + </object> + <packing> + <property name="top_attach">3</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label8"> + <property name="visible">True</property> + <property name="xalign">1</property> + <property name="label" translatable="yes"><b>Repeat:</b></property> + <property name="use_markup">True</property> + </object> + <packing> + <property name="top_attach">4</property> + </packing> + </child> + <child> + <object class="GtkComboBox" id="reconstruct_x_combo_box"> + <property name="visible">True</property> + </object> + <packing> + <property name="left_attach">1</property> + </packing> + </child> + <child> + <object class="GtkComboBox" id="reconstruct_y_combo_box"> + <property name="visible">True</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">1</property> + </packing> + </child> + <child> + <object class="GtkComboBox" id="sample_x_combo_box"> + <property name="visible">True</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">2</property> + </packing> + </child> + <child> + <object class="GtkComboBox" id="sample_y_combo_box"> + <property name="visible">True</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">3</property> + </packing> + </child> + <child> + <object class="GtkComboBox" id="repeat_combo_box"> + <property name="visible">True</property> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">4</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="padding">6</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="position">0</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="position">1</property> + </packing> + </child> + </object> + </child> + </object> +</interface> diff --git a/pixman/demos/zone_plate.png b/pixman/demos/zone_plate.png Binary files differnew file mode 100644 index 000000000..519291d6d --- /dev/null +++ b/pixman/demos/zone_plate.png diff --git a/pixman/pixman/Makefile.sources b/pixman/pixman/Makefile.sources index 5351fb03d..c624eb9a8 100644 --- a/pixman/pixman/Makefile.sources +++ b/pixman/pixman/Makefile.sources @@ -6,6 +6,7 @@ libpixman_sources = \ pixman-combine32.c \ pixman-combine-float.c \ pixman-conical-gradient.c \ + pixman-filter.c \ pixman-x86.c \ pixman-mips.c \ pixman-arm.c \ diff --git a/pixman/pixman/pixman-bits-image.c b/pixman/pixman/pixman-bits-image.c index 7787ef1b8..86d80c3f5 100644 --- a/pixman/pixman/pixman-bits-image.c +++ b/pixman/pixman/pixman-bits-image.c @@ -426,6 +426,104 @@ bits_image_fetch_pixel_convolution (bits_image_t *image, return ((satot << 24) | (srtot << 16) | (sgtot << 8) | (sbtot)); } +static uint32_t +bits_image_fetch_pixel_separable_convolution (bits_image_t *image, + pixman_fixed_t x, + pixman_fixed_t y, + get_pixel_t get_pixel) +{ + pixman_fixed_t *params = image->common.filter_params; + pixman_repeat_t repeat_mode = image->common.repeat; + int width = image->width; + int height = image->height; + int cwidth = pixman_fixed_to_int (params[0]); + int cheight = pixman_fixed_to_int (params[1]); + int x_phase_bits = pixman_fixed_to_int (params[2]); + int y_phase_bits = pixman_fixed_to_int (params[3]); + int x_phase_shift = 16 - x_phase_bits; + int y_phase_shift = 16 - y_phase_bits; + int x_off = ((cwidth << 16) - pixman_fixed_1) >> 1; + int y_off = ((cheight << 16) - pixman_fixed_1) >> 1; + pixman_fixed_t *y_params; + int srtot, sgtot, sbtot, satot; + int32_t x1, x2, y1, y2; + int32_t px, py; + int i, j; + + /* Round x and y to the middle of the closest phase before continuing. This + * ensures that the convolution matrix is aligned right, since it was + * positioned relative to a particular phase (and not relative to whatever + * exact fraction we happen to get here). + */ + x = ((x >> x_phase_shift) << x_phase_shift) + ((1 << x_phase_shift) >> 1); + y = ((y >> y_phase_shift) << y_phase_shift) + ((1 << y_phase_shift) >> 1); + + px = (x & 0xffff) >> x_phase_shift; + py = (y & 0xffff) >> y_phase_shift; + + y_params = params + 4 + (1 << x_phase_bits) * cwidth + py * cheight; + + x1 = pixman_fixed_to_int (x - pixman_fixed_e - x_off); + y1 = pixman_fixed_to_int (y - pixman_fixed_e - y_off); + x2 = x1 + cwidth; + y2 = y1 + cheight; + + srtot = sgtot = sbtot = satot = 0; + + for (i = y1; i < y2; ++i) + { + pixman_fixed_48_16_t fy = *y_params++; + pixman_fixed_t *x_params = params + 4 + px * cwidth; + + if (fy) + { + for (j = x1; j < x2; ++j) + { + pixman_fixed_t fx = *x_params++; + int rx = j; + int ry = i; + + if (fx) + { + pixman_fixed_t f; + uint32_t pixel; + + if (repeat_mode != PIXMAN_REPEAT_NONE) + { + repeat (repeat_mode, &rx, width); + repeat (repeat_mode, &ry, height); + + pixel = get_pixel (image, rx, ry, FALSE); + } + else + { + pixel = get_pixel (image, rx, ry, TRUE); + } + + f = (fy * fx + 0x8000) >> 16; + + srtot += (int)RED_8 (pixel) * f; + sgtot += (int)GREEN_8 (pixel) * f; + sbtot += (int)BLUE_8 (pixel) * f; + satot += (int)ALPHA_8 (pixel) * f; + } + } + } + } + + satot = (satot + 0x8000) >> 16; + srtot = (srtot + 0x8000) >> 16; + sgtot = (sgtot + 0x8000) >> 16; + sbtot = (sbtot + 0x8000) >> 16; + + satot = CLIP (satot, 0, 0xff); + srtot = CLIP (srtot, 0, 0xff); + sgtot = CLIP (sgtot, 0, 0xff); + sbtot = CLIP (sbtot, 0, 0xff); + + return ((satot << 24) | (srtot << 16) | (sgtot << 8) | (sbtot)); +} + static force_inline uint32_t bits_image_fetch_pixel_filtered (bits_image_t *image, pixman_fixed_t x, @@ -449,6 +547,10 @@ bits_image_fetch_pixel_filtered (bits_image_t *image, return bits_image_fetch_pixel_convolution (image, x, y, get_pixel); break; + case PIXMAN_FILTER_SEPARABLE_CONVOLUTION: + return bits_image_fetch_pixel_separable_convolution (image, x, y, get_pixel); + break; + default: break; } @@ -618,11 +720,155 @@ bits_image_fetch_general (pixman_iter_t *iter, return buffer; } -static const uint8_t zero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - typedef uint32_t (* convert_pixel_t) (const uint8_t *row, int x); static force_inline void +bits_image_fetch_separable_convolution_affine (pixman_image_t * image, + int offset, + int line, + int width, + uint32_t * buffer, + const uint32_t * mask, + + convert_pixel_t convert_pixel, + pixman_format_code_t format, + pixman_repeat_t repeat_mode) +{ + bits_image_t *bits = &image->bits; + pixman_fixed_t *params = image->common.filter_params; + int cwidth = pixman_fixed_to_int (params[0]); + int cheight = pixman_fixed_to_int (params[1]); + int x_off = ((cwidth << 16) - pixman_fixed_1) >> 1; + int y_off = ((cheight << 16) - pixman_fixed_1) >> 1; + int x_phase_bits = pixman_fixed_to_int (params[2]); + int y_phase_bits = pixman_fixed_to_int (params[3]); + int x_phase_shift = 16 - x_phase_bits; + int y_phase_shift = 16 - y_phase_bits; + pixman_fixed_t vx, vy; + pixman_fixed_t ux, uy; + pixman_vector_t v; + int k; + + /* reference point is the center of the pixel */ + v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2; + v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2; + v.vector[2] = pixman_fixed_1; + + if (!pixman_transform_point_3d (image->common.transform, &v)) + return; + + ux = image->common.transform->matrix[0][0]; + uy = image->common.transform->matrix[1][0]; + + vx = v.vector[0]; + vy = v.vector[1]; + + for (k = 0; k < width; ++k) + { + pixman_fixed_t *y_params; + int satot, srtot, sgtot, sbtot; + pixman_fixed_t x, y; + int32_t x1, x2, y1, y2; + int32_t px, py; + int i, j; + + if (mask && !mask[k]) + goto next; + + /* Round x and y to the middle of the closest phase before continuing. This + * ensures that the convolution matrix is aligned right, since it was + * positioned relative to a particular phase (and not relative to whatever + * exact fraction we happen to get here). + */ + x = ((vx >> x_phase_shift) << x_phase_shift) + ((1 << x_phase_shift) >> 1); + y = ((vy >> y_phase_shift) << y_phase_shift) + ((1 << y_phase_shift) >> 1); + + px = (x & 0xffff) >> x_phase_shift; + py = (y & 0xffff) >> y_phase_shift; + + x1 = pixman_fixed_to_int (x - pixman_fixed_e - x_off); + y1 = pixman_fixed_to_int (y - pixman_fixed_e - y_off); + x2 = x1 + cwidth; + y2 = y1 + cheight; + + satot = srtot = sgtot = sbtot = 0; + + y_params = params + 4 + (1 << x_phase_bits) * cwidth + py * cheight; + + for (i = y1; i < y2; ++i) + { + pixman_fixed_t fy = *y_params++; + + if (fy) + { + pixman_fixed_t *x_params = params + 4 + px * cwidth; + + for (j = x1; j < x2; ++j) + { + pixman_fixed_t fx = *x_params++; + int rx = j; + int ry = i; + + if (fx) + { + pixman_fixed_t f; + uint32_t pixel, mask; + uint8_t *row; + + mask = PIXMAN_FORMAT_A (format)? 0 : 0xff000000; + + if (repeat_mode != PIXMAN_REPEAT_NONE) + { + repeat (repeat_mode, &rx, bits->width); + repeat (repeat_mode, &ry, bits->height); + + row = (uint8_t *)bits->bits + bits->rowstride * 4 * ry; + pixel = convert_pixel (row, rx) | mask; + } + else + { + if (rx < 0 || ry < 0 || rx >= bits->width || ry >= bits->height) + { + pixel = 0; + } + else + { + row = (uint8_t *)bits->bits + bits->rowstride * 4 * ry; + pixel = convert_pixel (row, rx) | mask; + } + } + + f = ((pixman_fixed_32_32_t)fx * fy + 0x8000) >> 16; + srtot += (int)RED_8 (pixel) * f; + sgtot += (int)GREEN_8 (pixel) * f; + sbtot += (int)BLUE_8 (pixel) * f; + satot += (int)ALPHA_8 (pixel) * f; + } + } + } + } + + satot = (satot + 0x8000) >> 16; + srtot = (srtot + 0x8000) >> 16; + sgtot = (sgtot + 0x8000) >> 16; + sbtot = (sbtot + 0x8000) >> 16; + + satot = CLIP (satot, 0, 0xff); + srtot = CLIP (srtot, 0, 0xff); + sgtot = CLIP (sgtot, 0, 0xff); + sbtot = CLIP (sbtot, 0, 0xff); + + buffer[k] = (satot << 24) | (srtot << 16) | (sgtot << 8) | (sbtot << 0); + + next: + vx += ux; + vy += uy; + } +} + +static const uint8_t zero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + +static force_inline void bits_image_fetch_bilinear_affine (pixman_image_t * image, int offset, int line, @@ -871,6 +1117,23 @@ convert_r5g6b5 (const uint8_t *row, int x) return CONVERT_0565_TO_0888 (*((uint16_t *)row + x)); } +#define MAKE_SEPARABLE_CONVOLUTION_FETCHER(name, format, repeat_mode) \ + static uint32_t * \ + bits_image_fetch_separable_convolution_affine_ ## name (pixman_iter_t *iter, \ + const uint32_t * mask) \ + { \ + bits_image_fetch_separable_convolution_affine ( \ + iter->image, \ + iter->x, iter->y++, \ + iter->width, \ + iter->buffer, mask, \ + convert_ ## format, \ + PIXMAN_ ## format, \ + repeat_mode); \ + \ + return iter->buffer; \ + } + #define MAKE_BILINEAR_FETCHER(name, format, repeat_mode) \ static uint32_t * \ bits_image_fetch_bilinear_affine_ ## name (pixman_iter_t *iter, \ @@ -903,7 +1166,8 @@ convert_r5g6b5 (const uint8_t *row, int x) #define MAKE_FETCHERS(name, format, repeat_mode) \ MAKE_NEAREST_FETCHER (name, format, repeat_mode) \ - MAKE_BILINEAR_FETCHER (name, format, repeat_mode) + MAKE_BILINEAR_FETCHER (name, format, repeat_mode) \ + MAKE_SEPARABLE_CONVOLUTION_FETCHER (name, format, repeat_mode) MAKE_FETCHERS (pad_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_PAD) MAKE_FETCHERS (none_a8r8g8b8, a8r8g8b8, PIXMAN_REPEAT_NONE) @@ -1153,6 +1417,20 @@ static const fetcher_info_t fetcher_info[] = FAST_PATH_AFFINE_TRANSFORM | \ FAST_PATH_NEAREST_FILTER) +#define GENERAL_SEPARABLE_CONVOLUTION_FLAGS \ + (FAST_PATH_NO_ALPHA_MAP | \ + FAST_PATH_NO_ACCESSORS | \ + FAST_PATH_HAS_TRANSFORM | \ + FAST_PATH_AFFINE_TRANSFORM | \ + FAST_PATH_SEPARABLE_CONVOLUTION_FILTER) + +#define SEPARABLE_CONVOLUTION_AFFINE_FAST_PATH(name, format, repeat) \ + { PIXMAN_ ## format, \ + GENERAL_SEPARABLE_CONVOLUTION_FLAGS | FAST_PATH_ ## repeat ## _REPEAT, \ + bits_image_fetch_separable_convolution_affine_ ## name, \ + _pixman_image_get_scanline_generic_float \ + }, + #define BILINEAR_AFFINE_FAST_PATH(name, format, repeat) \ { PIXMAN_ ## format, \ GENERAL_BILINEAR_FLAGS | FAST_PATH_ ## repeat ## _REPEAT, \ @@ -1168,6 +1446,7 @@ static const fetcher_info_t fetcher_info[] = }, #define AFFINE_FAST_PATHS(name, format, repeat) \ + SEPARABLE_CONVOLUTION_AFFINE_FAST_PATH(name, format, repeat) \ BILINEAR_AFFINE_FAST_PATH(name, format, repeat) \ NEAREST_AFFINE_FAST_PATH(name, format, repeat) diff --git a/pixman/pixman/pixman-filter.c b/pixman/pixman/pixman-filter.c new file mode 100644 index 000000000..c9d2dc74c --- /dev/null +++ b/pixman/pixman/pixman-filter.c @@ -0,0 +1,340 @@ +/* + * Copyright 2012, Red Hat, Inc. + * Copyright 2012, Soren Sandmann + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Author: Soren Sandmann <soren.sandmann@gmail.com> + */ +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <math.h> +#include <assert.h> +#include <config.h> +#include "pixman-private.h" + +typedef double (* kernel_func_t) (double x); + +typedef struct +{ + pixman_kernel_t kernel; + kernel_func_t func; + double width; +} filter_info_t; + +static double +impulse_kernel (double x) +{ + return (x == 0.0)? 1.0 : 0.0; +} + +static double +box_kernel (double x) +{ + return 1; +} + +static double +linear_kernel (double x) +{ + return 1 - fabs (x); +} + +static double +gaussian_kernel (double x) +{ +#define SQRT2 (1.4142135623730950488016887242096980785696718753769480) +#define SIGMA (SQRT2 / 2.0) + + return exp (- x * x / (2 * SIGMA * SIGMA)) / (SIGMA * sqrt (2.0 * M_PI)); +} + +static double +sinc (double x) +{ + if (x == 0.0) + return 1.0; + else + return sin (M_PI * x) / (M_PI * x); +} + +static double +lanczos (double x, int n) +{ + return sinc (x) * sinc (x * (1.0 / n)); +} + +static double +lanczos2_kernel (double x) +{ + return lanczos (x, 2); +} + +static double +lanczos3_kernel (double x) +{ + return lanczos (x, 3); +} + +static double +nice_kernel (double x) +{ + return lanczos3_kernel (x * 0.75); +} + +static double +general_cubic (double x, double B, double C) +{ + double ax = fabs(x); + + if (ax < 1) + { + return ((12 - 9 * B - 6 * C) * ax * ax * ax + + (-18 + 12 * B + 6 * C) * ax * ax + (6 - 2 * B)) / 6; + } + else if (ax >= 1 && ax < 2) + { + return ((-B - 6 * C) * ax * ax * ax + + (6 * B + 30 * C) * ax * ax + (-12 * B - 48 * C) * + ax + (8 * B + 24 * C)) / 6; + } + else + { + return 0; + } +} + +static double +cubic_kernel (double x) +{ + /* This is the Mitchell-Netravali filter. + * + * (0.0, 0.5) would give us the Catmull-Rom spline, + * but that one seems to be indistinguishable from Lanczos2. + */ + return general_cubic (x, 1/3.0, 1/3.0); +} + +static const filter_info_t filters[] = +{ + { PIXMAN_KERNEL_IMPULSE, impulse_kernel, 0.0 }, + { PIXMAN_KERNEL_BOX, box_kernel, 1.0 }, + { PIXMAN_KERNEL_LINEAR, linear_kernel, 2.0 }, + { PIXMAN_KERNEL_CUBIC, cubic_kernel, 4.0 }, + { PIXMAN_KERNEL_GAUSSIAN, gaussian_kernel, 6 * SIGMA }, + { PIXMAN_KERNEL_LANCZOS2, lanczos2_kernel, 4.0 }, + { PIXMAN_KERNEL_LANCZOS3, lanczos3_kernel, 6.0 }, + { PIXMAN_KERNEL_LANCZOS3_STRETCHED, nice_kernel, 8.0 }, +}; + +/* This function scales @kernel2 by @scale, then + * aligns @x1 in @kernel1 with @x2 in @kernel2 and + * and integrates the product of the kernels across @width. + * + * This function assumes that the intervals are within + * the kernels in question. E.g., the caller must not + * try to integrate a linear kernel ouside of [-1:1] + */ +static double +integral (pixman_kernel_t kernel1, double x1, + pixman_kernel_t kernel2, double scale, double x2, + double width) +{ + /* If the integration interval crosses zero, break it into + * two separate integrals. This ensures that filters such + * as LINEAR that are not differentiable at 0 will still + * integrate properly. + */ + if (x1 < 0 && x1 + width > 0) + { + return + integral (kernel1, x1, kernel2, scale, x2, - x1) + + integral (kernel1, 0, kernel2, scale, x2 - x1, width + x1); + } + else if (x2 < 0 && x2 + width > 0) + { + return + integral (kernel1, x1, kernel2, scale, x2, - x2) + + integral (kernel1, x1 - x2, kernel2, scale, 0, width + x2); + } + else if (kernel1 == PIXMAN_KERNEL_IMPULSE) + { + assert (width == 0.0); + return filters[kernel2].func (x2 * scale); + } + else if (kernel2 == PIXMAN_KERNEL_IMPULSE) + { + assert (width == 0.0); + return filters[kernel1].func (x1); + } + else + { + /* Integration via Simpson's rule */ +#define N_SEGMENTS 128 +#define SAMPLE(a1, a2) \ + (filters[kernel1].func ((a1)) * filters[kernel2].func ((a2) * scale)) + + double s = 0.0; + double h = width / (double)N_SEGMENTS; + int i; + + s = SAMPLE (x1, x2); + + for (i = 1; i < N_SEGMENTS; i += 2) + { + double a1 = x1 + h * i; + double a2 = x2 + h * i; + + s += 2 * SAMPLE (a1, a2); + + if (i >= 2 && i < N_SEGMENTS - 1) + s += 4 * SAMPLE (a1, a2); + } + + s += SAMPLE (x1 + width, x2 + width); + + return h * s * (1.0 / 3.0); + } +} + +static pixman_fixed_t * +create_1d_filter (int *width, + pixman_kernel_t reconstruct, + pixman_kernel_t sample, + double scale, + int n_phases) +{ + pixman_fixed_t *params, *p; + double step; + double size; + int i; + + size = scale * filters[sample].width + filters[reconstruct].width; + *width = ceil (size); + + p = params = malloc (*width * n_phases * sizeof (pixman_fixed_t)); + + step = 1.0 / n_phases; + + for (i = 0; i < n_phases; ++i) + { + double frac = step / 2.0 + i * step; + pixman_fixed_t new_total; + int x, x1, x2; + double total; + + /* Sample convolution of reconstruction and sampling + * filter. See rounding.txt regarding the rounding + * and sample positions. + */ + + x1 = ceil (frac - *width / 2.0 - 0.5); + x2 = x1 + *width; + + total = 0; + for (x = x1; x < x2; ++x) + { + double pos = x + 0.5 - frac; + double rlow = - filters[reconstruct].width / 2.0; + double rhigh = rlow + filters[reconstruct].width; + double slow = pos - scale * filters[sample].width / 2.0; + double shigh = slow + scale * filters[sample].width; + double c = 0.0; + double ilow, ihigh; + + if (rhigh >= slow && rlow <= shigh) + { + ilow = MAX (slow, rlow); + ihigh = MIN (shigh, rhigh); + + c = integral (reconstruct, ilow, + sample, 1.0 / scale, ilow - pos, + ihigh - ilow); + } + + total += c; + *p++ = (pixman_fixed_t)(c * 65535.0 + 0.5); + } + + /* Normalize */ + p -= *width; + total = 1 / total; + new_total = 0; + for (x = x1; x < x2; ++x) + { + pixman_fixed_t t = (*p) * total + 0.5; + + new_total += t; + *p++ = t; + } + + if (new_total != pixman_fixed_1) + *(p - *width / 2) += (pixman_fixed_1 - new_total); + } + + return params; +} + +/* Create the parameter list for a SEPARABLE_CONVOLUTION filter + * with the given kernels and scale parameters + */ +PIXMAN_EXPORT pixman_fixed_t * +pixman_filter_create_separable_convolution (int *n_values, + pixman_fixed_t scale_x, + pixman_fixed_t scale_y, + pixman_kernel_t reconstruct_x, + pixman_kernel_t reconstruct_y, + pixman_kernel_t sample_x, + pixman_kernel_t sample_y, + int subsample_bits_x, + int subsample_bits_y) +{ + double sx = fabs (pixman_fixed_to_double (scale_x)); + double sy = fabs (pixman_fixed_to_double (scale_y)); + pixman_fixed_t *horz, *vert, *params; + int subsample_x, subsample_y; + int width, height; + + subsample_x = (1 << subsample_bits_x); + subsample_y = (1 << subsample_bits_y); + + horz = create_1d_filter (&width, reconstruct_x, sample_x, sx, subsample_x); + vert = create_1d_filter (&height, reconstruct_y, sample_y, sy, subsample_y); + + *n_values = 4 + width * subsample_x + height * subsample_y; + + params = malloc (*n_values * sizeof (pixman_fixed_t)); + + params[0] = pixman_int_to_fixed (width); + params[1] = pixman_int_to_fixed (height); + params[2] = pixman_int_to_fixed (subsample_bits_x); + params[3] = pixman_int_to_fixed (subsample_bits_y); + + memcpy (params + 4, horz, + width * subsample_x * sizeof (pixman_fixed_t)); + memcpy (params + 4 + width * subsample_x, vert, + height * subsample_y * sizeof (pixman_fixed_t)); + + free (horz); + free (vert); + + return params; +} diff --git a/pixman/pixman/pixman-image.c b/pixman/pixman/pixman-image.c index d9c303441..6f076d5c6 100644 --- a/pixman/pixman/pixman-image.c +++ b/pixman/pixman/pixman-image.c @@ -373,6 +373,10 @@ compute_image_info (pixman_image_t *image) case PIXMAN_FILTER_CONVOLUTION: break; + case PIXMAN_FILTER_SEPARABLE_CONVOLUTION: + flags |= FAST_PATH_SEPARABLE_CONVOLUTION_FILTER; + break; + default: flags |= FAST_PATH_NO_CONVOLUTION_FILTER; break; @@ -515,8 +519,9 @@ compute_image_info (pixman_image_t *image) * if all channels are opaque, so we simply turn it off * unconditionally for those images. */ - if (image->common.alpha_map || - image->common.filter == PIXMAN_FILTER_CONVOLUTION || + if (image->common.alpha_map || + image->common.filter == PIXMAN_FILTER_CONVOLUTION || + image->common.filter == PIXMAN_FILTER_SEPARABLE_CONVOLUTION || image->common.component_alpha) { flags &= ~(FAST_PATH_IS_OPAQUE | FAST_PATH_SAMPLES_OPAQUE); @@ -679,6 +684,19 @@ pixman_image_set_filter (pixman_image_t * image, if (params == common->filter_params && filter == common->filter) return TRUE; + if (filter == PIXMAN_FILTER_SEPARABLE_CONVOLUTION) + { + int width = pixman_fixed_to_int (params[0]); + int height = pixman_fixed_to_int (params[1]); + int x_phase_bits = pixman_fixed_to_int (params[2]); + int y_phase_bits = pixman_fixed_to_int (params[3]); + int n_x_phases = (1 << x_phase_bits); + int n_y_phases = (1 << y_phase_bits); + + return_val_if_fail ( + n_params == 4 + n_x_phases * width + n_y_phases * height, FALSE); + } + new_params = NULL; if (params) { diff --git a/pixman/pixman/pixman-private.h b/pixman/pixman/pixman-private.h index c0a6bc0a5..99125a17e 100644 --- a/pixman/pixman/pixman-private.h +++ b/pixman/pixman/pixman-private.h @@ -687,6 +687,7 @@ _pixman_iter_get_scanline_noop (pixman_iter_t *iter, const uint32_t *mask); #define FAST_PATH_SAMPLES_COVER_CLIP_NEAREST (1 << 23) #define FAST_PATH_SAMPLES_COVER_CLIP_BILINEAR (1 << 24) #define FAST_PATH_BITS_IMAGE (1 << 25) +#define FAST_PATH_SEPARABLE_CONVOLUTION_FILTER (1 << 26) #define FAST_PATH_PAD_REPEAT \ (FAST_PATH_NO_NONE_REPEAT | \ diff --git a/pixman/pixman/pixman.c b/pixman/pixman/pixman.c index e0ccd87d8..0661f41b0 100644 --- a/pixman/pixman/pixman.c +++ b/pixman/pixman/pixman.c @@ -455,6 +455,14 @@ analyze_extent (pixman_image_t *image, height = params[1]; break; + case PIXMAN_FILTER_SEPARABLE_CONVOLUTION: + params = image->common.filter_params; + x_off = - pixman_fixed_e - ((params[0] - pixman_fixed_1) >> 1); + y_off = - pixman_fixed_e - ((params[1] - pixman_fixed_1) >> 1); + width = params[0]; + height = params[1]; + break; + case PIXMAN_FILTER_GOOD: case PIXMAN_FILTER_BEST: case PIXMAN_FILTER_BILINEAR: diff --git a/pixman/pixman/pixman.h b/pixman/pixman/pixman.h index 33ebf3f64..7ff9fb52a 100644 --- a/pixman/pixman/pixman.h +++ b/pixman/pixman/pixman.h @@ -292,7 +292,28 @@ typedef enum PIXMAN_FILTER_BEST, PIXMAN_FILTER_NEAREST, PIXMAN_FILTER_BILINEAR, - PIXMAN_FILTER_CONVOLUTION + PIXMAN_FILTER_CONVOLUTION, + + /* The SEPARABLE_CONVOLUTION filter takes the following parameters: + * + * width: integer given as 16.16 fixpoint number + * height: integer given as 16.16 fixpoint number + * x_phase_bits: integer given as 16.16 fixpoint + * y_phase_bits: integer given as 16.16 fixpoint + * xtables: (1 << x_phase_bits) tables of size width + * ytables: (1 << y_phase_bits) tables of size height + * + * When sampling at (x, y), the location is first rounded to one of + * n_x_phases * n_y_phases subpixel positions. These subpixel positions + * determine an xtable and a ytable to use. + * + * Conceptually a width x height matrix is then formed in which each entry + * is the product of the corresponding entries in the x and y tables. + * This matrix is then aligned with the image pixels such that its center + * is as close as possible to the subpixel location chosen earlier. Then + * the image is convolved with the matrix and the resulting pixel returned. + */ + PIXMAN_FILTER_SEPARABLE_CONVOLUTION } pixman_filter_t; typedef enum @@ -810,6 +831,33 @@ int pixman_image_get_height (pixman_image_t int pixman_image_get_stride (pixman_image_t *image); /* in bytes */ int pixman_image_get_depth (pixman_image_t *image); pixman_format_code_t pixman_image_get_format (pixman_image_t *image); + +typedef enum +{ + PIXMAN_KERNEL_IMPULSE, + PIXMAN_KERNEL_BOX, + PIXMAN_KERNEL_LINEAR, + PIXMAN_KERNEL_CUBIC, + PIXMAN_KERNEL_GAUSSIAN, + PIXMAN_KERNEL_LANCZOS2, + PIXMAN_KERNEL_LANCZOS3, + PIXMAN_KERNEL_LANCZOS3_STRETCHED /* Jim Blinn's 'nice' filter */ +} pixman_kernel_t; + +/* Create the parameter list for a SEPARABLE_CONVOLUTION filter + * with the given kernels and scale parameters. + */ +pixman_fixed_t * +pixman_filter_create_separable_convolution (int *n_values, + pixman_fixed_t scale_x, + pixman_fixed_t scale_y, + pixman_kernel_t reconstruct_x, + pixman_kernel_t reconstruct_y, + pixman_kernel_t sample_x, + pixman_kernel_t sample_y, + int subsample_bits_x, + int subsample_bits_y); + pixman_bool_t pixman_image_fill_rectangles (pixman_op_t op, pixman_image_t *image, const pixman_color_t *color, diff --git a/pixman/pixman/rounding.txt b/pixman/pixman/rounding.txt index 1a19f450f..b52b08439 100644 --- a/pixman/pixman/rounding.txt +++ b/pixman/pixman/rounding.txt @@ -132,3 +132,36 @@ And so the final formula for the index k of x0 in the image is: Computing the result is then simply a matter of convolving all the pixels starting at k with all the samples in the matrix. + + +--- SEPARABLE_CONVOLUTION + +For this filter, x is first rounded to one of n regularly spaced +subpixel positions. This subpixel position determines which of n +convolution matrices is being used. + +Then, as in a regular convolution filter, the first pixel to be used +is determined: + + k = floor (x - (width - 1) / 2.0 - e) + +and then the image pixels starting there are convolved with the chosen +matrix. If we write x = xi + frac, where xi is an integer, we get + + k = xi + floor (frac - (width - 1) / 2.0 - e) + +so the location of k relative to x is given by: + + (k + 0.5 - x) = xi + floor (frac - (width - 1) / 2.0 - e) + 0.5 - x + + = floor (frac - (width - 1) / 2.0 - e) + 0.5 - frac + +which means the contents of the matrix corresponding to (frac) should +contain width samplings of the function, with the first sample at: + + floor (frac - (width - 1) / 2.0 - e) + 0.5 - frac + +This filter is called separable because each of the k x k convolution +matrices is specified with two k-wide vectors, one for each dimension, +where each entry in the matrix is computed as the product of the +corresponding entries in the vectors. diff --git a/pixman/test/Makefile.sources b/pixman/test/Makefile.sources index 077897161..8c0b505df 100644 --- a/pixman/test/Makefile.sources +++ b/pixman/test/Makefile.sources @@ -1,5 +1,6 @@ # Tests (sorted by expected completion time) TESTPROGRAMS = \ + prng-test \ a1-trap-test \ pdf-op-test \ region-test \ @@ -33,8 +34,10 @@ BENCHMARKS = \ # Utility functions libutils_sources = \ utils.c \ + utils-prng.c \ $(NULL) libutils_headers = \ utils.h \ + utils-prng.h \ $(NULL) diff --git a/pixman/test/affine-test.c b/pixman/test/affine-test.c index daa86c81d..f60ec14eb 100644 --- a/pixman/test/affine-test.c +++ b/pixman/test/affine-test.c @@ -48,18 +48,18 @@ test_composite (int testnum, uint32_t crc32; FLOAT_REGS_CORRUPTION_DETECTOR_START (); - lcg_srand (testnum); + prng_srand (testnum); - src_bpp = (lcg_rand_n (2) == 0) ? 2 : 4; - dst_bpp = (lcg_rand_n (2) == 0) ? 2 : 4; - op = (lcg_rand_n (2) == 0) ? PIXMAN_OP_SRC : PIXMAN_OP_OVER; + src_bpp = (prng_rand_n (2) == 0) ? 2 : 4; + dst_bpp = (prng_rand_n (2) == 0) ? 2 : 4; + op = (prng_rand_n (2) == 0) ? PIXMAN_OP_SRC : PIXMAN_OP_OVER; - src_width = lcg_rand_n (MAX_SRC_WIDTH) + 1; - src_height = lcg_rand_n (MAX_SRC_HEIGHT) + 1; - dst_width = lcg_rand_n (MAX_DST_WIDTH) + 1; - dst_height = lcg_rand_n (MAX_DST_HEIGHT) + 1; - src_stride = src_width * src_bpp + lcg_rand_n (MAX_STRIDE) * src_bpp; - dst_stride = dst_width * dst_bpp + lcg_rand_n (MAX_STRIDE) * dst_bpp; + src_width = prng_rand_n (MAX_SRC_WIDTH) + 1; + src_height = prng_rand_n (MAX_SRC_HEIGHT) + 1; + dst_width = prng_rand_n (MAX_DST_WIDTH) + 1; + dst_height = prng_rand_n (MAX_DST_HEIGHT) + 1; + src_stride = src_width * src_bpp + prng_rand_n (MAX_STRIDE) * src_bpp; + dst_stride = dst_width * dst_bpp + prng_rand_n (MAX_STRIDE) * dst_bpp; if (src_stride & 3) src_stride += 2; @@ -67,26 +67,23 @@ test_composite (int testnum, if (dst_stride & 3) dst_stride += 2; - src_x = -(src_width / 4) + lcg_rand_n (src_width * 3 / 2); - src_y = -(src_height / 4) + lcg_rand_n (src_height * 3 / 2); - dst_x = -(dst_width / 4) + lcg_rand_n (dst_width * 3 / 2); - dst_y = -(dst_height / 4) + lcg_rand_n (dst_height * 3 / 2); - w = lcg_rand_n (dst_width * 3 / 2 - dst_x); - h = lcg_rand_n (dst_height * 3 / 2 - dst_y); + src_x = -(src_width / 4) + prng_rand_n (src_width * 3 / 2); + src_y = -(src_height / 4) + prng_rand_n (src_height * 3 / 2); + dst_x = -(dst_width / 4) + prng_rand_n (dst_width * 3 / 2); + dst_y = -(dst_height / 4) + prng_rand_n (dst_height * 3 / 2); + w = prng_rand_n (dst_width * 3 / 2 - dst_x); + h = prng_rand_n (dst_height * 3 / 2 - dst_y); srcbuf = (uint32_t *)malloc (src_stride * src_height); dstbuf = (uint32_t *)malloc (dst_stride * dst_height); - for (i = 0; i < src_stride * src_height; i++) - *((uint8_t *)srcbuf + i) = lcg_rand_n (256); + prng_randmemset (srcbuf, src_stride * src_height, 0); + prng_randmemset (dstbuf, dst_stride * dst_height, 0); - for (i = 0; i < dst_stride * dst_height; i++) - *((uint8_t *)dstbuf + i) = lcg_rand_n (256); - - src_fmt = src_bpp == 4 ? (lcg_rand_n (2) == 0 ? + src_fmt = src_bpp == 4 ? (prng_rand_n (2) == 0 ? PIXMAN_a8r8g8b8 : PIXMAN_x8r8g8b8) : PIXMAN_r5g6b5; - dst_fmt = dst_bpp == 4 ? (lcg_rand_n (2) == 0 ? + dst_fmt = dst_bpp == 4 ? (prng_rand_n (2) == 0 ? PIXMAN_a8r8g8b8 : PIXMAN_x8r8g8b8) : PIXMAN_r5g6b5; src_img = pixman_image_create_bits ( @@ -100,29 +97,29 @@ test_composite (int testnum, pixman_transform_init_identity (&transform); - if (lcg_rand_n (3) > 0) + if (prng_rand_n (3) > 0) { - scale_x = -65536 * 3 + lcg_rand_N (65536 * 6); - if (lcg_rand_n (2)) - scale_y = -65536 * 3 + lcg_rand_N (65536 * 6); + scale_x = -65536 * 3 + prng_rand_n (65536 * 6); + if (prng_rand_n (2)) + scale_y = -65536 * 3 + prng_rand_n (65536 * 6); else scale_y = scale_x; pixman_transform_init_scale (&transform, scale_x, scale_y); } - if (lcg_rand_n (3) > 0) + if (prng_rand_n (3) > 0) { - translate_x = -65536 * 3 + lcg_rand_N (6 * 65536); - if (lcg_rand_n (2)) - translate_y = -65536 * 3 + lcg_rand_N (6 * 65536); + translate_x = -65536 * 3 + prng_rand_n (6 * 65536); + if (prng_rand_n (2)) + translate_y = -65536 * 3 + prng_rand_n (6 * 65536); else translate_y = translate_x; pixman_transform_translate (&transform, NULL, translate_x, translate_y); } - if (lcg_rand_n (4) > 0) + if (prng_rand_n (4) > 0) { int c, s, tx = 0, ty = 0; - switch (lcg_rand_n (4)) + switch (prng_rand_n (4)) { case 0: /* 90 degrees */ @@ -145,32 +142,32 @@ test_composite (int testnum, break; default: /* arbitrary rotation */ - c = lcg_rand_N (2 * 65536) - 65536; - s = lcg_rand_N (2 * 65536) - 65536; + c = prng_rand_n (2 * 65536) - 65536; + s = prng_rand_n (2 * 65536) - 65536; break; } pixman_transform_rotate (&transform, NULL, c, s); pixman_transform_translate (&transform, NULL, tx, ty); } - if (lcg_rand_n (8) == 0) + if (prng_rand_n (8) == 0) { /* Flip random bits */ int maxflipcount = 8; while (maxflipcount--) { - int i = lcg_rand_n (2); - int j = lcg_rand_n (3); - int bitnum = lcg_rand_n (32); + int i = prng_rand_n (2); + int j = prng_rand_n (3); + int bitnum = prng_rand_n (32); transform.matrix[i][j] ^= 1 << bitnum; - if (lcg_rand_n (2)) + if (prng_rand_n (2)) break; } } pixman_image_set_transform (src_img, &transform); - switch (lcg_rand_n (4)) + switch (prng_rand_n (4)) { case 0: repeat = PIXMAN_REPEAT_NONE; @@ -193,7 +190,7 @@ test_composite (int testnum, } pixman_image_set_repeat (src_img, repeat); - if (lcg_rand_n (2)) + if (prng_rand_n (2)) pixman_image_set_filter (src_img, PIXMAN_FILTER_NEAREST, NULL, 0); else pixman_image_set_filter (src_img, PIXMAN_FILTER_BILINEAR, NULL, 0); @@ -220,19 +217,19 @@ test_composite (int testnum, printf ("w=%d, h=%d\n", w, h); } - if (lcg_rand_n (8) == 0) + if (prng_rand_n (8) == 0) { pixman_box16_t clip_boxes[2]; - int n = lcg_rand_n (2) + 1; + int n = prng_rand_n (2) + 1; for (i = 0; i < n; i++) { - clip_boxes[i].x1 = lcg_rand_n (src_width); - clip_boxes[i].y1 = lcg_rand_n (src_height); + clip_boxes[i].x1 = prng_rand_n (src_width); + clip_boxes[i].y1 = prng_rand_n (src_height); clip_boxes[i].x2 = - clip_boxes[i].x1 + lcg_rand_n (src_width - clip_boxes[i].x1); + clip_boxes[i].x1 + prng_rand_n (src_width - clip_boxes[i].x1); clip_boxes[i].y2 = - clip_boxes[i].y1 + lcg_rand_n (src_height - clip_boxes[i].y1); + clip_boxes[i].y1 + prng_rand_n (src_height - clip_boxes[i].y1); if (verbose) { @@ -248,18 +245,18 @@ test_composite (int testnum, pixman_region_fini (&clip); } - if (lcg_rand_n (8) == 0) + if (prng_rand_n (8) == 0) { pixman_box16_t clip_boxes[2]; - int n = lcg_rand_n (2) + 1; + int n = prng_rand_n (2) + 1; for (i = 0; i < n; i++) { - clip_boxes[i].x1 = lcg_rand_n (dst_width); - clip_boxes[i].y1 = lcg_rand_n (dst_height); + clip_boxes[i].x1 = prng_rand_n (dst_width); + clip_boxes[i].y1 = prng_rand_n (dst_height); clip_boxes[i].x2 = - clip_boxes[i].x1 + lcg_rand_n (dst_width - clip_boxes[i].x1); + clip_boxes[i].x1 + prng_rand_n (dst_width - clip_boxes[i].x1); clip_boxes[i].y2 = - clip_boxes[i].y1 + lcg_rand_n (dst_height - clip_boxes[i].y1); + clip_boxes[i].y1 + prng_rand_n (dst_height - clip_boxes[i].y1); if (verbose) { @@ -310,11 +307,11 @@ test_composite (int testnum, } #if BILINEAR_INTERPOLATION_BITS == 8 -#define CHECKSUM 0x344413F0 +#define CHECKSUM 0x97097336 #elif BILINEAR_INTERPOLATION_BITS == 7 -#define CHECKSUM 0xC8181A76 +#define CHECKSUM 0x31D2DC21 #elif BILINEAR_INTERPOLATION_BITS == 4 -#define CHECKSUM 0xD672A457 +#define CHECKSUM 0x8B925154 #else #define CHECKSUM 0x00000000 #endif diff --git a/pixman/test/alpha-loop.c b/pixman/test/alpha-loop.c index e4d90a988..eca761537 100644 --- a/pixman/test/alpha-loop.c +++ b/pixman/test/alpha-loop.c @@ -8,9 +8,14 @@ int main (int argc, char **argv) { - uint8_t *alpha = make_random_bytes (WIDTH * HEIGHT); - uint32_t *src = (uint32_t *)make_random_bytes (WIDTH * HEIGHT * 4); - uint32_t *dest = (uint32_t *)make_random_bytes (WIDTH * HEIGHT * 4); + uint8_t *alpha; + uint32_t *src, *dest; + + prng_srand (0); + + alpha = make_random_bytes (WIDTH * HEIGHT); + 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); diff --git a/pixman/test/alphamap.c b/pixman/test/alphamap.c index 0c5757ea3..1a6fca55a 100644 --- a/pixman/test/alphamap.c +++ b/pixman/test/alphamap.c @@ -307,6 +307,8 @@ main (int argc, char **argv) { int i, j, a, b, x, y; + prng_srand (0); + for (i = 0; i < ARRAY_LENGTH (formats); ++i) { for (j = 0; j < ARRAY_LENGTH (formats); ++j) diff --git a/pixman/test/blitters-test.c b/pixman/test/blitters-test.c index 30d69124c..9bde99c62 100644 --- a/pixman/test/blitters-test.c +++ b/pixman/test/blitters-test.c @@ -25,7 +25,7 @@ create_random_image (pixman_format_code_t *allowed_formats, int max_extra_stride, pixman_format_code_t *used_fmt) { - int n = 0, i, width, height, stride; + int n = 0, width, height, stride; pixman_format_code_t fmt; uint32_t *buf; pixman_image_t *img; @@ -33,28 +33,20 @@ create_random_image (pixman_format_code_t *allowed_formats, while (allowed_formats[n] != PIXMAN_null) n++; - if (n > N_MOST_LIKELY_FORMATS && lcg_rand_n (4) != 0) + if (n > N_MOST_LIKELY_FORMATS && prng_rand_n (4) != 0) n = N_MOST_LIKELY_FORMATS; - fmt = allowed_formats[lcg_rand_n (n)]; + fmt = allowed_formats[prng_rand_n (n)]; - width = lcg_rand_n (max_width) + 1; - height = lcg_rand_n (max_height) + 1; + width = prng_rand_n (max_width) + 1; + height = prng_rand_n (max_height) + 1; stride = (width * PIXMAN_FORMAT_BPP (fmt) + 7) / 8 + - lcg_rand_n (max_extra_stride + 1); + prng_rand_n (max_extra_stride + 1); stride = (stride + 3) & ~3; /* do the allocation */ buf = aligned_malloc (64, stride * height); - /* initialize image with random data */ - for (i = 0; i < stride * height; i++) - { - /* generation is biased to having more 0 or 255 bytes as - * they are more likely to be special-cased in code - */ - *((uint8_t *)buf + i) = lcg_rand_n (4) ? lcg_rand_n (256) : - (lcg_rand_n (2) ? 0 : 255); - } + prng_randmemset (buf, stride * height, RANDMEMSET_MORE_00_AND_FF); img = pixman_image_create_bits (fmt, width, height, buf, stride); @@ -67,7 +59,7 @@ create_random_image (pixman_format_code_t *allowed_formats, pixman_image_set_indexed (img, &(y_palette[PIXMAN_FORMAT_BPP (fmt)])); } - if (lcg_rand_n (16) == 0) + if (prng_rand_n (16) == 0) pixman_image_set_filter (img, PIXMAN_FILTER_BILINEAR, NULL, 0); image_endian_swap (img); @@ -251,11 +243,11 @@ test_composite (int testnum, int verbose) if (max_extra_stride > 8) max_extra_stride = 8; - lcg_srand (testnum); + prng_srand (testnum); - op = op_list[lcg_rand_n (ARRAY_LENGTH (op_list))]; + op = op_list[prng_rand_n (ARRAY_LENGTH (op_list))]; - if (lcg_rand_n (8)) + if (prng_rand_n (8)) { /* normal image */ src_img = create_random_image (img_fmt_list, max_width, max_height, @@ -284,10 +276,10 @@ test_composite (int testnum, int verbose) dstbuf = pixman_image_get_data (dst_img); srcbuf = pixman_image_get_data (src_img); - src_x = lcg_rand_n (src_width); - src_y = lcg_rand_n (src_height); - dst_x = lcg_rand_n (dst_width); - dst_y = lcg_rand_n (dst_height); + src_x = prng_rand_n (src_width); + src_y = prng_rand_n (src_height); + dst_x = prng_rand_n (dst_width); + dst_y = prng_rand_n (dst_height); mask_img = NULL; mask_fmt = PIXMAN_null; @@ -296,10 +288,10 @@ test_composite (int testnum, int verbose) maskbuf = NULL; if ((src_fmt == PIXMAN_x8r8g8b8 || src_fmt == PIXMAN_x8b8g8r8) && - (lcg_rand_n (4) == 0)) + (prng_rand_n (4) == 0)) { /* PIXBUF */ - mask_fmt = lcg_rand_n (2) ? PIXMAN_a8r8g8b8 : PIXMAN_a8b8g8r8; + mask_fmt = prng_rand_n (2) ? PIXMAN_a8r8g8b8 : PIXMAN_a8b8g8r8; mask_img = pixman_image_create_bits (mask_fmt, src_width, src_height, @@ -309,9 +301,9 @@ test_composite (int testnum, int verbose) mask_y = src_y; maskbuf = srcbuf; } - else if (lcg_rand_n (2)) + else if (prng_rand_n (2)) { - if (lcg_rand_n (2)) + if (prng_rand_n (2)) { mask_img = create_random_image (mask_fmt_list, max_width, max_height, max_extra_stride, &mask_fmt); @@ -324,16 +316,16 @@ test_composite (int testnum, int verbose) pixman_image_set_repeat (mask_img, PIXMAN_REPEAT_NORMAL); } - if (lcg_rand_n (2)) + if (prng_rand_n (2)) pixman_image_set_component_alpha (mask_img, 1); - mask_x = lcg_rand_n (pixman_image_get_width (mask_img)); - mask_y = lcg_rand_n (pixman_image_get_height (mask_img)); + mask_x = prng_rand_n (pixman_image_get_width (mask_img)); + mask_y = prng_rand_n (pixman_image_get_height (mask_img)); } - w = lcg_rand_n (dst_width - dst_x + 1); - h = lcg_rand_n (dst_height - dst_y + 1); + w = prng_rand_n (dst_width - dst_x + 1); + h = prng_rand_n (dst_height - dst_y + 1); if (verbose) { @@ -390,6 +382,8 @@ main (int argc, const char *argv[]) { int i; + prng_srand (0); + for (i = 1; i <= 8; i++) { initialize_palette (&(rgb_palette[i]), i, TRUE); @@ -397,6 +391,6 @@ main (int argc, const char *argv[]) } return fuzzer_test_main("blitters", 2000000, - 0x46136E0A, + 0xD8265D5E, test_composite, argc, argv); } diff --git a/pixman/test/combiner-test.c b/pixman/test/combiner-test.c index c438ae62e..01f63a56e 100644 --- a/pixman/test/combiner-test.c +++ b/pixman/test/combiner-test.c @@ -67,7 +67,7 @@ static const pixman_op_t op_list[] = static float rand_float (void) { - uint32_t u = lcg_rand_u32(); + uint32_t u = prng_rand(); return *(float *)&u; } @@ -123,7 +123,7 @@ main () impl = _pixman_internal_only_get_implementation(); - lcg_srand (0); + prng_srand (0); for (i = 0; i < ARRAY_LENGTH (op_list); ++i) { diff --git a/pixman/test/composite-traps-test.c b/pixman/test/composite-traps-test.c index 9fc94a4d6..2983eae83 100644 --- a/pixman/test/composite-traps-test.c +++ b/pixman/test/composite-traps-test.c @@ -26,7 +26,7 @@ static pixman_op_t operators[] = }; #define RANDOM_ELT(array) \ - ((array)[lcg_rand_n(ARRAY_LENGTH((array)))]) + ((array)[prng_rand_n(ARRAY_LENGTH((array)))]) static void destroy_bits (pixman_image_t *image, void *data) @@ -37,7 +37,7 @@ destroy_bits (pixman_image_t *image, void *data) static pixman_fixed_t random_fixed (int n) { - return lcg_rand_N (n << 16); + return prng_rand_n (n << 16); } /* @@ -75,17 +75,17 @@ test_composite (int testnum, FLOAT_REGS_CORRUPTION_DETECTOR_START (); - lcg_srand (testnum); + prng_srand (testnum); op = RANDOM_ELT (operators); mask_format = RANDOM_ELT (mask_formats); /* Create source image */ - if (lcg_rand_n (4) == 0) + if (prng_rand_n (4) == 0) { src_img = pixman_image_create_solid_fill ( - &(colors[lcg_rand_n (ARRAY_LENGTH (colors))])); + &(colors[prng_rand_n (ARRAY_LENGTH (colors))])); src_x = 10; src_y = 234; @@ -94,13 +94,13 @@ test_composite (int testnum, { pixman_format_code_t src_format = RANDOM_ELT(formats); int src_bpp = (PIXMAN_FORMAT_BPP (src_format) + 7) / 8; - int src_width = lcg_rand_n (MAX_SRC_WIDTH) + 1; - int src_height = lcg_rand_n (MAX_SRC_HEIGHT) + 1; - int src_stride = src_width * src_bpp + lcg_rand_n (MAX_STRIDE) * src_bpp; + int src_width = prng_rand_n (MAX_SRC_WIDTH) + 1; + int src_height = prng_rand_n (MAX_SRC_HEIGHT) + 1; + int src_stride = src_width * src_bpp + prng_rand_n (MAX_STRIDE) * src_bpp; uint32_t *bits; - src_x = -(src_width / 4) + lcg_rand_n (src_width * 3 / 2); - src_y = -(src_height / 4) + lcg_rand_n (src_height * 3 / 2); + src_x = -(src_width / 4) + prng_rand_n (src_width * 3 / 2); + src_y = -(src_height / 4) + prng_rand_n (src_height * 3 / 2); src_stride = (src_stride + 3) & ~3; @@ -111,19 +111,19 @@ test_composite (int testnum, pixman_image_set_destroy_function (src_img, destroy_bits, bits); - if (lcg_rand_n (8) == 0) + if (prng_rand_n (8) == 0) { pixman_box16_t clip_boxes[2]; - int n = lcg_rand_n (2) + 1; + int n = prng_rand_n (2) + 1; for (i = 0; i < n; i++) { - clip_boxes[i].x1 = lcg_rand_n (src_width); - clip_boxes[i].y1 = lcg_rand_n (src_height); + clip_boxes[i].x1 = prng_rand_n (src_width); + clip_boxes[i].y1 = prng_rand_n (src_height); clip_boxes[i].x2 = - clip_boxes[i].x1 + lcg_rand_n (src_width - clip_boxes[i].x1); + clip_boxes[i].x1 + prng_rand_n (src_width - clip_boxes[i].x1); clip_boxes[i].y2 = - clip_boxes[i].y1 + lcg_rand_n (src_height - clip_boxes[i].y1); + clip_boxes[i].y1 + prng_rand_n (src_height - clip_boxes[i].y1); if (verbose) { @@ -146,15 +146,15 @@ test_composite (int testnum, { dst_format = RANDOM_ELT(formats); dst_bpp = (PIXMAN_FORMAT_BPP (dst_format) + 7) / 8; - dst_width = lcg_rand_n (MAX_DST_WIDTH) + 1; - dst_height = lcg_rand_n (MAX_DST_HEIGHT) + 1; - dst_stride = dst_width * dst_bpp + lcg_rand_n (MAX_STRIDE) * dst_bpp; + dst_width = prng_rand_n (MAX_DST_WIDTH) + 1; + dst_height = prng_rand_n (MAX_DST_HEIGHT) + 1; + dst_stride = dst_width * dst_bpp + prng_rand_n (MAX_STRIDE) * dst_bpp; dst_stride = (dst_stride + 3) & ~3; dst_bits = (uint32_t *)make_random_bytes (dst_stride * dst_height); - dst_x = -(dst_width / 4) + lcg_rand_n (dst_width * 3 / 2); - dst_y = -(dst_height / 4) + lcg_rand_n (dst_height * 3 / 2); + dst_x = -(dst_width / 4) + prng_rand_n (dst_width * 3 / 2); + dst_y = -(dst_height / 4) + prng_rand_n (dst_height * 3 / 2); dst_img = pixman_image_create_bits ( dst_format, dst_width, dst_height, dst_bits, dst_stride); @@ -166,7 +166,7 @@ test_composite (int testnum, { int i; - n_traps = lcg_rand_n (25); + n_traps = prng_rand_n (25); traps = fence_malloc (n_traps * sizeof (pixman_trapezoid_t)); for (i = 0; i < n_traps; ++i) @@ -186,18 +186,18 @@ test_composite (int testnum, } } - if (lcg_rand_n (8) == 0) + if (prng_rand_n (8) == 0) { pixman_box16_t clip_boxes[2]; - int n = lcg_rand_n (2) + 1; + int n = prng_rand_n (2) + 1; for (i = 0; i < n; i++) { - clip_boxes[i].x1 = lcg_rand_n (dst_width); - clip_boxes[i].y1 = lcg_rand_n (dst_height); + clip_boxes[i].x1 = prng_rand_n (dst_width); + clip_boxes[i].y1 = prng_rand_n (dst_height); clip_boxes[i].x2 = - clip_boxes[i].x1 + lcg_rand_n (dst_width - clip_boxes[i].x1); + clip_boxes[i].x1 + prng_rand_n (dst_width - clip_boxes[i].x1); clip_boxes[i].y2 = - clip_boxes[i].y1 + lcg_rand_n (dst_height - clip_boxes[i].y1); + clip_boxes[i].y1 + prng_rand_n (dst_height - clip_boxes[i].y1); if (verbose) { @@ -251,6 +251,6 @@ test_composite (int testnum, int main (int argc, const char *argv[]) { - return fuzzer_test_main("composite traps", 40000, 0x33BFAA55, + return fuzzer_test_main("composite traps", 40000, 0x749BCC57, test_composite, argc, argv); } diff --git a/pixman/test/composite.c b/pixman/test/composite.c index 2930fb75b..09752c5c7 100644 --- a/pixman/test/composite.c +++ b/pixman/test/composite.c @@ -725,19 +725,19 @@ image_fini (image_t *info) static int random_size (void) { - return lcg_rand_n (ARRAY_LENGTH (sizes)); + return prng_rand_n (ARRAY_LENGTH (sizes)); } static int random_color (void) { - return lcg_rand_n (ARRAY_LENGTH (colors)); + return prng_rand_n (ARRAY_LENGTH (colors)); } static int random_format (void) { - return lcg_rand_n (ARRAY_LENGTH (formats)); + return prng_rand_n (ARRAY_LENGTH (formats)); } static pixman_bool_t @@ -748,15 +748,15 @@ run_test (uint32_t seed) int ca; int ok; - lcg_srand (seed); + prng_srand (seed); image_init (&dst, random_color(), random_format(), 1); image_init (&src, random_color(), random_format(), random_size()); image_init (&mask, random_color(), random_format(), random_size()); - op = &(operators [lcg_rand_n (ARRAY_LENGTH (operators))]); + op = &(operators [prng_rand_n (ARRAY_LENGTH (operators))]); - ca = lcg_rand_n (3); + ca = prng_rand_n (3); switch (ca) { diff --git a/pixman/test/glyph-test.c b/pixman/test/glyph-test.c index 501cc2e6f..1811add73 100644 --- a/pixman/test/glyph-test.c +++ b/pixman/test/glyph-test.c @@ -107,7 +107,7 @@ random_format (const pixman_format_code_t *formats) i = 0; while (formats[i] != PIXMAN_null) ++i; - return formats[lcg_rand_n (i)]; + return formats[prng_rand_n (i)]; } static pixman_image_t * @@ -122,27 +122,27 @@ create_image (int max_size, const pixman_format_code_t *formats, uint32_t flags) int i; pixman_image_destroy_func_t destroy; - if ((flags & ALLOW_SOLID) && lcg_rand_n (4) == 0) + if ((flags & ALLOW_SOLID) && prng_rand_n (4) == 0) { pixman_color_t color; - color.alpha = lcg_rand_u32(); - color.red = lcg_rand_u32(); - color.green = lcg_rand_u32(); - color.blue = lcg_rand_u32(); + color.alpha = prng_rand(); + color.red = prng_rand(); + color.green = prng_rand(); + color.blue = prng_rand(); return pixman_image_create_solid_fill (&color); } - width = lcg_rand_n (max_size) + 1; - height = lcg_rand_n (max_size) + 1; + width = prng_rand_n (max_size) + 1; + height = prng_rand_n (max_size) + 1; format = random_format (formats); bpp = PIXMAN_FORMAT_BPP (format); - stride = (width * bpp + 7) / 8 + lcg_rand_n (17); + stride = (width * bpp + 7) / 8 + prng_rand_n (17); stride = (stride + 3) & ~3; - if (lcg_rand_n (64) == 0) + if (prng_rand_n (64) == 0) { if (!(data = (uint32_t *)make_random_bytes (stride * height))) { @@ -153,34 +153,28 @@ create_image (int max_size, const pixman_format_code_t *formats, uint32_t flags) } else { - uint8_t *d8; - data = malloc (stride * height); - - d8 = (uint8_t *)data; - for (i = 0; i < height * stride; ++i) - d8[i] = lcg_rand_n (256); - + prng_randmemset (data, height * stride, 0); destroy = destroy_malloced; } image = pixman_image_create_bits (format, width, height, data, stride); pixman_image_set_destroy_function (image, destroy, data); - if ((flags & ALLOW_CLIPPED) && lcg_rand_n (8) == 0) + if ((flags & ALLOW_CLIPPED) && prng_rand_n (8) == 0) { pixman_box16_t clip_boxes[8]; pixman_region16_t clip; - int n = lcg_rand_n (8) + 1; + int n = prng_rand_n (8) + 1; for (i = 0; i < n; i++) { - clip_boxes[i].x1 = lcg_rand_n (width); - clip_boxes[i].y1 = lcg_rand_n (height); + clip_boxes[i].x1 = prng_rand_n (width); + clip_boxes[i].y1 = prng_rand_n (height); clip_boxes[i].x2 = - clip_boxes[i].x1 + lcg_rand_n (width - clip_boxes[i].x1); + clip_boxes[i].x1 + prng_rand_n (width - clip_boxes[i].x1); clip_boxes[i].y2 = - clip_boxes[i].y1 + lcg_rand_n (height - clip_boxes[i].y1); + clip_boxes[i].y1 + prng_rand_n (height - clip_boxes[i].y1); } pixman_region_init_rects (&clip, clip_boxes, n); @@ -188,27 +182,27 @@ create_image (int max_size, const pixman_format_code_t *formats, uint32_t flags) pixman_region_fini (&clip); } - if ((flags & ALLOW_SOURCE_CLIPPING) && lcg_rand_n (4) == 0) + if ((flags & ALLOW_SOURCE_CLIPPING) && prng_rand_n (4) == 0) { pixman_image_set_source_clipping (image, TRUE); pixman_image_set_has_client_clip (image, TRUE); } - if ((flags & ALLOW_ALPHA_MAP) && lcg_rand_n (16) == 0) + if ((flags & ALLOW_ALPHA_MAP) && prng_rand_n (16) == 0) { pixman_image_t *alpha_map; int alpha_x, alpha_y; - alpha_x = lcg_rand_n (width); - alpha_y = lcg_rand_n (height); + alpha_x = prng_rand_n (width); + alpha_y = prng_rand_n (height); alpha_map = create_image (max_size, formats, (flags & ~(ALLOW_ALPHA_MAP | ALLOW_SOLID))); pixman_image_set_alpha_map (image, alpha_map, alpha_x, alpha_y); pixman_image_unref (alpha_map); } - if ((flags & ALLOW_REPEAT) && lcg_rand_n (2) == 0) - pixman_image_set_repeat (image, lcg_rand_n (4)); + if ((flags & ALLOW_REPEAT) && prng_rand_n (2) == 0) + pixman_image_set_repeat (image, prng_rand_n (4)); image_endian_swap (image); @@ -230,7 +224,7 @@ test_glyphs (int testnum, int verbose) int n_glyphs, i; pixman_glyph_cache_t *cache; - lcg_srand (testnum); + prng_srand (testnum); cache = pixman_glyph_cache_create (); @@ -245,13 +239,13 @@ test_glyphs (int testnum, int verbose) pixman_glyph_cache_freeze (cache); - n_glyphs = lcg_rand_n (MAX_GLYPHS); + n_glyphs = prng_rand_n (MAX_GLYPHS); for (i = 0; i < n_glyphs; ++i) glyph_images[i] = create_image (32, glyph_formats, 0); for (i = 0; i < 4 * n_glyphs; ++i) { - int g = lcg_rand_n (n_glyphs); + int g = prng_rand_n (n_glyphs); pixman_image_t *glyph_img = glyph_images[g]; void *key1 = KEY1 (glyph_img); void *key2 = KEY2 (glyph_img); @@ -264,21 +258,21 @@ test_glyphs (int testnum, int verbose) } glyphs[i].glyph = glyph; - glyphs[i].x = lcg_rand_n (128); - glyphs[i].y = lcg_rand_n (128); + glyphs[i].x = prng_rand_n (128); + glyphs[i].y = prng_rand_n (128); } - if (lcg_rand_n (2) == 0) + if (prng_rand_n (2) == 0) { - int src_x = lcg_rand_n (300) - 150; - int src_y = lcg_rand_n (300) - 150; - int mask_x = lcg_rand_n (64) - 32; - int mask_y = lcg_rand_n (64) - 32; - int dest_x = lcg_rand_n (64) - 32; - int dest_y = lcg_rand_n (64) - 32; - int width = lcg_rand_n (64); - int height = lcg_rand_n (64); - pixman_op_t op = operators[lcg_rand_n (ARRAY_LENGTH (operators))]; + int src_x = prng_rand_n (300) - 150; + int src_y = prng_rand_n (300) - 150; + int mask_x = prng_rand_n (64) - 32; + int mask_y = prng_rand_n (64) - 32; + int dest_x = prng_rand_n (64) - 32; + int dest_y = prng_rand_n (64) - 32; + int width = prng_rand_n (64); + int height = prng_rand_n (64); + pixman_op_t op = operators[prng_rand_n (ARRAY_LENGTH (operators))]; pixman_format_code_t format = random_format (glyph_formats); pixman_composite_glyphs ( @@ -292,11 +286,11 @@ test_glyphs (int testnum, int verbose) } else { - pixman_op_t op = operators[lcg_rand_n (ARRAY_LENGTH (operators))]; - int src_x = lcg_rand_n (300) - 150; - int src_y = lcg_rand_n (300) - 150; - int dest_x = lcg_rand_n (64) - 32; - int dest_y = lcg_rand_n (64) - 32; + pixman_op_t op = operators[prng_rand_n (ARRAY_LENGTH (operators))]; + int src_x = prng_rand_n (300) - 150; + int src_y = prng_rand_n (300) - 150; + int dest_x = prng_rand_n (64) - 32; + int dest_y = prng_rand_n (64) - 32; pixman_composite_glyphs_no_mask ( op, source, dest, @@ -333,6 +327,6 @@ int main (int argc, const char *argv[]) { return fuzzer_test_main ("glyph", 30000, - 0x79E74996, + 0xFA478A79, test_glyphs, argc, argv); } diff --git a/pixman/test/prng-test.c b/pixman/test/prng-test.c new file mode 100644 index 000000000..0a3ad5e8f --- /dev/null +++ b/pixman/test/prng-test.c @@ -0,0 +1,172 @@ +/* + * Copyright © 2012 Siarhei Siamashka <siarhei.siamashka@gmail.com> + * + * Based on the public domain implementation of small noncryptographic PRNG + * authored by Bob Jenkins: http://burtleburtle.net/bob/rand/smallprng.html + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include <assert.h> +#include <stdlib.h> +#include "utils-prng.h" +#include "utils.h" + +/* The original code from http://www.burtleburtle.net/bob/rand/smallprng.html */ + +typedef uint32_t u4; +typedef struct ranctx { u4 a; u4 b; u4 c; u4 d; } ranctx; + +#define rot(x,k) (((x)<<(k))|((x)>>(32-(k)))) +u4 ranval( ranctx *x ) { + u4 e = x->a - rot(x->b, 27); + x->a = x->b ^ rot(x->c, 17); + x->b = x->c + x->d; + x->c = x->d + e; + x->d = e + x->a; + return x->d; +} + +void raninit( ranctx *x, u4 seed ) { + u4 i; + x->a = 0xf1ea5eed, x->b = x->c = x->d = seed; + for (i=0; i<20; ++i) { + (void)ranval(x); + } +} + +/*****************************************************************************/ + +#define BUFSIZE (8 * 1024 * 1024) +#define N 50 + +void bench (void) +{ + double t1, t2; + int i; + prng_t prng; + uint8_t *buf = aligned_malloc (16, BUFSIZE + 1); + + prng_srand_r (&prng, 1234); + t1 = gettime(); + for (i = 0; i < N; i++) + prng_randmemset_r (&prng, buf, BUFSIZE, 0); + t2 = gettime(); + printf ("aligned randmemset : %.2f MB/s\n", + (double)BUFSIZE * N / 1000000. / (t2 - t1)); + + t1 = gettime(); + for (i = 0; i < N; i++) + prng_randmemset_r (&prng, buf + 1, BUFSIZE, 0); + t2 = gettime(); + printf ("unaligned randmemset : %.2f MB/s\n", + (double)BUFSIZE * N / 1000000. / (t2 - t1)); + + t1 = gettime(); + for (i = 0; i < N; i++) + { + prng_randmemset_r (&prng, buf, BUFSIZE, RANDMEMSET_MORE_00_AND_FF); + } + t2 = gettime (); + printf ("aligned randmemset (more 00 and FF) : %.2f MB/s\n", + (double)BUFSIZE * N / 1000000. / (t2 - t1)); + + t1 = gettime(); + for (i = 0; i < N; i++) + { + prng_randmemset_r (&prng, buf + 1, BUFSIZE, RANDMEMSET_MORE_00_AND_FF); + } + t2 = gettime (); + printf ("unaligned randmemset (more 00 and FF) : %.2f MB/s\n", + (double)BUFSIZE * N / 1000000. / (t2 - t1)); + + free (buf); +} + +#define SMALLBUFSIZE 100 + +int main (int argc, char *argv[]) +{ + const uint32_t ref_crc[RANDMEMSET_MORE_00_AND_FF + 1] = + { + 0xBA06763D, 0x103FC550, 0x8B59ABA5, 0xD82A0F39 + }; + uint32_t crc1, crc2; + uint32_t ref, seed, seed0, seed1, seed2, seed3; + prng_rand_128_data_t buf; + uint8_t *bytebuf = aligned_malloc(16, SMALLBUFSIZE + 1); + ranctx x; + prng_t prng; + prng_randmemset_flags_t flags; + + if (argc > 1 && strcmp(argv[1], "-bench") == 0) + { + bench (); + return 0; + } + + /* basic test */ + raninit (&x, 0); + prng_srand_r (&prng, 0); + assert (ranval (&x) == prng_rand_r (&prng)); + + /* test for simd code */ + seed = 0; + prng_srand_r (&prng, seed); + seed0 = (seed = seed * 1103515245 + 12345); + seed1 = (seed = seed * 1103515245 + 12345); + seed2 = (seed = seed * 1103515245 + 12345); + seed3 = (seed = seed * 1103515245 + 12345); + prng_rand_128_r (&prng, &buf); + + raninit (&x, seed0); + ref = ranval (&x); + assert (ref == buf.w[0]); + + raninit (&x, seed1); + ref = ranval (&x); + assert (ref == buf.w[1]); + + raninit (&x, seed2); + ref = ranval (&x); + assert (ref == buf.w[2]); + + raninit (&x, seed3); + ref = ranval (&x); + assert (ref == buf.w[3]); + + /* test for randmemset */ + for (flags = 0; flags <= RANDMEMSET_MORE_00_AND_FF; flags++) + { + prng_srand_r (&prng, 1234); + prng_randmemset_r (&prng, bytebuf, 16, flags); + prng_randmemset_r (&prng, bytebuf + 16, SMALLBUFSIZE - 17, flags); + crc1 = compute_crc32 (0, bytebuf, SMALLBUFSIZE - 1); + prng_srand_r (&prng, 1234); + prng_randmemset_r (&prng, bytebuf + 1, SMALLBUFSIZE - 1, flags); + crc2 = compute_crc32 (0, bytebuf + 1, SMALLBUFSIZE - 1); + assert (ref_crc[flags] == crc1); + assert (ref_crc[flags] == crc2); + } + + free (bytebuf); + + return 0; +} diff --git a/pixman/test/region-contains-test.c b/pixman/test/region-contains-test.c index 9524e2888..096e65179 100644 --- a/pixman/test/region-contains-test.c +++ b/pixman/test/region-contains-test.c @@ -9,16 +9,16 @@ make_random_region (pixman_region32_t *region) pixman_region32_init (region); - n_boxes = lcg_rand_n (64); + n_boxes = prng_rand_n (64); while (n_boxes--) { int32_t x, y; uint32_t w, h; - x = (int32_t)lcg_rand_u32() >> 2; - y = (int32_t)lcg_rand_u32() >> 2; - w = lcg_rand_u32() >> 2; - h = lcg_rand_u32() >> 2; + x = (int32_t)prng_rand() >> 2; + y = (int32_t)prng_rand() >> 2; + w = prng_rand() >> 2; + h = prng_rand() >> 2; pixman_region32_union_rect (region, region, x, y, w, h); } @@ -37,12 +37,12 @@ random_coord (pixman_region32_t *region, pixman_bool_t x) int n_boxes; int begin, end; - if (lcg_rand_n (14)) + if (prng_rand_n (14)) { bb = pixman_region32_rectangles (region, &n_boxes); if (n_boxes == 0) goto use_extent; - b = bb + lcg_rand_n (n_boxes); + b = bb + prng_rand_n (n_boxes); } else { @@ -62,12 +62,12 @@ random_coord (pixman_region32_t *region, pixman_bool_t x) end = b->y2; } - switch (lcg_rand_n (5)) + switch (prng_rand_n (5)) { case 0: - return begin - lcg_rand_u32(); + return begin - prng_rand(); case 1: - return end + lcg_rand_u32 (); + return end + prng_rand (); case 2: return end; case 3: @@ -111,14 +111,14 @@ test_region_contains_rectangle (int i, int verbose) pixman_region32_t region; uint32_t r, r1, r2, r3, r4, crc32; - lcg_srand (i); + prng_srand (i); make_random_region (®ion); box.x1 = random_coord (®ion, TRUE); - box.x2 = box.x1 + lcg_rand_u32 (); + box.x2 = box.x1 + prng_rand (); box.y1 = random_coord (®ion, FALSE); - box.y2 = box.y1 + lcg_rand_u32 (); + box.y2 = box.y1 + prng_rand (); if (verbose) { @@ -163,7 +163,7 @@ main (int argc, const char *argv[]) { return fuzzer_test_main ("region_contains", 1000000, - 0xD2BF8C73, + 0x548E0F3F, test_region_contains_rectangle, argc, argv); } diff --git a/pixman/test/region-test.c b/pixman/test/region-test.c index 9d5a41eb9..bfc219bc7 100644 --- a/pixman/test/region-test.c +++ b/pixman/test/region-test.c @@ -32,6 +32,8 @@ main () 0xffff }; + prng_srand (0); + /* This used to go into an infinite loop before pixman-region.c * was fixed to not use explict "short" variables */ @@ -91,10 +93,10 @@ main () /* Add some random rectangles */ for (j = 0; j < 64; j++) pixman_region32_union_rect (&r1, &r1, - lcg_rand_n (image_size), - lcg_rand_n (image_size), - lcg_rand_n (25), - lcg_rand_n (25)); + prng_rand_n (image_size), + prng_rand_n (image_size), + prng_rand_n (25), + prng_rand_n (25)); /* Clip to image size */ pixman_region32_init_rect (&r2, 0, 0, image_size, image_size); diff --git a/pixman/test/rotate-test.c b/pixman/test/rotate-test.c index a0488ef22..9d2a620cb 100644 --- a/pixman/test/rotate-test.c +++ b/pixman/test/rotate-test.c @@ -43,13 +43,13 @@ static const pixman_transform_t transforms[] = }; #define RANDOM_FORMAT() \ - (formats[lcg_rand_n (ARRAY_LENGTH (formats))]) + (formats[prng_rand_n (ARRAY_LENGTH (formats))]) #define RANDOM_OP() \ - (ops[lcg_rand_n (ARRAY_LENGTH (ops))]) + (ops[prng_rand_n (ARRAY_LENGTH (ops))]) #define RANDOM_TRANSFORM() \ - (&(transforms[lcg_rand_n (ARRAY_LENGTH (transforms))])) + (&(transforms[prng_rand_n (ARRAY_LENGTH (transforms))])) static void on_destroy (pixman_image_t *image, void *data) @@ -63,10 +63,8 @@ make_image (void) pixman_format_code_t format = RANDOM_FORMAT(); uint32_t *bytes = malloc (WIDTH * HEIGHT * 4); pixman_image_t *image; - int i; - for (i = 0; i < WIDTH * HEIGHT * 4; ++i) - ((uint8_t *)bytes)[i] = lcg_rand_n (256); + prng_randmemset (bytes, WIDTH * HEIGHT * 4, 0); image = pixman_image_create_bits ( format, WIDTH, HEIGHT, bytes, WIDTH * 4); @@ -86,7 +84,7 @@ test_transform (int testnum, int verbose) pixman_image_t *src, *dest; uint32_t crc; - lcg_srand (testnum); + prng_srand (testnum); src = make_image (); dest = make_image (); @@ -108,6 +106,6 @@ int main (int argc, const char *argv[]) { return fuzzer_test_main ("rotate", 15000, - 0x5236FD9F, + 0xECF5E426, test_transform, argc, argv); } diff --git a/pixman/test/scaling-helpers-test.c b/pixman/test/scaling-helpers-test.c index 33ec47c85..cd5ace0b2 100644 --- a/pixman/test/scaling-helpers-test.c +++ b/pixman/test/scaling-helpers-test.c @@ -52,14 +52,15 @@ int main (void) { int i; + prng_srand (0); for (i = 0; i < 10000; i++) { int32_t left_pad1, left_tz1, width1, right_tz1, right_pad1; int32_t left_pad2, left_tz2, width2, right_tz2, right_pad2; - pixman_fixed_t vx = lcg_rand_N(10000 << 16) - (3000 << 16); - int32_t width = lcg_rand_N(10000); - int32_t source_image_width = lcg_rand_N(10000) + 1; - pixman_fixed_t unit_x = lcg_rand_N(10 << 16) + 1; + pixman_fixed_t vx = prng_rand_n(10000 << 16) - (3000 << 16); + int32_t width = prng_rand_n(10000); + int32_t source_image_width = prng_rand_n(10000) + 1; + pixman_fixed_t unit_x = prng_rand_n(10 << 16) + 1; width1 = width2 = width; bilinear_pad_repeat_get_scanline_bounds_ref (source_image_width, diff --git a/pixman/test/scaling-test.c b/pixman/test/scaling-test.c index 035410333..64c12dd7c 100644 --- a/pixman/test/scaling-test.c +++ b/pixman/test/scaling-test.c @@ -26,7 +26,7 @@ get_format (int bpp) { if (bpp == 4) { - switch (lcg_rand_n (4)) + switch (prng_rand_n (4)) { default: case 0: @@ -80,11 +80,11 @@ test_composite (int testnum, uint32_t crc32; FLOAT_REGS_CORRUPTION_DETECTOR_START (); - lcg_srand (testnum); + prng_srand (testnum); - src_bpp = (lcg_rand_n (2) == 0) ? 2 : 4; - dst_bpp = (lcg_rand_n (2) == 0) ? 2 : 4; - switch (lcg_rand_n (3)) + src_bpp = (prng_rand_n (2) == 0) ? 2 : 4; + dst_bpp = (prng_rand_n (2) == 0) ? 2 : 4; + switch (prng_rand_n (3)) { case 0: op = PIXMAN_OP_SRC; @@ -97,24 +97,24 @@ test_composite (int testnum, break; } - src_width = lcg_rand_n (MAX_SRC_WIDTH) + 1; - src_height = lcg_rand_n (MAX_SRC_HEIGHT) + 1; + src_width = prng_rand_n (MAX_SRC_WIDTH) + 1; + src_height = prng_rand_n (MAX_SRC_HEIGHT) + 1; - if (lcg_rand_n (2)) + if (prng_rand_n (2)) { - mask_width = lcg_rand_n (MAX_SRC_WIDTH) + 1; - mask_height = lcg_rand_n (MAX_SRC_HEIGHT) + 1; + mask_width = prng_rand_n (MAX_SRC_WIDTH) + 1; + mask_height = prng_rand_n (MAX_SRC_HEIGHT) + 1; } else { mask_width = mask_height = 1; } - dst_width = lcg_rand_n (MAX_DST_WIDTH) + 1; - dst_height = lcg_rand_n (MAX_DST_HEIGHT) + 1; - src_stride = src_width * src_bpp + lcg_rand_n (MAX_STRIDE) * src_bpp; - mask_stride = mask_width * mask_bpp + lcg_rand_n (MAX_STRIDE) * mask_bpp; - dst_stride = dst_width * dst_bpp + lcg_rand_n (MAX_STRIDE) * dst_bpp; + dst_width = prng_rand_n (MAX_DST_WIDTH) + 1; + dst_height = prng_rand_n (MAX_DST_HEIGHT) + 1; + src_stride = src_width * src_bpp + prng_rand_n (MAX_STRIDE) * src_bpp; + mask_stride = mask_width * mask_bpp + prng_rand_n (MAX_STRIDE) * mask_bpp; + dst_stride = dst_width * dst_bpp + prng_rand_n (MAX_STRIDE) * dst_bpp; if (src_stride & 3) src_stride += 2; @@ -127,27 +127,22 @@ test_composite (int testnum, if (dst_stride & 3) dst_stride += 2; - src_x = -(src_width / 4) + lcg_rand_n (src_width * 3 / 2); - src_y = -(src_height / 4) + lcg_rand_n (src_height * 3 / 2); - mask_x = -(mask_width / 4) + lcg_rand_n (mask_width * 3 / 2); - mask_y = -(mask_height / 4) + lcg_rand_n (mask_height * 3 / 2); - dst_x = -(dst_width / 4) + lcg_rand_n (dst_width * 3 / 2); - dst_y = -(dst_height / 4) + lcg_rand_n (dst_height * 3 / 2); - w = lcg_rand_n (dst_width * 3 / 2 - dst_x); - h = lcg_rand_n (dst_height * 3 / 2 - dst_y); + src_x = -(src_width / 4) + prng_rand_n (src_width * 3 / 2); + src_y = -(src_height / 4) + prng_rand_n (src_height * 3 / 2); + mask_x = -(mask_width / 4) + prng_rand_n (mask_width * 3 / 2); + mask_y = -(mask_height / 4) + prng_rand_n (mask_height * 3 / 2); + dst_x = -(dst_width / 4) + prng_rand_n (dst_width * 3 / 2); + dst_y = -(dst_height / 4) + prng_rand_n (dst_height * 3 / 2); + w = prng_rand_n (dst_width * 3 / 2 - dst_x); + h = prng_rand_n (dst_height * 3 / 2 - dst_y); srcbuf = (uint32_t *)malloc (src_stride * src_height); maskbuf = (uint32_t *)malloc (mask_stride * mask_height); dstbuf = (uint32_t *)malloc (dst_stride * dst_height); - for (i = 0; i < src_stride * src_height; i++) - *((uint8_t *)srcbuf + i) = lcg_rand_n (256); - - for (i = 0; i < mask_stride * mask_height; i++) - *((uint8_t *)maskbuf + i) = lcg_rand_n (256); - - for (i = 0; i < dst_stride * dst_height; i++) - *((uint8_t *)dstbuf + i) = lcg_rand_n (256); + prng_randmemset (srcbuf, src_stride * src_height, 0); + prng_randmemset (maskbuf, mask_stride * mask_height, 0); + prng_randmemset (dstbuf, dst_stride * dst_height, 0); src_fmt = get_format (src_bpp); dst_fmt = get_format (dst_bpp); @@ -164,29 +159,29 @@ test_composite (int testnum, image_endian_swap (src_img); image_endian_swap (dst_img); - if (lcg_rand_n (4) > 0) + if (prng_rand_n (4) > 0) { - scale_x = -32768 * 3 + lcg_rand_N (65536 * 5); - scale_y = -32768 * 3 + lcg_rand_N (65536 * 5); - translate_x = lcg_rand_N (65536); - translate_y = lcg_rand_N (65536); + scale_x = -32768 * 3 + prng_rand_n (65536 * 5); + scale_y = -32768 * 3 + prng_rand_n (65536 * 5); + translate_x = prng_rand_n (65536); + translate_y = prng_rand_n (65536); pixman_transform_init_scale (&transform, scale_x, scale_y); pixman_transform_translate (&transform, NULL, translate_x, translate_y); pixman_image_set_transform (src_img, &transform); } - if (lcg_rand_n (2) > 0) + if (prng_rand_n (2) > 0) { - mask_scale_x = -32768 * 3 + lcg_rand_N (65536 * 5); - mask_scale_y = -32768 * 3 + lcg_rand_N (65536 * 5); - mask_translate_x = lcg_rand_N (65536); - mask_translate_y = lcg_rand_N (65536); + mask_scale_x = -32768 * 3 + prng_rand_n (65536 * 5); + mask_scale_y = -32768 * 3 + prng_rand_n (65536 * 5); + mask_translate_x = prng_rand_n (65536); + mask_translate_y = prng_rand_n (65536); pixman_transform_init_scale (&transform, mask_scale_x, mask_scale_y); pixman_transform_translate (&transform, NULL, mask_translate_x, mask_translate_y); pixman_image_set_transform (mask_img, &transform); } - switch (lcg_rand_n (4)) + switch (prng_rand_n (4)) { case 0: mask_repeat = PIXMAN_REPEAT_NONE; @@ -209,7 +204,7 @@ test_composite (int testnum, } pixman_image_set_repeat (mask_img, mask_repeat); - switch (lcg_rand_n (4)) + switch (prng_rand_n (4)) { case 0: repeat = PIXMAN_REPEAT_NONE; @@ -232,12 +227,12 @@ test_composite (int testnum, } pixman_image_set_repeat (src_img, repeat); - if (lcg_rand_n (2)) + if (prng_rand_n (2)) pixman_image_set_filter (src_img, PIXMAN_FILTER_NEAREST, NULL, 0); else pixman_image_set_filter (src_img, PIXMAN_FILTER_BILINEAR, NULL, 0); - if (lcg_rand_n (2)) + if (prng_rand_n (2)) pixman_image_set_filter (mask_img, PIXMAN_FILTER_NEAREST, NULL, 0); else pixman_image_set_filter (mask_img, PIXMAN_FILTER_BILINEAR, NULL, 0); @@ -256,19 +251,19 @@ test_composite (int testnum, printf ("w=%d, h=%d\n", w, h); } - if (lcg_rand_n (8) == 0) + if (prng_rand_n (8) == 0) { pixman_box16_t clip_boxes[2]; - int n = lcg_rand_n (2) + 1; + int n = prng_rand_n (2) + 1; for (i = 0; i < n; i++) { - clip_boxes[i].x1 = lcg_rand_n (src_width); - clip_boxes[i].y1 = lcg_rand_n (src_height); + clip_boxes[i].x1 = prng_rand_n (src_width); + clip_boxes[i].y1 = prng_rand_n (src_height); clip_boxes[i].x2 = - clip_boxes[i].x1 + lcg_rand_n (src_width - clip_boxes[i].x1); + clip_boxes[i].x1 + prng_rand_n (src_width - clip_boxes[i].x1); clip_boxes[i].y2 = - clip_boxes[i].y1 + lcg_rand_n (src_height - clip_boxes[i].y1); + clip_boxes[i].y1 + prng_rand_n (src_height - clip_boxes[i].y1); if (verbose) { @@ -284,19 +279,19 @@ test_composite (int testnum, pixman_region_fini (&clip); } - if (lcg_rand_n (8) == 0) + if (prng_rand_n (8) == 0) { pixman_box16_t clip_boxes[2]; - int n = lcg_rand_n (2) + 1; + int n = prng_rand_n (2) + 1; for (i = 0; i < n; i++) { - clip_boxes[i].x1 = lcg_rand_n (mask_width); - clip_boxes[i].y1 = lcg_rand_n (mask_height); + clip_boxes[i].x1 = prng_rand_n (mask_width); + clip_boxes[i].y1 = prng_rand_n (mask_height); clip_boxes[i].x2 = - clip_boxes[i].x1 + lcg_rand_n (mask_width - clip_boxes[i].x1); + clip_boxes[i].x1 + prng_rand_n (mask_width - clip_boxes[i].x1); clip_boxes[i].y2 = - clip_boxes[i].y1 + lcg_rand_n (mask_height - clip_boxes[i].y1); + clip_boxes[i].y1 + prng_rand_n (mask_height - clip_boxes[i].y1); if (verbose) { @@ -312,18 +307,18 @@ test_composite (int testnum, pixman_region_fini (&clip); } - if (lcg_rand_n (8) == 0) + if (prng_rand_n (8) == 0) { pixman_box16_t clip_boxes[2]; - int n = lcg_rand_n (2) + 1; + int n = prng_rand_n (2) + 1; for (i = 0; i < n; i++) { - clip_boxes[i].x1 = lcg_rand_n (dst_width); - clip_boxes[i].y1 = lcg_rand_n (dst_height); + clip_boxes[i].x1 = prng_rand_n (dst_width); + clip_boxes[i].y1 = prng_rand_n (dst_height); clip_boxes[i].x2 = - clip_boxes[i].x1 + lcg_rand_n (dst_width - clip_boxes[i].x1); + clip_boxes[i].x1 + prng_rand_n (dst_width - clip_boxes[i].x1); clip_boxes[i].y2 = - clip_boxes[i].y1 + lcg_rand_n (dst_height - clip_boxes[i].y1); + clip_boxes[i].y1 + prng_rand_n (dst_height - clip_boxes[i].y1); if (verbose) { @@ -337,7 +332,7 @@ test_composite (int testnum, pixman_region_fini (&clip); } - if (lcg_rand_n (2) == 0) + if (prng_rand_n (2) == 0) pixman_image_composite (op, src_img, NULL, dst_img, src_x, src_y, 0, 0, dst_x, dst_y, w, h); else @@ -380,11 +375,11 @@ test_composite (int testnum, } #if BILINEAR_INTERPOLATION_BITS == 8 -#define CHECKSUM 0x107B67ED +#define CHECKSUM 0x9096E6B6 #elif BILINEAR_INTERPOLATION_BITS == 7 -#define CHECKSUM 0x30EC0CF0 +#define CHECKSUM 0xCE8EC6BA #elif BILINEAR_INTERPOLATION_BITS == 4 -#define CHECKSUM 0x87B496BC +#define CHECKSUM 0xAB1D39BE #else #define CHECKSUM 0x00000000 #endif diff --git a/pixman/test/stress-test.c b/pixman/test/stress-test.c index 059250dd4..ee55c21ea 100644 --- a/pixman/test/stress-test.c +++ b/pixman/test/stress-test.c @@ -74,7 +74,7 @@ static pixman_filter_t filters[] = static int get_size (void) { - switch (lcg_rand_n (28)) + switch (prng_rand_n (28)) { case 0: return 1; @@ -84,10 +84,10 @@ get_size (void) default: case 2: - return lcg_rand_n (100); + return prng_rand_n (100); case 4: - return lcg_rand_n (2000) + 1000; + return prng_rand_n (2000) + 1000; case 5: return 65535; @@ -96,7 +96,7 @@ get_size (void) return 65536; case 7: - return lcg_rand_N (64000) + 63000; + return prng_rand_n (64000) + 63000; } } @@ -164,7 +164,7 @@ real_writer (void *src, uint32_t value, int size) static uint32_t fake_reader (const void *src, int size) { - uint32_t r = lcg_rand_u32 (); + uint32_t r = prng_rand (); assert (size == 1 || size == 2 || size == 4); @@ -182,16 +182,16 @@ log_rand (void) { uint32_t mask; - mask = (1 << lcg_rand_n (10)) - 1; + mask = (1 << prng_rand_n (10)) - 1; - return (lcg_rand_u32 () & mask) - (mask >> 1); + return (prng_rand () & mask) - (mask >> 1); } static int32_t rand_x (pixman_image_t *image) { if (image->type == BITS) - return lcg_rand_n (image->bits.width); + return prng_rand_n (image->bits.width); else return log_rand (); } @@ -200,7 +200,7 @@ static int32_t rand_y (pixman_image_t *image) { if (image->type == BITS) - return lcg_rand_n (image->bits.height); + return prng_rand_n (image->bits.height); else return log_rand (); } @@ -220,7 +220,7 @@ create_random_bits_image (void) int n_coefficients = 0; /* format */ - format = image_formats[lcg_rand_n (ARRAY_LENGTH (image_formats))]; + format = image_formats[prng_rand_n (ARRAY_LENGTH (image_formats))]; indexed = NULL; if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_COLOR) @@ -246,7 +246,7 @@ create_random_bits_image (void) while ((uint64_t)width * height > 200000) { - if (lcg_rand_n(2) == 0) + if (prng_rand_n(2) == 0) height = 200000 / width; else width = 200000 / height; @@ -258,11 +258,11 @@ create_random_bits_image (void) width = 1; /* bits */ - switch (lcg_rand_n (7)) + switch (prng_rand_n (7)) { default: case 0: - stride = width * PIXMAN_FORMAT_BPP (format) + lcg_rand_n (17); + stride = width * PIXMAN_FORMAT_BPP (format) + prng_rand_n (17); stride = (stride + 3) & (~3); bits = (uint32_t *)make_random_bytes (height * stride); break; @@ -273,7 +273,7 @@ create_random_bits_image (void) break; case 2: /* Zero-filled */ - stride = width * PIXMAN_FORMAT_BPP (format) + lcg_rand_n (17); + stride = width * PIXMAN_FORMAT_BPP (format) + prng_rand_n (17); stride = (stride + 3) & (~3); bits = fence_malloc (height * stride); if (!bits) @@ -282,7 +282,7 @@ create_random_bits_image (void) break; case 3: /* Filled with 0xFF */ - stride = width * PIXMAN_FORMAT_BPP (format) + lcg_rand_n (17); + stride = width * PIXMAN_FORMAT_BPP (format) + prng_rand_n (17); stride = (stride + 3) & (~3); bits = fence_malloc (height * stride); if (!bits) @@ -298,7 +298,7 @@ create_random_bits_image (void) break; case 5: /* bits is a real pointer, has read/write functions */ - stride = width * PIXMAN_FORMAT_BPP (format) + lcg_rand_n (17); + stride = width * PIXMAN_FORMAT_BPP (format) + prng_rand_n (17); stride = (stride + 3) & (~3); bits = fence_malloc (height * stride); if (!bits) @@ -309,7 +309,7 @@ create_random_bits_image (void) break; case 6: /* bits is a real pointer, stride is negative */ - stride = (width * PIXMAN_FORMAT_BPP (format) + lcg_rand_n (17)); + stride = (width * PIXMAN_FORMAT_BPP (format) + prng_rand_n (17)); stride = (stride + 3) & (~3); bits = (uint32_t *)make_random_bytes (height * stride); if (!bits) @@ -320,11 +320,11 @@ create_random_bits_image (void) } /* Filter */ - filter = filters[lcg_rand_n (ARRAY_LENGTH (filters))]; + filter = filters[prng_rand_n (ARRAY_LENGTH (filters))]; if (filter == PIXMAN_FILTER_CONVOLUTION) { - int width = lcg_rand_n (3); - int height = lcg_rand_n (4); + int width = prng_rand_n (3); + int height = prng_rand_n (4); n_coefficients = width * height + 2; coefficients = malloc (n_coefficients * sizeof (pixman_fixed_t)); @@ -334,7 +334,7 @@ create_random_bits_image (void) int i; for (i = 0; i < width * height; ++i) - coefficients[i + 2] = lcg_rand_u32(); + coefficients[i + 2] = prng_rand(); coefficients[0] = width << 16; coefficients[1] = height << 16; @@ -380,11 +380,11 @@ set_general_properties (pixman_image_t *image, pixman_bool_t allow_alpha_map) /* Set properties that are generic to all images */ /* Repeat */ - repeat = repeats[lcg_rand_n (ARRAY_LENGTH (repeats))]; + repeat = repeats[prng_rand_n (ARRAY_LENGTH (repeats))]; pixman_image_set_repeat (image, repeat); /* Alpha map */ - if (allow_alpha_map && lcg_rand_n (4) == 0) + if (allow_alpha_map && prng_rand_n (4) == 0) { pixman_image_t *alpha_map; int16_t x, y; @@ -405,17 +405,17 @@ set_general_properties (pixman_image_t *image, pixman_bool_t allow_alpha_map) } /* Component alpha */ - pixman_image_set_component_alpha (image, lcg_rand_n (3) == 0); + pixman_image_set_component_alpha (image, prng_rand_n (3) == 0); /* Clip region */ - if (lcg_rand_n (8) < 2) + if (prng_rand_n (8) < 2) { pixman_region32_t region; int i, n_rects; pixman_region32_init (®ion); - switch (lcg_rand_n (12)) + switch (prng_rand_n (12)) { case 0: n_rects = 0; @@ -434,7 +434,7 @@ set_general_properties (pixman_image_t *image, pixman_bool_t allow_alpha_map) break; default: - n_rects = lcg_rand_n (100); + n_rects = prng_rand_n (100); break; } @@ -452,7 +452,7 @@ set_general_properties (pixman_image_t *image, pixman_bool_t allow_alpha_map) ®ion, ®ion, x, y, width, height); } - if (image->type == BITS && lcg_rand_n (8) != 0) + if (image->type == BITS && prng_rand_n (8) != 0) { uint32_t width, height; int x, y; @@ -463,10 +463,10 @@ set_general_properties (pixman_image_t *image, pixman_bool_t allow_alpha_map) */ for (i = 0; i < 5; ++i) { - x = lcg_rand_n (2 * image->bits.width) - image->bits.width; - y = lcg_rand_n (2 * image->bits.height) - image->bits.height; - width = lcg_rand_n (image->bits.width) - x + 10; - height = lcg_rand_n (image->bits.height) - y + 10; + x = prng_rand_n (2 * image->bits.width) - image->bits.width; + y = prng_rand_n (2 * image->bits.height) - image->bits.height; + width = prng_rand_n (image->bits.width) - x + 10; + height = prng_rand_n (image->bits.height) - y + 10; if (width + x < x) width = INT32_MAX - x; @@ -484,13 +484,13 @@ set_general_properties (pixman_image_t *image, pixman_bool_t allow_alpha_map) } /* Whether source clipping is enabled */ - pixman_image_set_source_clipping (image, !!lcg_rand_n (2)); + pixman_image_set_source_clipping (image, !!prng_rand_n (2)); /* Client clip */ - pixman_image_set_has_client_clip (image, !!lcg_rand_n (2)); + pixman_image_set_has_client_clip (image, !!prng_rand_n (2)); /* Transform */ - if (lcg_rand_n (5) < 2) + if (prng_rand_n (5) < 2) { pixman_transform_t xform; int i, j, k; @@ -504,39 +504,39 @@ set_general_properties (pixman_image_t *image, pixman_bool_t allow_alpha_map) for (k = 0; k < 3; ++k) { - switch (lcg_rand_n (4)) + switch (prng_rand_n (4)) { case 0: /* rotation */ - c = lcg_rand_N (2 * 65536) - 65536; - s = lcg_rand_N (2 * 65536) - 65536; + c = prng_rand_n (2 * 65536) - 65536; + s = prng_rand_n (2 * 65536) - 65536; pixman_transform_rotate (&xform, NULL, c, s); break; case 1: /* translation */ - tx = lcg_rand_u32(); - ty = lcg_rand_u32(); + tx = prng_rand(); + ty = prng_rand(); pixman_transform_translate (&xform, NULL, tx, ty); break; case 2: /* scale */ - sx = lcg_rand_u32(); - sy = lcg_rand_u32(); + sx = prng_rand(); + sy = prng_rand(); pixman_transform_scale (&xform, NULL, sx, sy); break; case 3: - if (lcg_rand_n (16) == 0) + if (prng_rand_n (16) == 0) { /* random */ for (i = 0; i < 3; ++i) for (j = 0; j < 3; ++j) - xform.matrix[i][j] = lcg_rand_u32(); + xform.matrix[i][j] = prng_rand(); break; } - else if (lcg_rand_n (16) == 0) + else if (prng_rand_n (16) == 0) { /* zero */ memset (&xform, 0, sizeof xform); @@ -554,10 +554,10 @@ random_color (void) { pixman_color_t color = { - lcg_rand() & 0xffff, - lcg_rand() & 0xffff, - lcg_rand() & 0xffff, - lcg_rand() & 0xffff, + prng_rand() & 0xffff, + prng_rand() & 0xffff, + prng_rand() & 0xffff, + prng_rand() & 0xffff, }; return color; @@ -581,7 +581,7 @@ create_random_stops (int *n_stops) int i; pixman_gradient_stop_t *stops; - *n_stops = lcg_rand_n (50) + 1; + *n_stops = prng_rand_n (50) + 1; step = pixman_fixed_1 / *n_stops; @@ -646,8 +646,8 @@ create_random_radial_image (void) inner_c = create_random_point(); outer_c = create_random_point(); - inner_r = lcg_rand(); - outer_r = lcg_rand(); + inner_r = prng_rand(); + outer_r = prng_rand(); stops = create_random_stops (&n_stops); @@ -672,7 +672,7 @@ create_random_conical_image (void) pixman_image_t *result; c = create_random_point(); - angle = lcg_rand(); + angle = prng_rand(); stops = create_random_stops (&n_stops); @@ -691,7 +691,7 @@ create_random_image (void) { pixman_image_t *result; - switch (lcg_rand_n (5)) + switch (prng_rand_n (5)) { default: case 0: @@ -793,7 +793,7 @@ run_test (uint32_t seed, pixman_bool_t verbose, uint32_t mod) printf ("Seed 0x%08x\n", seed); } - lcg_srand (seed); + prng_srand (seed); source = create_random_image (); mask = create_random_image (); @@ -803,7 +803,7 @@ run_test (uint32_t seed, pixman_bool_t verbose, uint32_t mod) { set_general_properties (dest, TRUE); - op = op_list [lcg_rand_n (ARRAY_LENGTH (op_list))]; + op = op_list [prng_rand_n (ARRAY_LENGTH (op_list))]; pixman_image_composite32 (op, source, mask, dest, diff --git a/pixman/test/utils-prng.c b/pixman/test/utils-prng.c new file mode 100644 index 000000000..7c2dd6a9a --- /dev/null +++ b/pixman/test/utils-prng.c @@ -0,0 +1,238 @@ +/* + * Copyright © 2012 Siarhei Siamashka <siarhei.siamashka@gmail.com> + * + * Based on the public domain implementation of small noncryptographic PRNG + * authored by Bob Jenkins: http://burtleburtle.net/bob/rand/smallprng.html + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "utils.h" +#include "utils-prng.h" + +void smallprng_srand_r (smallprng_t *x, uint32_t seed) +{ + uint32_t i; + x->a = 0xf1ea5eed, x->b = x->c = x->d = seed; + for (i = 0; i < 20; ++i) + smallprng_rand_r (x); +} + +/* + * Set a 32-bit seed for PRNG + * + * LCG is used here for generating independent seeds for different + * smallprng instances (in the case if smallprng is also used for + * generating these seeds, "Big Crush" test from TestU01 detects + * some problems in the glued 'prng_rand_128_r' output data). + * Actually we might be even better using some cryptographic + * hash for this purpose, but LCG seems to be also enough for + * passing "Big Crush". + */ +void prng_srand_r (prng_t *x, uint32_t seed) +{ +#ifdef GCC_VECTOR_EXTENSIONS_SUPPORTED + int i; + prng_rand_128_data_t dummy; + smallprng_srand_r (&x->p0, seed); + x->a[0] = x->a[1] = x->a[2] = x->a[3] = 0xf1ea5eed; + x->b[0] = x->c[0] = x->d[0] = (seed = seed * 1103515245 + 12345); + x->b[1] = x->c[1] = x->d[1] = (seed = seed * 1103515245 + 12345); + x->b[2] = x->c[2] = x->d[2] = (seed = seed * 1103515245 + 12345); + x->b[3] = x->c[3] = x->d[3] = (seed = seed * 1103515245 + 12345); + for (i = 0; i < 20; ++i) + prng_rand_128_r (x, &dummy); +#else + smallprng_srand_r (&x->p0, seed); + smallprng_srand_r (&x->p1, (seed = seed * 1103515245 + 12345)); + smallprng_srand_r (&x->p2, (seed = seed * 1103515245 + 12345)); + smallprng_srand_r (&x->p3, (seed = seed * 1103515245 + 12345)); + smallprng_srand_r (&x->p4, (seed = seed * 1103515245 + 12345)); +#endif +} + +static force_inline void +store_rand_128_data (void *addr, prng_rand_128_data_t *d, int aligned) +{ +#ifdef GCC_VECTOR_EXTENSIONS_SUPPORTED + if (aligned) + { + *(uint8x16 *)addr = d->vb; + return; + } +#endif + /* we could try something better for unaligned writes (packed attribute), + * but GCC is not very reliable: http://gcc.gnu.org/PR55454 */ + memcpy (addr, d, 16); +} + +/* + * Helper function and the actual code for "prng_randmemset_r" function + */ +static force_inline void +randmemset_internal (prng_t *prng, + uint8_t *buf, + size_t size, + prng_randmemset_flags_t flags, + int aligned) +{ + prng_t local_prng = *prng; + prng_rand_128_data_t randdata; + + while (size >= 16) + { + prng_rand_128_data_t t; + if (flags == 0) + { + prng_rand_128_r (&local_prng, &randdata); + } + else + { + prng_rand_128_r (&local_prng, &t); + prng_rand_128_r (&local_prng, &randdata); +#ifdef GCC_VECTOR_EXTENSIONS_SUPPORTED + if (flags & RANDMEMSET_MORE_FF) + { + const uint8x16 const_C0 = + { + 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, + 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0 + }; + randdata.vb |= (t.vb >= const_C0); + } + if (flags & RANDMEMSET_MORE_00) + { + const uint8x16 const_40 = + { + 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40 + }; + randdata.vb &= (t.vb >= const_40); + } +#else + #define PROCESS_ONE_LANE(i) \ + if (flags & RANDMEMSET_MORE_FF) \ + { \ + uint32_t mask_ff = (t.w[i] & (t.w[i] << 1)) & 0x80808080; \ + mask_ff |= mask_ff >> 1; \ + mask_ff |= mask_ff >> 2; \ + mask_ff |= mask_ff >> 4; \ + randdata.w[i] |= mask_ff; \ + } \ + if (flags & RANDMEMSET_MORE_00) \ + { \ + uint32_t mask_00 = (t.w[i] | (t.w[i] << 1)) & 0x80808080; \ + mask_00 |= mask_00 >> 1; \ + mask_00 |= mask_00 >> 2; \ + mask_00 |= mask_00 >> 4; \ + randdata.w[i] &= mask_00; \ + } + + PROCESS_ONE_LANE (0) + PROCESS_ONE_LANE (1) + PROCESS_ONE_LANE (2) + PROCESS_ONE_LANE (3) +#endif + } + if (is_little_endian ()) + { + store_rand_128_data (buf, &randdata, aligned); + buf += 16; + } + else + { +#ifdef GCC_VECTOR_EXTENSIONS_SUPPORTED + const uint8x16 bswap_shufflemask = + { + 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12 + }; + randdata.vb = __builtin_shuffle (randdata.vb, bswap_shufflemask); + store_rand_128_data (buf, &randdata, aligned); + buf += 16; +#else + uint8_t t1, t2, t3, t4; + #define STORE_ONE_LANE(i) \ + t1 = randdata.b[i * 4 + 3]; \ + t2 = randdata.b[i * 4 + 2]; \ + t3 = randdata.b[i * 4 + 1]; \ + t4 = randdata.b[i * 4 + 0]; \ + *buf++ = t1; \ + *buf++ = t2; \ + *buf++ = t3; \ + *buf++ = t4; + + STORE_ONE_LANE (0) + STORE_ONE_LANE (1) + STORE_ONE_LANE (2) + STORE_ONE_LANE (3) +#endif + } + size -= 16; + } + while (size > 0) + { + uint8_t randbyte = prng_rand_r (&local_prng) & 0xFF; + if (flags != 0) + { + uint8_t t = prng_rand_r (&local_prng) & 0xFF; + if ((flags & RANDMEMSET_MORE_FF) && (t >= 0xC0)) + randbyte = 0xFF; + if ((flags & RANDMEMSET_MORE_00) && (t < 0x40)) + randbyte = 0x00; + } + *buf++ = randbyte; + size--; + } + *prng = local_prng; +} + +/* + * Fill memory buffer with random data. Flags argument may be used + * to tweak some statistics properties: + * RANDMEMSET_MORE_00 - set ~25% of bytes to 0x00 + * RANDMEMSET_MORE_FF - set ~25% of bytes to 0xFF + */ +void prng_randmemset_r (prng_t *prng, + void *voidbuf, + size_t size, + prng_randmemset_flags_t flags) +{ + uint8_t *buf = (uint8_t *)voidbuf; + if ((uintptr_t)buf & 15) + { + /* unaligned buffer */ + if (flags == 0) + randmemset_internal (prng, buf, size, 0, 0); + else if (flags == RANDMEMSET_MORE_00_AND_FF) + randmemset_internal (prng, buf, size, RANDMEMSET_MORE_00_AND_FF, 0); + else + randmemset_internal (prng, buf, size, flags, 0); + } + else + { + /* aligned buffer */ + if (flags == 0) + randmemset_internal (prng, buf, size, 0, 1); + else if (flags == RANDMEMSET_MORE_00_AND_FF) + randmemset_internal (prng, buf, size, RANDMEMSET_MORE_00_AND_FF, 1); + else + randmemset_internal (prng, buf, size, flags, 1); + } +} diff --git a/pixman/test/utils-prng.h b/pixman/test/utils-prng.h new file mode 100644 index 000000000..285107f08 --- /dev/null +++ b/pixman/test/utils-prng.h @@ -0,0 +1,168 @@ +/* + * Copyright © 2012 Siarhei Siamashka <siarhei.siamashka@gmail.com> + * + * Based on the public domain implementation of small noncryptographic PRNG + * authored by Bob Jenkins: http://burtleburtle.net/bob/rand/smallprng.html + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef __UTILS_PRNG_H__ +#define __UTILS_PRNG_H__ + +/* + * This file provides a fast SIMD-optimized noncryptographic PRNG (pseudorandom + * number generator), with the output good enough to pass "Big Crush" tests + * from TestU01 (http://en.wikipedia.org/wiki/TestU01). + * + * SIMD code uses http://gcc.gnu.org/onlinedocs/gcc/Vector-Extensions.html + * which is a GCC specific extension. There is also a slower alternative + * code path, which should work with any C compiler. + * + * The "prng_t" structure keeps the internal state of the random number + * generator. It is possible to have multiple instances of the random number + * generator active at the same time, in this case each of them needs to have + * its own "prng_t". All the functions take a pointer to "prng_t" + * as the first argument. + * + * Functions: + * + * ---------------------------------------------------------------------------- + * void prng_srand_r (prng_t *prng, uint32_t seed); + * + * Initialize the pseudorandom number generator. The sequence of preudorandom + * numbers is deterministic and only depends on "seed". Any two generators + * initialized with the same seed will produce exactly the same sequence. + * + * ---------------------------------------------------------------------------- + * uint32_t prng_rand_r (prng_t *prng); + * + * Generate a single uniformly distributed 32-bit pseudorandom value. + * + * ---------------------------------------------------------------------------- + * void prng_randmemset_r (prng_t *prng, + * void *buffer, + * size_t size, + * prng_randmemset_flags_t flags); + * + * Fills the memory buffer "buffer" with "size" bytes of pseudorandom data. + * The "flags" argument may be used to tweak some statistics properties: + * RANDMEMSET_MORE_00 - set ~25% of bytes to 0x00 + * RANDMEMSET_MORE_FF - set ~25% of bytes to 0xFF + * The flags can be combined. This allows a bit better simulation of typical + * pixel data, which normally contains a lot of fully transparent or fully + * opaque pixels. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "pixman-private.h" + +/*****************************************************************************/ + +#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) +#define GCC_VECTOR_EXTENSIONS_SUPPORTED +typedef uint32_t uint32x4 __attribute__ ((vector_size(16))); +typedef uint8_t uint8x16 __attribute__ ((vector_size(16))); +#endif + +typedef struct +{ + uint32_t a, b, c, d; +} smallprng_t; + +typedef struct +{ +#ifdef GCC_VECTOR_EXTENSIONS_SUPPORTED + uint32x4 a, b, c, d; +#else + smallprng_t p1, p2, p3, p4; +#endif + smallprng_t p0; +} prng_t; + +typedef union +{ + uint8_t b[16]; + uint32_t w[4]; +#ifdef GCC_VECTOR_EXTENSIONS_SUPPORTED + uint8x16 vb; + uint32x4 vw; +#endif +} prng_rand_128_data_t; + +/*****************************************************************************/ + +static force_inline uint32_t +smallprng_rand_r (smallprng_t *x) +{ + uint32_t e = x->a - ((x->b << 27) + (x->b >> (32 - 27))); + x->a = x->b ^ ((x->c << 17) ^ (x->c >> (32 - 17))); + x->b = x->c + x->d; + x->c = x->d + e; + x->d = e + x->a; + return x->d; +} + +/* Generate 4 bytes (32-bits) of random data */ +static force_inline uint32_t +prng_rand_r (prng_t *x) +{ + return smallprng_rand_r (&x->p0); +} + +/* Generate 16 bytes (128-bits) of random data */ +static force_inline void +prng_rand_128_r (prng_t *x, prng_rand_128_data_t *data) +{ +#ifdef GCC_VECTOR_EXTENSIONS_SUPPORTED + uint32x4 e = x->a - ((x->b << 27) + (x->b >> (32 - 27))); + x->a = x->b ^ ((x->c << 17) ^ (x->c >> (32 - 17))); + x->b = x->c + x->d; + x->c = x->d + e; + x->d = e + x->a; + data->vw = x->d; +#else + data->w[0] = smallprng_rand_r (&x->p1); + data->w[1] = smallprng_rand_r (&x->p2); + data->w[2] = smallprng_rand_r (&x->p3); + data->w[3] = smallprng_rand_r (&x->p4); +#endif +} + +typedef enum +{ + RANDMEMSET_MORE_00 = 1, /* ~25% chance for 0x00 bytes */ + RANDMEMSET_MORE_FF = 2, /* ~25% chance for 0xFF bytes */ + RANDMEMSET_MORE_00_AND_FF = (RANDMEMSET_MORE_00 | RANDMEMSET_MORE_FF) +} prng_randmemset_flags_t; + +/* Set the 32-bit seed for PRNG */ +void prng_srand_r (prng_t *prng, uint32_t seed); + +/* Fill memory buffer with random data */ +void prng_randmemset_r (prng_t *prng, + void *buffer, + size_t size, + prng_randmemset_flags_t flags); + +#endif diff --git a/pixman/test/utils.c b/pixman/test/utils.c index c887a6db9..66c8dcb89 100644 --- a/pixman/test/utils.c +++ b/pixman/test/utils.c @@ -27,10 +27,11 @@ #include <png.h> #endif -/* Random number seed +/* Random number generator state */ -uint32_t lcg_seed; +prng_t prng_state_data; +prng_t *prng_state; /*----------------------------------------------------------------------------*\ * CRC-32 version 2.0.0 by Craig Bruce, 2006-04-29. @@ -237,14 +238,6 @@ compute_crc32_for_image (uint32_t crc32, return crc32; } -pixman_bool_t -is_little_endian (void) -{ - volatile uint16_t endian_check_var = 0x1234; - - return (*(volatile uint8_t *)&endian_check_var == 0x34); -} - /* perform endian conversion of pixel data */ void @@ -431,13 +424,11 @@ uint8_t * make_random_bytes (int n_bytes) { uint8_t *bytes = fence_malloc (n_bytes); - int i; if (!bytes) return NULL; - for (i = 0; i < n_bytes; ++i) - bytes[i] = lcg_rand () & 0xff; + prng_randmemset (bytes, n_bytes, 0); return bytes; } @@ -689,9 +680,9 @@ get_random_seed (void) { union { double d; uint32_t u32; } t; t.d = gettime(); - lcg_srand (t.u32); + prng_srand (t.u32); - return lcg_rand_u32 (); + return prng_rand (); } #ifdef HAVE_SIGACTION @@ -785,7 +776,7 @@ initialize_palette (pixman_indexed_t *palette, uint32_t depth, int is_rgb) uint32_t mask = (1 << depth) - 1; for (i = 0; i < 32768; ++i) - palette->ent[i] = lcg_rand() & mask; + palette->ent[i] = prng_rand() & mask; memset (palette->rgba, 0, sizeof (palette->rgba)); @@ -805,7 +796,7 @@ initialize_palette (pixman_indexed_t *palette, uint32_t depth, int is_rgb) { uint32_t old_idx; - rgba24 = lcg_rand(); + rgba24 = prng_rand(); i15 = CONVERT_15 (rgba24, is_rgb); old_idx = palette->ent[i15]; diff --git a/pixman/test/utils.h b/pixman/test/utils.h index f7ea34c5f..78cf0d16d 100644 --- a/pixman/test/utils.h +++ b/pixman/test/utils.h @@ -4,6 +4,7 @@ #include <assert.h> #include "pixman-private.h" /* For 'inline' definition */ +#include "utils-prng.h" #define ARRAY_LENGTH(A) ((int) (sizeof (A) / sizeof ((A) [0]))) @@ -11,49 +12,44 @@ * taken from POSIX.1-2001 example */ -extern uint32_t lcg_seed; +extern prng_t prng_state_data; +extern prng_t *prng_state; #ifdef USE_OPENMP -#pragma omp threadprivate(lcg_seed) +#pragma omp threadprivate(prng_state_data) +#pragma omp threadprivate(prng_state) #endif static inline uint32_t -lcg_rand (void) +prng_rand (void) { - lcg_seed = lcg_seed * 1103515245 + 12345; - return ((uint32_t)(lcg_seed / 65536) % 32768); + return prng_rand_r (prng_state); } static inline void -lcg_srand (uint32_t seed) +prng_srand (uint32_t seed) { - lcg_seed = seed; + if (!prng_state) + { + /* Without setting a seed, PRNG does not work properly (is just + * returning zeros). So we only initialize the pointer here to + * make sure that 'prng_srand' is always called before any + * other 'prng_*' function. The wrongdoers violating this order + * will get a segfault. */ + prng_state = &prng_state_data; + } + prng_srand_r (prng_state, seed); } static inline uint32_t -lcg_rand_n (int max) +prng_rand_n (int max) { - return lcg_rand () % max; + return prng_rand () % max; } -static inline uint32_t -lcg_rand_N (int max) -{ - uint32_t lo = lcg_rand (); - uint32_t hi = lcg_rand () << 15; - return (lo | hi) % max; -} - -static inline uint32_t -lcg_rand_u32 (void) +static inline void +prng_randmemset (void *buffer, size_t size, prng_randmemset_flags_t flags) { - /* This uses the 10/11 most significant bits from the 3 lcg results - * (and mixes them with the low from the adjacent one). - */ - uint32_t lo = lcg_rand() >> -(32 - 15 - 11 * 2); - uint32_t mid = lcg_rand() << (32 - 15 - 11 * 1); - uint32_t hi = lcg_rand() << (32 - 15 - 11 * 0); - - return (hi ^ mid ^ lo); + prng_randmemset_r (prng_state, buffer, size, flags); } /* CRC 32 computation @@ -69,8 +65,12 @@ compute_crc32_for_image (uint32_t in_crc32, /* Returns TRUE if running on a little endian system */ -pixman_bool_t -is_little_endian (void); +static force_inline pixman_bool_t +is_little_endian (void) +{ + unsigned long endian_check_var = 1; + return *(unsigned char *)&endian_check_var == 1; +} /* perform endian conversion of pixel data */ |