Merge remote-tracking branch 'origin/5.4.0' into 5.4

Change-Id: I95f235a66ce2e9b1fa435c0f911c6f7e811755f0
This commit is contained in:
Frederik Gladhorn 2014-11-21 13:44:26 +01:00
commit 245acbf6e8
336 changed files with 18529 additions and 14538 deletions

7
configure vendored
View File

@ -3157,6 +3157,7 @@ if [ "$XPLATFORM_IOS" = "yes" ]; then
CFG_NOBUILD_PARTS="$CFG_NOBUILD_PARTS examples"
CFG_SHARED="no" # iOS builds should be static to be able to submit to the App Store
CFG_SKIP_MODULES="$CFG_SKIP_MODULES qtconnectivity qtdoc qtmacextras qtserialport qtwebkit qtwebkit-examples"
CFG_PRECOMPILE="no" # Precompiled headers not supported with multiple -arch arguments
# If the user passes -sdk on the command line we build a SDK-specific Qt build.
# Otherwise we build a joined simulator and device build, which is the default.
@ -5788,7 +5789,11 @@ fi
[ '!' -z "$INCLUDES" ] && QMakeVar add INCLUDEPATH "$INCLUDES"
[ '!' -z "$L_FLAGS" ] && QMakeVar add LIBS "$L_FLAGS"
if [ -z "`getXQMakeConf 'QMAKE_(LFLAGS_)?RPATH'`" ]; then
if [ "$XPLATFORM_MAC" = "yes" ] && [ "$QT_CROSS_COMPILE" = "no" ]; then
if [ "$CFG_RPATH" = "yes" ]; then
QMAKE_CONFIG="$QMAKE_CONFIG absolute_library_soname"
fi
elif [ -z "`getXQMakeConf 'QMAKE_(LFLAGS_)?RPATH'`" ]; then
if [ -n "$RPATH_FLAGS" ]; then
echo
echo "ERROR: -R cannot be used on this platform as \$QMAKE_LFLAGS_RPATH is"

43
dist/changes-5.4.0 vendored
View File

@ -47,3 +47,46 @@ OS X
- OS X 10.10 is now supported.
- QMacStyle has been updated with better OS 10.10 support.
- The Qt binary packages are now configured with C++11 enabled.
Windows
-------
- [QTBUG-38259] Changed configure defaults so that Qt5Core does not
link against ICU libraries anymore. Pass '-icu' to enable it.
****************************************************************************
* Tools *
****************************************************************************
configure & build system
------------------------
- The -process/-fully-process/-dont-process configure options have been
removed due to being unnecessary and counterproductive.
- [QTBUG-36955] The -vcproj configure option was removed. Use "qmake -r -tp vc"
_after_ building Qt in case you want to use Visual Studio to work on Qt.
- [QTBUG-37961] Qt plugins contain version info again.
- [QTBUG-39216] Fixed more cases where the Qt build would pick up headers
from a pre-existing Qt installation.
- [QTBUG-41267] Fixed parallelized (jom) -debug-and-release builds.
qmake
-----
- [QTBUG-21910][Unix] Added 'make dist' target for SUBDIRS projects.
- [QTBUG-32895][iOS] Fixed structure of bundles. They can be signed now.
- [QTBUG-26782][VS] Fixed handling of TARGET_EXT.
- [QTBUG-30712][VS] Fixed handling of QMAKE_LIBFLAGS.
- [QTBUG-30373][VS] Using different RESOURCES in different build variants
no longer produces invalid vcxproj files.
- [QTBUG-37520][VS] Made it possible to suppress qmake warnings about
unknown compiler options. CONFIG+=suppress_vcproj_warnings.
- [QTBUG-37363][MSVC2012+] embed_manifest_exe is now properly supported.
- [QTBUG-41504][MSVC2012+] Building DLLs targeting Windows XP is now
supported. As a side effect, Windows CE makespecs must not add /ENTRY: to
QMAKE_LFLAGS_CONSOLE any more. The flag is hard-coded in console.prf now.
- [QTBUG-35318][Xcode] Fixed QMAKE_BUNDLE_DATA's path resolution.
- [QTBUG-39527] Fixed qtCompile() when used with jom -jN.
- QMAKE_EXTRA_COMPILERS' commands and depend_command are no longer mangled.
Use $$shell_path() and $$shell_quote() to prepare the commands correctly.
- Added link-time optimization support for Clang, GCC and ICC. CONFIG+=ltgc.

View File

@ -359,7 +359,9 @@ h3.fn, span.fn {
margin: 0px;
margin-top: 45px;
}
h3.fn code {
float: right;
}
h3.fn:target {
background-color: #F6F6D6;
}
@ -705,8 +707,21 @@ Landing page
float: left;
}
.icons1of3 h2 {
.icons1of3 h2, .doc-column h2 {
font-size: 15px;
margin: 0px;
padding: 0px;
}
div.multi-column {
position: relative;
}
div.multi-column div {
display: -moz-inline-box;
display: inline-block;
vertical-align: top;
margin-top: 1em;
margin-right: 4em;
width: 24em;
}

View File

@ -7,6 +7,9 @@ QMAKE_COMPILER = gcc clang llvm # clang pretends to be gcc
QMAKE_CC = clang
QMAKE_CXX = clang++
QMAKE_LINK_C = $$QMAKE_CC
QMAKE_LINK_C_SHLIB = $$QMAKE_CC
QMAKE_LINK = $$QMAKE_CXX
QMAKE_LINK_SHLIB = $$QMAKE_CXX

View File

@ -52,6 +52,12 @@ QMAKE_DIR_REPLACE_SANE = PRECOMPILED_DIR OBJECTS_DIR MOC_DIR RCC_DIR UI_DIR
unset(modpath)
}
mac {
!isEmpty(QMAKE_RPATHDIR){
CONFIG += absolute_library_soname
}
}
cross_compile: \
CONFIG += force_bootstrap

View File

