diff options
author | marha <marha@users.sourceforge.net> | 2013-04-08 08:17:23 +0200 |
---|---|---|
committer | marha <marha@users.sourceforge.net> | 2013-04-11 11:13:40 +0200 |
commit | 59038e048c4be1e69744b087ba31386e98141a8f (patch) | |
tree | b91f0b662663be6f26e985b0c09a906cfad9ccc5 | |
parent | dde22e946ccfb0bd937224daf42403b80528c2a6 (diff) | |
download | vcxsrv-59038e048c4be1e69744b087ba31386e98141a8f.tar.gz vcxsrv-59038e048c4be1e69744b087ba31386e98141a8f.tar.bz2 vcxsrv-59038e048c4be1e69744b087ba31386e98141a8f.zip |
fontconfig libXau mesa xserver xkeyboard-config git update 8 Apr 2013
xserver commit 8928f8fa0bb154ce437af703ff702016f0dcf127
xkeyboard-config commit e5c6729f3679fe87a703eb1d7ec1cf0a61814ca8
libXau commit f5a57d8a21a34d7084cce294e24c0422e02ef8ef
fontconfig commit 18bf57c70aafcad031c0b43756b754dcaf6a756a
mesa commit eff66bc9f855fff5c4f5f57f247254a97431e8ad
118 files changed, 3417 insertions, 358 deletions
diff --git a/fontconfig/Makefile.am b/fontconfig/Makefile.am index cc5435ea0..d310b4b62 100644 --- a/fontconfig/Makefile.am +++ b/fontconfig/Makefile.am @@ -53,6 +53,7 @@ MAINTAINERCLEANFILES = \ $(srcdir)/ltmain.sh \ $(srcdir)/missing \ $(srcdir)/mkinstalldirs \ + $(srcdir)/test-driver \ `find "$(srcdir)" -type f -name Makefile.in -print` pkgconfig_DATA = fontconfig.pc diff --git a/fontconfig/README b/fontconfig/README index fcd3ab343..a855f28ff 100644 --- a/fontconfig/README +++ b/fontconfig/README @@ -1,12 +1,73 @@ Fontconfig Font configuration and customization library - Version 2.10.91 (2.11 RC1) - 2013-01-10 + Version 2.10.92 (2.11 RC2) + 2013-03-29 Check INSTALL for compilation and installation instructions. Report bugs to https://bugs.freedesktop.org in the fontconfig module. +2.10.92 (2.11 RC2) + +Akira TAGOH (33): + Fix the build fail on MinGW + Bug 50497 - RFE: Add OpenType feature tags support + Improve FcGetPrgname() to work on BSD + Better fix for 2fe5ddfd + Add missing file descriptor to F_DUPFD_CLOEXEC + Fix mkstemp absence for some platform + Fix installation on MinGW32 + Add another approach to FC_PRGNAME for Solaris 10 or before + remove the unnecessary code + Bug 59385 - Do the right thing for intermixed edit and test elements + Bug 23757 - Add mode="delete" to <edit> + Modernize configure.ac + Use AM_MISSING_PROG instead of hardcoding missing + Revert "test: Use SH_LOG_COMPILER and AM_TESTS_ENVIRONMENT" + Use AM_MISSING_PROG instead of hardcoding missing + Bug 50733 - Add font-file hash? + Bug 60312 - DIST_SUBDIRS should never appear in a conditional + Update _FcMatchers definition logic + Bump the cache version to 4 + Add Culmus foundry to the vendor list + Bug 60748 - broken conf.d/10-autohint.conf and conf.d/10-unhinted.conf + Bug 60783 - Add Liberation Sans Narrow to 30-metric-aliases.conf + Fix a typo + Fix a crash when the object is non-builtin object + Fix broken sort order with FcFontSort() + Fix a memory leak + Bug 59456 - Adding a --sysroot like option to fc-cache + Do not copy FC_*LANG_OBJECT even if it's not available on the pattern + Fix a SIGSEGV on FcPatternGet* with NULL pattern + Bug 38737 - Wishlist: support FC_POSTSCRIPT_NAME + Minor cleanup + Bump libtool revision + Minor fix + +Behdad Esfahbod (12): + Resepct $NOCONFIGURE + Ensure we find the uninstalled fontconfig header + Copy all values from pattern to font if the font doesn't have the element + Minor + Bug 59379 - FC_PRGNAME + Remove unused checks for common functions + Minor + Fix fc-cache crash caused by looking up NULL object incorrectly + Fix FC_PRGNAME default + Fix readlink failure + Accept digits as part of OpenType script tags + Fix crash with FcConfigSetCurrent(NULL) + +Christoph J. Thompson (1): + Use the PKG_INSTALLDIR macro. + +Colin Walters (1): + build: Only use PKG_INSTALLDIR if available + +Quentin Glidic (2): + test: Use SH_LOG_COMPILER and AM_TESTS_ENVIRONMENT + Use LOG_COMPILER and AM_TESTS_ENVIRONMENT + 2.10.91 (2.11 RC1) Akira TAGOH (19): diff --git a/fontconfig/Tools.mk b/fontconfig/Tools.mk index 56766da0e..f0fa0ec50 100644 --- a/fontconfig/Tools.mk +++ b/fontconfig/Tools.mk @@ -32,7 +32,7 @@ TOOL=./$(DIR)$(EXEEXT_FOR_BUILD) EXTRA_DIST = $(TARG) $(TMPL) $(TSRC) $(DIST) -INCLUDES = \ +AM_CPPFLAGS = \ -I$(builddir) \ -I$(srcdir) \ -I$(top_builddir)/src \ @@ -43,7 +43,7 @@ INCLUDES = \ $(WARN_CFLAGS) $(TOOL): $(TSRC) $(ALIAS_FILES) - $(AM_V_GEN) $(CC_FOR_BUILD) -o $(TOOL) $< $(INCLUDES) + $(AM_V_GEN) $(CC_FOR_BUILD) -o $(TOOL) $< $(AM_CPPFLAGS) $(TARG): $(TMPL) $(TSRC) $(DEPS) $(AM_V_GEN) $(MAKE) $(TOOL) && \ diff --git a/fontconfig/configure.ac b/fontconfig/configure.ac index 81e02ee1e..791937226 100644 --- a/fontconfig/configure.ac +++ b/fontconfig/configure.ac @@ -33,7 +33,7 @@ dnl This is the package version number, not the shared library dnl version. This same version number must appear in fontconfig/fontconfig.h dnl Yes, it is a pain to synchronize version numbers. Unfortunately, it's dnl not possible to extract the version number here from fontconfig.h -AC_INIT([fontconfig], [2.10.91], [https://bugs.freedesktop.org/enger_bug.cgi?product=fontconfig]) +AC_INIT([fontconfig], [2.10.92], [https://bugs.freedesktop.org/enger_bug.cgi?product=fontconfig]) AM_INIT_AUTOMAKE([1.11 parallel-tests dist-bzip2]) m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])]) @@ -42,11 +42,11 @@ dnl libtool versioning dnl bump revision when fixing bugs dnl bump current and age, reset revision to zero when adding APIs dnl bump current, leave age, reset revision to zero when changing/removing APIS -LIBT_CURRENT=7 -LIBT_REVISION=2 +LIBT_CURRENT=8 +LIBT_REVISION=0 AC_SUBST(LIBT_CURRENT) AC_SUBST(LIBT_REVISION) -LIBT_AGE=6 +LIBT_AGE=7 LIBT_VERSION_INFO="$LIBT_CURRENT:$LIBT_REVISION:$LIBT_AGE" AC_SUBST(LIBT_VERSION_INFO) diff --git a/fontconfig/fc-cache/Makefile.am b/fontconfig/fc-cache/Makefile.am index 7f7d1b1a0..0e1078629 100644 --- a/fontconfig/fc-cache/Makefile.am +++ b/fontconfig/fc-cache/Makefile.am @@ -36,7 +36,7 @@ uninstall-local: -$(RM) -rf "$(DESTDIR)$(fc_cachedir)" endif -INCLUDES=-I${top_srcdir} -I${top_srcdir}/src $(WARN_CFLAGS) +AM_CPPFLAGS=-I${top_srcdir} -I${top_srcdir}/src $(WARN_CFLAGS) bin_PROGRAMS=fc-cache diff --git a/fontconfig/fc-cat/Makefile.am b/fontconfig/fc-cat/Makefile.am index b426723ba..04c1cc48c 100644 --- a/fontconfig/fc-cat/Makefile.am +++ b/fontconfig/fc-cat/Makefile.am @@ -27,7 +27,7 @@ FC_CAT_SRC=${top_srcdir}/fc-cat SGML = ${FC_CAT_SRC}/fc-cat.sgml -INCLUDES=-I${top_srcdir} $(WARN_CFLAGS) +AM_CPPFLAGS=-I${top_srcdir} $(WARN_CFLAGS) bin_PROGRAMS=fc-cat diff --git a/fontconfig/fc-list/Makefile.am b/fontconfig/fc-list/Makefile.am index b2c499d23..c58540ec6 100644 --- a/fontconfig/fc-list/Makefile.am +++ b/fontconfig/fc-list/Makefile.am @@ -29,7 +29,7 @@ SGML = ${FC_LIST_SRC}/fc-list.sgml bin_PROGRAMS=fc-list -INCLUDES=-I${top_srcdir} $(WARN_CFLAGS) +AM_CPPFLAGS=-I${top_srcdir} $(WARN_CFLAGS) BUILT_MANS=fc-list.1 diff --git a/fontconfig/fc-match/Makefile.am b/fontconfig/fc-match/Makefile.am index 0e9e8fd0e..84afb8b26 100644 --- a/fontconfig/fc-match/Makefile.am +++ b/fontconfig/fc-match/Makefile.am @@ -29,7 +29,7 @@ FC_MATCH_SRC=${top_srcdir}/fc-match SGML = ${FC_MATCH_SRC}/fc-match.sgml -INCLUDES=-I${top_srcdir} $(WARN_CFLAGS) +AM_CPPFLAGS=-I${top_srcdir} $(WARN_CFLAGS) BUILT_MANS=fc-match.1 diff --git a/fontconfig/fc-pattern/Makefile.am b/fontconfig/fc-pattern/Makefile.am index 92b043398..c45624799 100644 --- a/fontconfig/fc-pattern/Makefile.am +++ b/fontconfig/fc-pattern/Makefile.am @@ -29,7 +29,7 @@ FC_PATTERN_SRC=${top_srcdir}/fc-pattern SGML = ${FC_PATTERN_SRC}/fc-pattern.sgml -INCLUDES=-I${top_srcdir} $(WARN_CFLAGS) +AM_CPPFLAGS=-I${top_srcdir} $(WARN_CFLAGS) BUILT_MANS=fc-pattern.1 diff --git a/fontconfig/fc-query/Makefile.am b/fontconfig/fc-query/Makefile.am index b3ea1e61d..73b3f11ee 100644 --- a/fontconfig/fc-query/Makefile.am +++ b/fontconfig/fc-query/Makefile.am @@ -29,7 +29,7 @@ FC_QUERY_SRC=${top_srcdir}/fc-query SGML = ${FC_QUERY_SRC}/fc-query.sgml -INCLUDES=-I${top_srcdir} $(FREETYPE_CFLAGS) $(WARN_CFLAGS) +AM_CPPFLAGS=-I${top_srcdir} $(FREETYPE_CFLAGS) $(WARN_CFLAGS) BUILT_MANS=fc-query.1 diff --git a/fontconfig/fc-scan/Makefile.am b/fontconfig/fc-scan/Makefile.am index 206340506..471a42fb6 100644 --- a/fontconfig/fc-scan/Makefile.am +++ b/fontconfig/fc-scan/Makefile.am @@ -29,7 +29,7 @@ FC_SCAN_SRC=${top_srcdir}/fc-scan SGML = ${FC_SCAN_SRC}/fc-scan.sgml -INCLUDES=-I${top_srcdir} $(FREETYPE_CFLAGS) $(WARN_CFLAGS) +AM_CPPFLAGS=-I${top_srcdir} $(FREETYPE_CFLAGS) $(WARN_CFLAGS) BUILT_MANS=fc-scan.1 diff --git a/fontconfig/fc-validate/Makefile.am b/fontconfig/fc-validate/Makefile.am index 54edec295..782ceadb8 100644 --- a/fontconfig/fc-validate/Makefile.am +++ b/fontconfig/fc-validate/Makefile.am @@ -29,7 +29,7 @@ FC_VALIDATE_SRC=${top_srcdir}/fc-validate SGML = ${FC_VALIDATE_SRC}/fc-validate.sgml -INCLUDES=-I${top_srcdir} $(FREETYPE_CFLAGS) $(WARN_CFLAGS) +AM_CPPFLAGS=-I${top_srcdir} $(FREETYPE_CFLAGS) $(WARN_CFLAGS) BUILT_MANS=fc-validate.1 diff --git a/fontconfig/fontconfig/fontconfig.h b/fontconfig/fontconfig/fontconfig.h index 194996587..361ca4f9e 100644 --- a/fontconfig/fontconfig/fontconfig.h +++ b/fontconfig/fontconfig/fontconfig.h @@ -52,7 +52,7 @@ typedef int FcBool; #define FC_MAJOR 2 #define FC_MINOR 10 -#define FC_REVISION 91 +#define FC_REVISION 92 #define FC_VERSION ((FC_MAJOR * 10000) + (FC_MINOR * 100) + (FC_REVISION)) diff --git a/fontconfig/new-version.sh b/fontconfig/new-version.sh index 39514302e..36e46f593 100644 --- a/fontconfig/new-version.sh +++ b/fontconfig/new-version.sh @@ -21,7 +21,7 @@ eval `echo $version | # Update the version numbers -sed -i configure.ac -e "/^AM_INIT_AUTOMAKE/s/2\.[0-9.]*/$version/" +sed -i configure.ac -e "/^AC_INIT(/s/2\.[0-9.]*/$version/" sed -i fontconfig/fontconfig.h \ -e "/^#define FC_MAJOR/s/[0-9][0-9]*/$major/" \ diff --git a/fontconfig/src/Makefile.am b/fontconfig/src/Makefile.am index 9fd7dd81a..066cc03e7 100644 --- a/fontconfig/src/Makefile.am +++ b/fontconfig/src/Makefile.am @@ -70,7 +70,7 @@ uninstall-ms-import-lib: endif -INCLUDES = \ +AM_CPPFLAGS = \ -I$(top_srcdir) \ -I$(top_srcdir)/src \ $(FREETYPE_CFLAGS) \ diff --git a/fontconfig/src/fcmatch.c b/fontconfig/src/fcmatch.c index 68f39aef5..2d7b79840 100644 --- a/fontconfig/src/fcmatch.c +++ b/fontconfig/src/fcmatch.c @@ -227,9 +227,10 @@ typedef enum _FcMatcherPriorityDummy { #undef FC_OBJECT #undef PRI1 -#define PRI1(n) \ - PRI_ ## n ## _STRONG, \ - PRI_ ## n ## _WEAK +#define PRI1(n) \ + PRI_ ## n, \ + PRI_ ## n ## _STRONG = PRI_ ## n, \ + PRI_ ## n ## _WEAK = PRI_ ## n typedef enum _FcMatcherPriority { PRI1(HASH), @@ -237,9 +238,8 @@ typedef enum _FcMatcherPriority { PRI1(FOUNDRY), PRI1(CHARSET), PRI_FAMILY_STRONG, - PRI_LANG_STRONG, PRI_POSTSCRIPT_NAME_STRONG, - PRI_LANG_WEAK, + PRI1(LANG), PRI_FAMILY_WEAK, PRI_POSTSCRIPT_NAME_WEAK, PRI1(SPACING), @@ -910,8 +910,7 @@ FcFontSetSort (FcConfig *config FC_UNUSED, * If this node matches any language, go check * which ones and satisfy those entries */ - if (nodeps[f]->score[PRI_LANG_STRONG] < 2000 || - nodeps[f]->score[PRI_LANG_WEAK] < 2000) + if (nodeps[f]->score[PRI_LANG] < 2000) { for (i = 0; i < nPatternLang; i++) { @@ -935,13 +934,6 @@ FcFontSetSort (FcConfig *config FC_UNUSED, } patternLangSat[i] = FcTrue; satisfies = FcTrue; - /* adjust score to ensure it's not more than 10000.0 - * which would means the lang didn't satisfy the requirements - */ - if (nodeps[f]->score[PRI_LANG_STRONG] > 10000.0) - nodeps[f]->score[PRI_LANG_STRONG] = 10000.0; - if (nodeps[f]->score[PRI_LANG_WEAK] > 10000.0) - nodeps[f]->score[PRI_LANG_WEAK] = 10000.0; break; } } @@ -949,8 +941,7 @@ FcFontSetSort (FcConfig *config FC_UNUSED, } if (!satisfies) { - nodeps[f]->score[PRI_LANG_STRONG] = 10000.0; - nodeps[f]->score[PRI_LANG_WEAK] = 10000.0; + nodeps[f]->score[PRI_LANG] = 10000.0; } } diff --git a/libXau/AuFileName.c b/libXau/AuFileName.c index 473fad110..090427387 100644 --- a/libXau/AuFileName.c +++ b/libXau/AuFileName.c @@ -57,9 +57,8 @@ XauFileName (void) name = getenv ("HOME"); if (!name) { #ifdef WIN32 - (void) strcpy (dir, "/users/"); if ((name = getenv("USERNAME"))) { - (void) strcat (dir, name); + snprintf(dir, sizeof(dir), "/users/%s", name); name = dir; } if (!name) @@ -81,7 +80,7 @@ XauFileName (void) bsize = size; } - strcpy (buf, name); - strcat (buf, slashDotXauthority + (name[1] == '\0' ? 1 : 0)); + snprintf (buf, bsize, "%s%s", name, + slashDotXauthority + (name[1] == '\0' ? 1 : 0)); return buf; } diff --git a/libXau/AuGetAddr.c b/libXau/AuGetAddr.c index 897d8b565..6f5fe16e4 100644 --- a/libXau/AuGetAddr.c +++ b/libXau/AuGetAddr.c @@ -30,14 +30,7 @@ in this Software without prior written authorization from The Open Group. #include <X11/Xauth.h> #include <X11/Xos.h> -static int -binaryEqual (_Xconst char *a, _Xconst char *b, int len) -{ - while (len--) - if (*a++ != *b++) - return 0; - return 1; -} +#define binaryEqual(a, b, len) (memcmp(a, b, len) == 0) Xauth * XauGetAuthByAddr ( @@ -94,13 +87,13 @@ _Xconst char* name) if ((family == FamilyWild || entry->family == FamilyWild || (entry->family == family && address_length == entry->address_length && - binaryEqual (entry->address, address, (int)address_length))) && + binaryEqual (entry->address, address, address_length))) && (number_length == 0 || entry->number_length == 0 || (number_length == entry->number_length && - binaryEqual (entry->number, number, (int)number_length))) && + binaryEqual (entry->number, number, number_length))) && (name_length == 0 || entry->name_length == 0 || (entry->name_length == name_length && - binaryEqual (entry->name, name, (int)name_length)))) + binaryEqual (entry->name, name, name_length)))) break; XauDisposeAuth (entry); } diff --git a/libXau/AuGetBest.c b/libXau/AuGetBest.c index 673ee406a..5556559ca 100644 --- a/libXau/AuGetBest.c +++ b/libXau/AuGetBest.c @@ -38,14 +38,7 @@ in this Software without prior written authorization from The Open Group. #include <X11/Xos_r.h> #endif -static int -binaryEqual (_Xconst char *a, _Xconst char *b, int len) -{ - while (len--) - if (*a++ != *b++) - return 0; - return 1; -} +#define binaryEqual(a, b, len) (memcmp(a, b, len) == 0) Xauth * XauGetBestAuthByAddr ( @@ -129,17 +122,17 @@ XauGetBestAuthByAddr ( if ((family == FamilyWild || entry->family == FamilyWild || (entry->family == family && ((address_length == entry->address_length && - binaryEqual (entry->address, address, (int)address_length)) + binaryEqual (entry->address, address, address_length)) #ifdef hpux || (family == FamilyLocal && fully_qual_address_length == entry->address_length && binaryEqual (entry->address, fully_qual_address, - (int) fully_qual_address_length)) + fully_qual_address_length)) #endif ))) && (number_length == 0 || entry->number_length == 0 || (number_length == entry->number_length && - binaryEqual (entry->number, number, (int)number_length)))) + binaryEqual (entry->number, number, number_length)))) { if (best_type == 0) { diff --git a/libXau/AuLock.c b/libXau/AuLock.c index 7bf9e5d30..5dfc1747e 100644 --- a/libXau/AuLock.c +++ b/libXau/AuLock.c @@ -33,15 +33,12 @@ in this Software without prior written authorization from The Open Group. #include <errno.h> #include <time.h> #define Time_t time_t -#ifndef X_NOT_POSIX -#include <unistd.h> -#else -#ifndef WIN32 -extern unsigned sleep (); -#else -#include <X11/Xwindows.h> -#define link rename +#ifdef HAVE_UNISTD_H +# include <unistd.h> #endif +#ifdef WIN32 +# include <X11/Xwindows.h> +# define link rename #endif int @@ -58,10 +55,8 @@ long dead) if (strlen (file_name) > 1022) return LOCK_ERROR; - (void) strcpy (creat_name, file_name); - (void) strcat (creat_name, "-c"); - (void) strcpy (link_name, file_name); - (void) strcat (link_name, "-l"); + snprintf (creat_name, sizeof(creat_name), "%s-c", file_name); + snprintf (link_name, sizeof(link_name), "%s-l", file_name); if (stat (creat_name, &statb) != -1) { now = time ((Time_t *) 0); /* @@ -69,8 +64,8 @@ long dead) * case a 0 deadtime to force lock removal */ if (dead == 0 || now - statb.st_ctime > dead) { - (void) unlink (creat_name); - (void) unlink (link_name); + (void) remove (creat_name); + (void) remove (link_name); } } @@ -84,7 +79,7 @@ long dead) (void) close (creat_fd); } if (creat_fd != -1) { -#ifndef X_NOT_POSIX +#ifdef HAVE_PATHCONF /* The file system may not support hard links, and pathconf should tell us that. */ if (1 == pathconf(creat_name, _PC_LINK_MAX)) { if (-1 == rename(creat_name, link_name)) { @@ -93,8 +88,9 @@ long dead) } else { return LOCK_SUCCESS; } - } else { + } else #endif + { if (link (creat_name, link_name) != -1) return LOCK_SUCCESS; if (errno == ENOENT) { @@ -103,9 +99,7 @@ long dead) } if (errno != EEXIST) return LOCK_ERROR; -#ifndef X_NOT_POSIX } -#endif } (void) sleep ((unsigned) timeout); --retries; diff --git a/libXau/AuUnlock.c b/libXau/AuUnlock.c index ddbe7db9e..b81724600 100644 --- a/libXau/AuUnlock.c +++ b/libXau/AuUnlock.c @@ -42,18 +42,16 @@ _Xconst char *file_name) if (strlen (file_name) > 1022) return 0; #ifndef WIN32 - (void) strcpy (creat_name, file_name); - (void) strcat (creat_name, "-c"); + snprintf (creat_name, sizeof(creat_name), "%s-c", file_name); #endif - (void) strcpy (link_name, file_name); - (void) strcat (link_name, "-l"); + snprintf (link_name, sizeof(link_name), "%s-l", file_name); /* * I think this is the correct order */ #ifndef WIN32 - (void) unlink (creat_name); + (void) remove (creat_name); #endif - (void) unlink (link_name); + (void) remove (link_name); return 1; } diff --git a/libXau/configure.ac b/libXau/configure.ac index 62a4717f5..e55cfceb6 100644 --- a/libXau/configure.ac +++ b/libXau/configure.ac @@ -26,6 +26,7 @@ AC_INIT([libXau], [1.0.7], [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], [libXau]) AC_CONFIG_SRCDIR([Makefile.am]) AC_CONFIG_HEADERS([config.h]) +AC_USE_SYSTEM_EXTENSIONS # Initialize Automake AM_INIT_AUTOMAKE([foreign dist-bzip2]) @@ -43,6 +44,9 @@ XORG_DEFAULT_OPTIONS # Checks for programs. AC_PROG_LN_S +# Checks for library functions. +AC_CHECK_FUNCS([pathconf]) + # Obtain compiler/linker options for depedencies PKG_CHECK_MODULES(XAU, xproto) diff --git a/mesalib/docs/GL3.txt b/mesalib/docs/GL3.txt index 640dec24c..d150b0874 100644 --- a/mesalib/docs/GL3.txt +++ b/mesalib/docs/GL3.txt @@ -87,7 +87,7 @@ GL_ARB_vertex_type_2_10_10_10_rev DONE (i965, r600) GL 4.0: GLSL 4.0 not started -GL_ARB_texture_query_lod not started +GL_ARB_texture_query_lod DONE (i965) GL_ARB_draw_buffers_blend DONE (i965, r600, softpipe) GL_ARB_draw_indirect not started GL_ARB_gpu_shader5 not started @@ -151,7 +151,7 @@ ARB_shader_storage_buffer_object not started ARB_stencil_texturing not started ARB_texture_buffer_range DONE (nv50, nvc0) ARB_texture_query_levels not started -ARB_texture_storage_multisample not started +ARB_texture_storage_multisample DONE (i965) ARB_texture_view not started ARB_vertex_attrib_binding not started diff --git a/mesalib/docs/application-issues.html b/mesalib/docs/application-issues.html new file mode 100644 index 000000000..6db086585 --- /dev/null +++ b/mesalib/docs/application-issues.html @@ -0,0 +1,83 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> +<html lang="en"> +<head> + <meta http-equiv="content-type" content="text/html; charset=utf-8"> + <title>Application Issues</title> + <link rel="stylesheet" type="text/css" href="mesa.css"> +</head> +<body> + +<div class="header"> + <h1>The Mesa 3D Graphics Library</h1> +</div> + +<iframe src="contents.html"></iframe> +<div class="content"> + +<h1>Application Issues</h1> + +<p> +This page documents known issues with some OpenGL applications. +</p> + + +<h2>Topogun</h2> + +<p> +<a href="http://www.topogun.com/">Topogun</a> for Linux (version 2, at least) +creates a GLX visual without requesting a depth buffer. +This causes bad rendering if the OpenGL driver happens to choose a visual +without a depth buffer. +</p> + +<p> +Mesa 9.1.2 and later (will) support a DRI configuration option to work around +this issue. +Using the <a href="http://dri.freedesktop.org/wiki/DriConf">driconf</a> tool, +set the "Create all visuals with a depth buffer" option before running Topogun. +Then, all GLX visuals will be created with a depth buffer. +</p> + + +<h2>Old OpenGL games</h2> + +<p> +Some old OpenGL games (approx. ten years or older) may crash during +start-up because of an extension string buffer-overflow problem. +</p> + +<p> +The problem is a modern OpenGL driver will return a very long string +for the glGetString(GL_EXTENSIONS) query and if the application +naively copies the string into a fixed-size buffer it can overflow the +buffer and crash the application. +</p> + +<p> +The work-around is to set the MESA_EXTENSION_MAX_YEAR environment variable +to the approximate release year of the game. +This will cause the glGetString(GL_EXTENSIONS) query to only report extensions +older than the given year. +</p> + +<p> +For example, if the game was released in 2001, do +<pre> +export MESA_EXTENSION_MAX_YEAR=2001 +</pre> +before running the game. +</p> + + + +<h2>Viewperf</h2> + +<p> +See the <a href="viewperf.html">Viewperf issues</a> page for a detailed list +of Viewperf issues. +</p> + + +</div> +</body> +</html> diff --git a/mesalib/docs/contents.html b/mesalib/docs/contents.html index 57522992c..50c0d5913 100644 --- a/mesalib/docs/contents.html +++ b/mesalib/docs/contents.html @@ -71,6 +71,7 @@ <li><a href="llvmpipe.html" target="_parent">Gallium llvmpipe driver</a> <li><a href="vmware-guest.html" target="_parent">VMware SVGA3D guest driver</a> <li><a href="postprocess.html" target="_parent">Gallium post-processing</a> +<li><a href="application-issues.html" target="_parent">Application Issues</a> <li><a href="viewperf.html" target="_parent">Viewperf Issues</a> </ul> diff --git a/mesalib/src/gallium/auxiliary/Makefile.sources b/mesalib/src/gallium/auxiliary/Makefile.sources index 898abe024..79def2177 100644 --- a/mesalib/src/gallium/auxiliary/Makefile.sources +++ b/mesalib/src/gallium/auxiliary/Makefile.sources @@ -37,6 +37,11 @@ C_SOURCES := \ draw/draw_vs.c \ draw/draw_vs_exec.c \ draw/draw_vs_variant.c \ + hud/font.c \ + hud/hud_context.c \ + hud/hud_cpu.c \ + hud/hud_fps.c \ + hud/hud_driver_query.c \ os/os_misc.c \ os/os_time.c \ pipebuffer/pb_buffer_fenced.c \ diff --git a/mesalib/src/gallium/auxiliary/hud/font.c b/mesalib/src/gallium/auxiliary/hud/font.c new file mode 100644 index 000000000..6747874ee --- /dev/null +++ b/mesalib/src/gallium/auxiliary/hud/font.c @@ -0,0 +1,446 @@ +/************************************************************************** + * + * Copyright 2013 Marek Olšák <maraeo@gmail.com> + * 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 THE AUTHORS 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. + * + **************************************************************************/ + +/* This is the "8_BY_13" font extracted from freeglut. */ + +/* + * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. + * Written by Pawel W. Olszta, <olszta@sourceforge.net> + * Creation date: Thu Dec 16 1999 + * + * 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 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 + * PAWEL W. OLSZTA 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 "hud/font.h" + +#include "pipe/p_compiler.h" +#include "pipe/p_screen.h" +#include "pipe/p_state.h" +#include "pipe/p_context.h" +#include "util/u_inlines.h" + +typedef unsigned char GLubyte; /* 1-byte unsigned */ +typedef struct tagSFG_Font SFG_Font; + +struct tagSFG_Font +{ + char* Name; /* The source font name */ + int Quantity; /* Number of chars in font */ + int Height; /* Height of the characters */ + const GLubyte** Characters; /* The characters mapping */ + + float xorig, yorig; /* Relative origin of the character */ +}; + +static const GLubyte Fixed8x13_Character_000[] = { 8, 0, 0, 0,170, 0,130, 0,130, 0,130, 0,170, 0, 0}; +static const GLubyte Fixed8x13_Character_001[] = { 8, 0, 0, 0, 0, 16, 56,124,254,124, 56, 16, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_002[] = { 8, 0,170, 85,170, 85,170, 85,170, 85,170, 85,170, 85,170}; +static const GLubyte Fixed8x13_Character_003[] = { 8, 0, 0, 0, 4, 4, 4, 4,174,160,224,160,160, 0, 0}; +static const GLubyte Fixed8x13_Character_004[] = { 8, 0, 0, 0, 8, 8, 12, 8,142,128,192,128,224, 0, 0}; +static const GLubyte Fixed8x13_Character_005[] = { 8, 0, 0, 0, 10, 10, 12, 10,108,128,128,128, 96, 0, 0}; +static const GLubyte Fixed8x13_Character_006[] = { 8, 0, 0, 0, 8, 8, 12, 8,238,128,128,128,128, 0, 0}; +static const GLubyte Fixed8x13_Character_007[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 24, 36, 36, 24, 0, 0}; +static const GLubyte Fixed8x13_Character_008[] = { 8, 0, 0, 0, 0,124, 0, 16, 16,124, 16, 16, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_009[] = { 8, 0, 0, 0, 14, 8, 8, 8,168,160,160,160,192, 0, 0}; +static const GLubyte Fixed8x13_Character_010[] = { 8, 0, 0, 0, 4, 4, 4, 4, 46, 80, 80,136,136, 0, 0}; +static const GLubyte Fixed8x13_Character_011[] = { 8, 0, 0, 0, 0, 0, 0, 0,240, 16, 16, 16, 16, 16, 16}; +static const GLubyte Fixed8x13_Character_012[] = { 8, 0, 16, 16, 16, 16, 16, 16,240, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_013[] = { 8, 0, 16, 16, 16, 16, 16, 16, 31, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_014[] = { 8, 0, 0, 0, 0, 0, 0, 0, 31, 16, 16, 16, 16, 16, 16}; +static const GLubyte Fixed8x13_Character_015[] = { 8, 0, 16, 16, 16, 16, 16, 16,255, 16, 16, 16, 16, 16, 16}; +static const GLubyte Fixed8x13_Character_016[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255}; +static const GLubyte Fixed8x13_Character_017[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_018[] = { 8, 0, 0, 0, 0, 0, 0, 0,255, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_019[] = { 8, 0, 0, 0, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_020[] = { 8, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_021[] = { 8, 0, 16, 16, 16, 16, 16, 16, 31, 16, 16, 16, 16, 16, 16}; +static const GLubyte Fixed8x13_Character_022[] = { 8, 0, 16, 16, 16, 16, 16, 16,240, 16, 16, 16, 16, 16, 16}; +static const GLubyte Fixed8x13_Character_023[] = { 8, 0, 0, 0, 0, 0, 0, 0,255, 16, 16, 16, 16, 16, 16}; +static const GLubyte Fixed8x13_Character_024[] = { 8, 0, 16, 16, 16, 16, 16, 16,255, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_025[] = { 8, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}; +static const GLubyte Fixed8x13_Character_026[] = { 8, 0, 0, 0,254, 0, 14, 48,192, 48, 14, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_027[] = { 8, 0, 0, 0,254, 0,224, 24, 6, 24,224, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_028[] = { 8, 0, 0, 0, 68, 68, 68, 68, 68,254, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_029[] = { 8, 0, 0, 0, 32, 32,126, 16, 8,126, 4, 4, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_030[] = { 8, 0, 0, 0,220, 98, 32, 32, 32,112, 32, 34, 28, 0, 0}; +static const GLubyte Fixed8x13_Character_031[] = { 8, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_032[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_033[] = { 8, 0, 0, 0, 16, 0, 16, 16, 16, 16, 16, 16, 16, 0, 0}; +static const GLubyte Fixed8x13_Character_034[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 36, 36, 0, 0}; +static const GLubyte Fixed8x13_Character_035[] = { 8, 0, 0, 0, 0, 36, 36,126, 36,126, 36, 36, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_036[] = { 8, 0, 0, 0, 16,120, 20, 20, 56, 80, 80, 60, 16, 0, 0}; +static const GLubyte Fixed8x13_Character_037[] = { 8, 0, 0, 0, 68, 42, 36, 16, 8, 8, 36, 82, 34, 0, 0}; +static const GLubyte Fixed8x13_Character_038[] = { 8, 0, 0, 0, 58, 68, 74, 48, 72, 72, 48, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_039[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 48, 56, 0, 0}; +static const GLubyte Fixed8x13_Character_040[] = { 8, 0, 0, 0, 4, 8, 8, 16, 16, 16, 8, 8, 4, 0, 0}; +static const GLubyte Fixed8x13_Character_041[] = { 8, 0, 0, 0, 32, 16, 16, 8, 8, 8, 16, 16, 32, 0, 0}; +static const GLubyte Fixed8x13_Character_042[] = { 8, 0, 0, 0, 0, 0, 36, 24,126, 24, 36, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_043[] = { 8, 0, 0, 0, 0, 0, 16, 16,124, 16, 16, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_044[] = { 8, 0, 0, 64, 48, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_045[] = { 8, 0, 0, 0, 0, 0, 0, 0,126, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_046[] = { 8, 0, 0, 16, 56, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_047[] = { 8, 0, 0, 0,128,128, 64, 32, 16, 8, 4, 2, 2, 0, 0}; +static const GLubyte Fixed8x13_Character_048[] = { 8, 0, 0, 0, 24, 36, 66, 66, 66, 66, 66, 36, 24, 0, 0}; +static const GLubyte Fixed8x13_Character_049[] = { 8, 0, 0, 0,124, 16, 16, 16, 16, 16, 80, 48, 16, 0, 0}; +static const GLubyte Fixed8x13_Character_050[] = { 8, 0, 0, 0,126, 64, 32, 24, 4, 2, 66, 66, 60, 0, 0}; +static const GLubyte Fixed8x13_Character_051[] = { 8, 0, 0, 0, 60, 66, 2, 2, 28, 8, 4, 2,126, 0, 0}; +static const GLubyte Fixed8x13_Character_052[] = { 8, 0, 0, 0, 4, 4,126, 68, 68, 36, 20, 12, 4, 0, 0}; +static const GLubyte Fixed8x13_Character_053[] = { 8, 0, 0, 0, 60, 66, 2, 2, 98, 92, 64, 64,126, 0, 0}; +static const GLubyte Fixed8x13_Character_054[] = { 8, 0, 0, 0, 60, 66, 66, 98, 92, 64, 64, 32, 28, 0, 0}; +static const GLubyte Fixed8x13_Character_055[] = { 8, 0, 0, 0, 32, 32, 16, 16, 8, 8, 4, 2,126, 0, 0}; +static const GLubyte Fixed8x13_Character_056[] = { 8, 0, 0, 0, 60, 66, 66, 66, 60, 66, 66, 66, 60, 0, 0}; +static const GLubyte Fixed8x13_Character_057[] = { 8, 0, 0, 0, 56, 4, 2, 2, 58, 70, 66, 66, 60, 0, 0}; +static const GLubyte Fixed8x13_Character_058[] = { 8, 0, 0, 16, 56, 16, 0, 0, 16, 56, 16, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_059[] = { 8, 0, 0, 64, 48, 56, 0, 0, 16, 56, 16, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_060[] = { 8, 0, 0, 0, 2, 4, 8, 16, 32, 16, 8, 4, 2, 0, 0}; +static const GLubyte Fixed8x13_Character_061[] = { 8, 0, 0, 0, 0, 0,126, 0, 0,126, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_062[] = { 8, 0, 0, 0, 64, 32, 16, 8, 4, 8, 16, 32, 64, 0, 0}; +static const GLubyte Fixed8x13_Character_063[] = { 8, 0, 0, 0, 8, 0, 8, 8, 4, 2, 66, 66, 60, 0, 0}; +static const GLubyte Fixed8x13_Character_064[] = { 8, 0, 0, 0, 60, 64, 74, 86, 82, 78, 66, 66, 60, 0, 0}; +static const GLubyte Fixed8x13_Character_065[] = { 8, 0, 0, 0, 66, 66, 66,126, 66, 66, 66, 36, 24, 0, 0}; +static const GLubyte Fixed8x13_Character_066[] = { 8, 0, 0, 0,252, 66, 66, 66,124, 66, 66, 66,252, 0, 0}; +static const GLubyte Fixed8x13_Character_067[] = { 8, 0, 0, 0, 60, 66, 64, 64, 64, 64, 64, 66, 60, 0, 0}; +static const GLubyte Fixed8x13_Character_068[] = { 8, 0, 0, 0,252, 66, 66, 66, 66, 66, 66, 66,252, 0, 0}; +static const GLubyte Fixed8x13_Character_069[] = { 8, 0, 0, 0,126, 64, 64, 64,120, 64, 64, 64,126, 0, 0}; +static const GLubyte Fixed8x13_Character_070[] = { 8, 0, 0, 0, 64, 64, 64, 64,120, 64, 64, 64,126, 0, 0}; +static const GLubyte Fixed8x13_Character_071[] = { 8, 0, 0, 0, 58, 70, 66, 78, 64, 64, 64, 66, 60, 0, 0}; +static const GLubyte Fixed8x13_Character_072[] = { 8, 0, 0, 0, 66, 66, 66, 66,126, 66, 66, 66, 66, 0, 0}; +static const GLubyte Fixed8x13_Character_073[] = { 8, 0, 0, 0,124, 16, 16, 16, 16, 16, 16, 16,124, 0, 0}; +static const GLubyte Fixed8x13_Character_074[] = { 8, 0, 0, 0, 56, 68, 4, 4, 4, 4, 4, 4, 31, 0, 0}; +static const GLubyte Fixed8x13_Character_075[] = { 8, 0, 0, 0, 66, 68, 72, 80, 96, 80, 72, 68, 66, 0, 0}; +static const GLubyte Fixed8x13_Character_076[] = { 8, 0, 0, 0,126, 64, 64, 64, 64, 64, 64, 64, 64, 0, 0}; +static const GLubyte Fixed8x13_Character_077[] = { 8, 0, 0, 0,130,130,130,146,146,170,198,130,130, 0, 0}; +static const GLubyte Fixed8x13_Character_078[] = { 8, 0, 0, 0, 66, 66, 66, 70, 74, 82, 98, 66, 66, 0, 0}; +static const GLubyte Fixed8x13_Character_079[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66, 66, 66, 66, 60, 0, 0}; +static const GLubyte Fixed8x13_Character_080[] = { 8, 0, 0, 0, 64, 64, 64, 64,124, 66, 66, 66,124, 0, 0}; +static const GLubyte Fixed8x13_Character_081[] = { 8, 0, 0, 2, 60, 74, 82, 66, 66, 66, 66, 66, 60, 0, 0}; +static const GLubyte Fixed8x13_Character_082[] = { 8, 0, 0, 0, 66, 68, 72, 80,124, 66, 66, 66,124, 0, 0}; +static const GLubyte Fixed8x13_Character_083[] = { 8, 0, 0, 0, 60, 66, 2, 2, 60, 64, 64, 66, 60, 0, 0}; +static const GLubyte Fixed8x13_Character_084[] = { 8, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16,254, 0, 0}; +static const GLubyte Fixed8x13_Character_085[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66, 66, 66, 66, 66, 0, 0}; +static const GLubyte Fixed8x13_Character_086[] = { 8, 0, 0, 0, 16, 40, 40, 40, 68, 68, 68,130,130, 0, 0}; +static const GLubyte Fixed8x13_Character_087[] = { 8, 0, 0, 0, 68,170,146,146,146,130,130,130,130, 0, 0}; +static const GLubyte Fixed8x13_Character_088[] = { 8, 0, 0, 0,130,130, 68, 40, 16, 40, 68,130,130, 0, 0}; +static const GLubyte Fixed8x13_Character_089[] = { 8, 0, 0, 0, 16, 16, 16, 16, 16, 40, 68,130,130, 0, 0}; +static const GLubyte Fixed8x13_Character_090[] = { 8, 0, 0, 0,126, 64, 64, 32, 16, 8, 4, 2,126, 0, 0}; +static const GLubyte Fixed8x13_Character_091[] = { 8, 0, 0, 0, 60, 32, 32, 32, 32, 32, 32, 32, 60, 0, 0}; +static const GLubyte Fixed8x13_Character_092[] = { 8, 0, 0, 0, 2, 2, 4, 8, 16, 32, 64,128,128, 0, 0}; +static const GLubyte Fixed8x13_Character_093[] = { 8, 0, 0, 0,120, 8, 8, 8, 8, 8, 8, 8,120, 0, 0}; +static const GLubyte Fixed8x13_Character_094[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 40, 16, 0, 0}; +static const GLubyte Fixed8x13_Character_095[] = { 8, 0, 0,254, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_096[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 24, 56, 0, 0}; +static const GLubyte Fixed8x13_Character_097[] = { 8, 0, 0, 0, 58, 70, 66, 62, 2, 60, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_098[] = { 8, 0, 0, 0, 92, 98, 66, 66, 98, 92, 64, 64, 64, 0, 0}; +static const GLubyte Fixed8x13_Character_099[] = { 8, 0, 0, 0, 60, 66, 64, 64, 66, 60, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_100[] = { 8, 0, 0, 0, 58, 70, 66, 66, 70, 58, 2, 2, 2, 0, 0}; +static const GLubyte Fixed8x13_Character_101[] = { 8, 0, 0, 0, 60, 66, 64,126, 66, 60, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_102[] = { 8, 0, 0, 0, 32, 32, 32, 32,124, 32, 32, 34, 28, 0, 0}; +static const GLubyte Fixed8x13_Character_103[] = { 8, 0, 60, 66, 60, 64, 56, 68, 68, 58, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_104[] = { 8, 0, 0, 0, 66, 66, 66, 66, 98, 92, 64, 64, 64, 0, 0}; +static const GLubyte Fixed8x13_Character_105[] = { 8, 0, 0, 0,124, 16, 16, 16, 16, 48, 0, 16, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_106[] = { 8, 0, 56, 68, 68, 4, 4, 4, 4, 12, 0, 4, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_107[] = { 8, 0, 0, 0, 66, 68, 72,112, 72, 68, 64, 64, 64, 0, 0}; +static const GLubyte Fixed8x13_Character_108[] = { 8, 0, 0, 0,124, 16, 16, 16, 16, 16, 16, 16, 48, 0, 0}; +static const GLubyte Fixed8x13_Character_109[] = { 8, 0, 0, 0,130,146,146,146,146,236, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_110[] = { 8, 0, 0, 0, 66, 66, 66, 66, 98, 92, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_111[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66, 60, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_112[] = { 8, 0, 64, 64, 64, 92, 98, 66, 98, 92, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_113[] = { 8, 0, 2, 2, 2, 58, 70, 66, 70, 58, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_114[] = { 8, 0, 0, 0, 32, 32, 32, 32, 34, 92, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_115[] = { 8, 0, 0, 0, 60, 66, 12, 48, 66, 60, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_116[] = { 8, 0, 0, 0, 28, 34, 32, 32, 32,124, 32, 32, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_117[] = { 8, 0, 0, 0, 58, 68, 68, 68, 68, 68, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_118[] = { 8, 0, 0, 0, 16, 40, 40, 68, 68, 68, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_119[] = { 8, 0, 0, 0, 68,170,146,146,130,130, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_120[] = { 8, 0, 0, 0, 66, 36, 24, 24, 36, 66, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_121[] = { 8, 0, 60, 66, 2, 58, 70, 66, 66, 66, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_122[] = { 8, 0, 0, 0,126, 32, 16, 8, 4,126, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_123[] = { 8, 0, 0, 0, 14, 16, 16, 8, 48, 8, 16, 16, 14, 0, 0}; +static const GLubyte Fixed8x13_Character_124[] = { 8, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0}; +static const GLubyte Fixed8x13_Character_125[] = { 8, 0, 0, 0,112, 8, 8, 16, 12, 16, 8, 8,112, 0, 0}; +static const GLubyte Fixed8x13_Character_126[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 84, 36, 0, 0}; +static const GLubyte Fixed8x13_Character_127[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_128[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_129[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_130[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_131[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_132[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_133[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_134[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_135[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_136[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_137[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_138[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_139[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_140[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_141[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_142[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_143[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_144[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_145[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_146[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_147[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_148[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_149[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_150[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_151[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_152[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_153[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_154[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_155[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_156[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_157[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_158[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_159[] = { 9, 0, 0, 0, 0, 0, 0,170, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,130, 0, 0, 0,170, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_160[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_161[] = { 8, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 0, 16, 0, 0}; +static const GLubyte Fixed8x13_Character_162[] = { 8, 0, 0, 0, 0, 16, 56, 84, 80, 80, 84, 56, 16, 0, 0}; +static const GLubyte Fixed8x13_Character_163[] = { 8, 0, 0, 0,220, 98, 32, 32, 32,112, 32, 34, 28, 0, 0}; +static const GLubyte Fixed8x13_Character_164[] = { 8, 0, 0, 0, 0, 66, 60, 36, 36, 60, 66, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_165[] = { 8, 0, 0, 0, 16, 16,124, 16,124, 40, 68,130,130, 0, 0}; +static const GLubyte Fixed8x13_Character_166[] = { 8, 0, 0, 0, 16, 16, 16, 16, 0, 16, 16, 16, 16, 0, 0}; +static const GLubyte Fixed8x13_Character_167[] = { 8, 0, 0, 0, 24, 36, 4, 24, 36, 36, 24, 32, 36, 24, 0}; +static const GLubyte Fixed8x13_Character_168[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,108, 0, 0}; +static const GLubyte Fixed8x13_Character_169[] = { 8, 0, 0, 0, 0, 56, 68,146,170,162,170,146, 68, 56, 0}; +static const GLubyte Fixed8x13_Character_170[] = { 8, 0, 0, 0, 0, 0,124, 0, 60, 68, 60, 4, 56, 0, 0}; +static const GLubyte Fixed8x13_Character_171[] = { 8, 0, 0, 0, 0, 18, 36, 72,144, 72, 36, 18, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_172[] = { 8, 0, 0, 0, 0, 2, 2, 2,126, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_173[] = { 8, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_174[] = { 8, 0, 0, 0, 0, 56, 68,170,178,170,170,146, 68, 56, 0}; +static const GLubyte Fixed8x13_Character_175[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,126, 0, 0}; +static const GLubyte Fixed8x13_Character_176[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 24, 36, 36, 24, 0, 0}; +static const GLubyte Fixed8x13_Character_177[] = { 8, 0, 0, 0, 0,124, 0, 16, 16,124, 16, 16, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_178[] = { 8, 0, 0, 0, 0, 0, 0, 0,120, 64, 48, 8, 72, 48, 0}; +static const GLubyte Fixed8x13_Character_179[] = { 8, 0, 0, 0, 0, 0, 0, 0, 48, 72, 8, 16, 72, 48, 0}; +static const GLubyte Fixed8x13_Character_180[] = { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 8, 0}; +static const GLubyte Fixed8x13_Character_181[] = { 8, 0, 0, 64, 90,102, 66, 66, 66, 66, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_182[] = { 8, 0, 0, 0, 20, 20, 20, 20, 52,116,116,116, 62, 0, 0}; +static const GLubyte Fixed8x13_Character_183[] = { 8, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_184[] = { 8, 0, 24, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_185[] = { 8, 0, 0, 0, 0, 0, 0, 0,112, 32, 32, 32, 96, 32, 0}; +static const GLubyte Fixed8x13_Character_186[] = { 8, 0, 0, 0, 0, 0, 0,120, 0, 48, 72, 72, 48, 0, 0}; +static const GLubyte Fixed8x13_Character_187[] = { 8, 0, 0, 0, 0,144, 72, 36, 18, 36, 72,144, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_188[] = { 8, 0, 0, 0, 6, 26, 18, 10,230, 66, 64, 64,192, 64, 0}; +static const GLubyte Fixed8x13_Character_189[] = { 8, 0, 0, 0, 30, 16, 12, 2,242, 76, 64, 64,192, 64, 0}; +static const GLubyte Fixed8x13_Character_190[] = { 8, 0, 0, 0, 6, 26, 18, 10,102,146, 16, 32,144, 96, 0}; +static const GLubyte Fixed8x13_Character_191[] = { 8, 0, 0, 0, 60, 66, 66, 64, 32, 16, 16, 0, 16, 0, 0}; +static const GLubyte Fixed8x13_Character_192[] = { 8, 0, 0, 0, 66, 66,126, 66, 66, 36, 24, 0, 8, 16, 0}; +static const GLubyte Fixed8x13_Character_193[] = { 8, 0, 0, 0, 66, 66,126, 66, 66, 36, 24, 0, 16, 8, 0}; +static const GLubyte Fixed8x13_Character_194[] = { 8, 0, 0, 0, 66, 66,126, 66, 66, 36, 24, 0, 36, 24, 0}; +static const GLubyte Fixed8x13_Character_195[] = { 8, 0, 0, 0, 66, 66,126, 66, 66, 36, 24, 0, 76, 50, 0}; +static const GLubyte Fixed8x13_Character_196[] = { 8, 0, 0, 0, 66, 66,126, 66, 66, 36, 24, 0, 36, 36, 0}; +static const GLubyte Fixed8x13_Character_197[] = { 8, 0, 0, 0, 66, 66,126, 66, 66, 36, 24, 24, 36, 24, 0}; +static const GLubyte Fixed8x13_Character_198[] = { 8, 0, 0, 0,158,144,144,240,156,144,144,144,110, 0, 0}; +static const GLubyte Fixed8x13_Character_199[] = { 8, 0, 16, 8, 60, 66, 64, 64, 64, 64, 64, 66, 60, 0, 0}; +static const GLubyte Fixed8x13_Character_200[] = { 8, 0, 0, 0,126, 64, 64,120, 64, 64,126, 0, 8, 16, 0}; +static const GLubyte Fixed8x13_Character_201[] = { 8, 0, 0, 0,126, 64, 64,120, 64, 64,126, 0, 16, 8, 0}; +static const GLubyte Fixed8x13_Character_202[] = { 8, 0, 0, 0,126, 64, 64,120, 64, 64,126, 0, 36, 24, 0}; +static const GLubyte Fixed8x13_Character_203[] = { 8, 0, 0, 0,126, 64, 64,120, 64, 64,126, 0, 36, 36, 0}; +static const GLubyte Fixed8x13_Character_204[] = { 8, 0, 0, 0,124, 16, 16, 16, 16, 16,124, 0, 16, 32, 0}; +static const GLubyte Fixed8x13_Character_205[] = { 8, 0, 0, 0,124, 16, 16, 16, 16, 16,124, 0, 16, 8, 0}; +static const GLubyte Fixed8x13_Character_206[] = { 8, 0, 0, 0,124, 16, 16, 16, 16, 16,124, 0, 36, 24, 0}; +static const GLubyte Fixed8x13_Character_207[] = { 8, 0, 0, 0,124, 16, 16, 16, 16, 16,124, 0, 40, 40, 0}; +static const GLubyte Fixed8x13_Character_208[] = { 8, 0, 0, 0,120, 68, 66, 66,226, 66, 66, 68,120, 0, 0}; +static const GLubyte Fixed8x13_Character_209[] = { 8, 0, 0, 0,130,134,138,146,162,194,130, 0,152,100, 0}; +static const GLubyte Fixed8x13_Character_210[] = { 8, 0, 0, 0,124,130,130,130,130,130,124, 0, 16, 32, 0}; +static const GLubyte Fixed8x13_Character_211[] = { 8, 0, 0, 0,124,130,130,130,130,130,124, 0, 16, 8, 0}; +static const GLubyte Fixed8x13_Character_212[] = { 8, 0, 0, 0,124,130,130,130,130,130,124, 0, 36, 24, 0}; +static const GLubyte Fixed8x13_Character_213[] = { 8, 0, 0, 0,124,130,130,130,130,130,124, 0,152,100, 0}; +static const GLubyte Fixed8x13_Character_214[] = { 8, 0, 0, 0,124,130,130,130,130,130,124, 0, 40, 40, 0}; +static const GLubyte Fixed8x13_Character_215[] = { 8, 0, 0, 0, 0, 66, 36, 24, 24, 36, 66, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_216[] = { 8, 0, 0, 64, 60, 98, 82, 82, 82, 74, 74, 70, 60, 2, 0}; +static const GLubyte Fixed8x13_Character_217[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66, 66, 66, 0, 8, 16, 0}; +static const GLubyte Fixed8x13_Character_218[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66, 66, 66, 0, 16, 8, 0}; +static const GLubyte Fixed8x13_Character_219[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66, 66, 66, 0, 36, 24, 0}; +static const GLubyte Fixed8x13_Character_220[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66, 66, 66, 0, 36, 36, 0}; +static const GLubyte Fixed8x13_Character_221[] = { 8, 0, 0, 0, 16, 16, 16, 16, 40, 68, 68, 0, 16, 8, 0}; +static const GLubyte Fixed8x13_Character_222[] = { 8, 0, 0, 0, 64, 64, 64,124, 66, 66, 66,124, 64, 0, 0}; +static const GLubyte Fixed8x13_Character_223[] = { 8, 0, 0, 0, 92, 66, 66, 76, 80, 72, 68, 68, 56, 0, 0}; +static const GLubyte Fixed8x13_Character_224[] = { 8, 0, 0, 0, 58, 70, 66, 62, 2, 60, 0, 0, 8, 16, 0}; +static const GLubyte Fixed8x13_Character_225[] = { 8, 0, 0, 0, 58, 70, 66, 62, 2, 60, 0, 0, 8, 4, 0}; +static const GLubyte Fixed8x13_Character_226[] = { 8, 0, 0, 0, 58, 70, 66, 62, 2, 60, 0, 0, 36, 24, 0}; +static const GLubyte Fixed8x13_Character_227[] = { 8, 0, 0, 0, 58, 70, 66, 62, 2, 60, 0, 0, 76, 50, 0}; +static const GLubyte Fixed8x13_Character_228[] = { 8, 0, 0, 0, 58, 70, 66, 62, 2, 60, 0, 0, 36, 36, 0}; +static const GLubyte Fixed8x13_Character_229[] = { 8, 0, 0, 0, 58, 70, 66, 62, 2, 60, 0, 24, 36, 24, 0}; +static const GLubyte Fixed8x13_Character_230[] = { 8, 0, 0, 0,108,146,144,124, 18,108, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_231[] = { 8, 0, 16, 8, 60, 66, 64, 64, 66, 60, 0, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_232[] = { 8, 0, 0, 0, 60, 66, 64,126, 66, 60, 0, 0, 8, 16, 0}; +static const GLubyte Fixed8x13_Character_233[] = { 8, 0, 0, 0, 60, 66, 64,126, 66, 60, 0, 0, 16, 8, 0}; +static const GLubyte Fixed8x13_Character_234[] = { 8, 0, 0, 0, 60, 66, 64,126, 66, 60, 0, 0, 36, 24, 0}; +static const GLubyte Fixed8x13_Character_235[] = { 8, 0, 0, 0, 60, 66, 64,126, 66, 60, 0, 0, 36, 36, 0}; +static const GLubyte Fixed8x13_Character_236[] = { 8, 0, 0, 0,124, 16, 16, 16, 16, 48, 0, 0, 16, 32, 0}; +static const GLubyte Fixed8x13_Character_237[] = { 8, 0, 0, 0,124, 16, 16, 16, 16, 48, 0, 0, 32, 16, 0}; +static const GLubyte Fixed8x13_Character_238[] = { 8, 0, 0, 0,124, 16, 16, 16, 16, 48, 0, 0, 72, 48, 0}; +static const GLubyte Fixed8x13_Character_239[] = { 8, 0, 0, 0,124, 16, 16, 16, 16, 48, 0, 0, 40, 40, 0}; +static const GLubyte Fixed8x13_Character_240[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66, 60, 4, 40, 24, 36, 0}; +static const GLubyte Fixed8x13_Character_241[] = { 8, 0, 0, 0, 66, 66, 66, 66, 98, 92, 0, 0, 76, 50, 0}; +static const GLubyte Fixed8x13_Character_242[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66, 60, 0, 0, 16, 32, 0}; +static const GLubyte Fixed8x13_Character_243[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66, 60, 0, 0, 16, 8, 0}; +static const GLubyte Fixed8x13_Character_244[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66, 60, 0, 0, 36, 24, 0}; +static const GLubyte Fixed8x13_Character_245[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66, 60, 0, 0, 76, 50, 0}; +static const GLubyte Fixed8x13_Character_246[] = { 8, 0, 0, 0, 60, 66, 66, 66, 66, 60, 0, 0, 36, 36, 0}; +static const GLubyte Fixed8x13_Character_247[] = { 8, 0, 0, 0, 0, 16, 16, 0,124, 0, 16, 16, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_248[] = { 8, 0, 0, 64, 60, 98, 82, 74, 70, 60, 2, 0, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_249[] = { 8, 0, 0, 0, 58, 68, 68, 68, 68, 68, 0, 0, 16, 32, 0}; +static const GLubyte Fixed8x13_Character_250[] = { 8, 0, 0, 0, 58, 68, 68, 68, 68, 68, 0, 0, 16, 8, 0}; +static const GLubyte Fixed8x13_Character_251[] = { 8, 0, 0, 0, 58, 68, 68, 68, 68, 68, 0, 0, 36, 24, 0}; +static const GLubyte Fixed8x13_Character_252[] = { 8, 0, 0, 0, 58, 68, 68, 68, 68, 68, 0, 0, 40, 40, 0}; +static const GLubyte Fixed8x13_Character_253[] = { 8, 0, 60, 66, 2, 58, 70, 66, 66, 66, 0, 0, 16, 8, 0}; +static const GLubyte Fixed8x13_Character_254[] = { 8, 0, 64, 64, 92, 98, 66, 66, 98, 92, 64, 64, 0, 0, 0}; +static const GLubyte Fixed8x13_Character_255[] = { 8, 0, 60, 66, 2, 58, 70, 66, 66, 66, 0, 0, 36, 36, 0}; + +/* The font characters mapping: */ +static const GLubyte* Fixed8x13_Character_Map[] = {Fixed8x13_Character_000,Fixed8x13_Character_001,Fixed8x13_Character_002,Fixed8x13_Character_003,Fixed8x13_Character_004,Fixed8x13_Character_005,Fixed8x13_Character_006,Fixed8x13_Character_007,Fixed8x13_Character_008,Fixed8x13_Character_009,Fixed8x13_Character_010,Fixed8x13_Character_011,Fixed8x13_Character_012,Fixed8x13_Character_013,Fixed8x13_Character_014,Fixed8x13_Character_015, + Fixed8x13_Character_016,Fixed8x13_Character_017,Fixed8x13_Character_018,Fixed8x13_Character_019,Fixed8x13_Character_020,Fixed8x13_Character_021,Fixed8x13_Character_022,Fixed8x13_Character_023,Fixed8x13_Character_024,Fixed8x13_Character_025,Fixed8x13_Character_026,Fixed8x13_Character_027,Fixed8x13_Character_028,Fixed8x13_Character_029,Fixed8x13_Character_030,Fixed8x13_Character_031, + Fixed8x13_Character_032,Fixed8x13_Character_033,Fixed8x13_Character_034,Fixed8x13_Character_035,Fixed8x13_Character_036,Fixed8x13_Character_037,Fixed8x13_Character_038,Fixed8x13_Character_039,Fixed8x13_Character_040,Fixed8x13_Character_041,Fixed8x13_Character_042,Fixed8x13_Character_043,Fixed8x13_Character_044,Fixed8x13_Character_045,Fixed8x13_Character_046,Fixed8x13_Character_047, + Fixed8x13_Character_048,Fixed8x13_Character_049,Fixed8x13_Character_050,Fixed8x13_Character_051,Fixed8x13_Character_052,Fixed8x13_Character_053,Fixed8x13_Character_054,Fixed8x13_Character_055,Fixed8x13_Character_056,Fixed8x13_Character_057,Fixed8x13_Character_058,Fixed8x13_Character_059,Fixed8x13_Character_060,Fixed8x13_Character_061,Fixed8x13_Character_062,Fixed8x13_Character_063, + Fixed8x13_Character_064,Fixed8x13_Character_065,Fixed8x13_Character_066,Fixed8x13_Character_067,Fixed8x13_Character_068,Fixed8x13_Character_069,Fixed8x13_Character_070,Fixed8x13_Character_071,Fixed8x13_Character_072,Fixed8x13_Character_073,Fixed8x13_Character_074,Fixed8x13_Character_075,Fixed8x13_Character_076,Fixed8x13_Character_077,Fixed8x13_Character_078,Fixed8x13_Character_079, + Fixed8x13_Character_080,Fixed8x13_Character_081,Fixed8x13_Character_082,Fixed8x13_Character_083,Fixed8x13_Character_084,Fixed8x13_Character_085,Fixed8x13_Character_086,Fixed8x13_Character_087,Fixed8x13_Character_088,Fixed8x13_Character_089,Fixed8x13_Character_090,Fixed8x13_Character_091,Fixed8x13_Character_092,Fixed8x13_Character_093,Fixed8x13_Character_094,Fixed8x13_Character_095, + Fixed8x13_Character_096,Fixed8x13_Character_097,Fixed8x13_Character_098,Fixed8x13_Character_099,Fixed8x13_Character_100,Fixed8x13_Character_101,Fixed8x13_Character_102,Fixed8x13_Character_103,Fixed8x13_Character_104,Fixed8x13_Character_105,Fixed8x13_Character_106,Fixed8x13_Character_107,Fixed8x13_Character_108,Fixed8x13_Character_109,Fixed8x13_Character_110,Fixed8x13_Character_111, + Fixed8x13_Character_112,Fixed8x13_Character_113,Fixed8x13_Character_114,Fixed8x13_Character_115,Fixed8x13_Character_116,Fixed8x13_Character_117,Fixed8x13_Character_118,Fixed8x13_Character_119,Fixed8x13_Character_120,Fixed8x13_Character_121,Fixed8x13_Character_122,Fixed8x13_Character_123,Fixed8x13_Character_124,Fixed8x13_Character_125,Fixed8x13_Character_126,Fixed8x13_Character_032, + Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032, + Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032,Fixed8x13_Character_032, + Fixed8x13_Character_160,Fixed8x13_Character_161,Fixed8x13_Character_162,Fixed8x13_Character_163,Fixed8x13_Character_164,Fixed8x13_Character_165,Fixed8x13_Character_166,Fixed8x13_Character_167,Fixed8x13_Character_168,Fixed8x13_Character_169,Fixed8x13_Character_170,Fixed8x13_Character_171,Fixed8x13_Character_172,Fixed8x13_Character_173,Fixed8x13_Character_174,Fixed8x13_Character_175, + Fixed8x13_Character_176,Fixed8x13_Character_177,Fixed8x13_Character_178,Fixed8x13_Character_179,Fixed8x13_Character_180,Fixed8x13_Character_181,Fixed8x13_Character_182,Fixed8x13_Character_183,Fixed8x13_Character_184,Fixed8x13_Character_185,Fixed8x13_Character_186,Fixed8x13_Character_187,Fixed8x13_Character_188,Fixed8x13_Character_189,Fixed8x13_Character_190,Fixed8x13_Character_191, + Fixed8x13_Character_192,Fixed8x13_Character_193,Fixed8x13_Character_194,Fixed8x13_Character_195,Fixed8x13_Character_196,Fixed8x13_Character_197,Fixed8x13_Character_198,Fixed8x13_Character_199,Fixed8x13_Character_200,Fixed8x13_Character_201,Fixed8x13_Character_202,Fixed8x13_Character_203,Fixed8x13_Character_204,Fixed8x13_Character_205,Fixed8x13_Character_206,Fixed8x13_Character_207, + Fixed8x13_Character_208,Fixed8x13_Character_209,Fixed8x13_Character_210,Fixed8x13_Character_211,Fixed8x13_Character_212,Fixed8x13_Character_213,Fixed8x13_Character_214,Fixed8x13_Character_215,Fixed8x13_Character_216,Fixed8x13_Character_217,Fixed8x13_Character_218,Fixed8x13_Character_219,Fixed8x13_Character_220,Fixed8x13_Character_221,Fixed8x13_Character_222,Fixed8x13_Character_223, + Fixed8x13_Character_224,Fixed8x13_Character_225,Fixed8x13_Character_226,Fixed8x13_Character_227,Fixed8x13_Character_228,Fixed8x13_Character_229,Fixed8x13_Character_230,Fixed8x13_Character_231,Fixed8x13_Character_232,Fixed8x13_Character_233,Fixed8x13_Character_234,Fixed8x13_Character_235,Fixed8x13_Character_236,Fixed8x13_Character_237,Fixed8x13_Character_238,Fixed8x13_Character_239, + Fixed8x13_Character_240,Fixed8x13_Character_241,Fixed8x13_Character_242,Fixed8x13_Character_243,Fixed8x13_Character_244,Fixed8x13_Character_245,Fixed8x13_Character_246,Fixed8x13_Character_247,Fixed8x13_Character_248,Fixed8x13_Character_249,Fixed8x13_Character_250,Fixed8x13_Character_251,Fixed8x13_Character_252,Fixed8x13_Character_253,Fixed8x13_Character_254,Fixed8x13_Character_255,NULL}; + +/* The font structure: */ +static const SFG_Font fgFontFixed8x13 = { "-misc-fixed-medium-r-normal--13-120-75-75-C-80-iso8859-1", 256, 14, Fixed8x13_Character_Map, 0, 3 }; + + +static void +util_font_draw_character(void *dst_mem, unsigned dst_stride, unsigned character) +{ + unsigned char *dst = (unsigned char*)dst_mem; + const SFG_Font *font = &fgFontFixed8x13; + unsigned width = font->Characters[character][0]; + unsigned bitmap_stride = (width + 7) / 8; + unsigned j,i; + const GLubyte *bitmap = font->Characters[character]+1 + bitmap_stride * (font->Height - 1); + + for (j = 0; j < font->Height; j++) { + for (i = 0; i < width; i++) { + dst[i] = bitmap[i/8] & (128 >> (i%8)) ? 0xff : 0; + } + dst += dst_stride; + bitmap -= bitmap_stride; + } +} + +static boolean +util_font_create_fixed_8x13(struct pipe_context *pipe, + struct util_font *out_font) +{ + struct pipe_screen *screen = pipe->screen; + struct pipe_resource tex_templ, *tex; + struct pipe_transfer *transfer = NULL; + char *map; + enum pipe_format tex_format; + int i; + + if (screen->is_format_supported(screen, PIPE_FORMAT_I8_UNORM, + PIPE_TEXTURE_RECT, 0, + PIPE_BIND_SAMPLER_VIEW)) { + tex_format = PIPE_FORMAT_I8_UNORM; + } + else if (screen->is_format_supported(screen, PIPE_FORMAT_L8_UNORM, + PIPE_TEXTURE_RECT, 0, + PIPE_BIND_SAMPLER_VIEW)) { + tex_format = PIPE_FORMAT_L8_UNORM; + } + else { + return FALSE; + } + + memset(&tex_templ, 0, sizeof(tex_templ)); + tex_templ.target = PIPE_TEXTURE_RECT; + tex_templ.format = tex_format; + tex_templ.width0 = 128; + tex_templ.height0 = 256; + tex_templ.depth0 = 1; + tex_templ.array_size = 1; + tex_templ.usage = PIPE_USAGE_STATIC; + tex_templ.bind = PIPE_BIND_SAMPLER_VIEW; + + tex = screen->resource_create(screen, &tex_templ); + if (!tex) { + return FALSE; + } + + map = pipe_transfer_map(pipe, tex, 0, 0, PIPE_TRANSFER_WRITE, 0, 0, + tex->width0, tex->height0, &transfer); + if (!map) { + pipe_resource_reference(&tex, NULL); + return FALSE; + } + + for (i = 0; i < 256; i++) { + int x = (i % 16) * 8; + int y = (i / 16) * 14; + + util_font_draw_character(map + y * transfer->stride + x, + transfer->stride, i); + } + + pipe_transfer_unmap(pipe, transfer); + + pipe_resource_reference(&out_font->texture, NULL); + out_font->texture = tex; + out_font->glyph_width = 8; + out_font->glyph_height = 14; + return TRUE; +} + + +boolean +util_font_create(struct pipe_context *pipe, enum util_font_name name, + struct util_font *out_font) +{ + switch (name) { + case UTIL_FONT_FIXED_8X13: + return util_font_create_fixed_8x13(pipe, out_font); + } + return FALSE; +} diff --git a/mesalib/src/gallium/auxiliary/hud/font.h b/mesalib/src/gallium/auxiliary/hud/font.h new file mode 100644 index 000000000..cf1c87984 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/hud/font.h @@ -0,0 +1,59 @@ +/************************************************************************** + * + * Copyright 2013 Marek Olšák <maraeo@gmail.com> + * 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 THE AUTHORS 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. + * + **************************************************************************/ + +#ifndef FONT_H +#define FONT_H + +#include "pipe/p_compiler.h" + +struct pipe_resource; +struct pipe_context; + +enum util_font_name { + UTIL_FONT_FIXED_8X13 +}; + +/* The font is stored in a RECT texture. There are 256 glyphs + * drawn in a 16x16 matrix. The texture coordinates of a glyph + * within the matrix should be calculated as follows: + * + * x1 = (glyph % 16) * glyph_width; + * y1 = (glyph / 16) * glyph_height; + * x2 = x1 + glyph_width; + * y2 = y1 + glyph_height; + */ +struct util_font { + struct pipe_resource *texture; + unsigned glyph_width; + unsigned glyph_height; +}; + +boolean +util_font_create(struct pipe_context *pipe, enum util_font_name name, + struct util_font *out_font); + +#endif diff --git a/mesalib/src/gallium/auxiliary/hud/hud_context.c b/mesalib/src/gallium/auxiliary/hud/hud_context.c new file mode 100644 index 000000000..983f05756 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/hud/hud_context.c @@ -0,0 +1,1078 @@ +/************************************************************************** + * + * Copyright 2013 Marek Olšák <maraeo@gmail.com> + * 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 THE AUTHORS 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. + * + **************************************************************************/ + +/* This head-up display module can draw transparent graphs on top of what + * the app is rendering, visualizing various data like framerate, cpu load, + * performance counters, etc. It can be hook up into any state tracker. + * + * The HUD is controlled with the GALLIUM_HUD environment variable. + * Set GALLIUM_HUD=help for more info. + */ + +#include "hud/hud_context.h" +#include "hud/hud_private.h" +#include "hud/font.h" + +#include "cso_cache/cso_context.h" +#include "util/u_draw_quad.h" +#include "util/u_inlines.h" +#include "util/u_memory.h" +#include "util/u_math.h" +#include "util/u_simple_shaders.h" +#include "util/u_string.h" +#include "util/u_upload_mgr.h" +#include "tgsi/tgsi_text.h" +#include "tgsi/tgsi_dump.h" + + +struct hud_context { + struct pipe_context *pipe; + struct cso_context *cso; + struct u_upload_mgr *uploader; + + struct list_head pane_list; + + /* states */ + struct pipe_blend_state alpha_blend; + struct pipe_depth_stencil_alpha_state dsa; + void *fs_color, *fs_text; + struct pipe_rasterizer_state rasterizer; + void *vs; + struct pipe_vertex_element velems[2]; + + /* font */ + struct util_font font; + struct pipe_sampler_view *font_sampler_view; + struct pipe_sampler_state font_sampler_state; + + /* VS constant buffer */ + struct { + float color[4]; + float two_div_fb_width; + float two_div_fb_height; + float translate[2]; + float scale[2]; + float padding[2]; + } constants; + struct pipe_constant_buffer constbuf; + + unsigned fb_width, fb_height; + + /* vertices for text and background drawing are accumulated here and then + * drawn all at once */ + struct vertex_queue { + float *vertices; + struct pipe_vertex_buffer vbuf; + unsigned max_num_vertices; + unsigned num_vertices; + } text, bg, whitelines; + + struct { + boolean query_pipeline_statistics; + } cap; +}; + + +static void +hud_draw_colored_prims(struct hud_context *hud, unsigned prim, + float *buffer, unsigned num_vertices, + float r, float g, float b, float a, + int xoffset, int yoffset, float yscale) +{ + struct cso_context *cso = hud->cso; + struct pipe_vertex_buffer vbuffer = {0}; + + hud->constants.color[0] = r; + hud->constants.color[1] = g; + hud->constants.color[2] = b; + hud->constants.color[3] = a; + hud->constants.translate[0] = xoffset; + hud->constants.translate[1] = yoffset; + hud->constants.scale[0] = 1; + hud->constants.scale[1] = yscale; + cso_set_constant_buffer(cso, PIPE_SHADER_VERTEX, 0, &hud->constbuf); + + vbuffer.user_buffer = buffer; + vbuffer.stride = 2 * sizeof(float); + + cso_set_vertex_buffers(cso, cso_get_aux_vertex_buffer_slot(cso), + 1, &vbuffer); + cso_set_fragment_shader_handle(hud->cso, hud->fs_color); + cso_draw_arrays(cso, prim, 0, num_vertices); +} + +static void +hud_draw_colored_quad(struct hud_context *hud, unsigned prim, + unsigned x1, unsigned y1, unsigned x2, unsigned y2, + float r, float g, float b, float a) +{ + float buffer[] = { + x1, y1, + x1, y2, + x2, y2, + x2, y1, + }; + + hud_draw_colored_prims(hud, prim, buffer, 4, r, g, b, a, 0, 0, 1); +} + +static void +hud_draw_background_quad(struct hud_context *hud, + unsigned x1, unsigned y1, unsigned x2, unsigned y2) +{ + float *vertices = hud->bg.vertices + hud->bg.num_vertices*2; + unsigned num = 0; + + assert(hud->bg.num_vertices + 4 <= hud->bg.max_num_vertices); + + vertices[num++] = x1; + vertices[num++] = y1; + + vertices[num++] = x1; + vertices[num++] = y2; + + vertices[num++] = x2; + vertices[num++] = y2; + + vertices[num++] = x2; + vertices[num++] = y1; + + hud->bg.num_vertices += num/2; +} + +static void +hud_draw_string(struct hud_context *hud, unsigned x, unsigned y, + const char *str, ...) +{ + char buf[256]; + char *s = buf; + float *vertices = hud->text.vertices + hud->text.num_vertices*4; + unsigned num = 0; + + va_list ap; + va_start(ap, str); + util_vsnprintf(buf, sizeof(buf), str, ap); + va_end(ap); + + if (!*s) + return; + + hud_draw_background_quad(hud, + x, y, + x + strlen(buf)*hud->font.glyph_width, + y + hud->font.glyph_height); + + while (*s) { + unsigned x1 = x; + unsigned y1 = y; + unsigned x2 = x + hud->font.glyph_width; + unsigned y2 = y + hud->font.glyph_height; + unsigned tx1 = (*s % 16) * hud->font.glyph_width; + unsigned ty1 = (*s / 16) * hud->font.glyph_height; + unsigned tx2 = tx1 + hud->font.glyph_width; + unsigned ty2 = ty1 + hud->font.glyph_height; + + if (*s == ' ') { + x += hud->font.glyph_width; + s++; + continue; + } + + assert(hud->text.num_vertices + num/4 + 4 <= hud->text.max_num_vertices); + + vertices[num++] = x1; + vertices[num++] = y1; + vertices[num++] = tx1; + vertices[num++] = ty1; + + vertices[num++] = x1; + vertices[num++] = y2; + vertices[num++] = tx1; + vertices[num++] = ty2; + + vertices[num++] = x2; + vertices[num++] = y2; + vertices[num++] = tx2; + vertices[num++] = ty2; + + vertices[num++] = x2; + vertices[num++] = y1; + vertices[num++] = tx2; + vertices[num++] = ty1; + + x += hud->font.glyph_width; + s++; + } + + hud->text.num_vertices += num/4; +} + +static void +number_to_human_readable(uint64_t num, boolean is_in_bytes, char *out) +{ + static const char *byte_units[] = + {"", " KB", " MB", " GB", " TB", " PB", " EB"}; + static const char *metric_units[] = + {"", " k", " M", " G", " T", " P", " E"}; + const char **units = is_in_bytes ? byte_units : metric_units; + double divisor = is_in_bytes ? 1024 : 1000; + int unit = 0; + double d = num; + + while (d > divisor) { + d /= divisor; + unit++; + } + + if (d >= 100 || d == (int)d) + sprintf(out, "%.0f%s", d, units[unit]); + else if (d >= 10 || d*10 == (int)(d*10)) + sprintf(out, "%.1f%s", d, units[unit]); + else + sprintf(out, "%.2f%s", d, units[unit]); +} + +static void +hud_draw_graph_line_strip(struct hud_context *hud, const struct hud_graph *gr, + unsigned xoffset, unsigned yoffset, float yscale) +{ + if (gr->num_vertices <= 1) + return; + + assert(gr->index <= gr->num_vertices); + + hud_draw_colored_prims(hud, PIPE_PRIM_LINE_STRIP, + gr->vertices, gr->index, + gr->color[0], gr->color[1], gr->color[2], 1, + xoffset + (gr->pane->max_num_vertices - gr->index - 1) * 2 - 1, + yoffset, yscale); + + if (gr->num_vertices <= gr->index) + return; + + hud_draw_colored_prims(hud, PIPE_PRIM_LINE_STRIP, + gr->vertices + gr->index*2, + gr->num_vertices - gr->index, + gr->color[0], gr->color[1], gr->color[2], 1, + xoffset - gr->index*2 - 1, yoffset, yscale); +} + +static void +hud_pane_accumulate_vertices(struct hud_context *hud, + const struct hud_pane *pane) +{ + struct hud_graph *gr; + float *line_verts = hud->whitelines.vertices + hud->whitelines.num_vertices*2; + unsigned i, num = 0; + char str[32]; + + /* draw background */ + hud_draw_background_quad(hud, + pane->x1, pane->y1, + pane->x2, pane->y2); + + /* draw numbers on the right-hand side */ + for (i = 0; i < 6; i++) { + unsigned x = pane->x2 + 2; + unsigned y = pane->inner_y1 + pane->inner_height * (5 - i) / 5 - + hud->font.glyph_height / 2; + + number_to_human_readable(pane->max_value * i / 5, + pane->uses_byte_units, str); + hud_draw_string(hud, x, y, str); + } + + /* draw info below the pane */ + i = 0; + LIST_FOR_EACH_ENTRY(gr, &pane->graph_list, head) { + unsigned x = pane->x1 + 2; + unsigned y = pane->y2 + 2 + i*hud->font.glyph_height; + + number_to_human_readable(gr->current_value, + pane->uses_byte_units, str); + hud_draw_string(hud, x, y, " %s: %s", gr->name, str); + i++; + } + + /* draw border */ + assert(hud->whitelines.num_vertices + num/2 + 8 <= hud->whitelines.max_num_vertices); + line_verts[num++] = pane->x1; + line_verts[num++] = pane->y1; + line_verts[num++] = pane->x2; + line_verts[num++] = pane->y1; + + line_verts[num++] = pane->x2; + line_verts[num++] = pane->y1; + line_verts[num++] = pane->x2; + line_verts[num++] = pane->y2; + + line_verts[num++] = pane->x1; + line_verts[num++] = pane->y2; + line_verts[num++] = pane->x2; + line_verts[num++] = pane->y2; + + line_verts[num++] = pane->x1; + line_verts[num++] = pane->y1; + line_verts[num++] = pane->x1; + line_verts[num++] = pane->y2; + + /* draw horizontal lines inside the graph */ + for (i = 0; i <= 5; i++) { + float y = round((pane->max_value * i / 5.0) * pane->yscale + pane->inner_y2); + + assert(hud->whitelines.num_vertices + num/2 + 2 <= hud->whitelines.max_num_vertices); + line_verts[num++] = pane->x1; + line_verts[num++] = y; + line_verts[num++] = pane->x2; + line_verts[num++] = y; + } + + hud->whitelines.num_vertices += num/2; +} + +static void +hud_pane_draw_colored_objects(struct hud_context *hud, + const struct hud_pane *pane) +{ + struct hud_graph *gr; + unsigned i; + + /* draw colored quads below the pane */ + i = 0; + LIST_FOR_EACH_ENTRY(gr, &pane->graph_list, head) { + unsigned x = pane->x1 + 2; + unsigned y = pane->y2 + 2 + i*hud->font.glyph_height; + + hud_draw_colored_quad(hud, PIPE_PRIM_QUADS, x + 1, y + 1, x + 12, y + 13, + gr->color[0], gr->color[1], gr->color[2], 1); + i++; + } + + /* draw the line strips */ + LIST_FOR_EACH_ENTRY(gr, &pane->graph_list, head) { + hud_draw_graph_line_strip(hud, gr, pane->inner_x1, pane->inner_y2, pane->yscale); + } +} + +static void +hud_alloc_vertices(struct hud_context *hud, struct vertex_queue *v, + unsigned num_vertices, unsigned stride) +{ + v->num_vertices = 0; + v->max_num_vertices = num_vertices; + v->vbuf.stride = stride; + u_upload_alloc(hud->uploader, 0, v->vbuf.stride * v->max_num_vertices, + &v->vbuf.buffer_offset, &v->vbuf.buffer, + (void**)&v->vertices); +} + +/** + * Draw the HUD to the texture \p tex. + * The texture is usually the back buffer being displayed. + */ +void +hud_draw(struct hud_context *hud, struct pipe_resource *tex) +{ + struct cso_context *cso = hud->cso; + struct pipe_context *pipe = hud->pipe; + struct pipe_framebuffer_state fb; + struct pipe_surface surf_templ, *surf; + struct pipe_viewport_state viewport; + const struct pipe_sampler_state *sampler_states[] = + { &hud->font_sampler_state }; + struct hud_pane *pane; + struct hud_graph *gr; + + hud->fb_width = tex->width0; + hud->fb_height = tex->height0; + hud->constants.two_div_fb_width = 2.0 / hud->fb_width; + hud->constants.two_div_fb_height = 2.0 / hud->fb_height; + + cso_save_framebuffer(cso); + cso_save_sample_mask(cso); + cso_save_blend(cso); + cso_save_depth_stencil_alpha(cso); + cso_save_fragment_shader(cso); + cso_save_sampler_views(cso, PIPE_SHADER_FRAGMENT); + cso_save_samplers(cso, PIPE_SHADER_FRAGMENT); + cso_save_rasterizer(cso); + cso_save_viewport(cso); + cso_save_stream_outputs(cso); + cso_save_geometry_shader(cso); + cso_save_vertex_shader(cso); + cso_save_vertex_elements(cso); + cso_save_aux_vertex_buffer_slot(cso); + cso_save_constant_buffer_slot0(cso, PIPE_SHADER_VERTEX); + cso_save_render_condition(cso); + + /* set states */ + memset(&surf_templ, 0, sizeof(surf_templ)); + surf_templ.format = tex->format; + surf = pipe->create_surface(pipe, tex, &surf_templ); + + memset(&fb, 0, sizeof(fb)); + fb.nr_cbufs = 1; + fb.cbufs[0] = surf; + fb.zsbuf = NULL; + fb.width = hud->fb_width; + fb.height = hud->fb_height; + + viewport.scale[0] = 0.5f * hud->fb_width; + viewport.scale[1] = 0.5f * hud->fb_height; + viewport.scale[2] = 1.0f; + viewport.scale[3] = 1.0f; + viewport.translate[0] = 0.5f * hud->fb_width; + viewport.translate[1] = 0.5f * hud->fb_height; + viewport.translate[2] = 0.0f; + viewport.translate[3] = 0.0f; + + cso_set_framebuffer(cso, &fb); + cso_set_sample_mask(cso, ~0); + cso_set_blend(cso, &hud->alpha_blend); + cso_set_depth_stencil_alpha(cso, &hud->dsa); + cso_set_rasterizer(cso, &hud->rasterizer); + cso_set_viewport(cso, &viewport); + cso_set_stream_outputs(cso, 0, NULL, 0); + cso_set_geometry_shader_handle(cso, NULL); + cso_set_vertex_shader_handle(cso, hud->vs); + cso_set_vertex_elements(cso, 2, hud->velems); + cso_set_render_condition(cso, NULL, 0); + cso_set_sampler_views(cso, PIPE_SHADER_FRAGMENT, 1, + &hud->font_sampler_view); + cso_set_samplers(cso, PIPE_SHADER_FRAGMENT, 1, sampler_states); + cso_set_constant_buffer(cso, PIPE_SHADER_VERTEX, 0, &hud->constbuf); + + /* prepare vertex buffers */ + hud_alloc_vertices(hud, &hud->bg, 4 * 64, 2 * sizeof(float)); + hud_alloc_vertices(hud, &hud->whitelines, 4 * 256, 2 * sizeof(float)); + hud_alloc_vertices(hud, &hud->text, 4 * 512, 4 * sizeof(float)); + + /* prepare all graphs */ + LIST_FOR_EACH_ENTRY(pane, &hud->pane_list, head) { + LIST_FOR_EACH_ENTRY(gr, &pane->graph_list, head) { + gr->query_new_value(gr); + } + + hud_pane_accumulate_vertices(hud, pane); + } + + /* unmap the uploader's vertex buffer before drawing */ + u_upload_flush(hud->uploader); + + /* draw accumulated vertices for background quads */ + cso_set_fragment_shader_handle(hud->cso, hud->fs_color); + + if (hud->bg.num_vertices) { + hud->constants.color[0] = 0; + hud->constants.color[1] = 0; + hud->constants.color[2] = 0; + hud->constants.color[3] = 0.666; + hud->constants.translate[0] = 0; + hud->constants.translate[1] = 0; + hud->constants.scale[0] = 1; + hud->constants.scale[1] = 1; + + cso_set_constant_buffer(cso, PIPE_SHADER_VERTEX, 0, &hud->constbuf); + cso_set_vertex_buffers(cso, cso_get_aux_vertex_buffer_slot(cso), 1, + &hud->bg.vbuf); + cso_draw_arrays(cso, PIPE_PRIM_QUADS, 0, hud->bg.num_vertices); + } + pipe_resource_reference(&hud->bg.vbuf.buffer, NULL); + + /* draw accumulated vertices for white lines */ + hud->constants.color[0] = 1; + hud->constants.color[1] = 1; + hud->constants.color[2] = 1; + hud->constants.color[3] = 1; + hud->constants.translate[0] = 0; + hud->constants.translate[1] = 0; + hud->constants.scale[0] = 1; + hud->constants.scale[1] = 1; + cso_set_constant_buffer(cso, PIPE_SHADER_VERTEX, 0, &hud->constbuf); + + if (hud->whitelines.num_vertices) { + cso_set_vertex_buffers(cso, cso_get_aux_vertex_buffer_slot(cso), 1, + &hud->whitelines.vbuf); + cso_set_fragment_shader_handle(hud->cso, hud->fs_color); + cso_draw_arrays(cso, PIPE_PRIM_LINES, 0, hud->whitelines.num_vertices); + } + pipe_resource_reference(&hud->whitelines.vbuf.buffer, NULL); + + /* draw accumulated vertices for text */ + if (hud->text.num_vertices) { + cso_set_vertex_buffers(cso, cso_get_aux_vertex_buffer_slot(cso), 1, + &hud->text.vbuf); + cso_set_fragment_shader_handle(hud->cso, hud->fs_text); + cso_draw_arrays(cso, PIPE_PRIM_QUADS, 0, hud->text.num_vertices); + } + pipe_resource_reference(&hud->text.vbuf.buffer, NULL); + + /* draw the rest */ + LIST_FOR_EACH_ENTRY(pane, &hud->pane_list, head) { + if (pane) + hud_pane_draw_colored_objects(hud, pane); + } + + /* restore states */ + cso_restore_framebuffer(cso); + cso_restore_sample_mask(cso); + cso_restore_blend(cso); + cso_restore_depth_stencil_alpha(cso); + cso_restore_fragment_shader(cso); + cso_restore_sampler_views(cso, PIPE_SHADER_FRAGMENT); + cso_restore_samplers(cso, PIPE_SHADER_FRAGMENT); + cso_restore_rasterizer(cso); + cso_restore_viewport(cso); + cso_restore_stream_outputs(cso); + cso_restore_geometry_shader(cso); + cso_restore_vertex_shader(cso); + cso_restore_vertex_elements(cso); + cso_restore_aux_vertex_buffer_slot(cso); + cso_restore_constant_buffer_slot0(cso, PIPE_SHADER_VERTEX); + cso_restore_render_condition(cso); + + pipe_surface_reference(&surf, NULL); +} + +/** + * Set the maximum value for the Y axis of the graph. + * This scales the graph accordingly. + */ +void +hud_pane_set_max_value(struct hud_pane *pane, uint64_t value) +{ + pane->max_value = value; + pane->yscale = -(int)pane->inner_height / (double)pane->max_value; +} + +static struct hud_pane * +hud_pane_create(unsigned x1, unsigned y1, unsigned x2, unsigned y2, + unsigned period, uint64_t max_value) +{ + struct hud_pane *pane = CALLOC_STRUCT(hud_pane); + + if (!pane) + return NULL; + + pane->x1 = x1; + pane->y1 = y1; + pane->x2 = x2; + pane->y2 = y2; + pane->inner_x1 = x1 + 1; + pane->inner_x2 = x2 - 1; + pane->inner_y1 = y1 + 1; + pane->inner_y2 = y2 - 1; + pane->inner_width = pane->inner_x2 - pane->inner_x1; + pane->inner_height = pane->inner_y2 - pane->inner_y1; + pane->period = period; + pane->max_num_vertices = (x2 - x1 + 2) / 2; + hud_pane_set_max_value(pane, max_value); + LIST_INITHEAD(&pane->graph_list); + return pane; +} + +/** + * Add a graph to an existing pane. + * One pane can contain multiple graphs over each other. + */ +void +hud_pane_add_graph(struct hud_pane *pane, struct hud_graph *gr) +{ + static const float colors[][3] = { + {0, 1, 0}, + {1, 0, 0}, + {0, 1, 1}, + {1, 0, 1}, + {1, 1, 0}, + {0.5, 0.5, 1}, + {0.5, 0.5, 0.5}, + }; + char *name = gr->name; + + /* replace '-' with a space */ + while (*name) { + if (*name == '-') + *name = ' '; + name++; + } + + assert(pane->num_graphs < Elements(colors)); + gr->vertices = MALLOC(pane->max_num_vertices * sizeof(float) * 2); + gr->color[0] = colors[pane->num_graphs][0]; + gr->color[1] = colors[pane->num_graphs][1]; + gr->color[2] = colors[pane->num_graphs][2]; + gr->pane = pane; + LIST_ADDTAIL(&gr->head, &pane->graph_list); + pane->num_graphs++; +} + +void +hud_graph_add_value(struct hud_graph *gr, uint64_t value) +{ + if (gr->index == gr->pane->max_num_vertices) { + gr->vertices[0] = 0; + gr->vertices[1] = gr->vertices[(gr->index-1)*2+1]; + gr->index = 1; + } + gr->vertices[(gr->index)*2+0] = gr->index*2; + gr->vertices[(gr->index)*2+1] = value; + gr->index++; + + if (gr->num_vertices < gr->pane->max_num_vertices) { + gr->num_vertices++; + } + + gr->current_value = value; + if (value > gr->pane->max_value) { + hud_pane_set_max_value(gr->pane, value); + } +} + +static void +hud_graph_destroy(struct hud_graph *graph) +{ + FREE(graph->vertices); + if (graph->free_query_data) + graph->free_query_data(graph->query_data); + FREE(graph); +} + +/** + * Read a string from the environment variable. + * The separators "+", ",", ":", and ";" terminate the string. + * Return the number of read characters. + */ +static int +parse_string(const char *s, char *out) +{ + int i; + + for (i = 0; *s && *s != '+' && *s != ',' && *s != ':' && *s != ';'; + s++, out++, i++) + *out = *s; + + *out = 0; + + if (*s && !i) + fprintf(stderr, "gallium_hud: syntax error: unexpected '%c' (%i) while " + "parsing a string\n", *s, *s); + return i; +} + +static boolean +has_occlusion_query(struct pipe_screen *screen) +{ + return screen->get_param(screen, PIPE_CAP_OCCLUSION_QUERY) != 0; +} + +static boolean +has_streamout(struct pipe_screen *screen) +{ + return screen->get_param(screen, PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS) != 0; +} + +static void +hud_parse_env_var(struct hud_context *hud, const char *env) +{ + unsigned num, i; + char name[256], s[256]; + struct hud_pane *pane = NULL; + unsigned x = 10, y = 10; + unsigned width = 251, height = 100; + unsigned period = 500 * 1000; /* default period (1/2 second) */ + const char *period_env; + + /* + * The GALLIUM_HUD_PERIOD env var sets the graph update rate. + * The env var is in seconds (a float). + * Zero means update after every frame. + */ + period_env = getenv("GALLIUM_HUD_PERIOD"); + if (period_env) { + float p = atof(period_env); + if (p >= 0.0) { + period = (unsigned) (p * 1000 * 1000); + } + } + + while ((num = parse_string(env, name)) != 0) { + env += num; + + if (!pane) { + pane = hud_pane_create(x, y, x + width, y + height, period, 10); + if (!pane) + return; + } + + /* add a graph */ + if (strcmp(name, "fps") == 0) { + hud_fps_graph_install(pane); + } + else if (strcmp(name, "cpu") == 0) { + hud_cpu_graph_install(pane, ALL_CPUS); + } + else if (sscanf(name, "cpu%u%s", &i, s) == 1) { + hud_cpu_graph_install(pane, i); + } + else if (strcmp(name, "samples-passed") == 0 && + has_occlusion_query(hud->pipe->screen)) { + hud_pipe_query_install(pane, hud->pipe, "samples-passed", + PIPE_QUERY_OCCLUSION_COUNTER, 0, 0, FALSE); + } + else if (strcmp(name, "primitives-generated") == 0 && + has_streamout(hud->pipe->screen)) { + hud_pipe_query_install(pane, hud->pipe, "primitives-generated", + PIPE_QUERY_PRIMITIVES_GENERATED, 0, 0, FALSE); + } + else if (strncmp(name, "pipeline-statistics-", 20) == 0) { + if (hud->cap.query_pipeline_statistics) { + static const char *pipeline_statistics_names[] = + { + "ia-vertices", + "ia-primitives", + "vs-invocations", + "gs-invocations", + "gs-primitives", + "clipper-invocations", + "clipper-primitives-generated", + "ps-invocations", + "hs-invocations", + "ds-invocations", + "cs-invocations" + }; + for (i = 0; i < Elements(pipeline_statistics_names); ++i) + if (strcmp(&name[20], pipeline_statistics_names[i]) == 0) + break; + if (i < Elements(pipeline_statistics_names)) + hud_pipe_query_install(pane, hud->pipe, &name[20], + PIPE_QUERY_PIPELINE_STATISTICS, i, + 0, FALSE); + else + fprintf(stderr, "gallium_hud: invalid pipeline-statistics-*\n"); + } else { + fprintf(stderr, "gallium_hud: PIPE_QUERY_PIPELINE_STATISTICS " + "not supported by the driver\n"); + } + } + else { + if (!hud_driver_query_install(pane, hud->pipe, name)){ + fprintf(stderr, "gallium_hud: unknown driver query '%s'\n", name); + } + } + + if (*env == ':') { + env++; + + if (!pane) { + fprintf(stderr, "gallium_hud: syntax error: unexpected ':', " + "expected a name\n"); + break; + } + + num = parse_string(env, s); + env += num; + + if (num && sscanf(s, "%u", &i) == 1) { + hud_pane_set_max_value(pane, i); + } + else { + fprintf(stderr, "gallium_hud: syntax error: unexpected '%c' (%i) " + "after ':'\n", *env, *env); + } + } + + if (*env == 0) + break; + + /* parse a separator */ + switch (*env) { + case '+': + env++; + break; + + case ',': + env++; + y += height + hud->font.glyph_height * (pane->num_graphs + 2); + + if (pane && pane->num_graphs) { + LIST_ADDTAIL(&pane->head, &hud->pane_list); + pane = NULL; + } + break; + + case ';': + env++; + y = 10; + x += width + hud->font.glyph_width * 7; + + if (pane && pane->num_graphs) { + LIST_ADDTAIL(&pane->head, &hud->pane_list); + pane = NULL; + } + break; + + default: + fprintf(stderr, "gallium_hud: syntax error: unexpected '%c'\n", *env); + } + } + + if (pane) { + if (pane->num_graphs) { + LIST_ADDTAIL(&pane->head, &hud->pane_list); + } + else { + FREE(pane); + } + } +} + +static void +print_help(struct pipe_screen *screen) +{ + int i, num_queries, num_cpus = hud_get_num_cpus(); + + puts("Syntax: GALLIUM_HUD=name1[+name2][...][:value1][,nameI...][;nameJ...]"); + puts(""); + puts(" Names are identifiers of data sources which will be drawn as graphs"); + puts(" in panes. Multiple graphs can be drawn in the same pane."); + puts(" There can be multiple panes placed in rows and columns."); + puts(""); + puts(" '+' separates names which will share a pane."); + puts(" ':[value]' specifies the initial maximum value of the Y axis"); + puts(" for the given pane."); + puts(" ',' creates a new pane below the last one."); + puts(" ';' creates a new pane at the top of the next column."); + puts(""); + puts(" Example: GALLIUM_HUD=\"cpu,fps;primitives-generated\""); + puts(""); + puts(" Available names:"); + puts(" fps"); + puts(" cpu"); + + for (i = 0; i < num_cpus; i++) + printf(" cpu%i\n", i); + + if (has_occlusion_query(screen)) + puts(" pixels-rendered"); + if (has_streamout(screen)) + puts(" primitives-generated"); + + if (screen->get_driver_query_info){ + struct pipe_driver_query_info info; + num_queries = screen->get_driver_query_info(screen, 0, NULL); + + for (i = 0; i < num_queries; i++){ + screen->get_driver_query_info(screen, i, &info); + printf(" %s\n", info.name); + } + } + + puts(""); +} + +struct hud_context * +hud_create(struct pipe_context *pipe, struct cso_context *cso) +{ + struct hud_context *hud; + struct pipe_sampler_view view_templ; + unsigned i; + const char *env = debug_get_option("GALLIUM_HUD", NULL); + + if (!env || !*env) + return NULL; + + if (strcmp(env, "help") == 0) { + print_help(pipe->screen); + return NULL; + } + + hud = CALLOC_STRUCT(hud_context); + if (!hud) + return NULL; + + hud->pipe = pipe; + hud->cso = cso; + hud->uploader = u_upload_create(pipe, 256 * 1024, 16, + PIPE_BIND_VERTEX_BUFFER); + + /* font */ + if (!util_font_create(pipe, UTIL_FONT_FIXED_8X13, &hud->font)) { + u_upload_destroy(hud->uploader); + FREE(hud); + return NULL; + } + + /* blend state */ + hud->alpha_blend.rt[0].colormask = PIPE_MASK_RGBA; + hud->alpha_blend.rt[0].blend_enable = 1; + hud->alpha_blend.rt[0].rgb_func = PIPE_BLEND_ADD; + hud->alpha_blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA; + hud->alpha_blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA; + hud->alpha_blend.rt[0].alpha_func = PIPE_BLEND_ADD; + hud->alpha_blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ZERO; + hud->alpha_blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ONE; + + /* fragment shader */ + hud->fs_color = + util_make_fragment_passthrough_shader(pipe, + TGSI_SEMANTIC_COLOR, + TGSI_INTERPOLATE_CONSTANT); + + { + /* Read a texture and do .xxxx swizzling. */ + static const char *fragment_shader_text = { + "FRAG\n" + "DCL IN[0], GENERIC[0], LINEAR\n" + "DCL SAMP[0]\n" + "DCL OUT[0], COLOR[0]\n" + "DCL TEMP[0]\n" + + "TEX TEMP[0], IN[0], SAMP[0], RECT\n" + "MOV OUT[0], TEMP[0].xxxx\n" + "END\n" + }; + + struct tgsi_token tokens[1000]; + struct pipe_shader_state state = {tokens}; + + if (!tgsi_text_translate(fragment_shader_text, tokens, Elements(tokens))) { + assert(0); + pipe_resource_reference(&hud->font.texture, NULL); + u_upload_destroy(hud->uploader); + FREE(hud); + return NULL; + } + + hud->fs_text = pipe->create_fs_state(pipe, &state); + } + + /* rasterizer */ + hud->rasterizer.gl_rasterization_rules = 1; + hud->rasterizer.depth_clip = 1; + hud->rasterizer.line_width = 1; + hud->rasterizer.line_last_pixel = 1; + + /* vertex shader */ + { + static const char *vertex_shader_text = { + "VERT\n" + "DCL IN[0..1]\n" + "DCL OUT[0], POSITION\n" + "DCL OUT[1], COLOR[0]\n" /* color */ + "DCL OUT[2], GENERIC[0]\n" /* texcoord */ + /* [0] = color, + * [1] = (2/fb_width, 2/fb_height, xoffset, yoffset) + * [2] = (xscale, yscale, 0, 0) */ + "DCL CONST[0..2]\n" + "DCL TEMP[0]\n" + "IMM[0] FLT32 { -1, 0, 0, 1 }\n" + + /* v = in * (xscale, yscale) + (xoffset, yoffset) */ + "MAD TEMP[0].xy, IN[0], CONST[2].xyyy, CONST[1].zwww\n" + /* pos = v * (2 / fb_width, 2 / fb_height) - (1, 1) */ + "MAD OUT[0].xy, TEMP[0], CONST[1].xyyy, IMM[0].xxxx\n" + "MOV OUT[0].zw, IMM[0]\n" + + "MOV OUT[1], CONST[0]\n" + "MOV OUT[2], IN[1]\n" + "END\n" + }; + + struct tgsi_token tokens[1000]; + struct pipe_shader_state state = {tokens}; + + if (!tgsi_text_translate(vertex_shader_text, tokens, Elements(tokens))) { + assert(0); + pipe_resource_reference(&hud->font.texture, NULL); + u_upload_destroy(hud->uploader); + FREE(hud); + return NULL; + } + + hud->vs = pipe->create_vs_state(pipe, &state); + } + + /* vertex elements */ + for (i = 0; i < 2; i++) { + hud->velems[i].src_offset = i * 2 * sizeof(float); + hud->velems[i].src_format = PIPE_FORMAT_R32G32_FLOAT; + hud->velems[i].vertex_buffer_index = cso_get_aux_vertex_buffer_slot(cso); + } + + /* sampler view */ + memset(&view_templ, 0, sizeof(view_templ)); + view_templ.format = hud->font.texture->format; + view_templ.swizzle_r = PIPE_SWIZZLE_RED; + view_templ.swizzle_g = PIPE_SWIZZLE_GREEN; + view_templ.swizzle_b = PIPE_SWIZZLE_BLUE; + view_templ.swizzle_a = PIPE_SWIZZLE_ALPHA; + hud->font_sampler_view = pipe->create_sampler_view(pipe, hud->font.texture, + &view_templ); + + /* sampler state (for font drawing) */ + hud->font_sampler_state.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + hud->font_sampler_state.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + hud->font_sampler_state.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + hud->font_sampler_state.normalized_coords = 0; + + /* constants */ + hud->constbuf.buffer_size = sizeof(hud->constants); + hud->constbuf.user_buffer = &hud->constants; + + LIST_INITHEAD(&hud->pane_list); + + hud->cap.query_pipeline_statistics = + pipe->screen->get_param(pipe->screen, PIPE_CAP_QUERY_PIPELINE_STATISTICS); + + hud_parse_env_var(hud, env); + return hud; +} + +void +hud_destroy(struct hud_context *hud) +{ + struct pipe_context *pipe = hud->pipe; + struct hud_pane *pane, *pane_tmp; + struct hud_graph *graph, *graph_tmp; + + LIST_FOR_EACH_ENTRY_SAFE(pane, pane_tmp, &hud->pane_list, head) { + LIST_FOR_EACH_ENTRY_SAFE(graph, graph_tmp, &pane->graph_list, head) { + LIST_DEL(&graph->head); + hud_graph_destroy(graph); + } + LIST_DEL(&pane->head); + FREE(pane); + } + + pipe->delete_fs_state(pipe, hud->fs_color); + pipe->delete_fs_state(pipe, hud->fs_text); + pipe->delete_vs_state(pipe, hud->vs); + pipe_sampler_view_reference(&hud->font_sampler_view, NULL); + pipe_resource_reference(&hud->font.texture, NULL); + u_upload_destroy(hud->uploader); + FREE(hud); +} diff --git a/mesalib/src/gallium/auxiliary/hud/hud_context.h b/mesalib/src/gallium/auxiliary/hud/hud_context.h new file mode 100644 index 000000000..abf2ad586 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/hud/hud_context.h @@ -0,0 +1,45 @@ +/************************************************************************** + * + * Copyright 2013 Marek Olšák <maraeo@gmail.com> + * 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 THE AUTHORS 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. + * + **************************************************************************/ + +#ifndef HUD_CONTEXT_H +#define HUD_CONTEXT_H + +struct hud_context; +struct cso_context; +struct pipe_context; +struct pipe_resource; + +struct hud_context * +hud_create(struct pipe_context *pipe, struct cso_context *cso); + +void +hud_destroy(struct hud_context *hud); + +void +hud_draw(struct hud_context *hud, struct pipe_resource *tex); + +#endif diff --git a/mesalib/src/gallium/auxiliary/hud/hud_cpu.c b/mesalib/src/gallium/auxiliary/hud/hud_cpu.c new file mode 100644 index 000000000..ce98115d5 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/hud/hud_cpu.c @@ -0,0 +1,166 @@ +/************************************************************************** + * + * Copyright 2013 Marek Olšák <maraeo@gmail.com> + * 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 THE AUTHORS 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. + * + **************************************************************************/ + +/* This file contains code for reading CPU load for displaying on the HUD. + */ + +#include "hud/hud_private.h" +#include "os/os_time.h" +#include "util/u_memory.h" +#include <stdio.h> +#include <inttypes.h> + +static boolean +get_cpu_stats(unsigned cpu_index, uint64_t *busy_time, uint64_t *total_time) +{ + char cpuname[32]; + char line[1024]; + FILE *f; + + if (cpu_index == ALL_CPUS) + strcpy(cpuname, "cpu"); + else + sprintf(cpuname, "cpu%u", cpu_index); + + f = fopen("/proc/stat", "r"); + if (!f) + return FALSE; + + while (!feof(f) && fgets(line, sizeof(line), f)) { + if (strstr(line, cpuname) == line) { + uint64_t v[12]; + int i, num; + + num = sscanf(line, + "%s %"PRIu64" %"PRIu64" %"PRIu64" %"PRIu64" %"PRIu64 + " %"PRIu64" %"PRIu64" %"PRIu64" %"PRIu64" %"PRIu64 + " %"PRIu64" %"PRIu64"", + cpuname, &v[0], &v[1], &v[2], &v[3], &v[4], &v[5], + &v[6], &v[7], &v[8], &v[9], &v[10], &v[11]); + if (num < 5) { + fclose(f); + return FALSE; + } + + /* user + nice + system */ + *busy_time = v[0] + v[1] + v[2]; + *total_time = *busy_time; + + /* ... + idle + iowait + irq + softirq + ... */ + for (i = 3; i < num-1; i++) { + *total_time += v[i]; + } + fclose(f); + return TRUE; + } + } + fclose(f); + return FALSE; +} + +struct cpu_info { + unsigned cpu_index; + uint64_t last_cpu_busy, last_cpu_total, last_time; +}; + +static void +query_cpu_load(struct hud_graph *gr) +{ + struct cpu_info *info = gr->query_data; + uint64_t now = os_time_get(); + + if (info->last_time) { + if (info->last_time + gr->pane->period <= now) { + uint64_t cpu_busy, cpu_total, cpu_load; + + get_cpu_stats(info->cpu_index, &cpu_busy, &cpu_total); + + cpu_load = (cpu_busy - info->last_cpu_busy) * 100 / + (double)(cpu_total - info->last_cpu_total); + hud_graph_add_value(gr, cpu_load); + + info->last_cpu_busy = cpu_busy; + info->last_cpu_total = cpu_total; + info->last_time = now; + } + } + else { + /* initialize */ + info->last_time = now; + get_cpu_stats(info->cpu_index, &info->last_cpu_busy, + &info->last_cpu_total); + } +} + +void +hud_cpu_graph_install(struct hud_pane *pane, unsigned cpu_index) +{ + struct hud_graph *gr; + struct cpu_info *info; + uint64_t busy, total; + + /* see if the cpu exists */ + if (cpu_index != ALL_CPUS && !get_cpu_stats(cpu_index, &busy, &total)) { + return; + } + + gr = CALLOC_STRUCT(hud_graph); + if (!gr) + return; + + if (cpu_index == ALL_CPUS) + strcpy(gr->name, "cpu"); + else + sprintf(gr->name, "cpu%u", cpu_index); + + gr->query_data = CALLOC_STRUCT(cpu_info); + if (!gr->query_data) { + FREE(gr); + return; + } + + gr->query_new_value = query_cpu_load; + gr->free_query_data = free; + + info = gr->query_data; + info->cpu_index = cpu_index; + + hud_pane_add_graph(pane, gr); + hud_pane_set_max_value(pane, 100); +} + +int +hud_get_num_cpus(void) +{ + uint64_t busy, total; + int i = 0; + + while (get_cpu_stats(i, &busy, &total)) + i++; + + return i; +} diff --git a/mesalib/src/gallium/auxiliary/hud/hud_driver_query.c b/mesalib/src/gallium/auxiliary/hud/hud_driver_query.c new file mode 100644 index 000000000..0f52e18cc --- /dev/null +++ b/mesalib/src/gallium/auxiliary/hud/hud_driver_query.c @@ -0,0 +1,210 @@ +/************************************************************************** + * + * Copyright 2013 Marek Olšák <maraeo@gmail.com> + * 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 THE AUTHORS 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. + * + **************************************************************************/ + +/* This file contains code for reading values from pipe queries + * for displaying on the HUD. To prevent stalls when reading queries, we + * keep a list of busy queries in a ring. We read only those queries which + * are idle. + */ + +#include "hud/hud_private.h" +#include "pipe/p_screen.h" +#include "os/os_time.h" +#include "util/u_memory.h" +#include <stdio.h> + +#define NUM_QUERIES 8 + +struct query_info { + struct pipe_context *pipe; + unsigned query_type; + unsigned result_index; /* unit depends on query_type */ + + /* Ring of queries. If a query is busy, we use another slot. */ + struct pipe_query *query[NUM_QUERIES]; + unsigned head, tail; + unsigned num_queries; + + uint64_t last_time; + uint64_t results_cumulative; + unsigned num_results; +}; + +static void +query_new_value(struct hud_graph *gr) +{ + struct query_info *info = gr->query_data; + struct pipe_context *pipe = info->pipe; + uint64_t now = os_time_get(); + + if (info->last_time) { + pipe->end_query(pipe, info->query[info->head]); + + /* read query results */ + while (1) { + struct pipe_query *query = info->query[info->tail]; + union pipe_query_result result; + uint64_t *res64 = (uint64_t *)&result; + + if (pipe->get_query_result(pipe, query, FALSE, &result)) { + info->results_cumulative += res64[info->result_index]; + info->num_results++; + + if (info->tail == info->head) + break; + + info->tail = (info->tail+1) % NUM_QUERIES; + } + else { + /* the oldest query is busy */ + if ((info->head+1) % NUM_QUERIES == info->tail) { + /* all queries are busy, throw away the last query and create + * a new one */ + fprintf(stderr, + "gallium_hud: all queries are busy after %i frames, " + "can't add another query\n", + NUM_QUERIES); + pipe->destroy_query(pipe, info->query[info->head]); + info->query[info->head] = + pipe->create_query(pipe, info->query_type); + } + else { + /* the last query is busy, we need to add a new one we can use + * for this frame */ + info->head = (info->head+1) % NUM_QUERIES; + if (!info->query[info->head]) { + info->query[info->head] = + pipe->create_query(pipe, info->query_type); + } + } + break; + } + } + + if (info->num_results && info->last_time + gr->pane->period <= now) { + /* compute the average value across all frames */ + hud_graph_add_value(gr, info->results_cumulative / info->num_results); + + info->last_time = now; + info->results_cumulative = 0; + info->num_results = 0; + } + + pipe->begin_query(pipe, info->query[info->head]); + } + else { + /* initialize */ + info->last_time = now; + info->query[info->head] = pipe->create_query(pipe, info->query_type); + pipe->begin_query(pipe, info->query[info->head]); + } +} + +static void +free_query_info(void *ptr) +{ + struct query_info *info = ptr; + + if (info->last_time) { + struct pipe_context *pipe = info->pipe; + int i; + + pipe->end_query(pipe, info->query[info->head]); + + for (i = 0; i < Elements(info->query); i++) { + if (info->query[i]) { + pipe->destroy_query(pipe, info->query[i]); + } + } + } + FREE(info); +} + +void +hud_pipe_query_install(struct hud_pane *pane, struct pipe_context *pipe, + const char *name, unsigned query_type, + unsigned result_index, + uint64_t max_value, boolean uses_byte_units) +{ + struct hud_graph *gr; + struct query_info *info; + + gr = CALLOC_STRUCT(hud_graph); + if (!gr) + return; + + strcpy(gr->name, name); + gr->query_data = CALLOC_STRUCT(query_info); + if (!gr->query_data) { + FREE(gr); + return; + } + + gr->query_new_value = query_new_value; + gr->free_query_data = free_query_info; + + info = gr->query_data; + info->pipe = pipe; + info->query_type = query_type; + info->result_index = result_index; + + hud_pane_add_graph(pane, gr); + if (pane->max_value < max_value) + hud_pane_set_max_value(pane, max_value); + if (uses_byte_units) + pane->uses_byte_units = TRUE; +} + +boolean +hud_driver_query_install(struct hud_pane *pane, struct pipe_context *pipe, + const char *name) +{ + struct pipe_screen *screen = pipe->screen; + struct pipe_driver_query_info query; + unsigned num_queries, i; + boolean found = FALSE; + + if (!screen->get_driver_query_info) + return FALSE; + + num_queries = screen->get_driver_query_info(screen, 0, NULL); + + for (i = 0; i < num_queries; i++) { + if (screen->get_driver_query_info(screen, i, &query) && + strcmp(query.name, name) == 0) { + found = TRUE; + break; + } + } + + if (!found) + return FALSE; + + hud_pipe_query_install(pane, pipe, query.name, query.query_type, 0, + query.max_value, query.uses_byte_units); + return TRUE; +} diff --git a/mesalib/src/gallium/auxiliary/hud/hud_fps.c b/mesalib/src/gallium/auxiliary/hud/hud_fps.c new file mode 100644 index 000000000..71cdfd04e --- /dev/null +++ b/mesalib/src/gallium/auxiliary/hud/hud_fps.c @@ -0,0 +1,81 @@ +/************************************************************************** + * + * Copyright 2013 Marek Olšák <maraeo@gmail.com> + * 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 THE AUTHORS 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. + * + **************************************************************************/ + +/* This file contains code for calculating framerate for displaying on the HUD. + */ + +#include "hud/hud_private.h" +#include "os/os_time.h" +#include "util/u_memory.h" + +struct fps_info { + int frames; + uint64_t last_time; +}; + +static void +query_fps(struct hud_graph *gr) +{ + struct fps_info *info = gr->query_data; + uint64_t now = os_time_get(); + + info->frames++; + + if (info->last_time) { + if (info->last_time + gr->pane->period <= now) { + double fps = info->frames * 1000000 / (double)(now - info->last_time); + info->frames = 0; + info->last_time = now; + + hud_graph_add_value(gr, fps); + } + } + else { + info->last_time = now; + } +} + +void +hud_fps_graph_install(struct hud_pane *pane) +{ + struct hud_graph *gr = CALLOC_STRUCT(hud_graph); + + if (!gr) + return; + + strcpy(gr->name, "fps"); + gr->query_data = CALLOC_STRUCT(fps_info); + if (!gr->query_data) { + FREE(gr); + return; + } + + gr->query_new_value = query_fps; + gr->free_query_data = free; + + hud_pane_add_graph(pane, gr); +} diff --git a/mesalib/src/gallium/auxiliary/hud/hud_private.h b/mesalib/src/gallium/auxiliary/hud/hud_private.h new file mode 100644 index 000000000..2b7d56bb1 --- /dev/null +++ b/mesalib/src/gallium/auxiliary/hud/hud_private.h @@ -0,0 +1,92 @@ +/************************************************************************** + * + * Copyright 2013 Marek Olšák <maraeo@gmail.com> + * 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 THE AUTHORS 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. + * + **************************************************************************/ + +#ifndef HUD_PRIVATE_H +#define HUD_PRIVATE_H + +#include "pipe/p_context.h" +#include "util/u_double_list.h" + +struct hud_graph { + /* initialized by common code */ + struct list_head head; + struct hud_pane *pane; + float color[3]; + float *vertices; /* ring buffer of vertices */ + + /* name and query */ + char name[128]; + void *query_data; + void (*query_new_value)(struct hud_graph *gr); + void (*free_query_data)(void *ptr); + + /* mutable variables */ + unsigned num_vertices; + unsigned index; /* vertex index being updated */ + uint64_t current_value; +}; + +struct hud_pane { + struct list_head head; + unsigned x1, y1, x2, y2; + unsigned inner_x1; + unsigned inner_y1; + unsigned inner_x2; + unsigned inner_y2; + unsigned inner_width; + unsigned inner_height; + float yscale; + unsigned max_num_vertices; + uint64_t max_value; + boolean uses_byte_units; + uint64_t period; /* in microseconds */ + + struct list_head graph_list; + unsigned num_graphs; +}; + + +/* core */ +void hud_pane_add_graph(struct hud_pane *pane, struct hud_graph *gr); +void hud_pane_set_max_value(struct hud_pane *pane, uint64_t value); +void hud_graph_add_value(struct hud_graph *gr, uint64_t value); + +/* graphs/queries */ +#define ALL_CPUS ~0 /* optionally set as cpu_index */ + +int hud_get_num_cpus(void); + +void hud_fps_graph_install(struct hud_pane *pane); +void hud_cpu_graph_install(struct hud_pane *pane, unsigned cpu_index); +void hud_pipe_query_install(struct hud_pane *pane, struct pipe_context *pipe, + const char *name, unsigned query_type, + unsigned result_index, + uint64_t max_value, boolean uses_byte_units); +boolean hud_driver_query_install(struct hud_pane *pane, + struct pipe_context *pipe, const char *name); + +#endif diff --git a/mesalib/src/gallium/auxiliary/util/u_blitter.c b/mesalib/src/gallium/auxiliary/util/u_blitter.c index 70fec9118..2a4a13e9f 100644 --- a/mesalib/src/gallium/auxiliary/util/u_blitter.c +++ b/mesalib/src/gallium/auxiliary/util/u_blitter.c @@ -1135,18 +1135,17 @@ static boolean is_blit_generic_supported(struct blitter_context *blitter, if (dst) { unsigned bind; - boolean is_stencil; const struct util_format_description *desc = util_format_description(dst_format); - - is_stencil = util_format_has_stencil(desc); + boolean dst_has_stencil = util_format_has_stencil(desc); /* Stencil export must be supported for stencil copy. */ - if ((mask & PIPE_MASK_S) && is_stencil && !ctx->has_stencil_export) { + if ((mask & PIPE_MASK_S) && dst_has_stencil && + !ctx->has_stencil_export) { return FALSE; } - if (is_stencil || util_format_has_depth(desc)) + if (dst_has_stencil || util_format_has_depth(desc)) bind = PIPE_BIND_DEPTH_STENCIL; else bind = PIPE_BIND_RENDER_TARGET; @@ -1168,15 +1167,18 @@ static boolean is_blit_generic_supported(struct blitter_context *blitter, } /* Check stencil sampler support for stencil copy. */ - if (util_format_has_stencil(util_format_description(src_format))) { - enum pipe_format stencil_format = + if (mask & PIPE_MASK_S) { + if (util_format_has_stencil(util_format_description(src_format))) { + enum pipe_format stencil_format = util_format_stencil_only(src_format); - assert(stencil_format != PIPE_FORMAT_NONE); + assert(stencil_format != PIPE_FORMAT_NONE); - if (stencil_format != src_format && - !screen->is_format_supported(screen, stencil_format, src->target, - src->nr_samples, PIPE_BIND_SAMPLER_VIEW)) { - return FALSE; + if (stencil_format != src_format && + !screen->is_format_supported(screen, stencil_format, + src->target, src->nr_samples, + PIPE_BIND_SAMPLER_VIEW)) { + return FALSE; + } } } } diff --git a/mesalib/src/gallium/auxiliary/util/u_cpu_detect.c b/mesalib/src/gallium/auxiliary/util/u_cpu_detect.c index 03280515b..7e6df9df1 100644 --- a/mesalib/src/gallium/auxiliary/util/u_cpu_detect.c +++ b/mesalib/src/gallium/auxiliary/util/u_cpu_detect.c @@ -279,6 +279,7 @@ util_cpu_detect(void) util_cpu_caps.has_sse4_1 = (regs2[2] >> 19) & 1; util_cpu_caps.has_sse4_2 = (regs2[2] >> 20) & 1; util_cpu_caps.has_avx = (regs2[2] >> 28) & 1; + util_cpu_caps.has_f16c = (regs2[2] >> 29) & 1; util_cpu_caps.has_mmx2 = util_cpu_caps.has_sse; /* SSE cpus supports mmxext too */ cacheline = ((regs2[1] >> 8) & 0xFF) * 8; diff --git a/mesalib/src/gallium/auxiliary/util/u_cpu_detect.h b/mesalib/src/gallium/auxiliary/util/u_cpu_detect.h index acac68658..21c2f048f 100644 --- a/mesalib/src/gallium/auxiliary/util/u_cpu_detect.h +++ b/mesalib/src/gallium/auxiliary/util/u_cpu_detect.h @@ -63,6 +63,7 @@ struct util_cpu_caps { unsigned has_sse4_1:1; unsigned has_sse4_2:1; unsigned has_avx:1; + unsigned has_f16c:1; unsigned has_3dnow:1; unsigned has_3dnow_ext:1; unsigned has_altivec:1; diff --git a/mesalib/src/gallium/auxiliary/util/u_debug_memory.c b/mesalib/src/gallium/auxiliary/util/u_debug_memory.c index 4bf26a524..472354781 100644 --- a/mesalib/src/gallium/auxiliary/util/u_debug_memory.c +++ b/mesalib/src/gallium/auxiliary/util/u_debug_memory.c @@ -76,6 +76,7 @@ struct debug_memory_header #endif unsigned magic; + unsigned tag; }; struct debug_memory_footer @@ -140,6 +141,7 @@ debug_malloc(const char *file, unsigned line, const char *function, hdr->function = function; hdr->size = size; hdr->magic = DEBUG_MEMORY_MAGIC; + hdr->tag = 0; #if DEBUG_FREED_MEMORY hdr->freed = FALSE; #endif @@ -263,6 +265,7 @@ debug_realloc(const char *file, unsigned line, const char *function, new_hdr->function = old_hdr->function; new_hdr->size = new_size; new_hdr->magic = DEBUG_MEMORY_MAGIC; + new_hdr->tag = 0; #if DEBUG_FREED_MEMORY new_hdr->freed = FALSE; #endif @@ -348,6 +351,58 @@ debug_memory_end(unsigned long start_no) /** + * Put a tag (arbitrary integer) on a memory block. + * Can be useful for debugging. + */ +void +debug_memory_tag(void *ptr, unsigned tag) +{ + struct debug_memory_header *hdr; + + if (!ptr) + return; + + hdr = header_from_data(ptr); + if (hdr->magic != DEBUG_MEMORY_MAGIC) { + debug_printf("%s corrupted memory at %p\n", __FUNCTION__, ptr); + debug_assert(0); + } + + hdr->tag = tag; +} + + +/** + * Check the given block of memory for validity/corruption. + */ +void +debug_memory_check_block(void *ptr) +{ + struct debug_memory_header *hdr; + struct debug_memory_footer *ftr; + + if (!ptr) + return; + + hdr = header_from_data(ptr); + ftr = footer_from_header(hdr); + + if (hdr->magic != DEBUG_MEMORY_MAGIC) { + debug_printf("%s:%u:%s: bad or corrupted memory %p\n", + hdr->file, hdr->line, hdr->function, ptr); + debug_assert(0); + } + + if (ftr->magic != DEBUG_MEMORY_MAGIC) { + debug_printf("%s:%u:%s: buffer overflow %p\n", + hdr->file, hdr->line, hdr->function, ptr); + debug_assert(0); + } +} + + + +/** * We can periodically call this from elsewhere to do a basic sanity * check of the heap memory we've allocated. */ diff --git a/mesalib/src/gallium/auxiliary/util/u_format.h b/mesalib/src/gallium/auxiliary/util/u_format.h index 00301265d..ed942fb16 100644 --- a/mesalib/src/gallium/auxiliary/util/u_format.h +++ b/mesalib/src/gallium/auxiliary/util/u_format.h @@ -447,6 +447,7 @@ util_format_is_compressed(enum pipe_format format) switch (desc->layout) { case UTIL_FORMAT_LAYOUT_S3TC: case UTIL_FORMAT_LAYOUT_RGTC: + case UTIL_FORMAT_LAYOUT_ETC: /* XXX add other formats in the future */ return TRUE; default: diff --git a/mesalib/src/gallium/auxiliary/util/u_inlines.h b/mesalib/src/gallium/auxiliary/util/u_inlines.h index ba745ebb5..7770cd514 100644 --- a/mesalib/src/gallium/auxiliary/util/u_inlines.h +++ b/mesalib/src/gallium/auxiliary/util/u_inlines.h @@ -517,7 +517,7 @@ util_query_clear_result(union pipe_query_result *result, unsigned type) memset(&result->pipeline_statistics, 0, sizeof(result->pipeline_statistics)); break; default: - assert(0); + memset(result, 0, sizeof(*result)); } } @@ -583,7 +583,7 @@ util_copy_constant_buffer(struct pipe_constant_buffer *dst, } static INLINE unsigned -util_max_layer(struct pipe_resource *r, unsigned level) +util_max_layer(const struct pipe_resource *r, unsigned level) { switch (r->target) { case PIPE_TEXTURE_CUBE: diff --git a/mesalib/src/gallium/auxiliary/util/u_resource.c b/mesalib/src/gallium/auxiliary/util/u_resource.c index a32c4f6df..66caaae84 100644 --- a/mesalib/src/gallium/auxiliary/util/u_resource.c +++ b/mesalib/src/gallium/auxiliary/util/u_resource.c @@ -1,76 +1,65 @@ +/* + * Copyright 2013 VMware, Inc. + * 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 THE AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ -#include "util/u_inlines.h" -#include "util/u_transfer.h" +#include "pipe/p_defines.h" +#include "pipe/p_state.h" +#include "util/u_format.h" +#include "util/u_math.h" +#include "util/u_resource.h" -static INLINE struct u_resource * -u_resource( struct pipe_resource *res ) -{ - return (struct u_resource *)res; -} -boolean u_resource_get_handle_vtbl(struct pipe_screen *screen, - struct pipe_resource *resource, - struct winsys_handle *handle) +/** + * Return the size of the resource in bytes. + */ +unsigned +util_resource_size(const struct pipe_resource *res) { - struct u_resource *ur = u_resource(resource); - return ur->vtbl->resource_get_handle(screen, resource, handle); -} + unsigned width = res->width0; + unsigned height = res->height0; + unsigned depth = res->depth0; + unsigned size = 0; + unsigned level; -void u_resource_destroy_vtbl(struct pipe_screen *screen, - struct pipe_resource *resource) -{ - struct u_resource *ur = u_resource(resource); - ur->vtbl->resource_destroy(screen, resource); -} + for (level = 0; level <= res->last_level; level++) { + unsigned slices; -void *u_transfer_map_vtbl(struct pipe_context *context, - struct pipe_resource *resource, - unsigned level, - unsigned usage, - const struct pipe_box *box, - struct pipe_transfer **transfer) -{ - struct u_resource *ur = u_resource(resource); - return ur->vtbl->transfer_map(context, resource, level, usage, box, - transfer); -} + if (res->target == PIPE_TEXTURE_CUBE) + slices = 6; + else if (res->target == PIPE_TEXTURE_3D) + slices = depth; + else + slices = res->array_size; -void u_transfer_flush_region_vtbl( struct pipe_context *pipe, - struct pipe_transfer *transfer, - const struct pipe_box *box) -{ - struct u_resource *ur = u_resource(transfer->resource); - ur->vtbl->transfer_flush_region(pipe, transfer, box); -} + size += (util_format_get_nblocksy(res->format, height) * + util_format_get_stride(res->format, width) * slices); -void u_transfer_unmap_vtbl( struct pipe_context *pipe, - struct pipe_transfer *transfer ) -{ - struct u_resource *ur = u_resource(transfer->resource); - ur->vtbl->transfer_unmap(pipe, transfer); -} + width = u_minify(width, 1); + height = u_minify(height, 1); + depth = u_minify(depth, 1); + } -void u_transfer_inline_write_vtbl( struct pipe_context *pipe, - struct pipe_resource *resource, - unsigned level, - unsigned usage, - const struct pipe_box *box, - const void *data, - unsigned stride, - unsigned layer_stride) -{ - struct u_resource *ur = u_resource(resource); - ur->vtbl->transfer_inline_write(pipe, - resource, - level, - usage, - box, - data, - stride, - layer_stride); + return size; } - - - - diff --git a/mesalib/src/gallium/auxiliary/util/u_resource.h b/mesalib/src/gallium/auxiliary/util/u_resource.h new file mode 100644 index 000000000..977e0136b --- /dev/null +++ b/mesalib/src/gallium/auxiliary/util/u_resource.h @@ -0,0 +1,34 @@ +/* + * Copyright 2013 VMware, Inc. + * 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 THE AUTHORS 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. + */ + +#ifndef U_RESOURCE_H +#define U_RESOURCE_H + +struct pipe_resource; + +unsigned +util_resource_size(const struct pipe_resource *res); + +#endif diff --git a/mesalib/src/gallium/auxiliary/util/u_transfer.c b/mesalib/src/gallium/auxiliary/util/u_transfer.c index 861682553..56e059bfd 100644 --- a/mesalib/src/gallium/auxiliary/util/u_transfer.c +++ b/mesalib/src/gallium/auxiliary/util/u_transfer.c @@ -87,3 +87,76 @@ void u_default_transfer_unmap( struct pipe_context *pipe, struct pipe_transfer *transfer ) { } + + +static INLINE struct u_resource * +u_resource( struct pipe_resource *res ) +{ + return (struct u_resource *)res; +} + +boolean u_resource_get_handle_vtbl(struct pipe_screen *screen, + struct pipe_resource *resource, + struct winsys_handle *handle) +{ + struct u_resource *ur = u_resource(resource); + return ur->vtbl->resource_get_handle(screen, resource, handle); +} + +void u_resource_destroy_vtbl(struct pipe_screen *screen, + struct pipe_resource *resource) +{ + struct u_resource *ur = u_resource(resource); + ur->vtbl->resource_destroy(screen, resource); +} + +void *u_transfer_map_vtbl(struct pipe_context *context, + struct pipe_resource *resource, + unsigned level, + unsigned usage, + const struct pipe_box *box, + struct pipe_transfer **transfer) +{ + struct u_resource *ur = u_resource(resource); + return ur->vtbl->transfer_map(context, resource, level, usage, box, + transfer); +} + +void u_transfer_flush_region_vtbl( struct pipe_context *pipe, + struct pipe_transfer *transfer, + const struct pipe_box *box) +{ + struct u_resource *ur = u_resource(transfer->resource); + ur->vtbl->transfer_flush_region(pipe, transfer, box); +} + +void u_transfer_unmap_vtbl( struct pipe_context *pipe, + struct pipe_transfer *transfer ) +{ + struct u_resource *ur = u_resource(transfer->resource); + ur->vtbl->transfer_unmap(pipe, transfer); +} + +void u_transfer_inline_write_vtbl( struct pipe_context *pipe, + struct pipe_resource *resource, + unsigned level, + unsigned usage, + const struct pipe_box *box, + const void *data, + unsigned stride, + unsigned layer_stride) +{ + struct u_resource *ur = u_resource(resource); + ur->vtbl->transfer_inline_write(pipe, + resource, + level, + usage, + box, + data, + stride, + layer_stride); +} + + + + diff --git a/mesalib/src/glsl/Makefile.sources b/mesalib/src/glsl/Makefile.sources index c294aa429..b5282a604 100644 --- a/mesalib/src/glsl/Makefile.sources +++ b/mesalib/src/glsl/Makefile.sources @@ -80,6 +80,7 @@ LIBGLSL_FILES = \ $(GLSL_SRCDIR)/opt_dead_code.cpp \ $(GLSL_SRCDIR)/opt_dead_code_local.cpp \ $(GLSL_SRCDIR)/opt_dead_functions.cpp \ + $(GLSL_SRCDIR)/opt_flatten_nested_if_blocks.cpp \ $(GLSL_SRCDIR)/opt_function_inlining.cpp \ $(GLSL_SRCDIR)/opt_if_simplification.cpp \ $(GLSL_SRCDIR)/opt_noop_swizzle.cpp \ diff --git a/mesalib/src/glsl/glcpp/glcpp-parse.y b/mesalib/src/glsl/glcpp/glcpp-parse.y index d6afe8814..00edbbfbd 100644 --- a/mesalib/src/glsl/glcpp/glcpp-parse.y +++ b/mesalib/src/glsl/glcpp/glcpp-parse.y @@ -1233,6 +1233,9 @@ glcpp_parser_create (const struct gl_extensions *extensions, int api) if (extensions->ARB_texture_multisample) add_builtin_define(parser, "GL_ARB_texture_multisample", 1); + + if (extensions->ARB_texture_query_lod) + add_builtin_define(parser, "GL_ARB_texture_query_lod", 1); } } diff --git a/mesalib/src/glsl/glsl_parser_extras.cpp b/mesalib/src/glsl/glsl_parser_extras.cpp index 56082f761..099229410 100644 --- a/mesalib/src/glsl/glsl_parser_extras.cpp +++ b/mesalib/src/glsl/glsl_parser_extras.cpp @@ -467,6 +467,7 @@ static const _mesa_glsl_extension _mesa_glsl_supported_extensions[] = { EXT(ARB_texture_cube_map_array, true, false, true, true, false, ARB_texture_cube_map_array), EXT(ARB_shading_language_packing, true, false, true, true, false, ARB_shading_language_packing), EXT(ARB_texture_multisample, true, false, true, true, false, ARB_texture_multisample), + EXT(ARB_texture_query_lod, false, false, true, true, false, ARB_texture_query_lod), }; #undef EXT @@ -1217,6 +1218,7 @@ do_common_optimization(exec_list *ir, bool linked, progress = do_structure_splitting(ir) || progress; } progress = do_if_simplification(ir) || progress; + progress = opt_flatten_nested_if_blocks(ir) || progress; progress = do_copy_propagation(ir) || progress; progress = do_copy_propagation_elements(ir) || progress; if (linked) diff --git a/mesalib/src/glsl/glsl_parser_extras.h b/mesalib/src/glsl/glsl_parser_extras.h index 1765cdf16..95891b595 100644 --- a/mesalib/src/glsl/glsl_parser_extras.h +++ b/mesalib/src/glsl/glsl_parser_extras.h @@ -282,6 +282,8 @@ struct _mesa_glsl_parse_state { bool ARB_shading_language_packing_warn; bool ARB_texture_multisample_enable; bool ARB_texture_multisample_warn; + bool ARB_texture_query_lod_enable; + bool ARB_texture_query_lod_warn; /*@}*/ /** Extensions supported by the OpenGL implementation. */ diff --git a/mesalib/src/glsl/glsl_types.cpp b/mesalib/src/glsl/glsl_types.cpp index 8b0a24805..419761a7d 100644 --- a/mesalib/src/glsl/glsl_types.cpp +++ b/mesalib/src/glsl/glsl_types.cpp @@ -476,6 +476,8 @@ const glsl_type *glsl_type::get_scalar_type() const return int_type; case GLSL_TYPE_FLOAT: return float_type; + case GLSL_TYPE_BOOL: + return bool_type; default: /* Handle everything else */ return type; diff --git a/mesalib/src/glsl/ir.cpp b/mesalib/src/glsl/ir.cpp index 60ef8b95a..05b77da2c 100644 --- a/mesalib/src/glsl/ir.cpp +++ b/mesalib/src/glsl/ir.cpp @@ -1307,7 +1307,7 @@ ir_dereference::is_lvalue() const } -static const char *tex_opcode_strs[] = { "tex", "txb", "txl", "txd", "txf", "txf_ms", "txs" }; +static const char *tex_opcode_strs[] = { "tex", "txb", "txl", "txd", "txf", "txf_ms", "txs", "lod" }; const char *ir_texture::opcode_string() { @@ -1338,6 +1338,9 @@ ir_texture::set_sampler(ir_dereference *sampler, const glsl_type *type) if (this->op == ir_txs) { assert(type->base_type == GLSL_TYPE_INT); + } else if (this->op == ir_lod) { + assert(type->vector_elements == 2); + assert(type->base_type == GLSL_TYPE_FLOAT); } else { assert(sampler->type->sampler_type == (int) type->base_type); if (sampler->type->sampler_shadow) diff --git a/mesalib/src/glsl/ir.h b/mesalib/src/glsl/ir.h index bbfec695f..0c3e39979 100644 --- a/mesalib/src/glsl/ir.h +++ b/mesalib/src/glsl/ir.h @@ -120,6 +120,7 @@ public: virtual class ir_dereference * as_dereference() { return NULL; } virtual class ir_dereference_array * as_dereference_array() { return NULL; } virtual class ir_dereference_variable *as_dereference_variable() { return NULL; } + virtual class ir_dereference_record *as_dereference_record() { return NULL; } virtual class ir_expression * as_expression() { return NULL; } virtual class ir_rvalue * as_rvalue() { return NULL; } virtual class ir_loop * as_loop() { return NULL; } @@ -1425,7 +1426,8 @@ enum ir_texture_opcode { ir_txd, /**< Texture look-up with partial derivatvies */ ir_txf, /**< Texel fetch with explicit LOD */ ir_txf_ms, /**< Multisample texture fetch */ - ir_txs /**< Texture size */ + ir_txs, /**< Texture size */ + ir_lod /**< Texture lod query */ }; @@ -1449,6 +1451,7 @@ enum ir_texture_opcode { * (txf_ms * <type> <sampler> <coordinate> <sample_index>) * (txs <type> <sampler> <lod>) + * (lod <type> <sampler> <coordinate>) */ class ir_texture : public ir_rvalue { public: @@ -1738,6 +1741,11 @@ public: virtual ir_constant *constant_expression_value(struct hash_table *variable_context = NULL); + virtual ir_dereference_record *as_dereference_record() + { + return this; + } + /** * Get the variable that is ultimately referenced by an r-value */ diff --git a/mesalib/src/glsl/ir_clone.cpp b/mesalib/src/glsl/ir_clone.cpp index 4797451d7..5b42935f8 100644 --- a/mesalib/src/glsl/ir_clone.cpp +++ b/mesalib/src/glsl/ir_clone.cpp @@ -243,6 +243,7 @@ ir_texture::clone(void *mem_ctx, struct hash_table *ht) const switch (this->op) { case ir_tex: + case ir_lod: break; case ir_txb: new_tex->lod_info.bias = this->lod_info.bias->clone(mem_ctx, ht); diff --git a/mesalib/src/glsl/ir_constant_expression.cpp b/mesalib/src/glsl/ir_constant_expression.cpp index c2d0dc46c..c09e56a3d 100644 --- a/mesalib/src/glsl/ir_constant_expression.cpp +++ b/mesalib/src/glsl/ir_constant_expression.cpp @@ -1398,7 +1398,7 @@ ir_dereference_array::constant_referenced(struct hash_table *variable_context, return; } - const glsl_type *vt = substore->type; + const glsl_type *vt = array->type; if (vt->is_array()) { store = substore->get_array_element(index); offset = 0; diff --git a/mesalib/src/glsl/ir_hv_accept.cpp b/mesalib/src/glsl/ir_hv_accept.cpp index 5fa75011e..559b71af3 100644 --- a/mesalib/src/glsl/ir_hv_accept.cpp +++ b/mesalib/src/glsl/ir_hv_accept.cpp @@ -213,6 +213,7 @@ ir_texture::accept(ir_hierarchical_visitor *v) switch (this->op) { case ir_tex: + case ir_lod: break; case ir_txb: s = this->lod_info.bias->accept(v); diff --git a/mesalib/src/glsl/ir_optimization.h b/mesalib/src/glsl/ir_optimization.h index 2454bbe6f..a8885d722 100644 --- a/mesalib/src/glsl/ir_optimization.h +++ b/mesalib/src/glsl/ir_optimization.h @@ -82,6 +82,7 @@ bool do_function_inlining(exec_list *instructions); bool do_lower_jumps(exec_list *instructions, bool pull_out_jumps = true, bool lower_sub_return = true, bool lower_main_return = false, bool lower_continue = false, bool lower_break = false); bool do_lower_texture_projection(exec_list *instructions); bool do_if_simplification(exec_list *instructions); +bool opt_flatten_nested_if_blocks(exec_list *instructions); bool do_discard_simplification(exec_list *instructions); bool lower_if_to_cond_assign(exec_list *instructions, unsigned max_depth = 0); bool do_mat_op_to_vec(exec_list *instructions); diff --git a/mesalib/src/glsl/ir_print_visitor.cpp b/mesalib/src/glsl/ir_print_visitor.cpp index 3bdea9bbc..597d2813f 100644 --- a/mesalib/src/glsl/ir_print_visitor.cpp +++ b/mesalib/src/glsl/ir_print_visitor.cpp @@ -278,6 +278,7 @@ void ir_print_visitor::visit(ir_texture *ir) switch (ir->op) { case ir_tex: + case ir_lod: break; case ir_txb: ir->lod_info.bias->accept(this); diff --git a/mesalib/src/glsl/ir_reader.cpp b/mesalib/src/glsl/ir_reader.cpp index 22ce03b0d..16fdc41b4 100644 --- a/mesalib/src/glsl/ir_reader.cpp +++ b/mesalib/src/glsl/ir_reader.cpp @@ -917,6 +917,8 @@ ir_reader::read_texture(s_expression *expr) s_pattern tex_pattern[] = { "tex", s_type, s_sampler, s_coord, s_offset, s_proj, s_shadow }; + s_pattern lod_pattern[] = + { "lod", s_type, s_sampler, s_coord }; s_pattern txf_pattern[] = { "txf", s_type, s_sampler, s_coord, s_offset, s_lod }; s_pattern txf_ms_pattern[] = @@ -926,7 +928,9 @@ ir_reader::read_texture(s_expression *expr) s_pattern other_pattern[] = { tag, s_type, s_sampler, s_coord, s_offset, s_proj, s_shadow, s_lod }; - if (MATCH(expr, tex_pattern)) { + if (MATCH(expr, lod_pattern)) { + op = ir_lod; + } else if (MATCH(expr, tex_pattern)) { op = ir_tex; } else if (MATCH(expr, txf_pattern)) { op = ir_txf; @@ -939,7 +943,7 @@ ir_reader::read_texture(s_expression *expr) if (op == -1) return NULL; } else { - ir_read_error(NULL, "unexpected texture pattern"); + ir_read_error(NULL, "unexpected texture pattern %s", tag->value()); return NULL; } @@ -971,7 +975,7 @@ ir_reader::read_texture(s_expression *expr) return NULL; } - if (op != ir_txf_ms) { + if (op != ir_txf_ms && op != ir_lod) { // Read texel offset - either 0 or an rvalue. s_int *si_offset = SX_AS_INT(s_offset); if (si_offset == NULL || si_offset->value() != 0) { @@ -984,7 +988,7 @@ ir_reader::read_texture(s_expression *expr) } } - if (op != ir_txf && op != ir_txf_ms && op != ir_txs) { + if (op != ir_txf && op != ir_txf_ms && op != ir_txs && op != ir_lod) { s_int *proj_as_int = SX_AS_INT(s_proj); if (proj_as_int && proj_as_int->value() == 1) { tex->projector = NULL; @@ -1054,7 +1058,7 @@ ir_reader::read_texture(s_expression *expr) break; } default: - // tex doesn't have any extra parameters. + // tex and lod don't have any extra parameters. break; }; return tex; diff --git a/mesalib/src/glsl/ir_rvalue_visitor.cpp b/mesalib/src/glsl/ir_rvalue_visitor.cpp index 543c54496..3504a4dda 100644 --- a/mesalib/src/glsl/ir_rvalue_visitor.cpp +++ b/mesalib/src/glsl/ir_rvalue_visitor.cpp @@ -57,6 +57,7 @@ ir_rvalue_base_visitor::rvalue_visit(ir_texture *ir) switch (ir->op) { case ir_tex: + case ir_lod: break; case ir_txb: handle_rvalue(&ir->lod_info.bias); diff --git a/mesalib/src/glsl/ir_validate.cpp b/mesalib/src/glsl/ir_validate.cpp index 24ea506dc..699c192cd 100644 --- a/mesalib/src/glsl/ir_validate.cpp +++ b/mesalib/src/glsl/ir_validate.cpp @@ -701,6 +701,11 @@ check_node_type(ir_instruction *ir, void *data) void validate_ir_tree(exec_list *instructions) { + /* We shouldn't have any reason to validate IR in a release build, + * and it's half composed of assert()s anyway which wouldn't do + * anything. + */ +#ifdef DEBUG ir_validate v; v.run(instructions); @@ -710,4 +715,5 @@ validate_ir_tree(exec_list *instructions) visit_tree(ir, check_node_type, NULL); } +#endif } diff --git a/mesalib/src/glsl/linker.cpp b/mesalib/src/glsl/linker.cpp index 29856b080..2b30d2b65 100644 --- a/mesalib/src/glsl/linker.cpp +++ b/mesalib/src/glsl/linker.cpp @@ -1067,13 +1067,11 @@ link_intrastage_shaders(void *mem_ctx, free(linking_shaders); -#ifdef DEBUG /* At this point linked should contain all of the linked IR, so * validate it to make sure nothing went wrong. */ if (linked) validate_ir_tree(linked->ir); -#endif /* Make a pass over all variable declarations to ensure that arrays with * unspecified sizes have a size specified. The size is inferred from the diff --git a/mesalib/src/glsl/lower_jumps.cpp b/mesalib/src/glsl/lower_jumps.cpp index 92813f567..bfc8c013b 100644 --- a/mesalib/src/glsl/lower_jumps.cpp +++ b/mesalib/src/glsl/lower_jumps.cpp @@ -1002,10 +1002,12 @@ do_lower_jumps(exec_list *instructions, bool pull_out_jumps, bool lower_sub_retu v.lower_sub_return = lower_sub_return; v.lower_main_return = lower_main_return; + bool progress_ever = false; do { v.progress = false; visit_exec_list(instructions, &v); + progress_ever = v.progress || progress_ever; } while (v.progress); - return v.progress; + return progress_ever; } diff --git a/mesalib/src/glsl/lower_ubo_reference.cpp b/mesalib/src/glsl/lower_ubo_reference.cpp index 026197df7..aade203e7 100644 --- a/mesalib/src/glsl/lower_ubo_reference.cpp +++ b/mesalib/src/glsl/lower_ubo_reference.cpp @@ -356,18 +356,14 @@ lower_ubo_reference_visitor::emit_ubo_loads(ir_dereference *deref, unsigned matrix_stride = 16; for (unsigned i = 0; i < deref->type->vector_elements; i++) { - ir_rvalue *chan = new(mem_ctx) ir_constant((int)i); - ir_dereference *deref_chan = - new(mem_ctx) ir_dereference_array(deref->clone(mem_ctx, NULL), - chan); - ir_rvalue *chan_offset = add(base_offset, new(mem_ctx) ir_constant(deref_offset + i * matrix_stride)); - base_ir->insert_before(assign(deref_chan, + base_ir->insert_before(assign(deref->clone(mem_ctx, NULL), ubo_load(glsl_type::float_type, - chan_offset))); + chan_offset), + (1U << i))); } } } diff --git a/mesalib/src/glsl/opt_flatten_nested_if_blocks.cpp b/mesalib/src/glsl/opt_flatten_nested_if_blocks.cpp new file mode 100644 index 000000000..c70210204 --- /dev/null +++ b/mesalib/src/glsl/opt_flatten_nested_if_blocks.cpp @@ -0,0 +1,103 @@ +/* + * Copyright © 2013 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. + */ + +/** + * \file opt_flatten_nested_if_blocks.cpp + * + * Flattens nested if blocks such as: + * + * if (x) { + * if (y) { + * ... + * } + * } + * + * into a single if block with a combined condition: + * + * if (x && y) { + * ... + * } + */ + +#include "ir.h" +#include "ir_builder.h" + +using namespace ir_builder; + +namespace { + +class nested_if_flattener : public ir_hierarchical_visitor { +public: + nested_if_flattener() + { + progress = false; + } + + ir_visitor_status visit_leave(ir_if *); + ir_visitor_status visit_enter(ir_assignment *); + + bool progress; +}; + +} /* unnamed namespace */ + +/* We only care about the top level "if" instructions, so don't + * descend into expressions. + */ +ir_visitor_status +nested_if_flattener::visit_enter(ir_assignment *ir) +{ + (void) ir; + return visit_continue_with_parent; +} + +bool +opt_flatten_nested_if_blocks(exec_list *instructions) +{ + nested_if_flattener v; + + v.run(instructions); + return v.progress; +} + + +ir_visitor_status +nested_if_flattener::visit_leave(ir_if *ir) +{ + /* Only handle a single ir_if within the then clause of an ir_if. No extra + * instructions, no else clauses, nothing. + */ + if (ir->then_instructions.is_empty() || !ir->else_instructions.is_empty()) + return visit_continue; + + ir_if *inner = ((ir_instruction *) ir->then_instructions.head)->as_if(); + if (!inner || !inner->next->is_tail_sentinel() || + !inner->else_instructions.is_empty()) + return visit_continue; + + ir->condition = logic_and(ir->condition, inner->condition); + inner->then_instructions.move_nodes_to(&ir->then_instructions); + + progress = true; + return visit_continue; +} diff --git a/mesalib/src/glsl/opt_tree_grafting.cpp b/mesalib/src/glsl/opt_tree_grafting.cpp index 985540196..9aceb134d 100644 --- a/mesalib/src/glsl/opt_tree_grafting.cpp +++ b/mesalib/src/glsl/opt_tree_grafting.cpp @@ -274,6 +274,7 @@ ir_tree_grafting_visitor::visit_enter(ir_texture *ir) switch (ir->op) { case ir_tex: + case ir_lod: break; case ir_txb: if (do_graft(&ir->lod_info.bias)) diff --git a/mesalib/src/glsl/standalone_scaffolding.cpp b/mesalib/src/glsl/standalone_scaffolding.cpp index b5ef768bd..0c1f52f48 100644 --- a/mesalib/src/glsl/standalone_scaffolding.cpp +++ b/mesalib/src/glsl/standalone_scaffolding.cpp @@ -103,6 +103,7 @@ void initialize_context_to_defaults(struct gl_context *ctx, gl_api api) ctx->Extensions.OES_standard_derivatives = true; ctx->Extensions.ARB_texture_cube_map_array = true; ctx->Extensions.ARB_texture_multisample = true; + ctx->Extensions.ARB_texture_query_lod = true; ctx->Const.GLSLVersion = 120; diff --git a/mesalib/src/mapi/glapi/gen/ARB_texture_storage_multisample.xml b/mesalib/src/mapi/glapi/gen/ARB_texture_storage_multisample.xml new file mode 100644 index 000000000..0f9d323d4 --- /dev/null +++ b/mesalib/src/mapi/glapi/gen/ARB_texture_storage_multisample.xml @@ -0,0 +1,31 @@ +<?xml version="1.0"?> +<!DOCTYPE OpenGLAPI SYSTEM "gl_API.dtd"> + +<!-- Note: no GLX protocol info yet. --> + +<OpenGLAPI> + +<category name="GL_ARB_texture_storage_multisample" number="141"> + + <function name="TexStorage2DMultisample" offset="assign"> + <param name="target" type="GLenum"/> + <param name="samples" type="GLsizei"/> + <param name="internalformat" type="GLenum"/> + <param name="width" type="GLsizei"/> + <param name="height" type="GLsizei"/> + <param name="fixedsamplelocations" type="GLboolean"/> + </function> + + <function name="TexStorage3DMultisample" offset="assign"> + <param name="target" type="GLenum"/> + <param name="samples" type="GLsizei"/> + <param name="internalformat" type="GLenum"/> + <param name="width" type="GLsizei"/> + <param name="height" type="GLsizei"/> + <param name="depth" type="GLsizei"/> + <param name="fixedsamplelocations" type="GLboolean"/> + </function> + +</category> + +</OpenGLAPI> diff --git a/mesalib/src/mapi/glapi/gen/gl_API.xml b/mesalib/src/mapi/glapi/gen/gl_API.xml index 75957dc7d..df9592477 100644 --- a/mesalib/src/mapi/glapi/gen/gl_API.xml +++ b/mesalib/src/mapi/glapi/gen/gl_API.xml @@ -8321,6 +8321,10 @@ <xi:include href="ARB_texture_buffer_range.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> +<!-- 140. GL_ARB_texture_query_levels --> + +<xi:include href="ARB_texture_storage_multisample.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> + <!-- Non-ARB extensions sorted by extension number. --> <category name="GL_EXT_blend_color" number="2"> diff --git a/mesalib/src/mesa/drivers/common/driverfuncs.c b/mesalib/src/mesa/drivers/common/driverfuncs.c index 731d46658..a98dfc607 100644 --- a/mesalib/src/mesa/drivers/common/driverfuncs.c +++ b/mesalib/src/mesa/drivers/common/driverfuncs.c @@ -28,6 +28,7 @@ #include "main/accum.h" #include "main/arrayobj.h" #include "main/context.h" +#include "main/formatquery.h" #include "main/framebuffer.h" #include "main/mipmap.h" #include "main/queryobj.h" @@ -90,7 +91,7 @@ _mesa_init_driver_functions(struct dd_function_table *driver) /* Texture functions */ driver->ChooseTextureFormat = _mesa_choose_tex_format; - driver->QuerySamplesForFormat = NULL; + driver->QuerySamplesForFormat = _mesa_query_samples_for_format; driver->TexImage = _mesa_store_teximage; driver->TexSubImage = _mesa_store_texsubimage; driver->GetTexImage = _mesa_meta_GetTexImage; diff --git a/mesalib/src/mesa/drivers/common/meta.c b/mesalib/src/mesa/drivers/common/meta.c index 8114550ba..e3ab82bfe 100644 --- a/mesalib/src/mesa/drivers/common/meta.c +++ b/mesalib/src/mesa/drivers/common/meta.c @@ -757,7 +757,8 @@ _mesa_meta_begin(struct gl_context *ctx, GLbitfield state) * it's for the pixel path (ClampFragmentColor is GL_TRUE), * regardless of the internal implementation of the metaops. */ - if (ctx->Color.ClampFragmentColor != GL_TRUE) + if (ctx->Color.ClampFragmentColor != GL_TRUE && + ctx->Extensions.ARB_color_buffer_float) _mesa_ClampColor(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE); } @@ -767,7 +768,8 @@ _mesa_meta_begin(struct gl_context *ctx, GLbitfield state) /* Generally in here we never want vertex color clamping -- * result clamping is only dependent on fragment clamping. */ - _mesa_ClampColor(GL_CLAMP_VERTEX_COLOR, GL_FALSE); + if (ctx->Extensions.ARB_color_buffer_float) + _mesa_ClampColor(GL_CLAMP_VERTEX_COLOR, GL_FALSE); } if (state & MESA_META_CONDITIONAL_RENDER) { @@ -1091,11 +1093,13 @@ _mesa_meta_end(struct gl_context *ctx) _mesa_DepthRange(save->DepthNear, save->DepthFar); } - if (state & MESA_META_CLAMP_FRAGMENT_COLOR) { + if (state & MESA_META_CLAMP_FRAGMENT_COLOR && + ctx->Extensions.ARB_color_buffer_float) { _mesa_ClampColor(GL_CLAMP_FRAGMENT_COLOR, save->ClampFragmentColor); } - if (state & MESA_META_CLAMP_VERTEX_COLOR) { + if (state & MESA_META_CLAMP_VERTEX_COLOR && + ctx->Extensions.ARB_color_buffer_float) { _mesa_ClampColor(GL_CLAMP_VERTEX_COLOR, save->ClampVertexColor); } @@ -2044,7 +2048,8 @@ _mesa_meta_Clear(struct gl_context *ctx, GLbitfield buffers) /* leave colormask, glDrawBuffer state as-is */ /* Clears never have the color clamped. */ - _mesa_ClampColor(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE); + if (ctx->Extensions.ARB_color_buffer_float) + _mesa_ClampColor(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE); } else { ASSERT(metaSave & MESA_META_COLOR_MASK); @@ -2295,7 +2300,8 @@ _mesa_meta_glsl_Clear(struct gl_context *ctx, GLbitfield buffers) /* leave colormask, glDrawBuffer state as-is */ /* Clears never have the color clamped. */ - _mesa_ClampColor(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE); + if (ctx->Extensions.ARB_color_buffer_float) + _mesa_ClampColor(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE); } else { ASSERT(metaSave & MESA_META_COLOR_MASK); diff --git a/mesalib/src/mesa/drivers/dri/common/Android.mk b/mesalib/src/mesa/drivers/dri/common/Android.mk index f428c3855..b3dac29dd 100644 --- a/mesalib/src/mesa/drivers/dri/common/Android.mk +++ b/mesalib/src/mesa/drivers/dri/common/Android.mk @@ -77,7 +77,8 @@ $(intermediates)/xmlpool/options.h: PRIVATE_SCRIPT := $(LOCAL_PATH)/xmlpool/gen_ $(intermediates)/xmlpool/options.h: PRIVATE_LOCALEDIR := $(intermediates)/xmlpool $(intermediates)/xmlpool/options.h: PRIVATE_TEMPLATE_HEADER := $(LOCAL_PATH)/xmlpool/t_options.h $(intermediates)/xmlpool/options.h: PRIVATE_MO_FILES := $(MESA_DRI_OPTIONS_LANGS:%=$(intermediates)/xmlpool/%/LC_MESSAGES/options.mo) -$(intermediates)/xmlpool/options.h: $(PRIVATE_SCRIPT) $(PRIVATE_TEMPLATE_HEADER) $(PRIVATE_MO_FILES) +.SECONDEXPANSION: +$(intermediates)/xmlpool/options.h: $$(PRIVATE_SCRIPT) $$(PRIVATE_TEMPLATE_HEADER) $$(PRIVATE_MO_FILES) mkdir -p $(dir $@) mkdir -p $(PRIVATE_LOCALEDIR) $(MESA_PYTHON2) $(PRIVATE_SCRIPT) $(PRIVATE_TEMPLATE_HEADER) \ diff --git a/mesalib/src/mesa/drivers/dri/common/drirc b/mesalib/src/mesa/drivers/dri/common/drirc index a13941f68..556d1b599 100644 --- a/mesalib/src/mesa/drivers/dri/common/drirc +++ b/mesalib/src/mesa/drivers/dri/common/drirc @@ -25,5 +25,11 @@ <application name="Savage 2" executable="savage2.bin"> <option name="disable_glsl_line_continuations" value="true" /> </application> + <application name="Topogun (32-bit)" executable="topogun32"> + <option name="always_have_depth_buffer" value="true" /> + </application> + <application name="Topogun (64-bit)" executable="topogun64"> + <option name="always_have_depth_buffer" value="true" /> + </application> </device> </driconf> diff --git a/mesalib/src/mesa/main/attrib.c b/mesalib/src/mesa/main/attrib.c index 3b991bcac..a672845bf 100644 --- a/mesalib/src/mesa/main/attrib.c +++ b/mesalib/src/mesa/main/attrib.c @@ -986,7 +986,9 @@ _mesa_PopAttrib(void) _mesa_set_enable(ctx, GL_INDEX_LOGIC_OP, color->IndexLogicOpEnabled); _mesa_set_enable(ctx, GL_DITHER, color->DitherFlag); - _mesa_ClampColor(GL_CLAMP_FRAGMENT_COLOR_ARB, color->ClampFragmentColor); + if (ctx->Extensions.ARB_color_buffer_float) + _mesa_ClampColor(GL_CLAMP_FRAGMENT_COLOR_ARB, + color->ClampFragmentColor); _mesa_ClampColor(GL_CLAMP_READ_COLOR_ARB, color->ClampReadColor); /* GL_ARB_framebuffer_sRGB / GL_EXT_framebuffer_sRGB */ @@ -1114,7 +1116,10 @@ _mesa_PopAttrib(void) /* materials */ memcpy(&ctx->Light.Material, &light->Material, sizeof(struct gl_material)); - _mesa_ClampColor(GL_CLAMP_VERTEX_COLOR_ARB, light->ClampVertexColor); + if (ctx->Extensions.ARB_color_buffer_float) { + _mesa_ClampColor(GL_CLAMP_VERTEX_COLOR_ARB, + light->ClampVertexColor); + } } break; case GL_LINE_BIT: diff --git a/mesalib/src/mesa/main/blend.c b/mesalib/src/mesa/main/blend.c index 309f1d538..09a1c9ae8 100644 --- a/mesalib/src/mesa/main/blend.c +++ b/mesalib/src/mesa/main/blend.c @@ -765,24 +765,96 @@ _mesa_ClampColor(GLenum target, GLenum clamp) switch (target) { case GL_CLAMP_VERTEX_COLOR_ARB: + if (ctx->API == API_OPENGL_CORE && + !ctx->Extensions.ARB_color_buffer_float) { + goto invalid_enum; + } FLUSH_VERTICES(ctx, _NEW_LIGHT); ctx->Light.ClampVertexColor = clamp; + _mesa_update_clamp_vertex_color(ctx); break; case GL_CLAMP_FRAGMENT_COLOR_ARB: + if (ctx->API == API_OPENGL_CORE && + !ctx->Extensions.ARB_color_buffer_float) { + goto invalid_enum; + } FLUSH_VERTICES(ctx, _NEW_FRAG_CLAMP); ctx->Color.ClampFragmentColor = clamp; + _mesa_update_clamp_fragment_color(ctx); break; case GL_CLAMP_READ_COLOR_ARB: FLUSH_VERTICES(ctx, _NEW_COLOR); ctx->Color.ClampReadColor = clamp; break; default: - _mesa_error(ctx, GL_INVALID_ENUM, "glClampColorARB(target)"); - return; + goto invalid_enum; } + return; + +invalid_enum: + _mesa_error(ctx, GL_INVALID_ENUM, "glClampColor(%s)", + _mesa_lookup_enum_by_nr(target)); +} + +static GLboolean +get_clamp_color(const struct gl_framebuffer *fb, GLenum clamp) +{ + if (clamp == GL_TRUE || clamp == GL_FALSE) + return clamp; + + ASSERT(clamp == GL_FIXED_ONLY); + if (!fb) + return GL_TRUE; + + return fb->_AllColorBuffersFixedPoint; +} + +GLboolean +_mesa_get_clamp_fragment_color(const struct gl_context *ctx) +{ + return get_clamp_color(ctx->DrawBuffer, + ctx->Color.ClampFragmentColor); +} + +GLboolean +_mesa_get_clamp_vertex_color(const struct gl_context *ctx) +{ + return get_clamp_color(ctx->DrawBuffer, ctx->Light.ClampVertexColor); +} + +GLboolean +_mesa_get_clamp_read_color(const struct gl_context *ctx) +{ + return get_clamp_color(ctx->ReadBuffer, ctx->Color.ClampReadColor); } +/** + * Update the ctx->Color._ClampFragmentColor field + */ +void +_mesa_update_clamp_fragment_color(struct gl_context *ctx) +{ + struct gl_framebuffer *fb = ctx->DrawBuffer; + /* Don't clamp if: + * - there is no colorbuffer + * - all colorbuffers are unsigned normalized, so clamping has no effect + * - there is an integer colorbuffer + */ + if (!fb || !fb->_HasSNormOrFloatColorBuffer || fb->_IntegerColor) + ctx->Color._ClampFragmentColor = GL_FALSE; + else + ctx->Color._ClampFragmentColor = _mesa_get_clamp_fragment_color(ctx); +} + +/** + * Update the ctx->Color._ClampVertexColor field + */ +void +_mesa_update_clamp_vertex_color(struct gl_context *ctx) +{ + ctx->Light._ClampVertexColor = _mesa_get_clamp_vertex_color(ctx); +} /**********************************************************************/ @@ -832,10 +904,10 @@ void _mesa_init_color( struct gl_context * ctx ) ctx->Color.DrawBuffer[0] = GL_FRONT; } - ctx->Color.ClampFragmentColor = GL_FIXED_ONLY_ARB; - ctx->Color._ClampFragmentColor = GL_TRUE; + ctx->Color.ClampFragmentColor = ctx->API == API_OPENGL_COMPAT ? + GL_FIXED_ONLY_ARB : GL_FALSE; + ctx->Color._ClampFragmentColor = GL_FALSE; ctx->Color.ClampReadColor = GL_FIXED_ONLY_ARB; - ctx->Color._ClampReadColor = GL_TRUE; if (ctx->API == API_OPENGLES2) { /* GLES 3 behaves as though GL_FRAMEBUFFER_SRGB is always enabled. */ diff --git a/mesalib/src/mesa/main/blend.h b/mesalib/src/mesa/main/blend.h index a539aa809..621311d55 100644 --- a/mesalib/src/mesa/main/blend.h +++ b/mesalib/src/mesa/main/blend.h @@ -99,6 +99,20 @@ _mesa_ColorMaski( GLuint buf, GLboolean red, GLboolean green, extern void GLAPIENTRY _mesa_ClampColor(GLenum target, GLenum clamp); +extern GLboolean +_mesa_get_clamp_fragment_color(const struct gl_context *ctx); + +extern GLboolean +_mesa_get_clamp_vertex_color(const struct gl_context *ctx); + +extern GLboolean +_mesa_get_clamp_read_color(const struct gl_context *ctx); + +extern void +_mesa_update_clamp_fragment_color(struct gl_context *ctx); + +extern void +_mesa_update_clamp_vertex_color(struct gl_context *ctx); extern void _mesa_init_color( struct gl_context * ctx ); diff --git a/mesalib/src/mesa/main/compiler.h b/mesalib/src/mesa/main/compiler.h index 8b23665e6..8431534c3 100644 --- a/mesalib/src/mesa/main/compiler.h +++ b/mesalib/src/mesa/main/compiler.h @@ -256,7 +256,7 @@ static INLINE GLuint CPU_TO_LE32(GLuint x) */ #define STATIC_ASSERT(COND) \ do { \ - typedef int static_assertion_failed[(!!(COND))*2-1]; \ + (void) sizeof(char [1 - 2*!(COND)]); \ } while (0) diff --git a/mesalib/src/mesa/main/extensions.c b/mesalib/src/mesa/main/extensions.c index e90a29680..c7f038b88 100644 --- a/mesalib/src/mesa/main/extensions.c +++ b/mesalib/src/mesa/main/extensions.c @@ -144,10 +144,12 @@ static const struct extension extension_table[] = { { "GL_ARB_texture_mirrored_repeat", o(dummy_true), GLL, 2001 }, { "GL_ARB_texture_multisample", o(ARB_texture_multisample), GL, 2009 }, { "GL_ARB_texture_non_power_of_two", o(ARB_texture_non_power_of_two), GL, 2003 }, + { "GL_ARB_texture_query_lod", o(ARB_texture_query_lod), GL, 2009 }, { "GL_ARB_texture_rectangle", o(NV_texture_rectangle), GL, 2004 }, { "GL_ARB_texture_rgb10_a2ui", o(ARB_texture_rgb10_a2ui), GL, 2009 }, { "GL_ARB_texture_rg", o(ARB_texture_rg), GL, 2008 }, { "GL_ARB_texture_storage", o(ARB_texture_storage), GL, 2011 }, + { "GL_ARB_texture_storage_multisample", o(ARB_texture_storage_multisample), GL, 2012 }, { "GL_ARB_texture_swizzle", o(EXT_texture_swizzle), GL, 2008 }, { "GL_ARB_timer_query", o(ARB_timer_query), GL, 2010 }, { "GL_ARB_transform_feedback2", o(ARB_transform_feedback2), GL, 2010 }, diff --git a/mesalib/src/mesa/main/fbobject.c b/mesalib/src/mesa/main/fbobject.c index 3fdf62667..fc2b2620b 100644 --- a/mesalib/src/mesa/main/fbobject.c +++ b/mesalib/src/mesa/main/fbobject.c @@ -784,6 +784,8 @@ _mesa_test_framebuffer_completeness(struct gl_context *ctx, numImages = 0; fb->Width = 0; fb->Height = 0; + fb->_AllColorBuffersFixedPoint = GL_TRUE; + fb->_HasSNormOrFloatColorBuffer = GL_FALSE; /* Start at -2 to more easily loop over all attachment points. * -2: depth buffer @@ -900,6 +902,19 @@ _mesa_test_framebuffer_completeness(struct gl_context *ctx, /* check if integer color */ fb->_IntegerColor = _mesa_is_format_integer_color(attFormat); + /* Update _AllColorBuffersFixedPoint and _HasSNormOrFloatColorBuffer. */ + if (i >= 0) { + GLenum type = _mesa_get_format_datatype(attFormat); + + fb->_AllColorBuffersFixedPoint = + fb->_AllColorBuffersFixedPoint && + (type == GL_UNSIGNED_NORMALIZED || type == GL_SIGNED_NORMALIZED); + + fb->_HasSNormOrFloatColorBuffer = + fb->_HasSNormOrFloatColorBuffer || + type == GL_SIGNED_NORMALIZED || type == GL_FLOAT; + } + /* Error-check width, height, format */ if (numImages == 1) { /* save format */ @@ -1537,15 +1552,16 @@ renderbuffer_storage(GLenum target, GLenum internalFormat, /* NumSamples == 0 indicates non-multisampling */ samples = 0; } - - /* check the sample count; - * note: driver may choose to use more samples than what's requested - */ - sample_count_error = _mesa_check_sample_count(ctx, target, - internalFormat, samples); - if (sample_count_error != GL_NO_ERROR) { - _mesa_error(ctx, sample_count_error, "%s(samples)", func); - return; + else { + /* check the sample count; + * note: driver may choose to use more samples than what's requested + */ + sample_count_error = _mesa_check_sample_count(ctx, target, + internalFormat, samples); + if (sample_count_error != GL_NO_ERROR) { + _mesa_error(ctx, sample_count_error, "%s(samples)", func); + return; + } } rb = ctx->CurrentRenderbuffer; diff --git a/mesalib/src/mesa/main/formatquery.c b/mesalib/src/mesa/main/formatquery.c index 78c5fbe5e..e45dc8680 100644 --- a/mesalib/src/mesa/main/formatquery.c +++ b/mesalib/src/mesa/main/formatquery.c @@ -30,6 +30,21 @@ #include "fbobject.h" #include "formatquery.h" +/* default implementation of QuerySamplesForFormat driverfunc, for + * non-multisample-capable drivers. */ +size_t +_mesa_query_samples_for_format(struct gl_context *ctx, GLenum target, + GLenum internalFormat, int samples[16]) +{ + (void) target; + (void) internalFormat; + (void) ctx; + + samples[0] = 1; + return 1; +} + + void GLAPIENTRY _mesa_GetInternalformativ(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params) diff --git a/mesalib/src/mesa/main/formatquery.h b/mesalib/src/mesa/main/formatquery.h index 585c3eb64..603400059 100644 --- a/mesalib/src/mesa/main/formatquery.h +++ b/mesalib/src/mesa/main/formatquery.h @@ -28,6 +28,10 @@ #include "compiler.h" #include "glheader.h" +size_t +_mesa_query_samples_for_format(struct gl_context *ctx, GLenum target, + GLenum internalFormat, int samples[16]); + extern void GLAPIENTRY _mesa_GetInternalformativ(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params); diff --git a/mesalib/src/mesa/main/framebuffer.c b/mesalib/src/mesa/main/framebuffer.c index 619aaa337..6c6977431 100644 --- a/mesalib/src/mesa/main/framebuffer.c +++ b/mesalib/src/mesa/main/framebuffer.c @@ -32,6 +32,7 @@ #include "glheader.h" #include "imports.h" +#include "blend.h" #include "buffers.h" #include "context.h" #include "enums.h" @@ -154,6 +155,8 @@ _mesa_initialize_window_framebuffer(struct gl_framebuffer *fb, fb->Delete = _mesa_destroy_framebuffer; fb->_Status = GL_FRAMEBUFFER_COMPLETE_EXT; + fb->_AllColorBuffersFixedPoint = !visual->floatMode; + fb->_HasSNormOrFloatColorBuffer = visual->floatMode; compute_depth_max(fb); } @@ -740,6 +743,9 @@ _mesa_update_framebuffer(struct gl_context *ctx) update_framebuffer(ctx, drawFb); if (readFb != drawFb) update_framebuffer(ctx, readFb); + + _mesa_update_clamp_vertex_color(ctx); + _mesa_update_clamp_fragment_color(ctx); } diff --git a/mesalib/src/mesa/main/get.c b/mesalib/src/mesa/main/get.c index 582ef3198..2ba868c0d 100644 --- a/mesalib/src/mesa/main/get.c +++ b/mesalib/src/mesa/main/get.c @@ -24,6 +24,7 @@ #include "glheader.h" #include "context.h" +#include "blend.h" #include "enable.h" #include "enums.h" #include "extensions.h" @@ -358,6 +359,13 @@ EXTRA_EXT(ARB_texture_buffer_range); EXTRA_EXT(ARB_texture_multisample); static const int +extra_ARB_color_buffer_float_or_glcore[] = { + EXT(ARB_color_buffer_float), + EXTRA_API_GL_CORE, + EXTRA_END +}; + +static const int extra_NV_primitive_restart[] = { EXT(NV_primitive_restart), EXTRA_END @@ -767,13 +775,13 @@ find_custom_value(struct gl_context *ctx, const struct value_desc *d, union valu break; case GL_FOG_COLOR: - if(ctx->Color._ClampFragmentColor) + if (_mesa_get_clamp_fragment_color(ctx)) COPY_4FV(v->value_float_4, ctx->Fog.Color); else COPY_4FV(v->value_float_4, ctx->Fog.ColorUnclamped); break; case GL_COLOR_CLEAR_VALUE: - if(ctx->Color._ClampFragmentColor) { + if (_mesa_get_clamp_fragment_color(ctx)) { v->value_float_4[0] = CLAMP(ctx->Color.ClearColor.f[0], 0.0F, 1.0F); v->value_float_4[1] = CLAMP(ctx->Color.ClearColor.f[1], 0.0F, 1.0F); v->value_float_4[2] = CLAMP(ctx->Color.ClearColor.f[2], 0.0F, 1.0F); @@ -782,13 +790,13 @@ find_custom_value(struct gl_context *ctx, const struct value_desc *d, union valu COPY_4FV(v->value_float_4, ctx->Color.ClearColor.f); break; case GL_BLEND_COLOR_EXT: - if(ctx->Color._ClampFragmentColor) + if (_mesa_get_clamp_fragment_color(ctx)) COPY_4FV(v->value_float_4, ctx->Color.BlendColor); else COPY_4FV(v->value_float_4, ctx->Color.BlendColorUnclamped); break; case GL_ALPHA_TEST_REF: - if(ctx->Color._ClampFragmentColor) + if (_mesa_get_clamp_fragment_color(ctx)) v->value_float = ctx->Color.AlphaRef; else v->value_float = ctx->Color.AlphaRefUnclamped; @@ -868,7 +876,7 @@ find_custom_value(struct gl_context *ctx, const struct value_desc *d, union valu * \param func name of calling glGet*v() function for error reporting * \param d the struct value_desc that has the extra constraints * - * \return GL_FALSE if one of the constraints was not satisfied, + * \return GL_FALSE if all of the constraints were not satisfied, * otherwise GL_TRUE. */ static GLboolean diff --git a/mesalib/src/mesa/main/get_hash_params.py b/mesalib/src/mesa/main/get_hash_params.py index 7d4f7e2a4..4ef23247b 100644 --- a/mesalib/src/mesa/main/get_hash_params.py +++ b/mesalib/src/mesa/main/get_hash_params.py @@ -96,7 +96,7 @@ descriptor=[ # GL_ARB_color_buffer_float [ "CLAMP_VERTEX_COLOR", "CONTEXT_ENUM(Light.ClampVertexColor), extra_ARB_color_buffer_float" ], [ "CLAMP_FRAGMENT_COLOR", "CONTEXT_ENUM(Color.ClampFragmentColor), extra_ARB_color_buffer_float" ], - [ "CLAMP_READ_COLOR", "CONTEXT_ENUM(Color.ClampReadColor), extra_ARB_color_buffer_float" ], + [ "CLAMP_READ_COLOR", "CONTEXT_ENUM(Color.ClampReadColor), extra_ARB_color_buffer_float_or_glcore" ], # GL_ARB_copy_buffer [ "COPY_READ_BUFFER", "LOC_CUSTOM, TYPE_INT, 0, NO_EXTRA" ], diff --git a/mesalib/src/mesa/main/imports.h b/mesalib/src/mesa/main/imports.h index 4b783818b..c4110ef10 100644 --- a/mesalib/src/mesa/main/imports.h +++ b/mesalib/src/mesa/main/imports.h @@ -500,17 +500,11 @@ _mesa_realloc( void *oldBuffer, size_t oldSize, size_t newSize ); #ifndef FFS_DEFINED #define FFS_DEFINED 1 #ifdef __GNUC__ - -#if defined(__MINGW32__) || defined(__CYGWIN__) || defined(ANDROID) || defined(__APPLE__) #define ffs __builtin_ffs #define ffsll __builtin_ffsll -#endif - #else - extern int ffs(int i); extern int ffsll(long long int i); - #endif /*__ GNUC__ */ #endif /* FFS_DEFINED */ diff --git a/mesalib/src/mesa/main/light.c b/mesalib/src/mesa/main/light.c index 3c43ec766..c694bebe6 100644 --- a/mesalib/src/mesa/main/light.c +++ b/mesalib/src/mesa/main/light.c @@ -1202,7 +1202,8 @@ _mesa_init_lighting( struct gl_context *ctx ) NULL ); ctx->Light.ColorMaterialEnabled = GL_FALSE; - ctx->Light.ClampVertexColor = GL_TRUE; + ctx->Light.ClampVertexColor = ctx->API == API_OPENGL_COMPAT; + ctx->Light._ClampVertexColor = ctx->API == API_OPENGL_COMPAT; /* Miscellaneous */ ctx->Light._NeedEyeCoords = GL_FALSE; diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h index a0e7e281d..008f68bda 100644 --- a/mesalib/src/mesa/main/mtypes.h +++ b/mesalib/src/mesa/main/mtypes.h @@ -146,9 +146,6 @@ typedef enum * VERT_ATTRIB_TEX * include the classic texture coordinate attributes. * Is a subset of VERT_ATTRIB_FF. - * VERT_ATTRIB_GENERIC_NV - * include the NV shader attributes. - * Is a subset of VERT_ATTRIB_FF. * VERT_ATTRIB_GENERIC * include the OpenGL 2.0+ GLSL generic shader attributes. * These alias the generic GL_ARB_vertex_shader attributes. @@ -159,9 +156,6 @@ typedef enum #define VERT_ATTRIB_TEX(i) (VERT_ATTRIB_TEX0 + (i)) #define VERT_ATTRIB_TEX_MAX MAX_TEXTURE_COORD_UNITS -#define VERT_ATTRIB_GENERIC_NV(i) (VERT_ATTRIB_POS + (i)) -#define VERT_ATTRIB_GENERIC_NV_MAX MAX_VERTEX_GENERIC_ATTRIBS - #define VERT_ATTRIB_GENERIC(i) (VERT_ATTRIB_GENERIC0 + (i)) #define VERT_ATTRIB_GENERIC_MAX MAX_VERTEX_GENERIC_ATTRIBS @@ -198,10 +192,6 @@ typedef enum #define VERT_BIT_TEX_ALL \ BITFIELD64_RANGE(VERT_ATTRIB_TEX(0), VERT_ATTRIB_TEX_MAX) -#define VERT_BIT_GENERIC_NV(i) VERT_BIT(VERT_ATTRIB_GENERIC_NV(i)) -#define VERT_BIT_GENERIC_NV_ALL \ - BITFIELD64_RANGE(VERT_ATTRIB_GENERIC_NV(0), VERT_ATTRIB_GENERIC_NV_MAX) - #define VERT_BIT_GENERIC(i) VERT_BIT(VERT_ATTRIB_GENERIC(i)) #define VERT_BIT_GENERIC_ALL \ BITFIELD64_RANGE(VERT_ATTRIB_GENERIC(0), VERT_ATTRIB_GENERIC_MAX) @@ -683,7 +673,6 @@ struct gl_colorbuffer_attrib GLenum ClampFragmentColor; /**< GL_TRUE, GL_FALSE or GL_FIXED_ONLY_ARB */ GLboolean _ClampFragmentColor; /** < with GL_FIXED_ONLY_ARB resolved */ GLenum ClampReadColor; /**< GL_TRUE, GL_FALSE or GL_FIXED_ONLY_ARB */ - GLboolean _ClampReadColor; /** < with GL_FIXED_ONLY_ARB resolved */ GLboolean sRGBEnabled; /**< Framebuffer sRGB blending/updating requested */ }; @@ -1025,6 +1014,7 @@ struct gl_stencil_attrib GLboolean TestTwoSide; /**< GL_EXT_stencil_two_side */ GLubyte ActiveFace; /**< GL_EXT_stencil_two_side (0 or 2) */ GLboolean _Enabled; /**< Enabled and stencil buffer present */ + GLboolean _WriteEnabled; /**< _Enabled and non-zero writemasks */ GLboolean _TestTwoSide; GLubyte _BackFace; /**< Current back stencil state (1 or 2) */ GLenum Function[3]; /**< Stencil function */ @@ -2670,6 +2660,10 @@ struct gl_framebuffer /** Integer color values */ GLboolean _IntegerColor; + /* ARB_color_buffer_float */ + GLboolean _AllColorBuffersFixedPoint; /* no integer, no float */ + GLboolean _HasSNormOrFloatColorBuffer; + /** Array of all renderbuffer attachments, indexed by BUFFER_* tokens. */ struct gl_renderbuffer_attachment Attachment[BUFFER_COUNT]; @@ -3002,9 +2996,11 @@ struct gl_extensions GLboolean ARB_texture_float; GLboolean ARB_texture_multisample; GLboolean ARB_texture_non_power_of_two; + GLboolean ARB_texture_query_lod; GLboolean ARB_texture_rg; GLboolean ARB_texture_rgb10_a2ui; GLboolean ARB_texture_storage; + GLboolean ARB_texture_storage_multisample; GLboolean ARB_timer_query; GLboolean ARB_transform_feedback2; GLboolean ARB_transform_feedback3; diff --git a/mesalib/src/mesa/main/readpix.c b/mesalib/src/mesa/main/readpix.c index d3d09dea3..0dee38063 100644 --- a/mesalib/src/mesa/main/readpix.c +++ b/mesalib/src/mesa/main/readpix.c @@ -24,6 +24,7 @@ #include "glheader.h" #include "imports.h" +#include "blend.h" #include "bufferobj.h" #include "context.h" #include "enums.h" @@ -80,7 +81,7 @@ get_readpixels_transfer_ops(const struct gl_context *ctx, gl_format texFormat, if (uses_blit) { /* For blit-based ReadPixels packing, the clamping is done automatically * unless the type is float. */ - if (ctx->Color._ClampReadColor == GL_TRUE && + if (_mesa_get_clamp_read_color(ctx) && (type == GL_FLOAT || type == GL_HALF_FLOAT)) { transferOps |= IMAGE_CLAMP_BIT; } @@ -88,7 +89,7 @@ get_readpixels_transfer_ops(const struct gl_context *ctx, gl_format texFormat, else { /* For CPU-based ReadPixels packing, the clamping must always be done * for non-float types, */ - if (ctx->Color._ClampReadColor == GL_TRUE || + if (_mesa_get_clamp_read_color(ctx) || (type != GL_FLOAT && type != GL_HALF_FLOAT)) { transferOps |= IMAGE_CLAMP_BIT; } diff --git a/mesalib/src/mesa/main/shaderapi.c b/mesalib/src/mesa/main/shaderapi.c index be6946798..2c307e79c 100644 --- a/mesalib/src/mesa/main/shaderapi.c +++ b/mesalib/src/mesa/main/shaderapi.c @@ -518,9 +518,11 @@ get_programiv(struct gl_context *ctx, GLuint program, GLenum pname, GLint *param GLint max_len = 0; for (i = 0; i < shProg->NumUserUniformStorage; i++) { - /* Add one for the terminating NUL character. + /* Add one for the terminating NUL character for a non-array, and + * 4 for the "[0]" and the NUL for an array. */ - const GLint len = strlen(shProg->UniformStorage[i].name) + 1; + const GLint len = strlen(shProg->UniformStorage[i].name) + 1 + + ((shProg->UniformStorage[i].array_elements != 0) ? 3 : 0); if (len > max_len) max_len = len; diff --git a/mesalib/src/mesa/main/state.c b/mesalib/src/mesa/main/state.c index fb8b71cfe..251c1aea9 100644 --- a/mesalib/src/mesa/main/state.c +++ b/mesalib/src/mesa/main/state.c @@ -51,6 +51,7 @@ #include "texobj.h" #include "texstate.h" #include "varray.h" +#include "blend.h" static void @@ -308,47 +309,6 @@ update_multisample(struct gl_context *ctx) /** - * Update the ctx->Color._ClampFragmentColor field - */ -static void -update_clamp_fragment_color(struct gl_context *ctx) -{ - if (ctx->Color.ClampFragmentColor == GL_FIXED_ONLY_ARB) - ctx->Color._ClampFragmentColor = - !ctx->DrawBuffer || !ctx->DrawBuffer->Visual.floatMode; - else - ctx->Color._ClampFragmentColor = ctx->Color.ClampFragmentColor; -} - - -/** - * Update the ctx->Color._ClampVertexColor field - */ -static void -update_clamp_vertex_color(struct gl_context *ctx) -{ - if (ctx->Light.ClampVertexColor == GL_FIXED_ONLY_ARB) - ctx->Light._ClampVertexColor = - !ctx->DrawBuffer || !ctx->DrawBuffer->Visual.floatMode; - else - ctx->Light._ClampVertexColor = ctx->Light.ClampVertexColor; -} - - -/** - * Update the ctx->Color._ClampReadColor field - */ -static void -update_clamp_read_color(struct gl_context *ctx) -{ - if (ctx->Color.ClampReadColor == GL_FIXED_ONLY_ARB) - ctx->Color._ClampReadColor = - !ctx->ReadBuffer || !ctx->ReadBuffer->Visual.floatMode; - else - ctx->Color._ClampReadColor = ctx->Color.ClampReadColor; -} - -/** * Update the ctx->VertexProgram._TwoSideEnabled flag. */ static void @@ -507,9 +467,6 @@ _mesa_update_state_locked( struct gl_context *ctx ) if (new_state & (_NEW_LIGHT | _NEW_PROGRAM)) update_twoside( ctx ); - if (new_state & (_NEW_LIGHT | _NEW_BUFFERS)) - update_clamp_vertex_color(ctx); - if (new_state & (_NEW_STENCIL | _NEW_BUFFERS)) _mesa_update_stencil( ctx ); @@ -525,12 +482,6 @@ _mesa_update_state_locked( struct gl_context *ctx ) if (new_state & (_NEW_MULTISAMPLE | _NEW_BUFFERS)) update_multisample( ctx ); - if (new_state & (_NEW_COLOR | _NEW_BUFFERS)) - update_clamp_read_color(ctx); - - if(new_state & (_NEW_FRAG_CLAMP | _NEW_BUFFERS)) - update_clamp_fragment_color(ctx); - #if 0 if (new_state & (_NEW_POINT | _NEW_LINE | _NEW_POLYGON | _NEW_LIGHT | _NEW_STENCIL | _MESA_NEW_SEPARATE_SPECULAR)) diff --git a/mesalib/src/mesa/main/stencil.c b/mesalib/src/mesa/main/stencil.c index c161808e5..330841731 100644 --- a/mesalib/src/mesa/main/stencil.c +++ b/mesalib/src/mesa/main/stencil.c @@ -551,6 +551,11 @@ _mesa_update_stencil(struct gl_context *ctx) ctx->Stencil.Ref[0] != ctx->Stencil.Ref[face] || ctx->Stencil.ValueMask[0] != ctx->Stencil.ValueMask[face] || ctx->Stencil.WriteMask[0] != ctx->Stencil.WriteMask[face]); + + ctx->Stencil._WriteEnabled = + ctx->Stencil._Enabled && + (ctx->Stencil.WriteMask[0] != 0 || + (ctx->Stencil._TestTwoSide && ctx->Stencil.WriteMask[face] != 0)); } diff --git a/mesalib/src/mesa/main/texenv.c b/mesalib/src/mesa/main/texenv.c index 0fe5fbd7a..2979e6706 100644 --- a/mesalib/src/mesa/main/texenv.c +++ b/mesalib/src/mesa/main/texenv.c @@ -32,6 +32,7 @@ #include "main/glheader.h" #include "main/context.h" +#include "main/blend.h" #include "main/enums.h" #include "main/macros.h" #include "main/mtypes.h" @@ -680,7 +681,7 @@ _mesa_GetTexEnvfv( GLenum target, GLenum pname, GLfloat *params ) if (pname == GL_TEXTURE_ENV_COLOR) { if(ctx->NewState & (_NEW_BUFFERS | _NEW_FRAG_CLAMP)) _mesa_update_state(ctx); - if(ctx->Color._ClampFragmentColor) + if (_mesa_get_clamp_fragment_color(ctx)) COPY_4FV( params, texUnit->EnvColor ); else COPY_4FV( params, texUnit->EnvColorUnclamped ); diff --git a/mesalib/src/mesa/main/teximage.c b/mesalib/src/mesa/main/teximage.c index bc755ae79..784b389a7 100644 --- a/mesalib/src/mesa/main/teximage.c +++ b/mesalib/src/mesa/main/teximage.c @@ -47,6 +47,7 @@ #include "teximage.h" #include "texobj.h" #include "texstate.h" +#include "texstorage.h" #include "mtypes.h" #include "glformats.h" @@ -4194,7 +4195,8 @@ check_multisample_target(GLuint dims, GLenum target) static void teximagemultisample(GLuint dims, GLenum target, GLsizei samples, GLint internalformat, GLsizei width, GLsizei height, - GLsizei depth, GLboolean fixedsamplelocations) + GLsizei depth, GLboolean fixedsamplelocations, + GLboolean immutable, const char *func) { struct gl_texture_object *texObj; struct gl_texture_image *texImage; @@ -4206,12 +4208,12 @@ teximagemultisample(GLuint dims, GLenum target, GLsizei samples, if (!(ctx->Extensions.ARB_texture_multisample && _mesa_is_desktop_gl(ctx))) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glTexImage%uDMultisample", dims); + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func); return; } if (!check_multisample_target(dims, target)) { - _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage%uDMultisample(target)", dims); + _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", func); return; } @@ -4219,26 +4221,40 @@ teximagemultisample(GLuint dims, GLenum target, GLsizei samples, * refer GL3.1 spec 4.4.4 */ + if (immutable && !_mesa_is_legal_tex_storage_format(ctx, internalformat)) { + _mesa_error(ctx, GL_INVALID_ENUM, + "%s(internalformat=%s not legal for immutable-format)", + func, _mesa_lookup_enum_by_nr(internalformat)); + return; + } + if (!is_renderable_texture_format(ctx, internalformat)) { _mesa_error(ctx, GL_INVALID_OPERATION, - "glTexImage%uDMultisample(internalformat=%s)", - dims, - _mesa_lookup_enum_by_nr(internalformat)); + "%s(internalformat=%s)", + func, _mesa_lookup_enum_by_nr(internalformat)); return; } sample_count_error = _mesa_check_sample_count(ctx, target, internalformat, samples); if (sample_count_error != GL_NO_ERROR) { - _mesa_error(ctx, sample_count_error, "glTexImage%uDMultisample(samples)", dims); + _mesa_error(ctx, sample_count_error, "%s(samples)", func); return; } texObj = _mesa_get_current_tex_object(ctx, target); + + if (immutable && (!texObj || (texObj->Name == 0))) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(texture object 0)", + func); + return; + } + texImage = _mesa_get_tex_image(ctx, texObj, 0, 0); if (texImage == NULL) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage%uDMultisample()", dims); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s()", func); return; } @@ -4268,13 +4284,19 @@ teximagemultisample(GLuint dims, GLenum target, GLsizei samples, else { if (!dimensionsOK) { _mesa_error(ctx, GL_INVALID_VALUE, - "glTexImage%uDMultisample(invalid width or height)", dims); + "%s(invalid width or height)", func); return; } if (!sizeOK) { _mesa_error(ctx, GL_OUT_OF_MEMORY, - "glTexImage%uDMultisample(texture too large)", dims); + "%s(texture too large)", func); + return; + } + + /* Check if texObj->Immutable is set */ + if (texObj->Immutable) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(immutable)", func); return; } @@ -4299,6 +4321,7 @@ teximagemultisample(GLuint dims, GLenum target, GLsizei samples, } } + texObj->Immutable = immutable; _mesa_update_fbo_texture(ctx, texObj, 0, 0); } } @@ -4309,7 +4332,7 @@ _mesa_TexImage2DMultisample(GLenum target, GLsizei samples, GLsizei height, GLboolean fixedsamplelocations) { teximagemultisample(2, target, samples, internalformat, - width, height, 1, fixedsamplelocations); + width, height, 1, fixedsamplelocations, GL_FALSE, "glTexImage2DMultisample"); } void GLAPIENTRY @@ -4319,5 +4342,25 @@ _mesa_TexImage3DMultisample(GLenum target, GLsizei samples, GLboolean fixedsamplelocations) { teximagemultisample(3, target, samples, internalformat, - width, height, depth, fixedsamplelocations); + width, height, depth, fixedsamplelocations, GL_FALSE, "glTexImage3DMultisample"); +} + + +void GLAPIENTRY +_mesa_TexStorage2DMultisample(GLenum target, GLsizei samples, + GLenum internalformat, GLsizei width, + GLsizei height, GLboolean fixedsamplelocations) +{ + teximagemultisample(2, target, samples, internalformat, + width, height, 1, fixedsamplelocations, GL_TRUE, "glTexStorage2DMultisample"); +} + +void GLAPIENTRY +_mesa_TexStorage3DMultisample(GLenum target, GLsizei samples, + GLenum internalformat, GLsizei width, + GLsizei height, GLsizei depth, + GLboolean fixedsamplelocations) +{ + teximagemultisample(3, target, samples, internalformat, + width, height, depth, fixedsamplelocations, GL_TRUE, "glTexStorage3DMultisample"); } diff --git a/mesalib/src/mesa/main/teximage.h b/mesalib/src/mesa/main/teximage.h index 744c47a8a..bb295c7a7 100644 --- a/mesalib/src/mesa/main/teximage.h +++ b/mesalib/src/mesa/main/teximage.h @@ -305,6 +305,17 @@ _mesa_TexImage3DMultisample(GLenum target, GLsizei samples, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); +extern void GLAPIENTRY +_mesa_TexStorage2DMultisample(GLenum target, GLsizei samples, + GLenum internalformat, GLsizei width, + GLsizei height, GLboolean fixedsamplelocations); + +extern void GLAPIENTRY +_mesa_TexStorage3DMultisample(GLenum target, GLsizei samples, + GLenum internalformat, GLsizei width, + GLsizei height, GLsizei depth, + GLboolean fixedsamplelocations); + /*@}*/ #ifdef __cplusplus diff --git a/mesalib/src/mesa/main/texparam.c b/mesalib/src/mesa/main/texparam.c index bd2f75170..f60eb204e 100644 --- a/mesalib/src/mesa/main/texparam.c +++ b/mesalib/src/mesa/main/texparam.c @@ -31,6 +31,7 @@ #include <stdbool.h> #include "main/glheader.h" +#include "main/blend.h" #include "main/colormac.h" #include "main/context.h" #include "main/enums.h" @@ -175,6 +176,16 @@ get_texobj(struct gl_context *ctx, GLenum target, GLboolean get) return texUnit->CurrentTex[TEXTURE_CUBE_ARRAY_INDEX]; } break; + case GL_TEXTURE_2D_MULTISAMPLE: + if (ctx->Extensions.ARB_texture_storage_multisample) { + return texUnit->CurrentTex[TEXTURE_2D_MULTISAMPLE_INDEX]; + } + break; + case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: + if (ctx->Extensions.ARB_texture_storage_multisample) { + return texUnit->CurrentTex[TEXTURE_2D_MULTISAMPLE_ARRAY_INDEX]; + } + break; default: ; } @@ -250,6 +261,20 @@ incomplete(struct gl_context *ctx, struct gl_texture_object *texObj) } +static GLboolean +target_allows_setting_sampler_parameters(GLenum target) +{ + switch (target) { + case GL_TEXTURE_2D_MULTISAMPLE: + case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: + return GL_FALSE; + + default: + return GL_TRUE; + } +} + + /** * Set an integer-valued texture parameter * \return GL_TRUE if legal AND the value changed, GL_FALSE otherwise @@ -261,6 +286,9 @@ set_tex_parameteri(struct gl_context *ctx, { switch (pname) { case GL_TEXTURE_MIN_FILTER: + if (!target_allows_setting_sampler_parameters(texObj->Target)) + goto invalid_operation; + if (texObj->Sampler.MinFilter == params[0]) return GL_FALSE; switch (params[0]) { @@ -286,6 +314,9 @@ set_tex_parameteri(struct gl_context *ctx, return GL_FALSE; case GL_TEXTURE_MAG_FILTER: + if (!target_allows_setting_sampler_parameters(texObj->Target)) + goto invalid_operation; + if (texObj->Sampler.MagFilter == params[0]) return GL_FALSE; switch (params[0]) { @@ -300,6 +331,9 @@ set_tex_parameteri(struct gl_context *ctx, return GL_FALSE; case GL_TEXTURE_WRAP_S: + if (!target_allows_setting_sampler_parameters(texObj->Target)) + goto invalid_operation; + if (texObj->Sampler.WrapS == params[0]) return GL_FALSE; if (validate_texture_wrap_mode(ctx, texObj->Target, params[0])) { @@ -310,6 +344,9 @@ set_tex_parameteri(struct gl_context *ctx, return GL_FALSE; case GL_TEXTURE_WRAP_T: + if (!target_allows_setting_sampler_parameters(texObj->Target)) + goto invalid_operation; + if (texObj->Sampler.WrapT == params[0]) return GL_FALSE; if (validate_texture_wrap_mode(ctx, texObj->Target, params[0])) { @@ -320,6 +357,9 @@ set_tex_parameteri(struct gl_context *ctx, return GL_FALSE; case GL_TEXTURE_WRAP_R: + if (!target_allows_setting_sampler_parameters(texObj->Target)) + goto invalid_operation; + if (texObj->Sampler.WrapR == params[0]) return GL_FALSE; if (validate_texture_wrap_mode(ctx, texObj->Target, params[0])) { @@ -335,6 +375,11 @@ set_tex_parameteri(struct gl_context *ctx, if (texObj->BaseLevel == params[0]) return GL_FALSE; + + if ((texObj->Target == GL_TEXTURE_2D_MULTISAMPLE || + texObj->Target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) && params[0] != 0) + goto invalid_operation; + if (params[0] < 0 || (texObj->Target == GL_TEXTURE_RECTANGLE_ARB && params[0] != 0)) { _mesa_error(ctx, GL_INVALID_VALUE, @@ -348,6 +393,7 @@ set_tex_parameteri(struct gl_context *ctx, case GL_TEXTURE_MAX_LEVEL: if (texObj->MaxLevel == params[0]) return GL_FALSE; + if (params[0] < 0 || texObj->Target == GL_TEXTURE_RECTANGLE_ARB) { _mesa_error(ctx, GL_INVALID_VALUE, "glTexParameter(param=%d)", params[0]); @@ -373,6 +419,10 @@ set_tex_parameteri(struct gl_context *ctx, case GL_TEXTURE_COMPARE_MODE_ARB: if ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_shadow) || _mesa_is_gles3(ctx)) { + + if (!target_allows_setting_sampler_parameters(texObj->Target)) + goto invalid_operation; + if (texObj->Sampler.CompareMode == params[0]) return GL_FALSE; if (params[0] == GL_NONE || @@ -388,6 +438,10 @@ set_tex_parameteri(struct gl_context *ctx, case GL_TEXTURE_COMPARE_FUNC_ARB: if ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_shadow) || _mesa_is_gles3(ctx)) { + + if (!target_allows_setting_sampler_parameters(texObj->Target)) + goto invalid_operation; + if (texObj->Sampler.CompareFunc == params[0]) return GL_FALSE; switch (params[0]) { @@ -489,7 +543,11 @@ set_tex_parameteri(struct gl_context *ctx, case GL_TEXTURE_SRGB_DECODE_EXT: if (_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_sRGB_decode) { - GLenum decode = params[0]; + GLenum decode = params[0]; + + if (!target_allows_setting_sampler_parameters(texObj->Target)) + goto invalid_operation; + if (decode == GL_DECODE_EXT || decode == GL_SKIP_DECODE_EXT) { if (texObj->Sampler.sRGBDecode != decode) { flush(ctx); @@ -504,6 +562,10 @@ set_tex_parameteri(struct gl_context *ctx, if (_mesa_is_desktop_gl(ctx) && ctx->Extensions.AMD_seamless_cubemap_per_texture) { GLenum param = params[0]; + + if (!target_allows_setting_sampler_parameters(texObj->Target)) + goto invalid_operation; + if (param != GL_TRUE && param != GL_FALSE) { goto invalid_param; } @@ -528,6 +590,11 @@ invalid_param: _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(param=%s)", _mesa_lookup_enum_by_nr(params[0])); return GL_FALSE; + +invalid_operation: + _mesa_error(ctx, GL_INVALID_OPERATION, "glTexParameter(pname=%s)", + _mesa_lookup_enum_by_nr(pname)); + return GL_FALSE; } @@ -545,6 +612,9 @@ set_tex_parameterf(struct gl_context *ctx, if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx)) goto invalid_pname; + if (!target_allows_setting_sampler_parameters(texObj->Target)) + goto invalid_operation; + if (texObj->Sampler.MinLod == params[0]) return GL_FALSE; flush(ctx); @@ -555,6 +625,9 @@ set_tex_parameterf(struct gl_context *ctx, if (!_mesa_is_desktop_gl(ctx) && !_mesa_is_gles3(ctx)) goto invalid_pname; + if (!target_allows_setting_sampler_parameters(texObj->Target)) + goto invalid_operation; + if (texObj->Sampler.MaxLod == params[0]) return GL_FALSE; flush(ctx); @@ -571,6 +644,9 @@ set_tex_parameterf(struct gl_context *ctx, case GL_TEXTURE_MAX_ANISOTROPY_EXT: if (ctx->Extensions.EXT_texture_filter_anisotropic) { + if (!target_allows_setting_sampler_parameters(texObj->Target)) + goto invalid_operation; + if (texObj->Sampler.MaxAnisotropy == params[0]) return GL_FALSE; if (params[0] < 1.0) { @@ -598,6 +674,9 @@ set_tex_parameterf(struct gl_context *ctx, if (ctx->API != API_OPENGL_COMPAT) goto invalid_pname; + if (!target_allows_setting_sampler_parameters(texObj->Target)) + goto invalid_operation; + if (texObj->Sampler.LodBias != params[0]) { flush(ctx); texObj->Sampler.LodBias = params[0]; @@ -609,6 +688,9 @@ set_tex_parameterf(struct gl_context *ctx, if (!_mesa_is_desktop_gl(ctx)) goto invalid_pname; + if (!target_allows_setting_sampler_parameters(texObj->Target)) + goto invalid_operation; + flush(ctx); /* ARB_texture_float disables clamping */ if (ctx->Extensions.ARB_texture_float) { @@ -633,6 +715,11 @@ invalid_pname: _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(pname=%s)", _mesa_lookup_enum_by_nr(pname)); return GL_FALSE; + +invalid_operation: + _mesa_error(ctx, GL_INVALID_OPERATION, "glTexParameter(pname=%s)", + _mesa_lookup_enum_by_nr(pname)); + return GL_FALSE; } @@ -1329,7 +1416,7 @@ _mesa_GetTexParameterfv( GLenum target, GLenum pname, GLfloat *params ) if (ctx->NewState & (_NEW_BUFFERS | _NEW_FRAG_CLAMP)) _mesa_update_state_locked(ctx); - if (ctx->Color._ClampFragmentColor) { + if (_mesa_get_clamp_fragment_color(ctx)) { params[0] = CLAMP(obj->Sampler.BorderColor.f[0], 0.0F, 1.0F); params[1] = CLAMP(obj->Sampler.BorderColor.f[1], 0.0F, 1.0F); params[2] = CLAMP(obj->Sampler.BorderColor.f[2], 0.0F, 1.0F); diff --git a/mesalib/src/mesa/main/texstorage.c b/mesalib/src/mesa/main/texstorage.c index 675fd745b..6309b5716 100644 --- a/mesalib/src/mesa/main/texstorage.c +++ b/mesalib/src/mesa/main/texstorage.c @@ -202,20 +202,9 @@ clear_texture_fields(struct gl_context *ctx, } -/** - * Do error checking for calls to glTexStorage1/2/3D(). - * If an error is found, record it with _mesa_error(), unless the target - * is a proxy texture. - * \return GL_TRUE if any error, GL_FALSE otherwise. - */ -static GLboolean -tex_storage_error_check(struct gl_context *ctx, GLuint dims, GLenum target, - GLsizei levels, GLenum internalformat, - GLsizei width, GLsizei height, GLsizei depth) +GLboolean +_mesa_is_legal_tex_storage_format(struct gl_context *ctx, GLenum internalformat) { - struct gl_texture_object *texObj; - GLboolean legalFormat; - /* check internal format - note that only sized formats are allowed */ switch (internalformat) { case GL_ALPHA: @@ -250,13 +239,27 @@ tex_storage_error_check(struct gl_context *ctx, GLuint dims, GLenum target, case GL_LUMINANCE_INTEGER_EXT: case GL_LUMINANCE_ALPHA_INTEGER_EXT: /* these unsized formats are illegal */ - legalFormat = GL_FALSE; - break; + return GL_FALSE; default: - legalFormat = _mesa_base_tex_format(ctx, internalformat) > 0; + return _mesa_base_tex_format(ctx, internalformat) > 0; } +} + + +/** + * Do error checking for calls to glTexStorage1/2/3D(). + * If an error is found, record it with _mesa_error(), unless the target + * is a proxy texture. + * \return GL_TRUE if any error, GL_FALSE otherwise. + */ +static GLboolean +tex_storage_error_check(struct gl_context *ctx, GLuint dims, GLenum target, + GLsizei levels, GLenum internalformat, + GLsizei width, GLsizei height, GLsizei depth) +{ + struct gl_texture_object *texObj; - if (!legalFormat) { + if (!_mesa_is_legal_tex_storage_format(ctx, internalformat)) { _mesa_error(ctx, GL_INVALID_ENUM, "glTexStorage%uD(internalformat = %s)", dims, _mesa_lookup_enum_by_nr(internalformat)); diff --git a/mesalib/src/mesa/main/texstorage.h b/mesalib/src/mesa/main/texstorage.h index 99382df51..9f172e1ca 100644 --- a/mesalib/src/mesa/main/texstorage.h +++ b/mesalib/src/mesa/main/texstorage.h @@ -57,5 +57,8 @@ _mesa_TextureStorage3DEXT(GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); +extern GLboolean +_mesa_is_legal_tex_storage_format(struct gl_context *ctx, GLenum internalformat); + #endif /* TEXSTORAGE_H */ diff --git a/mesalib/src/mesa/main/version.c b/mesalib/src/mesa/main/version.c index 3d4af5923..ecca446c1 100644 --- a/mesalib/src/mesa/main/version.c +++ b/mesalib/src/mesa/main/version.c @@ -233,7 +233,8 @@ compute_version(struct gl_context *ctx) const GLboolean ver_3_0 = (ver_2_1 && ctx->Const.GLSLVersion >= 130 && ctx->Const.MaxSamples >= 4 && - ctx->Extensions.ARB_color_buffer_float && + (ctx->API == API_OPENGL_CORE || + ctx->Extensions.ARB_color_buffer_float) && ctx->Extensions.ARB_depth_buffer_float && ctx->Extensions.ARB_half_float_pixel && ctx->Extensions.ARB_half_float_vertex && diff --git a/mesalib/src/mesa/program/ir_to_mesa.cpp b/mesalib/src/mesa/program/ir_to_mesa.cpp index 2cb5f02f4..14cf5baa7 100644 --- a/mesalib/src/mesa/program/ir_to_mesa.cpp +++ b/mesalib/src/mesa/program/ir_to_mesa.cpp @@ -2048,6 +2048,9 @@ ir_to_mesa_visitor::visit(ir_texture *ir) case ir_txf_ms: assert(!"Unexpected ir_txf_ms opcode"); break; + case ir_lod: + assert(!"Unexpected ir_lod opcode"); + break; } const glsl_type *sampler_type = ir->sampler->type; diff --git a/mesalib/src/mesa/program/prog_cache.c b/mesalib/src/mesa/program/prog_cache.c index 47f926b1b..1f1c6142d 100644 --- a/mesalib/src/mesa/program/prog_cache.c +++ b/mesalib/src/mesa/program/prog_cache.c @@ -37,6 +37,7 @@ struct cache_item { GLuint hash; + unsigned keysize; void *key; struct gl_program *program; struct cache_item *next; @@ -174,7 +175,8 @@ struct gl_program * _mesa_search_program_cache(struct gl_program_cache *cache, const void *key, GLuint keysize) { - if (cache->last && + if (cache->last && + cache->last->keysize == keysize && memcmp(cache->last->key, key, keysize) == 0) { return cache->last->program; } @@ -183,7 +185,10 @@ _mesa_search_program_cache(struct gl_program_cache *cache, struct cache_item *c; for (c = cache->items[hash % cache->size]; c; c = c->next) { - if (c->hash == hash && memcmp(c->key, key, keysize) == 0) { + if (c->hash == hash && + c->keysize == keysize && + memcmp(c->key, key, keysize) == 0) { + cache->last = c; return c->program; } @@ -207,6 +212,7 @@ _mesa_program_cache_insert(struct gl_context *ctx, c->key = malloc(keysize); memcpy(c->key, key, keysize); + c->keysize = keysize; c->program = program; /* no refcount change */ @@ -235,6 +241,7 @@ _mesa_shader_cache_insert(struct gl_context *ctx, c->key = malloc(keysize); memcpy(c->key, key, keysize); + c->keysize = keysize; c->program = (struct gl_program *)program; /* no refcount change */ diff --git a/mesalib/src/mesa/program/prog_statevars.c b/mesalib/src/mesa/program/prog_statevars.c index 5a350798c..09d2a568a 100644 --- a/mesalib/src/mesa/program/prog_statevars.c +++ b/mesalib/src/mesa/program/prog_statevars.c @@ -31,6 +31,7 @@ #include "main/glheader.h" #include "main/context.h" +#include "main/blend.h" #include "main/imports.h" #include "main/macros.h" #include "main/mtypes.h" @@ -239,14 +240,14 @@ _mesa_fetch_state(struct gl_context *ctx, const gl_state_index state[], { /* state[1] is the texture unit */ const GLuint unit = (GLuint) state[1]; - if(ctx->Color._ClampFragmentColor) + if (_mesa_get_clamp_fragment_color(ctx)) COPY_4V(value, ctx->Texture.Unit[unit].EnvColor); else COPY_4V(value, ctx->Texture.Unit[unit].EnvColorUnclamped); } return; case STATE_FOG_COLOR: - if(ctx->Color._ClampFragmentColor) + if (_mesa_get_clamp_fragment_color(ctx)) COPY_4V(value, ctx->Fog.Color); else COPY_4V(value, ctx->Fog.ColorUnclamped); @@ -871,6 +872,9 @@ append_token(char *dst, gl_state_index k) case STATE_CURRENT_ATTRIB: append(dst, "current"); break; + case STATE_CURRENT_ATTRIB_MAYBE_VP_CLAMPED: + append(dst, "currentAttribMaybeVPClamped"); + break; case STATE_NORMAL_SCALE: append(dst, "normalScale"); break; diff --git a/mesalib/src/mesa/program/register_allocate.c b/mesalib/src/mesa/program/register_allocate.c index a9064c38c..2c826fc66 100644 --- a/mesalib/src/mesa/program/register_allocate.c +++ b/mesalib/src/mesa/program/register_allocate.c @@ -70,6 +70,7 @@ * this during ra_set_finalize(). */ +#include <stdbool.h> #include <ralloc.h> #include "main/imports.h" @@ -93,6 +94,8 @@ struct ra_regs { struct ra_class **classes; unsigned int class_count; + + bool round_robin; }; struct ra_class { @@ -185,6 +188,22 @@ ra_alloc_reg_set(void *mem_ctx, unsigned int count) return regs; } +/** + * The register allocator by default prefers to allocate low register numbers, + * since it was written for hardware (gen4/5 Intel) that is limited in its + * multithreadedness by the number of registers used in a given shader. + * + * However, for hardware without that restriction, densely packed register + * allocation can put serious constraints on instruction scheduling. This + * function tells the allocator to rotate around the registers if possible as + * it allocates the nodes. + */ +void +ra_set_allocate_round_robin(struct ra_regs *regs) +{ + regs->round_robin = true; +} + static void ra_add_conflict_list(struct ra_regs *regs, unsigned int r1, unsigned int r2) { @@ -436,16 +455,19 @@ GLboolean ra_select(struct ra_graph *g) { int i; + int start_search_reg = 0; while (g->stack_count != 0) { - unsigned int r; + unsigned int ri; + unsigned int r = -1; int n = g->stack[g->stack_count - 1]; struct ra_class *c = g->regs->classes[g->nodes[n].class]; /* Find the lowest-numbered reg which is not used by a member * of the graph adjacent to us. */ - for (r = 0; r < g->regs->count; r++) { + for (ri = 0; ri < g->regs->count; ri++) { + r = (start_search_reg + ri) % g->regs->count; if (!c->regs[r]) continue; @@ -461,12 +483,15 @@ ra_select(struct ra_graph *g) if (i == g->nodes[n].adjacency_count) break; } - if (r == g->regs->count) + if (ri == g->regs->count) return GL_FALSE; g->nodes[n].reg = r; g->nodes[n].in_stack = GL_FALSE; g->stack_count--; + + if (g->regs->round_robin) + start_search_reg = r + 1; } return GL_TRUE; diff --git a/mesalib/src/mesa/program/register_allocate.h b/mesalib/src/mesa/program/register_allocate.h index 2a9d61191..fa119e320 100644 --- a/mesalib/src/mesa/program/register_allocate.h +++ b/mesalib/src/mesa/program/register_allocate.h @@ -37,6 +37,7 @@ struct ra_regs; * two real registers from which they are composed. */ struct ra_regs *ra_alloc_reg_set(void *mem_ctx, unsigned int count); +void ra_set_allocate_round_robin(struct ra_regs *regs); unsigned int ra_alloc_reg_class(struct ra_regs *regs); void ra_add_reg_conflict(struct ra_regs *regs, unsigned int r1, unsigned int r2); diff --git a/mesalib/src/mesa/state_tracker/st_atom_constbuf.c b/mesalib/src/mesa/state_tracker/st_atom_constbuf.c index 961fb28a9..56ba96fe3 100644 --- a/mesalib/src/mesa/state_tracker/st_atom_constbuf.c +++ b/mesalib/src/mesa/state_tracker/st_atom_constbuf.c @@ -39,6 +39,7 @@ #include "pipe/p_defines.h" #include "util/u_inlines.h" #include "util/u_upload_mgr.h" +#include "cso_cache/cso_context.h" #include "st_debug.h" #include "st_context.h" @@ -96,16 +97,17 @@ void st_upload_constants( struct st_context *st, _mesa_print_parameter_list(params); } - st->pipe->set_constant_buffer(st->pipe, shader_type, 0, &cb); + cso_set_constant_buffer(st->cso_context, shader_type, 0, &cb); pipe_resource_reference(&cb.buffer, NULL); st->state.constants[shader_type].ptr = params->ParameterValues; st->state.constants[shader_type].size = paramBytes; } else if (st->state.constants[shader_type].ptr) { + /* Unbind. */ st->state.constants[shader_type].ptr = NULL; st->state.constants[shader_type].size = 0; - st->pipe->set_constant_buffer(st->pipe, shader_type, 0, NULL); + cso_set_constant_buffer(st->cso_context, shader_type, 0, NULL); } } @@ -196,7 +198,7 @@ static void st_bind_ubos(struct st_context *st, cb.buffer_size = st_obj->buffer->width0 - binding->Offset; - st->pipe->set_constant_buffer(st->pipe, shader_type, 1 + i, &cb); + cso_set_constant_buffer(st->cso_context, shader_type, 1 + i, &cb); pipe_resource_reference(&cb.buffer, NULL); } } diff --git a/mesalib/src/mesa/state_tracker/st_atom_rasterizer.c b/mesalib/src/mesa/state_tracker/st_atom_rasterizer.c index 866e5627d..62464b475 100644 --- a/mesalib/src/mesa/state_tracker/st_atom_rasterizer.c +++ b/mesalib/src/mesa/state_tracker/st_atom_rasterizer.c @@ -227,8 +227,7 @@ static void update_raster_state( struct st_context *st ) /* _NEW_FRAG_CLAMP */ raster->clamp_fragment_color = !st->clamp_frag_color_in_shader && - ctx->Color._ClampFragmentColor && - !ctx->DrawBuffer->_IntegerColor; + ctx->Color._ClampFragmentColor; raster->gl_rasterization_rules = 1; /* _NEW_RASTERIZER_DISCARD */ diff --git a/mesalib/src/mesa/state_tracker/st_atom_shader.c b/mesalib/src/mesa/state_tracker/st_atom_shader.c index c1d7c80bb..c0239e929 100644 --- a/mesalib/src/mesa/state_tracker/st_atom_shader.c +++ b/mesalib/src/mesa/state_tracker/st_atom_shader.c @@ -86,8 +86,7 @@ update_fp( struct st_context *st ) /* _NEW_FRAG_CLAMP */ key.clamp_color = st->clamp_frag_color_in_shader && - st->ctx->Color._ClampFragmentColor && - !st->ctx->DrawBuffer->_IntegerColor; + st->ctx->Color._ClampFragmentColor; st->fp_variant = st_get_fp_variant(st, stfp, &key); diff --git a/mesalib/src/mesa/state_tracker/st_cb_bitmap.c b/mesalib/src/mesa/state_tracker/st_cb_bitmap.c index bae9ff858..b3ca40501 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_bitmap.c +++ b/mesalib/src/mesa/state_tracker/st_cb_bitmap.c @@ -417,8 +417,7 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, key.st = st; key.bitmap = GL_TRUE; key.clamp_color = st->clamp_frag_color_in_shader && - st->ctx->Color._ClampFragmentColor && - !st->ctx->DrawBuffer->_IntegerColor; + st->ctx->Color._ClampFragmentColor; fpv = st_get_fp_variant(st, st->fp, &key); @@ -766,6 +765,7 @@ st_Bitmap(struct gl_context *ctx, GLint x, GLint y, /* create pass-through vertex shader now */ const uint semantic_names[] = { TGSI_SEMANTIC_POSITION, TGSI_SEMANTIC_COLOR, + st->needs_texcoord_semantic ? TGSI_SEMANTIC_TEXCOORD : TGSI_SEMANTIC_GENERIC }; const uint semantic_indexes[] = { 0, 0, 0 }; st->bitmap.vs = util_make_vertex_passthrough_shader(st->pipe, 3, diff --git a/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c b/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c index f0baa3435..f5a1e27f7 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c +++ b/mesalib/src/mesa/state_tracker/st_cb_drawpixels.c @@ -294,6 +294,9 @@ static void * make_passthrough_vertex_shader(struct st_context *st, GLboolean passColor) { + const unsigned texcoord_semantic = st->needs_texcoord_semantic ? + TGSI_SEMANTIC_TEXCOORD : TGSI_SEMANTIC_GENERIC; + if (!st->drawpix.vert_shaders[passColor]) { struct ureg_program *ureg = ureg_create( TGSI_PROCESSOR_VERTEX ); @@ -307,7 +310,7 @@ make_passthrough_vertex_shader(struct st_context *st, /* MOV result.texcoord0, vertex.attr[1]; */ ureg_MOV(ureg, - ureg_DECL_output( ureg, TGSI_SEMANTIC_GENERIC, 0 ), + ureg_DECL_output( ureg, texcoord_semantic, 0 ), ureg_DECL_vs_input( ureg, 1 )); if (passColor) { @@ -707,8 +710,7 @@ draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, struct pipe_rasterizer_state rasterizer; memset(&rasterizer, 0, sizeof(rasterizer)); rasterizer.clamp_fragment_color = !st->clamp_frag_color_in_shader && - ctx->Color._ClampFragmentColor && - !ctx->DrawBuffer->_IntegerColor; + ctx->Color._ClampFragmentColor; rasterizer.gl_rasterization_rules = 1; rasterizer.depth_clip = !ctx->Transform.DepthClamp; rasterizer.scissor = ctx->Scissor.Enabled; @@ -1034,8 +1036,7 @@ get_color_fp_variant(struct st_context *st) ctx->Pixel.AlphaScale != 1.0); key.pixelMaps = ctx->Pixel.MapColorFlag; key.clamp_color = st->clamp_frag_color_in_shader && - st->ctx->Color._ClampFragmentColor && - !st->ctx->DrawBuffer->_IntegerColor; + st->ctx->Color._ClampFragmentColor; fpv = st_get_fp_variant(st, st->fp, &key); diff --git a/mesalib/src/mesa/state_tracker/st_cb_drawtex.c b/mesalib/src/mesa/state_tracker/st_cb_drawtex.c index a8806c91e..c4efce02f 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_drawtex.c +++ b/mesalib/src/mesa/state_tracker/st_cb_drawtex.c @@ -209,7 +209,9 @@ st_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z, SET_ATTRIB(2, attr, s1, t1, 0.0f, 1.0f); /* upper right */ SET_ATTRIB(3, attr, s0, t1, 0.0f, 1.0f); /* upper left */ - semantic_names[attr] = TGSI_SEMANTIC_GENERIC; + semantic_names[attr] = st->needs_texcoord_semantic ? + TGSI_SEMANTIC_TEXCOORD : TGSI_SEMANTIC_GENERIC; + /* XXX: should this use semantic index i instead of 0 ? */ semantic_indexes[attr] = 0; attr++; diff --git a/mesalib/src/mesa/state_tracker/st_cb_readpixels.c b/mesalib/src/mesa/state_tracker/st_cb_readpixels.c index bfed98870..9fab113fa 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_readpixels.c +++ b/mesalib/src/mesa/state_tracker/st_cb_readpixels.c @@ -133,7 +133,6 @@ st_readpixels(struct gl_context *ctx, GLint x, GLint y, !screen->is_format_supported(screen, src_format, src->target, src->nr_samples, PIPE_BIND_SAMPLER_VIEW)) { - printf("fallback: src format unsupported %s\n", util_format_short_name(src_format)); goto fallback; } @@ -147,8 +146,6 @@ st_readpixels(struct gl_context *ctx, GLint x, GLint y, dst_format = st_choose_matching_format(screen, bind, format, type, pack->SwapBytes); if (dst_format == PIPE_FORMAT_NONE) { - printf("fallback: no matching format for %s, %s\n", - _mesa_lookup_enum_by_nr(format), _mesa_lookup_enum_by_nr(type)); goto fallback; } diff --git a/mesalib/src/mesa/state_tracker/st_cb_texture.c b/mesalib/src/mesa/state_tracker/st_cb_texture.c index 94fbbf7be..0cd0d77af 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_texture.c +++ b/mesalib/src/mesa/state_tracker/st_cb_texture.c @@ -868,7 +868,7 @@ st_GetTexImage(struct gl_context * ctx, goto fallback; } - if (!stImage->pt) { + if (!stImage->pt || !src) { goto fallback; } diff --git a/mesalib/src/mesa/state_tracker/st_extensions.c b/mesalib/src/mesa/state_tracker/st_extensions.c index 11db9d3f3..2d8b9efec 100644 --- a/mesalib/src/mesa/state_tracker/st_extensions.c +++ b/mesalib/src/mesa/state_tracker/st_extensions.c @@ -629,6 +629,7 @@ void st_init_extensions(struct st_context *st) ctx->Const.PrimitiveRestartInSoftware = GL_TRUE; } + /* ARB_color_buffer_float. */ if (screen->get_param(screen, PIPE_CAP_VERTEX_COLOR_UNCLAMPED)) { ctx->Extensions.ARB_color_buffer_float = GL_TRUE; @@ -639,6 +640,16 @@ void st_init_extensions(struct st_context *st) if (!screen->get_param(screen, PIPE_CAP_FRAGMENT_COLOR_CLAMPED)) { st->clamp_frag_color_in_shader = TRUE; } + + /* For drivers which cannot do color clamping, it's better to just + * disable ARB_color_buffer_float in the core profile, because + * the clamping is deprecated there anyway. */ + if (ctx->API == API_OPENGL_CORE && + (st->clamp_frag_color_in_shader || st->clamp_vert_color_in_shader)) { + st->clamp_vert_color_in_shader = GL_FALSE; + st->clamp_frag_color_in_shader = GL_FALSE; + ctx->Extensions.ARB_color_buffer_float = GL_FALSE; + } } if (screen->fence_finish) { 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 e3718eeda..338c652cb 100644 --- a/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp +++ b/mesalib/src/mesa/state_tracker/st_glsl_to_tgsi.cpp @@ -1009,7 +1009,9 @@ glsl_to_tgsi_visitor::get_temp(const glsl_type *type) src.reladdr = NULL; src.negate = 0; - if (type->is_array() || type->is_matrix()) { + if (!options->EmitNoIndirectTemp && + (type->is_array() || type->is_matrix())) { + src.file = PROGRAM_ARRAY; src.index = next_array << 16 | 0x8000; array_sizes[next_array] = type_size(type); @@ -2772,6 +2774,9 @@ glsl_to_tgsi_visitor::visit(ir_texture *ir) case ir_txf_ms: assert(!"Unexpected ir_txf_ms opcode"); break; + case ir_lod: + assert(!"Unexpected ir_lod opcode"); + break; } if (ir->projector) { @@ -3191,7 +3196,7 @@ glsl_to_tgsi_visitor::simplify_cmp(void) prevWriteMask = tempWrites[inst->dst.index]; tempWrites[inst->dst.index] |= inst->dst.writemask; } else - break; + continue; /* For a CMP to be considered a conditional write, the destination * register and source register two must be the same. */ diff --git a/mesalib/src/mesa/state_tracker/st_manager.c b/mesalib/src/mesa/state_tracker/st_manager.c index 0b025d9d5..03e086a72 100644 --- a/mesalib/src/mesa/state_tracker/st_manager.c +++ b/mesalib/src/mesa/state_tracker/st_manager.c @@ -170,9 +170,8 @@ st_context_validate(struct st_context *st, /** * Validate a framebuffer to make sure up-to-date pipe_textures are used. - * The context we need to pass in is s dummy context needed only to be - * able to get a pipe context to create pipe surfaces, and to have a - * context to call _mesa_resize_framebuffer(): + * The context is only used for creating pipe surfaces and for calling + * _mesa_resize_framebuffer(). * (That should probably be rethought, since those surfaces become * drawable state, not context state, and can be freed by another pipe * context). diff --git a/mesalib/src/mesa/swrast/s_blit.c b/mesalib/src/mesa/swrast/s_blit.c index 82fa43f1c..051354dc8 100644 --- a/mesalib/src/mesa/swrast/s_blit.c +++ b/mesalib/src/mesa/swrast/s_blit.c @@ -110,8 +110,8 @@ blit_nearest(struct gl_context *ctx, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield buffer) { - struct gl_renderbuffer *readRb, *drawRb; - struct gl_renderbuffer_attachment *readAtt, *drawAtt; + struct gl_renderbuffer *readRb, *drawRb = NULL; + struct gl_renderbuffer_attachment *readAtt = NULL, *drawAtt = NULL; struct gl_framebuffer *readFb = ctx->ReadBuffer; struct gl_framebuffer *drawFb = ctx->DrawBuffer; GLuint numDrawBuffers = 0; @@ -135,12 +135,12 @@ blit_nearest(struct gl_context *ctx, UNPACK_Z_FLOAT, UNPACK_Z_INT, UNPACK_S, - } mode; + } mode = DIRECT; GLubyte *srcMap, *dstMap; GLint srcRowStride, dstRowStride; GLint dstRow; - GLint pixelSize; + GLint pixelSize = 0; GLvoid *srcBuffer, *dstBuffer; GLint prevY = -1; diff --git a/xorg-server/hw/kdrive/fbdev/fbdev.c b/xorg-server/hw/kdrive/fbdev/fbdev.c index fb6e3a292..d6fcf1a5f 100644 --- a/xorg-server/hw/kdrive/fbdev/fbdev.c +++ b/xorg-server/hw/kdrive/fbdev/fbdev.c @@ -465,6 +465,20 @@ fbdevRandRSetConfig(ScreenPtr pScreen, int oldheight; int oldmmwidth; int oldmmheight; + int newwidth, newheight, newmmwidth, newmmheight; + + if (screen->randr & (RR_Rotate_0 | RR_Rotate_180)) { + newwidth = pSize->width; + newheight = pSize->height; + newmmwidth = pSize->mmWidth; + newmmheight = pSize->mmHeight; + } + else { + newwidth = pSize->height; + newheight = pSize->width; + newmmwidth = pSize->mmHeight; + newmmheight = pSize->mmWidth; + } if (wasEnabled) KdDisableScreen(pScreen); @@ -481,6 +495,10 @@ fbdevRandRSetConfig(ScreenPtr pScreen, */ scrpriv->randr = KdAddRotation(screen->randr, randr); + pScreen->width = newwidth; + pScreen->height = newheight; + pScreen->mmWidth = newmmwidth; + pScreen->mmHeight = newmmheight; fbdevUnmapFramebuffer(screen); diff --git a/xorg-server/hw/xfree86/man/xorg.conf.man b/xorg-server/hw/xfree86/man/xorg.conf.man index 9361ce978..67d8594fb 100644 --- a/xorg-server/hw/xfree86/man/xorg.conf.man +++ b/xorg-server/hw/xfree86/man/xorg.conf.man @@ -1676,6 +1676,17 @@ This optional entry specifies a mode to be marked as the preferred initial mode of the monitor. (RandR 1.2-supporting drivers only) .TP 7 +.BI "Option \*qZoomModes\*q \*q" name " " name " " ... \*q +This optional entry specifies modes to be marked as zoom modes. +It is possible to switch to the next and previous mode via +.BR Ctrl+Alt+Keypad\-Plus " and " Ctrl+Alt+Keypad\-Minus . +All these keypad available modes are selected from the screen mode list. +This list is a copy of the compatibility output monitor mode list. +Since this output is the output connected to the lowest +dot-area monitor, as determined from its largest size mode, that +monitor defines the available zoom modes. +(RandR 1.2-supporting drivers only) +.TP 7 .BI "Option \*qPosition\*q \*q" x " " y \*q This optional entry specifies the position of the monitor within the X screen. diff --git a/xorg-server/hw/xfree86/modes/xf86Crtc.c b/xorg-server/hw/xfree86/modes/xf86Crtc.c index f9ae46596..e4b393cb1 100644 --- a/xorg-server/hw/xfree86/modes/xf86Crtc.c +++ b/xorg-server/hw/xfree86/modes/xf86Crtc.c @@ -428,6 +428,7 @@ extern XF86ConfigPtr xf86configptr; typedef enum { OPTION_PREFERRED_MODE, + OPTION_ZOOM_MODES, OPTION_POSITION, OPTION_BELOW, OPTION_RIGHT_OF, @@ -446,6 +447,7 @@ typedef enum { static OptionInfoRec xf86OutputOptions[] = { {OPTION_PREFERRED_MODE, "PreferredMode", OPTV_STRING, {0}, FALSE}, + {OPTION_ZOOM_MODES, "ZoomModes", OPTV_STRING, {0}, FALSE }, {OPTION_POSITION, "Position", OPTV_STRING, {0}, FALSE}, {OPTION_BELOW, "Below", OPTV_STRING, {0}, FALSE}, {OPTION_RIGHT_OF, "RightOf", OPTV_STRING, {0}, FALSE}, @@ -1418,6 +1420,90 @@ preferredMode(ScrnInfoPtr pScrn, xf86OutputPtr output) return preferred_mode; } +/** identify a token + * args + * *src a string with zero or more tokens, e.g. "tok0 tok1", + * **token stores a pointer to the first token character, + * *len stores the token length. + * return + * a pointer into src[] at the token terminating character, or + * NULL if no token is found. + */ +static const char * +gettoken(const char *src, const char **token, int *len) +{ + const char *delim = " \t"; + int skip; + + if (!src) + return NULL; + + skip = strspn(src, delim); + *token = &src[skip]; + + *len = strcspn(*token, delim); + /* Support for backslash escaped delimiters could be implemented + * here. + */ + + /* (*token)[0] != '\0' <==> *len > 0 */ + if (*len > 0) + return &(*token)[*len]; + else + return NULL; +} + +/** Check for a user configured zoom mode list, Option "ZoomModes": + * + * Section "Monitor" + * Identifier "a21inch" + * Option "ZoomModes" "1600x1200 1280x1024 1280x1024 640x480" + * EndSection + * + * Each user mode name is searched for independently so the list + * specification order is free. An output mode is matched at most + * once, a mode with an already set M_T_USERDEF type bit is skipped. + * Thus a repeat mode name specification matches the next output mode + * with the same name. + * + * Ctrl+Alt+Keypad-{Plus,Minus} zooms {in,out} by selecting the + * {next,previous} M_T_USERDEF mode in the screen modes list, itself + * sorted toward lower dot area or lower dot clock frequency, see + * modes/xf86Crtc.c: xf86SortModes() xf86SetScrnInfoModes(), and + * common/xf86Cursor.c: xf86ZoomViewport(). + */ +static int +processZoomModes(xf86OutputPtr output) +{ + const char *zoom_modes; + int count = 0; + + zoom_modes = xf86GetOptValString(output->options, OPTION_ZOOM_MODES); + + if (zoom_modes) { + const char *token, *next; + int len; + + next = gettoken(zoom_modes, &token, &len); + while (next) { + DisplayModePtr mode; + + for (mode = output->probed_modes; mode; mode = mode->next) + if (!strncmp(token, mode->name, len) /* prefix match */ + && mode->name[len] == '\0' /* equal length */ + && !(mode->type & M_T_USERDEF)) { /* no rematch */ + mode->type |= M_T_USERDEF; + break; + } + + count++; + next = gettoken(next, &token, &len); + } + } + + return count; +} + static void GuessRangeFromModes(MonPtr mon, DisplayModePtr mode) { @@ -1713,6 +1799,9 @@ xf86ProbeOutputModes(ScrnInfoPtr scrn, int maxX, int maxY) } } + /* Ctrl+Alt+Keypad-{Plus,Minus} zoom mode: M_T_USERDEF mode type */ + processZoomModes(output); + output->initial_rotation = xf86OutputInitialRotation(output); if (debug_modes) { diff --git a/xorg-server/xkeyboard-config/symbols/gb b/xorg-server/xkeyboard-config/symbols/gb index c7de8c33e..10372afcd 100644 --- a/xorg-server/xkeyboard-config/symbols/gb +++ b/xorg-server/xkeyboard-config/symbols/gb @@ -169,7 +169,8 @@ xkb_symbols "mac" { key <AE02> { [ 2, at, EuroSign ] }; key <AE03> { [ 3, sterling, numbersign ] }; - key <LSGT> { [ grave, asciitilde ] }; + key <TLDE> { [ section, plusminus ] }; + key <LSGT> { [ grave, asciitilde ] }; // End alphanumeric section diff --git a/xorg-server/xkeyboard-config/symbols/macintosh_vndr/gb b/xorg-server/xkeyboard-config/symbols/macintosh_vndr/gb index a6bc48e8c..4e4248561 100644 --- a/xorg-server/xkeyboard-config/symbols/macintosh_vndr/gb +++ b/xorg-server/xkeyboard-config/symbols/macintosh_vndr/gb @@ -4,12 +4,14 @@ xkb_symbols "basic" { // Describes the differences between a very simple en_US // keyboard and a very simple U.K. keyboard layout - include "latin" + include "macintosh_vndr/us" name[Group1]= "United Kingdom - Mac"; key <AE02> { [ 2, at, EuroSign ] }; key <AE03> { [ 3, sterling, numbersign ] }; + key <TLDE> { [ section, plusminus ] }; + key <LSGT> { [ grave, asciitilde ] }; // End alphanumeric section diff --git a/xorg-server/xkeyboard-config/symbols/md b/xorg-server/xkeyboard-config/symbols/md index 848fe05a7..f7700e930 100644 --- a/xorg-server/xkeyboard-config/symbols/md +++ b/xorg-server/xkeyboard-config/symbols/md @@ -38,7 +38,7 @@ name[Group1]="Moldavian (Gagauz)"; // Alphanumeric section key <TLDE> { [ grave, asciitilde ] }; key <AE01> { [ 1, exclam ] }; - key <AE02> { [ 2, quotedb1, at ] }; + key <AE02> { [ 2, quotedbl, at ] }; key <AE03> { [ 3, numbersign ] }; key <AE04> { [ 4, semicolon, dollar ] }; key <AE05> { [ 5, percent, EuroSign, cent ] }; |