Merge "Merge remote-tracking branch 'origin/5.5' into dev" into refs/staging/dev

This commit is contained in:
Frederik Gladhorn 2015-04-22 08:49:10 +00:00 committed by The Qt Project
commit fe7f4a6d85
790 changed files with 63267 additions and 45147 deletions

View File

@ -190,8 +190,9 @@ sub shouldMasterInclude {
}
######################################################################
# Syntax: classNames(iheader)
# Syntax: classNames(iheader, clean)
# Params: iheader, string, filename to parse for classname "symlinks"
# (out) clean, boolean, will be set to false if the header isn't clean
#
# Purpose: Scans through iheader to find all classnames that should be
# synced into library's include structure.
@ -199,7 +200,8 @@ sub shouldMasterInclude {
######################################################################
sub classNames {
my @ret;
my ($iheader) = @_;
my ($iheader, $clean) = @_;
$$clean = 1;
my $ihdrbase = basename($iheader);
my $classname = $classnames{$ihdrbase};
@ -212,6 +214,7 @@ sub classNames {
chomp $line;
chop $line if ($line =~ /\r$/);
if($line =~ /^\#/) {
$$clean = 0 if ($line =~ m/^#pragma qt_sync_skip_header_check/);
return @ret if($line =~ m/^#pragma qt_sync_stop_processing/);
push(@ret, $1) if($line =~ m/^#pragma qt_class\(([^)]*)\)[\r\n]*$/);
$line = 0;
@ -828,6 +831,7 @@ foreach my $lib (@modules_to_sync) {
my $pri_install_pfiles = "";
my $pri_install_qpafiles = "";
my $pri_injections = "";
my $pri_clean_files = "";
my $libcapitals = uc($lib);
my $master_contents =
@ -929,9 +933,10 @@ foreach my $lib (@modules_to_sync) {
}
}
my $clean_header;
my $iheader = $subdir . "/" . $header;
$iheader =~ s/^\Q$basedir\E/$out_basedir/ if ($shadow);
my @classes = $public_header && (!$minimal && $is_qt) ? classNames($iheader) : ();
my @classes = $public_header && (!$minimal && $is_qt) ? classNames($iheader, \$clean_header) : ();
if($showonly) {
print "$header [$lib]\n";
foreach(@classes) {
@ -980,6 +985,7 @@ foreach my $lib (@modules_to_sync) {
$injection .= ":$class";
}
$pri_install_files.= "$pri_install_iheader ";;
$pri_clean_files .= "$pri_install_iheader " if ($clean_header);
}
elsif ($qpa_header) {
$pri_install_qpafiles.= "$pri_install_iheader ";;
@ -1120,6 +1126,7 @@ foreach my $lib (@modules_to_sync) {
$headers_pri_contents .= "SYNCQT.HEADER_CLASSES = $pri_install_classes\n";
$headers_pri_contents .= "SYNCQT.PRIVATE_HEADER_FILES = $pri_install_pfiles\n";
$headers_pri_contents .= "SYNCQT.QPA_HEADER_FILES = $pri_install_qpafiles\n";
$headers_pri_contents .= "SYNCQT.CLEAN_HEADER_FILES = $pri_clean_files\n";
$headers_pri_contents .= "SYNCQT.INJECTIONS = $pri_injections\n";
my $headers_pri_file = "$out_basedir/include/$lib/headers.pri";
writeFile($headers_pri_file, $headers_pri_contents, $lib, "headers.pri file");

View File

@ -2,8 +2,6 @@ SOURCES = eglfs-brcm.cpp
CONFIG -= qt
INCLUDEPATH += $$[QT_SYSROOT]/opt/vc/include \
$$[QT_SYSROOT]/opt/vc/include/interface/vcos/pthreads \
$$[QT_SYSROOT]/opt/vc/include/interface/vmcs_host/linux
INCLUDEPATH += $$QMAKE_INCDIR_EGL
LIBS += -L$$[QT_SYSROOT]/opt/vc/lib -lEGL -lGLESv2 -lbcm_host
LIBS += -L$$QMAKE_LIBDIR_EGL -lEGL -lGLESv2 -lbcm_host

20
configure vendored
View File

@ -762,6 +762,7 @@ QPA_PLATFORM_GUARD=yes
CFG_CXX11=auto
CFG_DIRECTWRITE=no
CFG_WERROR=auto
CFG_HEADERSCLEAN=auto
CFG_QREAL=double
OPT_MAC_SDK=
COMMERCIAL_USER=ask
@ -2240,6 +2241,13 @@ while [ "$#" -gt 0 ]; do
UNKNOWN_OPT=yes
fi
;;
headersclean)
if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ]; then
CFG_HEADERSCLEAN="$VAL"
else
UNKNOWN_OPT=yes
fi
;;
xkb-config-root)
CFG_XKB_CONFIG_ROOT="$VAL"
;;
@ -6712,8 +6720,16 @@ if [ "$CFG_DEV" = "yes" ]; then
if [ "$CFG_WERROR" != "no" ]; then
QMAKE_CONFIG="$QMAKE_CONFIG warnings_are_errors"
fi
elif [ "$CFG_WERROR" = "yes" ]; then
QMAKE_CONFIG="$QMAKE_CONFIG warnings_are_errors"
if [ "$CFG_HEADERSCLEAN" != "no" ]; then
QMAKE_CONFIG="$QMAKE_CONFIG headersclean"
fi
else
if [ "$CFG_WERROR" = "yes" ]; then
QMAKE_CONFIG="$QMAKE_CONFIG warnings_are_errors"
fi
if [ "$CFG_HEADERSCLEAN" = "yes" ]; then
QMAKE_CONFIG="$QMAKE_CONFIG headersclean"
fi
fi
cat >>"$QTCONFIG.tmp" <<EOF

View File

@ -13,12 +13,12 @@ HTML.footer += \
" <nav class=\"footer-nav clearfix\">\n" \
" <div class=\"menu-footer-menu-container\"><ul id=\"menu-footer-menu\" class=\"menu\"><li id=\"menu-item-1350\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-has-children menu-item-1350\"><a href=\"http://qt.io/about-us/\">About us</a>\n" \
"<ul class=\"sub-menu\">\n" \
" <li id=\"menu-item-1353\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-1353\"><a href=\"http://qt.io/events/\">Events</a></li>\n" \
" <li id=\"menu-item-1353\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-1353\"><a href=\"http://qt.io/events/\">Training &amp; Events</a></li>\n" \
" <li id=\"menu-item-1596\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-1596\"><a href=\"http://qt.io/news/\">News</a></li>\n" \
" <li id=\"menu-item-1354\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-1354\"><a href=\"http://qt.io/resource-center/\">Resource Center</a></li>\n" \
" <li id=\"menu-item-1352\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-1352\"><a href=\"http://qt.io/partners/\">Partners</a></li>\n" \
" <li id=\"menu-item-1349\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-1349\"><a href=\"http://qt.io/careers/\">Careers</a></li>\n" \
" <li id=\"menu-item-1415\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-1415\"><a href=\"http://qt.io/terms-conditions/\">Terms &amp; Conditions</a></li>\n" \
" <li id=\"menu-item-11676\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-11676\"><a href=\"http://qt.io/locations/\">Locations</a></li>\n" \
"</ul>\n" \
"</li>\n" \
"<li id=\"menu-item-1355\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-has-children menu-item-1355\"><a href=\"http://qt.io/product/\">Product</a>\n" \
@ -28,7 +28,7 @@ HTML.footer += \
" <li id=\"menu-item-1359\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-1359\"><a href=\"http://qt.io/qt-quick/\">Qt Quick</a></li>\n" \
" <li id=\"menu-item-1357\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-1357\"><a href=\"http://qt.io/qt-for-device-creation/\">Qt for Device Creation</a></li>\n" \
" <li id=\"menu-item-10159\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-10159\"><a href=\"http://qt.io/mobile-app-development/\">Qt for Mobile Apps</a></li>\n" \
" <li id=\"menu-item-1366\" class=\"menu-item menu-item-type-custom menu-item-object-custom menu-item-1366\"><a href=\"http://showroom.qt-project.org/\">Showroom</a></li>\n" \
" <li id=\"menu-item-12576\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-12576\"><a href=\"http://qt.io/qt-in-use/\">Qt in Use</a></li>\n" \
"</ul>\n" \
"</li>\n" \
"<li id=\"menu-item-33\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-has-children menu-item-33\"><a href=\"http://qt.io/developers/\">Developers</a>\n" \
@ -53,18 +53,19 @@ HTML.footer += \
"</li>\n" \
"<li id=\"menu-item-1403\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-has-children menu-item-1403\"><a href=\"http://qt.io/download/\">Download</a>\n" \
"<ul class=\"sub-menu\">\n" \
" <li id=\"menu-item-1985\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-1985\"><a title=\"Professional\" href=\"http://qt.io/buy/\">Professional</a></li>\n" \
" <li id=\"menu-item-3346\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-3346\"><a title=\"Indie Mobile\" href=\"http://qt.io/download-mobile/\">Indie Mobile</a></li>\n" \
" <li id=\"menu-item-1982\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-1982\"><a title=\"Enterprise\" href=\"http://qt.io/download-enterprise-step-2/\">Enterprise</a></li>\n" \
" <li id=\"menu-item-3013\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-3013\"><a title=\"Evaluation\" href=\"http://qt.io/download-eval-step-2/\">Evaluation</a></li>\n" \
" <li id=\"menu-item-11677\" class=\"menu-item menu-item-type-custom menu-item-object-custom menu-item-11677\"><a href=\"http://qt.io/download/\">Free 30-Day Trial</a></li>\n" \
" <li id=\"menu-item-1982\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-1982\"><a href=\"http://qt.io/buy-enterprise-step-2/\">Enterprise</a></li>\n" \
" <li id=\"menu-item-1985\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-1985\"><a href=\"http://qt.io/buy-professional-step-2/\">Professional</a></li>\n" \
" <li id=\"menu-item-3346\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-3346\"><a href=\"http://qt.io/buy-indiemobile-step-2/\">Indie Mobile</a></li>\n" \
" <li id=\"menu-item-3343\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-3343\"><a href=\"http://qt.io/download-open-source/\">Community</a></li>\n" \
" <li id=\"menu-item-1415\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-1415\"><a href=\"http://qt.io/terms-conditions/\">Legal | Terms &amp; Conditions</a></li>\n" \
"</ul>\n" \
"</li>\n" \
"</ul></div></nav>\n" \
"<a href=\"http://qt.io/about-us/\" target=\"_blank\" class=\"theqtcompany\"></a>\n" \
" <div class=\"footer-social clearfix\">\n" \
" <div class=\"facebook\">\n" \
" <iframe scrolling=\"no\" frameborder=\"0\" allowTransparency=\"true\" src=\"//www.facebook.com/plugins/like.php?href=https%3A%2F%2Fwww.facebook.com%2Fqtbydigia&amp;width&amp;layout=button_count&amp;action=like&amp;show_faces=true&amp;share=false&amp;height=21\" style=\"border:none;overflow:hidden;height:21px;\"></iframe>\n" \
" <iframe scrolling=\"no\" frameborder=\"0\" allowTransparency=\"true\" src=\"//www.facebook.com/plugins/like.php?href=https%3A%2F%2Fwww.facebook.com%2Fqt&amp;width&amp;layout=button_count&amp;action=like&amp;show_faces=true&amp;share=false&amp;height=21\" style=\"border:none;overflow:hidden;height:21px;\"></iframe>\n" \
" </div>\n" \
" <div class=\"twitter\">\n" \
" <iframe id=\"twitter-widget-0\" scrolling=\"no\" frameborder=\"0\" allowtransparency=\"true\" src=\"http://platform.twitter.com/widgets/follow_button.33b190ea0cba008796487b65df7f6d8e.en.html#_=1414403615717&amp;id=twitter-widget-0&amp;lang=en&amp;screen_name=qtproject&amp;show_count=true&amp;show_screen_name=false&amp;size=m\" class=\"twitter-follow-button twitter-follow-button\" title=\"Twitter Follow Button\" data-twttr-rendered=\"true\" style=\"width: 160px; height: 20px;\"></iframe>\n" \

View File

@ -29,7 +29,7 @@ HTML.headerstyles = \
HTML.headerscripts = \
" <script type=\"text/javascript\"> wpThemeFolder = \'http://qt.io/wp-content/themes/oneqt\'; </script>\n" \
" <script type=\"text/javascript\" src=\"http://d3hp9ud7yvwzy0.cloudfront.net/wp-content/themes/oneqt/js/combo.js.gzip\"></script>\n" \
" <script type=\"text/javascript\" src=\"//d3hp9ud7yvwzy0.cloudfront.net/wp-content/themes/oneqt/js/combo.js.gzip\"></script>\n" \
" <script type=\"text/javascript\" src=\"scripts/main.js\"></script>\n" \
" <script type=\"text/javascript\" src=\"scripts/extras.js\"></script>\n" \
" <script type=\"text/javascript\">\n" \
@ -62,7 +62,7 @@ HTML.postheader = \
"<header id=\"navbar\" class=\"\">\n" \
" <div class=\"cookies_yum\">\n" \
" <div>\n" \
" <img src=\"http://qt.io/wp-content/themes/oneqt/assets/images/cookie_small.png\" align=\"left\">\n" \
" <img src=\"//d3hp9ud7yvwzy0.cloudfront.net/wp-content/themes/oneqt/assets/images/cookie_small.png\" align=\"left\">\n" \
" <p class=\"close_button\">\n" \
" We bake cookies in your browser for a better experience. Using this site means that you consent. <a href=\"//qt.io/terms-conditions/\">Read More</a>\n" \
" </p>\n" \
@ -95,12 +95,11 @@ HTML.postheader = \
" <a href=\"http://qt.io/\" class=\"navbar-oneQt retina\" data-icon=\"\">\n" \
" </a>\n" \
" <nav class=\"navbar-menu clearfix\" role=\"navigation\">\n" \
" <ul id=\"mainmenu\" class=\"menu\"><li id=\"menu-item-21\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-21\"><a href=\"http://qt.io/product/\">Product</a></li>\n" \
"<li id=\"menu-item-1381\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-1381\"><a href=\"http://qt.io/services/\">Services</a></li>\n" \
"<li id=\"menu-item-22\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-22\"><a href=\"http://qt.io/qt-in-use/\">Qt in Use</a></li>\n" \
"<li id=\"menu-item-20\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-20\"><a href=\"http://qt.io/developers/\">Developers</a></li>\n" \
"<li id=\"menu-item-4466\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-4466\"><a href=\"http://qt.io/licensing/\">Licensing</a></li>\n" \
"<li id=\"menu-item-18\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-18\"><a href=\"http://qt.io/download/\">Download</a></li>\n" \
" <ul id=\"mainmenu\" class=\"menu\"><li id=\"menu-item-18\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-18\"><a href=\"http://qt.io/download/\">Download</a></li>\n" \
"<li id=\"menu-item-12207\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-12207\"><a href=\"http://www.qt.io/qt-for-device-creation/\">Device Creation</a></li>\n" \
"<li id=\"menu-item-12208\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-12208\"><a href=\"http://www.qt.io/application-development/\">Application Development</a></li>\n" \
"<li id=\"menu-item-1381\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-1381\"><a href=\"http://www.qt.io/services/\">Services</a></li>\n" \
"<li id=\"menu-item-20\" class=\"menu-item menu-item-type-post_type menu-item-object-page menu-item-20\"><a href=\"http://www.qt.io/developers/\">Developers</a></li>\n" \
"</ul> <ul class=\"menuextraslanguages\">\n" \
" <li class=\"active dark\"><a class=\"dark\" href=\"http://qt.io/support/\">EN</a></li><li class=\"dark\"><a class=\"dark\" href=\"http://qt.io/ru/\">RU</a></li><li class=\"dark\"><a class=\"dark\" href=\"http://qt.io/zh-hans/\">ZH</a></li></ul>\n" \
" </nav>\n" \

View File

@ -4,7 +4,7 @@ $(function () {
$('a[href*=#]:not([href=#])').on('click', function (e) {
if (e.which == 2)
return true;
var target = $(this.hash);
var target = $(this.hash.replace(/(\.)/g, "\\$1"));
target = target.length ? target : $('[name=' + this.hash.slice(1) + ']');
if (target.length) {
setTimeout(function () {
@ -15,10 +15,10 @@ $(function () {
$(window).load(function () {
var h = window.location.hash;
var re = /[^a-z0-9_\#\-]/i
var re = /[^a-z0-9_\.\#\-]/i
if (h.length > 1 && !re.test(h)) {
setTimeout(function () {
$(window).scrollTop($(h).offset().top - vOffset);
$(window).scrollTop($(h.replace(/(\.)/g, "\\$1")).offset().top - vOffset);
}, 0);
}
});

View File

@ -36,7 +36,7 @@ function load_sdk(s, id, src) {
fjs.parentNode.insertBefore(js, fjs);
}
$(document).ready(function($) {
if (document.documentElement.clientWidth < 1220) {
if (document.documentElement.clientWidth < 1280) {
oneQt.extraLinksToMain();
}
@ -76,7 +76,7 @@ $(document).ready(function($) {
$(window).resize(function() {
oneQt.stickySidebar();
oneQt.footerPosition();
if (document.documentElement.clientWidth < 1220) {
if (document.documentElement.clientWidth < 1280) {
oneQt.extraLinksToMain();
} else {
oneQt.mainLinkstoExtra();
@ -216,7 +216,7 @@ var oneQt = {
var extramenuLinks = $('#menuextras').find('li');
var mainmenu = $('#mainmenu');
var count = 0;
if ($(extramenuLinks).length > 3) {
if ($(extramenuLinks).length > 2) {
$(extramenuLinks).each(function() {
if (count < 3) {
var newLink = $(this);

View File

@ -25,7 +25,9 @@
min-width:95px;
position:relative;
text-align:center;
margin:10px 0 0 0
border-left:1px solid #eee;
border-right:1px solid #eee;
padding:10px 0 10px 0
}
#navbar .navbar-toggle:hover figure {
background:#5caa15
@ -873,13 +875,13 @@ body.qt-account #navbar .navbar-oneQt h2 {
.clearfix .right {
float:right
}
html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video {
html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video {
margin:0;
padding:0;
border:0;
font-size:100%
}
html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,caption,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video {
html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,caption,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video {
vertical-align:baseline
}
body {

View File

@ -173,9 +173,28 @@ contains(CONFIG, plugin) {
CMAKE_MKSPEC = $$[QMAKE_XSPEC]
CMAKE_MODULE_DEPS = $$cmakeModuleList($$sort_depends(QT.$${MODULE}.depends, QT.))
CMAKE_PARTIAL_MODULE_DEPS = $$replace(CMAKE_MODULE_DEPS, ";", ";Qt5::")
!isEmpty(CMAKE_PARTIAL_MODULE_DEPS):CMAKE_QT5_MODULE_DEPS = "Qt5::$${CMAKE_PARTIAL_MODULE_DEPS}"
sorted_deps = $$sort_depends(QT.$${MODULE}.depends, QT.)
mod_deps =
lib_deps =
aux_mod_deps =
aux_lib_deps =
# Until CMake 3.0 is the minimum requirement of Qt 5, we need to filter
# out header-only modules from dependencies. CMake 3.0 provides INTERFACE
# libraries which are equivalent to header-only modules.
for (dep, sorted_deps) {
cdep = $$cmakeModuleName($$dep)
!contains(QT.$${dep}.module_config, no_link) {
mod_deps += $$cdep
lib_deps += Qt5::$$cdep
} else {
aux_mod_deps += $$cdep
aux_lib_deps += Qt5::$$cdep
}
}
CMAKE_MODULE_DEPS = $$join(mod_deps, ";")
CMAKE_QT5_MODULE_DEPS = $$join(lib_deps, ";")
CMAKE_INTERFACE_MODULE_DEPS = $$join(aux_mod_deps, ";")
CMAKE_INTERFACE_QT5_MODULE_DEPS = $$join(aux_lib_deps, ";")
CMAKE_QT_STEM = Qt$$QT_MAJOR_VERSION$${CMAKE_MODULE_NAME}$${QT_LIBINFIX}

View File

@ -61,7 +61,12 @@ BUILD_DIR = $$replace($$list($$OUT_PWD/build), /, $$QMAKE_DIR_SEP)
dependentmodules = $$resolve_depends(CMAKE_QT_MODULES_UNDER_TEST, "QT.")
dependentmodules -= $$CMAKE_QT_MODULES_UNDER_TEST
dependentmodules = $$cmakeModuleList($$dependentmodules)
mod_deps =
for (dep, dependentmodules): \
!contains(QT.$${dep}.module_config, no_link): \
mod_deps += $$cmakeModuleName($$dep)
dependentmodules = $$join(mod_deps, ";")
contains(QT_CONFIG, angle): CMAKE_GL_DEFINES = -DQT_WITH_ANGLE=True
!contains(QT_CONFIG, egl): CMAKE_GL_DEFINES += -DNO_EGL=True

View File

@ -1,7 +1,13 @@
!!IF !equals(TEMPLATE, aux)
if (CMAKE_VERSION VERSION_LESS 2.8.3)
message(FATAL_ERROR \"Qt 5 requires at least CMake version 2.8.3\")
endif()
!!ELSE
if (CMAKE_VERSION VERSION_LESS 3.0.0)
message(FATAL_ERROR \"Qt 5 $${CMAKE_MODULE_NAME} module requires at least CMake version 3.0.0\")
endif()
!!ENDIF
!!IF !isEmpty(CMAKE_USR_MOVE_WORKAROUND)
!!IF !isEmpty(CMAKE_LIB_DIR_IS_ABSOLUTE)
@ -46,7 +52,7 @@ but not all the files it references.
endif()
endmacro()
!!IF !equals(TEMPLATE, aux)
macro(_populate_$${CMAKE_MODULE_NAME}_target_properties Configuration LIB_LOCATION IMPLIB_LOCATION)
set_property(TARGET Qt5::$${CMAKE_MODULE_NAME} APPEND PROPERTY IMPORTED_CONFIGURATIONS ${Configuration})
@ -80,6 +86,7 @@ macro(_populate_$${CMAKE_MODULE_NAME}_target_properties Configuration LIB_LOCATI
endif()
!!ENDIF
endmacro()
!!ENDIF
if (NOT TARGET Qt5::$${CMAKE_MODULE_NAME})
@ -143,13 +150,20 @@ if (NOT TARGET Qt5::$${CMAKE_MODULE_NAME})
endif()
!!ENDIF
!!IF !equals(TEMPLATE, aux)
set(Qt5$${CMAKE_MODULE_NAME}_INCLUDE_DIRS ${_Qt5$${CMAKE_MODULE_NAME}_OWN_INCLUDE_DIRS})
set(Qt5$${CMAKE_MODULE_NAME}_DEFINITIONS -D$${MODULE_DEFINE})
set(Qt5$${CMAKE_MODULE_NAME}_COMPILE_DEFINITIONS $${MODULE_DEFINE})
!!ENDIF // TEMPLATE != aux
set(_Qt5$${CMAKE_MODULE_NAME}_MODULE_DEPENDENCIES \"$${CMAKE_MODULE_DEPS}\")
!!IF !isEmpty(CMAKE_INTERFACE_MODULE_DEPS)
if (NOT CMAKE_VERSION VERSION_LESS 3.0.0)
list(APPEND _Qt5$${CMAKE_MODULE_NAME}_MODULE_DEPENDENCIES \"$${CMAKE_INTERFACE_MODULE_DEPS}\")
endif()
!!ENDIF
set(_Qt5$${CMAKE_MODULE_NAME}_FIND_DEPENDENCIES_REQUIRED)
if (Qt5$${CMAKE_MODULE_NAME}_FIND_REQUIRED)
set(_Qt5$${CMAKE_MODULE_NAME}_FIND_DEPENDENCIES_REQUIRED REQUIRED)
@ -163,7 +177,9 @@ if (NOT TARGET Qt5::$${CMAKE_MODULE_NAME})
set(_Qt5$${CMAKE_MODULE_NAME}_FIND_VERSION_EXACT EXACT)
endif()
!!IF !equals(TEMPLATE, aux)
set(Qt5$${CMAKE_MODULE_NAME}_EXECUTABLE_COMPILE_FLAGS \"\")
!!ENDIF // TEMPLATE != aux
foreach(_module_dep ${_Qt5$${CMAKE_MODULE_NAME}_MODULE_DEPENDENCIES})
if (NOT Qt5${_module_dep}_FOUND)
@ -180,26 +196,40 @@ if (NOT TARGET Qt5::$${CMAKE_MODULE_NAME})
return()
endif()
!!IF !equals(TEMPLATE, aux)
list(APPEND Qt5$${CMAKE_MODULE_NAME}_INCLUDE_DIRS \"${Qt5${_module_dep}_INCLUDE_DIRS}\")
list(APPEND Qt5$${CMAKE_MODULE_NAME}_PRIVATE_INCLUDE_DIRS \"${Qt5${_module_dep}_PRIVATE_INCLUDE_DIRS}\")
list(APPEND Qt5$${CMAKE_MODULE_NAME}_DEFINITIONS ${Qt5${_module_dep}_DEFINITIONS})
list(APPEND Qt5$${CMAKE_MODULE_NAME}_COMPILE_DEFINITIONS ${Qt5${_module_dep}_COMPILE_DEFINITIONS})
list(APPEND Qt5$${CMAKE_MODULE_NAME}_EXECUTABLE_COMPILE_FLAGS ${Qt5${_module_dep}_EXECUTABLE_COMPILE_FLAGS})
!!ENDIF // TEMPLATE != aux
endforeach()
!!IF !equals(TEMPLATE, aux)
list(REMOVE_DUPLICATES Qt5$${CMAKE_MODULE_NAME}_INCLUDE_DIRS)
list(REMOVE_DUPLICATES Qt5$${CMAKE_MODULE_NAME}_PRIVATE_INCLUDE_DIRS)
list(REMOVE_DUPLICATES Qt5$${CMAKE_MODULE_NAME}_DEFINITIONS)
list(REMOVE_DUPLICATES Qt5$${CMAKE_MODULE_NAME}_COMPILE_DEFINITIONS)
list(REMOVE_DUPLICATES Qt5$${CMAKE_MODULE_NAME}_EXECUTABLE_COMPILE_FLAGS)
!!ENDIF // TEMPLATE != aux
set(_Qt5$${CMAKE_MODULE_NAME}_LIB_DEPENDENCIES \"$${CMAKE_QT5_MODULE_DEPS}\")
!!IF !isEmpty(CMAKE_INTERFACE_QT5_MODULE_DEPS)
if (NOT CMAKE_VERSION VERSION_LESS 3.0.0)
list(APPEND _Qt5$${CMAKE_MODULE_NAME}_LIB_DEPENDENCIES \"$${CMAKE_INTERFACE_QT5_MODULE_DEPS}\")
endif()
!!ENDIF
!!IF !isEmpty(CMAKE_STATIC_TYPE)
add_library(Qt5::$${CMAKE_MODULE_NAME} STATIC IMPORTED)
set_property(TARGET Qt5::$${CMAKE_MODULE_NAME} PROPERTY IMPORTED_LINK_INTERFACE_LANGUAGES "CXX")
!!ELSE
!!IF equals(TEMPLATE, aux)
add_library(Qt5::$${CMAKE_MODULE_NAME} INTERFACE IMPORTED)
!!ELSE
add_library(Qt5::$${CMAKE_MODULE_NAME} SHARED IMPORTED)
!!ENDIF
!!ENDIF
!!IF !isEmpty(CMAKE_BUILD_IS_FRAMEWORK)
set_property(TARGET Qt5::$${CMAKE_MODULE_NAME} PROPERTY FRAMEWORK 1)
!!ENDIF
@ -209,6 +239,7 @@ if (NOT TARGET Qt5::$${CMAKE_MODULE_NAME})
set_property(TARGET Qt5::$${CMAKE_MODULE_NAME} PROPERTY
INTERFACE_COMPILE_DEFINITIONS $${MODULE_DEFINE})
!!IF !equals(TEMPLATE, aux)
!!IF !isEmpty(CMAKE_RELEASE_TYPE)
!!IF !isEmpty(CMAKE_STATIC_WINDOWS_BUILD)
_populate_$${CMAKE_MODULE_NAME}_target_properties(RELEASE \"$${CMAKE_IMPLIB_FILE_LOCATION_RELEASE}\" \"\" )
@ -282,6 +313,11 @@ if (NOT TARGET Qt5::$${CMAKE_MODULE_NAME})
!!ENDIF // CMAKE_FIND_OTHER_LIBRARY_BUILD
!!ENDIF // CMAKE_DEBUG_TYPE
!!ELSE // TEMPLATE != aux
set_target_properties(Qt5::$${CMAKE_MODULE_NAME} PROPERTIES
INTERFACE_LINK_LIBRARIES \"${_Qt5$${CMAKE_MODULE_NAME}_LIB_DEPENDENCIES}\"
)
!!ENDIF // TEMPLATE != aux
file(GLOB pluginTargets \"${CMAKE_CURRENT_LIST_DIR}/Qt5$${CMAKE_MODULE_NAME}_*Plugin.cmake\")

View File

@ -0,0 +1,2 @@
// Used when we need to compile with no source code
// (controls are in the command-line)

View File

@ -14,17 +14,26 @@ host_build {
# Provide a function to be used by mkspecs
defineTest(deviceSanityCheckCompiler) {
equals(QMAKE_HOST.os, Windows): \
sfx = .exe
else: \
sfx =
# Check if the binary exists with an absolute path. Do this check
# before the CROSS_COMPILE empty check below to allow the mkspec
# to derive the compiler path from other device options.
exists($$QMAKE_CXX):return()
exists($$QMAKE_CXX$$sfx):return()
# Check for possible reasons of failure
# check if CROSS_COMPILE device-option is set
isEmpty(CROSS_COMPILE):error("CROSS_COMPILE needs to be set via -device-option CROSS_COMPILE=<path>")
# Check if QMAKE_CXX points to an executable.
system("which $$QMAKE_CXX > /dev/null"):return()
ensurePathEnv()
for (dir, QMAKE_PATH_ENV) {
exists($$dir/$${QMAKE_CXX}$$sfx): \
return()
}
# QMAKE_CXX does not point to a compiler.
error("Compiler $$QMAKE_CXX not found. Check the value of CROSS_COMPILE -device-option")

View File

@ -1,47 +0,0 @@
# The headersclean test attempts to ensure all public Qt headers
# abide by various rules.
#
# To use this test, create a project which contains nothing else than a
# QT= line with the modules you want to test (no presence conditionals needed),
# followed by load(qt_headersclean).
*-g++*: QMAKE_CXXFLAGS += -W -Wall -Wextra -Werror
# The flags here come from http://wiki.qt.io/Coding_Conventions#Conventions_for_public_header_files
# -Wold-style-cast cannot be used, /usr/include/bits/byteswap.h defines the macro bswap_16 using C style casts :(
# -Wfloat-equal cannot be used, qrect.h and qvector2d.h do exact comparisons in isNull and operator==. Would need #pragmas.
*-g++*: QMAKE_CXXFLAGS += -Woverloaded-virtual -Wshadow -Wundef
# Other nice flags
*-g++*: QMAKE_CXXFLAGS += -Wnon-virtual-dtor -ansi -Wchar-subscripts -Wpointer-arith -Wformat-security
# Enable pedantic mode, but accept variadic macros and 'long long' usage.
*-g++*: QMAKE_CXXFLAGS += -Wno-long-long -Wno-variadic-macros -pedantic-errors
QMAKE_CXXFLAGS += -DQT_NO_CAST_TO_ASCII \
-DQT_NO_CAST_FROM_ASCII \
-DQT_STRICT_ITERATORS \
-DQT_NO_URL_CAST_FROM_STRING \
-DQT_NO_CAST_FROM_BYTEARRAY \
-DQT_NO_KEYWORDS \
-DQT_USE_FAST_CONCATENATION \
-DQT_USE_FAST_OPERATOR_PLUS
TARGET = tst_headersclean
includes =
for(q, QT) {
sq = $$replace(q, -private\$, )
qn = $$eval(QT.$${sq}.name)
isEmpty(qn): \
QT -= $$q
else: \
includes += "$${LITERAL_HASH}include <$$qn/$$qn>"
}
includes = $$join(includes, $$escape_expand(\\n))
testfile.input = $$PWD/data/headersclean/tst_headersclean.cpp.in
testfile.output = $$OUT_PWD/tst_headersclean.cpp
QMAKE_SUBSTITUTES += testfile
SOURCES += $$testfile.output

View File

@ -60,10 +60,6 @@ MODULE_DEFINES = $$MODULE_DEFINE $$MODULE_DEFINES
load(qt_module_pris)
INCLUDEPATH *= $$eval(QT.$${MODULE}.includes) $$eval(QT.$${MODULE}_private.includes)
!no_module_headers: load(qt_module_headers)
#other
TEMPLATE = lib
DESTDIR = $$eval(QT.$${MODULE_ID}.libs)
@ -73,6 +69,11 @@ CONFIG += qmake_cache target_qt
QMAKE_DOCS_TARGETDIR = qt$${MODULE}
load(qt_common)
!no_module_headers: load(qt_module_headers)
INCLUDEPATH *= $$eval(QT.$${MODULE}.includes) $$eval(QT.$${MODULE}_private.includes)
# If Qt was configured with -debug-and-release then build the module the same way
# - unless this is a host library
!host_build:if(win32|mac):!macx-xcode {
@ -175,7 +176,6 @@ android: CONFIG += qt_android_deps
load(qt_installs)
load(qt_targets)
load(qt_common)
# this builds on top of qt_common
unix|mingw {

View File

@ -71,8 +71,94 @@ SYNCQT.HEADER_FILES += $$MODULE_MASTER_DEPS_HEADER
# Automatically enable precompiled headers for Qt modules,
# except for Gcc/Windows: Larger precompiled headers crash cc1plus.exe
# (e.g. with i686-4.8.2-release-posix-dwarf-rt_v3-rev3)
!gcc|!equals(QMAKE_HOST.os, Windows) {
!if(gcc:equals(QMAKE_HOST.os, Windows)):!equals(TEMPLATE, aux) {
isEmpty(PRECOMPILED_HEADER): PRECOMPILED_HEADER = $$MODULE_MASTER_DEPS_HEADER
}
CONFIG += qt_install_headers
headersclean:!internal_module {
# Make sure that the header compiles with our strict options
hcleanDEFS = -DQT_NO_CAST_TO_ASCII=1 \
-DQT_NO_CAST_FROM_ASCII=1 \
-DQT_STRICT_ITERATORS \
-DQT_NO_URL_CAST_FROM_STRING=1 \
-DQT_NO_CAST_FROM_BYTEARRAY=1 \
-DQT_NO_KEYWORDS=1 \
-DQT_USE_FAST_CONCATENATION \
-DQT_USE_FAST_OPERATOR_PLUS \
-Dsignals=int \
-Dslots=int \
-Demit=public: \
-Dforeach=public: \
-Dforever=public:
gcc {
# Turn on some extra warnings not found in -Wall -Wextra.
# Common to GCC, Clang and ICC (and other compilers that masquerade as GCC):
hcleanFLAGS = -Wall -Wextra -Werror \
-Woverloaded-virtual -Wshadow -Wundef \
-Wnon-virtual-dtor -Wpointer-arith -Wformat-security \
-Wno-long-long -Wno-variadic-macros -pedantic-errors
intel_icc {
# these warnings are disabled because explicit constructors with zero or
# multiple arguments are permitted in C++11:
# 2304: non-explicit constructor with single argument may cause implicit type conversion
# 2305: declaration of 'explicit' constructor without a single argument is redundant
hcleanFLAGS += -wd2304,2305
greaterThan(QT_ICC_MAJOR_VERSION, 13) {
# ICC 14+ has a bug with -Wshadow, emitting it for cases where there's no shadowing
# (issue ID 0000698329, task DPD200245740)
hcleanFLAGS -= -Wshadow
}
} else {
hcleanFLAGS += -Wchar-subscripts
!contains(QT_ARCH, arm):!contains(QT_ARCH, mips): \
hcleanFLAGS += -Wcast-align
}
# Use strict mode C++11 or C++98, with no GNU extensions (see -pedantic-errors above).
# The module might set CONFIG += c++11, but it might also change QMAKE_CXXFLAGS_CXX11
# or the module (or the mkspec) can set the C++11 flag on QMAKE_CXXFLAGS
# (or QMAKE_CXXFLAGS_{RELEASE,DEBUG} but that's unlikely).
c++11:contains(QMAKE_CXXFLAGS_CXX11, -std=gnu++11) {
hcleanFLAGS += -std=c++11
} else: contains(QMAKE_CXXFLAGS, -std=gnu++11) {
hcleanFLAGS += -std=c++11
} else: c++11:contains(QMAKE_CXXFLAGS_CXX11, -std=gnu++0x) {
hcleanFLAGS += -std=c++0x
} else: contains(QMAKE_CXXFLAGS, -std=gnu++0x) {
hcleanFLAGS += -std=c++0x
} else: !c++11:!contains(QMAKE_CXXFLAGS, -std=c++0x):!contains(QMAKE_CXXFLAGS, -std=c++11) {
hcleanFLAGS += -std=c++98
}
hcleanCOMMAND = $$QMAKE_CXX -c $(CXXFLAGS) $$hcleanFLAGS $(INCPATH) $$hcleanDEFS -xc++ ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT}
} else: win32-msvc2013 {
# 4180: qualifier applied to function type has no meaning; ignored
# 4458: declaration of 'identifier' hides class member
# -Za enables strict standards behavior, but we can't add it because
# <windows.h> and <GL.h> violate the standards.
hcleanFLAGS = -WX -W3 -wd4180 -wd4458
hcleanCOMMAND = $$QMAKE_CXX -c $(CXXFLAGS) $$hcleanFLAGS $(INCPATH) $$hcleanDEFS -FI${QMAKE_FILE_IN} -Fo${QMAKE_FILE_OUT} \
$$[QT_INSTALL_DATA/src]/mkspecs/features/data/dummy.cpp
}
!isEmpty(hcleanCOMMAND):if(!contains(QT_CONFIG, debug_and_release)|CONFIG(release, debug|release)) {
header_check.dependency_type = TYPE_C
header_check.CONFIG += no_link
header_check.output = ${QMAKE_VAR_OBJECTS_DIR}header_${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)}
header_check.input = SYNCQT.CLEAN_HEADER_FILES
header_check.variable_out = PRE_TARGETDEPS
header_check.name = headercheck ${QMAKE_FILE_IN}
header_check.commands = $$hcleanCOMMAND
silent:header_check.commands = @echo compiling[header] ${QMAKE_FILE_IN} && $$hcleanCOMMAND
QMAKE_EXTRA_COMPILERS += header_check
SYNCQT.CLEAN_HEADER_FILES -= $$HEADERSCLEAN_EXCLUDE
}
unset(hcleanCOMMAND)
unset(hcleanFLAGS)
unset(hcleanDEFS)
}

View File

@ -26,8 +26,11 @@ else: \
mod_inst_pfx = $$mod_work_pfx
!internal_module {
MODULE_ID = $$MODULE
MODULE_PRIVATE_PRI = $$mod_inst_pfx/qt_lib_$${MODULE}_private.pri
mods_to_load = $$MODULE $${MODULE}_private
mods_to_load = $$MODULE
!no_private_module {
MODULE_PRIVATE_PRI = $$mod_inst_pfx/qt_lib_$${MODULE}_private.pri
mods_to_load += $${MODULE}_private
}
} else {
MODULE_ID = $${MODULE}_private
mods_to_load = $${MODULE}_private

View File

@ -23,19 +23,25 @@ QMAKE_H_MOD_MOC = moc_
QMAKE_MOD_LEX = _lex
QMAKE_MOD_YACC = _yacc
defineTest(ensurePathEnv) {
isEmpty(QMAKE_PATH_ENV) {
QMAKE_PATH_ENV = $$(PATH)
QMAKE_PATH_ENV = $$split(QMAKE_PATH_ENV, $$QMAKE_DIRLIST_SEP)
export(QMAKE_PATH_ENV)
}
}
equals(QMAKE_HOST.os, Windows) {
QMAKE_EXT_OBJ = .obj
QMAKE_EXT_RES = .res
QMAKE_SH =
PATH = $$(PATH)
PATH = $$split(PATH, ;)
for(dir, PATH) {
ensurePathEnv()
for(dir, QMAKE_PATH_ENV) {
exists($$dir/sh.exe) {
QMAKE_SH = $$dir/sh.exe
break()
}
}
unset(PATH)
} else {
QMAKE_EXT_CPP += .C
QMAKE_EXT_H += .H

View File

@ -19,3 +19,17 @@ dumpcpp_impl.name = CPP
dumpcpp_impl.depends = ${QMAKE_FILE_BASE}.h
QMAKE_EXTRA_COMPILERS += dumpcpp_impl
# Create dependencies from every object file to our generated header files.
if(isEmpty(BUILDS)|build_pass):have_target:!contains(TEMPLATE, vc.*) {
for(tlb, TYPELIBS) {
hdr = $$basename(tlb)
hdr = $$section(hdr, ., 0, -2).h
TYPELIB_HEADERS += $$hdr
}
objtgt.target = $(OBJECTS)
objtgt.depends = $$TYPELIB_HEADERS
QMAKE_EXTRA_TARGETS += objtgt
}

View File

@ -21,7 +21,7 @@ wince* {
QMAKE_LIBDIR += $$QMAKE_LIBDIR_OPENGL_ES2_RELEASE
}
DEFINES += QT_OPENGL_ES_2 QT_OPENGL_ES_2_ANGLE
contains(QT_CONFIG, static): DEFINES += QT_OPENGL_ES_2_ANGLE_STATIC
contains(QT_CONFIG, static): DEFINES += QT_OPENGL_ES_2_ANGLE_STATIC GL_APICALL= EGLAPI=
QT_CONFIG -= opengl
} else {
!contains(QT_CONFIG, dynamicgl) {

View File

@ -333,7 +333,8 @@ win32:UI_DIR = c:/myproject/ui
#! [57]
VERSION = 1.2.3
win32:VERSION = 1.2.3.4 # major.minor.patch.build
else:VERSION = 1.2.3 # major.minor.patch
#! [57]
@ -982,3 +983,7 @@ QMAKE_SONAME_PREFIX = @executable_path/../Frameworks
QMAKE_SONAME_PREFIX = @loader_path/Frameworks
QMAKE_SONAME_PREFIX = /Library/Frameworks
#! [184]
#! [185]
VERSION_PE_HEADER = 1.2
#! [185]

View File

@ -763,9 +763,55 @@
\section1 Windows
Features specific to this platform include support for creating Visual
Studio project files and handling manifest files when deploying Qt
applications developed using Visual Studio 2005, or later.
Features specific to this platform include support for Windows resource
files (provided or auto-generated), creating Visual Studio project files,
and handling manifest files when deploying Qt applications developed
using Visual Studio 2005, or later.
\section2 Adding Windows Resource Files
This section describes how to handle a Windows resource file with
qmake to have it linked to an application executable (EXE) or dynamic
link library (DLL). qmake can optionally auto-generate a suitably
filled Windows resource file.
A linked Windows resource file may contain many elements that can
be accessed by its EXE or DLL. However, the
\l{The Qt Resource System}{Qt resource system} should be used for
accessing linked-in resources in a platform-independent way. But
some standard elements of the linked Windows resource file are
accessed by Windows itself. For example, in Windows explorer the
version tab of the file properties is filled by resource elements.
In addition, the program icon of the EXE is read from these elements.
So it is good practice for a Qt created Windows EXE or DLL to use
both techniques at the same time: link platform-independent resources
via the \l{The Qt Resource System}{Qt resource system} and add Windows
specific resources via a Windows resource file.
Typically, a resource-definition script (.rc file) is compiled to a
Windows resource file. Within the Microsoft toolchain, the RC tool
generates a .res file, which can be linked with the Microsoft linker
to an EXE or DLL. The MinGW toolchain uses the windres tool to generate
an .o file that can be linked with the MinGW linker to an EXE or DLL.
The optional auto-generation of a suitably filled .rc file by qmake is
triggered by setting at least one of the system variables \l{VERSION}
and \l{RC_ICONS}. The generated .rc file is automatically compiled and
linked. Elements that are added to the .rc file are defined by the system
variables \l{QMAKE_TARGET_COMPANY}, \l{QMAKE_TARGET_DESCRIPTION},
\l{QMAKE_TARGET_COPYRIGHT}, \l{QMAKE_TARGET_PRODUCT}, \l{RC_CODEPAGE},
\l{RC_ICONS}, \l{RC_LANG},and \l{VERSION}.
If these elements are not sufficient, qmake has the two system variables
\l{RC_FILE} and \l{RES_FILE} that point directly to an externally created
.rc or .res file. By setting one of these variables, the specified file
is linked to the EXE or DLL.
\note The generation of the .rc file by qmake is blocked, if \l{RC_FILE}
or \l{RES_FILE} is set. In this case, no further changes are made to the
given .rc file or the .res or .o file by qmake; the variables pertaining
to .rc file generation have no effect.
\section2 Creating Visual Studio Project Files
@ -2132,34 +2178,35 @@
\target QMAKE_TARGET_COMPANY
\section1 QMAKE_TARGET_COMPANY
Windows only. Specifies the company for the project target, this is used where
applicable for putting the company name in the application's properties. This is
only utilized if the VERSION or RC_ICONS variable is set and the RC_FILE and RES_FILE
variables are not set.
Windows only. Specifies the company for the project target; this is
used where applicable for putting the company name in the application's
properties. This is only utilized if the \l{VERSION} or \l{RC_ICONS}
variable is set and the \l{RC_FILE} and \l{RES_FILE} variables are not set.
\target QMAKE_TARGET_DESCRIPTION
\section1 QMAKE_TARGET_DESCRIPTION
Windows only. Specifies the description for the project target, this is used where
applicable for putting the description in the application's properties. This is only
utilized if the VERSION or RC_ICONS variable is set and the RC_FILE and RES_FILE variables
are not set.
Windows only. Specifies the description for the project target; this is
used where applicable for putting the description in the application's
properties. This is only utilized if the \l{VERSION} or \l{RC_ICONS}
variable is set and the \l{RC_FILE} and \l{RES_FILE} variables are not set.
\target QMAKE_TARGET_COPYRIGHT
\section1 QMAKE_TARGET_COPYRIGHT
Windows only. Specifies the copyright information for the project target, this is used where
applicable for putting the copyright information in the application's properties. This is only
utilized if the VERSION or RC_ICONS variable is set and the RC_FILE and RES_FILE variables
Windows only. Specifies the copyright information for the project target;
this is used where applicable for putting the copyright information in the
application's properties. This is only utilized if the \l{VERSION} or
\l{RC_ICONS} variable is set and the \l{RC_FILE} and \l{RES_FILE} variables
are not set.
\target QMAKE_TARGET_PRODUCT
\section1 QMAKE_TARGET_PRODUCT
Windows only. Specifies the product for the project target, this is used where
applicable for putting the product in the application's properties. This is only utilized if
the VERSION or RC_ICONS variable is set and the RC_FILE and RES_FILE variables
are not set.
Windows only. Specifies the product for the project target; this is used
where applicable for putting the product in the application's properties.
This is only utilized if the \l{VERSION} or \l{RC_ICONS} variable is set
and the \l{RC_FILE} and \l{RES_FILE} variables are not set.
\section1 QT
@ -2263,22 +2310,24 @@
\target RC_CODEPAGE
\section1 RC_CODEPAGE
Windows only. Specifies the codepage that should be specified in a generated rc file. This is
only utilized if the VERSION or RC_ICONS variable is set and the RC_FILE and RES_FILE variables
are not set.
Windows only. Specifies the codepage that should be specified in a generated
.rc file. This is only utilized if the \l{VERSION} or \l{RC_ICONS} variable
is set and the \l{RC_FILE} and \l{RES_FILE} variables are not set.
\target RC_ICONS
\section1 RC_ICONS
Windows only. Specifies the icons that should be included into a generated rc file, this
is only utilized if the RC_FILE and RES_FILE variable are not set.
Windows only. Specifies the icons that should be included into a generated
.rc file. This is only utilized if the \l{RC_FILE} and \l{RES_FILE} variable
are not set. More details about the generation of .rc files can be found in
the \l{Platform Notes}.
\target RC_LANG
\section1 RC_LANG
Windows only. Specifies the language that should be specified in a generated rc file. This is
only utilized if the VERSION or RC_ICONS variable is set and the RC_FILE and RES_FILE variables
are not set.
Windows only. Specifies the language that should be specified in a generated
.rc file. This is only utilized if the \l{VERSION} or \l{RC_ICONS} variable
is set and the \l{RC_FILE} and \l{RES_FILE} variables are not set.
\section1 RC_INCLUDEPATH
@ -2477,13 +2526,31 @@
\target VERSION
\section1 VERSION
Specifies the version number of the application if the \c app \l{#TEMPLATE}{template} is
specified or the version number of the library if the \c lib template is specified.
Specifies the version number of the application if the \c app
\l{#TEMPLATE}{template} is specified or the version number of
the library if the \c lib template is specified.
On Windows, triggers auto-generation of an .rc file if the \l{RC_FILE}
and \l{RES_FILE} variables are not set. The generated .rc file will have
the FILEVERSION and PRODUCTVERSION entries filled with major, minor, patch
level, and build number. Each number must be in the range from 0 to 65535.
More details about the generation of .rc files can be found in the
\l{Platform Notes}.
For example:
\snippet code/doc_src_qmake-manual.pro 57
\section1 VERSION_PE_HEADER
Windows only. Specifies the version number, that the Windows linker
puts into the header of the .exe or .dll file via the /VERSION option.
Only a major and minor version may be specified.
If VERSION_PE_HEADER is not set, it falls back to
the major and minor version from \l{VERSION} (if set).
\snippet code/doc_src_qmake-manual.pro 185
\section1 VER_MAJ
Specifies the major version number of the library if the
@ -4638,7 +4705,9 @@
When using this template, the following qmake
system variables are recognized. You should use these in your .pro file to
specify information about your application.
specify information about your application. For additional
platform-dependent system variables, you could have a look at the
\l{Platform Notes}.
\list
\li \l{HEADERS} - A list of header files for the application.
@ -4660,9 +4729,6 @@
\li \l{VPATH} - The search path to find supplied files.
\li \l{DEF_FILE} - Windows only: A .def file to be linked against for the
application.
\li \l{RC_FILE} - Windows only: A resource file for the application.
\li \l{RES_FILE} - Windows only: A resource file to be linked against for
the application.
\endlist
You only need to use the system variables that you have values for. For

View File

@ -105,7 +105,7 @@ ProjectBuilderMakefileGenerator::writeSubDirs(QTextStream &t)
{
if(project->isActiveConfig("generate_pbxbuild_makefile")) {
QString mkwrap = fileFixify(pbx_dir + Option::dir_sep + ".." + Option::dir_sep + project->first("MAKEFILE"),
qmake_getpwd());
FileFixifyToIndir);
QFile mkwrapf(mkwrap);
if(mkwrapf.open(QIODevice::WriteOnly | QIODevice::Text)) {
debug_msg(1, "pbuilder: Creating file: %s", mkwrap.toLatin1().constData());
@ -184,13 +184,13 @@ ProjectBuilderMakefileGenerator::writeSubDirs(QTextStream &t)
bool in_root = true;
QString name = qmake_getpwd();
if(project->isActiveConfig("flat")) {
QString flat_file = fileFixify(name, oldpwd, oldoutpwd, FileFixifyRelative);
QString flat_file = fileFixify(name, FileFixifyBackwards | FileFixifyRelative);
if(flat_file.indexOf(Option::dir_sep) != -1) {
QStringList dirs = flat_file.split(Option::dir_sep);
name = dirs.back();
}
} else {
QString flat_file = fileFixify(name, oldpwd, oldoutpwd, FileFixifyRelative);
QString flat_file = fileFixify(name, FileFixifyBackwards | FileFixifyRelative);
if(QDir::isRelativePath(flat_file) && flat_file.indexOf(Option::dir_sep) != -1) {
QString last_grp("QMAKE_SUBDIR_PBX_HEIR_GROUP");
QStringList dirs = flat_file.split(Option::dir_sep);
@ -507,14 +507,6 @@ static QString xcodeFiletypeForFilename(const QString &filename)
bool
ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
{
// The code in this function assumes that the current directory matches
// the output directory, which is not actually the case when we are called
// from the generic generator code. Instead of changing every single
// assumption and fileFixify we cheat by moving into the output directory
// for the duration of this function.
QString input_dir = qmake_getpwd();
qmake_setpwd(Option::output_dir);
ProStringList tmp;
bool did_preprocess = false;
@ -536,7 +528,6 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
QFile mkf(mkfile);
if(mkf.open(QIODevice::WriteOnly | QIODevice::Text)) {
writingUnixMakefileGenerator = true;
qmake_setpwd(input_dir); // Makefile generation assumes input_dir as pwd
debug_msg(1, "pbuilder: Creating file: %s", mkfile.toLatin1().constData());
QTextStream mkt(&mkf);
writeHeader(mkt);
@ -545,10 +536,9 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
mkt.flush();
mkf.close();
writingUnixMakefileGenerator = false;
qmake_setpwd(Option::output_dir);
}
QString phase_key = keyFor("QMAKE_PBX_MAKEQMAKE_BUILDPHASE");
mkfile = fileFixify(mkfile, qmake_getpwd());
mkfile = fileFixify(mkfile);
project->values("QMAKE_PBX_PRESCRIPT_BUILDPHASES").append(phase_key);
t << "\t\t" << phase_key << " = {\n"
<< "\t\t\t" << writeSettings("buildActionMask", "2147483647", SettingsNoQuote) << ";\n"
@ -557,17 +547,20 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
<< "\t\t\t" << writeSettings("runOnlyForDeploymentPostprocessing", "0", SettingsNoQuote) << ";\n"
<< "\t\t\t" << writeSettings("name", "Qt Qmake") << ";\n"
<< "\t\t\t" << writeSettings("shellPath", "/bin/sh") << ";\n"
<< "\t\t\t" << writeSettings("shellScript", "make -C " + IoUtils::shellQuoteUnix(qmake_getpwd()) + " -f " + IoUtils::shellQuoteUnix(mkfile)) << ";\n"
<< "\t\t\t" << writeSettings("shellScript", "make -C " + IoUtils::shellQuoteUnix(Option::output_dir)
+ " -f " + IoUtils::shellQuoteUnix(mkfile)) << ";\n"
<< "\t\t\t" << writeSettings("showEnvVarsInLog", "0") << ";\n"
<< "\t\t};\n";
}
// FIXME: Move all file resolving logic out of ProjectBuilderSources::files(), as it
// doesn't have access to any of the information it needs to resolve relative paths.
project->values("QMAKE_INTERNAL_INCLUDED_FILES").prepend(fileFixify(project->projectFile(), qmake_getpwd(), input_dir));
project->values("QMAKE_INTERNAL_INCLUDED_FILES").prepend(project->projectFile());
// Since we can't fileFixify inside ProjectBuilderSources::files(), we resolve the absolute paths here
project->values("QMAKE_INTERNAL_INCLUDED_FILES") = ProStringList(fileFixify(project->values("QMAKE_INTERNAL_INCLUDED_FILES").toQStringList(), FileFixifyAbsolute));
project->values("QMAKE_INTERNAL_INCLUDED_FILES") = ProStringList(
fileFixify(project->values("QMAKE_INTERNAL_INCLUDED_FILES").toQStringList(),
FileFixifyFromOutdir | FileFixifyAbsolute));
//DUMP SOURCES
QMap<QString, ProStringList> groups;
@ -624,7 +617,8 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
ProStringList &src_list = project->values(ProKey("QMAKE_PBX_" + sources.at(source).keyName()));
ProStringList &root_group_list = project->values("QMAKE_PBX_GROUPS");
const QStringList &files = fileFixify(sources.at(source).files(project));
const QStringList &files = fileFixify(sources.at(source).files(project),
FileFixifyFromOutdir | FileFixifyAbsolute);
for(int f = 0; f < files.count(); ++f) {
QString file = files[f];
if(!sources.at(source).compilerName().isNull() &&
@ -636,12 +630,11 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
bool in_root = true;
QString src_key = keyFor(file);
file = fileFixify(file, qmake_getpwd(), Option::output_dir, FileFixifyAbsolute);
QString name = file.split(Option::dir_sep).back();
if (!project->isActiveConfig("flat")) {
// Build group hierarchy for file references that match the source our build dir
QString relativePath = fileFixify(file, input_dir, qmake_getpwd(), FileFixifyRelative);
QString relativePath = fileFixify(file, FileFixifyToIndir | FileFixifyRelative);
if (QDir::isRelativePath(relativePath) && relativePath.startsWith(QLatin1String("../")))
relativePath = fileFixify(file, FileFixifyRelative); // Try build dir
@ -771,7 +764,7 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
if(added && !(added % 3))
mkt << "\\\n\t";
++added;
const QString file_name = fileFixify(fn, Option::output_dir, Option::output_dir);
const QString file_name = fileFixify(fn, FileFixifyFromOutdir);
mkt << ' ' << escapeDependencyPath(Option::fixPathToTargetOS(
replaceExtraCompilerVariables(tmp_out.first().toQString(), file_name, QString(), NoShell)));
}
@ -784,7 +777,7 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
mkt.flush();
mkf.close();
}
mkfile = fileFixify(mkfile, qmake_getpwd());
mkfile = fileFixify(mkfile);
QString phase_key = keyFor("QMAKE_PBX_PREPROCESS_TARGET");
// project->values("QMAKE_PBX_BUILDPHASES").append(phase_key);
project->values("QMAKE_PBX_PRESCRIPT_BUILDPHASES").append(phase_key);
@ -795,7 +788,8 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
<< "\t\t\t" << writeSettings("runOnlyForDeploymentPostprocessing", "0", SettingsNoQuote) << ";\n"
<< "\t\t\t" << writeSettings("name", "Qt Preprocessors") << ";\n"
<< "\t\t\t" << writeSettings("shellPath", "/bin/sh") << ";\n"
<< "\t\t\t" << writeSettings("shellScript", "make -C " + IoUtils::shellQuoteUnix(qmake_getpwd()) + " -f " + IoUtils::shellQuoteUnix(mkfile)) << ";\n"
<< "\t\t\t" << writeSettings("shellScript", "make -C " + IoUtils::shellQuoteUnix(Option::output_dir)
+ " -f " + IoUtils::shellQuoteUnix(mkfile)) << ";\n"
<< "\t\t\t" << writeSettings("showEnvVarsInLog", "0") << ";\n"
<< "\t\t};\n";
}
@ -927,7 +921,7 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
if(!path.isEmpty() && !libdirs.contains(path))
libdirs += path;
}
library = fileFixify(library);
library = fileFixify(library, FileFixifyFromOutdir);
QString key = keyFor(library);
if (!project->values("QMAKE_PBX_LIBRARIES").contains(key)) {
bool is_frmwrk = (library.endsWith(".framework"));
@ -984,7 +978,7 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
writingUnixMakefileGenerator = false;
}
QString phase_key = keyFor("QMAKE_PBX_SUBLIBS_BUILDPHASE");
mkfile = fileFixify(mkfile, qmake_getpwd());
mkfile = fileFixify(mkfile);
project->values("QMAKE_PBX_PRESCRIPT_BUILDPHASES").append(phase_key);
t << "\t\t" << phase_key << " = {\n"
<< "\t\t\t" << writeSettings("buildActionMask", "2147483647", SettingsNoQuote) << ";\n"
@ -993,7 +987,8 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
<< "\t\t\t" << writeSettings("runOnlyForDeploymentPostprocessing", "0", SettingsNoQuote) << ";\n"
<< "\t\t\t" << writeSettings("name", "Qt Sublibs") << ";\n"
<< "\t\t\t" << writeSettings("shellPath", "/bin/sh") << "\n"
<< "\t\t\t" << writeSettings("shellScript", "make -C " + IoUtils::shellQuoteUnix(qmake_getpwd()) + " -f " + IoUtils::shellQuoteUnix(mkfile)) << ";\n"
<< "\t\t\t" << writeSettings("shellScript", "make -C " + IoUtils::shellQuoteUnix(Option::output_dir)
+ " -f " + IoUtils::shellQuoteUnix(mkfile)) << ";\n"
<< "\t\t\t" << writeSettings("showEnvVarsInLog", "0") << ";\n"
<< "\t\t};\n";
}
@ -1080,8 +1075,8 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
if (!project->isEmpty("DESTDIR")) {
QString phase_key = keyFor("QMAKE_PBX_TARGET_COPY_PHASE");
QString destDir = project->first("DESTDIR").toQString();
destDir = fileInfo(Option::normalizePath(destDir)).absoluteFilePath();
QString destDir = fileFixify(project->first("DESTDIR").toQString(),
FileFixifyFromOutdir | FileFixifyAbsolute);
project->values("QMAKE_PBX_BUILDPHASES").append(phase_key);
t << "\t\t" << phase_key << " = {\n"
<< "\t\t\t" << writeSettings("isa", "PBXShellScriptBuildPhase", SettingsNoQuote) << ";\n"
@ -1111,7 +1106,7 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
//all files
const ProStringList &files = project->values(ProKey(bundle_data[i] + ".files"));
for(int file = 0; file < files.count(); file++) {
QString fn = fileFixify(files[file].toQString(), Option::output_dir, input_dir, FileFixifyRelative);
QString fn = fileFixify(files[file].toQString(), FileFixifyAbsolute);
QString name = fn.split(Option::dir_sep).back();
QString file_ref_key = keyFor("QMAKE_PBX_BUNDLE_DATA_FILE_REF." + bundle_data[i] + "-" + fn);
bundle_file_refs += file_ref_key;
@ -1475,10 +1470,10 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
if ((project->first("TEMPLATE") == "app" && project->isActiveConfig("app_bundle")) ||
(project->first("TEMPLATE") == "lib" && !project->isActiveConfig("staticlib") &&
project->isActiveConfig("lib_bundle"))) {
QString plist = fileFixify(project->first("QMAKE_INFO_PLIST").toQString(), Option::output_dir, input_dir);
QString plist = fileFixify(project->first("QMAKE_INFO_PLIST").toQString(), FileFixifyToIndir);
if (!plist.isEmpty()) {
if (exists(plist))
t << "\t\t\t\t" << writeSettings("INFOPLIST_FILE", plist) << ";\n";
t << "\t\t\t\t" << writeSettings("INFOPLIST_FILE", fileFixify(plist)) << ";\n";
else
warn_msg(WarnLogic, "Could not resolve Info.plist: '%s'. Check if QMAKE_INFO_PLIST points to a valid file.", plist.toLatin1().constData());
} else {
@ -1504,7 +1499,7 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
plist_in_text.replace("@TYPEINFO@",
(project->isEmpty("QMAKE_PKGINFO_TYPEINFO")
? QString::fromLatin1("????") : project->first("QMAKE_PKGINFO_TYPEINFO").left(4).toQString()));
QFile plist_out_file("Info.plist");
QFile plist_out_file(Option::output_dir + "/Info.plist");
if (plist_out_file.open(QIODevice::WriteOnly | QIODevice::Text)) {
QTextStream plist_out(&plist_out_file);
plist_out << plist_in_text;
@ -1514,12 +1509,12 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
}
}
t << "\t\t\t\t" << writeSettings("SYMROOT", qmake_getpwd()) << ";\n";
t << "\t\t\t\t" << writeSettings("SYMROOT", Option::output_dir) << ";\n";
if (!project->isEmpty("DESTDIR")) {
ProString dir = project->first("DESTDIR");
if (QDir::isRelativePath(dir.toQString()))
dir.prepend(qmake_getpwd() + Option::dir_sep);
dir.prepend(Option::output_dir + Option::dir_sep);
t << "\t\t\t\t" << writeSettings("INSTALL_DIR", dir) << ";\n";
}
@ -1656,8 +1651,7 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
<< "}\n";
if(project->isActiveConfig("generate_pbxbuild_makefile")) {
QString mkwrap = fileFixify(pbx_dir + Option::dir_sep + ".." + Option::dir_sep + project->first("MAKEFILE"),
qmake_getpwd());
QString mkwrap = Option::output_dir + project->first("/MAKEFILE");
QFile mkwrapf(mkwrap);
if(mkwrapf.open(QIODevice::WriteOnly | QIODevice::Text)) {
writingUnixMakefileGenerator = true;
@ -1729,8 +1723,6 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
"falling back to Xcode auto-generated schemes", qPrintable(projectSharedSchemesPath));
}
qmake_setpwd(input_dir);
return true;
}

View File

@ -162,8 +162,6 @@ MakefileGenerator::initOutPaths()
v["QMAKE_ABSOLUTE_SOURCE_PATH"].clear();
}
QString currentDir = qmake_getpwd(); //just to go back to
//some builtin directories
if(project->isEmpty("PRECOMPILED_DIR") && !project->isEmpty("OBJECTS_DIR"))
v["PRECOMPILED_DIR"] = v["OBJECTS_DIR"];
@ -177,7 +175,7 @@ MakefileGenerator::initOutPaths()
const ProString orig_path = v[dkey].first();
ProString &pathRef = v[dkey].first();
pathRef = fileFixify(pathRef.toQString(), Option::output_dir, Option::output_dir);
pathRef = fileFixify(pathRef.toQString(), FileFixifyFromOutdir);
#ifdef Q_OS_WIN
// We don't want to add a separator for DLLDESTDIR on Windows (###why?)
@ -192,7 +190,7 @@ MakefileGenerator::initOutPaths()
continue;
QString path = project->first(dkey).toQString(); //not to be changed any further
path = fileFixify(path, currentDir, Option::output_dir);
path = fileFixify(path, FileFixifyBackwards);
debug_msg(3, "Fixed output_dir %s (%s) into %s", dirs[x],
orig_path.toLatin1().constData(), path.toLatin1().constData());
if(!mkdir(path))
@ -210,7 +208,7 @@ MakefileGenerator::initOutPaths()
for (ProStringList::ConstIterator it2 = tmp.begin(); it2 != tmp.end(); ++it2) {
ProStringList &inputs = project->values((*it2).toKey());
for (ProStringList::Iterator input = inputs.begin(); input != inputs.end(); ++input) {
QString finp = fileFixify((*input).toQString(), Option::output_dir, Option::output_dir);
QString finp = fileFixify((*input).toQString(), FileFixifyFromOutdir);
*input = ProString(finp);
QString path = replaceExtraCompilerVariables(tmp_out, finp, QString(), NoShell);
path = Option::normalizePath(path);
@ -220,7 +218,7 @@ MakefileGenerator::initOutPaths()
// Make out path only if it does not contain makefile variables
if(!path.contains("${"))
if(path != "." &&
!mkdir(fileFixify(path, qmake_getpwd(), Option::output_dir)))
!mkdir(fileFixify(path, FileFixifyBackwards)))
warn_msg(WarnLogic, "%s: Cannot access directory '%s'",
(*it).toLatin1().constData(), path.toLatin1().constData());
}
@ -276,7 +274,7 @@ MakefileGenerator::findFilesInVPATH(ProStringList l, uchar flags, const QString
continue;
}
if(!(flags & VPATH_NoFixify))
file = fileFixify(file, qmake_getpwd(), Option::output_dir);
file = fileFixify(file, FileFixifyBackwards);
if(exists(file)) {
++val_it;
@ -314,7 +312,7 @@ MakefileGenerator::findFilesInVPATH(ProStringList l, uchar flags, const QString
dir = regex.left(regex.lastIndexOf(Option::dir_sep) + 1);
real_dir = dir;
if(!(flags & VPATH_NoFixify))
real_dir = fileFixify(real_dir, qmake_getpwd(), Option::output_dir) + '/';
real_dir = fileFixify(real_dir, FileFixifyBackwards) + '/';
regex.remove(0, dir.length());
}
if(real_dir.isEmpty() || exists(real_dir)) {
@ -495,10 +493,10 @@ MakefileGenerator::init()
sub.toLatin1().constData());
continue;
}
inn = fileFixify(tinn.first().toQString(), qmake_getpwd());
outn = fileFixify(toutn.first().toQString(), qmake_getpwd(), Option::output_dir);
inn = fileFixify(tinn.first().toQString(), FileFixifyToIndir);
outn = fileFixify(toutn.first().toQString(), FileFixifyBackwards);
} else {
inn = fileFixify(sub, qmake_getpwd());
inn = fileFixify(sub, FileFixifyToIndir);
if (!QFile::exists(inn)) {
// random insanity for backwards compat: .in file specified with absolute out dir
inn = fileFixify(sub);
@ -508,7 +506,7 @@ MakefileGenerator::init()
inn.toLatin1().constData());
continue;
}
outn = fileFixify(inn.left(inn.length()-3), qmake_getpwd(), Option::output_dir);
outn = fileFixify(inn.left(inn.length() - 3), FileFixifyBackwards);
}
const ProKey confign(sub + ".CONFIG");
@ -687,7 +685,7 @@ MakefileGenerator::init()
if(tmp_out.indexOf("$") == -1) {
if(!verifyExtraCompiler((*it), QString())) //verify
continue;
QString out = fileFixify(tmp_out.toQString(), Option::output_dir, Option::output_dir);
QString out = fileFixify(tmp_out.toQString(), FileFixifyFromOutdir);
bool pre_dep = (config.indexOf("target_predeps") != -1);
if (v.contains(vokey)) {
const ProStringList &var_out = v.value(vokey);
@ -728,7 +726,7 @@ MakefileGenerator::init()
if (!verifyExtraCompiler((*it).toQString(), inpf)) //verify
continue;
QString out = replaceExtraCompilerVariables(tmp_out.toQString(), inpf, QString(), NoShell);
out = fileFixify(out, Option::output_dir, Option::output_dir);
out = fileFixify(out, FileFixifyFromOutdir);
bool pre_dep = (config.indexOf("target_predeps") != -1);
if (v.contains(vokey)) {
const ProStringList &var_out = project->values(vokey);
@ -886,7 +884,7 @@ MakefileGenerator::processPrlFile(QString &file)
// meta_file = fileFixify(meta_file);
QString real_meta_file = Option::normalizePath(meta_file);
if(!meta_file.isEmpty()) {
QString f = fileFixify(real_meta_file, qmake_getpwd(), Option::output_dir);
QString f = fileFixify(real_meta_file, FileFixifyBackwards);
if(QMakeMetaInfo::libExists(f)) {
QMakeMetaInfo libinfo(project);
debug_msg(1, "Processing PRL file: %s", real_meta_file.toLatin1().constData());
@ -1101,7 +1099,7 @@ MakefileGenerator::prlFileName(bool fixify)
if(fixify) {
if(!project->isEmpty("DESTDIR"))
ret.prepend(project->first("DESTDIR").toQString());
ret = fileFixify(ret, qmake_getpwd(), Option::output_dir);
ret = fileFixify(ret, FileFixifyBackwards);
}
return ret;
}
@ -1507,7 +1505,7 @@ MakefileGenerator::createObjectList(const ProStringList &sources)
QString dir;
if (project->isActiveConfig("object_parallel_to_source")) {
// The source paths are relative to the output dir, but we need source-relative paths
QString sourceRelativePath = fileFixify(sfn, qmake_getpwd(), Option::output_dir);
QString sourceRelativePath = fileFixify(sfn, FileFixifyBackwards);
if (sourceRelativePath.startsWith(".." + Option::dir_sep))
sourceRelativePath = fileFixify(sourceRelativePath, FileFixifyAbsolute);
@ -1523,7 +1521,7 @@ MakefileGenerator::createObjectList(const ProStringList &sources)
if (!noIO()) {
// Ensure that the final output directory of each object exists
QString outRelativePath = fileFixify(dir, qmake_getpwd(), Option::output_dir);
QString outRelativePath = fileFixify(dir, FileFixifyBackwards);
if (!mkdir(outRelativePath))
warn_msg(WarnLogic, "Cannot create directory '%s'", outRelativePath.toLatin1().constData());
}
@ -1795,7 +1793,7 @@ MakefileGenerator::writeExtraTargets(QTextStream &t)
}
const ProStringList &config = project->values(ProKey(*it + ".CONFIG"));
if (config.indexOf("fix_target") != -1)
targ = fileFixify(targ, Option::output_dir, Option::output_dir);
targ = fileFixify(targ, FileFixifyFromOutdir);
if (config.indexOf("phony") != -1)
deps += QLatin1String(" FORCE");
t << escapeDependencyPath(targ) << ":" << deps;
@ -1812,7 +1810,7 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t)
const ProStringList &quc = project->values("QMAKE_EXTRA_COMPILERS");
for (ProStringList::ConstIterator it = quc.begin(); it != quc.end(); ++it) {
QString tmp_out = fileFixify(project->first(ProKey(*it + ".output")).toQString(),
Option::output_dir, Option::output_dir);
FileFixifyFromOutdir);
const QString tmp_cmd = project->values(ProKey(*it + ".commands")).join(' ');
const QString tmp_dep_cmd = project->values(ProKey(*it + ".depend_command")).join(' ');
QString dep_cd_cmd;
@ -1923,7 +1921,7 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t)
}
QStringList deps, inputs;
if(!tmp_dep.isEmpty())
deps += fileFixify(tmp_dep, Option::output_dir, Option::output_dir);
deps += fileFixify(tmp_dep, FileFixifyFromOutdir);
for (ProStringList::ConstIterator input = tmp_inputs.begin(); input != tmp_inputs.end(); ++input) {
QString inpf = (*input).toQString();
deps += findDependencies(inpf);
@ -1998,7 +1996,7 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t)
t << escapeDependencyPath(Option::fixPathToTargetOS(out)) << ":";
// compiler.CONFIG+=explicit_dependencies means that ONLY compiler.depends gets to cause Makefile dependencies
if (config.indexOf("explicit_dependencies") != -1) {
t << " " << valList(escapeDependencyPaths(fileFixify(tmp_dep, Option::output_dir, Option::output_dir)));
t << " " << valList(escapeDependencyPaths(fileFixify(tmp_dep, FileFixifyFromOutdir)));
} else {
t << " " << valList(escapeDependencyPaths(inputs)) << " " << valList(escapeDependencyPaths(deps));
}
@ -2012,7 +2010,7 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t)
deps << in;
QString out = Option::fixPathToTargetOS(replaceExtraCompilerVariables(tmp_out, inpf, QString(), NoShell));
if(!tmp_dep.isEmpty()) {
QStringList pre_deps = fileFixify(tmp_dep, Option::output_dir, Option::output_dir);
QStringList pre_deps = fileFixify(tmp_dep, FileFixifyFromOutdir);
for(int i = 0; i < pre_deps.size(); ++i)
deps << replaceExtraCompilerVariables(pre_deps.at(i), inpf, out, NoShell);
}
@ -2243,7 +2241,7 @@ QString MakefileGenerator::buildArgs()
//could get stored argv, but then it would have more options than are
//probably necesary this will try to guess the bare minimum..
QString MakefileGenerator::build_args(const QString &outdir)
QString MakefileGenerator::build_args()
{
QString ret = "$(QMAKE)";
@ -2256,7 +2254,7 @@ QString MakefileGenerator::build_args(const QString &outdir)
ret += " -o " + escapeFilePath(ofile);
//inputs
ret += " " + escapeFilePath(fileFixify(project->projectFile(), outdir));
ret += " " + escapeFilePath(fileFixify(project->projectFile()));
return ret;
}
@ -2330,7 +2328,7 @@ MakefileGenerator::findSubDirsSubTargets() const
if(fileInfo(st->in_directory).isRelative())
st->out_directory = st->in_directory;
else
st->out_directory = fileFixify(st->in_directory, qmake_getpwd(), Option::output_dir);
st->out_directory = fileFixify(st->in_directory, FileFixifyBackwards);
const ProKey mkey(fixedSubdir + ".makefile");
if (!project->isEmpty(mkey)) {
st->makefile = project->first(mkey).toQString();
@ -2808,22 +2806,20 @@ MakefileGenerator::escapeDependencyPaths(const ProStringList &paths) const
}
QStringList
MakefileGenerator::fileFixify(const QStringList& files, const QString &out_dir, const QString &in_dir,
FileFixifyType fix, bool canon) const
MakefileGenerator::fileFixify(const QStringList &files, FileFixifyTypes fix, bool canon) const
{
if(files.isEmpty())
return files;
QStringList ret;
for(QStringList::ConstIterator it = files.begin(); it != files.end(); ++it) {
if(!(*it).isEmpty())
ret << fileFixify((*it), out_dir, in_dir, fix, canon);
ret << fileFixify((*it), fix, canon);
}
return ret;
}
QString
MakefileGenerator::fileFixify(const QString& file, const QString &out_d, const QString &in_d,
FileFixifyType fix, bool canon) const
MakefileGenerator::fileFixify(const QString &file, FileFixifyTypes fix, bool canon) const
{
if(file.isEmpty())
return file;
@ -2837,17 +2833,23 @@ MakefileGenerator::fileFixify(const QString& file, const QString &out_d, const Q
else
warn_msg(WarnLogic, "Unable to expand ~ in %s", ret.toLatin1().constData());
}
if(fix == FileFixifyAbsolute || (fix == FileFixifyDefault && project->isActiveConfig("no_fixpath"))) {
if(fix == FileFixifyAbsolute && QDir::isRelativePath(ret)) { //already absolute
QString pwd = qmake_getpwd();
if ((fix & FileFixifyAbsolute)
|| (!(fix & FileFixifyRelative) && project->isActiveConfig("no_fixpath"))) {
if ((fix & FileFixifyAbsolute) && QDir::isRelativePath(ret)) {
QString pwd = !(fix & FileFixifyFromOutdir) ? project->projectDir() : Option::output_dir;
{
QFileInfo in_fi(fileInfo(pwd));
if (in_fi.exists())
pwd = in_fi.canonicalFilePath();
}
if (!pwd.endsWith(QLatin1Char('/')))
pwd += QLatin1Char('/');
ret.prepend(pwd);
}
ret = Option::fixPathToTargetOS(ret, false, canon);
} else { //fix it..
QString out_dir = QDir(Option::output_dir).absoluteFilePath(out_d);
QString in_dir = QDir(qmake_getpwd()).absoluteFilePath(in_d);
QString out_dir = (fix & FileFixifyToIndir) ? project->projectDir() : Option::output_dir;
QString in_dir = !(fix & FileFixifyFromOutdir) ? project->projectDir() : Option::output_dir;
{
QFileInfo in_fi(fileInfo(in_dir));
if(in_fi.exists())
@ -2865,9 +2867,6 @@ MakefileGenerator::fileFixify(const QString& file, const QString &out_d, const Q
qfileinfo.setFile(ret);
}
ret = Option::fixPathToTargetOS(ret, false, canon);
if(canon && qfileinfo.exists() &&
file == Option::fixPathToTargetOS(ret, true, canon))
ret = Option::fixPathToTargetOS(qfileinfo.canonicalFilePath());
QString match_dir = Option::fixPathToTargetOS(out_dir, false, canon);
if(ret == match_dir) {
ret = "";
@ -2912,8 +2911,8 @@ MakefileGenerator::fileFixify(const QString& file, const QString &out_d, const Q
}
if(ret.isEmpty())
ret = ".";
debug_msg(3, "Fixed[%d,%d] %s :: to :: %s [%s::%s] [%s::%s]", fix, canon, orig_file.toLatin1().constData(),
ret.toLatin1().constData(), in_d.toLatin1().constData(), out_d.toLatin1().constData(),
debug_msg(3, "Fixed[%d,%d] %s :: to :: %s [%s::%s]",
int(fix), canon, orig_file.toLatin1().constData(), ret.toLatin1().constData(),
qmake_getpwd().toLatin1().constData(), Option::output_dir.toLatin1().constData());
return ret;
}
@ -2922,7 +2921,7 @@ QMakeLocalFileName
MakefileGenerator::fixPathForFile(const QMakeLocalFileName &file, bool forOpen)
{
if(forOpen)
return QMakeLocalFileName(fileFixify(file.real(), qmake_getpwd(), Option::output_dir));
return QMakeLocalFileName(fileFixify(file.real(), FileFixifyBackwards));
return QMakeLocalFileName(fileFixify(file.real()));
}
@ -2977,7 +2976,7 @@ MakefileGenerator::findFileForDep(const QMakeLocalFileName &dep, const QMakeLoca
if(QDir::isRelativePath(dir)) {
if(!dir.endsWith(Option::dir_sep))
dir += Option::dir_sep;
QString shadow = fileFixify(dir + dep.local(), pwd, Option::output_dir);
QString shadow = fileFixify(dir + dep.local(), FileFixifyBackwards);
if(exists(shadow)) {
ret = QMakeLocalFileName(shadow);
goto found_dep_from_heuristic;
@ -3013,7 +3012,7 @@ MakefileGenerator::findFileForDep(const QMakeLocalFileName &dep, const QMakeLoca
QString out = Option::fixPathToTargetOS(
replaceExtraCompilerVariables(tmp_out.toQString(), (*input).toQString(), QString(), NoShell));
if (out == dep.real() || out.section(Option::dir_sep, -1) == dep_basename) {
ret = QMakeLocalFileName(fileFixify(out, qmake_getpwd(), Option::output_dir));
ret = QMakeLocalFileName(fileFixify(out, FileFixifyBackwards));
goto found_dep_from_heuristic;
}
}
@ -3130,7 +3129,7 @@ MakefileGenerator::pkgConfigFileName(bool fixify)
if(fixify) {
if(QDir::isRelativePath(ret) && !project->isEmpty("DESTDIR"))
ret.prepend(project->first("DESTDIR").toQString());
ret = fileFixify(ret, qmake_getpwd(), Option::output_dir);
ret = fileFixify(ret, FileFixifyBackwards);
}
return ret;
}

View File

@ -60,7 +60,7 @@ class MakefileGenerator : protected QMakeSourceFileInfo
bool no_io;
QHash<QString, bool> init_compiler_already;
QString makedir, chkexists;
QString build_args(const QString &outdir=QString());
QString build_args();
//internal caches
mutable QHash<QString, QMakeLocalFileName> depHeuristicsCache;
@ -224,16 +224,22 @@ protected:
ProStringList fixLibFlags(const ProKey &var);
virtual ProString fixLibFlag(const ProString &lib);
public:
//file fixification to unify all file names into a single pattern
enum FileFixifyType { FileFixifyAbsolute, FileFixifyRelative, FileFixifyDefault };
QString fileFixify(const QString& file, const QString &out_dir=QString(),
const QString &in_dir=QString(), FileFixifyType fix=FileFixifyDefault, bool canon=true) const;
inline QString fileFixify(const QString& file, FileFixifyType fix, bool canon=true) const
{ return fileFixify(file, QString(), QString(), fix, canon); }
QStringList fileFixify(const QStringList& files, const QString &out_dir=QString(),
const QString &in_dir=QString(), FileFixifyType fix=FileFixifyDefault, bool canon=true) const;
inline QStringList fileFixify(const QStringList& files, FileFixifyType fix, bool canon=true) const
{ return fileFixify(files, QString(), QString(), fix, canon); }
enum FileFixifyType {
FileFixifyFromIndir = 0,
FileFixifyFromOutdir = 1,
FileFixifyToOutDir = 0,
FileFixifyToIndir = 2,
FileFixifyBackwards = FileFixifyFromOutdir | FileFixifyToIndir,
FileFixifyDefault = 0,
FileFixifyAbsolute = 4,
FileFixifyRelative = 8
};
Q_DECLARE_FLAGS(FileFixifyTypes, FileFixifyType)
protected:
QString fileFixify(const QString &file, FileFixifyTypes fix = FileFixifyDefault, bool canon = true) const;
QStringList fileFixify(const QStringList &files, FileFixifyTypes fix = FileFixifyDefault, bool canon = true) const;
QString installMetaFile(const ProKey &replace_rule, const QString &src, const QString &dst);
@ -259,6 +265,7 @@ public:
bool isWindowsShell() const { return Option::dir_sep == QLatin1String("\\"); }
QString shellQuote(const QString &str);
};
Q_DECLARE_OPERATORS_FOR_FLAGS(MakefileGenerator::FileFixifyTypes)
inline void MakefileGenerator::setNoIO(bool o)
{ no_io = o; }

View File

@ -379,7 +379,7 @@ ProjectGenerator::addConfig(const QString &cfg, bool add)
bool
ProjectGenerator::addFile(QString file)
{
file = fileFixify(file, qmake_getpwd());
file = fileFixify(file, FileFixifyToIndir);
QString dir;
int s = file.lastIndexOf(Option::dir_sep);
if(s != -1)

View File

@ -107,7 +107,7 @@ UnixMakefileGenerator::writeDefaultVariables(QTextStream &t)
project->values("QMAKE_DISTDIR") = project->first("QMAKE_DISTNAME");
t << "DISTDIR = " << escapeFilePath(fileFixify(
(project->isEmpty("OBJECTS_DIR") ? ProString(".tmp/") : project->first("OBJECTS_DIR")) + project->first("QMAKE_DISTDIR"),
Option::output_dir, Option::output_dir, FileFixifyAbsolute)) << endl;
FileFixifyFromOutdir | FileFixifyAbsolute)) << endl;
}
void
@ -377,7 +377,7 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
}
if(!d_file.isEmpty()) {
d_file = odir + ".deps/" + fileFixify(d_file, pwd, Option::output_dir) + ".d";
d_file = odir + ".deps/" + fileFixify(d_file, FileFixifyBackwards) + ".d";
QString d_file_d = escapeDependencyPath(d_file);
QStringList deps = findDependencies((*it).toQString()).filter(QRegExp(
"((^|/)" + Option::h_moc_mod + "|" + Option::cpp_moc_ext + "$)"));
@ -1396,7 +1396,7 @@ UnixMakefileGenerator::libtoolFileName(bool fixify)
if(fixify) {
if(QDir::isRelativePath(ret) && !project->isEmpty("DESTDIR"))
ret.prepend(project->first("DESTDIR").toQString());
ret = fileFixify(ret, qmake_getpwd(), Option::output_dir);
ret = fileFixify(ret, FileFixifyBackwards);
}
return ret;
}

View File

@ -34,11 +34,22 @@
#include "cesdkhandler.h"
#include <qfile.h>
#include <qfileinfo.h>
#include <qdebug.h>
#include <qxmlstream.h>
#include <qsettings.h>
#include <qtextstream.h>
QT_BEGIN_NAMESPACE
struct PropertyContainer
{
void clear() { name.clear(); value.clear(); properties.clear(); }
QString name;
QString value;
QMap<QString, PropertyContainer> properties;
};
CeSdkInfo::CeSdkInfo() : m_major(0) , m_minor(0)
{
}
@ -47,22 +58,255 @@ CeSdkHandler::CeSdkHandler()
{
}
bool CeSdkHandler::parse()
struct ContainsPathKey
{
bool operator()(const QString &val)
{
return !(val.endsWith(QStringLiteral("MSBuildToolsPath"))
|| val.endsWith(QStringLiteral("MSBuildToolsRoot")));
}
};
struct ValueFromKey
{
ValueFromKey(const QSettings *settings) : settings(settings){}
QString operator()(const QString &key)
{
return settings->value(key).toString();
}
const QSettings *settings;
};
bool CeSdkHandler::parseMsBuildFile(QFile *file, CeSdkInfo *info)
{
bool result = file->open(QFile::ReadOnly | QFile::Text);
const QString IncludePath = QStringLiteral("IncludePath");
const QString LibraryPath = QStringLiteral("LibraryPath");
const QString PreprocessorDefinitions = QStringLiteral("PreprocessorDefinitions");
const QString SdkRootPathString = QStringLiteral("SdkRootPath");
const QString ExecutablePath = QStringLiteral("ExecutablePath");
enum ParserState{Not, Include, Lib, Define, BinDir, SdkRootPath};
QString includePath;
QString libraryPath;
QString defines;
QString binDirs;
QString sdkRootPath;
ParserState state = Not;
if (result) {
QXmlStreamReader xml(file);
while (!xml.atEnd()) {
if (xml.isStartElement()) {
if (xml.name() == IncludePath)
state = Include;
else if (xml.name() == LibraryPath)
state = Lib;
else if (xml.name() == PreprocessorDefinitions)
state = Define;
else if (xml.name() == SdkRootPathString)
state = SdkRootPath;
else if (xml.name() == ExecutablePath)
state = BinDir;
else
state = Not;
} else if (xml.isEndElement()) {
state = Not;
} else if (xml.isCharacters()) {
switch (state) {
case Include:
includePath += xml.text();
break;
case Lib:
libraryPath += xml.text();
break;
case Define:
defines += xml.text();
break;
case SdkRootPath:
sdkRootPath = xml.text().toString();
break;
case BinDir:
binDirs += xml.text();
case(Not):
break;
}
}
xml.readNext();
}
}
file->close();
const bool success = result && !includePath.isEmpty() && !libraryPath.isEmpty() &&
!defines.isEmpty() && !sdkRootPath.isEmpty();
if (success) {
const QString startPattern = QStringLiteral("$(Registry:");
const int startIndex = sdkRootPath.indexOf(startPattern);
const int endIndex = sdkRootPath.lastIndexOf(QStringLiteral(")"));
const QString regString = sdkRootPath.mid(startIndex + startPattern.size(),
endIndex - startIndex - startPattern.size());
QSettings sdkRootPathRegistry(regString, QSettings::NativeFormat);
const QString erg = sdkRootPathRegistry.value(QStringLiteral(".")).toString();
const QString fullSdkRootPath = erg + sdkRootPath.mid(endIndex + 1);
const QString rootString = QStringLiteral("$(SdkRootPath)");
includePath = includePath.replace(rootString, fullSdkRootPath);
libraryPath = libraryPath.replace(rootString, fullSdkRootPath);
binDirs = binDirs.replace(rootString, fullSdkRootPath);
info->m_include = includePath + ";$(INCLUDE)";
info->m_lib = libraryPath;
info->m_bin = binDirs;
}
return success;
}
QStringList CeSdkHandler::getMsBuildToolPaths() const
{
QSettings msbuildEntries("HKEY_LOCAL_MACHINE\\Software\\Microsoft\\MSBuild\\ToolsVersions",
QSettings::NativeFormat);
const QStringList allKeys = msbuildEntries.allKeys();
QStringList toolVersionKeys;
toolVersionKeys.push_back(QStringLiteral("c:\\Program Files\\MSBuild\\"));
std::remove_copy_if(allKeys.cbegin(), allKeys.cend(),
std::back_inserter(toolVersionKeys), ContainsPathKey());
QStringList toolVersionValues;
std::transform(toolVersionKeys.constBegin(), toolVersionKeys.constEnd(),
std::back_inserter(toolVersionValues),
ValueFromKey(&msbuildEntries));
return toolVersionValues;
}
QStringList CeSdkHandler::filterMsBuildToolPaths(const QStringList &paths) const
{
QStringList result;
foreach (const QString &path, paths) {
QDir dir(path);
if (path.endsWith(QStringLiteral("bin")))
dir.cdUp();
if (dir.cd(QStringLiteral("Microsoft.Cpp\\v4.0\\V110\\Platforms"))
|| dir.cd(QStringLiteral("Microsoft.Cpp\\v4.0\\V120\\Platforms"))) {
result << dir.absolutePath();
}
}
return result;
}
bool CeSdkHandler::retrieveEnvironment(const QStringList &relativePaths,
const QStringList &toolPaths,
CeSdkInfo *info)
{
bool result = false;
foreach (const QString &path, toolPaths) {
const QDir dir(path);
foreach (const QString &filePath, relativePaths) {
QFile file(dir.absoluteFilePath(filePath));
if (file.exists())
result = parseMsBuildFile(&file, info) || result;
}
}
return result;
}
void CeSdkHandler::retrieveWEC2013SDKs()
{
const QStringList toolPaths = getMsBuildToolPaths();
const QStringList filteredToolPaths = filterMsBuildToolPaths(toolPaths);
QSettings settings("HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows CE Tools\\SDKs", QSettings::NativeFormat);
const QStringList keys = settings.allKeys();
foreach (const QString &key, keys) {
if (key.contains(QLatin1String("SDKInformation")) || key.contains(QLatin1Char('.'))) {
QFile sdkPropertyFile(settings.value(key).toString());
if (!sdkPropertyFile.exists())
continue;
QFileInfo info(sdkPropertyFile);
if (info.isDir()) {
const QDir dir = info.absoluteFilePath();
QFileInfo fInfo(dir.filePath(QLatin1String("Properties.xml")));
if (fInfo.exists())
sdkPropertyFile.setFileName(fInfo.absoluteFilePath());
}
if (!sdkPropertyFile.open(QFile::ReadOnly))
continue;
QXmlStreamReader xml(&sdkPropertyFile);
QString currentElement;
QString curName;
PropertyContainer currentProperty;
QVector<PropertyContainer> propStack;
propStack.push_back(currentProperty);
while (!xml.atEnd()) {
xml.readNext();
if (xml.isStartElement()) {
currentElement = xml.name().toString();
if (currentElement == QLatin1String("Property")) {
QXmlStreamAttributes attributes = xml.attributes();
if (attributes.hasAttribute(QLatin1String("NAME")))
curName = attributes.value(QLatin1String("NAME")).toString();
Q_ASSERT(!curName.isEmpty());
currentProperty.clear();
currentProperty.name = curName;
propStack.push_back(currentProperty);
} else if (currentElement == QLatin1String("PropertyBag")) {
QXmlStreamAttributes attributes = xml.attributes();
if (attributes.hasAttribute(QLatin1String("NAME")))
curName = attributes.value(QLatin1String("NAME")).toString();
Q_ASSERT(!curName.isEmpty());
currentProperty.clear();
currentProperty.name = curName;
propStack.push_back(currentProperty);
}
} else if (xml.isEndElement()) {
currentElement = xml.name().toString();
PropertyContainer self = propStack.takeLast();
if (currentElement != QLatin1String("Root")) {
PropertyContainer &last = propStack.last();
last.properties[self.name] = self;
} else {
currentProperty = self;
}
} else if (xml.isCharacters()) {
PropertyContainer &self = propStack.last();
self.value = xml.text().toString();
}
}
if (xml.error() && xml.error() != QXmlStreamReader::PrematureEndOfDocumentError) {
qWarning() << "XML ERROR:" << xml.lineNumber() << ": " << xml.errorString();
return;
}
CeSdkInfo currentSdk;
const PropertyContainer &cpuInfo = currentProperty.properties.value(QLatin1String("CPU info"));
if (cpuInfo.properties.isEmpty())
continue;
const PropertyContainer &cpuInfoVal = cpuInfo.properties.first().properties.value(QLatin1String("CpuName"));
if (cpuInfoVal.name != QStringLiteral("CpuName"))
continue;
const QString SDKName = QStringLiteral("SDK name");
currentSdk.m_name = currentProperty.properties.value(SDKName).value+
QStringLiteral(" (") + cpuInfoVal.value + ")";
currentSdk.m_major = currentProperty.properties.value(QLatin1String("OSMajor")).value.toInt();
currentSdk.m_minor = currentProperty.properties.value(QLatin1String("OSMinor")).value.toInt();
retrieveEnvironment(currentProperty.properties.value(QLatin1String("MSBuild Files110")).value.split(';'),
filteredToolPaths, &currentSdk);
if (!currentSdk.m_include.isEmpty())
m_list.append(currentSdk);
}
}
}
void CeSdkHandler::retrieveWEC6n7SDKs()
{
// look at the file at %VCInstallDir%/vcpackages/WCE.VCPlatform.config
// and scan through all installed sdks...
m_list.clear();
m_vcInstallDir = QString::fromLatin1(qgetenv("VCInstallDir"));
if (m_vcInstallDir.isEmpty())
return false;
return;
QDir vStudioDir(m_vcInstallDir);
if (!vStudioDir.cd(QLatin1String("vcpackages")))
return false;
return;
QFile configFile(vStudioDir.absoluteFilePath(QLatin1String("WCE.VCPlatform.config")));
if (!configFile.open(QIODevice::ReadOnly))
return false;
return;
QString currentElement;
CeSdkInfo currentItem;
@ -94,13 +338,19 @@ bool CeSdkHandler::parse()
if (xml.error() && xml.error() != QXmlStreamReader::PrematureEndOfDocumentError) {
qWarning() << "XML ERROR:" << xml.lineNumber() << ": " << xml.errorString();
return false;
return;
}
return m_list.size() > 0;
}
QString CeSdkHandler::fixPaths(QString path) const
bool CeSdkHandler::retrieveAvailableSDKs()
{
m_list.clear();
retrieveWEC2013SDKs();
retrieveWEC6n7SDKs();
return !m_list.empty();
}
QString CeSdkHandler::fixPaths(const QString &path) const
{
QRegExp searchStr(QLatin1String("(\\$\\(\\w+\\))"));
QString fixedString = path;

View File

@ -73,10 +73,18 @@ class CeSdkHandler
{
public:
CeSdkHandler();
bool parse();
bool retrieveAvailableSDKs();
inline QList<CeSdkInfo> listAll() const { return m_list; }
private:
inline QString fixPaths(QString path) const;
void retrieveWEC6n7SDKs();
void retrieveWEC2013SDKs();
inline QString fixPaths(const QString &path) const;
QStringList getMsBuildToolPaths() const;
QStringList filterMsBuildToolPaths(const QStringList &paths) const;
bool parseMsBuildFile(QFile *file, CeSdkInfo *info);
bool retrieveEnvironment(const QStringList &relativePaths,
const QStringList &toolPaths,
CeSdkInfo *info);
QList<CeSdkInfo> m_list;
QString m_vcInstallDir;
};

View File

@ -79,7 +79,7 @@ NmakeMakefileGenerator::writeMakefile(QTextStream &t)
const ProValueMap &variables = project->variables();
if (project->isActiveConfig("wince")) {
CeSdkHandler sdkhandler;
sdkhandler.parse();
sdkhandler.retrieveAvailableSDKs();
const QString sdkName = variables["CE_SDK"].join(' ')
+ " (" + variables["CE_ARCH"].join(' ') + ")";
const QList<CeSdkInfo> sdkList = sdkhandler.listAll();
@ -354,14 +354,18 @@ void NmakeMakefileGenerator::init()
project->values("QMAKE_LFLAGS").append(QString("/DEF:") + escapeFilePath(defFileName));
}
if(!project->values("VERSION").isEmpty()) {
ProString version = project->values("VERSION")[0];
int firstDot = version.indexOf(".");
QString major = version.left(firstDot).toQString();
QString minor = version.right(version.length() - firstDot - 1).toQString();
minor.replace(".", "");
project->values("QMAKE_LFLAGS").append("/VERSION:" + major + "." + minor);
// set /VERSION for EXE/DLL header
ProString major_minor = project->first("VERSION_PE_HEADER");
if (major_minor.isEmpty()) {
ProString version = project->first("VERSION");
if (!version.isEmpty()) {
int firstDot = version.indexOf(".");
int secondDot = version.indexOf(".", firstDot + 1);
major_minor = version.left(secondDot);
}
}
if (!major_minor.isEmpty())
project->values("QMAKE_LFLAGS").append("/VERSION:" + major_minor);
if (project->isEmpty("QMAKE_LINK_O_FLAG"))
project->values("QMAKE_LINK_O_FLAG").append("/OUT:");

View File

@ -2337,7 +2337,7 @@ bool VCFilter::addExtraCompiler(const VCFilterFile &info)
for (int i = 0; i < extradeps.count(); ++i) {
QString dd = extradeps.at(i).simplified();
if (!dd.isEmpty())
deps += Project->fileFixify(dd, QString(), Option::output_dir);
deps += Project->fileFixify(dd, MakefileGenerator::FileFixifyFromOutdir);
}
}
}

View File

@ -787,14 +787,18 @@ void VcprojGenerator::init()
processVars();
if(!project->values("VERSION").isEmpty()) {
QString version = project->values("VERSION")[0].toQString();
int firstDot = version.indexOf(".");
QString major = version.left(firstDot);
QString minor = version.right(version.length() - firstDot - 1);
minor.replace(QRegExp("\\."), "");
project->values("QMAKE_LFLAGS").append("/VERSION:" + major + "." + minor);
// set /VERSION for EXE/DLL header
ProString major_minor = project->first("VERSION_PE_HEADER");
if (major_minor.isEmpty()) {
ProString version = project->first("VERSION");
if (!version.isEmpty()) {
int firstDot = version.indexOf(".");
int secondDot = version.indexOf(".", firstDot + 1);
major_minor = version.left(secondDot);
}
}
if (!major_minor.isEmpty())
project->values("QMAKE_LFLAGS").append("/VERSION:" + major_minor);
MakefileGenerator::init();
@ -1414,9 +1418,29 @@ void VcprojGenerator::initWinDeployQtTool()
conf.windeployqt.ExcludedFromBuild = true;
if (project->isActiveConfig("windeployqt")) {
conf.windeployqt.Record = QStringLiteral("$(TargetName).windeployqt.$(Platform).$(Configuration)");
conf.windeployqt.CommandLine =
MakefileGenerator::shellQuote(QDir::toNativeSeparators(project->first("QMAKE_WINDEPLOYQT").toQString()))
+ QLatin1Char(' ') + project->values("WINDEPLOYQT_OPTIONS").join(QLatin1Char(' '))
const QString commandLine = MakefileGenerator::shellQuote(QDir::toNativeSeparators(project->first("QMAKE_WINDEPLOYQT").toQString()))
+ QLatin1Char(' ') + project->values("WINDEPLOYQT_OPTIONS").join(QLatin1Char(' '));
// Visual Studio copies all files to be deployed into the MSIL directory
// and then invokes MDILXapCompile on it, which checks for managed code and
// translates it into native code. The problem is that all entries of the
// package will be copied into the MSIL directly, losing the subdirectory
// structure (for instance for plugins). However, the MDILXapCompile call
// itself contains the original subdirectories as parameters and hence the
// call fails.
// Neither there is a way to disable this behavior for Windows Phone, nor
// to influence the parameters. Hence the only way to get a release build
// done is to recreate the directory structure manually by invoking
// windeployqt a second time, so that the MDILXapCompile call succeeds and
// deployment continues.
if (conf.WinPhone && conf.Name == QStringLiteral("Release|ARM")) {
conf.windeployqt.CommandLine = commandLine
+ QStringLiteral(" -list relative -dir \"$(MSBuildProjectDirectory)\\")
+ var("OBJECTS_DIR")
+ QStringLiteral("MSIL\" \"$(OutDir)\\$(TargetName).exe\" ")
+ QLatin1String(" && ");
}
conf.windeployqt.CommandLine += commandLine
+ QStringLiteral(" -list relative -dir \"$(MSBuildProjectDirectory)\" \"$(OutDir)\\$(TargetName).exe\" > ")
+ MakefileGenerator::shellQuote(conf.windeployqt.Record);
conf.windeployqt.config = &vcProject.Configuration;
@ -1564,7 +1588,7 @@ void VcprojGenerator::initResourceFiles()
QT_PCLOSE(proc);
if(!indeps.isEmpty())
deps += fileFixify(indeps.replace('\n', ' ').simplified().split(' '),
QString(), Option::output_dir);
FileFixifyFromOutdir);
}
}
}

View File

@ -70,6 +70,7 @@ bool QMakeProject::read(const QString &project, LoadFlags what)
QString absproj = (project == QLatin1String("-"))
? QLatin1String("(stdin)")
: QDir::cleanPath(QDir(qmake_getpwd()).absoluteFilePath(project));
m_projectDir = QFileInfo(absproj).path();
return boolRet(evaluateFile(absproj, QMakeHandler::EvalProjectFile, what));
}

View File

@ -41,6 +41,7 @@ QT_BEGIN_NAMESPACE
class QMakeProject : private QMakeEvaluator
{
QString m_projectFile;
QString m_projectDir;
public:
QMakeProject();
@ -49,6 +50,7 @@ public:
bool read(const QString &project, LoadFlags what = LoadAll);
QString projectFile() const { return m_projectFile; }
QString projectDir() const { return m_projectDir; }
QString sourceRoot() const { return m_sourceRoot.isEmpty() ? m_buildRoot : m_sourceRoot; }
QString buildRoot() const { return m_buildRoot; }
QString confFile() const { return m_conffile; }

View File

@ -6,19 +6,28 @@ build
extensions
samples
tests
third_party
src/ipch
util
.svn
# Files from ANGLE we don't want/need
DEPS
*.chromium
*.isolate
*.md
*.gn
*.gyp
*.gypi
*.sh
*.bat
*.patch
*.py
*.rc
*_unittest.cpp
codereview.settings
src/commit.h
src/libANGLE/renderer/gl
src/third_party/khronos/GL
# Generated by flex/bison
src/compiler/preprocessor/Tokenizer.cpp
@ -28,5 +37,5 @@ src/compiler/translator/glslang_tab.cpp
src/compiler/translator/glslang_tab.h
# Generated by FXC
src/libGLESv2/renderer/d3d/d3d9/shaders/compiled/*.h
src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/*.h
src/libANGLE/renderer/d3d/d3d9/shaders/compiled/*.h
src/libANGLE/renderer/d3d/d3d11/shaders/compiled/*.h

View File

@ -16,17 +16,22 @@ Autodesk, Inc.
BlackBerry Limited
Cable Television Laboratories, Inc.
Cloud Party, Inc.
Imagination Technologies Ltd.
Intel Corporation
Mozilla Corporation
Turbulenz
Klarälvdalens Datakonsult AB
Microsoft Corporation
Microsoft Open Technologies, Inc.
NVIDIA Corporation
Opera Software ASA
The Qt Company Ltd.
Jacek Caban
Mark Callow
Ginn Chen
Tibor den Ouden
Régis Fénéon
James Hauxwell
Sam Hocevar
Pierre Leveille
@ -35,3 +40,4 @@ Boying Lu
Aitor Moreno
Yuri O'Donnell
Josh Soref
Maks Naumov

View File

@ -1,4 +1,4 @@
# This is the official list of people who can contribute
# This is the official list of people who can contribute
# (and who have contributed) code to the ANGLE project
# repository.
# The AUTHORS file lists the copyright holders; this file
@ -40,6 +40,7 @@ Google Inc.
thestig@chromium.org
Justin Schuh
Scott Graham
Corentin Wallez
Adobe Systems Inc.
Alexandru Chiculita
@ -55,6 +56,9 @@ Cloud Party, Inc.
The Qt Company Ltd.
Andrew Knight
Imagination Technologies Ltd.
Gregoire Payen de La Garanderie
Intel Corporation
Jin Yang
Andy Chen
@ -80,10 +84,21 @@ Mark Banner (standard8mbp)
David Kilzer
Jacek Caban
Tibor den Ouden
Régis Fénéon
Microsoft Corporation
Cooper Partin
Austin Kinross
Minmin Gong
Microsoft Open Technologies, Inc.
Cooper Partin
Austin Kinross
Cooper Partin
Austin Kinross
NVIDIA Corporation
Olli Etuaho
Arun Patole
Qingqing Deng
Opera Software ASA
Daniel Bratell

View File

@ -33,12 +33,12 @@ extern "C" {
** used to make the header, and the header can be found at
** http://www.opengl.org/registry/
**
** Khronos $Revision: 27018 $ on $Date: 2014-06-10 08:06:12 -0700 (Tue, 10 Jun 2014) $
** Khronos $Revision: 29318 $ on $Date: 2015-01-02 03:16:10 -0800 (Fri, 02 Jan 2015) $
*/
#include <EGL/eglplatform.h>
/* Generated on date 20140610 */
/* Generated on date 20150102 */
/* Generated C header for:
* API: egl
@ -240,6 +240,7 @@ EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext (void);
typedef void *EGLSync;
typedef intptr_t EGLAttrib;
typedef khronos_utime_nanoseconds_t EGLTime;
typedef void *EGLImage;
#define EGL_CONTEXT_MAJOR_VERSION 0x3098
#define EGL_CONTEXT_MINOR_VERSION 0x30FB
#define EGL_CONTEXT_OPENGL_PROFILE_MASK 0x30FD
@ -281,10 +282,14 @@ typedef khronos_utime_nanoseconds_t EGLTime;
#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x30B6
#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x30B7
#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x30B8
#define EGL_IMAGE_PRESERVED 0x30D2
#define EGL_NO_IMAGE ((EGLImage)0)
EGLAPI EGLSync EGLAPIENTRY eglCreateSync (EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list);
EGLAPI EGLBoolean EGLAPIENTRY eglDestroySync (EGLDisplay dpy, EGLSync sync);
EGLAPI EGLint EGLAPIENTRY eglClientWaitSync (EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout);
EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttrib (EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value);
EGLAPI EGLImage EGLAPIENTRY eglCreateImage (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLAttrib *attrib_list);
EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImage (EGLDisplay dpy, EGLImage image);
EGLAPI EGLDisplay EGLAPIENTRY eglGetPlatformDisplay (EGLenum platform, void *native_display, const EGLAttrib *attrib_list);
EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformWindowSurface (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLAttrib *attrib_list);
EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformPixmapSurface (EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLAttrib *attrib_list);

View File

@ -440,24 +440,28 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurfacePointerANGLE (EGLDisplay dpy, EGLSu
#ifndef EGL_ANGLE_platform_angle
#define EGL_ANGLE_platform_angle 1
#define EGL_PLATFORM_ANGLE_ANGLE 0x3201
#define EGL_PLATFORM_ANGLE_TYPE_ANGLE 0x3202
#define EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE 0x3203
#define EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE 0x3204
#define EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE 0x3205
#define EGL_PLATFORM_ANGLE_ANGLE 0x3202
#define EGL_PLATFORM_ANGLE_TYPE_ANGLE 0x3203
#define EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE 0x3204
#define EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE 0x3205
#define EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE 0x3206
#endif /* EGL_ANGLE_platform_angle */
#ifndef EGL_ANGLE_platform_angle_d3d
#define EGL_ANGLE_platform_angle_d3d 1
#define EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE 0x3206
#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3207
#define EGL_PLATFORM_ANGLE_USE_WARP_ANGLE 0x3208
#define EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE 0x3207
#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3208
#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE 0x3209
#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE 0x320A
#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE 0x320B
#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE 0x320C
#define EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE 0x320F
#endif /* EGL_ANGLE_platform_angle_d3d */
#ifndef EGL_ANGLE_platform_angle_opengl
#define EGL_ANGLE_platform_angle_opengl 1
#define EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE 0x3209
#define EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE 0x320A
#define EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE 0x320D
#define EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE 0x320E
#endif /* EGL_ANGLE_platform_angle_opengl */
#ifndef EGL_ARM_pixmap_multisample_discard

View File

@ -73,15 +73,14 @@
#endif
#include <windows.h>
typedef HDC EGLNativeDisplayType;
typedef HBITMAP EGLNativePixmapType;
#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PC_APP || WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) /* Windows Store */
#include <inspectable.h>
typedef IInspectable* EGLNativeDisplayType;
typedef IInspectable* EGLNativeWindowType;
#else
typedef HDC EGLNativeDisplayType;
#if !defined(WINAPI_FAMILY) || (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP) /* Windows Desktop */
typedef HWND EGLNativeWindowType;
#else /* Windows Store */
#include <inspectable.h>
typedef IInspectable* EGLNativeWindowType;
#endif
#elif defined(__WINSCW__) || defined(__SYMBIAN32__) /* Symbian */
@ -110,6 +109,14 @@ typedef Display *EGLNativeDisplayType;
typedef Pixmap EGLNativePixmapType;
typedef Window EGLNativeWindowType;
#elif defined(__GNUC__) && ( defined(__APPLE_CPP__) || defined(__APPLE_CC__) || defined(__MACOS_CLASSIC__) )
// TODO(jmadill): native implementation for OSX
typedef void *EGLNativeDisplayType;
typedef void *EGLNativePixmapType;
typedef void *EGLNativeWindowType;
#else
#error "Platform not recognized"
#endif

View File

@ -3,8 +3,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
#ifndef _COMPILER_INTERFACE_INCLUDED_
#define _COMPILER_INTERFACE_INCLUDED_
#ifndef GLSLANG_SHADERLANG_H_
#define GLSLANG_SHADERLANG_H_
#if defined(COMPONENT_BUILD) && !defined(ANGLE_TRANSLATOR_STATIC)
#if defined(_WIN32) || defined(_WIN64)
@ -48,7 +48,7 @@ typedef unsigned int GLenum;
// Version number for shader translation API.
// It is incremented every time the API changes.
#define ANGLE_SH_VERSION 132
#define ANGLE_SH_VERSION 134
typedef enum {
SH_GLES2_SPEC = 0x8B40,
@ -81,11 +81,16 @@ typedef enum {
} ShShaderSpec;
typedef enum {
SH_ESSL_OUTPUT = 0x8B45,
SH_GLSL_OUTPUT = 0x8B46,
SH_HLSL_OUTPUT = 0x8B47,
SH_HLSL9_OUTPUT = 0x8B47,
SH_HLSL11_OUTPUT = 0x8B48
SH_ESSL_OUTPUT = 0x8B45,
// SH_GLSL_OUTPUT is deprecated. This is to not break the build.
SH_GLSL_OUTPUT = 0x8B46,
SH_GLSL_COMPATIBILITY_OUTPUT = 0x8B46,
SH_GLSL_CORE_OUTPUT = 0x8B47,
// HLSL output only supported in some configurations.
SH_HLSL_OUTPUT = 0x8B48,
SH_HLSL9_OUTPUT = 0x8B48,
SH_HLSL11_OUTPUT = 0x8B49
} ShShaderOutput;
// Compile options.
@ -223,6 +228,10 @@ typedef struct
int EXT_draw_buffers;
int EXT_frag_depth;
int EXT_shader_texture_lod;
int WEBGL_debug_shader_precision;
int EXT_shader_framebuffer_fetch;
int NV_shader_framebuffer_fetch;
int ARM_shader_framebuffer_fetch;
// Set to 1 to enable replacing GL_EXT_draw_buffers #extension directives
// with GL_NV_draw_buffers in ESSL output. This flag can be used to emulate
@ -290,7 +299,8 @@ COMPILER_EXPORT const std::string &ShGetBuiltInResourcesString(const ShHandle ha
// spec: Specifies the language spec the compiler must conform to -
// SH_GLES2_SPEC or SH_WEBGL_SPEC.
// output: Specifies the output code type - SH_ESSL_OUTPUT, SH_GLSL_OUTPUT,
// SH_HLSL9_OUTPUT or SH_HLSL11_OUTPUT.
// SH_HLSL9_OUTPUT or SH_HLSL11_OUTPUT. Note: HLSL output is only
// supported in some configurations.
// resources: Specifies the built-in resources.
COMPILER_EXPORT ShHandle ShConstructCompiler(
sh::GLenum type,
@ -408,4 +418,4 @@ COMPILER_EXPORT bool ShGetUniformRegister(const ShHandle handle,
const std::string &uniformName,
unsigned int *indexOut);
#endif // _COMPILER_INTERFACE_INCLUDED_
#endif // GLSLANG_SHADERLANG_H_

View File

@ -7,8 +7,8 @@
// Types to represent GL variables (varyings, uniforms, etc)
//
#ifndef _COMPILER_INTERFACE_VARIABLES_
#define _COMPILER_INTERFACE_VARIABLES_
#ifndef GLSLANG_SHADERVARS_H_
#define GLSLANG_SHADERVARS_H_
#include <string>
#include <vector>
@ -28,6 +28,9 @@ enum InterpolationType
INTERPOLATION_FLAT
};
// Validate link & SSO consistency of interpolation qualifiers
COMPILER_EXPORT bool InterpolationTypesMatch(InterpolationType a, InterpolationType b);
// Uniform block layout qualifier, see section 4.3.8.3 of the ESSL 3.00.4 spec
enum BlockLayoutType
{
@ -182,4 +185,4 @@ struct COMPILER_EXPORT InterfaceBlock
}
#endif // _COMPILER_INTERFACE_VARIABLES_
#endif // GLSLANG_SHADERVARS_H_

2
src/3rdparty/angle/include/KHR/khrplatform.h vendored Normal file → Executable file
View File

@ -97,7 +97,7 @@
*-------------------------------------------------------------------------
* This precedes the return type of the function in the function prototype.
*/
#if defined(_WIN32) && !defined(__SCITECH_SNAP__) && !defined(QT_OPENGL_ES_2_ANGLE_STATIC)
#if defined(_WIN32) && !defined(__SCITECH_SNAP__)
# define KHRONOS_APICALL __declspec(dllimport)
#elif defined (__SYMBIAN32__)
# define KHRONOS_APICALL IMPORT_C

View File

@ -7,8 +7,8 @@
// Includes all necessary GL headers and definitions for ANGLE.
//
#ifndef ANGLE_GL_H_
#define ANGLE_GL_H_
#ifndef ANGLEGL_H_
#define ANGLEGL_H_
#include "GLES2/gl2.h"
#include "GLES2/gl2ext.h"
@ -20,4 +20,4 @@
#define GL_SAMPLER_2D_RECT_ARB 0x8B63
#endif
#endif // ANGLE_GL_H_
#endif // ANGLEGL_H_

28
src/3rdparty/angle/include/export.h vendored Normal file
View File

@ -0,0 +1,28 @@
//
// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// export.h : Defines ANGLE_EXPORT, a macro for exporting functions from the DLL
#ifndef LIBGLESV2_EXPORT_H_
#define LIBGLESV2_EXPORT_H_
#if defined(_WIN32)
# if defined(LIBGLESV2_IMPLEMENTATION) || defined(LIBANGLE_IMPLEMENTATION)
# define ANGLE_EXPORT __declspec(dllexport)
# else
# define ANGLE_EXPORT __declspec(dllimport)
# endif
#elif defined(__GNUC__)
# if defined(LIBGLESV2_IMPLEMENTATION) || defined(LIBANGLE_IMPLEMENTATION)
# define ANGLE_EXPORT __attribute__((visibility ("default")))
# else
# define ANGLE_EXPORT
# endif
#else
# define ANGLE_EXPORT
#endif
#endif // LIBGLESV2_EXPORT_H_

View File

@ -0,0 +1,112 @@
//
// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Platform.h: The public interface ANGLE exposes to the API layer, for
// doing platform-specific tasks like gathering data, or for tracing.
#ifndef ANGLE_PLATFORM_H
#define ANGLE_PLATFORM_H
#include <stdint.h>
#include "../export.h"
namespace angle
{
class Platform
{
public:
// Tracing --------
typedef uint64_t TraceEventHandle;
// Add a trace event to the platform tracing system. Depending on the actual
// enabled state, this event may be recorded or dropped.
// - phase specifies the type of event:
// - BEGIN ('B'): Marks the beginning of a scoped event.
// - END ('E'): Marks the end of a scoped event.
// - COMPLETE ('X'): Marks the beginning of a scoped event, but doesn't
// need a matching END event. Instead, at the end of the scope,
// updateTraceEventDuration() must be called with the TraceEventHandle
// returned from addTraceEvent().
// - INSTANT ('I'): Standalone, instantaneous event.
// - START ('S'): Marks the beginning of an asynchronous event (the end
// event can occur in a different scope or thread). The id parameter is
// used to match START/FINISH pairs.
// - FINISH ('F'): Marks the end of an asynchronous event.
// - COUNTER ('C'): Used to trace integer quantities that change over
// time. The argument values are expected to be of type int.
// - METADATA ('M'): Reserved for internal use.
// - categoryEnabled is the pointer returned by getTraceCategoryEnabledFlag.
// - name is the name of the event. Also used to match BEGIN/END and
// START/FINISH pairs.
// - id optionally allows events of the same name to be distinguished from
// each other. For example, to trace the consutruction and destruction of
// objects, specify the pointer as the id parameter.
// - numArgs specifies the number of elements in argNames, argTypes, and
// argValues.
// - argNames is the array of argument names. Use long-lived literal strings
// or specify the COPY flag.
// - argTypes is the array of argument types:
// - BOOL (1): bool
// - UINT (2): unsigned long long
// - INT (3): long long
// - DOUBLE (4): double
// - POINTER (5): void*
// - STRING (6): char* (long-lived null-terminated char* string)
// - COPY_STRING (7): char* (temporary null-terminated char* string)
// - CONVERTABLE (8): WebConvertableToTraceFormat
// - argValues is the array of argument values. Each value is the unsigned
// long long member of a union of all supported types.
// - flags can be 0 or one or more of the following, ORed together:
// - COPY (0x1): treat all strings (name, argNames and argValues of type
// string) as temporary so that they will be copied by addTraceEvent.
// - HAS_ID (0x2): use the id argument to uniquely identify the event for
// matching with other events of the same name.
// - MANGLE_ID (0x4): specify this flag if the id parameter is the value
// of a pointer.
virtual TraceEventHandle addTraceEvent(char phase,
const unsigned char *categoryEnabledFlag,
const char *name,
unsigned long long id,
double timestamp,
int numArgs,
const char **argNames,
const unsigned char *argTypes,
const unsigned long long *argValues,
unsigned char flags)
{
return 0;
}
// Set the duration field of a COMPLETE trace event.
virtual void updateTraceEventDuration(const unsigned char* categoryEnabledFlag, const char* name, TraceEventHandle) { }
// Callbacks for reporting histogram data.
// CustomCounts histogram has exponential bucket sizes, so that min=1, max=1000000, bucketCount=50 would do.
virtual void histogramCustomCounts(const char* name, int sample, int min, int max, int bucketCount) { }
// Enumeration histogram buckets are linear, boundaryValue should be larger than any possible sample value.
virtual void histogramEnumeration(const char* name, int sample, int boundaryValue) { }
// Unlike enumeration histograms, sparse histograms only allocate memory for non-empty buckets.
virtual void histogramSparse(const char* name, int sample) { }
protected:
virtual ~Platform() { }
};
}
typedef void(*ANGLEPlatformInitializeFunc)(angle::Platform*);
ANGLE_EXPORT void ANGLEPlatformInitialize(angle::Platform*);
typedef void (*ANGLEPlatformShutdownFunc)();
ANGLE_EXPORT void ANGLEPlatformShutdown();
typedef angle::Platform *(*ANGLEPlatformCurrentFunc)();
ANGLE_EXPORT angle::Platform *ANGLEPlatformCurrent();
#endif // ANGLE_PLATFORM_H

View File

@ -1,12 +0,0 @@
//
// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// commit.h:
// This is a default commit hash header, when git is not available.
//
#define ANGLE_COMMIT_HASH "30d6c255d238"
#define ANGLE_COMMIT_HASH_SIZE 12
#define ANGLE_COMMIT_DATE "2014-11-13 17:37:03 +0000"

View File

@ -4,12 +4,13 @@
// found in the LICENSE file.
//
#include "libGLESv2/renderer/d3d/MemoryBuffer.h"
#include "common/debug.h"
#include "common/MemoryBuffer.h"
#include <algorithm>
#include <cstdlib>
#include "common/debug.h"
namespace rx
{
@ -32,26 +33,31 @@ bool MemoryBuffer::resize(size_t size)
free(mData);
mData = NULL;
mSize = 0;
return true;
}
else
if (size == mSize)
{
uint8_t *newMemory = reinterpret_cast<uint8_t*>(malloc(sizeof(uint8_t) * size));
if (newMemory == NULL)
{
return false;
}
if (mData)
{
// Copy the intersection of the old data and the new data
std::copy(mData, mData + std::min(mSize, size), newMemory);
free(mData);
}
mData = newMemory;
mSize = size;
return true;
}
// Only reallocate if the size has changed.
uint8_t *newMemory = reinterpret_cast<uint8_t*>(malloc(sizeof(uint8_t) * size));
if (newMemory == NULL)
{
return false;
}
if (mData)
{
// Copy the intersection of the old data and the new data
std::copy(mData, mData + std::min(mSize, size), newMemory);
free(mData);
}
mData = newMemory;
mSize = size;
return true;
}

View File

@ -4,16 +4,18 @@
// found in the LICENSE file.
//
#ifndef LIBGLESV2_RENDERER_D3D_MEMORYBUFFER_H_
#define LIBGLESV2_RENDERER_D3D_MEMORYBUFFER_H_
#ifndef COMMON_MEMORYBUFFER_H_
#define COMMON_MEMORYBUFFER_H_
#include "common/angleutils.h"
#include <cstddef>
#include <cstdint>
#include <stdint.h>
namespace rx
{
class MemoryBuffer
class MemoryBuffer : angle::NonCopyable
{
public:
MemoryBuffer();
@ -33,4 +35,4 @@ class MemoryBuffer
}
#endif // LIBGLESV2_RENDERER_D3D_MEMORYBUFFER_H
#endif // COMMON_MEMORYBUFFER_H_

View File

@ -0,0 +1,61 @@
//
// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Optional.h:
// Represents a type that may be invalid, similar to std::optional.
//
#ifndef COMMON_OPTIONAL_H_
#define COMMON_OPTIONAL_H_
template <class T>
struct Optional
{
Optional()
: mValid(false),
mValue(T())
{}
explicit Optional(const T &valueIn)
: mValid(true),
mValue(valueIn)
{}
Optional(const Optional &other)
: mValid(other.mValid),
mValue(other.mValue)
{}
Optional &operator=(const Optional &other)
{
this->mValid = other.mValid;
this->mValue = other.mValue;
return *this;
}
static Optional None()
{
return Optional();
}
bool valid() const { return mValid; }
const T &value() const { return mValue; }
bool operator==(const Optional &other) const
{
return ((mValid == other.mValid) && (!mValid || (mValue == other.mValue)));
}
bool operator!=(const Optional &other) const
{
return !(*this == other);
}
private:
bool mValid;
T mValue;
};
#endif // COMMON_OPTIONAL_H_

View File

@ -1,95 +0,0 @@
//
// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// RefCountObject.h: Defines the gl::RefCountObject base class that provides
// lifecycle support for GL objects using the traditional BindObject scheme, but
// that need to be reference counted for correct cross-context deletion.
// (Concretely, textures, buffers and renderbuffers.)
#ifndef COMMON_REFCOUNTOBJECT_H_
#define COMMON_REFCOUNTOBJECT_H_
#include "common/debug.h"
#include "angle_gl.h"
#include <cstddef>
class RefCountObject
{
public:
explicit RefCountObject(GLuint id);
virtual ~RefCountObject();
virtual void addRef() const;
virtual void release() const;
GLuint id() const { return mId; }
private:
GLuint mId;
mutable std::size_t mRefCount;
};
class RefCountObjectBindingPointer
{
protected:
RefCountObjectBindingPointer() : mObject(NULL) { }
~RefCountObjectBindingPointer() { ASSERT(mObject == NULL); } // Objects have to be released before the resource manager is destroyed, so they must be explicitly cleaned up.
void set(RefCountObject *newObject);
RefCountObject *get() const { return mObject; }
public:
GLuint id() const { return (mObject != NULL) ? mObject->id() : 0; }
bool operator!() const { return (get() == NULL); }
private:
RefCountObject *mObject;
};
template <class ObjectType>
class BindingPointer : public RefCountObjectBindingPointer
{
public:
void set(ObjectType *newObject) { RefCountObjectBindingPointer::set(newObject); }
ObjectType *get() const { return static_cast<ObjectType*>(RefCountObjectBindingPointer::get()); }
ObjectType *operator->() const { return get(); }
};
template <class ObjectType>
class OffsetBindingPointer : public RefCountObjectBindingPointer
{
public:
OffsetBindingPointer() : mOffset(0), mSize(0) { }
void set(ObjectType *newObject)
{
RefCountObjectBindingPointer::set(newObject);
mOffset = 0;
mSize = 0;
}
void set(ObjectType *newObject, GLintptr offset, GLsizeiptr size)
{
RefCountObjectBindingPointer::set(newObject);
mOffset = offset;
mSize = size;
}
GLintptr getOffset() const { return mOffset; }
GLsizeiptr getSize() const { return mSize; }
ObjectType *get() const { return static_cast<ObjectType*>(RefCountObjectBindingPointer::get()); }
ObjectType *operator->() const { return get(); }
private:
GLintptr mOffset;
GLsizeiptr mSize;
};
#endif // COMMON_REFCOUNTOBJECT_H_

View File

@ -5,7 +5,8 @@
//
#include "common/angleutils.h"
#include "debug.h"
#include "common/debug.h"
#include <stdio.h>
#include <vector>

View File

@ -11,19 +11,31 @@
#include "common/platform.h"
#include <stddef.h>
#include <limits.h>
#include <climits>
#include <cstdarg>
#include <cstddef>
#include <string>
#include <set>
#include <sstream>
#include <cstdarg>
#include <vector>
// A macro to disallow the copy constructor and operator= functions
// This must be used in the private: declarations for a class
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName&); \
void operator=(const TypeName&)
// A helper class to disallow copy and assignment operators
namespace angle
{
class NonCopyable
{
#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
public:
NonCopyable() = default;
~NonCopyable() = default;
protected:
NonCopyable(const NonCopyable&) = delete;
void operator=(const NonCopyable&) = delete;
#endif
};
}
template <typename T, size_t N>
inline size_t ArraySize(T(&)[N])
@ -150,13 +162,12 @@ std::string FormatString(const char *fmt, ...);
#define snprintf _snprintf
#endif
#define VENDOR_ID_AMD 0x1002
#define VENDOR_ID_INTEL 0x8086
#define VENDOR_ID_NVIDIA 0x10DE
#define GL_BGRA4_ANGLEX 0x6ABC
#define GL_BGR5_A1_ANGLEX 0x6ABD
#define GL_INT_64_ANGLEX 0x6ABE
#define GL_STRUCT_ANGLEX 0x6ABF
// Hidden enum for the NULL D3D device type.
#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE 0x6AC0
#endif // COMMON_ANGLEUTILS_H_

View File

@ -17,172 +17,9 @@
namespace gl
{
#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
// Wraps the D3D9/D3D11 debug annotation functions.
class DebugAnnotationWrapper
namespace
{
public:
DebugAnnotationWrapper() { };
virtual ~DebugAnnotationWrapper() { };
virtual void beginEvent(const std::wstring &eventName) = 0;
virtual void endEvent() = 0;
virtual void setMarker(const std::wstring &markerName) = 0;
virtual bool getStatus() = 0;
};
#if defined(ANGLE_ENABLE_D3D9)
class D3D9DebugAnnotationWrapper : public DebugAnnotationWrapper
{
public:
void beginEvent(const std::wstring &eventName)
{
D3DPERF_BeginEvent(0, eventName.c_str());
}
void endEvent()
{
D3DPERF_EndEvent();
}
void setMarker(const std::wstring &markerName)
{
D3DPERF_SetMarker(0, markerName.c_str());
}
bool getStatus()
{
return !!D3DPERF_GetStatus();
}
};
#endif // ANGLE_ENABLE_D3D9
#if defined(ANGLE_ENABLE_D3D11)
class D3D11DebugAnnotationWrapper : public DebugAnnotationWrapper
{
public:
D3D11DebugAnnotationWrapper()
: mInitialized(false),
mD3d11Module(NULL),
mUserDefinedAnnotation(NULL)
{
// D3D11 devices can't be created during DllMain.
// We defer device creation until the object is actually used.
}
~D3D11DebugAnnotationWrapper()
{
if (mInitialized)
{
SafeRelease(mUserDefinedAnnotation);
FreeLibrary(mD3d11Module);
}
}
virtual void beginEvent(const std::wstring &eventName)
{
initializeDevice();
mUserDefinedAnnotation->BeginEvent(eventName.c_str());
}
virtual void endEvent()
{
initializeDevice();
mUserDefinedAnnotation->EndEvent();
}
virtual void setMarker(const std::wstring &markerName)
{
initializeDevice();
mUserDefinedAnnotation->SetMarker(markerName.c_str());
}
virtual bool getStatus()
{
// ID3DUserDefinedAnnotation::GetStatus doesn't work with the Graphics Diagnostics tools in Visual Studio 2013.
#if defined(_DEBUG) && defined(ANGLE_ENABLE_WINDOWS_STORE)
// In the Windows Store, we can use IDXGraphicsAnalysis. The call to GetDebugInterface1 only succeeds if the app is under capture.
// This should only be called in DEBUG mode.
// If an app links against DXGIGetDebugInterface1 in release mode then it will fail Windows Store ingestion checks.
IDXGraphicsAnalysis* graphicsAnalysis;
DXGIGetDebugInterface1(0, IID_PPV_ARGS(&graphicsAnalysis));
bool underCapture = (graphicsAnalysis != NULL);
SafeRelease(graphicsAnalysis);
return underCapture;
#endif
// Otherwise, we have to return true here.
return true;
}
protected:
void initializeDevice()
{
if (!mInitialized)
{
#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
mD3d11Module = LoadLibrary(TEXT("d3d11.dll"));
ASSERT(mD3d11Module);
PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice");
ASSERT(D3D11CreateDevice != NULL);
#endif // !ANGLE_ENABLE_WINDOWS_STORE
ID3D11Device* device = NULL;
ID3D11DeviceContext* context = NULL;
HRESULT hr = E_FAIL;
// Create a D3D_DRIVER_TYPE_NULL device, which is much cheaper than other types of device.
hr = D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_NULL, NULL, 0, NULL, 0, D3D11_SDK_VERSION, &device, NULL, &context);
ASSERT(SUCCEEDED(hr));
hr = context->QueryInterface(__uuidof(mUserDefinedAnnotation), reinterpret_cast<void**>(&mUserDefinedAnnotation));
ASSERT(SUCCEEDED(hr) && mUserDefinedAnnotation != NULL);
SafeRelease(device);
SafeRelease(context);
mInitialized = true;
}
}
bool mInitialized;
HMODULE mD3d11Module;
ID3DUserDefinedAnnotation* mUserDefinedAnnotation;
};
#endif // ANGLE_ENABLE_D3D11
static DebugAnnotationWrapper* g_DebugAnnotationWrapper = NULL;
void InitializeDebugAnnotations()
{
#if defined(ANGLE_ENABLE_D3D9)
g_DebugAnnotationWrapper = new D3D9DebugAnnotationWrapper();
#elif defined(ANGLE_ENABLE_D3D11)
// If the project uses D3D9 then we can use the D3D9 debug annotations, even with the D3D11 renderer.
// However, if D3D9 is unavailable (e.g. in Windows Store), then we use D3D11 debug annotations.
// The D3D11 debug annotations are methods on ID3DUserDefinedAnnotation, which is implemented by the DeviceContext.
// This doesn't have to be the same DeviceContext that the renderer uses, though.
g_DebugAnnotationWrapper = new D3D11DebugAnnotationWrapper();
#endif
}
void UninitializeDebugAnnotations()
{
if (g_DebugAnnotationWrapper != NULL)
{
SafeDelete(g_DebugAnnotationWrapper);
}
}
#endif // ANGLE_ENABLE_DEBUG_ANNOTATIONS
enum DebugTraceOutputType
{
DebugTraceOutputTypeNone,
@ -190,29 +27,44 @@ enum DebugTraceOutputType
DebugTraceOutputTypeBeginEvent
};
static void output(bool traceInDebugOnly, DebugTraceOutputType outputType, const char *format, va_list vararg)
{
#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
static std::vector<char> buffer(512);
DebugAnnotator *g_debugAnnotator = nullptr;
if (perfActive())
void output(bool traceInDebugOnly, MessageType messageType, DebugTraceOutputType outputType,
const char *format, va_list vararg)
{
if (DebugAnnotationsActive())
{
static std::vector<char> buffer(512);
size_t len = FormatStringIntoVector(format, vararg, buffer);
std::wstring formattedWideMessage(buffer.begin(), buffer.begin() + len);
ASSERT(g_debugAnnotator != nullptr);
switch (outputType)
{
case DebugTraceOutputTypeNone:
break;
case DebugTraceOutputTypeBeginEvent:
g_DebugAnnotationWrapper->beginEvent(formattedWideMessage);
break;
case DebugTraceOutputTypeSetMarker:
g_DebugAnnotationWrapper->setMarker(formattedWideMessage);
break;
case DebugTraceOutputTypeNone:
break;
case DebugTraceOutputTypeBeginEvent:
g_debugAnnotator->beginEvent(formattedWideMessage);
break;
case DebugTraceOutputTypeSetMarker:
g_debugAnnotator->setMarker(formattedWideMessage);
break;
}
}
#endif // ANGLE_ENABLE_DEBUG_ANNOTATIONS
std::string formattedMessage;
UNUSED_TRACE_VARIABLE(formattedMessage);
#if !defined(NDEBUG) && defined(_MSC_VER)
if (messageType == MESSAGE_ERR)
{
if (formattedMessage.empty())
{
formattedMessage = FormatString(format, vararg);
}
OutputDebugStringA(formattedMessage.c_str());
}
#endif
#if defined(ANGLE_ENABLE_DEBUG_TRACE)
#if defined(NDEBUG)
@ -221,7 +73,10 @@ static void output(bool traceInDebugOnly, DebugTraceOutputType outputType, const
return;
}
#endif // NDEBUG
std::string formattedMessage = FormatString(format, vararg);
if (formattedMessage.empty())
{
formattedMessage = FormatString(format, vararg);
}
static std::ofstream file(TRACE_OUTPUT_FILE, std::ofstream::app);
if (file)
@ -237,53 +92,57 @@ static void output(bool traceInDebugOnly, DebugTraceOutputType outputType, const
#endif // ANGLE_ENABLE_DEBUG_TRACE
}
void trace(bool traceInDebugOnly, const char *format, ...)
{
va_list vararg;
va_start(vararg, format);
#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
output(traceInDebugOnly, DebugTraceOutputTypeSetMarker, format, vararg);
#else
output(traceInDebugOnly, DebugTraceOutputTypeNone, format, vararg);
#endif
va_end(vararg);
}
} // namespace
bool perfActive()
bool DebugAnnotationsActive()
{
#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
static bool active = g_DebugAnnotationWrapper->getStatus();
return active;
return g_debugAnnotator != nullptr && g_debugAnnotator->getStatus();
#else
return false;
#endif
}
void InitializeDebugAnnotations(DebugAnnotator *debugAnnotator)
{
UninitializeDebugAnnotations();
g_debugAnnotator = debugAnnotator;
}
void UninitializeDebugAnnotations()
{
// Pointer is not managed.
g_debugAnnotator = nullptr;
}
void trace(bool traceInDebugOnly, MessageType messageType, const char *format, ...)
{
va_list vararg;
va_start(vararg, format);
output(traceInDebugOnly, messageType, DebugTraceOutputTypeSetMarker, format, vararg);
va_end(vararg);
}
ScopedPerfEventHelper::ScopedPerfEventHelper(const char* format, ...)
{
#if !defined(ANGLE_ENABLE_DEBUG_TRACE)
if (!perfActive())
if (!DebugAnnotationsActive())
{
return;
}
#endif // !ANGLE_ENABLE_DEBUG_TRACE
va_list vararg;
va_start(vararg, format);
#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
output(true, DebugTraceOutputTypeBeginEvent, format, vararg);
#else
output(true, DebugTraceOutputTypeNone, format, vararg);
#endif // ANGLE_ENABLE_DEBUG_ANNOTATIONS
output(true, MESSAGE_EVENT, DebugTraceOutputTypeBeginEvent, format, vararg);
va_end(vararg);
}
ScopedPerfEventHelper::~ScopedPerfEventHelper()
{
#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
if (perfActive())
if (DebugAnnotationsActive())
{
g_DebugAnnotationWrapper->endEvent();
g_debugAnnotator->endEvent();
}
#endif
}
}

View File

@ -9,8 +9,9 @@
#ifndef COMMON_DEBUG_H_
#define COMMON_DEBUG_H_
#include <stdio.h>
#include <assert.h>
#include <stdio.h>
#include <string>
#include "common/angleutils.h"
@ -20,50 +21,71 @@
namespace gl
{
// Outputs text to the debugging log, or the debugging window
void trace(bool traceInDebugOnly, const char *format, ...);
// Returns whether D3DPERF is active.
bool perfActive();
enum MessageType
{
MESSAGE_TRACE,
MESSAGE_FIXME,
MESSAGE_ERR,
MESSAGE_EVENT,
};
// Pairs a D3D begin event with an end event.
class ScopedPerfEventHelper
{
public:
ScopedPerfEventHelper(const char* format, ...);
~ScopedPerfEventHelper();
// Outputs text to the debugging log, or the debugging window
void trace(bool traceInDebugOnly, MessageType messageType, const char *format, ...);
private:
DISALLOW_COPY_AND_ASSIGN(ScopedPerfEventHelper);
};
// Pairs a D3D begin event with an end event.
class ScopedPerfEventHelper : angle::NonCopyable
{
public:
ScopedPerfEventHelper(const char* format, ...);
~ScopedPerfEventHelper();
};
// Wraps the D3D9/D3D11 debug annotation functions.
class DebugAnnotator : angle::NonCopyable
{
public:
DebugAnnotator() { };
virtual ~DebugAnnotator() { };
virtual void beginEvent(const std::wstring &eventName) = 0;
virtual void endEvent() = 0;
virtual void setMarker(const std::wstring &markerName) = 0;
virtual bool getStatus() = 0;
};
void InitializeDebugAnnotations(DebugAnnotator *debugAnnotator);
void UninitializeDebugAnnotations();
bool DebugAnnotationsActive();
void InitializeDebugAnnotations();
void UninitializeDebugAnnotations();
}
// A macro to output a trace of a function call and its arguments to the debugging log
#if defined(ANGLE_ENABLE_DEBUG_TRACE) || defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
#define TRACE(message, ...) gl::trace(true, "trace: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
#define ANGLE_TRACE_ENABLED
#endif
// A macro to output a trace of a function call and its arguments to the debugging log
#if defined(ANGLE_TRACE_ENABLED)
#define TRACE(message, ...) gl::trace(true, gl::MESSAGE_TRACE, "trace: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
#else
#define TRACE(message, ...) (void(0))
#endif
// A macro to output a function call and its arguments to the debugging log, to denote an item in need of fixing.
#if defined(ANGLE_ENABLE_DEBUG_TRACE) || defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
#define FIXME(message, ...) gl::trace(false, "fixme: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
#if defined(ANGLE_TRACE_ENABLED)
#define FIXME(message, ...) gl::trace(false, gl::MESSAGE_FIXME, "fixme: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
#else
#define FIXME(message, ...) (void(0))
#endif
// A macro to output a function call and its arguments to the debugging log, in case of error.
#if defined(ANGLE_ENABLE_DEBUG_TRACE) || defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
#define ERR(message, ...) gl::trace(false, "err: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
#if defined(ANGLE_TRACE_ENABLED)
#define ERR(message, ...) gl::trace(false, gl::MESSAGE_ERR, "err: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
#else
#define ERR(message, ...) (void(0))
#endif
// A macro to log a performance event around a scope.
#if defined(ANGLE_ENABLE_DEBUG_TRACE) || defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
#if defined(ANGLE_TRACE_ENABLED)
#if defined(_MSC_VER)
#define EVENT(message, ...) gl::ScopedPerfEventHelper scopedPerfEventHelper ## __LINE__("%s" message "\n", __FUNCTION__, __VA_ARGS__);
#else
@ -73,6 +95,10 @@ namespace gl
#define EVENT(message, ...) (void(0))
#endif
#if defined(ANGLE_TRACE_ENABLED)
#undef ANGLE_TRACE_ENABLED
#endif
// A macro asserting a condition and outputting failures to the debug log
#if !defined(NDEBUG)
#define ASSERT(expression) do { \
@ -130,14 +156,4 @@ namespace gl
#define HAS_DYNAMIC_TYPE(type, obj) true
#endif
// A macro functioning as a compile-time assert to validate constant conditions
#if (defined(_MSC_VER) && _MSC_VER >= 1600) || (defined(__GNUC__) && (__GNUC__ > 4 || __GNUC_MINOR__ >= 3))
#define META_ASSERT_MSG(condition, msg) static_assert(condition, msg)
#else
#define META_ASSERT_CONCAT(a, b) a ## b
#define META_ASSERT_CONCAT2(a, b) META_ASSERT_CONCAT(a, b)
#define META_ASSERT_MSG(condition, msg) typedef int META_ASSERT_CONCAT2(COMPILE_TIME_ASSERT_, __LINE__)[static_cast<bool>(condition)?1:-1]
#endif
#define META_ASSERT(condition) META_ASSERT_MSG(condition, "compile time assertion failed.")
#endif // COMMON_DEBUG_H_

View File

@ -0,0 +1,38 @@
// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "common/event_tracer.h"
namespace gl
{
GetCategoryEnabledFlagFunc g_getCategoryEnabledFlag;
AddTraceEventFunc g_addTraceEvent;
} // namespace gl
namespace gl
{
const unsigned char* TraceGetTraceCategoryEnabledFlag(const char* name)
{
if (g_getCategoryEnabledFlag)
{
return g_getCategoryEnabledFlag(name);
}
static unsigned char disabled = 0;
return &disabled;
}
void TraceAddTraceEvent(char phase, const unsigned char* categoryGroupEnabled, const char* name, unsigned long long id,
int numArgs, const char** argNames, const unsigned char* argTypes,
const unsigned long long* argValues, unsigned char flags)
{
if (g_addTraceEvent)
{
g_addTraceEvent(phase, categoryGroupEnabled, name, id, numArgs, argNames, argTypes, argValues, flags);
}
}
} // namespace gl

View File

@ -0,0 +1,34 @@
// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMMON_EVENT_TRACER_H_
#define COMMON_EVENT_TRACER_H_
#include "common/platform.h"
extern "C" {
typedef const unsigned char* (*GetCategoryEnabledFlagFunc)(const char* name);
typedef void (*AddTraceEventFunc)(char phase, const unsigned char* categoryGroupEnabled, const char* name,
unsigned long long id, int numArgs, const char** argNames,
const unsigned char* argTypes, const unsigned long long* argValues,
unsigned char flags);
}
namespace gl
{
extern GetCategoryEnabledFlagFunc g_getCategoryEnabledFlag;
extern AddTraceEventFunc g_addTraceEvent;
const unsigned char* TraceGetTraceCategoryEnabledFlag(const char* name);
void TraceAddTraceEvent(char phase, const unsigned char* categoryGroupEnabled, const char* name, unsigned long long id,
int numArgs, const char** argNames, const unsigned char* argTypes,
const unsigned long long* argValues, unsigned char flags);
}
#endif // COMMON_EVENT_TRACER_H_

View File

@ -6,8 +6,8 @@
// mathutil.h: Math and bit manipulation functions.
#ifndef LIBGLESV2_MATHUTIL_H_
#define LIBGLESV2_MATHUTIL_H_
#ifndef COMMON_MATHUTIL_H_
#define COMMON_MATHUTIL_H_
#include "common/debug.h"
#include "common/platform.h"
@ -15,6 +15,7 @@
#include <limits>
#include <algorithm>
#include <string.h>
#include <stdlib.h>
namespace gl
{
@ -118,6 +119,9 @@ inline bool supportsSSE2()
return supports;
}
#if defined(__GNUC__)
supports = __builtin_cpu_supports("sse2");
#else
int info[4];
__cpuid(info, 0);
@ -127,6 +131,7 @@ inline bool supportsSSE2()
supports = (info[3] >> 26) & 1;
}
#endif
checked = true;
@ -353,7 +358,7 @@ inline float float11ToFloat32(unsigned short fp11)
}
else // The value is zero
{
exponent = -112;
exponent = static_cast<unsigned short>(-112);
}
return bitCast<float>(((exponent + 112) << 23) | (mantissa << 17));
@ -392,7 +397,7 @@ inline float float10ToFloat32(unsigned short fp11)
}
else // The value is zero
{
exponent = -112;
exponent = static_cast<unsigned short>(-112);
}
return bitCast<float>(((exponent + 112) << 23) | (mantissa << 18));
@ -402,7 +407,7 @@ inline float float10ToFloat32(unsigned short fp11)
template <typename T>
inline float normalizedToFloat(T input)
{
META_ASSERT(std::numeric_limits<T>::is_integer);
static_assert(std::numeric_limits<T>::is_integer, "T must be an integer.");
const float inverseMax = 1.0f / std::numeric_limits<T>::max();
return input * inverseMax;
@ -411,8 +416,8 @@ inline float normalizedToFloat(T input)
template <unsigned int inputBitCount, typename T>
inline float normalizedToFloat(T input)
{
META_ASSERT(std::numeric_limits<T>::is_integer);
META_ASSERT(inputBitCount < (sizeof(T) * 8));
static_assert(std::numeric_limits<T>::is_integer, "T must be an integer.");
static_assert(inputBitCount < (sizeof(T) * 8), "T must have more bits than inputBitCount.");
const float inverseMax = 1.0f / ((1 << inputBitCount) - 1);
return input * inverseMax;
@ -427,14 +432,15 @@ inline T floatToNormalized(float input)
template <unsigned int outputBitCount, typename T>
inline T floatToNormalized(float input)
{
META_ASSERT(outputBitCount < (sizeof(T) * 8));
static_assert(outputBitCount < (sizeof(T) * 8), "T must have more bits than outputBitCount.");
return ((1 << outputBitCount) - 1) * input + 0.5f;
}
template <unsigned int inputBitCount, unsigned int inputBitStart, typename T>
inline T getShiftedData(T input)
{
META_ASSERT(inputBitCount + inputBitStart <= (sizeof(T) * 8));
static_assert(inputBitCount + inputBitStart <= (sizeof(T) * 8),
"T must have at least as many bits as inputBitCount + inputBitStart.");
const T mask = (1 << inputBitCount) - 1;
return (input >> inputBitStart) & mask;
}
@ -442,7 +448,8 @@ inline T getShiftedData(T input)
template <unsigned int inputBitCount, unsigned int inputBitStart, typename T>
inline T shiftData(T input)
{
META_ASSERT(inputBitCount + inputBitStart <= (sizeof(T) * 8));
static_assert(inputBitCount + inputBitStart <= (sizeof(T) * 8),
"T must have at least as many bits as inputBitCount + inputBitStart.");
const T mask = (1 << inputBitCount) - 1;
return (input & mask) << inputBitStart;
}
@ -503,6 +510,7 @@ inline unsigned int averageFloat10(unsigned int a, unsigned int b)
namespace rx
{
// Represents intervals of the type [a, b)
template <typename T>
struct Range
{
@ -513,6 +521,18 @@ struct Range
T end;
T length() const { return end - start; }
bool intersects(Range<T> other)
{
if (start <= other.start)
{
return other.start < end;
}
else
{
return start < other.end;
}
}
};
typedef Range<int> RangeI;
@ -533,14 +553,14 @@ inline unsigned int UnsignedCeilDivide(unsigned int value, unsigned int divisor)
template <class T>
inline bool IsUnsignedAdditionSafe(T lhs, T rhs)
{
META_ASSERT(!std::numeric_limits<T>::is_signed);
static_assert(!std::numeric_limits<T>::is_signed, "T must be unsigned.");
return (rhs <= std::numeric_limits<T>::max() - lhs);
}
template <class T>
inline bool IsUnsignedMultiplicationSafe(T lhs, T rhs)
{
META_ASSERT(!std::numeric_limits<T>::is_signed);
static_assert(!std::numeric_limits<T>::is_signed, "T must be unsigned.");
return (lhs == T(0) || rhs == T(0) || (rhs <= std::numeric_limits<T>::max() / lhs));
}
@ -550,6 +570,21 @@ inline bool IsIntegerCastSafe(BigIntT bigValue)
return (static_cast<BigIntT>(static_cast<SmallIntT>(bigValue)) == bigValue);
}
#if defined(_MSC_VER)
#define ANGLE_ROTL(x,y) _rotl(x,y)
#else
inline uint32_t RotL(uint32_t x, int8_t r)
{
return (x << r) | (x >> (32 - r));
}
#endif // LIBGLESV2_MATHUTIL_H_
#define ANGLE_ROTL(x,y) RotL(x,y)
#endif // namespace rx
}
#endif // COMMON_MATHUTIL_H_

View File

@ -14,12 +14,12 @@
#elif defined(__APPLE__)
# define ANGLE_PLATFORM_APPLE 1
# define ANGLE_PLATFORM_POSIX 1
#elif defined(__linux__)
# define ANGLE_PLATFORM_LINUX 1
# define ANGLE_PLATFORM_POSIX 1
#elif defined(ANDROID)
# define ANGLE_PLATFORM_ANDROID 1
# define ANGLE_PLATFORM_POSIX 1
#elif defined(__linux__) || defined(EMSCRIPTEN)
# define ANGLE_PLATFORM_LINUX 1
# define ANGLE_PLATFORM_POSIX 1
#elif defined(__FreeBSD__) || \
defined(__OpenBSD__) || \
defined(__NetBSD__) || \
@ -34,9 +34,6 @@
#endif
#ifdef ANGLE_PLATFORM_WINDOWS
# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PC_APP || WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
# define ANGLE_ENABLE_WINDOWS_STORE 1
# endif
# ifndef STRICT
# define STRICT 1
# endif
@ -50,24 +47,32 @@
# include <windows.h>
# include <intrin.h>
# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP)
# define ANGLE_ENABLE_WINDOWS_STORE 1
# endif
# if defined(ANGLE_ENABLE_D3D9)
# include <d3d9.h>
# include <dxgi.h>
# if !defined(COMPILER_IMPLEMENTATION)
# if !defined(ANGLE_TRANSLATOR_IMPLEMENTATION)
# include <d3dcompiler.h>
# endif
# endif
# if defined(ANGLE_ENABLE_D3D11)
# include <d3d10_1.h>
# include <d3d10.h>
# include <d3d11.h>
# include <dxgi.h>
# if defined(_MSC_VER) && (_MSC_VER >= 1700)
# if defined(__MINGW32__) && !defined(__d3d11sdklayers_h__)
# define ANGLE_MINGW32_COMPAT
# endif
# if defined(_MSC_VER) && _MSC_VER >= 1800
# define ANGLE_ENABLE_D3D11_1
# endif
# if defined(ANGLE_ENABLE_D3D11_1)
# include <d3d11_1.h>
# include <dxgi1_2.h>
# endif
# if !defined(COMPILER_IMPLEMENTATION)
# if !defined(ANGLE_TRANSLATOR_IMPLEMENTATION)
# include <d3dcompiler.h>
# endif
# endif
@ -75,88 +80,24 @@
# if defined(ANGLE_ENABLE_WINDOWS_STORE)
# include <dxgi1_3.h>
# if defined(_DEBUG)
# if (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP)
# if WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP
# include <DXProgrammableCapture.h>
# endif
# include <dxgidebug.h>
# endif
# endif
# if defined(__MINGW32__) // Missing defines on MinGW
typedef enum D3D11_MAP_FLAG
{
D3D11_MAP_FLAG_DO_NOT_WAIT = 0x100000L
} D3D11_MAP_FLAG;
typedef struct D3D11_QUERY_DATA_SO_STATISTICS
{
UINT64 NumPrimitivesWritten;
UINT64 PrimitivesStorageNeeded;
} D3D11_QUERY_DATA_SO_STATISTICS;
typedef HRESULT (WINAPI *PFN_D3D11_CREATE_DEVICE)(
IDXGIAdapter *, D3D_DRIVER_TYPE, HMODULE, UINT, CONST D3D_FEATURE_LEVEL *,
UINT FeatureLevels, UINT, ID3D11Device **, D3D_FEATURE_LEVEL *, ID3D11DeviceContext **);
#define D3D11_MESSAGE_CATEGORY UINT
#define D3D11_MESSAGE_SEVERITY UINT
#define D3D11_MESSAGE_ID UINT
struct D3D11_MESSAGE;
typedef struct D3D11_INFO_QUEUE_FILTER_DESC
{
UINT NumCategories;
D3D11_MESSAGE_CATEGORY *pCategoryList;
UINT NumSeverities;
D3D11_MESSAGE_SEVERITY *pSeverityList;
UINT NumIDs;
D3D11_MESSAGE_ID *pIDList;
} D3D11_INFO_QUEUE_FILTER_DESC;
typedef struct D3D11_INFO_QUEUE_FILTER
{
D3D11_INFO_QUEUE_FILTER_DESC AllowList;
D3D11_INFO_QUEUE_FILTER_DESC DenyList;
} D3D11_INFO_QUEUE_FILTER;
static const IID IID_ID3D11InfoQueue = { 0x6543dbb6, 0x1b48, 0x42f5, 0xab, 0x82, 0xe9, 0x7e, 0xc7, 0x43, 0x26, 0xf6 };
MIDL_INTERFACE("6543dbb6-1b48-42f5-ab82-e97ec74326f6") ID3D11InfoQueue : public IUnknown
{
public:
virtual HRESULT __stdcall SetMessageCountLimit(UINT64) = 0;
virtual void __stdcall ClearStoredMessages() = 0;
virtual HRESULT __stdcall GetMessage(UINT64, D3D11_MESSAGE *, SIZE_T *) = 0;
virtual UINT64 __stdcall GetNumMessagesAllowedByStorageFilter() = 0;
virtual UINT64 __stdcall GetNumMessagesDeniedByStorageFilter() = 0;
virtual UINT64 __stdcall GetNumStoredMessages() = 0;
virtual UINT64 __stdcall GetNumStoredMessagesAllowedByRetrievalFilter() = 0;
virtual UINT64 __stdcall GetNumMessagesDiscardedByMessageCountLimit() = 0;
virtual UINT64 __stdcall GetMessageCountLimit() = 0;
virtual HRESULT __stdcall AddStorageFilterEntries(D3D11_INFO_QUEUE_FILTER *) = 0;
virtual HRESULT __stdcall GetStorageFilter(D3D11_INFO_QUEUE_FILTER *, SIZE_T *) = 0;
virtual void __stdcall ClearStorageFilter() = 0;
virtual HRESULT __stdcall PushEmptyStorageFilter() = 0;
virtual HRESULT __stdcall PushCopyOfStorageFilter() = 0;
virtual HRESULT __stdcall PushStorageFilter(D3D11_INFO_QUEUE_FILTER *) = 0;
virtual void __stdcall PopStorageFilter() = 0;
virtual UINT __stdcall GetStorageFilterStackSize() = 0;
virtual HRESULT __stdcall AddRetrievalFilterEntries(D3D11_INFO_QUEUE_FILTER *) = 0;
virtual HRESULT __stdcall GetRetrievalFilter(D3D11_INFO_QUEUE_FILTER *, SIZE_T *) = 0;
virtual void __stdcall ClearRetrievalFilter() = 0;
virtual HRESULT __stdcall PushEmptyRetrievalFilter() = 0;
virtual HRESULT __stdcall PushCopyOfRetrievalFilter() = 0;
virtual HRESULT __stdcall PushRetrievalFilter(D3D11_INFO_QUEUE_FILTER *) = 0;
virtual void __stdcall PopRetrievalFilter() = 0;
virtual UINT __stdcall GetRetrievalFilterStackSize() = 0;
virtual HRESULT __stdcall AddMessage(D3D11_MESSAGE_CATEGORY, D3D11_MESSAGE_SEVERITY, D3D11_MESSAGE_ID, LPCSTR) = 0;
virtual HRESULT __stdcall AddApplicationMessage(D3D11_MESSAGE_SEVERITY, LPCSTR) = 0;
virtual HRESULT __stdcall SetBreakOnCategory(D3D11_MESSAGE_CATEGORY, BOOL) = 0;
virtual HRESULT __stdcall SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY, BOOL) = 0;
virtual HRESULT __stdcall SetBreakOnID(D3D11_MESSAGE_ID, BOOL) = 0;
virtual BOOL __stdcall GetBreakOnCategory(D3D11_MESSAGE_CATEGORY) = 0;
virtual BOOL __stdcall GetBreakOnSeverity(D3D11_MESSAGE_SEVERITY) = 0;
virtual BOOL __stdcall GetBreakOnID(D3D11_MESSAGE_ID) = 0;
virtual void __stdcall SetMuteDebugOutput(BOOL) = 0;
virtual BOOL __stdcall GetMuteDebugOutput() = 0;
};
#endif // __MINGW32__
# if defined(_MSC_VER) && (_MSC_VER <= 1600)
# define final
# define override
# endif
# undef near
# undef far
#endif
#if !defined(_M_ARM) && !defined(ANGLE_PLATFORM_ANDROID)
# define ANGLE_USE_SSE
#endif
#endif // COMMON_PLATFORM_H_

View File

@ -15,7 +15,9 @@
// TLS does not exist for Windows Store and needs to be emulated
# ifdef ANGLE_ENABLE_WINDOWS_STORE
# define TLS_OUT_OF_INDEXES -1
# ifndef TLS_OUT_OF_INDEXES
# define TLS_OUT_OF_INDEXES static_cast<DWORD>(0xFFFFFFFF)
# endif
# ifndef CREATE_SUSPENDED
# define CREATE_SUSPENDED 0x00000004
# endif

View File

@ -254,7 +254,7 @@ int VariableColumnCount(GLenum type)
return 0;
}
bool IsSampler(GLenum type)
bool IsSamplerType(GLenum type)
{
switch (type)
{
@ -343,9 +343,27 @@ int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsig
return -1;
}
bool IsCubemapTextureTarget(GLenum target)
static_assert(GL_TEXTURE_CUBE_MAP_NEGATIVE_X - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 1, "Unexpected GL cube map enum value.");
static_assert(GL_TEXTURE_CUBE_MAP_POSITIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 2, "Unexpected GL cube map enum value.");
static_assert(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 3, "Unexpected GL cube map enum value.");
static_assert(GL_TEXTURE_CUBE_MAP_POSITIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 4, "Unexpected GL cube map enum value.");
static_assert(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 5, "Unexpected GL cube map enum value.");
bool IsCubeMapTextureTarget(GLenum target)
{
return (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);
return (target >= FirstCubeMapTextureTarget && target <= LastCubeMapTextureTarget);
}
size_t CubeMapTextureTargetToLayerIndex(GLenum target)
{
ASSERT(IsCubeMapTextureTarget(target));
return target - static_cast<size_t>(FirstCubeMapTextureTarget);
}
GLenum LayerIndexToCubeMapTextureTarget(size_t index)
{
ASSERT(index <= (LastCubeMapTextureTarget - FirstCubeMapTextureTarget));
return FirstCubeMapTextureTarget + static_cast<GLenum>(index);
}
bool IsTriangleMode(GLenum drawMode)
@ -486,10 +504,15 @@ void writeFile(const char* path, const void* content, size_t size)
}
#endif // !ANGLE_ENABLE_WINDOWS_STORE
#if defined(ANGLE_ENABLE_WINDOWS_STORE) && _MSC_FULL_VER < 180031101
#if defined (ANGLE_PLATFORM_WINDOWS)
void Sleep(unsigned long dwMilliseconds)
// Causes the thread to relinquish the remainder of its time slice to any
// other thread that is ready to run.If there are no other threads ready
// to run, the function returns immediately, and the thread continues execution.
void ScheduleYield()
{
#if defined(ANGLE_ENABLE_WINDOWS_STORE)
// This implementation of Sleep exists because it is not available prior to Update 4.
static HANDLE singletonEvent = nullptr;
HANDLE sleepEvent = singletonEvent;
if (!sleepEvent)
@ -510,7 +533,10 @@ void Sleep(unsigned long dwMilliseconds)
}
// Emulate sleep by waiting with timeout on an event that is never signalled.
WaitForSingleObjectEx(sleepEvent, dwMilliseconds, false);
WaitForSingleObjectEx(sleepEvent, 0, false);
#else
Sleep(0);
#endif
}
#endif // ANGLE_ENABLE_WINDOWS_STORE
#endif

View File

@ -6,8 +6,8 @@
// utilities.h: Conversion functions and other utility routines.
#ifndef LIBGLESV2_UTILITIES_H
#define LIBGLESV2_UTILITIES_H
#ifndef COMMON_UTILITIES_H_
#define COMMON_UTILITIES_H_
#include "angle_gl.h"
#include <string>
@ -24,7 +24,7 @@ size_t VariableExternalSize(GLenum type);
GLenum VariableBoolVectorType(GLenum type);
int VariableRowCount(GLenum type);
int VariableColumnCount(GLenum type);
bool IsSampler(GLenum type);
bool IsSamplerType(GLenum type);
bool IsMatrixType(GLenum type);
GLenum TransposeMatrixType(GLenum type);
int VariableRegisterCount(GLenum type);
@ -34,7 +34,11 @@ int VariableSortOrder(GLenum type);
int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize);
bool IsCubemapTextureTarget(GLenum target);
static const GLenum FirstCubeMapTextureTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
static const GLenum LastCubeMapTextureTarget = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
bool IsCubeMapTextureTarget(GLenum target);
size_t CubeMapTextureTargetToLayerIndex(GLenum target);
GLenum LayerIndexToCubeMapTextureTarget(size_t index);
bool IsTriangleMode(GLenum drawMode);
@ -51,8 +55,8 @@ std::string getTempPath();
void writeFile(const char* path, const void* data, size_t size);
#endif
#if defined(ANGLE_ENABLE_WINDOWS_STORE) && _MSC_FULL_VER < 180031101
void Sleep(_In_ unsigned long dwMilliseconds);
#if defined (ANGLE_PLATFORM_WINDOWS)
void ScheduleYield();
#endif
#endif // LIBGLESV2_UTILITIES_H
#endif // COMMON_UTILITIES_H_

View File

@ -1,4 +1,13 @@
#include "../commit.h"
//
// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
#ifndef COMMON_VERSION_H_
#define COMMON_VERSION_H_
#include "id/commit.h"
#define ANGLE_MAJOR_VERSION 2
#define ANGLE_MINOR_VERSION 1
@ -10,3 +19,5 @@
ANGLE_MACRO_STRINGIFY(ANGLE_MAJOR_VERSION) "." \
ANGLE_MACRO_STRINGIFY(ANGLE_MINOR_VERSION) "." \
ANGLE_COMMIT_HASH
#endif // COMMON_VERSION_H_

View File

@ -1,39 +0,0 @@
//
// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// CoreWindowNativeWindow.h: NativeWindow for managing ICoreWindow native window types.
#ifndef COMMON_WINRT_COREWINDOWNATIVEWINDOW_H_
#define COMMON_WINRT_COREWINDOWNATIVEWINDOW_H_
#include "common/winrt/InspectableNativeWindow.h"
#include <memory>
#include <windows.graphics.display.h>
namespace rx
{
class CoreWindowNativeWindow : public InspectableNativeWindow, public std::enable_shared_from_this<CoreWindowNativeWindow>
{
public:
~CoreWindowNativeWindow();
bool initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet);
bool registerForSizeChangeEvents();
void unregisterForSizeChangeEvents();
HRESULT createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain);
private:
HRESULT onSizeChanged(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *);
ComPtr<ABI::Windows::UI::Core::ICoreWindow> mCoreWindow;
ComPtr<ABI::Windows::Graphics::Display::IDisplayInformation> mDisplayInformation;
ComPtr<IMap<HSTRING, IInspectable*>> mPropertyMap;
};
}
#endif // COMMON_WINRT_COREWINDOWNATIVEWINDOW_H_

View File

@ -4,8 +4,8 @@
// found in the LICENSE file.
//
#ifndef COMPILER_PREPROCESSOR_DIAGNOSTICS_H_
#define COMPILER_PREPROCESSOR_DIAGNOSTICS_H_
#ifndef COMPILER_PREPROCESSOR_DIAGNOSTICSBASE_H_
#define COMPILER_PREPROCESSOR_DIAGNOSTICSBASE_H_
#include <string>
@ -84,4 +84,5 @@ class Diagnostics
};
} // namespace pp
#endif // COMPILER_PREPROCESSOR_DIAGNOSTICS_H_
#endif // COMPILER_PREPROCESSOR_DIAGNOSTICSBASE_H_

View File

@ -4,8 +4,8 @@
// found in the LICENSE file.
//
#ifndef COMPILER_PREPROCESSOR_DIRECTIVE_HANDLER_H_
#define COMPILER_PREPROCESSOR_DIRECTIVE_HANDLER_H_
#ifndef COMPILER_PREPROCESSOR_DIRECTIVEHANDLERBASE_H_
#define COMPILER_PREPROCESSOR_DIRECTIVEHANDLERBASE_H_
#include <string>
@ -41,4 +41,5 @@ class DirectiveHandler
};
} // namespace pp
#endif // COMPILER_PREPROCESSOR_DIRECTIVE_HANDLER_H_
#endif // COMPILER_PREPROCESSOR_DIRECTIVEHANDLERBASE_H_

View File

@ -4,8 +4,8 @@
// found in the LICENSE file.
//
#ifndef COMPILER_PREPROCESSOR_DIRECTIVE_PARSER_H_
#define COMPILER_PREPROCESSOR_DIRECTIVE_PARSER_H_
#ifndef COMPILER_PREPROCESSOR_DIRECTIVEPARSER_H_
#define COMPILER_PREPROCESSOR_DIRECTIVEPARSER_H_
#include "Lexer.h"
#include "Macro.h"
@ -78,5 +78,5 @@ class DirectiveParser : public Lexer
};
} // namespace pp
#endif // COMPILER_PREPROCESSOR_DIRECTIVE_PARSER_H_
#endif // COMPILER_PREPROCESSOR_DIRECTIVEPARSER_H_

View File

@ -4,8 +4,8 @@
// found in the LICENSE file.
//
#ifndef COMPILER_PREPROCESSOR_EXPRESSION_PARSER_H_
#define COMPILER_PREPROCESSOR_EXPRESSION_PARSER_H_
#ifndef COMPILER_PREPROCESSOR_EXPRESSIONPARSER_H_
#define COMPILER_PREPROCESSOR_EXPRESSIONPARSER_H_
#include "pp_utils.h"
@ -31,4 +31,5 @@ class ExpressionParser
};
} // namespace pp
#endif // COMPILER_PREPROCESSOR_EXPRESSION_PARSER_H_
#endif // COMPILER_PREPROCESSOR_EXPRESSIONPARSER_H_

View File

@ -28,7 +28,7 @@ WHICH GENERATES THE GLSL ES preprocessor expression parser.
#pragma GCC diagnostic ignored "-Wuninitialized"
#endif
#elif defined(_MSC_VER)
#pragma warning(disable: 4065 4701)
#pragma warning(disable: 4065 4701 4702)
#endif
#include "ExpressionParser.h"
@ -69,7 +69,7 @@ struct Context
%}
%pure-parser
%name-prefix="pp"
%name-prefix "pp"
%parse-param {Context *context}
%lex-param {Context *context}

View File

@ -58,5 +58,5 @@ class Input
};
} // namespace pp
#endif // COMPILER_PREPROCESSOR_INPUT_H_
#endif // COMPILER_PREPROCESSOR_INPUT_H_

View File

@ -21,5 +21,5 @@ class Lexer
};
} // namespace pp
#endif // COMPILER_PREPROCESSOR_LEXER_H_
#endif // COMPILER_PREPROCESSOR_LEXER_H_

View File

@ -46,4 +46,5 @@ struct Macro
typedef std::map<std::string, Macro> MacroSet;
} // namespace pp
#endif // COMPILER_PREPROCESSOR_MACRO_H_

View File

@ -4,8 +4,8 @@
// found in the LICENSE file.
//
#ifndef COMPILER_PREPROCESSOR_MACRO_EXPANDER_H_
#define COMPILER_PREPROCESSOR_MACRO_EXPANDER_H_
#ifndef COMPILER_PREPROCESSOR_MACROEXPANDER_H_
#define COMPILER_PREPROCESSOR_MACROEXPANDER_H_
#include <cassert>
#include <memory>
@ -85,5 +85,5 @@ class MacroExpander : public Lexer
};
} // namespace pp
#endif // COMPILER_PREPROCESSOR_MACRO_EXPANDER_H_
#endif // COMPILER_PREPROCESSOR_MACROEXPANDER_H_

View File

@ -50,5 +50,5 @@ class Preprocessor
};
} // namespace pp
#endif // COMPILER_PREPROCESSOR_PREPROCESSOR_H_
#endif // COMPILER_PREPROCESSOR_PREPROCESSOR_H_

View File

@ -4,8 +4,8 @@
// found in the LICENSE file.
//
#ifndef COMPILER_PREPROCESSOR_SOURCE_LOCATION_H_
#define COMPILER_PREPROCESSOR_SOURCE_LOCATION_H_
#ifndef COMPILER_PREPROCESSOR_SOURCELOCATION_H_
#define COMPILER_PREPROCESSOR_SOURCELOCATION_H_
namespace pp
{
@ -43,4 +43,5 @@ inline bool operator!=(const SourceLocation &lhs, const SourceLocation &rhs)
}
} // namespace pp
#endif // COMPILER_PREPROCESSOR_SOURCE_LOCATION_H_
#endif // COMPILER_PREPROCESSOR_SOURCELOCATION_H_

View File

@ -116,4 +116,5 @@ inline bool operator!=(const Token &lhs, const Token &rhs)
extern std::ostream &operator<<(std::ostream &out, const Token &token);
} // namepsace pp
#endif // COMPILER_PREPROCESSOR_TOKEN_H_

View File

@ -55,5 +55,5 @@ class Tokenizer : public Lexer
};
} // namespace pp
#endif // COMPILER_PREPROCESSOR_TOKENIZER_H_
#endif // COMPILER_PREPROCESSOR_TOKENIZER_H_

View File

@ -267,7 +267,9 @@ FRACTIONAL_CONSTANT ({DIGIT}*"."{DIGIT}+)|({DIGIT}+".")
namespace pp {
Tokenizer::Tokenizer(Diagnostics *diagnostics) : mHandle(0)
Tokenizer::Tokenizer(Diagnostics *diagnostics)
: mHandle(0),
mMaxTokenSize(256)
{
mContext.diagnostics = diagnostics;
}

View File

@ -6,8 +6,8 @@
// numeric_lex.h: Functions to extract numeric values from string.
#ifndef COMPILER_PREPROCESSOR_NUMERIC_LEX_H_
#define COMPILER_PREPROCESSOR_NUMERIC_LEX_H_
#ifndef COMPILER_PREPROCESSOR_NUMERICLEX_H_
#define COMPILER_PREPROCESSOR_NUMERICLEX_H_
#include <sstream>
@ -58,4 +58,5 @@ bool numeric_lex_float(const std::string &str, FloatType *value)
}
} // namespace pp.
#endif // COMPILER_PREPROCESSOR_NUMERIC_LEX_H_
#endif // COMPILER_PREPROCESSOR_NUMERICLEX_H_

View File

@ -4,10 +4,10 @@
// found in the LICENSE file.
//
#ifndef _BASICTYPES_INCLUDED_
#define _BASICTYPES_INCLUDED_
#ifndef COMPILER_TRANSLATOR_BASETYPES_H_
#define COMPILER_TRANSLATOR_BASETYPES_H_
#include <assert.h>
#include "compiler/translator/compilerdebug.h"
//
// Precision qualifiers
@ -42,7 +42,15 @@ enum TBasicType
EbtInt,
EbtUInt,
EbtBool,
EbtGVec4, // non type: represents vec4, ivec4 and uvec4
EbtGVec4, // non type: represents vec4, ivec4, and uvec4
EbtGenType, // non type: represents float, vec2, vec3, and vec4
EbtGenIType, // non type: represents int, ivec2, ivec3, and ivec4
EbtGenUType, // non type: represents uint, uvec2, uvec3, and uvec4
EbtGenBType, // non type: represents bool, bvec2, bvec3, and bvec4
EbtVec, // non type: represents vec2, vec3, and vec4
EbtIVec, // non type: represents ivec2, ivec3, and ivec4
EbtUVec, // non type: represents uvec2, uvec3, and uvec4
EbtBVec, // non type: represents bvec2, bvec3, and bvec4
EbtGuardSamplerBegin, // non type: see implementation of IsSampler()
EbtSampler2D,
EbtSampler3D,
@ -62,10 +70,10 @@ enum TBasicType
EbtSamplerCubeShadow,
EbtSampler2DArrayShadow,
EbtGuardSamplerEnd, // non type: see implementation of IsSampler()
EbtGSampler2D, // non type: represents sampler2D, isampler2D and usampler2D
EbtGSampler3D, // non type: represents sampler3D, isampler3D and usampler3D
EbtGSamplerCube, // non type: represents samplerCube, isamplerCube and usamplerCube
EbtGSampler2DArray, // non type: represents sampler2DArray, isampler2DArray and usampler2DArray
EbtGSampler2D, // non type: represents sampler2D, isampler2D, and usampler2D
EbtGSampler3D, // non type: represents sampler3D, isampler3D, and usampler3D
EbtGSamplerCube, // non type: represents samplerCube, isamplerCube, and usamplerCube
EbtGSampler2DArray, // non type: represents sampler2DArray, isampler2DArray, and usampler2DArray
EbtStruct,
EbtInterfaceBlock,
EbtAddress, // should be deprecated??
@ -258,6 +266,11 @@ inline bool IsShadowSampler(TBasicType type)
return false;
}
inline bool IsInteger(TBasicType type)
{
return type == EbtInt || type == EbtUInt;
}
inline bool SupportsPrecision(TBasicType type)
{
return type == EbtFloat || type == EbtInt || type == EbtUInt || IsSampler(type);
@ -293,6 +306,9 @@ enum TQualifier
EvqInOut,
EvqConstReadOnly,
// built-ins read by vertex shader
EvqInstanceID,
// built-ins written by vertex shader
EvqPosition,
EvqPointSize,
@ -307,6 +323,10 @@ enum TQualifier
EvqFragData,
EvqFragDepth,
// built-ins written by the shader_framebuffer_fetch extension(s)
EvqLastFragColor,
EvqLastFragData,
// GLSL ES 3.0 vertex output and fragment input
EvqSmooth, // Incomplete qualifier, smooth is the default
EvqFlat, // Incomplete qualifier
@ -383,6 +403,7 @@ inline const char* getQualifierString(TQualifier q)
case EvqIn: return "in"; break;
case EvqOut: return "out"; break;
case EvqInOut: return "inout"; break;
case EvqInstanceID: return "InstanceID"; break;
case EvqPosition: return "Position"; break;
case EvqPointSize: return "PointSize"; break;
case EvqFragCoord: return "FragCoord"; break;
@ -396,7 +417,9 @@ inline const char* getQualifierString(TQualifier q)
case EvqSmoothIn: return "smooth in"; break;
case EvqCentroidIn: return "centroid in"; break;
case EvqFlatIn: return "flat in"; break;
default: return "unknown qualifier";
case EvqLastFragColor: return "LastFragColor"; break;
case EvqLastFragData: return "LastFragData"; break;
default: UNREACHABLE(); return "unknown qualifier";
}
}
@ -407,7 +430,7 @@ inline const char* getMatrixPackingString(TLayoutMatrixPacking mpq)
case EmpUnspecified: return "mp_unspecified";
case EmpRowMajor: return "row_major";
case EmpColumnMajor: return "column_major";
default: return "unknown matrix packing";
default: UNREACHABLE(); return "unknown matrix packing";
}
}
@ -419,7 +442,7 @@ inline const char* getBlockStorageString(TLayoutBlockStorage bsq)
case EbsShared: return "shared";
case EbsPacked: return "packed";
case EbsStd140: return "std140";
default: return "unknown block storage";
default: UNREACHABLE(); return "unknown block storage";
}
}
@ -433,8 +456,8 @@ inline const char* getInterpolationString(TQualifier q)
case EvqSmoothIn: return "smooth"; break;
case EvqCentroidIn: return "centroid"; break;
case EvqFlatIn: return "flat"; break;
default: return "unknown interpolation";
default: UNREACHABLE(); return "unknown interpolation";
}
}
#endif // _BASICTYPES_INCLUDED_
#endif // COMPILER_TRANSLATOR_BASETYPES_H_

View File

@ -8,193 +8,9 @@
#include "compiler/translator/BuiltInFunctionEmulator.h"
#include "compiler/translator/SymbolTable.h"
namespace {
// we use macros here instead of function definitions to work around more GLSL
// compiler bugs, in particular on NVIDIA hardware on Mac OSX. Macros are
// problematic because if the argument has side-effects they will be repeatedly
// evaluated. This is unlikely to show up in real shaders, but is something to
// consider.
const char* kFunctionEmulationVertexSource[] = {
"#error no emulation for cos(float)",
"#error no emulation for cos(vec2)",
"#error no emulation for cos(vec3)",
"#error no emulation for cos(vec4)",
"#define webgl_distance_emu(x, y) ((x) >= (y) ? (x) - (y) : (y) - (x))",
"#error no emulation for distance(vec2, vec2)",
"#error no emulation for distance(vec3, vec3)",
"#error no emulation for distance(vec4, vec4)",
"#define webgl_dot_emu(x, y) ((x) * (y))",
"#error no emulation for dot(vec2, vec2)",
"#error no emulation for dot(vec3, vec3)",
"#error no emulation for dot(vec4, vec4)",
"#define webgl_length_emu(x) ((x) >= 0.0 ? (x) : -(x))",
"#error no emulation for length(vec2)",
"#error no emulation for length(vec3)",
"#error no emulation for length(vec4)",
"#define webgl_normalize_emu(x) ((x) == 0.0 ? 0.0 : ((x) > 0.0 ? 1.0 : -1.0))",
"#error no emulation for normalize(vec2)",
"#error no emulation for normalize(vec3)",
"#error no emulation for normalize(vec4)",
"#define webgl_reflect_emu(I, N) ((I) - 2.0 * (N) * (I) * (N))",
"#error no emulation for reflect(vec2, vec2)",
"#error no emulation for reflect(vec3, vec3)",
"#error no emulation for reflect(vec4, vec4)"
};
const char* kFunctionEmulationFragmentSource[] = {
"webgl_emu_precision float webgl_cos_emu(webgl_emu_precision float a) { return cos(a); }",
"webgl_emu_precision vec2 webgl_cos_emu(webgl_emu_precision vec2 a) { return cos(a); }",
"webgl_emu_precision vec3 webgl_cos_emu(webgl_emu_precision vec3 a) { return cos(a); }",
"webgl_emu_precision vec4 webgl_cos_emu(webgl_emu_precision vec4 a) { return cos(a); }",
"#define webgl_distance_emu(x, y) ((x) >= (y) ? (x) - (y) : (y) - (x))",
"#error no emulation for distance(vec2, vec2)",
"#error no emulation for distance(vec3, vec3)",
"#error no emulation for distance(vec4, vec4)",
"#define webgl_dot_emu(x, y) ((x) * (y))",
"#error no emulation for dot(vec2, vec2)",
"#error no emulation for dot(vec3, vec3)",
"#error no emulation for dot(vec4, vec4)",
"#define webgl_length_emu(x) ((x) >= 0.0 ? (x) : -(x))",
"#error no emulation for length(vec2)",
"#error no emulation for length(vec3)",
"#error no emulation for length(vec4)",
"#define webgl_normalize_emu(x) ((x) == 0.0 ? 0.0 : ((x) > 0.0 ? 1.0 : -1.0))",
"#error no emulation for normalize(vec2)",
"#error no emulation for normalize(vec3)",
"#error no emulation for normalize(vec4)",
"#define webgl_reflect_emu(I, N) ((I) - 2.0 * (N) * (I) * (N))",
"#error no emulation for reflect(vec2, vec2)",
"#error no emulation for reflect(vec3, vec3)",
"#error no emulation for reflect(vec4, vec4)"
};
const bool kFunctionEmulationVertexMask[] = {
#if defined(__APPLE__)
// Work around ATI driver bugs in Mac.
false, // TFunctionCos1
false, // TFunctionCos2
false, // TFunctionCos3
false, // TFunctionCos4
true, // TFunctionDistance1_1
false, // TFunctionDistance2_2
false, // TFunctionDistance3_3
false, // TFunctionDistance4_4
true, // TFunctionDot1_1
false, // TFunctionDot2_2
false, // TFunctionDot3_3
false, // TFunctionDot4_4
true, // TFunctionLength1
false, // TFunctionLength2
false, // TFunctionLength3
false, // TFunctionLength4
true, // TFunctionNormalize1
false, // TFunctionNormalize2
false, // TFunctionNormalize3
false, // TFunctionNormalize4
true, // TFunctionReflect1_1
false, // TFunctionReflect2_2
false, // TFunctionReflect3_3
false, // TFunctionReflect4_4
#else
// Work around D3D driver bug in Win.
false, // TFunctionCos1
false, // TFunctionCos2
false, // TFunctionCos3
false, // TFunctionCos4
false, // TFunctionDistance1_1
false, // TFunctionDistance2_2
false, // TFunctionDistance3_3
false, // TFunctionDistance4_4
false, // TFunctionDot1_1
false, // TFunctionDot2_2
false, // TFunctionDot3_3
false, // TFunctionDot4_4
false, // TFunctionLength1
false, // TFunctionLength2
false, // TFunctionLength3
false, // TFunctionLength4
false, // TFunctionNormalize1
false, // TFunctionNormalize2
false, // TFunctionNormalize3
false, // TFunctionNormalize4
false, // TFunctionReflect1_1
false, // TFunctionReflect2_2
false, // TFunctionReflect3_3
false, // TFunctionReflect4_4
#endif
false // TFunctionUnknown
};
const bool kFunctionEmulationFragmentMask[] = {
#if defined(__APPLE__)
// Work around ATI driver bugs in Mac.
true, // TFunctionCos1
true, // TFunctionCos2
true, // TFunctionCos3
true, // TFunctionCos4
true, // TFunctionDistance1_1
false, // TFunctionDistance2_2
false, // TFunctionDistance3_3
false, // TFunctionDistance4_4
true, // TFunctionDot1_1
false, // TFunctionDot2_2
false, // TFunctionDot3_3
false, // TFunctionDot4_4
true, // TFunctionLength1
false, // TFunctionLength2
false, // TFunctionLength3
false, // TFunctionLength4
true, // TFunctionNormalize1
false, // TFunctionNormalize2
false, // TFunctionNormalize3
false, // TFunctionNormalize4
true, // TFunctionReflect1_1
false, // TFunctionReflect2_2
false, // TFunctionReflect3_3
false, // TFunctionReflect4_4
#else
// Work around D3D driver bug in Win.
false, // TFunctionCos1
false, // TFunctionCos2
false, // TFunctionCos3
false, // TFunctionCos4
false, // TFunctionDistance1_1
false, // TFunctionDistance2_2
false, // TFunctionDistance3_3
false, // TFunctionDistance4_4
false, // TFunctionDot1_1
false, // TFunctionDot2_2
false, // TFunctionDot3_3
false, // TFunctionDot4_4
false, // TFunctionLength1
false, // TFunctionLength2
false, // TFunctionLength3
false, // TFunctionLength4
false, // TFunctionNormalize1
false, // TFunctionNormalize2
false, // TFunctionNormalize3
false, // TFunctionNormalize4
false, // TFunctionReflect1_1
false, // TFunctionReflect2_2
false, // TFunctionReflect3_3
false, // TFunctionReflect4_4
#endif
false // TFunctionUnknown
};
class BuiltInFunctionEmulationMarker : public TIntermTraverser {
public:
class BuiltInFunctionEmulator::BuiltInFunctionEmulationMarker : public TIntermTraverser
{
public:
BuiltInFunctionEmulationMarker(BuiltInFunctionEmulator& emulator)
: mEmulator(emulator)
{
@ -238,148 +54,119 @@ public:
case EOpFaceForward:
case EOpReflect:
case EOpRefract:
case EOpOuterProduct:
case EOpMul:
break;
default:
return true;
};
const TIntermSequence& sequence = *(node->getSequence());
// Right now we only handle built-in functions with two parameters.
if (sequence.size() != 2)
bool needToEmulate = false;
// Right now we only handle built-in functions with two or three parameters.
if (sequence.size() == 2)
{
TIntermTyped* param1 = sequence[0]->getAsTyped();
TIntermTyped* param2 = sequence[1]->getAsTyped();
if (!param1 || !param2)
return true;
needToEmulate = mEmulator.SetFunctionCalled(
node->getOp(), param1->getType(), param2->getType());
}
else if (sequence.size() == 3)
{
TIntermTyped* param1 = sequence[0]->getAsTyped();
TIntermTyped* param2 = sequence[1]->getAsTyped();
TIntermTyped* param3 = sequence[2]->getAsTyped();
if (!param1 || !param2 || !param3)
return true;
needToEmulate = mEmulator.SetFunctionCalled(
node->getOp(), param1->getType(), param2->getType(), param3->getType());
}
else
{
return true;
TIntermTyped* param1 = sequence[0]->getAsTyped();
TIntermTyped* param2 = sequence[1]->getAsTyped();
if (!param1 || !param2)
return true;
bool needToEmulate = mEmulator.SetFunctionCalled(
node->getOp(), param1->getType(), param2->getType());
}
if (needToEmulate)
node->setUseEmulatedFunction();
}
return true;
}
private:
private:
BuiltInFunctionEmulator& mEmulator;
};
} // anonymous namepsace
BuiltInFunctionEmulator::BuiltInFunctionEmulator()
{}
BuiltInFunctionEmulator::BuiltInFunctionEmulator(sh::GLenum shaderType)
void BuiltInFunctionEmulator::addEmulatedFunction(
TOperator op, const TType& param,
const char* emulatedFunctionDefinition)
{
if (shaderType == GL_FRAGMENT_SHADER) {
mFunctionMask = kFunctionEmulationFragmentMask;
mFunctionSource = kFunctionEmulationFragmentSource;
} else {
mFunctionMask = kFunctionEmulationVertexMask;
mFunctionSource = kFunctionEmulationVertexSource;
mEmulatedFunctions[FunctionId(op, param)] =
std::string(emulatedFunctionDefinition);
}
void BuiltInFunctionEmulator::addEmulatedFunction(
TOperator op, const TType& param1, const TType& param2,
const char* emulatedFunctionDefinition)
{
mEmulatedFunctions[FunctionId(op, param1, param2)] =
std::string(emulatedFunctionDefinition);
}
void BuiltInFunctionEmulator::addEmulatedFunction(
TOperator op, const TType& param1, const TType& param2, const TType& param3,
const char* emulatedFunctionDefinition)
{
mEmulatedFunctions[FunctionId(op, param1, param2, param3)] =
std::string(emulatedFunctionDefinition);
}
bool BuiltInFunctionEmulator::IsOutputEmpty() const
{
return (mFunctions.size() == 0);
}
void BuiltInFunctionEmulator::OutputEmulatedFunctions(
TInfoSinkBase& out) const
{
for (size_t i = 0; i < mFunctions.size(); ++i) {
out << mEmulatedFunctions.find(mFunctions[i])->second << "\n\n";
}
}
bool BuiltInFunctionEmulator::SetFunctionCalled(
TOperator op, const TType& param)
{
TBuiltInFunction function = IdentifyFunction(op, param);
return SetFunctionCalled(function);
return SetFunctionCalled(FunctionId(op, param));
}
bool BuiltInFunctionEmulator::SetFunctionCalled(
TOperator op, const TType& param1, const TType& param2)
{
TBuiltInFunction function = IdentifyFunction(op, param1, param2);
return SetFunctionCalled(function);
return SetFunctionCalled(FunctionId(op, param1, param2));
}
bool BuiltInFunctionEmulator::SetFunctionCalled(
BuiltInFunctionEmulator::TBuiltInFunction function) {
if (function == TFunctionUnknown || mFunctionMask[function] == false)
return false;
for (size_t i = 0; i < mFunctions.size(); ++i) {
if (mFunctions[i] == function)
return true;
}
mFunctions.push_back(function);
return true;
TOperator op, const TType& param1, const TType& param2, const TType& param3)
{
return SetFunctionCalled(FunctionId(op, param1, param2, param3));
}
void BuiltInFunctionEmulator::OutputEmulatedFunctionDefinition(
TInfoSinkBase& out, bool withPrecision) const
{
if (mFunctions.size() == 0)
return;
out << "// BEGIN: Generated code for built-in function emulation\n\n";
if (withPrecision) {
out << "#if defined(GL_FRAGMENT_PRECISION_HIGH)\n"
<< "#define webgl_emu_precision highp\n"
<< "#else\n"
<< "#define webgl_emu_precision mediump\n"
<< "#endif\n\n";
} else {
out << "#define webgl_emu_precision\n\n";
bool BuiltInFunctionEmulator::SetFunctionCalled(
const FunctionId& functionId) {
if (mEmulatedFunctions.find(functionId) != mEmulatedFunctions.end())
{
for (size_t i = 0; i < mFunctions.size(); ++i) {
if (mFunctions[i] == functionId)
return true;
}
mFunctions.push_back(functionId);
return true;
}
for (size_t i = 0; i < mFunctions.size(); ++i) {
out << mFunctionSource[mFunctions[i]] << "\n\n";
}
out << "// END: Generated code for built-in function emulation\n\n";
}
BuiltInFunctionEmulator::TBuiltInFunction
BuiltInFunctionEmulator::IdentifyFunction(
TOperator op, const TType& param)
{
if (param.getNominalSize() > 4 || param.getSecondarySize() > 4)
return TFunctionUnknown;
unsigned int function = TFunctionUnknown;
switch (op) {
case EOpCos:
function = TFunctionCos1;
break;
case EOpLength:
function = TFunctionLength1;
break;
case EOpNormalize:
function = TFunctionNormalize1;
break;
default:
break;
}
if (function == TFunctionUnknown)
return TFunctionUnknown;
if (param.isVector())
function += param.getNominalSize() - 1;
return static_cast<TBuiltInFunction>(function);
}
BuiltInFunctionEmulator::TBuiltInFunction
BuiltInFunctionEmulator::IdentifyFunction(
TOperator op, const TType& param1, const TType& param2)
{
// Right now for all the emulated functions with two parameters, the two
// parameters have the same type.
if (param1.getNominalSize() != param2.getNominalSize() ||
param1.getSecondarySize() != param2.getSecondarySize() ||
param1.getNominalSize() > 4 || param1.getSecondarySize() > 4)
return TFunctionUnknown;
unsigned int function = TFunctionUnknown;
switch (op) {
case EOpDistance:
function = TFunctionDistance1_1;
break;
case EOpDot:
function = TFunctionDot1_1;
break;
case EOpReflect:
function = TFunctionReflect1_1;
break;
default:
break;
}
if (function == TFunctionUnknown)
return TFunctionUnknown;
if (param1.isVector())
function += param1.getNominalSize() - 1;
return static_cast<TBuiltInFunction>(function);
return false;
}
void BuiltInFunctionEmulator::MarkBuiltInFunctionsForEmulation(
@ -387,6 +174,9 @@ void BuiltInFunctionEmulator::MarkBuiltInFunctionsForEmulation(
{
ASSERT(root);
if (mEmulatedFunctions.empty())
return;
BuiltInFunctionEmulationMarker marker(*this);
root->traverse(&marker);
}
@ -404,3 +194,52 @@ TString BuiltInFunctionEmulator::GetEmulatedFunctionName(
return "webgl_" + name.substr(0, name.length() - 1) + "_emu(";
}
BuiltInFunctionEmulator::FunctionId::FunctionId
(TOperator op, const TType& param)
: mOp(op),
mParam1(param),
mParam2(EbtVoid),
mParam3(EbtVoid)
{
}
BuiltInFunctionEmulator::FunctionId::FunctionId
(TOperator op, const TType& param1, const TType& param2)
: mOp(op),
mParam1(param1),
mParam2(param2),
mParam3(EbtVoid)
{
}
BuiltInFunctionEmulator::FunctionId::FunctionId
(TOperator op, const TType& param1, const TType& param2, const TType& param3)
: mOp(op),
mParam1(param1),
mParam2(param2),
mParam3(param3)
{
}
bool BuiltInFunctionEmulator::FunctionId::operator==
(const BuiltInFunctionEmulator::FunctionId& other) const
{
return (mOp == other.mOp &&
mParam1 == other.mParam1 &&
mParam2 == other.mParam2 &&
mParam3 == other.mParam3);
}
bool BuiltInFunctionEmulator::FunctionId::operator<
(const BuiltInFunctionEmulator::FunctionId& other) const
{
if (mOp != other.mOp)
return mOp < other.mOp;
if (mParam1 != other.mParam1)
return mParam1 < other.mParam1;
if (mParam2 != other.mParam2)
return mParam2 < other.mParam2;
if (mParam3 != other.mParam3)
return mParam3 < other.mParam3;
return false; // all fields are equal
}

View File

@ -4,8 +4,8 @@
// found in the LICENSE file.
//
#ifndef COMPILIER_BUILT_IN_FUNCTION_EMULATOR_H_
#define COMPILIER_BUILT_IN_FUNCTION_EMULATOR_H_
#ifndef COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATOR_H_
#define COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATOR_H_
#include "compiler/translator/InfoSink.h"
#include "compiler/translator/IntermNode.h"
@ -13,23 +13,13 @@
//
// This class decides which built-in functions need to be replaced with the
// emulated ones.
// It's only a workaround for OpenGL driver bugs, and isn't needed in general.
// It can be used to work around driver bugs or implement functions that are
// not natively implemented on a specific platform.
//
class BuiltInFunctionEmulator {
public:
BuiltInFunctionEmulator(sh::GLenum shaderType);
// Records that a function is called by the shader and might needs to be
// emulated. If the function's group is not in mFunctionGroupFilter, this
// becomes an no-op.
// Returns true if the function call needs to be replaced with an emulated
// one.
bool SetFunctionCalled(TOperator op, const TType& param);
bool SetFunctionCalled(
TOperator op, const TType& param1, const TType& param2);
// Output function emulation definition. This should be before any other
// shader source.
void OutputEmulatedFunctionDefinition(TInfoSinkBase& out, bool withPrecision) const;
class BuiltInFunctionEmulator
{
public:
BuiltInFunctionEmulator();
void MarkBuiltInFunctionsForEmulation(TIntermNode* root);
@ -38,54 +28,52 @@ public:
// "name(" becomes "webgl_name_emu(".
static TString GetEmulatedFunctionName(const TString& name);
private:
//
// Built-in functions.
//
enum TBuiltInFunction {
TFunctionCos1 = 0, // float cos(float);
TFunctionCos2, // vec2 cos(vec2);
TFunctionCos3, // vec3 cos(vec3);
TFunctionCos4, // vec4 cos(vec4);
bool IsOutputEmpty() const;
TFunctionDistance1_1, // float distance(float, float);
TFunctionDistance2_2, // vec2 distance(vec2, vec2);
TFunctionDistance3_3, // vec3 distance(vec3, vec3);
TFunctionDistance4_4, // vec4 distance(vec4, vec4);
// Output function emulation definition. This should be before any other
// shader source.
void OutputEmulatedFunctions(TInfoSinkBase& out) const;
TFunctionDot1_1, // float dot(float, float);
TFunctionDot2_2, // vec2 dot(vec2, vec2);
TFunctionDot3_3, // vec3 dot(vec3, vec3);
TFunctionDot4_4, // vec4 dot(vec4, vec4);
// Add functions that need to be emulated.
void addEmulatedFunction(TOperator op, const TType& param, const char* emulatedFunctionDefinition);
void addEmulatedFunction(TOperator op, const TType& param1, const TType& param2, const char* emulatedFunctionDefinition);
void addEmulatedFunction(TOperator op, const TType& param1, const TType& param2, const TType& param3, const char* emulatedFunctionDefinition);
TFunctionLength1, // float length(float);
TFunctionLength2, // float length(vec2);
TFunctionLength3, // float length(vec3);
TFunctionLength4, // float length(vec4);
private:
class BuiltInFunctionEmulationMarker;
TFunctionNormalize1, // float normalize(float);
TFunctionNormalize2, // vec2 normalize(vec2);
TFunctionNormalize3, // vec3 normalize(vec3);
TFunctionNormalize4, // vec4 normalize(vec4);
// Records that a function is called by the shader and might need to be
// emulated. If the function is not in mEmulatedFunctions, this becomes a
// no-op. Returns true if the function call needs to be replaced with an
// emulated one.
bool SetFunctionCalled(TOperator op, const TType& param);
bool SetFunctionCalled(
TOperator op, const TType& param1, const TType& param2);
bool SetFunctionCalled(
TOperator op, const TType& param1, const TType& param2, const TType& param3);
TFunctionReflect1_1, // float reflect(float, float);
TFunctionReflect2_2, // vec2 reflect(vec2, vec2);
TFunctionReflect3_3, // vec3 reflect(vec3, vec3);
TFunctionReflect4_4, // vec4 reflect(vec4, vec4);
class FunctionId {
public:
FunctionId(TOperator op, const TType& param);
FunctionId(TOperator op, const TType& param1, const TType& param2);
FunctionId(TOperator op, const TType& param1, const TType& param2, const TType& param3);
TFunctionUnknown
bool operator==(const FunctionId& other) const;
bool operator<(const FunctionId& other) const;
private:
TOperator mOp;
TType mParam1;
TType mParam2;
TType mParam3;
};
TBuiltInFunction IdentifyFunction(TOperator op, const TType& param);
TBuiltInFunction IdentifyFunction(
TOperator op, const TType& param1, const TType& param2);
bool SetFunctionCalled(const FunctionId& functionId);
bool SetFunctionCalled(TBuiltInFunction function);
// Map from function id to emulated function definition
std::map<FunctionId, std::string> mEmulatedFunctions;
std::vector<TBuiltInFunction> mFunctions;
const bool* mFunctionMask; // a boolean flag for each function.
const char** mFunctionSource;
// Called function ids
std::vector<FunctionId> mFunctions;
};
#endif // COMPILIER_BUILT_IN_FUNCTION_EMULATOR_H_
#endif // COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATOR_H_

View File

@ -0,0 +1,37 @@
//
// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
#include "angle_gl.h"
#include "compiler/translator/BuiltInFunctionEmulator.h"
#include "compiler/translator/BuiltInFunctionEmulatorGLSL.h"
#include "compiler/translator/SymbolTable.h"
void InitBuiltInFunctionEmulatorForGLSL(BuiltInFunctionEmulator *emu, sh::GLenum shaderType)
{
// we use macros here instead of function definitions to work around more GLSL
// compiler bugs, in particular on NVIDIA hardware on Mac OSX. Macros are
// problematic because if the argument has side-effects they will be repeatedly
// evaluated. This is unlikely to show up in real shaders, but is something to
// consider.
TType float1(EbtFloat);
TType float2(EbtFloat, 2);
TType float3(EbtFloat, 3);
TType float4(EbtFloat, 4);
if (shaderType == GL_FRAGMENT_SHADER)
{
emu->addEmulatedFunction(EOpCos, float1, "webgl_emu_precision float webgl_cos_emu(webgl_emu_precision float a) { return cos(a); }");
emu->addEmulatedFunction(EOpCos, float2, "webgl_emu_precision vec2 webgl_cos_emu(webgl_emu_precision vec2 a) { return cos(a); }");
emu->addEmulatedFunction(EOpCos, float3, "webgl_emu_precision vec3 webgl_cos_emu(webgl_emu_precision vec3 a) { return cos(a); }");
emu->addEmulatedFunction(EOpCos, float4, "webgl_emu_precision vec4 webgl_cos_emu(webgl_emu_precision vec4 a) { return cos(a); }");
}
emu->addEmulatedFunction(EOpDistance, float1, float1, "#define webgl_distance_emu(x, y) ((x) >= (y) ? (x) - (y) : (y) - (x))");
emu->addEmulatedFunction(EOpDot, float1, float1, "#define webgl_dot_emu(x, y) ((x) * (y))");
emu->addEmulatedFunction(EOpLength, float1, "#define webgl_length_emu(x) ((x) >= 0.0 ? (x) : -(x))");
emu->addEmulatedFunction(EOpNormalize, float1, "#define webgl_normalize_emu(x) ((x) == 0.0 ? 0.0 : ((x) > 0.0 ? 1.0 : -1.0))");
emu->addEmulatedFunction(EOpReflect, float1, float1, "#define webgl_reflect_emu(I, N) ((I) - 2.0 * (N) * (I) * (N))");
}

View File

@ -0,0 +1,19 @@
//
// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
#ifndef COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORGLSL_H_
#define COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORGLSL_H_
#include "GLSLANG/ShaderLang.h"
class BuiltInFunctionEmulator;
//
// This is only a workaround for OpenGL driver bugs, and isn't needed in general.
//
void InitBuiltInFunctionEmulatorForGLSL(BuiltInFunctionEmulator *emu, sh::GLenum shaderType);
#endif // COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORGLSL_H_

View File

@ -0,0 +1,410 @@
//
// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
#include "angle_gl.h"
#include "compiler/translator/BuiltInFunctionEmulator.h"
#include "compiler/translator/BuiltInFunctionEmulatorHLSL.h"
#include "compiler/translator/SymbolTable.h"
void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu)
{
TType float1(EbtFloat);
TType float2(EbtFloat, 2);
TType float3(EbtFloat, 3);
TType float4(EbtFloat, 4);
emu->addEmulatedFunction(EOpMod, float1, float1,
"float webgl_mod_emu(float x, float y)\n"
"{\n"
" return x - y * floor(x / y);\n"
"}\n"
"\n");
emu->addEmulatedFunction(EOpMod, float2, float2,
"float2 webgl_mod_emu(float2 x, float2 y)\n"
"{\n"
" return x - y * floor(x / y);\n"
"}\n"
"\n");
emu->addEmulatedFunction(EOpMod, float2, float1,
"float2 webgl_mod_emu(float2 x, float y)\n"
"{\n"
" return x - y * floor(x / y);\n"
"}\n"
"\n");
emu->addEmulatedFunction(EOpMod, float3, float3,
"float3 webgl_mod_emu(float3 x, float3 y)\n"
"{\n"
" return x - y * floor(x / y);\n"
"}\n"
"\n");
emu->addEmulatedFunction(EOpMod, float3, float1,
"float3 webgl_mod_emu(float3 x, float y)\n"
"{\n"
" return x - y * floor(x / y);\n"
"}\n"
"\n");
emu->addEmulatedFunction(EOpMod, float4, float4,
"float4 webgl_mod_emu(float4 x, float4 y)\n"
"{\n"
" return x - y * floor(x / y);\n"
"}\n"
"\n");
emu->addEmulatedFunction(EOpMod, float4, float1,
"float4 webgl_mod_emu(float4 x, float y)\n"
"{\n"
" return x - y * floor(x / y);\n"
"}\n"
"\n");
emu->addEmulatedFunction(EOpFaceForward, float1, float1, float1,
"float webgl_faceforward_emu(float N, float I, float Nref)\n"
"{\n"
" if(dot(Nref, I) >= 0)\n"
" {\n"
" return -N;\n"
" }\n"
" else\n"
" {\n"
" return N;\n"
" }\n"
"}\n"
"\n");
emu->addEmulatedFunction(EOpFaceForward, float2, float2, float2,
"float2 webgl_faceforward_emu(float2 N, float2 I, float2 Nref)\n"
"{\n"
" if(dot(Nref, I) >= 0)\n"
" {\n"
" return -N;\n"
" }\n"
" else\n"
" {\n"
" return N;\n"
" }\n"
"}\n"
"\n");
emu->addEmulatedFunction(EOpFaceForward, float3, float3, float3,
"float3 webgl_faceforward_emu(float3 N, float3 I, float3 Nref)\n"
"{\n"
" if(dot(Nref, I) >= 0)\n"
" {\n"
" return -N;\n"
" }\n"
" else\n"
" {\n"
" return N;\n"
" }\n"
"}\n"
"\n");
emu->addEmulatedFunction(EOpFaceForward, float4, float4, float4,
"float4 webgl_faceforward_emu(float4 N, float4 I, float4 Nref)\n"
"{\n"
" if(dot(Nref, I) >= 0)\n"
" {\n"
" return -N;\n"
" }\n"
" else\n"
" {\n"
" return N;\n"
" }\n"
"}\n"
"\n");
emu->addEmulatedFunction(EOpAtan, float1, float1,
"float webgl_atan_emu(float y, float x)\n"
"{\n"
" if(x == 0 && y == 0) x = 1;\n" // Avoid producing a NaN
" return atan2(y, x);\n"
"}\n");
emu->addEmulatedFunction(EOpAtan, float2, float2,
"float2 webgl_atan_emu(float2 y, float2 x)\n"
"{\n"
" if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
" if(x[1] == 0 && y[1] == 0) x[1] = 1;\n"
" return float2(atan2(y[0], x[0]), atan2(y[1], x[1]));\n"
"}\n");
emu->addEmulatedFunction(EOpAtan, float3, float3,
"float3 webgl_atan_emu(float3 y, float3 x)\n"
"{\n"
" if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
" if(x[1] == 0 && y[1] == 0) x[1] = 1;\n"
" if(x[2] == 0 && y[2] == 0) x[2] = 1;\n"
" return float3(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]));\n"
"}\n");
emu->addEmulatedFunction(EOpAtan, float4, float4,
"float4 webgl_atan_emu(float4 y, float4 x)\n"
"{\n"
" if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
" if(x[1] == 0 && y[1] == 0) x[1] = 1;\n"
" if(x[2] == 0 && y[2] == 0) x[2] = 1;\n"
" if(x[3] == 0 && y[3] == 0) x[3] = 1;\n"
" return float4(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]), atan2(y[3], x[3]));\n"
"}\n");
emu->addEmulatedFunction(EOpAsinh, float1,
"float webgl_asinh_emu(in float x) {\n"
" return log(x + sqrt(pow(x, 2.0) + 1.0));\n"
"}\n");
emu->addEmulatedFunction(EOpAsinh, float2,
"float2 webgl_asinh_emu(in float2 x) {\n"
" return log(x + sqrt(pow(x, 2.0) + 1.0));\n"
"}\n");
emu->addEmulatedFunction(EOpAsinh, float3,
"float3 webgl_asinh_emu(in float3 x) {\n"
" return log(x + sqrt(pow(x, 2.0) + 1.0));\n"
"}\n");
emu->addEmulatedFunction(EOpAsinh, float4,
"float4 webgl_asinh_emu(in float4 x) {\n"
" return log(x + sqrt(pow(x, 2.0) + 1.0));\n"
"}\n");
emu->addEmulatedFunction(EOpAcosh, float1,
"float webgl_acosh_emu(in float x) {\n"
" return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n"
"}\n");
emu->addEmulatedFunction(EOpAcosh, float2,
"float2 webgl_acosh_emu(in float2 x) {\n"
" return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n"
"}\n");
emu->addEmulatedFunction(EOpAcosh, float3,
"float3 webgl_acosh_emu(in float3 x) {\n"
" return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n"
"}\n");
emu->addEmulatedFunction(EOpAcosh, float4,
"float4 webgl_acosh_emu(in float4 x) {\n"
" return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n"
"}\n");
emu->addEmulatedFunction(EOpAtanh, float1,
"float webgl_atanh_emu(in float x) {\n"
" return 0.5 * log((1.0 + x) / (1.0 - x));\n"
"}\n");
emu->addEmulatedFunction(EOpAtanh, float2,
"float2 webgl_atanh_emu(in float2 x) {\n"
" return 0.5 * log((1.0 + x) / (1.0 - x));\n"
"}\n");
emu->addEmulatedFunction(EOpAtanh, float3,
"float3 webgl_atanh_emu(in float3 x) {\n"
" return 0.5 * log((1.0 + x) / (1.0 - x));\n"
"}\n");
emu->addEmulatedFunction(EOpAtanh, float4,
"float4 webgl_atanh_emu(in float4 x) {\n"
" return 0.5 * log((1.0 + x) / (1.0 - x));\n"
"}\n");
emu->addEmulatedFunction(EOpRoundEven, float1,
"float webgl_roundEven_emu(in float x) {\n"
" return (frac(x) == 0.5 && trunc(x) % 2.0 == 0.0) ? trunc(x) : round(x);\n"
"}\n");
emu->addEmulatedFunction(EOpRoundEven, float2,
"float2 webgl_roundEven_emu(in float2 x) {\n"
" float2 v;\n"
" v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);\n"
" v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);\n"
" return v;\n"
"}\n");
emu->addEmulatedFunction(EOpRoundEven, float3,
"float3 webgl_roundEven_emu(in float3 x) {\n"
" float3 v;\n"
" v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);\n"
" v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);\n"
" v[2] = (frac(x[2]) == 0.5 && trunc(x[2]) % 2.0 == 0.0) ? trunc(x[2]) : round(x[2]);\n"
" return v;\n"
"}\n");
emu->addEmulatedFunction(EOpRoundEven, float4,
"float4 webgl_roundEven_emu(in float4 x) {\n"
" float4 v;\n"
" v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);\n"
" v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);\n"
" v[2] = (frac(x[2]) == 0.5 && trunc(x[2]) % 2.0 == 0.0) ? trunc(x[2]) : round(x[2]);\n"
" v[3] = (frac(x[3]) == 0.5 && trunc(x[3]) % 2.0 == 0.0) ? trunc(x[3]) : round(x[3]);\n"
" return v;\n"
"}\n");
emu->addEmulatedFunction(EOpPackSnorm2x16, float2,
"int webgl_toSnorm(in float x) {\n"
" return int(round(clamp(x, -1.0, 1.0) * 32767.0));\n"
"}\n"
"\n"
"uint webgl_packSnorm2x16_emu(in float2 v) {\n"
" int x = webgl_toSnorm(v.x);\n"
" int y = webgl_toSnorm(v.y);\n"
" return (asuint(y) << 16) | (asuint(x) & 0xffffu);\n"
"}\n");
emu->addEmulatedFunction(EOpPackUnorm2x16, float2,
"uint webgl_toUnorm(in float x) {\n"
" return uint(round(clamp(x, 0.0, 1.0) * 65535.0));\n"
"}\n"
"\n"
"uint webgl_packUnorm2x16_emu(in float2 v) {\n"
" uint x = webgl_toUnorm(v.x);\n"
" uint y = webgl_toUnorm(v.y);\n"
" return (y << 16) | x;\n"
"}\n");
emu->addEmulatedFunction(EOpPackHalf2x16, float2,
"uint webgl_packHalf2x16_emu(in float2 v) {\n"
" uint x = f32tof16(v.x);\n"
" uint y = f32tof16(v.y);\n"
" return (y << 16) | x;\n"
"}\n");
TType uint1(EbtUInt);
emu->addEmulatedFunction(EOpUnpackSnorm2x16, uint1,
"float webgl_fromSnorm(in uint x) {\n"
" int xi = asint(x & 0x7fffu) - asint(x & 0x8000u);\n"
" return clamp(float(xi) / 32767.0, -1.0, 1.0);\n"
"}\n"
"\n"
"float2 webgl_unpackSnorm2x16_emu(in uint u) {\n"
" uint y = (u >> 16);\n"
" uint x = u;\n"
" return float2(webgl_fromSnorm(x), webgl_fromSnorm(y));\n"
"}\n");
emu->addEmulatedFunction(EOpUnpackUnorm2x16, uint1,
"float webgl_fromUnorm(in uint x) {\n"
" return float(x) / 65535.0;\n"
"}\n"
"\n"
"float2 webgl_unpackUnorm2x16_emu(in uint u) {\n"
" uint y = (u >> 16);\n"
" uint x = u & 0xffffu;\n"
" return float2(webgl_fromUnorm(x), webgl_fromUnorm(y));\n"
"}\n");
emu->addEmulatedFunction(EOpUnpackHalf2x16, uint1,
"float2 webgl_unpackHalf2x16_emu(in uint u) {\n"
" uint y = (u >> 16);\n"
" uint x = u & 0xffffu;\n"
" return float2(f16tof32(x), f16tof32(y));\n"
"}\n");
// The matrix resulting from outer product needs to be transposed
// (matrices are stored as transposed to simplify element access in HLSL).
// So the function should return transpose(c * r) where c is a column vector
// and r is a row vector. This can be simplified by using the following
// formula:
// transpose(c * r) = transpose(r) * transpose(c)
// transpose(r) and transpose(c) are in a sense free, since to get the
// transpose of r, we simply can build a column matrix out of the original
// vector instead of a row matrix.
emu->addEmulatedFunction(EOpOuterProduct, float2, float2,
"float2x2 webgl_outerProduct_emu(in float2 c, in float2 r) {\n"
" return mul(float2x1(r), float1x2(c));\n"
"}\n");
emu->addEmulatedFunction(EOpOuterProduct, float3, float3,
"float3x3 webgl_outerProduct_emu(in float3 c, in float3 r) {\n"
" return mul(float3x1(r), float1x3(c));\n"
"}\n");
emu->addEmulatedFunction(EOpOuterProduct, float4, float4,
"float4x4 webgl_outerProduct_emu(in float4 c, in float4 r) {\n"
" return mul(float4x1(r), float1x4(c));\n"
"}\n");
emu->addEmulatedFunction(EOpOuterProduct, float3, float2,
"float2x3 webgl_outerProduct_emu(in float3 c, in float2 r) {\n"
" return mul(float2x1(r), float1x3(c));\n"
"}\n");
emu->addEmulatedFunction(EOpOuterProduct, float2, float3,
"float3x2 webgl_outerProduct_emu(in float2 c, in float3 r) {\n"
" return mul(float3x1(r), float1x2(c));\n"
"}\n");
emu->addEmulatedFunction(EOpOuterProduct, float4, float2,
"float2x4 webgl_outerProduct_emu(in float4 c, in float2 r) {\n"
" return mul(float2x1(r), float1x4(c));\n"
"}\n");
emu->addEmulatedFunction(EOpOuterProduct, float2, float4,
"float4x2 webgl_outerProduct_emu(in float2 c, in float4 r) {\n"
" return mul(float4x1(r), float1x2(c));\n"
"}\n");
emu->addEmulatedFunction(EOpOuterProduct, float4, float3,
"float3x4 webgl_outerProduct_emu(in float4 c, in float3 r) {\n"
" return mul(float3x1(r), float1x4(c));\n"
"}\n");
emu->addEmulatedFunction(EOpOuterProduct, float3, float4,
"float4x3 webgl_outerProduct_emu(in float3 c, in float4 r) {\n"
" return mul(float4x1(r), float1x3(c));\n"
"}\n");
TType mat2(EbtFloat, 2, 2);
TType mat3(EbtFloat, 3, 3);
TType mat4(EbtFloat, 4, 4);
// Remember here that the parameter matrix is actually the transpose
// of the matrix that we're trying to invert, and the resulting matrix
// should also be the transpose of the inverse.
// When accessing the parameter matrix with m[a][b] it can be thought of so
// that a is the column and b is the row of the matrix that we're inverting.
// We calculate the inverse as the adjugate matrix divided by the
// determinant of the matrix being inverted. However, as the result needs
// to be transposed, we actually use of the transpose of the adjugate matrix
// which happens to be the cofactor matrix. That's stored in "cof".
// We don't need to care about divide-by-zero since results are undefined
// for singular or poorly-conditioned matrices.
emu->addEmulatedFunction(EOpInverse, mat2,
"float2x2 webgl_inverse_emu(in float2x2 m) {\n"
" float2x2 cof = { m[1][1], -m[0][1], -m[1][0], m[0][0] };\n"
" return cof / determinant(transpose(m));\n"
"}\n");
// cofAB is the cofactor for column A and row B.
emu->addEmulatedFunction(EOpInverse, mat3,
"float3x3 webgl_inverse_emu(in float3x3 m) {\n"
" float cof00 = m[1][1] * m[2][2] - m[2][1] * m[1][2];\n"
" float cof01 = -(m[1][0] * m[2][2] - m[2][0] * m[1][2]);\n"
" float cof02 = m[1][0] * m[2][1] - m[2][0] * m[1][1];\n"
" float cof10 = -(m[0][1] * m[2][2] - m[2][1] * m[0][2]);\n"
" float cof11 = m[0][0] * m[2][2] - m[2][0] * m[0][2];\n"
" float cof12 = -(m[0][0] * m[2][1] - m[2][0] * m[0][1]);\n"
" float cof20 = m[0][1] * m[1][2] - m[1][1] * m[0][2];\n"
" float cof21 = -(m[0][0] * m[1][2] - m[1][0] * m[0][2]);\n"
" float cof22 = m[0][0] * m[1][1] - m[1][0] * m[0][1];\n"
" float3x3 cof = { cof00, cof10, cof20, cof01, cof11, cof21, cof02, cof12, cof22 };\n"
" return cof / determinant(transpose(m));\n"
"}\n");
emu->addEmulatedFunction(EOpInverse, mat4,
"float4x4 webgl_inverse_emu(in float4x4 m) {\n"
" float cof00 = m[1][1] * m[2][2] * m[3][3] + m[2][1] * m[3][2] * m[1][3] + m[3][1] * m[1][2] * m[2][3]"
" - m[1][1] * m[3][2] * m[2][3] - m[2][1] * m[1][2] * m[3][3] - m[3][1] * m[2][2] * m[1][3];\n"
" float cof01 = -(m[1][0] * m[2][2] * m[3][3] + m[2][0] * m[3][2] * m[1][3] + m[3][0] * m[1][2] * m[2][3]"
" - m[1][0] * m[3][2] * m[2][3] - m[2][0] * m[1][2] * m[3][3] - m[3][0] * m[2][2] * m[1][3]);\n"
" float cof02 = m[1][0] * m[2][1] * m[3][3] + m[2][0] * m[3][1] * m[1][3] + m[3][0] * m[1][1] * m[2][3]"
" - m[1][0] * m[3][1] * m[2][3] - m[2][0] * m[1][1] * m[3][3] - m[3][0] * m[2][1] * m[1][3];\n"
" float cof03 = -(m[1][0] * m[2][1] * m[3][2] + m[2][0] * m[3][1] * m[1][2] + m[3][0] * m[1][1] * m[2][2]"
" - m[1][0] * m[3][1] * m[2][2] - m[2][0] * m[1][1] * m[3][2] - m[3][0] * m[2][1] * m[1][2]);\n"
" float cof10 = -(m[0][1] * m[2][2] * m[3][3] + m[2][1] * m[3][2] * m[0][3] + m[3][1] * m[0][2] * m[2][3]"
" - m[0][1] * m[3][2] * m[2][3] - m[2][1] * m[0][2] * m[3][3] - m[3][1] * m[2][2] * m[0][3]);\n"
" float cof11 = m[0][0] * m[2][2] * m[3][3] + m[2][0] * m[3][2] * m[0][3] + m[3][0] * m[0][2] * m[2][3]"
" - m[0][0] * m[3][2] * m[2][3] - m[2][0] * m[0][2] * m[3][3] - m[3][0] * m[2][2] * m[0][3];\n"
" float cof12 = -(m[0][0] * m[2][1] * m[3][3] + m[2][0] * m[3][1] * m[0][3] + m[3][0] * m[0][1] * m[2][3]"
" - m[0][0] * m[3][1] * m[2][3] - m[2][0] * m[0][1] * m[3][3] - m[3][0] * m[2][1] * m[0][3]);\n"
" float cof13 = m[0][0] * m[2][1] * m[3][2] + m[2][0] * m[3][1] * m[0][2] + m[3][0] * m[0][1] * m[2][2]"
" - m[0][0] * m[3][1] * m[2][2] - m[2][0] * m[0][1] * m[3][2] - m[3][0] * m[2][1] * m[0][2];\n"
" float cof20 = m[0][1] * m[1][2] * m[3][3] + m[1][1] * m[3][2] * m[0][3] + m[3][1] * m[0][2] * m[1][3]"
" - m[0][1] * m[3][2] * m[1][3] - m[1][1] * m[0][2] * m[3][3] - m[3][1] * m[1][2] * m[0][3];\n"
" float cof21 = -(m[0][0] * m[1][2] * m[3][3] + m[1][0] * m[3][2] * m[0][3] + m[3][0] * m[0][2] * m[1][3]"
" - m[0][0] * m[3][2] * m[1][3] - m[1][0] * m[0][2] * m[3][3] - m[3][0] * m[1][2] * m[0][3]);\n"
" float cof22 = m[0][0] * m[1][1] * m[3][3] + m[1][0] * m[3][1] * m[0][3] + m[3][0] * m[0][1] * m[1][3]"
" - m[0][0] * m[3][1] * m[1][3] - m[1][0] * m[0][1] * m[3][3] - m[3][0] * m[1][1] * m[0][3];\n"
" float cof23 = -(m[0][0] * m[1][1] * m[3][2] + m[1][0] * m[3][1] * m[0][2] + m[3][0] * m[0][1] * m[1][2]"
" - m[0][0] * m[3][1] * m[1][2] - m[1][0] * m[0][1] * m[3][2] - m[3][0] * m[1][1] * m[0][2]);\n"
" float cof30 = -(m[0][1] * m[1][2] * m[2][3] + m[1][1] * m[2][2] * m[0][3] + m[2][1] * m[0][2] * m[1][3]"
" - m[0][1] * m[2][2] * m[1][3] - m[1][1] * m[0][2] * m[2][3] - m[2][1] * m[1][2] * m[0][3]);\n"
" float cof31 = m[0][0] * m[1][2] * m[2][3] + m[1][0] * m[2][2] * m[0][3] + m[2][0] * m[0][2] * m[1][3]"
" - m[0][0] * m[2][2] * m[1][3] - m[1][0] * m[0][2] * m[2][3] - m[2][0] * m[1][2] * m[0][3];\n"
" float cof32 = -(m[0][0] * m[1][1] * m[2][3] + m[1][0] * m[2][1] * m[0][3] + m[2][0] * m[0][1] * m[1][3]"
" - m[0][0] * m[2][1] * m[1][3] - m[1][0] * m[0][1] * m[2][3] - m[2][0] * m[1][1] * m[0][3]);\n"
" float cof33 = m[0][0] * m[1][1] * m[2][2] + m[1][0] * m[2][1] * m[0][2] + m[2][0] * m[0][1] * m[1][2]"
" - m[0][0] * m[2][1] * m[1][2] - m[1][0] * m[0][1] * m[2][2] - m[2][0] * m[1][1] * m[0][2];\n"
" float4x4 cof = { cof00, cof10, cof20, cof30, cof01, cof11, cof21, cof31,"
" cof02, cof12, cof22, cof32, cof03, cof13, cof23, cof33 };\n"
" return cof / determinant(transpose(m));\n"
"}\n");
}

View File

@ -0,0 +1,16 @@
//
// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
#ifndef COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORHLSL_H_
#define COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORHLSL_H_
#include "GLSLANG/ShaderLang.h"
class BuiltInFunctionEmulator;
void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu);
#endif // COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORHLSL_H_

View File

@ -6,7 +6,9 @@
#include "compiler/translator/TranslatorESSL.h"
#include "compiler/translator/TranslatorGLSL.h"
#ifdef ANGLE_ENABLE_HLSL
#include "compiler/translator/TranslatorHLSL.h"
#endif // ANGLE_ENABLE_HLSL
//
// This function must be provided to create the actual
@ -17,14 +19,22 @@ TCompiler* ConstructCompiler(
sh::GLenum type, ShShaderSpec spec, ShShaderOutput output)
{
switch (output) {
case SH_ESSL_OUTPUT:
case SH_ESSL_OUTPUT:
return new TranslatorESSL(type, spec);
case SH_GLSL_OUTPUT:
return new TranslatorGLSL(type, spec);
case SH_HLSL9_OUTPUT:
case SH_HLSL11_OUTPUT:
case SH_GLSL_CORE_OUTPUT:
case SH_GLSL_COMPATIBILITY_OUTPUT:
return new TranslatorGLSL(type, spec, output);
case SH_HLSL9_OUTPUT:
case SH_HLSL11_OUTPUT:
#ifdef ANGLE_ENABLE_HLSL
return new TranslatorHLSL(type, spec, output);
default:
#else
// This compiler is not supported in this
// configuration. Return NULL per the ShConstructCompiler API.
return NULL;
#endif // ANGLE_ENABLE_HLSL
default:
// Unknown format. Return NULL per the ShConstructCompiler API.
return NULL;
}
}

View File

@ -4,8 +4,8 @@
// found in the LICENSE file.
//
#ifndef _COMMON_INCLUDED_
#define _COMMON_INCLUDED_
#ifndef COMPILER_TRANSLATOR_COMMON_H_
#define COMPILER_TRANSLATOR_COMMON_H_
#include <map>
#include <sstream>
@ -89,4 +89,4 @@ inline TString str(T i)
return buffer;
}
#endif // _COMMON_INCLUDED_
#endif // COMPILER_TRANSLATOR_COMMON_H_

View File

@ -4,7 +4,6 @@
// found in the LICENSE file.
//
#include "compiler/translator/BuiltInFunctionEmulator.h"
#include "compiler/translator/Compiler.h"
#include "compiler/translator/DetectCallDepth.h"
#include "compiler/translator/ForLoopUnroll.h"
@ -126,7 +125,8 @@ TCompiler::TCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output)
maxCallStackDepth(0),
fragmentPrecisionHigh(false),
clampingStrategy(SH_CLAMP_WITH_CLAMP_INTRINSIC),
builtInFunctionEmulator(type)
builtInFunctionEmulator(),
mSourcePath(NULL)
{
}
@ -159,33 +159,41 @@ bool TCompiler::Init(const ShBuiltInResources& resources)
return true;
}
bool TCompiler::compile(const char* const shaderStrings[],
size_t numStrings,
int compileOptions)
TIntermNode *TCompiler::compileTreeForTesting(const char* const shaderStrings[],
size_t numStrings, int compileOptions)
{
return compileTreeImpl(shaderStrings, numStrings, compileOptions);
}
TIntermNode *TCompiler::compileTreeImpl(const char* const shaderStrings[],
size_t numStrings, int compileOptions)
{
TScopedPoolAllocator scopedAlloc(&allocator);
clearResults();
if (numStrings == 0)
return true;
ASSERT(numStrings > 0);
ASSERT(GetGlobalPoolAllocator());
// Reset the extension behavior for each compilation unit.
ResetExtensionBehavior(extensionBehavior);
// If compiling for WebGL, validate loop and indexing as well.
if (IsWebGLBasedSpec(shaderSpec))
compileOptions |= SH_VALIDATE_LOOP_INDEXING;
// First string is path of source file if flag is set. The actual source follows.
const char* sourcePath = NULL;
size_t firstSource = 0;
if (compileOptions & SH_SOURCE_PATH)
{
sourcePath = shaderStrings[0];
mSourcePath = shaderStrings[0];
++firstSource;
}
bool debugShaderPrecision = getResources().WEBGL_debug_shader_precision == 1;
TIntermediate intermediate(infoSink);
TParseContext parseContext(symbolTable, extensionBehavior, intermediate,
shaderType, shaderSpec, compileOptions, true,
sourcePath, infoSink);
infoSink, debugShaderPrecision);
parseContext.fragmentPrecisionHigh = fragmentPrecisionHigh;
SetGlobalParseContext(&parseContext);
@ -206,6 +214,8 @@ bool TCompiler::compile(const char* const shaderStrings[],
success = false;
}
TIntermNode *root = NULL;
if (success)
{
mPragma = parseContext.pragma();
@ -214,7 +224,7 @@ bool TCompiler::compile(const char* const shaderStrings[],
symbolTable.setGlobalInvariant();
}
TIntermNode* root = parseContext.treeRoot;
root = parseContext.treeRoot;
success = intermediate.postProcess(root);
// Disallow expressions deemed too complex.
@ -255,8 +265,11 @@ bool TCompiler::compile(const char* const shaderStrings[],
}
// Built-in function emulation needs to happen after validateLimitations pass.
if (success && (compileOptions & SH_EMULATE_BUILT_IN_FUNCTIONS))
if (success)
{
initBuiltInFunctionEmulator(&builtInFunctionEmulator, compileOptions);
builtInFunctionEmulator.MarkBuiltInFunctionsForEmulation(root);
}
// Clamping uniform array bounds needs to happen after validateLimitations pass.
if (success && (compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS))
@ -301,18 +314,37 @@ bool TCompiler::compile(const char* const shaderStrings[],
RegenerateStructNames gen(symbolTable, shaderVersion);
root->traverse(&gen);
}
if (success && (compileOptions & SH_INTERMEDIATE_TREE))
intermediate.outputTree(root);
if (success && (compileOptions & SH_OBJECT_CODE))
translate(root);
}
// Cleanup memory.
intermediate.remove(parseContext.treeRoot);
SetGlobalParseContext(NULL);
return success;
if (success)
return root;
return NULL;
}
bool TCompiler::compile(const char* const shaderStrings[],
size_t numStrings, int compileOptions)
{
if (numStrings == 0)
return true;
TScopedPoolAllocator scopedAlloc(&allocator);
TIntermNode *root = compileTreeImpl(shaderStrings, numStrings, compileOptions);
if (root)
{
if (compileOptions & SH_INTERMEDIATE_TREE)
TIntermediate::outputTree(root, infoSink.info);
if (compileOptions & SH_OBJECT_CODE)
translate(root, compileOptions);
// The IntermNode tree doesn't need to be deleted here, since the
// memory will be freed in a big chunk by the PoolAllocator.
return true;
}
return false;
}
bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources &resources)
@ -390,11 +422,15 @@ void TCompiler::setResourceString()
<< ":MaxCallStackDepth:" << compileResources.MaxCallStackDepth
<< ":EXT_frag_depth:" << compileResources.EXT_frag_depth
<< ":EXT_shader_texture_lod:" << compileResources.EXT_shader_texture_lod
<< ":EXT_shader_framebuffer_fetch:" << compileResources.EXT_shader_framebuffer_fetch
<< ":NV_shader_framebuffer_fetch:" << compileResources.NV_shader_framebuffer_fetch
<< ":ARM_shader_framebuffer_fetch:" << compileResources.ARM_shader_framebuffer_fetch
<< ":MaxVertexOutputVectors:" << compileResources.MaxVertexOutputVectors
<< ":MaxFragmentInputVectors:" << compileResources.MaxFragmentInputVectors
<< ":MinProgramTexelOffset:" << compileResources.MinProgramTexelOffset
<< ":MaxProgramTexelOffset:" << compileResources.MaxProgramTexelOffset
<< ":NV_draw_buffers:" << compileResources.NV_draw_buffers;
<< ":NV_draw_buffers:" << compileResources.NV_draw_buffers
<< ":WEBGL_debug_shader_precision:" << compileResources.WEBGL_debug_shader_precision;
builtInResourcesString = strstream.str();
}
@ -416,27 +452,29 @@ void TCompiler::clearResults()
builtInFunctionEmulator.Cleanup();
nameMap.clear();
mSourcePath = NULL;
}
bool TCompiler::detectCallDepth(TIntermNode* root, TInfoSink& infoSink, bool limitCallStackDepth)
bool TCompiler::detectCallDepth(TIntermNode* inputRoot, TInfoSink& inputInfoSink, bool limitCallStackDepth)
{
DetectCallDepth detect(infoSink, limitCallStackDepth, maxCallStackDepth);
root->traverse(&detect);
DetectCallDepth detect(inputInfoSink, limitCallStackDepth, maxCallStackDepth);
inputRoot->traverse(&detect);
switch (detect.detectCallDepth())
{
case DetectCallDepth::kErrorNone:
return true;
case DetectCallDepth::kErrorMissingMain:
infoSink.info.prefix(EPrefixError);
infoSink.info << "Missing main()";
inputInfoSink.info.prefix(EPrefixError);
inputInfoSink.info << "Missing main()";
return false;
case DetectCallDepth::kErrorRecursion:
infoSink.info.prefix(EPrefixError);
infoSink.info << "Function recursion detected";
inputInfoSink.info.prefix(EPrefixError);
inputInfoSink.info << "Function recursion detected";
return false;
case DetectCallDepth::kErrorMaxDepthExceeded:
infoSink.info.prefix(EPrefixError);
infoSink.info << "Function call stack too deep";
inputInfoSink.info.prefix(EPrefixError);
inputInfoSink.info << "Function call stack too deep";
return false;
default:
UNREACHABLE();
@ -594,6 +632,11 @@ const TExtensionBehavior& TCompiler::getExtensionBehavior() const
return extensionBehavior;
}
const char *TCompiler::getSourcePath() const
{
return mSourcePath;
}
const ShBuiltInResources& TCompiler::getResources() const
{
return compileResources;

View File

@ -4,8 +4,8 @@
// found in the LICENSE file.
//
#ifndef _SHHANDLE_INCLUDED_
#define _SHHANDLE_INCLUDED_
#ifndef COMPILER_TRANSLATOR_COMPILER_H_
#define COMPILER_TRANSLATOR_COMPILER_H_
//
// Machine independent part of the compiler private objects
@ -25,7 +25,9 @@
class TCompiler;
class TDependencyGraph;
#ifdef ANGLE_ENABLE_HLSL
class TranslatorHLSL;
#endif // ANGLE_ENABLE_HLSL
//
// Helper function to identify specs that are based on the WebGL spec,
@ -41,7 +43,9 @@ public:
TShHandleBase();
virtual ~TShHandleBase();
virtual TCompiler* getAsCompiler() { return 0; }
#ifdef ANGLE_ENABLE_HLSL
virtual TranslatorHLSL* getAsTranslatorHLSL() { return 0; }
#endif // ANGLE_ENABLE_HLSL
protected:
// Memory allocator. Allocates and tracks memory required by the compiler.
@ -61,9 +65,15 @@ class TCompiler : public TShHandleBase
virtual TCompiler* getAsCompiler() { return this; }
bool Init(const ShBuiltInResources& resources);
// compileTreeForTesting should be used only when tests require access to
// the AST. Users of this function need to manually manage the global pool
// allocator. Returns NULL whenever there are compilation errors.
TIntermNode *compileTreeForTesting(const char* const shaderStrings[],
size_t numStrings, int compileOptions);
bool compile(const char* const shaderStrings[],
size_t numStrings,
int compileOptions);
size_t numStrings, int compileOptions);
// Get results of the last compilation.
int getShaderVersion() const { return shaderVersion; }
@ -104,8 +114,10 @@ class TCompiler : public TShHandleBase
bool validateLimitations(TIntermNode* root);
// Collect info for all attribs, uniforms, varyings.
void collectVariables(TIntermNode* root);
// Add emulated functions to the built-in function emulator.
virtual void initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, int compileOptions) {};
// Translate to object code.
virtual void translate(TIntermNode* root) = 0;
virtual void translate(TIntermNode *root, int compileOptions) = 0;
// Returns true if, after applying the packing rules in the GLSL 1.017 spec
// Appendix A, section 7, the shader does not use too many uniforms.
bool enforcePackingRestrictions();
@ -130,6 +142,7 @@ class TCompiler : public TShHandleBase
bool limitExpressionComplexity(TIntermNode* root);
// Get built-in extensions with default behavior.
const TExtensionBehavior& getExtensionBehavior() const;
const char *getSourcePath() const;
const TPragma& getPragma() const { return mPragma; }
void writePragma();
@ -145,6 +158,9 @@ class TCompiler : public TShHandleBase
std::vector<sh::InterfaceBlock> interfaceBlocks;
private:
TIntermNode *compileTreeImpl(const char* const shaderStrings[],
size_t numStrings, int compileOptions);
sh::GLenum shaderType;
ShShaderSpec shaderSpec;
ShShaderOutput outputType;
@ -170,6 +186,7 @@ class TCompiler : public TShHandleBase
// Results of compilation.
int shaderVersion;
TInfoSink infoSink; // Output sink.
const char *mSourcePath; // Path of source file or NULL
// name hashing.
ShHashFunction64 hashFunction;
@ -191,4 +208,4 @@ TCompiler* ConstructCompiler(
sh::GLenum type, ShShaderSpec spec, ShShaderOutput output);
void DeleteCompiler(TCompiler*);
#endif // _SHHANDLE_INCLUDED_
#endif // COMPILER_TRANSLATOR_COMPILER_H_

View File

@ -4,8 +4,8 @@
// found in the LICENSE file.
//
#ifndef _CONSTANT_UNION_INCLUDED_
#define _CONSTANT_UNION_INCLUDED_
#ifndef COMPILER_TRANSLATOR_CONSTANTUNION_H_
#define COMPILER_TRANSLATOR_CONSTANTUNION_H_
#include <assert.h>
@ -254,7 +254,10 @@ public:
ConstantUnion operator<<(const ConstantUnion& constant) const
{
ConstantUnion returnValue;
assert(type == constant.type);
// The signedness of the second parameter might be different, but we
// don't care, since the result is undefined if the second parameter is
// negative, and aliasing should not be a problem with unions.
assert(constant.type == EbtInt || constant.type == EbtUInt);
switch (type) {
case EbtInt: returnValue.setIConst(iConst << constant.iConst); break;
case EbtUInt: returnValue.setUConst(uConst << constant.uConst); break;
@ -267,7 +270,7 @@ public:
ConstantUnion operator&(const ConstantUnion& constant) const
{
ConstantUnion returnValue;
assert(type == constant.type);
assert(constant.type == EbtInt || constant.type == EbtUInt);
switch (type) {
case EbtInt: returnValue.setIConst(iConst & constant.iConst); break;
case EbtUInt: returnValue.setUConst(uConst & constant.uConst); break;
@ -340,4 +343,4 @@ private:
TBasicType type;
};
#endif // _CONSTANT_UNION_INCLUDED_
#endif // COMPILER_TRANSLATOR_CONSTANTUNION_H_

View File

@ -33,7 +33,7 @@ int DetectCallDepth::FunctionNode::detectCallDepth(DetectCallDepth* detectCallDe
ASSERT(visit == PreVisit);
ASSERT(detectCallDepth);
int maxDepth = depth;
int retMaxDepth = depth;
visit = InVisit;
for (size_t i = 0; i < callees.size(); ++i) {
switch (callees[i]->visit) {
@ -52,7 +52,7 @@ int DetectCallDepth::FunctionNode::detectCallDepth(DetectCallDepth* detectCallDe
detectCallDepth->getInfoSink().info << "<-" << callees[i]->getName();
return callDepth;
}
maxDepth = std::max(callDepth, maxDepth);
retMaxDepth = std::max(callDepth, retMaxDepth);
break;
}
default:
@ -61,7 +61,7 @@ int DetectCallDepth::FunctionNode::detectCallDepth(DetectCallDepth* detectCallDe
}
}
visit = PostVisit;
return maxDepth;
return retMaxDepth;
}
void DetectCallDepth::FunctionNode::reset()

View File

@ -4,8 +4,8 @@
// found in the LICENSE file.
//
#ifndef COMPILER_DETECT_RECURSION_H_
#define COMPILER_DETECT_RECURSION_H_
#ifndef COMPILER_TRANSLATOR_DETECTCALLDEPTH_H_
#define COMPILER_TRANSLATOR_DETECTCALLDEPTH_H_
#include <limits.h>
#include "compiler/translator/IntermNode.h"
@ -75,4 +75,4 @@ private:
void operator=(const DetectCallDepth&);
};
#endif // COMPILER_DETECT_RECURSION_H_
#endif // COMPILER_TRANSLATOR_DETECTCALLDEPTH_H_

View File

@ -8,8 +8,8 @@
// gradients of functions with discontinuities.
//
#ifndef COMPILER_DETECTDISCONTINUITY_H_
#define COMPILER_DETECTDISCONTINUITY_H_
#ifndef COMPILER_TRANSLATOR_DETECTDISCONTINUITY_H_
#define COMPILER_TRANSLATOR_DETECTDISCONTINUITY_H_
#include "compiler/translator/IntermNode.h"
@ -68,4 +68,4 @@ bool containsGradientOperation(TIntermNode *node);
}
#endif // COMPILER_DETECTDISCONTINUITY_H_
#endif // COMPILER_TRANSLATOR_DETECTDISCONTINUITY_H_

View File

@ -4,14 +4,15 @@
// found in the LICENSE file.
//
#ifndef COMPILER_DIAGNOSTICS_H_
#define COMPILER_DIAGNOSTICS_H_
#ifndef COMPILER_TRANSLATOR_DIAGNOSTICS_H_
#define COMPILER_TRANSLATOR_DIAGNOSTICS_H_
#include "common/angleutils.h"
#include "compiler/preprocessor/DiagnosticsBase.h"
class TInfoSink;
class TDiagnostics : public pp::Diagnostics
class TDiagnostics : public pp::Diagnostics, angle::NonCopyable
{
public:
TDiagnostics(TInfoSink& infoSink);
@ -41,4 +42,4 @@ class TDiagnostics : public pp::Diagnostics
int mNumWarnings;
};
#endif // COMPILER_DIAGNOSTICS_H_
#endif // COMPILER_TRANSLATOR_DIAGNOSTICS_H_

View File

@ -27,10 +27,12 @@ static TBehavior getBehavior(const std::string& str)
TDirectiveHandler::TDirectiveHandler(TExtensionBehavior& extBehavior,
TDiagnostics& diagnostics,
int& shaderVersion)
int& shaderVersion,
bool debugShaderPrecisionSupported)
: mExtensionBehavior(extBehavior),
mDiagnostics(diagnostics),
mShaderVersion(shaderVersion)
mShaderVersion(shaderVersion),
mDebugShaderPrecisionSupported(debugShaderPrecisionSupported)
{
}
@ -65,6 +67,7 @@ void TDirectiveHandler::handlePragma(const pp::SourceLocation& loc,
{
const char kOptimize[] = "optimize";
const char kDebug[] = "debug";
const char kDebugShaderPrecision[] = "webgl_debug_shader_precision";
const char kOn[] = "on";
const char kOff[] = "off";
@ -81,6 +84,12 @@ void TDirectiveHandler::handlePragma(const pp::SourceLocation& loc,
else if (value == kOff) mPragma.debug = false;
else invalidValue = true;
}
else if (name == kDebugShaderPrecision && mDebugShaderPrecisionSupported)
{
if (value == kOn) mPragma.debugShaderPrecision = true;
else if (value == kOff) mPragma.debugShaderPrecision = false;
else invalidValue = true;
}
else
{
mDiagnostics.report(pp::Diagnostics::PP_UNRECOGNIZED_PRAGMA, loc, name);

View File

@ -4,21 +4,23 @@
// found in the LICENSE file.
//
#ifndef COMPILER_DIRECTIVE_HANDLER_H_
#define COMPILER_DIRECTIVE_HANDLER_H_
#ifndef COMPILER_TRANSLATOR_DIRECTIVEHANDLER_H_
#define COMPILER_TRANSLATOR_DIRECTIVEHANDLER_H_
#include "common/angleutils.h"
#include "compiler/translator/ExtensionBehavior.h"
#include "compiler/translator/Pragma.h"
#include "compiler/preprocessor/DirectiveHandlerBase.h"
class TDiagnostics;
class TDirectiveHandler : public pp::DirectiveHandler
class TDirectiveHandler : public pp::DirectiveHandler, angle::NonCopyable
{
public:
TDirectiveHandler(TExtensionBehavior& extBehavior,
TDiagnostics& diagnostics,
int& shaderVersion);
int& shaderVersion,
bool debugShaderPrecisionSupported);
virtual ~TDirectiveHandler();
const TPragma& pragma() const { return mPragma; }
@ -44,6 +46,7 @@ class TDirectiveHandler : public pp::DirectiveHandler
TExtensionBehavior& mExtensionBehavior;
TDiagnostics& mDiagnostics;
int& mShaderVersion;
bool mDebugShaderPrecisionSupported;
};
#endif // COMPILER_DIRECTIVE_HANDLER_H_
#endif // COMPILER_TRANSLATOR_DIRECTIVEHANDLER_H_

View File

@ -0,0 +1,528 @@
//
// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
#include "compiler/translator/EmulatePrecision.h"
namespace
{
static void writeVectorPrecisionEmulationHelpers(
TInfoSinkBase& sink, ShShaderOutput outputLanguage, unsigned int size)
{
std::stringstream vecTypeStrStr;
if (outputLanguage == SH_ESSL_OUTPUT)
vecTypeStrStr << "highp ";
vecTypeStrStr << "vec" << size;
std::string vecType = vecTypeStrStr.str();
sink <<
vecType << " angle_frm(in " << vecType << " v) {\n"
" v = clamp(v, -65504.0, 65504.0);\n"
" " << vecType << " exponent = floor(log2(abs(v) + 1e-30)) - 10.0;\n"
" bvec" << size << " isNonZero = greaterThanEqual(exponent, vec" << size << "(-25.0));\n"
" v = v * exp2(-exponent);\n"
" v = sign(v) * floor(abs(v));\n"
" return v * exp2(exponent) * vec" << size << "(isNonZero);\n"
"}\n";
sink <<
vecType << " angle_frl(in " << vecType << " v) {\n"
" v = clamp(v, -2.0, 2.0);\n"
" v = v * 256.0;\n"
" v = sign(v) * floor(abs(v));\n"
" return v * 0.00390625;\n"
"}\n";
}
static void writeMatrixPrecisionEmulationHelper(
TInfoSinkBase& sink, ShShaderOutput outputLanguage, unsigned int size, const char *functionName)
{
std::stringstream matTypeStrStr;
if (outputLanguage == SH_ESSL_OUTPUT)
matTypeStrStr << "highp ";
matTypeStrStr << "mat" << size;
std::string matType = matTypeStrStr.str();
sink << matType << " " << functionName << "(in " << matType << " m) {\n"
" " << matType << " rounded;\n";
for (unsigned int i = 0; i < size; ++i)
{
sink << " rounded[" << i << "] = " << functionName << "(m[" << i << "]);\n";
}
sink << " return rounded;\n"
"}\n";
}
static void writeCommonPrecisionEmulationHelpers(TInfoSinkBase& sink, ShShaderOutput outputLanguage)
{
// Write the angle_frm functions that round floating point numbers to
// half precision, and angle_frl functions that round them to minimum lowp
// precision.
// Unoptimized version of angle_frm for single floats:
//
// int webgl_maxNormalExponent(in int exponentBits) {
// int possibleExponents = int(exp2(float(exponentBits)));
// int exponentBias = possibleExponents / 2 - 1;
// int allExponentBitsOne = possibleExponents - 1;
// return (allExponentBitsOne - 1) - exponentBias;
// }
//
// float angle_frm(in float x) {
// int mantissaBits = 10;
// int exponentBits = 5;
// float possibleMantissas = exp2(float(mantissaBits));
// float mantissaMax = 2.0 - 1.0 / possibleMantissas;
// int maxNE = webgl_maxNormalExponent(exponentBits);
// float max = exp2(float(maxNE)) * mantissaMax;
// if (x > max) {
// return max;
// }
// if (x < -max) {
// return -max;
// }
// float exponent = floor(log2(abs(x)));
// if (abs(x) == 0.0 || exponent < -float(maxNE)) {
// return 0.0 * sign(x)
// }
// x = x * exp2(-(exponent - float(mantissaBits)));
// x = sign(x) * floor(abs(x));
// return x * exp2(exponent - float(mantissaBits));
// }
// All numbers with a magnitude less than 2^-15 are subnormal, and are
// flushed to zero.
// Note the constant numbers below:
// a) 65504 is the maximum possible mantissa (1.1111111111 in binary) times
// 2^15, the maximum normal exponent.
// b) 10.0 is the number of mantissa bits.
// c) -25.0 is the minimum normal half-float exponent -15.0 minus the number
// of mantissa bits.
// d) + 1e-30 is to make sure the argument of log2() won't be zero. It can
// only affect the result of log2 on x where abs(x) < 1e-22. Since these
// numbers will be flushed to zero either way (2^-15 is the smallest
// normal positive number), this does not introduce any error.
std::string floatType = "float";
if (outputLanguage == SH_ESSL_OUTPUT)
floatType = "highp float";
sink <<
floatType << " angle_frm(in " << floatType << " x) {\n"
" x = clamp(x, -65504.0, 65504.0);\n"
" " << floatType << " exponent = floor(log2(abs(x) + 1e-30)) - 10.0;\n"
" bool isNonZero = (exponent >= -25.0);\n"
" x = x * exp2(-exponent);\n"
" x = sign(x) * floor(abs(x));\n"
" return x * exp2(exponent) * float(isNonZero);\n"
"}\n";
sink <<
floatType << " angle_frl(in " << floatType << " x) {\n"
" x = clamp(x, -2.0, 2.0);\n"
" x = x * 256.0;\n"
" x = sign(x) * floor(abs(x));\n"
" return x * 0.00390625;\n"
"}\n";
writeVectorPrecisionEmulationHelpers(sink, outputLanguage, 2);
writeVectorPrecisionEmulationHelpers(sink, outputLanguage, 3);
writeVectorPrecisionEmulationHelpers(sink, outputLanguage, 4);
for (unsigned int size = 2; size <= 4; ++size)
{
writeMatrixPrecisionEmulationHelper(sink, outputLanguage, size, "angle_frm");
writeMatrixPrecisionEmulationHelper(sink, outputLanguage, size, "angle_frl");
}
}
static void writeCompoundAssignmentPrecisionEmulation(
TInfoSinkBase& sink, ShShaderOutput outputLanguage,
const char *lType, const char *rType, const char *opStr, const char *opNameStr)
{
std::string lTypeStr = lType;
std::string rTypeStr = rType;
if (outputLanguage == SH_ESSL_OUTPUT)
{
std::stringstream lTypeStrStr;
lTypeStrStr << "highp " << lType;
lTypeStr = lTypeStrStr.str();
std::stringstream rTypeStrStr;
rTypeStrStr << "highp " << rType;
rTypeStr = rTypeStrStr.str();
}
// Note that y should be passed through angle_frm at the function call site,
// but x can't be passed through angle_frm there since it is an inout parameter.
// So only pass x and the result through angle_frm here.
sink <<
lTypeStr << " angle_compound_" << opNameStr << "_frm(inout " << lTypeStr << " x, in " << rTypeStr << " y) {\n"
" x = angle_frm(angle_frm(x) " << opStr << " y);\n"
" return x;\n"
"}\n";
sink <<
lTypeStr << " angle_compound_" << opNameStr << "_frl(inout " << lTypeStr << " x, in " << rTypeStr << " y) {\n"
" x = angle_frl(angle_frm(x) " << opStr << " y);\n"
" return x;\n"
"}\n";
}
const char *getFloatTypeStr(const TType& type)
{
switch (type.getNominalSize())
{
case 1:
return "float";
case 2:
return type.getSecondarySize() > 1 ? "mat2" : "vec2";
case 3:
return type.getSecondarySize() > 1 ? "mat3" : "vec3";
case 4:
return type.getSecondarySize() > 1 ? "mat4" : "vec4";
default:
UNREACHABLE();
return NULL;
}
}
bool canRoundFloat(const TType &type)
{
return type.getBasicType() == EbtFloat && !type.isNonSquareMatrix() && !type.isArray() &&
(type.getPrecision() == EbpLow || type.getPrecision() == EbpMedium);
}
TIntermAggregate *createInternalFunctionCallNode(TString name, TIntermNode *child)
{
TIntermAggregate *callNode = new TIntermAggregate();
callNode->setOp(EOpInternalFunctionCall);
callNode->setName(name);
callNode->getSequence()->push_back(child);
return callNode;
}
TIntermAggregate *createRoundingFunctionCallNode(TIntermTyped *roundedChild)
{
TString roundFunctionName;
if (roundedChild->getPrecision() == EbpMedium)
roundFunctionName = "angle_frm";
else
roundFunctionName = "angle_frl";
return createInternalFunctionCallNode(roundFunctionName, roundedChild);
}
TIntermAggregate *createCompoundAssignmentFunctionCallNode(TIntermTyped *left, TIntermTyped *right, const char *opNameStr)
{
std::stringstream strstr;
if (left->getPrecision() == EbpMedium)
strstr << "angle_compound_" << opNameStr << "_frm";
else
strstr << "angle_compound_" << opNameStr << "_frl";
TString functionName = strstr.str().c_str();
TIntermAggregate *callNode = createInternalFunctionCallNode(functionName, left);
callNode->getSequence()->push_back(right);
return callNode;
}
bool parentUsesResult(TIntermNode* parent, TIntermNode* node)
{
if (!parent)
{
return false;
}
TIntermAggregate *aggParent = parent->getAsAggregate();
// If the parent's op is EOpSequence, the result is not assigned anywhere,
// so rounding it is not needed. In particular, this can avoid a lot of
// unnecessary rounding of unused return values of assignment.
if (aggParent && aggParent->getOp() == EOpSequence)
{
return false;
}
if (aggParent && aggParent->getOp() == EOpComma && (aggParent->getSequence()->back() != node))
{
return false;
}
return true;
}
} // namespace anonymous
EmulatePrecision::EmulatePrecision()
: TIntermTraverser(true, true, true),
mDeclaringVariables(false),
mInLValue(false),
mInFunctionCallOutParameter(false)
{}
void EmulatePrecision::visitSymbol(TIntermSymbol *node)
{
if (canRoundFloat(node->getType()) &&
!mDeclaringVariables && !mInLValue && !mInFunctionCallOutParameter)
{
TIntermNode *parent = getParentNode();
TIntermNode *replacement = createRoundingFunctionCallNode(node);
mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, true));
}
}
bool EmulatePrecision::visitBinary(Visit visit, TIntermBinary *node)
{
bool visitChildren = true;
if (node->isAssignment())
{
if (visit == PreVisit)
mInLValue = true;
else if (visit == InVisit)
mInLValue = false;
}
TOperator op = node->getOp();
// RHS of initialize is not being declared.
if (op == EOpInitialize && visit == InVisit)
mDeclaringVariables = false;
if ((op == EOpIndexDirectStruct || op == EOpVectorSwizzle) && visit == InVisit)
visitChildren = false;
if (visit != PreVisit)
return visitChildren;
const TType& type = node->getType();
bool roundFloat = canRoundFloat(type);
if (roundFloat) {
switch (op) {
// Math operators that can result in a float may need to apply rounding to the return
// value. Note that in the case of assignment, the rounding is applied to its return
// value here, not the value being assigned.
case EOpAssign:
case EOpAdd:
case EOpSub:
case EOpMul:
case EOpDiv:
case EOpVectorTimesScalar:
case EOpVectorTimesMatrix:
case EOpMatrixTimesVector:
case EOpMatrixTimesScalar:
case EOpMatrixTimesMatrix:
{
TIntermNode *parent = getParentNode();
if (!parentUsesResult(parent, node))
{
break;
}
TIntermNode *replacement = createRoundingFunctionCallNode(node);
mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, true));
break;
}
// Compound assignment cases need to replace the operator with a function call.
case EOpAddAssign:
{
mEmulateCompoundAdd.insert(TypePair(getFloatTypeStr(type), getFloatTypeStr(node->getRight()->getType())));
TIntermNode *parent = getParentNode();
TIntermNode *replacement = createCompoundAssignmentFunctionCallNode(node->getLeft(), node->getRight(), "add");
mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, false));
break;
}
case EOpSubAssign:
{
mEmulateCompoundSub.insert(TypePair(getFloatTypeStr(type), getFloatTypeStr(node->getRight()->getType())));
TIntermNode *parent = getParentNode();
TIntermNode *replacement = createCompoundAssignmentFunctionCallNode(node->getLeft(), node->getRight(), "sub");
mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, false));
break;
}
case EOpMulAssign:
case EOpVectorTimesMatrixAssign:
case EOpVectorTimesScalarAssign:
case EOpMatrixTimesScalarAssign:
case EOpMatrixTimesMatrixAssign:
{
mEmulateCompoundMul.insert(TypePair(getFloatTypeStr(type), getFloatTypeStr(node->getRight()->getType())));
TIntermNode *parent = getParentNode();
TIntermNode *replacement = createCompoundAssignmentFunctionCallNode(node->getLeft(), node->getRight(), "mul");
mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, false));
break;
}
case EOpDivAssign:
{
mEmulateCompoundDiv.insert(TypePair(getFloatTypeStr(type), getFloatTypeStr(node->getRight()->getType())));
TIntermNode *parent = getParentNode();
TIntermNode *replacement = createCompoundAssignmentFunctionCallNode(node->getLeft(), node->getRight(), "div");
mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, false));
break;
}
default:
// The rest of the binary operations should not need precision emulation.
break;
}
}
return visitChildren;
}
bool EmulatePrecision::visitAggregate(Visit visit, TIntermAggregate *node)
{
bool visitChildren = true;
switch (node->getOp())
{
case EOpSequence:
case EOpConstructStruct:
// No special handling
break;
case EOpFunction:
if (visit == PreVisit)
{
const TIntermSequence &sequence = *(node->getSequence());
TIntermSequence::const_iterator seqIter = sequence.begin();
TIntermAggregate *params = (*seqIter)->getAsAggregate();
ASSERT(params != NULL);
ASSERT(params->getOp() == EOpParameters);
mFunctionMap[node->getName()] = params->getSequence();
}
break;
case EOpPrototype:
if (visit == PreVisit)
mFunctionMap[node->getName()] = node->getSequence();
visitChildren = false;
break;
case EOpParameters:
visitChildren = false;
break;
case EOpInvariantDeclaration:
visitChildren = false;
break;
case EOpDeclaration:
// Variable declaration.
if (visit == PreVisit)
{
mDeclaringVariables = true;
}
else if (visit == InVisit)
{
mDeclaringVariables = true;
}
else
{
mDeclaringVariables = false;
}
break;
case EOpFunctionCall:
{
// Function call.
bool inFunctionMap = (mFunctionMap.find(node->getName()) != mFunctionMap.end());
if (visit == PreVisit)
{
// User-defined function return values are not rounded, this relies on that
// calculations producing the value were rounded.
TIntermNode *parent = getParentNode();
if (canRoundFloat(node->getType()) && !inFunctionMap && parentUsesResult(parent, node))
{
TIntermNode *replacement = createRoundingFunctionCallNode(node);
mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, true));
}
if (inFunctionMap)
{
mSeqIterStack.push_back(mFunctionMap[node->getName()]->begin());
if (mSeqIterStack.back() != mFunctionMap[node->getName()]->end())
{
TQualifier qualifier = (*mSeqIterStack.back())->getAsTyped()->getQualifier();
mInFunctionCallOutParameter = (qualifier == EvqOut || qualifier == EvqInOut);
}
}
else
{
// The function is not user-defined - it is likely built-in texture function.
// Assume that those do not have out parameters.
mInFunctionCallOutParameter = false;
}
}
else if (visit == InVisit)
{
if (inFunctionMap)
{
++mSeqIterStack.back();
TQualifier qualifier = (*mSeqIterStack.back())->getAsTyped()->getQualifier();
mInFunctionCallOutParameter = (qualifier == EvqOut || qualifier == EvqInOut);
}
}
else
{
if (inFunctionMap)
{
mSeqIterStack.pop_back();
mInFunctionCallOutParameter = false;
}
}
break;
}
default:
TIntermNode *parent = getParentNode();
if (canRoundFloat(node->getType()) && visit == PreVisit && parentUsesResult(parent, node))
{
TIntermNode *replacement = createRoundingFunctionCallNode(node);
mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, true));
}
break;
}
return visitChildren;
}
bool EmulatePrecision::visitUnary(Visit visit, TIntermUnary *node)
{
switch (node->getOp())
{
case EOpNegative:
case EOpVectorLogicalNot:
case EOpLogicalNot:
break;
case EOpPostIncrement:
case EOpPostDecrement:
case EOpPreIncrement:
case EOpPreDecrement:
if (visit == PreVisit)
mInLValue = true;
else if (visit == PostVisit)
mInLValue = false;
break;
default:
if (canRoundFloat(node->getType()) && visit == PreVisit)
{
TIntermNode *parent = getParentNode();
TIntermNode *replacement = createRoundingFunctionCallNode(node);
mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, true));
}
break;
}
return true;
}
void EmulatePrecision::writeEmulationHelpers(TInfoSinkBase& sink, ShShaderOutput outputLanguage)
{
// Other languages not yet supported
ASSERT(outputLanguage == SH_GLSL_COMPATIBILITY_OUTPUT ||
outputLanguage == SH_GLSL_CORE_OUTPUT ||
outputLanguage == SH_ESSL_OUTPUT);
writeCommonPrecisionEmulationHelpers(sink, outputLanguage);
EmulationSet::const_iterator it;
for (it = mEmulateCompoundAdd.begin(); it != mEmulateCompoundAdd.end(); it++)
writeCompoundAssignmentPrecisionEmulation(sink, outputLanguage, it->lType, it->rType, "+", "add");
for (it = mEmulateCompoundSub.begin(); it != mEmulateCompoundSub.end(); it++)
writeCompoundAssignmentPrecisionEmulation(sink, outputLanguage, it->lType, it->rType, "-", "sub");
for (it = mEmulateCompoundDiv.begin(); it != mEmulateCompoundDiv.end(); it++)
writeCompoundAssignmentPrecisionEmulation(sink, outputLanguage, it->lType, it->rType, "/", "div");
for (it = mEmulateCompoundMul.begin(); it != mEmulateCompoundMul.end(); it++)
writeCompoundAssignmentPrecisionEmulation(sink, outputLanguage, it->lType, it->rType, "*", "mul");
}

View File

@ -0,0 +1,74 @@
//
// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
#ifndef COMPILER_TRANSLATOR_EMULATE_PRECISION_H_
#define COMPILER_TRANSLATOR_EMULATE_PRECISION_H_
#include "common/angleutils.h"
#include "compiler/translator/InfoSink.h"
#include "compiler/translator/IntermNode.h"
#include "GLSLANG/ShaderLang.h"
// This class gathers all compound assignments from the AST and can then write
// the functions required for their precision emulation. This way there is no
// need to write a huge number of variations of the emulated compound assignment
// to every translated shader with emulation enabled.
class EmulatePrecision : public TIntermTraverser
{
public:
EmulatePrecision();
virtual void visitSymbol(TIntermSymbol *node);
virtual bool visitBinary(Visit visit, TIntermBinary *node);
virtual bool visitUnary(Visit visit, TIntermUnary *node);
virtual bool visitAggregate(Visit visit, TIntermAggregate *node);
void writeEmulationHelpers(TInfoSinkBase& sink, ShShaderOutput outputLanguage);
private:
struct TypePair
{
TypePair(const char *l, const char *r)
: lType(l), rType(r) { }
const char *lType;
const char *rType;
};
struct TypePairComparator
{
bool operator() (const TypePair& l, const TypePair& r) const
{
if (l.lType == r.lType)
return l.rType < r.rType;
return l.lType < r.lType;
}
};
typedef std::set<TypePair, TypePairComparator> EmulationSet;
EmulationSet mEmulateCompoundAdd;
EmulationSet mEmulateCompoundSub;
EmulationSet mEmulateCompoundMul;
EmulationSet mEmulateCompoundDiv;
// Stack of function call parameter iterators
std::vector<TIntermSequence::const_iterator> mSeqIterStack;
bool mDeclaringVariables;
bool mInLValue;
bool mInFunctionCallOutParameter;
struct TStringComparator
{
bool operator() (const TString& a, const TString& b) const { return a.compare(b) < 0; }
};
// Map from function names to their parameter sequences
std::map<TString, TIntermSequence*, TStringComparator> mFunctionMap;
};
#endif // COMPILER_TRANSLATOR_EMULATE_PRECISION_H_

View File

@ -4,8 +4,8 @@
// found in the LICENSE file.
//
#ifndef _EXTENSION_BEHAVIOR_INCLUDED_
#define _EXTENSION_BEHAVIOR_INCLUDED_
#ifndef COMPILER_TRANSLATOR_EXTENSIONBEHAVIOR_H_
#define COMPILER_TRANSLATOR_EXTENSIONBEHAVIOR_H_
#include <map>
#include <string>
@ -34,4 +34,4 @@ inline const char* getBehaviorString(TBehavior b)
// Mapping between extension name and behavior.
typedef std::map<std::string, TBehavior> TExtensionBehavior;
#endif // _EXTENSION_TABLE_INCLUDED_
#endif // COMPILER_TRANSLATOR_EXTENSIONBEHAVIOR_H_

Some files were not shown because too many files have changed in this diff Show More