@ -94,6 +94,8 @@ else: \
# OS X and iOS frameworks
mac:CONFIG(shared, static|shared):contains(QT_CONFIG, qt_framework) {
# Set the CFBundleIdentifier prefix for Qt frameworks
QMAKE_TARGET_BUNDLE_PREFIX = org.qt-project
#QMAKE_FRAMEWORK_VERSION = 4.0
CONFIG += lib_bundle sliced_bundle qt_framework
CONFIG -= qt_install_headers #no need to install these as well
@ -111,9 +113,6 @@ mac:CONFIG(shared, static|shared):contains(QT_CONFIG, qt_framework) {
}
}
mac:contains(QT_CONFIG, rpath): \
QMAKE_SONAME_PREFIX = @rpath
mac {
CONFIG += explicitlib
macx-g++ {

View File

@ -11,7 +11,7 @@ rcc.name = RCC ${QMAKE_FILE_IN}
rcc.depend_command = $$QMAKE_RCC_DEP -list $$QMAKE_RESOURCE_FLAGS ${QMAKE_FILE_IN}
rcc.CONFIG += add_inputs_as_makefile_deps
resources_small|ltcg|macx-xcode|contains(TEMPLATE, "vc.*") {
!resources_big|ltcg|macx-xcode|contains(TEMPLATE, "vc.*") {
rcc.output = $$RCC_DIR/$${first(QMAKE_MOD_RCC)}_${QMAKE_FILE_BASE}$${first(QMAKE_EXT_CPP)}
rcc.commands = $$QMAKE_RCC $$QMAKE_RESOURCE_FLAGS ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT}

View File

@ -14,6 +14,8 @@
<string>@TYPEINFO@</string>
<key>CFBundleExecutable</key>
<string>@LIBRARY@</string>
<key>CFBundleIdentifier</key>
<string>@BUNDLEIDENTIFIER@</string>
<key>NOTE</key>
<string>Please, do NOT change this file -- It was generated by Qt/QMake.</string>
</dict>

View File

@ -14,6 +14,8 @@
<string>@TYPEINFO@</string>
<key>CFBundleExecutable</key>
<string>@LIBRARY@</string>
<key>CFBundleIdentifier</key>
<string>@BUNDLEIDENTIFIER@</string>
<key>NOTE</key>
<string>Please, do NOT change this file -- It was generated by Qt/QMake.</string>
</dict>

View File

@ -14,6 +14,8 @@
<string>@TYPEINFO@</string>
<key>CFBundleExecutable</key>
<string>@LIBRARY@</string>
<key>CFBundleIdentifier</key>
<string>@BUNDLEIDENTIFIER@</string>
<key>NOTE</key>
<string>Please, do NOT change this file -- It was generated by Qt/QMake.</string>
</dict>

View File

@ -14,6 +14,8 @@
<string>@TYPEINFO@</string>
<key>CFBundleExecutable</key>
<string>@LIBRARY@</string>
<key>CFBundleIdentifier</key>
<string>@BUNDLEIDENTIFIER@</string>
<key>NOTE</key>
<string>Please, do NOT change this file -- It was generated by Qt/QMake.</string>
</dict>

View File

@ -14,6 +14,8 @@
<string>@TYPEINFO@</string>
<key>CFBundleExecutable</key>
<string>@LIBRARY@</string>
<key>CFBundleIdentifier</key>
<string>@BUNDLEIDENTIFIER@</string>
<key>NOTE</key>
<string>Please, do NOT change this file -- It was generated by Qt/QMake.</string>
</dict>

View File

@ -14,6 +14,8 @@
<string>@TYPEINFO@</string>
<key>CFBundleExecutable</key>
<string>@LIBRARY@</string>
<key>CFBundleIdentifier</key>
<string>@BUNDLEIDENTIFIER@</string>
<key>NOTE</key>
<string>Please, do NOT change this file -- It was generated by Qt/QMake.</string>
</dict>

View File

@ -14,6 +14,8 @@
<string>@TYPEINFO@</string>
<key>CFBundleExecutable</key>
<string>@LIBRARY@</string>
<key>CFBundleIdentifier</key>
<string>@BUNDLEIDENTIFIER@</string>
<key>NOTE</key>
<string>Please, do NOT change this file -- It was generated by Qt/QMake.</string>
</dict>

View File

@ -24,6 +24,8 @@
<string>1.0</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>

View File

@ -0,0 +1,45 @@
<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>
<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.XIB\" version=\"3.0\" toolsVersion=\"6250\" systemVersion=\"14A343f\" targetRuntime=\"iOS.CocoaTouch\" propertyAccessControl=\"none\" useAutolayout=\"YES\" launchScreen=\"YES\" useTraitCollections=\"YES\">
<dependencies>
<plugIn identifier=\"com.apple.InterfaceBuilder.IBCocoaTouchPlugin\" version=\"6244\"/>
<capability name=\"Constraints with non-1.0 multipliers\" minToolsVersion=\"5.1\"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier=\"IBFilesOwner\" id=\"-1\" userLabel=\"File\'s Owner\"/>
<placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"-2\" customClass=\"UIResponder\"/>
<view contentMode=\"scaleToFill\" id=\"iN0-l3-epB\">
<rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"480\" height=\"480\"/>
<autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>
<subviews>
<label opaque=\"NO\" clipsSubviews=\"YES\" userInteractionEnabled=\"NO\" contentMode=\"left\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" misplaced=\"YES\" text=\"\" textAlignment=\"center\" lineBreakMode=\"tailTruncation\" baselineAdjustment=\"alignBaselines\" minimumFontSize=\"9\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"8ie-xW-0ye\">
<rect key=\"frame\" x=\"20\" y=\"439\" width=\"441\" height=\"21\"/>
<fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"17\"/>
<color key=\"textColor\" cocoaTouchSystemColor=\"darkTextColor\"/>
<nil key=\"highlightedColor\"/>
<variation key=\"widthClass=compact\">
<fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"11\"/>
</variation>
</label>
<label opaque=\"NO\" clipsSubviews=\"YES\" userInteractionEnabled=\"NO\" contentMode=\"left\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" text=\"$$TARGET\"
textAlignment=\"center\" lineBreakMode=\"middleTruncation\" baselineAdjustment=\"alignBaselines\" minimumFontSize=\"18\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"kId-c2-rCX\">
<rect key=\"frame\" x=\"20\" y=\"140\" width=\"441\" height=\"43\"/>
<fontDescription key=\"fontDescription\" type=\"boldSystem\" pointSize=\"36\"/>
<color key=\"textColor\" cocoaTouchSystemColor=\"darkTextColor\"/>
<nil key=\"highlightedColor\"/>
</label>
</subviews>
<color key=\"backgroundColor\" white=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"calibratedWhite\"/>
<constraints>
<constraint firstItem=\"kId-c2-rCX\" firstAttribute=\"centerY\" secondItem=\"iN0-l3-epB\" secondAttribute=\"bottom\" multiplier=\"1/3\" constant=\"1\" id=\"Kid-kn-2rF\"/>
<constraint firstAttribute=\"centerX\" secondItem=\"kId-c2-rCX\" secondAttribute=\"centerX\" id=\"Koa-jz-hwk\"/>
<constraint firstAttribute=\"bottom\" secondItem=\"8ie-xW-0ye\" secondAttribute=\"bottom\" constant=\"20\" id=\"Kzo-t9-V3l\"/>
<constraint firstItem=\"8ie-xW-0ye\" firstAttribute=\"leading\" secondItem=\"iN0-l3-epB\" secondAttribute=\"leading\" constant=\"20\" symbolic=\"YES\" id=\"MfP-vx-nX0\"/>
<constraint firstAttribute=\"centerX\" secondItem=\"8ie-xW-0ye\" secondAttribute=\"centerX\" id=\"ZEH-qu-HZ9\"/>
<constraint firstItem=\"kId-c2-rCX\" firstAttribute=\"leading\" secondItem=\"iN0-l3-epB\" secondAttribute=\"leading\" constant=\"20\" symbolic=\"YES\" id=\"fvb-Df-36g\"/>
</constraints>
<nil key=\"simulatedStatusBarMetrics\"/>
<freeformSimulatedSizeMetrics key=\"simulatedDestinationMetrics\"/>
<point key=\"canvasLocation\" x=\"404\" y=\"445\"/>
</view>
</objects>
</document>

View File

@ -184,6 +184,14 @@ macx-xcode {
QMAKE_SUBSTITUTES += copy_image
launch_images.files = $$copy_image.output
QMAKE_BUNDLE_DATA += launch_images
# Set up default LaunchScreen to support iPhone6/6+
launch_screen = LaunchScreen.xib
copy_launch_screen.input = $$QMAKESPEC/$$launch_screen
copy_launch_screen.output = $$OUT_PWD/$${TARGET}.xcodeproj/$$launch_screen
QMAKE_SUBSTITUTES += copy_launch_screen
launch_screens.files = $$copy_launch_screen.output
QMAKE_BUNDLE_DATA += launch_screens
}
macx-xcode {
@ -193,22 +201,32 @@ macx-xcode {
arch_iphonesimulator.value = $$QMAKE_IOS_SIMULATOR_ARCHS
QMAKE_MAC_XCODE_SETTINGS += arch_iphoneos arch_iphonesimulator
unset(QMAKE_XCODE_ARCHS)
QMAKE_XCODE_ARCHS = $$QMAKE_IOS_DEVICE_ARCHS $$QMAKE_IOS_SIMULATOR_ARCHS
only_active_arch.name = ONLY_ACTIVE_ARCH
only_active_arch.value = YES
only_active_arch.build = debug
QMAKE_MAC_XCODE_SETTINGS += only_active_arch
} else {
# Be more specific about which architecture we're targeting
contains(QT_ARCH, arm.*): \
actual_archs = $$QMAKE_IOS_DEVICE_ARCHS
VALID_ARCHS = $$QMAKE_IOS_DEVICE_ARCHS
else: \
actual_archs = $$QMAKE_IOS_SIMULATOR_ARCHS
VALID_ARCHS = $$QMAKE_IOS_SIMULATOR_ARCHS
for(arch, actual_archs): \
arch_flags += -arch $$arch
single_arch: VALID_ARCHS = $$first(VALID_ARCHS)
ACTIVE_ARCHS = $(filter $(EXPORT_VALID_ARCHS), $(ARCHS))
ARCH_ARGS = $(foreach arch, $(if $(EXPORT_ACTIVE_ARCHS), $(EXPORT_ACTIVE_ARCHS), $(EXPORT_VALID_ARCHS)), -arch $(arch))
QMAKE_EXTRA_VARIABLES += VALID_ARCHS ACTIVE_ARCHS ARCH_ARGS
arch_flags = $(EXPORT_ARCH_ARGS)
QMAKE_CFLAGS += $$arch_flags
QMAKE_CXXFLAGS += $$arch_flags
QMAKE_OBJECTIVE_CFLAGS += $$arch_flags
QMAKE_LFLAGS += $$arch_flags
}
unset(actual_archs)
load(default_post)

View File

@ -32,17 +32,19 @@ equals(TEMPLATE, app):contains(QT, gui(-private)?) {
# called 'qt_main' now.
macx-xcode {
objects_dir = "${OBJECT_FILE_DIR}-${CURRENT_VARIANT}/${CURRENT_ARCH}"
objects_dir = "${OBJECT_FILE_DIR}-${CURRENT_VARIANT}"
archs = "${ARCHS}"
} else {
objects_dir = $$OBJECTS_DIR
isEmpty(objects_dir): \
objects_dir = .
archs = "$$QMAKE_IOS_DEVICE_ARCHS $$QMAKE_IOS_SIMULATOR_ARCHS"
}
!isEmpty(QMAKE_PRE_LINK): \
QMAKE_PRE_LINK += ";"
QMAKE_PRE_LINK += $$QMAKESPEC/rename_main.sh $${objects_dir}
QMAKE_PRE_LINK += $$QMAKESPEC/rename_main.sh $${objects_dir} \"$${archs}\"
}
}

View File

@ -9,4 +9,8 @@ isEmpty(QT_ARCH) {
QT_ARCH = arm
else: \ # Simulator
QT_ARCH = i386
# Prevent the arch/config tests from building as multi-arch binaries,
# as we only want the lowest common denominator features.
CONFIG += single_arch
}

View File

@ -15,8 +15,8 @@ DEFINES += DARWIN_NO_CARBON QT_NO_PRINTER QT_NO_PRINTDIALOG
# Universal target (iPhone and iPad)
QMAKE_IOS_TARGETED_DEVICE_FAMILY = 1,2
QMAKE_IOS_DEVICE_ARCHS = armv7
QMAKE_IOS_SIMULATOR_ARCHS = i386
QMAKE_IOS_DEVICE_ARCHS = armv7 arm64
QMAKE_IOS_SIMULATOR_ARCHS = i386 x86_64
include(../common/ios.conf)
include(../common/gcc-base-mac.conf)

View File

@ -41,10 +41,14 @@
##
#############################################################################
if [ $# -eq 0 ]; then
echo "usage: $0 <path to object files>"
if [ $# -ne 2 ]; then
echo "$0: wrong number of arguments for internal tool used by iOS mkspec"
else
for f in $(find $1 -name '*.o'); do
arch_paths=""
for a in $2; do
arch_paths="$arch_paths $1/$a"
done
for f in $(find $arch_paths -name '*.o'); do
# Skip object files without the _main symbol
nm $f 2>/dev/null | grep -q 'T _main$' || continue

View File

@ -14,6 +14,8 @@
<string>@TYPEINFO@</string>
<key>CFBundleExecutable</key>
<string>@LIBRARY@</string>
<key>CFBundleIdentifier</key>
<string>@BUNDLEIDENTIFIER@</string>
<key>NOTE</key>
<string>Please, do NOT change this file -- It was generated by Qt/QMake.</string>
</dict>

View File

@ -13,6 +13,7 @@ QMAKE_CXXFLAGS_THREAD = $$QMAKE_CFLAGS_THREAD
QMAKE_INCDIR = /usr/local/include
QMAKE_LIBDIR = /usr/local/lib
QMAKE_LFLAGS_NOUNDEF = -Wl,--no-undefined
QMAKE_LFLAGS_THREAD = -pthread
QMAKE_LIBS =
@ -28,6 +29,5 @@ QMAKE_RANLIB =
include(../../common/unix.conf)
include(../../common/gcc-base-unix.conf)
include(../../common/g++-unix.conf)
include(../../common/clang.conf)
load(qt_config)

View File

@ -1029,6 +1029,21 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
if (!project->isEmpty("QMAKE_PRE_LINK")) {
QString phase_key = keyFor("QMAKE_PBX_PRELINK_BUILDPHASE");
project->values("QMAKE_PBX_BUILDPHASES").append(phase_key);
ProStringList inputPaths;
ProStringList outputPaths;
const ProStringList &archs = project->values("QMAKE_XCODE_ARCHS");
if (!archs.isEmpty()) {
for (int i = 0; i < archs.size(); ++i) {
const ProString &arch = archs.at(i);
inputPaths << "$(OBJECT_FILE_DIR_$(CURRENT_VARIANT))/" + arch + "/";
outputPaths << "$(LINK_FILE_LIST_$(CURRENT_VARIANT)_" + arch + ")";
}
} else {
inputPaths << "$(OBJECT_FILE_DIR_$(CURRENT_VARIANT))/$(CURRENT_ARCH)/";
outputPaths << "$(LINK_FILE_LIST_$(CURRENT_VARIANT)_$(CURRENT_ARCH))";
}
t << "\t\t" << phase_key << " = {\n"
<< "\t\t\t" << writeSettings("buildActionMask", "2147483647", SettingsNoQuote) << ";\n"
<< "\t\t\t" << writeSettings("files", ProStringList(), SettingsAsList, 4) << ";\n"
@ -1036,8 +1051,8 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
// resolved dependenices, so we have to ensure that this phase is run after the
// compilation phase, and before the link phase. Making the phase depend on the
// object file directory, and "write" to the list of files to link achieves that.
<< "\t\t\t" << writeSettings("inputPaths", ProStringList("$(OBJECT_FILE_DIR_$(CURRENT_VARIANT))/$(CURRENT_ARCH)/"), SettingsAsList, 4) << ";\n"
<< "\t\t\t" << writeSettings("outputPaths", ProStringList("$(LINK_FILE_LIST_$(CURRENT_VARIANT)_$(CURRENT_ARCH))"), SettingsAsList, 4) << ";\n"
<< "\t\t\t" << writeSettings("inputPaths", inputPaths, SettingsAsList, 4) << ";\n"
<< "\t\t\t" << writeSettings("outputPaths", outputPaths, SettingsAsList, 4) << ";\n"
<< "\t\t\t" << writeSettings("isa", "PBXShellScriptBuildPhase", SettingsNoQuote) << ";\n"
<< "\t\t\t" << writeSettings("runOnlyForDeploymentPostprocessing", "0", SettingsNoQuote) << ";\n"
<< "\t\t\t" << writeSettings("name", "Qt Prelink") << ";\n"

View File

@ -814,22 +814,26 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t)
}
commonSedArgs << "-e \"s,@TYPEINFO@,"<< (project->isEmpty("QMAKE_PKGINFO_TYPEINFO") ?
QString::fromLatin1("????") : project->first("QMAKE_PKGINFO_TYPEINFO").left(4)) << ",g\" ";
QString bundlePrefix = project->first("QMAKE_TARGET_BUNDLE_PREFIX").toQString();
if (bundlePrefix.isEmpty())
bundlePrefix = "com.yourcompany";
if (bundlePrefix.endsWith("."))
bundlePrefix.chop(1);
QString bundleIdentifier = bundlePrefix + "." + var("QMAKE_BUNDLE");
if (bundleIdentifier.endsWith(".app"))
bundleIdentifier.chop(4);
if (bundleIdentifier.endsWith(".framework"))
bundleIdentifier.chop(10);
commonSedArgs << "-e \"s,@BUNDLEIDENTIFIER@," << bundleIdentifier << ",g\" ";
if (isApp) {
QString icon = fileFixify(var("ICON"));
QString bundlePrefix = project->first("QMAKE_TARGET_BUNDLE_PREFIX").toQString();
if (bundlePrefix.isEmpty())
bundlePrefix = "com.yourcompany";
if (bundlePrefix.endsWith("."))
bundlePrefix.chop(1);
QString bundleIdentifier = bundlePrefix + "." + var("QMAKE_BUNDLE");
if (bundleIdentifier.endsWith(".app"))
bundleIdentifier.chop(4);
t << "@$(DEL_FILE) " << info_plist_out << "\n\t"
<< "@sed ";
foreach (const ProString &arg, commonSedArgs)
t << arg;
t << "-e \"s,@ICON@," << icon.section(Option::dir_sep, -1) << ",g\" "
<< "-e \"s,@BUNDLEIDENTIFIER@," << bundleIdentifier << ",g\" "
<< "-e \"s,@EXECUTABLE@," << var("QMAKE_ORIG_TARGET") << ",g\" "
<< "-e \"s,@TYPEINFO@,"<< (project->isEmpty("QMAKE_PKGINFO_TYPEINFO") ?
QString::fromLatin1("????") : project->first("QMAKE_PKGINFO_TYPEINFO").left(4)) << ",g\" "

View File

@ -1915,10 +1915,10 @@ bool VCXProjectWriter::outputFileConfig(OutputFilterData *d, XmlOutput &xml, Xml
}
// Actual XML output ----------------------------------
if (hasCustomBuildStep || filter.useCompilerTool
if (hasCustomBuildStep || filter.useCustomBuildTool || filter.useCompilerTool
|| !d->inBuild || filter.Name.startsWith("Deployment Files")) {
if (hasCustomBuildStep)
if (hasCustomBuildStep || filter.useCustomBuildTool)
{
if (!fileAdded) {
fileAdded = true;

View File

@ -21,10 +21,12 @@ Mozilla Corporation
Turbulenz
Klarälvdalens Datakonsult AB
Microsoft Open Technologies, Inc.
NVIDIA Corporation
Jacek Caban
Mark Callow
Ginn Chen
Tibor den Ouden
James Hauxwell
Sam Hocevar
Pierre Leveille

View File

@ -78,7 +78,12 @@ Turbulenz
Ulrik Persson (ddefrostt)
Mark Banner (standard8mbp)
David Kilzer
Jacek Caban
Tibor den Ouden
Microsoft Open Technologies, Inc.
Cooper Partin
Austin Kinross
NVIDIA Corporation
Olli Etuaho

View File

@ -238,7 +238,7 @@ EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext (void);
#ifndef EGL_VERSION_1_5
#define EGL_VERSION_1_5 1
typedef void *EGLSync;
typedef khronos_intptr_t EGLAttrib;
typedef intptr_t EGLAttrib;
typedef khronos_utime_nanoseconds_t EGLTime;
#define EGL_CONTEXT_MAJOR_VERSION 0x3098
#define EGL_CONTEXT_MINOR_VERSION 0x30FB

View File

@ -59,7 +59,7 @@ extern "C" {
#ifndef EGL_KHR_cl_event2
#define EGL_KHR_cl_event2 1
typedef void *EGLSyncKHR;
typedef khronos_intptr_t EGLAttribKHR;
typedef intptr_t EGLAttribKHR;
typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESYNC64KHRPROC) (EGLDisplay dpy, EGLenum type, const EGLAttribKHR *attrib_list);
#ifdef EGL_EGLEXT_PROTOTYPES
EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSync64KHR (EGLDisplay dpy, EGLenum type, const EGLAttribKHR *attrib_list);
@ -442,20 +442,22 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurfacePointerANGLE (EGLDisplay dpy, EGLSu
#define EGL_ANGLE_platform_angle 1
#define EGL_PLATFORM_ANGLE_ANGLE 0x3201
#define EGL_PLATFORM_ANGLE_TYPE_ANGLE 0x3202
#define EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE 0x3203
#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
#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 0x3204
#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3205
#define EGL_PLATFORM_ANGLE_TYPE_D3D11_WARP_ANGLE 0x3206
#define EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE 0x3206
#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3207
#define EGL_PLATFORM_ANGLE_USE_WARP_ANGLE 0x3208
#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 0x3207
#define EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE 0x3208
#define EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE 0x3209
#define EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE 0x320A
#endif /* EGL_ANGLE_platform_angle_opengl */
#ifndef EGL_ARM_pixmap_multisample_discard

View File

@ -67,23 +67,22 @@
* implementations.
*/
#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP) /* Windows Runtime */
struct IUnknown;
typedef IUnknown *EGLNativeDisplayType;
typedef void *EGLNativePixmapType;
typedef IUnknown *EGLNativeWindowType;
#elif defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) /* Win32 and WinCE */
#if defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) /* Win32 and WinCE */
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN 1
#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;
typedef HWND EGLNativeWindowType;
#endif
#elif defined(__WINSCW__) || defined(__SYMBIAN32__) /* Symbian */

View File

@ -27,6 +27,10 @@
#include "KHR/khrplatform.h"
#include <map>
#include <string>
#include <vector>
//
// This is the platform independent interface between an OGL driver
// and the shading language compiler.
@ -42,18 +46,17 @@ typedef unsigned int GLenum;
// Note: make sure to increment ANGLE_SH_VERSION when changing ShaderVars.h
#include "ShaderVars.h"
#ifdef __cplusplus
extern "C" {
#endif
// Version number for shader translation API.
// It is incremented every time the API changes.
#define ANGLE_SH_VERSION 130
#define ANGLE_SH_VERSION 132
typedef enum {
SH_GLES2_SPEC = 0x8B40,
SH_WEBGL_SPEC = 0x8B41,
SH_GLES3_SPEC = 0x8B86,
SH_WEBGL2_SPEC = 0x8B87,
// The CSS Shaders spec is a subset of the WebGL spec.
//
// In both CSS vertex and fragment shaders, ANGLE:
@ -85,31 +88,6 @@ typedef enum {
SH_HLSL11_OUTPUT = 0x8B48
} ShShaderOutput;
typedef enum {
SH_PRECISION_HIGHP = 0x5001,
SH_PRECISION_MEDIUMP = 0x5002,
SH_PRECISION_LOWP = 0x5003,
SH_PRECISION_UNDEFINED = 0
} ShPrecisionType;
typedef enum {
SH_INFO_LOG_LENGTH = 0x8B84,
SH_OBJECT_CODE_LENGTH = 0x8B88, // GL_SHADER_SOURCE_LENGTH
SH_ACTIVE_UNIFORMS = 0x8B86,
SH_ACTIVE_UNIFORM_MAX_LENGTH = 0x8B87,
SH_ACTIVE_ATTRIBUTES = 0x8B89,
SH_ACTIVE_ATTRIBUTE_MAX_LENGTH = 0x8B8A,
SH_VARYINGS = 0x8BBB,
SH_VARYING_MAX_LENGTH = 0x8BBC,
SH_MAPPED_NAME_MAX_LENGTH = 0x6000,
SH_NAME_MAX_LENGTH = 0x6001,
SH_HASHED_NAME_MAX_LENGTH = 0x6002,
SH_HASHED_NAMES_COUNT = 0x6003,
SH_SHADER_VERSION = 0x6004,
SH_RESOURCES_STRING_LENGTH = 0x6005,
SH_OUTPUT_TYPE = 0x6006
} ShShaderInfo;
// Compile options.
typedef enum {
SH_VALIDATE = 0,
@ -208,14 +186,14 @@ typedef enum {
//
// Driver must call this first, once, before doing any other
// compiler operations.
// If the function succeeds, the return value is nonzero, else zero.
// If the function succeeds, the return value is true, else false.
//
COMPILER_EXPORT int ShInitialize();
COMPILER_EXPORT bool ShInitialize();
//
// Driver should call this at shutdown.
// If the function succeeds, the return value is nonzero, else zero.
// If the function succeeds, the return value is true, else false.
//
COMPILER_EXPORT int ShFinalize();
COMPILER_EXPORT bool ShFinalize();
// The 64 bits hash function. The first parameter is the input string; the
// second parameter is the string length.
@ -246,6 +224,12 @@ typedef struct
int EXT_frag_depth;
int EXT_shader_texture_lod;
// 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
// EXT_draw_buffers by using it in combination with GLES3.0 glDrawBuffers
// function. This applies to Tegra K1 devices.
int NV_draw_buffers;
// Set to 1 if highp precision is supported in the fragment language.
// Default is 0.
int FragmentPrecisionHigh;
@ -274,8 +258,10 @@ typedef struct
//
// Initialize built-in resources with minimum expected values.
// Parameters:
// resources: The object to initialize. Will be comparable with memcmp.
//
COMPILER_EXPORT void ShInitBuiltInResources(ShBuiltInResources* resources);
COMPILER_EXPORT void ShInitBuiltInResources(ShBuiltInResources *resources);
//
// ShHandle held by but opaque to the driver. It is allocated,
@ -284,18 +270,15 @@ COMPILER_EXPORT void ShInitBuiltInResources(ShBuiltInResources* resources);
//
// If handle creation fails, 0 will be returned.
//
typedef void* ShHandle;
typedef void *ShHandle;
//
// Returns the a concatenated list of the items in ShBuiltInResources as a string.
// Returns the a concatenated list of the items in ShBuiltInResources as a
// null-terminated string.
// This function must be updated whenever ShBuiltInResources is changed.
// Parameters:
// handle: Specifies the handle of the compiler to be used.
// outStringLen: Specifies the size of the buffer, in number of characters. The size
// of the buffer required to store the resources string can be obtained
// by calling ShGetInfo with SH_RESOURCES_STRING_LENGTH.
// outStr: Returns a null-terminated string representing all the built-in resources.
COMPILER_EXPORT void ShGetBuiltInResourcesString(const ShHandle handle, size_t outStringLen, char *outStr);
COMPILER_EXPORT const std::string &ShGetBuiltInResourcesString(const ShHandle handle);
//
// Driver calls these to create and destroy compiler objects.
@ -313,12 +296,12 @@ COMPILER_EXPORT ShHandle ShConstructCompiler(
sh::GLenum type,
ShShaderSpec spec,
ShShaderOutput output,
const ShBuiltInResources* resources);
const ShBuiltInResources *resources);
COMPILER_EXPORT void ShDestruct(ShHandle handle);
//
// Compiles the given shader source.
// If the function succeeds, the return value is nonzero, else zero.
// If the function succeeds, the return value is true, else false.
// Parameters:
// handle: Specifies the handle of compiler to be used.
// shaderStrings: Specifies an array of pointers to null-terminated strings
@ -340,123 +323,36 @@ COMPILER_EXPORT void ShDestruct(ShHandle handle);
// SH_VARIABLES: Extracts attributes, uniforms, and varyings.
// Can be queried by calling ShGetVariableInfo().
//
COMPILER_EXPORT int ShCompile(
COMPILER_EXPORT bool ShCompile(
const ShHandle handle,
const char* const shaderStrings[],
const char * const shaderStrings[],
size_t numStrings,
int compileOptions
);
int compileOptions);
// Returns a parameter from a compiled shader.
// Return the version of the shader language.
COMPILER_EXPORT int ShGetShaderVersion(const ShHandle handle);
// Return the currently set language output type.
COMPILER_EXPORT ShShaderOutput ShGetShaderOutputType(
const ShHandle handle);
// Returns null-terminated information log for a compiled shader.
// Parameters:
// handle: Specifies the compiler
// pname: Specifies the parameter to query.
// The following parameters are defined:
// SH_INFO_LOG_LENGTH: the number of characters in the information log
// including the null termination character.
// SH_OBJECT_CODE_LENGTH: the number of characters in the object code
// including the null termination character.
// SH_ACTIVE_ATTRIBUTES: the number of active attribute variables.
// SH_ACTIVE_ATTRIBUTE_MAX_LENGTH: the length of the longest active attribute
// variable name including the null
// termination character.
// SH_ACTIVE_UNIFORMS: the number of active uniform variables.
// SH_ACTIVE_UNIFORM_MAX_LENGTH: the length of the longest active uniform
// variable name including the null
// termination character.
// SH_VARYINGS: the number of varying variables.
// SH_VARYING_MAX_LENGTH: the length of the longest varying variable name
// including the null termination character.
// SH_MAPPED_NAME_MAX_LENGTH: the length of the mapped variable name including
// the null termination character.
// SH_NAME_MAX_LENGTH: the max length of a user-defined name including the
// null termination character.
// SH_HASHED_NAME_MAX_LENGTH: the max length of a hashed name including the
// null termination character.
// SH_HASHED_NAMES_COUNT: the number of hashed names from the latest compile.
// SH_SHADER_VERSION: the version of the shader language
// SH_OUTPUT_TYPE: the currently set language output type
//
// params: Requested parameter
COMPILER_EXPORT void ShGetInfo(const ShHandle handle,
ShShaderInfo pname,
size_t* params);
// Returns nul-terminated information log for a compiled shader.
// Parameters:
// handle: Specifies the compiler
// infoLog: Specifies an array of characters that is used to return
// the information log. It is assumed that infoLog has enough memory
// to accomodate the information log. The size of the buffer required
// to store the returned information log can be obtained by calling
// ShGetInfo with SH_INFO_LOG_LENGTH.
COMPILER_EXPORT void ShGetInfoLog(const ShHandle handle, char* infoLog);
COMPILER_EXPORT const std::string &ShGetInfoLog(const ShHandle handle);
// Returns null-terminated object code for a compiled shader.
// Parameters:
// handle: Specifies the compiler
// infoLog: Specifies an array of characters that is used to return
// the object code. It is assumed that infoLog has enough memory to
// accomodate the object code. The size of the buffer required to
// store the returned object code can be obtained by calling
// ShGetInfo with SH_OBJECT_CODE_LENGTH.
COMPILER_EXPORT void ShGetObjectCode(const ShHandle handle, char* objCode);
COMPILER_EXPORT const std::string &ShGetObjectCode(const ShHandle handle);
// Returns information about a shader variable.
// Returns a (original_name, hash) map containing all the user defined
// names in the shader, including variable names, function names, struct
// names, and struct field names.
// Parameters:
// handle: Specifies the compiler
// variableType: Specifies the variable type; options include
// SH_ACTIVE_ATTRIBUTES, SH_ACTIVE_UNIFORMS, SH_VARYINGS.
// index: Specifies the index of the variable to be queried.
// length: Returns the number of characters actually written in the string
// indicated by name (excluding the null terminator) if a value other
// than NULL is passed.
// size: Returns the size of the variable.
// type: Returns the data type of the variable.
// precision: Returns the precision of the variable.
// staticUse: Returns 1 if the variable is accessed in a statement after
// pre-processing, whether or not run-time flow of control will
// cause that statement to be executed.
// Returns 0 otherwise.
// name: Returns a null terminated string containing the name of the
// variable. It is assumed that name has enough memory to accormodate
// the variable name. The size of the buffer required to store the
// variable name can be obtained by calling ShGetInfo with
// SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, SH_ACTIVE_UNIFORM_MAX_LENGTH,
// SH_VARYING_MAX_LENGTH.
// mappedName: Returns a null terminated string containing the mapped name of
// the variable, It is assumed that mappedName has enough memory
// (SH_MAPPED_NAME_MAX_LENGTH), or NULL if don't care about the
// mapped name. If the name is not mapped, then name and mappedName
// are the same.
COMPILER_EXPORT void ShGetVariableInfo(const ShHandle handle,
ShShaderInfo variableType,
int index,
size_t* length,
int* size,
sh::GLenum* type,
ShPrecisionType* precision,
int* staticUse,
char* name,
char* mappedName);
// Returns information about a name hashing entry from the latest compile.
// Parameters:
// handle: Specifies the compiler
// index: Specifies the index of the name hashing entry to be queried.
// name: Returns a null terminated string containing the user defined name.
// It is assumed that name has enough memory to accomodate the name.
// The size of the buffer required to store the user defined name can
// be obtained by calling ShGetInfo with SH_NAME_MAX_LENGTH.
// hashedName: Returns a null terminated string containing the hashed name of
// the uniform variable, It is assumed that hashedName has enough
// memory to accomodate the name. The size of the buffer required
// to store the name can be obtained by calling ShGetInfo with
// SH_HASHED_NAME_MAX_LENGTH.
COMPILER_EXPORT void ShGetNameHashingEntry(const ShHandle handle,
int index,
char* name,
char* hashedName);
COMPILER_EXPORT const std::map<std::string, std::string> *ShGetNameHashingMap(
const ShHandle handle);
// Shader variable inspection.
// Returns a pointer to a list of variables of the designated type.
@ -476,17 +372,17 @@ typedef struct
int size;
} ShVariableInfo;
// Returns 1 if the passed in variables pack in maxVectors following
// Returns true if the passed in variables pack in maxVectors following
// the packing rules from the GLSL 1.017 spec, Appendix A, section 7.
// Returns 0 otherwise. Also look at the SH_ENFORCE_PACKING_RESTRICTIONS
// Returns false otherwise. Also look at the SH_ENFORCE_PACKING_RESTRICTIONS
// flag above.
// Parameters:
// maxVectors: the available rows of registers.
// varInfoArray: an array of variable info (types and sizes).
// varInfoArraySize: the size of the variable array.
COMPILER_EXPORT int ShCheckVariablesWithinPackingLimits(
COMPILER_EXPORT bool ShCheckVariablesWithinPackingLimits(
int maxVectors,
ShVariableInfo* varInfoArray,
ShVariableInfo *varInfoArray,
size_t varInfoArraySize);
// Gives the compiler-assigned register for an interface block.
@ -497,7 +393,7 @@ COMPILER_EXPORT int ShCheckVariablesWithinPackingLimits(
// interfaceBlockName: Specifies the interface block
// indexOut: output variable that stores the assigned register
COMPILER_EXPORT bool ShGetInterfaceBlockRegister(const ShHandle handle,
const char *interfaceBlockName,
const std::string &interfaceBlockName,
unsigned int *indexOut);
// Gives the compiler-assigned register for uniforms in the default
@ -509,11 +405,7 @@ COMPILER_EXPORT bool ShGetInterfaceBlockRegister(const ShHandle handle,
// interfaceBlockName: Specifies the uniform
// indexOut: output variable that stores the assigned register
COMPILER_EXPORT bool ShGetUniformRegister(const ShHandle handle,
const char *uniformName,
const std::string &uniformName,
unsigned int *indexOut);
#ifdef __cplusplus
}
#endif
#endif // _COMPILER_INTERFACE_INCLUDED_

View File

@ -52,6 +52,21 @@ struct COMPILER_EXPORT ShaderVariable
unsigned int elementCount() const { return std::max(1u, arraySize); }
bool isStruct() const { return !fields.empty(); }
// All of the shader's variables are described using nested data
// structures. This is needed in order to disambiguate similar looking
// types, such as two structs containing the same fields, but in
// different orders. "findInfoByMappedName" provides an easy query for
// users to dive into the data structure and fetch the unique variable
// instance corresponding to a dereferencing chain of the top-level
// variable.
// Given a mapped name like 'a[0].b.c[0]', return the ShaderVariable
// that defines 'c' in |leafVar|, and the original name 'A[0].B.C[0]'
// in |originalName|, based on the assumption that |this| defines 'a'.
// If no match is found, return false.
bool findInfoByMappedName(const std::string &mappedFullName,
const ShaderVariable **leafVar,
std::string* originalFullName) const;
GLenum type;
GLenum precision;
std::string name;
@ -60,6 +75,16 @@ struct COMPILER_EXPORT ShaderVariable
bool staticUse;
std::vector<ShaderVariable> fields;
std::string structName;
protected:
bool isSameVariableAtLinkTime(const ShaderVariable &other,
bool matchPrecision) const;
bool operator==(const ShaderVariable &other) const;
bool operator!=(const ShaderVariable &other) const
{
return !operator==(other);
}
};
struct COMPILER_EXPORT Uniform : public ShaderVariable
@ -68,6 +93,16 @@ struct COMPILER_EXPORT Uniform : public ShaderVariable
~Uniform();
Uniform(const Uniform &other);
Uniform &operator=(const Uniform &other);
bool operator==(const Uniform &other) const;
bool operator!=(const Uniform &other) const
{
return !operator==(other);
}
// Decide whether two uniforms are the same at shader link time,
// assuming one from vertex shader and the other from fragment shader.
// See GLSL ES Spec 3.00.3, sec 4.3.5.
bool isSameUniformAtLinkTime(const Uniform &other) const;
};
struct COMPILER_EXPORT Attribute : public ShaderVariable
@ -76,6 +111,11 @@ struct COMPILER_EXPORT Attribute : public ShaderVariable
~Attribute();
Attribute(const Attribute &other);
Attribute &operator=(const Attribute &other);
bool operator==(const Attribute &other) const;
bool operator!=(const Attribute &other) const
{
return !operator==(other);
}
int location;
};
@ -86,6 +126,18 @@ struct COMPILER_EXPORT InterfaceBlockField : public ShaderVariable
~InterfaceBlockField();
InterfaceBlockField(const InterfaceBlockField &other);
InterfaceBlockField &operator=(const InterfaceBlockField &other);
bool operator==(const InterfaceBlockField &other) const;
bool operator!=(const InterfaceBlockField &other) const
{
return !operator==(other);
}
// Decide whether two InterfaceBlock fields are the same at shader
// link time, assuming one from vertex shader and the other from
// fragment shader.
// See GLSL ES Spec 3.00.3, sec 4.3.7.
bool isSameInterfaceBlockFieldAtLinkTime(
const InterfaceBlockField &other) const;
bool isRowMajorLayout;
};
@ -94,8 +146,18 @@ struct COMPILER_EXPORT Varying : public ShaderVariable
{
Varying();
~Varying();
Varying(const Varying &other);
Varying(const Varying &otherg);
Varying &operator=(const Varying &other);
bool operator==(const Varying &other) const;
bool operator!=(const Varying &other) const
{
return !operator==(other);
}
// Decide whether two varyings are the same at shader link time,
// assuming one from vertex shader and the other from fragment shader.
// See GLSL ES Spec 3.00.3, sec 4.3.9.
bool isSameVaryingAtLinkTime(const Varying &other) const;
InterpolationType interpolation;
bool isInvariant;

View File

@ -0,0 +1,37 @@
//
// 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.
//
// angle_windowsstore.h:
#ifndef ANGLE_WINDOWSSTORE_H_
#define ANGLE_WINDOWSSTORE_H_
// The following properties can be set on the CoreApplication to support additional
// ANGLE configuration options.
//
// The Visual Studio sample templates provided with this version of ANGLE have examples
// of how to set these property values.
//
// Property: EGLNativeWindowTypeProperty
// Type: IInspectable
// Description: Set this property to specify the window type to use for creating a surface.
// If this property is missing, surface creation will fail.
//
const wchar_t EGLNativeWindowTypeProperty[] = L"EGLNativeWindowTypeProperty";
//
// Property: EGLRenderSurfaceSizeProperty
// Type: Size
// Description: Set this property to specify a preferred size in pixels of the render surface.
// The render surface size width and height must be greater than 0.
// If this property is set, then the render surface size is fixed.
// If this property is missing, a default behavior will be provided.
// The default behavior uses the window size if a CoreWindow is specified or
// the size of the SwapChainPanel control if one is specified.
//
const wchar_t EGLRenderSurfaceSizeProperty[] = L"EGLRenderSurfaceSizeProperty";
#endif // ANGLE_WINDOWSSTORE_H_

View File

@ -7,6 +7,6 @@
// This is a default commit hash header, when git is not available.
//
#define ANGLE_COMMIT_HASH "abce76206141"
#define ANGLE_COMMIT_HASH "30d6c255d238"
#define ANGLE_COMMIT_HASH_SIZE 12
#define ANGLE_COMMIT_DATE "2014-09-23 19:37:05 +0000"
#define ANGLE_COMMIT_DATE "2014-11-13 17:37:03 +0000"

View File

@ -0,0 +1,82 @@
//
// 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.
//
// NativeWindow.h: Defines NativeWindow, a class for managing and
// performing operations on an EGLNativeWindowType.
// It is used for HWND (Desktop Windows) and IInspectable objects
//(Windows Store Applications).
#ifndef COMMON_NATIVEWINDOW_H_
#define COMMON_NATIVEWINDOW_H_
#include <EGL/eglplatform.h>
#include "common/debug.h"
#include "common/platform.h"
// DXGISwapChain and DXGIFactory are typedef'd to specific required
// types. The HWND NativeWindow implementation requires IDXGISwapChain
// and IDXGIFactory and the Windows Store NativeWindow
// implementation requires IDXGISwapChain1 and IDXGIFactory2.
#if defined(ANGLE_ENABLE_WINDOWS_STORE)
typedef IDXGISwapChain1 DXGISwapChain;
typedef IDXGIFactory2 DXGIFactory;
#include <wrl.h>
#include <wrl/wrappers/corewrappers.h>
#include <windows.applicationmodel.core.h>
#include <memory>
namespace rx
{
class InspectableNativeWindow;
}
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;
#else
typedef IDXGISwapChain DXGISwapChain;
typedef IDXGIFactory DXGIFactory;
#endif
namespace rx
{
class NativeWindow
{
public:
explicit NativeWindow(EGLNativeWindowType window, EGLNativeDisplayType display);
bool initialize();
bool getClientRect(LPRECT rect);
bool isIconic();
# if defined(ANGLE_ENABLE_D3D11)
typedef ID3D11Device Device;
#else
typedef IDirect3DDevice9 Device;
#endif
HRESULT createSwapChain(Device* device, DXGIFactory* factory,
DXGI_FORMAT format, UINT width, UINT height,
DXGISwapChain** swapChain);
inline EGLNativeWindowType getNativeWindow() const { return mWindow; }
inline EGLNativeDisplayType getNativeDisplay() const { return mDisplay; }
private:
EGLNativeWindowType mWindow;
EGLNativeDisplayType mDisplay;
#if defined(ANGLE_ENABLE_WINDOWS_STORE)
std::shared_ptr<InspectableNativeWindow> mImpl;
#endif
};
bool IsValidEGLNativeWindowType(EGLNativeWindowType window);
}
#endif // COMMON_NATIVEWINDOW_H_

View File

@ -5,26 +5,33 @@
//
#include "common/angleutils.h"
#include "debug.h"
#include <stdio.h>
#include <vector>
size_t FormatStringIntoVector(const char *fmt, va_list vararg, std::vector<char>& outBuffer)
{
// Attempt to just print to the current buffer
int len = vsnprintf(&(outBuffer.front()), outBuffer.size(), fmt, vararg);
if (len < 0 || static_cast<size_t>(len) >= outBuffer.size())
{
// Buffer was not large enough, calculate the required size and resize the buffer
len = vsnprintf(NULL, 0, fmt, vararg);
outBuffer.resize(len + 1);
// Print again
len = vsnprintf(&(outBuffer.front()), outBuffer.size(), fmt, vararg);
}
ASSERT(len >= 0);
return static_cast<size_t>(len);
}
std::string FormatString(const char *fmt, va_list vararg)
{
static std::vector<char> buffer(512);
// Attempt to just print to the current buffer
int len = vsnprintf(&buffer[0], buffer.size(), fmt, vararg);
if (len < 0 || static_cast<size_t>(len) >= buffer.size())
{
// Buffer was not large enough, calculate the required size and resize the buffer
len = vsnprintf(NULL, 0, fmt, vararg);
buffer.resize(len + 1);
// Print again
vsnprintf(&buffer[0], buffer.size(), fmt, vararg);
}
return std::string(buffer.data(), len);
size_t len = FormatStringIntoVector(fmt, vararg, buffer);
return std::string(&buffer[0], len);
}
std::string FormatString(const char *fmt, ...)

View File

@ -17,6 +17,7 @@
#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
@ -95,6 +96,13 @@ inline void StructZero(T *obj)
memset(obj, 0, sizeof(T));
}
template <typename T>
inline bool IsMaskFlagSet(T mask, T flag)
{
// Handles multibit flags as well
return (mask & flag) == flag;
}
inline const char* MakeStaticString(const std::string &str)
{
static std::set<std::string> strings;
@ -132,9 +140,12 @@ inline std::string Str(int i)
return strstr.str();
}
size_t FormatStringIntoVector(const char *fmt, va_list vararg, std::vector<char>& buffer);
std::string FormatString(const char *fmt, va_list vararg);
std::string FormatString(const char *fmt, ...);
// snprintf is not defined with MSVC prior to to msvc14
#if defined(_MSC_VER) && _MSC_VER < 1900
#define snprintf _snprintf
#endif

View File

@ -17,41 +17,211 @@
namespace gl
{
#if defined(ANGLE_ENABLE_PERF)
typedef void (WINAPI *PerfOutputFunction)(D3DCOLOR, LPCWSTR);
#else
typedef void (*PerfOutputFunction)(unsigned int, const wchar_t*);
#endif
static void output(bool traceFileDebugOnly, PerfOutputFunction perfFunc, const char *format, va_list vararg)
#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
// Wraps the D3D9/D3D11 debug annotation functions.
class DebugAnnotationWrapper
{
#if defined(ANGLE_ENABLE_PERF) || defined(ANGLE_ENABLE_TRACE)
std::string formattedMessage = FormatString(format, vararg);
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
#if defined(ANGLE_ENABLE_PERF)
// 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,
DebugTraceOutputTypeSetMarker,
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);
if (perfActive())
{
// The perf function only accepts wide strings, widen the ascii message
static std::wstring wideMessage;
if (wideMessage.capacity() < formattedMessage.length())
size_t len = FormatStringIntoVector(format, vararg, buffer);
std::wstring formattedWideMessage(buffer.begin(), buffer.begin() + len);
switch (outputType)
{
wideMessage.reserve(formattedMessage.size());
case DebugTraceOutputTypeNone:
break;
case DebugTraceOutputTypeBeginEvent:
g_DebugAnnotationWrapper->beginEvent(formattedWideMessage);
break;
case DebugTraceOutputTypeSetMarker:
g_DebugAnnotationWrapper->setMarker(formattedWideMessage);
break;
}
wideMessage.assign(formattedMessage.begin(), formattedMessage.end());
perfFunc(0, wideMessage.c_str());
}
#endif // ANGLE_ENABLE_PERF
#endif // ANGLE_ENABLE_DEBUG_ANNOTATIONS
#if defined(ANGLE_ENABLE_TRACE)
#if defined(ANGLE_ENABLE_DEBUG_TRACE)
#if defined(NDEBUG)
if (traceFileDebugOnly)
if (traceInDebugOnly)
{
return;
}
#endif // NDEBUG
std::string formattedMessage = FormatString(format, vararg);
static std::ofstream file(TRACE_OUTPUT_FILE, std::ofstream::app);
if (file)
@ -60,25 +230,29 @@ static void output(bool traceFileDebugOnly, PerfOutputFunction perfFunc, const c
file.flush();
}
#endif // ANGLE_ENABLE_TRACE
#if defined(ANGLE_ENABLE_DEBUG_TRACE_TO_DEBUGGER)
OutputDebugStringA(formattedMessage.c_str());
#endif // ANGLE_ENABLE_DEBUG_TRACE_TO_DEBUGGER
#endif // ANGLE_ENABLE_DEBUG_TRACE
}
void trace(bool traceFileDebugOnly, const char *format, ...)
void trace(bool traceInDebugOnly, const char *format, ...)
{
va_list vararg;
va_start(vararg, format);
#if defined(ANGLE_ENABLE_PERF)
output(traceFileDebugOnly, D3DPERF_SetMarker, format, vararg);
#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
output(traceInDebugOnly, DebugTraceOutputTypeSetMarker, format, vararg);
#else
output(traceFileDebugOnly, NULL, format, vararg);
output(traceInDebugOnly, DebugTraceOutputTypeNone, format, vararg);
#endif
va_end(vararg);
}
bool perfActive()
{
#if defined(ANGLE_ENABLE_PERF)
static bool active = D3DPERF_GetStatus() != 0;
#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
static bool active = g_DebugAnnotationWrapper->getStatus();
return active;
#else
return false;
@ -87,26 +261,28 @@ bool perfActive()
ScopedPerfEventHelper::ScopedPerfEventHelper(const char* format, ...)
{
#if defined(ANGLE_ENABLE_PERF)
#if !defined(ANGLE_ENABLE_TRACE)
#if !defined(ANGLE_ENABLE_DEBUG_TRACE)
if (!perfActive())
{
return;
}
#endif // !ANGLE_ENABLE_TRACE
#endif // !ANGLE_ENABLE_DEBUG_TRACE
va_list vararg;
va_start(vararg, format);
output(true, reinterpret_cast<PerfOutputFunction>(D3DPERF_BeginEvent), format, vararg);
#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
output(true, DebugTraceOutputTypeBeginEvent, format, vararg);
#else
output(true, DebugTraceOutputTypeNone, format, vararg);
#endif // ANGLE_ENABLE_DEBUG_ANNOTATIONS
va_end(vararg);
#endif // ANGLE_ENABLE_PERF
}
ScopedPerfEventHelper::~ScopedPerfEventHelper()
{
#if defined(ANGLE_ENABLE_PERF)
#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
if (perfActive())
{
D3DPERF_EndEvent();
g_DebugAnnotationWrapper->endEvent();
}
#endif
}

View File

@ -20,8 +20,8 @@
namespace gl
{
// Outputs text to the debugging log
void trace(bool traceFileDebugOnly, const char *format, ...);
// Outputs text to the debugging log, or the debugging window
void trace(bool traceInDebugOnly, const char *format, ...);
// Returns whether D3DPERF is active.
bool perfActive();
@ -36,31 +36,34 @@ namespace gl
private:
DISALLOW_COPY_AND_ASSIGN(ScopedPerfEventHelper);
};
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_TRACE) || defined(ANGLE_ENABLE_PERF)
#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__)
#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_TRACE) || defined(ANGLE_ENABLE_PERF)
#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__)
#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_TRACE) || defined(ANGLE_ENABLE_PERF)
#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__)
#else
#define ERR(message, ...) (void(0))
#endif
// A macro to log a performance event around a scope.
#if defined(ANGLE_ENABLE_TRACE) || defined(ANGLE_ENABLE_PERF)
#if defined(ANGLE_ENABLE_DEBUG_TRACE) || defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
#if defined(_MSC_VER)
#define EVENT(message, ...) gl::ScopedPerfEventHelper scopedPerfEventHelper ## __LINE__("%s" message "\n", __FUNCTION__, __VA_ARGS__);
#else
@ -83,7 +86,7 @@ namespace gl
#define UNUSED_ASSERTION_VARIABLE(variable) ((void)variable)
#endif
#ifndef ANGLE_ENABLE_TRACE
#ifndef ANGLE_ENABLE_DEBUG_TRACE
#define UNUSED_TRACE_VARIABLE(variable) ((void)variable)
#else
#define UNUSED_TRACE_VARIABLE(variable)
@ -128,7 +131,7 @@ namespace gl
#endif
// A macro functioning as a compile-time assert to validate constant conditions
#if defined(_MSC_VER) && _MSC_VER >= 1600
#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

View File

@ -0,0 +1,35 @@
//
// 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.
//
#define ANGLE_DISABLED 0
#define ANGLE_ENABLED 1
// Feature defaults
// Direct3D9EX
// The "Debug This Pixel..." feature in PIX often fails when using the
// D3D9Ex interfaces. In order to get debug pixel to work on a Vista/Win 7
// machine, define "ANGLE_D3D9EX=0" in your project file.
#if !defined(ANGLE_D3D9EX)
#define ANGLE_D3D9EX ANGLE_ENABLED
#endif
// Vsync
// ENABLED allows Vsync to be configured at runtime
// DISABLED disallows Vsync
#if !defined(ANGLE_VSYNC)
#define ANGLE_VSYNC ANGLE_ENABLED
#endif
// Program binary loading
#if !defined(ANGLE_PROGRAM_BINARY_LOAD)
#define ANGLE_PROGRAM_BINARY_LOAD ANGLE_ENABLED
#endif
// Shader debug info
#if !defined(ANGLE_SHADER_DEBUG_INFO)
#define ANGLE_SHADER_DEBUG_INFO ANGLE_DISABLED
#endif

View File

@ -109,7 +109,7 @@ inline unsigned int unorm(float x)
inline bool supportsSSE2()
{
#ifdef ANGLE_PLATFORM_WINDOWS
#if defined(ANGLE_PLATFORM_WINDOWS) && !defined(_M_ARM)
static bool checked = false;
static bool supports = false;
@ -118,7 +118,6 @@ inline bool supportsSSE2()
return supports;
}
#if defined(_M_IX86) || defined(_M_AMD64) // ARM doesn't provide __cpuid()
int info[4];
__cpuid(info, 0);
@ -128,7 +127,6 @@ inline bool supportsSSE2()
supports = (info[3] >> 26) & 1;
}
#endif
checked = true;

View File

@ -11,9 +11,6 @@
#if defined(_WIN32) || defined(_WIN64)
# define ANGLE_PLATFORM_WINDOWS 1
# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
# define ANGLE_PLATFORM_WINRT 1
# endif
#elif defined(__APPLE__)
# define ANGLE_PLATFORM_APPLE 1
# define ANGLE_PLATFORM_POSIX 1
@ -37,6 +34,9 @@
#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,8 +50,9 @@
# include <windows.h>
# include <intrin.h>
# if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_PERF)
# if defined(ANGLE_ENABLE_D3D9)
# include <d3d9.h>
# include <dxgi.h>
# if !defined(COMPILER_IMPLEMENTATION)
# include <d3dcompiler.h>
# endif
@ -62,13 +63,26 @@
# include <d3d10.h>
# include <d3d11.h>
# include <dxgi.h>
# if _MSC_VER >= 1700
# if defined(_MSC_VER) && (_MSC_VER >= 1700)
# include <d3d11_1.h>
# include <dxgi1_2.h>
# endif
# if !defined(COMPILER_IMPLEMENTATION)
# include <d3dcompiler.h>
# endif
# if defined(__MINGW32__)
# endif
# if defined(ANGLE_ENABLE_WINDOWS_STORE)
# include <dxgi1_3.h>
# if defined(_DEBUG)
# 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
@ -78,8 +92,68 @@ typedef struct D3D11_QUERY_DATA_SO_STATISTICS
UINT64 NumPrimitivesWritten;
UINT64 PrimitivesStorageNeeded;
} D3D11_QUERY_DATA_SO_STATISTICS;
# endif
# endif
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__
# undef near
# undef far

View File

@ -10,29 +10,50 @@
#include <assert.h>
#if defined(ANGLE_PLATFORM_WINRT)
#ifdef ANGLE_ENABLE_WINDOWS_STORE
#include <vector>
std::vector<void *> *tls = nullptr;
std::vector<TLSIndex> *freeIndices = nullptr;
#include <set>
#include <map>
#include <mutex>
#include <wrl/client.h>
#include <wrl/async.h>
#include <Windows.System.Threading.h>
using namespace std;
using namespace Windows::Foundation;
using namespace ABI::Windows::System::Threading;
// Thread local storage for Windows Store support
typedef vector<void*> ThreadLocalData;
static __declspec(thread) ThreadLocalData* currentThreadData = nullptr;
static set<ThreadLocalData*> allThreadData;
static DWORD nextTlsIndex = 0;
static vector<DWORD> freeTlsIndices;
#endif
TLSIndex CreateTLSIndex()
{
TLSIndex index;
#if defined(ANGLE_PLATFORM_WINRT)
if (!tls)
tls = new std::vector<void *>;
if (freeIndices && !freeIndices->empty()) {
index = freeIndices->back();
freeIndices->pop_back();
return index;
} else {
tls->push_back(nullptr);
return tls->size() - 1;
#ifdef ANGLE_PLATFORM_WINDOWS
#ifdef ANGLE_ENABLE_WINDOWS_STORE
if (!freeTlsIndices.empty())
{
DWORD result = freeTlsIndices.back();
freeTlsIndices.pop_back();
index = result;
}
#elif defined(ANGLE_PLATFORM_WINDOWS)
else
{
index = nextTlsIndex++;
}
#else
index = TlsAlloc();
#endif
#elif defined(ANGLE_PLATFORM_POSIX)
// Create global pool key
if ((pthread_key_create(&index, NULL)) != 0)
@ -53,13 +74,23 @@ bool DestroyTLSIndex(TLSIndex index)
return false;
}
#if defined(ANGLE_PLATFORM_WINRT)
if (!freeIndices)
freeIndices = new std::vector<TLSIndex>;
freeIndices->push_back(index);
#ifdef ANGLE_PLATFORM_WINDOWS
#ifdef ANGLE_ENABLE_WINDOWS_STORE
assert(index < nextTlsIndex);
assert(find(freeTlsIndices.begin(), freeTlsIndices.end(), index) == freeTlsIndices.end());
freeTlsIndices.push_back(index);
for (auto threadData : allThreadData)
{
if (threadData->size() > index)
{
threadData->at(index) = nullptr;
}
}
return true;
#elif ANGLE_PLATFORM_WINDOWS
#else
return (TlsFree(index) == TRUE);
#endif
#elif defined(ANGLE_PLATFORM_POSIX)
return (pthread_key_delete(index) == 0);
#endif
@ -73,11 +104,25 @@ bool SetTLSValue(TLSIndex index, void *value)
return false;
}
#if defined(ANGLE_PLATFORM_WINRT)
tls->at(index) = value;
#ifdef ANGLE_PLATFORM_WINDOWS
#ifdef ANGLE_ENABLE_WINDOWS_STORE
ThreadLocalData* threadData = currentThreadData;
if (!threadData)
{
threadData = new ThreadLocalData(index + 1, nullptr);
allThreadData.insert(threadData);
currentThreadData = threadData;
}
else if (threadData->size() <= index)
{
threadData->resize(index + 1, nullptr);
}
threadData->at(index) = value;
return true;
#elif defined(ANGLE_PLATFORM_WINDOWS)
#else
return (TlsSetValue(index, value) == TRUE);
#endif
#elif defined(ANGLE_PLATFORM_POSIX)
return (pthread_setspecific(index, value) == 0);
#endif
@ -85,18 +130,26 @@ bool SetTLSValue(TLSIndex index, void *value)
void *GetTLSValue(TLSIndex index)
{
#if !defined(ANGLE_PLATFORM_WINRT) // Valid on WinRT, as Alloc handles the index creation
assert(index != TLS_INVALID_INDEX && "GetTLSValue(): Invalid TLS Index");
#endif
if (index == TLS_INVALID_INDEX)
{
return NULL;
}
#if defined(ANGLE_PLATFORM_WINRT)
return tls->at(index);
#elif defined(ANGLE_PLATFORM_WINDOWS)
#ifdef ANGLE_PLATFORM_WINDOWS
#ifdef ANGLE_ENABLE_WINDOWS_STORE
ThreadLocalData* threadData = currentThreadData;
if (threadData && threadData->size() > index)
{
return threadData->at(index);
}
else
{
return nullptr;
}
#else
return TlsGetValue(index);
#endif
#elif defined(ANGLE_PLATFORM_POSIX)
return pthread_getspecific(index);
#endif

View File

@ -11,11 +11,15 @@
#include "common/platform.h"
#if defined(ANGLE_PLATFORM_WINRT)
typedef size_t TLSIndex;
# define TLS_OUT_OF_INDEXES (static_cast<TLSIndex>(-1))
# define TLS_INVALID_INDEX TLS_OUT_OF_INDEXES
#elif defined(ANGLE_PLATFORM_WINDOWS)
#ifdef ANGLE_PLATFORM_WINDOWS
// TLS does not exist for Windows Store and needs to be emulated
# ifdef ANGLE_ENABLE_WINDOWS_STORE
# define TLS_OUT_OF_INDEXES -1
# ifndef CREATE_SUSPENDED
# define CREATE_SUSPENDED 0x00000004
# endif
# endif
typedef DWORD TLSIndex;
# define TLS_INVALID_INDEX (TLS_OUT_OF_INDEXES)
#elif defined(ANGLE_PLATFORM_POSIX)
@ -28,6 +32,9 @@
# error Unsupported platform.
#endif
// TODO(kbr): for POSIX platforms this will have to be changed to take
// in a destructor function pointer, to allow the thread-local storage
// to be properly deallocated upon thread exit.
TLSIndex CreateTLSIndex();
bool DestroyTLSIndex(TLSIndex index);

View File

@ -9,17 +9,16 @@
#include "common/utilities.h"
#include "common/mathutil.h"
#include "common/platform.h"
#if defined(ANGLE_PLATFORM_WINRT)
# include <locale>
# include <codecvt>
# include <wrl.h>
# include <windows.storage.h>
using namespace Microsoft::WRL;
using namespace ABI::Windows::Storage;
#endif
#include <set>
#if defined(ANGLE_ENABLE_WINDOWS_STORE)
# include <wrl.h>
# include <wrl/wrappers/corewrappers.h>
# include <windows.applicationmodel.core.h>
# include <windows.graphics.display.h>
#endif
namespace gl
{
@ -447,50 +446,10 @@ int VariableSortOrder(GLenum type)
}
#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
std::string getTempPath()
{
#if defined(ANGLE_PLATFORM_WINRT)
static std::string path;
while (path.empty())
{
ComPtr<IApplicationDataStatics> factory;
Wrappers::HStringReference classId(RuntimeClass_Windows_Storage_ApplicationData);
HRESULT result = RoGetActivationFactory(classId.Get(), IID_PPV_ARGS(&factory));
if (FAILED(result))
break;
ComPtr<IApplicationData> applicationData;
result = factory->get_Current(&applicationData);
if (FAILED(result))
break;
ComPtr<IStorageFolder> storageFolder;
result = applicationData->get_LocalFolder(&storageFolder);
if (FAILED(result))
break;
ComPtr<IStorageItem> localFolder;
result = storageFolder.As(&localFolder);
if (FAILED(result))
break;
HSTRING localFolderPath;
result = localFolder->get_Path(&localFolderPath);
if (FAILED(result))
break;
std::wstring_convert< std::codecvt_utf8<wchar_t> > converter;
path = converter.to_bytes(WindowsGetStringRawBuffer(localFolderPath, NULL));
if (path.empty())
{
UNREACHABLE();
break;
}
}
return path;
#elif defined(ANGLE_PLATFORM_WINDOWS)
#ifdef ANGLE_PLATFORM_WINDOWS
char path[MAX_PATH];
DWORD pathLen = GetTempPathA(sizeof(path) / sizeof(path[0]), path);
if (pathLen == 0)
@ -525,3 +484,33 @@ void writeFile(const char* path, const void* content, size_t size)
fwrite(content, sizeof(char), size, file);
fclose(file);
}
#endif // !ANGLE_ENABLE_WINDOWS_STORE
#if defined(ANGLE_ENABLE_WINDOWS_STORE)
void Sleep(unsigned long dwMilliseconds)
{
static HANDLE singletonEvent = nullptr;
HANDLE sleepEvent = singletonEvent;
if (!sleepEvent)
{
sleepEvent = CreateEventEx(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS);
if (!sleepEvent)
return;
HANDLE previousEvent = InterlockedCompareExchangePointerRelease(&singletonEvent, sleepEvent, nullptr);
if (previousEvent)
{
// Back out if multiple threads try to demand create at the same time.
CloseHandle(sleepEvent);
sleepEvent = previousEvent;
}
}
// Emulate sleep by waiting with timeout on an event that is never signalled.
WaitForSingleObjectEx(sleepEvent, dwMilliseconds, false);
}
#endif // ANGLE_ENABLE_WINDOWS_STORE

View File

@ -46,7 +46,13 @@ template <typename outT> outT uiround(GLfloat value) { return static_cast<outT>(
}
#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
std::string getTempPath();
void writeFile(const char* path, const void* data, size_t size);
#endif
#if defined(ANGLE_ENABLE_WINDOWS_STORE)
void Sleep(_In_ unsigned long dwMilliseconds);
#endif
#endif // LIBGLESV2_UTILITIES_H

View File

@ -0,0 +1,66 @@
//
// 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.
//
// NativeWindow.cpp: Handler for managing HWND native window types.
#include "common/NativeWindow.h"
#include "common/debug.h"
namespace rx
{
bool IsValidEGLNativeWindowType(EGLNativeWindowType window)
{
return (IsWindow(window) == TRUE);
}
NativeWindow::NativeWindow(EGLNativeWindowType window, EGLNativeDisplayType display) : mWindow(window), mDisplay(display)
{
}
bool NativeWindow::initialize()
{
return true;
}
bool NativeWindow::getClientRect(LPRECT rect)
{
return GetClientRect(mWindow, rect) == TRUE;
}
bool NativeWindow::isIconic()
{
return IsIconic(mWindow) == TRUE;
}
HRESULT NativeWindow::createSwapChain(NativeWindow::Device* device, DXGIFactory* factory,
DXGI_FORMAT format, unsigned int width, unsigned int height,
DXGISwapChain** swapChain)
{
if (device == NULL || factory == NULL || swapChain == NULL || width == 0 || height == 0)
{
return E_INVALIDARG;
}
DXGI_SWAP_CHAIN_DESC swapChainDesc = { 0 };
swapChainDesc.BufferCount = 1;
swapChainDesc.BufferDesc.Format = format;
swapChainDesc.BufferDesc.Width = width;
swapChainDesc.BufferDesc.Height = height;
swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
swapChainDesc.BufferDesc.RefreshRate.Numerator = 0;
swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER;
swapChainDesc.Flags = 0;
swapChainDesc.OutputWindow = mWindow;
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SampleDesc.Quality = 0;
swapChainDesc.Windowed = TRUE;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
return factory->CreateSwapChain(device, &swapChainDesc, swapChain);
}
}

View File

@ -0,0 +1,200 @@
//
// 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.cpp: NativeWindow for managing ICoreWindow native window types.
#include <algorithm>
#include "common/winrt/CoreWindowNativeWindow.h"
using namespace ABI::Windows::Foundation::Collections;
namespace rx
{
typedef ITypedEventHandler<ABI::Windows::UI::Core::CoreWindow *, ABI::Windows::UI::Core::WindowSizeChangedEventArgs *> SizeChangedHandler;
CoreWindowNativeWindow::~CoreWindowNativeWindow()
{
unregisterForSizeChangeEvents();
}
bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet)
{
ComPtr<IPropertySet> props = propertySet;
ComPtr<IInspectable> win = window;
ComPtr<IInspectable> displayInformation = display;
SIZE swapChainSize = {};
bool swapChainSizeSpecified = false;
HRESULT result = S_OK;
// IPropertySet is an optional parameter and can be null.
// If one is specified, cache as an IMap and read the properties
// used for initial host initialization.
if (propertySet)
{
result = props.As(&mPropertyMap);
if (SUCCEEDED(result))
{
// The EGLRenderSurfaceSizeProperty is optional and may be missing. The IPropertySet
// was prevalidated to contain the EGLNativeWindowType before being passed to
// this host.
result = GetOptionalSizePropertyValue(mPropertyMap, EGLRenderSurfaceSizeProperty, &swapChainSize, &swapChainSizeSpecified);
}
}
if (SUCCEEDED(result))
{
result = win.As(&mCoreWindow);
}
if (SUCCEEDED(result))
{
result = displayInformation.As(&mDisplayInformation);
}
if (SUCCEEDED(result))
{
#if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP
ComPtr<ABI::Windows::Graphics::Display::IDisplayInformation2> displayInformation2;
result = mDisplayInformation.As(&displayInformation2);
ASSERT(SUCCEEDED(result));
result = displayInformation2->get_RawPixelsPerViewPixel(&mScaleFactor);
ASSERT(SUCCEEDED(result));
#else
ABI::Windows::Graphics::Display::ResolutionScale resolutionScale;
result = mDisplayInformation->get_ResolutionScale(&resolutionScale);
ASSERT(SUCCEEDED(result));
mScaleFactor = DOUBLE(resolutionScale) / 100.0;
#endif
}
if (SUCCEEDED(result))
{
// If a swapchain size is specfied, then the automatic resize
// behaviors implemented by the host should be disabled. The swapchain
// will be still be scaled when being rendered to fit the bounds
// of the host.
// Scaling of the swapchain output occurs automatically because if
// the scaling mode setting DXGI_SCALING_STRETCH on the swapchain.
if (swapChainSizeSpecified)
{
mClientRect = { 0, 0, swapChainSize.cx, swapChainSize.cy };
mSupportsSwapChainResize = false;
}
else
{
ABI::Windows::Foundation::Rect rect;
HRESULT result = mCoreWindow->get_Bounds(&rect);
if (SUCCEEDED(result))
{
LONG width = std::floor(rect.Width * mScaleFactor + 0.5);
LONG height = std::floor(rect.Height * mScaleFactor + 0.5);
mClientRect = { 0, 0, width, height };
}
}
}
if (SUCCEEDED(result))
{
mNewClientRect = mClientRect;
mClientRectChanged = false;
return registerForSizeChangeEvents();
}
return false;
}
bool CoreWindowNativeWindow::registerForSizeChangeEvents()
{
HRESULT result = mCoreWindow->add_SizeChanged(Callback<SizeChangedHandler>(this, &CoreWindowNativeWindow::onSizeChanged).Get(),
&mSizeChangedEventToken);
if (SUCCEEDED(result))
{
return true;
}
return false;
}
void CoreWindowNativeWindow::unregisterForSizeChangeEvents()
{
if (mCoreWindow)
{
(void)mCoreWindow->remove_SizeChanged(mSizeChangedEventToken);
}
mSizeChangedEventToken.value = 0;
}
HRESULT CoreWindowNativeWindow::createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain)
{
if (device == NULL || factory == NULL || swapChain == NULL || width == 0 || height == 0)
{
return E_INVALIDARG;
}
DXGI_SWAP_CHAIN_DESC1 swapChainDesc = { 0 };
swapChainDesc.Width = width;
swapChainDesc.Height = height;
swapChainDesc.Format = format;
swapChainDesc.Stereo = FALSE;
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SampleDesc.Quality = 0;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER;
swapChainDesc.BufferCount = 2;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
*swapChain = nullptr;
ComPtr<IDXGISwapChain1> newSwapChain;
HRESULT result = factory->CreateSwapChainForCoreWindow(device, mCoreWindow.Get(), &swapChainDesc, nullptr, newSwapChain.ReleaseAndGetAddressOf());
if (SUCCEEDED(result))
{
#if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) // This block is disabled for Qt applications, as the resize events are expected
// Test if swapchain supports resize. On Windows Phone devices, this will return DXGI_ERROR_UNSUPPORTED. On
// other devices DXGI_ERROR_INVALID_CALL should be returned because the combination of flags passed
// (DXGI_SWAP_CHAIN_FLAG_NONPREROTATED | DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE) are invalid flag combinations.
if (newSwapChain->ResizeBuffers(swapChainDesc.BufferCount, swapChainDesc.Width, swapChainDesc.Height, swapChainDesc.Format, DXGI_SWAP_CHAIN_FLAG_NONPREROTATED | DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE) == DXGI_ERROR_UNSUPPORTED)
{
mSupportsSwapChainResize = false;
}
#endif // (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
result = newSwapChain.CopyTo(swapChain);
}
if (SUCCEEDED(result))
{
// If automatic swapchain resize behaviors have been disabled, then
// unregister for the resize change events.
if (mSupportsSwapChainResize == false)
{
unregisterForSizeChangeEvents();
}
}
return result;
}
// Basically, this shouldn't be used on Phone
HRESULT CoreWindowNativeWindow::onSizeChanged(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *e)
{
ABI::Windows::Foundation::Size size;
if (SUCCEEDED(e->get_Size(&size)))
{
SIZE windowSizeInPixels = {
std::floor(size.Width * mScaleFactor + 0.5),
std::floor(size.Height * mScaleFactor + 0.5)
};
setNewClientSize(windowSizeInPixels);
}
return S_OK;
}
}

View File

@ -0,0 +1,39 @@
//
// 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

@ -0,0 +1,274 @@
//
// 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.
//
// InspectableNativeWindow.cpp: NativeWindow base class for managing IInspectable native window types.
#include "common/winrt/CoreWindowNativeWindow.h"
#include "common/winrt/SwapChainPanelNativeWindow.h"
namespace rx
{
NativeWindow::NativeWindow(EGLNativeWindowType window, EGLNativeDisplayType display)
: mWindow(window), mDisplay(display)
{
}
bool NativeWindow::initialize()
{
// If the native window type is a IPropertySet, extract the
// EGLNativeWindowType (IInspectable) and initialize the
// proper host with this IPropertySet.
ComPtr<ABI::Windows::Foundation::Collections::IPropertySet> propertySet;
ComPtr<IInspectable> eglNativeWindow;
if (IsEGLConfiguredPropertySet(mWindow, &propertySet, &eglNativeWindow))
{
// A property set was found and the EGLNativeWindowType was
// retrieved. The mWindow member of the host to must be updated
// to use the EGLNativeWindowType specified in the property set.
// mWindow is treated as a raw pointer not an AddRef'd interface, so
// the old mWindow does not need a Release() before this assignment.
mWindow = eglNativeWindow.Get();
}
ComPtr<ABI::Windows::UI::Core::ICoreWindow> coreWindow;
ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> swapChainPanel;
if (IsCoreWindow(mWindow, &coreWindow))
{
mImpl = std::make_shared<CoreWindowNativeWindow>();
if (mImpl)
{
return mImpl->initialize(mWindow, mDisplay, propertySet.Get());
}
}
else if (IsSwapChainPanel(mWindow, &swapChainPanel))
{
mImpl = std::make_shared<SwapChainPanelNativeWindow>();
if (mImpl)
{
return mImpl->initialize(mWindow, mDisplay, propertySet.Get());
}
}
else
{
ERR("Invalid IInspectable EGLNativeWindowType detected. Valid IInspectables include ICoreWindow, ISwapChainPanel and IPropertySet");
}
return false;
}
bool NativeWindow::getClientRect(RECT *rect)
{
if (mImpl)
{
return mImpl->getClientRect(rect);
}
return false;
}
bool NativeWindow::isIconic()
{
return false;
}
HRESULT NativeWindow::createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain)
{
if (mImpl)
{
return mImpl->createSwapChain(device, factory, format, width, height, swapChain);
}
return E_UNEXPECTED;
}
bool IsCoreWindow(EGLNativeWindowType window, ComPtr<ABI::Windows::UI::Core::ICoreWindow> *coreWindow)
{
if (!window)
{
return false;
}
ComPtr<IInspectable> win = window;
ComPtr<ABI::Windows::UI::Core::ICoreWindow> coreWin;
if (SUCCEEDED(win.As(&coreWin)))
{
if (coreWindow != nullptr)
{
*coreWindow = coreWin.Detach();
}
return true;
}
return false;
}
bool IsSwapChainPanel(EGLNativeWindowType window, ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> *swapChainPanel)
{
if (!window)
{
return false;
}
ComPtr<IInspectable> win = window;
ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> panel;
if (SUCCEEDED(win.As(&panel)))
{
if (swapChainPanel != nullptr)
{
*swapChainPanel = panel.Detach();
}
return true;
}
return false;
}
bool IsEGLConfiguredPropertySet(EGLNativeWindowType window, ABI::Windows::Foundation::Collections::IPropertySet **propertySet, IInspectable **eglNativeWindow)
{
if (!window)
{
return false;
}
ComPtr<IInspectable> props = window;
ComPtr<IPropertySet> propSet;
ComPtr<IInspectable> nativeWindow;
ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable*>> propMap;
boolean hasEglNativeWindowPropertyKey = false;
HRESULT result = props.As(&propSet);
if (SUCCEEDED(result))
{
result = propSet.As(&propMap);
}
// Look for the presence of the EGLNativeWindowType in the property set
if (SUCCEEDED(result))
{
result = propMap->HasKey(HStringReference(EGLNativeWindowTypeProperty).Get(), &hasEglNativeWindowPropertyKey);
}
// If the IPropertySet does not contain the required EglNativeWindowType key, the property set is
// considered invalid.
if (SUCCEEDED(result) && !hasEglNativeWindowPropertyKey)
{
ERR("Could not find EGLNativeWindowTypeProperty in IPropertySet. Valid EGLNativeWindowTypeProperty values include ICoreWindow");
return false;
}
// The EglNativeWindowType property exists, so retreive the IInspectable that represents the EGLNativeWindowType
if (SUCCEEDED(result) && hasEglNativeWindowPropertyKey)
{
result = propMap->Lookup(HStringReference(EGLNativeWindowTypeProperty).Get(), &nativeWindow);
}
if (SUCCEEDED(result))
{
if (propertySet != nullptr)
{
result = propSet.CopyTo(propertySet);
}
}
if (SUCCEEDED(result))
{
if (eglNativeWindow != nullptr)
{
result = nativeWindow.CopyTo(eglNativeWindow);
}
}
if (SUCCEEDED(result))
{
return true;
}
return false;
}
// A Valid EGLNativeWindowType IInspectable can only be:
//
// ICoreWindow
// IPropertySet
//
// Anything else will be rejected as an invalid IInspectable.
bool IsValidEGLNativeWindowType(EGLNativeWindowType window)
{
return IsCoreWindow(window) || IsSwapChainPanel(window) || IsEGLConfiguredPropertySet(window);
}
// Attempts to read an optional SIZE property value that is assumed to be in the form of
// an ABI::Windows::Foundation::Size. This function validates the Size value before returning
// it to the caller.
//
// Possible return values are:
// S_OK, valueExists == true - optional SIZE value was successfully retrieved and validated
// S_OK, valueExists == false - optional SIZE value was not found
// E_INVALIDARG, valueExists = false - optional SIZE value was malformed in the property set.
// * Incorrect property type ( must be PropertyType_Size)
// * Invalid property value (width/height must be > 0)
// Additional errors may be returned from IMap or IPropertyValue
//
HRESULT GetOptionalSizePropertyValue(const ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable*>>& propertyMap, const wchar_t *propertyName, SIZE *value, bool *valueExists)
{
if (!propertyMap || !propertyName || !value || !valueExists)
{
return false;
}
// Assume that the value does not exist
*valueExists = false;
*value = { 0, 0 };
ComPtr<ABI::Windows::Foundation::IPropertyValue> propertyValue;
ABI::Windows::Foundation::PropertyType propertyType = ABI::Windows::Foundation::PropertyType::PropertyType_Empty;
Size sizeValue = { 0, 0 };
boolean hasKey = false;
HRESULT result = propertyMap->HasKey(HStringReference(propertyName).Get(), &hasKey);
if (SUCCEEDED(result) && !hasKey)
{
// Value does not exist, so return S_OK and set the exists parameter to false to indicate
// that a the optional property does not exist.
*valueExists = false;
return S_OK;
}
if (SUCCEEDED(result))
{
result = propertyMap->Lookup(HStringReference(propertyName).Get(), &propertyValue);
}
if (SUCCEEDED(result))
{
result = propertyValue->get_Type(&propertyType);
}
// Check if the expected Size property is of PropertyType_Size type.
if (SUCCEEDED(result) && propertyType == ABI::Windows::Foundation::PropertyType::PropertyType_Size)
{
if (SUCCEEDED(propertyValue->GetSize(&sizeValue)) && (sizeValue.Width > 0 && sizeValue.Height > 0))
{
// A valid property value exists
*value = { static_cast<long>(sizeValue.Width), static_cast<long>(sizeValue.Height) };
*valueExists = true;
result = S_OK;
}
else
{
// An invalid Size property was detected. Width/Height values must > 0
result = E_INVALIDARG;
}
}
else
{
// An invalid property type was detected. Size property must be of PropertyType_Size
result = E_INVALIDARG;
}
return result;
}
}

View File

@ -0,0 +1,91 @@
//
// 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.
//
// InspectableNativeWindow.h: Host specific implementation interface for
// managing IInspectable native window types.
#ifndef COMMON_WINRT_INSPECTABLENATIVEWINDOW_H_
#define COMMON_WINRT_INSPECTABLENATIVEWINDOW_H_
#include "common/platform.h"
#include "common/NativeWindow.h"
#include "angle_windowsstore.h"
#include <windows.ui.xaml.h>
#include <windows.ui.xaml.media.dxinterop.h>
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;
using namespace ABI::Windows::Foundation;
using namespace ABI::Windows::Foundation::Collections;
namespace rx
{
class InspectableNativeWindow
{
public:
InspectableNativeWindow() :
mSupportsSwapChainResize(true),
mRequiresSwapChainScaling(false),
mClientRectChanged(false),
mClientRect({0,0,0,0}),
mNewClientRect({0,0,0,0}),
mScaleFactor(1.0)
{
mSizeChangedEventToken.value = 0;
}
virtual ~InspectableNativeWindow(){}
virtual bool initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet) = 0;
virtual HRESULT createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain) = 0;
virtual bool registerForSizeChangeEvents() = 0;
virtual void unregisterForSizeChangeEvents() = 0;
virtual HRESULT scaleSwapChain(const SIZE& newSize) { return S_OK; }
bool getClientRect(RECT *rect)
{
if (mClientRectChanged && mSupportsSwapChainResize)
{
mClientRect = mNewClientRect;
mClientRectChanged = false;
}
*rect = mClientRect;
return true;
}
void setNewClientSize(const SIZE &newSize)
{
if (mSupportsSwapChainResize && !mRequiresSwapChainScaling)
{
mNewClientRect = { 0, 0, newSize.cx, newSize.cy };
mClientRectChanged = true;
}
if (mRequiresSwapChainScaling)
{
scaleSwapChain(newSize);
}
}
protected:
bool mSupportsSwapChainResize;
bool mRequiresSwapChainScaling;
RECT mClientRect;
RECT mNewClientRect;
bool mClientRectChanged;
DOUBLE mScaleFactor;
EventRegistrationToken mSizeChangedEventToken;
};
bool IsCoreWindow(EGLNativeWindowType window, ComPtr<ABI::Windows::UI::Core::ICoreWindow> *coreWindow = nullptr);
bool IsSwapChainPanel(EGLNativeWindowType window, ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> *swapChainPanel = nullptr);
bool IsEGLConfiguredPropertySet(EGLNativeWindowType window, ABI::Windows::Foundation::Collections::IPropertySet **propertySet = nullptr, IInspectable **inspectable = nullptr);
HRESULT GetOptionalSizePropertyValue(const ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable*>>& propertyMap, const wchar_t *propertyName, SIZE *value, bool *valueExists);
}
#endif // COMMON_WINRT_INSPECTABLENATIVEWINDOW_H_

View File

@ -0,0 +1,226 @@
//
// 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.
//
// SwapChainPanelNativeWindow.cpp: NativeWindow for managing ISwapChainPanel native window types.
#include "common/winrt/SwapChainPanelNativeWindow.h"
#include <algorithm>
#include <math.h>
using namespace ABI::Windows::Foundation::Collections;
namespace rx
{
SwapChainPanelNativeWindow::~SwapChainPanelNativeWindow()
{
unregisterForSizeChangeEvents();
}
bool SwapChainPanelNativeWindow::initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet)
{
ComPtr<IPropertySet> props = propertySet;
ComPtr<IInspectable> win = window;
SIZE swapChainSize = {};
bool swapChainSizeSpecified = false;
HRESULT result = S_OK;
// IPropertySet is an optional parameter and can be null.
// If one is specified, cache as an IMap and read the properties
// used for initial host initialization.
if (propertySet)
{
result = props.As(&mPropertyMap);
if (SUCCEEDED(result))
{
// The EGLRenderSurfaceSizeProperty is optional and may be missing. The IPropertySet
// was prevalidated to contain the EGLNativeWindowType before being passed to
// this host.
result = GetOptionalSizePropertyValue(mPropertyMap, EGLRenderSurfaceSizeProperty, &swapChainSize, &swapChainSizeSpecified);
}
}
if (SUCCEEDED(result))
{
result = win.As(&mSwapChainPanel);
}
if (SUCCEEDED(result))
{
// If a swapchain size is specfied, then the automatic resize
// behaviors implemented by the host should be disabled. The swapchain
// will be still be scaled when being rendered to fit the bounds
// of the host.
// Scaling of the swapchain output needs to be handled by the
// host for swapchain panels even though the scaling mode setting
// DXGI_SCALING_STRETCH is configured on the swapchain.
if (swapChainSizeSpecified)
{
mClientRect = { 0, 0, swapChainSize.cx, swapChainSize.cy };
// Enable host swapchain scaling
mRequiresSwapChainScaling = true;
}
else
{
result = GetSwapChainPanelSize(mSwapChainPanel, &mClientRect);
}
}
if (SUCCEEDED(result))
{
mNewClientRect = mClientRect;
mClientRectChanged = false;
return registerForSizeChangeEvents();
}
return false;
}
bool SwapChainPanelNativeWindow::registerForSizeChangeEvents()
{
ComPtr<ABI::Windows::UI::Xaml::ISizeChangedEventHandler> sizeChangedHandler;
ComPtr<ABI::Windows::UI::Xaml::IFrameworkElement> frameworkElement;
HRESULT result = Microsoft::WRL::MakeAndInitialize<SwapChainPanelSizeChangedHandler>(sizeChangedHandler.ReleaseAndGetAddressOf(), this->shared_from_this());
if (SUCCEEDED(result))
{
result = mSwapChainPanel.As(&frameworkElement);
}
if (SUCCEEDED(result))
{
result = frameworkElement->add_SizeChanged(sizeChangedHandler.Get(), &mSizeChangedEventToken);
}
if (SUCCEEDED(result))
{
return true;
}
return false;
}
void SwapChainPanelNativeWindow::unregisterForSizeChangeEvents()
{
ComPtr<ABI::Windows::UI::Xaml::IFrameworkElement> frameworkElement;
if (SUCCEEDED(mSwapChainPanel.As(&frameworkElement)))
{
(void)frameworkElement->remove_SizeChanged(mSizeChangedEventToken);
}
mSizeChangedEventToken.value = 0;
}
HRESULT SwapChainPanelNativeWindow::createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain)
{
if (device == NULL || factory == NULL || swapChain == NULL || width == 0 || height == 0)
{
return E_INVALIDARG;
}
DXGI_SWAP_CHAIN_DESC1 swapChainDesc = { 0 };
swapChainDesc.Width = width;
swapChainDesc.Height = height;
swapChainDesc.Format = format;
swapChainDesc.Stereo = FALSE;
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SampleDesc.Quality = 0;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER;
swapChainDesc.BufferCount = 2;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE;
*swapChain = nullptr;
ComPtr<IDXGISwapChain1> newSwapChain;
ComPtr<ISwapChainPanelNative> swapChainPanelNative;
RECT currentPanelSize = {};
HRESULT result = factory->CreateSwapChainForComposition(device, &swapChainDesc, nullptr, newSwapChain.ReleaseAndGetAddressOf());
if (SUCCEEDED(result))
{
result = mSwapChainPanel.As(&swapChainPanelNative);
}
if (SUCCEEDED(result))
{
result = swapChainPanelNative->SetSwapChain(newSwapChain.Get());
}
if (SUCCEEDED(result))
{
// The swapchain panel host requires an instance of the swapchain set on the SwapChainPanel
// to perform the runtime-scale behavior. This swapchain is cached here because there are
// no methods for retreiving the currently configured on from ISwapChainPanelNative.
mSwapChain = newSwapChain;
result = newSwapChain.CopyTo(swapChain);
}
// If the host is responsible for scaling the output of the swapchain, then
// scale it now before returning an instance to the caller. This is done by
// first reading the current size of the swapchain panel, then scaling
if (SUCCEEDED(result) && mRequiresSwapChainScaling)
{
result = GetSwapChainPanelSize(mSwapChainPanel, &currentPanelSize);
}
// Scale the swapchain to fit inside the contents of the panel.
if (SUCCEEDED(result) && mRequiresSwapChainScaling)
{
SIZE currentSize = { currentPanelSize.right, currentPanelSize.bottom };
result = scaleSwapChain(currentSize);
}
if (SUCCEEDED(result))
{
// If automatic swapchain resize behaviors have been disabled, then
// unregister for the resize change events.
if (mSupportsSwapChainResize == false)
{
unregisterForSizeChangeEvents();
}
}
return result;
}
HRESULT SwapChainPanelNativeWindow::scaleSwapChain(const SIZE &newSize)
{
ABI::Windows::Foundation::Size renderScale = { (float)newSize.cx/(float)mClientRect.right, (float)newSize.cy/(float)mClientRect.bottom };
// Setup a scale matrix for the swap chain
DXGI_MATRIX_3X2_F scaleMatrix = {};
scaleMatrix._11 = renderScale.Width;
scaleMatrix._22 = renderScale.Height;
ComPtr<IDXGISwapChain2> swapChain2;
HRESULT result = mSwapChain.As(&swapChain2);
if (SUCCEEDED(result))
{
result = swapChain2->SetMatrixTransform(&scaleMatrix);
}
return result;
}
HRESULT GetSwapChainPanelSize(const ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> &swapChainPanel, RECT *windowSize)
{
ComPtr<ABI::Windows::UI::Xaml::IUIElement> uiElement;
ABI::Windows::Foundation::Size renderSize = { 0, 0 };
HRESULT result = swapChainPanel.As(&uiElement);
if (SUCCEEDED(result))
{
result = uiElement->get_RenderSize(&renderSize);
}
if (SUCCEEDED(result))
{
*windowSize = { 0, 0, lround(renderSize.Width), lround(renderSize.Height) };
}
return result;
}
}

View File

@ -0,0 +1,79 @@
//
// 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.
//
// SwapChainPanelNativeWindow.h: NativeWindow for managing ISwapChainPanel native window types.
#ifndef COMMON_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_
#define COMMON_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_
#include "common/winrt/InspectableNativeWindow.h"
namespace rx
{
class SwapChainPanelNativeWindow : public InspectableNativeWindow, public std::enable_shared_from_this<SwapChainPanelNativeWindow>
{
public:
~SwapChainPanelNativeWindow();
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);
HRESULT scaleSwapChain(const SIZE &newSize);
private:
ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> mSwapChainPanel;
ComPtr<IMap<HSTRING, IInspectable*>> mPropertyMap;
ComPtr<DXGISwapChain> mSwapChain;
};
[uuid(8ACBD974-8187-4508-AD80-AEC77F93CF36)]
class SwapChainPanelSizeChangedHandler :
public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, ABI::Windows::UI::Xaml::ISizeChangedEventHandler>
{
public:
SwapChainPanelSizeChangedHandler() { }
HRESULT RuntimeClassInitialize(std::shared_ptr<InspectableNativeWindow> host)
{
if (!host)
{
return E_INVALIDARG;
}
mHost = host;
return S_OK;
}
// ISizeChangedEventHandler
IFACEMETHOD(Invoke)(IInspectable *sender, ABI::Windows::UI::Xaml::ISizeChangedEventArgs *sizeChangedEventArgs)
{
std::shared_ptr<InspectableNativeWindow> host = mHost.lock();
if (host)
{
// The size of the ISwapChainPanel control is returned in DIPs.
// We are keeping these in dips because the swapchain created for composition
// also uses dip units. This keeps dimensions, viewports, etc in the same unit.
// XAML Clients of the ISwapChainPanel are required to use dips to define their
// layout sizes as well.
ABI::Windows::Foundation::Size newSize;
HRESULT result = sizeChangedEventArgs->get_NewSize(&newSize);
if (SUCCEEDED(result))
{
SIZE windowSize = { lround(newSize.Width), lround(newSize.Height) };
host->setNewClientSize(windowSize);
}
}
return S_OK;
}
private:
std::weak_ptr<InspectableNativeWindow> mHost;
};
HRESULT GetSwapChainPanelSize(const ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> &swapChainPanel, RECT *windowSize);
}
#endif // COMMON_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_

View File

@ -29,7 +29,8 @@ class DirectiveHandler
// Handle pragma of form: #pragma name[(value)]
virtual void handlePragma(const SourceLocation &loc,
const std::string &name,
const std::string &value) = 0;
const std::string &value,
bool stdgl) = 0;
virtual void handleExtension(const SourceLocation &loc,
const std::string &name,

View File

@ -38,19 +38,19 @@ enum DirectiveType
DirectiveType getDirective(const pp::Token *token)
{
static const std::string kDirectiveDefine("define");
static const std::string kDirectiveUndef("undef");
static const std::string kDirectiveIf("if");
static const std::string kDirectiveIfdef("ifdef");
static const std::string kDirectiveIfndef("ifndef");
static const std::string kDirectiveElse("else");
static const std::string kDirectiveElif("elif");
static const std::string kDirectiveEndif("endif");
static const std::string kDirectiveError("error");
static const std::string kDirectivePragma("pragma");
static const std::string kDirectiveExtension("extension");
static const std::string kDirectiveVersion("version");
static const std::string kDirectiveLine("line");
const char kDirectiveDefine[] = "define";
const char kDirectiveUndef[] = "undef";
const char kDirectiveIf[] = "if";
const char kDirectiveIfdef[] = "ifdef";
const char kDirectiveIfndef[] = "ifndef";
const char kDirectiveElse[] = "else";
const char kDirectiveElif[] = "elif";
const char kDirectiveEndif[] = "endif";
const char kDirectiveError[] = "error";
const char kDirectivePragma[] = "pragma";
const char kDirectiveExtension[] = "extension";
const char kDirectiveVersion[] = "version";
const char kDirectiveLine[] = "line";
if (token->type != pp::Token::IDENTIFIER)
return DIRECTIVE_NONE;
@ -155,7 +155,7 @@ class DefinedParser : public Lexer
protected:
virtual void lex(Token *token)
{
static const std::string kDefined("defined");
const char kDefined[] = "defined";
mLexer->lex(token);
if (token->type != Token::IDENTIFIER)
@ -592,6 +592,11 @@ void DirectiveParser::parsePragma(Token *token)
int state = PRAGMA_NAME;
mTokenizer->lex(token);
bool stdgl = token->text == "STDGL";
if (stdgl)
{
mTokenizer->lex(token);
}
while ((token->type != '\n') && (token->type != Token::LAST))
{
switch(state++)
@ -627,7 +632,7 @@ void DirectiveParser::parsePragma(Token *token)
}
else if (state > PRAGMA_NAME) // Do not notify for empty pragma.
{
mDirectiveHandler->handlePragma(token->location, name, value);
mDirectiveHandler->handlePragma(token->location, name, value, stdgl);
}
}

View File

@ -194,8 +194,8 @@ bool MacroExpander::expandMacro(const Macro &macro,
if (macro.predefined)
{
static const std::string kLine = "__LINE__";
static const std::string kFile = "__FILE__";
const char kLine[] = "__LINE__";
const char kFile[] = "__FILE__";
assert(replacements->size() == 1);
Token& repl = replacements->front();

View File

@ -29,24 +29,27 @@
bool IsWebGLBasedSpec(ShShaderSpec spec)
{
return spec == SH_WEBGL_SPEC || spec == SH_CSS_SHADERS_SPEC;
return (spec == SH_WEBGL_SPEC ||
spec == SH_CSS_SHADERS_SPEC ||
spec == SH_WEBGL2_SPEC);
}
size_t GetGlobalMaxTokenSize(ShShaderSpec spec)
{
// WebGL defines a max token legnth of 256, while ES2 leaves max token
// size undefined. ES3 defines a max size of 1024 characters.
if (IsWebGLBasedSpec(spec))
switch (spec)
{
case SH_WEBGL_SPEC:
case SH_CSS_SHADERS_SPEC:
return 256;
}
else
{
default:
return 1024;
}
}
namespace {
class TScopedPoolAllocator
{
public:
@ -82,6 +85,24 @@ class TScopedSymbolTableLevel
private:
TSymbolTable* mTable;
};
int MapSpecToShaderVersion(ShShaderSpec spec)
{
switch (spec)
{
case SH_GLES2_SPEC:
case SH_WEBGL_SPEC:
case SH_CSS_SHADERS_SPEC:
return 100;
case SH_GLES3_SPEC:
case SH_WEBGL2_SPEC:
return 300;
default:
UNREACHABLE();
return 0;
}
}
} // namespace
TShHandleBase::TShHandleBase()
@ -178,9 +199,21 @@ bool TCompiler::compile(const char* const shaderStrings[],
(parseContext.treeRoot != NULL);
shaderVersion = parseContext.getShaderVersion();
if (success && MapSpecToShaderVersion(shaderSpec) < shaderVersion)
{
infoSink.info.prefix(EPrefixError);
infoSink.info << "unsupported shader version";
success = false;
}
if (success)
{
mPragma = parseContext.pragma();
if (mPragma.stdgl.invariantAll)
{
symbolTable.setGlobalInvariant();
}
TIntermNode* root = parseContext.treeRoot;
success = intermediate.postProcess(root);
@ -360,7 +393,8 @@ void TCompiler::setResourceString()
<< ":MaxVertexOutputVectors:" << compileResources.MaxVertexOutputVectors
<< ":MaxFragmentInputVectors:" << compileResources.MaxFragmentInputVectors
<< ":MinProgramTexelOffset:" << compileResources.MinProgramTexelOffset
<< ":MaxProgramTexelOffset:" << compileResources.MaxProgramTexelOffset;
<< ":MaxProgramTexelOffset:" << compileResources.MaxProgramTexelOffset
<< ":NV_draw_buffers:" << compileResources.NV_draw_buffers;
builtInResourcesString = strstream.str();
}
@ -377,7 +411,6 @@ void TCompiler::clearResults()
uniforms.clear();
expandedUniforms.clear();
varyings.clear();
expandedVaryings.clear();
interfaceBlocks.clear();
builtInFunctionEmulator.Cleanup();
@ -507,13 +540,12 @@ void TCompiler::collectVariables(TIntermNode* root)
&uniforms,
&varyings,
&interfaceBlocks,
hashFunction);
hashFunction,
symbolTable);
root->traverse(&collect);
// For backwards compatiblity with ShGetVariableInfo, expand struct
// uniforms and varyings into separate variables for each field.
sh::ExpandVariables(uniforms, &expandedUniforms);
sh::ExpandVariables(varyings, &expandedVaryings);
// This is for enforcePackingRestriction().
sh::ExpandUniforms(uniforms, &expandedUniforms);
}
bool TCompiler::enforcePackingRestrictions()
@ -581,3 +613,10 @@ const BuiltInFunctionEmulator& TCompiler::getBuiltInFunctionEmulator() const
{
return builtInFunctionEmulator;
}
void TCompiler::writePragma()
{
TInfoSinkBase &sink = infoSink.obj;
if (mPragma.stdgl.invariantAll)
sink << "#pragma STDGL invariant(all)\n";
}

View File

@ -18,6 +18,7 @@
#include "compiler/translator/ExtensionBehavior.h"
#include "compiler/translator/HashNames.h"
#include "compiler/translator/InfoSink.h"
#include "compiler/translator/Pragma.h"
#include "compiler/translator/SymbolTable.h"
#include "compiler/translator/VariableInfo.h"
#include "third_party/compiler/ArrayBoundsClamper.h"
@ -71,9 +72,7 @@ class TCompiler : public TShHandleBase
const std::vector<sh::Attribute> &getAttributes() const { return attributes; }
const std::vector<sh::Attribute> &getOutputVariables() const { return outputVariables; }
const std::vector<sh::Uniform> &getUniforms() const { return uniforms; }
const std::vector<sh::ShaderVariable> &getExpandedUniforms() const { return expandedUniforms; }
const std::vector<sh::Varying> &getVaryings() const { return varyings; }
const std::vector<sh::ShaderVariable> &getExpandedVaryings() const { return expandedVaryings; }
const std::vector<sh::InterfaceBlock> &getInterfaceBlocks() const { return interfaceBlocks; }
ShHashFunction64 getHashFunction() const { return hashFunction; }
@ -81,7 +80,7 @@ class TCompiler : public TShHandleBase
TSymbolTable& getSymbolTable() { return symbolTable; }
ShShaderSpec getShaderSpec() const { return shaderSpec; }
ShShaderOutput getOutputType() const { return outputType; }
std::string getBuiltInResourcesString() const { return builtInResourcesString; }
const std::string &getBuiltInResourcesString() const { return builtInResourcesString; }
// Get the resources set by InitBuiltInSymbolTable
const ShBuiltInResources& getResources() const;
@ -131,6 +130,8 @@ class TCompiler : public TShHandleBase
bool limitExpressionComplexity(TIntermNode* root);
// Get built-in extensions with default behavior.
const TExtensionBehavior& getExtensionBehavior() const;
const TPragma& getPragma() const { return mPragma; }
void writePragma();
const ArrayBoundsClamper& getArrayBoundsClamper() const;
ShArrayIndexClampingStrategy getArrayIndexClampingStrategy() const;
@ -141,7 +142,6 @@ class TCompiler : public TShHandleBase
std::vector<sh::Uniform> uniforms;
std::vector<sh::ShaderVariable> expandedUniforms;
std::vector<sh::Varying> varyings;
std::vector<sh::ShaderVariable> expandedVaryings;
std::vector<sh::InterfaceBlock> interfaceBlocks;
private:
@ -174,6 +174,8 @@ class TCompiler : public TShHandleBase
// name hashing.
ShHashFunction64 hashFunction;
NameMap nameMap;
TPragma mPragma;
};
//

View File

@ -14,6 +14,9 @@
namespace sh
{
// Detect Loop Discontinuity
bool DetectLoopDiscontinuity::traverse(TIntermNode *node)
{
mLoopDepth = 0;
@ -74,6 +77,55 @@ bool containsLoopDiscontinuity(TIntermNode *node)
return detectLoopDiscontinuity.traverse(node);
}
// Detect Any Loop
bool DetectAnyLoop::traverse(TIntermNode *node)
{
mHasLoop = false;
node->traverse(this);
return mHasLoop;
}
bool DetectAnyLoop::visitLoop(Visit visit, TIntermLoop *loop)
{
mHasLoop = true;
return false;
}
// The following definitions stop all traversal when we have found a loop
bool DetectAnyLoop::visitBinary(Visit, TIntermBinary *)
{
return !mHasLoop;
}
bool DetectAnyLoop::visitUnary(Visit, TIntermUnary *)
{
return !mHasLoop;
}
bool DetectAnyLoop::visitSelection(Visit, TIntermSelection *)
{
return !mHasLoop;
}
bool DetectAnyLoop::visitAggregate(Visit, TIntermAggregate *)
{
return !mHasLoop;
}
bool DetectAnyLoop::visitBranch(Visit, TIntermBranch *)
{
return !mHasLoop;
}
bool containsAnyLoop(TIntermNode *node)
{
DetectAnyLoop detectAnyLoop;
return detectAnyLoop.traverse(node);
}
// Detect Gradient Operation
bool DetectGradientOperation::traverse(TIntermNode *node)
{
mGradientOperation = false;

View File

@ -32,6 +32,25 @@ class DetectLoopDiscontinuity : public TIntermTraverser
bool containsLoopDiscontinuity(TIntermNode *node);
// Checks for the existence of any loop
class DetectAnyLoop : public TIntermTraverser
{
public:
bool traverse(TIntermNode *node);
protected:
bool visitBinary(Visit, TIntermBinary *);
bool visitUnary(Visit, TIntermUnary *);
bool visitSelection(Visit, TIntermSelection *);
bool visitAggregate(Visit, TIntermAggregate *);
bool visitLoop(Visit, TIntermLoop *);
bool visitBranch(Visit, TIntermBranch *);
bool mHasLoop;
};
bool containsAnyLoop(TIntermNode *node);
// Checks for intrinsic functions which compute gradients
class DetectGradientOperation : public TIntermTraverser
{

View File

@ -13,10 +13,10 @@
static TBehavior getBehavior(const std::string& str)
{
static const std::string kRequire("require");
static const std::string kEnable("enable");
static const std::string kDisable("disable");
static const std::string kWarn("warn");
const char kRequire[] = "require";
const char kEnable[] = "enable";
const char kDisable[] = "disable";
const char kWarn[] = "warn";
if (str == kRequire) return EBhRequire;
else if (str == kEnable) return EBhEnable;
@ -46,50 +46,61 @@ void TDirectiveHandler::handleError(const pp::SourceLocation& loc,
void TDirectiveHandler::handlePragma(const pp::SourceLocation& loc,
const std::string& name,
const std::string& value)
const std::string& value,
bool stdgl)
{
static const std::string kSTDGL("STDGL");
static const std::string kOptimize("optimize");
static const std::string kDebug("debug");
static const std::string kOn("on");
static const std::string kOff("off");
if (stdgl)
{
const char kInvariant[] = "invariant";
const char kAll[] = "all";
bool invalidValue = false;
if (name == kSTDGL)
{
if (name == kInvariant && value == kAll)
mPragma.stdgl.invariantAll = true;
// The STDGL pragma is used to reserve pragmas for use by future
// revisions of GLSL. Ignore it.
// revisions of GLSL. Do not generate an error on unexpected
// name and value.
return;
}
else if (name == kOptimize)
{
if (value == kOn) mPragma.optimize = true;
else if (value == kOff) mPragma.optimize = false;
else invalidValue = true;
}
else if (name == kDebug)
{
if (value == kOn) mPragma.debug = true;
else if (value == kOff) mPragma.debug = false;
else invalidValue = true;
}
else
{
mDiagnostics.report(pp::Diagnostics::PP_UNRECOGNIZED_PRAGMA, loc, name);
return;
}
const char kOptimize[] = "optimize";
const char kDebug[] = "debug";
const char kOn[] = "on";
const char kOff[] = "off";
if (invalidValue)
mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc,
"invalid pragma value", value,
"'on' or 'off' expected");
bool invalidValue = false;
if (name == kOptimize)
{
if (value == kOn) mPragma.optimize = true;
else if (value == kOff) mPragma.optimize = false;
else invalidValue = true;
}
else if (name == kDebug)
{
if (value == kOn) mPragma.debug = true;
else if (value == kOff) mPragma.debug = false;
else invalidValue = true;
}
else
{
mDiagnostics.report(pp::Diagnostics::PP_UNRECOGNIZED_PRAGMA, loc, name);
return;
}
if (invalidValue)
{
mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc,
"invalid pragma value", value,
"'on' or 'off' expected");
}
}
}
void TDirectiveHandler::handleExtension(const pp::SourceLocation& loc,
const std::string& name,
const std::string& behavior)
{
static const std::string kExtAll("all");
const char kExtAll[] = "all";
TBehavior behaviorVal = getBehavior(behavior);
if (behaviorVal == EBhUndefined)

View File

@ -29,7 +29,8 @@ class TDirectiveHandler : public pp::DirectiveHandler
virtual void handlePragma(const pp::SourceLocation& loc,
const std::string& name,
const std::string& value);
const std::string& value,
bool stdgl);
virtual void handleExtension(const pp::SourceLocation& loc,
const std::string& name,

View File

@ -133,6 +133,14 @@ bool CompareStructure(const TType &leftNodeType,
//
////////////////////////////////////////////////////////////////
void TIntermTyped::setTypePreservePrecision(const TType &t)
{
TPrecision precision = getPrecision();
mType = t;
ASSERT(mType.getBasicType() != EbtBool || precision == EbpUndefined);
mType.setPrecision(precision);
}
#define REPLACE_IF_IS(node, type, original, replacement) \
if (node == original) { \
node = static_cast<type *>(replacement); \
@ -237,6 +245,52 @@ void TIntermAggregate::enqueueChildren(std::queue<TIntermNode *> *nodeQueue) con
}
}
void TIntermAggregate::setPrecisionFromChildren()
{
if (getBasicType() == EbtBool)
{
mType.setPrecision(EbpUndefined);
return;
}
TPrecision precision = EbpUndefined;
TIntermSequence::iterator childIter = mSequence.begin();
while (childIter != mSequence.end())
{
TIntermTyped *typed = (*childIter)->getAsTyped();
if (typed)
precision = GetHigherPrecision(typed->getPrecision(), precision);
++childIter;
}
mType.setPrecision(precision);
}
void TIntermAggregate::setBuiltInFunctionPrecision()
{
// All built-ins returning bool should be handled as ops, not functions.
ASSERT(getBasicType() != EbtBool);
TPrecision precision = EbpUndefined;
TIntermSequence::iterator childIter = mSequence.begin();
while (childIter != mSequence.end())
{
TIntermTyped *typed = (*childIter)->getAsTyped();
// ESSL spec section 8: texture functions get their precision from the sampler.
if (typed && IsSampler(typed->getBasicType()))
{
precision = typed->getPrecision();
break;
}
++childIter;
}
// ESSL 3.0 spec section 8: textureSize always gets highp precision.
// All other functions that take a sampler are assumed to be texture functions.
if (mName.find("textureSize") == 0)
mType.setPrecision(EbpHigh);
else
mType.setPrecision(precision);
}
bool TIntermSelection::replaceChildNode(
TIntermNode *original, TIntermNode *replacement)
{
@ -336,6 +390,7 @@ bool TIntermUnary::promote(TInfoSink &)
return false;
break;
case EOpNegative:
case EOpPositive:
case EOpPostIncrement:
case EOpPostDecrement:
case EOpPreIncrement:
@ -1068,6 +1123,27 @@ TIntermTyped *TIntermConstantUnion::fold(
}
break;
case EOpPositive:
switch (getType().getBasicType())
{
case EbtFloat:
tempConstArray[i].setFConst(unionArray[i].getFConst());
break;
case EbtInt:
tempConstArray[i].setIConst(unionArray[i].getIConst());
break;
case EbtUInt:
tempConstArray[i].setUConst(static_cast<unsigned int>(
static_cast<int>(unionArray[i].getUConst())));
break;
default:
infoSink.info.message(
EPrefixInternalError, getLine(),
"Unary operation not folded into constant");
return NULL;
}
break;
case EOpLogicalNot:
// this code is written for possible future use,
// will not get executed currently

View File

@ -45,6 +45,7 @@ enum TOperator
//
EOpNegative,
EOpPositive,
EOpLogicalNot,
EOpVectorLogicalNot,
@ -265,6 +266,7 @@ class TIntermTyped : public TIntermNode
virtual bool hasSideEffects() const = 0;
void setType(const TType &t) { mType = t; }
void setTypePreservePrecision(const TType &t);
const TType &getType() const { return mType; }
TType *getTypePointer() { return &mType; }
@ -613,6 +615,9 @@ class TIntermAggregate : public TIntermOperator
virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const;
void setPrecisionFromChildren();
void setBuiltInFunctionPrecision();
protected:
TIntermAggregate(const TIntermAggregate &); // disallow copy constructor
TIntermAggregate &operator=(const TIntermAggregate &); // disallow assignment operator

View File

@ -198,6 +198,7 @@ TIntermTyped *TIntermediate::addUnaryMath(
case EOpPostDecrement:
case EOpPreDecrement:
case EOpNegative:
case EOpPositive:
if (child->getType().getBasicType() == EbtStruct ||
child->getType().isArray())
{

View File

@ -395,6 +395,7 @@ bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary *node)
switch (node->getOp())
{
case EOpNegative: preString = "(-"; break;
case EOpPositive: preString = "(+"; break;
case EOpVectorLogicalNot: preString = "not("; break;
case EOpLogicalNot: preString = "(!"; break;
@ -574,7 +575,7 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)
// Function declaration.
ASSERT(visit == PreVisit);
writeVariableType(node->getType());
out << " " << hashName(node->getName());
out << " " << hashFunctionName(node->getName());
out << "(";
writeFunctionParameters(*(node->getSequence()));
@ -649,17 +650,18 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)
mDeclaringVariables = false;
}
break;
case EOpInvariantDeclaration: {
// Invariant declaration.
ASSERT(visit == PreVisit);
case EOpInvariantDeclaration:
// Invariant declaration.
ASSERT(visit == PreVisit);
{
const TIntermSequence *sequence = node->getSequence();
ASSERT(sequence && sequence->size() == 1);
const TIntermSymbol *symbol = sequence->front()->getAsSymbolNode();
ASSERT(symbol);
out << "invariant " << symbol->getSymbol() << ";";
visitChildren = false;
break;
out << "invariant " << hashVariableName(symbol->getSymbol());
}
visitChildren = false;
break;
case EOpConstructFloat:
writeTriplet(visit, "float(", NULL, ")");
break;
@ -741,7 +743,7 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)
writeBuiltInFunctionTriplet(visit, "notEqual(", useEmulatedFunction);
break;
case EOpComma:
writeTriplet(visit, NULL, ", ", NULL);
writeTriplet(visit, "(", ", ", ")");
break;
case EOpMod:

View File

@ -135,6 +135,7 @@ OutputHLSL::OutputHLSL(TParseContext &context, TranslatorHLSL *parentTranslator)
mUniqueIndex = 0;
mContainsLoopDiscontinuity = false;
mContainsAnyLoop = false;
mOutputLod0Function = false;
mInsideDiscontinuousLoop = false;
mNestedLoopDepth = 0;
@ -172,6 +173,7 @@ OutputHLSL::~OutputHLSL()
void OutputHLSL::output()
{
mContainsLoopDiscontinuity = mContext.shaderType == GL_FRAGMENT_SHADER && containsLoopDiscontinuity(mContext.treeRoot);
mContainsAnyLoop = containsAnyLoop(mContext.treeRoot);
const std::vector<TIntermTyped*> &flaggedStructs = FlagStd140ValueStructs(mContext.treeRoot);
makeFlaggedStructMaps(flaggedStructs);
@ -320,14 +322,22 @@ void OutputHLSL::header()
if (mUsesDiscardRewriting)
{
out << "#define ANGLE_USES_DISCARD_REWRITING" << "\n";
out << "#define ANGLE_USES_DISCARD_REWRITING\n";
}
if (mUsesNestedBreak)
{
out << "#define ANGLE_USES_NESTED_BREAK" << "\n";
out << "#define ANGLE_USES_NESTED_BREAK\n";
}
out << "#ifdef ANGLE_ENABLE_LOOP_FLATTEN\n"
"#define LOOP [loop]\n"
"#define FLATTEN [flatten]\n"
"#else\n"
"#define LOOP\n"
"#define FLATTEN\n"
"#endif\n";
if (mContext.shaderType == GL_FRAGMENT_SHADER)
{
TExtensionBehavior::const_iterator iter = mContext.extensionBehavior().find("GL_EXT_draw_buffers");
@ -1747,6 +1757,7 @@ bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node)
switch (node->getOp())
{
case EOpNegative: outputTriplet(visit, "(-", "", ")"); break;
case EOpPositive: outputTriplet(visit, "(+", "", ")"); break;
case EOpVectorLogicalNot: outputTriplet(visit, "(!", "", ")"); break;
case EOpLogicalNot: outputTriplet(visit, "(!", "", ")"); break;
case EOpPostIncrement: outputTriplet(visit, "(", "", "++)"); break;
@ -1860,15 +1871,20 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
if (!variable->getAsSymbolNode() || variable->getAsSymbolNode()->getSymbol() != "") // Variable declaration
{
if (!mInsideFunction)
{
out << "static ";
}
out << TypeString(variable->getType()) + " ";
for (TIntermSequence::iterator sit = sequence->begin(); sit != sequence->end(); sit++)
{
if (isSingleStatement(*sit))
{
mUnfoldShortCircuit->traverse(*sit);
}
if (!mInsideFunction)
{
out << "static ";
}
out << TypeString(variable->getType()) + " ";
TIntermSymbol *symbol = (*sit)->getAsSymbolNode();
if (symbol)
@ -1884,7 +1900,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
if (*sit != sequence->back())
{
out << ", ";
out << ";\n";
}
}
}
@ -1925,7 +1941,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
case EOpPrototype:
if (visit == PreVisit)
{
out << TypeString(node->getType()) << " " << Decorate(node->getName()) << (mOutputLod0Function ? "Lod0(" : "(");
out << TypeString(node->getType()) << " " << Decorate(TFunction::unmangleName(node->getName())) << (mOutputLod0Function ? "Lod0(" : "(");
TIntermSequence *arguments = node->getSequence();
@ -2287,6 +2303,15 @@ bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node)
{
mUnfoldShortCircuit->traverse(node->getCondition());
// D3D errors when there is a gradient operation in a loop in an unflattened if
// however flattening all the ifs in branch heavy shaders made D3D error too.
// As a temporary workaround we flatten the ifs only if there is at least a loop
// present somewhere in the shader.
if (mContext.shaderType == GL_FRAGMENT_SHADER && mContainsAnyLoop)
{
out << "FLATTEN ";
}
out << "if (";
node->getCondition()->traverse(this);
@ -2367,14 +2392,14 @@ bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node)
if (node->getType() == ELoopDoWhile)
{
out << "{do\n";
out << "{LOOP do\n";
outputLineDirective(node->getLine().first_line);
out << "{\n";
}
else
{
out << "{for(";
out << "{LOOP for(";
if (node->getInit())
{
@ -2503,6 +2528,12 @@ bool OutputHLSL::isSingleStatement(TIntermNode *node)
{
return false;
}
else if (aggregate->getOp() == EOpDeclaration)
{
// Declaring multiple comma-separated variables must be considered multiple statements
// because each individual declaration has side effects which are visible in the next.
return false;
}
else
{
for (TIntermSequence::iterator sit = aggregate->getSequence()->begin(); sit != aggregate->getSequence()->end(); sit++)
@ -2675,7 +2706,7 @@ bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node)
// for(int index = initial; index < clampedLimit; index += increment)
out << "for(";
out << "LOOP for(";
index->traverse(this);
out << " = ";
out << initial;

View File

@ -144,6 +144,7 @@ class OutputHLSL : public TIntermTraverser
int mUniqueIndex; // For creating unique names
bool mContainsLoopDiscontinuity;
bool mContainsAnyLoop;
bool mOutputLod0Function;
bool mInsideDiscontinuousLoop;
int mNestedLoopDepth;

View File

@ -1004,12 +1004,12 @@ void TParseContext::handleExtensionDirective(const TSourceLoc& loc, const char*
directiveHandler.handleExtension(srcLoc, extName, behavior);
}
void TParseContext::handlePragmaDirective(const TSourceLoc& loc, const char* name, const char* value)
void TParseContext::handlePragmaDirective(const TSourceLoc& loc, const char* name, const char* value, bool stdgl)
{
pp::SourceLocation srcLoc;
srcLoc.file = loc.first_file;
srcLoc.line = loc.first_line;
directiveHandler.handlePragma(srcLoc, name, value);
directiveHandler.handlePragma(srcLoc, name, value, stdgl);
}
/////////////////////////////////////////////////////////////////////////////////
@ -1364,11 +1364,18 @@ TIntermAggregate* TParseContext::parseInvariantDeclaration(const TSourceLoc &inv
{
error(identifierLoc, "undeclared identifier declared as invariant", identifier->c_str());
recover();
return NULL;
}
else
{
const TString kGlFrontFacing("gl_FrontFacing");
if (*identifier == kGlFrontFacing)
{
error(identifierLoc, "identifier should not be declared as invariant", identifier->c_str());
recover();
return NULL;
}
symbolTable.addInvariantVarying(*identifier);
const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol);
ASSERT(variable);
const TType &type = variable->getType();

View File

@ -116,7 +116,7 @@ struct TParseContext {
bool supportsExtension(const char* extension);
bool isExtensionEnabled(const char* extension) const;
void handleExtensionDirective(const TSourceLoc& loc, const char* extName, const char* behavior);
void handlePragmaDirective(const TSourceLoc& loc, const char* name, const char* value);
void handlePragmaDirective(const TSourceLoc& loc, const char* name, const char* value, bool stdgl);
bool containsSampler(TType& type);
bool areAllChildConst(TIntermAggregate* aggrNode);

View File

@ -7,13 +7,23 @@
#ifndef COMPILER_PRAGMA_H_
#define COMPILER_PRAGMA_H_
struct TPragma {
struct TPragma
{
struct STDGL
{
STDGL() : invariantAll(false) { }
bool invariantAll;
};
// By default optimization is turned on and debug is turned off.
TPragma() : optimize(true), debug(false) { }
TPragma(bool o, bool d) : optimize(o), debug(d) { }
bool optimize;
bool debug;
STDGL stdgl;
};
#endif // COMPILER_PRAGMA_H_

View File

@ -37,72 +37,6 @@ bool isInitialized = false;
// and the shading language compiler.
//
static bool CheckVariableMaxLengths(const ShHandle handle,
size_t expectedValue)
{
size_t activeUniformLimit = 0;
ShGetInfo(handle, SH_ACTIVE_UNIFORM_MAX_LENGTH, &activeUniformLimit);
size_t activeAttribLimit = 0;
ShGetInfo(handle, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, &activeAttribLimit);
size_t varyingLimit = 0;
ShGetInfo(handle, SH_VARYING_MAX_LENGTH, &varyingLimit);
return (expectedValue == activeUniformLimit &&
expectedValue == activeAttribLimit &&
expectedValue == varyingLimit);
}
bool CheckMappedNameMaxLength(const ShHandle handle, size_t expectedValue)
{
size_t mappedNameMaxLength = 0;
ShGetInfo(handle, SH_MAPPED_NAME_MAX_LENGTH, &mappedNameMaxLength);
return (expectedValue == mappedNameMaxLength);
}
template <typename VarT>
const sh::ShaderVariable *ReturnVariable(const std::vector<VarT> &infoList, int index)
{
if (index < 0 || static_cast<size_t>(index) >= infoList.size())
{
return NULL;
}
return &infoList[index];
}
const sh::ShaderVariable *GetVariable(const TCompiler *compiler, ShShaderInfo varType, int index)
{
switch (varType)
{
case SH_ACTIVE_ATTRIBUTES:
return ReturnVariable(compiler->getAttributes(), index);
case SH_ACTIVE_UNIFORMS:
return ReturnVariable(compiler->getExpandedUniforms(), index);
case SH_VARYINGS:
return ReturnVariable(compiler->getExpandedVaryings(), index);
default:
UNREACHABLE();
return NULL;
}
}
ShPrecisionType ConvertPrecision(sh::GLenum precision)
{
switch (precision)
{
case GL_HIGH_FLOAT:
case GL_HIGH_INT:
return SH_PRECISION_HIGHP;
case GL_MEDIUM_FLOAT:
case GL_MEDIUM_INT:
return SH_PRECISION_MEDIUMP;
case GL_LOW_FLOAT:
case GL_LOW_INT:
return SH_PRECISION_LOWP;
default:
return SH_PRECISION_UNDEFINED;
}
}
template <typename VarT>
const std::vector<VarT> *GetVariableList(const TCompiler *compiler, ShaderVariableType variableType);
@ -150,32 +84,48 @@ const std::vector<VarT> *GetShaderVariables(const ShHandle handle, ShaderVariabl
return GetVariableList<VarT>(compiler, variableType);
}
TCompiler *GetCompilerFromHandle(ShHandle handle)
{
if (!handle)
return NULL;
TShHandleBase *base = static_cast<TShHandleBase *>(handle);
return base->getAsCompiler();
}
TranslatorHLSL *GetTranslatorHLSLFromHandle(ShHandle handle)
{
if (!handle)
return NULL;
TShHandleBase *base = static_cast<TShHandleBase *>(handle);
return base->getAsTranslatorHLSL();
}
} // namespace anonymous
//
// Driver must call this first, once, before doing any other compiler operations.
// Subsequent calls to this function are no-op.
//
int ShInitialize()
bool ShInitialize()
{
if (!isInitialized)
{
isInitialized = InitProcess();
}
return isInitialized ? 1 : 0;
return isInitialized;
}
//
// Cleanup symbol tables
//
int ShFinalize()
bool ShFinalize()
{
if (isInitialized)
{
DetachProcess();
isInitialized = false;
}
return 1;
return true;
}
//
@ -183,6 +133,9 @@ int ShFinalize()
//
void ShInitBuiltInResources(ShBuiltInResources* resources)
{
// Make comparable.
memset(resources, 0, sizeof(*resources));
// Constants.
resources->MaxVertexAttribs = 8;
resources->MaxVertexUniformVectors = 128;
@ -201,6 +154,8 @@ void ShInitBuiltInResources(ShBuiltInResources* resources)
resources->EXT_frag_depth = 0;
resources->EXT_shader_texture_lod = 0;
resources->NV_draw_buffers = 0;
// Disable highp precision in fragment shader by default.
resources->FragmentPrecisionHigh = 0;
@ -251,23 +206,13 @@ void ShDestruct(ShHandle handle)
DeleteCompiler(base->getAsCompiler());
}
void ShGetBuiltInResourcesString(const ShHandle handle, size_t outStringLen, char *outString)
const std::string &ShGetBuiltInResourcesString(const ShHandle handle)
{
if (!handle || !outString)
{
return;
}
TShHandleBase *base = static_cast<TShHandleBase*>(handle);
TCompiler *compiler = base->getAsCompiler();
if (!compiler)
{
return;
}
strncpy(outString, compiler->getBuiltInResourcesString().c_str(), outStringLen);
outString[outStringLen - 1] = '\0';
TCompiler *compiler = GetCompilerFromHandle(handle);
ASSERT(compiler);
return compiler->getBuiltInResourcesString();
}
//
// Do an actual compile on the given strings. The result is left
// in the given compile object.
@ -275,219 +220,62 @@ void ShGetBuiltInResourcesString(const ShHandle handle, size_t outStringLen, cha
// Return: The return value of ShCompile is really boolean, indicating
// success or failure.
//
int ShCompile(
bool ShCompile(
const ShHandle handle,
const char* const shaderStrings[],
const char *const shaderStrings[],
size_t numStrings,
int compileOptions)
{
if (handle == 0)
return 0;
TCompiler *compiler = GetCompilerFromHandle(handle);
ASSERT(compiler);
TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
TCompiler* compiler = base->getAsCompiler();
if (compiler == 0)
return 0;
bool success = compiler->compile(shaderStrings, numStrings, compileOptions);
return success ? 1 : 0;
return compiler->compile(shaderStrings, numStrings, compileOptions);
}
void ShGetInfo(const ShHandle handle, ShShaderInfo pname, size_t* params)
int ShGetShaderVersion(const ShHandle handle)
{
if (!handle || !params)
return;
TCompiler* compiler = GetCompilerFromHandle(handle);
ASSERT(compiler);
return compiler->getShaderVersion();
}
TShHandleBase* base = static_cast<TShHandleBase*>(handle);
TCompiler* compiler = base->getAsCompiler();
if (!compiler) return;
switch(pname)
{
case SH_INFO_LOG_LENGTH:
*params = compiler->getInfoSink().info.size() + 1;
break;
case SH_OBJECT_CODE_LENGTH:
*params = compiler->getInfoSink().obj.size() + 1;
break;
case SH_ACTIVE_UNIFORMS:
*params = compiler->getExpandedUniforms().size();
break;
case SH_ACTIVE_UNIFORM_MAX_LENGTH:
*params = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec());
break;
case SH_ACTIVE_ATTRIBUTES:
*params = compiler->getAttributes().size();
break;
case SH_ACTIVE_ATTRIBUTE_MAX_LENGTH:
*params = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec());
break;
case SH_VARYINGS:
*params = compiler->getExpandedVaryings().size();
break;
case SH_VARYING_MAX_LENGTH:
*params = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec());
break;
case SH_MAPPED_NAME_MAX_LENGTH:
// Use longer length than MAX_SHORTENED_IDENTIFIER_SIZE to
// handle array and struct dereferences.
*params = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec());
break;
case SH_NAME_MAX_LENGTH:
*params = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec());
break;
case SH_HASHED_NAME_MAX_LENGTH:
if (compiler->getHashFunction() == NULL) {
*params = 0;
} else {
// 64 bits hashing output requires 16 bytes for hex
// representation.
const char HashedNamePrefix[] = HASHED_NAME_PREFIX;
(void)HashedNamePrefix;
*params = 16 + sizeof(HashedNamePrefix);
}
break;
case SH_HASHED_NAMES_COUNT:
*params = compiler->getNameMap().size();
break;
case SH_SHADER_VERSION:
*params = compiler->getShaderVersion();
break;
case SH_RESOURCES_STRING_LENGTH:
*params = compiler->getBuiltInResourcesString().length() + 1;
break;
case SH_OUTPUT_TYPE:
*params = compiler->getOutputType();
break;
default: UNREACHABLE();
}
ShShaderOutput ShGetShaderOutputType(const ShHandle handle)
{
TCompiler* compiler = GetCompilerFromHandle(handle);
ASSERT(compiler);
return compiler->getOutputType();
}
//
// Return any compiler log of messages for the application.
//
void ShGetInfoLog(const ShHandle handle, char* infoLog)
const std::string &ShGetInfoLog(const ShHandle handle)
{
if (!handle || !infoLog)
return;
TCompiler *compiler = GetCompilerFromHandle(handle);
ASSERT(compiler);
TShHandleBase* base = static_cast<TShHandleBase*>(handle);
TCompiler* compiler = base->getAsCompiler();
if (!compiler) return;
TInfoSink& infoSink = compiler->getInfoSink();
strcpy(infoLog, infoSink.info.c_str());
TInfoSink &infoSink = compiler->getInfoSink();
return infoSink.info.str();
}
//
// Return any object code.
//
void ShGetObjectCode(const ShHandle handle, char* objCode)
const std::string &ShGetObjectCode(const ShHandle handle)
{
if (!handle || !objCode)
return;
TCompiler *compiler = GetCompilerFromHandle(handle);
ASSERT(compiler);
TShHandleBase* base = static_cast<TShHandleBase*>(handle);
TCompiler* compiler = base->getAsCompiler();
if (!compiler) return;
TInfoSink& infoSink = compiler->getInfoSink();
strcpy(objCode, infoSink.obj.c_str());
TInfoSink &infoSink = compiler->getInfoSink();
return infoSink.obj.str();
}
void ShGetVariableInfo(const ShHandle handle,
ShShaderInfo varType,
int index,
size_t* length,
int* size,
sh::GLenum* type,
ShPrecisionType* precision,
int* staticUse,
char* name,
char* mappedName)
const std::map<std::string, std::string> *ShGetNameHashingMap(
const ShHandle handle)
{
if (!handle || !size || !type || !precision || !staticUse || !name)
return;
ASSERT((varType == SH_ACTIVE_ATTRIBUTES) ||
(varType == SH_ACTIVE_UNIFORMS) ||
(varType == SH_VARYINGS));
TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
TCompiler* compiler = base->getAsCompiler();
if (compiler == 0)
return;
const sh::ShaderVariable *varInfo = GetVariable(compiler, varType, index);
if (!varInfo)
{
return;
}
if (length) *length = varInfo->name.size();
*size = varInfo->elementCount();
*type = varInfo->type;
*precision = ConvertPrecision(varInfo->precision);
*staticUse = varInfo->staticUse ? 1 : 0;
// This size must match that queried by
// SH_ACTIVE_UNIFORM_MAX_LENGTH, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, SH_VARYING_MAX_LENGTH
// in ShGetInfo, below.
size_t variableLength = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec());
ASSERT(CheckVariableMaxLengths(handle, variableLength));
strncpy(name, varInfo->name.c_str(), variableLength);
name[variableLength - 1] = 0;
if (mappedName)
{
// This size must match that queried by
// SH_MAPPED_NAME_MAX_LENGTH in ShGetInfo, below.
size_t maxMappedNameLength = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec());
ASSERT(CheckMappedNameMaxLength(handle, maxMappedNameLength));
strncpy(mappedName, varInfo->mappedName.c_str(), maxMappedNameLength);
mappedName[maxMappedNameLength - 1] = 0;
}
}
void ShGetNameHashingEntry(const ShHandle handle,
int index,
char* name,
char* hashedName)
{
if (!handle || !name || !hashedName || index < 0)
return;
TShHandleBase* base = static_cast<TShHandleBase*>(handle);
TCompiler* compiler = base->getAsCompiler();
if (!compiler) return;
const NameMap& nameMap = compiler->getNameMap();
if (index >= static_cast<int>(nameMap.size()))
return;
NameMap::const_iterator it = nameMap.begin();
for (int i = 0; i < index; ++i)
++it;
size_t len = it->first.length() + 1;
size_t max_len = 0;
ShGetInfo(handle, SH_NAME_MAX_LENGTH, &max_len);
if (len > max_len) {
ASSERT(false);
len = max_len;
}
strncpy(name, it->first.c_str(), len);
// To be on the safe side in case the source is longer than expected.
name[len - 1] = '\0';
len = it->second.length() + 1;
max_len = 0;
ShGetInfo(handle, SH_HASHED_NAME_MAX_LENGTH, &max_len);
if (len > max_len) {
ASSERT(false);
len = max_len;
}
strncpy(hashedName, it->second.c_str(), len);
// To be on the safe side in case the source is longer than expected.
hashedName[len - 1] = '\0';
TCompiler *compiler = GetCompilerFromHandle(handle);
ASSERT(compiler);
return &(compiler->getNameMap());
}
const std::vector<sh::Uniform> *ShGetUniforms(const ShHandle handle)
@ -515,11 +303,11 @@ const std::vector<sh::InterfaceBlock> *ShGetInterfaceBlocks(const ShHandle handl
return GetShaderVariables<sh::InterfaceBlock>(handle, SHADERVAR_INTERFACEBLOCK);
}
int ShCheckVariablesWithinPackingLimits(
int maxVectors, ShVariableInfo* varInfoArray, size_t varInfoArraySize)
bool ShCheckVariablesWithinPackingLimits(
int maxVectors, ShVariableInfo *varInfoArray, size_t varInfoArraySize)
{
if (varInfoArraySize == 0)
return 1;
return true;
ASSERT(varInfoArray);
std::vector<sh::ShaderVariable> variables;
for (size_t ii = 0; ii < varInfoArraySize; ++ii)
@ -528,24 +316,17 @@ int ShCheckVariablesWithinPackingLimits(
variables.push_back(var);
}
VariablePacker packer;
return packer.CheckVariablesWithinPackingLimits(maxVectors, variables) ? 1 : 0;
return packer.CheckVariablesWithinPackingLimits(maxVectors, variables);
}
bool ShGetInterfaceBlockRegister(const ShHandle handle,
const char *interfaceBlockName,
const std::string &interfaceBlockName,
unsigned int *indexOut)
{
if (!handle || !interfaceBlockName || !indexOut)
{
return false;
}
ASSERT(indexOut);
TShHandleBase* base = static_cast<TShHandleBase*>(handle);
TranslatorHLSL* translator = base->getAsTranslatorHLSL();
if (!translator)
{
return false;
}
TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle);
ASSERT(translator);
if (!translator->hasInterfaceBlock(interfaceBlockName))
{
@ -557,20 +338,12 @@ bool ShGetInterfaceBlockRegister(const ShHandle handle,
}
bool ShGetUniformRegister(const ShHandle handle,
const char *uniformName,
const std::string &uniformName,
unsigned int *indexOut)
{
if (!handle || !uniformName || !indexOut)
{
return false;
}
TShHandleBase* base = static_cast<TShHandleBase*>(handle);
TranslatorHLSL* translator = base->getAsTranslatorHLSL();
if (!translator)
{
return false;
}
ASSERT(indexOut);
TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle);
ASSERT(translator);
if (!translator->hasUniform(uniformName))
{

View File

@ -9,6 +9,8 @@
#include <GLSLANG/ShaderLang.h>
#include "compiler/translator/compilerdebug.h"
namespace sh
{
@ -53,6 +55,126 @@ ShaderVariable &ShaderVariable::operator=(const ShaderVariable &other)
return *this;
}
bool ShaderVariable::operator==(const ShaderVariable &other) const
{
if (type != other.type ||
precision != other.precision ||
name != other.name ||
mappedName != other.mappedName ||
arraySize != other.arraySize ||
staticUse != other.staticUse ||
fields.size() != other.fields.size() ||
structName != other.structName)
{
return false;
}
for (size_t ii = 0; ii < fields.size(); ++ii)
{
if (fields[ii] != other.fields[ii])
return false;
}
return true;
}
bool ShaderVariable::findInfoByMappedName(
const std::string &mappedFullName,
const ShaderVariable **leafVar, std::string *originalFullName) const
{
ASSERT(leafVar && originalFullName);
// There are three cases:
// 1) the top variable is of struct type;
// 2) the top variable is an array;
// 3) otherwise.
size_t pos = mappedFullName.find_first_of(".[");
std::string topName;
if (pos == std::string::npos)
{
// Case 3.
if (mappedFullName != this->mappedName)
return false;
*originalFullName = this->name;
*leafVar = this;
return true;
}
else
{
std::string topName = mappedFullName.substr(0, pos);
if (topName != this->mappedName)
return false;
std::string originalName = this->name;
std::string remaining;
if (mappedFullName[pos] == '[')
{
// Case 2.
size_t closePos = mappedFullName.find_first_of(']');
if (closePos < pos || closePos == std::string::npos)
return false;
// Append '[index]'.
originalName += mappedFullName.substr(pos, closePos - pos + 1);
if (closePos + 1 == mappedFullName.size())
{
*originalFullName = originalName;
*leafVar = this;
return true;
}
else
{
// In the form of 'a[0].b', so after ']', '.' is expected.
if (mappedFullName[closePos + 1] != '.')
return false;
remaining = mappedFullName.substr(closePos + 2); // Skip "]."
}
}
else
{
// Case 1.
remaining = mappedFullName.substr(pos + 1); // Skip "."
}
for (size_t ii = 0; ii < this->fields.size(); ++ii)
{
const ShaderVariable *fieldVar = NULL;
std::string originalFieldName;
bool found = fields[ii].findInfoByMappedName(
remaining, &fieldVar, &originalFieldName);
if (found)
{
*originalFullName = originalName + "." + originalFieldName;
*leafVar = fieldVar;
return true;
}
}
return false;
}
}
bool ShaderVariable::isSameVariableAtLinkTime(
const ShaderVariable &other, bool matchPrecision) const
{
if (type != other.type)
return false;
if (matchPrecision && precision != other.precision)
return false;
if (name != other.name)
return false;
ASSERT(mappedName == other.mappedName);
if (arraySize != other.arraySize)
return false;
if (fields.size() != other.fields.size())
return false;
for (size_t ii = 0; ii < fields.size(); ++ii)
{
if (!fields[ii].isSameVariableAtLinkTime(other.fields[ii],
matchPrecision))
{
return false;
}
}
if (structName != other.structName)
return false;
return true;
}
Uniform::Uniform()
{}
@ -69,6 +191,16 @@ Uniform &Uniform::operator=(const Uniform &other)
return *this;
}
bool Uniform::operator==(const Uniform &other) const
{
return ShaderVariable::operator==(other);
}
bool Uniform::isSameUniformAtLinkTime(const Uniform &other) const
{
return ShaderVariable::isSameVariableAtLinkTime(other, true);
}
Attribute::Attribute()
: location(-1)
{}
@ -88,6 +220,12 @@ Attribute &Attribute::operator=(const Attribute &other)
return *this;
}
bool Attribute::operator==(const Attribute &other) const
{
return (ShaderVariable::operator==(other) &&
location == other.location);
}
InterfaceBlockField::InterfaceBlockField()
: isRowMajorLayout(false)
{}
@ -107,6 +245,19 @@ InterfaceBlockField &InterfaceBlockField::operator=(const InterfaceBlockField &o
return *this;
}
bool InterfaceBlockField::operator==(const InterfaceBlockField &other) const
{
return (ShaderVariable::operator==(other) &&
isRowMajorLayout == other.isRowMajorLayout);
}
bool InterfaceBlockField::isSameInterfaceBlockFieldAtLinkTime(
const InterfaceBlockField &other) const
{
return (ShaderVariable::isSameVariableAtLinkTime(other, true) &&
isRowMajorLayout == other.isRowMajorLayout);
}
Varying::Varying()
: interpolation(INTERPOLATION_SMOOTH),
isInvariant(false)
@ -129,6 +280,20 @@ Varying &Varying::operator=(const Varying &other)
return *this;
}
bool Varying::operator==(const Varying &other) const
{
return (ShaderVariable::operator==(other) &&
interpolation == other.interpolation &&
isInvariant == other.isInvariant);
}
bool Varying::isSameVaryingAtLinkTime(const Varying &other) const
{
return (ShaderVariable::isSameVariableAtLinkTime(other, false) &&
interpolation == other.interpolation &&
isInvariant == other.isInvariant);
}
InterfaceBlock::InterfaceBlock()
: arraySize(0),
layout(BLOCKLAYOUT_PACKED),

View File

@ -31,6 +31,7 @@
//
#include <assert.h>
#include <set>
#include "common/angleutils.h"
#include "compiler/translator/InfoSink.h"
@ -299,19 +300,21 @@ class TSymbolTableLevel
tLevel level;
};
enum ESymbolLevel
{
COMMON_BUILTINS = 0,
ESSL1_BUILTINS = 1,
ESSL3_BUILTINS = 2,
LAST_BUILTIN_LEVEL = ESSL3_BUILTINS,
GLOBAL_LEVEL = 3
};
// Define ESymbolLevel as int rather than an enum since level can go
// above GLOBAL_LEVEL and cause atBuiltInLevel() to fail if the
// compiler optimizes the >= of the last element to ==.
typedef int ESymbolLevel;
const int COMMON_BUILTINS = 0;
const int ESSL1_BUILTINS = 1;
const int ESSL3_BUILTINS = 2;
const int LAST_BUILTIN_LEVEL = ESSL3_BUILTINS;
const int GLOBAL_LEVEL = 3;
class TSymbolTable
{
public:
TSymbolTable()
: mGlobalInvariant(false)
{
// The symbol table cannot be used until push() is called, but
// the lack of an initial call to push() can be used to detect
@ -408,6 +411,25 @@ class TSymbolTable
// for the specified TBasicType
TPrecision getDefaultPrecision(TBasicType type) const;
// This records invariant varyings declared through
// "invariant varying_name;".
void addInvariantVarying(const TString &originalName)
{
mInvariantVaryings.insert(originalName);
}
// If this returns false, the varying could still be invariant
// if it is set as invariant during the varying variable
// declaration - this piece of information is stored in the
// variable's type, not here.
bool isVaryingInvariant(const TString &originalName) const
{
return (mGlobalInvariant ||
mInvariantVaryings.count(originalName) > 0);
}
void setGlobalInvariant() { mGlobalInvariant = true; }
bool getGlobalInvariant() const { return mGlobalInvariant; }
static int nextUniqueId()
{
return ++uniqueIdCounter;
@ -423,6 +445,9 @@ class TSymbolTable
typedef TMap<TBasicType, TPrecision> PrecisionStackLevel;
std::vector< PrecisionStackLevel *> precisionStack;
std::set<TString> mInvariantVaryings;
bool mGlobalInvariant;
static int uniqueIdCounter;
};

View File

@ -16,6 +16,8 @@ TranslatorESSL::TranslatorESSL(sh::GLenum type, ShShaderSpec spec)
void TranslatorESSL::translate(TIntermNode* root) {
TInfoSinkBase& sink = getInfoSink().obj;
writePragma();
// Write built-in extension behaviors.
writeExtensionBehavior();
@ -37,8 +39,13 @@ void TranslatorESSL::writeExtensionBehavior() {
for (TExtensionBehavior::const_iterator iter = extensionBehavior.begin();
iter != extensionBehavior.end(); ++iter) {
if (iter->second != EBhUndefined) {
sink << "#extension " << iter->first << " : "
<< getBehaviorString(iter->second) << "\n";
if (getResources().NV_draw_buffers && iter->first == "GL_EXT_draw_buffers") {
sink << "#extension GL_NV_draw_buffers : "
<< getBehaviorString(iter->second) << "\n";
} else {
sink << "#extension " << iter->first << " : "
<< getBehaviorString(iter->second) << "\n";
}
}
}
}

View File

@ -9,18 +9,6 @@
#include "compiler/translator/OutputGLSL.h"
#include "compiler/translator/VersionGLSL.h"
static void writeVersion(sh::GLenum type, TIntermNode* root,
TInfoSinkBase& sink) {
TVersionGLSL versionGLSL(type);
root->traverse(&versionGLSL);
int version = versionGLSL.getVersion();
// We need to write version directive only if it is greater than 110.
// If there is no version directive in the shader, 110 is implied.
if (version > 110) {
sink << "#version " << version << "\n";
}
}
TranslatorGLSL::TranslatorGLSL(sh::GLenum type, ShShaderSpec spec)
: TCompiler(type, spec, SH_GLSL_OUTPUT) {
}
@ -29,7 +17,9 @@ void TranslatorGLSL::translate(TIntermNode* root) {
TInfoSinkBase& sink = getInfoSink().obj;
// Write GLSL version.
writeVersion(getShaderType(), root, sink);
writeVersion(root);
writePragma();
// Write extension behaviour as needed
writeExtensionBehavior();
@ -46,6 +36,20 @@ void TranslatorGLSL::translate(TIntermNode* root) {
root->traverse(&outputGLSL);
}
void TranslatorGLSL::writeVersion(TIntermNode *root)
{
TVersionGLSL versionGLSL(getShaderType(), getPragma());
root->traverse(&versionGLSL);
int version = versionGLSL.getVersion();
// We need to write version directive only if it is greater than 110.
// If there is no version directive in the shader, 110 is implied.
if (version > 110)
{
TInfoSinkBase& sink = getInfoSink().obj;
sink << "#version " << version << "\n";
}
}
void TranslatorGLSL::writeExtensionBehavior() {
TInfoSinkBase& sink = getInfoSink().obj;
const TExtensionBehavior& extensionBehavior = getExtensionBehavior();

View File

@ -9,14 +9,16 @@
#include "compiler/translator/Compiler.h"
class TranslatorGLSL : public TCompiler {
public:
class TranslatorGLSL : public TCompiler
{
public:
TranslatorGLSL(sh::GLenum type, ShShaderSpec spec);
protected:
virtual void translate(TIntermNode* root);
protected:
virtual void translate(TIntermNode *root);
private:
private:
void writeVersion(TIntermNode *root);
void writeExtensionBehavior();
};

View File

@ -94,6 +94,7 @@ const char *GetOperatorString(TOperator op)
case EOpLogicalXor: return "^^";
case EOpLogicalAnd: return "&&";
case EOpNegative: return "-";
case EOpPositive: return "+";
case EOpVectorLogicalNot: return "not";
case EOpLogicalNot: return "!";
case EOpPostIncrement: return "++";

View File

@ -5,6 +5,7 @@
//
#include "angle_gl.h"
#include "compiler/translator/SymbolTable.h"
#include "compiler/translator/VariableInfo.h"
#include "compiler/translator/util.h"
#include "common/utilities.h"
@ -131,7 +132,8 @@ CollectVariables::CollectVariables(std::vector<sh::Attribute> *attribs,
std::vector<sh::Uniform> *uniforms,
std::vector<sh::Varying> *varyings,
std::vector<sh::InterfaceBlock> *interfaceBlocks,
ShHashFunction64 hashFunction)
ShHashFunction64 hashFunction,
const TSymbolTable &symbolTable)
: mAttribs(attribs),
mOutputVariables(outputVariables),
mUniforms(uniforms),
@ -140,7 +142,10 @@ CollectVariables::CollectVariables(std::vector<sh::Attribute> *attribs,
mPointCoordAdded(false),
mFrontFacingAdded(false),
mFragCoordAdded(false),
mHashFunction(hashFunction)
mPositionAdded(false),
mPointSizeAdded(false),
mHashFunction(hashFunction),
mSymbolTable(symbolTable)
{
}
@ -200,12 +205,14 @@ void CollectVariables::visitSymbol(TIntermSymbol *symbol)
if (!mFragCoordAdded)
{
Varying info;
info.name = "gl_FragCoord";
info.mappedName = "gl_FragCoord";
const char kName[] = "gl_FragCoord";
info.name = kName;
info.mappedName = kName;
info.type = GL_FLOAT_VEC4;
info.arraySize = 0;
info.precision = GL_MEDIUM_FLOAT; // Use mediump as it doesn't really matter.
info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
info.staticUse = true;
info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
mVaryings->push_back(info);
mFragCoordAdded = true;
}
@ -214,12 +221,14 @@ void CollectVariables::visitSymbol(TIntermSymbol *symbol)
if (!mFrontFacingAdded)
{
Varying info;
info.name = "gl_FrontFacing";
info.mappedName = "gl_FrontFacing";
const char kName[] = "gl_FrontFacing";
info.name = kName;
info.mappedName = kName;
info.type = GL_BOOL;
info.arraySize = 0;
info.precision = GL_NONE;
info.staticUse = true;
info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
mVaryings->push_back(info);
mFrontFacingAdded = true;
}
@ -228,16 +237,50 @@ void CollectVariables::visitSymbol(TIntermSymbol *symbol)
if (!mPointCoordAdded)
{
Varying info;
info.name = "gl_PointCoord";
info.mappedName = "gl_PointCoord";
const char kName[] = "gl_PointCoord";
info.name = kName;
info.mappedName = kName;
info.type = GL_FLOAT_VEC2;
info.arraySize = 0;
info.precision = GL_MEDIUM_FLOAT; // Use mediump as it doesn't really matter.
info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
info.staticUse = true;
info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
mVaryings->push_back(info);
mPointCoordAdded = true;
}
return;
case EvqPosition:
if (!mPositionAdded)
{
Varying info;
const char kName[] = "gl_Position";
info.name = kName;
info.mappedName = kName;
info.type = GL_FLOAT_VEC4;
info.arraySize = 0;
info.precision = GL_HIGH_FLOAT; // Defined by spec.
info.staticUse = true;
info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
mVaryings->push_back(info);
mPositionAdded = true;
}
return;
case EvqPointSize:
if (!mPointSizeAdded)
{
Varying info;
const char kName[] = "gl_PointSize";
info.name = kName;
info.mappedName = kName;
info.type = GL_FLOAT;
info.arraySize = 0;
info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
info.staticUse = true;
info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
mVaryings->push_back(info);
mPointSizeAdded = true;
}
return;
default:
break;
}
@ -251,8 +294,10 @@ void CollectVariables::visitSymbol(TIntermSymbol *symbol)
class NameHashingTraverser : public GetVariableTraverser
{
public:
NameHashingTraverser(ShHashFunction64 hashFunction)
: mHashFunction(hashFunction)
NameHashingTraverser(ShHashFunction64 hashFunction,
const TSymbolTable &symbolTable)
: GetVariableTraverser(symbolTable),
mHashFunction(hashFunction)
{}
private:
@ -312,7 +357,7 @@ void CollectVariables::visitVariable(const TIntermSymbol *variable,
const TString &fullFieldName = InterfaceBlockFieldName(*blockType, field);
const TType &fieldType = *field.type();
GetVariableTraverser traverser;
GetVariableTraverser traverser(mSymbolTable);
traverser.traverse(fieldType, fullFieldName, &interfaceBlock.fields);
interfaceBlock.fields.back().isRowMajorLayout = (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor);
@ -325,7 +370,7 @@ template <typename VarT>
void CollectVariables::visitVariable(const TIntermSymbol *variable,
std::vector<VarT> *infoList) const
{
NameHashingTraverser traverser(mHashFunction);
NameHashingTraverser traverser(mHashFunction, mSymbolTable);
traverser.traverse(variable->getType(), variable->getSymbol(), infoList);
}
@ -421,9 +466,8 @@ bool CollectVariables::visitBinary(Visit, TIntermBinary *binaryNode)
return true;
}
template <typename VarT>
void ExpandVariables(const std::vector<VarT> &compact,
std::vector<ShaderVariable> *expanded)
void ExpandUniforms(const std::vector<Uniform> &compact,
std::vector<ShaderVariable> *expanded)
{
for (size_t variableIndex = 0; variableIndex < compact.size(); variableIndex++)
{
@ -432,7 +476,4 @@ void ExpandVariables(const std::vector<VarT> &compact,
}
}
template void ExpandVariables(const std::vector<Uniform> &, std::vector<ShaderVariable> *);
template void ExpandVariables(const std::vector<Varying> &, std::vector<ShaderVariable> *);
}

View File

@ -11,6 +11,8 @@
#include "compiler/translator/IntermNode.h"
class TSymbolTable;
namespace sh
{
@ -23,7 +25,8 @@ class CollectVariables : public TIntermTraverser
std::vector<Uniform> *uniforms,
std::vector<Varying> *varyings,
std::vector<InterfaceBlock> *interfaceBlocks,
ShHashFunction64 hashFunction);
ShHashFunction64 hashFunction,
const TSymbolTable &symbolTable);
virtual void visitSymbol(TIntermSymbol *symbol);
virtual bool visitAggregate(Visit, TIntermAggregate *node);
@ -48,13 +51,17 @@ class CollectVariables : public TIntermTraverser
bool mFrontFacingAdded;
bool mFragCoordAdded;
bool mPositionAdded;
bool mPointSizeAdded;
ShHashFunction64 mHashFunction;
const TSymbolTable &mSymbolTable;
};
// Expand struct variables to flattened lists of split variables
template <typename VarT>
void ExpandVariables(const std::vector<VarT> &compact,
std::vector<ShaderVariable> *expanded);
// Expand struct uniforms to flattened lists of split variables
void ExpandUniforms(const std::vector<Uniform> &compact,
std::vector<ShaderVariable> *expanded);
}

View File

@ -26,18 +26,12 @@ static const int GLSL_VERSION_120 = 120;
// GLSL 1.2 relaxed the restriction on arrays, section 5.8: "Variables that
// are built-in types, entire structures or arrays... are all l-values."
//
// TODO(alokp): The following two cases of invariant decalaration get lost
// during parsing - they do not get carried over to the intermediate tree.
// Handle these cases:
// 1. When a pragma is used to force all output variables to be invariant:
// - #pragma STDGL invariant(all)
// 2. When a previously decalared or built-in variable is marked invariant:
// - invariant gl_Position;
// - varying vec3 color; invariant color;
//
TVersionGLSL::TVersionGLSL(sh::GLenum type)
: mVersion(GLSL_VERSION_110)
TVersionGLSL::TVersionGLSL(sh::GLenum type, const TPragma &pragma)
{
if (pragma.stdgl.invariantAll)
mVersion = GLSL_VERSION_120;
else
mVersion = GLSL_VERSION_110;
}
void TVersionGLSL::visitSymbol(TIntermSymbol *node)

View File

@ -9,6 +9,8 @@
#include "compiler/translator/IntermNode.h"
#include "compiler/translator/Pragma.h"
// Traverses the intermediate tree to return the minimum GLSL version
// required to legally access all built-in features used in the shader.
// GLSL 1.1 which is mandated by OpenGL 2.0 provides:
@ -27,7 +29,7 @@
class TVersionGLSL : public TIntermTraverser
{
public:
TVersionGLSL(sh::GLenum type);
TVersionGLSL(sh::GLenum type, const TPragma &pragma);
// Returns 120 if the following is used the shader:
// - "invariant",

View File

@ -354,6 +354,15 @@ function_call
// Treat it like a built-in unary operator.
//
$$ = context->intermediate.addUnaryMath(op, $1.intermNode, @1);
const TType& returnType = fnCandidate->getReturnType();
if (returnType.getBasicType() == EbtBool) {
// Bool types should not have precision, so we'll override any precision
// that might have been set by addUnaryMath.
$$->setType(returnType);
} else {
// addUnaryMath has set the precision of the node based on the operand.
$$->setTypePreservePrecision(returnType);
}
if ($$ == 0) {
std::stringstream extraInfoStream;
extraInfoStream << "built in unary operator function. Type: " << static_cast<TIntermTyped*>($1.intermNode)->getCompleteString();
@ -362,20 +371,29 @@ function_call
YYERROR;
}
} else {
$$ = context->intermediate.setAggregateOperator($1.intermAggregate, op, @1);
TIntermAggregate *aggregate = context->intermediate.setAggregateOperator($1.intermAggregate, op, @1);
aggregate->setType(fnCandidate->getReturnType());
aggregate->setPrecisionFromChildren();
$$ = aggregate;
}
} else {
// This is a real function call
$$ = context->intermediate.setAggregateOperator($1.intermAggregate, EOpFunctionCall, @1);
$$->setType(fnCandidate->getReturnType());
TIntermAggregate *aggregate = context->intermediate.setAggregateOperator($1.intermAggregate, EOpFunctionCall, @1);
aggregate->setType(fnCandidate->getReturnType());
// this is how we know whether the given function is a builtIn function or a user defined function
// if builtIn == false, it's a userDefined -> could be an overloaded builtIn function also
// if builtIn == true, it's definitely a builtIn function with EOpNull
if (!builtIn)
$$->getAsAggregate()->setUserDefined();
$$->getAsAggregate()->setName(fnCandidate->getMangledName());
aggregate->setUserDefined();
aggregate->setName(fnCandidate->getMangledName());
// This needs to happen after the name is set
if (builtIn)
aggregate->setBuiltInFunctionPrecision();
$$ = aggregate;
TQualifier qual;
for (size_t i = 0; i < fnCandidate->getParamCount(); ++i) {
@ -388,7 +406,6 @@ function_call
}
}
}
$$->setType(fnCandidate->getReturnType());
} else {
// error message was put out by PaFindFunction()
// Put on a dummy node for error recovery
@ -500,6 +517,7 @@ unary_expression
const char* errorOp = "";
switch($1.op) {
case EOpNegative: errorOp = "-"; break;
case EOpPositive: errorOp = "+"; break;
case EOpLogicalNot: errorOp = "!"; break;
default: break;
}
@ -514,7 +532,7 @@ unary_expression
// Grammar Note: No traditional style type casts.
unary_operator
: PLUS { $$.op = EOpNull; }
: PLUS { $$.op = EOpPositive; }
| DASH { $$.op = EOpNegative; }
| BANG { $$.op = EOpLogicalNot; }
;
@ -762,7 +780,7 @@ declaration
TIntermAggregate *prototype = new TIntermAggregate;
prototype->setType(function.getReturnType());
prototype->setName(function.getName());
prototype->setName(function.getMangledName());
for (size_t i = 0; i < function.getParamCount(); i++)
{

View File

@ -62,7 +62,9 @@ TString TType::getCompleteString() const
TStringStream stream;
if (qualifier != EvqTemporary && qualifier != EvqGlobal)
stream << getQualifierString() << " " << getPrecisionString() << " ";
stream << getQualifierString() << " ";
if (precision != EbpUndefined)
stream << getPrecisionString() << " ";
if (array)
stream << "array[" << getArraySize() << "] of ";
if (isMatrix())
@ -221,6 +223,7 @@ bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary *node)
switch (node->getOp())
{
case EOpNegative: out << "Negate value"; break;
case EOpPositive: out << "Positive sign"; break;
case EOpVectorLogicalNot:
case EOpLogicalNot: out << "Negate conditional"; break;
@ -292,6 +295,7 @@ bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
case EOpFunction: out << "Function Definition: " << node->getName(); break;
case EOpFunctionCall: out << "Function Call: " << node->getName(); break;
case EOpParameters: out << "Function Parameters: "; break;
case EOpPrototype: out << "Function Prototype: " << node->getName(); break;
case EOpConstructFloat: out << "Construct float"; break;
case EOpConstructVec2: out << "Construct vec2"; break;

View File

@ -9,6 +9,7 @@
#include <limits>
#include "compiler/preprocessor/numeric_lex.h"
#include "compiler/translator/SymbolTable.h"
#include "common/utilities.h"
bool atof_clamp(const char *str, float *value)
@ -281,8 +282,47 @@ InterpolationType GetInterpolationType(TQualifier qualifier)
}
}
GetVariableTraverser::GetVariableTraverser(const TSymbolTable &symbolTable)
: mSymbolTable(symbolTable)
{
}
template void GetVariableTraverser::setTypeSpecificInfo(
const TType &type, const TString& name, InterfaceBlockField *variable);
template void GetVariableTraverser::setTypeSpecificInfo(
const TType &type, const TString& name, ShaderVariable *variable);
template void GetVariableTraverser::setTypeSpecificInfo(
const TType &type, const TString& name, Uniform *variable);
template<>
void GetVariableTraverser::setTypeSpecificInfo(
const TType &type, const TString& name, Varying *variable)
{
ASSERT(variable);
switch (type.getQualifier())
{
case EvqInvariantVaryingIn:
case EvqInvariantVaryingOut:
variable->isInvariant = true;
break;
case EvqVaryingIn:
case EvqVaryingOut:
if (mSymbolTable.isVaryingInvariant(name))
{
variable->isInvariant = true;
}
break;
default:
break;
}
variable->interpolation = GetInterpolationType(type.getQualifier());
}
template <typename VarT>
void GetVariableTraverser::traverse(const TType &type, const TString &name, std::vector<VarT> *output)
void GetVariableTraverser::traverse(const TType &type,
const TString &name,
std::vector<VarT> *output)
{
const TStructure *structure = type.getStruct();
@ -309,15 +349,16 @@ void GetVariableTraverser::traverse(const TType &type, const TString &name, std:
traverse(*field->type(), field->name(), &variable.fields);
}
}
setTypeSpecificInfo(type, name, &variable);
visitVariable(&variable);
ASSERT(output);
output->push_back(variable);
}
template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector<InterfaceBlockField> *);
template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector<ShaderVariable> *);
template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector<Uniform> *);
template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector<Varying> *);
template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector<InterfaceBlockField> *);
}

View File

@ -24,6 +24,8 @@ extern bool atof_clamp(const char *str, float *value);
// Return false if overflow happens.
extern bool atoi_clamp(const char *str, int *value);
class TSymbolTable;
namespace sh
{
@ -38,7 +40,7 @@ TString ArrayString(const TType &type);
class GetVariableTraverser
{
public:
GetVariableTraverser() {}
GetVariableTraverser(const TSymbolTable &symbolTable);
template <typename VarT>
void traverse(const TType &type, const TString &name, std::vector<VarT> *output);
@ -48,6 +50,14 @@ class GetVariableTraverser
virtual void visitVariable(ShaderVariable *newVar) {}
private:
// Helper function called by traverse() to fill specific fields
// for attributes/varyings/uniforms.
template <typename VarT>
void setTypeSpecificInfo(
const TType &type, const TString &name, VarT *variable) {}
const TSymbolTable &mSymbolTable;
DISALLOW_COPY_AND_ASSIGN(GetVariableTraverser);
};

View File

@ -0,0 +1,40 @@
//
// 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 "libEGL/AttributeMap.h"
namespace egl
{
AttributeMap::AttributeMap()
{
}
AttributeMap::AttributeMap(const EGLint *attributes)
{
for (const EGLint *curAttrib = attributes; curAttrib[0] != EGL_NONE; curAttrib += 2)
{
insert(curAttrib[0], curAttrib[1]);
}
}
void AttributeMap::insert(EGLint key, EGLint value)
{
mAttributes[key] = value;
}
bool AttributeMap::contains(EGLint key) const
{
return (mAttributes.find(key) != mAttributes.end());
}
EGLint AttributeMap::get(EGLint key, EGLint defaultValue) const
{
std::map<EGLint, EGLint>::const_iterator iter = mAttributes.find(key);
return (mAttributes.find(key) != mAttributes.end()) ? iter->second : defaultValue;
}
}

View File

@ -0,0 +1,33 @@
//
// 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 LIBEGL_ATTRIBUTEMAP_H_
#define LIBEGL_ATTRIBUTEMAP_H_
#include <EGL/egl.h>
#include <map>
namespace egl
{
class AttributeMap
{
public:
AttributeMap();
explicit AttributeMap(const EGLint *attributes);
virtual void insert(EGLint key, EGLint value);
virtual bool contains(EGLint key) const;
virtual EGLint get(EGLint key, EGLint defaultValue) const;
private:
std::map<EGLint, EGLint> mAttributes;
};
}
#endif // LIBEGL_ATTRIBUTEMAP_H_

View File

@ -35,32 +35,36 @@ static DisplayMap *GetDisplayMap()
return &displays;
}
egl::Display *Display::getDisplay(EGLNativeDisplayType displayId, EGLint displayType)
egl::Display *Display::getDisplay(EGLNativeDisplayType displayId, const AttributeMap &attribMap)
{
Display *display = NULL;
DisplayMap *displays = GetDisplayMap();
DisplayMap::const_iterator iter = displays->find(displayId);
if (iter != displays->end())
{
return iter->second;
display = iter->second;
}
else
{
display = new egl::Display(displayId);
displays->insert(std::make_pair(displayId, display));
}
// FIXME: Check if displayId is a valid display device context
egl::Display *display = new egl::Display(displayId, displayType);
displays->insert(std::make_pair(displayId, display));
// Apply new attributes if the display is not initialized yet.
if (!display->isInitialized())
{
display->setAttributes(attribMap);
}
return display;
}
Display::Display(EGLNativeDisplayType displayId, EGLint displayType)
Display::Display(EGLNativeDisplayType displayId)
: mDisplayId(displayId),
mRequestedDisplayType(displayType),
mAttributeMap(),
mRenderer(NULL)
{
#if defined(ANGLE_PLATFORM_WINRT)
if (mDisplayId)
mDisplayId->AddRef();
#endif
}
Display::~Display()
@ -73,28 +77,29 @@ Display::~Display()
{
displays->erase(iter);
}
#if defined(ANGLE_PLATFORM_WINRT)
if (mDisplayId)
mDisplayId->Release();
#endif
}
bool Display::initialize()
void Display::setAttributes(const AttributeMap &attribMap)
{
mAttributeMap = attribMap;
}
Error Display::initialize()
{
if (isInitialized())
{
return true;
return Error(EGL_SUCCESS);
}
mRenderer = glCreateRenderer(this, mDisplayId, mRequestedDisplayType);
mRenderer = glCreateRenderer(this, mDisplayId, mAttributeMap);
if (!mRenderer)
{
terminate();
return error(EGL_NOT_INITIALIZED, false);
return Error(EGL_NOT_INITIALIZED);
}
//TODO(jmadill): should be part of caps?
EGLint minSwapInterval = mRenderer->getMinSwapInterval();
EGLint maxSwapInterval = mRenderer->getMaxSwapInterval();
EGLint maxTextureSize = mRenderer->getRendererCaps().max2DTextureSize;
@ -125,13 +130,13 @@ bool Display::initialize()
if (!isInitialized())
{
terminate();
return false;
return Error(EGL_NOT_INITIALIZED);
}
initDisplayExtensionString();
initVendorString();
return true;
return Error(EGL_SUCCESS);
}
void Display::terminate()
@ -148,6 +153,8 @@ void Display::terminate()
glDestroyRenderer(mRenderer);
mRenderer = NULL;
mConfigSet.mSet.clear();
}
bool Display::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig)
@ -202,7 +209,7 @@ bool Display::getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value)
EGLSurface Display::createWindowSurface(EGLNativeWindowType window, EGLConfig config, const EGLint *attribList)
Error Display::createWindowSurface(EGLNativeWindowType window, EGLConfig config, const EGLint *attribList, EGLSurface *outSurface)
{
const Config *configuration = mConfigSet.get(config);
EGLint postSubBufferSupported = EGL_FALSE;
@ -223,9 +230,9 @@ EGLSurface Display::createWindowSurface(EGLNativeWindowType window, EGLConfig co
case EGL_BACK_BUFFER:
break;
case EGL_SINGLE_BUFFER:
return error(EGL_BAD_MATCH, EGL_NO_SURFACE); // Rendering directly to front buffer not supported
return Error(EGL_BAD_MATCH); // Rendering directly to front buffer not supported
default:
return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
return Error(EGL_BAD_ATTRIBUTE);
}
break;
case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
@ -241,11 +248,11 @@ EGLSurface Display::createWindowSurface(EGLNativeWindowType window, EGLConfig co
fixedSize = attribList[1];
break;
case EGL_VG_COLORSPACE:
return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
return Error(EGL_BAD_MATCH);
case EGL_VG_ALPHA_FORMAT:
return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
return Error(EGL_BAD_MATCH);
default:
return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
return Error(EGL_BAD_ATTRIBUTE);
}
attribList += 2;
@ -254,7 +261,7 @@ EGLSurface Display::createWindowSurface(EGLNativeWindowType window, EGLConfig co
if (width < 0 || height < 0)
{
return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
return Error(EGL_BAD_PARAMETER);
}
if (!fixedSize)
@ -265,29 +272,33 @@ EGLSurface Display::createWindowSurface(EGLNativeWindowType window, EGLConfig co
if (hasExistingWindowSurface(window))
{
return error(EGL_BAD_ALLOC, EGL_NO_SURFACE);
return Error(EGL_BAD_ALLOC);
}
if (mRenderer->testDeviceLost(false))
{
if (!restoreLostDevice())
return EGL_NO_SURFACE;
Error error = restoreLostDevice();
if (error.isError())
{
return error;
}
}
Surface *surface = new Surface(this, configuration, window, fixedSize, width, height, postSubBufferSupported);
if (!surface->initialize())
Error error = surface->initialize();
if (error.isError())
{
delete surface;
return EGL_NO_SURFACE;
SafeDelete(surface);
return error;
}
mSurfaceSet.insert(surface);
return success(surface);
*outSurface = surface;
return Error(EGL_SUCCESS);
}
EGLSurface Display::createOffscreenSurface(EGLConfig config, HANDLE shareHandle, const EGLint *attribList)
Error Display::createOffscreenSurface(EGLConfig config, HANDLE shareHandle, const EGLint *attribList, EGLSurface *outSurface)
{
EGLint width = 0, height = 0;
EGLenum textureFormat = EGL_NO_TEXTURE;
@ -319,7 +330,7 @@ EGLSurface Display::createOffscreenSurface(EGLConfig config, HANDLE shareHandle,
textureFormat = attribList[1];
break;
default:
return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
return Error(EGL_BAD_ATTRIBUTE);
}
break;
case EGL_TEXTURE_TARGET:
@ -330,19 +341,19 @@ EGLSurface Display::createOffscreenSurface(EGLConfig config, HANDLE shareHandle,
textureTarget = attribList[1];
break;
default:
return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
return Error(EGL_BAD_ATTRIBUTE);
}
break;
case EGL_MIPMAP_TEXTURE:
if (attribList[1] != EGL_FALSE)
return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
return Error(EGL_BAD_ATTRIBUTE);
break;
case EGL_VG_COLORSPACE:
return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
return Error(EGL_BAD_MATCH);
case EGL_VG_ALPHA_FORMAT:
return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
return Error(EGL_BAD_MATCH);
default:
return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
return Error(EGL_BAD_ATTRIBUTE);
}
attribList += 2;
@ -351,88 +362,100 @@ EGLSurface Display::createOffscreenSurface(EGLConfig config, HANDLE shareHandle,
if (width < 0 || height < 0)
{
return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
return Error(EGL_BAD_PARAMETER);
}
if (width == 0 || height == 0)
{
return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
return Error(EGL_BAD_ATTRIBUTE);
}
if (textureFormat != EGL_NO_TEXTURE && !mRenderer->getRendererExtensions().textureNPOT && (!gl::isPow2(width) || !gl::isPow2(height)))
{
return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
return Error(EGL_BAD_MATCH);
}
if ((textureFormat != EGL_NO_TEXTURE && textureTarget == EGL_NO_TEXTURE) ||
(textureFormat == EGL_NO_TEXTURE && textureTarget != EGL_NO_TEXTURE))
{
return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
return Error(EGL_BAD_MATCH);
}
if (!(configuration->mSurfaceType & EGL_PBUFFER_BIT))
{
return error(EGL_BAD_MATCH, EGL_NO_SURFACE);
return Error(EGL_BAD_MATCH);
}
if ((textureFormat == EGL_TEXTURE_RGB && configuration->mBindToTextureRGB != EGL_TRUE) ||
(textureFormat == EGL_TEXTURE_RGBA && configuration->mBindToTextureRGBA != EGL_TRUE))
{
return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
return Error(EGL_BAD_ATTRIBUTE);
}
if (mRenderer->testDeviceLost(false))
{
if (!restoreLostDevice())
return EGL_NO_SURFACE;
Error error = restoreLostDevice();
if (error.isError())
{
return error;
}
}
Surface *surface = new Surface(this, configuration, shareHandle, width, height, textureFormat, textureTarget);
if (!surface->initialize())
Error error = surface->initialize();
if (error.isError())
{
delete surface;
return EGL_NO_SURFACE;
SafeDelete(surface);
return error;
}
mSurfaceSet.insert(surface);
return success(surface);
*outSurface = surface;
return Error(EGL_SUCCESS);
}
EGLContext Display::createContext(EGLConfig configHandle, EGLint clientVersion, const gl::Context *shareContext, bool notifyResets, bool robustAccess)
Error Display::createContext(EGLConfig configHandle, EGLint clientVersion, const gl::Context *shareContext, bool notifyResets,
bool robustAccess, EGLContext *outContext)
{
if (!mRenderer)
{
return EGL_NO_CONTEXT;
*outContext = EGL_NO_CONTEXT;
return Error(EGL_SUCCESS);
}
else if (mRenderer->testDeviceLost(false)) // Lost device
{
if (!restoreLostDevice())
Error error = restoreLostDevice();
if (error.isError())
{
return error(EGL_CONTEXT_LOST, EGL_NO_CONTEXT);
return error;
}
}
//TODO(jmadill): shader model is not cross-platform
if (clientVersion > 2 && mRenderer->getMajorShaderModel() < 4)
{
return error(EGL_BAD_CONFIG, EGL_NO_CONTEXT);
return Error(EGL_BAD_CONFIG);
}
gl::Context *context = glCreateContext(clientVersion, shareContext, mRenderer, notifyResets, robustAccess);
mContextSet.insert(context);
return success(context);
*outContext = context;
return Error(EGL_SUCCESS);
}
bool Display::restoreLostDevice()
Error Display::restoreLostDevice()
{
for (ContextSet::iterator ctx = mContextSet.begin(); ctx != mContextSet.end(); ctx++)
{
if ((*ctx)->isResetNotificationEnabled())
return false; // If reset notifications have been requested, application must delete all contexts first
{
// If reset notifications have been requested, application must delete all contexts first
return Error(EGL_CONTEXT_LOST);
}
}
// Release surface resources to make the Reset() succeed
for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++)
{
@ -441,16 +464,20 @@ bool Display::restoreLostDevice()
if (!mRenderer->resetDevice())
{
return error(EGL_BAD_ALLOC, false);
return Error(EGL_BAD_ALLOC);
}
// Restore any surfaces that may have been lost
for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++)
{
(*surface)->resetSwapChain();
Error error = (*surface)->resetSwapChain();
if (error.isError())
{
return error;
}
}
return true;
return Error(EGL_SUCCESS);
}
@ -472,7 +499,6 @@ void Display::notifyDeviceLost()
{
(*context)->markContextLost();
}
egl::error(EGL_CONTEXT_LOST);
}
void Display::recreateSwapChains()
@ -604,10 +630,11 @@ void Display::initVendorString()
LUID adapterLuid = {0};
//TODO(jmadill): LUID is not cross-platform
if (mRenderer && mRenderer->getLUID(&adapterLuid))
{
char adapterLuidString[64];
snprintf(adapterLuidString, sizeof(adapterLuidString), " (adapter LUID: %08x%08x)", adapterLuid.HighPart, adapterLuid.LowPart);
sprintf_s(adapterLuidString, sizeof(adapterLuidString), " (adapter LUID: %08x%08x)", adapterLuid.HighPart, adapterLuid.LowPart);
mVendorString += adapterLuidString;
}

View File

@ -14,7 +14,9 @@
#include <set>
#include <vector>
#include "libEGL/Error.h"
#include "libEGL/Config.h"
#include "libEGL/AttributeMap.h"
namespace gl
{
@ -30,10 +32,10 @@ class Display
public:
~Display();
bool initialize();
Error initialize();
void terminate();
static egl::Display *getDisplay(EGLNativeDisplayType displayId, EGLint displayType);
static egl::Display *getDisplay(EGLNativeDisplayType displayId, const AttributeMap &attribMap);
static const char *getExtensionString(egl::Display *display);
@ -43,9 +45,10 @@ class Display
bool getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig);
bool getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value);
EGLSurface createWindowSurface(EGLNativeWindowType window, EGLConfig config, const EGLint *attribList);
EGLSurface createOffscreenSurface(EGLConfig config, HANDLE shareHandle, const EGLint *attribList);
EGLContext createContext(EGLConfig configHandle, EGLint clientVersion, const gl::Context *shareContext, bool notifyResets, bool robustAccess);
Error createWindowSurface(EGLNativeWindowType window, EGLConfig config, const EGLint *attribList, EGLSurface *outSurface);
Error createOffscreenSurface(EGLConfig config, HANDLE shareHandle, const EGLint *attribList, EGLSurface *outSurface);
Error createContext(EGLConfig configHandle, EGLint clientVersion, const gl::Context *shareContext, bool notifyResets,
bool robustAccess, EGLContext *outContext);
void destroySurface(egl::Surface *surface);
void destroyContext(gl::Context *context);
@ -64,18 +67,19 @@ class Display
const char *getExtensionString() const;
const char *getVendorString() const;
EGLNativeDisplayType getDisplayId() const { return mDisplayId; }
private:
DISALLOW_COPY_AND_ASSIGN(Display);
Display(EGLNativeDisplayType displayId, EGLint displayType);
Display(EGLNativeDisplayType displayId);
bool restoreLostDevice();
void setAttributes(const AttributeMap &attribMap);
Error restoreLostDevice();
EGLNativeDisplayType mDisplayId;
EGLint mRequestedDisplayType;
AttributeMap mAttributeMap;
typedef std::set<Surface*> SurfaceSet;
SurfaceSet mSurfaceSet;

48
src/3rdparty/angle/src/libEGL/Error.cpp vendored Normal file
View File

@ -0,0 +1,48 @@
//
// 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.
//
// Error.cpp: Implements the egl::Error class which encapsulates an EGL error
// and optional error message.
#include "libEGL/Error.h"
#include "common/angleutils.h"
#include <cstdarg>
namespace egl
{
Error::Error(EGLint errorCode)
: mCode(errorCode),
mMessage()
{
}
Error::Error(EGLint errorCode, const char *msg, ...)
: mCode(errorCode),
mMessage()
{
va_list vararg;
va_start(vararg, msg);
mMessage = FormatString(msg, vararg);
va_end(vararg);
}
Error::Error(const Error &other)
: mCode(other.mCode),
mMessage(other.mMessage)
{
}
Error &Error::operator=(const Error &other)
{
mCode = other.mCode;
mMessage = other.mMessage;
return *this;
}
}

39
src/3rdparty/angle/src/libEGL/Error.h vendored Normal file
View File

@ -0,0 +1,39 @@
//
// 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.
// Error.h: Defines the egl::Error class which encapsulates an EGL error
// and optional error message.
#ifndef LIBEGL_ERROR_H_
#define LIBEGL_ERROR_H_
#include <EGL/egl.h>
#include <string>
namespace egl
{
class Error
{
public:
explicit Error(EGLint errorCode);
Error(EGLint errorCode, const char *msg, ...);
Error(const Error &other);
Error &operator=(const Error &other);
EGLint getCode() const { return mCode; }
bool isError() const { return (mCode != EGL_SUCCESS); }
const std::string &getMessage() const { return mMessage; }
private:
EGLint mCode;
std::string mMessage;
};
}
#endif // LIBEGL_ERROR_H_

View File

@ -22,23 +22,19 @@
#include "libEGL/main.h"
#include "libEGL/Display.h"
#if defined(ANGLE_PLATFORM_WINRT)
# include "wrl.h"
# include "windows.graphics.display.h"
# include "windows.ui.core.h"
using namespace ABI::Windows::Graphics::Display;
using namespace ABI::Windows::Foundation;
using namespace ABI::Windows::UI::Core;
using namespace Microsoft::WRL;
#endif
#include "common/NativeWindow.h"
//TODO(jmadill): phase this out
#include "libGLESv2/renderer/d3d/RendererD3D.h"
namespace egl
{
Surface::Surface(Display *display, const Config *config, EGLNativeWindowType window, EGLint fixedSize, EGLint width, EGLint height, EGLint postSubBufferSupported)
: mDisplay(display), mConfig(config), mWindow(window), mPostSubBufferSupported(postSubBufferSupported)
Surface::Surface(Display *display, const Config *config, EGLNativeWindowType window, EGLint fixedSize, EGLint width, EGLint height, EGLint postSubBufferSupported)
: mDisplay(display), mConfig(config), mNativeWindow(window, display->getDisplayId()), mPostSubBufferSupported(postSubBufferSupported)
{
mRenderer = mDisplay->getRenderer();
//TODO(jmadill): MANGLE refactor. (note, can't call makeRendererD3D because of dll export issues)
mRenderer = static_cast<rx::RendererD3D*>(mDisplay->getRenderer());
mSwapChain = NULL;
mShareHandle = NULL;
mTexture = NULL;
@ -51,27 +47,19 @@ Surface::Surface(Display *display, const Config *config, EGLNativeWindowType win
mSwapInterval = -1;
mWidth = width;
mHeight = height;
mFixedWidth = mWidth;
mFixedHeight = mHeight;
setSwapInterval(1);
mFixedSize = fixedSize;
mSwapFlags = rx::SWAP_NORMAL;
#if defined(ANGLE_PLATFORM_WINRT)
if (mWindow)
mWindow->AddRef();
mScaleFactor = 1.0;
mSizeToken.value = 0;
mDpiToken.value = 0;
# if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP
mOrientationToken.value = 0;
# endif
#endif
subclassWindow();
}
Surface::Surface(Display *display, const Config *config, HANDLE shareHandle, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureType)
: mDisplay(display), mWindow(NULL), mConfig(config), mShareHandle(shareHandle), mWidth(width), mHeight(height), mPostSubBufferSupported(EGL_FALSE)
: mDisplay(display), mNativeWindow(NULL, NULL), mConfig(config), mShareHandle(shareHandle), mWidth(width), mHeight(height), mPostSubBufferSupported(EGL_FALSE)
{
mRenderer = mDisplay->getRenderer();
//TODO(jmadill): MANGLE refactor. (note, can't call makeRendererD3D because of dll export issues)
mRenderer = static_cast<rx::RendererD3D*>(mDisplay->getRenderer());
mSwapChain = NULL;
mWindowSubclassed = false;
mTexture = NULL;
@ -85,90 +73,33 @@ Surface::Surface(Display *display, const Config *config, HANDLE shareHandle, EGL
setSwapInterval(1);
// This constructor is for offscreen surfaces, which are always fixed-size.
mFixedSize = EGL_TRUE;
mSwapFlags = rx::SWAP_NORMAL;
#if defined(ANGLE_PLATFORM_WINRT)
mScaleFactor = 1.0;
mSizeToken.value = 0;
mDpiToken.value = 0;
# if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP
mOrientationToken.value = 0;
# endif
#endif
mFixedWidth = mWidth;
mFixedHeight = mHeight;
}
Surface::~Surface()
{
#if defined(ANGLE_PLATFORM_WINRT)
if (mSizeToken.value) {
ComPtr<ICoreWindow> coreWindow;
HRESULT hr = mWindow->QueryInterface(coreWindow.GetAddressOf());
ASSERT(SUCCEEDED(hr));
hr = coreWindow->remove_SizeChanged(mSizeToken);
ASSERT(SUCCEEDED(hr));
}
if (mDpiToken.value) {
ComPtr<IDisplayInformation> displayInformation;
HRESULT hr = mDisplay->getDisplayId()->QueryInterface(displayInformation.GetAddressOf());
ASSERT(SUCCEEDED(hr));
hr = displayInformation->remove_DpiChanged(mDpiToken);
ASSERT(SUCCEEDED(hr));
}
# if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
if (mOrientationToken.value) {
ComPtr<IDisplayInformation> displayInformation;
HRESULT hr = mDisplay->getDisplayId()->QueryInterface(displayInformation.GetAddressOf());
ASSERT(SUCCEEDED(hr));
hr = displayInformation->remove_OrientationChanged(mOrientationToken);
ASSERT(SUCCEEDED(hr));
}
# endif
#endif
unsubclassWindow();
release();
}
bool Surface::initialize()
Error Surface::initialize()
{
#if defined(ANGLE_PLATFORM_WINRT)
if (!mFixedSize) {
HRESULT hr;
ComPtr<IDisplayInformation> displayInformation;
hr = mDisplay->getDisplayId()->QueryInterface(displayInformation.GetAddressOf());
ASSERT(SUCCEEDED(hr));
onDpiChanged(displayInformation.Get(), 0);
hr = displayInformation->add_DpiChanged(Callback<ITypedEventHandler<DisplayInformation *, IInspectable *>>(this, &Surface::onDpiChanged).Get(),
&mDpiToken);
ASSERT(SUCCEEDED(hr));
# if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP
onOrientationChanged(displayInformation.Get(), 0);
hr = displayInformation->add_OrientationChanged(Callback<ITypedEventHandler<DisplayInformation *, IInspectable *>>(this, &Surface::onOrientationChanged).Get(),
&mOrientationToken);
ASSERT(SUCCEEDED(hr));
# endif
ComPtr<ICoreWindow> coreWindow;
hr = mWindow->QueryInterface(coreWindow.GetAddressOf());
ASSERT(SUCCEEDED(hr));
Rect rect;
hr = coreWindow->get_Bounds(&rect);
ASSERT(SUCCEEDED(hr));
mWidth = rect.Width * mScaleFactor;
mHeight = rect.Height * mScaleFactor;
hr = coreWindow->add_SizeChanged(Callback<ITypedEventHandler<CoreWindow *, WindowSizeChangedEventArgs *>>(this, &Surface::onSizeChanged).Get(),
&mSizeToken);
ASSERT(SUCCEEDED(hr));
if (mNativeWindow.getNativeWindow())
{
if (!mNativeWindow.initialize())
{
return Error(EGL_BAD_SURFACE);
}
}
#endif
if (!resetSwapChain())
return false;
Error error = resetSwapChain();
if (error.isError())
{
return error;
}
return true;
return Error(EGL_SUCCESS);
}
void Surface::release()
@ -181,85 +112,80 @@ void Surface::release()
mTexture->releaseTexImage();
mTexture = NULL;
}
#if defined(ANGLE_PLATFORM_WINRT)
if (mWindow)
mWindow->Release();
#endif
}
bool Surface::resetSwapChain()
Error Surface::resetSwapChain()
{
ASSERT(!mSwapChain);
int width;
int height;
#if !defined(ANGLE_PLATFORM_WINRT)
if (!mFixedSize)
{
RECT windowRect;
if (!GetClientRect(getWindowHandle(), &windowRect))
if (!mNativeWindow.getClientRect(&windowRect))
{
ASSERT(false);
ERR("Could not retrieve the window dimensions");
return error(EGL_BAD_SURFACE, false);
return Error(EGL_BAD_SURFACE, "Could not retrieve the window dimensions");
}
width = windowRect.right - windowRect.left;
height = windowRect.bottom - windowRect.top;
}
else
#endif
{
// non-window surface - size is determined at creation
width = mWidth;
height = mHeight;
}
mSwapChain = mRenderer->createSwapChain(mWindow, mShareHandle,
mSwapChain = mRenderer->createSwapChain(mNativeWindow, mShareHandle,
mConfig->mRenderTargetFormat,
mConfig->mDepthStencilFormat);
if (!mSwapChain)
{
return error(EGL_BAD_ALLOC, false);
return Error(EGL_BAD_ALLOC);
}
if (!resetSwapChain(width, height))
Error error = resetSwapChain(width, height);
if (error.isError())
{
delete mSwapChain;
mSwapChain = NULL;
return false;
SafeDelete(mSwapChain);
return error;
}
return true;
return Error(EGL_SUCCESS);
}
bool Surface::resizeSwapChain(int backbufferWidth, int backbufferHeight)
Error Surface::resizeSwapChain(int backbufferWidth, int backbufferHeight)
{
ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0);
ASSERT(mSwapChain);
EGLint status = mSwapChain->resize(std::max(1, backbufferWidth), std::max(1, backbufferHeight));
#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
backbufferWidth = std::max(1, backbufferWidth);
backbufferHeight = std::max(1, backbufferHeight);
#endif
EGLint status = mSwapChain->resize(backbufferWidth, backbufferHeight);
if (status == EGL_CONTEXT_LOST)
{
mDisplay->notifyDeviceLost();
return false;
return Error(status);
}
else if (status != EGL_SUCCESS)
{
return error(status, false);
return Error(status);
}
mWidth = backbufferWidth;
mHeight = backbufferHeight;
return true;
return Error(EGL_SUCCESS);
}
bool Surface::resetSwapChain(int backbufferWidth, int backbufferHeight)
Error Surface::resetSwapChain(int backbufferWidth, int backbufferHeight)
{
ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0);
ASSERT(mSwapChain);
@ -269,69 +195,71 @@ bool Surface::resetSwapChain(int backbufferWidth, int backbufferHeight)
if (status == EGL_CONTEXT_LOST)
{
mRenderer->notifyDeviceLost();
return false;
return Error(status);
}
else if (status != EGL_SUCCESS)
{
return error(status, false);
return Error(status);
}
mWidth = backbufferWidth;
mHeight = backbufferHeight;
mSwapIntervalDirty = false;
return true;
return Error(EGL_SUCCESS);
}
bool Surface::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
Error Surface::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
{
if (!mSwapChain)
{
return true;
return Error(EGL_SUCCESS);
}
if (x + width > mWidth)
if (x + width > abs(mWidth))
{
width = mWidth - x;
width = abs(mWidth) - x;
}
if (y + height > mHeight)
if (y + height > abs(mHeight))
{
height = mHeight - y;
height = abs(mHeight) - y;
}
if (width == 0 || height == 0)
{
return true;
return Error(EGL_SUCCESS);
}
EGLint status = mSwapChain->swapRect(x, y, width, height, mSwapFlags);
ASSERT(width > 0);
ASSERT(height > 0);
EGLint status = mSwapChain->swapRect(x, y, width, height);
if (status == EGL_CONTEXT_LOST)
{
mRenderer->notifyDeviceLost();
return false;
return Error(status);
}
else if (status != EGL_SUCCESS)
{
return error(status, false);
return Error(status);
}
checkForOutOfDateSwapChain();
return true;
return Error(EGL_SUCCESS);
}
EGLNativeWindowType Surface::getWindowHandle()
{
return mWindow;
return mNativeWindow.getNativeWindow();
}
#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
#define kSurfaceProperty _TEXT("Egl::SurfaceOwner")
#define kParentWndProc _TEXT("Egl::SurfaceParentWndProc")
#if !defined(ANGLE_PLATFORM_WINRT)
static LRESULT CALLBACK SurfaceWindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
{
if (message == WM_SIZE)
@ -349,45 +277,50 @@ static LRESULT CALLBACK SurfaceWindowProc(HWND hwnd, UINT message, WPARAM wparam
void Surface::subclassWindow()
{
#if !defined(ANGLE_PLATFORM_WINRT)
if (!mWindow)
#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
HWND window = mNativeWindow.getNativeWindow();
if (!window)
{
return;
}
DWORD processId;
DWORD threadId = GetWindowThreadProcessId(mWindow, &processId);
DWORD threadId = GetWindowThreadProcessId(window, &processId);
if (processId != GetCurrentProcessId() || threadId != GetCurrentThreadId())
{
return;
}
SetLastError(0);
LONG_PTR oldWndProc = SetWindowLongPtr(mWindow, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(SurfaceWindowProc));
LONG_PTR oldWndProc = SetWindowLongPtr(window, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(SurfaceWindowProc));
if(oldWndProc == 0 && GetLastError() != ERROR_SUCCESS)
{
mWindowSubclassed = false;
return;
}
SetProp(mWindow, kSurfaceProperty, reinterpret_cast<HANDLE>(this));
SetProp(mWindow, kParentWndProc, reinterpret_cast<HANDLE>(oldWndProc));
SetProp(window, kSurfaceProperty, reinterpret_cast<HANDLE>(this));
SetProp(window, kParentWndProc, reinterpret_cast<HANDLE>(oldWndProc));
mWindowSubclassed = true;
#else
mWindowSubclassed = false;
#endif
}
void Surface::unsubclassWindow()
{
#if !defined(ANGLE_PLATFORM_WINRT)
if(!mWindowSubclassed)
{
return;
}
#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
HWND window = mNativeWindow.getNativeWindow();
if (!window)
{
return;
}
// un-subclass
LONG_PTR parentWndFunc = reinterpret_cast<LONG_PTR>(GetProp(mWindow, kParentWndProc));
LONG_PTR parentWndFunc = reinterpret_cast<LONG_PTR>(GetProp(window, kParentWndProc));
// Check the windowproc is still SurfaceWindowProc.
// If this assert fails, then it is likely the application has subclassed the
@ -396,29 +329,28 @@ void Surface::unsubclassWindow()
// EGL context, or to unsubclass before destroying the EGL context.
if(parentWndFunc)
{
LONG_PTR prevWndFunc = SetWindowLongPtr(mWindow, GWLP_WNDPROC, parentWndFunc);
LONG_PTR prevWndFunc = SetWindowLongPtr(window, GWLP_WNDPROC, parentWndFunc);
UNUSED_ASSERTION_VARIABLE(prevWndFunc);
ASSERT(prevWndFunc == reinterpret_cast<LONG_PTR>(SurfaceWindowProc));
}
RemoveProp(mWindow, kSurfaceProperty);
RemoveProp(mWindow, kParentWndProc);
mWindowSubclassed = false;
RemoveProp(window, kSurfaceProperty);
RemoveProp(window, kParentWndProc);
#endif
mWindowSubclassed = false;
}
bool Surface::checkForOutOfDateSwapChain()
{
RECT client;
int clientWidth = getWidth();
int clientHeight = getHeight();
bool sizeDirty = false;
#if !defined(ANGLE_PLATFORM_WINRT)
if (!mFixedSize && !IsIconic(getWindowHandle()))
if (!mFixedSize && !mNativeWindow.isIconic())
{
RECT client;
// The window is automatically resized to 150x22 when it's minimized, but the swapchain shouldn't be resized
// because that's not a useful size to render to.
if (!GetClientRect(getWindowHandle(), &client))
if (!mNativeWindow.getClientRect(&client))
{
ASSERT(false);
return false;
@ -429,7 +361,13 @@ bool Surface::checkForOutOfDateSwapChain()
clientHeight = client.bottom - client.top;
sizeDirty = clientWidth != getWidth() || clientHeight != getHeight();
}
#endif
if (mFixedSize && (mWidth != mFixedWidth || mHeight != mFixedHeight))
{
clientWidth = mFixedWidth;
clientHeight = mFixedHeight;
sizeDirty = true;
}
bool wasDirty = (mSwapIntervalDirty || sizeDirty);
@ -455,17 +393,17 @@ bool Surface::checkForOutOfDateSwapChain()
return false;
}
bool Surface::swap()
Error Surface::swap()
{
return swapRect(0, 0, mWidth, mHeight);
return swapRect(0, 0, abs(mWidth), abs(mHeight));
}
bool Surface::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
Error Surface::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
{
if (!mPostSubBufferSupported)
{
// Spec is not clear about how this should be handled.
return true;
return Error(EGL_SUCCESS);
}
return swapRect(x, y, width, height);
@ -550,77 +488,18 @@ EGLint Surface::isFixedSize() const
return mFixedSize;
}
void Surface::setFixedWidth(EGLint width)
{
mFixedWidth = width;
}
void Surface::setFixedHeight(EGLint height)
{
mFixedHeight = height;
}
EGLenum Surface::getFormat() const
{
return mConfig->mRenderTargetFormat;
}
#if defined(ANGLE_PLATFORM_WINRT)
HRESULT Surface::onSizeChanged(ICoreWindow *, IWindowSizeChangedEventArgs *args)
{
HRESULT hr;
Size size;
hr = args->get_Size(&size);
ASSERT(SUCCEEDED(hr));
resizeSwapChain(std::floor(size.Width * mScaleFactor + 0.5),
std::floor(size.Height * mScaleFactor + 0.5));
if (static_cast<egl::Surface*>(getCurrentDrawSurface()) == this)
{
glMakeCurrent(glGetCurrentContext(), static_cast<egl::Display*>(getCurrentDisplay()), this);
}
return S_OK;
}
HRESULT Surface::onDpiChanged(IDisplayInformation *displayInformation, IInspectable *)
{
HRESULT hr;
# if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP
ComPtr<IDisplayInformation2> displayInformation2;
hr = displayInformation->QueryInterface(displayInformation2.GetAddressOf());
ASSERT(SUCCEEDED(hr));
hr = displayInformation2->get_RawPixelsPerViewPixel(&mScaleFactor);
ASSERT(SUCCEEDED(hr));
# else
ResolutionScale resolutionScale;
hr = displayInformation->get_ResolutionScale(&resolutionScale);
ASSERT(SUCCEEDED(hr));
mScaleFactor = double(resolutionScale) / 100.0;
# endif
return S_OK;
}
# if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
HRESULT Surface::onOrientationChanged(IDisplayInformation *displayInformation, IInspectable *)
{
HRESULT hr;
DisplayOrientations orientation;
hr = displayInformation->get_CurrentOrientation(&orientation);
ASSERT(SUCCEEDED(hr));
switch (orientation) {
default:
case DisplayOrientations_Portrait:
mSwapFlags = rx::SWAP_NORMAL;
break;
case DisplayOrientations_Landscape:
mSwapFlags = rx::SWAP_ROTATE_90;
break;
case DisplayOrientations_LandscapeFlipped:
mSwapFlags = rx::SWAP_ROTATE_270;
break;
case DisplayOrientations_PortraitFlipped:
mSwapFlags = rx::SWAP_ROTATE_180;
break;
}
return S_OK;
}
# endif
#endif
}

View File

@ -11,23 +11,12 @@
#ifndef LIBEGL_SURFACE_H_
#define LIBEGL_SURFACE_H_
#include "libEGL/Error.h"
#include <EGL/egl.h>
#include "common/angleutils.h"
#if defined(ANGLE_PLATFORM_WINRT)
#include <EventToken.h>
namespace ABI { namespace Windows {
namespace UI { namespace Core {
struct ICoreWindow;
struct IWindowSizeChangedEventArgs;
} }
namespace Graphics { namespace Display {
struct IDisplayInformation;
} }
} }
struct IInspectable;
#endif
#include "common/NativeWindow.h"
namespace gl
{
@ -35,8 +24,8 @@ class Texture2D;
}
namespace rx
{
class Renderer;
class SwapChain;
class RendererD3D; //TODO(jmadill): remove this
}
namespace egl
@ -52,13 +41,13 @@ class Surface
virtual ~Surface();
bool initialize();
Error initialize();
void release();
bool resetSwapChain();
Error resetSwapChain();
EGLNativeWindowType getWindowHandle();
bool swap();
bool postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height);
Error swap();
Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height);
virtual EGLint isPostSubBufferSupported() const;
@ -81,35 +70,31 @@ class Surface
virtual gl::Texture2D *getBoundTexture() const;
EGLint isFixedSize() const;
void setFixedWidth(EGLint width);
void setFixedHeight(EGLint height);
private:
private:
DISALLOW_COPY_AND_ASSIGN(Surface);
#if defined(ANGLE_PLATFORM_WINRT)
HRESULT onSizeChanged(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *);
HRESULT onDpiChanged(ABI::Windows::Graphics::Display::IDisplayInformation *, IInspectable *);
# if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP
HRESULT onOrientationChanged(ABI::Windows::Graphics::Display::IDisplayInformation *, IInspectable *);
# endif
#endif
Display *const mDisplay;
rx::Renderer *mRenderer;
rx::RendererD3D *mRenderer;
HANDLE mShareHandle;
rx::SwapChain *mSwapChain;
void subclassWindow();
void unsubclassWindow();
bool resizeSwapChain(int backbufferWidth, int backbufferHeight);
bool resetSwapChain(int backbufferWidth, int backbufferHeight);
bool swapRect(EGLint x, EGLint y, EGLint width, EGLint height);
Error resizeSwapChain(int backbufferWidth, int backbufferHeight);
Error resetSwapChain(int backbufferWidth, int backbufferHeight);
Error swapRect(EGLint x, EGLint y, EGLint width, EGLint height);
const EGLNativeWindowType mWindow; // Window that the surface is created for.
rx::NativeWindow mNativeWindow; // Handler for the Window that the surface is created for.
bool mWindowSubclassed; // Indicates whether we successfully subclassed mWindow for WM_RESIZE hooking
const egl::Config *mConfig; // EGL config surface was created with
EGLint mHeight; // Height of surface
EGLint mWidth; // Width of surface
EGLint mFixedHeight; // Pending height of the surface
EGLint mFixedWidth; // Pending width of the surface
// EGLint horizontalResolution; // Horizontal dot pitch
// EGLint verticalResolution; // Vertical dot pitch
// EGLBoolean largestPBuffer; // If true, create largest pbuffer possible
@ -126,18 +111,9 @@ private:
EGLint mSwapInterval;
EGLint mPostSubBufferSupported;
EGLint mFixedSize;
EGLint mSwapFlags;
bool mSwapIntervalDirty;
gl::Texture2D *mTexture;
#if defined(ANGLE_PLATFORM_WINRT)
double mScaleFactor;
EventRegistrationToken mSizeToken;
EventRegistrationToken mDpiToken;
# if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP
EventRegistrationToken mOrientationToken;
# endif
#endif
};
}

View File

@ -13,7 +13,6 @@
#include "common/debug.h"
#include "common/version.h"
#include "common/platform.h"
#include "libGLESv2/Context.h"
#include "libGLESv2/Texture.h"
#include "libGLESv2/main.h"
@ -26,16 +25,20 @@
#include "libEGL/Display.h"
#include "libEGL/Surface.h"
#include "common/NativeWindow.h"
bool validateDisplay(egl::Display *display)
{
if (display == EGL_NO_DISPLAY)
{
return egl::error(EGL_BAD_DISPLAY, false);
recordError(egl::Error(EGL_BAD_DISPLAY));
return false;
}
if (!display->isInitialized())
{
return egl::error(EGL_NOT_INITIALIZED, false);
recordError(egl::Error(EGL_NOT_INITIALIZED));
return false;
}
return true;
@ -50,7 +53,8 @@ bool validateConfig(egl::Display *display, EGLConfig config)
if (!display->isValidConfig(config))
{
return egl::error(EGL_BAD_CONFIG, false);
recordError(egl::Error(EGL_BAD_CONFIG));
return false;
}
return true;
@ -65,7 +69,8 @@ bool validateContext(egl::Display *display, gl::Context *context)
if (!display->isValidContext(context))
{
return egl::error(EGL_BAD_CONTEXT, false);
recordError(egl::Error(EGL_BAD_CONTEXT));
return false;
}
return true;
@ -80,7 +85,8 @@ bool validateSurface(egl::Display *display, egl::Surface *surface)
if (!display->isValidSurface(surface))
{
return egl::error(EGL_BAD_SURFACE, false);
recordError(egl::Error(EGL_BAD_SURFACE));
return false;
}
return true;
@ -93,12 +99,7 @@ EGLint __stdcall eglGetError(void)
EVENT("()");
EGLint error = egl::getCurrentError();
if (error != EGL_SUCCESS)
{
egl::setCurrentError(EGL_SUCCESS);
}
recordError(egl::Error(EGL_SUCCESS));
return error;
}
@ -106,7 +107,7 @@ EGLDisplay __stdcall eglGetDisplay(EGLNativeDisplayType display_id)
{
EVENT("(EGLNativeDisplayType display_id = 0x%0.8p)", display_id);
return egl::Display::getDisplay(display_id, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE);
return egl::Display::getDisplay(display_id, egl::AttributeMap());
}
EGLDisplay __stdcall eglGetPlatformDisplayEXT(EGLenum platform, void *native_display, const EGLint *attrib_list)
@ -120,19 +121,26 @@ EGLDisplay __stdcall eglGetPlatformDisplayEXT(EGLenum platform, void *native_dis
break;
default:
return egl::error(EGL_BAD_CONFIG, EGL_NO_DISPLAY);
recordError(egl::Error(EGL_BAD_CONFIG));
return EGL_NO_DISPLAY;
}
EGLNativeDisplayType displayId = static_cast<EGLNativeDisplayType>(native_display);
#if !defined(ANGLE_PLATFORM_WINRT)
#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
// Validate the display device context
if (WindowFromDC(displayId) == NULL)
{
return egl::success(EGL_NO_DISPLAY);
recordError(egl::Error(EGL_SUCCESS));
return EGL_NO_DISPLAY;
}
#endif
EGLint requestedDisplayType = EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE;
EGLint platformType = EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE;
bool majorVersionSpecified = false;
bool minorVersionSpecified = false;
bool requestedWARP = false;
if (attrib_list)
{
for (const EGLint *curAttrib = attrib_list; curAttrib[0] != EGL_NONE; curAttrib += 2)
@ -140,7 +148,69 @@ EGLDisplay __stdcall eglGetPlatformDisplayEXT(EGLenum platform, void *native_dis
switch (curAttrib[0])
{
case EGL_PLATFORM_ANGLE_TYPE_ANGLE:
requestedDisplayType = curAttrib[1];
switch (curAttrib[1])
{
case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE:
break;
case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE:
case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE:
if (!egl::Display::supportsPlatformD3D())
{
recordError(egl::Error(EGL_SUCCESS));
return EGL_NO_DISPLAY;
}
break;
case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE:
case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:
if (!egl::Display::supportsPlatformOpenGL())
{
recordError(egl::Error(EGL_SUCCESS));
return EGL_NO_DISPLAY;
}
break;
default:
recordError(egl::Error(EGL_SUCCESS));
return EGL_NO_DISPLAY;
}
platformType = curAttrib[1];
break;
case EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE:
if (curAttrib[1] != EGL_DONT_CARE)
{
majorVersionSpecified = true;
}
break;
case EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE:
if (curAttrib[1] != EGL_DONT_CARE)
{
minorVersionSpecified = true;
}
break;
case EGL_PLATFORM_ANGLE_USE_WARP_ANGLE:
if (!egl::Display::supportsPlatformD3D())
{
recordError(egl::Error(EGL_SUCCESS));
return EGL_NO_DISPLAY;
}
switch (curAttrib[1])
{
case EGL_FALSE:
case EGL_TRUE:
break;
default:
recordError(egl::Error(EGL_SUCCESS));
return EGL_NO_DISPLAY;
}
requestedWARP = (curAttrib[1] == EGL_TRUE);
break;
default:
@ -149,33 +219,20 @@ EGLDisplay __stdcall eglGetPlatformDisplayEXT(EGLenum platform, void *native_dis
}
}
switch (requestedDisplayType)
if (!majorVersionSpecified && minorVersionSpecified)
{
case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE:
break;
case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE:
case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE:
case EGL_PLATFORM_ANGLE_TYPE_D3D11_WARP_ANGLE:
if (!egl::Display::supportsPlatformD3D())
{
return egl::success(EGL_NO_DISPLAY);
}
break;
case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE:
case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:
if (!egl::Display::supportsPlatformOpenGL())
{
return egl::success(EGL_NO_DISPLAY);
}
break;
default:
return egl::success(EGL_NO_DISPLAY);
recordError(egl::Error(EGL_BAD_ATTRIBUTE));
return EGL_NO_DISPLAY;
}
return egl::Display::getDisplay(displayId, requestedDisplayType);
if (platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE && requestedWARP)
{
recordError(egl::Error(EGL_BAD_ATTRIBUTE));
return EGL_NO_DISPLAY;
}
recordError(egl::Error(EGL_SUCCESS));
return egl::Display::getDisplay(displayId, egl::AttributeMap(attrib_list));
}
EGLBoolean __stdcall eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
@ -185,20 +242,24 @@ EGLBoolean __stdcall eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
if (dpy == EGL_NO_DISPLAY)
{
return egl::error(EGL_BAD_DISPLAY, EGL_FALSE);
recordError(egl::Error(EGL_BAD_DISPLAY));
return EGL_FALSE;
}
egl::Display *display = static_cast<egl::Display*>(dpy);
if (!display->initialize())
egl::Error error = display->initialize();
if (error.isError())
{
return egl::error(EGL_NOT_INITIALIZED, EGL_FALSE);
recordError(error);
return EGL_FALSE;
}
if (major) *major = 1;
if (minor) *minor = 4;
return egl::success(EGL_TRUE);
recordError(egl::Error(EGL_SUCCESS));
return EGL_TRUE;
}
EGLBoolean __stdcall eglTerminate(EGLDisplay dpy)
@ -207,14 +268,16 @@ EGLBoolean __stdcall eglTerminate(EGLDisplay dpy)
if (dpy == EGL_NO_DISPLAY)
{
return egl::error(EGL_BAD_DISPLAY, EGL_FALSE);
recordError(egl::Error(EGL_BAD_DISPLAY));
return EGL_FALSE;
}
egl::Display *display = static_cast<egl::Display*>(dpy);
display->terminate();
return egl::success(EGL_TRUE);
recordError(egl::Error(EGL_SUCCESS));
return EGL_TRUE;
}
const char *__stdcall eglQueryString(EGLDisplay dpy, EGLint name)
@ -227,19 +290,28 @@ const char *__stdcall eglQueryString(EGLDisplay dpy, EGLint name)
return NULL;
}
const char *result;
switch (name)
{
case EGL_CLIENT_APIS:
return egl::success("OpenGL_ES");
result = "OpenGL_ES";
break;
case EGL_EXTENSIONS:
return egl::success(egl::Display::getExtensionString(display));
result = egl::Display::getExtensionString(display);
break;
case EGL_VENDOR:
return egl::success(display->getVendorString());
result = display->getVendorString();
break;
case EGL_VERSION:
return egl::success("1.4 (ANGLE " ANGLE_VERSION_STRING ")");
result = "1.4 (ANGLE " ANGLE_VERSION_STRING ")";
break;
default:
return egl::error(EGL_BAD_PARAMETER, (const char*)NULL);
recordError(egl::Error(EGL_BAD_PARAMETER));
return NULL;
}
recordError(egl::Error(EGL_SUCCESS));
return result;
}
EGLBoolean __stdcall eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config)
@ -257,17 +329,20 @@ EGLBoolean __stdcall eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint co
if (!num_config)
{
return egl::error(EGL_BAD_PARAMETER, EGL_FALSE);
recordError(egl::Error(EGL_BAD_PARAMETER));
return EGL_FALSE;
}
const EGLint attribList[] = {EGL_NONE};
if (!display->getConfigs(configs, attribList, config_size, num_config))
{
return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
recordError(egl::Error(EGL_BAD_ATTRIBUTE));
return EGL_FALSE;
}
return egl::success(EGL_TRUE);
recordError(egl::Error(EGL_SUCCESS));
return EGL_TRUE;
}
EGLBoolean __stdcall eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
@ -285,7 +360,8 @@ EGLBoolean __stdcall eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list,
if (!num_config)
{
return egl::error(EGL_BAD_PARAMETER, EGL_FALSE);
recordError(egl::Error(EGL_BAD_PARAMETER));
return EGL_FALSE;
}
const EGLint attribList[] = {EGL_NONE};
@ -297,7 +373,8 @@ EGLBoolean __stdcall eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list,
display->getConfigs(configs, attrib_list, config_size, num_config);
return egl::success(EGL_TRUE);
recordError(egl::Error(EGL_SUCCESS));
return EGL_TRUE;
}
EGLBoolean __stdcall eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)
@ -314,10 +391,12 @@ EGLBoolean __stdcall eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint
if (!display->getConfigAttrib(config, attribute, value))
{
return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
recordError(egl::Error(EGL_BAD_ATTRIBUTE));
return EGL_FALSE;
}
return egl::success(EGL_TRUE);
recordError(egl::Error(EGL_SUCCESS));
return EGL_TRUE;
}
EGLSurface __stdcall eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list)
@ -332,16 +411,21 @@ EGLSurface __stdcall eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EG
return EGL_NO_SURFACE;
}
#if !defined(ANGLE_PLATFORM_WINRT)
HWND window = (HWND)win;
if (!IsWindow(window))
if (!rx::IsValidEGLNativeWindowType(win))
{
return egl::error(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
recordError(egl::Error(EGL_BAD_NATIVE_WINDOW));
return EGL_NO_SURFACE;
}
#endif
return display->createWindowSurface(win, config, attrib_list);
EGLSurface surface = EGL_NO_SURFACE;
egl::Error error = display->createWindowSurface(win, config, attrib_list, &surface);
if (error.isError())
{
recordError(error);
return EGL_NO_SURFACE;
}
return surface;
}
EGLSurface __stdcall eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
@ -356,7 +440,15 @@ EGLSurface __stdcall eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, c
return EGL_NO_SURFACE;
}
return display->createOffscreenSurface(config, NULL, attrib_list);
EGLSurface surface = EGL_NO_SURFACE;
egl::Error error = display->createOffscreenSurface(config, NULL, attrib_list, &surface);
if (error.isError())
{
recordError(error);
return EGL_NO_SURFACE;
}
return surface;
}
EGLSurface __stdcall eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list)
@ -373,7 +465,8 @@ EGLSurface __stdcall eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EG
UNIMPLEMENTED(); // FIXME
return egl::success(EGL_NO_SURFACE);
recordError(egl::Error(EGL_SUCCESS));
return EGL_NO_SURFACE;
}
EGLBoolean __stdcall eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
@ -390,12 +483,14 @@ EGLBoolean __stdcall eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
if (surface == EGL_NO_SURFACE)
{
return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
recordError(egl::Error(EGL_BAD_SURFACE));
return EGL_FALSE;
}
display->destroySurface((egl::Surface*)surface);
return egl::success(EGL_TRUE);
recordError(egl::Error(EGL_SUCCESS));
return EGL_TRUE;
}
EGLBoolean __stdcall eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value)
@ -413,7 +508,8 @@ EGLBoolean __stdcall eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint
if (surface == EGL_NO_SURFACE)
{
return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
recordError(egl::Error(EGL_BAD_SURFACE));
return EGL_FALSE;
}
switch (attribute)
@ -473,10 +569,12 @@ EGLBoolean __stdcall eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint
*value = eglSurface->isFixedSize();
break;
default:
return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
recordError(egl::Error(EGL_BAD_ATTRIBUTE));
return EGL_FALSE;
}
return egl::success(EGL_TRUE);
recordError(egl::Error(EGL_SUCCESS));
return EGL_TRUE;
}
EGLBoolean __stdcall eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value)
@ -498,7 +596,8 @@ EGLBoolean __stdcall eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surf
if (surface == EGL_NO_SURFACE)
{
return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
recordError(egl::Error(EGL_BAD_SURFACE));
return EGL_FALSE;
}
rx::SwapChain *swapchain = eglSurface->getSwapChain();
@ -522,7 +621,8 @@ EGLBoolean __stdcall eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surf
if (renderer->getMajorShaderModel() < 4)
{
return egl::error(EGL_BAD_CONTEXT, EGL_FALSE);
recordError(egl::Error(EGL_BAD_CONTEXT));
return EGL_FALSE;
}
*value = static_cast<rx::Renderer11*>(renderer)->getDevice();
@ -530,10 +630,12 @@ EGLBoolean __stdcall eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surf
break;
#endif
default:
return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
recordError(egl::Error(EGL_BAD_ATTRIBUTE));
return EGL_FALSE;
}
return egl::success(EGL_TRUE);
recordError(egl::Error(EGL_SUCCESS));
return EGL_TRUE;
}
EGLBoolean __stdcall eglBindAPI(EGLenum api)
@ -544,16 +646,19 @@ EGLBoolean __stdcall eglBindAPI(EGLenum api)
{
case EGL_OPENGL_API:
case EGL_OPENVG_API:
return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); // Not supported by this implementation
recordError(egl::Error(EGL_BAD_PARAMETER));
return EGL_FALSE; // Not supported by this implementation
case EGL_OPENGL_ES_API:
break;
default:
return egl::error(EGL_BAD_PARAMETER, EGL_FALSE);
recordError(egl::Error(EGL_BAD_PARAMETER));
return EGL_FALSE;
}
egl::setCurrentAPI(api);
return egl::success(EGL_TRUE);
recordError(egl::Error(EGL_SUCCESS));
return EGL_TRUE;
}
EGLenum __stdcall eglQueryAPI(void)
@ -562,7 +667,8 @@ EGLenum __stdcall eglQueryAPI(void)
EGLenum API = egl::getCurrentAPI();
return egl::success(API);
recordError(egl::Error(EGL_SUCCESS));
return API;
}
EGLBoolean __stdcall eglWaitClient(void)
@ -571,7 +677,8 @@ EGLBoolean __stdcall eglWaitClient(void)
UNIMPLEMENTED(); // FIXME
return egl::success(0);
recordError(egl::Error(EGL_SUCCESS));
return 0;
}
EGLBoolean __stdcall eglReleaseThread(void)
@ -580,7 +687,8 @@ EGLBoolean __stdcall eglReleaseThread(void)
eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE);
return egl::success(EGL_TRUE);
recordError(egl::Error(EGL_SUCCESS));
return EGL_TRUE;
}
EGLSurface __stdcall eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list)
@ -598,10 +706,19 @@ EGLSurface __stdcall eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum bu
if (buftype != EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE || !buffer)
{
return egl::error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
recordError(egl::Error(EGL_BAD_PARAMETER));
return EGL_NO_SURFACE;
}
return display->createOffscreenSurface(config, (HANDLE)buffer, attrib_list);
EGLSurface surface = EGL_NO_SURFACE;
egl::Error error = display->createOffscreenSurface(config, (HANDLE)buffer, attrib_list, &surface);
if (error.isError())
{
recordError(error);
return EGL_NO_SURFACE;
}
return surface;
}
EGLBoolean __stdcall eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
@ -617,9 +734,30 @@ EGLBoolean __stdcall eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint
return EGL_FALSE;
}
switch (attribute)
{
case EGL_WIDTH:
if (!eglSurface->isFixedSize() || !value) {
recordError(egl::Error(EGL_BAD_PARAMETER));
return EGL_FALSE;
}
eglSurface->setFixedWidth(value);
return EGL_TRUE;
case EGL_HEIGHT:
if (!eglSurface->isFixedSize() || !value) {
recordError(egl::Error(EGL_BAD_PARAMETER));
return EGL_FALSE;
}
eglSurface->setFixedHeight(value);
return EGL_TRUE;
default:
break;
}
UNIMPLEMENTED(); // FIXME
return egl::success(EGL_TRUE);
recordError(egl::Error(EGL_SUCCESS));
return EGL_TRUE;
}
EGLBoolean __stdcall eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
@ -636,30 +774,36 @@ EGLBoolean __stdcall eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint
if (buffer != EGL_BACK_BUFFER)
{
return egl::error(EGL_BAD_PARAMETER, EGL_FALSE);
recordError(egl::Error(EGL_BAD_PARAMETER));
return EGL_FALSE;
}
if (surface == EGL_NO_SURFACE || eglSurface->getWindowHandle())
{
return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
recordError(egl::Error(EGL_BAD_SURFACE));
return EGL_FALSE;
}
if (eglSurface->getBoundTexture())
{
return egl::error(EGL_BAD_ACCESS, EGL_FALSE);
recordError(egl::Error(EGL_BAD_ACCESS));
return EGL_FALSE;
}
if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE)
{
return egl::error(EGL_BAD_MATCH, EGL_FALSE);
recordError(egl::Error(EGL_BAD_MATCH));
return EGL_FALSE;
}
if (!glBindTexImage(eglSurface))
{
return egl::error(EGL_BAD_MATCH, EGL_FALSE);
recordError(egl::Error(EGL_BAD_MATCH));
return EGL_FALSE;
}
return egl::success(EGL_TRUE);
recordError(egl::Error(EGL_SUCCESS));
return EGL_TRUE;
}
EGLBoolean __stdcall eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
@ -676,17 +820,20 @@ EGLBoolean __stdcall eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLi
if (buffer != EGL_BACK_BUFFER)
{
return egl::error(EGL_BAD_PARAMETER, EGL_FALSE);
recordError(egl::Error(EGL_BAD_PARAMETER));
return EGL_FALSE;
}
if (surface == EGL_NO_SURFACE || eglSurface->getWindowHandle())
{
return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
recordError(egl::Error(EGL_BAD_SURFACE));
return EGL_FALSE;
}
if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE)
{
return egl::error(EGL_BAD_MATCH, EGL_FALSE);
recordError(egl::Error(EGL_BAD_MATCH));
return EGL_FALSE;
}
gl::Texture2D *texture = eglSurface->getBoundTexture();
@ -696,7 +843,8 @@ EGLBoolean __stdcall eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLi
texture->releaseTexImage();
}
return egl::success(EGL_TRUE);
recordError(egl::Error(EGL_SUCCESS));
return EGL_TRUE;
}
EGLBoolean __stdcall eglSwapInterval(EGLDisplay dpy, EGLint interval)
@ -714,12 +862,14 @@ EGLBoolean __stdcall eglSwapInterval(EGLDisplay dpy, EGLint interval)
if (draw_surface == NULL)
{
return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
recordError(egl::Error(EGL_BAD_SURFACE));
return EGL_FALSE;
}
draw_surface->setSwapInterval(interval);
return egl::success(EGL_TRUE);
recordError(egl::Error(EGL_SUCCESS));
return EGL_TRUE;
}
EGLContext __stdcall eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list)
@ -744,27 +894,38 @@ EGLContext __stdcall eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLConte
case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
if (attribute[1] == EGL_TRUE)
{
return egl::error(EGL_BAD_CONFIG, EGL_NO_CONTEXT); // Unimplemented
recordError(egl::Error(EGL_BAD_CONFIG)); // Unimplemented
return EGL_NO_CONTEXT;
// robust_access = true;
}
else if (attribute[1] != EGL_FALSE)
return egl::error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
{
recordError(egl::Error(EGL_BAD_ATTRIBUTE));
return EGL_NO_CONTEXT;
}
break;
case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
if (attribute[1] == EGL_LOSE_CONTEXT_ON_RESET_EXT)
{
reset_notification = true;
}
else if (attribute[1] != EGL_NO_RESET_NOTIFICATION_EXT)
return egl::error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
{
recordError(egl::Error(EGL_BAD_ATTRIBUTE));
return EGL_NO_CONTEXT;
}
break;
default:
return egl::error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
recordError(egl::Error(EGL_BAD_ATTRIBUTE));
return EGL_NO_CONTEXT;
}
}
}
if (client_version != 2 && client_version != 3)
{
return egl::error(EGL_BAD_CONFIG, EGL_NO_CONTEXT);
recordError(egl::Error(EGL_BAD_CONFIG));
return EGL_NO_CONTEXT;
}
egl::Display *display = static_cast<egl::Display*>(dpy);
@ -775,18 +936,21 @@ EGLContext __stdcall eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLConte
if (sharedGLContext->isResetNotificationEnabled() != reset_notification)
{
return egl::error(EGL_BAD_MATCH, EGL_NO_CONTEXT);
recordError(egl::Error(EGL_BAD_MATCH));
return EGL_NO_CONTEXT;
}
if (sharedGLContext->getClientVersion() != client_version)
{
return egl::error(EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
recordError(egl::Error(EGL_BAD_CONTEXT));
return EGL_NO_CONTEXT;
}
// Can not share contexts between displays
if (sharedGLContext->getRenderer() != display->getRenderer())
{
return egl::error(EGL_BAD_MATCH, EGL_NO_CONTEXT);
recordError(egl::Error(EGL_BAD_MATCH));
return EGL_NO_CONTEXT;
}
}
@ -795,7 +959,16 @@ EGLContext __stdcall eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLConte
return EGL_NO_CONTEXT;
}
return display->createContext(config, client_version, static_cast<gl::Context*>(share_context), reset_notification, robust_access);
EGLContext context = EGL_NO_CONTEXT;
egl::Error error = display->createContext(config, client_version, static_cast<gl::Context*>(share_context),
reset_notification, robust_access, &context);
if (error.isError())
{
recordError(error);
return EGL_NO_CONTEXT;
}
return context;
}
EGLBoolean __stdcall eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
@ -812,12 +985,14 @@ EGLBoolean __stdcall eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
if (ctx == EGL_NO_CONTEXT)
{
return egl::error(EGL_BAD_CONTEXT, EGL_FALSE);
recordError(egl::Error(EGL_BAD_CONTEXT));
return EGL_FALSE;
}
display->destroyContext(context);
return egl::success(EGL_TRUE);
recordError(egl::Error(EGL_SUCCESS));
return EGL_TRUE;
}
EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
@ -832,7 +1007,8 @@ EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface
bool noSurface = (draw == EGL_NO_SURFACE || read == EGL_NO_SURFACE);
if (noContext != noSurface)
{
return egl::error(EGL_BAD_MATCH, EGL_FALSE);
recordError(egl::Error(EGL_BAD_MATCH));
return EGL_FALSE;
}
if (ctx != EGL_NO_CONTEXT && !validateContext(display, context))
@ -850,7 +1026,8 @@ EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface
if (renderer->isDeviceLost())
{
return egl::error(EGL_CONTEXT_LOST, EGL_FALSE);
recordError(egl::Error(EGL_CONTEXT_LOST));
return EGL_FALSE;
}
}
@ -871,7 +1048,8 @@ EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface
glMakeCurrent(context, display, static_cast<egl::Surface*>(draw));
return egl::success(EGL_TRUE);
recordError(egl::Error(EGL_SUCCESS));
return EGL_TRUE;
}
EGLContext __stdcall eglGetCurrentContext(void)
@ -880,7 +1058,8 @@ EGLContext __stdcall eglGetCurrentContext(void)
EGLContext context = glGetCurrentContext();
return egl::success(context);
recordError(egl::Error(EGL_SUCCESS));
return context;
}
EGLSurface __stdcall eglGetCurrentSurface(EGLint readdraw)
@ -889,17 +1068,18 @@ EGLSurface __stdcall eglGetCurrentSurface(EGLint readdraw)
if (readdraw == EGL_READ)
{
EGLSurface read = egl::getCurrentReadSurface();
return egl::success(read);
recordError(egl::Error(EGL_SUCCESS));
return egl::getCurrentReadSurface();
}
else if (readdraw == EGL_DRAW)
{
EGLSurface draw = egl::getCurrentDrawSurface();
return egl::success(draw);
recordError(egl::Error(EGL_SUCCESS));
return egl::getCurrentDrawSurface();
}
else
{
return egl::error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
recordError(egl::Error(EGL_BAD_PARAMETER));
return EGL_NO_SURFACE;
}
}
@ -909,7 +1089,8 @@ EGLDisplay __stdcall eglGetCurrentDisplay(void)
EGLDisplay dpy = egl::getCurrentDisplay();
return egl::success(dpy);
recordError(egl::Error(EGL_SUCCESS));
return dpy;
}
EGLBoolean __stdcall eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
@ -927,7 +1108,8 @@ EGLBoolean __stdcall eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attr
UNIMPLEMENTED(); // FIXME
return egl::success(0);
recordError(egl::Error(EGL_SUCCESS));
return 0;
}
EGLBoolean __stdcall eglWaitGL(void)
@ -936,7 +1118,8 @@ EGLBoolean __stdcall eglWaitGL(void)
UNIMPLEMENTED(); // FIXME
return egl::success(0);
recordError(egl::Error(EGL_SUCCESS));
return 0;
}
EGLBoolean __stdcall eglWaitNative(EGLint engine)
@ -945,7 +1128,8 @@ EGLBoolean __stdcall eglWaitNative(EGLint engine)
UNIMPLEMENTED(); // FIXME
return egl::success(0);
recordError(egl::Error(EGL_SUCCESS));
return 0;
}
EGLBoolean __stdcall eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
@ -962,20 +1146,25 @@ EGLBoolean __stdcall eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
if (display->getRenderer()->isDeviceLost())
{
return egl::error(EGL_CONTEXT_LOST, EGL_FALSE);
recordError(egl::Error(EGL_CONTEXT_LOST));
return EGL_FALSE;
}
if (surface == EGL_NO_SURFACE)
{
return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
recordError(egl::Error(EGL_BAD_SURFACE));
return EGL_FALSE;
}
if (eglSurface->swap())
egl::Error error = eglSurface->swap();
if (error.isError())
{
return egl::success(EGL_TRUE);
recordError(error);
return EGL_FALSE;
}
return EGL_FALSE;
recordError(egl::Error(EGL_SUCCESS));
return EGL_TRUE;
}
EGLBoolean __stdcall eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
@ -992,12 +1181,14 @@ EGLBoolean __stdcall eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativ
if (display->getRenderer()->isDeviceLost())
{
return egl::error(EGL_CONTEXT_LOST, EGL_FALSE);
recordError(egl::Error(EGL_CONTEXT_LOST));
return EGL_FALSE;
}
UNIMPLEMENTED(); // FIXME
return egl::success(0);
recordError(egl::Error(EGL_SUCCESS));
return 0;
}
EGLBoolean __stdcall eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height)
@ -1006,7 +1197,8 @@ EGLBoolean __stdcall eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLi
if (x < 0 || y < 0 || width < 0 || height < 0)
{
return egl::error(EGL_BAD_PARAMETER, EGL_FALSE);
recordError(egl::Error(EGL_BAD_PARAMETER));
return EGL_FALSE;
}
egl::Display *display = static_cast<egl::Display*>(dpy);
@ -1019,20 +1211,25 @@ EGLBoolean __stdcall eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLi
if (display->getRenderer()->isDeviceLost())
{
return egl::error(EGL_CONTEXT_LOST, EGL_FALSE);
recordError(egl::Error(EGL_CONTEXT_LOST));
return EGL_FALSE;
}
if (surface == EGL_NO_SURFACE)
{
return egl::error(EGL_BAD_SURFACE, EGL_FALSE);
recordError(egl::Error(EGL_BAD_SURFACE));
return EGL_FALSE;
}
if (eglSurface->postSubBuffer(x, y, width, height))
egl::Error error = eglSurface->postSubBuffer(x, y, width, height);
if (error.isError())
{
return egl::success(EGL_TRUE);
recordError(error);
return EGL_FALSE;
}
return EGL_FALSE;
recordError(egl::Error(EGL_SUCCESS));
return EGL_TRUE;
}
__eglMustCastToProperFunctionPointerType __stdcall eglGetProcAddress(const char *procname)

View File

@ -11,9 +11,6 @@
#include "common/debug.h"
#include "common/tls.h"
#if defined(ANGLE_PLATFORM_WINRT)
__declspec(thread)
#endif
static TLSIndex currentTLS = TLS_OUT_OF_INDEXES;
namespace egl
@ -21,12 +18,6 @@ namespace egl
Current *AllocateCurrent()
{
#if defined(ANGLE_PLATFORM_WINRT)
if (currentTLS == TLS_OUT_OF_INDEXES)
{
currentTLS = CreateTLSIndex();
}
#endif
ASSERT(currentTLS != TLS_OUT_OF_INDEXES);
if (currentTLS == TLS_OUT_OF_INDEXES)
{
@ -51,12 +42,6 @@ Current *AllocateCurrent()
void DeallocateCurrent()
{
#if defined(ANGLE_PLATFORM_WINRT)
if (currentTLS == TLS_OUT_OF_INDEXES)
{
return;
}
#endif
Current *current = reinterpret_cast<Current*>(GetTLSValue(currentTLS));
SafeDelete(current);
SetTLSValue(currentTLS, NULL);
@ -72,7 +57,7 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved
{
case DLL_PROCESS_ATTACH:
{
#if defined(ANGLE_ENABLE_TRACE)
#if defined(ANGLE_ENABLE_DEBUG_TRACE)
FILE *debug = fopen(TRACE_OUTPUT_FILE, "rt");
if (debug)
@ -87,15 +72,15 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved
}
#endif
#if defined(ANGLE_PLATFORM_WINRT) // On WinRT, don't handle TLS from DllMain
return DisableThreadLibraryCalls(instance);
#endif
currentTLS = CreateTLSIndex();
if (currentTLS == TLS_OUT_OF_INDEXES)
{
return FALSE;
}
#ifdef ANGLE_ENABLE_DEBUG_ANNOTATIONS
gl::InitializeDebugAnnotations();
#endif
}
// Fall through to initialize index
case DLL_THREAD_ATTACH:
@ -105,15 +90,17 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved
break;
case DLL_THREAD_DETACH:
{
#if !defined(ANGLE_PLATFORM_WINRT)
egl::DeallocateCurrent();
#endif
}
break;
case DLL_PROCESS_DETACH:
{
egl::DeallocateCurrent();
DestroyTLSIndex(currentTLS);
#ifdef ANGLE_ENABLE_DEBUG_ANNOTATIONS
gl::UninitializeDebugAnnotations();
#endif
}
break;
default:
@ -143,11 +130,11 @@ Current *GetCurrentData()
#endif
}
void setCurrentError(EGLint error)
void recordError(const Error &error)
{
Current *current = GetCurrentData();
current->error = error;
current->error = error.getCode();
}
EGLint getCurrentError()
@ -213,9 +200,4 @@ EGLSurface getCurrentReadSurface()
return current->readSurface;
}
void error(EGLint errorCode)
{
egl::setCurrentError(errorCode);
}
}

View File

@ -9,6 +9,8 @@
#ifndef LIBEGL_MAIN_H_
#define LIBEGL_MAIN_H_
#include "libEGL/Error.h"
#include <EGL/egl.h>
#include <EGL/eglext.h>
@ -23,7 +25,7 @@ struct Current
EGLSurface readSurface;
};
void setCurrentError(EGLint error);
void recordError(const Error &error);
EGLint getCurrentError();
void setCurrentAPI(EGLenum API);
@ -38,24 +40,6 @@ EGLSurface getCurrentDrawSurface();
void setCurrentReadSurface(EGLSurface surface);
EGLSurface getCurrentReadSurface();
void error(EGLint errorCode);
template<class T>
const T &error(EGLint errorCode, const T &returnValue)
{
error(errorCode);
return returnValue;
}
template<class T>
const T &success(const T &returnValue)
{
egl::setCurrentError(EGL_SUCCESS);
return returnValue;
}
}
#endif // LIBEGL_MAIN_H_

View File

@ -15,6 +15,7 @@
#include <cstddef>
#include <string>
#include <vector>
#include <stdint.h>
namespace gl
{
@ -26,7 +27,7 @@ class BinaryInputStream
{
mError = false;
mOffset = 0;
mData = static_cast<const char*>(data);
mData = static_cast<const uint8_t*>(data);
mLength = length;
}
@ -85,7 +86,7 @@ class BinaryInputStream
return;
}
v->assign(mData + mOffset, length);
v->assign(reinterpret_cast<const char *>(mData) + mOffset, length);
mOffset += length;
}
@ -115,11 +116,16 @@ class BinaryInputStream
return mOffset == mLength;
}
const uint8_t *data()
{
return mData;
}
private:
DISALLOW_COPY_AND_ASSIGN(BinaryInputStream);
bool mError;
size_t mOffset;
const char *mData;
const uint8_t *mData;
size_t mLength;
template <typename T>

View File

@ -19,7 +19,6 @@
namespace rx
{
class Renderer;
class BufferImpl;
};

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