<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[164567] trunk/Source/ThirdParty/ANGLE</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/164567">164567</a></dd>
<dt>Author</dt> <dd>dino@apple.com</dd>
<dt>Date</dt> <dd>2014-02-23 16:58:19 -0800 (Sun, 23 Feb 2014)</dd>
</dl>
<h3>Log Message</h3>
<pre>Missing files from previous commit.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceThirdPartyANGLEChangeLog">trunk/Source/ThirdParty/ANGLE/ChangeLog</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li>trunk/Source/ThirdParty/ANGLE/src/compiler/translator/</li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorBaseTypesh">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/BaseTypes.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorBuiltInFunctionEmulatorcpp">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/BuiltInFunctionEmulator.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorBuiltInFunctionEmulatorh">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/BuiltInFunctionEmulator.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorCodeGencpp">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/CodeGen.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorCommonh">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Common.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorCompilercpp">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Compiler.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorConstantUnionh">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ConstantUnion.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorDetectCallDepthcpp">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/DetectCallDepth.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorDetectCallDepthh">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/DetectCallDepth.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorDetectDiscontinuitycpp">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/DetectDiscontinuity.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorDetectDiscontinuityh">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/DetectDiscontinuity.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorDiagnosticscpp">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Diagnostics.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorDiagnosticsh">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Diagnostics.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorDirectiveHandlercpp">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/DirectiveHandler.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorDirectiveHandlerh">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/DirectiveHandler.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorExtensionBehaviorh">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ExtensionBehavior.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorForLoopUnrollcpp">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ForLoopUnroll.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorForLoopUnrollh">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ForLoopUnroll.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorHashNamesh">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/HashNames.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorInfoSinkcpp">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/InfoSink.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorInfoSinkh">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/InfoSink.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorInitializecpp">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Initialize.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorInitializeh">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Initialize.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorInitializeDllcpp">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/InitializeDll.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorInitializeDllh">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/InitializeDll.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorInitializeGlobalsh">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/InitializeGlobals.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorInitializeParseContextcpp">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/InitializeParseContext.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorInitializeParseContexth">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/InitializeParseContext.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorInitializeVariablescpp">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/InitializeVariables.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorInitializeVariablesh">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/InitializeVariables.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorIntermTraversecpp">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/IntermTraverse.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorIntermediatecpp">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Intermediate.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorMMaph">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/MMap.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorMapLongVariableNamescpp">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/MapLongVariableNames.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorMapLongVariableNamesh">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/MapLongVariableNames.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorNodeSearchh">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/NodeSearch.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorOutputESSLcpp">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/OutputESSL.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorOutputESSLh">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/OutputESSL.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorOutputGLSLcpp">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/OutputGLSL.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorOutputGLSLh">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/OutputGLSL.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorOutputGLSLBasecpp">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/OutputGLSLBase.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorOutputGLSLBaseh">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/OutputGLSLBase.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorOutputHLSLcpp">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/OutputHLSL.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorOutputHLSLh">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/OutputHLSL.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorParseContextcpp">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ParseContext.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorParseContexth">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ParseContext.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorPoolAlloccpp">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/PoolAlloc.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorPoolAlloch">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/PoolAlloc.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorPragmah">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Pragma.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorQualifierAlivecpp">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/QualifierAlive.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorQualifierAliveh">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/QualifierAlive.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorRemoveTreecpp">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/RemoveTree.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorRemoveTreeh">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/RemoveTree.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorRenameFunctionh">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/RenameFunction.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorRewriteElseBlockscpp">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/RewriteElseBlocks.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorRewriteElseBlocksh">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/RewriteElseBlocks.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorSearchSymbolcpp">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/SearchSymbol.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorSearchSymbolh">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/SearchSymbol.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorShHandleh">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ShHandle.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorShaderLangcpp">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ShaderLang.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorSymbolTablecpp">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/SymbolTable.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorSymbolTableh">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/SymbolTable.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorTranslatorESSLcpp">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/TranslatorESSL.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorTranslatorESSLh">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/TranslatorESSL.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorTranslatorGLSLcpp">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/TranslatorGLSL.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorTranslatorGLSLh">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/TranslatorGLSL.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorTranslatorHLSLcpp">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/TranslatorHLSL.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorTranslatorHLSLh">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/TranslatorHLSL.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorTypesh">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Types.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorUnfoldShortCircuitcpp">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/UnfoldShortCircuit.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorUnfoldShortCircuith">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/UnfoldShortCircuit.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorUnfoldShortCircuitASTcpp">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/UnfoldShortCircuitAST.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorUnfoldShortCircuitASTh">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/UnfoldShortCircuitAST.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorUniformcpp">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Uniform.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorUniformh">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Uniform.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorValidateLimitationscpp">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ValidateLimitations.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorValidateLimitationsh">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ValidateLimitations.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorVariableInfocpp">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/VariableInfo.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorVariableInfoh">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/VariableInfo.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorVariablePackercpp">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/VariablePacker.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorVariablePackerh">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/VariablePacker.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorVersionGLSLcpp">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/VersionGLSL.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorVersionGLSLh">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/VersionGLSL.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorcompilerdebugcpp">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/compilerdebug.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorcompilerdebugh">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/compilerdebug.h</a></li>
<li>trunk/Source/ThirdParty/ANGLE/src/compiler/translator/depgraph/</li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatordepgraphDependencyGraphcpp">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/depgraph/DependencyGraph.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatordepgraphDependencyGraphh">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/depgraph/DependencyGraph.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatordepgraphDependencyGraphBuildercpp">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/depgraph/DependencyGraphBuilder.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatordepgraphDependencyGraphBuilderh">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/depgraph/DependencyGraphBuilder.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatordepgraphDependencyGraphOutputcpp">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/depgraph/DependencyGraphOutput.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatordepgraphDependencyGraphOutputh">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/depgraph/DependencyGraphOutput.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatordepgraphDependencyGraphTraversecpp">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/depgraph/DependencyGraphTraverse.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorgenerate_parsersh">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/generate_parser.sh</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorglslangh">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/glslang.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorglslangl">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/glslang.l</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorglslangy">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/glslang.y</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorglslang_lexcpp">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/glslang_lex.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorglslang_tabcpp">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/glslang_tab.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorglslang_tabh">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/glslang_tab.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorintermOutcpp">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/intermOut.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorintermediateh">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/intermediate.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorlocalintermediateh">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/localintermediate.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorosincludeh">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/osinclude.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorossource_posixcpp">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ossource_posix.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorossource_wincpp">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ossource_win.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorparseConstcpp">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/parseConst.cpp</a></li>
<li>trunk/Source/ThirdParty/ANGLE/src/compiler/translator/timing/</li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatortimingRestrictFragmentShaderTimingcpp">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/timing/RestrictFragmentShaderTiming.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatortimingRestrictFragmentShaderTimingh">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/timing/RestrictFragmentShaderTiming.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatortimingRestrictVertexShaderTimingcpp">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/timing/RestrictVertexShaderTiming.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatortimingRestrictVertexShaderTimingh">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/timing/RestrictVertexShaderTiming.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorutilcpp">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/util.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrccompilertranslatorutilh">trunk/Source/ThirdParty/ANGLE/src/compiler/translator/util.h</a></li>
<li>trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/</li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11BufferStorage11cpp">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/BufferStorage11.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11BufferStorage11h">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/BufferStorage11.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11Fence11cpp">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/Fence11.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11Fence11h">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/Fence11.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11Image11cpp">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/Image11.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11Image11h">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/Image11.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11IndexBuffer11cpp">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/IndexBuffer11.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11IndexBuffer11h">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/IndexBuffer11.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11InputLayoutCachecpp">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/InputLayoutCache.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11InputLayoutCacheh">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/InputLayoutCache.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11Query11cpp">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/Query11.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11Query11h">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/Query11.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11RenderStateCachecpp">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/RenderStateCache.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11RenderStateCacheh">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/RenderStateCache.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11RenderTarget11cpp">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/RenderTarget11.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11RenderTarget11h">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/RenderTarget11.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11Renderer11cpp">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/Renderer11.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11Renderer11h">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/Renderer11.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11ShaderExecutable11cpp">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/ShaderExecutable11.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11ShaderExecutable11h">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/ShaderExecutable11.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11SwapChain11cpp">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/SwapChain11.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11SwapChain11h">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/SwapChain11.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11TextureStorage11cpp">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/TextureStorage11.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11TextureStorage11h">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/TextureStorage11.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11VertexBuffer11cpp">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/VertexBuffer11.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11VertexBuffer11h">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/VertexBuffer11.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11renderer11_utilscpp">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/renderer11_utils.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11renderer11_utilsh">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/renderer11_utils.h</a></li>
<li>trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/</li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11shadersClear11hlsl">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/Clear11.hlsl</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11shadersPassthrough11hlsl">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/Passthrough11.hlsl</a></li>
<li>trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/compiled/</li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11shaderscompiledclear11vsh">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/compiled/clear11vs.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11shaderscompiledclearmultiple11psh">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/compiled/clearmultiple11ps.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11shaderscompiledclearsingle11psh">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/compiled/clearsingle11ps.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11shaderscompiledpassthrough11vsh">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/compiled/passthrough11vs.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11shaderscompiledpassthroughlum11psh">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughlum11ps.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11shaderscompiledpassthroughlumalpha11psh">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughlumalpha11ps.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11shaderscompiledpassthroughrgb11psh">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgb11ps.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11shaderscompiledpassthroughrgba11psh">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgba11ps.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11shadersgenerate_shadersbat">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/generate_shaders.bat</a></li>
<li>trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/</li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9Blitcpp">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Blit.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9Blith">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Blit.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9BufferStorage9cpp">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/BufferStorage9.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9BufferStorage9h">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/BufferStorage9.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9Fence9cpp">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Fence9.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9Fence9h">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Fence9.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9Image9cpp">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Image9.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9Image9h">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Image9.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9IndexBuffer9cpp">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/IndexBuffer9.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9IndexBuffer9h">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/IndexBuffer9.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9Query9cpp">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Query9.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9Query9h">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Query9.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9RenderTarget9cpp">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/RenderTarget9.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9RenderTarget9h">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/RenderTarget9.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9Renderer9cpp">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Renderer9.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9Renderer9h">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Renderer9.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9ShaderExecutable9cpp">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/ShaderExecutable9.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9ShaderExecutable9h">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/ShaderExecutable9.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9SwapChain9cpp">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/SwapChain9.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9SwapChain9h">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/SwapChain9.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9TextureStorage9cpp">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/TextureStorage9.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9TextureStorage9h">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/TextureStorage9.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9VertexBuffer9cpp">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/VertexBuffer9.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9VertexBuffer9h">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/VertexBuffer9.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9VertexDeclarationCachecpp">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/VertexDeclarationCache.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9VertexDeclarationCacheh">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/VertexDeclarationCache.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9renderer9_utilscpp">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/renderer9_utils.cpp</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9renderer9_utilsh">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/renderer9_utils.h</a></li>
<li>trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/shaders/</li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9shadersBlitps">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/shaders/Blit.ps</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9shadersBlitvs">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/shaders/Blit.vs</a></li>
<li>trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/shaders/compiled/</li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9shaderscompiledcomponentmaskpsh">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/shaders/compiled/componentmaskps.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9shaderscompiledflipyvsh">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/shaders/compiled/flipyvs.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9shaderscompiledluminancepsh">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/shaders/compiled/luminanceps.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9shaderscompiledpassthroughpsh">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/shaders/compiled/passthroughps.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9shaderscompiledstandardvsh">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/shaders/compiled/standardvs.h</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9shadersgenerate_shadersbat">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/shaders/generate_shaders.bat</a></li>
<li><a href="#trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9vertexconversionh">trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/vertexconversion.h</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceThirdPartyANGLEChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/ThirdParty/ANGLE/ChangeLog (164566 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/ChangeLog        2014-02-24 00:51:05 UTC (rev 164566)
+++ trunk/Source/ThirdParty/ANGLE/ChangeLog        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -1,5 +1,9 @@
</span><span class="cx"> 2014-02-23 Dean Jackson <dino@apple.com>
</span><span class="cx">
</span><ins>+ Missing files from previous commit.
+
+2014-02-23 Dean Jackson <dino@apple.com>
+
</ins><span class="cx"> Update ANGLE to 836bd2176e5607b14846cf1fbc5932dbc91318f4
</span><span class="cx"> https://bugs.webkit.org/show_bug.cgi?id=129232
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorBaseTypesh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/BaseTypes.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/BaseTypes.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/BaseTypes.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,149 @@
</span><ins>+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef _BASICTYPES_INCLUDED_
+#define _BASICTYPES_INCLUDED_
+
+//
+// Precision qualifiers
+//
+enum TPrecision
+{
+ // These need to be kept sorted
+ EbpUndefined,
+ EbpLow,
+ EbpMedium,
+ EbpHigh
+};
+
+inline const char* getPrecisionString(TPrecision p)
+{
+ switch(p)
+ {
+ case EbpHigh: return "highp"; break;
+ case EbpMedium: return "mediump"; break;
+ case EbpLow: return "lowp"; break;
+ default: return "mediump"; break; // Safest fallback
+ }
+}
+
+//
+// Basic type. Arrays, vectors, etc., are orthogonal to this.
+//
+enum TBasicType
+{
+ EbtVoid,
+ EbtFloat,
+ EbtInt,
+ EbtBool,
+ EbtGuardSamplerBegin, // non type: see implementation of IsSampler()
+ EbtSampler2D,
+ EbtSamplerCube,
+ EbtSamplerExternalOES, // Only valid if OES_EGL_image_external exists.
+ EbtSampler2DRect, // Only valid if GL_ARB_texture_rectangle exists.
+ EbtGuardSamplerEnd, // non type: see implementation of IsSampler()
+ EbtStruct,
+ EbtAddress, // should be deprecated??
+ EbtInvariant // used as a type when qualifying a previously declared variable as being invariant
+};
+
+inline const char* getBasicString(TBasicType t)
+{
+ switch (t)
+ {
+ case EbtVoid: return "void"; break;
+ case EbtFloat: return "float"; break;
+ case EbtInt: return "int"; break;
+ case EbtBool: return "bool"; break;
+ case EbtSampler2D: return "sampler2D"; break;
+ case EbtSamplerCube: return "samplerCube"; break;
+ case EbtSamplerExternalOES: return "samplerExternalOES"; break;
+ case EbtSampler2DRect: return "sampler2DRect"; break;
+ case EbtStruct: return "structure"; break;
+ default: return "unknown type";
+ }
+}
+
+inline bool IsSampler(TBasicType type)
+{
+ return type > EbtGuardSamplerBegin && type < EbtGuardSamplerEnd;
+}
+
+//
+// Qualifiers and built-ins. These are mainly used to see what can be read
+// or written, and by the machine dependent translator to know which registers
+// to allocate variables in. Since built-ins tend to go to different registers
+// than varying or uniform, it makes sense they are peers, not sub-classes.
+//
+enum TQualifier
+{
+ EvqTemporary, // For temporaries (within a function), read/write
+ EvqGlobal, // For globals read/write
+ EvqInternal, // For internal use, not visible to the user
+ EvqConst, // User defined constants and non-output parameters in functions
+ EvqAttribute, // Readonly
+ EvqVaryingIn, // readonly, fragment shaders only
+ EvqVaryingOut, // vertex shaders only read/write
+ EvqInvariantVaryingIn, // readonly, fragment shaders only
+ EvqInvariantVaryingOut, // vertex shaders only read/write
+ EvqUniform, // Readonly, vertex and fragment
+
+ // parameters
+ EvqIn,
+ EvqOut,
+ EvqInOut,
+ EvqConstReadOnly,
+
+ // built-ins written by vertex shader
+ EvqPosition,
+ EvqPointSize,
+
+ // built-ins read by fragment shader
+ EvqFragCoord,
+ EvqFrontFacing,
+ EvqPointCoord,
+
+ // built-ins written by fragment shader
+ EvqFragColor,
+ EvqFragData,
+ EvqFragDepth,
+
+ // end of list
+ EvqLast
+};
+
+//
+// This is just for debug print out, carried along with the definitions above.
+//
+inline const char* getQualifierString(TQualifier q)
+{
+ switch(q)
+ {
+ case EvqTemporary: return "Temporary"; break;
+ case EvqGlobal: return "Global"; break;
+ case EvqConst: return "const"; break;
+ case EvqConstReadOnly: return "const"; break;
+ case EvqAttribute: return "attribute"; break;
+ case EvqVaryingIn: return "varying"; break;
+ case EvqVaryingOut: return "varying"; break;
+ case EvqInvariantVaryingIn: return "invariant varying"; break;
+ case EvqInvariantVaryingOut:return "invariant varying"; break;
+ case EvqUniform: return "uniform"; break;
+ case EvqIn: return "in"; break;
+ case EvqOut: return "out"; break;
+ case EvqInOut: return "inout"; break;
+ case EvqPosition: return "Position"; break;
+ case EvqPointSize: return "PointSize"; break;
+ case EvqFragCoord: return "FragCoord"; break;
+ case EvqFrontFacing: return "FrontFacing"; break;
+ case EvqFragColor: return "FragColor"; break;
+ case EvqFragData: return "FragData"; break;
+ case EvqFragDepth: return "FragDepth"; break;
+ default: return "unknown qualifier";
+ }
+}
+
+#endif // _BASICTYPES_INCLUDED_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/BaseTypes.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorBuiltInFunctionEmulatorcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/BuiltInFunctionEmulator.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/BuiltInFunctionEmulator.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/BuiltInFunctionEmulator.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,406 @@
</span><ins>+//
+// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/BuiltInFunctionEmulator.h"
+
+#include "compiler/translator/SymbolTable.h"
+
+namespace {
+
+// we use macros here instead of function definitions to work around more GLSL
+// compiler bugs, in particular on NVIDIA hardware on Mac OSX. Macros are
+// problematic because if the argument has side-effects they will be repeatedly
+// evaluated. This is unlikely to show up in real shaders, but is something to
+// consider.
+const char* kFunctionEmulationVertexSource[] = {
+ "#error no emulation for cos(float)",
+ "#error no emulation for cos(vec2)",
+ "#error no emulation for cos(vec3)",
+ "#error no emulation for cos(vec4)",
+
+ "#define webgl_distance_emu(x, y) ((x) >= (y) ? (x) - (y) : (y) - (x))",
+ "#error no emulation for distance(vec2, vec2)",
+ "#error no emulation for distance(vec3, vec3)",
+ "#error no emulation for distance(vec4, vec4)",
+
+ "#define webgl_dot_emu(x, y) ((x) * (y))",
+ "#error no emulation for dot(vec2, vec2)",
+ "#error no emulation for dot(vec3, vec3)",
+ "#error no emulation for dot(vec4, vec4)",
+
+ "#define webgl_length_emu(x) ((x) >= 0.0 ? (x) : -(x))",
+ "#error no emulation for length(vec2)",
+ "#error no emulation for length(vec3)",
+ "#error no emulation for length(vec4)",
+
+ "#define webgl_normalize_emu(x) ((x) == 0.0 ? 0.0 : ((x) > 0.0 ? 1.0 : -1.0))",
+ "#error no emulation for normalize(vec2)",
+ "#error no emulation for normalize(vec3)",
+ "#error no emulation for normalize(vec4)",
+
+ "#define webgl_reflect_emu(I, N) ((I) - 2.0 * (N) * (I) * (N))",
+ "#error no emulation for reflect(vec2, vec2)",
+ "#error no emulation for reflect(vec3, vec3)",
+ "#error no emulation for reflect(vec4, vec4)"
+};
+
+const char* kFunctionEmulationFragmentSource[] = {
+ "webgl_emu_precision float webgl_cos_emu(webgl_emu_precision float a) { return cos(a); }",
+ "webgl_emu_precision vec2 webgl_cos_emu(webgl_emu_precision vec2 a) { return cos(a); }",
+ "webgl_emu_precision vec3 webgl_cos_emu(webgl_emu_precision vec3 a) { return cos(a); }",
+ "webgl_emu_precision vec4 webgl_cos_emu(webgl_emu_precision vec4 a) { return cos(a); }",
+
+ "#define webgl_distance_emu(x, y) ((x) >= (y) ? (x) - (y) : (y) - (x))",
+ "#error no emulation for distance(vec2, vec2)",
+ "#error no emulation for distance(vec3, vec3)",
+ "#error no emulation for distance(vec4, vec4)",
+
+ "#define webgl_dot_emu(x, y) ((x) * (y))",
+ "#error no emulation for dot(vec2, vec2)",
+ "#error no emulation for dot(vec3, vec3)",
+ "#error no emulation for dot(vec4, vec4)",
+
+ "#define webgl_length_emu(x) ((x) >= 0.0 ? (x) : -(x))",
+ "#error no emulation for length(vec2)",
+ "#error no emulation for length(vec3)",
+ "#error no emulation for length(vec4)",
+
+ "#define webgl_normalize_emu(x) ((x) == 0.0 ? 0.0 : ((x) > 0.0 ? 1.0 : -1.0))",
+ "#error no emulation for normalize(vec2)",
+ "#error no emulation for normalize(vec3)",
+ "#error no emulation for normalize(vec4)",
+
+ "#define webgl_reflect_emu(I, N) ((I) - 2.0 * (N) * (I) * (N))",
+ "#error no emulation for reflect(vec2, vec2)",
+ "#error no emulation for reflect(vec3, vec3)",
+ "#error no emulation for reflect(vec4, vec4)"
+};
+
+const bool kFunctionEmulationVertexMask[] = {
+#if defined(__APPLE__)
+ // Work around ATI driver bugs in Mac.
+ false, // TFunctionCos1
+ false, // TFunctionCos2
+ false, // TFunctionCos3
+ false, // TFunctionCos4
+ true, // TFunctionDistance1_1
+ false, // TFunctionDistance2_2
+ false, // TFunctionDistance3_3
+ false, // TFunctionDistance4_4
+ true, // TFunctionDot1_1
+ false, // TFunctionDot2_2
+ false, // TFunctionDot3_3
+ false, // TFunctionDot4_4
+ true, // TFunctionLength1
+ false, // TFunctionLength2
+ false, // TFunctionLength3
+ false, // TFunctionLength4
+ true, // TFunctionNormalize1
+ false, // TFunctionNormalize2
+ false, // TFunctionNormalize3
+ false, // TFunctionNormalize4
+ true, // TFunctionReflect1_1
+ false, // TFunctionReflect2_2
+ false, // TFunctionReflect3_3
+ false, // TFunctionReflect4_4
+#else
+ // Work around D3D driver bug in Win.
+ false, // TFunctionCos1
+ false, // TFunctionCos2
+ false, // TFunctionCos3
+ false, // TFunctionCos4
+ false, // TFunctionDistance1_1
+ false, // TFunctionDistance2_2
+ false, // TFunctionDistance3_3
+ false, // TFunctionDistance4_4
+ false, // TFunctionDot1_1
+ false, // TFunctionDot2_2
+ false, // TFunctionDot3_3
+ false, // TFunctionDot4_4
+ false, // TFunctionLength1
+ false, // TFunctionLength2
+ false, // TFunctionLength3
+ false, // TFunctionLength4
+ false, // TFunctionNormalize1
+ false, // TFunctionNormalize2
+ false, // TFunctionNormalize3
+ false, // TFunctionNormalize4
+ false, // TFunctionReflect1_1
+ false, // TFunctionReflect2_2
+ false, // TFunctionReflect3_3
+ false, // TFunctionReflect4_4
+#endif
+ false // TFunctionUnknown
+};
+
+const bool kFunctionEmulationFragmentMask[] = {
+#if defined(__APPLE__)
+ // Work around ATI driver bugs in Mac.
+ true, // TFunctionCos1
+ true, // TFunctionCos2
+ true, // TFunctionCos3
+ true, // TFunctionCos4
+ true, // TFunctionDistance1_1
+ false, // TFunctionDistance2_2
+ false, // TFunctionDistance3_3
+ false, // TFunctionDistance4_4
+ true, // TFunctionDot1_1
+ false, // TFunctionDot2_2
+ false, // TFunctionDot3_3
+ false, // TFunctionDot4_4
+ true, // TFunctionLength1
+ false, // TFunctionLength2
+ false, // TFunctionLength3
+ false, // TFunctionLength4
+ true, // TFunctionNormalize1
+ false, // TFunctionNormalize2
+ false, // TFunctionNormalize3
+ false, // TFunctionNormalize4
+ true, // TFunctionReflect1_1
+ false, // TFunctionReflect2_2
+ false, // TFunctionReflect3_3
+ false, // TFunctionReflect4_4
+#else
+ // Work around D3D driver bug in Win.
+ false, // TFunctionCos1
+ false, // TFunctionCos2
+ false, // TFunctionCos3
+ false, // TFunctionCos4
+ false, // TFunctionDistance1_1
+ false, // TFunctionDistance2_2
+ false, // TFunctionDistance3_3
+ false, // TFunctionDistance4_4
+ false, // TFunctionDot1_1
+ false, // TFunctionDot2_2
+ false, // TFunctionDot3_3
+ false, // TFunctionDot4_4
+ false, // TFunctionLength1
+ false, // TFunctionLength2
+ false, // TFunctionLength3
+ false, // TFunctionLength4
+ false, // TFunctionNormalize1
+ false, // TFunctionNormalize2
+ false, // TFunctionNormalize3
+ false, // TFunctionNormalize4
+ false, // TFunctionReflect1_1
+ false, // TFunctionReflect2_2
+ false, // TFunctionReflect3_3
+ false, // TFunctionReflect4_4
+#endif
+ false // TFunctionUnknown
+};
+
+class BuiltInFunctionEmulationMarker : public TIntermTraverser {
+public:
+ BuiltInFunctionEmulationMarker(BuiltInFunctionEmulator& emulator)
+ : mEmulator(emulator)
+ {
+ }
+
+ virtual bool visitUnary(Visit visit, TIntermUnary* node)
+ {
+ if (visit == PreVisit) {
+ bool needToEmulate = mEmulator.SetFunctionCalled(
+ node->getOp(), node->getOperand()->getType());
+ if (needToEmulate)
+ node->setUseEmulatedFunction();
+ }
+ return true;
+ }
+
+ virtual bool visitAggregate(Visit visit, TIntermAggregate* node)
+ {
+ if (visit == PreVisit) {
+ // Here we handle all the built-in functions instead of the ones we
+ // currently identified as problematic.
+ switch (node->getOp()) {
+ case EOpLessThan:
+ case EOpGreaterThan:
+ case EOpLessThanEqual:
+ case EOpGreaterThanEqual:
+ case EOpVectorEqual:
+ case EOpVectorNotEqual:
+ case EOpMod:
+ case EOpPow:
+ case EOpAtan:
+ case EOpMin:
+ case EOpMax:
+ case EOpClamp:
+ case EOpMix:
+ case EOpStep:
+ case EOpSmoothStep:
+ case EOpDistance:
+ case EOpDot:
+ case EOpCross:
+ case EOpFaceForward:
+ case EOpReflect:
+ case EOpRefract:
+ case EOpMul:
+ break;
+ default:
+ return true;
+ };
+ const TIntermSequence& sequence = node->getSequence();
+ // Right now we only handle built-in functions with two parameters.
+ if (sequence.size() != 2)
+ return true;
+ TIntermTyped* param1 = sequence[0]->getAsTyped();
+ TIntermTyped* param2 = sequence[1]->getAsTyped();
+ if (!param1 || !param2)
+ return true;
+ bool needToEmulate = mEmulator.SetFunctionCalled(
+ node->getOp(), param1->getType(), param2->getType());
+ if (needToEmulate)
+ node->setUseEmulatedFunction();
+ }
+ return true;
+ }
+
+private:
+ BuiltInFunctionEmulator& mEmulator;
+};
+
+} // anonymous namepsace
+
+BuiltInFunctionEmulator::BuiltInFunctionEmulator(ShShaderType shaderType)
+{
+ if (shaderType == SH_FRAGMENT_SHADER) {
+ mFunctionMask = kFunctionEmulationFragmentMask;
+ mFunctionSource = kFunctionEmulationFragmentSource;
+ } else {
+ mFunctionMask = kFunctionEmulationVertexMask;
+ mFunctionSource = kFunctionEmulationVertexSource;
+ }
+}
+
+bool BuiltInFunctionEmulator::SetFunctionCalled(
+ TOperator op, const TType& param)
+{
+ TBuiltInFunction function = IdentifyFunction(op, param);
+ return SetFunctionCalled(function);
+}
+
+bool BuiltInFunctionEmulator::SetFunctionCalled(
+ TOperator op, const TType& param1, const TType& param2)
+{
+ TBuiltInFunction function = IdentifyFunction(op, param1, param2);
+ return SetFunctionCalled(function);
+}
+
+bool BuiltInFunctionEmulator::SetFunctionCalled(
+ BuiltInFunctionEmulator::TBuiltInFunction function) {
+ if (function == TFunctionUnknown || mFunctionMask[function] == false)
+ return false;
+ for (size_t i = 0; i < mFunctions.size(); ++i) {
+ if (mFunctions[i] == function)
+ return true;
+ }
+ mFunctions.push_back(function);
+ return true;
+}
+
+void BuiltInFunctionEmulator::OutputEmulatedFunctionDefinition(
+ TInfoSinkBase& out, bool withPrecision) const
+{
+ if (mFunctions.size() == 0)
+ return;
+ out << "// BEGIN: Generated code for built-in function emulation\n\n";
+ if (withPrecision) {
+ out << "#if defined(GL_FRAGMENT_PRECISION_HIGH)\n"
+ << "#define webgl_emu_precision highp\n"
+ << "#else\n"
+ << "#define webgl_emu_precision mediump\n"
+ << "#endif\n\n";
+ } else {
+ out << "#define webgl_emu_precision\n\n";
+ }
+ for (size_t i = 0; i < mFunctions.size(); ++i) {
+ out << mFunctionSource[mFunctions[i]] << "\n\n";
+ }
+ out << "// END: Generated code for built-in function emulation\n\n";
+}
+
+BuiltInFunctionEmulator::TBuiltInFunction
+BuiltInFunctionEmulator::IdentifyFunction(
+ TOperator op, const TType& param)
+{
+ if (param.getNominalSize() > 4)
+ return TFunctionUnknown;
+ unsigned int function = TFunctionUnknown;
+ switch (op) {
+ case EOpCos:
+ function = TFunctionCos1;
+ break;
+ case EOpLength:
+ function = TFunctionLength1;
+ break;
+ case EOpNormalize:
+ function = TFunctionNormalize1;
+ break;
+ default:
+ break;
+ }
+ if (function == TFunctionUnknown)
+ return TFunctionUnknown;
+ if (param.isVector())
+ function += param.getNominalSize() - 1;
+ return static_cast<TBuiltInFunction>(function);
+}
+
+BuiltInFunctionEmulator::TBuiltInFunction
+BuiltInFunctionEmulator::IdentifyFunction(
+ TOperator op, const TType& param1, const TType& param2)
+{
+ // Right now for all the emulated functions with two parameters, the two
+ // parameters have the same type.
+ if (param1.isVector() != param2.isVector() ||
+ param1.getNominalSize() != param2.getNominalSize() ||
+ param1.getNominalSize() > 4)
+ return TFunctionUnknown;
+
+ unsigned int function = TFunctionUnknown;
+ switch (op) {
+ case EOpDistance:
+ function = TFunctionDistance1_1;
+ break;
+ case EOpDot:
+ function = TFunctionDot1_1;
+ break;
+ case EOpReflect:
+ function = TFunctionReflect1_1;
+ break;
+ default:
+ break;
+ }
+ if (function == TFunctionUnknown)
+ return TFunctionUnknown;
+ if (param1.isVector())
+ function += param1.getNominalSize() - 1;
+ return static_cast<TBuiltInFunction>(function);
+}
+
+void BuiltInFunctionEmulator::MarkBuiltInFunctionsForEmulation(
+ TIntermNode* root)
+{
+ ASSERT(root);
+
+ BuiltInFunctionEmulationMarker marker(*this);
+ root->traverse(&marker);
+}
+
+void BuiltInFunctionEmulator::Cleanup()
+{
+ mFunctions.clear();
+}
+
+//static
+TString BuiltInFunctionEmulator::GetEmulatedFunctionName(
+ const TString& name)
+{
+ ASSERT(name[name.length() - 1] == '(');
+ return "webgl_" + name.substr(0, name.length() - 1) + "_emu(";
+}
+
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/BuiltInFunctionEmulator.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorBuiltInFunctionEmulatorh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/BuiltInFunctionEmulator.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/BuiltInFunctionEmulator.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/BuiltInFunctionEmulator.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,93 @@
</span><ins>+//
+// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILIER_BUILT_IN_FUNCTION_EMULATOR_H_
+#define COMPILIER_BUILT_IN_FUNCTION_EMULATOR_H_
+
+#include "GLSLANG/ShaderLang.h"
+
+#include "compiler/translator/InfoSink.h"
+#include "compiler/translator/intermediate.h"
+
+//
+// This class decides which built-in functions need to be replaced with the
+// emulated ones.
+// It's only a workaround for OpenGL driver bugs, and isn't needed in general.
+//
+class BuiltInFunctionEmulator {
+public:
+ BuiltInFunctionEmulator(ShShaderType shaderType);
+ // Records that a function is called by the shader and might needs to be
+ // emulated. If the function's group is not in mFunctionGroupFilter, this
+ // becomes an no-op.
+ // Returns true if the function call needs to be replaced with an emulated
+ // one.
+ bool SetFunctionCalled(TOperator op, const TType& param);
+ bool SetFunctionCalled(
+ TOperator op, const TType& param1, const TType& param2);
+
+ // Output function emulation definition. This should be before any other
+ // shader source.
+ void OutputEmulatedFunctionDefinition(TInfoSinkBase& out, bool withPrecision) const;
+
+ void MarkBuiltInFunctionsForEmulation(TIntermNode* root);
+
+ void Cleanup();
+
+ // "name(" becomes "webgl_name_emu(".
+ static TString GetEmulatedFunctionName(const TString& name);
+
+private:
+ //
+ // Built-in functions.
+ //
+ enum TBuiltInFunction {
+ TFunctionCos1 = 0, // float cos(float);
+ TFunctionCos2, // vec2 cos(vec2);
+ TFunctionCos3, // vec3 cos(vec3);
+ TFunctionCos4, // vec4 cos(vec4);
+
+ TFunctionDistance1_1, // float distance(float, float);
+ TFunctionDistance2_2, // vec2 distance(vec2, vec2);
+ TFunctionDistance3_3, // vec3 distance(vec3, vec3);
+ TFunctionDistance4_4, // vec4 distance(vec4, vec4);
+
+ TFunctionDot1_1, // float dot(float, float);
+ TFunctionDot2_2, // vec2 dot(vec2, vec2);
+ TFunctionDot3_3, // vec3 dot(vec3, vec3);
+ TFunctionDot4_4, // vec4 dot(vec4, vec4);
+
+ TFunctionLength1, // float length(float);
+ TFunctionLength2, // float length(vec2);
+ TFunctionLength3, // float length(vec3);
+ TFunctionLength4, // float length(vec4);
+
+ TFunctionNormalize1, // float normalize(float);
+ TFunctionNormalize2, // vec2 normalize(vec2);
+ TFunctionNormalize3, // vec3 normalize(vec3);
+ TFunctionNormalize4, // vec4 normalize(vec4);
+
+ TFunctionReflect1_1, // float reflect(float, float);
+ TFunctionReflect2_2, // vec2 reflect(vec2, vec2);
+ TFunctionReflect3_3, // vec3 reflect(vec3, vec3);
+ TFunctionReflect4_4, // vec4 reflect(vec4, vec4);
+
+ TFunctionUnknown
+ };
+
+ TBuiltInFunction IdentifyFunction(TOperator op, const TType& param);
+ TBuiltInFunction IdentifyFunction(
+ TOperator op, const TType& param1, const TType& param2);
+
+ bool SetFunctionCalled(TBuiltInFunction function);
+
+ std::vector<TBuiltInFunction> mFunctions;
+
+ const bool* mFunctionMask; // a boolean flag for each function.
+ const char** mFunctionSource;
+};
+
+#endif // COMPILIER_BUILT_IN_FUNCTION_EMULATOR_H_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/BuiltInFunctionEmulator.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorCodeGencpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/CodeGen.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/CodeGen.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/CodeGen.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,38 @@
</span><ins>+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/TranslatorESSL.h"
+#include "compiler/translator/TranslatorGLSL.h"
+#include "compiler/translator/TranslatorHLSL.h"
+
+//
+// This function must be provided to create the actual
+// compile object used by higher level code. It returns
+// a subclass of TCompiler.
+//
+TCompiler* ConstructCompiler(
+ ShShaderType type, ShShaderSpec spec, ShShaderOutput output)
+{
+ switch (output) {
+ case SH_ESSL_OUTPUT:
+ return new TranslatorESSL(type, spec);
+ case SH_GLSL_OUTPUT:
+ return new TranslatorGLSL(type, spec);
+ case SH_HLSL9_OUTPUT:
+ case SH_HLSL11_OUTPUT:
+ return new TranslatorHLSL(type, spec, output);
+ default:
+ return NULL;
+ }
+}
+
+//
+// Delete the compiler made by ConstructCompiler
+//
+void DeleteCompiler(TCompiler* compiler)
+{
+ delete compiler;
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/CodeGen.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorCommonh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Common.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Common.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Common.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,92 @@
</span><ins>+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef _COMMON_INCLUDED_
+#define _COMMON_INCLUDED_
+
+#include <map>
+#include <sstream>
+#include <string>
+#include <vector>
+#include <limits>
+#include <stdio.h>
+
+#include "compiler/translator/PoolAlloc.h"
+#include "compiler/translator/compilerdebug.h"
+#include "common/angleutils.h"
+
+struct TSourceLoc {
+ int first_file;
+ int first_line;
+ int last_file;
+ int last_line;
+};
+
+//
+// Put POOL_ALLOCATOR_NEW_DELETE in base classes to make them use this scheme.
+//
+#define POOL_ALLOCATOR_NEW_DELETE() \
+ void* operator new(size_t s) { return GetGlobalPoolAllocator()->allocate(s); } \
+ void* operator new(size_t, void *_Where) { return (_Where); } \
+ void operator delete(void*) { } \
+ void operator delete(void *, void *) { } \
+ void* operator new[](size_t s) { return GetGlobalPoolAllocator()->allocate(s); } \
+ void* operator new[](size_t, void *_Where) { return (_Where); } \
+ void operator delete[](void*) { } \
+ void operator delete[](void *, void *) { }
+
+//
+// Pool version of string.
+//
+typedef pool_allocator<char> TStringAllocator;
+typedef std::basic_string <char, std::char_traits<char>, TStringAllocator> TString;
+typedef std::basic_ostringstream<char, std::char_traits<char>, TStringAllocator> TStringStream;
+inline TString* NewPoolTString(const char* s)
+{
+ void* memory = GetGlobalPoolAllocator()->allocate(sizeof(TString));
+ return new(memory) TString(s);
+}
+
+//
+// Persistent string memory. Should only be used for strings that survive
+// across compiles.
+//
+#define TPersistString std::string
+#define TPersistStringStream std::ostringstream
+
+//
+// Pool allocator versions of vectors, lists, and maps
+//
+template <class T> class TVector : public std::vector<T, pool_allocator<T> > {
+public:
+ typedef typename std::vector<T, pool_allocator<T> >::size_type size_type;
+ TVector() : std::vector<T, pool_allocator<T> >() {}
+ TVector(const pool_allocator<T>& a) : std::vector<T, pool_allocator<T> >(a) {}
+ TVector(size_type i): std::vector<T, pool_allocator<T> >(i) {}
+};
+
+template <class K, class D, class CMP = std::less<K> >
+class TMap : public std::map<K, D, CMP, pool_allocator<std::pair<const K, D> > > {
+public:
+ typedef pool_allocator<std::pair<const K, D> > tAllocator;
+
+ TMap() : std::map<K, D, CMP, tAllocator>() {}
+ // use correct two-stage name lookup supported in gcc 3.4 and above
+ TMap(const tAllocator& a) : std::map<K, D, CMP, tAllocator>(std::map<K, D, CMP, tAllocator>::key_compare(), a) {}
+};
+
+// Integer to TString conversion
+template <typename T>
+inline TString str(T i)
+{
+ ASSERT(std::numeric_limits<T>::is_integer);
+ char buffer[((8 * sizeof(T)) / 3) + 3];
+ const char *formatStr = std::numeric_limits<T>::is_signed ? "%d" : "%u";
+ snprintf(buffer, sizeof(buffer), formatStr, i);
+ return buffer;
+}
+
+#endif // _COMMON_INCLUDED_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Common.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorCompilercpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Compiler.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Compiler.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Compiler.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,538 @@
</span><ins>+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/BuiltInFunctionEmulator.h"
+#include "compiler/translator/DetectCallDepth.h"
+#include "compiler/translator/ForLoopUnroll.h"
+#include "compiler/translator/Initialize.h"
+#include "compiler/translator/InitializeParseContext.h"
+#include "compiler/translator/InitializeVariables.h"
+#include "compiler/translator/MapLongVariableNames.h"
+#include "compiler/translator/ParseContext.h"
+#include "compiler/translator/RenameFunction.h"
+#include "compiler/translator/ShHandle.h"
+#include "compiler/translator/UnfoldShortCircuitAST.h"
+#include "compiler/translator/ValidateLimitations.h"
+#include "compiler/translator/VariablePacker.h"
+#include "compiler/translator/depgraph/DependencyGraph.h"
+#include "compiler/translator/depgraph/DependencyGraphOutput.h"
+#include "compiler/translator/timing/RestrictFragmentShaderTiming.h"
+#include "compiler/translator/timing/RestrictVertexShaderTiming.h"
+#include "third_party/compiler/ArrayBoundsClamper.h"
+
+bool isWebGLBasedSpec(ShShaderSpec spec)
+{
+ return spec == SH_WEBGL_SPEC || spec == SH_CSS_SHADERS_SPEC;
+}
+
+namespace {
+class TScopedPoolAllocator
+{
+ public:
+ TScopedPoolAllocator(TPoolAllocator* allocator) : mAllocator(allocator)
+ {
+ mAllocator->push();
+ SetGlobalPoolAllocator(mAllocator);
+ }
+ ~TScopedPoolAllocator()
+ {
+ SetGlobalPoolAllocator(NULL);
+ mAllocator->pop();
+ }
+
+ private:
+ TPoolAllocator* mAllocator;
+};
+
+class TScopedSymbolTableLevel
+{
+ public:
+ TScopedSymbolTableLevel(TSymbolTable* table) : mTable(table)
+ {
+ ASSERT(mTable->atBuiltInLevel());
+ mTable->push();
+ }
+ ~TScopedSymbolTableLevel()
+ {
+ while (!mTable->atBuiltInLevel())
+ mTable->pop();
+ }
+
+ private:
+ TSymbolTable* mTable;
+};
+} // namespace
+
+TShHandleBase::TShHandleBase()
+{
+ allocator.push();
+ SetGlobalPoolAllocator(&allocator);
+}
+
+TShHandleBase::~TShHandleBase()
+{
+ SetGlobalPoolAllocator(NULL);
+ allocator.popAll();
+}
+
+TCompiler::TCompiler(ShShaderType type, ShShaderSpec spec)
+ : shaderType(type),
+ shaderSpec(spec),
+ maxUniformVectors(0),
+ maxVaryingVectors(0),
+ maxExpressionComplexity(0),
+ maxCallStackDepth(0),
+ fragmentPrecisionHigh(false),
+ clampingStrategy(SH_CLAMP_WITH_CLAMP_INTRINSIC),
+ builtInFunctionEmulator(type)
+{
+ longNameMap = LongNameMap::GetInstance();
+}
+
+TCompiler::~TCompiler()
+{
+ ASSERT(longNameMap);
+ longNameMap->Release();
+}
+
+bool TCompiler::Init(const ShBuiltInResources& resources)
+{
+ maxUniformVectors = (shaderType == SH_VERTEX_SHADER) ?
+ resources.MaxVertexUniformVectors :
+ resources.MaxFragmentUniformVectors;
+ maxVaryingVectors = resources.MaxVaryingVectors;
+ maxExpressionComplexity = resources.MaxExpressionComplexity;
+ maxCallStackDepth = resources.MaxCallStackDepth;
+
+ SetGlobalPoolAllocator(&allocator);
+
+ // Generate built-in symbol table.
+ if (!InitBuiltInSymbolTable(resources))
+ return false;
+ InitExtensionBehavior(resources, extensionBehavior);
+ fragmentPrecisionHigh = resources.FragmentPrecisionHigh == 1;
+
+ arrayBoundsClamper.SetClampingStrategy(resources.ArrayIndexClampingStrategy);
+ clampingStrategy = resources.ArrayIndexClampingStrategy;
+
+ hashFunction = resources.HashFunction;
+
+ return true;
+}
+
+bool TCompiler::compile(const char* const shaderStrings[],
+ size_t numStrings,
+ int compileOptions)
+{
+ TScopedPoolAllocator scopedAlloc(&allocator);
+ clearResults();
+
+ if (numStrings == 0)
+ return true;
+
+ // If compiling for WebGL, validate loop and indexing as well.
+ if (isWebGLBasedSpec(shaderSpec))
+ compileOptions |= SH_VALIDATE_LOOP_INDEXING;
+
+ // First string is path of source file if flag is set. The actual source follows.
+ const char* sourcePath = NULL;
+ size_t firstSource = 0;
+ if (compileOptions & SH_SOURCE_PATH)
+ {
+ sourcePath = shaderStrings[0];
+ ++firstSource;
+ }
+
+ TIntermediate intermediate(infoSink);
+ TParseContext parseContext(symbolTable, extensionBehavior, intermediate,
+ shaderType, shaderSpec, compileOptions, true,
+ sourcePath, infoSink);
+ parseContext.fragmentPrecisionHigh = fragmentPrecisionHigh;
+ SetGlobalParseContext(&parseContext);
+
+ // We preserve symbols at the built-in level from compile-to-compile.
+ // Start pushing the user-defined symbols at global level.
+ TScopedSymbolTableLevel scopedSymbolLevel(&symbolTable);
+
+ // Parse shader.
+ bool success =
+ (PaParseStrings(numStrings - firstSource, &shaderStrings[firstSource], NULL, &parseContext) == 0) &&
+ (parseContext.treeRoot != NULL);
+ if (success)
+ {
+ TIntermNode* root = parseContext.treeRoot;
+ success = intermediate.postProcess(root);
+
+ if (success)
+ success = detectCallDepth(root, infoSink, (compileOptions & SH_LIMIT_CALL_STACK_DEPTH) != 0);
+
+ if (success && (compileOptions & SH_VALIDATE_LOOP_INDEXING))
+ success = validateLimitations(root);
+
+ if (success && (compileOptions & SH_TIMING_RESTRICTIONS))
+ success = enforceTimingRestrictions(root, (compileOptions & SH_DEPENDENCY_GRAPH) != 0);
+
+ if (success && shaderSpec == SH_CSS_SHADERS_SPEC)
+ rewriteCSSShader(root);
+
+ // Unroll for-loop markup needs to happen after validateLimitations pass.
+ if (success && (compileOptions & SH_UNROLL_FOR_LOOP_WITH_INTEGER_INDEX))
+ ForLoopUnroll::MarkForLoopsWithIntegerIndicesForUnrolling(root);
+
+ // Built-in function emulation needs to happen after validateLimitations pass.
+ if (success && (compileOptions & SH_EMULATE_BUILT_IN_FUNCTIONS))
+ builtInFunctionEmulator.MarkBuiltInFunctionsForEmulation(root);
+
+ // Clamping uniform array bounds needs to happen after validateLimitations pass.
+ if (success && (compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS))
+ arrayBoundsClamper.MarkIndirectArrayBoundsForClamping(root);
+
+ // Disallow expressions deemed too complex.
+ if (success && (compileOptions & SH_LIMIT_EXPRESSION_COMPLEXITY))
+ success = limitExpressionComplexity(root);
+
+ // Call mapLongVariableNames() before collectAttribsUniforms() so in
+ // collectAttribsUniforms() we already have the mapped symbol names and
+ // we could composite mapped and original variable names.
+ // Also, if we hash all the names, then no need to do this for long names.
+ if (success && (compileOptions & SH_MAP_LONG_VARIABLE_NAMES) && hashFunction == NULL)
+ mapLongVariableNames(root);
+
+ if (success && shaderType == SH_VERTEX_SHADER && (compileOptions & SH_INIT_GL_POSITION))
+ initializeGLPosition(root);
+
+ if (success && (compileOptions & SH_UNFOLD_SHORT_CIRCUIT))
+ {
+ UnfoldShortCircuitAST unfoldShortCircuit;
+ root->traverse(&unfoldShortCircuit);
+ unfoldShortCircuit.updateTree();
+ }
+
+ if (success && (compileOptions & SH_VARIABLES))
+ {
+ collectVariables(root);
+ if (compileOptions & SH_ENFORCE_PACKING_RESTRICTIONS)
+ success = enforcePackingRestrictions();
+
+ if (success && shaderType == SH_VERTEX_SHADER &&
+ (compileOptions & SH_INIT_VARYINGS_WITHOUT_STATIC_USE))
+ initializeVaryingsWithoutStaticUse(root);
+ }
+
+ if (success && (compileOptions & SH_INTERMEDIATE_TREE))
+ intermediate.outputTree(root);
+
+ if (success && (compileOptions & SH_OBJECT_CODE))
+ translate(root);
+ }
+
+ // Cleanup memory.
+ intermediate.remove(parseContext.treeRoot);
+
+ return success;
+}
+
+bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources &resources)
+{
+ compileResources = resources;
+
+ assert(symbolTable.isEmpty());
+ symbolTable.push();
+
+ TPublicType integer;
+ integer.type = EbtInt;
+ integer.size = 1;
+ integer.matrix = false;
+ integer.array = false;
+
+ TPublicType floatingPoint;
+ floatingPoint.type = EbtFloat;
+ floatingPoint.size = 1;
+ floatingPoint.matrix = false;
+ floatingPoint.array = false;
+
+ TPublicType sampler;
+ sampler.size = 1;
+ sampler.matrix = false;
+ sampler.array = false;
+
+ switch(shaderType)
+ {
+ case SH_FRAGMENT_SHADER:
+ symbolTable.setDefaultPrecision(integer, EbpMedium);
+ break;
+ case SH_VERTEX_SHADER:
+ symbolTable.setDefaultPrecision(integer, EbpHigh);
+ symbolTable.setDefaultPrecision(floatingPoint, EbpHigh);
+ break;
+ default:
+ assert(false && "Language not supported");
+ }
+ // We set defaults for all the sampler types, even those that are
+ // only available if an extension exists.
+ for (int samplerType = EbtGuardSamplerBegin + 1;
+ samplerType < EbtGuardSamplerEnd; ++samplerType)
+ {
+ sampler.type = static_cast<TBasicType>(samplerType);
+ symbolTable.setDefaultPrecision(sampler, EbpLow);
+ }
+
+ InsertBuiltInFunctions(shaderType, shaderSpec, resources, symbolTable);
+
+ IdentifyBuiltIns(shaderType, shaderSpec, resources, symbolTable);
+
+ return true;
+}
+
+void TCompiler::clearResults()
+{
+ arrayBoundsClamper.Cleanup();
+ infoSink.info.erase();
+ infoSink.obj.erase();
+ infoSink.debug.erase();
+
+ attribs.clear();
+ uniforms.clear();
+ varyings.clear();
+
+ builtInFunctionEmulator.Cleanup();
+
+ nameMap.clear();
+}
+
+bool TCompiler::detectCallDepth(TIntermNode* root, TInfoSink& infoSink, bool limitCallStackDepth)
+{
+ DetectCallDepth detect(infoSink, limitCallStackDepth, maxCallStackDepth);
+ root->traverse(&detect);
+ switch (detect.detectCallDepth())
+ {
+ case DetectCallDepth::kErrorNone:
+ return true;
+ case DetectCallDepth::kErrorMissingMain:
+ infoSink.info.prefix(EPrefixError);
+ infoSink.info << "Missing main()";
+ return false;
+ case DetectCallDepth::kErrorRecursion:
+ infoSink.info.prefix(EPrefixError);
+ infoSink.info << "Function recursion detected";
+ return false;
+ case DetectCallDepth::kErrorMaxDepthExceeded:
+ infoSink.info.prefix(EPrefixError);
+ infoSink.info << "Function call stack too deep";
+ return false;
+ default:
+ UNREACHABLE();
+ return false;
+ }
+}
+
+void TCompiler::rewriteCSSShader(TIntermNode* root)
+{
+ RenameFunction renamer("main(", "css_main(");
+ root->traverse(&renamer);
+}
+
+bool TCompiler::validateLimitations(TIntermNode* root)
+{
+ ValidateLimitations validate(shaderType, infoSink.info);
+ root->traverse(&validate);
+ return validate.numErrors() == 0;
+}
+
+bool TCompiler::enforceTimingRestrictions(TIntermNode* root, bool outputGraph)
+{
+ if (shaderSpec != SH_WEBGL_SPEC)
+ {
+ infoSink.info << "Timing restrictions must be enforced under the WebGL spec.";
+ return false;
+ }
+
+ if (shaderType == SH_FRAGMENT_SHADER)
+ {
+ TDependencyGraph graph(root);
+
+ // Output any errors first.
+ bool success = enforceFragmentShaderTimingRestrictions(graph);
+
+ // Then, output the dependency graph.
+ if (outputGraph)
+ {
+ TDependencyGraphOutput output(infoSink.info);
+ output.outputAllSpanningTrees(graph);
+ }
+
+ return success;
+ }
+ else
+ {
+ return enforceVertexShaderTimingRestrictions(root);
+ }
+}
+
+bool TCompiler::limitExpressionComplexity(TIntermNode* root)
+{
+ TIntermTraverser traverser;
+ root->traverse(&traverser);
+ TDependencyGraph graph(root);
+
+ for (TFunctionCallVector::const_iterator iter = graph.beginUserDefinedFunctionCalls();
+ iter != graph.endUserDefinedFunctionCalls();
+ ++iter)
+ {
+ TGraphFunctionCall* samplerSymbol = *iter;
+ TDependencyGraphTraverser graphTraverser;
+ samplerSymbol->traverse(&graphTraverser);
+ }
+
+ if (traverser.getMaxDepth() > maxExpressionComplexity)
+ {
+ infoSink.info << "Expression too complex.";
+ return false;
+ }
+ return true;
+}
+
+bool TCompiler::enforceFragmentShaderTimingRestrictions(const TDependencyGraph& graph)
+{
+ RestrictFragmentShaderTiming restrictor(infoSink.info);
+ restrictor.enforceRestrictions(graph);
+ return restrictor.numErrors() == 0;
+}
+
+bool TCompiler::enforceVertexShaderTimingRestrictions(TIntermNode* root)
+{
+ RestrictVertexShaderTiming restrictor(infoSink.info);
+ restrictor.enforceRestrictions(root);
+ return restrictor.numErrors() == 0;
+}
+
+void TCompiler::collectVariables(TIntermNode* root)
+{
+ CollectVariables collect(attribs, uniforms, varyings, hashFunction);
+ root->traverse(&collect);
+}
+
+bool TCompiler::enforcePackingRestrictions()
+{
+ VariablePacker packer;
+ bool success = packer.CheckVariablesWithinPackingLimits(maxUniformVectors, uniforms);
+ if (!success) {
+ infoSink.info.prefix(EPrefixError);
+ infoSink.info << "too many uniforms";
+ return false;
+ }
+
+ success = packer.CheckVariablesWithinPackingLimits(maxVaryingVectors, varyings);
+
+ if (!success) {
+ infoSink.info.prefix(EPrefixError);
+ infoSink.info << "too many varyings";
+ return false;
+ }
+
+ return true;
+}
+
+void TCompiler::initializeGLPosition(TIntermNode* root)
+{
+ InitializeVariables::InitVariableInfoList variables;
+ InitializeVariables::InitVariableInfo var(
+ "gl_Position", TType(EbtFloat, EbpUndefined, EvqPosition, 4));
+ variables.push_back(var);
+ InitializeVariables initializer(variables);
+ root->traverse(&initializer);
+}
+
+void TCompiler::initializeVaryingsWithoutStaticUse(TIntermNode* root)
+{
+ InitializeVariables::InitVariableInfoList variables;
+ for (size_t ii = 0; ii < varyings.size(); ++ii)
+ {
+ const TVariableInfo& varying = varyings[ii];
+ if (varying.staticUse)
+ continue;
+ unsigned char size = 0;
+ bool matrix = false;
+ switch (varying.type)
+ {
+ case SH_FLOAT:
+ size = 1;
+ break;
+ case SH_FLOAT_VEC2:
+ size = 2;
+ break;
+ case SH_FLOAT_VEC3:
+ size = 3;
+ break;
+ case SH_FLOAT_VEC4:
+ size = 4;
+ break;
+ case SH_FLOAT_MAT2:
+ size = 2;
+ matrix = true;
+ break;
+ case SH_FLOAT_MAT3:
+ size = 3;
+ matrix = true;
+ break;
+ case SH_FLOAT_MAT4:
+ size = 4;
+ matrix = true;
+ break;
+ default:
+ ASSERT(false);
+ }
+ TType type(EbtFloat, EbpUndefined, EvqVaryingOut, size, matrix, varying.isArray);
+ TString name = varying.name.c_str();
+ if (varying.isArray)
+ {
+ type.setArraySize(varying.size);
+ name = name.substr(0, name.find_first_of('['));
+ }
+
+ InitializeVariables::InitVariableInfo var(name, type);
+ variables.push_back(var);
+ }
+ InitializeVariables initializer(variables);
+ root->traverse(&initializer);
+}
+
+void TCompiler::mapLongVariableNames(TIntermNode* root)
+{
+ ASSERT(longNameMap);
+ MapLongVariableNames map(longNameMap);
+ root->traverse(&map);
+}
+
+int TCompiler::getMappedNameMaxLength() const
+{
+ return MAX_SHORTENED_IDENTIFIER_SIZE + 1;
+}
+
+const TExtensionBehavior& TCompiler::getExtensionBehavior() const
+{
+ return extensionBehavior;
+}
+
+const ShBuiltInResources& TCompiler::getResources() const
+{
+ return compileResources;
+}
+
+const ArrayBoundsClamper& TCompiler::getArrayBoundsClamper() const
+{
+ return arrayBoundsClamper;
+}
+
+ShArrayIndexClampingStrategy TCompiler::getArrayIndexClampingStrategy() const
+{
+ return clampingStrategy;
+}
+
+const BuiltInFunctionEmulator& TCompiler::getBuiltInFunctionEmulator() const
+{
+ return builtInFunctionEmulator;
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Compiler.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorConstantUnionh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ConstantUnion.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ConstantUnion.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ConstantUnion.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,257 @@
</span><ins>+//
+// Copyright (c) 2002-2013 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 _CONSTANT_UNION_INCLUDED_
+#define _CONSTANT_UNION_INCLUDED_
+
+#include <assert.h>
+
+class ConstantUnion {
+public:
+ POOL_ALLOCATOR_NEW_DELETE();
+ ConstantUnion()
+ {
+ iConst = 0;
+ type = EbtVoid;
+ }
+
+ void setIConst(int i) {iConst = i; type = EbtInt; }
+ void setFConst(float f) {fConst = f; type = EbtFloat; }
+ void setBConst(bool b) {bConst = b; type = EbtBool; }
+
+ int getIConst() { return iConst; }
+ float getFConst() { return fConst; }
+ bool getBConst() { return bConst; }
+ int getIConst() const { return iConst; }
+ float getFConst() const { return fConst; }
+ bool getBConst() const { return bConst; }
+
+ bool operator==(const int i) const
+ {
+ return i == iConst;
+ }
+
+ bool operator==(const float f) const
+ {
+ return f == fConst;
+ }
+
+ bool operator==(const bool b) const
+ {
+ return b == bConst;
+ }
+
+ bool operator==(const ConstantUnion& constant) const
+ {
+ if (constant.type != type)
+ return false;
+
+ switch (type) {
+ case EbtInt:
+ return constant.iConst == iConst;
+ case EbtFloat:
+ return constant.fConst == fConst;
+ case EbtBool:
+ return constant.bConst == bConst;
+ default:
+ return false;
+ }
+ }
+
+ bool operator!=(const int i) const
+ {
+ return !operator==(i);
+ }
+
+ bool operator!=(const float f) const
+ {
+ return !operator==(f);
+ }
+
+ bool operator!=(const bool b) const
+ {
+ return !operator==(b);
+ }
+
+ bool operator!=(const ConstantUnion& constant) const
+ {
+ return !operator==(constant);
+ }
+
+ bool operator>(const ConstantUnion& constant) const
+ {
+ assert(type == constant.type);
+ switch (type) {
+ case EbtInt:
+ return iConst > constant.iConst;
+ case EbtFloat:
+ return fConst > constant.fConst;
+ default:
+ return false; // Invalid operation, handled at semantic analysis
+ }
+ }
+
+ bool operator<(const ConstantUnion& constant) const
+ {
+ assert(type == constant.type);
+ switch (type) {
+ case EbtInt:
+ return iConst < constant.iConst;
+ case EbtFloat:
+ return fConst < constant.fConst;
+ default:
+ return false; // Invalid operation, handled at semantic analysis
+ }
+ }
+
+ ConstantUnion operator+(const ConstantUnion& constant) const
+ {
+ ConstantUnion returnValue;
+ assert(type == constant.type);
+ switch (type) {
+ case EbtInt: returnValue.setIConst(iConst + constant.iConst); break;
+ case EbtFloat: returnValue.setFConst(fConst + constant.fConst); break;
+ default: assert(false && "Default missing");
+ }
+
+ return returnValue;
+ }
+
+ ConstantUnion operator-(const ConstantUnion& constant) const
+ {
+ ConstantUnion returnValue;
+ assert(type == constant.type);
+ switch (type) {
+ case EbtInt: returnValue.setIConst(iConst - constant.iConst); break;
+ case EbtFloat: returnValue.setFConst(fConst - constant.fConst); break;
+ default: assert(false && "Default missing");
+ }
+
+ return returnValue;
+ }
+
+ ConstantUnion operator*(const ConstantUnion& constant) const
+ {
+ ConstantUnion returnValue;
+ assert(type == constant.type);
+ switch (type) {
+ case EbtInt: returnValue.setIConst(iConst * constant.iConst); break;
+ case EbtFloat: returnValue.setFConst(fConst * constant.fConst); break;
+ default: assert(false && "Default missing");
+ }
+
+ return returnValue;
+ }
+
+ ConstantUnion operator%(const ConstantUnion& constant) const
+ {
+ ConstantUnion returnValue;
+ assert(type == constant.type);
+ switch (type) {
+ case EbtInt: returnValue.setIConst(iConst % constant.iConst); break;
+ default: assert(false && "Default missing");
+ }
+
+ return returnValue;
+ }
+
+ ConstantUnion operator>>(const ConstantUnion& constant) const
+ {
+ ConstantUnion returnValue;
+ assert(type == constant.type);
+ switch (type) {
+ case EbtInt: returnValue.setIConst(iConst >> constant.iConst); break;
+ default: assert(false && "Default missing");
+ }
+
+ return returnValue;
+ }
+
+ ConstantUnion operator<<(const ConstantUnion& constant) const
+ {
+ ConstantUnion returnValue;
+ assert(type == constant.type);
+ switch (type) {
+ case EbtInt: returnValue.setIConst(iConst << constant.iConst); break;
+ default: assert(false && "Default missing");
+ }
+
+ return returnValue;
+ }
+
+ ConstantUnion operator&(const ConstantUnion& constant) const
+ {
+ ConstantUnion returnValue;
+ assert(type == constant.type);
+ switch (type) {
+ case EbtInt: returnValue.setIConst(iConst & constant.iConst); break;
+ default: assert(false && "Default missing");
+ }
+
+ return returnValue;
+ }
+
+ ConstantUnion operator|(const ConstantUnion& constant) const
+ {
+ ConstantUnion returnValue;
+ assert(type == constant.type);
+ switch (type) {
+ case EbtInt: returnValue.setIConst(iConst | constant.iConst); break;
+ default: assert(false && "Default missing");
+ }
+
+ return returnValue;
+ }
+
+ ConstantUnion operator^(const ConstantUnion& constant) const
+ {
+ ConstantUnion returnValue;
+ assert(type == constant.type);
+ switch (type) {
+ case EbtInt: returnValue.setIConst(iConst ^ constant.iConst); break;
+ default: assert(false && "Default missing");
+ }
+
+ return returnValue;
+ }
+
+ ConstantUnion operator&&(const ConstantUnion& constant) const
+ {
+ ConstantUnion returnValue;
+ assert(type == constant.type);
+ switch (type) {
+ case EbtBool: returnValue.setBConst(bConst && constant.bConst); break;
+ default: assert(false && "Default missing");
+ }
+
+ return returnValue;
+ }
+
+ ConstantUnion operator||(const ConstantUnion& constant) const
+ {
+ ConstantUnion returnValue;
+ assert(type == constant.type);
+ switch (type) {
+ case EbtBool: returnValue.setBConst(bConst || constant.bConst); break;
+ default: assert(false && "Default missing");
+ }
+
+ return returnValue;
+ }
+
+ TBasicType getType() const { return type; }
+private:
+
+ union {
+ int iConst; // used for ivec, scalar ints
+ bool bConst; // used for bvec, scalar bools
+ float fConst; // used for vec, mat, scalar floats
+ } ;
+
+ TBasicType type;
+};
+
+#endif // _CONSTANT_UNION_INCLUDED_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ConstantUnion.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorDetectCallDepthcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/DetectCallDepth.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/DetectCallDepth.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/DetectCallDepth.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,185 @@
</span><ins>+//
+// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/DetectCallDepth.h"
+#include "compiler/translator/InfoSink.h"
+
+DetectCallDepth::FunctionNode::FunctionNode(const TString& fname)
+ : name(fname),
+ visit(PreVisit)
+{
+}
+
+const TString& DetectCallDepth::FunctionNode::getName() const
+{
+ return name;
+}
+
+void DetectCallDepth::FunctionNode::addCallee(
+ DetectCallDepth::FunctionNode* callee)
+{
+ for (size_t i = 0; i < callees.size(); ++i) {
+ if (callees[i] == callee)
+ return;
+ }
+ callees.push_back(callee);
+}
+
+int DetectCallDepth::FunctionNode::detectCallDepth(DetectCallDepth* detectCallDepth, int depth)
+{
+ ASSERT(visit == PreVisit);
+ ASSERT(detectCallDepth);
+
+ int maxDepth = depth;
+ visit = InVisit;
+ for (size_t i = 0; i < callees.size(); ++i) {
+ switch (callees[i]->visit) {
+ case InVisit:
+ // cycle detected, i.e., recursion detected.
+ return kInfiniteCallDepth;
+ case PostVisit:
+ break;
+ case PreVisit: {
+ // Check before we recurse so we don't go too depth
+ if (detectCallDepth->checkExceedsMaxDepth(depth))
+ return depth;
+ int callDepth = callees[i]->detectCallDepth(detectCallDepth, depth + 1);
+ // Check after we recurse so we can exit immediately and provide info.
+ if (detectCallDepth->checkExceedsMaxDepth(callDepth)) {
+ detectCallDepth->getInfoSink().info << "<-" << callees[i]->getName();
+ return callDepth;
+ }
+ maxDepth = std::max(callDepth, maxDepth);
+ break;
+ }
+ default:
+ UNREACHABLE();
+ break;
+ }
+ }
+ visit = PostVisit;
+ return maxDepth;
+}
+
+void DetectCallDepth::FunctionNode::reset()
+{
+ visit = PreVisit;
+}
+
+DetectCallDepth::DetectCallDepth(TInfoSink& infoSink, bool limitCallStackDepth, int maxCallStackDepth)
+ : TIntermTraverser(true, false, true, false),
+ currentFunction(NULL),
+ infoSink(infoSink),
+ maxDepth(limitCallStackDepth ? maxCallStackDepth : FunctionNode::kInfiniteCallDepth)
+{
+}
+
+DetectCallDepth::~DetectCallDepth()
+{
+ for (size_t i = 0; i < functions.size(); ++i)
+ delete functions[i];
+}
+
+bool DetectCallDepth::visitAggregate(Visit visit, TIntermAggregate* node)
+{
+ switch (node->getOp())
+ {
+ case EOpPrototype:
+ // Function declaration.
+ // Don't add FunctionNode here because node->getName() is the
+ // unmangled function name.
+ break;
+ case EOpFunction: {
+ // Function definition.
+ if (visit == PreVisit) {
+ currentFunction = findFunctionByName(node->getName());
+ if (currentFunction == NULL) {
+ currentFunction = new FunctionNode(node->getName());
+ functions.push_back(currentFunction);
+ }
+ } else if (visit == PostVisit) {
+ currentFunction = NULL;
+ }
+ break;
+ }
+ case EOpFunctionCall: {
+ // Function call.
+ if (visit == PreVisit) {
+ FunctionNode* func = findFunctionByName(node->getName());
+ if (func == NULL) {
+ func = new FunctionNode(node->getName());
+ functions.push_back(func);
+ }
+ if (currentFunction)
+ currentFunction->addCallee(func);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ return true;
+}
+
+bool DetectCallDepth::checkExceedsMaxDepth(int depth)
+{
+ return depth >= maxDepth;
+}
+
+void DetectCallDepth::resetFunctionNodes()
+{
+ for (size_t i = 0; i < functions.size(); ++i) {
+ functions[i]->reset();
+ }
+}
+
+DetectCallDepth::ErrorCode DetectCallDepth::detectCallDepthForFunction(FunctionNode* func)
+{
+ currentFunction = NULL;
+ resetFunctionNodes();
+
+ int maxCallDepth = func->detectCallDepth(this, 1);
+
+ if (maxCallDepth == FunctionNode::kInfiniteCallDepth)
+ return kErrorRecursion;
+
+ if (maxCallDepth >= maxDepth)
+ return kErrorMaxDepthExceeded;
+
+ return kErrorNone;
+}
+
+DetectCallDepth::ErrorCode DetectCallDepth::detectCallDepth()
+{
+ if (maxDepth != FunctionNode::kInfiniteCallDepth) {
+ // Check all functions because the driver may fail on them
+ // TODO: Before detectingRecursion, strip unused functions.
+ for (size_t i = 0; i < functions.size(); ++i) {
+ ErrorCode error = detectCallDepthForFunction(functions[i]);
+ if (error != kErrorNone)
+ return error;
+ }
+ } else {
+ FunctionNode* main = findFunctionByName("main(");
+ if (main == NULL)
+ return kErrorMissingMain;
+
+ return detectCallDepthForFunction(main);
+ }
+
+ return kErrorNone;
+}
+
+DetectCallDepth::FunctionNode* DetectCallDepth::findFunctionByName(
+ const TString& name)
+{
+ for (size_t i = 0; i < functions.size(); ++i) {
+ if (functions[i]->getName() == name)
+ return functions[i];
+ }
+ return NULL;
+}
+
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/DetectCallDepth.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorDetectCallDepthh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/DetectCallDepth.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/DetectCallDepth.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/DetectCallDepth.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,80 @@
</span><ins>+//
+// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_DETECT_RECURSION_H_
+#define COMPILER_DETECT_RECURSION_H_
+
+#include "GLSLANG/ShaderLang.h"
+
+#include <limits.h>
+#include "compiler/translator/intermediate.h"
+#include "compiler/translator/VariableInfo.h"
+
+class TInfoSink;
+
+// Traverses intermediate tree to detect function recursion.
+class DetectCallDepth : public TIntermTraverser {
+public:
+ enum ErrorCode {
+ kErrorMissingMain,
+ kErrorRecursion,
+ kErrorMaxDepthExceeded,
+ kErrorNone
+ };
+
+ DetectCallDepth(TInfoSink& infoSync, bool limitCallStackDepth, int maxCallStackDepth);
+ ~DetectCallDepth();
+
+ virtual bool visitAggregate(Visit, TIntermAggregate*);
+
+ bool checkExceedsMaxDepth(int depth);
+
+ ErrorCode detectCallDepth();
+
+private:
+ class FunctionNode {
+ public:
+ static const int kInfiniteCallDepth = INT_MAX;
+
+ FunctionNode(const TString& fname);
+
+ const TString& getName() const;
+
+ // If a function is already in the callee list, this becomes a no-op.
+ void addCallee(FunctionNode* callee);
+
+ // Returns kInifinityCallDepth if recursive function calls are detected.
+ int detectCallDepth(DetectCallDepth* detectCallDepth, int depth);
+
+ // Reset state.
+ void reset();
+
+ private:
+ // mangled function name is unique.
+ TString name;
+
+ // functions that are directly called by this function.
+ TVector<FunctionNode*> callees;
+
+ Visit visit;
+ };
+
+ ErrorCode detectCallDepthForFunction(FunctionNode* func);
+ FunctionNode* findFunctionByName(const TString& name);
+ void resetFunctionNodes();
+
+ TInfoSink& getInfoSink() { return infoSink; }
+
+ TVector<FunctionNode*> functions;
+ FunctionNode* currentFunction;
+ TInfoSink& infoSink;
+ int maxDepth;
+
+ DetectCallDepth(const DetectCallDepth&);
+ void operator=(const DetectCallDepth&);
+};
+
+#endif // COMPILER_DETECT_RECURSION_H_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/DetectCallDepth.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorDetectDiscontinuitycpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/DetectDiscontinuity.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/DetectDiscontinuity.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/DetectDiscontinuity.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,139 @@
</span><ins>+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Contains analysis utilities for dealing with HLSL's lack of support for
+// the use of intrinsic functions which (implicitly or explicitly) compute
+// gradients of functions with discontinuities.
+//
+
+#include "compiler/translator/DetectDiscontinuity.h"
+
+#include "compiler/translator/ParseContext.h"
+
+namespace sh
+{
+bool DetectLoopDiscontinuity::traverse(TIntermNode *node)
+{
+ mLoopDepth = 0;
+ mLoopDiscontinuity = false;
+ node->traverse(this);
+ return mLoopDiscontinuity;
+}
+
+bool DetectLoopDiscontinuity::visitLoop(Visit visit, TIntermLoop *loop)
+{
+ if (visit == PreVisit)
+ {
+ ++mLoopDepth;
+ }
+ else if (visit == PostVisit)
+ {
+ --mLoopDepth;
+ }
+
+ return true;
+}
+
+bool DetectLoopDiscontinuity::visitBranch(Visit visit, TIntermBranch *node)
+{
+ if (mLoopDiscontinuity)
+ {
+ return false;
+ }
+
+ if (!mLoopDepth)
+ {
+ return true;
+ }
+
+ switch (node->getFlowOp())
+ {
+ case EOpKill:
+ break;
+ case EOpBreak:
+ case EOpContinue:
+ case EOpReturn:
+ mLoopDiscontinuity = true;
+ break;
+ default: UNREACHABLE();
+ }
+
+ return !mLoopDiscontinuity;
+}
+
+bool DetectLoopDiscontinuity::visitAggregate(Visit visit, TIntermAggregate *node)
+{
+ return !mLoopDiscontinuity;
+}
+
+bool containsLoopDiscontinuity(TIntermNode *node)
+{
+ DetectLoopDiscontinuity detectLoopDiscontinuity;
+ return detectLoopDiscontinuity.traverse(node);
+}
+
+bool DetectGradientOperation::traverse(TIntermNode *node)
+{
+ mGradientOperation = false;
+ node->traverse(this);
+ return mGradientOperation;
+}
+
+bool DetectGradientOperation::visitUnary(Visit visit, TIntermUnary *node)
+{
+ if (mGradientOperation)
+ {
+ return false;
+ }
+
+ switch (node->getOp())
+ {
+ case EOpDFdx:
+ case EOpDFdy:
+ mGradientOperation = true;
+ default:
+ break;
+ }
+
+ return !mGradientOperation;
+}
+
+bool DetectGradientOperation::visitAggregate(Visit visit, TIntermAggregate *node)
+{
+ if (mGradientOperation)
+ {
+ return false;
+ }
+
+ if (node->getOp() == EOpFunctionCall)
+ {
+ if (!node->isUserDefined())
+ {
+ TString name = TFunction::unmangleName(node->getName());
+
+ if (name == "texture2D" ||
+ name == "texture2DProj" ||
+ name == "textureCube")
+ {
+ mGradientOperation = true;
+ }
+ }
+ else
+ {
+ // When a user defined function is called, we have to
+ // conservatively assume it to contain gradient operations
+ mGradientOperation = true;
+ }
+ }
+
+ return !mGradientOperation;
+}
+
+bool containsGradientOperation(TIntermNode *node)
+{
+ DetectGradientOperation detectGradientOperation;
+ return detectGradientOperation.traverse(node);
+}
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/DetectDiscontinuity.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorDetectDiscontinuityh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/DetectDiscontinuity.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/DetectDiscontinuity.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/DetectDiscontinuity.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,52 @@
</span><ins>+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Contains analysis utilities for dealing with HLSL's lack of support for
+// the use of intrinsic functions which (implicitly or explicitly) compute
+// gradients of functions with discontinuities.
+//
+
+#ifndef COMPILER_DETECTDISCONTINUITY_H_
+#define COMPILER_DETECTDISCONTINUITY_H_
+
+#include "compiler/translator/intermediate.h"
+
+namespace sh
+{
+// Checks whether a loop can run for a variable number of iterations
+class DetectLoopDiscontinuity : public TIntermTraverser
+{
+ public:
+ bool traverse(TIntermNode *node);
+
+ protected:
+ bool visitBranch(Visit visit, TIntermBranch *node);
+ bool visitLoop(Visit visit, TIntermLoop *loop);
+ bool visitAggregate(Visit visit, TIntermAggregate *node);
+
+ int mLoopDepth;
+ bool mLoopDiscontinuity;
+};
+
+bool containsLoopDiscontinuity(TIntermNode *node);
+
+// Checks for intrinsic functions which compute gradients
+class DetectGradientOperation : public TIntermTraverser
+{
+ public:
+ bool traverse(TIntermNode *node);
+
+ protected:
+ bool visitUnary(Visit visit, TIntermUnary *node);
+ bool visitAggregate(Visit visit, TIntermAggregate *node);
+
+ bool mGradientOperation;
+};
+
+bool containsGradientOperation(TIntermNode *node);
+
+}
+
+#endif // COMPILER_DETECTDISCONTINUITY_H_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/DetectDiscontinuity.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorDiagnosticscpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Diagnostics.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Diagnostics.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Diagnostics.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,63 @@
</span><ins>+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/Diagnostics.h"
+
+#include "compiler/translator/compilerdebug.h"
+#include "compiler/translator/InfoSink.h"
+#include "compiler/preprocessor/SourceLocation.h"
+
+TDiagnostics::TDiagnostics(TInfoSink& infoSink) :
+ mInfoSink(infoSink),
+ mNumErrors(0),
+ mNumWarnings(0)
+{
+}
+
+TDiagnostics::~TDiagnostics()
+{
+}
+
+void TDiagnostics::writeInfo(Severity severity,
+ const pp::SourceLocation& loc,
+ const std::string& reason,
+ const std::string& token,
+ const std::string& extra)
+{
+ TPrefixType prefix = EPrefixNone;
+ switch (severity)
+ {
+ case PP_ERROR:
+ ++mNumErrors;
+ prefix = EPrefixError;
+ break;
+ case PP_WARNING:
+ ++mNumWarnings;
+ prefix = EPrefixWarning;
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ TInfoSinkBase& sink = mInfoSink.info;
+ /* VC++ format: file(linenum) : error #: 'token' : extrainfo */
+ sink.prefix(prefix);
+ sink.location(loc.file, loc.line);
+ sink << "'" << token << "' : " << reason << " " << extra << "\n";
+}
+
+void TDiagnostics::writeDebug(const std::string& str)
+{
+ mInfoSink.debug << str;
+}
+
+void TDiagnostics::print(ID id,
+ const pp::SourceLocation& loc,
+ const std::string& text)
+{
+ writeInfo(severity(id), loc, message(id), text, "");
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Diagnostics.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorDiagnosticsh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Diagnostics.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Diagnostics.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Diagnostics.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,44 @@
</span><ins>+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_DIAGNOSTICS_H_
+#define COMPILER_DIAGNOSTICS_H_
+
+#include "compiler/preprocessor/DiagnosticsBase.h"
+
+class TInfoSink;
+
+class TDiagnostics : public pp::Diagnostics
+{
+ public:
+ TDiagnostics(TInfoSink& infoSink);
+ virtual ~TDiagnostics();
+
+ TInfoSink& infoSink() { return mInfoSink; }
+
+ int numErrors() const { return mNumErrors; }
+ int numWarnings() const { return mNumWarnings; }
+
+ void writeInfo(Severity severity,
+ const pp::SourceLocation& loc,
+ const std::string& reason,
+ const std::string& token,
+ const std::string& extra);
+
+ void writeDebug(const std::string& str);
+
+ protected:
+ virtual void print(ID id,
+ const pp::SourceLocation& loc,
+ const std::string& text);
+
+ private:
+ TInfoSink& mInfoSink;
+ int mNumErrors;
+ int mNumWarnings;
+};
+
+#endif // COMPILER_DIAGNOSTICS_H_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Diagnostics.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorDirectiveHandlercpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/DirectiveHandler.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/DirectiveHandler.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/DirectiveHandler.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,161 @@
</span><ins>+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/DirectiveHandler.h"
+
+#include <sstream>
+
+#include "compiler/translator/compilerdebug.h"
+#include "compiler/translator/Diagnostics.h"
+
+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");
+
+ if (str == kRequire) return EBhRequire;
+ else if (str == kEnable) return EBhEnable;
+ else if (str == kDisable) return EBhDisable;
+ else if (str == kWarn) return EBhWarn;
+ return EBhUndefined;
+}
+
+TDirectiveHandler::TDirectiveHandler(TExtensionBehavior& extBehavior,
+ TDiagnostics& diagnostics)
+ : mExtensionBehavior(extBehavior),
+ mDiagnostics(diagnostics)
+{
+}
+
+TDirectiveHandler::~TDirectiveHandler()
+{
+}
+
+void TDirectiveHandler::handleError(const pp::SourceLocation& loc,
+ const std::string& msg)
+{
+ mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc, msg, "", "");
+}
+
+void TDirectiveHandler::handlePragma(const pp::SourceLocation& loc,
+ const std::string& name,
+ const std::string& value)
+{
+ 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");
+
+ bool invalidValue = false;
+ if (name == kSTDGL)
+ {
+ // The STDGL pragma is used to reserve pragmas for use by future
+ // revisions of GLSL. Ignore it.
+ 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;
+ }
+
+ 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");
+
+ TBehavior behaviorVal = getBehavior(behavior);
+ if (behaviorVal == EBhUndefined)
+ {
+ mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc,
+ "behavior", name, "invalid");
+ return;
+ }
+
+ if (name == kExtAll)
+ {
+ if (behaviorVal == EBhRequire)
+ {
+ mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc,
+ "extension", name,
+ "cannot have 'require' behavior");
+ }
+ else if (behaviorVal == EBhEnable)
+ {
+ mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc,
+ "extension", name,
+ "cannot have 'enable' behavior");
+ }
+ else
+ {
+ for (TExtensionBehavior::iterator iter = mExtensionBehavior.begin();
+ iter != mExtensionBehavior.end(); ++iter)
+ iter->second = behaviorVal;
+ }
+ return;
+ }
+
+ TExtensionBehavior::iterator iter = mExtensionBehavior.find(name);
+ if (iter != mExtensionBehavior.end())
+ {
+ iter->second = behaviorVal;
+ return;
+ }
+
+ pp::Diagnostics::Severity severity = pp::Diagnostics::PP_ERROR;
+ switch (behaviorVal) {
+ case EBhRequire:
+ severity = pp::Diagnostics::PP_ERROR;
+ break;
+ case EBhEnable:
+ case EBhWarn:
+ case EBhDisable:
+ severity = pp::Diagnostics::PP_WARNING;
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ mDiagnostics.writeInfo(severity, loc,
+ "extension", name, "is not supported");
+}
+
+void TDirectiveHandler::handleVersion(const pp::SourceLocation& loc,
+ int version)
+{
+ static const int kVersion = 100;
+
+ if (version != kVersion)
+ {
+ std::stringstream stream;
+ stream << version;
+ std::string str = stream.str();
+ mDiagnostics.writeInfo(pp::Diagnostics::PP_ERROR, loc,
+ "version number", str, "not supported");
+ }
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/DirectiveHandler.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorDirectiveHandlerh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/DirectiveHandler.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/DirectiveHandler.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/DirectiveHandler.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,46 @@
</span><ins>+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_DIRECTIVE_HANDLER_H_
+#define COMPILER_DIRECTIVE_HANDLER_H_
+
+#include "compiler/translator/ExtensionBehavior.h"
+#include "compiler/translator/Pragma.h"
+#include "compiler/preprocessor/DirectiveHandlerBase.h"
+
+class TDiagnostics;
+
+class TDirectiveHandler : public pp::DirectiveHandler
+{
+ public:
+ TDirectiveHandler(TExtensionBehavior& extBehavior,
+ TDiagnostics& diagnostics);
+ virtual ~TDirectiveHandler();
+
+ const TPragma& pragma() const { return mPragma; }
+ const TExtensionBehavior& extensionBehavior() const { return mExtensionBehavior; }
+
+ virtual void handleError(const pp::SourceLocation& loc,
+ const std::string& msg);
+
+ virtual void handlePragma(const pp::SourceLocation& loc,
+ const std::string& name,
+ const std::string& value);
+
+ virtual void handleExtension(const pp::SourceLocation& loc,
+ const std::string& name,
+ const std::string& behavior);
+
+ virtual void handleVersion(const pp::SourceLocation& loc,
+ int version);
+
+ private:
+ TPragma mPragma;
+ TExtensionBehavior& mExtensionBehavior;
+ TDiagnostics& mDiagnostics;
+};
+
+#endif // COMPILER_DIRECTIVE_HANDLER_H_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/DirectiveHandler.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorExtensionBehaviorh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ExtensionBehavior.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ExtensionBehavior.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ExtensionBehavior.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,37 @@
</span><ins>+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef _EXTENSION_BEHAVIOR_INCLUDED_
+#define _EXTENSION_BEHAVIOR_INCLUDED_
+
+#include <map>
+#include <string>
+
+typedef enum
+{
+ EBhRequire,
+ EBhEnable,
+ EBhWarn,
+ EBhDisable,
+ EBhUndefined
+} TBehavior;
+
+inline const char* getBehaviorString(TBehavior b)
+{
+ switch(b)
+ {
+ case EBhRequire: return "require";
+ case EBhEnable: return "enable";
+ case EBhWarn: return "warn";
+ case EBhDisable: return "disable";
+ default: return NULL;
+ }
+}
+
+// Mapping between extension name and behavior.
+typedef std::map<std::string, TBehavior> TExtensionBehavior;
+
+#endif // _EXTENSION_TABLE_INCLUDED_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ExtensionBehavior.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorForLoopUnrollcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ForLoopUnroll.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ForLoopUnroll.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ForLoopUnroll.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,215 @@
</span><ins>+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/ForLoopUnroll.h"
+
+namespace {
+
+class IntegerForLoopUnrollMarker : public TIntermTraverser {
+public:
+
+ virtual bool visitLoop(Visit, TIntermLoop* node)
+ {
+ // This is called after ValidateLimitations pass, so all the ASSERT
+ // should never fail.
+ // See ValidateLimitations::validateForLoopInit().
+ ASSERT(node);
+ ASSERT(node->getType() == ELoopFor);
+ ASSERT(node->getInit());
+ TIntermAggregate* decl = node->getInit()->getAsAggregate();
+ ASSERT(decl && decl->getOp() == EOpDeclaration);
+ TIntermSequence& declSeq = decl->getSequence();
+ ASSERT(declSeq.size() == 1);
+ TIntermBinary* declInit = declSeq[0]->getAsBinaryNode();
+ ASSERT(declInit && declInit->getOp() == EOpInitialize);
+ ASSERT(declInit->getLeft());
+ TIntermSymbol* symbol = declInit->getLeft()->getAsSymbolNode();
+ ASSERT(symbol);
+ TBasicType type = symbol->getBasicType();
+ ASSERT(type == EbtInt || type == EbtFloat);
+ if (type == EbtInt)
+ node->setUnrollFlag(true);
+ return true;
+ }
+
+};
+
+} // anonymous namepsace
+
+void ForLoopUnroll::FillLoopIndexInfo(TIntermLoop* node, TLoopIndexInfo& info)
+{
+ ASSERT(node->getType() == ELoopFor);
+ ASSERT(node->getUnrollFlag());
+
+ TIntermNode* init = node->getInit();
+ ASSERT(init != NULL);
+ TIntermAggregate* decl = init->getAsAggregate();
+ ASSERT((decl != NULL) && (decl->getOp() == EOpDeclaration));
+ TIntermSequence& declSeq = decl->getSequence();
+ ASSERT(declSeq.size() == 1);
+ TIntermBinary* declInit = declSeq[0]->getAsBinaryNode();
+ ASSERT((declInit != NULL) && (declInit->getOp() == EOpInitialize));
+ TIntermSymbol* symbol = declInit->getLeft()->getAsSymbolNode();
+ ASSERT(symbol != NULL);
+ ASSERT(symbol->getBasicType() == EbtInt);
+
+ info.id = symbol->getId();
+
+ ASSERT(declInit->getRight() != NULL);
+ TIntermConstantUnion* initNode = declInit->getRight()->getAsConstantUnion();
+ ASSERT(initNode != NULL);
+
+ info.initValue = evaluateIntConstant(initNode);
+ info.currentValue = info.initValue;
+
+ TIntermNode* cond = node->getCondition();
+ ASSERT(cond != NULL);
+ TIntermBinary* binOp = cond->getAsBinaryNode();
+ ASSERT(binOp != NULL);
+ ASSERT(binOp->getRight() != NULL);
+ ASSERT(binOp->getRight()->getAsConstantUnion() != NULL);
+
+ info.incrementValue = getLoopIncrement(node);
+ info.stopValue = evaluateIntConstant(
+ binOp->getRight()->getAsConstantUnion());
+ info.op = binOp->getOp();
+}
+
+void ForLoopUnroll::Step()
+{
+ ASSERT(mLoopIndexStack.size() > 0);
+ TLoopIndexInfo& info = mLoopIndexStack[mLoopIndexStack.size() - 1];
+ info.currentValue += info.incrementValue;
+}
+
+bool ForLoopUnroll::SatisfiesLoopCondition()
+{
+ ASSERT(mLoopIndexStack.size() > 0);
+ TLoopIndexInfo& info = mLoopIndexStack[mLoopIndexStack.size() - 1];
+ // Relational operator is one of: > >= < <= == or !=.
+ switch (info.op) {
+ case EOpEqual:
+ return (info.currentValue == info.stopValue);
+ case EOpNotEqual:
+ return (info.currentValue != info.stopValue);
+ case EOpLessThan:
+ return (info.currentValue < info.stopValue);
+ case EOpGreaterThan:
+ return (info.currentValue > info.stopValue);
+ case EOpLessThanEqual:
+ return (info.currentValue <= info.stopValue);
+ case EOpGreaterThanEqual:
+ return (info.currentValue >= info.stopValue);
+ default:
+ UNREACHABLE();
+ }
+ return false;
+}
+
+bool ForLoopUnroll::NeedsToReplaceSymbolWithValue(TIntermSymbol* symbol)
+{
+ for (TVector<TLoopIndexInfo>::iterator i = mLoopIndexStack.begin();
+ i != mLoopIndexStack.end();
+ ++i) {
+ if (i->id == symbol->getId())
+ return true;
+ }
+ return false;
+}
+
+int ForLoopUnroll::GetLoopIndexValue(TIntermSymbol* symbol)
+{
+ for (TVector<TLoopIndexInfo>::iterator i = mLoopIndexStack.begin();
+ i != mLoopIndexStack.end();
+ ++i) {
+ if (i->id == symbol->getId())
+ return i->currentValue;
+ }
+ UNREACHABLE();
+ return false;
+}
+
+void ForLoopUnroll::Push(TLoopIndexInfo& info)
+{
+ mLoopIndexStack.push_back(info);
+}
+
+void ForLoopUnroll::Pop()
+{
+ mLoopIndexStack.pop_back();
+}
+
+// static
+void ForLoopUnroll::MarkForLoopsWithIntegerIndicesForUnrolling(
+ TIntermNode* root)
+{
+ ASSERT(root);
+
+ IntegerForLoopUnrollMarker marker;
+ root->traverse(&marker);
+}
+
+int ForLoopUnroll::getLoopIncrement(TIntermLoop* node)
+{
+ TIntermNode* expr = node->getExpression();
+ ASSERT(expr != NULL);
+ // for expression has one of the following forms:
+ // loop_index++
+ // loop_index--
+ // loop_index += constant_expression
+ // loop_index -= constant_expression
+ // ++loop_index
+ // --loop_index
+ // The last two forms are not specified in the spec, but I am assuming
+ // its an oversight.
+ TIntermUnary* unOp = expr->getAsUnaryNode();
+ TIntermBinary* binOp = unOp ? NULL : expr->getAsBinaryNode();
+
+ TOperator op = EOpNull;
+ TIntermConstantUnion* incrementNode = NULL;
+ if (unOp != NULL) {
+ op = unOp->getOp();
+ } else if (binOp != NULL) {
+ op = binOp->getOp();
+ ASSERT(binOp->getRight() != NULL);
+ incrementNode = binOp->getRight()->getAsConstantUnion();
+ ASSERT(incrementNode != NULL);
+ }
+
+ int increment = 0;
+ // The operator is one of: ++ -- += -=.
+ switch (op) {
+ case EOpPostIncrement:
+ case EOpPreIncrement:
+ ASSERT((unOp != NULL) && (binOp == NULL));
+ increment = 1;
+ break;
+ case EOpPostDecrement:
+ case EOpPreDecrement:
+ ASSERT((unOp != NULL) && (binOp == NULL));
+ increment = -1;
+ break;
+ case EOpAddAssign:
+ ASSERT((unOp == NULL) && (binOp != NULL));
+ increment = evaluateIntConstant(incrementNode);
+ break;
+ case EOpSubAssign:
+ ASSERT((unOp == NULL) && (binOp != NULL));
+ increment = - evaluateIntConstant(incrementNode);
+ break;
+ default:
+ ASSERT(false);
+ }
+
+ return increment;
+}
+
+int ForLoopUnroll::evaluateIntConstant(TIntermConstantUnion* node)
+{
+ ASSERT((node != NULL) && (node->getUnionArrayPointer() != NULL));
+ return node->getIConst(0);
+}
+
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ForLoopUnroll.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorForLoopUnrollh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ForLoopUnroll.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ForLoopUnroll.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ForLoopUnroll.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,52 @@
</span><ins>+//
+// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_FORLOOPUNROLL_H_
+#define COMPILER_FORLOOPUNROLL_H_
+
+#include "compiler/translator/intermediate.h"
+
+struct TLoopIndexInfo {
+ int id;
+ int initValue;
+ int stopValue;
+ int incrementValue;
+ TOperator op;
+ int currentValue;
+};
+
+class ForLoopUnroll {
+public:
+ ForLoopUnroll() { }
+
+ void FillLoopIndexInfo(TIntermLoop* node, TLoopIndexInfo& info);
+
+ // Update the info.currentValue for the next loop iteration.
+ void Step();
+
+ // Return false if loop condition is no longer satisfied.
+ bool SatisfiesLoopCondition();
+
+ // Check if the symbol is the index of a loop that's unrolled.
+ bool NeedsToReplaceSymbolWithValue(TIntermSymbol* symbol);
+
+ // Return the current value of a given loop index symbol.
+ int GetLoopIndexValue(TIntermSymbol* symbol);
+
+ void Push(TLoopIndexInfo& info);
+ void Pop();
+
+ static void MarkForLoopsWithIntegerIndicesForUnrolling(TIntermNode* root);
+
+private:
+ int getLoopIncrement(TIntermLoop* node);
+
+ int evaluateIntConstant(TIntermConstantUnion* node);
+
+ TVector<TLoopIndexInfo> mLoopIndexStack;
+};
+
+#endif
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ForLoopUnroll.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorHashNamesh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/HashNames.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/HashNames.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/HashNames.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,19 @@
</span><ins>+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_HASH_NAMES_H_
+#define COMPILER_HASH_NAMES_H_
+
+#include <map>
+
+#include "compiler/translator/intermediate.h"
+#include "GLSLANG/ShaderLang.h"
+
+#define HASHED_NAME_PREFIX "webgl_"
+
+typedef std::map<TPersistString, TPersistString> NameMap;
+
+#endif // COMPILER_HASH_NAMES_H_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/HashNames.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorInfoSinkcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/InfoSink.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/InfoSink.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/InfoSink.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,54 @@
</span><ins>+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/InfoSink.h"
+
+void TInfoSinkBase::prefix(TPrefixType p) {
+ switch(p) {
+ case EPrefixNone:
+ break;
+ case EPrefixWarning:
+ sink.append("WARNING: ");
+ break;
+ case EPrefixError:
+ sink.append("ERROR: ");
+ break;
+ case EPrefixInternalError:
+ sink.append("INTERNAL ERROR: ");
+ break;
+ case EPrefixUnimplemented:
+ sink.append("UNIMPLEMENTED: ");
+ break;
+ case EPrefixNote:
+ sink.append("NOTE: ");
+ break;
+ default:
+ sink.append("UNKOWN ERROR: ");
+ break;
+ }
+}
+
+void TInfoSinkBase::location(int file, int line) {
+ TPersistStringStream stream;
+ if (line)
+ stream << file << ":" << line;
+ else
+ stream << file << ":? ";
+ stream << ": ";
+
+ sink.append(stream.str());
+}
+
+void TInfoSinkBase::location(const TSourceLoc& loc) {
+ location(loc.first_file, loc.first_line);
+}
+
+void TInfoSinkBase::message(TPrefixType p, const TSourceLoc& loc, const char* m) {
+ prefix(p);
+ location(loc);
+ sink.append(m);
+ sink.append("\n");
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/InfoSink.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorInfoSinkh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/InfoSink.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/InfoSink.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/InfoSink.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,116 @@
</span><ins>+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef _INFOSINK_INCLUDED_
+#define _INFOSINK_INCLUDED_
+
+#include <math.h>
+#include <stdlib.h>
+#include "compiler/translator/Common.h"
+
+// Returns the fractional part of the given floating-point number.
+inline float fractionalPart(float f) {
+ float intPart = 0.0f;
+ return modff(f, &intPart);
+}
+
+//
+// TPrefixType is used to centralize how info log messages start.
+// See below.
+//
+enum TPrefixType {
+ EPrefixNone,
+ EPrefixWarning,
+ EPrefixError,
+ EPrefixInternalError,
+ EPrefixUnimplemented,
+ EPrefixNote
+};
+
+//
+// Encapsulate info logs for all objects that have them.
+//
+// The methods are a general set of tools for getting a variety of
+// messages and types inserted into the log.
+//
+class TInfoSinkBase {
+public:
+ TInfoSinkBase() {}
+
+ template <typename T>
+ TInfoSinkBase& operator<<(const T& t) {
+ TPersistStringStream stream;
+ stream << t;
+ sink.append(stream.str());
+ return *this;
+ }
+ // Override << operator for specific types. It is faster to append strings
+ // and characters directly to the sink.
+ TInfoSinkBase& operator<<(char c) {
+ sink.append(1, c);
+ return *this;
+ }
+ TInfoSinkBase& operator<<(const char* str) {
+ sink.append(str);
+ return *this;
+ }
+ TInfoSinkBase& operator<<(const TPersistString& str) {
+ sink.append(str);
+ return *this;
+ }
+ TInfoSinkBase& operator<<(const TString& str) {
+ sink.append(str.c_str());
+ return *this;
+ }
+ // Make sure floats are written with correct precision.
+ TInfoSinkBase& operator<<(float f) {
+ // Make sure that at least one decimal point is written. If a number
+ // does not have a fractional part, the default precision format does
+ // not write the decimal portion which gets interpreted as integer by
+ // the compiler.
+ TPersistStringStream stream;
+ if (fractionalPart(f) == 0.0f) {
+ stream.precision(1);
+ stream << std::showpoint << std::fixed << f;
+ } else {
+ stream.unsetf(std::ios::fixed);
+ stream.unsetf(std::ios::scientific);
+ stream.precision(8);
+ stream << f;
+ }
+ sink.append(stream.str());
+ return *this;
+ }
+ // Write boolean values as their names instead of integral value.
+ TInfoSinkBase& operator<<(bool b) {
+ const char* str = b ? "true" : "false";
+ sink.append(str);
+ return *this;
+ }
+
+ void erase() { sink.clear(); }
+ int size() { return static_cast<int>(sink.size()); }
+
+ const TPersistString& str() const { return sink; }
+ const char* c_str() const { return sink.c_str(); }
+
+ void prefix(TPrefixType p);
+ void location(int file, int line);
+ void location(const TSourceLoc& loc);
+ void message(TPrefixType p, const TSourceLoc& loc, const char* m);
+
+private:
+ TPersistString sink;
+};
+
+class TInfoSink {
+public:
+ TInfoSinkBase info;
+ TInfoSinkBase debug;
+ TInfoSinkBase obj;
+};
+
+#endif // _INFOSINK_INCLUDED_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/InfoSink.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorInitializecpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Initialize.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Initialize.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Initialize.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,564 @@
</span><ins>+//
+// Copyright (c) 2002-2013 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.
+//
+
+//
+// Create strings that declare built-in definitions, add built-ins that
+// cannot be expressed in the files, and establish mappings between
+// built-in functions and operators.
+//
+
+#include "compiler/translator/Initialize.h"
+
+#include "compiler/translator/intermediate.h"
+
+void InsertBuiltInFunctions(ShShaderType type, ShShaderSpec spec, const ShBuiltInResources &resources, TSymbolTable &symbolTable)
+{
+ TType *float1 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 1);
+ TType *float2 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 2);
+ TType *float3 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 3);
+ TType *float4 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 4);
+
+ TType *int2 = new TType(EbtInt, EbpUndefined, EvqGlobal, 2);
+ TType *int3 = new TType(EbtInt, EbpUndefined, EvqGlobal, 3);
+ TType *int4 = new TType(EbtInt, EbpUndefined, EvqGlobal, 4);
+
+ //
+ // Angle and Trigonometric Functions.
+ //
+ symbolTable.insertBuiltIn(float1, "radians", float1);
+ symbolTable.insertBuiltIn(float2, "radians", float2);
+ symbolTable.insertBuiltIn(float3, "radians", float3);
+ symbolTable.insertBuiltIn(float4, "radians", float4);
+
+ symbolTable.insertBuiltIn(float1, "degrees", float1);
+ symbolTable.insertBuiltIn(float2, "degrees", float2);
+ symbolTable.insertBuiltIn(float3, "degrees", float3);
+ symbolTable.insertBuiltIn(float4, "degrees", float4);
+
+ symbolTable.insertBuiltIn(float1, "sin", float1);
+ symbolTable.insertBuiltIn(float2, "sin", float2);
+ symbolTable.insertBuiltIn(float3, "sin", float3);
+ symbolTable.insertBuiltIn(float4, "sin", float4);
+
+ symbolTable.insertBuiltIn(float1, "cos", float1);
+ symbolTable.insertBuiltIn(float2, "cos", float2);
+ symbolTable.insertBuiltIn(float3, "cos", float3);
+ symbolTable.insertBuiltIn(float4, "cos", float4);
+
+ symbolTable.insertBuiltIn(float1, "tan", float1);
+ symbolTable.insertBuiltIn(float2, "tan", float2);
+ symbolTable.insertBuiltIn(float3, "tan", float3);
+ symbolTable.insertBuiltIn(float4, "tan", float4);
+
+ symbolTable.insertBuiltIn(float1, "asin", float1);
+ symbolTable.insertBuiltIn(float2, "asin", float2);
+ symbolTable.insertBuiltIn(float3, "asin", float3);
+ symbolTable.insertBuiltIn(float4, "asin", float4);
+
+ symbolTable.insertBuiltIn(float1, "acos", float1);
+ symbolTable.insertBuiltIn(float2, "acos", float2);
+ symbolTable.insertBuiltIn(float3, "acos", float3);
+ symbolTable.insertBuiltIn(float4, "acos", float4);
+
+ symbolTable.insertBuiltIn(float1, "atan", float1, float1);
+ symbolTable.insertBuiltIn(float2, "atan", float2, float2);
+ symbolTable.insertBuiltIn(float3, "atan", float3, float3);
+ symbolTable.insertBuiltIn(float4, "atan", float4, float4);
+
+ symbolTable.insertBuiltIn(float1, "atan", float1);
+ symbolTable.insertBuiltIn(float2, "atan", float2);
+ symbolTable.insertBuiltIn(float3, "atan", float3);
+ symbolTable.insertBuiltIn(float4, "atan", float4);
+
+ //
+ // Exponential Functions.
+ //
+ symbolTable.insertBuiltIn(float1, "pow", float1, float1);
+ symbolTable.insertBuiltIn(float2, "pow", float2, float2);
+ symbolTable.insertBuiltIn(float3, "pow", float3, float3);
+ symbolTable.insertBuiltIn(float4, "pow", float4, float4);
+
+ symbolTable.insertBuiltIn(float1, "exp", float1);
+ symbolTable.insertBuiltIn(float2, "exp", float2);
+ symbolTable.insertBuiltIn(float3, "exp", float3);
+ symbolTable.insertBuiltIn(float4, "exp", float4);
+
+ symbolTable.insertBuiltIn(float1, "log", float1);
+ symbolTable.insertBuiltIn(float2, "log", float2);
+ symbolTable.insertBuiltIn(float3, "log", float3);
+ symbolTable.insertBuiltIn(float4, "log", float4);
+
+ symbolTable.insertBuiltIn(float1, "exp2", float1);
+ symbolTable.insertBuiltIn(float2, "exp2", float2);
+ symbolTable.insertBuiltIn(float3, "exp2", float3);
+ symbolTable.insertBuiltIn(float4, "exp2", float4);
+
+ symbolTable.insertBuiltIn(float1, "log2", float1);
+ symbolTable.insertBuiltIn(float2, "log2", float2);
+ symbolTable.insertBuiltIn(float3, "log2", float3);
+ symbolTable.insertBuiltIn(float4, "log2", float4);
+
+ symbolTable.insertBuiltIn(float1, "sqrt", float1);
+ symbolTable.insertBuiltIn(float2, "sqrt", float2);
+ symbolTable.insertBuiltIn(float3, "sqrt", float3);
+ symbolTable.insertBuiltIn(float4, "sqrt", float4);
+
+ symbolTable.insertBuiltIn(float1, "inversesqrt", float1);
+ symbolTable.insertBuiltIn(float2, "inversesqrt", float2);
+ symbolTable.insertBuiltIn(float3, "inversesqrt", float3);
+ symbolTable.insertBuiltIn(float4, "inversesqrt", float4);
+
+ //
+ // Common Functions.
+ //
+ symbolTable.insertBuiltIn(float1, "abs", float1);
+ symbolTable.insertBuiltIn(float2, "abs", float2);
+ symbolTable.insertBuiltIn(float3, "abs", float3);
+ symbolTable.insertBuiltIn(float4, "abs", float4);
+
+ symbolTable.insertBuiltIn(float1, "sign", float1);
+ symbolTable.insertBuiltIn(float2, "sign", float2);
+ symbolTable.insertBuiltIn(float3, "sign", float3);
+ symbolTable.insertBuiltIn(float4, "sign", float4);
+
+ symbolTable.insertBuiltIn(float1, "floor", float1);
+ symbolTable.insertBuiltIn(float2, "floor", float2);
+ symbolTable.insertBuiltIn(float3, "floor", float3);
+ symbolTable.insertBuiltIn(float4, "floor", float4);
+
+ symbolTable.insertBuiltIn(float1, "ceil", float1);
+ symbolTable.insertBuiltIn(float2, "ceil", float2);
+ symbolTable.insertBuiltIn(float3, "ceil", float3);
+ symbolTable.insertBuiltIn(float4, "ceil", float4);
+
+ symbolTable.insertBuiltIn(float1, "fract", float1);
+ symbolTable.insertBuiltIn(float2, "fract", float2);
+ symbolTable.insertBuiltIn(float3, "fract", float3);
+ symbolTable.insertBuiltIn(float4, "fract", float4);
+
+ symbolTable.insertBuiltIn(float1, "mod", float1, float1);
+ symbolTable.insertBuiltIn(float2, "mod", float2, float1);
+ symbolTable.insertBuiltIn(float3, "mod", float3, float1);
+ symbolTable.insertBuiltIn(float4, "mod", float4, float1);
+ symbolTable.insertBuiltIn(float2, "mod", float2, float2);
+ symbolTable.insertBuiltIn(float3, "mod", float3, float3);
+ symbolTable.insertBuiltIn(float4, "mod", float4, float4);
+
+ symbolTable.insertBuiltIn(float1, "min", float1, float1);
+ symbolTable.insertBuiltIn(float2, "min", float2, float1);
+ symbolTable.insertBuiltIn(float3, "min", float3, float1);
+ symbolTable.insertBuiltIn(float4, "min", float4, float1);
+ symbolTable.insertBuiltIn(float2, "min", float2, float2);
+ symbolTable.insertBuiltIn(float3, "min", float3, float3);
+ symbolTable.insertBuiltIn(float4, "min", float4, float4);
+
+ symbolTable.insertBuiltIn(float1, "max", float1, float1);
+ symbolTable.insertBuiltIn(float2, "max", float2, float1);
+ symbolTable.insertBuiltIn(float3, "max", float3, float1);
+ symbolTable.insertBuiltIn(float4, "max", float4, float1);
+ symbolTable.insertBuiltIn(float2, "max", float2, float2);
+ symbolTable.insertBuiltIn(float3, "max", float3, float3);
+ symbolTable.insertBuiltIn(float4, "max", float4, float4);
+
+ symbolTable.insertBuiltIn(float1, "clamp", float1, float1, float1);
+ symbolTable.insertBuiltIn(float2, "clamp", float2, float1, float1);
+ symbolTable.insertBuiltIn(float3, "clamp", float3, float1, float1);
+ symbolTable.insertBuiltIn(float4, "clamp", float4, float1, float1);
+ symbolTable.insertBuiltIn(float2, "clamp", float2, float2, float2);
+ symbolTable.insertBuiltIn(float3, "clamp", float3, float3, float3);
+ symbolTable.insertBuiltIn(float4, "clamp", float4, float4, float4);
+
+ symbolTable.insertBuiltIn(float1, "mix", float1, float1, float1);
+ symbolTable.insertBuiltIn(float2, "mix", float2, float2, float1);
+ symbolTable.insertBuiltIn(float3, "mix", float3, float3, float1);
+ symbolTable.insertBuiltIn(float4, "mix", float4, float4, float1);
+ symbolTable.insertBuiltIn(float2, "mix", float2, float2, float2);
+ symbolTable.insertBuiltIn(float3, "mix", float3, float3, float3);
+ symbolTable.insertBuiltIn(float4, "mix", float4, float4, float4);
+
+ symbolTable.insertBuiltIn(float1, "step", float1, float1);
+ symbolTable.insertBuiltIn(float2, "step", float2, float2);
+ symbolTable.insertBuiltIn(float3, "step", float3, float3);
+ symbolTable.insertBuiltIn(float4, "step", float4, float4);
+ symbolTable.insertBuiltIn(float2, "step", float1, float2);
+ symbolTable.insertBuiltIn(float3, "step", float1, float3);
+ symbolTable.insertBuiltIn(float4, "step", float1, float4);
+
+ symbolTable.insertBuiltIn(float1, "smoothstep", float1, float1, float1);
+ symbolTable.insertBuiltIn(float2, "smoothstep", float2, float2, float2);
+ symbolTable.insertBuiltIn(float3, "smoothstep", float3, float3, float3);
+ symbolTable.insertBuiltIn(float4, "smoothstep", float4, float4, float4);
+ symbolTable.insertBuiltIn(float2, "smoothstep", float1, float1, float2);
+ symbolTable.insertBuiltIn(float3, "smoothstep", float1, float1, float3);
+ symbolTable.insertBuiltIn(float4, "smoothstep", float1, float1, float4);
+
+ //
+ // Geometric Functions.
+ //
+ symbolTable.insertBuiltIn(float1, "length", float1);
+ symbolTable.insertBuiltIn(float1, "length", float2);
+ symbolTable.insertBuiltIn(float1, "length", float3);
+ symbolTable.insertBuiltIn(float1, "length", float4);
+
+ symbolTable.insertBuiltIn(float1, "distance", float1, float1);
+ symbolTable.insertBuiltIn(float1, "distance", float2, float2);
+ symbolTable.insertBuiltIn(float1, "distance", float3, float3);
+ symbolTable.insertBuiltIn(float1, "distance", float4, float4);
+
+ symbolTable.insertBuiltIn(float1, "dot", float1, float1);
+ symbolTable.insertBuiltIn(float1, "dot", float2, float2);
+ symbolTable.insertBuiltIn(float1, "dot", float3, float3);
+ symbolTable.insertBuiltIn(float1, "dot", float4, float4);
+
+ symbolTable.insertBuiltIn(float3, "cross", float3, float3);
+ symbolTable.insertBuiltIn(float1, "normalize", float1);
+ symbolTable.insertBuiltIn(float2, "normalize", float2);
+ symbolTable.insertBuiltIn(float3, "normalize", float3);
+ symbolTable.insertBuiltIn(float4, "normalize", float4);
+
+ symbolTable.insertBuiltIn(float1, "faceforward", float1, float1, float1);
+ symbolTable.insertBuiltIn(float2, "faceforward", float2, float2, float2);
+ symbolTable.insertBuiltIn(float3, "faceforward", float3, float3, float3);
+ symbolTable.insertBuiltIn(float4, "faceforward", float4, float4, float4);
+
+ symbolTable.insertBuiltIn(float1, "reflect", float1, float1);
+ symbolTable.insertBuiltIn(float2, "reflect", float2, float2);
+ symbolTable.insertBuiltIn(float3, "reflect", float3, float3);
+ symbolTable.insertBuiltIn(float4, "reflect", float4, float4);
+
+ symbolTable.insertBuiltIn(float1, "refract", float1, float1, float1);
+ symbolTable.insertBuiltIn(float2, "refract", float2, float2, float1);
+ symbolTable.insertBuiltIn(float3, "refract", float3, float3, float1);
+ symbolTable.insertBuiltIn(float4, "refract", float4, float4, float1);
+
+ TType *mat2 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 2, true);
+ TType *mat3 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 3, true);
+ TType *mat4 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 4, true);
+
+ //
+ // Matrix Functions.
+ //
+ symbolTable.insertBuiltIn(mat2, "matrixCompMult", mat2, mat2);
+ symbolTable.insertBuiltIn(mat3, "matrixCompMult", mat3, mat3);
+ symbolTable.insertBuiltIn(mat4, "matrixCompMult", mat4, mat4);
+
+ TType *bool1 = new TType(EbtBool, EbpUndefined, EvqGlobal, 1);
+ TType *bool2 = new TType(EbtBool, EbpUndefined, EvqGlobal, 2);
+ TType *bool3 = new TType(EbtBool, EbpUndefined, EvqGlobal, 3);
+ TType *bool4 = new TType(EbtBool, EbpUndefined, EvqGlobal, 4);
+
+ //
+ // Vector relational functions.
+ //
+ symbolTable.insertBuiltIn(bool2, "lessThan", float2, float2);
+ symbolTable.insertBuiltIn(bool3, "lessThan", float3, float3);
+ symbolTable.insertBuiltIn(bool4, "lessThan", float4, float4);
+
+ symbolTable.insertBuiltIn(bool2, "lessThan", int2, int2);
+ symbolTable.insertBuiltIn(bool3, "lessThan", int3, int3);
+ symbolTable.insertBuiltIn(bool4, "lessThan", int4, int4);
+
+ symbolTable.insertBuiltIn(bool2, "lessThanEqual", float2, float2);
+ symbolTable.insertBuiltIn(bool3, "lessThanEqual", float3, float3);
+ symbolTable.insertBuiltIn(bool4, "lessThanEqual", float4, float4);
+
+ symbolTable.insertBuiltIn(bool2, "lessThanEqual", int2, int2);
+ symbolTable.insertBuiltIn(bool3, "lessThanEqual", int3, int3);
+ symbolTable.insertBuiltIn(bool4, "lessThanEqual", int4, int4);
+
+ symbolTable.insertBuiltIn(bool2, "greaterThan", float2, float2);
+ symbolTable.insertBuiltIn(bool3, "greaterThan", float3, float3);
+ symbolTable.insertBuiltIn(bool4, "greaterThan", float4, float4);
+
+ symbolTable.insertBuiltIn(bool2, "greaterThan", int2, int2);
+ symbolTable.insertBuiltIn(bool3, "greaterThan", int3, int3);
+ symbolTable.insertBuiltIn(bool4, "greaterThan", int4, int4);
+
+ symbolTable.insertBuiltIn(bool2, "greaterThanEqual", float2, float2);
+ symbolTable.insertBuiltIn(bool3, "greaterThanEqual", float3, float3);
+ symbolTable.insertBuiltIn(bool4, "greaterThanEqual", float4, float4);
+
+ symbolTable.insertBuiltIn(bool2, "greaterThanEqual", int2, int2);
+ symbolTable.insertBuiltIn(bool3, "greaterThanEqual", int3, int3);
+ symbolTable.insertBuiltIn(bool4, "greaterThanEqual", int4, int4);
+
+ symbolTable.insertBuiltIn(bool2, "equal", float2, float2);
+ symbolTable.insertBuiltIn(bool3, "equal", float3, float3);
+ symbolTable.insertBuiltIn(bool4, "equal", float4, float4);
+
+ symbolTable.insertBuiltIn(bool2, "equal", int2, int2);
+ symbolTable.insertBuiltIn(bool3, "equal", int3, int3);
+ symbolTable.insertBuiltIn(bool4, "equal", int4, int4);
+
+ symbolTable.insertBuiltIn(bool2, "equal", bool2, bool2);
+ symbolTable.insertBuiltIn(bool3, "equal", bool3, bool3);
+ symbolTable.insertBuiltIn(bool4, "equal", bool4, bool4);
+
+ symbolTable.insertBuiltIn(bool2, "notEqual", float2, float2);
+ symbolTable.insertBuiltIn(bool3, "notEqual", float3, float3);
+ symbolTable.insertBuiltIn(bool4, "notEqual", float4, float4);
+
+ symbolTable.insertBuiltIn(bool2, "notEqual", int2, int2);
+ symbolTable.insertBuiltIn(bool3, "notEqual", int3, int3);
+ symbolTable.insertBuiltIn(bool4, "notEqual", int4, int4);
+
+ symbolTable.insertBuiltIn(bool2, "notEqual", bool2, bool2);
+ symbolTable.insertBuiltIn(bool3, "notEqual", bool3, bool3);
+ symbolTable.insertBuiltIn(bool4, "notEqual", bool4, bool4);
+
+ symbolTable.insertBuiltIn(bool1, "any", bool2);
+ symbolTable.insertBuiltIn(bool1, "any", bool3);
+ symbolTable.insertBuiltIn(bool1, "any", bool4);
+
+ symbolTable.insertBuiltIn(bool1, "all", bool2);
+ symbolTable.insertBuiltIn(bool1, "all", bool3);
+ symbolTable.insertBuiltIn(bool1, "all", bool4);
+
+ symbolTable.insertBuiltIn(bool2, "not", bool2);
+ symbolTable.insertBuiltIn(bool3, "not", bool3);
+ symbolTable.insertBuiltIn(bool4, "not", bool4);
+
+ TType *sampler2D = new TType(EbtSampler2D, EbpUndefined, EvqGlobal, 1);
+ TType *samplerCube = new TType(EbtSamplerCube, EbpUndefined, EvqGlobal, 1);
+
+ //
+ // Texture Functions for GLSL ES 1.0
+ //
+ symbolTable.insertBuiltIn(float4, "texture2D", sampler2D, float2);
+ symbolTable.insertBuiltIn(float4, "texture2DProj", sampler2D, float3);
+ symbolTable.insertBuiltIn(float4, "texture2DProj", sampler2D, float4);
+ symbolTable.insertBuiltIn(float4, "textureCube", samplerCube, float3);
+
+ if (resources.OES_EGL_image_external)
+ {
+ TType *samplerExternalOES = new TType(EbtSamplerExternalOES, EbpUndefined, EvqGlobal, 1);
+
+ symbolTable.insertBuiltIn(float4, "texture2D", samplerExternalOES, float2);
+ symbolTable.insertBuiltIn(float4, "texture2DProj", samplerExternalOES, float3);
+ symbolTable.insertBuiltIn(float4, "texture2DProj", samplerExternalOES, float4);
+ }
+
+ if (resources.ARB_texture_rectangle)
+ {
+ TType *sampler2DRect = new TType(EbtSampler2DRect, EbpUndefined, EvqGlobal, 1);
+
+ symbolTable.insertBuiltIn(float4, "texture2DRect", sampler2DRect, float2);
+ symbolTable.insertBuiltIn(float4, "texture2DRectProj", sampler2DRect, float3);
+ symbolTable.insertBuiltIn(float4, "texture2DRectProj", sampler2DRect, float4);
+ }
+
+ if (type == SH_FRAGMENT_SHADER)
+ {
+ symbolTable.insertBuiltIn(float4, "texture2D", sampler2D, float2, float1);
+ symbolTable.insertBuiltIn(float4, "texture2DProj", sampler2D, float3, float1);
+ symbolTable.insertBuiltIn(float4, "texture2DProj", sampler2D, float4, float1);
+ symbolTable.insertBuiltIn(float4, "textureCube", samplerCube, float3, float1);
+
+ if (resources.OES_standard_derivatives)
+ {
+ symbolTable.insertBuiltIn(float1, "dFdx", float1);
+ symbolTable.insertBuiltIn(float2, "dFdx", float2);
+ symbolTable.insertBuiltIn(float3, "dFdx", float3);
+ symbolTable.insertBuiltIn(float4, "dFdx", float4);
+
+ symbolTable.insertBuiltIn(float1, "dFdy", float1);
+ symbolTable.insertBuiltIn(float2, "dFdy", float2);
+ symbolTable.insertBuiltIn(float3, "dFdy", float3);
+ symbolTable.insertBuiltIn(float4, "dFdy", float4);
+
+ symbolTable.insertBuiltIn(float1, "fwidth", float1);
+ symbolTable.insertBuiltIn(float2, "fwidth", float2);
+ symbolTable.insertBuiltIn(float3, "fwidth", float3);
+ symbolTable.insertBuiltIn(float4, "fwidth", float4);
+ }
+ }
+
+ if(type == SH_VERTEX_SHADER)
+ {
+ symbolTable.insertBuiltIn(float4, "texture2DLod", sampler2D, float2, float1);
+ symbolTable.insertBuiltIn(float4, "texture2DProjLod", sampler2D, float3, float1);
+ symbolTable.insertBuiltIn(float4, "texture2DProjLod", sampler2D, float4, float1);
+ symbolTable.insertBuiltIn(float4, "textureCubeLod", samplerCube, float3, float1);
+ }
+
+ //
+ // Depth range in window coordinates
+ //
+ TFieldList *fields = NewPoolTFieldList();
+ TField *near = new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1), NewPoolTString("near"));
+ TField *far = new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1), NewPoolTString("far"));
+ TField *diff = new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1), NewPoolTString("diff"));
+ fields->push_back(near);
+ fields->push_back(far);
+ fields->push_back(diff);
+ TStructure *depthRangeStruct = new TStructure(NewPoolTString("gl_DepthRangeParameters"), fields);
+ TVariable *depthRangeParameters = new TVariable(&depthRangeStruct->name(), depthRangeStruct, true);
+ symbolTable.insert(*depthRangeParameters);
+ TVariable *depthRange = new TVariable(NewPoolTString("gl_DepthRange"), TType(depthRangeStruct));
+ depthRange->setQualifier(EvqUniform);
+ symbolTable.insert(*depthRange);
+
+ //
+ // Implementation dependent built-in constants.
+ //
+ symbolTable.insertConstInt("gl_MaxVertexAttribs", resources.MaxVertexAttribs);
+ symbolTable.insertConstInt("gl_MaxVertexUniformVectors", resources.MaxVertexUniformVectors);
+ symbolTable.insertConstInt("gl_MaxVaryingVectors", resources.MaxVaryingVectors);
+ symbolTable.insertConstInt("gl_MaxVertexTextureImageUnits", resources.MaxVertexTextureImageUnits);
+ symbolTable.insertConstInt("gl_MaxCombinedTextureImageUnits", resources.MaxCombinedTextureImageUnits);
+ symbolTable.insertConstInt("gl_MaxTextureImageUnits", resources.MaxTextureImageUnits);
+ symbolTable.insertConstInt("gl_MaxFragmentUniformVectors", resources.MaxFragmentUniformVectors);
+
+ if (spec != SH_CSS_SHADERS_SPEC)
+ {
+ symbolTable.insertConstInt("gl_MaxDrawBuffers", resources.MaxDrawBuffers);
+ }
+}
+
+void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec,
+ const ShBuiltInResources &resources,
+ TSymbolTable &symbolTable)
+{
+ //
+ // First, insert some special built-in variables that are not in
+ // the built-in header files.
+ //
+ switch(type) {
+ case SH_FRAGMENT_SHADER:
+ symbolTable.insert(*new TVariable(NewPoolTString("gl_FragCoord"), TType(EbtFloat, EbpMedium, EvqFragCoord, 4)));
+ symbolTable.insert(*new TVariable(NewPoolTString("gl_FrontFacing"), TType(EbtBool, EbpUndefined, EvqFrontFacing, 1)));
+ symbolTable.insert(*new TVariable(NewPoolTString("gl_PointCoord"), TType(EbtFloat, EbpMedium, EvqPointCoord, 2)));
+
+ //
+ // In CSS Shaders, gl_FragColor, gl_FragData, and gl_MaxDrawBuffers are not available.
+ // Instead, css_MixColor and css_ColorMatrix are available.
+ //
+ if (spec != SH_CSS_SHADERS_SPEC) {
+ symbolTable.insert(*new TVariable(NewPoolTString("gl_FragColor"), TType(EbtFloat, EbpMedium, EvqFragColor, 4)));
+ symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData[gl_MaxDrawBuffers]"), TType(EbtFloat, EbpMedium, EvqFragData, 4)));
+ if (resources.EXT_frag_depth) {
+ symbolTable.insert(*new TVariable(NewPoolTString("gl_FragDepthEXT"), TType(EbtFloat, resources.FragmentPrecisionHigh ? EbpHigh : EbpMedium, EvqFragDepth, 1)));
+ symbolTable.relateToExtension("gl_FragDepthEXT", "GL_EXT_frag_depth");
+ }
+ } else {
+ symbolTable.insert(*new TVariable(NewPoolTString("css_MixColor"), TType(EbtFloat, EbpMedium, EvqGlobal, 4)));
+ symbolTable.insert(*new TVariable(NewPoolTString("css_ColorMatrix"), TType(EbtFloat, EbpMedium, EvqGlobal, 4, true)));
+ }
+
+ break;
+
+ case SH_VERTEX_SHADER:
+ symbolTable.insert(*new TVariable(NewPoolTString("gl_Position"), TType(EbtFloat, EbpHigh, EvqPosition, 4)));
+ symbolTable.insert(*new TVariable(NewPoolTString("gl_PointSize"), TType(EbtFloat, EbpMedium, EvqPointSize, 1)));
+ break;
+
+ default: assert(false && "Language not supported");
+ }
+
+ //
+ // Next, identify which built-ins from the already loaded headers have
+ // a mapping to an operator. Those that are not identified as such are
+ // expected to be resolved through a library of functions, versus as
+ // operations.
+ //
+ symbolTable.relateToOperator("matrixCompMult", EOpMul);
+
+ symbolTable.relateToOperator("equal", EOpVectorEqual);
+ symbolTable.relateToOperator("notEqual", EOpVectorNotEqual);
+ symbolTable.relateToOperator("lessThan", EOpLessThan);
+ symbolTable.relateToOperator("greaterThan", EOpGreaterThan);
+ symbolTable.relateToOperator("lessThanEqual", EOpLessThanEqual);
+ symbolTable.relateToOperator("greaterThanEqual", EOpGreaterThanEqual);
+
+ symbolTable.relateToOperator("radians", EOpRadians);
+ symbolTable.relateToOperator("degrees", EOpDegrees);
+ symbolTable.relateToOperator("sin", EOpSin);
+ symbolTable.relateToOperator("cos", EOpCos);
+ symbolTable.relateToOperator("tan", EOpTan);
+ symbolTable.relateToOperator("asin", EOpAsin);
+ symbolTable.relateToOperator("acos", EOpAcos);
+ symbolTable.relateToOperator("atan", EOpAtan);
+
+ symbolTable.relateToOperator("pow", EOpPow);
+ symbolTable.relateToOperator("exp2", EOpExp2);
+ symbolTable.relateToOperator("log", EOpLog);
+ symbolTable.relateToOperator("exp", EOpExp);
+ symbolTable.relateToOperator("log2", EOpLog2);
+ symbolTable.relateToOperator("sqrt", EOpSqrt);
+ symbolTable.relateToOperator("inversesqrt", EOpInverseSqrt);
+
+ symbolTable.relateToOperator("abs", EOpAbs);
+ symbolTable.relateToOperator("sign", EOpSign);
+ symbolTable.relateToOperator("floor", EOpFloor);
+ symbolTable.relateToOperator("ceil", EOpCeil);
+ symbolTable.relateToOperator("fract", EOpFract);
+ symbolTable.relateToOperator("mod", EOpMod);
+ symbolTable.relateToOperator("min", EOpMin);
+ symbolTable.relateToOperator("max", EOpMax);
+ symbolTable.relateToOperator("clamp", EOpClamp);
+ symbolTable.relateToOperator("mix", EOpMix);
+ symbolTable.relateToOperator("step", EOpStep);
+ symbolTable.relateToOperator("smoothstep", EOpSmoothStep);
+
+ symbolTable.relateToOperator("length", EOpLength);
+ symbolTable.relateToOperator("distance", EOpDistance);
+ symbolTable.relateToOperator("dot", EOpDot);
+ symbolTable.relateToOperator("cross", EOpCross);
+ symbolTable.relateToOperator("normalize", EOpNormalize);
+ symbolTable.relateToOperator("faceforward", EOpFaceForward);
+ symbolTable.relateToOperator("reflect", EOpReflect);
+ symbolTable.relateToOperator("refract", EOpRefract);
+
+ symbolTable.relateToOperator("any", EOpAny);
+ symbolTable.relateToOperator("all", EOpAll);
+ symbolTable.relateToOperator("not", EOpVectorLogicalNot);
+
+ // Map language-specific operators.
+ switch(type) {
+ case SH_VERTEX_SHADER:
+ break;
+ case SH_FRAGMENT_SHADER:
+ if (resources.OES_standard_derivatives) {
+ symbolTable.relateToOperator("dFdx", EOpDFdx);
+ symbolTable.relateToOperator("dFdy", EOpDFdy);
+ symbolTable.relateToOperator("fwidth", EOpFwidth);
+
+ symbolTable.relateToExtension("dFdx", "GL_OES_standard_derivatives");
+ symbolTable.relateToExtension("dFdy", "GL_OES_standard_derivatives");
+ symbolTable.relateToExtension("fwidth", "GL_OES_standard_derivatives");
+ }
+ break;
+ default: break;
+ }
+
+ // Finally add resource-specific variables.
+ switch(type) {
+ case SH_FRAGMENT_SHADER:
+ if (spec != SH_CSS_SHADERS_SPEC) {
+ // Set up gl_FragData. The array size.
+ TType fragData(EbtFloat, EbpMedium, EvqFragData, 4, false, true);
+ fragData.setArraySize(resources.MaxDrawBuffers);
+ symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData"), fragData));
+ }
+ break;
+ default: break;
+ }
+}
+
+void InitExtensionBehavior(const ShBuiltInResources& resources,
+ TExtensionBehavior& extBehavior)
+{
+ if (resources.OES_standard_derivatives)
+ extBehavior["GL_OES_standard_derivatives"] = EBhUndefined;
+ if (resources.OES_EGL_image_external)
+ extBehavior["GL_OES_EGL_image_external"] = EBhUndefined;
+ if (resources.ARB_texture_rectangle)
+ extBehavior["GL_ARB_texture_rectangle"] = EBhUndefined;
+ if (resources.EXT_draw_buffers)
+ extBehavior["GL_EXT_draw_buffers"] = EBhUndefined;
+ if (resources.EXT_frag_depth)
+ extBehavior["GL_EXT_frag_depth"] = EBhUndefined;
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Initialize.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorInitializeh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Initialize.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Initialize.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Initialize.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,23 @@
</span><ins>+//
+// Copyright (c) 2002-2013 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 _INITIALIZE_INCLUDED_
+#define _INITIALIZE_INCLUDED_
+
+#include "compiler/translator/Common.h"
+#include "compiler/translator/ShHandle.h"
+#include "compiler/translator/SymbolTable.h"
+
+void InsertBuiltInFunctions(ShShaderType type, ShShaderSpec spec, const ShBuiltInResources &resources, TSymbolTable &table);
+
+void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec,
+ const ShBuiltInResources& resources,
+ TSymbolTable& symbolTable);
+
+void InitExtensionBehavior(const ShBuiltInResources& resources,
+ TExtensionBehavior& extensionBehavior);
+
+#endif // _INITIALIZE_INCLUDED_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Initialize.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorInitializeDllcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/InitializeDll.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/InitializeDll.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/InitializeDll.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,32 @@
</span><ins>+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/InitializeDll.h"
+
+#include "compiler/translator/InitializeGlobals.h"
+#include "compiler/translator/InitializeParseContext.h"
+#include "compiler/translator/osinclude.h"
+
+bool InitProcess()
+{
+ if (!InitializePoolIndex()) {
+ assert(0 && "InitProcess(): Failed to initalize global pool");
+ return false;
+ }
+
+ if (!InitializeParseContextIndex()) {
+ assert(0 && "InitProcess(): Failed to initalize parse context");
+ return false;
+ }
+
+ return true;
+}
+
+void DetachProcess()
+{
+ FreeParseContextIndex();
+ FreePoolIndex();
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/InitializeDll.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorInitializeDllh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/InitializeDll.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/InitializeDll.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/InitializeDll.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,13 @@
</span><ins>+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+#ifndef __INITIALIZEDLL_H
+#define __INITIALIZEDLL_H
+
+bool InitProcess();
+void DetachProcess();
+
+#endif // __INITIALIZEDLL_H
+
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/InitializeDll.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorInitializeGlobalsh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/InitializeGlobals.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/InitializeGlobals.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/InitializeGlobals.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,13 @@
</span><ins>+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef __INITIALIZE_GLOBALS_INCLUDED_
+#define __INITIALIZE_GLOBALS_INCLUDED_
+
+bool InitializePoolIndex();
+void FreePoolIndex();
+
+#endif // __INITIALIZE_GLOBALS_INCLUDED_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/InitializeGlobals.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorInitializeParseContextcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/InitializeParseContext.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/InitializeParseContext.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/InitializeParseContext.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,40 @@
</span><ins>+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/InitializeParseContext.h"
+
+#include "compiler/translator/osinclude.h"
+
+OS_TLSIndex GlobalParseContextIndex = OS_INVALID_TLS_INDEX;
+
+bool InitializeParseContextIndex()
+{
+ assert(GlobalParseContextIndex == OS_INVALID_TLS_INDEX);
+
+ GlobalParseContextIndex = OS_AllocTLSIndex();
+ return GlobalParseContextIndex != OS_INVALID_TLS_INDEX;
+}
+
+void FreeParseContextIndex()
+{
+ assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX);
+
+ OS_FreeTLSIndex(GlobalParseContextIndex);
+ GlobalParseContextIndex = OS_INVALID_TLS_INDEX;
+}
+
+void SetGlobalParseContext(TParseContext* context)
+{
+ assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX);
+ OS_SetTLSValue(GlobalParseContextIndex, context);
+}
+
+TParseContext* GetGlobalParseContext()
+{
+ assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX);
+ return static_cast<TParseContext*>(OS_GetTLSValue(GlobalParseContextIndex));
+}
+
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/InitializeParseContext.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorInitializeParseContexth"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/InitializeParseContext.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/InitializeParseContext.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/InitializeParseContext.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,17 @@
</span><ins>+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef __INITIALIZE_PARSE_CONTEXT_INCLUDED_
+#define __INITIALIZE_PARSE_CONTEXT_INCLUDED_
+
+bool InitializeParseContextIndex();
+void FreeParseContextIndex();
+
+struct TParseContext;
+extern void SetGlobalParseContext(TParseContext* context);
+extern TParseContext* GetGlobalParseContext();
+
+#endif // __INITIALIZE_PARSE_CONTEXT_INCLUDED_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/InitializeParseContext.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorInitializeVariablescpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/InitializeVariables.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/InitializeVariables.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/InitializeVariables.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,116 @@
</span><ins>+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/InitializeVariables.h"
+#include "compiler/translator/compilerdebug.h"
+
+namespace
+{
+
+TIntermConstantUnion* constructFloatConstUnionNode(const TType& type)
+{
+ TType myType = type;
+ unsigned char size = myType.getNominalSize();
+ if (myType.isMatrix())
+ size *= size;
+ ConstantUnion *u = new ConstantUnion[size];
+ for (int ii = 0; ii < size; ++ii)
+ u[ii].setFConst(0.0f);
+
+ myType.clearArrayness();
+ myType.setQualifier(EvqConst);
+ TIntermConstantUnion *node = new TIntermConstantUnion(u, myType);
+ return node;
+}
+
+TIntermConstantUnion* constructIndexNode(int index)
+{
+ ConstantUnion *u = new ConstantUnion[1];
+ u[0].setIConst(index);
+
+ TType type(EbtInt, EbpUndefined, EvqConst, 1);
+ TIntermConstantUnion *node = new TIntermConstantUnion(u, type);
+ return node;
+}
+
+} // namespace anonymous
+
+bool InitializeVariables::visitAggregate(Visit visit, TIntermAggregate* node)
+{
+ bool visitChildren = !mCodeInserted;
+ switch (node->getOp())
+ {
+ case EOpSequence:
+ break;
+ case EOpFunction:
+ {
+ // Function definition.
+ ASSERT(visit == PreVisit);
+ if (node->getName() == "main(")
+ {
+ TIntermSequence &sequence = node->getSequence();
+ ASSERT((sequence.size() == 1) || (sequence.size() == 2));
+ TIntermAggregate *body = NULL;
+ if (sequence.size() == 1)
+ {
+ body = new TIntermAggregate(EOpSequence);
+ sequence.push_back(body);
+ }
+ else
+ {
+ body = sequence[1]->getAsAggregate();
+ }
+ ASSERT(body);
+ insertInitCode(body->getSequence());
+ mCodeInserted = true;
+ }
+ break;
+ }
+ default:
+ visitChildren = false;
+ break;
+ }
+ return visitChildren;
+}
+
+void InitializeVariables::insertInitCode(TIntermSequence& sequence)
+{
+ for (size_t ii = 0; ii < mVariables.size(); ++ii)
+ {
+ const InitVariableInfo& varInfo = mVariables[ii];
+
+ if (varInfo.type.isArray())
+ {
+ for (int index = varInfo.type.getArraySize() - 1; index >= 0; --index)
+ {
+ TIntermBinary *assign = new TIntermBinary(EOpAssign);
+ sequence.insert(sequence.begin(), assign);
+
+ TIntermBinary *indexDirect = new TIntermBinary(EOpIndexDirect);
+ TIntermSymbol *symbol = new TIntermSymbol(0, varInfo.name, varInfo.type);
+ indexDirect->setLeft(symbol);
+ TIntermConstantUnion *indexNode = constructIndexNode(index);
+ indexDirect->setRight(indexNode);
+
+ assign->setLeft(indexDirect);
+
+ TIntermConstantUnion *zeroConst = constructFloatConstUnionNode(varInfo.type);
+ assign->setRight(zeroConst);
+ }
+ }
+ else
+ {
+ TIntermBinary *assign = new TIntermBinary(EOpAssign);
+ sequence.insert(sequence.begin(), assign);
+ TIntermSymbol *symbol = new TIntermSymbol(0, varInfo.name, varInfo.type);
+ assign->setLeft(symbol);
+ TIntermConstantUnion *zeroConst = constructFloatConstUnionNode(varInfo.type);
+ assign->setRight(zeroConst);
+ }
+
+ }
+}
+
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/InitializeVariables.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorInitializeVariablesh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/InitializeVariables.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/InitializeVariables.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/InitializeVariables.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,50 @@
</span><ins>+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_INITIALIZE_VARIABLES_H_
+#define COMPILER_INITIALIZE_VARIABLES_H_
+
+#include "compiler/translator/intermediate.h"
+
+class InitializeVariables : public TIntermTraverser
+{
+ public:
+ struct InitVariableInfo
+ {
+ TString name;
+ TType type;
+
+ InitVariableInfo(const TString& _name, const TType& _type)
+ : name(_name),
+ type(_type)
+ {
+ }
+ };
+ typedef TVector<InitVariableInfo> InitVariableInfoList;
+
+ InitializeVariables(const InitVariableInfoList& vars)
+ : mCodeInserted(false),
+ mVariables(vars)
+ {
+ }
+
+ protected:
+ virtual bool visitBinary(Visit visit, TIntermBinary* node) { return false; }
+ virtual bool visitUnary(Visit visit, TIntermUnary* node) { return false; }
+ virtual bool visitSelection(Visit visit, TIntermSelection* node) { return false; }
+ virtual bool visitLoop(Visit visit, TIntermLoop* node) { return false; }
+ virtual bool visitBranch(Visit visit, TIntermBranch* node) { return false; }
+
+ virtual bool visitAggregate(Visit visit, TIntermAggregate* node);
+
+ private:
+ void insertInitCode(TIntermSequence& sequence);
+
+ InitVariableInfoList mVariables;
+ bool mCodeInserted;
+};
+
+#endif // COMPILER_INITIALIZE_VARIABLES_H_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/InitializeVariables.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorIntermTraversecpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/IntermTraverse.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/IntermTraverse.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/IntermTraverse.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,259 @@
</span><ins>+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/intermediate.h"
+
+//
+// Traverse the intermediate representation tree, and
+// call a node type specific function for each node.
+// Done recursively through the member function Traverse().
+// Node types can be skipped if their function to call is 0,
+// but their subtree will still be traversed.
+// Nodes with children can have their whole subtree skipped
+// if preVisit is turned on and the type specific function
+// returns false.
+//
+// preVisit, postVisit, and rightToLeft control what order
+// nodes are visited in.
+//
+
+//
+// Traversal functions for terminals are straighforward....
+//
+void TIntermSymbol::traverse(TIntermTraverser *it)
+{
+ it->visitSymbol(this);
+}
+
+void TIntermConstantUnion::traverse(TIntermTraverser *it)
+{
+ it->visitConstantUnion(this);
+}
+
+//
+// Traverse a binary node.
+//
+void TIntermBinary::traverse(TIntermTraverser *it)
+{
+ bool visit = true;
+
+ //
+ // visit the node before children if pre-visiting.
+ //
+ if (it->preVisit)
+ visit = it->visitBinary(PreVisit, this);
+
+ //
+ // Visit the children, in the right order.
+ //
+ if (visit)
+ {
+ it->incrementDepth(this);
+
+ if (it->rightToLeft)
+ {
+ if (right)
+ right->traverse(it);
+
+ if (it->inVisit)
+ visit = it->visitBinary(InVisit, this);
+
+ if (visit && left)
+ left->traverse(it);
+ }
+ else
+ {
+ if (left)
+ left->traverse(it);
+
+ if (it->inVisit)
+ visit = it->visitBinary(InVisit, this);
+
+ if (visit && right)
+ right->traverse(it);
+ }
+
+ it->decrementDepth();
+ }
+
+ //
+ // Visit the node after the children, if requested and the traversal
+ // hasn't been cancelled yet.
+ //
+ if (visit && it->postVisit)
+ it->visitBinary(PostVisit, this);
+}
+
+//
+// Traverse a unary node. Same comments in binary node apply here.
+//
+void TIntermUnary::traverse(TIntermTraverser *it)
+{
+ bool visit = true;
+
+ if (it->preVisit)
+ visit = it->visitUnary(PreVisit, this);
+
+ if (visit) {
+ it->incrementDepth(this);
+ operand->traverse(it);
+ it->decrementDepth();
+ }
+
+ if (visit && it->postVisit)
+ it->visitUnary(PostVisit, this);
+}
+
+//
+// Traverse an aggregate node. Same comments in binary node apply here.
+//
+void TIntermAggregate::traverse(TIntermTraverser *it)
+{
+ bool visit = true;
+
+ if (it->preVisit)
+ visit = it->visitAggregate(PreVisit, this);
+
+ if (visit)
+ {
+ it->incrementDepth(this);
+
+ if (it->rightToLeft)
+ {
+ for (TIntermSequence::reverse_iterator sit = sequence.rbegin(); sit != sequence.rend(); sit++)
+ {
+ (*sit)->traverse(it);
+
+ if (visit && it->inVisit)
+ {
+ if (*sit != sequence.front())
+ visit = it->visitAggregate(InVisit, this);
+ }
+ }
+ }
+ else
+ {
+ for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++)
+ {
+ (*sit)->traverse(it);
+
+ if (visit && it->inVisit)
+ {
+ if (*sit != sequence.back())
+ visit = it->visitAggregate(InVisit, this);
+ }
+ }
+ }
+
+ it->decrementDepth();
+ }
+
+ if (visit && it->postVisit)
+ it->visitAggregate(PostVisit, this);
+}
+
+//
+// Traverse a selection node. Same comments in binary node apply here.
+//
+void TIntermSelection::traverse(TIntermTraverser *it)
+{
+ bool visit = true;
+
+ if (it->preVisit)
+ visit = it->visitSelection(PreVisit, this);
+
+ if (visit) {
+ it->incrementDepth(this);
+ if (it->rightToLeft) {
+ if (falseBlock)
+ falseBlock->traverse(it);
+ if (trueBlock)
+ trueBlock->traverse(it);
+ condition->traverse(it);
+ } else {
+ condition->traverse(it);
+ if (trueBlock)
+ trueBlock->traverse(it);
+ if (falseBlock)
+ falseBlock->traverse(it);
+ }
+ it->decrementDepth();
+ }
+
+ if (visit && it->postVisit)
+ it->visitSelection(PostVisit, this);
+}
+
+//
+// Traverse a loop node. Same comments in binary node apply here.
+//
+void TIntermLoop::traverse(TIntermTraverser *it)
+{
+ bool visit = true;
+
+ if (it->preVisit)
+ visit = it->visitLoop(PreVisit, this);
+
+ if (visit)
+ {
+ it->incrementDepth(this);
+
+ if (it->rightToLeft)
+ {
+ if (expr)
+ expr->traverse(it);
+
+ if (body)
+ body->traverse(it);
+
+ if (cond)
+ cond->traverse(it);
+
+ if (init)
+ init->traverse(it);
+ }
+ else
+ {
+ if (init)
+ init->traverse(it);
+
+ if (cond)
+ cond->traverse(it);
+
+ if (body)
+ body->traverse(it);
+
+ if (expr)
+ expr->traverse(it);
+ }
+
+ it->decrementDepth();
+ }
+
+ if (visit && it->postVisit)
+ it->visitLoop(PostVisit, this);
+}
+
+//
+// Traverse a branch node. Same comments in binary node apply here.
+//
+void TIntermBranch::traverse(TIntermTraverser *it)
+{
+ bool visit = true;
+
+ if (it->preVisit)
+ visit = it->visitBranch(PreVisit, this);
+
+ if (visit && expression) {
+ it->incrementDepth(this);
+ expression->traverse(it);
+ it->decrementDepth();
+ }
+
+ if (visit && it->postVisit)
+ it->visitBranch(PostVisit, this);
+}
+
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/IntermTraverse.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorIntermediatecpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Intermediate.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Intermediate.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Intermediate.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,1500 @@
</span><ins>+//
+// Copyright (c) 2002-2013 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.
+//
+
+//
+// Build the intermediate representation.
+//
+
+#include <float.h>
+#include <limits.h>
+#include <algorithm>
+
+#include "compiler/translator/HashNames.h"
+#include "compiler/translator/localintermediate.h"
+#include "compiler/translator/QualifierAlive.h"
+#include "compiler/translator/RemoveTree.h"
+
+bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray);
+
+static TPrecision GetHigherPrecision(TPrecision left, TPrecision right)
+{
+ return left > right ? left : right;
+}
+
+const char* getOperatorString(TOperator op)
+{
+ switch (op) {
+ case EOpInitialize: return "=";
+ case EOpAssign: return "=";
+ case EOpAddAssign: return "+=";
+ case EOpSubAssign: return "-=";
+ case EOpDivAssign: return "/=";
+
+ // Fall-through.
+ case EOpMulAssign:
+ case EOpVectorTimesMatrixAssign:
+ case EOpVectorTimesScalarAssign:
+ case EOpMatrixTimesScalarAssign:
+ case EOpMatrixTimesMatrixAssign: return "*=";
+
+ // Fall-through.
+ case EOpIndexDirect:
+ case EOpIndexIndirect: return "[]";
+
+ case EOpIndexDirectStruct: return ".";
+ case EOpVectorSwizzle: return ".";
+ case EOpAdd: return "+";
+ case EOpSub: return "-";
+ case EOpMul: return "*";
+ case EOpDiv: return "/";
+ case EOpMod: UNIMPLEMENTED(); break;
+ case EOpEqual: return "==";
+ case EOpNotEqual: return "!=";
+ case EOpLessThan: return "<";
+ case EOpGreaterThan: return ">";
+ case EOpLessThanEqual: return "<=";
+ case EOpGreaterThanEqual: return ">=";
+
+ // Fall-through.
+ case EOpVectorTimesScalar:
+ case EOpVectorTimesMatrix:
+ case EOpMatrixTimesVector:
+ case EOpMatrixTimesScalar:
+ case EOpMatrixTimesMatrix: return "*";
+
+ case EOpLogicalOr: return "||";
+ case EOpLogicalXor: return "^^";
+ case EOpLogicalAnd: return "&&";
+ case EOpNegative: return "-";
+ case EOpVectorLogicalNot: return "not";
+ case EOpLogicalNot: return "!";
+ case EOpPostIncrement: return "++";
+ case EOpPostDecrement: return "--";
+ case EOpPreIncrement: return "++";
+ case EOpPreDecrement: return "--";
+
+ // Fall-through.
+ case EOpConvIntToBool:
+ case EOpConvFloatToBool: return "bool";
+
+ // Fall-through.
+ case EOpConvBoolToFloat:
+ case EOpConvIntToFloat: return "float";
+
+ // Fall-through.
+ case EOpConvFloatToInt:
+ case EOpConvBoolToInt: return "int";
+
+ case EOpRadians: return "radians";
+ case EOpDegrees: return "degrees";
+ case EOpSin: return "sin";
+ case EOpCos: return "cos";
+ case EOpTan: return "tan";
+ case EOpAsin: return "asin";
+ case EOpAcos: return "acos";
+ case EOpAtan: return "atan";
+ case EOpExp: return "exp";
+ case EOpLog: return "log";
+ case EOpExp2: return "exp2";
+ case EOpLog2: return "log2";
+ case EOpSqrt: return "sqrt";
+ case EOpInverseSqrt: return "inversesqrt";
+ case EOpAbs: return "abs";
+ case EOpSign: return "sign";
+ case EOpFloor: return "floor";
+ case EOpCeil: return "ceil";
+ case EOpFract: return "fract";
+ case EOpLength: return "length";
+ case EOpNormalize: return "normalize";
+ case EOpDFdx: return "dFdx";
+ case EOpDFdy: return "dFdy";
+ case EOpFwidth: return "fwidth";
+ case EOpAny: return "any";
+ case EOpAll: return "all";
+
+ default: break;
+ }
+ return "";
+}
+
+////////////////////////////////////////////////////////////////////////////
+//
+// First set of functions are to help build the intermediate representation.
+// These functions are not member functions of the nodes.
+// They are called from parser productions.
+//
+/////////////////////////////////////////////////////////////////////////////
+
+//
+// Add a terminal node for an identifier in an expression.
+//
+// Returns the added node.
+//
+TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, const TSourceLoc& line)
+{
+ TIntermSymbol* node = new TIntermSymbol(id, name, type);
+ node->setLine(line);
+
+ return node;
+}
+
+//
+// Connect two nodes with a new parent that does a binary operation on the nodes.
+//
+// Returns the added node.
+//
+TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc& line, TSymbolTable& symbolTable)
+{
+ switch (op) {
+ case EOpEqual:
+ case EOpNotEqual:
+ if (left->isArray())
+ return 0;
+ break;
+ case EOpLessThan:
+ case EOpGreaterThan:
+ case EOpLessThanEqual:
+ case EOpGreaterThanEqual:
+ if (left->isMatrix() || left->isArray() || left->isVector() || left->getBasicType() == EbtStruct) {
+ return 0;
+ }
+ break;
+ case EOpLogicalOr:
+ case EOpLogicalXor:
+ case EOpLogicalAnd:
+ if (left->getBasicType() != EbtBool || left->isMatrix() || left->isArray() || left->isVector()) {
+ return 0;
+ }
+ break;
+ case EOpAdd:
+ case EOpSub:
+ case EOpDiv:
+ case EOpMul:
+ if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool)
+ return 0;
+ default: break;
+ }
+
+ //
+ // First try converting the children to compatible types.
+ //
+ if (left->getType().getStruct() && right->getType().getStruct()) {
+ if (left->getType() != right->getType())
+ return 0;
+ } else {
+ TIntermTyped* child = addConversion(op, left->getType(), right);
+ if (child)
+ right = child;
+ else {
+ child = addConversion(op, right->getType(), left);
+ if (child)
+ left = child;
+ else
+ return 0;
+ }
+ }
+
+ //
+ // Need a new node holding things together then. Make
+ // one and promote it to the right type.
+ //
+ TIntermBinary* node = new TIntermBinary(op);
+ node->setLine(line);
+
+ node->setLeft(left);
+ node->setRight(right);
+ if (!node->promote(infoSink))
+ return 0;
+
+ //
+ // See if we can fold constants.
+ //
+ TIntermTyped* typedReturnNode = 0;
+ TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion();
+ TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion();
+ if (leftTempConstant && rightTempConstant) {
+ typedReturnNode = leftTempConstant->fold(node->getOp(), rightTempConstant, infoSink);
+
+ if (typedReturnNode)
+ return typedReturnNode;
+ }
+
+ return node;
+}
+
+//
+// Connect two nodes through an assignment.
+//
+// Returns the added node.
+//
+TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc& line)
+{
+ //
+ // Like adding binary math, except the conversion can only go
+ // from right to left.
+ //
+ TIntermBinary* node = new TIntermBinary(op);
+ node->setLine(line);
+
+ TIntermTyped* child = addConversion(op, left->getType(), right);
+ if (child == 0)
+ return 0;
+
+ node->setLeft(left);
+ node->setRight(child);
+ if (! node->promote(infoSink))
+ return 0;
+
+ return node;
+}
+
+//
+// Connect two nodes through an index operator, where the left node is the base
+// of an array or struct, and the right node is a direct or indirect offset.
+//
+// Returns the added node.
+// The caller should set the type of the returned node.
+//
+TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, const TSourceLoc& line)
+{
+ TIntermBinary* node = new TIntermBinary(op);
+ node->setLine(line);
+ node->setLeft(base);
+ node->setRight(index);
+
+ // caller should set the type
+
+ return node;
+}
+
+//
+// Add one node as the parent of another that it operates on.
+//
+// Returns the added node.
+//
+TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, const TSourceLoc& line, TSymbolTable& symbolTable)
+{
+ TIntermUnary* node;
+ TIntermTyped* child = childNode->getAsTyped();
+
+ if (child == 0) {
+ infoSink.info.message(EPrefixInternalError, line, "Bad type in AddUnaryMath");
+ return 0;
+ }
+
+ switch (op) {
+ case EOpLogicalNot:
+ if (child->getType().getBasicType() != EbtBool || child->getType().isMatrix() || child->getType().isArray() || child->getType().isVector()) {
+ return 0;
+ }
+ break;
+
+ case EOpPostIncrement:
+ case EOpPreIncrement:
+ case EOpPostDecrement:
+ case EOpPreDecrement:
+ case EOpNegative:
+ if (child->getType().getBasicType() == EbtStruct || child->getType().isArray())
+ return 0;
+ default: break;
+ }
+
+ //
+ // Do we need to promote the operand?
+ //
+ // Note: Implicit promotions were removed from the language.
+ //
+ TBasicType newType = EbtVoid;
+ switch (op) {
+ case EOpConstructInt: newType = EbtInt; break;
+ case EOpConstructBool: newType = EbtBool; break;
+ case EOpConstructFloat: newType = EbtFloat; break;
+ default: break;
+ }
+
+ if (newType != EbtVoid) {
+ child = addConversion(op, TType(newType, child->getPrecision(), EvqTemporary,
+ child->getNominalSize(),
+ child->isMatrix(),
+ child->isArray()),
+ child);
+ if (child == 0)
+ return 0;
+ }
+
+ //
+ // For constructors, we are now done, it's all in the conversion.
+ //
+ switch (op) {
+ case EOpConstructInt:
+ case EOpConstructBool:
+ case EOpConstructFloat:
+ return child;
+ default: break;
+ }
+
+ TIntermConstantUnion *childTempConstant = 0;
+ if (child->getAsConstantUnion())
+ childTempConstant = child->getAsConstantUnion();
+
+ //
+ // Make a new node for the operator.
+ //
+ node = new TIntermUnary(op);
+ node->setLine(line);
+ node->setOperand(child);
+
+ if (! node->promote(infoSink))
+ return 0;
+
+ if (childTempConstant) {
+ TIntermTyped* newChild = childTempConstant->fold(op, 0, infoSink);
+
+ if (newChild)
+ return newChild;
+ }
+
+ return node;
+}
+
+//
+// This is the safe way to change the operator on an aggregate, as it
+// does lots of error checking and fixing. Especially for establishing
+// a function call's operation on it's set of parameters. Sequences
+// of instructions are also aggregates, but they just direnctly set
+// their operator to EOpSequence.
+//
+// Returns an aggregate node, which could be the one passed in if
+// it was already an aggregate but no operator was set.
+//
+TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, const TSourceLoc& line)
+{
+ TIntermAggregate* aggNode;
+
+ //
+ // Make sure we have an aggregate. If not turn it into one.
+ //
+ if (node) {
+ aggNode = node->getAsAggregate();
+ if (aggNode == 0 || aggNode->getOp() != EOpNull) {
+ //
+ // Make an aggregate containing this node.
+ //
+ aggNode = new TIntermAggregate();
+ aggNode->getSequence().push_back(node);
+ }
+ } else
+ aggNode = new TIntermAggregate();
+
+ //
+ // Set the operator.
+ //
+ aggNode->setOp(op);
+ aggNode->setLine(line);
+
+ return aggNode;
+}
+
+//
+// Convert one type to another.
+//
+// Returns the node representing the conversion, which could be the same
+// node passed in if no conversion was needed.
+//
+// Return 0 if a conversion can't be done.
+//
+TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TIntermTyped* node)
+{
+ //
+ // Does the base type allow operation?
+ //
+ switch (node->getBasicType()) {
+ case EbtVoid:
+ case EbtSampler2D:
+ case EbtSamplerCube:
+ return 0;
+ default: break;
+ }
+
+ //
+ // Otherwise, if types are identical, no problem
+ //
+ if (type == node->getType())
+ return node;
+
+ //
+ // If one's a structure, then no conversions.
+ //
+ if (type.getStruct() || node->getType().getStruct())
+ return 0;
+
+ //
+ // If one's an array, then no conversions.
+ //
+ if (type.isArray() || node->getType().isArray())
+ return 0;
+
+ TBasicType promoteTo;
+
+ switch (op) {
+ //
+ // Explicit conversions
+ //
+ case EOpConstructBool:
+ promoteTo = EbtBool;
+ break;
+ case EOpConstructFloat:
+ promoteTo = EbtFloat;
+ break;
+ case EOpConstructInt:
+ promoteTo = EbtInt;
+ break;
+ default:
+ //
+ // implicit conversions were removed from the language.
+ //
+ if (type.getBasicType() != node->getType().getBasicType())
+ return 0;
+ //
+ // Size and structure could still differ, but that's
+ // handled by operator promotion.
+ //
+ return node;
+ }
+
+ if (node->getAsConstantUnion()) {
+
+ return (promoteConstantUnion(promoteTo, node->getAsConstantUnion()));
+ } else {
+
+ //
+ // Add a new newNode for the conversion.
+ //
+ TIntermUnary* newNode = 0;
+
+ TOperator newOp = EOpNull;
+ switch (promoteTo) {
+ case EbtFloat:
+ switch (node->getBasicType()) {
+ case EbtInt: newOp = EOpConvIntToFloat; break;
+ case EbtBool: newOp = EOpConvBoolToFloat; break;
+ default:
+ infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node");
+ return 0;
+ }
+ break;
+ case EbtBool:
+ switch (node->getBasicType()) {
+ case EbtInt: newOp = EOpConvIntToBool; break;
+ case EbtFloat: newOp = EOpConvFloatToBool; break;
+ default:
+ infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node");
+ return 0;
+ }
+ break;
+ case EbtInt:
+ switch (node->getBasicType()) {
+ case EbtBool: newOp = EOpConvBoolToInt; break;
+ case EbtFloat: newOp = EOpConvFloatToInt; break;
+ default:
+ infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node");
+ return 0;
+ }
+ break;
+ default:
+ infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion type");
+ return 0;
+ }
+
+ TType type(promoteTo, node->getPrecision(), EvqTemporary, node->getNominalSize(), node->isMatrix(), node->isArray());
+ newNode = new TIntermUnary(newOp, type);
+ newNode->setLine(node->getLine());
+ newNode->setOperand(node);
+
+ return newNode;
+ }
+}
+
+//
+// Safe way to combine two nodes into an aggregate. Works with null pointers,
+// a node that's not a aggregate yet, etc.
+//
+// Returns the resulting aggregate, unless 0 was passed in for
+// both existing nodes.
+//
+TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc& line)
+{
+ if (left == 0 && right == 0)
+ return 0;
+
+ TIntermAggregate* aggNode = 0;
+ if (left)
+ aggNode = left->getAsAggregate();
+ if (!aggNode || aggNode->getOp() != EOpNull) {
+ aggNode = new TIntermAggregate;
+ if (left)
+ aggNode->getSequence().push_back(left);
+ }
+
+ if (right)
+ aggNode->getSequence().push_back(right);
+
+ aggNode->setLine(line);
+
+ return aggNode;
+}
+
+//
+// Turn an existing node into an aggregate.
+//
+// Returns an aggregate, unless 0 was passed in for the existing node.
+//
+TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, const TSourceLoc& line)
+{
+ if (node == 0)
+ return 0;
+
+ TIntermAggregate* aggNode = new TIntermAggregate;
+ aggNode->getSequence().push_back(node);
+ aggNode->setLine(line);
+
+ return aggNode;
+}
+
+//
+// For "if" test nodes. There are three children; a condition,
+// a true path, and a false path. The two paths are in the
+// nodePair.
+//
+// Returns the selection node created.
+//
+TIntermNode* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, const TSourceLoc& line)
+{
+ //
+ // For compile time constant selections, prune the code and
+ // test now.
+ //
+
+ if (cond->getAsTyped() && cond->getAsTyped()->getAsConstantUnion()) {
+ if (cond->getAsConstantUnion()->getBConst(0) == true)
+ return nodePair.node1 ? setAggregateOperator(nodePair.node1, EOpSequence, nodePair.node1->getLine()) : NULL;
+ else
+ return nodePair.node2 ? setAggregateOperator(nodePair.node2, EOpSequence, nodePair.node2->getLine()) : NULL;
+ }
+
+ TIntermSelection* node = new TIntermSelection(cond, nodePair.node1, nodePair.node2);
+ node->setLine(line);
+
+ return node;
+}
+
+
+TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc& line)
+{
+ if (left->getType().getQualifier() == EvqConst && right->getType().getQualifier() == EvqConst) {
+ return right;
+ } else {
+ TIntermTyped *commaAggregate = growAggregate(left, right, line);
+ commaAggregate->getAsAggregate()->setOp(EOpComma);
+ commaAggregate->setType(right->getType());
+ commaAggregate->getTypePointer()->setQualifier(EvqTemporary);
+ return commaAggregate;
+ }
+}
+
+//
+// For "?:" test nodes. There are three children; a condition,
+// a true path, and a false path. The two paths are specified
+// as separate parameters.
+//
+// Returns the selection node created, or 0 if one could not be.
+//
+TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc& line)
+{
+ //
+ // Get compatible types.
+ //
+ TIntermTyped* child = addConversion(EOpSequence, trueBlock->getType(), falseBlock);
+ if (child)
+ falseBlock = child;
+ else {
+ child = addConversion(EOpSequence, falseBlock->getType(), trueBlock);
+ if (child)
+ trueBlock = child;
+ else
+ return 0;
+ }
+
+ //
+ // See if all the operands are constant, then fold it otherwise not.
+ //
+
+ if (cond->getAsConstantUnion() && trueBlock->getAsConstantUnion() && falseBlock->getAsConstantUnion()) {
+ if (cond->getAsConstantUnion()->getBConst(0))
+ return trueBlock;
+ else
+ return falseBlock;
+ }
+
+ //
+ // Make a selection node.
+ //
+ TIntermSelection* node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType());
+ node->getTypePointer()->setQualifier(EvqTemporary);
+ node->setLine(line);
+
+ return node;
+}
+
+//
+// Constant terminal nodes. Has a union that contains bool, float or int constants
+//
+// Returns the constant union node created.
+//
+
+TIntermConstantUnion* TIntermediate::addConstantUnion(ConstantUnion* unionArrayPointer, const TType& t, const TSourceLoc& line)
+{
+ TIntermConstantUnion* node = new TIntermConstantUnion(unionArrayPointer, t);
+ node->setLine(line);
+
+ return node;
+}
+
+TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, const TSourceLoc& line)
+{
+
+ TIntermAggregate* node = new TIntermAggregate(EOpSequence);
+
+ node->setLine(line);
+ TIntermConstantUnion* constIntNode;
+ TIntermSequence &sequenceVector = node->getSequence();
+ ConstantUnion* unionArray;
+
+ for (int i = 0; i < fields.num; i++) {
+ unionArray = new ConstantUnion[1];
+ unionArray->setIConst(fields.offsets[i]);
+ constIntNode = addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), line);
+ sequenceVector.push_back(constIntNode);
+ }
+
+ return node;
+}
+
+//
+// Create loop nodes.
+//
+TIntermNode* TIntermediate::addLoop(TLoopType type, TIntermNode* init, TIntermTyped* cond, TIntermTyped* expr, TIntermNode* body, const TSourceLoc& line)
+{
+ TIntermNode* node = new TIntermLoop(type, init, cond, expr, body);
+ node->setLine(line);
+
+ return node;
+}
+
+//
+// Add branches.
+//
+TIntermBranch* TIntermediate::addBranch(TOperator branchOp, const TSourceLoc& line)
+{
+ return addBranch(branchOp, 0, line);
+}
+
+TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, const TSourceLoc& line)
+{
+ TIntermBranch* node = new TIntermBranch(branchOp, expression);
+ node->setLine(line);
+
+ return node;
+}
+
+//
+// This is to be executed once the final root is put on top by the parsing
+// process.
+//
+bool TIntermediate::postProcess(TIntermNode* root)
+{
+ if (root == 0)
+ return true;
+
+ //
+ // First, finish off the top level sequence, if any
+ //
+ TIntermAggregate* aggRoot = root->getAsAggregate();
+ if (aggRoot && aggRoot->getOp() == EOpNull)
+ aggRoot->setOp(EOpSequence);
+
+ return true;
+}
+
+//
+// This deletes the tree.
+//
+void TIntermediate::remove(TIntermNode* root)
+{
+ if (root)
+ RemoveAllTreeNodes(root);
+}
+
+////////////////////////////////////////////////////////////////
+//
+// Member functions of the nodes used for building the tree.
+//
+////////////////////////////////////////////////////////////////
+
+#define REPLACE_IF_IS(node, type, original, replacement) \
+ if (node == original) { \
+ node = static_cast<type *>(replacement); \
+ return true; \
+ }
+
+bool TIntermLoop::replaceChildNode(
+ TIntermNode *original, TIntermNode *replacement)
+{
+ REPLACE_IF_IS(init, TIntermNode, original, replacement);
+ REPLACE_IF_IS(cond, TIntermTyped, original, replacement);
+ REPLACE_IF_IS(expr, TIntermTyped, original, replacement);
+ REPLACE_IF_IS(body, TIntermNode, original, replacement);
+ return false;
+}
+
+bool TIntermBranch::replaceChildNode(
+ TIntermNode *original, TIntermNode *replacement)
+{
+ REPLACE_IF_IS(expression, TIntermTyped, original, replacement);
+ return false;
+}
+
+bool TIntermBinary::replaceChildNode(
+ TIntermNode *original, TIntermNode *replacement)
+{
+ REPLACE_IF_IS(left, TIntermTyped, original, replacement);
+ REPLACE_IF_IS(right, TIntermTyped, original, replacement);
+ return false;
+}
+
+bool TIntermUnary::replaceChildNode(
+ TIntermNode *original, TIntermNode *replacement)
+{
+ REPLACE_IF_IS(operand, TIntermTyped, original, replacement);
+ return false;
+}
+
+bool TIntermAggregate::replaceChildNode(
+ TIntermNode *original, TIntermNode *replacement)
+{
+ for (size_t ii = 0; ii < sequence.size(); ++ii)
+ {
+ REPLACE_IF_IS(sequence[ii], TIntermNode, original, replacement);
+ }
+ return false;
+}
+
+bool TIntermSelection::replaceChildNode(
+ TIntermNode *original, TIntermNode *replacement)
+{
+ REPLACE_IF_IS(condition, TIntermTyped, original, replacement);
+ REPLACE_IF_IS(trueBlock, TIntermNode, original, replacement);
+ REPLACE_IF_IS(falseBlock, TIntermNode, original, replacement);
+ return false;
+}
+
+//
+// Say whether or not an operation node changes the value of a variable.
+//
+bool TIntermOperator::isAssignment() const
+{
+ switch (op) {
+ case EOpPostIncrement:
+ case EOpPostDecrement:
+ case EOpPreIncrement:
+ case EOpPreDecrement:
+ case EOpAssign:
+ case EOpAddAssign:
+ case EOpSubAssign:
+ case EOpMulAssign:
+ case EOpVectorTimesMatrixAssign:
+ case EOpVectorTimesScalarAssign:
+ case EOpMatrixTimesScalarAssign:
+ case EOpMatrixTimesMatrixAssign:
+ case EOpDivAssign:
+ return true;
+ default:
+ return false;
+ }
+}
+
+//
+// returns true if the operator is for one of the constructors
+//
+bool TIntermOperator::isConstructor() const
+{
+ switch (op) {
+ case EOpConstructVec2:
+ case EOpConstructVec3:
+ case EOpConstructVec4:
+ case EOpConstructMat2:
+ case EOpConstructMat3:
+ case EOpConstructMat4:
+ case EOpConstructFloat:
+ case EOpConstructIVec2:
+ case EOpConstructIVec3:
+ case EOpConstructIVec4:
+ case EOpConstructInt:
+ case EOpConstructBVec2:
+ case EOpConstructBVec3:
+ case EOpConstructBVec4:
+ case EOpConstructBool:
+ case EOpConstructStruct:
+ return true;
+ default:
+ return false;
+ }
+}
+
+//
+// Make sure the type of a unary operator is appropriate for its
+// combination of operation and operand type.
+//
+// Returns false in nothing makes sense.
+//
+bool TIntermUnary::promote(TInfoSink&)
+{
+ switch (op) {
+ case EOpLogicalNot:
+ if (operand->getBasicType() != EbtBool)
+ return false;
+ break;
+ case EOpNegative:
+ case EOpPostIncrement:
+ case EOpPostDecrement:
+ case EOpPreIncrement:
+ case EOpPreDecrement:
+ if (operand->getBasicType() == EbtBool)
+ return false;
+ break;
+
+ // operators for built-ins are already type checked against their prototype
+ case EOpAny:
+ case EOpAll:
+ case EOpVectorLogicalNot:
+ return true;
+
+ default:
+ if (operand->getBasicType() != EbtFloat)
+ return false;
+ }
+
+ setType(operand->getType());
+ type.setQualifier(EvqTemporary);
+
+ return true;
+}
+
+//
+// Establishes the type of the resultant operation, as well as
+// makes the operator the correct one for the operands.
+//
+// Returns false if operator can't work on operands.
+//
+bool TIntermBinary::promote(TInfoSink& infoSink)
+{
+ // This function only handles scalars, vectors, and matrices.
+ if (left->isArray() || right->isArray()) {
+ infoSink.info.message(EPrefixInternalError, getLine(), "Invalid operation for arrays");
+ return false;
+ }
+
+ // GLSL ES 2.0 does not support implicit type casting.
+ // So the basic type should always match.
+ if (left->getBasicType() != right->getBasicType())
+ return false;
+
+ //
+ // Base assumption: just make the type the same as the left
+ // operand. Then only deviations from this need be coded.
+ //
+ setType(left->getType());
+
+ // The result gets promoted to the highest precision.
+ TPrecision higherPrecision = GetHigherPrecision(left->getPrecision(), right->getPrecision());
+ getTypePointer()->setPrecision(higherPrecision);
+
+ // Binary operations results in temporary variables unless both
+ // operands are const.
+ if (left->getQualifier() != EvqConst || right->getQualifier() != EvqConst) {
+ getTypePointer()->setQualifier(EvqTemporary);
+ }
+
+ int size = std::max(left->getNominalSize(), right->getNominalSize());
+
+ //
+ // All scalars. Code after this test assumes this case is removed!
+ //
+ if (size == 1) {
+ switch (op) {
+ //
+ // Promote to conditional
+ //
+ case EOpEqual:
+ case EOpNotEqual:
+ case EOpLessThan:
+ case EOpGreaterThan:
+ case EOpLessThanEqual:
+ case EOpGreaterThanEqual:
+ setType(TType(EbtBool, EbpUndefined));
+ break;
+
+ //
+ // And and Or operate on conditionals
+ //
+ case EOpLogicalAnd:
+ case EOpLogicalOr:
+ // Both operands must be of type bool.
+ if (left->getBasicType() != EbtBool || right->getBasicType() != EbtBool)
+ return false;
+ setType(TType(EbtBool, EbpUndefined));
+ break;
+
+ default:
+ break;
+ }
+ return true;
+ }
+
+ // If we reach here, at least one of the operands is vector or matrix.
+ // The other operand could be a scalar, vector, or matrix.
+ // Are the sizes compatible?
+ //
+ if (left->getNominalSize() != right->getNominalSize()) {
+ // If the nominal size of operands do not match:
+ // One of them must be scalar.
+ if (left->getNominalSize() != 1 && right->getNominalSize() != 1)
+ return false;
+ // Operator cannot be of type pure assignment.
+ if (op == EOpAssign || op == EOpInitialize)
+ return false;
+ }
+
+ //
+ // Can these two operands be combined?
+ //
+ TBasicType basicType = left->getBasicType();
+ switch (op) {
+ case EOpMul:
+ if (!left->isMatrix() && right->isMatrix()) {
+ if (left->isVector())
+ op = EOpVectorTimesMatrix;
+ else {
+ op = EOpMatrixTimesScalar;
+ setType(TType(basicType, higherPrecision, EvqTemporary, size, true));
+ }
+ } else if (left->isMatrix() && !right->isMatrix()) {
+ if (right->isVector()) {
+ op = EOpMatrixTimesVector;
+ setType(TType(basicType, higherPrecision, EvqTemporary, size, false));
+ } else {
+ op = EOpMatrixTimesScalar;
+ }
+ } else if (left->isMatrix() && right->isMatrix()) {
+ op = EOpMatrixTimesMatrix;
+ } else if (!left->isMatrix() && !right->isMatrix()) {
+ if (left->isVector() && right->isVector()) {
+ // leave as component product
+ } else if (left->isVector() || right->isVector()) {
+ op = EOpVectorTimesScalar;
+ setType(TType(basicType, higherPrecision, EvqTemporary, size, false));
+ }
+ } else {
+ infoSink.info.message(EPrefixInternalError, getLine(), "Missing elses");
+ return false;
+ }
+ break;
+ case EOpMulAssign:
+ if (!left->isMatrix() && right->isMatrix()) {
+ if (left->isVector())
+ op = EOpVectorTimesMatrixAssign;
+ else {
+ return false;
+ }
+ } else if (left->isMatrix() && !right->isMatrix()) {
+ if (right->isVector()) {
+ return false;
+ } else {
+ op = EOpMatrixTimesScalarAssign;
+ }
+ } else if (left->isMatrix() && right->isMatrix()) {
+ op = EOpMatrixTimesMatrixAssign;
+ } else if (!left->isMatrix() && !right->isMatrix()) {
+ if (left->isVector() && right->isVector()) {
+ // leave as component product
+ } else if (left->isVector() || right->isVector()) {
+ if (! left->isVector())
+ return false;
+ op = EOpVectorTimesScalarAssign;
+ setType(TType(basicType, higherPrecision, EvqTemporary, size, false));
+ }
+ } else {
+ infoSink.info.message(EPrefixInternalError, getLine(), "Missing elses");
+ return false;
+ }
+ break;
+
+ case EOpAssign:
+ case EOpInitialize:
+ case EOpAdd:
+ case EOpSub:
+ case EOpDiv:
+ case EOpAddAssign:
+ case EOpSubAssign:
+ case EOpDivAssign:
+ if ((left->isMatrix() && right->isVector()) ||
+ (left->isVector() && right->isMatrix()))
+ return false;
+ setType(TType(basicType, higherPrecision, EvqTemporary, size, left->isMatrix() || right->isMatrix()));
+ break;
+
+ case EOpEqual:
+ case EOpNotEqual:
+ case EOpLessThan:
+ case EOpGreaterThan:
+ case EOpLessThanEqual:
+ case EOpGreaterThanEqual:
+ if ((left->isMatrix() && right->isVector()) ||
+ (left->isVector() && right->isMatrix()))
+ return false;
+ setType(TType(EbtBool, EbpUndefined));
+ break;
+
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+bool CompareStruct(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
+{
+ const TFieldList& fields = leftNodeType.getStruct()->fields();
+
+ size_t structSize = fields.size();
+ size_t index = 0;
+
+ for (size_t j = 0; j < structSize; j++) {
+ size_t size = fields[j]->type()->getObjectSize();
+ for (size_t i = 0; i < size; i++) {
+ if (fields[j]->type()->getBasicType() == EbtStruct) {
+ if (!CompareStructure(*(fields[j]->type()), &rightUnionArray[index], &leftUnionArray[index]))
+ return false;
+ } else {
+ if (leftUnionArray[index] != rightUnionArray[index])
+ return false;
+ index++;
+ }
+ }
+ }
+ return true;
+}
+
+bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
+{
+ if (leftNodeType.isArray()) {
+ TType typeWithoutArrayness = leftNodeType;
+ typeWithoutArrayness.clearArrayness();
+
+ size_t arraySize = leftNodeType.getArraySize();
+
+ for (size_t i = 0; i < arraySize; ++i) {
+ size_t offset = typeWithoutArrayness.getObjectSize() * i;
+ if (!CompareStruct(typeWithoutArrayness, &rightUnionArray[offset], &leftUnionArray[offset]))
+ return false;
+ }
+ } else
+ return CompareStruct(leftNodeType, rightUnionArray, leftUnionArray);
+
+ return true;
+}
+
+//
+// The fold functions see if an operation on a constant can be done in place,
+// without generating run-time code.
+//
+// Returns the node to keep using, which may or may not be the node passed in.
+//
+
+TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNode, TInfoSink& infoSink)
+{
+ ConstantUnion *unionArray = getUnionArrayPointer();
+ size_t objectSize = getType().getObjectSize();
+
+ if (constantNode) { // binary operations
+ TIntermConstantUnion *node = constantNode->getAsConstantUnion();
+ ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
+ TType returnType = getType();
+
+ // for a case like float f = 1.2 + vec4(2,3,4,5);
+ if (constantNode->getType().getObjectSize() == 1 && objectSize > 1) {
+ rightUnionArray = new ConstantUnion[objectSize];
+ for (size_t i = 0; i < objectSize; ++i)
+ rightUnionArray[i] = *node->getUnionArrayPointer();
+ returnType = getType();
+ } else if (constantNode->getType().getObjectSize() > 1 && objectSize == 1) {
+ // for a case like float f = vec4(2,3,4,5) + 1.2;
+ unionArray = new ConstantUnion[constantNode->getType().getObjectSize()];
+ for (size_t i = 0; i < constantNode->getType().getObjectSize(); ++i)
+ unionArray[i] = *getUnionArrayPointer();
+ returnType = node->getType();
+ objectSize = constantNode->getType().getObjectSize();
+ }
+
+ ConstantUnion* tempConstArray = 0;
+ TIntermConstantUnion *tempNode;
+
+ bool boolNodeFlag = false;
+ switch(op) {
+ case EOpAdd:
+ tempConstArray = new ConstantUnion[objectSize];
+ {// support MSVC++6.0
+ for (size_t i = 0; i < objectSize; i++)
+ tempConstArray[i] = unionArray[i] + rightUnionArray[i];
+ }
+ break;
+ case EOpSub:
+ tempConstArray = new ConstantUnion[objectSize];
+ {// support MSVC++6.0
+ for (size_t i = 0; i < objectSize; i++)
+ tempConstArray[i] = unionArray[i] - rightUnionArray[i];
+ }
+ break;
+
+ case EOpMul:
+ case EOpVectorTimesScalar:
+ case EOpMatrixTimesScalar:
+ tempConstArray = new ConstantUnion[objectSize];
+ {// support MSVC++6.0
+ for (size_t i = 0; i < objectSize; i++)
+ tempConstArray[i] = unionArray[i] * rightUnionArray[i];
+ }
+ break;
+ case EOpMatrixTimesMatrix:
+ if (getType().getBasicType() != EbtFloat || node->getBasicType() != EbtFloat) {
+ infoSink.info.message(EPrefixInternalError, getLine(), "Constant Folding cannot be done for matrix multiply");
+ return 0;
+ }
+ {// support MSVC++6.0
+ int size = getNominalSize();
+ tempConstArray = new ConstantUnion[size*size];
+ for (int row = 0; row < size; row++) {
+ for (int column = 0; column < size; column++) {
+ tempConstArray[size * column + row].setFConst(0.0f);
+ for (int i = 0; i < size; i++) {
+ tempConstArray[size * column + row].setFConst(tempConstArray[size * column + row].getFConst() + unionArray[i * size + row].getFConst() * (rightUnionArray[column * size + i].getFConst()));
+ }
+ }
+ }
+ }
+ break;
+ case EOpDiv:
+ tempConstArray = new ConstantUnion[objectSize];
+ {// support MSVC++6.0
+ for (size_t i = 0; i < objectSize; i++) {
+ switch (getType().getBasicType()) {
+ case EbtFloat:
+ if (rightUnionArray[i] == 0.0f) {
+ infoSink.info.message(EPrefixWarning, getLine(), "Divide by zero error during constant folding");
+ tempConstArray[i].setFConst(unionArray[i].getFConst() < 0 ? -FLT_MAX : FLT_MAX);
+ } else
+ tempConstArray[i].setFConst(unionArray[i].getFConst() / rightUnionArray[i].getFConst());
+ break;
+
+ case EbtInt:
+ if (rightUnionArray[i] == 0) {
+ infoSink.info.message(EPrefixWarning, getLine(), "Divide by zero error during constant folding");
+ tempConstArray[i].setIConst(INT_MAX);
+ } else
+ tempConstArray[i].setIConst(unionArray[i].getIConst() / rightUnionArray[i].getIConst());
+ break;
+ default:
+ infoSink.info.message(EPrefixInternalError, getLine(), "Constant folding cannot be done for \"/\"");
+ return 0;
+ }
+ }
+ }
+ break;
+
+ case EOpMatrixTimesVector:
+ if (node->getBasicType() != EbtFloat) {
+ infoSink.info.message(EPrefixInternalError, getLine(), "Constant Folding cannot be done for matrix times vector");
+ return 0;
+ }
+ tempConstArray = new ConstantUnion[getNominalSize()];
+
+ {// support MSVC++6.0
+ for (int size = getNominalSize(), i = 0; i < size; i++) {
+ tempConstArray[i].setFConst(0.0f);
+ for (int j = 0; j < size; j++) {
+ tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j*size + i].getFConst()) * rightUnionArray[j].getFConst()));
+ }
+ }
+ }
+
+ tempNode = new TIntermConstantUnion(tempConstArray, node->getType());
+ tempNode->setLine(getLine());
+
+ return tempNode;
+
+ case EOpVectorTimesMatrix:
+ if (getType().getBasicType() != EbtFloat) {
+ infoSink.info.message(EPrefixInternalError, getLine(), "Constant Folding cannot be done for vector times matrix");
+ return 0;
+ }
+
+ tempConstArray = new ConstantUnion[getNominalSize()];
+ {// support MSVC++6.0
+ for (int size = getNominalSize(), i = 0; i < size; i++) {
+ tempConstArray[i].setFConst(0.0f);
+ for (int j = 0; j < size; j++) {
+ tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j].getFConst()) * rightUnionArray[i*size + j].getFConst()));
+ }
+ }
+ }
+ break;
+
+ case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently
+ tempConstArray = new ConstantUnion[objectSize];
+ {// support MSVC++6.0
+ for (size_t i = 0; i < objectSize; i++)
+ tempConstArray[i] = unionArray[i] && rightUnionArray[i];
+ }
+ break;
+
+ case EOpLogicalOr: // this code is written for possible future use, will not get executed currently
+ tempConstArray = new ConstantUnion[objectSize];
+ {// support MSVC++6.0
+ for (size_t i = 0; i < objectSize; i++)
+ tempConstArray[i] = unionArray[i] || rightUnionArray[i];
+ }
+ break;
+
+ case EOpLogicalXor:
+ tempConstArray = new ConstantUnion[objectSize];
+ {// support MSVC++6.0
+ for (size_t i = 0; i < objectSize; i++)
+ switch (getType().getBasicType()) {
+ case EbtBool: tempConstArray[i].setBConst((unionArray[i] == rightUnionArray[i]) ? false : true); break;
+ default: assert(false && "Default missing");
+ }
+ }
+ break;
+
+ case EOpLessThan:
+ assert(objectSize == 1);
+ tempConstArray = new ConstantUnion[1];
+ tempConstArray->setBConst(*unionArray < *rightUnionArray);
+ returnType = TType(EbtBool, EbpUndefined, EvqConst);
+ break;
+ case EOpGreaterThan:
+ assert(objectSize == 1);
+ tempConstArray = new ConstantUnion[1];
+ tempConstArray->setBConst(*unionArray > *rightUnionArray);
+ returnType = TType(EbtBool, EbpUndefined, EvqConst);
+ break;
+ case EOpLessThanEqual:
+ {
+ assert(objectSize == 1);
+ ConstantUnion constant;
+ constant.setBConst(*unionArray > *rightUnionArray);
+ tempConstArray = new ConstantUnion[1];
+ tempConstArray->setBConst(!constant.getBConst());
+ returnType = TType(EbtBool, EbpUndefined, EvqConst);
+ break;
+ }
+ case EOpGreaterThanEqual:
+ {
+ assert(objectSize == 1);
+ ConstantUnion constant;
+ constant.setBConst(*unionArray < *rightUnionArray);
+ tempConstArray = new ConstantUnion[1];
+ tempConstArray->setBConst(!constant.getBConst());
+ returnType = TType(EbtBool, EbpUndefined, EvqConst);
+ break;
+ }
+
+ case EOpEqual:
+ if (getType().getBasicType() == EbtStruct) {
+ if (!CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
+ boolNodeFlag = true;
+ } else {
+ for (size_t i = 0; i < objectSize; i++) {
+ if (unionArray[i] != rightUnionArray[i]) {
+ boolNodeFlag = true;
+ break; // break out of for loop
+ }
+ }
+ }
+
+ tempConstArray = new ConstantUnion[1];
+ if (!boolNodeFlag) {
+ tempConstArray->setBConst(true);
+ }
+ else {
+ tempConstArray->setBConst(false);
+ }
+
+ tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConst));
+ tempNode->setLine(getLine());
+
+ return tempNode;
+
+ case EOpNotEqual:
+ if (getType().getBasicType() == EbtStruct) {
+ if (CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
+ boolNodeFlag = true;
+ } else {
+ for (size_t i = 0; i < objectSize; i++) {
+ if (unionArray[i] == rightUnionArray[i]) {
+ boolNodeFlag = true;
+ break; // break out of for loop
+ }
+ }
+ }
+
+ tempConstArray = new ConstantUnion[1];
+ if (!boolNodeFlag) {
+ tempConstArray->setBConst(true);
+ }
+ else {
+ tempConstArray->setBConst(false);
+ }
+
+ tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConst));
+ tempNode->setLine(getLine());
+
+ return tempNode;
+
+ default:
+ infoSink.info.message(EPrefixInternalError, getLine(), "Invalid operator for constant folding");
+ return 0;
+ }
+ tempNode = new TIntermConstantUnion(tempConstArray, returnType);
+ tempNode->setLine(getLine());
+
+ return tempNode;
+ } else {
+ //
+ // Do unary operations
+ //
+ TIntermConstantUnion *newNode = 0;
+ ConstantUnion* tempConstArray = new ConstantUnion[objectSize];
+ for (size_t i = 0; i < objectSize; i++) {
+ switch(op) {
+ case EOpNegative:
+ switch (getType().getBasicType()) {
+ case EbtFloat: tempConstArray[i].setFConst(-unionArray[i].getFConst()); break;
+ case EbtInt: tempConstArray[i].setIConst(-unionArray[i].getIConst()); break;
+ default:
+ infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
+ return 0;
+ }
+ break;
+ case EOpLogicalNot: // this code is written for possible future use, will not get executed currently
+ switch (getType().getBasicType()) {
+ case EbtBool: tempConstArray[i].setBConst(!unionArray[i].getBConst()); break;
+ default:
+ infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
+ return 0;
+ }
+ break;
+ default:
+ return 0;
+ }
+ }
+ newNode = new TIntermConstantUnion(tempConstArray, getType());
+ newNode->setLine(getLine());
+ return newNode;
+ }
+}
+
+TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node)
+{
+ size_t size = node->getType().getObjectSize();
+
+ ConstantUnion *leftUnionArray = new ConstantUnion[size];
+
+ for (size_t i = 0; i < size; i++) {
+
+ switch (promoteTo) {
+ case EbtFloat:
+ switch (node->getType().getBasicType()) {
+ case EbtInt:
+ leftUnionArray[i].setFConst(static_cast<float>(node->getIConst(i)));
+ break;
+ case EbtBool:
+ leftUnionArray[i].setFConst(static_cast<float>(node->getBConst(i)));
+ break;
+ case EbtFloat:
+ leftUnionArray[i].setFConst(static_cast<float>(node->getFConst(i)));
+ break;
+ default:
+ infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote");
+ return 0;
+ }
+ break;
+ case EbtInt:
+ switch (node->getType().getBasicType()) {
+ case EbtInt:
+ leftUnionArray[i].setIConst(static_cast<int>(node->getIConst(i)));
+ break;
+ case EbtBool:
+ leftUnionArray[i].setIConst(static_cast<int>(node->getBConst(i)));
+ break;
+ case EbtFloat:
+ leftUnionArray[i].setIConst(static_cast<int>(node->getFConst(i)));
+ break;
+ default:
+ infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote");
+ return 0;
+ }
+ break;
+ case EbtBool:
+ switch (node->getType().getBasicType()) {
+ case EbtInt:
+ leftUnionArray[i].setBConst(node->getIConst(i) != 0);
+ break;
+ case EbtBool:
+ leftUnionArray[i].setBConst(node->getBConst(i));
+ break;
+ case EbtFloat:
+ leftUnionArray[i].setBConst(node->getFConst(i) != 0.0f);
+ break;
+ default:
+ infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote");
+ return 0;
+ }
+
+ break;
+ default:
+ infoSink.info.message(EPrefixInternalError, node->getLine(), "Incorrect data type found");
+ return 0;
+ }
+
+ }
+
+ const TType& t = node->getType();
+
+ return addConstantUnion(leftUnionArray, TType(promoteTo, t.getPrecision(), t.getQualifier(), t.getNominalSize(), t.isMatrix(), t.isArray()), node->getLine());
+}
+
+// static
+TString TIntermTraverser::hash(const TString& name, ShHashFunction64 hashFunction)
+{
+ if (hashFunction == NULL || name.empty())
+ return name;
+ khronos_uint64_t number = (*hashFunction)(name.c_str(), name.length());
+ TStringStream stream;
+ stream << HASHED_NAME_PREFIX << std::hex << number;
+ TString hashedName = stream.str();
+ return hashedName;
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Intermediate.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorMMaph"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/MMap.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/MMap.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/MMap.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,56 @@
</span><ins>+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef _MMAP_INCLUDED_
+#define _MMAP_INCLUDED_
+
+//
+// Encapsulate memory mapped files
+//
+
+class TMMap {
+public:
+ TMMap(const char* fileName) :
+ fSize(-1), // -1 is the error value returned by GetFileSize()
+ fp(NULL),
+ fBuff(0) // 0 is the error value returned by MapViewOfFile()
+ {
+ if ((fp = fopen(fileName, "r")) == NULL)
+ return;
+ char c = getc(fp);
+ fSize = 0;
+ while (c != EOF) {
+ fSize++;
+ c = getc(fp);
+ }
+ if (c == EOF)
+ fSize++;
+ rewind(fp);
+ fBuff = (char*)malloc(sizeof(char) * fSize);
+ int count = 0;
+ c = getc(fp);
+ while (c != EOF) {
+ fBuff[count++] = c;
+ c = getc(fp);
+ }
+ fBuff[count++] = c;
+ }
+
+ char* getData() { return fBuff; }
+ int getSize() { return fSize; }
+
+ ~TMMap() {
+ if (fp != NULL)
+ fclose(fp);
+ }
+
+private:
+ int fSize; // size of file to map in
+ FILE *fp;
+ char* fBuff; // the actual data;
+};
+
+#endif // _MMAP_INCLUDED_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/MMap.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorMapLongVariableNamescpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/MapLongVariableNames.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/MapLongVariableNames.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/MapLongVariableNames.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,115 @@
</span><ins>+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/MapLongVariableNames.h"
+
+namespace {
+
+TString mapLongName(size_t id, const TString& name, bool isGlobal)
+{
+ ASSERT(name.size() > MAX_SHORTENED_IDENTIFIER_SIZE);
+ TStringStream stream;
+ stream << "webgl_";
+ if (isGlobal)
+ stream << "g";
+ stream << id;
+ if (name[0] != '_')
+ stream << "_";
+ stream << name.substr(0, MAX_SHORTENED_IDENTIFIER_SIZE - stream.str().size());
+ return stream.str();
+}
+
+LongNameMap* gLongNameMapInstance = NULL;
+
+} // anonymous namespace
+
+LongNameMap::LongNameMap()
+ : refCount(0)
+{
+}
+
+LongNameMap::~LongNameMap()
+{
+}
+
+// static
+LongNameMap* LongNameMap::GetInstance()
+{
+ if (gLongNameMapInstance == NULL)
+ gLongNameMapInstance = new LongNameMap;
+ gLongNameMapInstance->refCount++;
+ return gLongNameMapInstance;
+}
+
+void LongNameMap::Release()
+{
+ ASSERT(gLongNameMapInstance == this);
+ ASSERT(refCount > 0);
+ refCount--;
+ if (refCount == 0) {
+ delete gLongNameMapInstance;
+ gLongNameMapInstance = NULL;
+ }
+}
+
+const char* LongNameMap::Find(const char* originalName) const
+{
+ std::map<std::string, std::string>::const_iterator it = mLongNameMap.find(
+ originalName);
+ if (it != mLongNameMap.end())
+ return (*it).second.c_str();
+ return NULL;
+}
+
+void LongNameMap::Insert(const char* originalName, const char* mappedName)
+{
+ mLongNameMap.insert(std::map<std::string, std::string>::value_type(
+ originalName, mappedName));
+}
+
+size_t LongNameMap::Size() const
+{
+ return mLongNameMap.size();
+}
+
+MapLongVariableNames::MapLongVariableNames(LongNameMap* globalMap)
+{
+ ASSERT(globalMap);
+ mGlobalMap = globalMap;
+}
+
+void MapLongVariableNames::visitSymbol(TIntermSymbol* symbol)
+{
+ ASSERT(symbol != NULL);
+ if (symbol->getSymbol().size() > MAX_SHORTENED_IDENTIFIER_SIZE) {
+ switch (symbol->getQualifier()) {
+ case EvqVaryingIn:
+ case EvqVaryingOut:
+ case EvqInvariantVaryingIn:
+ case EvqInvariantVaryingOut:
+ case EvqUniform:
+ symbol->setSymbol(
+ mapGlobalLongName(symbol->getSymbol()));
+ break;
+ default:
+ symbol->setSymbol(
+ mapLongName(symbol->getId(), symbol->getSymbol(), false));
+ break;
+ };
+ }
+}
+
+TString MapLongVariableNames::mapGlobalLongName(const TString& name)
+{
+ ASSERT(mGlobalMap);
+ const char* mappedName = mGlobalMap->Find(name.c_str());
+ if (mappedName != NULL)
+ return mappedName;
+ size_t id = mGlobalMap->Size();
+ TString rt = mapLongName(id, name, true);
+ mGlobalMap->Insert(name.c_str(), rt.c_str());
+ return rt;
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/MapLongVariableNames.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorMapLongVariableNamesh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/MapLongVariableNames.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/MapLongVariableNames.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/MapLongVariableNames.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,58 @@
</span><ins>+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_MAP_LONG_VARIABLE_NAMES_H_
+#define COMPILER_MAP_LONG_VARIABLE_NAMES_H_
+
+#include "GLSLANG/ShaderLang.h"
+
+#include "compiler/translator/intermediate.h"
+#include "compiler/translator/VariableInfo.h"
+
+// This size does not include '\0' in the end.
+#define MAX_SHORTENED_IDENTIFIER_SIZE 32
+
+// This is a ref-counted singleton. GetInstance() returns a pointer to the
+// singleton, and after use, call Release(). GetInstance() and Release() should
+// be paired.
+class LongNameMap {
+public:
+ static LongNameMap* GetInstance();
+ void Release();
+
+ // Return the mapped name if <originalName, mappedName> is in the map;
+ // otherwise, return NULL.
+ const char* Find(const char* originalName) const;
+
+ // Insert a pair into the map.
+ void Insert(const char* originalName, const char* mappedName);
+
+ // Return the number of entries in the map.
+ size_t Size() const;
+
+private:
+ LongNameMap();
+ ~LongNameMap();
+
+ size_t refCount;
+ std::map<std::string, std::string> mLongNameMap;
+};
+
+// Traverses intermediate tree to map attributes and uniforms names that are
+// longer than MAX_SHORTENED_IDENTIFIER_SIZE to MAX_SHORTENED_IDENTIFIER_SIZE.
+class MapLongVariableNames : public TIntermTraverser {
+public:
+ MapLongVariableNames(LongNameMap* globalMap);
+
+ virtual void visitSymbol(TIntermSymbol*);
+
+private:
+ TString mapGlobalLongName(const TString& name);
+
+ LongNameMap* mGlobalMap;
+};
+
+#endif // COMPILER_MAP_LONG_VARIABLE_NAMES_H_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/MapLongVariableNames.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorNodeSearchh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/NodeSearch.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/NodeSearch.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/NodeSearch.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,80 @@
</span><ins>+//
+// Copyright (c) 2002-2013 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.
+//
+// NodeSearch.h: Utilities for searching translator node graphs
+//
+
+#ifndef TRANSLATOR_NODESEARCH_H_
+#define TRANSLATOR_NODESEARCH_H_
+
+#include "compiler/translator/intermediate.h"
+
+namespace sh
+{
+
+template <class Parent>
+class NodeSearchTraverser : public TIntermTraverser
+{
+ public:
+ NodeSearchTraverser()
+ : mFound(false)
+ {}
+
+ bool found() const { return mFound; }
+
+ static bool search(TIntermNode *node)
+ {
+ Parent searchTraverser;
+ node->traverse(&searchTraverser);
+ return searchTraverser.found();
+ }
+
+ protected:
+ bool mFound;
+};
+
+class FindDiscard : public NodeSearchTraverser<FindDiscard>
+{
+ public:
+ virtual bool visitBranch(Visit visit, TIntermBranch *node)
+ {
+ switch (node->getFlowOp())
+ {
+ case EOpKill:
+ mFound = true;
+ break;
+
+ default: break;
+ }
+
+ return !mFound;
+ }
+};
+
+class FindSideEffectRewriting : public NodeSearchTraverser<FindSideEffectRewriting>
+{
+ public:
+ virtual bool visitBinary(Visit visit, TIntermBinary *node)
+ {
+ switch (node->getOp())
+ {
+ case EOpLogicalOr:
+ case EOpLogicalAnd:
+ if (node->getRight()->hasSideEffects())
+ {
+ mFound = true;
+ }
+ break;
+
+ default: break;
+ }
+
+ return !mFound;
+ }
+};
+
+}
+
+#endif // TRANSLATOR_NODESEARCH_H_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/NodeSearch.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorOutputESSLcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/OutputESSL.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/OutputESSL.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/OutputESSL.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,26 @@
</span><ins>+//
+// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/OutputESSL.h"
+
+TOutputESSL::TOutputESSL(TInfoSinkBase& objSink,
+ ShArrayIndexClampingStrategy clampingStrategy,
+ ShHashFunction64 hashFunction,
+ NameMap& nameMap,
+ TSymbolTable& symbolTable)
+ : TOutputGLSLBase(objSink, clampingStrategy, hashFunction, nameMap, symbolTable)
+{
+}
+
+bool TOutputESSL::writeVariablePrecision(TPrecision precision)
+{
+ if (precision == EbpUndefined)
+ return false;
+
+ TInfoSinkBase& out = objSink();
+ out << getPrecisionString(precision);
+ return true;
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/OutputESSL.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorOutputESSLh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/OutputESSL.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/OutputESSL.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/OutputESSL.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,25 @@
</span><ins>+//
+// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef CROSSCOMPILERGLSL_OUTPUTESSL_H_
+#define CROSSCOMPILERGLSL_OUTPUTESSL_H_
+
+#include "compiler/translator/OutputGLSLBase.h"
+
+class TOutputESSL : public TOutputGLSLBase
+{
+public:
+ TOutputESSL(TInfoSinkBase& objSink,
+ ShArrayIndexClampingStrategy clampingStrategy,
+ ShHashFunction64 hashFunction,
+ NameMap& nameMap,
+ TSymbolTable& symbolTable);
+
+protected:
+ virtual bool writeVariablePrecision(TPrecision precision);
+};
+
+#endif // CROSSCOMPILERGLSL_OUTPUTESSL_H_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/OutputESSL.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorOutputGLSLcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/OutputGLSL.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/OutputGLSL.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/OutputGLSL.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,35 @@
</span><ins>+//
+// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/OutputGLSL.h"
+
+TOutputGLSL::TOutputGLSL(TInfoSinkBase& objSink,
+ ShArrayIndexClampingStrategy clampingStrategy,
+ ShHashFunction64 hashFunction,
+ NameMap& nameMap,
+ TSymbolTable& symbolTable)
+ : TOutputGLSLBase(objSink, clampingStrategy, hashFunction, nameMap, symbolTable)
+{
+}
+
+bool TOutputGLSL::writeVariablePrecision(TPrecision)
+{
+ return false;
+}
+
+void TOutputGLSL::visitSymbol(TIntermSymbol* node)
+{
+ TInfoSinkBase& out = objSink();
+
+ if (node->getSymbol() == "gl_FragDepthEXT")
+ {
+ out << "gl_FragDepth";
+ }
+ else
+ {
+ TOutputGLSLBase::visitSymbol(node);
+ }
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/OutputGLSL.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorOutputGLSLh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/OutputGLSL.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/OutputGLSL.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/OutputGLSL.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,26 @@
</span><ins>+//
+// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef CROSSCOMPILERGLSL_OUTPUTGLSL_H_
+#define CROSSCOMPILERGLSL_OUTPUTGLSL_H_
+
+#include "compiler/translator/OutputGLSLBase.h"
+
+class TOutputGLSL : public TOutputGLSLBase
+{
+public:
+ TOutputGLSL(TInfoSinkBase& objSink,
+ ShArrayIndexClampingStrategy clampingStrategy,
+ ShHashFunction64 hashFunction,
+ NameMap& nameMap,
+ TSymbolTable& symbolTable);
+
+protected:
+ virtual bool writeVariablePrecision(TPrecision);
+ virtual void visitSymbol(TIntermSymbol* node);
+};
+
+#endif // CROSSCOMPILERGLSL_OUTPUTGLSL_H_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/OutputGLSL.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorOutputGLSLBasecpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/OutputGLSLBase.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/OutputGLSLBase.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/OutputGLSLBase.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,817 @@
</span><ins>+//
+// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/OutputGLSLBase.h"
+#include "compiler/translator/compilerdebug.h"
+
+#include <cfloat>
+
+namespace
+{
+TString arrayBrackets(const TType& type)
+{
+ ASSERT(type.isArray());
+ TInfoSinkBase out;
+ out << "[" << type.getArraySize() << "]";
+ return TString(out.c_str());
+}
+
+bool isSingleStatement(TIntermNode* node) {
+ if (const TIntermAggregate* aggregate = node->getAsAggregate())
+ {
+ return (aggregate->getOp() != EOpFunction) &&
+ (aggregate->getOp() != EOpSequence);
+ }
+ else if (const TIntermSelection* selection = node->getAsSelectionNode())
+ {
+ // Ternary operators are usually part of an assignment operator.
+ // This handles those rare cases in which they are all by themselves.
+ return selection->usesTernaryOperator();
+ }
+ else if (node->getAsLoopNode())
+ {
+ return false;
+ }
+ return true;
+}
+} // namespace
+
+TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase& objSink,
+ ShArrayIndexClampingStrategy clampingStrategy,
+ ShHashFunction64 hashFunction,
+ NameMap& nameMap,
+ TSymbolTable& symbolTable)
+ : TIntermTraverser(true, true, true),
+ mObjSink(objSink),
+ mDeclaringVariables(false),
+ mClampingStrategy(clampingStrategy),
+ mHashFunction(hashFunction),
+ mNameMap(nameMap),
+ mSymbolTable(symbolTable)
+{
+}
+
+void TOutputGLSLBase::writeTriplet(Visit visit, const char* preStr, const char* inStr, const char* postStr)
+{
+ TInfoSinkBase& out = objSink();
+ if (visit == PreVisit && preStr)
+ {
+ out << preStr;
+ }
+ else if (visit == InVisit && inStr)
+ {
+ out << inStr;
+ }
+ else if (visit == PostVisit && postStr)
+ {
+ out << postStr;
+ }
+}
+
+void TOutputGLSLBase::writeVariableType(const TType& type)
+{
+ TInfoSinkBase& out = objSink();
+ TQualifier qualifier = type.getQualifier();
+ // TODO(alokp): Validate qualifier for variable declarations.
+ if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal))
+ out << type.getQualifierString() << " ";
+ // Declare the struct if we have not done so already.
+ if ((type.getBasicType() == EbtStruct) && !structDeclared(type.getStruct()))
+ {
+ declareStruct(type.getStruct());
+ }
+ else
+ {
+ if (writeVariablePrecision(type.getPrecision()))
+ out << " ";
+ out << getTypeName(type);
+ }
+}
+
+void TOutputGLSLBase::writeFunctionParameters(const TIntermSequence& args)
+{
+ TInfoSinkBase& out = objSink();
+ for (TIntermSequence::const_iterator iter = args.begin();
+ iter != args.end(); ++iter)
+ {
+ const TIntermSymbol* arg = (*iter)->getAsSymbolNode();
+ ASSERT(arg != NULL);
+
+ const TType& type = arg->getType();
+ writeVariableType(type);
+
+ const TString& name = arg->getSymbol();
+ if (!name.empty())
+ out << " " << hashName(name);
+ if (type.isArray())
+ out << arrayBrackets(type);
+
+ // Put a comma if this is not the last argument.
+ if (iter != args.end() - 1)
+ out << ", ";
+ }
+}
+
+const ConstantUnion* TOutputGLSLBase::writeConstantUnion(const TType& type,
+ const ConstantUnion* pConstUnion)
+{
+ TInfoSinkBase& out = objSink();
+
+ if (type.getBasicType() == EbtStruct)
+ {
+ const TStructure* structure = type.getStruct();
+ out << hashName(structure->name()) << "(";
+
+ const TFieldList& fields = structure->fields();
+ for (size_t i = 0; i < fields.size(); ++i)
+ {
+ const TType* fieldType = fields[i]->type();
+ ASSERT(fieldType != NULL);
+ pConstUnion = writeConstantUnion(*fieldType, pConstUnion);
+ if (i != fields.size() - 1) out << ", ";
+ }
+ out << ")";
+ }
+ else
+ {
+ size_t size = type.getObjectSize();
+ bool writeType = size > 1;
+ if (writeType) out << getTypeName(type) << "(";
+ for (size_t i = 0; i < size; ++i, ++pConstUnion)
+ {
+ switch (pConstUnion->getType())
+ {
+ case EbtFloat: out << std::min(FLT_MAX, std::max(-FLT_MAX, pConstUnion->getFConst())); break;
+ case EbtInt: out << pConstUnion->getIConst(); break;
+ case EbtBool: out << pConstUnion->getBConst(); break;
+ default: UNREACHABLE();
+ }
+ if (i != size - 1) out << ", ";
+ }
+ if (writeType) out << ")";
+ }
+ return pConstUnion;
+}
+
+void TOutputGLSLBase::visitSymbol(TIntermSymbol* node)
+{
+ TInfoSinkBase& out = objSink();
+ if (mLoopUnroll.NeedsToReplaceSymbolWithValue(node))
+ out << mLoopUnroll.GetLoopIndexValue(node);
+ else
+ out << hashVariableName(node->getSymbol());
+
+ if (mDeclaringVariables && node->getType().isArray())
+ out << arrayBrackets(node->getType());
+}
+
+void TOutputGLSLBase::visitConstantUnion(TIntermConstantUnion* node)
+{
+ writeConstantUnion(node->getType(), node->getUnionArrayPointer());
+}
+
+bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary* node)
+{
+ bool visitChildren = true;
+ TInfoSinkBase& out = objSink();
+ switch (node->getOp())
+ {
+ case EOpInitialize:
+ if (visit == InVisit)
+ {
+ out << " = ";
+ // RHS of initialize is not being declared.
+ mDeclaringVariables = false;
+ }
+ break;
+ case EOpAssign: writeTriplet(visit, "(", " = ", ")"); break;
+ case EOpAddAssign: writeTriplet(visit, "(", " += ", ")"); break;
+ case EOpSubAssign: writeTriplet(visit, "(", " -= ", ")"); break;
+ case EOpDivAssign: writeTriplet(visit, "(", " /= ", ")"); break;
+ // Notice the fall-through.
+ case EOpMulAssign:
+ case EOpVectorTimesMatrixAssign:
+ case EOpVectorTimesScalarAssign:
+ case EOpMatrixTimesScalarAssign:
+ case EOpMatrixTimesMatrixAssign:
+ writeTriplet(visit, "(", " *= ", ")");
+ break;
+
+ case EOpIndexDirect:
+ writeTriplet(visit, NULL, "[", "]");
+ break;
+ case EOpIndexIndirect:
+ if (node->getAddIndexClamp())
+ {
+ if (visit == InVisit)
+ {
+ if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC) {
+ out << "[int(clamp(float(";
+ } else {
+ out << "[webgl_int_clamp(";
+ }
+ }
+ else if (visit == PostVisit)
+ {
+ int maxSize;
+ TIntermTyped *left = node->getLeft();
+ TType leftType = left->getType();
+
+ if (left->isArray())
+ {
+ // The shader will fail validation if the array length is not > 0.
+ maxSize = leftType.getArraySize() - 1;
+ }
+ else
+ {
+ maxSize = leftType.getNominalSize() - 1;
+ }
+
+ if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC) {
+ out << "), 0.0, float(" << maxSize << ")))]";
+ } else {
+ out << ", 0, " << maxSize << ")]";
+ }
+ }
+ }
+ else
+ {
+ writeTriplet(visit, NULL, "[", "]");
+ }
+ break;
+ case EOpIndexDirectStruct:
+ if (visit == InVisit)
+ {
+ // Here we are writing out "foo.bar", where "foo" is struct
+ // and "bar" is field. In AST, it is represented as a binary
+ // node, where left child represents "foo" and right child "bar".
+ // The node itself represents ".". The struct field "bar" is
+ // actually stored as an index into TStructure::fields.
+ out << ".";
+ const TStructure* structure = node->getLeft()->getType().getStruct();
+ const TIntermConstantUnion* index = node->getRight()->getAsConstantUnion();
+ const TField* field = structure->fields()[index->getIConst(0)];
+
+ TString fieldName = field->name();
+ if (!mSymbolTable.findBuiltIn(structure->name()))
+ fieldName = hashName(fieldName);
+
+ out << fieldName;
+ visitChildren = false;
+ }
+ break;
+ case EOpVectorSwizzle:
+ if (visit == InVisit)
+ {
+ out << ".";
+ TIntermAggregate* rightChild = node->getRight()->getAsAggregate();
+ TIntermSequence& sequence = rightChild->getSequence();
+ for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); ++sit)
+ {
+ TIntermConstantUnion* element = (*sit)->getAsConstantUnion();
+ ASSERT(element->getBasicType() == EbtInt);
+ ASSERT(element->getNominalSize() == 1);
+ const ConstantUnion& data = element->getUnionArrayPointer()[0];
+ ASSERT(data.getType() == EbtInt);
+ switch (data.getIConst())
+ {
+ case 0: out << "x"; break;
+ case 1: out << "y"; break;
+ case 2: out << "z"; break;
+ case 3: out << "w"; break;
+ default: UNREACHABLE(); break;
+ }
+ }
+ visitChildren = false;
+ }
+ break;
+
+ case EOpAdd: writeTriplet(visit, "(", " + ", ")"); break;
+ case EOpSub: writeTriplet(visit, "(", " - ", ")"); break;
+ case EOpMul: writeTriplet(visit, "(", " * ", ")"); break;
+ case EOpDiv: writeTriplet(visit, "(", " / ", ")"); break;
+ case EOpMod: UNIMPLEMENTED(); break;
+ case EOpEqual: writeTriplet(visit, "(", " == ", ")"); break;
+ case EOpNotEqual: writeTriplet(visit, "(", " != ", ")"); break;
+ case EOpLessThan: writeTriplet(visit, "(", " < ", ")"); break;
+ case EOpGreaterThan: writeTriplet(visit, "(", " > ", ")"); break;
+ case EOpLessThanEqual: writeTriplet(visit, "(", " <= ", ")"); break;
+ case EOpGreaterThanEqual: writeTriplet(visit, "(", " >= ", ")"); break;
+
+ // Notice the fall-through.
+ case EOpVectorTimesScalar:
+ case EOpVectorTimesMatrix:
+ case EOpMatrixTimesVector:
+ case EOpMatrixTimesScalar:
+ case EOpMatrixTimesMatrix:
+ writeTriplet(visit, "(", " * ", ")");
+ break;
+
+ case EOpLogicalOr: writeTriplet(visit, "(", " || ", ")"); break;
+ case EOpLogicalXor: writeTriplet(visit, "(", " ^^ ", ")"); break;
+ case EOpLogicalAnd: writeTriplet(visit, "(", " && ", ")"); break;
+ default: UNREACHABLE(); break;
+ }
+
+ return visitChildren;
+}
+
+bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary* node)
+{
+ TString preString;
+ TString postString = ")";
+
+ switch (node->getOp())
+ {
+ case EOpNegative: preString = "(-"; break;
+ case EOpVectorLogicalNot: preString = "not("; break;
+ case EOpLogicalNot: preString = "(!"; break;
+
+ case EOpPostIncrement: preString = "("; postString = "++)"; break;
+ case EOpPostDecrement: preString = "("; postString = "--)"; break;
+ case EOpPreIncrement: preString = "(++"; break;
+ case EOpPreDecrement: preString = "(--"; break;
+
+ case EOpConvIntToBool:
+ case EOpConvFloatToBool:
+ switch (node->getOperand()->getType().getNominalSize())
+ {
+ case 1: preString = "bool("; break;
+ case 2: preString = "bvec2("; break;
+ case 3: preString = "bvec3("; break;
+ case 4: preString = "bvec4("; break;
+ default: UNREACHABLE();
+ }
+ break;
+ case EOpConvBoolToFloat:
+ case EOpConvIntToFloat:
+ switch (node->getOperand()->getType().getNominalSize())
+ {
+ case 1: preString = "float("; break;
+ case 2: preString = "vec2("; break;
+ case 3: preString = "vec3("; break;
+ case 4: preString = "vec4("; break;
+ default: UNREACHABLE();
+ }
+ break;
+ case EOpConvFloatToInt:
+ case EOpConvBoolToInt:
+ switch (node->getOperand()->getType().getNominalSize())
+ {
+ case 1: preString = "int("; break;
+ case 2: preString = "ivec2("; break;
+ case 3: preString = "ivec3("; break;
+ case 4: preString = "ivec4("; break;
+ default: UNREACHABLE();
+ }
+ break;
+
+ case EOpRadians: preString = "radians("; break;
+ case EOpDegrees: preString = "degrees("; break;
+ case EOpSin: preString = "sin("; break;
+ case EOpCos: preString = "cos("; break;
+ case EOpTan: preString = "tan("; break;
+ case EOpAsin: preString = "asin("; break;
+ case EOpAcos: preString = "acos("; break;
+ case EOpAtan: preString = "atan("; break;
+
+ case EOpExp: preString = "exp("; break;
+ case EOpLog: preString = "log("; break;
+ case EOpExp2: preString = "exp2("; break;
+ case EOpLog2: preString = "log2("; break;
+ case EOpSqrt: preString = "sqrt("; break;
+ case EOpInverseSqrt: preString = "inversesqrt("; break;
+
+ case EOpAbs: preString = "abs("; break;
+ case EOpSign: preString = "sign("; break;
+ case EOpFloor: preString = "floor("; break;
+ case EOpCeil: preString = "ceil("; break;
+ case EOpFract: preString = "fract("; break;
+
+ case EOpLength: preString = "length("; break;
+ case EOpNormalize: preString = "normalize("; break;
+
+ case EOpDFdx: preString = "dFdx("; break;
+ case EOpDFdy: preString = "dFdy("; break;
+ case EOpFwidth: preString = "fwidth("; break;
+
+ case EOpAny: preString = "any("; break;
+ case EOpAll: preString = "all("; break;
+
+ default: UNREACHABLE(); break;
+ }
+
+ if (visit == PreVisit && node->getUseEmulatedFunction())
+ preString = BuiltInFunctionEmulator::GetEmulatedFunctionName(preString);
+ writeTriplet(visit, preString.c_str(), NULL, postString.c_str());
+
+ return true;
+}
+
+bool TOutputGLSLBase::visitSelection(Visit visit, TIntermSelection* node)
+{
+ TInfoSinkBase& out = objSink();
+
+ if (node->usesTernaryOperator())
+ {
+ // Notice two brackets at the beginning and end. The outer ones
+ // encapsulate the whole ternary expression. This preserves the
+ // order of precedence when ternary expressions are used in a
+ // compound expression, i.e., c = 2 * (a < b ? 1 : 2).
+ out << "((";
+ node->getCondition()->traverse(this);
+ out << ") ? (";
+ node->getTrueBlock()->traverse(this);
+ out << ") : (";
+ node->getFalseBlock()->traverse(this);
+ out << "))";
+ }
+ else
+ {
+ out << "if (";
+ node->getCondition()->traverse(this);
+ out << ")\n";
+
+ incrementDepth(node);
+ visitCodeBlock(node->getTrueBlock());
+
+ if (node->getFalseBlock())
+ {
+ out << "else\n";
+ visitCodeBlock(node->getFalseBlock());
+ }
+ decrementDepth();
+ }
+ return false;
+}
+
+bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate* node)
+{
+ bool visitChildren = true;
+ TInfoSinkBase& out = objSink();
+ TString preString;
+ bool delayedWrite = false;
+ switch (node->getOp())
+ {
+ case EOpSequence: {
+ // Scope the sequences except when at the global scope.
+ if (depth > 0) out << "{\n";
+
+ incrementDepth(node);
+ const TIntermSequence& sequence = node->getSequence();
+ for (TIntermSequence::const_iterator iter = sequence.begin();
+ iter != sequence.end(); ++iter)
+ {
+ TIntermNode* node = *iter;
+ ASSERT(node != NULL);
+ node->traverse(this);
+
+ if (isSingleStatement(node))
+ out << ";\n";
+ }
+ decrementDepth();
+
+ // Scope the sequences except when at the global scope.
+ if (depth > 0) out << "}\n";
+ visitChildren = false;
+ break;
+ }
+ case EOpPrototype: {
+ // Function declaration.
+ ASSERT(visit == PreVisit);
+ writeVariableType(node->getType());
+ out << " " << hashName(node->getName());
+
+ out << "(";
+ writeFunctionParameters(node->getSequence());
+ out << ")";
+
+ visitChildren = false;
+ break;
+ }
+ case EOpFunction: {
+ // Function definition.
+ ASSERT(visit == PreVisit);
+ writeVariableType(node->getType());
+ out << " " << hashFunctionName(node->getName());
+
+ incrementDepth(node);
+ // Function definition node contains one or two children nodes
+ // representing function parameters and function body. The latter
+ // is not present in case of empty function bodies.
+ const TIntermSequence& sequence = node->getSequence();
+ ASSERT((sequence.size() == 1) || (sequence.size() == 2));
+ TIntermSequence::const_iterator seqIter = sequence.begin();
+
+ // Traverse function parameters.
+ TIntermAggregate* params = (*seqIter)->getAsAggregate();
+ ASSERT(params != NULL);
+ ASSERT(params->getOp() == EOpParameters);
+ params->traverse(this);
+
+ // Traverse function body.
+ TIntermAggregate* body = ++seqIter != sequence.end() ?
+ (*seqIter)->getAsAggregate() : NULL;
+ visitCodeBlock(body);
+ decrementDepth();
+
+ // Fully processed; no need to visit children.
+ visitChildren = false;
+ break;
+ }
+ case EOpFunctionCall:
+ // Function call.
+ if (visit == PreVisit)
+ {
+ out << hashFunctionName(node->getName()) << "(";
+ }
+ else if (visit == InVisit)
+ {
+ out << ", ";
+ }
+ else
+ {
+ out << ")";
+ }
+ break;
+ case EOpParameters: {
+ // Function parameters.
+ ASSERT(visit == PreVisit);
+ out << "(";
+ writeFunctionParameters(node->getSequence());
+ out << ")";
+ visitChildren = false;
+ break;
+ }
+ case EOpDeclaration: {
+ // Variable declaration.
+ if (visit == PreVisit)
+ {
+ const TIntermSequence& sequence = node->getSequence();
+ const TIntermTyped* variable = sequence.front()->getAsTyped();
+ writeVariableType(variable->getType());
+ out << " ";
+ mDeclaringVariables = true;
+ }
+ else if (visit == InVisit)
+ {
+ out << ", ";
+ mDeclaringVariables = true;
+ }
+ else
+ {
+ mDeclaringVariables = false;
+ }
+ break;
+ }
+ case EOpConstructFloat: writeTriplet(visit, "float(", NULL, ")"); break;
+ case EOpConstructVec2: writeTriplet(visit, "vec2(", ", ", ")"); break;
+ case EOpConstructVec3: writeTriplet(visit, "vec3(", ", ", ")"); break;
+ case EOpConstructVec4: writeTriplet(visit, "vec4(", ", ", ")"); break;
+ case EOpConstructBool: writeTriplet(visit, "bool(", NULL, ")"); break;
+ case EOpConstructBVec2: writeTriplet(visit, "bvec2(", ", ", ")"); break;
+ case EOpConstructBVec3: writeTriplet(visit, "bvec3(", ", ", ")"); break;
+ case EOpConstructBVec4: writeTriplet(visit, "bvec4(", ", ", ")"); break;
+ case EOpConstructInt: writeTriplet(visit, "int(", NULL, ")"); break;
+ case EOpConstructIVec2: writeTriplet(visit, "ivec2(", ", ", ")"); break;
+ case EOpConstructIVec3: writeTriplet(visit, "ivec3(", ", ", ")"); break;
+ case EOpConstructIVec4: writeTriplet(visit, "ivec4(", ", ", ")"); break;
+ case EOpConstructMat2: writeTriplet(visit, "mat2(", ", ", ")"); break;
+ case EOpConstructMat3: writeTriplet(visit, "mat3(", ", ", ")"); break;
+ case EOpConstructMat4: writeTriplet(visit, "mat4(", ", ", ")"); break;
+ case EOpConstructStruct:
+ if (visit == PreVisit)
+ {
+ const TType& type = node->getType();
+ ASSERT(type.getBasicType() == EbtStruct);
+ out << hashName(type.getStruct()->name()) << "(";
+ }
+ else if (visit == InVisit)
+ {
+ out << ", ";
+ }
+ else
+ {
+ out << ")";
+ }
+ break;
+
+ case EOpLessThan: preString = "lessThan("; delayedWrite = true; break;
+ case EOpGreaterThan: preString = "greaterThan("; delayedWrite = true; break;
+ case EOpLessThanEqual: preString = "lessThanEqual("; delayedWrite = true; break;
+ case EOpGreaterThanEqual: preString = "greaterThanEqual("; delayedWrite = true; break;
+ case EOpVectorEqual: preString = "equal("; delayedWrite = true; break;
+ case EOpVectorNotEqual: preString = "notEqual("; delayedWrite = true; break;
+ case EOpComma: writeTriplet(visit, NULL, ", ", NULL); break;
+
+ case EOpMod: preString = "mod("; delayedWrite = true; break;
+ case EOpPow: preString = "pow("; delayedWrite = true; break;
+ case EOpAtan: preString = "atan("; delayedWrite = true; break;
+ case EOpMin: preString = "min("; delayedWrite = true; break;
+ case EOpMax: preString = "max("; delayedWrite = true; break;
+ case EOpClamp: preString = "clamp("; delayedWrite = true; break;
+ case EOpMix: preString = "mix("; delayedWrite = true; break;
+ case EOpStep: preString = "step("; delayedWrite = true; break;
+ case EOpSmoothStep: preString = "smoothstep("; delayedWrite = true; break;
+
+ case EOpDistance: preString = "distance("; delayedWrite = true; break;
+ case EOpDot: preString = "dot("; delayedWrite = true; break;
+ case EOpCross: preString = "cross("; delayedWrite = true; break;
+ case EOpFaceForward: preString = "faceforward("; delayedWrite = true; break;
+ case EOpReflect: preString = "reflect("; delayedWrite = true; break;
+ case EOpRefract: preString = "refract("; delayedWrite = true; break;
+ case EOpMul: preString = "matrixCompMult("; delayedWrite = true; break;
+
+ default: UNREACHABLE(); break;
+ }
+ if (delayedWrite && visit == PreVisit && node->getUseEmulatedFunction())
+ preString = BuiltInFunctionEmulator::GetEmulatedFunctionName(preString);
+ if (delayedWrite)
+ writeTriplet(visit, preString.c_str(), ", ", ")");
+ return visitChildren;
+}
+
+bool TOutputGLSLBase::visitLoop(Visit visit, TIntermLoop* node)
+{
+ TInfoSinkBase& out = objSink();
+
+ incrementDepth(node);
+ // Loop header.
+ TLoopType loopType = node->getType();
+ if (loopType == ELoopFor) // for loop
+ {
+ if (!node->getUnrollFlag()) {
+ out << "for (";
+ if (node->getInit())
+ node->getInit()->traverse(this);
+ out << "; ";
+
+ if (node->getCondition())
+ node->getCondition()->traverse(this);
+ out << "; ";
+
+ if (node->getExpression())
+ node->getExpression()->traverse(this);
+ out << ")\n";
+ }
+ }
+ else if (loopType == ELoopWhile) // while loop
+ {
+ out << "while (";
+ ASSERT(node->getCondition() != NULL);
+ node->getCondition()->traverse(this);
+ out << ")\n";
+ }
+ else // do-while loop
+ {
+ ASSERT(loopType == ELoopDoWhile);
+ out << "do\n";
+ }
+
+ // Loop body.
+ if (node->getUnrollFlag())
+ {
+ TLoopIndexInfo indexInfo;
+ mLoopUnroll.FillLoopIndexInfo(node, indexInfo);
+ mLoopUnroll.Push(indexInfo);
+ while (mLoopUnroll.SatisfiesLoopCondition())
+ {
+ visitCodeBlock(node->getBody());
+ mLoopUnroll.Step();
+ }
+ mLoopUnroll.Pop();
+ }
+ else
+ {
+ visitCodeBlock(node->getBody());
+ }
+
+ // Loop footer.
+ if (loopType == ELoopDoWhile) // do-while loop
+ {
+ out << "while (";
+ ASSERT(node->getCondition() != NULL);
+ node->getCondition()->traverse(this);
+ out << ");\n";
+ }
+ decrementDepth();
+
+ // No need to visit children. They have been already processed in
+ // this function.
+ return false;
+}
+
+bool TOutputGLSLBase::visitBranch(Visit visit, TIntermBranch* node)
+{
+ switch (node->getFlowOp())
+ {
+ case EOpKill: writeTriplet(visit, "discard", NULL, NULL); break;
+ case EOpBreak: writeTriplet(visit, "break", NULL, NULL); break;
+ case EOpContinue: writeTriplet(visit, "continue", NULL, NULL); break;
+ case EOpReturn: writeTriplet(visit, "return ", NULL, NULL); break;
+ default: UNREACHABLE(); break;
+ }
+
+ return true;
+}
+
+void TOutputGLSLBase::visitCodeBlock(TIntermNode* node) {
+ TInfoSinkBase &out = objSink();
+ if (node != NULL)
+ {
+ node->traverse(this);
+ // Single statements not part of a sequence need to be terminated
+ // with semi-colon.
+ if (isSingleStatement(node))
+ out << ";\n";
+ }
+ else
+ {
+ out << "{\n}\n"; // Empty code block.
+ }
+}
+
+TString TOutputGLSLBase::getTypeName(const TType& type)
+{
+ TInfoSinkBase out;
+ if (type.isMatrix())
+ {
+ out << "mat";
+ out << type.getNominalSize();
+ }
+ else if (type.isVector())
+ {
+ switch (type.getBasicType())
+ {
+ case EbtFloat: out << "vec"; break;
+ case EbtInt: out << "ivec"; break;
+ case EbtBool: out << "bvec"; break;
+ default: UNREACHABLE(); break;
+ }
+ out << type.getNominalSize();
+ }
+ else
+ {
+ if (type.getBasicType() == EbtStruct)
+ out << hashName(type.getStruct()->name());
+ else
+ out << type.getBasicString();
+ }
+ return TString(out.c_str());
+}
+
+TString TOutputGLSLBase::hashName(const TString& name)
+{
+ if (mHashFunction == NULL || name.empty())
+ return name;
+ NameMap::const_iterator it = mNameMap.find(name.c_str());
+ if (it != mNameMap.end())
+ return it->second.c_str();
+ TString hashedName = TIntermTraverser::hash(name, mHashFunction);
+ mNameMap[name.c_str()] = hashedName.c_str();
+ return hashedName;
+}
+
+TString TOutputGLSLBase::hashVariableName(const TString& name)
+{
+ if (mSymbolTable.findBuiltIn(name) != NULL)
+ return name;
+ return hashName(name);
+}
+
+TString TOutputGLSLBase::hashFunctionName(const TString& mangled_name)
+{
+ TString name = TFunction::unmangleName(mangled_name);
+ if (mSymbolTable.findBuiltIn(mangled_name) != NULL || name == "main")
+ return name;
+ return hashName(name);
+}
+
+bool TOutputGLSLBase::structDeclared(const TStructure* structure) const
+{
+ return mDeclaredStructs.find(structure->name()) != mDeclaredStructs.end();
+}
+
+void TOutputGLSLBase::declareStruct(const TStructure* structure)
+{
+ TInfoSinkBase& out = objSink();
+
+ out << "struct " << hashName(structure->name()) << "{\n";
+ const TFieldList& fields = structure->fields();
+ for (size_t i = 0; i < fields.size(); ++i)
+ {
+ const TField* field = fields[i];
+ if (writeVariablePrecision(field->type()->getPrecision()))
+ out << " ";
+ out << getTypeName(*field->type()) << " " << hashName(field->name());
+ if (field->type()->isArray())
+ out << arrayBrackets(*field->type());
+ out << ";\n";
+ }
+ out << "}";
+
+ mDeclaredStructs.insert(structure->name());
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/OutputGLSLBase.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorOutputGLSLBaseh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/OutputGLSLBase.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/OutputGLSLBase.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/OutputGLSLBase.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,79 @@
</span><ins>+//
+// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef CROSSCOMPILERGLSL_OUTPUTGLSLBASE_H_
+#define CROSSCOMPILERGLSL_OUTPUTGLSLBASE_H_
+
+#include <set>
+
+#include "compiler/translator/ForLoopUnroll.h"
+#include "compiler/translator/intermediate.h"
+#include "compiler/translator/ParseContext.h"
+
+class TOutputGLSLBase : public TIntermTraverser
+{
+public:
+ TOutputGLSLBase(TInfoSinkBase& objSink,
+ ShArrayIndexClampingStrategy clampingStrategy,
+ ShHashFunction64 hashFunction,
+ NameMap& nameMap,
+ TSymbolTable& symbolTable);
+
+protected:
+ TInfoSinkBase& objSink() { return mObjSink; }
+ void writeTriplet(Visit visit, const char* preStr, const char* inStr, const char* postStr);
+ void writeVariableType(const TType& type);
+ virtual bool writeVariablePrecision(TPrecision precision) = 0;
+ void writeFunctionParameters(const TIntermSequence& args);
+ const ConstantUnion* writeConstantUnion(const TType& type, const ConstantUnion* pConstUnion);
+ TString getTypeName(const TType& type);
+
+ virtual void visitSymbol(TIntermSymbol* node);
+ virtual void visitConstantUnion(TIntermConstantUnion* node);
+ virtual bool visitBinary(Visit visit, TIntermBinary* node);
+ virtual bool visitUnary(Visit visit, TIntermUnary* node);
+ virtual bool visitSelection(Visit visit, TIntermSelection* node);
+ virtual bool visitAggregate(Visit visit, TIntermAggregate* node);
+ virtual bool visitLoop(Visit visit, TIntermLoop* node);
+ virtual bool visitBranch(Visit visit, TIntermBranch* node);
+
+ void visitCodeBlock(TIntermNode* node);
+
+
+ // Return the original name if hash function pointer is NULL;
+ // otherwise return the hashed name.
+ TString hashName(const TString& name);
+ // Same as hashName(), but without hashing built-in variables.
+ TString hashVariableName(const TString& name);
+ // Same as hashName(), but without hashing built-in functions.
+ TString hashFunctionName(const TString& mangled_name);
+
+private:
+ bool structDeclared(const TStructure* structure) const;
+ void declareStruct(const TStructure* structure);
+
+ TInfoSinkBase& mObjSink;
+ bool mDeclaringVariables;
+
+ // Structs are declared as the tree is traversed. This set contains all
+ // the structs already declared. It is maintained so that a struct is
+ // declared only once.
+ typedef std::set<TString> DeclaredStructs;
+ DeclaredStructs mDeclaredStructs;
+
+ ForLoopUnroll mLoopUnroll;
+
+ ShArrayIndexClampingStrategy mClampingStrategy;
+
+ // name hashing.
+ ShHashFunction64 mHashFunction;
+
+ NameMap& mNameMap;
+
+ TSymbolTable& mSymbolTable;
+};
+
+#endif // CROSSCOMPILERGLSL_OUTPUTGLSLBASE_H_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/OutputGLSLBase.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorOutputHLSLcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/OutputHLSL.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/OutputHLSL.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/OutputHLSL.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,3138 @@
</span><ins>+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/OutputHLSL.h"
+
+#include "common/angleutils.h"
+#include "compiler/translator/compilerdebug.h"
+#include "compiler/translator/DetectDiscontinuity.h"
+#include "compiler/translator/InfoSink.h"
+#include "compiler/translator/SearchSymbol.h"
+#include "compiler/translator/UnfoldShortCircuit.h"
+#include "compiler/translator/NodeSearch.h"
+#include "compiler/translator/RewriteElseBlocks.h"
+
+#include <algorithm>
+#include <cfloat>
+#include <stdio.h>
+
+namespace sh
+{
+
+OutputHLSL::OutputHLSL(TParseContext &context, const ShBuiltInResources& resources, ShShaderOutput outputType)
+ : TIntermTraverser(true, true, true), mContext(context), mOutputType(outputType)
+{
+ mUnfoldShortCircuit = new UnfoldShortCircuit(context, this);
+ mInsideFunction = false;
+
+ mUsesTexture2D = false;
+ mUsesTexture2D_bias = false;
+ mUsesTexture2DProj = false;
+ mUsesTexture2DProj_bias = false;
+ mUsesTexture2DProjLod = false;
+ mUsesTexture2DLod = false;
+ mUsesTextureCube = false;
+ mUsesTextureCube_bias = false;
+ mUsesTextureCubeLod = false;
+ mUsesTexture2DLod0 = false;
+ mUsesTexture2DLod0_bias = false;
+ mUsesTexture2DProjLod0 = false;
+ mUsesTexture2DProjLod0_bias = false;
+ mUsesTextureCubeLod0 = false;
+ mUsesTextureCubeLod0_bias = false;
+ mUsesFragColor = false;
+ mUsesFragData = false;
+ mUsesDepthRange = false;
+ mUsesFragCoord = false;
+ mUsesPointCoord = false;
+ mUsesFrontFacing = false;
+ mUsesPointSize = false;
+ mUsesFragDepth = false;
+ mUsesXor = false;
+ mUsesMod1 = false;
+ mUsesMod2v = false;
+ mUsesMod2f = false;
+ mUsesMod3v = false;
+ mUsesMod3f = false;
+ mUsesMod4v = false;
+ mUsesMod4f = false;
+ mUsesFaceforward1 = false;
+ mUsesFaceforward2 = false;
+ mUsesFaceforward3 = false;
+ mUsesFaceforward4 = false;
+ mUsesAtan2_1 = false;
+ mUsesAtan2_2 = false;
+ mUsesAtan2_3 = false;
+ mUsesAtan2_4 = false;
+ mUsesDiscardRewriting = false;
+
+ mNumRenderTargets = resources.EXT_draw_buffers ? resources.MaxDrawBuffers : 1;
+
+ mScopeDepth = 0;
+
+ mUniqueIndex = 0;
+
+ mContainsLoopDiscontinuity = false;
+ mOutputLod0Function = false;
+ mInsideDiscontinuousLoop = false;
+
+ mExcessiveLoopIndex = NULL;
+
+ if (mOutputType == SH_HLSL9_OUTPUT)
+ {
+ if (mContext.shaderType == SH_FRAGMENT_SHADER)
+ {
+ mUniformRegister = 3; // Reserve registers for dx_DepthRange, dx_ViewCoords and dx_DepthFront
+ }
+ else
+ {
+ mUniformRegister = 2; // Reserve registers for dx_DepthRange and dx_ViewAdjust
+ }
+ }
+ else
+ {
+ mUniformRegister = 0;
+ }
+
+ mSamplerRegister = 0;
+}
+
+OutputHLSL::~OutputHLSL()
+{
+ delete mUnfoldShortCircuit;
+}
+
+void OutputHLSL::output()
+{
+ mContainsLoopDiscontinuity = mContext.shaderType == SH_FRAGMENT_SHADER && containsLoopDiscontinuity(mContext.treeRoot);
+
+ // Work around D3D9 bug that would manifest in vertex shaders with selection blocks which
+ // use a vertex attribute as a condition, and some related computation in the else block.
+ if (mOutputType == SH_HLSL9_OUTPUT && mContext.shaderType == SH_VERTEX_SHADER)
+ {
+ RewriteElseBlocks(mContext.treeRoot);
+ }
+
+ mContext.treeRoot->traverse(this); // Output the body first to determine what has to go in the header
+ header();
+
+ mContext.infoSink().obj << mHeader.c_str();
+ mContext.infoSink().obj << mBody.c_str();
+}
+
+TInfoSinkBase &OutputHLSL::getBodyStream()
+{
+ return mBody;
+}
+
+const ActiveUniforms &OutputHLSL::getUniforms()
+{
+ return mActiveUniforms;
+}
+
+int OutputHLSL::vectorSize(const TType &type) const
+{
+ int elementSize = type.isMatrix() ? type.getNominalSize() : 1;
+ int arraySize = type.isArray() ? type.getArraySize() : 1;
+
+ return elementSize * arraySize;
+}
+
+void OutputHLSL::header()
+{
+ ShShaderType shaderType = mContext.shaderType;
+ TInfoSinkBase &out = mHeader;
+
+ for (StructDeclarations::iterator structDeclaration = mStructDeclarations.begin(); structDeclaration != mStructDeclarations.end(); structDeclaration++)
+ {
+ out << *structDeclaration;
+ }
+
+ for (Constructors::iterator constructor = mConstructors.begin(); constructor != mConstructors.end(); constructor++)
+ {
+ out << *constructor;
+ }
+
+ TString uniforms;
+ TString varyings;
+ TString attributes;
+
+ for (ReferencedSymbols::const_iterator uniform = mReferencedUniforms.begin(); uniform != mReferencedUniforms.end(); uniform++)
+ {
+ const TType &type = uniform->second->getType();
+ const TString &name = uniform->second->getSymbol();
+
+ if (mOutputType == SH_HLSL11_OUTPUT && IsSampler(type.getBasicType())) // Also declare the texture
+ {
+ int index = samplerRegister(mReferencedUniforms[name]);
+
+ uniforms += "uniform SamplerState sampler_" + decorateUniform(name, type) + arrayString(type) +
+ " : register(s" + str(index) + ");\n";
+
+ uniforms += "uniform " + textureString(type) + " texture_" + decorateUniform(name, type) + arrayString(type) +
+ " : register(t" + str(index) + ");\n";
+ }
+ else
+ {
+ uniforms += "uniform " + typeString(type) + " " + decorateUniform(name, type) + arrayString(type) +
+ " : register(" + registerString(mReferencedUniforms[name]) + ");\n";
+ }
+ }
+
+ for (ReferencedSymbols::const_iterator varying = mReferencedVaryings.begin(); varying != mReferencedVaryings.end(); varying++)
+ {
+ const TType &type = varying->second->getType();
+ const TString &name = varying->second->getSymbol();
+
+ // Program linking depends on this exact format
+ varyings += "static " + typeString(type) + " " + decorate(name) + arrayString(type) + " = " + initializer(type) + ";\n";
+ }
+
+ for (ReferencedSymbols::const_iterator attribute = mReferencedAttributes.begin(); attribute != mReferencedAttributes.end(); attribute++)
+ {
+ const TType &type = attribute->second->getType();
+ const TString &name = attribute->second->getSymbol();
+
+ attributes += "static " + typeString(type) + " " + decorate(name) + arrayString(type) + " = " + initializer(type) + ";\n";
+ }
+
+ if (mUsesDiscardRewriting)
+ {
+ out << "#define ANGLE_USES_DISCARD_REWRITING" << "\n";
+ }
+
+ if (shaderType == SH_FRAGMENT_SHADER)
+ {
+ TExtensionBehavior::const_iterator iter = mContext.extensionBehavior().find("GL_EXT_draw_buffers");
+ const bool usingMRTExtension = (iter != mContext.extensionBehavior().end() && (iter->second == EBhEnable || iter->second == EBhRequire));
+
+ const unsigned int numColorValues = usingMRTExtension ? mNumRenderTargets : 1;
+
+ out << "// Varyings\n";
+ out << varyings;
+ out << "\n"
+ "static float4 gl_Color[" << numColorValues << "] =\n"
+ "{\n";
+ for (unsigned int i = 0; i < numColorValues; i++)
+ {
+ out << " float4(0, 0, 0, 0)";
+ if (i + 1 != numColorValues)
+ {
+ out << ",";
+ }
+ out << "\n";
+ }
+ out << "};\n";
+
+ if (mUsesFragDepth)
+ {
+ out << "static float gl_Depth = 0.0;\n";
+ }
+
+ if (mUsesFragCoord)
+ {
+ out << "static float4 gl_FragCoord = float4(0, 0, 0, 0);\n";
+ }
+
+ if (mUsesPointCoord)
+ {
+ out << "static float2 gl_PointCoord = float2(0.5, 0.5);\n";
+ }
+
+ if (mUsesFrontFacing)
+ {
+ out << "static bool gl_FrontFacing = false;\n";
+ }
+
+ out << "\n";
+
+ if (mUsesDepthRange)
+ {
+ out << "struct gl_DepthRangeParameters\n"
+ "{\n"
+ " float near;\n"
+ " float far;\n"
+ " float diff;\n"
+ "};\n"
+ "\n";
+ }
+
+ if (mOutputType == SH_HLSL11_OUTPUT)
+ {
+ out << "cbuffer DriverConstants : register(b1)\n"
+ "{\n";
+
+ if (mUsesDepthRange)
+ {
+ out << " float3 dx_DepthRange : packoffset(c0);\n";
+ }
+
+ if (mUsesFragCoord)
+ {
+ out << " float4 dx_ViewCoords : packoffset(c1);\n";
+ }
+
+ if (mUsesFragCoord || mUsesFrontFacing)
+ {
+ out << " float3 dx_DepthFront : packoffset(c2);\n";
+ }
+
+ out << "};\n";
+ }
+ else
+ {
+ if (mUsesDepthRange)
+ {
+ out << "uniform float3 dx_DepthRange : register(c0);";
+ }
+
+ if (mUsesFragCoord)
+ {
+ out << "uniform float4 dx_ViewCoords : register(c1);\n";
+ }
+
+ if (mUsesFragCoord || mUsesFrontFacing)
+ {
+ out << "uniform float3 dx_DepthFront : register(c2);\n";
+ }
+ }
+
+ out << "\n";
+
+ if (mUsesDepthRange)
+ {
+ out << "static gl_DepthRangeParameters gl_DepthRange = {dx_DepthRange.x, dx_DepthRange.y, dx_DepthRange.z};\n"
+ "\n";
+ }
+
+ out << uniforms;
+ out << "\n";
+
+ if (mUsesTexture2D)
+ {
+ if (mOutputType == SH_HLSL9_OUTPUT)
+ {
+ out << "float4 gl_texture2D(sampler2D s, float2 t)\n"
+ "{\n"
+ " return tex2D(s, t);\n"
+ "}\n"
+ "\n";
+ }
+ else if (mOutputType == SH_HLSL11_OUTPUT)
+ {
+ out << "float4 gl_texture2D(Texture2D t, SamplerState s, float2 uv)\n"
+ "{\n"
+ " return t.Sample(s, uv);\n"
+ "}\n"
+ "\n";
+ }
+ else UNREACHABLE();
+ }
+
+ if (mUsesTexture2D_bias)
+ {
+ if (mOutputType == SH_HLSL9_OUTPUT)
+ {
+ out << "float4 gl_texture2D(sampler2D s, float2 t, float bias)\n"
+ "{\n"
+ " return tex2Dbias(s, float4(t.x, t.y, 0, bias));\n"
+ "}\n"
+ "\n";
+ }
+ else if (mOutputType == SH_HLSL11_OUTPUT)
+ {
+ out << "float4 gl_texture2D(Texture2D t, SamplerState s, float2 uv, float bias)\n"
+ "{\n"
+ " return t.SampleBias(s, uv, bias);\n"
+ "}\n"
+ "\n";
+ }
+ else UNREACHABLE();
+ }
+
+ if (mUsesTexture2DProj)
+ {
+ if (mOutputType == SH_HLSL9_OUTPUT)
+ {
+ out << "float4 gl_texture2DProj(sampler2D s, float3 t)\n"
+ "{\n"
+ " return tex2Dproj(s, float4(t.x, t.y, 0, t.z));\n"
+ "}\n"
+ "\n"
+ "float4 gl_texture2DProj(sampler2D s, float4 t)\n"
+ "{\n"
+ " return tex2Dproj(s, t);\n"
+ "}\n"
+ "\n";
+ }
+ else if (mOutputType == SH_HLSL11_OUTPUT)
+ {
+ out << "float4 gl_texture2DProj(Texture2D t, SamplerState s, float3 uvw)\n"
+ "{\n"
+ " return t.Sample(s, float2(uvw.x / uvw.z, uvw.y / uvw.z));\n"
+ "}\n"
+ "\n"
+ "float4 gl_texture2DProj(Texture2D t, SamplerState s, float4 uvw)\n"
+ "{\n"
+ " return t.Sample(s, float2(uvw.x / uvw.w, uvw.y / uvw.w));\n"
+ "}\n"
+ "\n";
+ }
+ else UNREACHABLE();
+ }
+
+ if (mUsesTexture2DProj_bias)
+ {
+ if (mOutputType == SH_HLSL9_OUTPUT)
+ {
+ out << "float4 gl_texture2DProj(sampler2D s, float3 t, float bias)\n"
+ "{\n"
+ " return tex2Dbias(s, float4(t.x / t.z, t.y / t.z, 0, bias));\n"
+ "}\n"
+ "\n"
+ "float4 gl_texture2DProj(sampler2D s, float4 t, float bias)\n"
+ "{\n"
+ " return tex2Dbias(s, float4(t.x / t.w, t.y / t.w, 0, bias));\n"
+ "}\n"
+ "\n";
+ }
+ else if (mOutputType == SH_HLSL11_OUTPUT)
+ {
+ out << "float4 gl_texture2DProj(Texture2D t, SamplerState s, float3 uvw, float bias)\n"
+ "{\n"
+ " return t.SampleBias(s, float2(uvw.x / uvw.z, uvw.y / uvw.z), bias);\n"
+ "}\n"
+ "\n"
+ "float4 gl_texture2DProj(Texture2D t, SamplerState s, float4 uvw, float bias)\n"
+ "{\n"
+ " return t.SampleBias(s, float2(uvw.x / uvw.w, uvw.y / uvw.w), bias);\n"
+ "}\n"
+ "\n";
+ }
+ else UNREACHABLE();
+ }
+
+ if (mUsesTextureCube)
+ {
+ if (mOutputType == SH_HLSL9_OUTPUT)
+ {
+ out << "float4 gl_textureCube(samplerCUBE s, float3 t)\n"
+ "{\n"
+ " return texCUBE(s, t);\n"
+ "}\n"
+ "\n";
+ }
+ else if (mOutputType == SH_HLSL11_OUTPUT)
+ {
+ out << "float4 gl_textureCube(TextureCube t, SamplerState s, float3 uvw)\n"
+ "{\n"
+ " return t.Sample(s, uvw);\n"
+ "}\n"
+ "\n";
+ }
+ else UNREACHABLE();
+ }
+
+ if (mUsesTextureCube_bias)
+ {
+ if (mOutputType == SH_HLSL9_OUTPUT)
+ {
+ out << "float4 gl_textureCube(samplerCUBE s, float3 t, float bias)\n"
+ "{\n"
+ " return texCUBEbias(s, float4(t.x, t.y, t.z, bias));\n"
+ "}\n"
+ "\n";
+ }
+ else if (mOutputType == SH_HLSL11_OUTPUT)
+ {
+ out << "float4 gl_textureCube(TextureCube t, SamplerState s, float3 uvw, float bias)\n"
+ "{\n"
+ " return t.SampleBias(s, uvw, bias);\n"
+ "}\n"
+ "\n";
+ }
+ else UNREACHABLE();
+ }
+
+ // These *Lod0 intrinsics are not available in GL fragment shaders.
+ // They are used to sample using discontinuous texture coordinates.
+ if (mUsesTexture2DLod0)
+ {
+ if (mOutputType == SH_HLSL9_OUTPUT)
+ {
+ out << "float4 gl_texture2DLod0(sampler2D s, float2 t)\n"
+ "{\n"
+ " return tex2Dlod(s, float4(t.x, t.y, 0, 0));\n"
+ "}\n"
+ "\n";
+ }
+ else if (mOutputType == SH_HLSL11_OUTPUT)
+ {
+ out << "float4 gl_texture2DLod0(Texture2D t, SamplerState s, float2 uv)\n"
+ "{\n"
+ " return t.SampleLevel(s, uv, 0);\n"
+ "}\n"
+ "\n";
+ }
+ else UNREACHABLE();
+ }
+
+ if (mUsesTexture2DLod0_bias)
+ {
+ if (mOutputType == SH_HLSL9_OUTPUT)
+ {
+ out << "float4 gl_texture2DLod0(sampler2D s, float2 t, float bias)\n"
+ "{\n"
+ " return tex2Dlod(s, float4(t.x, t.y, 0, 0));\n"
+ "}\n"
+ "\n";
+ }
+ else if (mOutputType == SH_HLSL11_OUTPUT)
+ {
+ out << "float4 gl_texture2DLod0(Texture2D t, SamplerState s, float2 uv, float bias)\n"
+ "{\n"
+ " return t.SampleLevel(s, uv, 0);\n"
+ "}\n"
+ "\n";
+ }
+ else UNREACHABLE();
+ }
+
+ if (mUsesTexture2DProjLod0)
+ {
+ if (mOutputType == SH_HLSL9_OUTPUT)
+ {
+ out << "float4 gl_texture2DProjLod0(sampler2D s, float3 t)\n"
+ "{\n"
+ " return tex2Dlod(s, float4(t.x / t.z, t.y / t.z, 0, 0));\n"
+ "}\n"
+ "\n"
+ "float4 gl_texture2DProjLod(sampler2D s, float4 t)\n"
+ "{\n"
+ " return tex2Dlod(s, float4(t.x / t.w, t.y / t.w, 0, 0));\n"
+ "}\n"
+ "\n";
+ }
+ else if (mOutputType == SH_HLSL11_OUTPUT)
+ {
+ out << "float4 gl_texture2DProjLod0(Texture2D t, SamplerState s, float3 uvw)\n"
+ "{\n"
+ " return t.SampleLevel(s, float2(uvw.x / uvw.z, uvw.y / uvw.z), 0);\n"
+ "}\n"
+ "\n"
+ "float4 gl_texture2DProjLod0(Texture2D t, SamplerState s, float4 uvw)\n"
+ "{\n"
+ " return t.SampleLevel(s, float2(uvw.x / uvw.w, uvw.y / uvw.w), 0);\n"
+ "}\n"
+ "\n";
+ }
+ else UNREACHABLE();
+ }
+
+ if (mUsesTexture2DProjLod0_bias)
+ {
+ if (mOutputType == SH_HLSL9_OUTPUT)
+ {
+ out << "float4 gl_texture2DProjLod0_bias(sampler2D s, float3 t, float bias)\n"
+ "{\n"
+ " return tex2Dlod(s, float4(t.x / t.z, t.y / t.z, 0, 0));\n"
+ "}\n"
+ "\n"
+ "float4 gl_texture2DProjLod_bias(sampler2D s, float4 t, float bias)\n"
+ "{\n"
+ " return tex2Dlod(s, float4(t.x / t.w, t.y / t.w, 0, 0));\n"
+ "}\n"
+ "\n";
+ }
+ else if (mOutputType == SH_HLSL11_OUTPUT)
+ {
+ out << "float4 gl_texture2DProjLod_bias(Texture2D t, SamplerState s, float3 uvw, float bias)\n"
+ "{\n"
+ " return t.SampleLevel(s, float2(uvw.x / uvw.z, uvw.y / uvw.z), 0);\n"
+ "}\n"
+ "\n"
+ "float4 gl_texture2DProjLod_bias(Texture2D t, SamplerState s, float4 uvw, float bias)\n"
+ "{\n"
+ " return t.SampleLevel(s, float2(uvw.x / uvw.w, uvw.y / uvw.w), 0);\n"
+ "}\n"
+ "\n";
+ }
+ else UNREACHABLE();
+ }
+
+ if (mUsesTextureCubeLod0)
+ {
+ if (mOutputType == SH_HLSL9_OUTPUT)
+ {
+ out << "float4 gl_textureCubeLod0(samplerCUBE s, float3 t)\n"
+ "{\n"
+ " return texCUBElod(s, float4(t.x, t.y, t.z, 0));\n"
+ "}\n"
+ "\n";
+ }
+ else if (mOutputType == SH_HLSL11_OUTPUT)
+ {
+ out << "float4 gl_textureCubeLod0(TextureCube t, SamplerState s, float3 uvw)\n"
+ "{\n"
+ " return t.SampleLevel(s, uvw, 0);\n"
+ "}\n"
+ "\n";
+ }
+ else UNREACHABLE();
+ }
+
+ if (mUsesTextureCubeLod0_bias)
+ {
+ if (mOutputType == SH_HLSL9_OUTPUT)
+ {
+ out << "float4 gl_textureCubeLod0(samplerCUBE s, float3 t, float bias)\n"
+ "{\n"
+ " return texCUBElod(s, float4(t.x, t.y, t.z, 0));\n"
+ "}\n"
+ "\n";
+ }
+ else if (mOutputType == SH_HLSL11_OUTPUT)
+ {
+ out << "float4 gl_textureCubeLod0(TextureCube t, SamplerState s, float3 uvw, float bias)\n"
+ "{\n"
+ " return t.SampleLevel(s, uvw, 0);\n"
+ "}\n"
+ "\n";
+ }
+ else UNREACHABLE();
+ }
+
+ if (usingMRTExtension && mNumRenderTargets > 1)
+ {
+ out << "#define GL_USES_MRT\n";
+ }
+
+ if (mUsesFragColor)
+ {
+ out << "#define GL_USES_FRAG_COLOR\n";
+ }
+
+ if (mUsesFragData)
+ {
+ out << "#define GL_USES_FRAG_DATA\n";
+ }
+ }
+ else // Vertex shader
+ {
+ out << "// Attributes\n";
+ out << attributes;
+ out << "\n"
+ "static float4 gl_Position = float4(0, 0, 0, 0);\n";
+
+ if (mUsesPointSize)
+ {
+ out << "static float gl_PointSize = float(1);\n";
+ }
+
+ out << "\n"
+ "// Varyings\n";
+ out << varyings;
+ out << "\n";
+
+ if (mUsesDepthRange)
+ {
+ out << "struct gl_DepthRangeParameters\n"
+ "{\n"
+ " float near;\n"
+ " float far;\n"
+ " float diff;\n"
+ "};\n"
+ "\n";
+ }
+
+ if (mOutputType == SH_HLSL11_OUTPUT)
+ {
+ if (mUsesDepthRange)
+ {
+ out << "cbuffer DriverConstants : register(b1)\n"
+ "{\n"
+ " float3 dx_DepthRange : packoffset(c0);\n"
+ "};\n"
+ "\n";
+ }
+ }
+ else
+ {
+ if (mUsesDepthRange)
+ {
+ out << "uniform float3 dx_DepthRange : register(c0);\n";
+ }
+
+ out << "uniform float4 dx_ViewAdjust : register(c1);\n"
+ "\n";
+ }
+
+ if (mUsesDepthRange)
+ {
+ out << "static gl_DepthRangeParameters gl_DepthRange = {dx_DepthRange.x, dx_DepthRange.y, dx_DepthRange.z};\n"
+ "\n";
+ }
+
+ out << uniforms;
+ out << "\n";
+
+ if (mUsesTexture2D)
+ {
+ if (mOutputType == SH_HLSL9_OUTPUT)
+ {
+ out << "float4 gl_texture2D(sampler2D s, float2 t)\n"
+ "{\n"
+ " return tex2Dlod(s, float4(t.x, t.y, 0, 0));\n"
+ "}\n"
+ "\n";
+ }
+ else if (mOutputType == SH_HLSL11_OUTPUT)
+ {
+ out << "float4 gl_texture2D(Texture2D t, SamplerState s, float2 uv)\n"
+ "{\n"
+ " return t.SampleLevel(s, uv, 0);\n"
+ "}\n"
+ "\n";
+ }
+ else UNREACHABLE();
+ }
+
+ if (mUsesTexture2DLod)
+ {
+ if (mOutputType == SH_HLSL9_OUTPUT)
+ {
+ out << "float4 gl_texture2DLod(sampler2D s, float2 t, float lod)\n"
+ "{\n"
+ " return tex2Dlod(s, float4(t.x, t.y, 0, lod));\n"
+ "}\n"
+ "\n";
+ }
+ else if (mOutputType == SH_HLSL11_OUTPUT)
+ {
+ out << "float4 gl_texture2DLod(Texture2D t, SamplerState s, float2 uv, float lod)\n"
+ "{\n"
+ " return t.SampleLevel(s, uv, lod);\n"
+ "}\n"
+ "\n";
+ }
+ else UNREACHABLE();
+ }
+
+ if (mUsesTexture2DProj)
+ {
+ if (mOutputType == SH_HLSL9_OUTPUT)
+ {
+ out << "float4 gl_texture2DProj(sampler2D s, float3 t)\n"
+ "{\n"
+ " return tex2Dlod(s, float4(t.x / t.z, t.y / t.z, 0, 0));\n"
+ "}\n"
+ "\n"
+ "float4 gl_texture2DProj(sampler2D s, float4 t)\n"
+ "{\n"
+ " return tex2Dlod(s, float4(t.x / t.w, t.y / t.w, 0, 0));\n"
+ "}\n"
+ "\n";
+ }
+ else if (mOutputType == SH_HLSL11_OUTPUT)
+ {
+ out << "float4 gl_texture2DProj(Texture2D t, SamplerState s, float3 uvw)\n"
+ "{\n"
+ " return t.SampleLevel(s, float2(uvw.x / uvw.z, uvw.y / uvw.z), 0);\n"
+ "}\n"
+ "\n"
+ "float4 gl_texture2DProj(Texture2D t, SamplerState s, float4 uvw)\n"
+ "{\n"
+ " return t.SampleLevel(s, float2(uvw.x / uvw.w, uvw.y / uvw.w), 0);\n"
+ "}\n"
+ "\n";
+ }
+ else UNREACHABLE();
+ }
+
+ if (mUsesTexture2DProjLod)
+ {
+ if (mOutputType == SH_HLSL9_OUTPUT)
+ {
+ out << "float4 gl_texture2DProjLod(sampler2D s, float3 t, float lod)\n"
+ "{\n"
+ " return tex2Dlod(s, float4(t.x / t.z, t.y / t.z, 0, lod));\n"
+ "}\n"
+ "\n"
+ "float4 gl_texture2DProjLod(sampler2D s, float4 t, float lod)\n"
+ "{\n"
+ " return tex2Dlod(s, float4(t.x / t.w, t.y / t.w, 0, lod));\n"
+ "}\n"
+ "\n";
+ }
+ else if (mOutputType == SH_HLSL11_OUTPUT)
+ {
+ out << "float4 gl_texture2DProjLod(Texture2D t, SamplerState s, float3 uvw, float lod)\n"
+ "{\n"
+ " return t.SampleLevel(s, float2(uvw.x / uvw.z, uvw.y / uvw.z), lod);\n"
+ "}\n"
+ "\n"
+ "float4 gl_texture2DProjLod(Texture2D t, SamplerState s, float4 uvw, float lod)\n"
+ "{\n"
+ " return t.SampleLevel(s, float2(uvw.x / uvw.w, uvw.y / uvw.w), lod);\n"
+ "}\n"
+ "\n";
+ }
+ else UNREACHABLE();
+ }
+
+ if (mUsesTextureCube)
+ {
+ if (mOutputType == SH_HLSL9_OUTPUT)
+ {
+ out << "float4 gl_textureCube(samplerCUBE s, float3 t)\n"
+ "{\n"
+ " return texCUBElod(s, float4(t.x, t.y, t.z, 0));\n"
+ "}\n"
+ "\n";
+ }
+ else if (mOutputType == SH_HLSL11_OUTPUT)
+ {
+ out << "float4 gl_textureCube(TextureCube t, SamplerState s, float3 uvw)\n"
+ "{\n"
+ " return t.SampleLevel(s, uvw, 0);\n"
+ "}\n"
+ "\n";
+ }
+ else UNREACHABLE();
+ }
+
+ if (mUsesTextureCubeLod)
+ {
+ if (mOutputType == SH_HLSL9_OUTPUT)
+ {
+ out << "float4 gl_textureCubeLod(samplerCUBE s, float3 t, float lod)\n"
+ "{\n"
+ " return texCUBElod(s, float4(t.x, t.y, t.z, lod));\n"
+ "}\n"
+ "\n";
+ }
+ else if (mOutputType == SH_HLSL11_OUTPUT)
+ {
+ out << "float4 gl_textureCubeLod(TextureCube t, SamplerState s, float3 uvw, float lod)\n"
+ "{\n"
+ " return t.SampleLevel(s, uvw, lod);\n"
+ "}\n"
+ "\n";
+ }
+ else UNREACHABLE();
+ }
+ }
+
+ if (mUsesFragCoord)
+ {
+ out << "#define GL_USES_FRAG_COORD\n";
+ }
+
+ if (mUsesPointCoord)
+ {
+ out << "#define GL_USES_POINT_COORD\n";
+ }
+
+ if (mUsesFrontFacing)
+ {
+ out << "#define GL_USES_FRONT_FACING\n";
+ }
+
+ if (mUsesPointSize)
+ {
+ out << "#define GL_USES_POINT_SIZE\n";
+ }
+
+ if (mUsesFragDepth)
+ {
+ out << "#define GL_USES_FRAG_DEPTH\n";
+ }
+
+ if (mUsesDepthRange)
+ {
+ out << "#define GL_USES_DEPTH_RANGE\n";
+ }
+
+ if (mUsesXor)
+ {
+ out << "bool xor(bool p, bool q)\n"
+ "{\n"
+ " return (p || q) && !(p && q);\n"
+ "}\n"
+ "\n";
+ }
+
+ if (mUsesMod1)
+ {
+ out << "float mod(float x, float y)\n"
+ "{\n"
+ " return x - y * floor(x / y);\n"
+ "}\n"
+ "\n";
+ }
+
+ if (mUsesMod2v)
+ {
+ out << "float2 mod(float2 x, float2 y)\n"
+ "{\n"
+ " return x - y * floor(x / y);\n"
+ "}\n"
+ "\n";
+ }
+
+ if (mUsesMod2f)
+ {
+ out << "float2 mod(float2 x, float y)\n"
+ "{\n"
+ " return x - y * floor(x / y);\n"
+ "}\n"
+ "\n";
+ }
+
+ if (mUsesMod3v)
+ {
+ out << "float3 mod(float3 x, float3 y)\n"
+ "{\n"
+ " return x - y * floor(x / y);\n"
+ "}\n"
+ "\n";
+ }
+
+ if (mUsesMod3f)
+ {
+ out << "float3 mod(float3 x, float y)\n"
+ "{\n"
+ " return x - y * floor(x / y);\n"
+ "}\n"
+ "\n";
+ }
+
+ if (mUsesMod4v)
+ {
+ out << "float4 mod(float4 x, float4 y)\n"
+ "{\n"
+ " return x - y * floor(x / y);\n"
+ "}\n"
+ "\n";
+ }
+
+ if (mUsesMod4f)
+ {
+ out << "float4 mod(float4 x, float y)\n"
+ "{\n"
+ " return x - y * floor(x / y);\n"
+ "}\n"
+ "\n";
+ }
+
+ if (mUsesFaceforward1)
+ {
+ out << "float faceforward(float N, float I, float Nref)\n"
+ "{\n"
+ " if(dot(Nref, I) >= 0)\n"
+ " {\n"
+ " return -N;\n"
+ " }\n"
+ " else\n"
+ " {\n"
+ " return N;\n"
+ " }\n"
+ "}\n"
+ "\n";
+ }
+
+ if (mUsesFaceforward2)
+ {
+ out << "float2 faceforward(float2 N, float2 I, float2 Nref)\n"
+ "{\n"
+ " if(dot(Nref, I) >= 0)\n"
+ " {\n"
+ " return -N;\n"
+ " }\n"
+ " else\n"
+ " {\n"
+ " return N;\n"
+ " }\n"
+ "}\n"
+ "\n";
+ }
+
+ if (mUsesFaceforward3)
+ {
+ out << "float3 faceforward(float3 N, float3 I, float3 Nref)\n"
+ "{\n"
+ " if(dot(Nref, I) >= 0)\n"
+ " {\n"
+ " return -N;\n"
+ " }\n"
+ " else\n"
+ " {\n"
+ " return N;\n"
+ " }\n"
+ "}\n"
+ "\n";
+ }
+
+ if (mUsesFaceforward4)
+ {
+ out << "float4 faceforward(float4 N, float4 I, float4 Nref)\n"
+ "{\n"
+ " if(dot(Nref, I) >= 0)\n"
+ " {\n"
+ " return -N;\n"
+ " }\n"
+ " else\n"
+ " {\n"
+ " return N;\n"
+ " }\n"
+ "}\n"
+ "\n";
+ }
+
+ if (mUsesAtan2_1)
+ {
+ out << "float atanyx(float y, float x)\n"
+ "{\n"
+ " if(x == 0 && y == 0) x = 1;\n" // Avoid producing a NaN
+ " return atan2(y, x);\n"
+ "}\n";
+ }
+
+ if (mUsesAtan2_2)
+ {
+ out << "float2 atanyx(float2 y, float2 x)\n"
+ "{\n"
+ " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
+ " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n"
+ " return float2(atan2(y[0], x[0]), atan2(y[1], x[1]));\n"
+ "}\n";
+ }
+
+ if (mUsesAtan2_3)
+ {
+ out << "float3 atanyx(float3 y, float3 x)\n"
+ "{\n"
+ " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
+ " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n"
+ " if(x[2] == 0 && y[2] == 0) x[2] = 1;\n"
+ " return float3(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]));\n"
+ "}\n";
+ }
+
+ if (mUsesAtan2_4)
+ {
+ out << "float4 atanyx(float4 y, float4 x)\n"
+ "{\n"
+ " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
+ " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n"
+ " if(x[2] == 0 && y[2] == 0) x[2] = 1;\n"
+ " if(x[3] == 0 && y[3] == 0) x[3] = 1;\n"
+ " return float4(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]), atan2(y[3], x[3]));\n"
+ "}\n";
+ }
+}
+
+void OutputHLSL::visitSymbol(TIntermSymbol *node)
+{
+ TInfoSinkBase &out = mBody;
+
+ TString name = node->getSymbol();
+
+ if (name == "gl_FragColor")
+ {
+ out << "gl_Color[0]";
+ mUsesFragColor = true;
+ }
+ else if (name == "gl_FragData")
+ {
+ out << "gl_Color";
+ mUsesFragData = true;
+ }
+ else if (name == "gl_DepthRange")
+ {
+ mUsesDepthRange = true;
+ out << name;
+ }
+ else if (name == "gl_FragCoord")
+ {
+ mUsesFragCoord = true;
+ out << name;
+ }
+ else if (name == "gl_PointCoord")
+ {
+ mUsesPointCoord = true;
+ out << name;
+ }
+ else if (name == "gl_FrontFacing")
+ {
+ mUsesFrontFacing = true;
+ out << name;
+ }
+ else if (name == "gl_PointSize")
+ {
+ mUsesPointSize = true;
+ out << name;
+ }
+ else if (name == "gl_FragDepthEXT")
+ {
+ mUsesFragDepth = true;
+ out << "gl_Depth";
+ }
+ else
+ {
+ TQualifier qualifier = node->getQualifier();
+
+ if (qualifier == EvqUniform)
+ {
+ mReferencedUniforms[name] = node;
+ out << decorateUniform(name, node->getType());
+ }
+ else if (qualifier == EvqAttribute)
+ {
+ mReferencedAttributes[name] = node;
+ out << decorate(name);
+ }
+ else if (qualifier == EvqVaryingOut || qualifier == EvqInvariantVaryingOut || qualifier == EvqVaryingIn || qualifier == EvqInvariantVaryingIn)
+ {
+ mReferencedVaryings[name] = node;
+ out << decorate(name);
+ }
+ else if (qualifier == EvqInternal)
+ {
+ out << name;
+ }
+ else
+ {
+ out << decorate(name);
+ }
+ }
+}
+
+bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
+{
+ TInfoSinkBase &out = mBody;
+
+ switch (node->getOp())
+ {
+ case EOpAssign: outputTriplet(visit, "(", " = ", ")"); break;
+ case EOpInitialize:
+ if (visit == PreVisit)
+ {
+ // GLSL allows to write things like "float x = x;" where a new variable x is defined
+ // and the value of an existing variable x is assigned. HLSL uses C semantics (the
+ // new variable is created before the assignment is evaluated), so we need to convert
+ // this to "float t = x, x = t;".
+
+ TIntermSymbol *symbolNode = node->getLeft()->getAsSymbolNode();
+ TIntermTyped *expression = node->getRight();
+
+ sh::SearchSymbol searchSymbol(symbolNode->getSymbol());
+ expression->traverse(&searchSymbol);
+ bool sameSymbol = searchSymbol.foundMatch();
+
+ if (sameSymbol)
+ {
+ // Type already printed
+ out << "t" + str(mUniqueIndex) + " = ";
+ expression->traverse(this);
+ out << ", ";
+ symbolNode->traverse(this);
+ out << " = t" + str(mUniqueIndex);
+
+ mUniqueIndex++;
+ return false;
+ }
+ }
+ else if (visit == InVisit)
+ {
+ out << " = ";
+ }
+ break;
+ case EOpAddAssign: outputTriplet(visit, "(", " += ", ")"); break;
+ case EOpSubAssign: outputTriplet(visit, "(", " -= ", ")"); break;
+ case EOpMulAssign: outputTriplet(visit, "(", " *= ", ")"); break;
+ case EOpVectorTimesScalarAssign: outputTriplet(visit, "(", " *= ", ")"); break;
+ case EOpMatrixTimesScalarAssign: outputTriplet(visit, "(", " *= ", ")"); break;
+ case EOpVectorTimesMatrixAssign:
+ if (visit == PreVisit)
+ {
+ out << "(";
+ }
+ else if (visit == InVisit)
+ {
+ out << " = mul(";
+ node->getLeft()->traverse(this);
+ out << ", transpose(";
+ }
+ else
+ {
+ out << ")))";
+ }
+ break;
+ case EOpMatrixTimesMatrixAssign:
+ if (visit == PreVisit)
+ {
+ out << "(";
+ }
+ else if (visit == InVisit)
+ {
+ out << " = mul(";
+ node->getLeft()->traverse(this);
+ out << ", ";
+ }
+ else
+ {
+ out << "))";
+ }
+ break;
+ case EOpDivAssign: outputTriplet(visit, "(", " /= ", ")"); break;
+ case EOpIndexDirect: outputTriplet(visit, "", "[", "]"); break;
+ case EOpIndexIndirect: outputTriplet(visit, "", "[", "]"); break;
+ case EOpIndexDirectStruct:
+ if (visit == InVisit)
+ {
+ const TStructure* structure = node->getLeft()->getType().getStruct();
+ const TIntermConstantUnion* index = node->getRight()->getAsConstantUnion();
+ const TField* field = structure->fields()[index->getIConst(0)];
+ out << "." + decorateField(field->name(), node->getLeft()->getType());
+
+ return false;
+ }
+ break;
+ case EOpVectorSwizzle:
+ if (visit == InVisit)
+ {
+ out << ".";
+
+ TIntermAggregate *swizzle = node->getRight()->getAsAggregate();
+
+ if (swizzle)
+ {
+ TIntermSequence &sequence = swizzle->getSequence();
+
+ for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++)
+ {
+ TIntermConstantUnion *element = (*sit)->getAsConstantUnion();
+
+ if (element)
+ {
+ int i = element->getIConst(0);
+
+ switch (i)
+ {
+ case 0: out << "x"; break;
+ case 1: out << "y"; break;
+ case 2: out << "z"; break;
+ case 3: out << "w"; break;
+ default: UNREACHABLE();
+ }
+ }
+ else UNREACHABLE();
+ }
+ }
+ else UNREACHABLE();
+
+ return false; // Fully processed
+ }
+ break;
+ case EOpAdd: outputTriplet(visit, "(", " + ", ")"); break;
+ case EOpSub: outputTriplet(visit, "(", " - ", ")"); break;
+ case EOpMul: outputTriplet(visit, "(", " * ", ")"); break;
+ case EOpDiv: outputTriplet(visit, "(", " / ", ")"); break;
+ case EOpEqual:
+ case EOpNotEqual:
+ if (node->getLeft()->isScalar())
+ {
+ if (node->getOp() == EOpEqual)
+ {
+ outputTriplet(visit, "(", " == ", ")");
+ }
+ else
+ {
+ outputTriplet(visit, "(", " != ", ")");
+ }
+ }
+ else if (node->getLeft()->getBasicType() == EbtStruct)
+ {
+ if (node->getOp() == EOpEqual)
+ {
+ out << "(";
+ }
+ else
+ {
+ out << "!(";
+ }
+
+ const TFieldList &fields = node->getLeft()->getType().getStruct()->fields();
+
+ for (size_t i = 0; i < fields.size(); i++)
+ {
+ const TField *field = fields[i];
+
+ node->getLeft()->traverse(this);
+ out << "." + decorateField(field->name(), node->getLeft()->getType()) + " == ";
+ node->getRight()->traverse(this);
+ out << "." + decorateField(field->name(), node->getLeft()->getType());
+
+ if (i < fields.size() - 1)
+ {
+ out << " && ";
+ }
+ }
+
+ out << ")";
+
+ return false;
+ }
+ else
+ {
+ ASSERT(node->getLeft()->isMatrix() || node->getLeft()->isVector());
+
+ if (node->getOp() == EOpEqual)
+ {
+ outputTriplet(visit, "all(", " == ", ")");
+ }
+ else
+ {
+ outputTriplet(visit, "!all(", " == ", ")");
+ }
+ }
+ break;
+ case EOpLessThan: outputTriplet(visit, "(", " < ", ")"); break;
+ case EOpGreaterThan: outputTriplet(visit, "(", " > ", ")"); break;
+ case EOpLessThanEqual: outputTriplet(visit, "(", " <= ", ")"); break;
+ case EOpGreaterThanEqual: outputTriplet(visit, "(", " >= ", ")"); break;
+ case EOpVectorTimesScalar: outputTriplet(visit, "(", " * ", ")"); break;
+ case EOpMatrixTimesScalar: outputTriplet(visit, "(", " * ", ")"); break;
+ case EOpVectorTimesMatrix: outputTriplet(visit, "mul(", ", transpose(", "))"); break;
+ case EOpMatrixTimesVector: outputTriplet(visit, "mul(transpose(", "), ", ")"); break;
+ case EOpMatrixTimesMatrix: outputTriplet(visit, "transpose(mul(transpose(", "), transpose(", ")))"); break;
+ case EOpLogicalOr:
+ if (node->getRight()->hasSideEffects())
+ {
+ out << "s" << mUnfoldShortCircuit->getNextTemporaryIndex();
+ return false;
+ }
+ else
+ {
+ outputTriplet(visit, "(", " || ", ")");
+ return true;
+ }
+ case EOpLogicalXor:
+ mUsesXor = true;
+ outputTriplet(visit, "xor(", ", ", ")");
+ break;
+ case EOpLogicalAnd:
+ if (node->getRight()->hasSideEffects())
+ {
+ out << "s" << mUnfoldShortCircuit->getNextTemporaryIndex();
+ return false;
+ }
+ else
+ {
+ outputTriplet(visit, "(", " && ", ")");
+ return true;
+ }
+ default: UNREACHABLE();
+ }
+
+ return true;
+}
+
+bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node)
+{
+ switch (node->getOp())
+ {
+ case EOpNegative: outputTriplet(visit, "(-", "", ")"); break;
+ case EOpVectorLogicalNot: outputTriplet(visit, "(!", "", ")"); break;
+ case EOpLogicalNot: outputTriplet(visit, "(!", "", ")"); break;
+ case EOpPostIncrement: outputTriplet(visit, "(", "", "++)"); break;
+ case EOpPostDecrement: outputTriplet(visit, "(", "", "--)"); break;
+ case EOpPreIncrement: outputTriplet(visit, "(++", "", ")"); break;
+ case EOpPreDecrement: outputTriplet(visit, "(--", "", ")"); break;
+ case EOpConvIntToBool:
+ case EOpConvFloatToBool:
+ switch (node->getOperand()->getType().getNominalSize())
+ {
+ case 1: outputTriplet(visit, "bool(", "", ")"); break;
+ case 2: outputTriplet(visit, "bool2(", "", ")"); break;
+ case 3: outputTriplet(visit, "bool3(", "", ")"); break;
+ case 4: outputTriplet(visit, "bool4(", "", ")"); break;
+ default: UNREACHABLE();
+ }
+ break;
+ case EOpConvBoolToFloat:
+ case EOpConvIntToFloat:
+ switch (node->getOperand()->getType().getNominalSize())
+ {
+ case 1: outputTriplet(visit, "float(", "", ")"); break;
+ case 2: outputTriplet(visit, "float2(", "", ")"); break;
+ case 3: outputTriplet(visit, "float3(", "", ")"); break;
+ case 4: outputTriplet(visit, "float4(", "", ")"); break;
+ default: UNREACHABLE();
+ }
+ break;
+ case EOpConvFloatToInt:
+ case EOpConvBoolToInt:
+ switch (node->getOperand()->getType().getNominalSize())
+ {
+ case 1: outputTriplet(visit, "int(", "", ")"); break;
+ case 2: outputTriplet(visit, "int2(", "", ")"); break;
+ case 3: outputTriplet(visit, "int3(", "", ")"); break;
+ case 4: outputTriplet(visit, "int4(", "", ")"); break;
+ default: UNREACHABLE();
+ }
+ break;
+ case EOpRadians: outputTriplet(visit, "radians(", "", ")"); break;
+ case EOpDegrees: outputTriplet(visit, "degrees(", "", ")"); break;
+ case EOpSin: outputTriplet(visit, "sin(", "", ")"); break;
+ case EOpCos: outputTriplet(visit, "cos(", "", ")"); break;
+ case EOpTan: outputTriplet(visit, "tan(", "", ")"); break;
+ case EOpAsin: outputTriplet(visit, "asin(", "", ")"); break;
+ case EOpAcos: outputTriplet(visit, "acos(", "", ")"); break;
+ case EOpAtan: outputTriplet(visit, "atan(", "", ")"); break;
+ case EOpExp: outputTriplet(visit, "exp(", "", ")"); break;
+ case EOpLog: outputTriplet(visit, "log(", "", ")"); break;
+ case EOpExp2: outputTriplet(visit, "exp2(", "", ")"); break;
+ case EOpLog2: outputTriplet(visit, "log2(", "", ")"); break;
+ case EOpSqrt: outputTriplet(visit, "sqrt(", "", ")"); break;
+ case EOpInverseSqrt: outputTriplet(visit, "rsqrt(", "", ")"); break;
+ case EOpAbs: outputTriplet(visit, "abs(", "", ")"); break;
+ case EOpSign: outputTriplet(visit, "sign(", "", ")"); break;
+ case EOpFloor: outputTriplet(visit, "floor(", "", ")"); break;
+ case EOpCeil: outputTriplet(visit, "ceil(", "", ")"); break;
+ case EOpFract: outputTriplet(visit, "frac(", "", ")"); break;
+ case EOpLength: outputTriplet(visit, "length(", "", ")"); break;
+ case EOpNormalize: outputTriplet(visit, "normalize(", "", ")"); break;
+ case EOpDFdx:
+ if(mInsideDiscontinuousLoop || mOutputLod0Function)
+ {
+ outputTriplet(visit, "(", "", ", 0.0)");
+ }
+ else
+ {
+ outputTriplet(visit, "ddx(", "", ")");
+ }
+ break;
+ case EOpDFdy:
+ if(mInsideDiscontinuousLoop || mOutputLod0Function)
+ {
+ outputTriplet(visit, "(", "", ", 0.0)");
+ }
+ else
+ {
+ outputTriplet(visit, "ddy(", "", ")");
+ }
+ break;
+ case EOpFwidth:
+ if(mInsideDiscontinuousLoop || mOutputLod0Function)
+ {
+ outputTriplet(visit, "(", "", ", 0.0)");
+ }
+ else
+ {
+ outputTriplet(visit, "fwidth(", "", ")");
+ }
+ break;
+ case EOpAny: outputTriplet(visit, "any(", "", ")"); break;
+ case EOpAll: outputTriplet(visit, "all(", "", ")"); break;
+ default: UNREACHABLE();
+ }
+
+ return true;
+}
+
+bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
+{
+ TInfoSinkBase &out = mBody;
+
+ switch (node->getOp())
+ {
+ case EOpSequence:
+ {
+ if (mInsideFunction)
+ {
+ outputLineDirective(node->getLine().first_line);
+ out << "{\n";
+
+ mScopeDepth++;
+
+ if (mScopeBracket.size() < mScopeDepth)
+ {
+ mScopeBracket.push_back(0); // New scope level
+ }
+ else
+ {
+ mScopeBracket[mScopeDepth - 1]++; // New scope at existing level
+ }
+ }
+
+ for (TIntermSequence::iterator sit = node->getSequence().begin(); sit != node->getSequence().end(); sit++)
+ {
+ outputLineDirective((*sit)->getLine().first_line);
+
+ traverseStatements(*sit);
+
+ out << ";\n";
+ }
+
+ if (mInsideFunction)
+ {
+ outputLineDirective(node->getLine().last_line);
+ out << "}\n";
+
+ mScopeDepth--;
+ }
+
+ return false;
+ }
+ case EOpDeclaration:
+ if (visit == PreVisit)
+ {
+ TIntermSequence &sequence = node->getSequence();
+ TIntermTyped *variable = sequence[0]->getAsTyped();
+
+ if (variable && (variable->getQualifier() == EvqTemporary || variable->getQualifier() == EvqGlobal))
+ {
+ if (variable->getType().getStruct())
+ {
+ addConstructor(variable->getType(), scopedStruct(variable->getType().getStruct()->name()), NULL);
+ }
+
+ 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++)
+ {
+ TIntermSymbol *symbol = (*sit)->getAsSymbolNode();
+
+ if (symbol)
+ {
+ symbol->traverse(this);
+ out << arrayString(symbol->getType());
+ out << " = " + initializer(symbol->getType());
+ }
+ else
+ {
+ (*sit)->traverse(this);
+ }
+
+ if (*sit != sequence.back())
+ {
+ out << ", ";
+ }
+ }
+ }
+ else if (variable->getAsSymbolNode() && variable->getAsSymbolNode()->getSymbol() == "") // Type (struct) declaration
+ {
+ // Already added to constructor map
+ }
+ else UNREACHABLE();
+ }
+ else if (variable && (variable->getQualifier() == EvqVaryingOut || variable->getQualifier() == EvqInvariantVaryingOut))
+ {
+ for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++)
+ {
+ TIntermSymbol *symbol = (*sit)->getAsSymbolNode();
+
+ if (symbol)
+ {
+ // Vertex (output) varyings which are declared but not written to should still be declared to allow successful linking
+ mReferencedVaryings[symbol->getSymbol()] = symbol;
+ }
+ else
+ {
+ (*sit)->traverse(this);
+ }
+ }
+ }
+
+ return false;
+ }
+ else if (visit == InVisit)
+ {
+ out << ", ";
+ }
+ break;
+ case EOpPrototype:
+ if (visit == PreVisit)
+ {
+ out << typeString(node->getType()) << " " << decorate(node->getName()) << (mOutputLod0Function ? "Lod0(" : "(");
+
+ TIntermSequence &arguments = node->getSequence();
+
+ for (unsigned int i = 0; i < arguments.size(); i++)
+ {
+ TIntermSymbol *symbol = arguments[i]->getAsSymbolNode();
+
+ if (symbol)
+ {
+ out << argumentString(symbol);
+
+ if (i < arguments.size() - 1)
+ {
+ out << ", ";
+ }
+ }
+ else UNREACHABLE();
+ }
+
+ out << ");\n";
+
+ // Also prototype the Lod0 variant if needed
+ if (mContainsLoopDiscontinuity && !mOutputLod0Function)
+ {
+ mOutputLod0Function = true;
+ node->traverse(this);
+ mOutputLod0Function = false;
+ }
+
+ return false;
+ }
+ break;
+ case EOpComma: outputTriplet(visit, "(", ", ", ")"); break;
+ case EOpFunction:
+ {
+ TString name = TFunction::unmangleName(node->getName());
+
+ out << typeString(node->getType()) << " ";
+
+ if (name == "main")
+ {
+ out << "gl_main(";
+ }
+ else
+ {
+ out << decorate(name) << (mOutputLod0Function ? "Lod0(" : "(");
+ }
+
+ TIntermSequence &sequence = node->getSequence();
+ TIntermSequence &arguments = sequence[0]->getAsAggregate()->getSequence();
+
+ for (unsigned int i = 0; i < arguments.size(); i++)
+ {
+ TIntermSymbol *symbol = arguments[i]->getAsSymbolNode();
+
+ if (symbol)
+ {
+ if (symbol->getType().getStruct())
+ {
+ addConstructor(symbol->getType(), scopedStruct(symbol->getType().getStruct()->name()), NULL);
+ }
+
+ out << argumentString(symbol);
+
+ if (i < arguments.size() - 1)
+ {
+ out << ", ";
+ }
+ }
+ else UNREACHABLE();
+ }
+
+ out << ")\n"
+ "{\n";
+
+ if (sequence.size() > 1)
+ {
+ mInsideFunction = true;
+ sequence[1]->traverse(this);
+ mInsideFunction = false;
+ }
+
+ out << "}\n";
+
+ if (mContainsLoopDiscontinuity && !mOutputLod0Function)
+ {
+ if (name != "main")
+ {
+ mOutputLod0Function = true;
+ node->traverse(this);
+ mOutputLod0Function = false;
+ }
+ }
+
+ return false;
+ }
+ break;
+ case EOpFunctionCall:
+ {
+ TString name = TFunction::unmangleName(node->getName());
+ bool lod0 = mInsideDiscontinuousLoop || mOutputLod0Function;
+
+ if (node->isUserDefined())
+ {
+ out << decorate(name) << (lod0 ? "Lod0(" : "(");
+ }
+ else
+ {
+ if (name == "texture2D")
+ {
+ if (!lod0)
+ {
+ if (node->getSequence().size() == 2)
+ {
+ mUsesTexture2D = true;
+ }
+ else if (node->getSequence().size() == 3)
+ {
+ mUsesTexture2D_bias = true;
+ }
+ else UNREACHABLE();
+
+ out << "gl_texture2D(";
+ }
+ else
+ {
+ if (node->getSequence().size() == 2)
+ {
+ mUsesTexture2DLod0 = true;
+ }
+ else if (node->getSequence().size() == 3)
+ {
+ mUsesTexture2DLod0_bias = true;
+ }
+ else UNREACHABLE();
+
+ out << "gl_texture2DLod0(";
+ }
+ }
+ else if (name == "texture2DProj")
+ {
+ if (!lod0)
+ {
+ if (node->getSequence().size() == 2)
+ {
+ mUsesTexture2DProj = true;
+ }
+ else if (node->getSequence().size() == 3)
+ {
+ mUsesTexture2DProj_bias = true;
+ }
+ else UNREACHABLE();
+
+ out << "gl_texture2DProj(";
+ }
+ else
+ {
+ if (node->getSequence().size() == 2)
+ {
+ mUsesTexture2DProjLod0 = true;
+ }
+ else if (node->getSequence().size() == 3)
+ {
+ mUsesTexture2DProjLod0_bias = true;
+ }
+ else UNREACHABLE();
+
+ out << "gl_texture2DProjLod0(";
+ }
+ }
+ else if (name == "textureCube")
+ {
+ if (!lod0)
+ {
+ if (node->getSequence().size() == 2)
+ {
+ mUsesTextureCube = true;
+ }
+ else if (node->getSequence().size() == 3)
+ {
+ mUsesTextureCube_bias = true;
+ }
+ else UNREACHABLE();
+
+ out << "gl_textureCube(";
+ }
+ else
+ {
+ if (node->getSequence().size() == 2)
+ {
+ mUsesTextureCubeLod0 = true;
+ }
+ else if (node->getSequence().size() == 3)
+ {
+ mUsesTextureCubeLod0_bias = true;
+ }
+ else UNREACHABLE();
+
+ out << "gl_textureCubeLod0(";
+ }
+ }
+ else if (name == "texture2DLod")
+ {
+ if (node->getSequence().size() == 3)
+ {
+ mUsesTexture2DLod = true;
+ }
+ else UNREACHABLE();
+
+ out << "gl_texture2DLod(";
+ }
+ else if (name == "texture2DProjLod")
+ {
+ if (node->getSequence().size() == 3)
+ {
+ mUsesTexture2DProjLod = true;
+ }
+ else UNREACHABLE();
+
+ out << "gl_texture2DProjLod(";
+ }
+ else if (name == "textureCubeLod")
+ {
+ if (node->getSequence().size() == 3)
+ {
+ mUsesTextureCubeLod = true;
+ }
+ else UNREACHABLE();
+
+ out << "gl_textureCubeLod(";
+ }
+ else UNREACHABLE();
+ }
+
+ TIntermSequence &arguments = node->getSequence();
+
+ for (TIntermSequence::iterator arg = arguments.begin(); arg != arguments.end(); arg++)
+ {
+ if (mOutputType == SH_HLSL11_OUTPUT && IsSampler((*arg)->getAsTyped()->getBasicType()))
+ {
+ out << "texture_";
+ (*arg)->traverse(this);
+ out << ", sampler_";
+ }
+
+ (*arg)->traverse(this);
+
+ if (arg < arguments.end() - 1)
+ {
+ out << ", ";
+ }
+ }
+
+ out << ")";
+
+ return false;
+ }
+ break;
+ case EOpParameters: outputTriplet(visit, "(", ", ", ")\n{\n"); break;
+ case EOpConstructFloat:
+ addConstructor(node->getType(), "vec1", &node->getSequence());
+ outputTriplet(visit, "vec1(", "", ")");
+ break;
+ case EOpConstructVec2:
+ addConstructor(node->getType(), "vec2", &node->getSequence());
+ outputTriplet(visit, "vec2(", ", ", ")");
+ break;
+ case EOpConstructVec3:
+ addConstructor(node->getType(), "vec3", &node->getSequence());
+ outputTriplet(visit, "vec3(", ", ", ")");
+ break;
+ case EOpConstructVec4:
+ addConstructor(node->getType(), "vec4", &node->getSequence());
+ outputTriplet(visit, "vec4(", ", ", ")");
+ break;
+ case EOpConstructBool:
+ addConstructor(node->getType(), "bvec1", &node->getSequence());
+ outputTriplet(visit, "bvec1(", "", ")");
+ break;
+ case EOpConstructBVec2:
+ addConstructor(node->getType(), "bvec2", &node->getSequence());
+ outputTriplet(visit, "bvec2(", ", ", ")");
+ break;
+ case EOpConstructBVec3:
+ addConstructor(node->getType(), "bvec3", &node->getSequence());
+ outputTriplet(visit, "bvec3(", ", ", ")");
+ break;
+ case EOpConstructBVec4:
+ addConstructor(node->getType(), "bvec4", &node->getSequence());
+ outputTriplet(visit, "bvec4(", ", ", ")");
+ break;
+ case EOpConstructInt:
+ addConstructor(node->getType(), "ivec1", &node->getSequence());
+ outputTriplet(visit, "ivec1(", "", ")");
+ break;
+ case EOpConstructIVec2:
+ addConstructor(node->getType(), "ivec2", &node->getSequence());
+ outputTriplet(visit, "ivec2(", ", ", ")");
+ break;
+ case EOpConstructIVec3:
+ addConstructor(node->getType(), "ivec3", &node->getSequence());
+ outputTriplet(visit, "ivec3(", ", ", ")");
+ break;
+ case EOpConstructIVec4:
+ addConstructor(node->getType(), "ivec4", &node->getSequence());
+ outputTriplet(visit, "ivec4(", ", ", ")");
+ break;
+ case EOpConstructMat2:
+ addConstructor(node->getType(), "mat2", &node->getSequence());
+ outputTriplet(visit, "mat2(", ", ", ")");
+ break;
+ case EOpConstructMat3:
+ addConstructor(node->getType(), "mat3", &node->getSequence());
+ outputTriplet(visit, "mat3(", ", ", ")");
+ break;
+ case EOpConstructMat4:
+ addConstructor(node->getType(), "mat4", &node->getSequence());
+ outputTriplet(visit, "mat4(", ", ", ")");
+ break;
+ case EOpConstructStruct:
+ addConstructor(node->getType(), scopedStruct(node->getType().getStruct()->name()), &node->getSequence());
+ outputTriplet(visit, structLookup(node->getType().getStruct()->name()) + "_ctor(", ", ", ")");
+ break;
+ case EOpLessThan: outputTriplet(visit, "(", " < ", ")"); break;
+ case EOpGreaterThan: outputTriplet(visit, "(", " > ", ")"); break;
+ case EOpLessThanEqual: outputTriplet(visit, "(", " <= ", ")"); break;
+ case EOpGreaterThanEqual: outputTriplet(visit, "(", " >= ", ")"); break;
+ case EOpVectorEqual: outputTriplet(visit, "(", " == ", ")"); break;
+ case EOpVectorNotEqual: outputTriplet(visit, "(", " != ", ")"); break;
+ case EOpMod:
+ {
+ // We need to look at the number of components in both arguments
+ switch (node->getSequence()[0]->getAsTyped()->getNominalSize() * 10
+ + node->getSequence()[1]->getAsTyped()->getNominalSize())
+ {
+ case 11: mUsesMod1 = true; break;
+ case 22: mUsesMod2v = true; break;
+ case 21: mUsesMod2f = true; break;
+ case 33: mUsesMod3v = true; break;
+ case 31: mUsesMod3f = true; break;
+ case 44: mUsesMod4v = true; break;
+ case 41: mUsesMod4f = true; break;
+ default: UNREACHABLE();
+ }
+
+ outputTriplet(visit, "mod(", ", ", ")");
+ }
+ break;
+ case EOpPow: outputTriplet(visit, "pow(", ", ", ")"); break;
+ case EOpAtan:
+ ASSERT(node->getSequence().size() == 2); // atan(x) is a unary operator
+ switch (node->getSequence()[0]->getAsTyped()->getNominalSize())
+ {
+ case 1: mUsesAtan2_1 = true; break;
+ case 2: mUsesAtan2_2 = true; break;
+ case 3: mUsesAtan2_3 = true; break;
+ case 4: mUsesAtan2_4 = true; break;
+ default: UNREACHABLE();
+ }
+ outputTriplet(visit, "atanyx(", ", ", ")");
+ break;
+ case EOpMin: outputTriplet(visit, "min(", ", ", ")"); break;
+ case EOpMax: outputTriplet(visit, "max(", ", ", ")"); break;
+ case EOpClamp: outputTriplet(visit, "clamp(", ", ", ")"); break;
+ case EOpMix: outputTriplet(visit, "lerp(", ", ", ")"); break;
+ case EOpStep: outputTriplet(visit, "step(", ", ", ")"); break;
+ case EOpSmoothStep: outputTriplet(visit, "smoothstep(", ", ", ")"); break;
+ case EOpDistance: outputTriplet(visit, "distance(", ", ", ")"); break;
+ case EOpDot: outputTriplet(visit, "dot(", ", ", ")"); break;
+ case EOpCross: outputTriplet(visit, "cross(", ", ", ")"); break;
+ case EOpFaceForward:
+ {
+ switch (node->getSequence()[0]->getAsTyped()->getNominalSize()) // Number of components in the first argument
+ {
+ case 1: mUsesFaceforward1 = true; break;
+ case 2: mUsesFaceforward2 = true; break;
+ case 3: mUsesFaceforward3 = true; break;
+ case 4: mUsesFaceforward4 = true; break;
+ default: UNREACHABLE();
+ }
+
+ outputTriplet(visit, "faceforward(", ", ", ")");
+ }
+ break;
+ case EOpReflect: outputTriplet(visit, "reflect(", ", ", ")"); break;
+ case EOpRefract: outputTriplet(visit, "refract(", ", ", ")"); break;
+ case EOpMul: outputTriplet(visit, "(", " * ", ")"); break;
+ default: UNREACHABLE();
+ }
+
+ return true;
+}
+
+bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node)
+{
+ TInfoSinkBase &out = mBody;
+
+ if (node->usesTernaryOperator())
+ {
+ out << "s" << mUnfoldShortCircuit->getNextTemporaryIndex();
+ }
+ else // if/else statement
+ {
+ mUnfoldShortCircuit->traverse(node->getCondition());
+
+ out << "if (";
+
+ node->getCondition()->traverse(this);
+
+ out << ")\n";
+
+ outputLineDirective(node->getLine().first_line);
+ out << "{\n";
+
+ bool discard = false;
+
+ if (node->getTrueBlock())
+ {
+ traverseStatements(node->getTrueBlock());
+
+ // Detect true discard
+ discard = (discard || FindDiscard::search(node->getTrueBlock()));
+ }
+
+ outputLineDirective(node->getLine().first_line);
+ out << ";\n}\n";
+
+ if (node->getFalseBlock())
+ {
+ out << "else\n";
+
+ outputLineDirective(node->getFalseBlock()->getLine().first_line);
+ out << "{\n";
+
+ outputLineDirective(node->getFalseBlock()->getLine().first_line);
+ traverseStatements(node->getFalseBlock());
+
+ outputLineDirective(node->getFalseBlock()->getLine().first_line);
+ out << ";\n}\n";
+
+ // Detect false discard
+ discard = (discard || FindDiscard::search(node->getFalseBlock()));
+ }
+
+ // ANGLE issue 486: Detect problematic conditional discard
+ if (discard && FindSideEffectRewriting::search(node))
+ {
+ mUsesDiscardRewriting = true;
+ }
+ }
+
+ return false;
+}
+
+void OutputHLSL::visitConstantUnion(TIntermConstantUnion *node)
+{
+ writeConstantUnion(node->getType(), node->getUnionArrayPointer());
+}
+
+bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node)
+{
+ bool wasDiscontinuous = mInsideDiscontinuousLoop;
+
+ if (mContainsLoopDiscontinuity && !mInsideDiscontinuousLoop)
+ {
+ mInsideDiscontinuousLoop = containsLoopDiscontinuity(node);
+ }
+
+ if (mOutputType == SH_HLSL9_OUTPUT)
+ {
+ if (handleExcessiveLoop(node))
+ {
+ return false;
+ }
+ }
+
+ TInfoSinkBase &out = mBody;
+
+ if (node->getType() == ELoopDoWhile)
+ {
+ out << "{do\n";
+
+ outputLineDirective(node->getLine().first_line);
+ out << "{\n";
+ }
+ else
+ {
+ out << "{for(";
+
+ if (node->getInit())
+ {
+ node->getInit()->traverse(this);
+ }
+
+ out << "; ";
+
+ if (node->getCondition())
+ {
+ node->getCondition()->traverse(this);
+ }
+
+ out << "; ";
+
+ if (node->getExpression())
+ {
+ node->getExpression()->traverse(this);
+ }
+
+ out << ")\n";
+
+ outputLineDirective(node->getLine().first_line);
+ out << "{\n";
+ }
+
+ if (node->getBody())
+ {
+ traverseStatements(node->getBody());
+ }
+
+ outputLineDirective(node->getLine().first_line);
+ out << ";}\n";
+
+ if (node->getType() == ELoopDoWhile)
+ {
+ outputLineDirective(node->getCondition()->getLine().first_line);
+ out << "while(\n";
+
+ node->getCondition()->traverse(this);
+
+ out << ");";
+ }
+
+ out << "}\n";
+
+ mInsideDiscontinuousLoop = wasDiscontinuous;
+
+ return false;
+}
+
+bool OutputHLSL::visitBranch(Visit visit, TIntermBranch *node)
+{
+ TInfoSinkBase &out = mBody;
+
+ switch (node->getFlowOp())
+ {
+ case EOpKill:
+ outputTriplet(visit, "discard;\n", "", "");
+ break;
+ case EOpBreak:
+ if (visit == PreVisit)
+ {
+ if (mExcessiveLoopIndex)
+ {
+ out << "{Break";
+ mExcessiveLoopIndex->traverse(this);
+ out << " = true; break;}\n";
+ }
+ else
+ {
+ out << "break;\n";
+ }
+ }
+ break;
+ case EOpContinue: outputTriplet(visit, "continue;\n", "", ""); break;
+ case EOpReturn:
+ if (visit == PreVisit)
+ {
+ if (node->getExpression())
+ {
+ out << "return ";
+ }
+ else
+ {
+ out << "return;\n";
+ }
+ }
+ else if (visit == PostVisit)
+ {
+ if (node->getExpression())
+ {
+ out << ";\n";
+ }
+ }
+ break;
+ default: UNREACHABLE();
+ }
+
+ return true;
+}
+
+void OutputHLSL::traverseStatements(TIntermNode *node)
+{
+ if (isSingleStatement(node))
+ {
+ mUnfoldShortCircuit->traverse(node);
+ }
+
+ node->traverse(this);
+}
+
+bool OutputHLSL::isSingleStatement(TIntermNode *node)
+{
+ TIntermAggregate *aggregate = node->getAsAggregate();
+
+ if (aggregate)
+ {
+ if (aggregate->getOp() == EOpSequence)
+ {
+ return false;
+ }
+ else
+ {
+ for (TIntermSequence::iterator sit = aggregate->getSequence().begin(); sit != aggregate->getSequence().end(); sit++)
+ {
+ if (!isSingleStatement(*sit))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+ }
+
+ return true;
+}
+
+// Handle loops with more than 254 iterations (unsupported by D3D9) by splitting them
+// (The D3D documentation says 255 iterations, but the compiler complains at anything more than 254).
+bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node)
+{
+ const int MAX_LOOP_ITERATIONS = 254;
+ TInfoSinkBase &out = mBody;
+
+ // Parse loops of the form:
+ // for(int index = initial; index [comparator] limit; index += increment)
+ TIntermSymbol *index = NULL;
+ TOperator comparator = EOpNull;
+ int initial = 0;
+ int limit = 0;
+ int increment = 0;
+
+ // Parse index name and intial value
+ if (node->getInit())
+ {
+ TIntermAggregate *init = node->getInit()->getAsAggregate();
+
+ if (init)
+ {
+ TIntermSequence &sequence = init->getSequence();
+ TIntermTyped *variable = sequence[0]->getAsTyped();
+
+ if (variable && variable->getQualifier() == EvqTemporary)
+ {
+ TIntermBinary *assign = variable->getAsBinaryNode();
+
+ if (assign->getOp() == EOpInitialize)
+ {
+ TIntermSymbol *symbol = assign->getLeft()->getAsSymbolNode();
+ TIntermConstantUnion *constant = assign->getRight()->getAsConstantUnion();
+
+ if (symbol && constant)
+ {
+ if (constant->getBasicType() == EbtInt && constant->getNominalSize() == 1)
+ {
+ index = symbol;
+ initial = constant->getIConst(0);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Parse comparator and limit value
+ if (index != NULL && node->getCondition())
+ {
+ TIntermBinary *test = node->getCondition()->getAsBinaryNode();
+
+ if (test && test->getLeft()->getAsSymbolNode()->getId() == index->getId())
+ {
+ TIntermConstantUnion *constant = test->getRight()->getAsConstantUnion();
+
+ if (constant)
+ {
+ if (constant->getBasicType() == EbtInt && constant->getNominalSize() == 1)
+ {
+ comparator = test->getOp();
+ limit = constant->getIConst(0);
+ }
+ }
+ }
+ }
+
+ // Parse increment
+ if (index != NULL && comparator != EOpNull && node->getExpression())
+ {
+ TIntermBinary *binaryTerminal = node->getExpression()->getAsBinaryNode();
+ TIntermUnary *unaryTerminal = node->getExpression()->getAsUnaryNode();
+
+ if (binaryTerminal)
+ {
+ TOperator op = binaryTerminal->getOp();
+ TIntermConstantUnion *constant = binaryTerminal->getRight()->getAsConstantUnion();
+
+ if (constant)
+ {
+ if (constant->getBasicType() == EbtInt && constant->getNominalSize() == 1)
+ {
+ int value = constant->getIConst(0);
+
+ switch (op)
+ {
+ case EOpAddAssign: increment = value; break;
+ case EOpSubAssign: increment = -value; break;
+ default: UNIMPLEMENTED();
+ }
+ }
+ }
+ }
+ else if (unaryTerminal)
+ {
+ TOperator op = unaryTerminal->getOp();
+
+ switch (op)
+ {
+ case EOpPostIncrement: increment = 1; break;
+ case EOpPostDecrement: increment = -1; break;
+ case EOpPreIncrement: increment = 1; break;
+ case EOpPreDecrement: increment = -1; break;
+ default: UNIMPLEMENTED();
+ }
+ }
+ }
+
+ if (index != NULL && comparator != EOpNull && increment != 0)
+ {
+ if (comparator == EOpLessThanEqual)
+ {
+ comparator = EOpLessThan;
+ limit += 1;
+ }
+
+ if (comparator == EOpLessThan)
+ {
+ int iterations = (limit - initial) / increment;
+
+ if (iterations <= MAX_LOOP_ITERATIONS)
+ {
+ return false; // Not an excessive loop
+ }
+
+ TIntermSymbol *restoreIndex = mExcessiveLoopIndex;
+ mExcessiveLoopIndex = index;
+
+ out << "{int ";
+ index->traverse(this);
+ out << ";\n"
+ "bool Break";
+ index->traverse(this);
+ out << " = false;\n";
+
+ bool firstLoopFragment = true;
+
+ while (iterations > 0)
+ {
+ int clampedLimit = initial + increment * std::min(MAX_LOOP_ITERATIONS, iterations);
+
+ if (!firstLoopFragment)
+ {
+ out << "if (!Break";
+ index->traverse(this);
+ out << ") {\n";
+ }
+
+ if (iterations <= MAX_LOOP_ITERATIONS) // Last loop fragment
+ {
+ mExcessiveLoopIndex = NULL; // Stops setting the Break flag
+ }
+
+ // for(int index = initial; index < clampedLimit; index += increment)
+
+ out << "for(";
+ index->traverse(this);
+ out << " = ";
+ out << initial;
+
+ out << "; ";
+ index->traverse(this);
+ out << " < ";
+ out << clampedLimit;
+
+ out << "; ";
+ index->traverse(this);
+ out << " += ";
+ out << increment;
+ out << ")\n";
+
+ outputLineDirective(node->getLine().first_line);
+ out << "{\n";
+
+ if (node->getBody())
+ {
+ node->getBody()->traverse(this);
+ }
+
+ outputLineDirective(node->getLine().first_line);
+ out << ";}\n";
+
+ if (!firstLoopFragment)
+ {
+ out << "}\n";
+ }
+
+ firstLoopFragment = false;
+
+ initial += MAX_LOOP_ITERATIONS * increment;
+ iterations -= MAX_LOOP_ITERATIONS;
+ }
+
+ out << "}";
+
+ mExcessiveLoopIndex = restoreIndex;
+
+ return true;
+ }
+ else UNIMPLEMENTED();
+ }
+
+ return false; // Not handled as an excessive loop
+}
+
+void OutputHLSL::outputTriplet(Visit visit, const TString &preString, const TString &inString, const TString &postString)
+{
+ TInfoSinkBase &out = mBody;
+
+ if (visit == PreVisit)
+ {
+ out << preString;
+ }
+ else if (visit == InVisit)
+ {
+ out << inString;
+ }
+ else if (visit == PostVisit)
+ {
+ out << postString;
+ }
+}
+
+void OutputHLSL::outputLineDirective(int line)
+{
+ if ((mContext.compileOptions & SH_LINE_DIRECTIVES) && (line > 0))
+ {
+ mBody << "\n";
+ mBody << "#line " << line;
+
+ if (mContext.sourcePath)
+ {
+ mBody << " \"" << mContext.sourcePath << "\"";
+ }
+
+ mBody << "\n";
+ }
+}
+
+TString OutputHLSL::argumentString(const TIntermSymbol *symbol)
+{
+ TQualifier qualifier = symbol->getQualifier();
+ const TType &type = symbol->getType();
+ TString name = symbol->getSymbol();
+
+ if (name.empty()) // HLSL demands named arguments, also for prototypes
+ {
+ name = "x" + str(mUniqueIndex++);
+ }
+ else
+ {
+ name = decorate(name);
+ }
+
+ if (mOutputType == SH_HLSL11_OUTPUT && IsSampler(type.getBasicType()))
+ {
+ return qualifierString(qualifier) + " " + textureString(type) + " texture_" + name + arrayString(type) + ", " +
+ qualifierString(qualifier) + " SamplerState sampler_" + name + arrayString(type);
+ }
+
+ return qualifierString(qualifier) + " " + typeString(type) + " " + name + arrayString(type);
+}
+
+TString OutputHLSL::qualifierString(TQualifier qualifier)
+{
+ switch(qualifier)
+ {
+ case EvqIn: return "in";
+ case EvqOut: return "out";
+ case EvqInOut: return "inout";
+ case EvqConstReadOnly: return "const";
+ default: UNREACHABLE();
+ }
+
+ return "";
+}
+
+TString OutputHLSL::typeString(const TType &type)
+{
+ if (type.getBasicType() == EbtStruct)
+ {
+ const TString& typeName = type.getStruct()->name();
+ if (typeName != "")
+ {
+ return structLookup(typeName);
+ }
+ else // Nameless structure, define in place
+ {
+ const TFieldList &fields = type.getStruct()->fields();
+
+ TString string = "struct\n"
+ "{\n";
+
+ for (unsigned int i = 0; i < fields.size(); i++)
+ {
+ const TField *field = fields[i];
+
+ string += " " + typeString(*field->type()) + " " + decorate(field->name()) + arrayString(*field->type()) + ";\n";
+ }
+
+ string += "} ";
+
+ return string;
+ }
+ }
+ else if (type.isMatrix())
+ {
+ switch (type.getNominalSize())
+ {
+ case 2: return "float2x2";
+ case 3: return "float3x3";
+ case 4: return "float4x4";
+ }
+ }
+ else
+ {
+ switch (type.getBasicType())
+ {
+ case EbtFloat:
+ switch (type.getNominalSize())
+ {
+ case 1: return "float";
+ case 2: return "float2";
+ case 3: return "float3";
+ case 4: return "float4";
+ }
+ case EbtInt:
+ switch (type.getNominalSize())
+ {
+ case 1: return "int";
+ case 2: return "int2";
+ case 3: return "int3";
+ case 4: return "int4";
+ }
+ case EbtBool:
+ switch (type.getNominalSize())
+ {
+ case 1: return "bool";
+ case 2: return "bool2";
+ case 3: return "bool3";
+ case 4: return "bool4";
+ }
+ case EbtVoid:
+ return "void";
+ case EbtSampler2D:
+ return "sampler2D";
+ case EbtSamplerCube:
+ return "samplerCUBE";
+ case EbtSamplerExternalOES:
+ return "sampler2D";
+ default:
+ break;
+ }
+ }
+
+ UNREACHABLE();
+ return "<unknown type>";
+}
+
+TString OutputHLSL::textureString(const TType &type)
+{
+ switch (type.getBasicType())
+ {
+ case EbtSampler2D:
+ return "Texture2D";
+ case EbtSamplerCube:
+ return "TextureCube";
+ case EbtSamplerExternalOES:
+ return "Texture2D";
+ default:
+ break;
+ }
+
+ UNREACHABLE();
+ return "<unknown texture type>";
+}
+
+TString OutputHLSL::arrayString(const TType &type)
+{
+ if (!type.isArray())
+ {
+ return "";
+ }
+
+ return "[" + str(type.getArraySize()) + "]";
+}
+
+TString OutputHLSL::initializer(const TType &type)
+{
+ TString string;
+
+ size_t size = type.getObjectSize();
+ for (size_t component = 0; component < size; component++)
+ {
+ string += "0";
+
+ if (component + 1 < size)
+ {
+ string += ", ";
+ }
+ }
+
+ return "{" + string + "}";
+}
+
+void OutputHLSL::addConstructor(const TType &type, const TString &name, const TIntermSequence *parameters)
+{
+ if (name == "")
+ {
+ return; // Nameless structures don't have constructors
+ }
+
+ if (type.getStruct() && mStructNames.find(decorate(name)) != mStructNames.end())
+ {
+ return; // Already added
+ }
+
+ TType ctorType = type;
+ ctorType.clearArrayness();
+ ctorType.setPrecision(EbpHigh);
+ ctorType.setQualifier(EvqTemporary);
+
+ TString ctorName = type.getStruct() ? decorate(name) : name;
+
+ typedef std::vector<TType> ParameterArray;
+ ParameterArray ctorParameters;
+
+ if (type.getStruct())
+ {
+ mStructNames.insert(decorate(name));
+
+ TString structure;
+ structure += "struct " + decorate(name) + "\n"
+ "{\n";
+
+ const TFieldList &fields = type.getStruct()->fields();
+
+ for (unsigned int i = 0; i < fields.size(); i++)
+ {
+ const TField *field = fields[i];
+
+ structure += " " + typeString(*field->type()) + " " + decorateField(field->name(), type) + arrayString(*field->type()) + ";\n";
+ }
+
+ structure += "};\n";
+
+ if (std::find(mStructDeclarations.begin(), mStructDeclarations.end(), structure) == mStructDeclarations.end())
+ {
+ mStructDeclarations.push_back(structure);
+ }
+
+ for (unsigned int i = 0; i < fields.size(); i++)
+ {
+ ctorParameters.push_back(*fields[i]->type());
+ }
+ }
+ else if (parameters)
+ {
+ for (TIntermSequence::const_iterator parameter = parameters->begin(); parameter != parameters->end(); parameter++)
+ {
+ ctorParameters.push_back((*parameter)->getAsTyped()->getType());
+ }
+ }
+ else UNREACHABLE();
+
+ TString constructor;
+
+ if (ctorType.getStruct())
+ {
+ constructor += ctorName + " " + ctorName + "_ctor(";
+ }
+ else // Built-in type
+ {
+ constructor += typeString(ctorType) + " " + ctorName + "(";
+ }
+
+ for (unsigned int parameter = 0; parameter < ctorParameters.size(); parameter++)
+ {
+ const TType &type = ctorParameters[parameter];
+
+ constructor += typeString(type) + " x" + str(parameter) + arrayString(type);
+
+ if (parameter < ctorParameters.size() - 1)
+ {
+ constructor += ", ";
+ }
+ }
+
+ constructor += ")\n"
+ "{\n";
+
+ if (ctorType.getStruct())
+ {
+ constructor += " " + ctorName + " structure = {";
+ }
+ else
+ {
+ constructor += " return " + typeString(ctorType) + "(";
+ }
+
+ if (ctorType.isMatrix() && ctorParameters.size() == 1)
+ {
+ int dim = ctorType.getNominalSize();
+ const TType &parameter = ctorParameters[0];
+
+ if (parameter.isScalar())
+ {
+ for (int row = 0; row < dim; row++)
+ {
+ for (int col = 0; col < dim; col++)
+ {
+ constructor += TString((row == col) ? "x0" : "0.0");
+
+ if (row < dim - 1 || col < dim - 1)
+ {
+ constructor += ", ";
+ }
+ }
+ }
+ }
+ else if (parameter.isMatrix())
+ {
+ for (int row = 0; row < dim; row++)
+ {
+ for (int col = 0; col < dim; col++)
+ {
+ if (row < parameter.getNominalSize() && col < parameter.getNominalSize())
+ {
+ constructor += TString("x0") + "[" + str(row) + "]" + "[" + str(col) + "]";
+ }
+ else
+ {
+ constructor += TString((row == col) ? "1.0" : "0.0");
+ }
+
+ if (row < dim - 1 || col < dim - 1)
+ {
+ constructor += ", ";
+ }
+ }
+ }
+ }
+ else UNREACHABLE();
+ }
+ else
+ {
+ size_t remainingComponents = ctorType.getObjectSize();
+ size_t parameterIndex = 0;
+
+ while (remainingComponents > 0)
+ {
+ const TType &parameter = ctorParameters[parameterIndex];
+ const size_t parameterSize = parameter.getObjectSize();
+ bool moreParameters = parameterIndex + 1 < ctorParameters.size();
+
+ constructor += "x" + str(parameterIndex);
+
+ if (parameter.isScalar())
+ {
+ ASSERT(parameterSize <= remainingComponents);
+ remainingComponents -= parameterSize;
+ }
+ else if (parameter.isVector())
+ {
+ if (remainingComponents == parameterSize || moreParameters)
+ {
+ ASSERT(parameterSize <= remainingComponents);
+ remainingComponents -= parameterSize;
+ }
+ else if (remainingComponents < static_cast<size_t>(parameter.getNominalSize()))
+ {
+ switch (remainingComponents)
+ {
+ case 1: constructor += ".x"; break;
+ case 2: constructor += ".xy"; break;
+ case 3: constructor += ".xyz"; break;
+ case 4: constructor += ".xyzw"; break;
+ default: UNREACHABLE();
+ }
+
+ remainingComponents = 0;
+ }
+ else UNREACHABLE();
+ }
+ else if (parameter.isMatrix() || parameter.getStruct())
+ {
+ ASSERT(remainingComponents == parameterSize || moreParameters);
+ ASSERT(parameterSize <= remainingComponents);
+
+ remainingComponents -= parameterSize;
+ }
+ else UNREACHABLE();
+
+ if (moreParameters)
+ {
+ parameterIndex++;
+ }
+
+ if (remainingComponents)
+ {
+ constructor += ", ";
+ }
+ }
+ }
+
+ if (ctorType.getStruct())
+ {
+ constructor += "};\n"
+ " return structure;\n"
+ "}\n";
+ }
+ else
+ {
+ constructor += ");\n"
+ "}\n";
+ }
+
+ mConstructors.insert(constructor);
+}
+
+const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const ConstantUnion *constUnion)
+{
+ TInfoSinkBase &out = mBody;
+
+ if (type.getBasicType() == EbtStruct)
+ {
+ out << structLookup(type.getStruct()->name()) + "_ctor(";
+
+ const TFieldList &fields = type.getStruct()->fields();
+
+ for (size_t i = 0; i < fields.size(); i++)
+ {
+ const TType *fieldType = fields[i]->type();
+
+ constUnion = writeConstantUnion(*fieldType, constUnion);
+
+ if (i != fields.size() - 1)
+ {
+ out << ", ";
+ }
+ }
+
+ out << ")";
+ }
+ else
+ {
+ size_t size = type.getObjectSize();
+ bool writeType = size > 1;
+
+ if (writeType)
+ {
+ out << typeString(type) << "(";
+ }
+
+ for (size_t i = 0; i < size; i++, constUnion++)
+ {
+ switch (constUnion->getType())
+ {
+ case EbtFloat: out << std::min(FLT_MAX, std::max(-FLT_MAX, constUnion->getFConst())); break;
+ case EbtInt: out << constUnion->getIConst(); break;
+ case EbtBool: out << constUnion->getBConst(); break;
+ default: UNREACHABLE();
+ }
+
+ if (i != size - 1)
+ {
+ out << ", ";
+ }
+ }
+
+ if (writeType)
+ {
+ out << ")";
+ }
+ }
+
+ return constUnion;
+}
+
+TString OutputHLSL::scopeString(unsigned int depthLimit)
+{
+ TString string;
+
+ for (unsigned int i = 0; i < mScopeBracket.size() && i < depthLimit; i++)
+ {
+ string += "_" + str(i);
+ }
+
+ return string;
+}
+
+TString OutputHLSL::scopedStruct(const TString &typeName)
+{
+ if (typeName == "")
+ {
+ return typeName;
+ }
+
+ return typeName + scopeString(mScopeDepth);
+}
+
+TString OutputHLSL::structLookup(const TString &typeName)
+{
+ for (int depth = mScopeDepth; depth >= 0; depth--)
+ {
+ TString scopedName = decorate(typeName + scopeString(depth));
+
+ for (StructNames::iterator structName = mStructNames.begin(); structName != mStructNames.end(); structName++)
+ {
+ if (*structName == scopedName)
+ {
+ return scopedName;
+ }
+ }
+ }
+
+ UNREACHABLE(); // Should have found a matching constructor
+
+ return typeName;
+}
+
+TString OutputHLSL::decorate(const TString &string)
+{
+ if (string.compare(0, 3, "gl_") != 0 && string.compare(0, 3, "dx_") != 0)
+ {
+ return "_" + string;
+ }
+
+ return string;
+}
+
+TString OutputHLSL::decorateUniform(const TString &string, const TType &type)
+{
+ if (type.getBasicType() == EbtSamplerExternalOES)
+ {
+ return "ex_" + string;
+ }
+
+ return decorate(string);
+}
+
+TString OutputHLSL::decorateField(const TString &string, const TType &structure)
+{
+ if (structure.getStruct()->name().compare(0, 3, "gl_") != 0)
+ {
+ return decorate(string);
+ }
+
+ return string;
+}
+
+TString OutputHLSL::registerString(TIntermSymbol *operand)
+{
+ ASSERT(operand->getQualifier() == EvqUniform);
+
+ if (IsSampler(operand->getBasicType()))
+ {
+ return "s" + str(samplerRegister(operand));
+ }
+
+ return "c" + str(uniformRegister(operand));
+}
+
+int OutputHLSL::samplerRegister(TIntermSymbol *sampler)
+{
+ const TType &type = sampler->getType();
+ ASSERT(IsSampler(type.getBasicType()));
+
+ int index = mSamplerRegister;
+ mSamplerRegister += sampler->totalRegisterCount();
+
+ declareUniform(type, sampler->getSymbol(), index);
+
+ return index;
+}
+
+int OutputHLSL::uniformRegister(TIntermSymbol *uniform)
+{
+ const TType &type = uniform->getType();
+ ASSERT(!IsSampler(type.getBasicType()));
+
+ int index = mUniformRegister;
+ mUniformRegister += uniform->totalRegisterCount();
+
+ declareUniform(type, uniform->getSymbol(), index);
+
+ return index;
+}
+
+void OutputHLSL::declareUniform(const TType &type, const TString &name, int index)
+{
+ TStructure *structure = type.getStruct();
+
+ if (!structure)
+ {
+ mActiveUniforms.push_back(Uniform(glVariableType(type), glVariablePrecision(type), name.c_str(), type.getArraySize(), index));
+ }
+ else
+ {
+ const TFieldList &fields = structure->fields();
+
+ if (type.isArray())
+ {
+ int elementIndex = index;
+
+ for (int i = 0; i < type.getArraySize(); i++)
+ {
+ for (size_t j = 0; j < fields.size(); j++)
+ {
+ const TType &fieldType = *fields[j]->type();
+ const TString uniformName = name + "[" + str(i) + "]." + fields[j]->name();
+ declareUniform(fieldType, uniformName, elementIndex);
+ elementIndex += fieldType.totalRegisterCount();
+ }
+ }
+ }
+ else
+ {
+ int fieldIndex = index;
+
+ for (size_t i = 0; i < fields.size(); i++)
+ {
+ const TType &fieldType = *fields[i]->type();
+ const TString uniformName = name + "." + fields[i]->name();
+ declareUniform(fieldType, uniformName, fieldIndex);
+ fieldIndex += fieldType.totalRegisterCount();
+ }
+ }
+ }
+}
+
+GLenum OutputHLSL::glVariableType(const TType &type)
+{
+ if (type.getBasicType() == EbtFloat)
+ {
+ if (type.isScalar())
+ {
+ return GL_FLOAT;
+ }
+ else if (type.isVector())
+ {
+ switch(type.getNominalSize())
+ {
+ case 2: return GL_FLOAT_VEC2;
+ case 3: return GL_FLOAT_VEC3;
+ case 4: return GL_FLOAT_VEC4;
+ default: UNREACHABLE();
+ }
+ }
+ else if (type.isMatrix())
+ {
+ switch(type.getNominalSize())
+ {
+ case 2: return GL_FLOAT_MAT2;
+ case 3: return GL_FLOAT_MAT3;
+ case 4: return GL_FLOAT_MAT4;
+ default: UNREACHABLE();
+ }
+ }
+ else UNREACHABLE();
+ }
+ else if (type.getBasicType() == EbtInt)
+ {
+ if (type.isScalar())
+ {
+ return GL_INT;
+ }
+ else if (type.isVector())
+ {
+ switch(type.getNominalSize())
+ {
+ case 2: return GL_INT_VEC2;
+ case 3: return GL_INT_VEC3;
+ case 4: return GL_INT_VEC4;
+ default: UNREACHABLE();
+ }
+ }
+ else UNREACHABLE();
+ }
+ else if (type.getBasicType() == EbtBool)
+ {
+ if (type.isScalar())
+ {
+ return GL_BOOL;
+ }
+ else if (type.isVector())
+ {
+ switch(type.getNominalSize())
+ {
+ case 2: return GL_BOOL_VEC2;
+ case 3: return GL_BOOL_VEC3;
+ case 4: return GL_BOOL_VEC4;
+ default: UNREACHABLE();
+ }
+ }
+ else UNREACHABLE();
+ }
+ else if (type.getBasicType() == EbtSampler2D)
+ {
+ return GL_SAMPLER_2D;
+ }
+ else if (type.getBasicType() == EbtSamplerCube)
+ {
+ return GL_SAMPLER_CUBE;
+ }
+ else UNREACHABLE();
+
+ return GL_NONE;
+}
+
+GLenum OutputHLSL::glVariablePrecision(const TType &type)
+{
+ if (type.getBasicType() == EbtFloat)
+ {
+ switch (type.getPrecision())
+ {
+ case EbpHigh: return GL_HIGH_FLOAT;
+ case EbpMedium: return GL_MEDIUM_FLOAT;
+ case EbpLow: return GL_LOW_FLOAT;
+ case EbpUndefined:
+ // Should be defined as the default precision by the parser
+ default: UNREACHABLE();
+ }
+ }
+ else if (type.getBasicType() == EbtInt)
+ {
+ switch (type.getPrecision())
+ {
+ case EbpHigh: return GL_HIGH_INT;
+ case EbpMedium: return GL_MEDIUM_INT;
+ case EbpLow: return GL_LOW_INT;
+ case EbpUndefined:
+ // Should be defined as the default precision by the parser
+ default: UNREACHABLE();
+ }
+ }
+
+ // Other types (boolean, sampler) don't have a precision
+ return GL_NONE;
+}
+
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/OutputHLSL.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorOutputHLSLh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/OutputHLSL.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/OutputHLSL.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/OutputHLSL.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,167 @@
</span><ins>+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_OUTPUTHLSL_H_
+#define COMPILER_OUTPUTHLSL_H_
+
+#include <list>
+#include <set>
+#include <map>
+
+#define GL_APICALL
+#include <GLES2/gl2.h>
+
+#include "compiler/translator/intermediate.h"
+#include "compiler/translator/ParseContext.h"
+#include "compiler/translator/Uniform.h"
+
+namespace sh
+{
+class UnfoldShortCircuit;
+
+class OutputHLSL : public TIntermTraverser
+{
+ public:
+ OutputHLSL(TParseContext &context, const ShBuiltInResources& resources, ShShaderOutput outputType);
+ ~OutputHLSL();
+
+ void output();
+
+ TInfoSinkBase &getBodyStream();
+ const ActiveUniforms &getUniforms();
+
+ TString typeString(const TType &type);
+ TString textureString(const TType &type);
+ static TString qualifierString(TQualifier qualifier);
+ static TString arrayString(const TType &type);
+ static TString initializer(const TType &type);
+ static TString decorate(const TString &string); // Prepends an underscore to avoid naming clashes
+ static TString decorateUniform(const TString &string, const TType &type);
+ static TString decorateField(const TString &string, const TType &structure);
+
+ protected:
+ void header();
+
+ // Visit AST nodes and output their code to the body stream
+ void visitSymbol(TIntermSymbol*);
+ void visitConstantUnion(TIntermConstantUnion*);
+ bool visitBinary(Visit visit, TIntermBinary*);
+ bool visitUnary(Visit visit, TIntermUnary*);
+ bool visitSelection(Visit visit, TIntermSelection*);
+ bool visitAggregate(Visit visit, TIntermAggregate*);
+ bool visitLoop(Visit visit, TIntermLoop*);
+ bool visitBranch(Visit visit, TIntermBranch*);
+
+ void traverseStatements(TIntermNode *node);
+ bool isSingleStatement(TIntermNode *node);
+ bool handleExcessiveLoop(TIntermLoop *node);
+ void outputTriplet(Visit visit, const TString &preString, const TString &inString, const TString &postString);
+ void outputLineDirective(int line);
+ TString argumentString(const TIntermSymbol *symbol);
+ int vectorSize(const TType &type) const;
+
+ void addConstructor(const TType &type, const TString &name, const TIntermSequence *parameters);
+ const ConstantUnion *writeConstantUnion(const TType &type, const ConstantUnion *constUnion);
+
+ TString scopeString(unsigned int depthLimit);
+ TString scopedStruct(const TString &typeName);
+ TString structLookup(const TString &typeName);
+
+ TParseContext &mContext;
+ const ShShaderOutput mOutputType;
+ UnfoldShortCircuit *mUnfoldShortCircuit;
+ bool mInsideFunction;
+
+ // Output streams
+ TInfoSinkBase mHeader;
+ TInfoSinkBase mBody;
+ TInfoSinkBase mFooter;
+
+ typedef std::map<TString, TIntermSymbol*> ReferencedSymbols;
+ ReferencedSymbols mReferencedUniforms;
+ ReferencedSymbols mReferencedAttributes;
+ ReferencedSymbols mReferencedVaryings;
+
+ // Parameters determining what goes in the header output
+ bool mUsesTexture2D;
+ bool mUsesTexture2D_bias;
+ bool mUsesTexture2DLod;
+ bool mUsesTexture2DProj;
+ bool mUsesTexture2DProj_bias;
+ bool mUsesTexture2DProjLod;
+ bool mUsesTextureCube;
+ bool mUsesTextureCube_bias;
+ bool mUsesTextureCubeLod;
+ bool mUsesTexture2DLod0;
+ bool mUsesTexture2DLod0_bias;
+ bool mUsesTexture2DProjLod0;
+ bool mUsesTexture2DProjLod0_bias;
+ bool mUsesTextureCubeLod0;
+ bool mUsesTextureCubeLod0_bias;
+ bool mUsesFragColor;
+ bool mUsesFragData;
+ bool mUsesDepthRange;
+ bool mUsesFragCoord;
+ bool mUsesPointCoord;
+ bool mUsesFrontFacing;
+ bool mUsesPointSize;
+ bool mUsesFragDepth;
+ bool mUsesXor;
+ bool mUsesMod1;
+ bool mUsesMod2v;
+ bool mUsesMod2f;
+ bool mUsesMod3v;
+ bool mUsesMod3f;
+ bool mUsesMod4v;
+ bool mUsesMod4f;
+ bool mUsesFaceforward1;
+ bool mUsesFaceforward2;
+ bool mUsesFaceforward3;
+ bool mUsesFaceforward4;
+ bool mUsesAtan2_1;
+ bool mUsesAtan2_2;
+ bool mUsesAtan2_3;
+ bool mUsesAtan2_4;
+ bool mUsesDiscardRewriting;
+
+ int mNumRenderTargets;
+
+ typedef std::set<TString> Constructors;
+ Constructors mConstructors;
+
+ typedef std::set<TString> StructNames;
+ StructNames mStructNames;
+
+ typedef std::list<TString> StructDeclarations;
+ StructDeclarations mStructDeclarations;
+
+ typedef std::vector<int> ScopeBracket;
+ ScopeBracket mScopeBracket;
+ unsigned int mScopeDepth;
+
+ int mUniqueIndex; // For creating unique names
+
+ bool mContainsLoopDiscontinuity;
+ bool mOutputLod0Function;
+ bool mInsideDiscontinuousLoop;
+
+ TIntermSymbol *mExcessiveLoopIndex;
+
+ int mUniformRegister;
+ int mSamplerRegister;
+
+ TString registerString(TIntermSymbol *operand);
+ int samplerRegister(TIntermSymbol *sampler);
+ int uniformRegister(TIntermSymbol *uniform);
+ void declareUniform(const TType &type, const TString &name, int index);
+ static GLenum glVariableType(const TType &type);
+ static GLenum glVariablePrecision(const TType &type);
+
+ ActiveUniforms mActiveUniforms;
+};
+}
+
+#endif // COMPILER_OUTPUTHLSL_H_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/OutputHLSL.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorParseContextcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ParseContext.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ParseContext.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ParseContext.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,1602 @@
</span><ins>+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/ParseContext.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+
+#include "compiler/translator/glslang.h"
+#include "compiler/preprocessor/SourceLocation.h"
+
+///////////////////////////////////////////////////////////////////////
+//
+// Sub- vector and matrix fields
+//
+////////////////////////////////////////////////////////////////////////
+
+//
+// Look at a '.' field selector string and change it into offsets
+// for a vector.
+//
+bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TVectorFields& fields, const TSourceLoc& line)
+{
+ fields.num = (int) compString.size();
+ if (fields.num > 4) {
+ error(line, "illegal vector field selection", compString.c_str());
+ return false;
+ }
+
+ enum {
+ exyzw,
+ ergba,
+ estpq
+ } fieldSet[4];
+
+ for (int i = 0; i < fields.num; ++i) {
+ switch (compString[i]) {
+ case 'x':
+ fields.offsets[i] = 0;
+ fieldSet[i] = exyzw;
+ break;
+ case 'r':
+ fields.offsets[i] = 0;
+ fieldSet[i] = ergba;
+ break;
+ case 's':
+ fields.offsets[i] = 0;
+ fieldSet[i] = estpq;
+ break;
+ case 'y':
+ fields.offsets[i] = 1;
+ fieldSet[i] = exyzw;
+ break;
+ case 'g':
+ fields.offsets[i] = 1;
+ fieldSet[i] = ergba;
+ break;
+ case 't':
+ fields.offsets[i] = 1;
+ fieldSet[i] = estpq;
+ break;
+ case 'z':
+ fields.offsets[i] = 2;
+ fieldSet[i] = exyzw;
+ break;
+ case 'b':
+ fields.offsets[i] = 2;
+ fieldSet[i] = ergba;
+ break;
+ case 'p':
+ fields.offsets[i] = 2;
+ fieldSet[i] = estpq;
+ break;
+
+ case 'w':
+ fields.offsets[i] = 3;
+ fieldSet[i] = exyzw;
+ break;
+ case 'a':
+ fields.offsets[i] = 3;
+ fieldSet[i] = ergba;
+ break;
+ case 'q':
+ fields.offsets[i] = 3;
+ fieldSet[i] = estpq;
+ break;
+ default:
+ error(line, "illegal vector field selection", compString.c_str());
+ return false;
+ }
+ }
+
+ for (int i = 0; i < fields.num; ++i) {
+ if (fields.offsets[i] >= vecSize) {
+ error(line, "vector field selection out of range", compString.c_str());
+ return false;
+ }
+
+ if (i > 0) {
+ if (fieldSet[i] != fieldSet[i-1]) {
+ error(line, "illegal - vector component fields not from the same set", compString.c_str());
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+
+//
+// Look at a '.' field selector string and change it into offsets
+// for a matrix.
+//
+bool TParseContext::parseMatrixFields(const TString& compString, int matSize, TMatrixFields& fields, const TSourceLoc& line)
+{
+ fields.wholeRow = false;
+ fields.wholeCol = false;
+ fields.row = -1;
+ fields.col = -1;
+
+ if (compString.size() != 2) {
+ error(line, "illegal length of matrix field selection", compString.c_str());
+ return false;
+ }
+
+ if (compString[0] == '_') {
+ if (compString[1] < '0' || compString[1] > '3') {
+ error(line, "illegal matrix field selection", compString.c_str());
+ return false;
+ }
+ fields.wholeCol = true;
+ fields.col = compString[1] - '0';
+ } else if (compString[1] == '_') {
+ if (compString[0] < '0' || compString[0] > '3') {
+ error(line, "illegal matrix field selection", compString.c_str());
+ return false;
+ }
+ fields.wholeRow = true;
+ fields.row = compString[0] - '0';
+ } else {
+ if (compString[0] < '0' || compString[0] > '3' ||
+ compString[1] < '0' || compString[1] > '3') {
+ error(line, "illegal matrix field selection", compString.c_str());
+ return false;
+ }
+ fields.row = compString[0] - '0';
+ fields.col = compString[1] - '0';
+ }
+
+ if (fields.row >= matSize || fields.col >= matSize) {
+ error(line, "matrix field selection out of range", compString.c_str());
+ return false;
+ }
+
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////
+//
+// Errors
+//
+////////////////////////////////////////////////////////////////////////
+
+//
+// Track whether errors have occurred.
+//
+void TParseContext::recover()
+{
+}
+
+//
+// Used by flex/bison to output all syntax and parsing errors.
+//
+void TParseContext::error(const TSourceLoc& loc,
+ const char* reason, const char* token,
+ const char* extraInfo)
+{
+ pp::SourceLocation srcLoc;
+ srcLoc.file = loc.first_file;
+ srcLoc.line = loc.first_line;
+ diagnostics.writeInfo(pp::Diagnostics::PP_ERROR,
+ srcLoc, reason, token, extraInfo);
+
+}
+
+void TParseContext::warning(const TSourceLoc& loc,
+ const char* reason, const char* token,
+ const char* extraInfo) {
+ pp::SourceLocation srcLoc;
+ srcLoc.file = loc.first_file;
+ srcLoc.line = loc.first_line;
+ diagnostics.writeInfo(pp::Diagnostics::PP_WARNING,
+ srcLoc, reason, token, extraInfo);
+}
+
+void TParseContext::trace(const char* str)
+{
+ diagnostics.writeDebug(str);
+}
+
+//
+// Same error message for all places assignments don't work.
+//
+void TParseContext::assignError(const TSourceLoc& line, const char* op, TString left, TString right)
+{
+ std::stringstream extraInfoStream;
+ extraInfoStream << "cannot convert from '" << right << "' to '" << left << "'";
+ std::string extraInfo = extraInfoStream.str();
+ error(line, "", op, extraInfo.c_str());
+}
+
+//
+// Same error message for all places unary operations don't work.
+//
+void TParseContext::unaryOpError(const TSourceLoc& line, const char* op, TString operand)
+{
+ std::stringstream extraInfoStream;
+ extraInfoStream << "no operation '" << op << "' exists that takes an operand of type " << operand
+ << " (or there is no acceptable conversion)";
+ std::string extraInfo = extraInfoStream.str();
+ error(line, " wrong operand type", op, extraInfo.c_str());
+}
+
+//
+// Same error message for all binary operations don't work.
+//
+void TParseContext::binaryOpError(const TSourceLoc& line, const char* op, TString left, TString right)
+{
+ std::stringstream extraInfoStream;
+ extraInfoStream << "no operation '" << op << "' exists that takes a left-hand operand of type '" << left
+ << "' and a right operand of type '" << right << "' (or there is no acceptable conversion)";
+ std::string extraInfo = extraInfoStream.str();
+ error(line, " wrong operand types ", op, extraInfo.c_str());
+}
+
+bool TParseContext::precisionErrorCheck(const TSourceLoc& line, TPrecision precision, TBasicType type){
+ if (!checksPrecisionErrors)
+ return false;
+ switch( type ){
+ case EbtFloat:
+ if( precision == EbpUndefined ){
+ error( line, "No precision specified for (float)", "" );
+ return true;
+ }
+ break;
+ case EbtInt:
+ if( precision == EbpUndefined ){
+ error( line, "No precision specified (int)", "" );
+ return true;
+ }
+ break;
+ default:
+ return false;
+ }
+ return false;
+}
+
+//
+// Both test and if necessary, spit out an error, to see if the node is really
+// an l-value that can be operated on this way.
+//
+// Returns true if the was an error.
+//
+bool TParseContext::lValueErrorCheck(const TSourceLoc& line, const char* op, TIntermTyped* node)
+{
+ TIntermSymbol* symNode = node->getAsSymbolNode();
+ TIntermBinary* binaryNode = node->getAsBinaryNode();
+
+ if (binaryNode) {
+ bool errorReturn;
+
+ switch(binaryNode->getOp()) {
+ case EOpIndexDirect:
+ case EOpIndexIndirect:
+ case EOpIndexDirectStruct:
+ return lValueErrorCheck(line, op, binaryNode->getLeft());
+ case EOpVectorSwizzle:
+ errorReturn = lValueErrorCheck(line, op, binaryNode->getLeft());
+ if (!errorReturn) {
+ int offset[4] = {0,0,0,0};
+
+ TIntermTyped* rightNode = binaryNode->getRight();
+ TIntermAggregate *aggrNode = rightNode->getAsAggregate();
+
+ for (TIntermSequence::iterator p = aggrNode->getSequence().begin();
+ p != aggrNode->getSequence().end(); p++) {
+ int value = (*p)->getAsTyped()->getAsConstantUnion()->getIConst(0);
+ offset[value]++;
+ if (offset[value] > 1) {
+ error(line, " l-value of swizzle cannot have duplicate components", op);
+
+ return true;
+ }
+ }
+ }
+
+ return errorReturn;
+ default:
+ break;
+ }
+ error(line, " l-value required", op);
+
+ return true;
+ }
+
+
+ const char* symbol = 0;
+ if (symNode != 0)
+ symbol = symNode->getSymbol().c_str();
+
+ const char* message = 0;
+ switch (node->getQualifier()) {
+ case EvqConst: message = "can't modify a const"; break;
+ case EvqConstReadOnly: message = "can't modify a const"; break;
+ case EvqAttribute: message = "can't modify an attribute"; break;
+ case EvqUniform: message = "can't modify a uniform"; break;
+ case EvqVaryingIn: message = "can't modify a varying"; break;
+ case EvqFragCoord: message = "can't modify gl_FragCoord"; break;
+ case EvqFrontFacing: message = "can't modify gl_FrontFacing"; break;
+ case EvqPointCoord: message = "can't modify gl_PointCoord"; break;
+ default:
+
+ //
+ // Type that can't be written to?
+ //
+ switch (node->getBasicType()) {
+ case EbtSampler2D:
+ case EbtSamplerCube:
+ message = "can't modify a sampler";
+ break;
+ case EbtVoid:
+ message = "can't modify void";
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (message == 0 && binaryNode == 0 && symNode == 0) {
+ error(line, " l-value required", op);
+
+ return true;
+ }
+
+
+ //
+ // Everything else is okay, no error.
+ //
+ if (message == 0)
+ return false;
+
+ //
+ // If we get here, we have an error and a message.
+ //
+ if (symNode) {
+ std::stringstream extraInfoStream;
+ extraInfoStream << "\"" << symbol << "\" (" << message << ")";
+ std::string extraInfo = extraInfoStream.str();
+ error(line, " l-value required", op, extraInfo.c_str());
+ }
+ else {
+ std::stringstream extraInfoStream;
+ extraInfoStream << "(" << message << ")";
+ std::string extraInfo = extraInfoStream.str();
+ error(line, " l-value required", op, extraInfo.c_str());
+ }
+
+ return true;
+}
+
+//
+// Both test, and if necessary spit out an error, to see if the node is really
+// a constant.
+//
+// Returns true if the was an error.
+//
+bool TParseContext::constErrorCheck(TIntermTyped* node)
+{
+ if (node->getQualifier() == EvqConst)
+ return false;
+
+ error(node->getLine(), "constant expression required", "");
+
+ return true;
+}
+
+//
+// Both test, and if necessary spit out an error, to see if the node is really
+// an integer.
+//
+// Returns true if the was an error.
+//
+bool TParseContext::integerErrorCheck(TIntermTyped* node, const char* token)
+{
+ if (node->getBasicType() == EbtInt && node->getNominalSize() == 1)
+ return false;
+
+ error(node->getLine(), "integer expression required", token);
+
+ return true;
+}
+
+//
+// Both test, and if necessary spit out an error, to see if we are currently
+// globally scoped.
+//
+// Returns true if the was an error.
+//
+bool TParseContext::globalErrorCheck(const TSourceLoc& line, bool global, const char* token)
+{
+ if (global)
+ return false;
+
+ error(line, "only allowed at global scope", token);
+
+ return true;
+}
+
+//
+// For now, keep it simple: if it starts "gl_", it's reserved, independent
+// of scope. Except, if the symbol table is at the built-in push-level,
+// which is when we are parsing built-ins.
+// Also checks for "webgl_" and "_webgl_" reserved identifiers if parsing a
+// webgl shader.
+//
+// Returns true if there was an error.
+//
+bool TParseContext::reservedErrorCheck(const TSourceLoc& line, const TString& identifier)
+{
+ static const char* reservedErrMsg = "reserved built-in name";
+ if (!symbolTable.atBuiltInLevel()) {
+ if (identifier.compare(0, 3, "gl_") == 0) {
+ error(line, reservedErrMsg, "gl_");
+ return true;
+ }
+ if (isWebGLBasedSpec(shaderSpec)) {
+ if (identifier.compare(0, 6, "webgl_") == 0) {
+ error(line, reservedErrMsg, "webgl_");
+ return true;
+ }
+ if (identifier.compare(0, 7, "_webgl_") == 0) {
+ error(line, reservedErrMsg, "_webgl_");
+ return true;
+ }
+ if (shaderSpec == SH_CSS_SHADERS_SPEC && identifier.compare(0, 4, "css_") == 0) {
+ error(line, reservedErrMsg, "css_");
+ return true;
+ }
+ }
+ if (identifier.find("__") != TString::npos) {
+ error(line, "identifiers containing two consecutive underscores (__) are reserved as possible future keywords", identifier.c_str());
+ return true;
+ }
+ }
+
+ return false;
+}
+
+//
+// Make sure there is enough data provided to the constructor to build
+// something of the type of the constructor. Also returns the type of
+// the constructor.
+//
+// Returns true if there was an error in construction.
+//
+bool TParseContext::constructorErrorCheck(const TSourceLoc& line, TIntermNode* node, TFunction& function, TOperator op, TType* type)
+{
+ *type = function.getReturnType();
+
+ bool constructingMatrix = false;
+ switch(op) {
+ case EOpConstructMat2:
+ case EOpConstructMat3:
+ case EOpConstructMat4:
+ constructingMatrix = true;
+ break;
+ default:
+ break;
+ }
+
+ //
+ // Note: It's okay to have too many components available, but not okay to have unused
+ // arguments. 'full' will go to true when enough args have been seen. If we loop
+ // again, there is an extra argument, so 'overfull' will become true.
+ //
+
+ size_t size = 0;
+ bool constType = true;
+ bool full = false;
+ bool overFull = false;
+ bool matrixInMatrix = false;
+ bool arrayArg = false;
+ for (size_t i = 0; i < function.getParamCount(); ++i) {
+ const TParameter& param = function.getParam(i);
+ size += param.type->getObjectSize();
+
+ if (constructingMatrix && param.type->isMatrix())
+ matrixInMatrix = true;
+ if (full)
+ overFull = true;
+ if (op != EOpConstructStruct && !type->isArray() && size >= type->getObjectSize())
+ full = true;
+ if (param.type->getQualifier() != EvqConst)
+ constType = false;
+ if (param.type->isArray())
+ arrayArg = true;
+ }
+
+ if (constType)
+ type->setQualifier(EvqConst);
+
+ if (type->isArray() && static_cast<size_t>(type->getArraySize()) != function.getParamCount()) {
+ error(line, "array constructor needs one argument per array element", "constructor");
+ return true;
+ }
+
+ if (arrayArg && op != EOpConstructStruct) {
+ error(line, "constructing from a non-dereferenced array", "constructor");
+ return true;
+ }
+
+ if (matrixInMatrix && !type->isArray()) {
+ if (function.getParamCount() != 1) {
+ error(line, "constructing matrix from matrix can only take one argument", "constructor");
+ return true;
+ }
+ }
+
+ if (overFull) {
+ error(line, "too many arguments", "constructor");
+ return true;
+ }
+
+ if (op == EOpConstructStruct && !type->isArray() && type->getStruct()->fields().size() != function.getParamCount()) {
+ error(line, "Number of constructor parameters does not match the number of structure fields", "constructor");
+ return true;
+ }
+
+ if (!type->isMatrix() || !matrixInMatrix) {
+ if ((op != EOpConstructStruct && size != 1 && size < type->getObjectSize()) ||
+ (op == EOpConstructStruct && size < type->getObjectSize())) {
+ error(line, "not enough data provided for construction", "constructor");
+ return true;
+ }
+ }
+
+ TIntermTyped *typed = node ? node->getAsTyped() : 0;
+ if (typed == 0) {
+ error(line, "constructor argument does not have a type", "constructor");
+ return true;
+ }
+ if (op != EOpConstructStruct && IsSampler(typed->getBasicType())) {
+ error(line, "cannot convert a sampler", "constructor");
+ return true;
+ }
+ if (typed->getBasicType() == EbtVoid) {
+ error(line, "cannot convert a void", "constructor");
+ return true;
+ }
+
+ return false;
+}
+
+// This function checks to see if a void variable has been declared and raise an error message for such a case
+//
+// returns true in case of an error
+//
+bool TParseContext::voidErrorCheck(const TSourceLoc& line, const TString& identifier, const TPublicType& pubType)
+{
+ if (pubType.type == EbtVoid) {
+ error(line, "illegal use of type 'void'", identifier.c_str());
+ return true;
+ }
+
+ return false;
+}
+
+// This function checks to see if the node (for the expression) contains a scalar boolean expression or not
+//
+// returns true in case of an error
+//
+bool TParseContext::boolErrorCheck(const TSourceLoc& line, const TIntermTyped* type)
+{
+ if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector()) {
+ error(line, "boolean expression expected", "");
+ return true;
+ }
+
+ return false;
+}
+
+// This function checks to see if the node (for the expression) contains a scalar boolean expression or not
+//
+// returns true in case of an error
+//
+bool TParseContext::boolErrorCheck(const TSourceLoc& line, const TPublicType& pType)
+{
+ if (pType.type != EbtBool || pType.array || pType.matrix || (pType.size > 1)) {
+ error(line, "boolean expression expected", "");
+ return true;
+ }
+
+ return false;
+}
+
+bool TParseContext::samplerErrorCheck(const TSourceLoc& line, const TPublicType& pType, const char* reason)
+{
+ if (pType.type == EbtStruct) {
+ if (containsSampler(*pType.userDef)) {
+ error(line, reason, getBasicString(pType.type), "(structure contains a sampler)");
+
+ return true;
+ }
+
+ return false;
+ } else if (IsSampler(pType.type)) {
+ error(line, reason, getBasicString(pType.type));
+
+ return true;
+ }
+
+ return false;
+}
+
+bool TParseContext::structQualifierErrorCheck(const TSourceLoc& line, const TPublicType& pType)
+{
+ if ((pType.qualifier == EvqVaryingIn || pType.qualifier == EvqVaryingOut || pType.qualifier == EvqAttribute) &&
+ pType.type == EbtStruct) {
+ error(line, "cannot be used with a structure", getQualifierString(pType.qualifier));
+
+ return true;
+ }
+
+ if (pType.qualifier != EvqUniform && samplerErrorCheck(line, pType, "samplers must be uniform"))
+ return true;
+
+ return false;
+}
+
+bool TParseContext::parameterSamplerErrorCheck(const TSourceLoc& line, TQualifier qualifier, const TType& type)
+{
+ if ((qualifier == EvqOut || qualifier == EvqInOut) &&
+ type.getBasicType() != EbtStruct && IsSampler(type.getBasicType())) {
+ error(line, "samplers cannot be output parameters", type.getBasicString());
+ return true;
+ }
+
+ return false;
+}
+
+bool TParseContext::containsSampler(TType& type)
+{
+ if (IsSampler(type.getBasicType()))
+ return true;
+
+ if (type.getBasicType() == EbtStruct) {
+ const TFieldList& fields = type.getStruct()->fields();
+ for (unsigned int i = 0; i < fields.size(); ++i) {
+ if (containsSampler(*fields[i]->type()))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+//
+// Do size checking for an array type's size.
+//
+// Returns true if there was an error.
+//
+bool TParseContext::arraySizeErrorCheck(const TSourceLoc& line, TIntermTyped* expr, int& size)
+{
+ TIntermConstantUnion* constant = expr->getAsConstantUnion();
+ if (constant == 0 || constant->getBasicType() != EbtInt) {
+ error(line, "array size must be a constant integer expression", "");
+ return true;
+ }
+
+ size = constant->getIConst(0);
+
+ if (size <= 0) {
+ error(line, "array size must be a positive integer", "");
+ size = 1;
+ return true;
+ }
+
+ return false;
+}
+
+//
+// See if this qualifier can be an array.
+//
+// Returns true if there is an error.
+//
+bool TParseContext::arrayQualifierErrorCheck(const TSourceLoc& line, TPublicType type)
+{
+ if ((type.qualifier == EvqAttribute) || (type.qualifier == EvqConst)) {
+ error(line, "cannot declare arrays of this qualifier", TType(type).getCompleteString().c_str());
+ return true;
+ }
+
+ return false;
+}
+
+//
+// See if this type can be an array.
+//
+// Returns true if there is an error.
+//
+bool TParseContext::arrayTypeErrorCheck(const TSourceLoc& line, TPublicType type)
+{
+ //
+ // Can the type be an array?
+ //
+ if (type.array) {
+ error(line, "cannot declare arrays of arrays", TType(type).getCompleteString().c_str());
+ return true;
+ }
+
+ return false;
+}
+
+//
+// Do all the semantic checking for declaring an array, with and
+// without a size, and make the right changes to the symbol table.
+//
+// size == 0 means no specified size.
+//
+// Returns true if there was an error.
+//
+bool TParseContext::arrayErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType type, TVariable*& variable)
+{
+ //
+ // Don't check for reserved word use until after we know it's not in the symbol table,
+ // because reserved arrays can be redeclared.
+ //
+
+ bool builtIn = false;
+ bool sameScope = false;
+ TSymbol* symbol = symbolTable.find(identifier, &builtIn, &sameScope);
+ if (symbol == 0 || !sameScope) {
+ if (reservedErrorCheck(line, identifier))
+ return true;
+
+ variable = new TVariable(&identifier, TType(type));
+
+ if (type.arraySize)
+ variable->getType().setArraySize(type.arraySize);
+
+ if (! symbolTable.insert(*variable)) {
+ delete variable;
+ error(line, "INTERNAL ERROR inserting new symbol", identifier.c_str());
+ return true;
+ }
+ } else {
+ if (! symbol->isVariable()) {
+ error(line, "variable expected", identifier.c_str());
+ return true;
+ }
+
+ variable = static_cast<TVariable*>(symbol);
+ if (! variable->getType().isArray()) {
+ error(line, "redeclaring non-array as array", identifier.c_str());
+ return true;
+ }
+ if (variable->getType().getArraySize() > 0) {
+ error(line, "redeclaration of array with size", identifier.c_str());
+ return true;
+ }
+
+ if (! variable->getType().sameElementType(TType(type))) {
+ error(line, "redeclaration of array with a different type", identifier.c_str());
+ return true;
+ }
+
+ if (type.arraySize)
+ variable->getType().setArraySize(type.arraySize);
+ }
+
+ if (voidErrorCheck(line, identifier, type))
+ return true;
+
+ return false;
+}
+
+//
+// Enforce non-initializer type/qualifier rules.
+//
+// Returns true if there was an error.
+//
+bool TParseContext::nonInitConstErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType& type, bool array)
+{
+ if (type.qualifier == EvqConst)
+ {
+ // Make the qualifier make sense.
+ type.qualifier = EvqTemporary;
+
+ if (array)
+ {
+ error(line, "arrays may not be declared constant since they cannot be initialized", identifier.c_str());
+ }
+ else if (type.isStructureContainingArrays())
+ {
+ error(line, "structures containing arrays may not be declared constant since they cannot be initialized", identifier.c_str());
+ }
+ else
+ {
+ error(line, "variables with qualifier 'const' must be initialized", identifier.c_str());
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+//
+// Do semantic checking for a variable declaration that has no initializer,
+// and update the symbol table.
+//
+// Returns true if there was an error.
+//
+bool TParseContext::nonInitErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType& type, TVariable*& variable)
+{
+ if (reservedErrorCheck(line, identifier))
+ recover();
+
+ variable = new TVariable(&identifier, TType(type));
+
+ if (! symbolTable.insert(*variable)) {
+ error(line, "redefinition", variable->getName().c_str());
+ delete variable;
+ variable = 0;
+ return true;
+ }
+
+ if (voidErrorCheck(line, identifier, type))
+ return true;
+
+ return false;
+}
+
+bool TParseContext::paramErrorCheck(const TSourceLoc& line, TQualifier qualifier, TQualifier paramQualifier, TType* type)
+{
+ if (qualifier != EvqConst && qualifier != EvqTemporary) {
+ error(line, "qualifier not allowed on function parameter", getQualifierString(qualifier));
+ return true;
+ }
+ if (qualifier == EvqConst && paramQualifier != EvqIn) {
+ error(line, "qualifier not allowed with ", getQualifierString(qualifier), getQualifierString(paramQualifier));
+ return true;
+ }
+
+ if (qualifier == EvqConst)
+ type->setQualifier(EvqConstReadOnly);
+ else
+ type->setQualifier(paramQualifier);
+
+ return false;
+}
+
+bool TParseContext::extensionErrorCheck(const TSourceLoc& line, const TString& extension)
+{
+ const TExtensionBehavior& extBehavior = extensionBehavior();
+ TExtensionBehavior::const_iterator iter = extBehavior.find(extension.c_str());
+ if (iter == extBehavior.end()) {
+ error(line, "extension", extension.c_str(), "is not supported");
+ return true;
+ }
+ // In GLSL ES, an extension's default behavior is "disable".
+ if (iter->second == EBhDisable || iter->second == EBhUndefined) {
+ error(line, "extension", extension.c_str(), "is disabled");
+ return true;
+ }
+ if (iter->second == EBhWarn) {
+ warning(line, "extension", extension.c_str(), "is being used");
+ return false;
+ }
+
+ return false;
+}
+
+bool TParseContext::supportsExtension(const char* extension)
+{
+ const TExtensionBehavior& extbehavior = extensionBehavior();
+ TExtensionBehavior::const_iterator iter = extbehavior.find(extension);
+ return (iter != extbehavior.end());
+}
+
+bool TParseContext::isExtensionEnabled(const char* extension) const
+{
+ const TExtensionBehavior& extbehavior = extensionBehavior();
+ TExtensionBehavior::const_iterator iter = extbehavior.find(extension);
+
+ if (iter == extbehavior.end())
+ {
+ return false;
+ }
+
+ return (iter->second == EBhEnable || iter->second == EBhRequire);
+}
+
+/////////////////////////////////////////////////////////////////////////////////
+//
+// Non-Errors.
+//
+/////////////////////////////////////////////////////////////////////////////////
+
+//
+// Look up a function name in the symbol table, and make sure it is a function.
+//
+// Return the function symbol if found, otherwise 0.
+//
+const TFunction* TParseContext::findFunction(const TSourceLoc& line, TFunction* call, bool *builtIn)
+{
+ // First find by unmangled name to check whether the function name has been
+ // hidden by a variable name or struct typename.
+ // If a function is found, check for one with a matching argument list.
+ const TSymbol* symbol = symbolTable.find(call->getName(), builtIn);
+ if (symbol == 0 || symbol->isFunction()) {
+ symbol = symbolTable.find(call->getMangledName(), builtIn);
+ }
+
+ if (symbol == 0) {
+ error(line, "no matching overloaded function found", call->getName().c_str());
+ return 0;
+ }
+
+ if (!symbol->isFunction()) {
+ error(line, "function name expected", call->getName().c_str());
+ return 0;
+ }
+
+ return static_cast<const TFunction*>(symbol);
+}
+
+//
+// Initializers show up in several places in the grammar. Have one set of
+// code to handle them here.
+//
+bool TParseContext::executeInitializer(const TSourceLoc& line, TString& identifier, TPublicType& pType,
+ TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable)
+{
+ TType type = TType(pType);
+
+ if (variable == 0) {
+ if (reservedErrorCheck(line, identifier))
+ return true;
+
+ if (voidErrorCheck(line, identifier, pType))
+ return true;
+
+ //
+ // add variable to symbol table
+ //
+ variable = new TVariable(&identifier, type);
+ if (! symbolTable.insert(*variable)) {
+ error(line, "redefinition", variable->getName().c_str());
+ return true;
+ // don't delete variable, it's used by error recovery, and the pool
+ // pop will take care of the memory
+ }
+ }
+
+ //
+ // identifier must be of type constant, a global, or a temporary
+ //
+ TQualifier qualifier = variable->getType().getQualifier();
+ if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConst)) {
+ error(line, " cannot initialize this type of qualifier ", variable->getType().getQualifierString());
+ return true;
+ }
+ //
+ // test for and propagate constant
+ //
+
+ if (qualifier == EvqConst) {
+ if (qualifier != initializer->getType().getQualifier()) {
+ std::stringstream extraInfoStream;
+ extraInfoStream << "'" << variable->getType().getCompleteString() << "'";
+ std::string extraInfo = extraInfoStream.str();
+ error(line, " assigning non-constant to", "=", extraInfo.c_str());
+ variable->getType().setQualifier(EvqTemporary);
+ return true;
+ }
+ if (type != initializer->getType()) {
+ error(line, " non-matching types for const initializer ",
+ variable->getType().getQualifierString());
+ variable->getType().setQualifier(EvqTemporary);
+ return true;
+ }
+ if (initializer->getAsConstantUnion()) {
+ variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer());
+ } else if (initializer->getAsSymbolNode()) {
+ const TSymbol* symbol = symbolTable.find(initializer->getAsSymbolNode()->getSymbol());
+ const TVariable* tVar = static_cast<const TVariable*>(symbol);
+
+ ConstantUnion* constArray = tVar->getConstPointer();
+ variable->shareConstPointer(constArray);
+ } else {
+ std::stringstream extraInfoStream;
+ extraInfoStream << "'" << variable->getType().getCompleteString() << "'";
+ std::string extraInfo = extraInfoStream.str();
+ error(line, " cannot assign to", "=", extraInfo.c_str());
+ variable->getType().setQualifier(EvqTemporary);
+ return true;
+ }
+ }
+
+ if (qualifier != EvqConst) {
+ TIntermSymbol* intermSymbol = intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), line);
+ intermNode = intermediate.addAssign(EOpInitialize, intermSymbol, initializer, line);
+ if (intermNode == 0) {
+ assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString());
+ return true;
+ }
+ } else
+ intermNode = 0;
+
+ return false;
+}
+
+bool TParseContext::areAllChildConst(TIntermAggregate* aggrNode)
+{
+ ASSERT(aggrNode != NULL);
+ if (!aggrNode->isConstructor())
+ return false;
+
+ bool allConstant = true;
+
+ // check if all the child nodes are constants so that they can be inserted into
+ // the parent node
+ TIntermSequence &sequence = aggrNode->getSequence() ;
+ for (TIntermSequence::iterator p = sequence.begin(); p != sequence.end(); ++p) {
+ if (!(*p)->getAsTyped()->getAsConstantUnion())
+ return false;
+ }
+
+ return allConstant;
+}
+
+// This function is used to test for the correctness of the parameters passed to various constructor functions
+// and also convert them to the right datatype if it is allowed and required.
+//
+// Returns 0 for an error or the constructed node (aggregate or typed) for no error.
+//
+TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type, TOperator op, TFunction* fnCall, const TSourceLoc& line)
+{
+ if (node == 0)
+ return 0;
+
+ TIntermAggregate* aggrNode = node->getAsAggregate();
+
+ TFieldList::const_iterator memberFields;
+ if (op == EOpConstructStruct)
+ memberFields = type->getStruct()->fields().begin();
+
+ TType elementType = *type;
+ if (type->isArray())
+ elementType.clearArrayness();
+
+ bool singleArg;
+ if (aggrNode) {
+ if (aggrNode->getOp() != EOpNull || aggrNode->getSequence().size() == 1)
+ singleArg = true;
+ else
+ singleArg = false;
+ } else
+ singleArg = true;
+
+ TIntermTyped *newNode;
+ if (singleArg) {
+ // If structure constructor or array constructor is being called
+ // for only one parameter inside the structure, we need to call constructStruct function once.
+ if (type->isArray())
+ newNode = constructStruct(node, &elementType, 1, node->getLine(), false);
+ else if (op == EOpConstructStruct)
+ newNode = constructStruct(node, (*memberFields)->type(), 1, node->getLine(), false);
+ else
+ newNode = constructBuiltIn(type, op, node, node->getLine(), false);
+
+ if (newNode && newNode->getAsAggregate()) {
+ TIntermTyped* constConstructor = foldConstConstructor(newNode->getAsAggregate(), *type);
+ if (constConstructor)
+ return constConstructor;
+ }
+
+ return newNode;
+ }
+
+ //
+ // Handle list of arguments.
+ //
+ TIntermSequence &sequenceVector = aggrNode->getSequence() ; // Stores the information about the parameter to the constructor
+ // if the structure constructor contains more than one parameter, then construct
+ // each parameter
+
+ int paramCount = 0; // keeps a track of the constructor parameter number being checked
+
+ // for each parameter to the constructor call, check to see if the right type is passed or convert them
+ // to the right type if possible (and allowed).
+ // for structure constructors, just check if the right type is passed, no conversion is allowed.
+
+ for (TIntermSequence::iterator p = sequenceVector.begin();
+ p != sequenceVector.end(); p++, paramCount++) {
+ if (type->isArray())
+ newNode = constructStruct(*p, &elementType, paramCount+1, node->getLine(), true);
+ else if (op == EOpConstructStruct)
+ newNode = constructStruct(*p, memberFields[paramCount]->type(), paramCount+1, node->getLine(), true);
+ else
+ newNode = constructBuiltIn(type, op, *p, node->getLine(), true);
+
+ if (newNode) {
+ *p = newNode;
+ }
+ }
+
+ TIntermTyped* constructor = intermediate.setAggregateOperator(aggrNode, op, line);
+ TIntermTyped* constConstructor = foldConstConstructor(constructor->getAsAggregate(), *type);
+ if (constConstructor)
+ return constConstructor;
+
+ return constructor;
+}
+
+TIntermTyped* TParseContext::foldConstConstructor(TIntermAggregate* aggrNode, const TType& type)
+{
+ bool canBeFolded = areAllChildConst(aggrNode);
+ aggrNode->setType(type);
+ if (canBeFolded) {
+ bool returnVal = false;
+ ConstantUnion* unionArray = new ConstantUnion[type.getObjectSize()];
+ if (aggrNode->getSequence().size() == 1) {
+ returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), symbolTable, type, true);
+ }
+ else {
+ returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), symbolTable, type);
+ }
+ if (returnVal)
+ return 0;
+
+ return intermediate.addConstantUnion(unionArray, type, aggrNode->getLine());
+ }
+
+ return 0;
+}
+
+// Function for constructor implementation. Calls addUnaryMath with appropriate EOp value
+// for the parameter to the constructor (passed to this function). Essentially, it converts
+// the parameter types correctly. If a constructor expects an int (like ivec2) and is passed a
+// float, then float is converted to int.
+//
+// Returns 0 for an error or the constructed node.
+//
+TIntermTyped* TParseContext::constructBuiltIn(const TType* type, TOperator op, TIntermNode* node, const TSourceLoc& line, bool subset)
+{
+ TIntermTyped* newNode;
+ TOperator basicOp;
+
+ //
+ // First, convert types as needed.
+ //
+ switch (op) {
+ case EOpConstructVec2:
+ case EOpConstructVec3:
+ case EOpConstructVec4:
+ case EOpConstructMat2:
+ case EOpConstructMat3:
+ case EOpConstructMat4:
+ case EOpConstructFloat:
+ basicOp = EOpConstructFloat;
+ break;
+
+ case EOpConstructIVec2:
+ case EOpConstructIVec3:
+ case EOpConstructIVec4:
+ case EOpConstructInt:
+ basicOp = EOpConstructInt;
+ break;
+
+ case EOpConstructBVec2:
+ case EOpConstructBVec3:
+ case EOpConstructBVec4:
+ case EOpConstructBool:
+ basicOp = EOpConstructBool;
+ break;
+
+ default:
+ error(line, "unsupported construction", "");
+ recover();
+
+ return 0;
+ }
+ newNode = intermediate.addUnaryMath(basicOp, node, node->getLine(), symbolTable);
+ if (newNode == 0) {
+ error(line, "can't convert", "constructor");
+ return 0;
+ }
+
+ //
+ // Now, if there still isn't an operation to do the construction, and we need one, add one.
+ //
+
+ // Otherwise, skip out early.
+ if (subset || (newNode != node && newNode->getType() == *type))
+ return newNode;
+
+ // setAggregateOperator will insert a new node for the constructor, as needed.
+ return intermediate.setAggregateOperator(newNode, op, line);
+}
+
+// This function tests for the type of the parameters to the structures constructors. Raises
+// an error message if the expected type does not match the parameter passed to the constructor.
+//
+// Returns 0 for an error or the input node itself if the expected and the given parameter types match.
+//
+TIntermTyped* TParseContext::constructStruct(TIntermNode* node, TType* type, int paramCount, const TSourceLoc& line, bool subset)
+{
+ if (*type == node->getAsTyped()->getType()) {
+ if (subset)
+ return node->getAsTyped();
+ else
+ return intermediate.setAggregateOperator(node->getAsTyped(), EOpConstructStruct, line);
+ } else {
+ std::stringstream extraInfoStream;
+ extraInfoStream << "cannot convert parameter " << paramCount
+ << " from '" << node->getAsTyped()->getType().getBasicString()
+ << "' to '" << type->getBasicString() << "'";
+ std::string extraInfo = extraInfoStream.str();
+ error(line, "", "constructor", extraInfo.c_str());
+ recover();
+ }
+
+ return 0;
+}
+
+//
+// This function returns the tree representation for the vector field(s) being accessed from contant vector.
+// If only one component of vector is accessed (v.x or v[0] where v is a contant vector), then a contant node is
+// returned, else an aggregate node is returned (for v.xy). The input to this function could either be the symbol
+// node or it could be the intermediate tree representation of accessing fields in a constant structure or column of
+// a constant matrix.
+//
+TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTyped* node, const TSourceLoc& line)
+{
+ TIntermTyped* typedNode;
+ TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
+
+ ConstantUnion *unionArray;
+ if (tempConstantNode) {
+ unionArray = tempConstantNode->getUnionArrayPointer();
+
+ if (!unionArray) {
+ return node;
+ }
+ } else { // The node has to be either a symbol node or an aggregate node or a tempConstant node, else, its an error
+ error(line, "Cannot offset into the vector", "Error");
+ recover();
+
+ return 0;
+ }
+
+ ConstantUnion* constArray = new ConstantUnion[fields.num];
+
+ for (int i = 0; i < fields.num; i++) {
+ if (fields.offsets[i] >= node->getType().getNominalSize()) {
+ std::stringstream extraInfoStream;
+ extraInfoStream << "vector field selection out of range '" << fields.offsets[i] << "'";
+ std::string extraInfo = extraInfoStream.str();
+ error(line, "", "[", extraInfo.c_str());
+ recover();
+ fields.offsets[i] = 0;
+ }
+
+ constArray[i] = unionArray[fields.offsets[i]];
+
+ }
+ typedNode = intermediate.addConstantUnion(constArray, node->getType(), line);
+ return typedNode;
+}
+
+//
+// This function returns the column being accessed from a constant matrix. The values are retrieved from
+// the symbol table and parse-tree is built for a vector (each column of a matrix is a vector). The input
+// to the function could either be a symbol node (m[0] where m is a constant matrix)that represents a
+// constant matrix or it could be the tree representation of the constant matrix (s.m1[0] where s is a constant structure)
+//
+TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, const TSourceLoc& line)
+{
+ TIntermTyped* typedNode;
+ TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
+
+ if (index >= node->getType().getNominalSize()) {
+ std::stringstream extraInfoStream;
+ extraInfoStream << "matrix field selection out of range '" << index << "'";
+ std::string extraInfo = extraInfoStream.str();
+ error(line, "", "[", extraInfo.c_str());
+ recover();
+ index = 0;
+ }
+
+ if (tempConstantNode) {
+ ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer();
+ int size = tempConstantNode->getType().getNominalSize();
+ typedNode = intermediate.addConstantUnion(&unionArray[size*index], tempConstantNode->getType(), line);
+ } else {
+ error(line, "Cannot offset into the matrix", "Error");
+ recover();
+
+ return 0;
+ }
+
+ return typedNode;
+}
+
+
+//
+// This function returns an element of an array accessed from a constant array. The values are retrieved from
+// the symbol table and parse-tree is built for the type of the element. The input
+// to the function could either be a symbol node (a[0] where a is a constant array)that represents a
+// constant array or it could be the tree representation of the constant array (s.a1[0] where s is a constant structure)
+//
+TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, const TSourceLoc& line)
+{
+ TIntermTyped* typedNode;
+ TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
+ TType arrayElementType = node->getType();
+ arrayElementType.clearArrayness();
+
+ if (index >= node->getType().getArraySize()) {
+ std::stringstream extraInfoStream;
+ extraInfoStream << "array field selection out of range '" << index << "'";
+ std::string extraInfo = extraInfoStream.str();
+ error(line, "", "[", extraInfo.c_str());
+ recover();
+ index = 0;
+ }
+
+ if (tempConstantNode) {
+ size_t arrayElementSize = arrayElementType.getObjectSize();
+ ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer();
+ typedNode = intermediate.addConstantUnion(&unionArray[arrayElementSize * index], tempConstantNode->getType(), line);
+ } else {
+ error(line, "Cannot offset into the array", "Error");
+ recover();
+
+ return 0;
+ }
+
+ return typedNode;
+}
+
+
+//
+// This function returns the value of a particular field inside a constant structure from the symbol table.
+// If there is an embedded/nested struct, it appropriately calls addConstStructNested or addConstStructFromAggr
+// function and returns the parse-tree with the values of the embedded/nested struct.
+//
+TIntermTyped* TParseContext::addConstStruct(TString& identifier, TIntermTyped* node, const TSourceLoc& line)
+{
+ const TFieldList& fields = node->getType().getStruct()->fields();
+
+ size_t instanceSize = 0;
+ for (size_t index = 0; index < fields.size(); ++index) {
+ if (fields[index]->name() == identifier) {
+ break;
+ } else {
+ instanceSize += fields[index]->type()->getObjectSize();
+ }
+ }
+
+ TIntermTyped* typedNode = 0;
+ TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
+ if (tempConstantNode) {
+ ConstantUnion* constArray = tempConstantNode->getUnionArrayPointer();
+
+ typedNode = intermediate.addConstantUnion(constArray+instanceSize, tempConstantNode->getType(), line); // type will be changed in the calling function
+ } else {
+ error(line, "Cannot offset into the structure", "Error");
+ recover();
+
+ return 0;
+ }
+
+ return typedNode;
+}
+
+bool TParseContext::enterStructDeclaration(const TSourceLoc& line, const TString& identifier)
+{
+ ++structNestingLevel;
+
+ // Embedded structure definitions are not supported per GLSL ES spec.
+ // They aren't allowed in GLSL either, but we need to detect this here
+ // so we don't rely on the GLSL compiler to catch it.
+ if (structNestingLevel > 1) {
+ error(line, "", "Embedded struct definitions are not allowed");
+ return true;
+ }
+
+ return false;
+}
+
+void TParseContext::exitStructDeclaration()
+{
+ --structNestingLevel;
+}
+
+namespace {
+
+const int kWebGLMaxStructNesting = 4;
+
+} // namespace
+
+bool TParseContext::structNestingErrorCheck(const TSourceLoc& line, const TField& field)
+{
+ if (!isWebGLBasedSpec(shaderSpec)) {
+ return false;
+ }
+
+ if (field.type()->getBasicType() != EbtStruct) {
+ return false;
+ }
+
+ // We're already inside a structure definition at this point, so add
+ // one to the field's struct nesting.
+ if (1 + field.type()->getDeepestStructNesting() > kWebGLMaxStructNesting) {
+ std::stringstream reasonStream;
+ reasonStream << "Reference of struct type "
+ << field.type()->getStruct()->name().c_str()
+ << " exceeds maximum allowed nesting level of "
+ << kWebGLMaxStructNesting;
+ std::string reason = reasonStream.str();
+ error(line, reason.c_str(), field.name().c_str(), "");
+ return true;
+ }
+
+ return false;
+}
+
+//
+// Parse an array index expression
+//
+TIntermTyped* TParseContext::addIndexExpression(TIntermTyped *baseExpression, const TSourceLoc& location, TIntermTyped *indexExpression)
+{
+ TIntermTyped *indexedExpression = NULL;
+
+ if (!baseExpression->isArray() && !baseExpression->isMatrix() && !baseExpression->isVector())
+ {
+ if (baseExpression->getAsSymbolNode())
+ {
+ error(location, " left of '[' is not of type array, matrix, or vector ", baseExpression->getAsSymbolNode()->getSymbol().c_str());
+ }
+ else
+ {
+ error(location, " left of '[' is not of type array, matrix, or vector ", "expression");
+ }
+ recover();
+ }
+
+ if (indexExpression->getQualifier() == EvqConst)
+ {
+ int index = indexExpression->getAsConstantUnion()->getIConst(0);
+ if (index < 0)
+ {
+ std::stringstream infoStream;
+ infoStream << index;
+ std::string info = infoStream.str();
+ error(location, "negative index", info.c_str());
+ recover();
+ index = 0;
+ }
+ if (baseExpression->getType().getQualifier() == EvqConst)
+ {
+ if (baseExpression->isArray())
+ {
+ // constant folding for arrays
+ indexedExpression = addConstArrayNode(index, baseExpression, location);
+ }
+ else if (baseExpression->isVector())
+ {
+ // constant folding for vectors
+ TVectorFields fields;
+ fields.num = 1;
+ fields.offsets[0] = index; // need to do it this way because v.xy sends fields integer array
+ indexedExpression = addConstVectorNode(fields, baseExpression, location);
+ }
+ else if (baseExpression->isMatrix())
+ {
+ // constant folding for matrices
+ indexedExpression = addConstMatrixNode(index, baseExpression, location);
+ }
+ }
+ else
+ {
+ if (baseExpression->isArray())
+ {
+ if (index >= baseExpression->getType().getArraySize())
+ {
+ std::stringstream extraInfoStream;
+ extraInfoStream << "array index out of range '" << index << "'";
+ std::string extraInfo = extraInfoStream.str();
+ error(location, "", "[", extraInfo.c_str());
+ recover();
+ index = baseExpression->getType().getArraySize() - 1;
+ }
+ else if (baseExpression->getQualifier() == EvqFragData && index > 0 && !isExtensionEnabled("GL_EXT_draw_buffers"))
+ {
+ error(location, "", "[", "array indexes for gl_FragData must be zero when GL_EXT_draw_buffers is disabled");
+ recover();
+ index = 0;
+ }
+ }
+ else if ((baseExpression->isVector() || baseExpression->isMatrix()) && baseExpression->getType().getNominalSize() <= index)
+ {
+ std::stringstream extraInfoStream;
+ extraInfoStream << "field selection out of range '" << index << "'";
+ std::string extraInfo = extraInfoStream.str();
+ error(location, "", "[", extraInfo.c_str());
+ recover();
+ index = baseExpression->getType().getNominalSize() - 1;
+ }
+
+ indexExpression->getAsConstantUnion()->getUnionArrayPointer()->setIConst(index);
+ indexedExpression = intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location);
+ }
+ }
+ else
+ {
+ indexedExpression = intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location);
+ }
+
+ if (indexedExpression == 0)
+ {
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setFConst(0.0f);
+ indexedExpression = intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst), location);
+ }
+ else if (baseExpression->isArray())
+ {
+ const TType &baseType = baseExpression->getType();
+ if (baseType.getStruct())
+ {
+ TType copyOfType(baseType.getStruct());
+ indexedExpression->setType(copyOfType);
+ }
+ else
+ {
+ indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), EvqTemporary, baseExpression->getNominalSize(), baseExpression->isMatrix()));
+ }
+
+ if (baseExpression->getType().getQualifier() == EvqConst)
+ {
+ indexedExpression->getTypePointer()->setQualifier(EvqConst);
+ }
+ }
+ else if (baseExpression->isMatrix())
+ {
+ TQualifier qualifier = baseExpression->getType().getQualifier() == EvqConst ? EvqConst : EvqTemporary;
+ indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), qualifier, baseExpression->getNominalSize()));
+ }
+ else if (baseExpression->isVector())
+ {
+ TQualifier qualifier = baseExpression->getType().getQualifier() == EvqConst ? EvqConst : EvqTemporary;
+ indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), qualifier));
+ }
+ else
+ {
+ indexedExpression->setType(baseExpression->getType());
+ }
+
+ return indexedExpression;
+}
+
+//
+// Parse an array of strings using yyparse.
+//
+// Returns 0 for success.
+//
+int PaParseStrings(size_t count, const char* const string[], const int length[],
+ TParseContext* context) {
+ if ((count == 0) || (string == NULL))
+ return 1;
+
+ if (glslang_initialize(context))
+ return 1;
+
+ int error = glslang_scan(count, string, length, context);
+ if (!error)
+ error = glslang_parse(context);
+
+ glslang_finalize(context);
+
+ return (error == 0) && (context->numErrors() == 0) ? 0 : 1;
+}
+
+
+
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ParseContext.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorParseContexth"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ParseContext.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ParseContext.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ParseContext.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,134 @@
</span><ins>+//
+// Copyright (c) 2002-2013 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 _PARSER_HELPER_INCLUDED_
+#define _PARSER_HELPER_INCLUDED_
+
+#include "compiler/translator/Diagnostics.h"
+#include "compiler/translator/DirectiveHandler.h"
+#include "compiler/translator/localintermediate.h"
+#include "compiler/preprocessor/Preprocessor.h"
+#include "compiler/translator/ShHandle.h"
+#include "compiler/translator/SymbolTable.h"
+
+struct TMatrixFields {
+ bool wholeRow;
+ bool wholeCol;
+ int row;
+ int col;
+};
+
+//
+// The following are extra variables needed during parsing, grouped together so
+// they can be passed to the parser without needing a global.
+//
+struct TParseContext {
+ TParseContext(TSymbolTable& symt, TExtensionBehavior& ext, TIntermediate& interm, ShShaderType type, ShShaderSpec spec, int options, bool checksPrecErrors, const char* sourcePath, TInfoSink& is) :
+ intermediate(interm),
+ symbolTable(symt),
+ shaderType(type),
+ shaderSpec(spec),
+ compileOptions(options),
+ sourcePath(sourcePath),
+ treeRoot(0),
+ loopNestingLevel(0),
+ structNestingLevel(0),
+ currentFunctionType(NULL),
+ functionReturnsValue(false),
+ checksPrecisionErrors(checksPrecErrors),
+ diagnostics(is),
+ directiveHandler(ext, diagnostics),
+ preprocessor(&diagnostics, &directiveHandler),
+ scanner(NULL) { }
+ TIntermediate& intermediate; // to hold and build a parse tree
+ TSymbolTable& symbolTable; // symbol table that goes with the language currently being parsed
+ ShShaderType shaderType; // vertex or fragment language (future: pack or unpack)
+ ShShaderSpec shaderSpec; // The language specification compiler conforms to - GLES2 or WebGL.
+ int compileOptions;
+ const char* sourcePath; // Path of source file or NULL.
+ TIntermNode* treeRoot; // root of parse tree being created
+ int loopNestingLevel; // 0 if outside all loops
+ int structNestingLevel; // incremented while parsing a struct declaration
+ const TType* currentFunctionType; // the return type of the function that's currently being parsed
+ bool functionReturnsValue; // true if a non-void function has a return
+ bool checksPrecisionErrors; // true if an error will be generated when a variable is declared without precision, explicit or implicit.
+ bool fragmentPrecisionHigh; // true if highp precision is supported in the fragment language.
+ TString HashErrMsg;
+ TDiagnostics diagnostics;
+ TDirectiveHandler directiveHandler;
+ pp::Preprocessor preprocessor;
+ void* scanner;
+
+ int numErrors() const { return diagnostics.numErrors(); }
+ TInfoSink& infoSink() { return diagnostics.infoSink(); }
+ void error(const TSourceLoc& loc, const char *reason, const char* token,
+ const char* extraInfo="");
+ void warning(const TSourceLoc& loc, const char* reason, const char* token,
+ const char* extraInfo="");
+ void trace(const char* str);
+ void recover();
+
+ bool parseVectorFields(const TString&, int vecSize, TVectorFields&, const TSourceLoc& line);
+ bool parseMatrixFields(const TString&, int matSize, TMatrixFields&, const TSourceLoc& line);
+
+ bool reservedErrorCheck(const TSourceLoc& line, const TString& identifier);
+ void assignError(const TSourceLoc& line, const char* op, TString left, TString right);
+ void unaryOpError(const TSourceLoc& line, const char* op, TString operand);
+ void binaryOpError(const TSourceLoc& line, const char* op, TString left, TString right);
+ bool precisionErrorCheck(const TSourceLoc& line, TPrecision precision, TBasicType type);
+ bool lValueErrorCheck(const TSourceLoc& line, const char* op, TIntermTyped*);
+ bool constErrorCheck(TIntermTyped* node);
+ bool integerErrorCheck(TIntermTyped* node, const char* token);
+ bool globalErrorCheck(const TSourceLoc& line, bool global, const char* token);
+ bool constructorErrorCheck(const TSourceLoc& line, TIntermNode*, TFunction&, TOperator, TType*);
+ bool arraySizeErrorCheck(const TSourceLoc& line, TIntermTyped* expr, int& size);
+ bool arrayQualifierErrorCheck(const TSourceLoc& line, TPublicType type);
+ bool arrayTypeErrorCheck(const TSourceLoc& line, TPublicType type);
+ bool arrayErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType type, TVariable*& variable);
+ bool voidErrorCheck(const TSourceLoc&, const TString&, const TPublicType&);
+ bool boolErrorCheck(const TSourceLoc&, const TIntermTyped*);
+ bool boolErrorCheck(const TSourceLoc&, const TPublicType&);
+ bool samplerErrorCheck(const TSourceLoc& line, const TPublicType& pType, const char* reason);
+ bool structQualifierErrorCheck(const TSourceLoc& line, const TPublicType& pType);
+ bool parameterSamplerErrorCheck(const TSourceLoc& line, TQualifier qualifier, const TType& type);
+ bool nonInitConstErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType& type, bool array);
+ bool nonInitErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType& type, TVariable*& variable);
+ bool paramErrorCheck(const TSourceLoc& line, TQualifier qualifier, TQualifier paramQualifier, TType* type);
+ bool extensionErrorCheck(const TSourceLoc& line, const TString&);
+
+ const TPragma& pragma() const { return directiveHandler.pragma(); }
+ const TExtensionBehavior& extensionBehavior() const { return directiveHandler.extensionBehavior(); }
+ bool supportsExtension(const char* extension);
+ bool isExtensionEnabled(const char* extension) const;
+
+ bool containsSampler(TType& type);
+ bool areAllChildConst(TIntermAggregate* aggrNode);
+ const TFunction* findFunction(const TSourceLoc& line, TFunction* pfnCall, bool *builtIn = 0);
+ bool executeInitializer(const TSourceLoc& line, TString& identifier, TPublicType& pType,
+ TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable = 0);
+
+ TIntermTyped* addConstructor(TIntermNode*, const TType*, TOperator, TFunction*, const TSourceLoc&);
+ TIntermTyped* foldConstConstructor(TIntermAggregate* aggrNode, const TType& type);
+ TIntermTyped* constructStruct(TIntermNode*, TType*, int, const TSourceLoc&, bool subset);
+ TIntermTyped* constructBuiltIn(const TType*, TOperator, TIntermNode*, const TSourceLoc&, bool subset);
+ TIntermTyped* addConstVectorNode(TVectorFields&, TIntermTyped*, const TSourceLoc&);
+ TIntermTyped* addConstMatrixNode(int , TIntermTyped*, const TSourceLoc&);
+ TIntermTyped* addConstArrayNode(int index, TIntermTyped* node, const TSourceLoc& line);
+ TIntermTyped* addConstStruct(TString& , TIntermTyped*, const TSourceLoc&);
+ TIntermTyped* addIndexExpression(TIntermTyped *baseExpression, const TSourceLoc& location, TIntermTyped *indexExpression);
+
+ // Performs an error check for embedded struct declarations.
+ // Returns true if an error was raised due to the declaration of
+ // this struct.
+ bool enterStructDeclaration(const TSourceLoc& line, const TString& identifier);
+ void exitStructDeclaration();
+
+ bool structNestingErrorCheck(const TSourceLoc& line, const TField& field);
+};
+
+int PaParseStrings(size_t count, const char* const string[], const int length[],
+ TParseContext* context);
+
+#endif // _PARSER_HELPER_INCLUDED_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ParseContext.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorPoolAlloccpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/PoolAlloc.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/PoolAlloc.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/PoolAlloc.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,294 @@
</span><ins>+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/PoolAlloc.h"
+
+#ifndef _MSC_VER
+#include <stdint.h>
+#endif
+#include <stdio.h>
+
+#include "common/angleutils.h"
+#include "compiler/translator/InitializeGlobals.h"
+#include "compiler/translator/osinclude.h"
+
+OS_TLSIndex PoolIndex = OS_INVALID_TLS_INDEX;
+
+bool InitializePoolIndex()
+{
+ assert(PoolIndex == OS_INVALID_TLS_INDEX);
+
+ PoolIndex = OS_AllocTLSIndex();
+ return PoolIndex != OS_INVALID_TLS_INDEX;
+}
+
+void FreePoolIndex()
+{
+ assert(PoolIndex != OS_INVALID_TLS_INDEX);
+
+ OS_FreeTLSIndex(PoolIndex);
+ PoolIndex = OS_INVALID_TLS_INDEX;
+}
+
+TPoolAllocator* GetGlobalPoolAllocator()
+{
+ assert(PoolIndex != OS_INVALID_TLS_INDEX);
+ return static_cast<TPoolAllocator*>(OS_GetTLSValue(PoolIndex));
+}
+
+void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator)
+{
+ assert(PoolIndex != OS_INVALID_TLS_INDEX);
+ OS_SetTLSValue(PoolIndex, poolAllocator);
+}
+
+//
+// Implement the functionality of the TPoolAllocator class, which
+// is documented in PoolAlloc.h.
+//
+TPoolAllocator::TPoolAllocator(int growthIncrement, int allocationAlignment) :
+ pageSize(growthIncrement),
+ alignment(allocationAlignment),
+ freeList(0),
+ inUseList(0),
+ numCalls(0),
+ totalBytes(0)
+{
+ //
+ // Don't allow page sizes we know are smaller than all common
+ // OS page sizes.
+ //
+ if (pageSize < 4*1024)
+ pageSize = 4*1024;
+
+ //
+ // A large currentPageOffset indicates a new page needs to
+ // be obtained to allocate memory.
+ //
+ currentPageOffset = pageSize;
+
+ //
+ // Adjust alignment to be at least pointer aligned and
+ // power of 2.
+ //
+ size_t minAlign = sizeof(void*);
+ alignment &= ~(minAlign - 1);
+ if (alignment < minAlign)
+ alignment = minAlign;
+ size_t a = 1;
+ while (a < alignment)
+ a <<= 1;
+ alignment = a;
+ alignmentMask = a - 1;
+
+ //
+ // Align header skip
+ //
+ headerSkip = minAlign;
+ if (headerSkip < sizeof(tHeader)) {
+ headerSkip = (sizeof(tHeader) + alignmentMask) & ~alignmentMask;
+ }
+}
+
+TPoolAllocator::~TPoolAllocator()
+{
+ while (inUseList) {
+ tHeader* next = inUseList->nextPage;
+ inUseList->~tHeader();
+ delete [] reinterpret_cast<char*>(inUseList);
+ inUseList = next;
+ }
+
+ // We should not check the guard blocks
+ // here, because we did it already when the block was
+ // placed into the free list.
+ //
+ while (freeList) {
+ tHeader* next = freeList->nextPage;
+ delete [] reinterpret_cast<char*>(freeList);
+ freeList = next;
+ }
+}
+
+// Support MSVC++ 6.0
+const unsigned char TAllocation::guardBlockBeginVal = 0xfb;
+const unsigned char TAllocation::guardBlockEndVal = 0xfe;
+const unsigned char TAllocation::userDataFill = 0xcd;
+
+#ifdef GUARD_BLOCKS
+ const size_t TAllocation::guardBlockSize = 16;
+#else
+ const size_t TAllocation::guardBlockSize = 0;
+#endif
+
+//
+// Check a single guard block for damage
+//
+void TAllocation::checkGuardBlock(unsigned char* blockMem, unsigned char val, const char* locText) const
+{
+#ifdef GUARD_BLOCKS
+ for (size_t x = 0; x < guardBlockSize; x++) {
+ if (blockMem[x] != val) {
+ char assertMsg[80];
+
+ // We don't print the assert message. It's here just to be helpful.
+#if defined(_MSC_VER)
+ snprintf(assertMsg, sizeof(assertMsg), "PoolAlloc: Damage %s %Iu byte allocation at 0x%p\n",
+ locText, size, data());
+#else
+ snprintf(assertMsg, sizeof(assertMsg), "PoolAlloc: Damage %s %zu byte allocation at 0x%p\n",
+ locText, size, data());
+#endif
+ assert(0 && "PoolAlloc: Damage in guard block");
+ }
+ }
+#endif
+}
+
+
+void TPoolAllocator::push()
+{
+ tAllocState state = { currentPageOffset, inUseList };
+
+ stack.push_back(state);
+
+ //
+ // Indicate there is no current page to allocate from.
+ //
+ currentPageOffset = pageSize;
+}
+
+//
+// Do a mass-deallocation of all the individual allocations
+// that have occurred since the last push(), or since the
+// last pop(), or since the object's creation.
+//
+// The deallocated pages are saved for future allocations.
+//
+void TPoolAllocator::pop()
+{
+ if (stack.size() < 1)
+ return;
+
+ tHeader* page = stack.back().page;
+ currentPageOffset = stack.back().offset;
+
+ while (inUseList != page) {
+ // invoke destructor to free allocation list
+ inUseList->~tHeader();
+
+ tHeader* nextInUse = inUseList->nextPage;
+ if (inUseList->pageCount > 1)
+ delete [] reinterpret_cast<char*>(inUseList);
+ else {
+ inUseList->nextPage = freeList;
+ freeList = inUseList;
+ }
+ inUseList = nextInUse;
+ }
+
+ stack.pop_back();
+}
+
+//
+// Do a mass-deallocation of all the individual allocations
+// that have occurred.
+//
+void TPoolAllocator::popAll()
+{
+ while (stack.size() > 0)
+ pop();
+}
+
+void* TPoolAllocator::allocate(size_t numBytes)
+{
+ //
+ // Just keep some interesting statistics.
+ //
+ ++numCalls;
+ totalBytes += numBytes;
+
+ // If we are using guard blocks, all allocations are bracketed by
+ // them: [guardblock][allocation][guardblock]. numBytes is how
+ // much memory the caller asked for. allocationSize is the total
+ // size including guard blocks. In release build,
+ // guardBlockSize=0 and this all gets optimized away.
+ size_t allocationSize = TAllocation::allocationSize(numBytes);
+ // Detect integer overflow.
+ if (allocationSize < numBytes)
+ return 0;
+
+ //
+ // Do the allocation, most likely case first, for efficiency.
+ // This step could be moved to be inline sometime.
+ //
+ if (allocationSize <= pageSize - currentPageOffset) {
+ //
+ // Safe to allocate from currentPageOffset.
+ //
+ unsigned char* memory = reinterpret_cast<unsigned char *>(inUseList) + currentPageOffset;
+ currentPageOffset += allocationSize;
+ currentPageOffset = (currentPageOffset + alignmentMask) & ~alignmentMask;
+
+ return initializeAllocation(inUseList, memory, numBytes);
+ }
+
+ if (allocationSize > pageSize - headerSkip) {
+ //
+ // Do a multi-page allocation. Don't mix these with the others.
+ // The OS is efficient and allocating and free-ing multiple pages.
+ //
+ size_t numBytesToAlloc = allocationSize + headerSkip;
+ // Detect integer overflow.
+ if (numBytesToAlloc < allocationSize)
+ return 0;
+
+ tHeader* memory = reinterpret_cast<tHeader*>(::new char[numBytesToAlloc]);
+ if (memory == 0)
+ return 0;
+
+ // Use placement-new to initialize header
+ new(memory) tHeader(inUseList, (numBytesToAlloc + pageSize - 1) / pageSize);
+ inUseList = memory;
+
+ currentPageOffset = pageSize; // make next allocation come from a new page
+
+ // No guard blocks for multi-page allocations (yet)
+ return reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(memory) + headerSkip);
+ }
+
+ //
+ // Need a simple page to allocate from.
+ //
+ tHeader* memory;
+ if (freeList) {
+ memory = freeList;
+ freeList = freeList->nextPage;
+ } else {
+ memory = reinterpret_cast<tHeader*>(::new char[pageSize]);
+ if (memory == 0)
+ return 0;
+ }
+
+ // Use placement-new to initialize header
+ new(memory) tHeader(inUseList, 1);
+ inUseList = memory;
+
+ unsigned char* ret = reinterpret_cast<unsigned char *>(inUseList) + headerSkip;
+ currentPageOffset = (headerSkip + allocationSize + alignmentMask) & ~alignmentMask;
+
+ return initializeAllocation(inUseList, ret, numBytes);
+}
+
+
+//
+// Check all allocations in a list for damage by calling check on each.
+//
+void TAllocation::checkAllocList() const
+{
+ for (const TAllocation* alloc = this; alloc != 0; alloc = alloc->prevAlloc)
+ alloc->check();
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/PoolAlloc.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorPoolAlloch"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/PoolAlloc.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/PoolAlloc.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/PoolAlloc.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,300 @@
</span><ins>+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef _POOLALLOC_INCLUDED_
+#define _POOLALLOC_INCLUDED_
+
+#ifdef _DEBUG
+#define GUARD_BLOCKS // define to enable guard block sanity checking
+#endif
+
+//
+// This header defines an allocator that can be used to efficiently
+// allocate a large number of small requests for heap memory, with the
+// intention that they are not individually deallocated, but rather
+// collectively deallocated at one time.
+//
+// This simultaneously
+//
+// * Makes each individual allocation much more efficient; the
+// typical allocation is trivial.
+// * Completely avoids the cost of doing individual deallocation.
+// * Saves the trouble of tracking down and plugging a large class of leaks.
+//
+// Individual classes can use this allocator by supplying their own
+// new and delete methods.
+//
+// STL containers can use this allocator by using the pool_allocator
+// class as the allocator (second) template argument.
+//
+
+#include <stddef.h>
+#include <string.h>
+#include <vector>
+
+// If we are using guard blocks, we must track each indivual
+// allocation. If we aren't using guard blocks, these
+// never get instantiated, so won't have any impact.
+//
+
+class TAllocation {
+public:
+ TAllocation(size_t size, unsigned char* mem, TAllocation* prev = 0) :
+ size(size), mem(mem), prevAlloc(prev) {
+ // Allocations are bracketed:
+ // [allocationHeader][initialGuardBlock][userData][finalGuardBlock]
+ // This would be cleaner with if (guardBlockSize)..., but that
+ // makes the compiler print warnings about 0 length memsets,
+ // even with the if() protecting them.
+#ifdef GUARD_BLOCKS
+ memset(preGuard(), guardBlockBeginVal, guardBlockSize);
+ memset(data(), userDataFill, size);
+ memset(postGuard(), guardBlockEndVal, guardBlockSize);
+#endif
+ }
+
+ void check() const {
+ checkGuardBlock(preGuard(), guardBlockBeginVal, "before");
+ checkGuardBlock(postGuard(), guardBlockEndVal, "after");
+ }
+
+ void checkAllocList() const;
+
+ // Return total size needed to accomodate user buffer of 'size',
+ // plus our tracking data.
+ inline static size_t allocationSize(size_t size) {
+ return size + 2 * guardBlockSize + headerSize();
+ }
+
+ // Offset from surrounding buffer to get to user data buffer.
+ inline static unsigned char* offsetAllocation(unsigned char* m) {
+ return m + guardBlockSize + headerSize();
+ }
+
+private:
+ void checkGuardBlock(unsigned char* blockMem, unsigned char val, const char* locText) const;
+
+ // Find offsets to pre and post guard blocks, and user data buffer
+ unsigned char* preGuard() const { return mem + headerSize(); }
+ unsigned char* data() const { return preGuard() + guardBlockSize; }
+ unsigned char* postGuard() const { return data() + size; }
+
+ size_t size; // size of the user data area
+ unsigned char* mem; // beginning of our allocation (pts to header)
+ TAllocation* prevAlloc; // prior allocation in the chain
+
+ // Support MSVC++ 6.0
+ const static unsigned char guardBlockBeginVal;
+ const static unsigned char guardBlockEndVal;
+ const static unsigned char userDataFill;
+
+ const static size_t guardBlockSize;
+#ifdef GUARD_BLOCKS
+ inline static size_t headerSize() { return sizeof(TAllocation); }
+#else
+ inline static size_t headerSize() { return 0; }
+#endif
+};
+
+//
+// There are several stacks. One is to track the pushing and popping
+// of the user, and not yet implemented. The others are simply a
+// repositories of free pages or used pages.
+//
+// Page stacks are linked together with a simple header at the beginning
+// of each allocation obtained from the underlying OS. Multi-page allocations
+// are returned to the OS. Individual page allocations are kept for future
+// re-use.
+//
+// The "page size" used is not, nor must it match, the underlying OS
+// page size. But, having it be about that size or equal to a set of
+// pages is likely most optimal.
+//
+class TPoolAllocator {
+public:
+ TPoolAllocator(int growthIncrement = 8*1024, int allocationAlignment = 16);
+
+ //
+ // Don't call the destructor just to free up the memory, call pop()
+ //
+ ~TPoolAllocator();
+
+ //
+ // Call push() to establish a new place to pop memory too. Does not
+ // have to be called to get things started.
+ //
+ void push();
+
+ //
+ // Call pop() to free all memory allocated since the last call to push(),
+ // or if no last call to push, frees all memory since first allocation.
+ //
+ void pop();
+
+ //
+ // Call popAll() to free all memory allocated.
+ //
+ void popAll();
+
+ //
+ // Call allocate() to actually acquire memory. Returns 0 if no memory
+ // available, otherwise a properly aligned pointer to 'numBytes' of memory.
+ //
+ void* allocate(size_t numBytes);
+
+ //
+ // There is no deallocate. The point of this class is that
+ // deallocation can be skipped by the user of it, as the model
+ // of use is to simultaneously deallocate everything at once
+ // by calling pop(), and to not have to solve memory leak problems.
+ //
+
+protected:
+ friend struct tHeader;
+
+ struct tHeader {
+ tHeader(tHeader* nextPage, size_t pageCount) :
+ nextPage(nextPage),
+ pageCount(pageCount)
+#ifdef GUARD_BLOCKS
+ , lastAllocation(0)
+#endif
+ { }
+
+ ~tHeader() {
+#ifdef GUARD_BLOCKS
+ if (lastAllocation)
+ lastAllocation->checkAllocList();
+#endif
+ }
+
+ tHeader* nextPage;
+ size_t pageCount;
+#ifdef GUARD_BLOCKS
+ TAllocation* lastAllocation;
+#endif
+ };
+
+ struct tAllocState {
+ size_t offset;
+ tHeader* page;
+ };
+ typedef std::vector<tAllocState> tAllocStack;
+
+ // Track allocations if and only if we're using guard blocks
+ void* initializeAllocation(tHeader* block, unsigned char* memory, size_t numBytes) {
+#ifdef GUARD_BLOCKS
+ new(memory) TAllocation(numBytes, memory, block->lastAllocation);
+ block->lastAllocation = reinterpret_cast<TAllocation*>(memory);
+#endif
+ // This is optimized entirely away if GUARD_BLOCKS is not defined.
+ return TAllocation::offsetAllocation(memory);
+ }
+
+ size_t pageSize; // granularity of allocation from the OS
+ size_t alignment; // all returned allocations will be aligned at
+ // this granularity, which will be a power of 2
+ size_t alignmentMask;
+ size_t headerSkip; // amount of memory to skip to make room for the
+ // header (basically, size of header, rounded
+ // up to make it aligned
+ size_t currentPageOffset; // next offset in top of inUseList to allocate from
+ tHeader* freeList; // list of popped memory
+ tHeader* inUseList; // list of all memory currently being used
+ tAllocStack stack; // stack of where to allocate from, to partition pool
+
+ int numCalls; // just an interesting statistic
+ size_t totalBytes; // just an interesting statistic
+private:
+ TPoolAllocator& operator=(const TPoolAllocator&); // dont allow assignment operator
+ TPoolAllocator(const TPoolAllocator&); // dont allow default copy constructor
+};
+
+
+//
+// There could potentially be many pools with pops happening at
+// different times. But a simple use is to have a global pop
+// with everyone using the same global allocator.
+//
+extern TPoolAllocator* GetGlobalPoolAllocator();
+extern void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator);
+
+//
+// This STL compatible allocator is intended to be used as the allocator
+// parameter to templatized STL containers, like vector and map.
+//
+// It will use the pools for allocation, and not
+// do any deallocation, but will still do destruction.
+//
+template<class T>
+class pool_allocator {
+public:
+ typedef size_t size_type;
+ typedef ptrdiff_t difference_type;
+ typedef T* pointer;
+ typedef const T* const_pointer;
+ typedef T& reference;
+ typedef const T& const_reference;
+ typedef T value_type;
+
+ template<class Other>
+ struct rebind {
+ typedef pool_allocator<Other> other;
+ };
+ pointer address(reference x) const { return &x; }
+ const_pointer address(const_reference x) const { return &x; }
+
+ pool_allocator() : allocator(GetGlobalPoolAllocator()) { }
+ pool_allocator(TPoolAllocator& a) : allocator(&a) { }
+ pool_allocator(const pool_allocator<T>& p) : allocator(p.allocator) { }
+
+ template <class Other>
+ pool_allocator<T>& operator=(const pool_allocator<Other>& p) {
+ allocator = p.allocator;
+ return *this;
+ }
+
+ template<class Other>
+ pool_allocator(const pool_allocator<Other>& p) : allocator(&p.getAllocator()) { }
+
+#if defined(__SUNPRO_CC) && !defined(_RWSTD_ALLOCATOR)
+ // libCStd on some platforms have a different allocate/deallocate interface.
+ // Caller pre-bakes sizeof(T) into 'n' which is the number of bytes to be
+ // allocated, not the number of elements.
+ void* allocate(size_type n) {
+ return getAllocator().allocate(n);
+ }
+ void* allocate(size_type n, const void*) {
+ return getAllocator().allocate(n);
+ }
+ void deallocate(void*, size_type) {}
+#else
+ pointer allocate(size_type n) {
+ return reinterpret_cast<pointer>(getAllocator().allocate(n * sizeof(T)));
+ }
+ pointer allocate(size_type n, const void*) {
+ return reinterpret_cast<pointer>(getAllocator().allocate(n * sizeof(T)));
+ }
+ void deallocate(pointer, size_type) {}
+#endif // _RWSTD_ALLOCATOR
+
+ void construct(pointer p, const T& val) { new ((void *)p) T(val); }
+ void destroy(pointer p) { p->T::~T(); }
+
+ bool operator==(const pool_allocator& rhs) const { return &getAllocator() == &rhs.getAllocator(); }
+ bool operator!=(const pool_allocator& rhs) const { return &getAllocator() != &rhs.getAllocator(); }
+
+ size_type max_size() const { return static_cast<size_type>(-1) / sizeof(T); }
+ size_type max_size(int size) const { return static_cast<size_type>(-1) / size; }
+
+ void setAllocator(TPoolAllocator* a) { allocator = a; }
+ TPoolAllocator& getAllocator() const { return *allocator; }
+
+protected:
+ TPoolAllocator* allocator;
+};
+
+#endif // _POOLALLOC_INCLUDED_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/PoolAlloc.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorPragmah"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Pragma.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Pragma.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Pragma.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,19 @@
</span><ins>+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_PRAGMA_H_
+#define COMPILER_PRAGMA_H_
+
+struct TPragma {
+ // 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;
+};
+
+#endif // COMPILER_PRAGMA_H_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Pragma.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorQualifierAlivecpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/QualifierAlive.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/QualifierAlive.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/QualifierAlive.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,58 @@
</span><ins>+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/intermediate.h"
+
+class TAliveTraverser : public TIntermTraverser {
+public:
+ TAliveTraverser(TQualifier q) : TIntermTraverser(true, false, false, true), found(false), qualifier(q)
+ {
+ }
+
+ bool wasFound() { return found; }
+
+protected:
+ bool found;
+ TQualifier qualifier;
+
+ void visitSymbol(TIntermSymbol*);
+ bool visitSelection(Visit, TIntermSelection*);
+};
+
+//
+// Report whether or not a variable of the given qualifier type
+// is guaranteed written. Not always possible to determine if
+// it is written conditionally.
+//
+// ?? It does not do this well yet, this is just a place holder
+// that simply determines if it was reference at all, anywhere.
+//
+bool QualifierWritten(TIntermNode* node, TQualifier qualifier)
+{
+ TAliveTraverser it(qualifier);
+
+ if (node)
+ node->traverse(&it);
+
+ return it.wasFound();
+}
+
+void TAliveTraverser::visitSymbol(TIntermSymbol* node)
+{
+ //
+ // If it's what we're looking for, record it.
+ //
+ if (node->getQualifier() == qualifier)
+ found = true;
+}
+
+bool TAliveTraverser::visitSelection(Visit preVisit, TIntermSelection* node)
+{
+ if (wasFound())
+ return false;
+
+ return true;
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/QualifierAlive.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorQualifierAliveh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/QualifierAlive.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/QualifierAlive.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/QualifierAlive.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,7 @@
</span><ins>+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+bool QualifierWritten(TIntermNode* root, TQualifier);
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/QualifierAlive.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorRemoveTreecpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/RemoveTree.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/RemoveTree.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/RemoveTree.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,77 @@
</span><ins>+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/intermediate.h"
+#include "compiler/translator/RemoveTree.h"
+
+//
+// Code to recursively delete the intermediate tree.
+//
+
+class RemoveTree : public TIntermTraverser
+{
+public:
+ RemoveTree() : TIntermTraverser(false, false, true)
+ {
+ }
+
+protected:
+ void visitSymbol(TIntermSymbol*);
+ void visitConstantUnion(TIntermConstantUnion*);
+ bool visitBinary(Visit visit, TIntermBinary*);
+ bool visitUnary(Visit visit, TIntermUnary*);
+ bool visitSelection(Visit visit, TIntermSelection*);
+ bool visitAggregate(Visit visit, TIntermAggregate*);
+};
+
+void RemoveTree::visitSymbol(TIntermSymbol* node)
+{
+ delete node;
+}
+
+bool RemoveTree::visitBinary(Visit visit, TIntermBinary* node)
+{
+ delete node;
+
+ return true;
+}
+
+bool RemoveTree::visitUnary(Visit visit, TIntermUnary* node)
+{
+ delete node;
+
+ return true;
+}
+
+bool RemoveTree::visitAggregate(Visit visit, TIntermAggregate* node)
+{
+ delete node;
+
+ return true;
+}
+
+bool RemoveTree::visitSelection(Visit visit, TIntermSelection* node)
+{
+ delete node;
+
+ return true;
+}
+
+void RemoveTree::visitConstantUnion(TIntermConstantUnion* node)
+{
+ delete node;
+}
+
+//
+// Entry point.
+//
+void RemoveAllTreeNodes(TIntermNode* root)
+{
+ RemoveTree it;
+
+ root->traverse(&it);
+}
+
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/RemoveTree.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorRemoveTreeh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/RemoveTree.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/RemoveTree.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/RemoveTree.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,7 @@
</span><ins>+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+void RemoveAllTreeNodes(TIntermNode*);
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/RemoveTree.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorRenameFunctionh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/RenameFunction.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/RenameFunction.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/RenameFunction.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,36 @@
</span><ins>+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_RENAME_FUNCTION
+#define COMPILER_RENAME_FUNCTION
+
+#include "compiler/translator/intermediate.h"
+
+//
+// Renames a function, including its declaration and any calls to it.
+//
+class RenameFunction : public TIntermTraverser
+{
+public:
+ RenameFunction(const TString& oldFunctionName, const TString& newFunctionName)
+ : TIntermTraverser(true, false, false)
+ , mOldFunctionName(oldFunctionName)
+ , mNewFunctionName(newFunctionName) {}
+
+ virtual bool visitAggregate(Visit visit, TIntermAggregate* node)
+ {
+ TOperator op = node->getOp();
+ if ((op == EOpFunction || op == EOpFunctionCall) && node->getName() == mOldFunctionName)
+ node->setName(mNewFunctionName);
+ return true;
+ }
+
+private:
+ const TString mOldFunctionName;
+ const TString mNewFunctionName;
+};
+
+#endif // COMPILER_RENAME_FUNCTION
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/RenameFunction.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorRewriteElseBlockscpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/RewriteElseBlocks.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/RewriteElseBlocks.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/RewriteElseBlocks.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,98 @@
</span><ins>+//
+// 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.
+//
+// RewriteElseBlocks.cpp: Implementation for tree transform to change
+// all if-else blocks to if-if blocks.
+//
+
+#include "compiler/translator/RewriteElseBlocks.h"
+#include "compiler/translator/NodeSearch.h"
+#include "compiler/translator/SymbolTable.h"
+
+namespace sh
+{
+
+TIntermSymbol *MakeNewTemporary(const TString &name, TBasicType type)
+{
+ TType variableType(type, EbpHigh, EvqInternal);
+ return new TIntermSymbol(-1, name, variableType);
+}
+
+TIntermBinary *MakeNewBinary(TOperator op, TIntermTyped *left, TIntermTyped *right, const TType &resultType)
+{
+ TIntermBinary *binary = new TIntermBinary(op);
+ binary->setLeft(left);
+ binary->setRight(right);
+ binary->setType(resultType);
+ return binary;
+}
+
+TIntermUnary *MakeNewUnary(TOperator op, TIntermTyped *operand)
+{
+ TIntermUnary *unary = new TIntermUnary(op, operand->getType());
+ unary->setOperand(operand);
+ return unary;
+}
+
+bool ElseBlockRewriter::visitAggregate(Visit visit, TIntermAggregate *node)
+{
+ switch (node->getOp())
+ {
+ case EOpSequence:
+ {
+ for (size_t statementIndex = 0; statementIndex != node->getSequence().size(); statementIndex++)
+ {
+ TIntermNode *statement = node->getSequence()[statementIndex];
+ TIntermSelection *selection = statement->getAsSelectionNode();
+ if (selection && selection->getFalseBlock() != NULL)
+ {
+ node->getSequence()[statementIndex] = rewriteSelection(selection);
+ delete selection;
+ }
+ }
+ }
+ break;
+
+ default: break;
+ }
+
+ return true;
+}
+
+TIntermNode *ElseBlockRewriter::rewriteSelection(TIntermSelection *selection)
+{
+ ASSERT(selection->getFalseBlock() != NULL);
+
+ TString temporaryName = "cond_" + str(mTemporaryIndex++);
+ TIntermTyped *typedCondition = selection->getCondition()->getAsTyped();
+ TType resultType(EbtBool, EbpUndefined);
+ TIntermSymbol *conditionSymbolA = MakeNewTemporary(temporaryName, EbtBool);
+ TIntermSymbol *conditionSymbolB = MakeNewTemporary(temporaryName, EbtBool);
+ TIntermSymbol *conditionSymbolC = MakeNewTemporary(temporaryName, EbtBool);
+ TIntermBinary *storeCondition = MakeNewBinary(EOpInitialize, conditionSymbolA,
+ typedCondition, resultType);
+ TIntermUnary *negatedCondition = MakeNewUnary(EOpLogicalNot, conditionSymbolB);
+ TIntermSelection *falseBlock = new TIntermSelection(negatedCondition,
+ selection->getFalseBlock(), NULL);
+ TIntermSelection *newIfElse = new TIntermSelection(conditionSymbolC,
+ selection->getTrueBlock(), falseBlock);
+
+ TIntermAggregate *declaration = new TIntermAggregate(EOpDeclaration);
+ declaration->getSequence().push_back(storeCondition);
+
+ TIntermAggregate *block = new TIntermAggregate(EOpSequence);
+ block->getSequence().push_back(declaration);
+ block->getSequence().push_back(newIfElse);
+
+ return block;
+}
+
+void RewriteElseBlocks(TIntermNode *node)
+{
+ ElseBlockRewriter rewriter;
+ node->traverse(&rewriter);
+}
+
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/RewriteElseBlocks.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorRewriteElseBlocksh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/RewriteElseBlocks.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/RewriteElseBlocks.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/RewriteElseBlocks.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,39 @@
</span><ins>+//
+// 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.
+//
+// RewriteElseBlocks.h: Prototype for tree transform to change
+// all if-else blocks to if-if blocks.
+//
+
+#ifndef COMPILER_REWRITE_ELSE_BLOCKS_H_
+#define COMPILER_REWRITE_ELSE_BLOCKS_H_
+
+#include "compiler/translator/intermediate.h"
+
+namespace sh
+{
+
+class ElseBlockRewriter : public TIntermTraverser
+{
+ public:
+ ElseBlockRewriter()
+ : TIntermTraverser(false, false, true, false)
+ , mTemporaryIndex(0)
+ {}
+
+ protected:
+ bool visitAggregate(Visit visit, TIntermAggregate *aggregate);
+
+ private:
+ int mTemporaryIndex;
+
+ TIntermNode *rewriteSelection(TIntermSelection *selection);
+};
+
+void RewriteElseBlocks(TIntermNode *node);
+
+}
+
+#endif // COMPILER_REWRITE_ELSE_BLOCKS_H_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/RewriteElseBlocks.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorSearchSymbolcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/SearchSymbol.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/SearchSymbol.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/SearchSymbol.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,38 @@
</span><ins>+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// SearchSymbol is an AST traverser to detect the use of a given symbol name
+//
+
+#include "compiler/translator/SearchSymbol.h"
+
+#include "compiler/translator/InfoSink.h"
+#include "compiler/translator/OutputHLSL.h"
+
+namespace sh
+{
+SearchSymbol::SearchSymbol(const TString &symbol) : mSymbol(symbol)
+{
+ match = false;
+}
+
+void SearchSymbol::traverse(TIntermNode *node)
+{
+ node->traverse(this);
+}
+
+void SearchSymbol::visitSymbol(TIntermSymbol *symbolNode)
+{
+ if (symbolNode->getSymbol() == mSymbol)
+ {
+ match = true;
+ }
+}
+
+bool SearchSymbol::foundMatch() const
+{
+ return match;
+}
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/SearchSymbol.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorSearchSymbolh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/SearchSymbol.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/SearchSymbol.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/SearchSymbol.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,33 @@
</span><ins>+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// SearchSymbol is an AST traverser to detect the use of a given symbol name
+//
+
+#ifndef COMPILER_SEARCHSYMBOL_H_
+#define COMPILER_SEARCHSYMBOL_H_
+
+#include "compiler/translator/intermediate.h"
+#include "compiler/translator/ParseContext.h"
+
+namespace sh
+{
+class SearchSymbol : public TIntermTraverser
+{
+ public:
+ SearchSymbol(const TString &symbol);
+
+ void traverse(TIntermNode *node);
+ void visitSymbol(TIntermSymbol *symbolNode);
+
+ bool foundMatch() const;
+
+ protected:
+ const TString &mSymbol;
+ bool match;
+};
+}
+
+#endif // COMPILER_SEARCHSYMBOL_H_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/SearchSymbol.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorShHandleh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ShHandle.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ShHandle.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ShHandle.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,180 @@
</span><ins>+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef _SHHANDLE_INCLUDED_
+#define _SHHANDLE_INCLUDED_
+
+//
+// Machine independent part of the compiler private objects
+// sent as ShHandle to the driver.
+//
+// This should not be included by driver code.
+//
+
+#include "GLSLANG/ShaderLang.h"
+
+#include "compiler/translator/BuiltInFunctionEmulator.h"
+#include "compiler/translator/ExtensionBehavior.h"
+#include "compiler/translator/HashNames.h"
+#include "compiler/translator/InfoSink.h"
+#include "compiler/translator/SymbolTable.h"
+#include "compiler/translator/VariableInfo.h"
+#include "third_party/compiler/ArrayBoundsClamper.h"
+
+class LongNameMap;
+class TCompiler;
+class TDependencyGraph;
+class TranslatorHLSL;
+
+//
+// Helper function to identify specs that are based on the WebGL spec,
+// like the CSS Shaders spec.
+//
+bool isWebGLBasedSpec(ShShaderSpec spec);
+
+//
+// The base class used to back handles returned to the driver.
+//
+class TShHandleBase {
+public:
+ TShHandleBase();
+ virtual ~TShHandleBase();
+ virtual TCompiler* getAsCompiler() { return 0; }
+ virtual TranslatorHLSL* getAsTranslatorHLSL() { return 0; }
+
+protected:
+ // Memory allocator. Allocates and tracks memory required by the compiler.
+ // Deallocates all memory when compiler is destructed.
+ TPoolAllocator allocator;
+};
+
+//
+// The base class for the machine dependent compiler to derive from
+// for managing object code from the compile.
+//
+class TCompiler : public TShHandleBase {
+public:
+ TCompiler(ShShaderType type, ShShaderSpec spec);
+ virtual ~TCompiler();
+ virtual TCompiler* getAsCompiler() { return this; }
+
+ bool Init(const ShBuiltInResources& resources);
+ bool compile(const char* const shaderStrings[],
+ size_t numStrings,
+ int compileOptions);
+
+ // Get results of the last compilation.
+ TInfoSink& getInfoSink() { return infoSink; }
+ const TVariableInfoList& getAttribs() const { return attribs; }
+ const TVariableInfoList& getUniforms() const { return uniforms; }
+ const TVariableInfoList& getVaryings() const { return varyings; }
+ int getMappedNameMaxLength() const;
+
+ ShHashFunction64 getHashFunction() const { return hashFunction; }
+ NameMap& getNameMap() { return nameMap; }
+ TSymbolTable& getSymbolTable() { return symbolTable; }
+
+protected:
+ ShShaderType getShaderType() const { return shaderType; }
+ ShShaderSpec getShaderSpec() const { return shaderSpec; }
+ // Initialize symbol-table with built-in symbols.
+ bool InitBuiltInSymbolTable(const ShBuiltInResources& resources);
+ // Clears the results from the previous compilation.
+ void clearResults();
+ // Return true if function recursion is detected or call depth exceeded.
+ bool detectCallDepth(TIntermNode* root, TInfoSink& infoSink, bool limitCallStackDepth);
+ // Rewrites a shader's intermediate tree according to the CSS Shaders spec.
+ void rewriteCSSShader(TIntermNode* root);
+ // Returns true if the given shader does not exceed the minimum
+ // functionality mandated in GLSL 1.0 spec Appendix A.
+ bool validateLimitations(TIntermNode* root);
+ // Collect info for all attribs, uniforms, varyings.
+ void collectVariables(TIntermNode* root);
+ // Map long variable names into shorter ones.
+ void mapLongVariableNames(TIntermNode* root);
+ // Translate to object code.
+ virtual void translate(TIntermNode* root) = 0;
+ // Returns true if, after applying the packing rules in the GLSL 1.017 spec
+ // Appendix A, section 7, the shader does not use too many uniforms.
+ bool enforcePackingRestrictions();
+ // Insert statements to initialize varyings without static use in the beginning
+ // of main(). It is to work around a Mac driver where such varyings in a vertex
+ // shader may be optimized out incorrectly at compile time, causing a link failure.
+ // This function should only be applied to vertex shaders.
+ void initializeVaryingsWithoutStaticUse(TIntermNode* root);
+ // Insert gl_Position = vec4(0,0,0,0) to the beginning of main().
+ // It is to work around a Linux driver bug where missing this causes compile failure
+ // while spec says it is allowed.
+ // This function should only be applied to vertex shaders.
+ void initializeGLPosition(TIntermNode* root);
+ // Returns true if the shader passes the restrictions that aim to prevent timing attacks.
+ bool enforceTimingRestrictions(TIntermNode* root, bool outputGraph);
+ // Returns true if the shader does not use samplers.
+ bool enforceVertexShaderTimingRestrictions(TIntermNode* root);
+ // Returns true if the shader does not use sampler dependent values to affect control
+ // flow or in operations whose time can depend on the input values.
+ bool enforceFragmentShaderTimingRestrictions(const TDependencyGraph& graph);
+ // Return true if the maximum expression complexity below the limit.
+ bool limitExpressionComplexity(TIntermNode* root);
+ // Get built-in extensions with default behavior.
+ const TExtensionBehavior& getExtensionBehavior() const;
+ // Get the resources set by InitBuiltInSymbolTable
+ const ShBuiltInResources& getResources() const;
+
+ const ArrayBoundsClamper& getArrayBoundsClamper() const;
+ ShArrayIndexClampingStrategy getArrayIndexClampingStrategy() const;
+ const BuiltInFunctionEmulator& getBuiltInFunctionEmulator() const;
+
+private:
+ ShShaderType shaderType;
+ ShShaderSpec shaderSpec;
+
+ int maxUniformVectors;
+ int maxVaryingVectors;
+ int maxExpressionComplexity;
+ int maxCallStackDepth;
+
+ ShBuiltInResources compileResources;
+
+ // Built-in symbol table for the given language, spec, and resources.
+ // It is preserved from compile-to-compile.
+ TSymbolTable symbolTable;
+ // Built-in extensions with default behavior.
+ TExtensionBehavior extensionBehavior;
+ bool fragmentPrecisionHigh;
+
+ ArrayBoundsClamper arrayBoundsClamper;
+ ShArrayIndexClampingStrategy clampingStrategy;
+ BuiltInFunctionEmulator builtInFunctionEmulator;
+
+ // Results of compilation.
+ TInfoSink infoSink; // Output sink.
+ TVariableInfoList attribs; // Active attributes in the compiled shader.
+ TVariableInfoList uniforms; // Active uniforms in the compiled shader.
+ TVariableInfoList varyings; // Varyings in the compiled shader.
+
+ // Cached copy of the ref-counted singleton.
+ LongNameMap* longNameMap;
+
+ // name hashing.
+ ShHashFunction64 hashFunction;
+ NameMap nameMap;
+};
+
+//
+// This is the interface between the machine independent code
+// and the machine dependent code.
+//
+// The machine dependent code should derive from the classes
+// above. Then Construct*() and Delete*() will create and
+// destroy the machine dependent objects, which contain the
+// above machine independent information.
+//
+TCompiler* ConstructCompiler(
+ ShShaderType type, ShShaderSpec spec, ShShaderOutput output);
+void DeleteCompiler(TCompiler*);
+
+#endif // _SHHANDLE_INCLUDED_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ShHandle.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorShaderLangcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ShaderLang.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ShaderLang.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ShaderLang.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,390 @@
</span><ins>+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+//
+// Implement the top-level of interface to the compiler,
+// as defined in ShaderLang.h
+//
+
+#include "GLSLANG/ShaderLang.h"
+
+#include "compiler/translator/InitializeDll.h"
+#include "compiler/preprocessor/length_limits.h"
+#include "compiler/translator/ShHandle.h"
+#include "compiler/translator/TranslatorHLSL.h"
+#include "compiler/translator/VariablePacker.h"
+
+//
+// This is the platform independent interface between an OGL driver
+// 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);
+}
+
+static bool checkMappedNameMaxLength(const ShHandle handle, size_t expectedValue)
+{
+ size_t mappedNameMaxLength = 0;
+ ShGetInfo(handle, SH_MAPPED_NAME_MAX_LENGTH, &mappedNameMaxLength);
+ return (expectedValue == mappedNameMaxLength);
+}
+
+//
+// Driver must call this first, once, before doing any other compiler operations.
+// Subsequent calls to this function are no-op.
+//
+int ShInitialize()
+{
+ static const bool kInitialized = InitProcess();
+ return kInitialized ? 1 : 0;
+}
+
+//
+// Cleanup symbol tables
+//
+int ShFinalize()
+{
+ DetachProcess();
+ return 1;
+}
+
+//
+// Initialize built-in resources with minimum expected values.
+//
+void ShInitBuiltInResources(ShBuiltInResources* resources)
+{
+ // Constants.
+ resources->MaxVertexAttribs = 8;
+ resources->MaxVertexUniformVectors = 128;
+ resources->MaxVaryingVectors = 8;
+ resources->MaxVertexTextureImageUnits = 0;
+ resources->MaxCombinedTextureImageUnits = 8;
+ resources->MaxTextureImageUnits = 8;
+ resources->MaxFragmentUniformVectors = 16;
+ resources->MaxDrawBuffers = 1;
+
+ // Extensions.
+ resources->OES_standard_derivatives = 0;
+ resources->OES_EGL_image_external = 0;
+ resources->ARB_texture_rectangle = 0;
+ resources->EXT_draw_buffers = 0;
+ resources->EXT_frag_depth = 0;
+
+ // Disable highp precision in fragment shader by default.
+ resources->FragmentPrecisionHigh = 0;
+
+ // Disable name hashing by default.
+ resources->HashFunction = NULL;
+
+ resources->ArrayIndexClampingStrategy = SH_CLAMP_WITH_CLAMP_INTRINSIC;
+
+ resources->MaxExpressionComplexity = 256;
+ resources->MaxCallStackDepth = 256;
+}
+
+//
+// Driver calls these to create and destroy compiler objects.
+//
+ShHandle ShConstructCompiler(ShShaderType type, ShShaderSpec spec,
+ ShShaderOutput output,
+ const ShBuiltInResources* resources)
+{
+ TShHandleBase* base = static_cast<TShHandleBase*>(ConstructCompiler(type, spec, output));
+ TCompiler* compiler = base->getAsCompiler();
+ if (compiler == 0)
+ return 0;
+
+ // Generate built-in symbol table.
+ if (!compiler->Init(*resources)) {
+ ShDestruct(base);
+ return 0;
+ }
+
+ return reinterpret_cast<void*>(base);
+}
+
+void ShDestruct(ShHandle handle)
+{
+ if (handle == 0)
+ return;
+
+ TShHandleBase* base = static_cast<TShHandleBase*>(handle);
+
+ if (base->getAsCompiler())
+ DeleteCompiler(base->getAsCompiler());
+}
+
+//
+// Do an actual compile on the given strings. The result is left
+// in the given compile object.
+//
+// Return: The return value of ShCompile is really boolean, indicating
+// success or failure.
+//
+int ShCompile(
+ const ShHandle handle,
+ const char* const shaderStrings[],
+ size_t numStrings,
+ int compileOptions)
+{
+ if (handle == 0)
+ return 0;
+
+ 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;
+}
+
+void ShGetInfo(const ShHandle handle, ShShaderInfo pname, size_t* params)
+{
+ if (!handle || !params)
+ return;
+
+ 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->getUniforms().size();
+ break;
+ case SH_ACTIVE_UNIFORM_MAX_LENGTH:
+ *params = 1 + MAX_SYMBOL_NAME_LEN;
+ break;
+ case SH_ACTIVE_ATTRIBUTES:
+ *params = compiler->getAttribs().size();
+ break;
+ case SH_ACTIVE_ATTRIBUTE_MAX_LENGTH:
+ *params = 1 + MAX_SYMBOL_NAME_LEN;
+ break;
+ case SH_VARYINGS:
+ *params = compiler->getVaryings().size();
+ break;
+ case SH_VARYING_MAX_LENGTH:
+ *params = 1 + MAX_SYMBOL_NAME_LEN;
+ break;
+ case SH_MAPPED_NAME_MAX_LENGTH:
+ // Use longer length than MAX_SHORTENED_IDENTIFIER_SIZE to
+ // handle array and struct dereferences.
+ *params = 1 + MAX_SYMBOL_NAME_LEN;
+ break;
+ case SH_NAME_MAX_LENGTH:
+ *params = 1 + MAX_SYMBOL_NAME_LEN;
+ 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;
+ *params = 16 + sizeof(HashedNamePrefix);
+ }
+ break;
+ case SH_HASHED_NAMES_COUNT:
+ *params = compiler->getNameMap().size();
+ break;
+ default: UNREACHABLE();
+ }
+}
+
+//
+// Return any compiler log of messages for the application.
+//
+void ShGetInfoLog(const ShHandle handle, char* infoLog)
+{
+ if (!handle || !infoLog)
+ return;
+
+ TShHandleBase* base = static_cast<TShHandleBase*>(handle);
+ TCompiler* compiler = base->getAsCompiler();
+ if (!compiler) return;
+
+ TInfoSink& infoSink = compiler->getInfoSink();
+ strcpy(infoLog, infoSink.info.c_str());
+}
+
+//
+// Return any object code.
+//
+void ShGetObjectCode(const ShHandle handle, char* objCode)
+{
+ if (!handle || !objCode)
+ return;
+
+ TShHandleBase* base = static_cast<TShHandleBase*>(handle);
+ TCompiler* compiler = base->getAsCompiler();
+ if (!compiler) return;
+
+ TInfoSink& infoSink = compiler->getInfoSink();
+ strcpy(objCode, infoSink.obj.c_str());
+}
+
+void ShGetVariableInfo(const ShHandle handle,
+ ShShaderInfo varType,
+ int index,
+ size_t* length,
+ int* size,
+ ShDataType* type,
+ ShPrecisionType* precision,
+ int* staticUse,
+ char* name,
+ char* mappedName)
+{
+ 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 TVariableInfoList& varList =
+ varType == SH_ACTIVE_ATTRIBUTES ? compiler->getAttribs() :
+ (varType == SH_ACTIVE_UNIFORMS ? compiler->getUniforms() :
+ compiler->getVaryings());
+ if (index < 0 || index >= static_cast<int>(varList.size()))
+ return;
+
+ const TVariableInfo& varInfo = varList[index];
+ if (length) *length = varInfo.name.size();
+ *size = varInfo.size;
+ *type = varInfo.type;
+ switch (varInfo.precision) {
+ case EbpLow:
+ *precision = SH_PRECISION_LOWP;
+ break;
+ case EbpMedium:
+ *precision = SH_PRECISION_MEDIUMP;
+ break;
+ case EbpHigh:
+ *precision = SH_PRECISION_HIGHP;
+ break;
+ default:
+ // Some types does not support precision, for example, boolean.
+ *precision = SH_PRECISION_UNDEFINED;
+ break;
+ }
+ *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 + MAX_SYMBOL_NAME_LEN;
+ 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 + MAX_SYMBOL_NAME_LEN;
+ 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';
+}
+
+void ShGetInfoPointer(const ShHandle handle, ShShaderInfo pname, void** params)
+{
+ if (!handle || !params)
+ return;
+
+ TShHandleBase* base = static_cast<TShHandleBase*>(handle);
+ TranslatorHLSL* translator = base->getAsTranslatorHLSL();
+ if (!translator) return;
+
+ switch(pname)
+ {
+ case SH_ACTIVE_UNIFORMS_ARRAY:
+ *params = (void*)&translator->getUniforms();
+ break;
+ default: UNREACHABLE();
+ }
+}
+
+int ShCheckVariablesWithinPackingLimits(
+ int maxVectors, ShVariableInfo* varInfoArray, size_t varInfoArraySize)
+{
+ if (varInfoArraySize == 0)
+ return 1;
+ ASSERT(varInfoArray);
+ TVariableInfoList variables;
+ for (size_t ii = 0; ii < varInfoArraySize; ++ii)
+ {
+ TVariableInfo var(varInfoArray[ii].type, varInfoArray[ii].size);
+ variables.push_back(var);
+ }
+ VariablePacker packer;
+ return packer.CheckVariablesWithinPackingLimits(maxVectors, variables) ? 1 : 0;
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ShaderLang.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorSymbolTablecpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/SymbolTable.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/SymbolTable.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/SymbolTable.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,216 @@
</span><ins>+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+//
+// Symbol table for parsing. Most functionaliy and main ideas
+// are documented in the header file.
+//
+
+#if defined(_MSC_VER)
+#pragma warning(disable: 4718)
+#endif
+
+#include "compiler/translator/SymbolTable.h"
+
+#include <stdio.h>
+#include <algorithm>
+#include <climits>
+
+TType::TType(const TPublicType &p) :
+ type(p.type), precision(p.precision), qualifier(p.qualifier), size(p.size), matrix(p.matrix), array(p.array), arraySize(p.arraySize), structure(0)
+{
+ if (p.userDef)
+ structure = p.userDef->getStruct();
+}
+
+//
+// Recursively generate mangled names.
+//
+TString TType::buildMangledName() const
+{
+ TString mangledName;
+ if (isMatrix())
+ mangledName += 'm';
+ else if (isVector())
+ mangledName += 'v';
+
+ switch (type) {
+ case EbtFloat: mangledName += 'f'; break;
+ case EbtInt: mangledName += 'i'; break;
+ case EbtBool: mangledName += 'b'; break;
+ case EbtSampler2D: mangledName += "s2"; break;
+ case EbtSamplerCube: mangledName += "sC"; break;
+ case EbtStruct: mangledName += structure->mangledName(); break;
+ default: break;
+ }
+
+ mangledName += static_cast<char>('0' + getNominalSize());
+ if (isArray()) {
+ char buf[20];
+ snprintf(buf, sizeof(buf), "%d", arraySize);
+ mangledName += '[';
+ mangledName += buf;
+ mangledName += ']';
+ }
+ return mangledName;
+}
+
+size_t TType::getObjectSize() const
+{
+ size_t totalSize = 0;
+
+ if (getBasicType() == EbtStruct)
+ totalSize = structure->objectSize();
+ else if (matrix)
+ totalSize = size * size;
+ else
+ totalSize = size;
+
+ if (isArray()) {
+ size_t arraySize = getArraySize();
+ if (arraySize > INT_MAX / totalSize)
+ totalSize = INT_MAX;
+ else
+ totalSize *= arraySize;
+ }
+
+ return totalSize;
+}
+
+bool TStructure::containsArrays() const
+{
+ for (size_t i = 0; i < mFields->size(); ++i) {
+ const TType* fieldType = (*mFields)[i]->type();
+ if (fieldType->isArray() || fieldType->isStructureContainingArrays())
+ return true;
+ }
+ return false;
+}
+
+TString TStructure::buildMangledName() const
+{
+ TString mangledName("struct-");
+ mangledName += *mName;
+ for (size_t i = 0; i < mFields->size(); ++i) {
+ mangledName += '-';
+ mangledName += (*mFields)[i]->type()->getMangledName();
+ }
+ return mangledName;
+}
+
+size_t TStructure::calculateObjectSize() const
+{
+ size_t size = 0;
+ for (size_t i = 0; i < mFields->size(); ++i) {
+ size_t fieldSize = (*mFields)[i]->type()->getObjectSize();
+ if (fieldSize > INT_MAX - size)
+ size = INT_MAX;
+ else
+ size += fieldSize;
+ }
+ return size;
+}
+
+int TStructure::calculateDeepestNesting() const
+{
+ int maxNesting = 0;
+ for (size_t i = 0; i < mFields->size(); ++i) {
+ maxNesting = std::max(maxNesting, (*mFields)[i]->type()->getDeepestStructNesting());
+ }
+ return 1 + maxNesting;
+}
+
+//
+// Dump functions.
+//
+
+void TVariable::dump(TInfoSink& infoSink) const
+{
+ infoSink.debug << getName().c_str() << ": " << type.getQualifierString() << " " << type.getPrecisionString() << " " << type.getBasicString();
+ if (type.isArray()) {
+ infoSink.debug << "[0]";
+ }
+ infoSink.debug << "\n";
+}
+
+void TFunction::dump(TInfoSink &infoSink) const
+{
+ infoSink.debug << getName().c_str() << ": " << returnType.getBasicString() << " " << getMangledName().c_str() << "\n";
+}
+
+void TSymbolTableLevel::dump(TInfoSink &infoSink) const
+{
+ tLevel::const_iterator it;
+ for (it = level.begin(); it != level.end(); ++it)
+ (*it).second->dump(infoSink);
+}
+
+void TSymbolTable::dump(TInfoSink &infoSink) const
+{
+ for (int level = currentLevel(); level >= 0; --level) {
+ infoSink.debug << "LEVEL " << level << "\n";
+ table[level]->dump(infoSink);
+ }
+}
+
+//
+// Functions have buried pointers to delete.
+//
+TFunction::~TFunction()
+{
+ for (TParamList::iterator i = parameters.begin(); i != parameters.end(); ++i)
+ delete (*i).type;
+}
+
+//
+// Symbol table levels are a map of pointers to symbols that have to be deleted.
+//
+TSymbolTableLevel::~TSymbolTableLevel()
+{
+ for (tLevel::iterator it = level.begin(); it != level.end(); ++it)
+ delete (*it).second;
+}
+
+//
+// Change all function entries in the table with the non-mangled name
+// to be related to the provided built-in operation. This is a low
+// performance operation, and only intended for symbol tables that
+// live across a large number of compiles.
+//
+void TSymbolTableLevel::relateToOperator(const char* name, TOperator op)
+{
+ tLevel::iterator it;
+ for (it = level.begin(); it != level.end(); ++it) {
+ if ((*it).second->isFunction()) {
+ TFunction* function = static_cast<TFunction*>((*it).second);
+ if (function->getName() == name)
+ function->relateToOperator(op);
+ }
+ }
+}
+
+//
+// Change all function entries in the table with the non-mangled name
+// to be related to the provided built-in extension. This is a low
+// performance operation, and only intended for symbol tables that
+// live across a large number of compiles.
+//
+void TSymbolTableLevel::relateToExtension(const char* name, const TString& ext)
+{
+ for (tLevel::iterator it = level.begin(); it != level.end(); ++it) {
+ TSymbol* symbol = it->second;
+ if (symbol->getName() == name)
+ symbol->relateToExtension(ext);
+ }
+}
+
+TSymbolTable::~TSymbolTable()
+{
+ for (size_t i = 0; i < table.size(); ++i)
+ delete table[i];
+ for (size_t i = 0; i < precisionStack.size(); ++i)
+ delete precisionStack[i];
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/SymbolTable.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorSymbolTableh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/SymbolTable.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/SymbolTable.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/SymbolTable.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,382 @@
</span><ins>+//
+// Copyright (c) 2002-2013 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 _SYMBOL_TABLE_INCLUDED_
+#define _SYMBOL_TABLE_INCLUDED_
+
+//
+// Symbol table for parsing. Has these design characteristics:
+//
+// * Same symbol table can be used to compile many shaders, to preserve
+// effort of creating and loading with the large numbers of built-in
+// symbols.
+//
+// * Name mangling will be used to give each function a unique name
+// so that symbol table lookups are never ambiguous. This allows
+// a simpler symbol table structure.
+//
+// * Pushing and popping of scope, so symbol table will really be a stack
+// of symbol tables. Searched from the top, with new inserts going into
+// the top.
+//
+// * Constants: Compile time constant symbols will keep their values
+// in the symbol table. The parser can substitute constants at parse
+// time, including doing constant folding and constant propagation.
+//
+// * No temporaries: Temporaries made from operations (+, --, .xy, etc.)
+// are tracked in the intermediate representation, not the symbol table.
+//
+
+#include <assert.h>
+
+#include "common/angleutils.h"
+#include "compiler/translator/InfoSink.h"
+#include "compiler/translator/intermediate.h"
+
+//
+// Symbol base class. (Can build functions or variables out of these...)
+//
+class TSymbol {
+public:
+ POOL_ALLOCATOR_NEW_DELETE();
+ TSymbol(const TString* n) : uniqueId(0), name(n) { }
+ virtual ~TSymbol() { /* don't delete name, it's from the pool */ }
+
+ const TString& getName() const { return *name; }
+ virtual const TString& getMangledName() const { return getName(); }
+ virtual bool isFunction() const { return false; }
+ virtual bool isVariable() const { return false; }
+ void setUniqueId(int id) { uniqueId = id; }
+ int getUniqueId() const { return uniqueId; }
+ virtual void dump(TInfoSink &infoSink) const = 0;
+ void relateToExtension(const TString& ext) { extension = ext; }
+ const TString& getExtension() const { return extension; }
+
+private:
+ DISALLOW_COPY_AND_ASSIGN(TSymbol);
+
+ int uniqueId; // For real comparing during code generation
+ const TString *name;
+ TString extension;
+};
+
+//
+// Variable class, meaning a symbol that's not a function.
+//
+// There could be a separate class heirarchy for Constant variables;
+// Only one of int, bool, or float, (or none) is correct for
+// any particular use, but it's easy to do this way, and doesn't
+// seem worth having separate classes, and "getConst" can't simply return
+// different values for different types polymorphically, so this is
+// just simple and pragmatic.
+//
+class TVariable : public TSymbol {
+public:
+ TVariable(const TString *name, const TType& t, bool uT = false ) : TSymbol(name), type(t), userType(uT), unionArray(0) { }
+ virtual ~TVariable() { }
+ virtual bool isVariable() const { return true; }
+ TType& getType() { return type; }
+ const TType& getType() const { return type; }
+ bool isUserType() const { return userType; }
+ void setQualifier(TQualifier qualifier) { type.setQualifier(qualifier); }
+
+ virtual void dump(TInfoSink &infoSink) const;
+
+ ConstantUnion* getConstPointer()
+ {
+ if (!unionArray)
+ unionArray = new ConstantUnion[type.getObjectSize()];
+
+ return unionArray;
+ }
+
+ ConstantUnion* getConstPointer() const { return unionArray; }
+
+ void shareConstPointer( ConstantUnion *constArray)
+ {
+ if (unionArray == constArray)
+ return;
+
+ delete[] unionArray;
+ unionArray = constArray;
+ }
+
+private:
+ DISALLOW_COPY_AND_ASSIGN(TVariable);
+
+ TType type;
+ bool userType;
+ // we are assuming that Pool Allocator will free the memory allocated to unionArray
+ // when this object is destroyed
+ ConstantUnion *unionArray;
+};
+
+//
+// The function sub-class of symbols and the parser will need to
+// share this definition of a function parameter.
+//
+struct TParameter {
+ TString *name;
+ TType* type;
+};
+
+//
+// The function sub-class of a symbol.
+//
+class TFunction : public TSymbol {
+public:
+ TFunction(TOperator o) :
+ TSymbol(0),
+ returnType(TType(EbtVoid, EbpUndefined)),
+ op(o),
+ defined(false) { }
+ TFunction(const TString *name, TType& retType, TOperator tOp = EOpNull) :
+ TSymbol(name),
+ returnType(retType),
+ mangledName(TFunction::mangleName(*name)),
+ op(tOp),
+ defined(false) { }
+ virtual ~TFunction();
+ virtual bool isFunction() const { return true; }
+
+ static TString mangleName(const TString& name) { return name + '('; }
+ static TString unmangleName(const TString& mangledName)
+ {
+ return TString(mangledName.c_str(), mangledName.find_first_of('('));
+ }
+
+ void addParameter(TParameter& p)
+ {
+ parameters.push_back(p);
+ mangledName = mangledName + p.type->getMangledName();
+ }
+
+ const TString& getMangledName() const { return mangledName; }
+ const TType& getReturnType() const { return returnType; }
+
+ void relateToOperator(TOperator o) { op = o; }
+ TOperator getBuiltInOp() const { return op; }
+
+ void setDefined() { defined = true; }
+ bool isDefined() { return defined; }
+
+ size_t getParamCount() const { return parameters.size(); }
+ const TParameter& getParam(size_t i) const { return parameters[i]; }
+
+ virtual void dump(TInfoSink &infoSink) const;
+
+private:
+ DISALLOW_COPY_AND_ASSIGN(TFunction);
+
+ typedef TVector<TParameter> TParamList;
+ TParamList parameters;
+ TType returnType;
+ TString mangledName;
+ TOperator op;
+ bool defined;
+};
+
+
+class TSymbolTableLevel {
+public:
+ typedef TMap<TString, TSymbol*> tLevel;
+ typedef tLevel::const_iterator const_iterator;
+ typedef const tLevel::value_type tLevelPair;
+ typedef std::pair<tLevel::iterator, bool> tInsertResult;
+
+ TSymbolTableLevel() { }
+ ~TSymbolTableLevel();
+
+ bool insert(const TString &name, TSymbol &symbol)
+ {
+ //
+ // returning true means symbol was added to the table
+ //
+ tInsertResult result = level.insert(tLevelPair(name, &symbol));
+
+ return result.second;
+ }
+
+ bool insert(TSymbol &symbol)
+ {
+ return insert(symbol.getMangledName(), symbol);
+ }
+
+ TSymbol* find(const TString& name) const
+ {
+ tLevel::const_iterator it = level.find(name);
+ if (it == level.end())
+ return 0;
+ else
+ return (*it).second;
+ }
+
+ const_iterator begin() const
+ {
+ return level.begin();
+ }
+
+ const_iterator end() const
+ {
+ return level.end();
+ }
+
+ void relateToOperator(const char* name, TOperator op);
+ void relateToExtension(const char* name, const TString& ext);
+ void dump(TInfoSink &infoSink) const;
+
+protected:
+ tLevel level;
+};
+
+class TSymbolTable {
+public:
+ TSymbolTable() : uniqueId(0)
+ {
+ //
+ // The symbol table cannot be used until push() is called, but
+ // the lack of an initial call to push() can be used to detect
+ // that the symbol table has not been preloaded with built-ins.
+ //
+ }
+ ~TSymbolTable();
+
+ //
+ // When the symbol table is initialized with the built-ins, there should
+ // 'push' calls, so that built-ins are at level 0 and the shader
+ // globals are at level 1.
+ //
+ bool isEmpty() { return table.size() == 0; }
+ bool atBuiltInLevel() { return table.size() == 1; }
+ bool atGlobalLevel() { return table.size() <= 2; }
+ void push()
+ {
+ table.push_back(new TSymbolTableLevel);
+ precisionStack.push_back(new PrecisionStackLevel);
+ }
+
+ void pop()
+ {
+ delete table.back();
+ table.pop_back();
+
+ delete precisionStack.back();
+ precisionStack.pop_back();
+ }
+
+ bool insert(TSymbol& symbol)
+ {
+ symbol.setUniqueId(++uniqueId);
+ return table[currentLevel()]->insert(symbol);
+ }
+
+ bool insertConstInt(const char *name, int value)
+ {
+ TVariable *constant = new TVariable(NewPoolTString(name), TType(EbtInt, EbpUndefined, EvqConst, 1));
+ constant->getConstPointer()->setIConst(value);
+ return insert(*constant);
+ }
+
+ bool insertBuiltIn(TType *rvalue, const char *name, TType *ptype1, TType *ptype2 = 0, TType *ptype3 = 0)
+ {
+ TFunction *function = new TFunction(NewPoolTString(name), *rvalue);
+
+ TParameter param1 = {NULL, ptype1};
+ function->addParameter(param1);
+
+ if(ptype2)
+ {
+ TParameter param2 = {NULL, ptype2};
+ function->addParameter(param2);
+ }
+
+ if(ptype3)
+ {
+ TParameter param3 = {NULL, ptype3};
+ function->addParameter(param3);
+ }
+
+ return insert(*function);
+ }
+
+ TSymbol* find(const TString& name, bool* builtIn = 0, bool *sameScope = 0)
+ {
+ int level = currentLevel();
+ TSymbol* symbol;
+ do {
+ symbol = table[level]->find(name);
+ --level;
+ } while (symbol == 0 && level >= 0);
+ level++;
+ if (builtIn)
+ *builtIn = level == 0;
+ if (sameScope)
+ *sameScope = level == currentLevel();
+ return symbol;
+ }
+
+ TSymbol* findBuiltIn(const TString &name)
+ {
+ return table[0]->find(name);
+ }
+
+ TSymbolTableLevel* getOuterLevel() {
+ assert(table.size() >= 2);
+ return table[currentLevel() - 1];
+ }
+
+ void relateToOperator(const char* name, TOperator op) {
+ table[0]->relateToOperator(name, op);
+ }
+ void relateToExtension(const char* name, const TString& ext) {
+ table[0]->relateToExtension(name, ext);
+ }
+ void dump(TInfoSink &infoSink) const;
+
+ bool setDefaultPrecision(const TPublicType& type, TPrecision prec) {
+ if (!supportsPrecision(type.type))
+ return false;
+ if (type.size != 1 || type.matrix || type.array)
+ return false; // Not allowed to set for aggregate types
+ int indexOfLastElement = static_cast<int>(precisionStack.size()) - 1;
+ (*precisionStack[indexOfLastElement])[type.type] = prec; // Uses map operator [], overwrites the current value
+ return true;
+ }
+
+ // Searches down the precisionStack for a precision qualifier for the specified TBasicType
+ TPrecision getDefaultPrecision(TBasicType type) {
+ if (!supportsPrecision(type))
+ return EbpUndefined;
+ int level = static_cast<int>(precisionStack.size()) - 1;
+ assert(level >= 0); // Just to be safe. Should not happen.
+ PrecisionStackLevel::iterator it;
+ TPrecision prec = EbpUndefined; // If we dont find anything we return this. Should we error check this?
+ while (level >= 0) {
+ it = precisionStack[level]->find(type);
+ if (it != precisionStack[level]->end()) {
+ prec = (*it).second;
+ break;
+ }
+ level--;
+ }
+ return prec;
+ }
+
+private:
+ int currentLevel() const { return static_cast<int>(table.size()) - 1; }
+
+ bool supportsPrecision(TBasicType type) {
+ // Only supports precision for int, float, and sampler types.
+ return type == EbtFloat || type == EbtInt || IsSampler(type);
+ }
+
+ int uniqueId; // for unique identification in code generation
+ std::vector<TSymbolTableLevel*> table;
+ typedef TMap<TBasicType, TPrecision> PrecisionStackLevel;
+ std::vector<PrecisionStackLevel*> precisionStack;
+};
+
+#endif // _SYMBOL_TABLE_INCLUDED_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/SymbolTable.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorTranslatorESSLcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/TranslatorESSL.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/TranslatorESSL.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/TranslatorESSL.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,43 @@
</span><ins>+//
+// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/TranslatorESSL.h"
+
+#include "compiler/translator/OutputESSL.h"
+
+TranslatorESSL::TranslatorESSL(ShShaderType type, ShShaderSpec spec)
+ : TCompiler(type, spec) {
+}
+
+void TranslatorESSL::translate(TIntermNode* root) {
+ TInfoSinkBase& sink = getInfoSink().obj;
+
+ // Write built-in extension behaviors.
+ writeExtensionBehavior();
+
+ // Write emulated built-in functions if needed.
+ getBuiltInFunctionEmulator().OutputEmulatedFunctionDefinition(
+ sink, getShaderType() == SH_FRAGMENT_SHADER);
+
+ // Write array bounds clamping emulation if needed.
+ getArrayBoundsClamper().OutputClampingFunctionDefinition(sink);
+
+ // Write translated shader.
+ TOutputESSL outputESSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), getNameMap(), getSymbolTable());
+ root->traverse(&outputESSL);
+}
+
+void TranslatorESSL::writeExtensionBehavior() {
+ TInfoSinkBase& sink = getInfoSink().obj;
+ const TExtensionBehavior& extensionBehavior = getExtensionBehavior();
+ for (TExtensionBehavior::const_iterator iter = extensionBehavior.begin();
+ iter != extensionBehavior.end(); ++iter) {
+ if (iter->second != EBhUndefined) {
+ sink << "#extension " << iter->first << " : "
+ << getBehaviorString(iter->second) << "\n";
+ }
+ }
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/TranslatorESSL.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorTranslatorESSLh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/TranslatorESSL.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/TranslatorESSL.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/TranslatorESSL.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,23 @@
</span><ins>+//
+// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TRANSLATORESSL_H_
+#define COMPILER_TRANSLATORESSL_H_
+
+#include "compiler/translator/ShHandle.h"
+
+class TranslatorESSL : public TCompiler {
+public:
+ TranslatorESSL(ShShaderType type, ShShaderSpec spec);
+
+protected:
+ virtual void translate(TIntermNode* root);
+
+private:
+ void writeExtensionBehavior();
+};
+
+#endif // COMPILER_TRANSLATORESSL_H_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/TranslatorESSL.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorTranslatorGLSLcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/TranslatorGLSL.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/TranslatorGLSL.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/TranslatorGLSL.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,44 @@
</span><ins>+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/TranslatorGLSL.h"
+
+#include "compiler/translator/OutputGLSL.h"
+#include "compiler/translator/VersionGLSL.h"
+
+static void writeVersion(ShShaderType 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(ShShaderType type, ShShaderSpec spec)
+ : TCompiler(type, spec) {
+}
+
+void TranslatorGLSL::translate(TIntermNode* root) {
+ TInfoSinkBase& sink = getInfoSink().obj;
+
+ // Write GLSL version.
+ writeVersion(getShaderType(), root, sink);
+
+ // Write emulated built-in functions if needed.
+ getBuiltInFunctionEmulator().OutputEmulatedFunctionDefinition(
+ sink, false);
+
+ // Write array bounds clamping emulation if needed.
+ getArrayBoundsClamper().OutputClampingFunctionDefinition(sink);
+
+ // Write translated shader.
+ TOutputGLSL outputGLSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), getNameMap(), getSymbolTable());
+ root->traverse(&outputGLSL);
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/TranslatorGLSL.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorTranslatorGLSLh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/TranslatorGLSL.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/TranslatorGLSL.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/TranslatorGLSL.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,20 @@
</span><ins>+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TRANSLATORGLSL_H_
+#define COMPILER_TRANSLATORGLSL_H_
+
+#include "compiler/translator/ShHandle.h"
+
+class TranslatorGLSL : public TCompiler {
+public:
+ TranslatorGLSL(ShShaderType type, ShShaderSpec spec);
+
+protected:
+ virtual void translate(TIntermNode* root);
+};
+
+#endif // COMPILER_TRANSLATORGLSL_H_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/TranslatorGLSL.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorTranslatorHLSLcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/TranslatorHLSL.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/TranslatorHLSL.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/TranslatorHLSL.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,24 @@
</span><ins>+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/TranslatorHLSL.h"
+
+#include "compiler/translator/InitializeParseContext.h"
+#include "compiler/translator/OutputHLSL.h"
+
+TranslatorHLSL::TranslatorHLSL(ShShaderType type, ShShaderSpec spec, ShShaderOutput output)
+ : TCompiler(type, spec), mOutputType(output)
+{
+}
+
+void TranslatorHLSL::translate(TIntermNode *root)
+{
+ TParseContext& parseContext = *GetGlobalParseContext();
+ sh::OutputHLSL outputHLSL(parseContext, getResources(), mOutputType);
+
+ outputHLSL.output();
+ mActiveUniforms = outputHLSL.getUniforms();
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/TranslatorHLSL.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorTranslatorHLSLh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/TranslatorHLSL.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/TranslatorHLSL.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/TranslatorHLSL.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,27 @@
</span><ins>+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TRANSLATORHLSL_H_
+#define COMPILER_TRANSLATORHLSL_H_
+
+#include "compiler/translator/ShHandle.h"
+#include "compiler/translator/Uniform.h"
+
+class TranslatorHLSL : public TCompiler {
+public:
+ TranslatorHLSL(ShShaderType type, ShShaderSpec spec, ShShaderOutput output);
+
+ virtual TranslatorHLSL *getAsTranslatorHLSL() { return this; }
+ const sh::ActiveUniforms &getUniforms() { return mActiveUniforms; }
+
+protected:
+ virtual void translate(TIntermNode* root);
+
+ sh::ActiveUniforms mActiveUniforms;
+ ShShaderOutput mOutputType;
+};
+
+#endif // COMPILER_TRANSLATORHLSL_H_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/TranslatorHLSL.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorTypesh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Types.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Types.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Types.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,307 @@
</span><ins>+//
+// Copyright (c) 2002-2013 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 _TYPES_INCLUDED
+#define _TYPES_INCLUDED
+
+#include "common/angleutils.h"
+
+#include "compiler/translator/BaseTypes.h"
+#include "compiler/translator/Common.h"
+#include "compiler/translator/compilerdebug.h"
+
+struct TPublicType;
+class TType;
+
+class TField
+{
+public:
+ POOL_ALLOCATOR_NEW_DELETE();
+ TField(TType* type, TString* name) : mType(type), mName(name) {}
+
+ // TODO(alokp): We should only return const type.
+ // Fix it by tweaking grammar.
+ TType* type() { return mType; }
+ const TType* type() const { return mType; }
+
+ const TString& name() const { return *mName; }
+
+private:
+ DISALLOW_COPY_AND_ASSIGN(TField);
+ TType* mType;
+ TString* mName;
+};
+
+typedef TVector<TField*> TFieldList;
+inline TFieldList* NewPoolTFieldList()
+{
+ void* memory = GetGlobalPoolAllocator()->allocate(sizeof(TFieldList));
+ return new(memory) TFieldList;
+}
+
+class TStructure
+{
+public:
+ POOL_ALLOCATOR_NEW_DELETE();
+ TStructure(TString* name, TFieldList* fields)
+ : mName(name),
+ mFields(fields),
+ mObjectSize(0),
+ mDeepestNesting(0) {
+ }
+
+ const TString& name() const { return *mName; }
+ const TFieldList& fields() const { return *mFields; }
+
+ const TString& mangledName() const {
+ if (mMangledName.empty())
+ mMangledName = buildMangledName();
+ return mMangledName;
+ }
+ size_t objectSize() const {
+ if (mObjectSize == 0)
+ mObjectSize = calculateObjectSize();
+ return mObjectSize;
+ };
+ int deepestNesting() const {
+ if (mDeepestNesting == 0)
+ mDeepestNesting = calculateDeepestNesting();
+ return mDeepestNesting;
+ }
+ bool containsArrays() const;
+
+private:
+ DISALLOW_COPY_AND_ASSIGN(TStructure);
+ TString buildMangledName() const;
+ size_t calculateObjectSize() const;
+ int calculateDeepestNesting() const;
+
+ TString* mName;
+ TFieldList* mFields;
+
+ mutable TString mMangledName;
+ mutable size_t mObjectSize;
+ mutable int mDeepestNesting;
+};
+
+//
+// Base class for things that have a type.
+//
+class TType
+{
+public:
+ POOL_ALLOCATOR_NEW_DELETE();
+ TType() {}
+ TType(TBasicType t, TPrecision p, TQualifier q = EvqTemporary, unsigned char s = 1, bool m = false, bool a = false) :
+ type(t), precision(p), qualifier(q), size(s), matrix(m), array(a), arraySize(0), structure(0)
+ {
+ }
+ explicit TType(const TPublicType &p);
+ TType(TStructure* userDef, TPrecision p = EbpUndefined) :
+ type(EbtStruct), precision(p), qualifier(EvqTemporary), size(1), matrix(false), array(false), arraySize(0), structure(userDef)
+ {
+ }
+
+ TBasicType getBasicType() const { return type; }
+ void setBasicType(TBasicType t) { type = t; }
+
+ TPrecision getPrecision() const { return precision; }
+ void setPrecision(TPrecision p) { precision = p; }
+
+ TQualifier getQualifier() const { return qualifier; }
+ void setQualifier(TQualifier q) { qualifier = q; }
+
+ // One-dimensional size of single instance type
+ int getNominalSize() const { return size; }
+ void setNominalSize(unsigned char s) { size = s; }
+ // Full size of single instance of type
+ size_t getObjectSize() const;
+
+ int elementRegisterCount() const
+ {
+ if (structure)
+ {
+ const TFieldList &fields = getStruct()->fields();
+ int registerCount = 0;
+
+ for (size_t i = 0; i < fields.size(); i++)
+ {
+ registerCount += fields[i]->type()->totalRegisterCount();
+ }
+
+ return registerCount;
+ }
+ else if (isMatrix())
+ {
+ return getNominalSize();
+ }
+ else
+ {
+ return 1;
+ }
+ }
+
+ int totalRegisterCount() const
+ {
+ if (array)
+ {
+ return arraySize * elementRegisterCount();
+ }
+ else
+ {
+ return elementRegisterCount();
+ }
+ }
+
+ bool isMatrix() const { return matrix ? true : false; }
+ void setMatrix(bool m) { matrix = m; }
+
+ bool isArray() const { return array ? true : false; }
+ int getArraySize() const { return arraySize; }
+ void setArraySize(int s) { array = true; arraySize = s; }
+ void clearArrayness() { array = false; arraySize = 0; }
+
+ bool isVector() const { return size > 1 && !matrix; }
+ bool isScalar() const { return size == 1 && !matrix && !structure; }
+
+ TStructure* getStruct() const { return structure; }
+ void setStruct(TStructure* s) { structure = s; }
+
+ const TString& getMangledName() const {
+ if (mangled.empty()) {
+ mangled = buildMangledName();
+ mangled += ';';
+ }
+ return mangled;
+ }
+
+ bool sameElementType(const TType& right) const {
+ return type == right.type &&
+ size == right.size &&
+ matrix == right.matrix &&
+ structure == right.structure;
+ }
+ bool operator==(const TType& right) const {
+ return type == right.type &&
+ size == right.size &&
+ matrix == right.matrix &&
+ array == right.array && (!array || arraySize == right.arraySize) &&
+ structure == right.structure;
+ // don't check the qualifier, it's not ever what's being sought after
+ }
+ bool operator!=(const TType& right) const {
+ return !operator==(right);
+ }
+ bool operator<(const TType& right) const {
+ if (type != right.type) return type < right.type;
+ if (size != right.size) return size < right.size;
+ if (matrix != right.matrix) return matrix < right.matrix;
+ if (array != right.array) return array < right.array;
+ if (arraySize != right.arraySize) return arraySize < right.arraySize;
+ if (structure != right.structure) return structure < right.structure;
+
+ return false;
+ }
+
+ const char* getBasicString() const { return ::getBasicString(type); }
+ const char* getPrecisionString() const { return ::getPrecisionString(precision); }
+ const char* getQualifierString() const { return ::getQualifierString(qualifier); }
+ TString getCompleteString() const;
+
+ // If this type is a struct, returns the deepest struct nesting of
+ // any field in the struct. For example:
+ // struct nesting1 {
+ // vec4 position;
+ // };
+ // struct nesting2 {
+ // nesting1 field1;
+ // vec4 field2;
+ // };
+ // For type "nesting2", this method would return 2 -- the number
+ // of structures through which indirection must occur to reach the
+ // deepest field (nesting2.field1.position).
+ int getDeepestStructNesting() const {
+ return structure ? structure->deepestNesting() : 0;
+ }
+
+ bool isStructureContainingArrays() const {
+ return structure ? structure->containsArrays() : false;
+ }
+
+private:
+ TString buildMangledName() const;
+
+ TBasicType type;
+ TPrecision precision;
+ TQualifier qualifier;
+ unsigned char size;
+ bool matrix;
+ bool array;
+ int arraySize;
+
+ TStructure* structure; // 0 unless this is a struct
+
+ mutable TString mangled;
+};
+
+//
+// This is a workaround for a problem with the yacc stack, It can't have
+// types that it thinks have non-trivial constructors. It should
+// just be used while recognizing the grammar, not anything else. Pointers
+// could be used, but also trying to avoid lots of memory management overhead.
+//
+// Not as bad as it looks, there is no actual assumption that the fields
+// match up or are name the same or anything like that.
+//
+struct TPublicType
+{
+ TBasicType type;
+ TQualifier qualifier;
+ TPrecision precision;
+ unsigned char size; // size of vector or matrix, not size of array
+ bool matrix;
+ bool array;
+ int arraySize;
+ TType* userDef;
+ TSourceLoc line;
+
+ void setBasic(TBasicType bt, TQualifier q, const TSourceLoc& ln)
+ {
+ type = bt;
+ qualifier = q;
+ precision = EbpUndefined;
+ size = 1;
+ matrix = false;
+ array = false;
+ arraySize = 0;
+ userDef = 0;
+ line = ln;
+ }
+
+ void setAggregate(unsigned char s, bool m = false)
+ {
+ size = s;
+ matrix = m;
+ }
+
+ void setArray(bool a, int s = 0)
+ {
+ array = a;
+ arraySize = s;
+ }
+
+ bool isStructureContainingArrays() const
+ {
+ if (!userDef)
+ {
+ return false;
+ }
+
+ return userDef->isStructureContainingArrays();
+ }
+};
+
+#endif // _TYPES_INCLUDED_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Types.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorUnfoldShortCircuitcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/UnfoldShortCircuit.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/UnfoldShortCircuit.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/UnfoldShortCircuit.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,184 @@
</span><ins>+//
+// Copyright (c) 2002-2013 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.
+//
+// UnfoldShortCircuit is an AST traverser to output short-circuiting operators as if-else statements.
+// The results are assigned to s# temporaries, which are used by the main translator instead of
+// the original expression.
+//
+
+#include "compiler/translator/UnfoldShortCircuit.h"
+
+#include "compiler/translator/InfoSink.h"
+#include "compiler/translator/OutputHLSL.h"
+
+namespace sh
+{
+UnfoldShortCircuit::UnfoldShortCircuit(TParseContext &context, OutputHLSL *outputHLSL) : mContext(context), mOutputHLSL(outputHLSL)
+{
+ mTemporaryIndex = 0;
+}
+
+void UnfoldShortCircuit::traverse(TIntermNode *node)
+{
+ int rewindIndex = mTemporaryIndex;
+ node->traverse(this);
+ mTemporaryIndex = rewindIndex;
+}
+
+bool UnfoldShortCircuit::visitBinary(Visit visit, TIntermBinary *node)
+{
+ TInfoSinkBase &out = mOutputHLSL->getBodyStream();
+
+ // If our right node doesn't have side effects, we know we don't need to unfold this
+ // expression: there will be no short-circuiting side effects to avoid
+ // (note: unfolding doesn't depend on the left node -- it will always be evaluated)
+ if (!node->getRight()->hasSideEffects())
+ {
+ return true;
+ }
+
+ switch (node->getOp())
+ {
+ case EOpLogicalOr:
+ // "x || y" is equivalent to "x ? true : y", which unfolds to "bool s; if(x) s = true; else s = y;",
+ // and then further simplifies down to "bool s = x; if(!s) s = y;".
+ {
+ int i = mTemporaryIndex;
+
+ out << "bool s" << i << ";\n";
+
+ out << "{\n";
+
+ mTemporaryIndex = i + 1;
+ node->getLeft()->traverse(this);
+ out << "s" << i << " = ";
+ mTemporaryIndex = i + 1;
+ node->getLeft()->traverse(mOutputHLSL);
+ out << ";\n";
+ out << "if (!s" << i << ")\n"
+ "{\n";
+ mTemporaryIndex = i + 1;
+ node->getRight()->traverse(this);
+ out << " s" << i << " = ";
+ mTemporaryIndex = i + 1;
+ node->getRight()->traverse(mOutputHLSL);
+ out << ";\n"
+ "}\n";
+
+ out << "}\n";
+
+ mTemporaryIndex = i + 1;
+ }
+ return false;
+ case EOpLogicalAnd:
+ // "x && y" is equivalent to "x ? y : false", which unfolds to "bool s; if(x) s = y; else s = false;",
+ // and then further simplifies down to "bool s = x; if(s) s = y;".
+ {
+ int i = mTemporaryIndex;
+
+ out << "bool s" << i << ";\n";
+
+ out << "{\n";
+
+ mTemporaryIndex = i + 1;
+ node->getLeft()->traverse(this);
+ out << "s" << i << " = ";
+ mTemporaryIndex = i + 1;
+ node->getLeft()->traverse(mOutputHLSL);
+ out << ";\n";
+ out << "if (s" << i << ")\n"
+ "{\n";
+ mTemporaryIndex = i + 1;
+ node->getRight()->traverse(this);
+ out << " s" << i << " = ";
+ mTemporaryIndex = i + 1;
+ node->getRight()->traverse(mOutputHLSL);
+ out << ";\n"
+ "}\n";
+
+ out << "}\n";
+
+ mTemporaryIndex = i + 1;
+ }
+ return false;
+ default:
+ return true;
+ }
+}
+
+bool UnfoldShortCircuit::visitSelection(Visit visit, TIntermSelection *node)
+{
+ TInfoSinkBase &out = mOutputHLSL->getBodyStream();
+
+ // Unfold "b ? x : y" into "type s; if(b) s = x; else s = y;"
+ if (node->usesTernaryOperator())
+ {
+ int i = mTemporaryIndex;
+
+ out << mOutputHLSL->typeString(node->getType()) << " s" << i << ";\n";
+
+ out << "{\n";
+
+ mTemporaryIndex = i + 1;
+ node->getCondition()->traverse(this);
+ out << "if (";
+ mTemporaryIndex = i + 1;
+ node->getCondition()->traverse(mOutputHLSL);
+ out << ")\n"
+ "{\n";
+ mTemporaryIndex = i + 1;
+ node->getTrueBlock()->traverse(this);
+ out << " s" << i << " = ";
+ mTemporaryIndex = i + 1;
+ node->getTrueBlock()->traverse(mOutputHLSL);
+ out << ";\n"
+ "}\n"
+ "else\n"
+ "{\n";
+ mTemporaryIndex = i + 1;
+ node->getFalseBlock()->traverse(this);
+ out << " s" << i << " = ";
+ mTemporaryIndex = i + 1;
+ node->getFalseBlock()->traverse(mOutputHLSL);
+ out << ";\n"
+ "}\n";
+
+ out << "}\n";
+
+ mTemporaryIndex = i + 1;
+ }
+
+ return false;
+}
+
+bool UnfoldShortCircuit::visitLoop(Visit visit, TIntermLoop *node)
+{
+ int rewindIndex = mTemporaryIndex;
+
+ if (node->getInit())
+ {
+ node->getInit()->traverse(this);
+ }
+
+ if (node->getCondition())
+ {
+ node->getCondition()->traverse(this);
+ }
+
+ if (node->getExpression())
+ {
+ node->getExpression()->traverse(this);
+ }
+
+ mTemporaryIndex = rewindIndex;
+
+ return false;
+}
+
+int UnfoldShortCircuit::getNextTemporaryIndex()
+{
+ return mTemporaryIndex++;
+}
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/UnfoldShortCircuit.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorUnfoldShortCircuith"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/UnfoldShortCircuit.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/UnfoldShortCircuit.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/UnfoldShortCircuit.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,39 @@
</span><ins>+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// UnfoldShortCircuit is an AST traverser to output short-circuiting operators as if-else statements
+//
+
+#ifndef COMPILER_UNFOLDSHORTCIRCUIT_H_
+#define COMPILER_UNFOLDSHORTCIRCUIT_H_
+
+#include "compiler/translator/intermediate.h"
+#include "compiler/translator/ParseContext.h"
+
+namespace sh
+{
+class OutputHLSL;
+
+class UnfoldShortCircuit : public TIntermTraverser
+{
+ public:
+ UnfoldShortCircuit(TParseContext &context, OutputHLSL *outputHLSL);
+
+ void traverse(TIntermNode *node);
+ bool visitBinary(Visit visit, TIntermBinary*);
+ bool visitSelection(Visit visit, TIntermSelection *node);
+ bool visitLoop(Visit visit, TIntermLoop *node);
+
+ int getNextTemporaryIndex();
+
+ protected:
+ TParseContext &mContext;
+ OutputHLSL *const mOutputHLSL;
+
+ int mTemporaryIndex;
+};
+}
+
+#endif // COMPILER_UNFOLDSHORTCIRCUIT_H_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/UnfoldShortCircuit.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorUnfoldShortCircuitASTcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/UnfoldShortCircuitAST.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/UnfoldShortCircuitAST.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/UnfoldShortCircuitAST.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,81 @@
</span><ins>+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/UnfoldShortCircuitAST.h"
+
+namespace
+{
+
+// "x || y" is equivalent to "x ? true : y".
+TIntermSelection *UnfoldOR(TIntermTyped *x, TIntermTyped *y)
+{
+ const TType boolType(EbtBool, EbpUndefined);
+ ConstantUnion *u = new ConstantUnion;
+ u->setBConst(true);
+ TIntermConstantUnion *trueNode = new TIntermConstantUnion(
+ u, TType(EbtBool, EbpUndefined, EvqConst, 1));
+ return new TIntermSelection(x, trueNode, y, boolType);
+}
+
+// "x && y" is equivalent to "x ? y : false".
+TIntermSelection *UnfoldAND(TIntermTyped *x, TIntermTyped *y)
+{
+ const TType boolType(EbtBool, EbpUndefined);
+ ConstantUnion *u = new ConstantUnion;
+ u->setBConst(false);
+ TIntermConstantUnion *falseNode = new TIntermConstantUnion(
+ u, TType(EbtBool, EbpUndefined, EvqConst, 1));
+ return new TIntermSelection(x, y, falseNode, boolType);
+}
+
+} // namespace anonymous
+
+bool UnfoldShortCircuitAST::visitBinary(Visit visit, TIntermBinary *node)
+{
+ TIntermSelection *replacement = NULL;
+
+ switch (node->getOp())
+ {
+ case EOpLogicalOr:
+ replacement = UnfoldOR(node->getLeft(), node->getRight());
+ break;
+ case EOpLogicalAnd:
+ replacement = UnfoldAND(node->getLeft(), node->getRight());
+ break;
+ default:
+ break;
+ }
+ if (replacement)
+ {
+ replacements.push_back(
+ NodeUpdateEntry(getParentNode(), node, replacement));
+ }
+ return true;
+}
+
+void UnfoldShortCircuitAST::updateTree()
+{
+ for (size_t ii = 0; ii < replacements.size(); ++ii)
+ {
+ const NodeUpdateEntry& entry = replacements[ii];
+ ASSERT(entry.parent);
+ bool replaced = entry.parent->replaceChildNode(
+ entry.original, entry.replacement);
+ ASSERT(replaced);
+
+ // In AST traversing, a parent is visited before its children.
+ // After we replace a node, if an immediate child is to
+ // be replaced, we need to make sure we don't update the replaced
+ // node; instead, we update the replacement node.
+ for (size_t jj = ii + 1; jj < replacements.size(); ++jj)
+ {
+ NodeUpdateEntry& entry2 = replacements[jj];
+ if (entry2.parent == entry.original)
+ entry2.parent = entry.replacement;
+ }
+ }
+}
+
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/UnfoldShortCircuitAST.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorUnfoldShortCircuitASTh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/UnfoldShortCircuitAST.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/UnfoldShortCircuitAST.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/UnfoldShortCircuitAST.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,51 @@
</span><ins>+//
+// Copyright (c) 2002-2013 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.
+//
+// UnfoldShortCircuitAST is an AST traverser to replace short-circuiting
+// operations with ternary operations.
+//
+
+#ifndef COMPILER_UNFOLD_SHORT_CIRCUIT_AST_H_
+#define COMPILER_UNFOLD_SHORT_CIRCUIT_AST_H_
+
+#include "common/angleutils.h"
+#include "compiler/translator/intermediate.h"
+
+// This traverser identifies all the short circuit binary nodes that need to
+// be replaced, and creates the corresponding replacement nodes. However,
+// the actual replacements happen after the traverse through updateTree().
+
+class UnfoldShortCircuitAST : public TIntermTraverser
+{
+ public:
+ UnfoldShortCircuitAST() { }
+
+ virtual bool visitBinary(Visit visit, TIntermBinary *);
+
+ void updateTree();
+
+ private:
+ struct NodeUpdateEntry
+ {
+ NodeUpdateEntry(TIntermNode *_parent,
+ TIntermNode *_original,
+ TIntermNode *_replacement)
+ : parent(_parent),
+ original(_original),
+ replacement(_replacement) {}
+
+ TIntermNode *parent;
+ TIntermNode *original;
+ TIntermNode *replacement;
+ };
+
+ // During traversing, save all the replacements that need to happen;
+ // then replace them by calling updateNodes().
+ std::vector<NodeUpdateEntry> replacements;
+
+ DISALLOW_COPY_AND_ASSIGN(UnfoldShortCircuitAST);
+};
+
+#endif // COMPILER_UNFOLD_SHORT_CIRCUIT_AST_H_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/UnfoldShortCircuitAST.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorUniformcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Uniform.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Uniform.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Uniform.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,21 @@
</span><ins>+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/Uniform.h"
+
+namespace sh
+{
+
+Uniform::Uniform(GLenum type, GLenum precision, const char *name, int arraySize, int registerIndex)
+{
+ this->type = type;
+ this->precision = precision;
+ this->name = name;
+ this->arraySize = arraySize;
+ this->registerIndex = registerIndex;
+}
+
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Uniform.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorUniformh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Uniform.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Uniform.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Uniform.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,35 @@
</span><ins>+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_UNIFORM_H_
+#define COMPILER_UNIFORM_H_
+
+#include <string>
+#include <vector>
+
+#define GL_APICALL
+#include <GLES2/gl2.h>
+
+namespace sh
+{
+
+struct Uniform
+{
+ Uniform(GLenum type, GLenum precision, const char *name, int arraySize, int registerIndex);
+
+ GLenum type;
+ GLenum precision;
+ std::string name;
+ unsigned int arraySize;
+
+ int registerIndex;
+};
+
+typedef std::vector<Uniform> ActiveUniforms;
+
+}
+
+#endif // COMPILER_UNIFORM_H_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/Uniform.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorValidateLimitationscpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ValidateLimitations.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ValidateLimitations.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ValidateLimitations.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,512 @@
</span><ins>+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/ValidateLimitations.h"
+#include "compiler/translator/InfoSink.h"
+#include "compiler/translator/InitializeParseContext.h"
+#include "compiler/translator/ParseContext.h"
+
+namespace {
+bool IsLoopIndex(const TIntermSymbol* symbol, const TLoopStack& stack) {
+ for (TLoopStack::const_iterator i = stack.begin(); i != stack.end(); ++i) {
+ if (i->index.id == symbol->getId())
+ return true;
+ }
+ return false;
+}
+
+void MarkLoopForUnroll(const TIntermSymbol* symbol, TLoopStack& stack) {
+ for (TLoopStack::iterator i = stack.begin(); i != stack.end(); ++i) {
+ if (i->index.id == symbol->getId()) {
+ ASSERT(i->loop != NULL);
+ i->loop->setUnrollFlag(true);
+ return;
+ }
+ }
+ UNREACHABLE();
+}
+
+// Traverses a node to check if it represents a constant index expression.
+// Definition:
+// constant-index-expressions are a superset of constant-expressions.
+// Constant-index-expressions can include loop indices as defined in
+// GLSL ES 1.0 spec, Appendix A, section 4.
+// The following are constant-index-expressions:
+// - Constant expressions
+// - Loop indices as defined in section 4
+// - Expressions composed of both of the above
+class ValidateConstIndexExpr : public TIntermTraverser {
+public:
+ ValidateConstIndexExpr(const TLoopStack& stack)
+ : mValid(true), mLoopStack(stack) {}
+
+ // Returns true if the parsed node represents a constant index expression.
+ bool isValid() const { return mValid; }
+
+ virtual void visitSymbol(TIntermSymbol* symbol) {
+ // Only constants and loop indices are allowed in a
+ // constant index expression.
+ if (mValid) {
+ mValid = (symbol->getQualifier() == EvqConst) ||
+ IsLoopIndex(symbol, mLoopStack);
+ }
+ }
+
+private:
+ bool mValid;
+ const TLoopStack& mLoopStack;
+};
+
+// Traverses a node to check if it uses a loop index.
+// If an int loop index is used in its body as a sampler array index,
+// mark the loop for unroll.
+class ValidateLoopIndexExpr : public TIntermTraverser {
+public:
+ ValidateLoopIndexExpr(TLoopStack& stack)
+ : mUsesFloatLoopIndex(false),
+ mUsesIntLoopIndex(false),
+ mLoopStack(stack) {}
+
+ bool usesFloatLoopIndex() const { return mUsesFloatLoopIndex; }
+ bool usesIntLoopIndex() const { return mUsesIntLoopIndex; }
+
+ virtual void visitSymbol(TIntermSymbol* symbol) {
+ if (IsLoopIndex(symbol, mLoopStack)) {
+ switch (symbol->getBasicType()) {
+ case EbtFloat:
+ mUsesFloatLoopIndex = true;
+ break;
+ case EbtInt:
+ mUsesIntLoopIndex = true;
+ MarkLoopForUnroll(symbol, mLoopStack);
+ break;
+ default:
+ UNREACHABLE();
+ }
+ }
+ }
+
+private:
+ bool mUsesFloatLoopIndex;
+ bool mUsesIntLoopIndex;
+ TLoopStack& mLoopStack;
+};
+} // namespace
+
+ValidateLimitations::ValidateLimitations(ShShaderType shaderType,
+ TInfoSinkBase& sink)
+ : mShaderType(shaderType),
+ mSink(sink),
+ mNumErrors(0)
+{
+}
+
+bool ValidateLimitations::visitBinary(Visit, TIntermBinary* node)
+{
+ // Check if loop index is modified in the loop body.
+ validateOperation(node, node->getLeft());
+
+ // Check indexing.
+ switch (node->getOp()) {
+ case EOpIndexDirect:
+ validateIndexing(node);
+ break;
+ case EOpIndexIndirect:
+#if defined(__APPLE__)
+ // Loop unrolling is a work-around for a Mac Cg compiler bug where it
+ // crashes when a sampler array's index is also the loop index.
+ // Once Apple fixes this bug, we should remove the code in this CL.
+ // See http://codereview.appspot.com/4331048/.
+ if ((node->getLeft() != NULL) && (node->getRight() != NULL) &&
+ (node->getLeft()->getAsSymbolNode())) {
+ TIntermSymbol* symbol = node->getLeft()->getAsSymbolNode();
+ if (IsSampler(symbol->getBasicType()) && symbol->isArray()) {
+ ValidateLoopIndexExpr validate(mLoopStack);
+ node->getRight()->traverse(&validate);
+ if (validate.usesFloatLoopIndex()) {
+ error(node->getLine(),
+ "sampler array index is float loop index",
+ "for");
+ }
+ }
+ }
+#endif
+ validateIndexing(node);
+ break;
+ default: break;
+ }
+ return true;
+}
+
+bool ValidateLimitations::visitUnary(Visit, TIntermUnary* node)
+{
+ // Check if loop index is modified in the loop body.
+ validateOperation(node, node->getOperand());
+
+ return true;
+}
+
+bool ValidateLimitations::visitAggregate(Visit, TIntermAggregate* node)
+{
+ switch (node->getOp()) {
+ case EOpFunctionCall:
+ validateFunctionCall(node);
+ break;
+ default:
+ break;
+ }
+ return true;
+}
+
+bool ValidateLimitations::visitLoop(Visit, TIntermLoop* node)
+{
+ if (!validateLoopType(node))
+ return false;
+
+ TLoopInfo info;
+ memset(&info, 0, sizeof(TLoopInfo));
+ info.loop = node;
+ if (!validateForLoopHeader(node, &info))
+ return false;
+
+ TIntermNode* body = node->getBody();
+ if (body != NULL) {
+ mLoopStack.push_back(info);
+ body->traverse(this);
+ mLoopStack.pop_back();
+ }
+
+ // The loop is fully processed - no need to visit children.
+ return false;
+}
+
+void ValidateLimitations::error(TSourceLoc loc,
+ const char *reason, const char* token)
+{
+ mSink.prefix(EPrefixError);
+ mSink.location(loc);
+ mSink << "'" << token << "' : " << reason << "\n";
+ ++mNumErrors;
+}
+
+bool ValidateLimitations::withinLoopBody() const
+{
+ return !mLoopStack.empty();
+}
+
+bool ValidateLimitations::isLoopIndex(const TIntermSymbol* symbol) const
+{
+ return IsLoopIndex(symbol, mLoopStack);
+}
+
+bool ValidateLimitations::validateLoopType(TIntermLoop* node) {
+ TLoopType type = node->getType();
+ if (type == ELoopFor)
+ return true;
+
+ // Reject while and do-while loops.
+ error(node->getLine(),
+ "This type of loop is not allowed",
+ type == ELoopWhile ? "while" : "do");
+ return false;
+}
+
+bool ValidateLimitations::validateForLoopHeader(TIntermLoop* node,
+ TLoopInfo* info)
+{
+ ASSERT(node->getType() == ELoopFor);
+
+ //
+ // The for statement has the form:
+ // for ( init-declaration ; condition ; expression ) statement
+ //
+ if (!validateForLoopInit(node, info))
+ return false;
+ if (!validateForLoopCond(node, info))
+ return false;
+ if (!validateForLoopExpr(node, info))
+ return false;
+
+ return true;
+}
+
+bool ValidateLimitations::validateForLoopInit(TIntermLoop* node,
+ TLoopInfo* info)
+{
+ TIntermNode* init = node->getInit();
+ if (init == NULL) {
+ error(node->getLine(), "Missing init declaration", "for");
+ return false;
+ }
+
+ //
+ // init-declaration has the form:
+ // type-specifier identifier = constant-expression
+ //
+ TIntermAggregate* decl = init->getAsAggregate();
+ if ((decl == NULL) || (decl->getOp() != EOpDeclaration)) {
+ error(init->getLine(), "Invalid init declaration", "for");
+ return false;
+ }
+ // To keep things simple do not allow declaration list.
+ TIntermSequence& declSeq = decl->getSequence();
+ if (declSeq.size() != 1) {
+ error(decl->getLine(), "Invalid init declaration", "for");
+ return false;
+ }
+ TIntermBinary* declInit = declSeq[0]->getAsBinaryNode();
+ if ((declInit == NULL) || (declInit->getOp() != EOpInitialize)) {
+ error(decl->getLine(), "Invalid init declaration", "for");
+ return false;
+ }
+ TIntermSymbol* symbol = declInit->getLeft()->getAsSymbolNode();
+ if (symbol == NULL) {
+ error(declInit->getLine(), "Invalid init declaration", "for");
+ return false;
+ }
+ // The loop index has type int or float.
+ TBasicType type = symbol->getBasicType();
+ if ((type != EbtInt) && (type != EbtFloat)) {
+ error(symbol->getLine(),
+ "Invalid type for loop index", getBasicString(type));
+ return false;
+ }
+ // The loop index is initialized with constant expression.
+ if (!isConstExpr(declInit->getRight())) {
+ error(declInit->getLine(),
+ "Loop index cannot be initialized with non-constant expression",
+ symbol->getSymbol().c_str());
+ return false;
+ }
+
+ info->index.id = symbol->getId();
+ return true;
+}
+
+bool ValidateLimitations::validateForLoopCond(TIntermLoop* node,
+ TLoopInfo* info)
+{
+ TIntermNode* cond = node->getCondition();
+ if (cond == NULL) {
+ error(node->getLine(), "Missing condition", "for");
+ return false;
+ }
+ //
+ // condition has the form:
+ // loop_index relational_operator constant_expression
+ //
+ TIntermBinary* binOp = cond->getAsBinaryNode();
+ if (binOp == NULL) {
+ error(node->getLine(), "Invalid condition", "for");
+ return false;
+ }
+ // Loop index should be to the left of relational operator.
+ TIntermSymbol* symbol = binOp->getLeft()->getAsSymbolNode();
+ if (symbol == NULL) {
+ error(binOp->getLine(), "Invalid condition", "for");
+ return false;
+ }
+ if (symbol->getId() != info->index.id) {
+ error(symbol->getLine(),
+ "Expected loop index", symbol->getSymbol().c_str());
+ return false;
+ }
+ // Relational operator is one of: > >= < <= == or !=.
+ switch (binOp->getOp()) {
+ case EOpEqual:
+ case EOpNotEqual:
+ case EOpLessThan:
+ case EOpGreaterThan:
+ case EOpLessThanEqual:
+ case EOpGreaterThanEqual:
+ break;
+ default:
+ error(binOp->getLine(),
+ "Invalid relational operator",
+ getOperatorString(binOp->getOp()));
+ break;
+ }
+ // Loop index must be compared with a constant.
+ if (!isConstExpr(binOp->getRight())) {
+ error(binOp->getLine(),
+ "Loop index cannot be compared with non-constant expression",
+ symbol->getSymbol().c_str());
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateLimitations::validateForLoopExpr(TIntermLoop* node,
+ TLoopInfo* info)
+{
+ TIntermNode* expr = node->getExpression();
+ if (expr == NULL) {
+ error(node->getLine(), "Missing expression", "for");
+ return false;
+ }
+
+ // for expression has one of the following forms:
+ // loop_index++
+ // loop_index--
+ // loop_index += constant_expression
+ // loop_index -= constant_expression
+ // ++loop_index
+ // --loop_index
+ // The last two forms are not specified in the spec, but I am assuming
+ // its an oversight.
+ TIntermUnary* unOp = expr->getAsUnaryNode();
+ TIntermBinary* binOp = unOp ? NULL : expr->getAsBinaryNode();
+
+ TOperator op = EOpNull;
+ TIntermSymbol* symbol = NULL;
+ if (unOp != NULL) {
+ op = unOp->getOp();
+ symbol = unOp->getOperand()->getAsSymbolNode();
+ } else if (binOp != NULL) {
+ op = binOp->getOp();
+ symbol = binOp->getLeft()->getAsSymbolNode();
+ }
+
+ // The operand must be loop index.
+ if (symbol == NULL) {
+ error(expr->getLine(), "Invalid expression", "for");
+ return false;
+ }
+ if (symbol->getId() != info->index.id) {
+ error(symbol->getLine(),
+ "Expected loop index", symbol->getSymbol().c_str());
+ return false;
+ }
+
+ // The operator is one of: ++ -- += -=.
+ switch (op) {
+ case EOpPostIncrement:
+ case EOpPostDecrement:
+ case EOpPreIncrement:
+ case EOpPreDecrement:
+ ASSERT((unOp != NULL) && (binOp == NULL));
+ break;
+ case EOpAddAssign:
+ case EOpSubAssign:
+ ASSERT((unOp == NULL) && (binOp != NULL));
+ break;
+ default:
+ error(expr->getLine(), "Invalid operator", getOperatorString(op));
+ return false;
+ }
+
+ // Loop index must be incremented/decremented with a constant.
+ if (binOp != NULL) {
+ if (!isConstExpr(binOp->getRight())) {
+ error(binOp->getLine(),
+ "Loop index cannot be modified by non-constant expression",
+ symbol->getSymbol().c_str());
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateLimitations::validateFunctionCall(TIntermAggregate* node)
+{
+ ASSERT(node->getOp() == EOpFunctionCall);
+
+ // If not within loop body, there is nothing to check.
+ if (!withinLoopBody())
+ return true;
+
+ // List of param indices for which loop indices are used as argument.
+ typedef std::vector<size_t> ParamIndex;
+ ParamIndex pIndex;
+ TIntermSequence& params = node->getSequence();
+ for (TIntermSequence::size_type i = 0; i < params.size(); ++i) {
+ TIntermSymbol* symbol = params[i]->getAsSymbolNode();
+ if (symbol && isLoopIndex(symbol))
+ pIndex.push_back(i);
+ }
+ // If none of the loop indices are used as arguments,
+ // there is nothing to check.
+ if (pIndex.empty())
+ return true;
+
+ bool valid = true;
+ TSymbolTable& symbolTable = GetGlobalParseContext()->symbolTable;
+ TSymbol* symbol = symbolTable.find(node->getName());
+ ASSERT(symbol && symbol->isFunction());
+ TFunction* function = static_cast<TFunction*>(symbol);
+ for (ParamIndex::const_iterator i = pIndex.begin();
+ i != pIndex.end(); ++i) {
+ const TParameter& param = function->getParam(*i);
+ TQualifier qual = param.type->getQualifier();
+ if ((qual == EvqOut) || (qual == EvqInOut)) {
+ error(params[*i]->getLine(),
+ "Loop index cannot be used as argument to a function out or inout parameter",
+ params[*i]->getAsSymbolNode()->getSymbol().c_str());
+ valid = false;
+ }
+ }
+
+ return valid;
+}
+
+bool ValidateLimitations::validateOperation(TIntermOperator* node,
+ TIntermNode* operand) {
+ // Check if loop index is modified in the loop body.
+ if (!withinLoopBody() || !node->isAssignment())
+ return true;
+
+ const TIntermSymbol* symbol = operand->getAsSymbolNode();
+ if (symbol && isLoopIndex(symbol)) {
+ error(node->getLine(),
+ "Loop index cannot be statically assigned to within the body of the loop",
+ symbol->getSymbol().c_str());
+ }
+ return true;
+}
+
+bool ValidateLimitations::isConstExpr(TIntermNode* node)
+{
+ ASSERT(node != NULL);
+ return node->getAsConstantUnion() != NULL;
+}
+
+bool ValidateLimitations::isConstIndexExpr(TIntermNode* node)
+{
+ ASSERT(node != NULL);
+
+ ValidateConstIndexExpr validate(mLoopStack);
+ node->traverse(&validate);
+ return validate.isValid();
+}
+
+bool ValidateLimitations::validateIndexing(TIntermBinary* node)
+{
+ ASSERT((node->getOp() == EOpIndexDirect) ||
+ (node->getOp() == EOpIndexIndirect));
+
+ bool valid = true;
+ TIntermTyped* index = node->getRight();
+ // The index expression must have integral type.
+ if (!index->isScalar() || (index->getBasicType() != EbtInt)) {
+ error(index->getLine(),
+ "Index expression must have integral type",
+ index->getCompleteString().c_str());
+ valid = false;
+ }
+ // The index expession must be a constant-index-expression unless
+ // the operand is a uniform in a vertex shader.
+ TIntermTyped* operand = node->getLeft();
+ bool skip = (mShaderType == SH_VERTEX_SHADER) &&
+ (operand->getQualifier() == EvqUniform);
+ if (!skip && !isConstIndexExpr(index)) {
+ error(index->getLine(), "Index expression must be constant", "[]");
+ valid = false;
+ }
+ return valid;
+}
+
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ValidateLimitations.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorValidateLimitationsh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ValidateLimitations.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ValidateLimitations.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ValidateLimitations.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,59 @@
</span><ins>+//
+// Copyright (c) 2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "GLSLANG/ShaderLang.h"
+#include "compiler/translator/intermediate.h"
+
+class TInfoSinkBase;
+
+struct TLoopInfo {
+ struct TIndex {
+ int id; // symbol id.
+ } index;
+ TIntermLoop* loop;
+};
+typedef TVector<TLoopInfo> TLoopStack;
+
+// Traverses intermediate tree to ensure that the shader does not exceed the
+// minimum functionality mandated in GLSL 1.0 spec, Appendix A.
+class ValidateLimitations : public TIntermTraverser {
+public:
+ ValidateLimitations(ShShaderType shaderType, TInfoSinkBase& sink);
+
+ int numErrors() const { return mNumErrors; }
+
+ virtual bool visitBinary(Visit, TIntermBinary*);
+ virtual bool visitUnary(Visit, TIntermUnary*);
+ virtual bool visitAggregate(Visit, TIntermAggregate*);
+ virtual bool visitLoop(Visit, TIntermLoop*);
+
+private:
+ void error(TSourceLoc loc, const char *reason, const char* token);
+
+ bool withinLoopBody() const;
+ bool isLoopIndex(const TIntermSymbol* symbol) const;
+ bool validateLoopType(TIntermLoop* node);
+ bool validateForLoopHeader(TIntermLoop* node, TLoopInfo* info);
+ bool validateForLoopInit(TIntermLoop* node, TLoopInfo* info);
+ bool validateForLoopCond(TIntermLoop* node, TLoopInfo* info);
+ bool validateForLoopExpr(TIntermLoop* node, TLoopInfo* info);
+ // Returns true if none of the loop indices is used as the argument to
+ // the given function out or inout parameter.
+ bool validateFunctionCall(TIntermAggregate* node);
+ bool validateOperation(TIntermOperator* node, TIntermNode* operand);
+
+ // Returns true if indexing does not exceed the minimum functionality
+ // mandated in GLSL 1.0 spec, Appendix A, Section 5.
+ bool isConstExpr(TIntermNode* node);
+ bool isConstIndexExpr(TIntermNode* node);
+ bool validateIndexing(TIntermBinary* node);
+
+ ShShaderType mShaderType;
+ TInfoSinkBase& mSink;
+ int mNumErrors;
+ TLoopStack mLoopStack;
+};
+
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ValidateLimitations.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorVariableInfocpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/VariableInfo.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/VariableInfo.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/VariableInfo.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,312 @@
</span><ins>+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/VariableInfo.h"
+
+namespace {
+
+TString arrayBrackets(int index)
+{
+ TStringStream stream;
+ stream << "[" << index << "]";
+ return stream.str();
+}
+
+// Returns the data type for an attribute, uniform, or varying.
+ShDataType getVariableDataType(const TType& type)
+{
+ switch (type.getBasicType()) {
+ case EbtFloat:
+ if (type.isMatrix()) {
+ switch (type.getNominalSize()) {
+ case 2: return SH_FLOAT_MAT2;
+ case 3: return SH_FLOAT_MAT3;
+ case 4: return SH_FLOAT_MAT4;
+ default: UNREACHABLE();
+ }
+ } else if (type.isVector()) {
+ switch (type.getNominalSize()) {
+ case 2: return SH_FLOAT_VEC2;
+ case 3: return SH_FLOAT_VEC3;
+ case 4: return SH_FLOAT_VEC4;
+ default: UNREACHABLE();
+ }
+ } else {
+ return SH_FLOAT;
+ }
+ case EbtInt:
+ if (type.isMatrix()) {
+ UNREACHABLE();
+ } else if (type.isVector()) {
+ switch (type.getNominalSize()) {
+ case 2: return SH_INT_VEC2;
+ case 3: return SH_INT_VEC3;
+ case 4: return SH_INT_VEC4;
+ default: UNREACHABLE();
+ }
+ } else {
+ return SH_INT;
+ }
+ case EbtBool:
+ if (type.isMatrix()) {
+ UNREACHABLE();
+ } else if (type.isVector()) {
+ switch (type.getNominalSize()) {
+ case 2: return SH_BOOL_VEC2;
+ case 3: return SH_BOOL_VEC3;
+ case 4: return SH_BOOL_VEC4;
+ default: UNREACHABLE();
+ }
+ } else {
+ return SH_BOOL;
+ }
+ case EbtSampler2D: return SH_SAMPLER_2D;
+ case EbtSamplerCube: return SH_SAMPLER_CUBE;
+ case EbtSamplerExternalOES: return SH_SAMPLER_EXTERNAL_OES;
+ case EbtSampler2DRect: return SH_SAMPLER_2D_RECT_ARB;
+ default: UNREACHABLE();
+ }
+ return SH_NONE;
+}
+
+void getBuiltInVariableInfo(const TType& type,
+ const TString& name,
+ const TString& mappedName,
+ TVariableInfoList& infoList);
+void getUserDefinedVariableInfo(const TType& type,
+ const TString& name,
+ const TString& mappedName,
+ TVariableInfoList& infoList,
+ ShHashFunction64 hashFunction);
+
+// Returns info for an attribute, uniform, or varying.
+void getVariableInfo(const TType& type,
+ const TString& name,
+ const TString& mappedName,
+ TVariableInfoList& infoList,
+ ShHashFunction64 hashFunction)
+{
+ if (type.getBasicType() == EbtStruct) {
+ if (type.isArray()) {
+ for (int i = 0; i < type.getArraySize(); ++i) {
+ TString lname = name + arrayBrackets(i);
+ TString lmappedName = mappedName + arrayBrackets(i);
+ getUserDefinedVariableInfo(type, lname, lmappedName, infoList, hashFunction);
+ }
+ } else {
+ getUserDefinedVariableInfo(type, name, mappedName, infoList, hashFunction);
+ }
+ } else {
+ getBuiltInVariableInfo(type, name, mappedName, infoList);
+ }
+}
+
+void getBuiltInVariableInfo(const TType& type,
+ const TString& name,
+ const TString& mappedName,
+ TVariableInfoList& infoList)
+{
+ ASSERT(type.getBasicType() != EbtStruct);
+
+ TVariableInfo varInfo;
+ if (type.isArray()) {
+ varInfo.name = (name + "[0]").c_str();
+ varInfo.mappedName = (mappedName + "[0]").c_str();
+ varInfo.size = type.getArraySize();
+ varInfo.isArray = true;
+ } else {
+ varInfo.name = name.c_str();
+ varInfo.mappedName = mappedName.c_str();
+ varInfo.size = 1;
+ varInfo.isArray = false;
+ }
+ varInfo.precision = type.getPrecision();
+ varInfo.type = getVariableDataType(type);
+ infoList.push_back(varInfo);
+}
+
+void getUserDefinedVariableInfo(const TType& type,
+ const TString& name,
+ const TString& mappedName,
+ TVariableInfoList& infoList,
+ ShHashFunction64 hashFunction)
+{
+ ASSERT(type.getBasicType() == EbtStruct);
+
+ const TFieldList& fields = type.getStruct()->fields();
+ for (size_t i = 0; i < fields.size(); ++i) {
+ const TType& fieldType = *(fields[i]->type());
+ const TString& fieldName = fields[i]->name();
+ getVariableInfo(fieldType,
+ name + "." + fieldName,
+ mappedName + "." + TIntermTraverser::hash(fieldName, hashFunction),
+ infoList,
+ hashFunction);
+ }
+}
+
+TVariableInfo* findVariable(const TType& type,
+ const TString& name,
+ TVariableInfoList& infoList)
+{
+ // TODO(zmo): optimize this function.
+ TString myName = name;
+ if (type.isArray())
+ myName += "[0]";
+ for (size_t ii = 0; ii < infoList.size(); ++ii)
+ {
+ if (infoList[ii].name.c_str() == myName)
+ return &(infoList[ii]);
+ }
+ return NULL;
+}
+
+} // namespace anonymous
+
+TVariableInfo::TVariableInfo()
+ : type(SH_NONE),
+ size(0),
+ isArray(false),
+ precision(EbpUndefined),
+ staticUse(false)
+{
+}
+
+TVariableInfo::TVariableInfo(ShDataType type, int size)
+ : type(type),
+ size(size),
+ isArray(false),
+ precision(EbpUndefined),
+ staticUse(false)
+{
+}
+
+CollectVariables::CollectVariables(TVariableInfoList& attribs,
+ TVariableInfoList& uniforms,
+ TVariableInfoList& varyings,
+ ShHashFunction64 hashFunction)
+ : mAttribs(attribs),
+ mUniforms(uniforms),
+ mVaryings(varyings),
+ mPointCoordAdded(false),
+ mFrontFacingAdded(false),
+ mFragCoordAdded(false),
+ mHashFunction(hashFunction)
+{
+}
+
+// We want to check whether a uniform/varying is statically used
+// because we only count the used ones in packing computing.
+// Also, gl_FragCoord, gl_PointCoord, and gl_FrontFacing count
+// toward varying counting if they are statically used in a fragment
+// shader.
+void CollectVariables::visitSymbol(TIntermSymbol* symbol)
+{
+ ASSERT(symbol != NULL);
+ TVariableInfo* var = NULL;
+ switch (symbol->getQualifier())
+ {
+ case EvqVaryingOut:
+ case EvqInvariantVaryingOut:
+ case EvqVaryingIn:
+ case EvqInvariantVaryingIn:
+ var = findVariable(symbol->getType(), symbol->getSymbol(), mVaryings);
+ break;
+ case EvqUniform:
+ var = findVariable(symbol->getType(), symbol->getSymbol(), mUniforms);
+ break;
+ case EvqFragCoord:
+ if (!mFragCoordAdded) {
+ TVariableInfo info;
+ info.name = "gl_FragCoord";
+ info.mappedName = "gl_FragCoord";
+ info.type = SH_FLOAT_VEC4;
+ info.size = 1;
+ info.precision = EbpMedium; // Use mediump as it doesn't really matter.
+ info.staticUse = true;
+ mVaryings.push_back(info);
+ mFragCoordAdded = true;
+ }
+ return;
+ case EvqFrontFacing:
+ if (!mFrontFacingAdded) {
+ TVariableInfo info;
+ info.name = "gl_FrontFacing";
+ info.mappedName = "gl_FrontFacing";
+ info.type = SH_BOOL;
+ info.size = 1;
+ info.precision = EbpUndefined;
+ info.staticUse = true;
+ mVaryings.push_back(info);
+ mFrontFacingAdded = true;
+ }
+ return;
+ case EvqPointCoord:
+ if (!mPointCoordAdded) {
+ TVariableInfo info;
+ info.name = "gl_PointCoord";
+ info.mappedName = "gl_PointCoord";
+ info.type = SH_FLOAT_VEC2;
+ info.size = 1;
+ info.precision = EbpMedium; // Use mediump as it doesn't really matter.
+ info.staticUse = true;
+ mVaryings.push_back(info);
+ mPointCoordAdded = true;
+ }
+ return;
+ default:
+ break;
+ }
+ if (var)
+ var->staticUse = true;
+}
+
+bool CollectVariables::visitAggregate(Visit, TIntermAggregate* node)
+{
+ bool visitChildren = true;
+
+ switch (node->getOp())
+ {
+ case EOpDeclaration: {
+ const TIntermSequence& sequence = node->getSequence();
+ TQualifier qualifier = sequence.front()->getAsTyped()->getQualifier();
+ if (qualifier == EvqAttribute || qualifier == EvqUniform ||
+ qualifier == EvqVaryingIn || qualifier == EvqVaryingOut ||
+ qualifier == EvqInvariantVaryingIn || qualifier == EvqInvariantVaryingOut)
+ {
+ TVariableInfoList& infoList = qualifier == EvqAttribute ? mAttribs :
+ (qualifier == EvqUniform ? mUniforms : mVaryings);
+ for (TIntermSequence::const_iterator i = sequence.begin();
+ i != sequence.end(); ++i)
+ {
+ const TIntermSymbol* variable = (*i)->getAsSymbolNode();
+ // The only case in which the sequence will not contain a
+ // TIntermSymbol node is initialization. It will contain a
+ // TInterBinary node in that case. Since attributes, uniforms,
+ // and varyings cannot be initialized in a shader, we must have
+ // only TIntermSymbol nodes in the sequence.
+ ASSERT(variable != NULL);
+ TString processedSymbol;
+ if (mHashFunction == NULL)
+ processedSymbol = variable->getSymbol();
+ else
+ processedSymbol = TIntermTraverser::hash(variable->getOriginalSymbol(), mHashFunction);
+ getVariableInfo(variable->getType(),
+ variable->getOriginalSymbol(),
+ processedSymbol,
+ infoList,
+ mHashFunction);
+ visitChildren = false;
+ }
+ }
+ break;
+ }
+ default: break;
+ }
+
+ return visitChildren;
+}
+
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/VariableInfo.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorVariableInfoh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/VariableInfo.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/VariableInfo.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/VariableInfo.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,52 @@
</span><ins>+//
+// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_VARIABLE_INFO_H_
+#define COMPILER_VARIABLE_INFO_H_
+
+#include "GLSLANG/ShaderLang.h"
+#include "compiler/translator/intermediate.h"
+
+// Provides information about a variable.
+// It is currently being used to store info about active attribs and uniforms.
+struct TVariableInfo {
+ TVariableInfo(ShDataType type, int size);
+ TVariableInfo();
+
+ TPersistString name;
+ TPersistString mappedName;
+ ShDataType type;
+ int size;
+ bool isArray;
+ TPrecision precision;
+ bool staticUse;
+};
+typedef std::vector<TVariableInfo> TVariableInfoList;
+
+// Traverses intermediate tree to collect all attributes, uniforms, varyings.
+class CollectVariables : public TIntermTraverser {
+public:
+ CollectVariables(TVariableInfoList& attribs,
+ TVariableInfoList& uniforms,
+ TVariableInfoList& varyings,
+ ShHashFunction64 hashFunction);
+
+ virtual void visitSymbol(TIntermSymbol*);
+ virtual bool visitAggregate(Visit, TIntermAggregate*);
+
+private:
+ TVariableInfoList& mAttribs;
+ TVariableInfoList& mUniforms;
+ TVariableInfoList& mVaryings;
+
+ bool mPointCoordAdded;
+ bool mFrontFacingAdded;
+ bool mFragCoordAdded;
+
+ ShHashFunction64 mHashFunction;
+};
+
+#endif // COMPILER_VARIABLE_INFO_H_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/VariableInfo.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorVariablePackercpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/VariablePacker.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/VariablePacker.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/VariablePacker.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,297 @@
</span><ins>+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+#include "compiler/translator/VariablePacker.h"
+
+#include <algorithm>
+#include "compiler/translator/ShHandle.h"
+
+namespace {
+int GetSortOrder(ShDataType type)
+{
+ switch (type) {
+ case SH_FLOAT_MAT4:
+ return 0;
+ case SH_FLOAT_MAT2:
+ return 1;
+ case SH_FLOAT_VEC4:
+ case SH_INT_VEC4:
+ case SH_BOOL_VEC4:
+ return 2;
+ case SH_FLOAT_MAT3:
+ return 3;
+ case SH_FLOAT_VEC3:
+ case SH_INT_VEC3:
+ case SH_BOOL_VEC3:
+ return 4;
+ case SH_FLOAT_VEC2:
+ case SH_INT_VEC2:
+ case SH_BOOL_VEC2:
+ return 5;
+ case SH_FLOAT:
+ case SH_INT:
+ case SH_BOOL:
+ case SH_SAMPLER_2D:
+ case SH_SAMPLER_CUBE:
+ case SH_SAMPLER_EXTERNAL_OES:
+ case SH_SAMPLER_2D_RECT_ARB:
+ return 6;
+ default:
+ ASSERT(false);
+ return 7;
+ }
+}
+} // namespace
+
+int VariablePacker::GetNumComponentsPerRow(ShDataType type)
+{
+ switch (type) {
+ case SH_FLOAT_MAT4:
+ case SH_FLOAT_MAT2:
+ case SH_FLOAT_VEC4:
+ case SH_INT_VEC4:
+ case SH_BOOL_VEC4:
+ return 4;
+ case SH_FLOAT_MAT3:
+ case SH_FLOAT_VEC3:
+ case SH_INT_VEC3:
+ case SH_BOOL_VEC3:
+ return 3;
+ case SH_FLOAT_VEC2:
+ case SH_INT_VEC2:
+ case SH_BOOL_VEC2:
+ return 2;
+ case SH_FLOAT:
+ case SH_INT:
+ case SH_BOOL:
+ case SH_SAMPLER_2D:
+ case SH_SAMPLER_CUBE:
+ case SH_SAMPLER_EXTERNAL_OES:
+ case SH_SAMPLER_2D_RECT_ARB:
+ return 1;
+ default:
+ ASSERT(false);
+ return 5;
+ }
+}
+
+int VariablePacker::GetNumRows(ShDataType type)
+{
+ switch (type) {
+ case SH_FLOAT_MAT4:
+ return 4;
+ case SH_FLOAT_MAT3:
+ return 3;
+ case SH_FLOAT_MAT2:
+ return 2;
+ case SH_FLOAT_VEC4:
+ case SH_INT_VEC4:
+ case SH_BOOL_VEC4:
+ case SH_FLOAT_VEC3:
+ case SH_INT_VEC3:
+ case SH_BOOL_VEC3:
+ case SH_FLOAT_VEC2:
+ case SH_INT_VEC2:
+ case SH_BOOL_VEC2:
+ case SH_FLOAT:
+ case SH_INT:
+ case SH_BOOL:
+ case SH_SAMPLER_2D:
+ case SH_SAMPLER_CUBE:
+ case SH_SAMPLER_EXTERNAL_OES:
+ case SH_SAMPLER_2D_RECT_ARB:
+ return 1;
+ default:
+ ASSERT(false);
+ return 100000;
+ }
+}
+
+struct TVariableInfoComparer {
+ bool operator()(const TVariableInfo& lhs, const TVariableInfo& rhs) const
+ {
+ int lhsSortOrder = GetSortOrder(lhs.type);
+ int rhsSortOrder = GetSortOrder(rhs.type);
+ if (lhsSortOrder != rhsSortOrder) {
+ return lhsSortOrder < rhsSortOrder;
+ }
+ // Sort by largest first.
+ return lhs.size > rhs.size;
+ }
+};
+
+unsigned VariablePacker::makeColumnFlags(int column, int numComponentsPerRow)
+{
+ return ((kColumnMask << (kNumColumns - numComponentsPerRow)) &
+ kColumnMask) >> column;
+}
+
+void VariablePacker::fillColumns(int topRow, int numRows, int column, int numComponentsPerRow)
+{
+ unsigned columnFlags = makeColumnFlags(column, numComponentsPerRow);
+ for (int r = 0; r < numRows; ++r) {
+ int row = topRow + r;
+ ASSERT((rows_[row] & columnFlags) == 0);
+ rows_[row] |= columnFlags;
+ }
+}
+
+bool VariablePacker::searchColumn(int column, int numRows, int* destRow, int* destSize)
+{
+ ASSERT(destRow);
+
+ for (; topNonFullRow_ < maxRows_ && rows_[topNonFullRow_] == kColumnMask;
+ ++topNonFullRow_) {
+ }
+
+ for (; bottomNonFullRow_ >= 0 && rows_[bottomNonFullRow_] == kColumnMask;
+ --bottomNonFullRow_) {
+ }
+
+ if (bottomNonFullRow_ - topNonFullRow_ + 1 < numRows) {
+ return false;
+ }
+
+ unsigned columnFlags = makeColumnFlags(column, 1);
+ int topGoodRow = 0;
+ int smallestGoodTop = -1;
+ int smallestGoodSize = maxRows_ + 1;
+ int bottomRow = bottomNonFullRow_ + 1;
+ bool found = false;
+ for (int row = topNonFullRow_; row <= bottomRow; ++row) {
+ bool rowEmpty = row < bottomRow ? ((rows_[row] & columnFlags) == 0) : false;
+ if (rowEmpty) {
+ if (!found) {
+ topGoodRow = row;
+ found = true;
+ }
+ } else {
+ if (found) {
+ int size = row - topGoodRow;
+ if (size >= numRows && size < smallestGoodSize) {
+ smallestGoodSize = size;
+ smallestGoodTop = topGoodRow;
+ }
+ }
+ found = false;
+ }
+ }
+ if (smallestGoodTop < 0) {
+ return false;
+ }
+
+ *destRow = smallestGoodTop;
+ if (destSize) {
+ *destSize = smallestGoodSize;
+ }
+ return true;
+}
+
+bool VariablePacker::CheckVariablesWithinPackingLimits(int maxVectors, const TVariableInfoList& in_variables)
+{
+ ASSERT(maxVectors > 0);
+ maxRows_ = maxVectors;
+ topNonFullRow_ = 0;
+ bottomNonFullRow_ = maxRows_ - 1;
+ TVariableInfoList variables(in_variables);
+
+ // As per GLSL 1.017 Appendix A, Section 7 variables are packed in specific
+ // order by type, then by size of array, largest first.
+ std::sort(variables.begin(), variables.end(), TVariableInfoComparer());
+ rows_.clear();
+ rows_.resize(maxVectors, 0);
+
+ // Packs the 4 column variables.
+ size_t ii = 0;
+ for (; ii < variables.size(); ++ii) {
+ const TVariableInfo& variable = variables[ii];
+ if (GetNumComponentsPerRow(variable.type) != 4) {
+ break;
+ }
+ topNonFullRow_ += GetNumRows(variable.type) * variable.size;
+ }
+
+ if (topNonFullRow_ > maxRows_) {
+ return false;
+ }
+
+ // Packs the 3 column variables.
+ int num3ColumnRows = 0;
+ for (; ii < variables.size(); ++ii) {
+ const TVariableInfo& variable = variables[ii];
+ if (GetNumComponentsPerRow(variable.type) != 3) {
+ break;
+ }
+ num3ColumnRows += GetNumRows(variable.type) * variable.size;
+ }
+
+ if (topNonFullRow_ + num3ColumnRows > maxRows_) {
+ return false;
+ }
+
+ fillColumns(topNonFullRow_, num3ColumnRows, 0, 3);
+
+ // Packs the 2 column variables.
+ int top2ColumnRow = topNonFullRow_ + num3ColumnRows;
+ int twoColumnRowsAvailable = maxRows_ - top2ColumnRow;
+ int rowsAvailableInColumns01 = twoColumnRowsAvailable;
+ int rowsAvailableInColumns23 = twoColumnRowsAvailable;
+ for (; ii < variables.size(); ++ii) {
+ const TVariableInfo& variable = variables[ii];
+ if (GetNumComponentsPerRow(variable.type) != 2) {
+ break;
+ }
+ int numRows = GetNumRows(variable.type) * variable.size;
+ if (numRows <= rowsAvailableInColumns01) {
+ rowsAvailableInColumns01 -= numRows;
+ } else if (numRows <= rowsAvailableInColumns23) {
+ rowsAvailableInColumns23 -= numRows;
+ } else {
+ return false;
+ }
+ }
+
+ int numRowsUsedInColumns01 =
+ twoColumnRowsAvailable - rowsAvailableInColumns01;
+ int numRowsUsedInColumns23 =
+ twoColumnRowsAvailable - rowsAvailableInColumns23;
+ fillColumns(top2ColumnRow, numRowsUsedInColumns01, 0, 2);
+ fillColumns(maxRows_ - numRowsUsedInColumns23, numRowsUsedInColumns23,
+ 2, 2);
+
+ // Packs the 1 column variables.
+ for (; ii < variables.size(); ++ii) {
+ const TVariableInfo& variable = variables[ii];
+ ASSERT(1 == GetNumComponentsPerRow(variable.type));
+ int numRows = GetNumRows(variable.type) * variable.size;
+ int smallestColumn = -1;
+ int smallestSize = maxRows_ + 1;
+ int topRow = -1;
+ for (int column = 0; column < kNumColumns; ++column) {
+ int row = 0;
+ int size = 0;
+ if (searchColumn(column, numRows, &row, &size)) {
+ if (size < smallestSize) {
+ smallestSize = size;
+ smallestColumn = column;
+ topRow = row;
+ }
+ }
+ }
+
+ if (smallestColumn < 0) {
+ return false;
+ }
+
+ fillColumns(topRow, numRows, smallestColumn, 1);
+ }
+
+ ASSERT(variables.size() == ii);
+
+ return true;
+}
+
+
+
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/VariablePacker.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorVariablePackerh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/VariablePacker.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/VariablePacker.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/VariablePacker.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,41 @@
</span><ins>+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef _VARIABLEPACKER_INCLUDED_
+#define _VARIABLEPACKER_INCLUDED_
+
+#include <vector>
+#include "compiler/translator/ShHandle.h"
+
+class VariablePacker {
+ public:
+ // Returns true if the passed in variables pack in maxVectors following
+ // the packing rules from the GLSL 1.017 spec, Appendix A, section 7.
+ bool CheckVariablesWithinPackingLimits(
+ int maxVectors,
+ const TVariableInfoList& in_variables);
+
+ // Gets how many components in a row a data type takes.
+ static int GetNumComponentsPerRow(ShDataType type);
+
+ // Gets how many rows a data type takes.
+ static int GetNumRows(ShDataType type);
+
+ private:
+ static const int kNumColumns = 4;
+ static const unsigned kColumnMask = (1 << kNumColumns) - 1;
+
+ unsigned makeColumnFlags(int column, int numComponentsPerRow);
+ void fillColumns(int topRow, int numRows, int column, int numComponentsPerRow);
+ bool searchColumn(int column, int numRows, int* destRow, int* destSize);
+
+ int topNonFullRow_;
+ int bottomNonFullRow_;
+ int maxRows_;
+ std::vector<unsigned> rows_;
+};
+
+#endif // _VARIABLEPACKER_INCLUDED_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/VariablePacker.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorVersionGLSLcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/VersionGLSL.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/VersionGLSL.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/VersionGLSL.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,140 @@
</span><ins>+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/VersionGLSL.h"
+
+static const int GLSL_VERSION_110 = 110;
+static const int GLSL_VERSION_120 = 120;
+
+// We need to scan for the following:
+// 1. "invariant" keyword: This can occur in both - vertex and fragment shaders
+// but only at the global scope.
+// 2. "gl_PointCoord" built-in variable: This can only occur in fragment shader
+// but inside any scope.
+// 3. Call to a matrix constructor with another matrix as argument.
+// (These constructors were reserved in GLSL version 1.10.)
+// 4. Arrays as "out" function parameters.
+// GLSL spec section 6.1.1: "When calling a function, expressions that do
+// not evaluate to l-values cannot be passed to parameters declared as
+// out or inout."
+// GLSL 1.1 section 5.8: "Other binary or unary expressions,
+// non-dereferenced arrays, function names, swizzles with repeated fields,
+// and constants cannot be l-values."
+// 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(ShShaderType type)
+ : mShaderType(type),
+ mVersion(GLSL_VERSION_110)
+{
+}
+
+void TVersionGLSL::visitSymbol(TIntermSymbol* node)
+{
+ if (node->getSymbol() == "gl_PointCoord")
+ updateVersion(GLSL_VERSION_120);
+}
+
+void TVersionGLSL::visitConstantUnion(TIntermConstantUnion*)
+{
+}
+
+bool TVersionGLSL::visitBinary(Visit, TIntermBinary*)
+{
+ return true;
+}
+
+bool TVersionGLSL::visitUnary(Visit, TIntermUnary*)
+{
+ return true;
+}
+
+bool TVersionGLSL::visitSelection(Visit, TIntermSelection*)
+{
+ return true;
+}
+
+bool TVersionGLSL::visitAggregate(Visit, TIntermAggregate* node)
+{
+ bool visitChildren = true;
+
+ switch (node->getOp()) {
+ case EOpSequence:
+ // We need to visit sequence children to get to global or inner scope.
+ visitChildren = true;
+ break;
+ case EOpDeclaration: {
+ const TIntermSequence& sequence = node->getSequence();
+ TQualifier qualifier = sequence.front()->getAsTyped()->getQualifier();
+ if ((qualifier == EvqInvariantVaryingIn) ||
+ (qualifier == EvqInvariantVaryingOut)) {
+ updateVersion(GLSL_VERSION_120);
+ }
+ break;
+ }
+ case EOpParameters: {
+ const TIntermSequence& params = node->getSequence();
+ for (TIntermSequence::const_iterator iter = params.begin();
+ iter != params.end(); ++iter)
+ {
+ const TIntermTyped* param = (*iter)->getAsTyped();
+ if (param->isArray())
+ {
+ TQualifier qualifier = param->getQualifier();
+ if ((qualifier == EvqOut) || (qualifier == EvqInOut))
+ {
+ updateVersion(GLSL_VERSION_120);
+ break;
+ }
+ }
+ }
+ // Fully processed. No need to visit children.
+ visitChildren = false;
+ break;
+ }
+ case EOpConstructMat2:
+ case EOpConstructMat3:
+ case EOpConstructMat4: {
+ const TIntermSequence& sequence = node->getSequence();
+ if (sequence.size() == 1) {
+ TIntermTyped* typed = sequence.front()->getAsTyped();
+ if (typed && typed->isMatrix()) {
+ updateVersion(GLSL_VERSION_120);
+ }
+ }
+ break;
+ }
+
+ default: break;
+ }
+
+ return visitChildren;
+}
+
+bool TVersionGLSL::visitLoop(Visit, TIntermLoop*)
+{
+ return true;
+}
+
+bool TVersionGLSL::visitBranch(Visit, TIntermBranch*)
+{
+ return true;
+}
+
+void TVersionGLSL::updateVersion(int version)
+{
+ mVersion = std::max(version, mVersion);
+}
+
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/VersionGLSL.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorVersionGLSLh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/VersionGLSL.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/VersionGLSL.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/VersionGLSL.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,56 @@
</span><ins>+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_VERSIONGLSL_H_
+#define COMPILER_VERSIONGLSL_H_
+
+#include "GLSLANG/ShaderLang.h"
+#include "compiler/translator/intermediate.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:
+// - #version and #extension to declare version and extensions.
+// - built-in functions refract, exp, and log.
+// - updated step() to compare x < edge instead of x <= edge.
+// GLSL 1.2 which is mandated by OpenGL 2.1 provides:
+// - many changes to reduce differences when compared to the ES specification.
+// - invariant keyword and its support.
+// - c++ style name hiding rules.
+// - built-in variable gl_PointCoord for fragment shaders.
+// - matrix constructors taking matrix as argument.
+// - array as "out" function parameters
+//
+class TVersionGLSL : public TIntermTraverser {
+public:
+ TVersionGLSL(ShShaderType type);
+
+ // Returns 120 if the following is used the shader:
+ // - "invariant",
+ // - "gl_PointCoord",
+ // - matrix/matrix constructors
+ // - array "out" parameters
+ // Else 110 is returned.
+ int getVersion() { return mVersion; }
+
+ virtual void visitSymbol(TIntermSymbol*);
+ virtual void visitConstantUnion(TIntermConstantUnion*);
+ virtual bool visitBinary(Visit, TIntermBinary*);
+ virtual bool visitUnary(Visit, TIntermUnary*);
+ virtual bool visitSelection(Visit, TIntermSelection*);
+ virtual bool visitAggregate(Visit, TIntermAggregate*);
+ virtual bool visitLoop(Visit, TIntermLoop*);
+ virtual bool visitBranch(Visit, TIntermBranch*);
+
+protected:
+ void updateVersion(int version);
+
+private:
+ ShShaderType mShaderType;
+ int mVersion;
+};
+
+#endif // COMPILER_VERSIONGLSL_H_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/VersionGLSL.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorcompilerdebugcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/compilerdebug.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/compilerdebug.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/compilerdebug.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,37 @@
</span><ins>+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// debug.cpp: Debugging utilities.
+
+#include "compiler/translator/compilerdebug.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+
+#include "compiler/translator/InitializeParseContext.h"
+#include "compiler/translator/ParseContext.h"
+
+#ifdef TRACE_ENABLED
+static const int kTraceBufferLen = 1024;
+
+extern "C" {
+void Trace(const char *format, ...) {
+ if (!format) return;
+
+ TParseContext* parseContext = GetGlobalParseContext();
+ if (parseContext) {
+ char buf[kTraceBufferLen];
+ va_list args;
+ va_start(args, format);
+ vsnprintf(buf, kTraceBufferLen, format, args);
+ va_end(args);
+
+ parseContext->trace(buf);
+ }
+}
+} // extern "C"
+#endif // TRACE_ENABLED
+
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/compilerdebug.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorcompilerdebugh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/compilerdebug.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/compilerdebug.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/compilerdebug.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,53 @@
</span><ins>+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// debug.h: Debugging utilities.
+
+#ifndef COMPILER_DEBUG_H_
+#define COMPILER_DEBUG_H_
+
+#include <assert.h>
+
+#ifdef _DEBUG
+#define TRACE_ENABLED // define to enable debug message tracing
+#endif // _DEBUG
+
+// Outputs text to the debug log
+#ifdef TRACE_ENABLED
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+void Trace(const char* format, ...);
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#else // TRACE_ENABLED
+
+#define Trace(...) ((void)0)
+
+#endif // TRACE_ENABLED
+
+// A macro asserting a condition and outputting failures to the debug log
+#define ASSERT(expression) do { \
+ if(!(expression)) \
+ Trace("Assert failed: %s(%d): "#expression"\n", __FUNCTION__, __LINE__); \
+ assert(expression); \
+} while(0)
+
+#define UNIMPLEMENTED() do { \
+ Trace("Unimplemented invoked: %s(%d)\n", __FUNCTION__, __LINE__); \
+ assert(false); \
+} while(0)
+
+#define UNREACHABLE() do { \
+ Trace("Unreachable reached: %s(%d)\n", __FUNCTION__, __LINE__); \
+ assert(false); \
+} while(0)
+
+#endif // COMPILER_DEBUG_H_
+
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/compilerdebug.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatordepgraphDependencyGraphcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/depgraph/DependencyGraph.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/depgraph/DependencyGraph.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/depgraph/DependencyGraph.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,97 @@
</span><ins>+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#pragma warning(disable: 4718)
+
+#include "compiler/translator/depgraph/DependencyGraph.h"
+#include "compiler/translator/depgraph/DependencyGraphBuilder.h"
+
+TDependencyGraph::TDependencyGraph(TIntermNode* intermNode)
+{
+ TDependencyGraphBuilder::build(intermNode, this);
+}
+
+TDependencyGraph::~TDependencyGraph()
+{
+ for (TGraphNodeVector::const_iterator iter = mAllNodes.begin(); iter != mAllNodes.end(); ++iter)
+ {
+ TGraphNode* node = *iter;
+ delete node;
+ }
+}
+
+TGraphArgument* TDependencyGraph::createArgument(TIntermAggregate* intermFunctionCall,
+ int argumentNumber)
+{
+ TGraphArgument* argument = new TGraphArgument(intermFunctionCall, argumentNumber);
+ mAllNodes.push_back(argument);
+ return argument;
+}
+
+TGraphFunctionCall* TDependencyGraph::createFunctionCall(TIntermAggregate* intermFunctionCall)
+{
+ TGraphFunctionCall* functionCall = new TGraphFunctionCall(intermFunctionCall);
+ mAllNodes.push_back(functionCall);
+ if (functionCall->getIntermFunctionCall()->isUserDefined())
+ mUserDefinedFunctionCalls.push_back(functionCall);
+ return functionCall;
+}
+
+TGraphSymbol* TDependencyGraph::getOrCreateSymbol(TIntermSymbol* intermSymbol)
+{
+ TSymbolIdMap::const_iterator iter = mSymbolIdMap.find(intermSymbol->getId());
+
+ TGraphSymbol* symbol = NULL;
+
+ if (iter != mSymbolIdMap.end()) {
+ TSymbolIdPair pair = *iter;
+ symbol = pair.second;
+ } else {
+ symbol = new TGraphSymbol(intermSymbol);
+ mAllNodes.push_back(symbol);
+
+ TSymbolIdPair pair(intermSymbol->getId(), symbol);
+ mSymbolIdMap.insert(pair);
+
+ // We save all sampler symbols in a collection, so we can start graph traversals from them quickly.
+ if (IsSampler(intermSymbol->getBasicType()))
+ mSamplerSymbols.push_back(symbol);
+ }
+
+ return symbol;
+}
+
+TGraphSelection* TDependencyGraph::createSelection(TIntermSelection* intermSelection)
+{
+ TGraphSelection* selection = new TGraphSelection(intermSelection);
+ mAllNodes.push_back(selection);
+ return selection;
+}
+
+TGraphLoop* TDependencyGraph::createLoop(TIntermLoop* intermLoop)
+{
+ TGraphLoop* loop = new TGraphLoop(intermLoop);
+ mAllNodes.push_back(loop);
+ return loop;
+}
+
+TGraphLogicalOp* TDependencyGraph::createLogicalOp(TIntermBinary* intermLogicalOp)
+{
+ TGraphLogicalOp* logicalOp = new TGraphLogicalOp(intermLogicalOp);
+ mAllNodes.push_back(logicalOp);
+ return logicalOp;
+}
+
+const char* TGraphLogicalOp::getOpString() const
+{
+ const char* opString = NULL;
+ switch (getIntermLogicalOp()->getOp()) {
+ case EOpLogicalAnd: opString = "and"; break;
+ case EOpLogicalOr: opString = "or"; break;
+ default: opString = "unknown"; break;
+ }
+ return opString;
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/depgraph/DependencyGraph.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatordepgraphDependencyGraphh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/depgraph/DependencyGraph.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/depgraph/DependencyGraph.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/depgraph/DependencyGraph.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,212 @@
</span><ins>+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_H
+#define COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_H
+
+#include "compiler/translator/intermediate.h"
+
+#include <set>
+#include <stack>
+
+class TGraphNode;
+class TGraphParentNode;
+class TGraphArgument;
+class TGraphFunctionCall;
+class TGraphSymbol;
+class TGraphSelection;
+class TGraphLoop;
+class TGraphLogicalOp;
+class TDependencyGraphTraverser;
+class TDependencyGraphOutput;
+
+typedef std::set<TGraphNode*> TGraphNodeSet;
+typedef std::vector<TGraphNode*> TGraphNodeVector;
+typedef std::vector<TGraphSymbol*> TGraphSymbolVector;
+typedef std::vector<TGraphFunctionCall*> TFunctionCallVector;
+
+//
+// Base class for all dependency graph nodes.
+//
+class TGraphNode {
+public:
+ TGraphNode(TIntermNode* node) : intermNode(node) {}
+ virtual ~TGraphNode() {}
+ virtual void traverse(TDependencyGraphTraverser* graphTraverser);
+protected:
+ TIntermNode* intermNode;
+};
+
+//
+// Base class for dependency graph nodes that may have children.
+//
+class TGraphParentNode : public TGraphNode {
+public:
+ TGraphParentNode(TIntermNode* node) : TGraphNode(node) {}
+ virtual ~TGraphParentNode() {}
+ void addDependentNode(TGraphNode* node) { if (node != this) mDependentNodes.insert(node); }
+ virtual void traverse(TDependencyGraphTraverser* graphTraverser);
+private:
+ TGraphNodeSet mDependentNodes;
+};
+
+//
+// Handle function call arguments.
+//
+class TGraphArgument : public TGraphParentNode {
+public:
+ TGraphArgument(TIntermAggregate* intermFunctionCall, int argumentNumber)
+ : TGraphParentNode(intermFunctionCall)
+ , mArgumentNumber(argumentNumber) {}
+ virtual ~TGraphArgument() {}
+ const TIntermAggregate* getIntermFunctionCall() const { return intermNode->getAsAggregate(); }
+ int getArgumentNumber() const { return mArgumentNumber; }
+ virtual void traverse(TDependencyGraphTraverser* graphTraverser);
+private:
+ int mArgumentNumber;
+};
+
+//
+// Handle function calls.
+//
+class TGraphFunctionCall : public TGraphParentNode {
+public:
+ TGraphFunctionCall(TIntermAggregate* intermFunctionCall)
+ : TGraphParentNode(intermFunctionCall) {}
+ virtual ~TGraphFunctionCall() {}
+ const TIntermAggregate* getIntermFunctionCall() const { return intermNode->getAsAggregate(); }
+ virtual void traverse(TDependencyGraphTraverser* graphTraverser);
+};
+
+//
+// Handle symbols.
+//
+class TGraphSymbol : public TGraphParentNode {
+public:
+ TGraphSymbol(TIntermSymbol* intermSymbol) : TGraphParentNode(intermSymbol) {}
+ virtual ~TGraphSymbol() {}
+ const TIntermSymbol* getIntermSymbol() const { return intermNode->getAsSymbolNode(); }
+ virtual void traverse(TDependencyGraphTraverser* graphTraverser);
+};
+
+//
+// Handle if statements and ternary operators.
+//
+class TGraphSelection : public TGraphNode {
+public:
+ TGraphSelection(TIntermSelection* intermSelection) : TGraphNode(intermSelection) {}
+ virtual ~TGraphSelection() {}
+ const TIntermSelection* getIntermSelection() const { return intermNode->getAsSelectionNode(); }
+ virtual void traverse(TDependencyGraphTraverser* graphTraverser);
+};
+
+//
+// Handle for, do-while, and while loops.
+//
+class TGraphLoop : public TGraphNode {
+public:
+ TGraphLoop(TIntermLoop* intermLoop) : TGraphNode(intermLoop) {}
+ virtual ~TGraphLoop() {}
+ const TIntermLoop* getIntermLoop() const { return intermNode->getAsLoopNode(); }
+ virtual void traverse(TDependencyGraphTraverser* graphTraverser);
+};
+
+//
+// Handle logical and, or.
+//
+class TGraphLogicalOp : public TGraphNode {
+public:
+ TGraphLogicalOp(TIntermBinary* intermLogicalOp) : TGraphNode(intermLogicalOp) {}
+ virtual ~TGraphLogicalOp() {}
+ const TIntermBinary* getIntermLogicalOp() const { return intermNode->getAsBinaryNode(); }
+ const char* getOpString() const;
+ virtual void traverse(TDependencyGraphTraverser* graphTraverser);
+};
+
+//
+// A dependency graph of symbols, function calls, conditions etc.
+//
+// This class provides an interface to the entry points of the dependency graph.
+//
+// Dependency graph nodes should be created by using one of the provided "create..." methods.
+// This class (and nobody else) manages the memory of the created nodes.
+// Nodes may not be removed after being added, so all created nodes will exist while the
+// TDependencyGraph instance exists.
+//
+class TDependencyGraph {
+public:
+ TDependencyGraph(TIntermNode* intermNode);
+ ~TDependencyGraph();
+ TGraphNodeVector::const_iterator begin() const { return mAllNodes.begin(); }
+ TGraphNodeVector::const_iterator end() const { return mAllNodes.end(); }
+
+ TGraphSymbolVector::const_iterator beginSamplerSymbols() const
+ {
+ return mSamplerSymbols.begin();
+ }
+
+ TGraphSymbolVector::const_iterator endSamplerSymbols() const
+ {
+ return mSamplerSymbols.end();
+ }
+
+ TFunctionCallVector::const_iterator beginUserDefinedFunctionCalls() const
+ {
+ return mUserDefinedFunctionCalls.begin();
+ }
+
+ TFunctionCallVector::const_iterator endUserDefinedFunctionCalls() const
+ {
+ return mUserDefinedFunctionCalls.end();
+ }
+
+ TGraphArgument* createArgument(TIntermAggregate* intermFunctionCall, int argumentNumber);
+ TGraphFunctionCall* createFunctionCall(TIntermAggregate* intermFunctionCall);
+ TGraphSymbol* getOrCreateSymbol(TIntermSymbol* intermSymbol);
+ TGraphSelection* createSelection(TIntermSelection* intermSelection);
+ TGraphLoop* createLoop(TIntermLoop* intermLoop);
+ TGraphLogicalOp* createLogicalOp(TIntermBinary* intermLogicalOp);
+private:
+ typedef TMap<int, TGraphSymbol*> TSymbolIdMap;
+ typedef std::pair<int, TGraphSymbol*> TSymbolIdPair;
+
+ TGraphNodeVector mAllNodes;
+ TGraphSymbolVector mSamplerSymbols;
+ TFunctionCallVector mUserDefinedFunctionCalls;
+ TSymbolIdMap mSymbolIdMap;
+};
+
+//
+// For traversing the dependency graph. Users should derive from this,
+// put their traversal specific data in it, and then pass it to a
+// traverse method.
+//
+// When using this, just fill in the methods for nodes you want visited.
+//
+class TDependencyGraphTraverser {
+public:
+ TDependencyGraphTraverser() : mDepth(0) {}
+
+ virtual void visitSymbol(TGraphSymbol* symbol) {};
+ virtual void visitArgument(TGraphArgument* selection) {};
+ virtual void visitFunctionCall(TGraphFunctionCall* functionCall) {};
+ virtual void visitSelection(TGraphSelection* selection) {};
+ virtual void visitLoop(TGraphLoop* loop) {};
+ virtual void visitLogicalOp(TGraphLogicalOp* logicalOp) {};
+
+ int getDepth() const { return mDepth; }
+ void incrementDepth() { ++mDepth; }
+ void decrementDepth() { --mDepth; }
+
+ void clearVisited() { mVisited.clear(); }
+ void markVisited(TGraphNode* node) { mVisited.insert(node); }
+ bool isVisited(TGraphNode* node) const { return mVisited.find(node) != mVisited.end(); }
+private:
+ int mDepth;
+ TGraphNodeSet mVisited;
+};
+
+#endif
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/depgraph/DependencyGraph.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatordepgraphDependencyGraphBuildercpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/depgraph/DependencyGraphBuilder.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/depgraph/DependencyGraphBuilder.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/depgraph/DependencyGraphBuilder.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,227 @@
</span><ins>+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/depgraph/DependencyGraphBuilder.h"
+
+void TDependencyGraphBuilder::build(TIntermNode* node, TDependencyGraph* graph)
+{
+ TDependencyGraphBuilder builder(graph);
+ builder.build(node);
+}
+
+bool TDependencyGraphBuilder::visitAggregate(Visit visit, TIntermAggregate* intermAggregate)
+{
+ switch (intermAggregate->getOp()) {
+ case EOpFunction: visitFunctionDefinition(intermAggregate); break;
+ case EOpFunctionCall: visitFunctionCall(intermAggregate); break;
+ default: visitAggregateChildren(intermAggregate); break;
+ }
+
+ return false;
+}
+
+void TDependencyGraphBuilder::visitFunctionDefinition(TIntermAggregate* intermAggregate)
+{
+ // Currently, we do not support user defined functions.
+ if (intermAggregate->getName() != "main(")
+ return;
+
+ visitAggregateChildren(intermAggregate);
+}
+
+// Takes an expression like "f(x)" and creates a dependency graph like
+// "x -> argument 0 -> function call".
+void TDependencyGraphBuilder::visitFunctionCall(TIntermAggregate* intermFunctionCall)
+{
+ TGraphFunctionCall* functionCall = mGraph->createFunctionCall(intermFunctionCall);
+
+ // Run through the function call arguments.
+ int argumentNumber = 0;
+ TIntermSequence& intermArguments = intermFunctionCall->getSequence();
+ for (TIntermSequence::const_iterator iter = intermArguments.begin();
+ iter != intermArguments.end();
+ ++iter, ++argumentNumber)
+ {
+ TNodeSetMaintainer nodeSetMaintainer(this);
+
+ TIntermNode* intermArgument = *iter;
+ intermArgument->traverse(this);
+
+ if (TParentNodeSet* argumentNodes = mNodeSets.getTopSet()) {
+ TGraphArgument* argument = mGraph->createArgument(intermFunctionCall, argumentNumber);
+ connectMultipleNodesToSingleNode(argumentNodes, argument);
+ argument->addDependentNode(functionCall);
+ }
+ }
+
+ // Push the leftmost symbol of this function call into the current set of dependent symbols to
+ // represent the result of this function call.
+ // Thus, an expression like "y = f(x)" will yield a dependency graph like
+ // "x -> argument 0 -> function call -> y".
+ // This line essentially passes the function call node back up to an earlier visitAssignment
+ // call, which will create the connection "function call -> y".
+ mNodeSets.insertIntoTopSet(functionCall);
+}
+
+void TDependencyGraphBuilder::visitAggregateChildren(TIntermAggregate* intermAggregate)
+{
+ TIntermSequence& sequence = intermAggregate->getSequence();
+ for(TIntermSequence::const_iterator iter = sequence.begin(); iter != sequence.end(); ++iter)
+ {
+ TIntermNode* intermChild = *iter;
+ intermChild->traverse(this);
+ }
+}
+
+void TDependencyGraphBuilder::visitSymbol(TIntermSymbol* intermSymbol)
+{
+ // Push this symbol into the set of dependent symbols for the current assignment or condition
+ // that we are traversing.
+ TGraphSymbol* symbol = mGraph->getOrCreateSymbol(intermSymbol);
+ mNodeSets.insertIntoTopSet(symbol);
+
+ // If this symbol is the current leftmost symbol under an assignment, replace the previous
+ // leftmost symbol with this symbol.
+ if (!mLeftmostSymbols.empty() && mLeftmostSymbols.top() != &mRightSubtree) {
+ mLeftmostSymbols.pop();
+ mLeftmostSymbols.push(symbol);
+ }
+}
+
+bool TDependencyGraphBuilder::visitBinary(Visit visit, TIntermBinary* intermBinary)
+{
+ TOperator op = intermBinary->getOp();
+ if (op == EOpInitialize || intermBinary->isAssignment())
+ visitAssignment(intermBinary);
+ else if (op == EOpLogicalAnd || op == EOpLogicalOr)
+ visitLogicalOp(intermBinary);
+ else
+ visitBinaryChildren(intermBinary);
+
+ return false;
+}
+
+void TDependencyGraphBuilder::visitAssignment(TIntermBinary* intermAssignment)
+{
+ TIntermTyped* intermLeft = intermAssignment->getLeft();
+ if (!intermLeft)
+ return;
+
+ TGraphSymbol* leftmostSymbol = NULL;
+
+ {
+ TNodeSetMaintainer nodeSetMaintainer(this);
+
+ {
+ TLeftmostSymbolMaintainer leftmostSymbolMaintainer(this, mLeftSubtree);
+ intermLeft->traverse(this);
+ leftmostSymbol = mLeftmostSymbols.top();
+
+ // After traversing the left subtree of this assignment, we should have found a real
+ // leftmost symbol, and the leftmost symbol should not be a placeholder.
+ ASSERT(leftmostSymbol != &mLeftSubtree);
+ ASSERT(leftmostSymbol != &mRightSubtree);
+ }
+
+ if (TIntermTyped* intermRight = intermAssignment->getRight()) {
+ TLeftmostSymbolMaintainer leftmostSymbolMaintainer(this, mRightSubtree);
+ intermRight->traverse(this);
+ }
+
+ if (TParentNodeSet* assignmentNodes = mNodeSets.getTopSet())
+ connectMultipleNodesToSingleNode(assignmentNodes, leftmostSymbol);
+ }
+
+ // Push the leftmost symbol of this assignment into the current set of dependent symbols to
+ // represent the result of this assignment.
+ // An expression like "a = (b = c)" will yield a dependency graph like "c -> b -> a".
+ // This line essentially passes the leftmost symbol of the nested assignment ("b" in this
+ // example) back up to the earlier visitAssignment call for the outer assignment, which will
+ // create the connection "b -> a".
+ mNodeSets.insertIntoTopSet(leftmostSymbol);
+}
+
+void TDependencyGraphBuilder::visitLogicalOp(TIntermBinary* intermLogicalOp)
+{
+ if (TIntermTyped* intermLeft = intermLogicalOp->getLeft()) {
+ TNodeSetPropagatingMaintainer nodeSetMaintainer(this);
+
+ intermLeft->traverse(this);
+ if (TParentNodeSet* leftNodes = mNodeSets.getTopSet()) {
+ TGraphLogicalOp* logicalOp = mGraph->createLogicalOp(intermLogicalOp);
+ connectMultipleNodesToSingleNode(leftNodes, logicalOp);
+ }
+ }
+
+ if (TIntermTyped* intermRight = intermLogicalOp->getRight()) {
+ TLeftmostSymbolMaintainer leftmostSymbolMaintainer(this, mRightSubtree);
+ intermRight->traverse(this);
+ }
+}
+
+void TDependencyGraphBuilder::visitBinaryChildren(TIntermBinary* intermBinary)
+{
+ if (TIntermTyped* intermLeft = intermBinary->getLeft())
+ intermLeft->traverse(this);
+
+ if (TIntermTyped* intermRight = intermBinary->getRight()) {
+ TLeftmostSymbolMaintainer leftmostSymbolMaintainer(this, mRightSubtree);
+ intermRight->traverse(this);
+ }
+}
+
+bool TDependencyGraphBuilder::visitSelection(Visit visit, TIntermSelection* intermSelection)
+{
+ if (TIntermNode* intermCondition = intermSelection->getCondition()) {
+ TNodeSetMaintainer nodeSetMaintainer(this);
+
+ intermCondition->traverse(this);
+ if (TParentNodeSet* conditionNodes = mNodeSets.getTopSet()) {
+ TGraphSelection* selection = mGraph->createSelection(intermSelection);
+ connectMultipleNodesToSingleNode(conditionNodes, selection);
+ }
+ }
+
+ if (TIntermNode* intermTrueBlock = intermSelection->getTrueBlock())
+ intermTrueBlock->traverse(this);
+
+ if (TIntermNode* intermFalseBlock = intermSelection->getFalseBlock())
+ intermFalseBlock->traverse(this);
+
+ return false;
+}
+
+bool TDependencyGraphBuilder::visitLoop(Visit visit, TIntermLoop* intermLoop)
+{
+ if (TIntermTyped* intermCondition = intermLoop->getCondition()) {
+ TNodeSetMaintainer nodeSetMaintainer(this);
+
+ intermCondition->traverse(this);
+ if (TParentNodeSet* conditionNodes = mNodeSets.getTopSet()) {
+ TGraphLoop* loop = mGraph->createLoop(intermLoop);
+ connectMultipleNodesToSingleNode(conditionNodes, loop);
+ }
+ }
+
+ if (TIntermNode* intermBody = intermLoop->getBody())
+ intermBody->traverse(this);
+
+ if (TIntermTyped* intermExpression = intermLoop->getExpression())
+ intermExpression->traverse(this);
+
+ return false;
+}
+
+
+void TDependencyGraphBuilder::connectMultipleNodesToSingleNode(TParentNodeSet* nodes,
+ TGraphNode* node) const
+{
+ for (TParentNodeSet::const_iterator iter = nodes->begin(); iter != nodes->end(); ++iter)
+ {
+ TGraphParentNode* currentNode = *iter;
+ currentNode->addDependentNode(node);
+ }
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/depgraph/DependencyGraphBuilder.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatordepgraphDependencyGraphBuilderh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/depgraph/DependencyGraphBuilder.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/depgraph/DependencyGraphBuilder.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/depgraph/DependencyGraphBuilder.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,181 @@
</span><ins>+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_BUILDER_H
+#define COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_BUILDER_H
+
+#include "compiler/translator/depgraph/DependencyGraph.h"
+
+//
+// Creates a dependency graph of symbols, function calls, conditions etc. by traversing a
+// intermediate tree.
+//
+class TDependencyGraphBuilder : public TIntermTraverser {
+public:
+ static void build(TIntermNode* node, TDependencyGraph* graph);
+
+ virtual void visitSymbol(TIntermSymbol*);
+ virtual bool visitBinary(Visit visit, TIntermBinary*);
+ virtual bool visitSelection(Visit visit, TIntermSelection*);
+ virtual bool visitAggregate(Visit visit, TIntermAggregate*);
+ virtual bool visitLoop(Visit visit, TIntermLoop*);
+
+private:
+ typedef std::stack<TGraphSymbol*> TSymbolStack;
+ typedef std::set<TGraphParentNode*> TParentNodeSet;
+
+ //
+ // For collecting the dependent nodes of assignments, conditions, etc.
+ // while traversing the intermediate tree.
+ //
+ // This data structure is stack of sets. Each set contains dependency graph parent nodes.
+ //
+ class TNodeSetStack {
+ public:
+ TNodeSetStack() {};
+ ~TNodeSetStack() { clear(); }
+
+ // This should only be called after a pushSet.
+ // Returns NULL if the top set is empty.
+ TParentNodeSet* getTopSet() const
+ {
+ ASSERT(!nodeSets.empty());
+ TParentNodeSet* topSet = nodeSets.top();
+ return !topSet->empty() ? topSet : NULL;
+ }
+
+ void pushSet() { nodeSets.push(new TParentNodeSet()); }
+ void popSet()
+ {
+ ASSERT(!nodeSets.empty());
+ delete nodeSets.top();
+ nodeSets.pop();
+ }
+
+ // Pops the top set and adds its contents to the new top set.
+ // This should only be called after a pushSet.
+ // If there is no set below the top set, the top set is just deleted.
+ void popSetIntoNext()
+ {
+ ASSERT(!nodeSets.empty());
+ TParentNodeSet* oldTopSet = nodeSets.top();
+ nodeSets.pop();
+
+ if (!nodeSets.empty()) {
+ TParentNodeSet* newTopSet = nodeSets.top();
+ newTopSet->insert(oldTopSet->begin(), oldTopSet->end());
+ }
+
+ delete oldTopSet;
+ }
+
+ // Does nothing if there is no top set.
+ // This can be called when there is no top set if we are visiting
+ // symbols that are not under an assignment or condition.
+ // We don't need to track those symbols.
+ void insertIntoTopSet(TGraphParentNode* node)
+ {
+ if (nodeSets.empty())
+ return;
+
+ nodeSets.top()->insert(node);
+ }
+
+ void clear()
+ {
+ while (!nodeSets.empty())
+ popSet();
+ }
+
+ private:
+ typedef std::stack<TParentNodeSet*> TParentNodeSetStack;
+
+ TParentNodeSetStack nodeSets;
+ };
+
+ //
+ // An instance of this class pushes a new node set when instantiated.
+ // When the instance goes out of scope, it and pops the node set.
+ //
+ class TNodeSetMaintainer {
+ public:
+ TNodeSetMaintainer(TDependencyGraphBuilder* factory)
+ : sets(factory->mNodeSets) { sets.pushSet(); }
+ ~TNodeSetMaintainer() { sets.popSet(); }
+ protected:
+ TNodeSetStack& sets;
+ };
+
+ //
+ // An instance of this class pushes a new node set when instantiated.
+ // When the instance goes out of scope, it and pops the top node set and adds its contents to
+ // the new top node set.
+ //
+ class TNodeSetPropagatingMaintainer {
+ public:
+ TNodeSetPropagatingMaintainer(TDependencyGraphBuilder* factory)
+ : sets(factory->mNodeSets) { sets.pushSet(); }
+ ~TNodeSetPropagatingMaintainer() { sets.popSetIntoNext(); }
+ protected:
+ TNodeSetStack& sets;
+ };
+
+ //
+ // An instance of this class keeps track of the leftmost symbol while we're exploring an
+ // assignment.
+ // It will push the placeholder symbol kLeftSubtree when instantiated under a left subtree,
+ // and kRightSubtree under a right subtree.
+ // When it goes out of scope, it will pop the leftmost symbol at the top of the scope.
+ // During traversal, the TDependencyGraphBuilder will replace kLeftSubtree with a real symbol.
+ // kRightSubtree will never be replaced by a real symbol because we are tracking the leftmost
+ // symbol.
+ //
+ class TLeftmostSymbolMaintainer {
+ public:
+ TLeftmostSymbolMaintainer(TDependencyGraphBuilder* factory, TGraphSymbol& subtree)
+ : leftmostSymbols(factory->mLeftmostSymbols)
+ {
+ needsPlaceholderSymbol = leftmostSymbols.empty() || leftmostSymbols.top() != &subtree;
+ if (needsPlaceholderSymbol)
+ leftmostSymbols.push(&subtree);
+ }
+
+ ~TLeftmostSymbolMaintainer()
+ {
+ if (needsPlaceholderSymbol)
+ leftmostSymbols.pop();
+ }
+
+ protected:
+ TSymbolStack& leftmostSymbols;
+ bool needsPlaceholderSymbol;
+ };
+
+ TDependencyGraphBuilder(TDependencyGraph* graph)
+ : TIntermTraverser(true, false, false)
+ , mLeftSubtree(NULL)
+ , mRightSubtree(NULL)
+ , mGraph(graph) {}
+ void build(TIntermNode* intermNode) { intermNode->traverse(this); }
+
+ void connectMultipleNodesToSingleNode(TParentNodeSet* nodes, TGraphNode* node) const;
+
+ void visitAssignment(TIntermBinary*);
+ void visitLogicalOp(TIntermBinary*);
+ void visitBinaryChildren(TIntermBinary*);
+ void visitFunctionDefinition(TIntermAggregate*);
+ void visitFunctionCall(TIntermAggregate* intermFunctionCall);
+ void visitAggregateChildren(TIntermAggregate*);
+
+ TGraphSymbol mLeftSubtree;
+ TGraphSymbol mRightSubtree;
+
+ TDependencyGraph* mGraph;
+ TNodeSetStack mNodeSets;
+ TSymbolStack mLeftmostSymbols;
+};
+
+#endif // COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_BUILDER_H
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/depgraph/DependencyGraphBuilder.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatordepgraphDependencyGraphOutputcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/depgraph/DependencyGraphOutput.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/depgraph/DependencyGraphOutput.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/depgraph/DependencyGraphOutput.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,65 @@
</span><ins>+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/depgraph/DependencyGraphOutput.h"
+
+void TDependencyGraphOutput::outputIndentation()
+{
+ for (int i = 0; i < getDepth(); ++i)
+ mSink << " ";
+}
+
+void TDependencyGraphOutput::visitArgument(TGraphArgument* parameter)
+{
+ outputIndentation();
+ mSink << "argument " << parameter->getArgumentNumber() << " of call to "
+ << parameter->getIntermFunctionCall()->getName() << "\n";
+}
+
+void TDependencyGraphOutput::visitFunctionCall(TGraphFunctionCall* functionCall)
+{
+ outputIndentation();
+ mSink << "function call " << functionCall->getIntermFunctionCall()->getName() << "\n";
+}
+
+void TDependencyGraphOutput::visitSymbol(TGraphSymbol* symbol)
+{
+ outputIndentation();
+ mSink << symbol->getIntermSymbol()->getSymbol() << " (symbol id: "
+ << symbol->getIntermSymbol()->getId() << ")\n";
+}
+
+void TDependencyGraphOutput::visitSelection(TGraphSelection* selection)
+{
+ outputIndentation();
+ mSink << "selection\n";
+}
+
+void TDependencyGraphOutput::visitLoop(TGraphLoop* loop)
+{
+ outputIndentation();
+ mSink << "loop condition\n";
+}
+
+void TDependencyGraphOutput::visitLogicalOp(TGraphLogicalOp* logicalOp)
+{
+ outputIndentation();
+ mSink << "logical " << logicalOp->getOpString() << "\n";
+}
+
+void TDependencyGraphOutput::outputAllSpanningTrees(TDependencyGraph& graph)
+{
+ mSink << "\n";
+
+ for (TGraphNodeVector::const_iterator iter = graph.begin(); iter != graph.end(); ++iter)
+ {
+ TGraphNode* symbol = *iter;
+ mSink << "--- Dependency graph spanning tree ---\n";
+ clearVisited();
+ symbol->traverse(this);
+ mSink << "\n";
+ }
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/depgraph/DependencyGraphOutput.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatordepgraphDependencyGraphOutputh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/depgraph/DependencyGraphOutput.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/depgraph/DependencyGraphOutput.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/depgraph/DependencyGraphOutput.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,30 @@
</span><ins>+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_OUTPUT_H
+#define COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_OUTPUT_H
+
+#include "compiler/translator/depgraph/DependencyGraph.h"
+#include "compiler/translator/InfoSink.h"
+
+class TDependencyGraphOutput : public TDependencyGraphTraverser {
+public:
+ TDependencyGraphOutput(TInfoSinkBase& sink) : mSink(sink) {}
+ virtual void visitSymbol(TGraphSymbol* symbol);
+ virtual void visitArgument(TGraphArgument* parameter);
+ virtual void visitFunctionCall(TGraphFunctionCall* functionCall);
+ virtual void visitSelection(TGraphSelection* selection);
+ virtual void visitLoop(TGraphLoop* loop);
+ virtual void visitLogicalOp(TGraphLogicalOp* logicalOp);
+
+ void outputAllSpanningTrees(TDependencyGraph& graph);
+private:
+ void outputIndentation();
+
+ TInfoSinkBase& mSink;
+};
+
+#endif // COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_OUTPUT_H
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/depgraph/DependencyGraphOutput.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatordepgraphDependencyGraphTraversecpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/depgraph/DependencyGraphTraverse.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/depgraph/DependencyGraphTraverse.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/depgraph/DependencyGraphTraverse.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,69 @@
</span><ins>+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/depgraph/DependencyGraph.h"
+
+// These methods do a breadth-first traversal through the graph and mark visited nodes.
+
+void TGraphNode::traverse(TDependencyGraphTraverser* graphTraverser)
+{
+ graphTraverser->markVisited(this);
+}
+
+void TGraphParentNode::traverse(TDependencyGraphTraverser* graphTraverser)
+{
+ TGraphNode::traverse(graphTraverser);
+
+ graphTraverser->incrementDepth();
+
+ // Visit the parent node's children.
+ for (TGraphNodeSet::const_iterator iter = mDependentNodes.begin();
+ iter != mDependentNodes.end();
+ ++iter)
+ {
+ TGraphNode* node = *iter;
+ if (!graphTraverser->isVisited(node))
+ node->traverse(graphTraverser);
+ }
+
+ graphTraverser->decrementDepth();
+}
+
+void TGraphArgument::traverse(TDependencyGraphTraverser* graphTraverser)
+{
+ graphTraverser->visitArgument(this);
+ TGraphParentNode::traverse(graphTraverser);
+}
+
+void TGraphFunctionCall::traverse(TDependencyGraphTraverser* graphTraverser)
+{
+ graphTraverser->visitFunctionCall(this);
+ TGraphParentNode::traverse(graphTraverser);
+}
+
+void TGraphSymbol::traverse(TDependencyGraphTraverser* graphTraverser)
+{
+ graphTraverser->visitSymbol(this);
+ TGraphParentNode::traverse(graphTraverser);
+}
+
+void TGraphSelection::traverse(TDependencyGraphTraverser* graphTraverser)
+{
+ graphTraverser->visitSelection(this);
+ TGraphNode::traverse(graphTraverser);
+}
+
+void TGraphLoop::traverse(TDependencyGraphTraverser* graphTraverser)
+{
+ graphTraverser->visitLoop(this);
+ TGraphNode::traverse(graphTraverser);
+}
+
+void TGraphLogicalOp::traverse(TDependencyGraphTraverser* graphTraverser)
+{
+ graphTraverser->visitLogicalOp(this);
+ TGraphNode::traverse(graphTraverser);
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/depgraph/DependencyGraphTraverse.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorgenerate_parsersh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/generate_parser.sh (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/generate_parser.sh         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/generate_parser.sh        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,27 @@
</span><ins>+#!/bin/bash
+# Copyright (c) 2010 The ANGLE Project Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Generates GLSL ES parser - glslang_lex.cpp, glslang_tab.h, and glslang_tab.cpp
+
+run_flex()
+{
+input_file=$script_dir/$1.l
+output_source=$script_dir/$1_lex.cpp
+flex --noline --nounistd --outfile=$output_source $input_file
+}
+
+run_bison()
+{
+input_file=$script_dir/$1.y
+output_header=$script_dir/$1_tab.h
+output_source=$script_dir/$1_tab.cpp
+bison --no-lines --skeleton=yacc.c --defines=$output_header --output=$output_source $input_file
+}
+
+script_dir=$(dirname $0)
+
+# Generate Parser
+run_flex glslang
+run_bison glslang
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/generate_parser.sh
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorglslangh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/glslang.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/glslang.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/glslang.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,16 @@
</span><ins>+//
+// Copyright (c) 2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+struct TParseContext;
+extern int glslang_initialize(TParseContext* context);
+extern int glslang_finalize(TParseContext* context);
+
+extern int glslang_scan(size_t count,
+ const char* const string[],
+ const int length[],
+ TParseContext* context);
+extern int glslang_parse(TParseContext* context);
+
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/glslang.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorglslangl"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/glslang.l (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/glslang.l         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/glslang.l        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,355 @@
</span><ins>+/*
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+This file contains the Lex specification for GLSL ES.
+Based on ANSI C grammar, Lex specification:
+http://www.lysator.liu.se/c/ANSI-C-grammar-l.html
+
+IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh,
+WHICH GENERATES THE GLSL ES LEXER (glslang_lex.cpp).
+*/
+
+%top{
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// This file is auto-generated by generate_parser.sh. DO NOT EDIT!
+
+// Ignore errors in auto-generated code.
+#if defined(__GNUC__)
+#pragma GCC diagnostic ignored "-Wunused-function"
+#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wswitch-enum"
+#elif defined(_MSC_VER)
+#pragma warning(disable: 4065)
+#pragma warning(disable: 4189)
+#pragma warning(disable: 4505)
+#pragma warning(disable: 4701)
+#endif
+}
+
+%{
+#include "compiler/translator/glslang.h"
+#include "compiler/translator/ParseContext.h"
+#include "compiler/preprocessor/Token.h"
+#include "compiler/translator/util.h"
+#include "compiler/translator/glslang_tab.h"
+
+/* windows only pragma */
+#ifdef _MSC_VER
+#pragma warning(disable : 4102)
+#endif
+
+#define YY_USER_ACTION \
+ yylloc->first_file = yylloc->last_file = yycolumn; \
+ yylloc->first_line = yylloc->last_line = yylineno;
+
+#define YY_INPUT(buf, result, max_size) \
+ result = string_input(buf, max_size, yyscanner);
+
+static yy_size_t string_input(char* buf, yy_size_t max_size, yyscan_t yyscanner);
+static int check_type(yyscan_t yyscanner);
+static int reserved_word(yyscan_t yyscanner);
+static int int_constant(yyscan_t yyscanner);
+static int float_constant(yyscan_t yyscanner);
+%}
+
+%option noyywrap nounput never-interactive
+%option yylineno reentrant bison-bridge bison-locations
+%option extra-type="TParseContext*"
+
+D [0-9]
+L [a-zA-Z_]
+H [a-fA-F0-9]
+E [Ee][+-]?{D}+
+O [0-7]
+
+%%
+
+"invariant" { return INVARIANT; }
+"highp" { return HIGH_PRECISION; }
+"mediump" { return MEDIUM_PRECISION; }
+"lowp" { return LOW_PRECISION; }
+"precision" { return PRECISION; }
+
+"attribute" { return ATTRIBUTE; }
+"const" { return CONST_QUAL; }
+"uniform" { return UNIFORM; }
+"varying" { return VARYING; }
+
+"break" { return BREAK; }
+"continue" { return CONTINUE; }
+"do" { return DO; }
+"for" { return FOR; }
+"while" { return WHILE; }
+
+"if" { return IF; }
+"else" { return ELSE; }
+
+"in" { return IN_QUAL; }
+"out" { return OUT_QUAL; }
+"inout" { return INOUT_QUAL; }
+
+"float" { return FLOAT_TYPE; }
+"int" { return INT_TYPE; }
+"void" { return VOID_TYPE; }
+"bool" { return BOOL_TYPE; }
+"true" { yylval->lex.b = true; return BOOLCONSTANT; }
+"false" { yylval->lex.b = false; return BOOLCONSTANT; }
+
+"discard" { return DISCARD; }
+"return" { return RETURN; }
+
+"mat2" { return MATRIX2; }
+"mat3" { return MATRIX3; }
+"mat4" { return MATRIX4; }
+
+"vec2" { return VEC2; }
+"vec3" { return VEC3; }
+"vec4" { return VEC4; }
+"ivec2" { return IVEC2; }
+"ivec3" { return IVEC3; }
+"ivec4" { return IVEC4; }
+"bvec2" { return BVEC2; }
+"bvec3" { return BVEC3; }
+"bvec4" { return BVEC4; }
+
+"sampler2D" { return SAMPLER2D; }
+"samplerCube" { return SAMPLERCUBE; }
+"samplerExternalOES" { return SAMPLER_EXTERNAL_OES; }
+"sampler2DRect" { return SAMPLER2DRECT; }
+
+"struct" { return STRUCT; }
+
+"asm" { return reserved_word(yyscanner); }
+
+"class" { return reserved_word(yyscanner); }
+"union" { return reserved_word(yyscanner); }
+"enum" { return reserved_word(yyscanner); }
+"typedef" { return reserved_word(yyscanner); }
+"template" { return reserved_word(yyscanner); }
+"this" { return reserved_word(yyscanner); }
+"packed" { return reserved_word(yyscanner); }
+
+"goto" { return reserved_word(yyscanner); }
+"switch" { return reserved_word(yyscanner); }
+"default" { return reserved_word(yyscanner); }
+
+"inline" { return reserved_word(yyscanner); }
+"noinline" { return reserved_word(yyscanner); }
+"volatile" { return reserved_word(yyscanner); }
+"public" { return reserved_word(yyscanner); }
+"static" { return reserved_word(yyscanner); }
+"extern" { return reserved_word(yyscanner); }
+"external" { return reserved_word(yyscanner); }
+"interface" { return reserved_word(yyscanner); }
+"flat" { return reserved_word(yyscanner); }
+
+"long" { return reserved_word(yyscanner); }
+"short" { return reserved_word(yyscanner); }
+"double" { return reserved_word(yyscanner); }
+"half" { return reserved_word(yyscanner); }
+"fixed" { return reserved_word(yyscanner); }
+"unsigned" { return reserved_word(yyscanner); }
+"superp" { return reserved_word(yyscanner); }
+
+"input" { return reserved_word(yyscanner); }
+"output" { return reserved_word(yyscanner); }
+
+"hvec2" { return reserved_word(yyscanner); }
+"hvec3" { return reserved_word(yyscanner); }
+"hvec4" { return reserved_word(yyscanner); }
+"dvec2" { return reserved_word(yyscanner); }
+"dvec3" { return reserved_word(yyscanner); }
+"dvec4" { return reserved_word(yyscanner); }
+"fvec2" { return reserved_word(yyscanner); }
+"fvec3" { return reserved_word(yyscanner); }
+"fvec4" { return reserved_word(yyscanner); }
+
+"sampler1D" { return reserved_word(yyscanner); }
+"sampler3D" { return reserved_word(yyscanner); }
+"sampler1DShadow" { return reserved_word(yyscanner); }
+"sampler2DShadow" { return reserved_word(yyscanner); }
+"sampler3DRect" { return reserved_word(yyscanner); }
+"sampler2DRectShadow" { return reserved_word(yyscanner); }
+
+"sizeof" { return reserved_word(yyscanner); }
+"cast" { return reserved_word(yyscanner); }
+
+"namespace" { return reserved_word(yyscanner); }
+"using" { return reserved_word(yyscanner); }
+
+{L}({L}|{D})* {
+ yylval->lex.string = NewPoolTString(yytext);
+ return check_type(yyscanner);
+}
+
+0[xX]{H}+ { return int_constant(yyscanner); }
+0{O}+ { return int_constant(yyscanner); }
+{D}+ { return int_constant(yyscanner); }
+
+{D}+{E} { return float_constant(yyscanner); }
+{D}+"."{D}*({E})? { return float_constant(yyscanner); }
+"."{D}+({E})? { return float_constant(yyscanner); }
+
+"+=" { return ADD_ASSIGN; }
+"-=" { return SUB_ASSIGN; }
+"*=" { return MUL_ASSIGN; }
+"/=" { return DIV_ASSIGN; }
+"%=" { return MOD_ASSIGN; }
+"<<=" { return LEFT_ASSIGN; }
+">>=" { return RIGHT_ASSIGN; }
+"&=" { return AND_ASSIGN; }
+"^=" { return XOR_ASSIGN; }
+"|=" { return OR_ASSIGN; }
+
+"++" { return INC_OP; }
+"--" { return DEC_OP; }
+"&&" { return AND_OP; }
+"||" { return OR_OP; }
+"^^" { return XOR_OP; }
+"<=" { return LE_OP; }
+">=" { return GE_OP; }
+"==" { return EQ_OP; }
+"!=" { return NE_OP; }
+"<<" { return LEFT_OP; }
+">>" { return RIGHT_OP; }
+";" { return SEMICOLON; }
+("{"|"<%") { return LEFT_BRACE; }
+("}"|"%>") { return RIGHT_BRACE; }
+"," { return COMMA; }
+":" { return COLON; }
+"=" { return EQUAL; }
+"(" { return LEFT_PAREN; }
+")" { return RIGHT_PAREN; }
+("["|"<:") { return LEFT_BRACKET; }
+("]"|":>") { return RIGHT_BRACKET; }
+"." { return DOT; }
+"!" { return BANG; }
+"-" { return DASH; }
+"~" { return TILDE; }
+"+" { return PLUS; }
+"*" { return STAR; }
+"/" { return SLASH; }
+"%" { return PERCENT; }
+"<" { return LEFT_ANGLE; }
+">" { return RIGHT_ANGLE; }
+"|" { return VERTICAL_BAR; }
+"^" { return CARET; }
+"&" { return AMPERSAND; }
+"?" { return QUESTION; }
+
+[ \t\v\n\f\r] { }
+<<EOF>> { yyterminate(); }
+. { assert(false); return 0; }
+
+%%
+
+yy_size_t string_input(char* buf, yy_size_t max_size, yyscan_t yyscanner) {
+ pp::Token token;
+ yyget_extra(yyscanner)->preprocessor.lex(&token);
+ yy_size_t len = token.type == pp::Token::LAST ? 0 : token.text.size();
+ if (len < max_size)
+ memcpy(buf, token.text.c_str(), len);
+ yyset_column(token.location.file, yyscanner);
+ yyset_lineno(token.location.line, yyscanner);
+
+ if (len >= max_size)
+ YY_FATAL_ERROR("Input buffer overflow");
+ else if (len > 0)
+ buf[len++] = ' ';
+ return len;
+}
+
+int check_type(yyscan_t yyscanner) {
+ struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
+
+ int token = IDENTIFIER;
+ TSymbol* symbol = yyextra->symbolTable.find(yytext);
+ if (symbol && symbol->isVariable()) {
+ TVariable* variable = static_cast<TVariable*>(symbol);
+ if (variable->isUserType())
+ token = TYPE_NAME;
+ }
+ yylval->lex.symbol = symbol;
+ return token;
+}
+
+int reserved_word(yyscan_t yyscanner) {
+ struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
+
+ yyextra->error(*yylloc, "Illegal use of reserved word", yytext, "");
+ yyextra->recover();
+ return 0;
+}
+
+void yyerror(YYLTYPE* lloc, TParseContext* context, const char* reason) {
+ context->error(*lloc, reason, yyget_text(context->scanner));
+ context->recover();
+}
+
+int int_constant(yyscan_t yyscanner) {
+ struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
+
+ if (!atoi_clamp(yytext, &(yylval->lex.i)))
+ yyextra->warning(*yylloc, "Integer overflow", yytext, "");
+ return INTCONSTANT;
+}
+
+int float_constant(yyscan_t yyscanner) {
+ struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
+
+ if (!atof_clamp(yytext, &(yylval->lex.f)))
+ yyextra->warning(*yylloc, "Float overflow", yytext, "");
+ return FLOATCONSTANT;
+}
+
+int glslang_initialize(TParseContext* context) {
+ yyscan_t scanner = NULL;
+ if (yylex_init_extra(context, &scanner))
+ return 1;
+
+ context->scanner = scanner;
+ return 0;
+}
+
+int glslang_finalize(TParseContext* context) {
+ yyscan_t scanner = context->scanner;
+ if (scanner == NULL) return 0;
+
+ context->scanner = NULL;
+ yylex_destroy(scanner);
+
+ return 0;
+}
+
+int glslang_scan(size_t count, const char* const string[], const int length[],
+ TParseContext* context) {
+ yyrestart(NULL, context->scanner);
+ yyset_column(0, context->scanner);
+ yyset_lineno(1, context->scanner);
+
+ // Initialize preprocessor.
+ if (!context->preprocessor.init(count, string, length))
+ return 1;
+ context->preprocessor.setMaxTokenLength(SH_MAX_TOKEN_LENGTH);
+
+ // Define extension macros.
+ const TExtensionBehavior& extBehavior = context->extensionBehavior();
+ for (TExtensionBehavior::const_iterator iter = extBehavior.begin();
+ iter != extBehavior.end(); ++iter) {
+ context->preprocessor.predefineMacro(iter->first.c_str(), 1);
+ }
+ if (context->fragmentPrecisionHigh)
+ context->preprocessor.predefineMacro("GL_FRAGMENT_PRECISION_HIGH", 1);
+
+ return 0;
+}
+
</ins></span></pre></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorglslangy"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/glslang.y (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/glslang.y         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/glslang.y        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,2015 @@
</span><ins>+/*
+//
+// Copyright (c) 2002-2013 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.
+//
+
+This file contains the Yacc grammar for GLSL ES.
+Based on ANSI C Yacc grammar:
+http://www.lysator.liu.se/c/ANSI-C-grammar-y.html
+
+IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh,
+WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h).
+*/
+
+%{
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// This file is auto-generated by generate_parser.sh. DO NOT EDIT!
+
+// Ignore errors in auto-generated code.
+#if defined(__GNUC__)
+#pragma GCC diagnostic ignored "-Wunused-function"
+#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wswitch-enum"
+#elif defined(_MSC_VER)
+#pragma warning(disable: 4065)
+#pragma warning(disable: 4189)
+#pragma warning(disable: 4505)
+#pragma warning(disable: 4701)
+#endif
+
+#include "compiler/translator/SymbolTable.h"
+#include "compiler/translator/ParseContext.h"
+#include "GLSLANG/ShaderLang.h"
+
+#define YYENABLE_NLS 0
+
+#define YYLEX_PARAM context->scanner
+%}
+
+%expect 1 /* One shift reduce conflict because of if | else */
+%pure-parser
+%parse-param {TParseContext* context}
+%locations
+%lex-param {YYLEX_PARAM}
+
+%code requires {
+#define YYLTYPE TSourceLoc
+#define YYLTYPE_IS_DECLARED 1
+#define SH_MAX_TOKEN_LENGTH 256 // WebGL spec.
+}
+
+%union {
+ struct {
+ union {
+ TString *string;
+ float f;
+ int i;
+ bool b;
+ };
+ TSymbol* symbol;
+ } lex;
+ struct {
+ TOperator op;
+ union {
+ TIntermNode* intermNode;
+ TIntermNodePair nodePair;
+ TIntermTyped* intermTypedNode;
+ TIntermAggregate* intermAggregate;
+ };
+ union {
+ TPublicType type;
+ TPrecision precision;
+ TQualifier qualifier;
+ TFunction* function;
+ TParameter param;
+ TField* field;
+ TFieldList* fieldList;
+ };
+ } interm;
+}
+
+%{
+extern int yylex(YYSTYPE* yylval, YYLTYPE* yylloc, void* yyscanner);
+extern void yyerror(YYLTYPE* yylloc, TParseContext* context, const char* reason);
+
+#define YYLLOC_DEFAULT(Current, Rhs, N) \
+ do { \
+ if (N) { \
+ (Current).first_file = YYRHSLOC(Rhs, 1).first_file; \
+ (Current).first_line = YYRHSLOC(Rhs, 1).first_line; \
+ (Current).last_file = YYRHSLOC(Rhs, N).last_file; \
+ (Current).last_line = YYRHSLOC(Rhs, N).last_line; \
+ } \
+ else { \
+ (Current).first_file = YYRHSLOC(Rhs, 0).last_file; \
+ (Current).first_line = YYRHSLOC(Rhs, 0).last_line; \
+ (Current).last_file = YYRHSLOC(Rhs, 0).last_file; \
+ (Current).last_line = YYRHSLOC(Rhs, 0).last_line; \
+ } \
+ } while (0)
+
+#define VERTEX_ONLY(S, L) { \
+ if (context->shaderType != SH_VERTEX_SHADER) { \
+ context->error(L, " supported in vertex shaders only ", S); \
+ context->recover(); \
+ } \
+}
+
+#define FRAG_ONLY(S, L) { \
+ if (context->shaderType != SH_FRAGMENT_SHADER) { \
+ context->error(L, " supported in fragment shaders only ", S); \
+ context->recover(); \
+ } \
+}
+%}
+
+%token <lex> INVARIANT HIGH_PRECISION MEDIUM_PRECISION LOW_PRECISION PRECISION
+%token <lex> ATTRIBUTE CONST_QUAL BOOL_TYPE FLOAT_TYPE INT_TYPE
+%token <lex> BREAK CONTINUE DO ELSE FOR IF DISCARD RETURN
+%token <lex> BVEC2 BVEC3 BVEC4 IVEC2 IVEC3 IVEC4 VEC2 VEC3 VEC4
+%token <lex> MATRIX2 MATRIX3 MATRIX4 IN_QUAL OUT_QUAL INOUT_QUAL UNIFORM VARYING
+%token <lex> STRUCT VOID_TYPE WHILE
+%token <lex> SAMPLER2D SAMPLERCUBE SAMPLER_EXTERNAL_OES SAMPLER2DRECT
+
+%token <lex> IDENTIFIER TYPE_NAME FLOATCONSTANT INTCONSTANT BOOLCONSTANT
+%token <lex> LEFT_OP RIGHT_OP
+%token <lex> INC_OP DEC_OP LE_OP GE_OP EQ_OP NE_OP
+%token <lex> AND_OP OR_OP XOR_OP MUL_ASSIGN DIV_ASSIGN ADD_ASSIGN
+%token <lex> MOD_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN XOR_ASSIGN OR_ASSIGN
+%token <lex> SUB_ASSIGN
+
+%token <lex> LEFT_PAREN RIGHT_PAREN LEFT_BRACKET RIGHT_BRACKET LEFT_BRACE RIGHT_BRACE DOT
+%token <lex> COMMA COLON EQUAL SEMICOLON BANG DASH TILDE PLUS STAR SLASH PERCENT
+%token <lex> LEFT_ANGLE RIGHT_ANGLE VERTICAL_BAR CARET AMPERSAND QUESTION
+
+%type <lex> identifier
+%type <interm> assignment_operator unary_operator
+%type <interm.intermTypedNode> variable_identifier primary_expression postfix_expression
+%type <interm.intermTypedNode> expression integer_expression assignment_expression
+%type <interm.intermTypedNode> unary_expression multiplicative_expression additive_expression
+%type <interm.intermTypedNode> relational_expression equality_expression
+%type <interm.intermTypedNode> conditional_expression constant_expression
+%type <interm.intermTypedNode> logical_or_expression logical_xor_expression logical_and_expression
+%type <interm.intermTypedNode> shift_expression and_expression exclusive_or_expression inclusive_or_expression
+%type <interm.intermTypedNode> function_call initializer condition conditionopt
+
+%type <interm.intermNode> translation_unit function_definition
+%type <interm.intermNode> statement simple_statement
+%type <interm.intermAggregate> statement_list compound_statement
+%type <interm.intermNode> declaration_statement selection_statement expression_statement
+%type <interm.intermNode> declaration external_declaration
+%type <interm.intermNode> for_init_statement compound_statement_no_new_scope
+%type <interm.nodePair> selection_rest_statement for_rest_statement
+%type <interm.intermNode> iteration_statement jump_statement statement_no_new_scope statement_with_scope
+%type <interm> single_declaration init_declarator_list
+
+%type <interm> parameter_declaration parameter_declarator parameter_type_specifier
+%type <interm.qualifier> parameter_qualifier
+
+%type <interm.precision> precision_qualifier
+%type <interm.type> type_qualifier fully_specified_type type_specifier
+%type <interm.type> type_specifier_no_prec type_specifier_nonarray
+%type <interm.type> struct_specifier
+%type <interm.field> struct_declarator
+%type <interm.fieldList> struct_declarator_list struct_declaration struct_declaration_list
+%type <interm.function> function_header function_declarator function_identifier
+%type <interm.function> function_header_with_parameters function_call_header
+%type <interm> function_call_header_with_parameters function_call_header_no_parameters function_call_generic function_prototype
+%type <interm> function_call_or_method
+
+%start translation_unit
+%%
+
+identifier
+ : IDENTIFIER
+ | TYPE_NAME
+
+variable_identifier
+ : IDENTIFIER {
+ // The symbol table search was done in the lexical phase
+ const TSymbol *symbol = $1.symbol;
+ const TVariable *variable = 0;
+
+ if (!symbol)
+ {
+ context->error(@1, "undeclared identifier", $1.string->c_str());
+ context->recover();
+ }
+ else if (!symbol->isVariable())
+ {
+ context->error(@1, "variable expected", $1.string->c_str());
+ context->recover();
+ }
+ else
+ {
+ variable = static_cast<const TVariable*>(symbol);
+
+ if (context->symbolTable.findBuiltIn(variable->getName()) &&
+ !variable->getExtension().empty() &&
+ context->extensionErrorCheck(@1, variable->getExtension()))
+ {
+ context->recover();
+ }
+ }
+
+ if (!variable)
+ {
+ TType type(EbtFloat, EbpUndefined);
+ TVariable *fakeVariable = new TVariable($1.string, type);
+ context->symbolTable.insert(*fakeVariable);
+ variable = fakeVariable;
+ }
+
+ if (variable->getType().getQualifier() == EvqConst)
+ {
+ ConstantUnion* constArray = variable->getConstPointer();
+ TType t(variable->getType());
+ $$ = context->intermediate.addConstantUnion(constArray, t, @1);
+ }
+ else
+ {
+ $$ = context->intermediate.addSymbol(variable->getUniqueId(),
+ variable->getName(),
+ variable->getType(),
+ @1);
+ }
+
+ // don't delete $1.string, it's used by error recovery, and the pool
+ // pop will reclaim the memory
+ }
+ ;
+
+primary_expression
+ : variable_identifier {
+ $$ = $1;
+ }
+ | INTCONSTANT {
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setIConst($1.i);
+ $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), @1);
+ }
+ | FLOATCONSTANT {
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setFConst($1.f);
+ $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), @1);
+ }
+ | BOOLCONSTANT {
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setBConst($1.b);
+ $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @1);
+ }
+ | LEFT_PAREN expression RIGHT_PAREN {
+ $$ = $2;
+ }
+ ;
+
+postfix_expression
+ : primary_expression {
+ $$ = $1;
+ }
+ | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET {
+ $$ = context->addIndexExpression($1, @2, $3);
+ }
+ | function_call {
+ $$ = $1;
+ }
+ | postfix_expression DOT identifier {
+ if ($1->isArray()) {
+ context->error(@3, "cannot apply dot operator to an array", ".");
+ context->recover();
+ }
+
+ if ($1->isVector()) {
+ TVectorFields fields;
+ if (! context->parseVectorFields(*$3.string, $1->getNominalSize(), fields, @3)) {
+ fields.num = 1;
+ fields.offsets[0] = 0;
+ context->recover();
+ }
+
+ if ($1->getType().getQualifier() == EvqConst) { // constant folding for vector fields
+ $$ = context->addConstVectorNode(fields, $1, @3);
+ if ($$ == 0) {
+ context->recover();
+ $$ = $1;
+ }
+ else
+ $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqConst, (int) (*$3.string).size()));
+ } else {
+ TString vectorString = *$3.string;
+ TIntermTyped* index = context->intermediate.addSwizzle(fields, @3);
+ $$ = context->intermediate.addIndex(EOpVectorSwizzle, $1, index, @2);
+ $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary, (int) vectorString.size()));
+ }
+ } else if ($1->isMatrix()) {
+ TMatrixFields fields;
+ if (! context->parseMatrixFields(*$3.string, $1->getNominalSize(), fields, @3)) {
+ fields.wholeRow = false;
+ fields.wholeCol = false;
+ fields.row = 0;
+ fields.col = 0;
+ context->recover();
+ }
+
+ if (fields.wholeRow || fields.wholeCol) {
+ context->error(@2, " non-scalar fields not implemented yet", ".");
+ context->recover();
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setIConst(0);
+ TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), @3);
+ $$ = context->intermediate.addIndex(EOpIndexDirect, $1, index, @2);
+ $$->setType(TType($1->getBasicType(), $1->getPrecision(),EvqTemporary, $1->getNominalSize()));
+ } else {
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setIConst(fields.col * $1->getNominalSize() + fields.row);
+ TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), @3);
+ $$ = context->intermediate.addIndex(EOpIndexDirect, $1, index, @2);
+ $$->setType(TType($1->getBasicType(), $1->getPrecision()));
+ }
+ } else if ($1->getBasicType() == EbtStruct) {
+ bool fieldFound = false;
+ const TFieldList& fields = $1->getType().getStruct()->fields();
+ unsigned int i;
+ for (i = 0; i < fields.size(); ++i) {
+ if (fields[i]->name() == *$3.string) {
+ fieldFound = true;
+ break;
+ }
+ }
+ if (fieldFound) {
+ if ($1->getType().getQualifier() == EvqConst) {
+ $$ = context->addConstStruct(*$3.string, $1, @2);
+ if ($$ == 0) {
+ context->recover();
+ $$ = $1;
+ }
+ else {
+ $$->setType(*fields[i]->type());
+ // change the qualifier of the return type, not of the structure field
+ // as the structure definition is shared between various structures.
+ $$->getTypePointer()->setQualifier(EvqConst);
+ }
+ } else {
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setIConst(i);
+ TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, *fields[i]->type(), @3);
+ $$ = context->intermediate.addIndex(EOpIndexDirectStruct, $1, index, @2);
+ $$->setType(*fields[i]->type());
+ }
+ } else {
+ context->error(@2, " no such field in structure", $3.string->c_str());
+ context->recover();
+ $$ = $1;
+ }
+ } else {
+ context->error(@2, " field selection requires structure, vector, or matrix on left hand side", $3.string->c_str());
+ context->recover();
+ $$ = $1;
+ }
+ // don't delete $3.string, it's from the pool
+ }
+ | postfix_expression INC_OP {
+ if (context->lValueErrorCheck(@2, "++", $1))
+ context->recover();
+ $$ = context->intermediate.addUnaryMath(EOpPostIncrement, $1, @2, context->symbolTable);
+ if ($$ == 0) {
+ context->unaryOpError(@2, "++", $1->getCompleteString());
+ context->recover();
+ $$ = $1;
+ }
+ }
+ | postfix_expression DEC_OP {
+ if (context->lValueErrorCheck(@2, "--", $1))
+ context->recover();
+ $$ = context->intermediate.addUnaryMath(EOpPostDecrement, $1, @2, context->symbolTable);
+ if ($$ == 0) {
+ context->unaryOpError(@2, "--", $1->getCompleteString());
+ context->recover();
+ $$ = $1;
+ }
+ }
+ ;
+
+integer_expression
+ : expression {
+ if (context->integerErrorCheck($1, "[]"))
+ context->recover();
+ $$ = $1;
+ }
+ ;
+
+function_call
+ : function_call_or_method {
+ TFunction* fnCall = $1.function;
+ TOperator op = fnCall->getBuiltInOp();
+
+ if (op != EOpNull)
+ {
+ //
+ // Then this should be a constructor.
+ // Don't go through the symbol table for constructors.
+ // Their parameters will be verified algorithmically.
+ //
+ TType type(EbtVoid, EbpUndefined); // use this to get the type back
+ if (context->constructorErrorCheck(@1, $1.intermNode, *fnCall, op, &type)) {
+ $$ = 0;
+ } else {
+ //
+ // It's a constructor, of type 'type'.
+ //
+ $$ = context->addConstructor($1.intermNode, &type, op, fnCall, @1);
+ }
+
+ if ($$ == 0) {
+ context->recover();
+ $$ = context->intermediate.setAggregateOperator(0, op, @1);
+ }
+ $$->setType(type);
+ } else {
+ //
+ // Not a constructor. Find it in the symbol table.
+ //
+ const TFunction* fnCandidate;
+ bool builtIn;
+ fnCandidate = context->findFunction(@1, fnCall, &builtIn);
+ if (fnCandidate) {
+ //
+ // A declared function.
+ //
+ if (builtIn && !fnCandidate->getExtension().empty() &&
+ context->extensionErrorCheck(@1, fnCandidate->getExtension())) {
+ context->recover();
+ }
+ op = fnCandidate->getBuiltInOp();
+ if (builtIn && op != EOpNull) {
+ //
+ // A function call mapped to a built-in operation.
+ //
+ if (fnCandidate->getParamCount() == 1) {
+ //
+ // Treat it like a built-in unary operator.
+ //
+ $$ = context->intermediate.addUnaryMath(op, $1.intermNode, @1, context->symbolTable);
+ if ($$ == 0) {
+ std::stringstream extraInfoStream;
+ extraInfoStream << "built in unary operator function. Type: " << static_cast<TIntermTyped*>($1.intermNode)->getCompleteString();
+ std::string extraInfo = extraInfoStream.str();
+ context->error($1.intermNode->getLine(), " wrong operand type", "Internal Error", extraInfo.c_str());
+ YYERROR;
+ }
+ } else {
+ $$ = context->intermediate.setAggregateOperator($1.intermAggregate, op, @1);
+ }
+ } else {
+ // This is a real function call
+
+ $$ = context->intermediate.setAggregateOperator($1.intermAggregate, EOpFunctionCall, @1);
+ $$->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());
+
+ TQualifier qual;
+ for (size_t i = 0; i < fnCandidate->getParamCount(); ++i) {
+ qual = fnCandidate->getParam(i).type->getQualifier();
+ if (qual == EvqOut || qual == EvqInOut) {
+ if (context->lValueErrorCheck($$->getLine(), "assign", $$->getAsAggregate()->getSequence()[i]->getAsTyped())) {
+ context->error($1.intermNode->getLine(), "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error");
+ context->recover();
+ }
+ }
+ }
+ }
+ $$->setType(fnCandidate->getReturnType());
+ } else {
+ // error message was put out by PaFindFunction()
+ // Put on a dummy node for error recovery
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setFConst(0.0f);
+ $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), @1);
+ context->recover();
+ }
+ }
+ delete fnCall;
+ }
+ ;
+
+function_call_or_method
+ : function_call_generic {
+ $$ = $1;
+ }
+ | postfix_expression DOT function_call_generic {
+ context->error(@3, "methods are not supported", "");
+ context->recover();
+ $$ = $3;
+ }
+ ;
+
+function_call_generic
+ : function_call_header_with_parameters RIGHT_PAREN {
+ $$ = $1;
+ }
+ | function_call_header_no_parameters RIGHT_PAREN {
+ $$ = $1;
+ }
+ ;
+
+function_call_header_no_parameters
+ : function_call_header VOID_TYPE {
+ $$.function = $1;
+ $$.intermNode = 0;
+ }
+ | function_call_header {
+ $$.function = $1;
+ $$.intermNode = 0;
+ }
+ ;
+
+function_call_header_with_parameters
+ : function_call_header assignment_expression {
+ TParameter param = { 0, new TType($2->getType()) };
+ $1->addParameter(param);
+ $$.function = $1;
+ $$.intermNode = $2;
+ }
+ | function_call_header_with_parameters COMMA assignment_expression {
+ TParameter param = { 0, new TType($3->getType()) };
+ $1.function->addParameter(param);
+ $$.function = $1.function;
+ $$.intermNode = context->intermediate.growAggregate($1.intermNode, $3, @2);
+ }
+ ;
+
+function_call_header
+ : function_identifier LEFT_PAREN {
+ $$ = $1;
+ }
+ ;
+
+// Grammar Note: Constructors look like functions, but are recognized as types.
+
+function_identifier
+ : type_specifier_nonarray {
+ //
+ // Constructor
+ //
+ TOperator op = EOpNull;
+ if ($1.userDef) {
+ op = EOpConstructStruct;
+ } else {
+ switch ($1.type) {
+ case EbtFloat:
+ if ($1.matrix) {
+ switch($1.size) {
+ case 2: op = EOpConstructMat2; break;
+ case 3: op = EOpConstructMat3; break;
+ case 4: op = EOpConstructMat4; break;
+ }
+ } else {
+ switch($1.size) {
+ case 1: op = EOpConstructFloat; break;
+ case 2: op = EOpConstructVec2; break;
+ case 3: op = EOpConstructVec3; break;
+ case 4: op = EOpConstructVec4; break;
+ }
+ }
+ break;
+ case EbtInt:
+ switch($1.size) {
+ case 1: op = EOpConstructInt; break;
+ case 2: op = EOpConstructIVec2; break;
+ case 3: op = EOpConstructIVec3; break;
+ case 4: op = EOpConstructIVec4; break;
+ }
+ break;
+ case EbtBool:
+ switch($1.size) {
+ case 1: op = EOpConstructBool; break;
+ case 2: op = EOpConstructBVec2; break;
+ case 3: op = EOpConstructBVec3; break;
+ case 4: op = EOpConstructBVec4; break;
+ }
+ break;
+ default: break;
+ }
+ if (op == EOpNull) {
+ context->error(@1, "cannot construct this type", getBasicString($1.type));
+ context->recover();
+ $1.type = EbtFloat;
+ op = EOpConstructFloat;
+ }
+ }
+ TString tempString;
+ TType type($1);
+ TFunction *function = new TFunction(&tempString, type, op);
+ $$ = function;
+ }
+ | IDENTIFIER {
+ if (context->reservedErrorCheck(@1, *$1.string))
+ context->recover();
+ TType type(EbtVoid, EbpUndefined);
+ TFunction *function = new TFunction($1.string, type);
+ $$ = function;
+ }
+ ;
+
+unary_expression
+ : postfix_expression {
+ $$ = $1;
+ }
+ | INC_OP unary_expression {
+ if (context->lValueErrorCheck(@1, "++", $2))
+ context->recover();
+ $$ = context->intermediate.addUnaryMath(EOpPreIncrement, $2, @1, context->symbolTable);
+ if ($$ == 0) {
+ context->unaryOpError(@1, "++", $2->getCompleteString());
+ context->recover();
+ $$ = $2;
+ }
+ }
+ | DEC_OP unary_expression {
+ if (context->lValueErrorCheck(@1, "--", $2))
+ context->recover();
+ $$ = context->intermediate.addUnaryMath(EOpPreDecrement, $2, @1, context->symbolTable);
+ if ($$ == 0) {
+ context->unaryOpError(@1, "--", $2->getCompleteString());
+ context->recover();
+ $$ = $2;
+ }
+ }
+ | unary_operator unary_expression {
+ if ($1.op != EOpNull) {
+ $$ = context->intermediate.addUnaryMath($1.op, $2, @1, context->symbolTable);
+ if ($$ == 0) {
+ const char* errorOp = "";
+ switch($1.op) {
+ case EOpNegative: errorOp = "-"; break;
+ case EOpLogicalNot: errorOp = "!"; break;
+ default: break;
+ }
+ context->unaryOpError(@1, errorOp, $2->getCompleteString());
+ context->recover();
+ $$ = $2;
+ }
+ } else
+ $$ = $2;
+ }
+ ;
+// Grammar Note: No traditional style type casts.
+
+unary_operator
+ : PLUS { $$.op = EOpNull; }
+ | DASH { $$.op = EOpNegative; }
+ | BANG { $$.op = EOpLogicalNot; }
+ ;
+// Grammar Note: No '*' or '&' unary ops. Pointers are not supported.
+
+multiplicative_expression
+ : unary_expression { $$ = $1; }
+ | multiplicative_expression STAR unary_expression {
+ $$ = context->intermediate.addBinaryMath(EOpMul, $1, $3, @2, context->symbolTable);
+ if ($$ == 0) {
+ context->binaryOpError(@2, "*", $1->getCompleteString(), $3->getCompleteString());
+ context->recover();
+ $$ = $1;
+ }
+ }
+ | multiplicative_expression SLASH unary_expression {
+ $$ = context->intermediate.addBinaryMath(EOpDiv, $1, $3, @2, context->symbolTable);
+ if ($$ == 0) {
+ context->binaryOpError(@2, "/", $1->getCompleteString(), $3->getCompleteString());
+ context->recover();
+ $$ = $1;
+ }
+ }
+ ;
+
+additive_expression
+ : multiplicative_expression { $$ = $1; }
+ | additive_expression PLUS multiplicative_expression {
+ $$ = context->intermediate.addBinaryMath(EOpAdd, $1, $3, @2, context->symbolTable);
+ if ($$ == 0) {
+ context->binaryOpError(@2, "+", $1->getCompleteString(), $3->getCompleteString());
+ context->recover();
+ $$ = $1;
+ }
+ }
+ | additive_expression DASH multiplicative_expression {
+ $$ = context->intermediate.addBinaryMath(EOpSub, $1, $3, @2, context->symbolTable);
+ if ($$ == 0) {
+ context->binaryOpError(@2, "-", $1->getCompleteString(), $3->getCompleteString());
+ context->recover();
+ $$ = $1;
+ }
+ }
+ ;
+
+shift_expression
+ : additive_expression { $$ = $1; }
+ ;
+
+relational_expression
+ : shift_expression { $$ = $1; }
+ | relational_expression LEFT_ANGLE shift_expression {
+ $$ = context->intermediate.addBinaryMath(EOpLessThan, $1, $3, @2, context->symbolTable);
+ if ($$ == 0) {
+ context->binaryOpError(@2, "<", $1->getCompleteString(), $3->getCompleteString());
+ context->recover();
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setBConst(false);
+ $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
+ }
+ }
+ | relational_expression RIGHT_ANGLE shift_expression {
+ $$ = context->intermediate.addBinaryMath(EOpGreaterThan, $1, $3, @2, context->symbolTable);
+ if ($$ == 0) {
+ context->binaryOpError(@2, ">", $1->getCompleteString(), $3->getCompleteString());
+ context->recover();
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setBConst(false);
+ $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
+ }
+ }
+ | relational_expression LE_OP shift_expression {
+ $$ = context->intermediate.addBinaryMath(EOpLessThanEqual, $1, $3, @2, context->symbolTable);
+ if ($$ == 0) {
+ context->binaryOpError(@2, "<=", $1->getCompleteString(), $3->getCompleteString());
+ context->recover();
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setBConst(false);
+ $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
+ }
+ }
+ | relational_expression GE_OP shift_expression {
+ $$ = context->intermediate.addBinaryMath(EOpGreaterThanEqual, $1, $3, @2, context->symbolTable);
+ if ($$ == 0) {
+ context->binaryOpError(@2, ">=", $1->getCompleteString(), $3->getCompleteString());
+ context->recover();
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setBConst(false);
+ $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
+ }
+ }
+ ;
+
+equality_expression
+ : relational_expression { $$ = $1; }
+ | equality_expression EQ_OP relational_expression {
+ $$ = context->intermediate.addBinaryMath(EOpEqual, $1, $3, @2, context->symbolTable);
+ if ($$ == 0) {
+ context->binaryOpError(@2, "==", $1->getCompleteString(), $3->getCompleteString());
+ context->recover();
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setBConst(false);
+ $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
+ }
+ }
+ | equality_expression NE_OP relational_expression {
+ $$ = context->intermediate.addBinaryMath(EOpNotEqual, $1, $3, @2, context->symbolTable);
+ if ($$ == 0) {
+ context->binaryOpError(@2, "!=", $1->getCompleteString(), $3->getCompleteString());
+ context->recover();
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setBConst(false);
+ $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
+ }
+ }
+ ;
+
+and_expression
+ : equality_expression { $$ = $1; }
+ ;
+
+exclusive_or_expression
+ : and_expression { $$ = $1; }
+ ;
+
+inclusive_or_expression
+ : exclusive_or_expression { $$ = $1; }
+ ;
+
+logical_and_expression
+ : inclusive_or_expression { $$ = $1; }
+ | logical_and_expression AND_OP inclusive_or_expression {
+ $$ = context->intermediate.addBinaryMath(EOpLogicalAnd, $1, $3, @2, context->symbolTable);
+ if ($$ == 0) {
+ context->binaryOpError(@2, "&&", $1->getCompleteString(), $3->getCompleteString());
+ context->recover();
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setBConst(false);
+ $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
+ }
+ }
+ ;
+
+logical_xor_expression
+ : logical_and_expression { $$ = $1; }
+ | logical_xor_expression XOR_OP logical_and_expression {
+ $$ = context->intermediate.addBinaryMath(EOpLogicalXor, $1, $3, @2, context->symbolTable);
+ if ($$ == 0) {
+ context->binaryOpError(@2, "^^", $1->getCompleteString(), $3->getCompleteString());
+ context->recover();
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setBConst(false);
+ $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
+ }
+ }
+ ;
+
+logical_or_expression
+ : logical_xor_expression { $$ = $1; }
+ | logical_or_expression OR_OP logical_xor_expression {
+ $$ = context->intermediate.addBinaryMath(EOpLogicalOr, $1, $3, @2, context->symbolTable);
+ if ($$ == 0) {
+ context->binaryOpError(@2, "||", $1->getCompleteString(), $3->getCompleteString());
+ context->recover();
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setBConst(false);
+ $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
+ }
+ }
+ ;
+
+conditional_expression
+ : logical_or_expression { $$ = $1; }
+ | logical_or_expression QUESTION expression COLON assignment_expression {
+ if (context->boolErrorCheck(@2, $1))
+ context->recover();
+
+ $$ = context->intermediate.addSelection($1, $3, $5, @2);
+ if ($3->getType() != $5->getType())
+ $$ = 0;
+
+ if ($$ == 0) {
+ context->binaryOpError(@2, ":", $3->getCompleteString(), $5->getCompleteString());
+ context->recover();
+ $$ = $5;
+ }
+ }
+ ;
+
+assignment_expression
+ : conditional_expression { $$ = $1; }
+ | unary_expression assignment_operator assignment_expression {
+ if (context->lValueErrorCheck(@2, "assign", $1))
+ context->recover();
+ $$ = context->intermediate.addAssign($2.op, $1, $3, @2);
+ if ($$ == 0) {
+ context->assignError(@2, "assign", $1->getCompleteString(), $3->getCompleteString());
+ context->recover();
+ $$ = $1;
+ }
+ }
+ ;
+
+assignment_operator
+ : EQUAL { $$.op = EOpAssign; }
+ | MUL_ASSIGN { $$.op = EOpMulAssign; }
+ | DIV_ASSIGN { $$.op = EOpDivAssign; }
+ | ADD_ASSIGN { $$.op = EOpAddAssign; }
+ | SUB_ASSIGN { $$.op = EOpSubAssign; }
+ ;
+
+expression
+ : assignment_expression {
+ $$ = $1;
+ }
+ | expression COMMA assignment_expression {
+ $$ = context->intermediate.addComma($1, $3, @2);
+ if ($$ == 0) {
+ context->binaryOpError(@2, ",", $1->getCompleteString(), $3->getCompleteString());
+ context->recover();
+ $$ = $3;
+ }
+ }
+ ;
+
+constant_expression
+ : conditional_expression {
+ if (context->constErrorCheck($1))
+ context->recover();
+ $$ = $1;
+ }
+ ;
+
+declaration
+ : function_prototype SEMICOLON {
+ TFunction &function = *($1.function);
+
+ TIntermAggregate *prototype = new TIntermAggregate;
+ prototype->setType(function.getReturnType());
+ prototype->setName(function.getName());
+
+ for (size_t i = 0; i < function.getParamCount(); i++)
+ {
+ const TParameter &param = function.getParam(i);
+ if (param.name != 0)
+ {
+ TVariable variable(param.name, *param.type);
+
+ prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(variable.getUniqueId(), variable.getName(), variable.getType(), @1), @1);
+ }
+ else
+ {
+ prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(0, "", *param.type, @1), @1);
+ }
+ }
+
+ prototype->setOp(EOpPrototype);
+ $$ = prototype;
+
+ context->symbolTable.pop();
+ }
+ | init_declarator_list SEMICOLON {
+ if ($1.intermAggregate)
+ $1.intermAggregate->setOp(EOpDeclaration);
+ $$ = $1.intermAggregate;
+ }
+ | PRECISION precision_qualifier type_specifier_no_prec SEMICOLON {
+ if (($2 == EbpHigh) && (context->shaderType == SH_FRAGMENT_SHADER) && !context->fragmentPrecisionHigh) {
+ context->error(@1, "precision is not supported in fragment shader", "highp");
+ context->recover();
+ }
+ if (!context->symbolTable.setDefaultPrecision( $3, $2 )) {
+ context->error(@1, "illegal type argument for default precision qualifier", getBasicString($3.type));
+ context->recover();
+ }
+ $$ = 0;
+ }
+ ;
+
+function_prototype
+ : function_declarator RIGHT_PAREN {
+ //
+ // Multiple declarations of the same function are allowed.
+ //
+ // If this is a definition, the definition production code will check for redefinitions
+ // (we don't know at this point if it's a definition or not).
+ //
+ // Redeclarations are allowed. But, return types and parameter qualifiers must match.
+ //
+ TFunction* prevDec = static_cast<TFunction*>(context->symbolTable.find($1->getMangledName()));
+ if (prevDec) {
+ if (prevDec->getReturnType() != $1->getReturnType()) {
+ context->error(@2, "overloaded functions must have the same return type", $1->getReturnType().getBasicString());
+ context->recover();
+ }
+ for (size_t i = 0; i < prevDec->getParamCount(); ++i) {
+ if (prevDec->getParam(i).type->getQualifier() != $1->getParam(i).type->getQualifier()) {
+ context->error(@2, "overloaded functions must have the same parameter qualifiers", $1->getParam(i).type->getQualifierString());
+ context->recover();
+ }
+ }
+ }
+
+ //
+ // Check for previously declared variables using the same name.
+ //
+ TSymbol *prevSym = context->symbolTable.find($1->getName());
+ if (prevSym)
+ {
+ if (!prevSym->isFunction())
+ {
+ context->error(@2, "redefinition", $1->getName().c_str(), "function");
+ context->recover();
+ }
+ }
+ else
+ {
+ // Insert the unmangled name to detect potential future redefinition as a variable.
+ context->symbolTable.getOuterLevel()->insert($1->getName(), *$1);
+ }
+
+ //
+ // If this is a redeclaration, it could also be a definition,
+ // in which case, we want to use the variable names from this one, and not the one that's
+ // being redeclared. So, pass back up this declaration, not the one in the symbol table.
+ //
+ $$.function = $1;
+
+ // We're at the inner scope level of the function's arguments and body statement.
+ // Add the function prototype to the surrounding scope instead.
+ context->symbolTable.getOuterLevel()->insert(*$$.function);
+ }
+ ;
+
+function_declarator
+ : function_header {
+ $$ = $1;
+ }
+ | function_header_with_parameters {
+ $$ = $1;
+ }
+ ;
+
+
+function_header_with_parameters
+ : function_header parameter_declaration {
+ // Add the parameter
+ $$ = $1;
+ if ($2.param.type->getBasicType() != EbtVoid)
+ $1->addParameter($2.param);
+ else
+ delete $2.param.type;
+ }
+ | function_header_with_parameters COMMA parameter_declaration {
+ //
+ // Only first parameter of one-parameter functions can be void
+ // The check for named parameters not being void is done in parameter_declarator
+ //
+ if ($3.param.type->getBasicType() == EbtVoid) {
+ //
+ // This parameter > first is void
+ //
+ context->error(@2, "cannot be an argument type except for '(void)'", "void");
+ context->recover();
+ delete $3.param.type;
+ } else {
+ // Add the parameter
+ $$ = $1;
+ $1->addParameter($3.param);
+ }
+ }
+ ;
+
+function_header
+ : fully_specified_type IDENTIFIER LEFT_PAREN {
+ if ($1.qualifier != EvqGlobal && $1.qualifier != EvqTemporary) {
+ context->error(@2, "no qualifiers allowed for function return", getQualifierString($1.qualifier));
+ context->recover();
+ }
+ // make sure a sampler is not involved as well...
+ if (context->structQualifierErrorCheck(@2, $1))
+ context->recover();
+
+ // Add the function as a prototype after parsing it (we do not support recursion)
+ TFunction *function;
+ TType type($1);
+ function = new TFunction($2.string, type);
+ $$ = function;
+
+ context->symbolTable.push();
+ }
+ ;
+
+parameter_declarator
+ // Type + name
+ : type_specifier identifier {
+ if ($1.type == EbtVoid) {
+ context->error(@2, "illegal use of type 'void'", $2.string->c_str());
+ context->recover();
+ }
+ if (context->reservedErrorCheck(@2, *$2.string))
+ context->recover();
+ TParameter param = {$2.string, new TType($1)};
+ $$.param = param;
+ }
+ | type_specifier identifier LEFT_BRACKET constant_expression RIGHT_BRACKET {
+ // Check that we can make an array out of this type
+ if (context->arrayTypeErrorCheck(@3, $1))
+ context->recover();
+
+ if (context->reservedErrorCheck(@2, *$2.string))
+ context->recover();
+
+ int size;
+ if (context->arraySizeErrorCheck(@3, $4, size))
+ context->recover();
+ $1.setArray(true, size);
+
+ TType* type = new TType($1);
+ TParameter param = { $2.string, type };
+ $$.param = param;
+ }
+ ;
+
+parameter_declaration
+ //
+ // The only parameter qualifier a parameter can have are
+ // IN_QUAL, OUT_QUAL, INOUT_QUAL, or CONST.
+ //
+
+ //
+ // Type + name
+ //
+ : type_qualifier parameter_qualifier parameter_declarator {
+ $$ = $3;
+ if (context->paramErrorCheck(@3, $1.qualifier, $2, $$.param.type))
+ context->recover();
+ }
+ | parameter_qualifier parameter_declarator {
+ $$ = $2;
+ if (context->parameterSamplerErrorCheck(@2, $1, *$2.param.type))
+ context->recover();
+ if (context->paramErrorCheck(@2, EvqTemporary, $1, $$.param.type))
+ context->recover();
+ }
+ //
+ // Only type
+ //
+ | type_qualifier parameter_qualifier parameter_type_specifier {
+ $$ = $3;
+ if (context->paramErrorCheck(@3, $1.qualifier, $2, $$.param.type))
+ context->recover();
+ }
+ | parameter_qualifier parameter_type_specifier {
+ $$ = $2;
+ if (context->parameterSamplerErrorCheck(@2, $1, *$2.param.type))
+ context->recover();
+ if (context->paramErrorCheck(@2, EvqTemporary, $1, $$.param.type))
+ context->recover();
+ }
+ ;
+
+parameter_qualifier
+ : /* empty */ {
+ $$ = EvqIn;
+ }
+ | IN_QUAL {
+ $$ = EvqIn;
+ }
+ | OUT_QUAL {
+ $$ = EvqOut;
+ }
+ | INOUT_QUAL {
+ $$ = EvqInOut;
+ }
+ ;
+
+parameter_type_specifier
+ : type_specifier {
+ TParameter param = { 0, new TType($1) };
+ $$.param = param;
+ }
+ ;
+
+init_declarator_list
+ : single_declaration {
+ $$ = $1;
+ }
+ | init_declarator_list COMMA identifier {
+ if ($1.type.type == EbtInvariant && !$3.symbol)
+ {
+ context->error(@3, "undeclared identifier declared as invariant", $3.string->c_str());
+ context->recover();
+ }
+
+ TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$3.string, TType($1.type), @3);
+ $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, symbol, @3);
+
+ if (context->structQualifierErrorCheck(@3, $$.type))
+ context->recover();
+
+ if (context->nonInitConstErrorCheck(@3, *$3.string, $$.type, false))
+ context->recover();
+
+ TVariable* variable = 0;
+ if (context->nonInitErrorCheck(@3, *$3.string, $$.type, variable))
+ context->recover();
+ if (symbol && variable)
+ symbol->setId(variable->getUniqueId());
+ }
+ | init_declarator_list COMMA identifier LEFT_BRACKET RIGHT_BRACKET {
+ if (context->structQualifierErrorCheck(@3, $1.type))
+ context->recover();
+
+ if (context->nonInitConstErrorCheck(@3, *$3.string, $1.type, true))
+ context->recover();
+
+ $$ = $1;
+
+ if (context->arrayTypeErrorCheck(@4, $1.type) || context->arrayQualifierErrorCheck(@4, $1.type))
+ context->recover();
+ else {
+ $1.type.setArray(true);
+ TVariable* variable;
+ if (context->arrayErrorCheck(@4, *$3.string, $1.type, variable))
+ context->recover();
+ }
+ }
+ | init_declarator_list COMMA identifier LEFT_BRACKET constant_expression RIGHT_BRACKET {
+ if (context->structQualifierErrorCheck(@3, $1.type))
+ context->recover();
+
+ if (context->nonInitConstErrorCheck(@3, *$3.string, $1.type, true))
+ context->recover();
+
+ $$ = $1;
+
+ if (context->arrayTypeErrorCheck(@4, $1.type) || context->arrayQualifierErrorCheck(@4, $1.type))
+ context->recover();
+ else {
+ int size;
+ if (context->arraySizeErrorCheck(@4, $5, size))
+ context->recover();
+ $1.type.setArray(true, size);
+ TVariable* variable = 0;
+ if (context->arrayErrorCheck(@4, *$3.string, $1.type, variable))
+ context->recover();
+ TType type = TType($1.type);
+ type.setArraySize(size);
+ $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, context->intermediate.addSymbol(variable ? variable->getUniqueId() : 0, *$3.string, type, @3), @3);
+ }
+ }
+ | init_declarator_list COMMA identifier EQUAL initializer {
+ if (context->structQualifierErrorCheck(@3, $1.type))
+ context->recover();
+
+ $$ = $1;
+
+ TIntermNode* intermNode;
+ if (!context->executeInitializer(@3, *$3.string, $1.type, $5, intermNode)) {
+ //
+ // build the intermediate representation
+ //
+ if (intermNode)
+ $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, intermNode, @4);
+ else
+ $$.intermAggregate = $1.intermAggregate;
+ } else {
+ context->recover();
+ $$.intermAggregate = 0;
+ }
+ }
+ ;
+
+single_declaration
+ : fully_specified_type {
+ $$.type = $1;
+ $$.intermAggregate = context->intermediate.makeAggregate(context->intermediate.addSymbol(0, "", TType($1), @1), @1);
+ }
+ | fully_specified_type identifier {
+ TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, TType($1), @2);
+ $$.intermAggregate = context->intermediate.makeAggregate(symbol, @2);
+
+ if (context->structQualifierErrorCheck(@2, $$.type))
+ context->recover();
+
+ if (context->nonInitConstErrorCheck(@2, *$2.string, $$.type, false))
+ context->recover();
+
+ $$.type = $1;
+
+ TVariable* variable = 0;
+ if (context->nonInitErrorCheck(@2, *$2.string, $$.type, variable))
+ context->recover();
+ if (variable && symbol)
+ symbol->setId(variable->getUniqueId());
+ }
+ | fully_specified_type identifier LEFT_BRACKET RIGHT_BRACKET {
+ context->error(@2, "unsized array declarations not supported", $2.string->c_str());
+ context->recover();
+
+ TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, TType($1), @2);
+ $$.intermAggregate = context->intermediate.makeAggregate(symbol, @2);
+ $$.type = $1;
+ }
+ | fully_specified_type identifier LEFT_BRACKET constant_expression RIGHT_BRACKET {
+ TType type = TType($1);
+ int size;
+ if (context->arraySizeErrorCheck(@2, $4, size))
+ context->recover();
+ type.setArraySize(size);
+ TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, type, @2);
+ $$.intermAggregate = context->intermediate.makeAggregate(symbol, @2);
+
+ if (context->structQualifierErrorCheck(@2, $1))
+ context->recover();
+
+ if (context->nonInitConstErrorCheck(@2, *$2.string, $1, true))
+ context->recover();
+
+ $$.type = $1;
+
+ if (context->arrayTypeErrorCheck(@3, $1) || context->arrayQualifierErrorCheck(@3, $1))
+ context->recover();
+ else {
+ int size;
+ if (context->arraySizeErrorCheck(@3, $4, size))
+ context->recover();
+
+ $1.setArray(true, size);
+ TVariable* variable = 0;
+ if (context->arrayErrorCheck(@3, *$2.string, $1, variable))
+ context->recover();
+ if (variable && symbol)
+ symbol->setId(variable->getUniqueId());
+ }
+ }
+ | fully_specified_type identifier EQUAL initializer {
+ if (context->structQualifierErrorCheck(@2, $1))
+ context->recover();
+
+ $$.type = $1;
+
+ TIntermNode* intermNode;
+ if (!context->executeInitializer(@2, *$2.string, $1, $4, intermNode)) {
+ //
+ // Build intermediate representation
+ //
+ if(intermNode)
+ $$.intermAggregate = context->intermediate.makeAggregate(intermNode, @3);
+ else
+ $$.intermAggregate = 0;
+ } else {
+ context->recover();
+ $$.intermAggregate = 0;
+ }
+ }
+ | INVARIANT IDENTIFIER {
+ VERTEX_ONLY("invariant declaration", @1);
+ if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "invariant varying"))
+ context->recover();
+ $$.type.setBasic(EbtInvariant, EvqInvariantVaryingOut, @2);
+ if (!$2.symbol)
+ {
+ context->error(@2, "undeclared identifier declared as invariant", $2.string->c_str());
+ context->recover();
+
+ $$.intermAggregate = 0;
+ }
+ else
+ {
+ TIntermSymbol *symbol = context->intermediate.addSymbol(0, *$2.string, TType($$.type), @2);
+ $$.intermAggregate = context->intermediate.makeAggregate(symbol, @2);
+ }
+ }
+ ;
+
+fully_specified_type
+ : type_specifier {
+ $$ = $1;
+
+ if ($1.array) {
+ context->error(@1, "not supported", "first-class array");
+ context->recover();
+ $1.setArray(false);
+ }
+ }
+ | type_qualifier type_specifier {
+ if ($2.array) {
+ context->error(@2, "not supported", "first-class array");
+ context->recover();
+ $2.setArray(false);
+ }
+
+ if ($1.qualifier == EvqAttribute &&
+ ($2.type == EbtBool || $2.type == EbtInt)) {
+ context->error(@2, "cannot be bool or int", getQualifierString($1.qualifier));
+ context->recover();
+ }
+ if (($1.qualifier == EvqVaryingIn || $1.qualifier == EvqVaryingOut) &&
+ ($2.type == EbtBool || $2.type == EbtInt)) {
+ context->error(@2, "cannot be bool or int", getQualifierString($1.qualifier));
+ context->recover();
+ }
+ $$ = $2;
+ $$.qualifier = $1.qualifier;
+ }
+ ;
+
+type_qualifier
+ : CONST_QUAL {
+ $$.setBasic(EbtVoid, EvqConst, @1);
+ }
+ | ATTRIBUTE {
+ VERTEX_ONLY("attribute", @1);
+ if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "attribute"))
+ context->recover();
+ $$.setBasic(EbtVoid, EvqAttribute, @1);
+ }
+ | VARYING {
+ if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "varying"))
+ context->recover();
+ if (context->shaderType == SH_VERTEX_SHADER)
+ $$.setBasic(EbtVoid, EvqVaryingOut, @1);
+ else
+ $$.setBasic(EbtVoid, EvqVaryingIn, @1);
+ }
+ | INVARIANT VARYING {
+ if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "invariant varying"))
+ context->recover();
+ if (context->shaderType == SH_VERTEX_SHADER)
+ $$.setBasic(EbtVoid, EvqInvariantVaryingOut, @1);
+ else
+ $$.setBasic(EbtVoid, EvqInvariantVaryingIn, @1);
+ }
+ | UNIFORM {
+ if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "uniform"))
+ context->recover();
+ $$.setBasic(EbtVoid, EvqUniform, @1);
+ }
+ ;
+
+type_specifier
+ : type_specifier_no_prec {
+ $$ = $1;
+
+ if ($$.precision == EbpUndefined) {
+ $$.precision = context->symbolTable.getDefaultPrecision($1.type);
+ if (context->precisionErrorCheck(@1, $$.precision, $1.type)) {
+ context->recover();
+ }
+ }
+ }
+ | precision_qualifier type_specifier_no_prec {
+ $$ = $2;
+ $$.precision = $1;
+ }
+ ;
+
+precision_qualifier
+ : HIGH_PRECISION {
+ $$ = EbpHigh;
+ }
+ | MEDIUM_PRECISION {
+ $$ = EbpMedium;
+ }
+ | LOW_PRECISION {
+ $$ = EbpLow;
+ }
+ ;
+
+type_specifier_no_prec
+ : type_specifier_nonarray {
+ $$ = $1;
+ }
+ | type_specifier_nonarray LEFT_BRACKET constant_expression RIGHT_BRACKET {
+ $$ = $1;
+
+ if (context->arrayTypeErrorCheck(@2, $1))
+ context->recover();
+ else {
+ int size;
+ if (context->arraySizeErrorCheck(@2, $3, size))
+ context->recover();
+ $$.setArray(true, size);
+ }
+ }
+ ;
+
+type_specifier_nonarray
+ : VOID_TYPE {
+ TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ $$.setBasic(EbtVoid, qual, @1);
+ }
+ | FLOAT_TYPE {
+ TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ $$.setBasic(EbtFloat, qual, @1);
+ }
+ | INT_TYPE {
+ TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ $$.setBasic(EbtInt, qual, @1);
+ }
+ | BOOL_TYPE {
+ TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ $$.setBasic(EbtBool, qual, @1);
+ }
+ | VEC2 {
+ TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ $$.setBasic(EbtFloat, qual, @1);
+ $$.setAggregate(2);
+ }
+ | VEC3 {
+ TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ $$.setBasic(EbtFloat, qual, @1);
+ $$.setAggregate(3);
+ }
+ | VEC4 {
+ TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ $$.setBasic(EbtFloat, qual, @1);
+ $$.setAggregate(4);
+ }
+ | BVEC2 {
+ TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ $$.setBasic(EbtBool, qual, @1);
+ $$.setAggregate(2);
+ }
+ | BVEC3 {
+ TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ $$.setBasic(EbtBool, qual, @1);
+ $$.setAggregate(3);
+ }
+ | BVEC4 {
+ TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ $$.setBasic(EbtBool, qual, @1);
+ $$.setAggregate(4);
+ }
+ | IVEC2 {
+ TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ $$.setBasic(EbtInt, qual, @1);
+ $$.setAggregate(2);
+ }
+ | IVEC3 {
+ TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ $$.setBasic(EbtInt, qual, @1);
+ $$.setAggregate(3);
+ }
+ | IVEC4 {
+ TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ $$.setBasic(EbtInt, qual, @1);
+ $$.setAggregate(4);
+ }
+ | MATRIX2 {
+ TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ $$.setBasic(EbtFloat, qual, @1);
+ $$.setAggregate(2, true);
+ }
+ | MATRIX3 {
+ TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ $$.setBasic(EbtFloat, qual, @1);
+ $$.setAggregate(3, true);
+ }
+ | MATRIX4 {
+ TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ $$.setBasic(EbtFloat, qual, @1);
+ $$.setAggregate(4, true);
+ }
+ | SAMPLER2D {
+ TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ $$.setBasic(EbtSampler2D, qual, @1);
+ }
+ | SAMPLERCUBE {
+ TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ $$.setBasic(EbtSamplerCube, qual, @1);
+ }
+ | SAMPLER_EXTERNAL_OES {
+ if (!context->supportsExtension("GL_OES_EGL_image_external")) {
+ context->error(@1, "unsupported type", "samplerExternalOES");
+ context->recover();
+ }
+ TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ $$.setBasic(EbtSamplerExternalOES, qual, @1);
+ }
+ | SAMPLER2DRECT {
+ if (!context->supportsExtension("GL_ARB_texture_rectangle")) {
+ context->error(@1, "unsupported type", "sampler2DRect");
+ context->recover();
+ }
+ TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ $$.setBasic(EbtSampler2DRect, qual, @1);
+ }
+ | struct_specifier {
+ $$ = $1;
+ $$.qualifier = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ }
+ | TYPE_NAME {
+ //
+ // This is for user defined type names. The lexical phase looked up the
+ // type.
+ //
+ TType& structure = static_cast<TVariable*>($1.symbol)->getType();
+ TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ $$.setBasic(EbtStruct, qual, @1);
+ $$.userDef = &structure;
+ }
+ ;
+
+struct_specifier
+ : STRUCT identifier LEFT_BRACE { if (context->enterStructDeclaration(@2, *$2.string)) context->recover(); } struct_declaration_list RIGHT_BRACE {
+ if (context->reservedErrorCheck(@2, *$2.string))
+ context->recover();
+
+ TType* structure = new TType(new TStructure($2.string, $5));
+ TVariable* userTypeDef = new TVariable($2.string, *structure, true);
+ if (! context->symbolTable.insert(*userTypeDef)) {
+ context->error(@2, "redefinition", $2.string->c_str(), "struct");
+ context->recover();
+ }
+ $$.setBasic(EbtStruct, EvqTemporary, @1);
+ $$.userDef = structure;
+ context->exitStructDeclaration();
+ }
+ | STRUCT LEFT_BRACE { if (context->enterStructDeclaration(@2, *$2.string)) context->recover(); } struct_declaration_list RIGHT_BRACE {
+ TType* structure = new TType(new TStructure(NewPoolTString(""), $4));
+ $$.setBasic(EbtStruct, EvqTemporary, @1);
+ $$.userDef = structure;
+ context->exitStructDeclaration();
+ }
+ ;
+
+struct_declaration_list
+ : struct_declaration {
+ $$ = $1;
+ }
+ | struct_declaration_list struct_declaration {
+ $$ = $1;
+ for (size_t i = 0; i < $2->size(); ++i) {
+ TField* field = (*$2)[i];
+ for (size_t j = 0; j < $$->size(); ++j) {
+ if ((*$$)[j]->name() == field->name()) {
+ context->error(@2, "duplicate field name in structure:", "struct", field->name().c_str());
+ context->recover();
+ }
+ }
+ $$->push_back(field);
+ }
+ }
+ ;
+
+struct_declaration
+ : type_specifier struct_declarator_list SEMICOLON {
+ $$ = $2;
+
+ if (context->voidErrorCheck(@1, (*$2)[0]->name(), $1)) {
+ context->recover();
+ }
+ for (unsigned int i = 0; i < $$->size(); ++i) {
+ //
+ // Careful not to replace already known aspects of type, like array-ness
+ //
+ TType* type = (*$$)[i]->type();
+ type->setBasicType($1.type);
+ type->setNominalSize($1.size);
+ type->setMatrix($1.matrix);
+ type->setPrecision($1.precision);
+
+ // don't allow arrays of arrays
+ if (type->isArray()) {
+ if (context->arrayTypeErrorCheck(@1, $1))
+ context->recover();
+ }
+ if ($1.array)
+ type->setArraySize($1.arraySize);
+ if ($1.userDef)
+ type->setStruct($1.userDef->getStruct());
+
+ if (context->structNestingErrorCheck(@1, *(*$$)[i]))
+ context->recover();
+ }
+ }
+ ;
+
+struct_declarator_list
+ : struct_declarator {
+ $$ = NewPoolTFieldList();
+ $$->push_back($1);
+ }
+ | struct_declarator_list COMMA struct_declarator {
+ $$->push_back($3);
+ }
+ ;
+
+struct_declarator
+ : identifier {
+ if (context->reservedErrorCheck(@1, *$1.string))
+ context->recover();
+
+ TType* type = new TType(EbtVoid, EbpUndefined);
+ $$ = new TField(type, $1.string);
+ }
+ | identifier LEFT_BRACKET constant_expression RIGHT_BRACKET {
+ if (context->reservedErrorCheck(@1, *$1.string))
+ context->recover();
+
+ TType* type = new TType(EbtVoid, EbpUndefined);
+ int size = 0;
+ if (context->arraySizeErrorCheck(@3, $3, size))
+ context->recover();
+ type->setArraySize(size);
+
+ $$ = new TField(type, $1.string);
+ }
+ ;
+
+initializer
+ : assignment_expression { $$ = $1; }
+ ;
+
+declaration_statement
+ : declaration { $$ = $1; }
+ ;
+
+statement
+ : compound_statement { $$ = $1; }
+ | simple_statement { $$ = $1; }
+ ;
+
+// Grammar Note: No labeled statements; 'goto' is not supported.
+
+simple_statement
+ : declaration_statement { $$ = $1; }
+ | expression_statement { $$ = $1; }
+ | selection_statement { $$ = $1; }
+ | iteration_statement { $$ = $1; }
+ | jump_statement { $$ = $1; }
+ ;
+
+compound_statement
+ : LEFT_BRACE RIGHT_BRACE { $$ = 0; }
+ | LEFT_BRACE { context->symbolTable.push(); } statement_list { context->symbolTable.pop(); } RIGHT_BRACE {
+ if ($3 != 0) {
+ $3->setOp(EOpSequence);
+ $3->setLine(@$);
+ }
+ $$ = $3;
+ }
+ ;
+
+statement_no_new_scope
+ : compound_statement_no_new_scope { $$ = $1; }
+ | simple_statement { $$ = $1; }
+ ;
+
+statement_with_scope
+ : { context->symbolTable.push(); } compound_statement_no_new_scope { context->symbolTable.pop(); $$ = $2; }
+ | { context->symbolTable.push(); } simple_statement { context->symbolTable.pop(); $$ = $2; }
+ ;
+
+compound_statement_no_new_scope
+ // Statement that doesn't create a new scope, for selection_statement, iteration_statement
+ : LEFT_BRACE RIGHT_BRACE {
+ $$ = 0;
+ }
+ | LEFT_BRACE statement_list RIGHT_BRACE {
+ if ($2) {
+ $2->setOp(EOpSequence);
+ $2->setLine(@$);
+ }
+ $$ = $2;
+ }
+ ;
+
+statement_list
+ : statement {
+ $$ = context->intermediate.makeAggregate($1, @$);
+ }
+ | statement_list statement {
+ $$ = context->intermediate.growAggregate($1, $2, @$);
+ }
+ ;
+
+expression_statement
+ : SEMICOLON { $$ = 0; }
+ | expression SEMICOLON { $$ = static_cast<TIntermNode*>($1); }
+ ;
+
+selection_statement
+ : IF LEFT_PAREN expression RIGHT_PAREN selection_rest_statement {
+ if (context->boolErrorCheck(@1, $3))
+ context->recover();
+ $$ = context->intermediate.addSelection($3, $5, @1);
+ }
+ ;
+
+selection_rest_statement
+ : statement_with_scope ELSE statement_with_scope {
+ $$.node1 = $1;
+ $$.node2 = $3;
+ }
+ | statement_with_scope {
+ $$.node1 = $1;
+ $$.node2 = 0;
+ }
+ ;
+
+// Grammar Note: No 'switch'. Switch statements not supported.
+
+condition
+ // In 1996 c++ draft, conditions can include single declarations
+ : expression {
+ $$ = $1;
+ if (context->boolErrorCheck($1->getLine(), $1))
+ context->recover();
+ }
+ | fully_specified_type identifier EQUAL initializer {
+ TIntermNode* intermNode;
+ if (context->structQualifierErrorCheck(@2, $1))
+ context->recover();
+ if (context->boolErrorCheck(@2, $1))
+ context->recover();
+
+ if (!context->executeInitializer(@2, *$2.string, $1, $4, intermNode))
+ $$ = $4;
+ else {
+ context->recover();
+ $$ = 0;
+ }
+ }
+ ;
+
+iteration_statement
+ : WHILE LEFT_PAREN { context->symbolTable.push(); ++context->loopNestingLevel; } condition RIGHT_PAREN statement_no_new_scope {
+ context->symbolTable.pop();
+ $$ = context->intermediate.addLoop(ELoopWhile, 0, $4, 0, $6, @1);
+ --context->loopNestingLevel;
+ }
+ | DO { ++context->loopNestingLevel; } statement_with_scope WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON {
+ if (context->boolErrorCheck(@8, $6))
+ context->recover();
+
+ $$ = context->intermediate.addLoop(ELoopDoWhile, 0, $6, 0, $3, @4);
+ --context->loopNestingLevel;
+ }
+ | FOR LEFT_PAREN { context->symbolTable.push(); ++context->loopNestingLevel; } for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope {
+ context->symbolTable.pop();
+ $$ = context->intermediate.addLoop(ELoopFor, $4, reinterpret_cast<TIntermTyped*>($5.node1), reinterpret_cast<TIntermTyped*>($5.node2), $7, @1);
+ --context->loopNestingLevel;
+ }
+ ;
+
+for_init_statement
+ : expression_statement {
+ $$ = $1;
+ }
+ | declaration_statement {
+ $$ = $1;
+ }
+ ;
+
+conditionopt
+ : condition {
+ $$ = $1;
+ }
+ | /* May be null */ {
+ $$ = 0;
+ }
+ ;
+
+for_rest_statement
+ : conditionopt SEMICOLON {
+ $$.node1 = $1;
+ $$.node2 = 0;
+ }
+ | conditionopt SEMICOLON expression {
+ $$.node1 = $1;
+ $$.node2 = $3;
+ }
+ ;
+
+jump_statement
+ : CONTINUE SEMICOLON {
+ if (context->loopNestingLevel <= 0) {
+ context->error(@1, "continue statement only allowed in loops", "");
+ context->recover();
+ }
+ $$ = context->intermediate.addBranch(EOpContinue, @1);
+ }
+ | BREAK SEMICOLON {
+ if (context->loopNestingLevel <= 0) {
+ context->error(@1, "break statement only allowed in loops", "");
+ context->recover();
+ }
+ $$ = context->intermediate.addBranch(EOpBreak, @1);
+ }
+ | RETURN SEMICOLON {
+ $$ = context->intermediate.addBranch(EOpReturn, @1);
+ if (context->currentFunctionType->getBasicType() != EbtVoid) {
+ context->error(@1, "non-void function must return a value", "return");
+ context->recover();
+ }
+ }
+ | RETURN expression SEMICOLON {
+ $$ = context->intermediate.addBranch(EOpReturn, $2, @1);
+ context->functionReturnsValue = true;
+ if (context->currentFunctionType->getBasicType() == EbtVoid) {
+ context->error(@1, "void function cannot return a value", "return");
+ context->recover();
+ } else if (*(context->currentFunctionType) != $2->getType()) {
+ context->error(@1, "function return is not matching type:", "return");
+ context->recover();
+ }
+ }
+ | DISCARD SEMICOLON {
+ FRAG_ONLY("discard", @1);
+ $$ = context->intermediate.addBranch(EOpKill, @1);
+ }
+ ;
+
+// Grammar Note: No 'goto'. Gotos are not supported.
+
+translation_unit
+ : external_declaration {
+ $$ = $1;
+ context->treeRoot = $$;
+ }
+ | translation_unit external_declaration {
+ $$ = context->intermediate.growAggregate($1, $2, @$);
+ context->treeRoot = $$;
+ }
+ ;
+
+external_declaration
+ : function_definition {
+ $$ = $1;
+ }
+ | declaration {
+ $$ = $1;
+ }
+ ;
+
+function_definition
+ : function_prototype {
+ TFunction* function = $1.function;
+
+ const TSymbol *builtIn = context->symbolTable.findBuiltIn(function->getMangledName());
+
+ if (builtIn)
+ {
+ context->error(@1, "built-in functions cannot be redefined", function->getName().c_str());
+ context->recover();
+ }
+
+ TFunction* prevDec = static_cast<TFunction*>(context->symbolTable.find(function->getMangledName()));
+ //
+ // Note: 'prevDec' could be 'function' if this is the first time we've seen function
+ // as it would have just been put in the symbol table. Otherwise, we're looking up
+ // an earlier occurance.
+ //
+ if (prevDec->isDefined()) {
+ //
+ // Then this function already has a body.
+ //
+ context->error(@1, "function already has a body", function->getName().c_str());
+ context->recover();
+ }
+ prevDec->setDefined();
+
+ //
+ // Raise error message if main function takes any parameters or return anything other than void
+ //
+ if (function->getName() == "main") {
+ if (function->getParamCount() > 0) {
+ context->error(@1, "function cannot take any parameter(s)", function->getName().c_str());
+ context->recover();
+ }
+ if (function->getReturnType().getBasicType() != EbtVoid) {
+ context->error(@1, "", function->getReturnType().getBasicString(), "main function cannot return a value");
+ context->recover();
+ }
+ }
+
+ //
+ // Remember the return type for later checking for RETURN statements.
+ //
+ context->currentFunctionType = &(prevDec->getReturnType());
+ context->functionReturnsValue = false;
+
+ //
+ // Insert parameters into the symbol table.
+ // If the parameter has no name, it's not an error, just don't insert it
+ // (could be used for unused args).
+ //
+ // Also, accumulate the list of parameters into the HIL, so lower level code
+ // knows where to find parameters.
+ //
+ TIntermAggregate* paramNodes = new TIntermAggregate;
+ for (size_t i = 0; i < function->getParamCount(); i++) {
+ const TParameter& param = function->getParam(i);
+ if (param.name != 0) {
+ TVariable *variable = new TVariable(param.name, *param.type);
+ //
+ // Insert the parameters with name in the symbol table.
+ //
+ if (! context->symbolTable.insert(*variable)) {
+ context->error(@1, "redefinition", variable->getName().c_str());
+ context->recover();
+ delete variable;
+ }
+
+ //
+ // Add the parameter to the HIL
+ //
+ paramNodes = context->intermediate.growAggregate(
+ paramNodes,
+ context->intermediate.addSymbol(variable->getUniqueId(),
+ variable->getName(),
+ variable->getType(),
+ @1),
+ @1);
+ } else {
+ paramNodes = context->intermediate.growAggregate(paramNodes, context->intermediate.addSymbol(0, "", *param.type, @1), @1);
+ }
+ }
+ context->intermediate.setAggregateOperator(paramNodes, EOpParameters, @1);
+ $1.intermAggregate = paramNodes;
+ context->loopNestingLevel = 0;
+ }
+ compound_statement_no_new_scope {
+ //?? Check that all paths return a value if return type != void ?
+ // May be best done as post process phase on intermediate code
+ if (context->currentFunctionType->getBasicType() != EbtVoid && ! context->functionReturnsValue) {
+ context->error(@1, "function does not return a value:", "", $1.function->getName().c_str());
+ context->recover();
+ }
+
+ $$ = context->intermediate.growAggregate($1.intermAggregate, $3, @$);
+ context->intermediate.setAggregateOperator($$, EOpFunction, @1);
+ $$->getAsAggregate()->setName($1.function->getMangledName().c_str());
+ $$->getAsAggregate()->setType($1.function->getReturnType());
+
+ // store the pragma information for debug and optimize and other vendor specific
+ // information. This information can be queried from the parse tree
+ $$->getAsAggregate()->setOptimize(context->pragma().optimize);
+ $$->getAsAggregate()->setDebug(context->pragma().debug);
+
+ context->symbolTable.pop();
+ }
+ ;
+
+%%
+
+int glslang_parse(TParseContext* context) {
+ return yyparse(context);
+}
</ins></span></pre></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorglslang_lexcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/glslang_lex.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/glslang_lex.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/glslang_lex.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,2978 @@
</span><ins>+#line 17 "./glslang.l"
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// This file is auto-generated by generate_parser.sh. DO NOT EDIT!
+
+// Ignore errors in auto-generated code.
+#if defined(__GNUC__)
+#pragma GCC diagnostic ignored "-Wunused-function"
+#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wswitch-enum"
+#elif defined(_MSC_VER)
+#pragma warning(disable: 4065)
+#pragma warning(disable: 4189)
+#pragma warning(disable: 4505)
+#pragma warning(disable: 4701)
+#endif
+
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunknown-pragmas"
+#pragma clang diagnostic ignored "-Wdeprecated-register"
+#endif
+
+#line 25 "./glslang_lex.cpp"
+
+#define YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 37
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types.
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t;
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX (4294967295U)
+#endif
+
+#endif /* ! C99 */
+
+#endif /* ! FLEXINT_H */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else /* ! __cplusplus */
+
+/* C99 requires __STDC__ to be defined as 1. */
+#if defined (__STDC__)
+
+#define YY_USE_CONST
+
+#endif /* defined (__STDC__) */
+#endif /* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index. If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* An opaque pointer. */
+#ifndef YY_TYPEDEF_YY_SCANNER_T
+#define YY_TYPEDEF_YY_SCANNER_T
+typedef void* yyscan_t;
+#endif
+
+/* For convenience, these vars (plus the bison vars far below)
+ are macros in the reentrant scanner. */
+#define yyin yyg->yyin_r
+#define yyout yyg->yyout_r
+#define yyextra yyg->yyextra_r
+#define yyleng yyg->yyleng_r
+#define yytext yyg->yytext_r
+#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)
+#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
+#define yy_flex_debug yyg->yy_flex_debug_r
+
+/* Enter a start condition. This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN yyg->yy_start = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state. The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START ((yyg->yy_start - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart(yyin ,yyscanner )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#define YY_BUF_SIZE 16384
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+ /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires
+ * access to the local variable yy_act. Since yyless() is a macro, it would break
+ * existing scanners that call yyless() from OUTSIDE yylex.
+ * One obvious solution it to make yy_act a global. I tried that, and saw
+ * a 5% performance hit in a non-yylineno scanner, because yy_act is
+ * normally declared as a register variable-- so it is not worth it.
+ */
+ #define YY_LESS_LINENO(n) \
+ do { \
+ int yyl;\
+ for ( yyl = n; yyl < yyleng; ++yyl )\
+ if ( yytext[yyl] == '\n' )\
+ --yylineno;\
+ }while(0)
+
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ int yyless_macro_arg = (n); \
+ YY_LESS_LINENO(yyless_macro_arg);\
+ *yy_cp = yyg->yy_hold_char; \
+ YY_RESTORE_YY_MORE_OFFSET \
+ yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+ YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+ } \
+ while ( 0 )
+
+#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner )
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+ {
+ FILE *yy_input_file;
+
+ char *yy_ch_buf; /* input buffer */
+ char *yy_buf_pos; /* current position in input buffer */
+
+ /* Size of input buffer in bytes, not including room for EOB
+ * characters.
+ */
+ yy_size_t yy_buf_size;
+
+ /* Number of characters read into yy_ch_buf, not including EOB
+ * characters.
+ */
+ yy_size_t yy_n_chars;
+
+ /* Whether we "own" the buffer - i.e., we know we created it,
+ * and can realloc() it to grow it, and should free() it to
+ * delete it.
+ */
+ int yy_is_our_buffer;
+
+ /* Whether this is an "interactive" input source; if so, and
+ * if we're using stdio for input, then we want to use getc()
+ * instead of fread(), to make sure we stop fetching input after
+ * each newline.
+ */
+ int yy_is_interactive;
+
+ /* Whether we're considered to be at the beginning of a line.
+ * If so, '^' rules will be active on the next match, otherwise
+ * not.
+ */
+ int yy_at_bol;
+
+ int yy_bs_lineno; /**< The line count. */
+ int yy_bs_column; /**< The column count. */
+
+ /* Whether to try to fill the input buffer when we reach the
+ * end of it.
+ */
+ int yy_fill_buffer;
+
+ int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+ /* When an EOF's been seen but there's still some text to process
+ * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+ * shouldn't try reading from the input source any more. We might
+ * still have a bunch of tokens to match, though, because of
+ * possible backing-up.
+ *
+ * When we actually see the EOF, we change the status to "new"
+ * (via yyrestart()), so that the user can continue scanning by
+ * just pointing yyin at a new input file.
+ */
+#define YY_BUFFER_EOF_PENDING 2
+
+ };
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \
+ ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \
+ : NULL)
+
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]
+
+void yyrestart (FILE *input_file ,yyscan_t yyscanner );
+void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+YY_BUFFER_STATE yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner );
+void yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+void yypop_buffer_state (yyscan_t yyscanner );
+
+static void yyensure_buffer_stack (yyscan_t yyscanner );
+static void yy_load_buffer_state (yyscan_t yyscanner );
+static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner );
+
+#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER ,yyscanner)
+
+YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,yy_size_t len ,yyscan_t yyscanner );
+
+void *yyalloc (yy_size_t ,yyscan_t yyscanner );
+void *yyrealloc (void *,yy_size_t ,yyscan_t yyscanner );
+void yyfree (void * ,yyscan_t yyscanner );
+
+#define yy_new_buffer yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){ \
+ yyensure_buffer_stack (yyscanner); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+ }
+
+#define yy_set_bol(at_bol) \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){\
+ yyensure_buffer_stack (yyscanner); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+ }
+
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* Begin user sect3 */
+
+#define yywrap(yyscanner) 1
+#define YY_SKIP_YYWRAP
+
+typedef unsigned char YY_CHAR;
+
+typedef int yy_state_type;
+
+#define yytext_ptr yytext_r
+
+static yy_state_type yy_get_previous_state (yyscan_t yyscanner );
+static yy_state_type yy_try_NUL_trans (yy_state_type current_state ,yyscan_t yyscanner);
+static int yy_get_next_buffer (yyscan_t yyscanner );
+static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+ yyg->yytext_ptr = yy_bp; \
+ yyleng = (size_t) (yy_cp - yy_bp); \
+ yyg->yy_hold_char = *yy_cp; \
+ *yy_cp = '\0'; \
+ yyg->yy_c_buf_p = yy_cp;
+
+#define YY_NUM_RULES 147
+#define YY_END_OF_BUFFER 148
+/* This struct is not used in this scanner,
+ but its presence is necessary. */
+struct yy_trans_info
+ {
+ flex_int32_t yy_verify;
+ flex_int32_t yy_nxt;
+ };
+static yyconst flex_int16_t yy_accept[443] =
+ { 0,
+ 0, 0, 148, 146, 145, 145, 132, 138, 143, 127,
+ 128, 136, 135, 124, 133, 131, 137, 96, 96, 125,
+ 121, 139, 126, 140, 144, 93, 129, 130, 142, 93,
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 122,
+ 141, 123, 134, 118, 104, 123, 112, 107, 102, 110,
+ 100, 111, 101, 99, 103, 98, 95, 96, 0, 0,
+ 130, 122, 129, 119, 115, 117, 116, 120, 93, 108,
+ 114, 93, 93, 93, 93, 93, 93, 93, 93, 93,
+ 93, 12, 93, 93, 93, 93, 93, 93, 93, 93,
+
+ 93, 93, 93, 93, 93, 15, 17, 93, 93, 93,
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
+ 93, 93, 93, 93, 109, 113, 0, 98, 0, 0,
+ 97, 94, 105, 106, 45, 93, 93, 93, 93, 93,
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
+ 93, 93, 93, 13, 93, 93, 93, 93, 93, 93,
+ 93, 93, 21, 93, 93, 93, 93, 93, 93, 93,
+ 93, 18, 93, 93, 93, 93, 93, 93, 93, 93,
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
+
+ 93, 93, 93, 93, 93, 0, 99, 0, 98, 93,
+ 23, 93, 93, 90, 93, 93, 93, 93, 93, 93,
+ 93, 16, 48, 93, 93, 93, 64, 93, 93, 53,
+ 68, 93, 93, 93, 93, 93, 93, 93, 93, 65,
+ 4, 28, 29, 30, 93, 93, 93, 93, 93, 93,
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
+ 51, 24, 93, 93, 93, 93, 93, 93, 31, 32,
+ 33, 22, 93, 93, 93, 10, 37, 38, 39, 46,
+ 7, 93, 93, 93, 93, 77, 78, 79, 93, 25,
+ 69, 20, 80, 81, 82, 2, 74, 75, 76, 93,
+
+ 19, 72, 93, 93, 34, 35, 36, 93, 93, 93,
+ 93, 93, 93, 93, 93, 93, 66, 93, 93, 93,
+ 93, 93, 93, 93, 93, 47, 93, 92, 93, 93,
+ 14, 93, 93, 93, 93, 67, 61, 56, 93, 93,
+ 93, 93, 93, 73, 52, 93, 59, 27, 93, 89,
+ 60, 44, 71, 54, 93, 93, 93, 93, 93, 93,
+ 93, 93, 55, 26, 93, 93, 93, 3, 93, 93,
+ 93, 93, 93, 49, 8, 93, 9, 93, 93, 11,
+ 62, 93, 93, 93, 57, 93, 93, 93, 93, 93,
+ 93, 50, 70, 58, 6, 63, 1, 91, 5, 83,
+
+ 40, 84, 93, 93, 93, 93, 93, 93, 93, 93,
+ 93, 93, 93, 93, 41, 93, 93, 93, 93, 93,
+ 93, 93, 43, 93, 87, 93, 93, 93, 93, 93,
+ 85, 93, 86, 93, 93, 93, 93, 93, 93, 42,
+ 88, 0
+ } ;
+
+static yyconst flex_int32_t yy_ec[256] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
+ 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 4, 1, 1, 1, 5, 6, 1, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 20, 20, 21, 21, 22, 23, 24,
+ 25, 26, 27, 1, 28, 28, 29, 30, 31, 28,
+ 32, 32, 32, 32, 32, 32, 32, 32, 33, 32,
+ 32, 34, 35, 32, 32, 32, 32, 36, 32, 32,
+ 37, 1, 38, 39, 32, 1, 40, 41, 42, 43,
+
+ 44, 45, 46, 47, 48, 32, 49, 50, 51, 52,
+ 53, 54, 32, 55, 56, 57, 58, 59, 60, 61,
+ 62, 63, 64, 65, 66, 67, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1
+ } ;
+
+static yyconst flex_int32_t yy_meta[68] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 2, 2, 2, 2, 2, 2,
+ 2, 1, 1, 1, 1, 1, 1, 2, 2, 2,
+ 2, 3, 3, 3, 3, 3, 1, 1, 1, 2,
+ 2, 2, 2, 2, 2, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 1, 1, 1, 1
+ } ;
+
+static yyconst flex_int16_t yy_base[445] =
+ { 0,
+ 0, 0, 587, 588, 588, 588, 561, 43, 64, 588,
+ 588, 560, 61, 588, 60, 58, 559, 77, 86, 557,
+ 588, 104, 557, 55, 588, 0, 588, 588, 75, 26,
+ 57, 82, 83, 73, 93, 528, 97, 95, 527, 44,
+ 71, 521, 104, 534, 110, 116, 35, 111, 530, 588,
+ 114, 588, 588, 588, 588, 588, 588, 588, 588, 588,
+ 588, 588, 588, 165, 588, 172, 202, 211, 233, 0,
+ 588, 588, 588, 551, 588, 588, 588, 550, 0, 588,
+ 588, 523, 516, 519, 527, 526, 513, 528, 515, 521,
+ 509, 506, 519, 506, 503, 503, 509, 497, 108, 502,
+
+ 512, 498, 504, 507, 508, 0, 145, 507, 113, 493,
+ 506, 497, 499, 489, 503, 500, 502, 485, 490, 487,
+ 476, 157, 484, 489, 485, 487, 476, 479, 118, 484,
+ 476, 488, 70, 481, 588, 588, 246, 253, 270, 219,
+ 283, 0, 588, 588, 0, 473, 477, 486, 483, 467,
+ 467, 119, 482, 479, 479, 477, 474, 466, 472, 459,
+ 470, 456, 472, 0, 469, 457, 464, 461, 465, 458,
+ 447, 446, 459, 462, 459, 454, 445, 188, 450, 453,
+ 444, 441, 445, 451, 442, 433, 436, 434, 444, 430,
+ 428, 441, 427, 429, 426, 437, 436, 124, 431, 426,
+
+ 415, 258, 433, 435, 424, 290, 297, 304, 311, 425,
+ 0, 423, 275, 0, 415, 413, 421, 410, 427, 416,
+ 316, 0, 0, 410, 420, 420, 0, 405, 319, 0,
+ 0, 407, 322, 408, 402, 401, 402, 401, 325, 0,
+ 0, 0, 0, 0, 397, 398, 403, 394, 407, 402,
+ 401, 393, 397, 389, 392, 396, 401, 387, 399, 390,
+ 0, 0, 396, 385, 385, 390, 389, 386, 0, 0,
+ 0, 0, 376, 388, 390, 0, 0, 0, 0, 0,
+ 0, 378, 379, 373, 383, 0, 0, 0, 374, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 381,
+
+ 0, 0, 379, 375, 0, 0, 0, 371, 367, 372,
+ 362, 375, 361, 374, 363, 370, 0, 368, 370, 354,
+ 356, 362, 368, 363, 351, 0, 353, 0, 352, 355,
+ 0, 344, 343, 343, 356, 0, 358, 0, 357, 356,
+ 341, 354, 341, 0, 0, 344, 0, 0, 336, 0,
+ 0, 0, 0, 0, 333, 344, 337, 343, 340, 335,
+ 327, 339, 0, 0, 332, 339, 328, 0, 337, 334,
+ 324, 329, 332, 0, 0, 332, 0, 330, 329, 0,
+ 0, 328, 314, 326, 0, 317, 338, 337, 336, 307,
+ 303, 0, 0, 0, 0, 0, 0, 0, 0, 328,
+
+ 166, 325, 316, 299, 308, 310, 306, 308, 307, 306,
+ 309, 306, 256, 253, 0, 228, 238, 222, 235, 203,
+ 207, 204, 212, 191, 0, 201, 165, 167, 153, 161,
+ 0, 170, 0, 175, 151, 141, 100, 114, 59, 0,
+ 0, 588, 359, 113
+ } ;
+
+static yyconst flex_int16_t yy_def[445] =
+ { 0,
+ 442, 1, 442, 442, 442, 442, 442, 442, 442, 442,
+ 442, 442, 442, 442, 442, 442, 442, 442, 442, 442,
+ 442, 442, 442, 442, 442, 443, 442, 442, 442, 443,
+ 443, 443, 443, 443, 443, 443, 443, 443, 443, 443,
+ 443, 443, 443, 443, 443, 443, 443, 443, 443, 442,
+ 442, 442, 442, 442, 442, 442, 442, 442, 442, 442,
+ 442, 442, 442, 442, 442, 442, 442, 442, 442, 444,
+ 442, 442, 442, 442, 442, 442, 442, 442, 443, 442,
+ 442, 443, 443, 443, 443, 443, 443, 443, 443, 443,
+ 443, 443, 443, 443, 443, 443, 443, 443, 443, 443,
+
+ 443, 443, 443, 443, 443, 443, 443, 443, 443, 443,
+ 443, 443, 443, 443, 443, 443, 443, 443, 443, 443,
+ 443, 443, 443, 443, 443, 443, 443, 443, 443, 443,
+ 443, 443, 443, 443, 442, 442, 442, 442, 442, 442,
+ 442, 444, 442, 442, 443, 443, 443, 443, 443, 443,
+ 443, 443, 443, 443, 443, 443, 443, 443, 443, 443,
+ 443, 443, 443, 443, 443, 443, 443, 443, 443, 443,
+ 443, 443, 443, 443, 443, 443, 443, 443, 443, 443,
+ 443, 443, 443, 443, 443, 443, 443, 443, 443, 443,
+ 443, 443, 443, 443, 443, 443, 443, 443, 443, 443,
+
+ 443, 443, 443, 443, 443, 442, 442, 442, 442, 443,
+ 443, 443, 443, 443, 443, 443, 443, 443, 443, 443,
+ 443, 443, 443, 443, 443, 443, 443, 443, 443, 443,
+ 443, 443, 443, 443, 443, 443, 443, 443, 443, 443,
+ 443, 443, 443, 443, 443, 443, 443, 443, 443, 443,
+ 443, 443, 443, 443, 443, 443, 443, 443, 443, 443,
+ 443, 443, 443, 443, 443, 443, 443, 443, 443, 443,
+ 443, 443, 443, 443, 443, 443, 443, 443, 443, 443,
+ 443, 443, 443, 443, 443, 443, 443, 443, 443, 443,
+ 443, 443, 443, 443, 443, 443, 443, 443, 443, 443,
+
+ 443, 443, 443, 443, 443, 443, 443, 443, 443, 443,
+ 443, 443, 443, 443, 443, 443, 443, 443, 443, 443,
+ 443, 443, 443, 443, 443, 443, 443, 443, 443, 443,
+ 443, 443, 443, 443, 443, 443, 443, 443, 443, 443,
+ 443, 443, 443, 443, 443, 443, 443, 443, 443, 443,
+ 443, 443, 443, 443, 443, 443, 443, 443, 443, 443,
+ 443, 443, 443, 443, 443, 443, 443, 443, 443, 443,
+ 443, 443, 443, 443, 443, 443, 443, 443, 443, 443,
+ 443, 443, 443, 443, 443, 443, 443, 443, 443, 443,
+ 443, 443, 443, 443, 443, 443, 443, 443, 443, 443,
+
+ 443, 443, 443, 443, 443, 443, 443, 443, 443, 443,
+ 443, 443, 443, 443, 443, 443, 443, 443, 443, 443,
+ 443, 443, 443, 443, 443, 443, 443, 443, 443, 443,
+ 443, 443, 443, 443, 443, 443, 443, 443, 443, 443,
+ 443, 0, 442, 442
+ } ;
+
+static yyconst flex_int16_t yy_nxt[656] =
+ { 0,
+ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
+ 14, 15, 16, 17, 18, 19, 19, 19, 19, 19,
+ 19, 20, 21, 22, 23, 24, 25, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 27, 28, 29, 30,
+ 31, 32, 33, 34, 35, 36, 37, 38, 26, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 26, 26, 26, 50, 51, 52, 53, 55, 56, 57,
+ 60, 62, 64, 64, 64, 64, 64, 64, 64, 77,
+ 78, 82, 83, 110, 63, 61, 129, 111, 58, 66,
+ 130, 67, 67, 67, 67, 67, 67, 68, 66, 80,
+
+ 68, 68, 68, 68, 68, 68, 68, 69, 72, 84,
+ 112, 85, 70, 81, 142, 86, 69, 203, 441, 204,
+ 69, 87, 94, 113, 95, 73, 90, 74, 75, 69,
+ 91, 88, 97, 96, 89, 92, 103, 70, 135, 106,
+ 98, 93, 99, 115, 104, 100, 107, 162, 440, 119,
+ 131, 101, 439, 108, 132, 105, 120, 121, 116, 125,
+ 163, 117, 126, 133, 176, 198, 122, 123, 264, 124,
+ 127, 438, 177, 199, 216, 217, 265, 128, 136, 64,
+ 64, 64, 64, 64, 64, 64, 138, 138, 138, 138,
+ 138, 138, 138, 437, 170, 137, 190, 171, 172, 406,
+
+ 407, 173, 139, 174, 242, 243, 244, 436, 137, 435,
+ 434, 191, 433, 432, 66, 139, 67, 67, 67, 67,
+ 67, 67, 68, 66, 431, 68, 68, 68, 68, 68,
+ 68, 68, 69, 141, 141, 141, 141, 141, 141, 141,
+ 430, 69, 140, 429, 140, 69, 428, 141, 141, 141,
+ 141, 141, 141, 141, 69, 206, 427, 206, 426, 425,
+ 207, 207, 207, 207, 207, 207, 207, 138, 138, 138,
+ 138, 138, 138, 138, 269, 270, 271, 424, 423, 208,
+ 422, 208, 421, 139, 209, 209, 209, 209, 209, 209,
+ 209, 277, 278, 279, 420, 419, 139, 141, 141, 141,
+
+ 141, 141, 141, 141, 207, 207, 207, 207, 207, 207,
+ 207, 207, 207, 207, 207, 207, 207, 207, 209, 209,
+ 209, 209, 209, 209, 209, 209, 209, 209, 209, 209,
+ 209, 209, 286, 287, 288, 293, 294, 295, 297, 298,
+ 299, 305, 306, 307, 387, 388, 389, 418, 417, 416,
+ 415, 414, 413, 412, 411, 410, 409, 390, 408, 391,
+ 79, 79, 405, 404, 403, 402, 401, 400, 399, 398,
+ 397, 396, 395, 394, 393, 392, 386, 385, 384, 383,
+ 382, 381, 380, 379, 378, 377, 376, 375, 374, 373,
+ 372, 371, 370, 369, 368, 367, 366, 365, 364, 363,
+
+ 362, 361, 360, 359, 358, 357, 356, 355, 354, 353,
+ 352, 351, 350, 349, 348, 347, 346, 345, 344, 343,
+ 342, 341, 340, 339, 338, 337, 336, 335, 334, 333,
+ 332, 331, 330, 329, 328, 327, 326, 325, 324, 323,
+ 322, 321, 320, 319, 318, 317, 316, 315, 314, 313,
+ 312, 311, 310, 309, 308, 304, 303, 302, 301, 300,
+ 296, 292, 291, 290, 289, 285, 284, 283, 282, 281,
+ 280, 276, 275, 274, 273, 272, 268, 267, 266, 263,
+ 262, 261, 260, 259, 258, 257, 256, 255, 254, 253,
+ 252, 251, 250, 249, 248, 247, 246, 245, 241, 240,
+
+ 239, 238, 237, 236, 235, 234, 233, 232, 231, 230,
+ 229, 228, 227, 226, 225, 224, 223, 222, 221, 220,
+ 219, 218, 215, 214, 213, 212, 211, 210, 205, 202,
+ 201, 200, 197, 196, 195, 194, 193, 192, 189, 188,
+ 187, 186, 185, 184, 183, 182, 181, 180, 179, 178,
+ 175, 169, 168, 167, 166, 165, 164, 161, 160, 159,
+ 158, 157, 156, 155, 154, 153, 152, 151, 150, 149,
+ 148, 147, 146, 145, 144, 143, 134, 118, 114, 109,
+ 102, 76, 71, 65, 59, 54, 442, 3, 442, 442,
+ 442, 442, 442, 442, 442, 442, 442, 442, 442, 442,
+
+ 442, 442, 442, 442, 442, 442, 442, 442, 442, 442,
+ 442, 442, 442, 442, 442, 442, 442, 442, 442, 442,
+ 442, 442, 442, 442, 442, 442, 442, 442, 442, 442,
+ 442, 442, 442, 442, 442, 442, 442, 442, 442, 442,
+ 442, 442, 442, 442, 442, 442, 442, 442, 442, 442,
+ 442, 442, 442, 442, 442
+ } ;
+
+static yyconst flex_int16_t yy_chk[656] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 8, 8, 9,
+ 13, 15, 16, 16, 16, 16, 16, 16, 16, 24,
+ 24, 30, 30, 40, 15, 13, 47, 40, 9, 18,
+ 47, 18, 18, 18, 18, 18, 18, 18, 19, 29,
+
+ 19, 19, 19, 19, 19, 19, 19, 18, 22, 31,
+ 41, 31, 18, 29, 444, 31, 19, 133, 439, 133,
+ 18, 32, 34, 41, 34, 22, 33, 22, 22, 19,
+ 33, 32, 35, 34, 32, 33, 37, 18, 51, 38,
+ 35, 33, 35, 43, 37, 35, 38, 99, 438, 45,
+ 48, 35, 437, 38, 48, 37, 45, 45, 43, 46,
+ 99, 43, 46, 48, 109, 129, 45, 45, 198, 45,
+ 46, 436, 109, 129, 152, 152, 198, 46, 51, 64,
+ 64, 64, 64, 64, 64, 64, 66, 66, 66, 66,
+ 66, 66, 66, 435, 107, 64, 122, 107, 107, 401,
+
+ 401, 107, 66, 107, 178, 178, 178, 434, 64, 432,
+ 430, 122, 429, 428, 67, 66, 67, 67, 67, 67,
+ 67, 67, 67, 68, 427, 68, 68, 68, 68, 68,
+ 68, 68, 67, 140, 140, 140, 140, 140, 140, 140,
+ 426, 68, 69, 424, 69, 67, 423, 69, 69, 69,
+ 69, 69, 69, 69, 68, 137, 422, 137, 421, 420,
+ 137, 137, 137, 137, 137, 137, 137, 138, 138, 138,
+ 138, 138, 138, 138, 202, 202, 202, 419, 418, 139,
+ 417, 139, 416, 138, 139, 139, 139, 139, 139, 139,
+ 139, 213, 213, 213, 414, 413, 138, 141, 141, 141,
+
+ 141, 141, 141, 141, 206, 206, 206, 206, 206, 206,
+ 206, 207, 207, 207, 207, 207, 207, 207, 208, 208,
+ 208, 208, 208, 208, 208, 209, 209, 209, 209, 209,
+ 209, 209, 221, 221, 221, 229, 229, 229, 233, 233,
+ 233, 239, 239, 239, 372, 372, 372, 412, 411, 410,
+ 409, 408, 407, 406, 405, 404, 403, 372, 402, 372,
+ 443, 443, 400, 391, 390, 389, 388, 387, 386, 384,
+ 383, 382, 379, 378, 376, 373, 371, 370, 369, 367,
+ 366, 365, 362, 361, 360, 359, 358, 357, 356, 355,
+ 349, 346, 343, 342, 341, 340, 339, 337, 335, 334,
+
+ 333, 332, 330, 329, 327, 325, 324, 323, 322, 321,
+ 320, 319, 318, 316, 315, 314, 313, 312, 311, 310,
+ 309, 308, 304, 303, 300, 289, 285, 284, 283, 282,
+ 275, 274, 273, 268, 267, 266, 265, 264, 263, 260,
+ 259, 258, 257, 256, 255, 254, 253, 252, 251, 250,
+ 249, 248, 247, 246, 245, 238, 237, 236, 235, 234,
+ 232, 228, 226, 225, 224, 220, 219, 218, 217, 216,
+ 215, 212, 210, 205, 204, 203, 201, 200, 199, 197,
+ 196, 195, 194, 193, 192, 191, 190, 189, 188, 187,
+ 186, 185, 184, 183, 182, 181, 180, 179, 177, 176,
+
+ 175, 174, 173, 172, 171, 170, 169, 168, 167, 166,
+ 165, 163, 162, 161, 160, 159, 158, 157, 156, 155,
+ 154, 153, 151, 150, 149, 148, 147, 146, 134, 132,
+ 131, 130, 128, 127, 126, 125, 124, 123, 121, 120,
+ 119, 118, 117, 116, 115, 114, 113, 112, 111, 110,
+ 108, 105, 104, 103, 102, 101, 100, 98, 97, 96,
+ 95, 94, 93, 92, 91, 90, 89, 88, 87, 86,
+ 85, 84, 83, 82, 78, 74, 49, 44, 42, 39,
+ 36, 23, 20, 17, 12, 7, 3, 442, 442, 442,
+ 442, 442, 442, 442, 442, 442, 442, 442, 442, 442,
+
+ 442, 442, 442, 442, 442, 442, 442, 442, 442, 442,
+ 442, 442, 442, 442, 442, 442, 442, 442, 442, 442,
+ 442, 442, 442, 442, 442, 442, 442, 442, 442, 442,
+ 442, 442, 442, 442, 442, 442, 442, 442, 442, 442,
+ 442, 442, 442, 442, 442, 442, 442, 442, 442, 442,
+ 442, 442, 442, 442, 442
+ } ;
+
+/* Table of booleans, true if rule could match eol. */
+static yyconst flex_int32_t yy_rule_can_match_eol[148] =
+ { 0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, };
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+/*
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+This file contains the Lex specification for GLSL ES.
+Based on ANSI C grammar, Lex specification:
+http://www.lysator.liu.se/c/ANSI-C-grammar-l.html
+
+IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh,
+WHICH GENERATES THE GLSL ES LEXER (glslang_lex.cpp).
+*/
+
+#include "compiler/translator/glslang.h"
+#include "compiler/translator/ParseContext.h"
+#include "compiler/preprocessor/Token.h"
+#include "compiler/translator/util.h"
+#include "compiler/translator/glslang_tab.h"
+
+/* windows only pragma */
+#ifdef _MSC_VER
+#pragma warning(disable : 4102)
+#endif
+
+#define YY_USER_ACTION \
+ yylloc->first_file = yylloc->last_file = yycolumn; \
+ yylloc->first_line = yylloc->last_line = yylineno;
+
+#define YY_INPUT(buf, result, max_size) \
+ result = string_input(buf, max_size, yyscanner);
+
+static yy_size_t string_input(char* buf, yy_size_t max_size, yyscan_t yyscanner);
+static int check_type(yyscan_t yyscanner);
+static int reserved_word(yyscan_t yyscanner);
+static int int_constant(yyscan_t yyscanner);
+static int float_constant(yyscan_t yyscanner);
+
+#define INITIAL 0
+
+#define YY_EXTRA_TYPE TParseContext*
+
+/* Holds the entire state of the reentrant scanner. */
+struct yyguts_t
+ {
+
+ /* User-defined. Not touched by flex. */
+ YY_EXTRA_TYPE yyextra_r;
+
+ /* The rest are the same as the globals declared in the non-reentrant scanner. */
+ FILE *yyin_r, *yyout_r;
+ size_t yy_buffer_stack_top; /**< index of top of stack. */
+ size_t yy_buffer_stack_max; /**< capacity of stack. */
+ YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */
+ char yy_hold_char;
+ yy_size_t yy_n_chars;
+ yy_size_t yyleng_r;
+ char *yy_c_buf_p;
+ int yy_init;
+ int yy_start;
+ int yy_did_buffer_switch_on_eof;
+ int yy_start_stack_ptr;
+ int yy_start_stack_depth;
+ int *yy_start_stack;
+ yy_state_type yy_last_accepting_state;
+ char* yy_last_accepting_cpos;
+
+ int yylineno_r;
+ int yy_flex_debug_r;
+
+ char *yytext_r;
+ int yy_more_flag;
+ int yy_more_len;
+
+ YYSTYPE * yylval_r;
+
+ YYLTYPE * yylloc_r;
+
+ }; /* end struct yyguts_t */
+
+static int yy_init_globals (yyscan_t yyscanner );
+
+ /* This must go here because YYSTYPE and YYLTYPE are included
+ * from bison output in section 1.*/
+ # define yylval yyg->yylval_r
+
+ # define yylloc yyg->yylloc_r
+
+int yylex_init (yyscan_t* scanner);
+
+int yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
+
+/* Accessor methods to globals.
+ These are made visible to non-reentrant scanners for convenience. */
+
+int yylex_destroy (yyscan_t yyscanner );
+
+int yyget_debug (yyscan_t yyscanner );
+
+void yyset_debug (int debug_flag ,yyscan_t yyscanner );
+
+YY_EXTRA_TYPE yyget_extra (yyscan_t yyscanner );
+
+void yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
+
+FILE *yyget_in (yyscan_t yyscanner );
+
+void yyset_in (FILE * in_str ,yyscan_t yyscanner );
+
+FILE *yyget_out (yyscan_t yyscanner );
+
+void yyset_out (FILE * out_str ,yyscan_t yyscanner );
+
+yy_size_t yyget_leng (yyscan_t yyscanner );
+
+char *yyget_text (yyscan_t yyscanner );
+
+int yyget_lineno (yyscan_t yyscanner );
+
+void yyset_lineno (int line_number ,yyscan_t yyscanner );
+
+int yyget_column (yyscan_t yyscanner );
+
+void yyset_column (int column_no ,yyscan_t yyscanner );
+
+YYSTYPE * yyget_lval (yyscan_t yyscanner );
+
+void yyset_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner );
+
+ YYLTYPE *yyget_lloc (yyscan_t yyscanner );
+
+ void yyset_lloc (YYLTYPE * yylloc_param ,yyscan_t yyscanner );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap (yyscan_t yyscanner );
+#else
+extern int yywrap (yyscan_t yyscanner );
+#endif
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
+#endif
+
+#ifndef YY_NO_INPUT
+
+#ifdef __cplusplus
+static int yyinput (yyscan_t yyscanner );
+#else
+static int input (yyscan_t yyscanner );
+#endif
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0)
+#endif
+
+/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+ { \
+ int c = '*'; \
+ size_t n; \
+ for ( n = 0; n < max_size && \
+ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+ buf[n] = (char) c; \
+ if ( c == '\n' ) \
+ buf[n++] = (char) c; \
+ if ( c == EOF && ferror( yyin ) ) \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ result = n; \
+ } \
+ else \
+ { \
+ errno=0; \
+ while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+ { \
+ if( errno != EINTR) \
+ { \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ break; \
+ } \
+ errno=0; \
+ clearerr(yyin); \
+ } \
+ }\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner)
+#endif
+
+/* end tables serialization structures and prototypes */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int yylex \
+ (YYSTYPE * yylval_param,YYLTYPE * yylloc_param ,yyscan_t yyscanner);
+
+#define YY_DECL int yylex \
+ (YYSTYPE * yylval_param, YYLTYPE * yylloc_param , yyscan_t yyscanner)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+ YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+ register yy_state_type yy_current_state;
+ register char *yy_cp, *yy_bp;
+ register int yy_act;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ yylval = yylval_param;
+
+ yylloc = yylloc_param;
+
+ if ( !yyg->yy_init )
+ {
+ yyg->yy_init = 1;
+
+#ifdef YY_USER_INIT
+ YY_USER_INIT;
+#endif
+
+ if ( ! yyg->yy_start )
+ yyg->yy_start = 1; /* first start state */
+
+ if ( ! yyin )
+ yyin = stdin;
+
+ if ( ! yyout )
+ yyout = stdout;
+
+ if ( ! YY_CURRENT_BUFFER ) {
+ yyensure_buffer_stack (yyscanner);
+ YY_CURRENT_BUFFER_LVALUE =
+ yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+ }
+
+ yy_load_buffer_state(yyscanner );
+ }
+
+ while ( 1 ) /* loops until end-of-file is reached */
+ {
+ yy_cp = yyg->yy_c_buf_p;
+
+ /* Support of yytext. */
+ *yy_cp = yyg->yy_hold_char;
+
+ /* yy_bp points to the position in yy_ch_buf of the start of
+ * the current run.
+ */
+ yy_bp = yy_cp;
+
+ yy_current_state = yyg->yy_start;
+yy_match:
+ do
+ {
+ register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+ if ( yy_accept[yy_current_state] )
+ {
+ yyg->yy_last_accepting_state = yy_current_state;
+ yyg->yy_last_accepting_cpos = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 443 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ ++yy_cp;
+ }
+ while ( yy_current_state != 442 );
+ yy_cp = yyg->yy_last_accepting_cpos;
+ yy_current_state = yyg->yy_last_accepting_state;
+
+yy_find_action:
+ yy_act = yy_accept[yy_current_state];
+
+ YY_DO_BEFORE_ACTION;
+
+ if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] )
+ {
+ yy_size_t yyl;
+ for ( yyl = 0; yyl < yyleng; ++yyl )
+ if ( yytext[yyl] == '\n' )
+
+ do{ yylineno++;
+ yycolumn=0;
+ }while(0)
+;
+ }
+
+do_action: /* This label is used only to access EOF actions. */
+
+ switch ( yy_act )
+ { /* beginning of action switch */
+ case 0: /* must back up */
+ /* undo the effects of YY_DO_BEFORE_ACTION */
+ *yy_cp = yyg->yy_hold_char;
+ yy_cp = yyg->yy_last_accepting_cpos;
+ yy_current_state = yyg->yy_last_accepting_state;
+ goto yy_find_action;
+
+case 1:
+YY_RULE_SETUP
+{ return INVARIANT; }
+ YY_BREAK
+case 2:
+YY_RULE_SETUP
+{ return HIGH_PRECISION; }
+ YY_BREAK
+case 3:
+YY_RULE_SETUP
+{ return MEDIUM_PRECISION; }
+ YY_BREAK
+case 4:
+YY_RULE_SETUP
+{ return LOW_PRECISION; }
+ YY_BREAK
+case 5:
+YY_RULE_SETUP
+{ return PRECISION; }
+ YY_BREAK
+case 6:
+YY_RULE_SETUP
+{ return ATTRIBUTE; }
+ YY_BREAK
+case 7:
+YY_RULE_SETUP
+{ return CONST_QUAL; }
+ YY_BREAK
+case 8:
+YY_RULE_SETUP
+{ return UNIFORM; }
+ YY_BREAK
+case 9:
+YY_RULE_SETUP
+{ return VARYING; }
+ YY_BREAK
+case 10:
+YY_RULE_SETUP
+{ return BREAK; }
+ YY_BREAK
+case 11:
+YY_RULE_SETUP
+{ return CONTINUE; }
+ YY_BREAK
+case 12:
+YY_RULE_SETUP
+{ return DO; }
+ YY_BREAK
+case 13:
+YY_RULE_SETUP
+{ return FOR; }
+ YY_BREAK
+case 14:
+YY_RULE_SETUP
+{ return WHILE; }
+ YY_BREAK
+case 15:
+YY_RULE_SETUP
+{ return IF; }
+ YY_BREAK
+case 16:
+YY_RULE_SETUP
+{ return ELSE; }
+ YY_BREAK
+case 17:
+YY_RULE_SETUP
+{ return IN_QUAL; }
+ YY_BREAK
+case 18:
+YY_RULE_SETUP
+{ return OUT_QUAL; }
+ YY_BREAK
+case 19:
+YY_RULE_SETUP
+{ return INOUT_QUAL; }
+ YY_BREAK
+case 20:
+YY_RULE_SETUP
+{ return FLOAT_TYPE; }
+ YY_BREAK
+case 21:
+YY_RULE_SETUP
+{ return INT_TYPE; }
+ YY_BREAK
+case 22:
+YY_RULE_SETUP
+{ return VOID_TYPE; }
+ YY_BREAK
+case 23:
+YY_RULE_SETUP
+{ return BOOL_TYPE; }
+ YY_BREAK
+case 24:
+YY_RULE_SETUP
+{ yylval->lex.b = true; return BOOLCONSTANT; }
+ YY_BREAK
+case 25:
+YY_RULE_SETUP
+{ yylval->lex.b = false; return BOOLCONSTANT; }
+ YY_BREAK
+case 26:
+YY_RULE_SETUP
+{ return DISCARD; }
+ YY_BREAK
+case 27:
+YY_RULE_SETUP
+{ return RETURN; }
+ YY_BREAK
+case 28:
+YY_RULE_SETUP
+{ return MATRIX2; }
+ YY_BREAK
+case 29:
+YY_RULE_SETUP
+{ return MATRIX3; }
+ YY_BREAK
+case 30:
+YY_RULE_SETUP
+{ return MATRIX4; }
+ YY_BREAK
+case 31:
+YY_RULE_SETUP
+{ return VEC2; }
+ YY_BREAK
+case 32:
+YY_RULE_SETUP
+{ return VEC3; }
+ YY_BREAK
+case 33:
+YY_RULE_SETUP
+{ return VEC4; }
+ YY_BREAK
+case 34:
+YY_RULE_SETUP
+{ return IVEC2; }
+ YY_BREAK
+case 35:
+YY_RULE_SETUP
+{ return IVEC3; }
+ YY_BREAK
+case 36:
+YY_RULE_SETUP
+{ return IVEC4; }
+ YY_BREAK
+case 37:
+YY_RULE_SETUP
+{ return BVEC2; }
+ YY_BREAK
+case 38:
+YY_RULE_SETUP
+{ return BVEC3; }
+ YY_BREAK
+case 39:
+YY_RULE_SETUP
+{ return BVEC4; }
+ YY_BREAK
+case 40:
+YY_RULE_SETUP
+{ return SAMPLER2D; }
+ YY_BREAK
+case 41:
+YY_RULE_SETUP
+{ return SAMPLERCUBE; }
+ YY_BREAK
+case 42:
+YY_RULE_SETUP
+{ return SAMPLER_EXTERNAL_OES; }
+ YY_BREAK
+case 43:
+YY_RULE_SETUP
+{ return SAMPLER2DRECT; }
+ YY_BREAK
+case 44:
+YY_RULE_SETUP
+{ return STRUCT; }
+ YY_BREAK
+case 45:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+ YY_BREAK
+case 46:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+ YY_BREAK
+case 47:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+ YY_BREAK
+case 48:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+ YY_BREAK
+case 49:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+ YY_BREAK
+case 50:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+ YY_BREAK
+case 51:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+ YY_BREAK
+case 52:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+ YY_BREAK
+case 53:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+ YY_BREAK
+case 54:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+ YY_BREAK
+case 55:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+ YY_BREAK
+case 56:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+ YY_BREAK
+case 57:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+ YY_BREAK
+case 58:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+ YY_BREAK
+case 59:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+ YY_BREAK
+case 60:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+ YY_BREAK
+case 61:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+ YY_BREAK
+case 62:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+ YY_BREAK
+case 63:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+ YY_BREAK
+case 64:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+ YY_BREAK
+case 65:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+ YY_BREAK
+case 66:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+ YY_BREAK
+case 67:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+ YY_BREAK
+case 68:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+ YY_BREAK
+case 69:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+ YY_BREAK
+case 70:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+ YY_BREAK
+case 71:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+ YY_BREAK
+case 72:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+ YY_BREAK
+case 73:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+ YY_BREAK
+case 74:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+ YY_BREAK
+case 75:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+ YY_BREAK
+case 76:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+ YY_BREAK
+case 77:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+ YY_BREAK
+case 78:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+ YY_BREAK
+case 79:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+ YY_BREAK
+case 80:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+ YY_BREAK
+case 81:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+ YY_BREAK
+case 82:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+ YY_BREAK
+case 83:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+ YY_BREAK
+case 84:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+ YY_BREAK
+case 85:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+ YY_BREAK
+case 86:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+ YY_BREAK
+case 87:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+ YY_BREAK
+case 88:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+ YY_BREAK
+case 89:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+ YY_BREAK
+case 90:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+ YY_BREAK
+case 91:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+ YY_BREAK
+case 92:
+YY_RULE_SETUP
+{ return reserved_word(yyscanner); }
+ YY_BREAK
+case 93:
+YY_RULE_SETUP
+{
+ yylval->lex.string = NewPoolTString(yytext);
+ return check_type(yyscanner);
+}
+ YY_BREAK
+case 94:
+YY_RULE_SETUP
+{ return int_constant(yyscanner); }
+ YY_BREAK
+case 95:
+YY_RULE_SETUP
+{ return int_constant(yyscanner); }
+ YY_BREAK
+case 96:
+YY_RULE_SETUP
+{ return int_constant(yyscanner); }
+ YY_BREAK
+case 97:
+YY_RULE_SETUP
+{ return float_constant(yyscanner); }
+ YY_BREAK
+case 98:
+YY_RULE_SETUP
+{ return float_constant(yyscanner); }
+ YY_BREAK
+case 99:
+YY_RULE_SETUP
+{ return float_constant(yyscanner); }
+ YY_BREAK
+case 100:
+YY_RULE_SETUP
+{ return ADD_ASSIGN; }
+ YY_BREAK
+case 101:
+YY_RULE_SETUP
+{ return SUB_ASSIGN; }
+ YY_BREAK
+case 102:
+YY_RULE_SETUP
+{ return MUL_ASSIGN; }
+ YY_BREAK
+case 103:
+YY_RULE_SETUP
+{ return DIV_ASSIGN; }
+ YY_BREAK
+case 104:
+YY_RULE_SETUP
+{ return MOD_ASSIGN; }
+ YY_BREAK
+case 105:
+YY_RULE_SETUP
+{ return LEFT_ASSIGN; }
+ YY_BREAK
+case 106:
+YY_RULE_SETUP
+{ return RIGHT_ASSIGN; }
+ YY_BREAK
+case 107:
+YY_RULE_SETUP
+{ return AND_ASSIGN; }
+ YY_BREAK
+case 108:
+YY_RULE_SETUP
+{ return XOR_ASSIGN; }
+ YY_BREAK
+case 109:
+YY_RULE_SETUP
+{ return OR_ASSIGN; }
+ YY_BREAK
+case 110:
+YY_RULE_SETUP
+{ return INC_OP; }
+ YY_BREAK
+case 111:
+YY_RULE_SETUP
+{ return DEC_OP; }
+ YY_BREAK
+case 112:
+YY_RULE_SETUP
+{ return AND_OP; }
+ YY_BREAK
+case 113:
+YY_RULE_SETUP
+{ return OR_OP; }
+ YY_BREAK
+case 114:
+YY_RULE_SETUP
+{ return XOR_OP; }
+ YY_BREAK
+case 115:
+YY_RULE_SETUP
+{ return LE_OP; }
+ YY_BREAK
+case 116:
+YY_RULE_SETUP
+{ return GE_OP; }
+ YY_BREAK
+case 117:
+YY_RULE_SETUP
+{ return EQ_OP; }
+ YY_BREAK
+case 118:
+YY_RULE_SETUP
+{ return NE_OP; }
+ YY_BREAK
+case 119:
+YY_RULE_SETUP
+{ return LEFT_OP; }
+ YY_BREAK
+case 120:
+YY_RULE_SETUP
+{ return RIGHT_OP; }
+ YY_BREAK
+case 121:
+YY_RULE_SETUP
+{ return SEMICOLON; }
+ YY_BREAK
+case 122:
+YY_RULE_SETUP
+{ return LEFT_BRACE; }
+ YY_BREAK
+case 123:
+YY_RULE_SETUP
+{ return RIGHT_BRACE; }
+ YY_BREAK
+case 124:
+YY_RULE_SETUP
+{ return COMMA; }
+ YY_BREAK
+case 125:
+YY_RULE_SETUP
+{ return COLON; }
+ YY_BREAK
+case 126:
+YY_RULE_SETUP
+{ return EQUAL; }
+ YY_BREAK
+case 127:
+YY_RULE_SETUP
+{ return LEFT_PAREN; }
+ YY_BREAK
+case 128:
+YY_RULE_SETUP
+{ return RIGHT_PAREN; }
+ YY_BREAK
+case 129:
+YY_RULE_SETUP
+{ return LEFT_BRACKET; }
+ YY_BREAK
+case 130:
+YY_RULE_SETUP
+{ return RIGHT_BRACKET; }
+ YY_BREAK
+case 131:
+YY_RULE_SETUP
+{ return DOT; }
+ YY_BREAK
+case 132:
+YY_RULE_SETUP
+{ return BANG; }
+ YY_BREAK
+case 133:
+YY_RULE_SETUP
+{ return DASH; }
+ YY_BREAK
+case 134:
+YY_RULE_SETUP
+{ return TILDE; }
+ YY_BREAK
+case 135:
+YY_RULE_SETUP
+{ return PLUS; }
+ YY_BREAK
+case 136:
+YY_RULE_SETUP
+{ return STAR; }
+ YY_BREAK
+case 137:
+YY_RULE_SETUP
+{ return SLASH; }
+ YY_BREAK
+case 138:
+YY_RULE_SETUP
+{ return PERCENT; }
+ YY_BREAK
+case 139:
+YY_RULE_SETUP
+{ return LEFT_ANGLE; }
+ YY_BREAK
+case 140:
+YY_RULE_SETUP
+{ return RIGHT_ANGLE; }
+ YY_BREAK
+case 141:
+YY_RULE_SETUP
+{ return VERTICAL_BAR; }
+ YY_BREAK
+case 142:
+YY_RULE_SETUP
+{ return CARET; }
+ YY_BREAK
+case 143:
+YY_RULE_SETUP
+{ return AMPERSAND; }
+ YY_BREAK
+case 144:
+YY_RULE_SETUP
+{ return QUESTION; }
+ YY_BREAK
+case 145:
+/* rule 145 can match eol */
+YY_RULE_SETUP
+{ }
+ YY_BREAK
+case YY_STATE_EOF(INITIAL):
+{ yyterminate(); }
+ YY_BREAK
+case 146:
+YY_RULE_SETUP
+{ assert(false); return 0; }
+ YY_BREAK
+case 147:
+YY_RULE_SETUP
+ECHO;
+ YY_BREAK
+
+ case YY_END_OF_BUFFER:
+ {
+ /* Amount of text matched not including the EOB char. */
+ int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1;
+
+ /* Undo the effects of YY_DO_BEFORE_ACTION. */
+ *yy_cp = yyg->yy_hold_char;
+ YY_RESTORE_YY_MORE_OFFSET
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+ {
+ /* We're scanning a new file or input source. It's
+ * possible that this happened because the user
+ * just pointed yyin at a new source and called
+ * yylex(). If so, then we have to assure
+ * consistency between YY_CURRENT_BUFFER and our
+ * globals. Here is the right place to do so, because
+ * this is the first action (other than possibly a
+ * back-up) that will match for the new input source.
+ */
+ yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+ YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
+ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+ }
+
+ /* Note that here we test for yy_c_buf_p "<=" to the position
+ * of the first EOB in the buffer, since yy_c_buf_p will
+ * already have been incremented past the NUL character
+ * (since all states make transitions on EOB to the
+ * end-of-buffer state). Contrast this with the test
+ * in input().
+ */
+ if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
+ { /* This was really a NUL. */
+ yy_state_type yy_next_state;
+
+ yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state( yyscanner );
+
+ /* Okay, we're now positioned to make the NUL
+ * transition. We couldn't have
+ * yy_get_previous_state() go ahead and do it
+ * for us because it doesn't know how to deal
+ * with the possibility of jamming (and we don't
+ * want to build jamming into it because then it
+ * will run more slowly).
+ */
+
+ yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner);
+
+ yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+
+ if ( yy_next_state )
+ {
+ /* Consume the NUL. */
+ yy_cp = ++yyg->yy_c_buf_p;
+ yy_current_state = yy_next_state;
+ goto yy_match;
+ }
+
+ else
+ {
+ yy_cp = yyg->yy_last_accepting_cpos;
+ yy_current_state = yyg->yy_last_accepting_state;
+ goto yy_find_action;
+ }
+ }
+
+ else switch ( yy_get_next_buffer( yyscanner ) )
+ {
+ case EOB_ACT_END_OF_FILE:
+ {
+ yyg->yy_did_buffer_switch_on_eof = 0;
+
+ if ( yywrap(yyscanner ) )
+ {
+ /* Note: because we've taken care in
+ * yy_get_next_buffer() to have set up
+ * yytext, we can now set up
+ * yy_c_buf_p so that if some total
+ * hoser (like flex itself) wants to
+ * call the scanner after we return the
+ * YY_NULL, it'll still work - another
+ * YY_NULL will get returned.
+ */
+ yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ;
+
+ yy_act = YY_STATE_EOF(YY_START);
+ goto do_action;
+ }
+
+ else
+ {
+ if ( ! yyg->yy_did_buffer_switch_on_eof )
+ YY_NEW_FILE;
+ }
+ break;
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ yyg->yy_c_buf_p =
+ yyg->yytext_ptr + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state( yyscanner );
+
+ yy_cp = yyg->yy_c_buf_p;
+ yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+ goto yy_match;
+
+ case EOB_ACT_LAST_MATCH:
+ yyg->yy_c_buf_p =
+ &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars];
+
+ yy_current_state = yy_get_previous_state( yyscanner );
+
+ yy_cp = yyg->yy_c_buf_p;
+ yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+ goto yy_find_action;
+ }
+ break;
+ }
+
+ default:
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--no action found" );
+ } /* end of action switch */
+ } /* end of scanning one token */
+} /* end of yylex */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ * EOB_ACT_LAST_MATCH -
+ * EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ * EOB_ACT_END_OF_FILE - end of file
+ */
+static int yy_get_next_buffer (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+ register char *source = yyg->yytext_ptr;
+ register int number_to_move, i;
+ int ret_val;
+
+ if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] )
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--end of buffer missed" );
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+ { /* Don't try to fill the buffer, so this is an EOF. */
+ if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 )
+ {
+ /* We matched a single character, the EOB, so
+ * treat this as a final EOF.
+ */
+ return EOB_ACT_END_OF_FILE;
+ }
+
+ else
+ {
+ /* We matched some text prior to the EOB, first
+ * process it.
+ */
+ return EOB_ACT_LAST_MATCH;
+ }
+ }
+
+ /* Try to read more data. */
+
+ /* First move last chars to start of buffer. */
+ number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1;
+
+ for ( i = 0; i < number_to_move; ++i )
+ *(dest++) = *(source++);
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+ /* don't do the read, it's not guaranteed to return an EOF,
+ * just force an EOF
+ */
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0;
+
+ else
+ {
+ yy_size_t num_to_read =
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+ while ( num_to_read <= 0 )
+ { /* Not enough room in the buffer - grow it. */
+
+ /* just a shorter name for the current buffer */
+ YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE;
+
+ int yy_c_buf_p_offset =
+ (int) (yyg->yy_c_buf_p - b->yy_ch_buf);
+
+ if ( b->yy_is_our_buffer )
+ {
+ yy_size_t new_size = b->yy_buf_size * 2;
+
+ if ( new_size <= 0 )
+ b->yy_buf_size += b->yy_buf_size / 8;
+ else
+ b->yy_buf_size *= 2;
+
+ b->yy_ch_buf = (char *)
+ /* Include room in for 2 EOB chars. */
+ yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner );
+ }
+ else
+ /* Can't grow it, we don't own it. */
+ b->yy_ch_buf = 0;
+
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR(
+ "fatal error - scanner input buffer overflow" );
+
+ yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+ num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+ number_to_move - 1;
+
+ }
+
+ if ( num_to_read > YY_READ_BUF_SIZE )
+ num_to_read = YY_READ_BUF_SIZE;
+
+ /* Read in more data. */
+ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+ yyg->yy_n_chars, num_to_read );
+
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+ }
+
+ if ( yyg->yy_n_chars == 0 )
+ {
+ if ( number_to_move == YY_MORE_ADJ )
+ {
+ ret_val = EOB_ACT_END_OF_FILE;
+ yyrestart(yyin ,yyscanner);
+ }
+
+ else
+ {
+ ret_val = EOB_ACT_LAST_MATCH;
+ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+ YY_BUFFER_EOF_PENDING;
+ }
+ }
+
+ else
+ ret_val = EOB_ACT_CONTINUE_SCAN;
+
+ if ((yy_size_t) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+ /* Extend the array by 50%, plus the number we really need. */
+ yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner );
+ if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+ }
+
+ yyg->yy_n_chars += number_to_move;
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+
+ yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+ return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+ static yy_state_type yy_get_previous_state (yyscan_t yyscanner)
+{
+ register yy_state_type yy_current_state;
+ register char *yy_cp;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ yy_current_state = yyg->yy_start;
+
+ for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp )
+ {
+ register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+ if ( yy_accept[yy_current_state] )
+ {
+ yyg->yy_last_accepting_state = yy_current_state;
+ yyg->yy_last_accepting_cpos = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 443 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ }
+
+ return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ * next_state = yy_try_NUL_trans( current_state );
+ */
+ static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state , yyscan_t yyscanner)
+{
+ register int yy_is_jam;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */
+ register char *yy_cp = yyg->yy_c_buf_p;
+
+ register YY_CHAR yy_c = 1;
+ if ( yy_accept[yy_current_state] )
+ {
+ yyg->yy_last_accepting_state = yy_current_state;
+ yyg->yy_last_accepting_cpos = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 443 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ yy_is_jam = (yy_current_state == 442);
+
+ (void)yyg;
+ return yy_is_jam ? 0 : yy_current_state;
+}
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+ static int yyinput (yyscan_t yyscanner)
+#else
+ static int input (yyscan_t yyscanner)
+#endif
+
+{
+ int c;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ *yyg->yy_c_buf_p = yyg->yy_hold_char;
+
+ if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
+ {
+ /* yy_c_buf_p now points to the character we want to return.
+ * If this occurs *before* the EOB characters, then it's a
+ * valid NUL; if not, then we've hit the end of the buffer.
+ */
+ if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
+ /* This was really a NUL. */
+ *yyg->yy_c_buf_p = '\0';
+
+ else
+ { /* need more input */
+ yy_size_t offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
+ ++yyg->yy_c_buf_p;
+
+ switch ( yy_get_next_buffer( yyscanner ) )
+ {
+ case EOB_ACT_LAST_MATCH:
+ /* This happens because yy_g_n_b()
+ * sees that we've accumulated a
+ * token and flags that we need to
+ * try matching the token before
+ * proceeding. But for input(),
+ * there's no matching to consider.
+ * So convert the EOB_ACT_LAST_MATCH
+ * to EOB_ACT_END_OF_FILE.
+ */
+
+ /* Reset buffer status. */
+ yyrestart(yyin ,yyscanner);
+
+ /*FALLTHROUGH*/
+
+ case EOB_ACT_END_OF_FILE:
+ {
+ if ( yywrap(yyscanner ) )
+ return EOF;
+
+ if ( ! yyg->yy_did_buffer_switch_on_eof )
+ YY_NEW_FILE;
+#ifdef __cplusplus
+ return yyinput(yyscanner);
+#else
+ return input(yyscanner);
+#endif
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ yyg->yy_c_buf_p = yyg->yytext_ptr + offset;
+ break;
+ }
+ }
+ }
+
+ c = *(unsigned char *) yyg->yy_c_buf_p; /* cast for 8-bit char's */
+ *yyg->yy_c_buf_p = '\0'; /* preserve yytext */
+ yyg->yy_hold_char = *++yyg->yy_c_buf_p;
+
+ if ( c == '\n' )
+
+ do{ yylineno++;
+ yycolumn=0;
+ }while(0)
+;
+
+ return c;
+}
+#endif /* ifndef YY_NO_INPUT */
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ * @param yyscanner The scanner object.
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+ void yyrestart (FILE * input_file , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if ( ! YY_CURRENT_BUFFER ){
+ yyensure_buffer_stack (yyscanner);
+ YY_CURRENT_BUFFER_LVALUE =
+ yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+ }
+
+ yy_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner);
+ yy_load_buffer_state(yyscanner );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ * @param yyscanner The scanner object.
+ */
+ void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ /* TODO. We should be able to replace this entire function body
+ * with
+ * yypop_buffer_state();
+ * yypush_buffer_state(new_buffer);
+ */
+ yyensure_buffer_stack (yyscanner);
+ if ( YY_CURRENT_BUFFER == new_buffer )
+ return;
+
+ if ( YY_CURRENT_BUFFER )
+ {
+ /* Flush out information for old buffer. */
+ *yyg->yy_c_buf_p = yyg->yy_hold_char;
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+ }
+
+ YY_CURRENT_BUFFER_LVALUE = new_buffer;
+ yy_load_buffer_state(yyscanner );
+
+ /* We don't actually know whether we did this switch during
+ * EOF (yywrap()) processing, but the only time this flag
+ * is looked at is after yywrap() is called, so it's safe
+ * to go ahead and always set it.
+ */
+ yyg->yy_did_buffer_switch_on_eof = 1;
+}
+
+static void yy_load_buffer_state (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+ yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+ yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+ yyg->yy_hold_char = *yyg->yy_c_buf_p;
+}
+
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ * @param yyscanner The scanner object.
+ * @return the allocated buffer state.
+ */
+ YY_BUFFER_STATE yy_create_buffer (FILE * file, int size , yyscan_t yyscanner)
+{
+ YY_BUFFER_STATE b;
+
+ b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+ b->yy_buf_size = size;
+
+ /* yy_ch_buf has to be 2 characters longer than the size given because
+ * we need to put in 2 end-of-buffer characters.
+ */
+ b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 ,yyscanner );
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+ b->yy_is_our_buffer = 1;
+
+ yy_init_buffer(b,file ,yyscanner);
+
+ return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with yy_create_buffer()
+ * @param yyscanner The scanner object.
+ */
+ void yy_delete_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if ( ! b )
+ return;
+
+ if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+ YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+ if ( b->yy_is_our_buffer )
+ yyfree((void *) b->yy_ch_buf ,yyscanner );
+
+ yyfree((void *) b ,yyscanner );
+}
+
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a yyrestart() or at EOF.
+ */
+ static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner)
+
+{
+ int oerrno = errno;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ yy_flush_buffer(b ,yyscanner);
+
+ b->yy_input_file = file;
+ b->yy_fill_buffer = 1;
+
+ /* If b is the current buffer, then yy_init_buffer was _probably_
+ * called from yyrestart() or through yy_get_next_buffer.
+ * In that case, we don't want to reset the lineno or column.
+ */
+ if (b != YY_CURRENT_BUFFER){
+ b->yy_bs_lineno = 1;
+ b->yy_bs_column = 0;
+ }
+
+ b->yy_is_interactive = 0;
+
+ errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ * @param yyscanner The scanner object.
+ */
+ void yy_flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ if ( ! b )
+ return;
+
+ b->yy_n_chars = 0;
+
+ /* We always need two end-of-buffer characters. The first causes
+ * a transition to the end-of-buffer state. The second causes
+ * a jam in that state.
+ */
+ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+ b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+ b->yy_buf_pos = &b->yy_ch_buf[0];
+
+ b->yy_at_bol = 1;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ if ( b == YY_CURRENT_BUFFER )
+ yy_load_buffer_state(yyscanner );
+}
+
+/** Pushes the new state onto the stack. The new state becomes
+ * the current state. This function will allocate the stack
+ * if necessary.
+ * @param new_buffer The new state.
+ * @param yyscanner The scanner object.
+ */
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ if (new_buffer == NULL)
+ return;
+
+ yyensure_buffer_stack(yyscanner);
+
+ /* This block is copied from yy_switch_to_buffer. */
+ if ( YY_CURRENT_BUFFER )
+ {
+ /* Flush out information for old buffer. */
+ *yyg->yy_c_buf_p = yyg->yy_hold_char;
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+ }
+
+ /* Only push if top exists. Otherwise, replace top. */
+ if (YY_CURRENT_BUFFER)
+ yyg->yy_buffer_stack_top++;
+ YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+ /* copied from yy_switch_to_buffer. */
+ yy_load_buffer_state(yyscanner );
+ yyg->yy_did_buffer_switch_on_eof = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ * The next element becomes the new top.
+ * @param yyscanner The scanner object.
+ */
+void yypop_buffer_state (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ if (!YY_CURRENT_BUFFER)
+ return;
+
+ yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner);
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ if (yyg->yy_buffer_stack_top > 0)
+ --yyg->yy_buffer_stack_top;
+
+ if (YY_CURRENT_BUFFER) {
+ yy_load_buffer_state(yyscanner );
+ yyg->yy_did_buffer_switch_on_eof = 1;
+ }
+}
+
+/* Allocates the stack if it does not exist.
+ * Guarantees space for at least one push.
+ */
+static void yyensure_buffer_stack (yyscan_t yyscanner)
+{
+ yy_size_t num_to_alloc;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if (!yyg->yy_buffer_stack) {
+
+ /* First allocation is just for 2 elements, since we don't know if this
+ * scanner will even need a stack. We use 2 instead of 1 to avoid an
+ * immediate realloc on the next call.
+ */
+ num_to_alloc = 1;
+ yyg->yy_buffer_stack = (struct yy_buffer_state**)yyalloc
+ (num_to_alloc * sizeof(struct yy_buffer_state*)
+ , yyscanner);
+ if ( ! yyg->yy_buffer_stack )
+ YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+
+ memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+
+ yyg->yy_buffer_stack_max = num_to_alloc;
+ yyg->yy_buffer_stack_top = 0;
+ return;
+ }
+
+ if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){
+
+ /* Increase the buffer to prepare for a possible push. */
+ int grow_size = 8 /* arbitrary grow size */;
+
+ num_to_alloc = yyg->yy_buffer_stack_max + grow_size;
+ yyg->yy_buffer_stack = (struct yy_buffer_state**)yyrealloc
+ (yyg->yy_buffer_stack,
+ num_to_alloc * sizeof(struct yy_buffer_state*)
+ , yyscanner);
+ if ( ! yyg->yy_buffer_stack )
+ YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+
+ /* zero only the new slots.*/
+ memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*));
+ yyg->yy_buffer_stack_max = num_to_alloc;
+ }
+}
+
+/** Setup the input buffer state to scan directly from a user-specified character buffer.
+ * @param base the character buffer
+ * @param size the size in bytes of the character buffer
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner)
+{
+ YY_BUFFER_STATE b;
+
+ if ( size < 2 ||
+ base[size-2] != YY_END_OF_BUFFER_CHAR ||
+ base[size-1] != YY_END_OF_BUFFER_CHAR )
+ /* They forgot to leave room for the EOB's. */
+ return 0;
+
+ b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+
+ b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
+ b->yy_buf_pos = b->yy_ch_buf = base;
+ b->yy_is_our_buffer = 0;
+ b->yy_input_file = 0;
+ b->yy_n_chars = b->yy_buf_size;
+ b->yy_is_interactive = 0;
+ b->yy_at_bol = 1;
+ b->yy_fill_buffer = 0;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ yy_switch_to_buffer(b ,yyscanner );
+
+ return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to yylex() will
+ * scan from a @e copy of @a str.
+ * @param yystr a NUL-terminated string to scan
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object.
+ * @note If you want to scan bytes that may contain NUL values, then use
+ * yy_scan_bytes() instead.
+ */
+YY_BUFFER_STATE yy_scan_string (yyconst char * yystr , yyscan_t yyscanner)
+{
+
+ return yy_scan_bytes(yystr,strlen(yystr) ,yyscanner);
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to yylex() will
+ * scan from a @e copy of @a bytes.
+ * @param yybytes the byte buffer to scan
+ * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len , yyscan_t yyscanner)
+{
+ YY_BUFFER_STATE b;
+ char *buf;
+ yy_size_t n;
+ yy_size_t i;
+
+ /* Get memory for full buffer, including space for trailing EOB's. */
+ n = _yybytes_len + 2;
+ buf = (char *) yyalloc(n ,yyscanner );
+ if ( ! buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+
+ for ( i = 0; i < _yybytes_len; ++i )
+ buf[i] = yybytes[i];
+
+ buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+ b = yy_scan_buffer(buf,n ,yyscanner);
+ if ( ! b )
+ YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
+
+ /* It's okay to grow etc. this buffer, and we should throw it
+ * away when we're done.
+ */
+ b->yy_is_our_buffer = 1;
+
+ return b;
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
+{
+ (void) fprintf( stderr, "%s\n", msg );
+ exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ int yyless_macro_arg = (n); \
+ YY_LESS_LINENO(yyless_macro_arg);\
+ yytext[yyleng] = yyg->yy_hold_char; \
+ yyg->yy_c_buf_p = yytext + yyless_macro_arg; \
+ yyg->yy_hold_char = *yyg->yy_c_buf_p; \
+ *yyg->yy_c_buf_p = '\0'; \
+ yyleng = yyless_macro_arg; \
+ } \
+ while ( 0 )
+
+/* Accessor methods (get/set functions) to struct members. */
+
+/** Get the user-defined data for this scanner.
+ * @param yyscanner The scanner object.
+ */
+YY_EXTRA_TYPE yyget_extra (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yyextra;
+}
+
+/** Get the current line number.
+ * @param yyscanner The scanner object.
+ */
+int yyget_lineno (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if (! YY_CURRENT_BUFFER)
+ return 0;
+
+ return yylineno;
+}
+
+/** Get the current column number.
+ * @param yyscanner The scanner object.
+ */
+int yyget_column (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if (! YY_CURRENT_BUFFER)
+ return 0;
+
+ return yycolumn;
+}
+
+/** Get the input stream.
+ * @param yyscanner The scanner object.
+ */
+FILE *yyget_in (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yyin;
+}
+
+/** Get the output stream.
+ * @param yyscanner The scanner object.
+ */
+FILE *yyget_out (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yyout;
+}
+
+/** Get the length of the current token.
+ * @param yyscanner The scanner object.
+ */
+yy_size_t yyget_leng (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yyleng;
+}
+
+/** Get the current token.
+ * @param yyscanner The scanner object.
+ */
+
+char *yyget_text (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yytext;
+}
+
+/** Set the user-defined data. This data is never touched by the scanner.
+ * @param user_defined The data to be associated with this scanner.
+ * @param yyscanner The scanner object.
+ */
+void yyset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yyextra = user_defined ;
+}
+
+/** Set the current line number.
+ * @param line_number
+ * @param yyscanner The scanner object.
+ */
+void yyset_lineno (int line_number , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ /* lineno is only valid if an input buffer exists. */
+ if (! YY_CURRENT_BUFFER )
+ YY_FATAL_ERROR( "yyset_lineno called with no buffer" );
+
+ yylineno = line_number;
+}
+
+/** Set the current column.
+ * @param line_number
+ * @param yyscanner The scanner object.
+ */
+void yyset_column (int column_no , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ /* column is only valid if an input buffer exists. */
+ if (! YY_CURRENT_BUFFER )
+ YY_FATAL_ERROR( "yyset_column called with no buffer" );
+
+ yycolumn = column_no;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param in_str A readable stream.
+ * @param yyscanner The scanner object.
+ * @see yy_switch_to_buffer
+ */
+void yyset_in (FILE * in_str , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yyin = in_str ;
+}
+
+void yyset_out (FILE * out_str , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yyout = out_str ;
+}
+
+int yyget_debug (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yy_flex_debug;
+}
+
+void yyset_debug (int bdebug , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yy_flex_debug = bdebug ;
+}
+
+/* Accessor methods for yylval and yylloc */
+
+YYSTYPE * yyget_lval (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yylval;
+}
+
+void yyset_lval (YYSTYPE * yylval_param , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yylval = yylval_param;
+}
+
+YYLTYPE *yyget_lloc (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yylloc;
+}
+
+void yyset_lloc (YYLTYPE * yylloc_param , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yylloc = yylloc_param;
+}
+
+/* User-visible API */
+
+/* yylex_init is special because it creates the scanner itself, so it is
+ * the ONLY reentrant function that doesn't take the scanner as the last argument.
+ * That's why we explicitly handle the declaration, instead of using our macros.
+ */
+
+int yylex_init(yyscan_t* ptr_yy_globals)
+
+{
+ if (ptr_yy_globals == NULL){
+ errno = EINVAL;
+ return 1;
+ }
+
+ *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), NULL );
+
+ if (*ptr_yy_globals == NULL){
+ errno = ENOMEM;
+ return 1;
+ }
+
+ /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */
+ memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
+
+ return yy_init_globals ( *ptr_yy_globals );
+}
+
+/* yylex_init_extra has the same functionality as yylex_init, but follows the
+ * convention of taking the scanner as the last argument. Note however, that
+ * this is a *pointer* to a scanner, as it will be allocated by this call (and
+ * is the reason, too, why this function also must handle its own declaration).
+ * The user defined value in the first argument will be available to yyalloc in
+ * the yyextra field.
+ */
+
+int yylex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals )
+
+{
+ struct yyguts_t dummy_yyguts;
+
+ yyset_extra (yy_user_defined, &dummy_yyguts);
+
+ if (ptr_yy_globals == NULL){
+ errno = EINVAL;
+ return 1;
+ }
+
+ *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts );
+
+ if (*ptr_yy_globals == NULL){
+ errno = ENOMEM;
+ return 1;
+ }
+
+ /* By setting to 0xAA, we expose bugs in
+ yy_init_globals. Leave at 0x00 for releases. */
+ memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
+
+ yyset_extra (yy_user_defined, *ptr_yy_globals);
+
+ return yy_init_globals ( *ptr_yy_globals );
+}
+
+static int yy_init_globals (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ /* Initialization is the same as for the non-reentrant scanner.
+ * This function is called from yylex_destroy(), so don't allocate here.
+ */
+
+ yyg->yy_buffer_stack = 0;
+ yyg->yy_buffer_stack_top = 0;
+ yyg->yy_buffer_stack_max = 0;
+ yyg->yy_c_buf_p = (char *) 0;
+ yyg->yy_init = 0;
+ yyg->yy_start = 0;
+
+ yyg->yy_start_stack_ptr = 0;
+ yyg->yy_start_stack_depth = 0;
+ yyg->yy_start_stack = NULL;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+ yyin = stdin;
+ yyout = stdout;
+#else
+ yyin = (FILE *) 0;
+ yyout = (FILE *) 0;
+#endif
+
+ /* For future reference: Set errno on error, since we are called by
+ * yylex_init()
+ */
+ return 0;
+}
+
+/* yylex_destroy is for both reentrant and non-reentrant scanners. */
+int yylex_destroy (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ /* Pop the buffer stack, destroying each element. */
+ while(YY_CURRENT_BUFFER){
+ yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner );
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ yypop_buffer_state(yyscanner);
+ }
+
+ /* Destroy the stack itself. */
+ yyfree(yyg->yy_buffer_stack ,yyscanner);
+ yyg->yy_buffer_stack = NULL;
+
+ /* Destroy the start condition stack. */
+ yyfree(yyg->yy_start_stack ,yyscanner );
+ yyg->yy_start_stack = NULL;
+
+ /* Reset the globals. This is important in a non-reentrant scanner so the next time
+ * yylex() is called, initialization will occur. */
+ yy_init_globals( yyscanner);
+
+ /* Destroy the main struct (reentrant only). */
+ yyfree ( yyscanner , yyscanner );
+ yyscanner = NULL;
+ return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)
+{
+ register int i;
+ for ( i = 0; i < n; ++i )
+ s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
+{
+ register int n;
+ for ( n = 0; s[n]; ++n )
+ ;
+
+ return n;
+}
+#endif
+
+void *yyalloc (yy_size_t size , yyscan_t yyscanner)
+{
+ return (void *) malloc( size );
+}
+
+void *yyrealloc (void * ptr, yy_size_t size , yyscan_t yyscanner)
+{
+ /* The cast to (char *) in the following accommodates both
+ * implementations that use char* generic pointers, and those
+ * that use void* generic pointers. It works with the latter
+ * because both ANSI C and C++ allow castless assignment from
+ * any pointer type to void*, and deal with argument conversions
+ * as though doing an assignment.
+ */
+ return (void *) realloc( (char *) ptr, size );
+}
+
+void yyfree (void * ptr , yyscan_t yyscanner)
+{
+ free( (char *) ptr ); /* see yyrealloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#endif
+
+yy_size_t string_input(char* buf, yy_size_t max_size, yyscan_t yyscanner) {
+ pp::Token token;
+ yyget_extra(yyscanner)->preprocessor.lex(&token);
+ yy_size_t len = token.type == pp::Token::LAST ? 0 : token.text.size();
+ if (len < max_size)
+ memcpy(buf, token.text.c_str(), len);
+ yyset_column(token.location.file,yyscanner);
+ yyset_lineno(token.location.line,yyscanner);
+
+ if (len >= max_size)
+ YY_FATAL_ERROR("Input buffer overflow");
+ else if (len > 0)
+ buf[len++] = ' ';
+ return len;
+}
+
+int check_type(yyscan_t yyscanner) {
+ struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
+
+ int token = IDENTIFIER;
+ TSymbol* symbol = yyextra->symbolTable.find(yytext);
+ if (symbol && symbol->isVariable()) {
+ TVariable* variable = static_cast<TVariable*>(symbol);
+ if (variable->isUserType())
+ token = TYPE_NAME;
+ }
+ yylval->lex.symbol = symbol;
+ return token;
+}
+
+int reserved_word(yyscan_t yyscanner) {
+ struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
+
+ yyextra->error(*yylloc, "Illegal use of reserved word", yytext, "");
+ yyextra->recover();
+ return 0;
+}
+
+void yyerror(YYLTYPE* lloc, TParseContext* context, const char* reason) {
+ context->error(*lloc, reason, yyget_text(context->scanner));
+ context->recover();
+}
+
+int int_constant(yyscan_t yyscanner) {
+ struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
+
+ if (!atoi_clamp(yytext, &(yylval->lex.i)))
+ yyextra->warning(*yylloc, "Integer overflow", yytext, "");
+ return INTCONSTANT;
+}
+
+int float_constant(yyscan_t yyscanner) {
+ struct yyguts_t* yyg = (struct yyguts_t*) yyscanner;
+
+ if (!atof_clamp(yytext, &(yylval->lex.f)))
+ yyextra->warning(*yylloc, "Float overflow", yytext, "");
+ return FLOATCONSTANT;
+}
+
+int glslang_initialize(TParseContext* context) {
+ yyscan_t scanner = NULL;
+ if (yylex_init_extra(context,&scanner))
+ return 1;
+
+ context->scanner = scanner;
+ return 0;
+}
+
+int glslang_finalize(TParseContext* context) {
+ yyscan_t scanner = context->scanner;
+ if (scanner == NULL) return 0;
+
+ context->scanner = NULL;
+ yylex_destroy(scanner);
+
+ return 0;
+}
+
+int glslang_scan(size_t count, const char* const string[], const int length[],
+ TParseContext* context) {
+ yyrestart(NULL,context->scanner);
+ yyset_column(0,context->scanner);
+ yyset_lineno(1,context->scanner);
+
+ // Initialize preprocessor.
+ if (!context->preprocessor.init(count, string, length))
+ return 1;
+ context->preprocessor.setMaxTokenLength(SH_MAX_TOKEN_LENGTH);
+
+ // Define extension macros.
+ const TExtensionBehavior& extBehavior = context->extensionBehavior();
+ for (TExtensionBehavior::const_iterator iter = extBehavior.begin();
+ iter != extBehavior.end(); ++iter) {
+ context->preprocessor.predefineMacro(iter->first.c_str(), 1);
+ }
+ if (context->fragmentPrecisionHigh)
+ context->preprocessor.predefineMacro("GL_FRAGMENT_PRECISION_HIGH", 1);
+
+ return 0;
+}
+
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/glslang_lex.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorglslang_tabcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/glslang_tab.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/glslang_tab.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/glslang_tab.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,4884 @@
</span><ins>+/* A Bison parser, made by GNU Bison 2.7.1. */
+
+/* Apple Note: For the avoidance of doubt, Apple elects to distribute this file under the terms of the BSD license. */
+
+/* Bison implementation for Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+ simplifying the original so-called "semantic" parser. */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+ infringing on user name space. This should be done even for local
+ variables, as they might otherwise be expanded by user macros.
+ There are some unavoidable exceptions within include files to
+ define necessary library symbols; they are noted "INFRINGES ON
+ USER NAME SPACE" below. */
+
+/* Identify Bison output. */
+#define YYBISON 1
+
+/* Bison version. */
+#define YYBISON_VERSION "2.7.1"
+
+/* Skeleton name. */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers. */
+#define YYPURE 1
+
+/* Push parsers. */
+#define YYPUSH 0
+
+/* Pull parsers. */
+#define YYPULL 1
+
+
+
+
+/* Copy the first part of user declarations. */
+
+
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// This file is auto-generated by generate_parser.sh. DO NOT EDIT!
+
+// Ignore errors in auto-generated code.
+#if defined(__GNUC__)
+#pragma GCC diagnostic ignored "-Wunused-function"
+#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wswitch-enum"
+#elif defined(_MSC_VER)
+#pragma warning(disable: 4065)
+#pragma warning(disable: 4189)
+#pragma warning(disable: 4505)
+#pragma warning(disable: 4701)
+#endif
+
+#include "compiler/translator/SymbolTable.h"
+#include "compiler/translator/ParseContext.h"
+#include "GLSLANG/ShaderLang.h"
+
+#define YYENABLE_NLS 0
+
+#define YYLEX_PARAM context->scanner
+
+
+
+# ifndef YY_NULL
+# if defined __cplusplus && 201103L <= __cplusplus
+# define YY_NULL nullptr
+# else
+# define YY_NULL 0
+# endif
+# endif
+
+/* Enabling verbose error messages. */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+/* In a future release of Bison, this section will be replaced
+ by #include "glslang_tab.h". */
+#ifndef YY_YY_GLSLANG_TAB_H_INCLUDED
+# define YY_YY_GLSLANG_TAB_H_INCLUDED
+/* Enabling traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+#if YYDEBUG
+extern int yydebug;
+#endif
+/* "%code requires" blocks. */
+
+
+#define YYLTYPE TSourceLoc
+#define YYLTYPE_IS_DECLARED 1
+#define SH_MAX_TOKEN_LENGTH 256 // WebGL spec.
+
+
+
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ INVARIANT = 258,
+ HIGH_PRECISION = 259,
+ MEDIUM_PRECISION = 260,
+ LOW_PRECISION = 261,
+ PRECISION = 262,
+ ATTRIBUTE = 263,
+ CONST_QUAL = 264,
+ BOOL_TYPE = 265,
+ FLOAT_TYPE = 266,
+ INT_TYPE = 267,
+ BREAK = 268,
+ CONTINUE = 269,
+ DO = 270,
+ ELSE = 271,
+ FOR = 272,
+ IF = 273,
+ DISCARD = 274,
+ RETURN = 275,
+ BVEC2 = 276,
+ BVEC3 = 277,
+ BVEC4 = 278,
+ IVEC2 = 279,
+ IVEC3 = 280,
+ IVEC4 = 281,
+ VEC2 = 282,
+ VEC3 = 283,
+ VEC4 = 284,
+ MATRIX2 = 285,
+ MATRIX3 = 286,
+ MATRIX4 = 287,
+ IN_QUAL = 288,
+ OUT_QUAL = 289,
+ INOUT_QUAL = 290,
+ UNIFORM = 291,
+ VARYING = 292,
+ STRUCT = 293,
+ VOID_TYPE = 294,
+ WHILE = 295,
+ SAMPLER2D = 296,
+ SAMPLERCUBE = 297,
+ SAMPLER_EXTERNAL_OES = 298,
+ SAMPLER2DRECT = 299,
+ IDENTIFIER = 300,
+ TYPE_NAME = 301,
+ FLOATCONSTANT = 302,
+ INTCONSTANT = 303,
+ BOOLCONSTANT = 304,
+ LEFT_OP = 305,
+ RIGHT_OP = 306,
+ INC_OP = 307,
+ DEC_OP = 308,
+ LE_OP = 309,
+ GE_OP = 310,
+ EQ_OP = 311,
+ NE_OP = 312,
+ AND_OP = 313,
+ OR_OP = 314,
+ XOR_OP = 315,
+ MUL_ASSIGN = 316,
+ DIV_ASSIGN = 317,
+ ADD_ASSIGN = 318,
+ MOD_ASSIGN = 319,
+ LEFT_ASSIGN = 320,
+ RIGHT_ASSIGN = 321,
+ AND_ASSIGN = 322,
+ XOR_ASSIGN = 323,
+ OR_ASSIGN = 324,
+ SUB_ASSIGN = 325,
+ LEFT_PAREN = 326,
+ RIGHT_PAREN = 327,
+ LEFT_BRACKET = 328,
+ RIGHT_BRACKET = 329,
+ LEFT_BRACE = 330,
+ RIGHT_BRACE = 331,
+ DOT = 332,
+ COMMA = 333,
+ COLON = 334,
+ EQUAL = 335,
+ SEMICOLON = 336,
+ BANG = 337,
+ DASH = 338,
+ TILDE = 339,
+ PLUS = 340,
+ STAR = 341,
+ SLASH = 342,
+ PERCENT = 343,
+ LEFT_ANGLE = 344,
+ RIGHT_ANGLE = 345,
+ VERTICAL_BAR = 346,
+ CARET = 347,
+ AMPERSAND = 348,
+ QUESTION = 349
+ };
+#endif
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+{
+
+
+ struct {
+ union {
+ TString *string;
+ float f;
+ int i;
+ bool b;
+ };
+ TSymbol* symbol;
+ } lex;
+ struct {
+ TOperator op;
+ union {
+ TIntermNode* intermNode;
+ TIntermNodePair nodePair;
+ TIntermTyped* intermTypedNode;
+ TIntermAggregate* intermAggregate;
+ };
+ union {
+ TPublicType type;
+ TPrecision precision;
+ TQualifier qualifier;
+ TFunction* function;
+ TParameter param;
+ TField* field;
+ TFieldList* fieldList;
+ };
+ } interm;
+
+
+
+} YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
+typedef struct YYLTYPE
+{
+ int first_line;
+ int first_column;
+ int last_line;
+ int last_column;
+} YYLTYPE;
+# define yyltype YYLTYPE /* obsolescent; will be withdrawn */
+# define YYLTYPE_IS_DECLARED 1
+# define YYLTYPE_IS_TRIVIAL 1
+#endif
+
+
+#ifdef YYPARSE_PARAM
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void *YYPARSE_PARAM);
+#else
+int yyparse ();
+#endif
+#else /* ! YYPARSE_PARAM */
+#if defined __STDC__ || defined __cplusplus
+int yyparse (TParseContext* context);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
+
+#endif /* !YY_YY_GLSLANG_TAB_H_INCLUDED */
+
+/* Copy the second part of user declarations. */
+
+
+extern int yylex(YYSTYPE* yylval, YYLTYPE* yylloc, void* yyscanner);
+extern void yyerror(YYLTYPE* yylloc, TParseContext* context, const char* reason);
+
+#define YYLLOC_DEFAULT(Current, Rhs, N) \
+ do { \
+ if (YYID(N)) { \
+ (Current).first_file = YYRHSLOC(Rhs, 1).first_file; \
+ (Current).first_line = YYRHSLOC(Rhs, 1).first_line; \
+ (Current).last_file = YYRHSLOC(Rhs, N).last_file; \
+ (Current).last_line = YYRHSLOC(Rhs, N).last_line; \
+ } \
+ else { \
+ (Current).first_file = YYRHSLOC(Rhs, 0).last_file; \
+ (Current).first_line = YYRHSLOC(Rhs, 0).last_line; \
+ (Current).last_file = YYRHSLOC(Rhs, 0).last_file; \
+ (Current).last_line = YYRHSLOC(Rhs, 0).last_line; \
+ } \
+ } while (0)
+
+#define VERTEX_ONLY(S, L) { \
+ if (context->shaderType != SH_VERTEX_SHADER) { \
+ context->error(L, " supported in vertex shaders only ", S); \
+ context->recover(); \
+ } \
+}
+
+#define FRAG_ONLY(S, L) { \
+ if (context->shaderType != SH_FRAGMENT_SHADER) { \
+ context->error(L, " supported in fragment shaders only ", S); \
+ context->recover(); \
+ } \
+}
+
+
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#elif (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+typedef signed char yytype_int8;
+#else
+typedef short int yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+# define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+# define YYSIZE_T size_t
+# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+# else
+# define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if defined YYENABLE_NLS && YYENABLE_NLS
+# if ENABLE_NLS
+# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+# define YY_(Msgid) dgettext ("bison-runtime", Msgid)
+# endif
+# endif
+# ifndef YY_
+# define YY_(Msgid) Msgid
+# endif
+#endif
+
+#ifndef __attribute__
+/* This feature is available in gcc versions 2.5 and later. */
+# if (! defined __GNUC__ || __GNUC__ < 2 \
+ || (__GNUC__ == 2 && __GNUC_MINOR__ < 5))
+# define __attribute__(Spec) /* empty */
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E. */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(E) ((void) (E))
+#else
+# define YYUSE(E) /* empty */
+#endif
+
+
+/* Identity function, used to suppress warnings about constant conditions. */
+#ifndef lint
+# define YYID(N) (N)
+#else
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static int
+YYID (int yyi)
+#else
+static int
+YYID (yyi)
+ int yyi;
+#endif
+{
+ return yyi;
+}
+#endif
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols. */
+
+# ifdef YYSTACK_USE_ALLOCA
+# if YYSTACK_USE_ALLOCA
+# ifdef __GNUC__
+# define YYSTACK_ALLOC __builtin_alloca
+# elif defined __BUILTIN_VA_ARG_INCR
+# include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+# elif defined _AIX
+# define YYSTACK_ALLOC __alloca
+# elif defined _MSC_VER
+# include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+# define alloca _alloca
+# else
+# define YYSTACK_ALLOC alloca
+# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+ /* Use EXIT_SUCCESS as a witness for stdlib.h. */
+# ifndef EXIT_SUCCESS
+# define EXIT_SUCCESS 0
+# endif
+# endif
+# endif
+# endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+ /* Pacify GCC's `empty if-body' warning. */
+# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
+# ifndef YYSTACK_ALLOC_MAXIMUM
+ /* The OS might guarantee only one guard page at the bottom of the stack,
+ and a page size can be as small as 4096 bytes. So we cannot safely
+ invoke alloca (N) if N exceeds 4096. Use a slightly smaller number
+ to allow for a few compiler-allocated temporary stack slots. */
+# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+# endif
+# else
+# define YYSTACK_ALLOC YYMALLOC
+# define YYSTACK_FREE YYFREE
+# ifndef YYSTACK_ALLOC_MAXIMUM
+# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+# endif
+# if (defined __cplusplus && ! defined EXIT_SUCCESS \
+ && ! ((defined YYMALLOC || defined malloc) \
+ && (defined YYFREE || defined free)))
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef EXIT_SUCCESS
+# define EXIT_SUCCESS 0
+# endif
+# endif
+# ifndef YYMALLOC
+# define YYMALLOC malloc
+# if ! defined malloc && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# ifndef YYFREE
+# define YYFREE free
+# if ! defined free && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+ && (! defined __cplusplus \
+ || (defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL \
+ && defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member. */
+union yyalloc
+{
+ yytype_int16 yyss_alloc;
+ YYSTYPE yyvs_alloc;
+ YYLTYPE yyls_alloc;
+};
+
+/* The size of the maximum gap between one aligned stack and the next. */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+ N elements. */
+# define YYSTACK_BYTES(N) \
+ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \
+ + 2 * YYSTACK_GAP_MAXIMUM)
+
+# define YYCOPY_NEEDED 1
+
+/* Relocate STACK from its old location to the new one. The
+ local variables YYSIZE and YYSTACKSIZE give the old and new number of
+ elements in the stack, and YYPTR gives the new location of the
+ stack. Advance YYPTR to a properly aligned location for the next
+ stack. */
+# define YYSTACK_RELOCATE(Stack_alloc, Stack) \
+ do \
+ { \
+ YYSIZE_T yynewbytes; \
+ YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \
+ Stack = &yyptr->Stack_alloc; \
+ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+ yyptr += yynewbytes / sizeof (*yyptr); \
+ } \
+ while (YYID (0))
+
+#endif
+
+#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
+/* Copy COUNT objects from SRC to DST. The source and destination do
+ not overlap. */
+# ifndef YYCOPY
+# if defined __GNUC__ && 1 < __GNUC__
+# define YYCOPY(Dst, Src, Count) \
+ __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src)))
+# else
+# define YYCOPY(Dst, Src, Count) \
+ do \
+ { \
+ YYSIZE_T yyi; \
+ for (yyi = 0; yyi < (Count); yyi++) \
+ (Dst)[yyi] = (Src)[yyi]; \
+ } \
+ while (YYID (0))
+# endif
+# endif
+#endif /* !YYCOPY_NEEDED */
+
+/* YYFINAL -- State number of the termination state. */
+#define YYFINAL 74
+/* YYLAST -- Last index in YYTABLE. */
+#define YYLAST 1490
+
+/* YYNTOKENS -- Number of terminals. */
+#define YYNTOKENS 95
+/* YYNNTS -- Number of nonterminals. */
+#define YYNNTS 84
+/* YYNRULES -- Number of rules. */
+#define YYNRULES 202
+/* YYNRULES -- Number of states. */
+#define YYNSTATES 307
+
+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
+#define YYUNDEFTOK 2
+#define YYMAXUTOK 349
+
+#define YYTRANSLATE(YYX) \
+ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
+static const yytype_uint8 yytranslate[] =
+{
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
+ 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
+ 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
+ 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
+ 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
+ 85, 86, 87, 88, 89, 90, 91, 92, 93, 94
+};
+
+#if YYDEBUG
+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+ YYRHS. */
+static const yytype_uint16 yyprhs[] =
+{
+ 0, 0, 3, 5, 7, 9, 11, 13, 15, 17,
+ 21, 23, 28, 30, 34, 37, 40, 42, 44, 46,
+ 50, 53, 56, 59, 61, 64, 68, 71, 73, 75,
+ 77, 80, 83, 86, 88, 90, 92, 94, 98, 102,
+ 104, 108, 112, 114, 116, 120, 124, 128, 132, 134,
+ 138, 142, 144, 146, 148, 150, 154, 156, 160, 162,
+ 166, 168, 174, 176, 180, 182, 184, 186, 188, 190,
+ 192, 196, 198, 201, 204, 209, 212, 214, 216, 219,
+ 223, 227, 230, 236, 240, 243, 247, 250, 251, 253,
+ 255, 257, 259, 261, 265, 271, 278, 284, 286, 289,
+ 294, 300, 305, 308, 310, 313, 315, 317, 319, 322,
+ 324, 326, 329, 331, 333, 335, 337, 342, 344, 346,
+ 348, 350, 352, 354, 356, 358, 360, 362, 364, 366,
+ 368, 370, 372, 374, 376, 378, 380, 382, 384, 386,
+ 387, 394, 395, 401, 403, 406, 410, 412, 416, 418,
+ 423, 425, 427, 429, 431, 433, 435, 437, 439, 441,
+ 444, 445, 446, 452, 454, 456, 457, 460, 461, 464,
+ 467, 471, 473, 476, 478, 481, 487, 491, 493, 495,
+ 500, 501, 508, 509, 518, 519, 527, 529, 531, 533,
+ 534, 537, 541, 544, 547, 550, 554, 557, 559, 562,
+ 564, 566, 567
+};
+
+/* YYRHS -- A `-1'-separated list of the rules' RHS. */
+static const yytype_int16 yyrhs[] =
+{
+ 175, 0, -1, 45, -1, 46, -1, 45, -1, 97,
+ -1, 48, -1, 47, -1, 49, -1, 71, 124, 72,
+ -1, 98, -1, 99, 73, 100, 74, -1, 101, -1,
+ 99, 77, 96, -1, 99, 52, -1, 99, 53, -1,
+ 124, -1, 102, -1, 103, -1, 99, 77, 103, -1,
+ 105, 72, -1, 104, 72, -1, 106, 39, -1, 106,
+ -1, 106, 122, -1, 105, 78, 122, -1, 107, 71,
+ -1, 142, -1, 45, -1, 99, -1, 52, 108, -1,
+ 53, 108, -1, 109, 108, -1, 85, -1, 83, -1,
+ 82, -1, 108, -1, 110, 86, 108, -1, 110, 87,
+ 108, -1, 110, -1, 111, 85, 110, -1, 111, 83,
+ 110, -1, 111, -1, 112, -1, 113, 89, 112, -1,
+ 113, 90, 112, -1, 113, 54, 112, -1, 113, 55,
+ 112, -1, 113, -1, 114, 56, 113, -1, 114, 57,
+ 113, -1, 114, -1, 115, -1, 116, -1, 117, -1,
+ 118, 58, 117, -1, 118, -1, 119, 60, 118, -1,
+ 119, -1, 120, 59, 119, -1, 120, -1, 120, 94,
+ 124, 79, 122, -1, 121, -1, 108, 123, 122, -1,
+ 80, -1, 61, -1, 62, -1, 63, -1, 70, -1,
+ 122, -1, 124, 78, 122, -1, 121, -1, 127, 81,
+ -1, 135, 81, -1, 7, 140, 141, 81, -1, 128,
+ 72, -1, 130, -1, 129, -1, 130, 132, -1, 129,
+ 78, 132, -1, 137, 45, 71, -1, 139, 96, -1,
+ 139, 96, 73, 125, 74, -1, 138, 133, 131, -1,
+ 133, 131, -1, 138, 133, 134, -1, 133, 134, -1,
+ -1, 33, -1, 34, -1, 35, -1, 139, -1, 136,
+ -1, 135, 78, 96, -1, 135, 78, 96, 73, 74,
+ -1, 135, 78, 96, 73, 125, 74, -1, 135, 78,
+ 96, 80, 150, -1, 137, -1, 137, 96, -1, 137,
+ 96, 73, 74, -1, 137, 96, 73, 125, 74, -1,
+ 137, 96, 80, 150, -1, 3, 45, -1, 139, -1,
+ 138, 139, -1, 9, -1, 8, -1, 37, -1, 3,
+ 37, -1, 36, -1, 141, -1, 140, 141, -1, 4,
+ -1, 5, -1, 6, -1, 142, -1, 142, 73, 125,
+ 74, -1, 39, -1, 11, -1, 12, -1, 10, -1,
+ 27, -1, 28, -1, 29, -1, 21, -1, 22, -1,
+ 23, -1, 24, -1, 25, -1, 26, -1, 30, -1,
+ 31, -1, 32, -1, 41, -1, 42, -1, 43, -1,
+ 44, -1, 143, -1, 46, -1, -1, 38, 96, 75,
+ 144, 146, 76, -1, -1, 38, 75, 145, 146, 76,
+ -1, 147, -1, 146, 147, -1, 139, 148, 81, -1,
+ 149, -1, 148, 78, 149, -1, 96, -1, 96, 73,
+ 125, 74, -1, 122, -1, 126, -1, 154, -1, 153,
+ -1, 151, -1, 163, -1, 164, -1, 167, -1, 174,
+ -1, 75, 76, -1, -1, -1, 75, 155, 162, 156,
+ 76, -1, 161, -1, 153, -1, -1, 159, 161, -1,
+ -1, 160, 153, -1, 75, 76, -1, 75, 162, 76,
+ -1, 152, -1, 162, 152, -1, 81, -1, 124, 81,
+ -1, 18, 71, 124, 72, 165, -1, 158, 16, 158,
+ -1, 158, -1, 124, -1, 137, 96, 80, 150, -1,
+ -1, 40, 71, 168, 166, 72, 157, -1, -1, 15,
+ 169, 158, 40, 71, 124, 72, 81, -1, -1, 17,
+ 71, 170, 171, 173, 72, 157, -1, 163, -1, 151,
+ -1, 166, -1, -1, 172, 81, -1, 172, 81, 124,
+ -1, 14, 81, -1, 13, 81, -1, 20, 81, -1,
+ 20, 124, 81, -1, 19, 81, -1, 176, -1, 175,
+ 176, -1, 177, -1, 126, -1, -1, 127, 178, 161,
+ -1
+};
+
+/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
+static const yytype_uint16 yyrline[] =
+{
+ 0, 180, 180, 181, 184, 239, 242, 247, 252, 257,
+ 263, 266, 269, 272, 367, 377, 390, 398, 498, 501,
+ 509, 512, 518, 522, 529, 535, 544, 552, 607, 617,
+ 620, 630, 640, 661, 662, 663, 668, 669, 677, 688,
+ 689, 697, 708, 712, 713, 723, 733, 743, 756, 757,
+ 767, 780, 784, 788, 792, 793, 806, 807, 820, 821,
+ 834, 835, 852, 853, 866, 867, 868, 869, 870, 874,
+ 877, 888, 896, 923, 928, 942, 997, 1000, 1007, 1015,
+ 1036, 1057, 1067, 1095, 1100, 1110, 1115, 1125, 1128, 1131,
+ 1134, 1140, 1147, 1150, 1172, 1190, 1214, 1237, 1241, 1259,
+ 1267, 1299, 1319, 1340, 1349, 1372, 1375, 1381, 1389, 1397,
+ 1405, 1415, 1422, 1425, 1428, 1434, 1437, 1452, 1456, 1460,
+ 1464, 1468, 1473, 1478, 1483, 1488, 1493, 1498, 1503, 1508,
+ 1513, 1518, 1523, 1528, 1532, 1536, 1544, 1552, 1556, 1569,
+ 1569, 1583, 1583, 1592, 1595, 1611, 1644, 1648, 1654, 1661,
+ 1676, 1680, 1684, 1685, 1691, 1692, 1693, 1694, 1695, 1699,
+ 1700, 1700, 1700, 1710, 1711, 1715, 1715, 1716, 1716, 1721,
+ 1724, 1734, 1737, 1743, 1744, 1748, 1756, 1760, 1770, 1775,
+ 1792, 1792, 1797, 1797, 1804, 1804, 1812, 1815, 1821, 1824,
+ 1830, 1834, 1841, 1848, 1855, 1862, 1873, 1882, 1886, 1893,
+ 1896, 1902, 1902
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || 0
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+ First, the terminals, then, starting at YYNTOKENS, nonterminals. */
+static const char *const yytname[] =
+{
+ "$end", "error", "$undefined", "INVARIANT", "HIGH_PRECISION",
+ "MEDIUM_PRECISION", "LOW_PRECISION", "PRECISION", "ATTRIBUTE",
+ "CONST_QUAL", "BOOL_TYPE", "FLOAT_TYPE", "INT_TYPE", "BREAK", "CONTINUE",
+ "DO", "ELSE", "FOR", "IF", "DISCARD", "RETURN", "BVEC2", "BVEC3",
+ "BVEC4", "IVEC2", "IVEC3", "IVEC4", "VEC2", "VEC3", "VEC4", "MATRIX2",
+ "MATRIX3", "MATRIX4", "IN_QUAL", "OUT_QUAL", "INOUT_QUAL", "UNIFORM",
+ "VARYING", "STRUCT", "VOID_TYPE", "WHILE", "SAMPLER2D", "SAMPLERCUBE",
+ "SAMPLER_EXTERNAL_OES", "SAMPLER2DRECT", "IDENTIFIER", "TYPE_NAME",
+ "FLOATCONSTANT", "INTCONSTANT", "BOOLCONSTANT", "LEFT_OP", "RIGHT_OP",
+ "INC_OP", "DEC_OP", "LE_OP", "GE_OP", "EQ_OP", "NE_OP", "AND_OP",
+ "OR_OP", "XOR_OP", "MUL_ASSIGN", "DIV_ASSIGN", "ADD_ASSIGN",
+ "MOD_ASSIGN", "LEFT_ASSIGN", "RIGHT_ASSIGN", "AND_ASSIGN", "XOR_ASSIGN",
+ "OR_ASSIGN", "SUB_ASSIGN", "LEFT_PAREN", "RIGHT_PAREN", "LEFT_BRACKET",
+ "RIGHT_BRACKET", "LEFT_BRACE", "RIGHT_BRACE", "DOT", "COMMA", "COLON",
+ "EQUAL", "SEMICOLON", "BANG", "DASH", "TILDE", "PLUS", "STAR", "SLASH",
+ "PERCENT", "LEFT_ANGLE", "RIGHT_ANGLE", "VERTICAL_BAR", "CARET",
+ "AMPERSAND", "QUESTION", "$accept", "identifier", "variable_identifier",
+ "primary_expression", "postfix_expression", "integer_expression",
+ "function_call", "function_call_or_method", "function_call_generic",
+ "function_call_header_no_parameters",
+ "function_call_header_with_parameters", "function_call_header",
+ "function_identifier", "unary_expression", "unary_operator",
+ "multiplicative_expression", "additive_expression", "shift_expression",
+ "relational_expression", "equality_expression", "and_expression",
+ "exclusive_or_expression", "inclusive_or_expression",
+ "logical_and_expression", "logical_xor_expression",
+ "logical_or_expression", "conditional_expression",
+ "assignment_expression", "assignment_operator", "expression",
+ "constant_expression", "declaration", "function_prototype",
+ "function_declarator", "function_header_with_parameters",
+ "function_header", "parameter_declarator", "parameter_declaration",
+ "parameter_qualifier", "parameter_type_specifier",
+ "init_declarator_list", "single_declaration", "fully_specified_type",
+ "type_qualifier", "type_specifier", "precision_qualifier",
+ "type_specifier_no_prec", "type_specifier_nonarray", "struct_specifier",
+ "$@1", "$@2", "struct_declaration_list", "struct_declaration",
+ "struct_declarator_list", "struct_declarator", "initializer",
+ "declaration_statement", "statement", "simple_statement",
+ "compound_statement", "$@3", "$@4", "statement_no_new_scope",
+ "statement_with_scope", "$@5", "$@6", "compound_statement_no_new_scope",
+ "statement_list", "expression_statement", "selection_statement",
+ "selection_rest_statement", "condition", "iteration_statement", "$@7",
+ "$@8", "$@9", "for_init_statement", "conditionopt", "for_rest_statement",
+ "jump_statement", "translation_unit", "external_declaration",
+ "function_definition", "$@10", YY_NULL
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+ token YYLEX-NUM. */
+static const yytype_uint16 yytoknum[] =
+{
+ 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
+ 265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
+ 275, 276, 277, 278, 279, 280, 281, 282, 283, 284,
+ 285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
+ 295, 296, 297, 298, 299, 300, 301, 302, 303, 304,
+ 305, 306, 307, 308, 309, 310, 311, 312, 313, 314,
+ 315, 316, 317, 318, 319, 320, 321, 322, 323, 324,
+ 325, 326, 327, 328, 329, 330, 331, 332, 333, 334,
+ 335, 336, 337, 338, 339, 340, 341, 342, 343, 344,
+ 345, 346, 347, 348, 349
+};
+# endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+static const yytype_uint8 yyr1[] =
+{
+ 0, 95, 96, 96, 97, 98, 98, 98, 98, 98,
+ 99, 99, 99, 99, 99, 99, 100, 101, 102, 102,
+ 103, 103, 104, 104, 105, 105, 106, 107, 107, 108,
+ 108, 108, 108, 109, 109, 109, 110, 110, 110, 111,
+ 111, 111, 112, 113, 113, 113, 113, 113, 114, 114,
+ 114, 115, 116, 117, 118, 118, 119, 119, 120, 120,
+ 121, 121, 122, 122, 123, 123, 123, 123, 123, 124,
+ 124, 125, 126, 126, 126, 127, 128, 128, 129, 129,
+ 130, 131, 131, 132, 132, 132, 132, 133, 133, 133,
+ 133, 134, 135, 135, 135, 135, 135, 136, 136, 136,
+ 136, 136, 136, 137, 137, 138, 138, 138, 138, 138,
+ 139, 139, 140, 140, 140, 141, 141, 142, 142, 142,
+ 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
+ 142, 142, 142, 142, 142, 142, 142, 142, 142, 144,
+ 143, 145, 143, 146, 146, 147, 148, 148, 149, 149,
+ 150, 151, 152, 152, 153, 153, 153, 153, 153, 154,
+ 155, 156, 154, 157, 157, 159, 158, 160, 158, 161,
+ 161, 162, 162, 163, 163, 164, 165, 165, 166, 166,
+ 168, 167, 169, 167, 170, 167, 171, 171, 172, 172,
+ 173, 173, 174, 174, 174, 174, 174, 175, 175, 176,
+ 176, 178, 177
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
+static const yytype_uint8 yyr2[] =
+{
+ 0, 2, 1, 1, 1, 1, 1, 1, 1, 3,
+ 1, 4, 1, 3, 2, 2, 1, 1, 1, 3,
+ 2, 2, 2, 1, 2, 3, 2, 1, 1, 1,
+ 2, 2, 2, 1, 1, 1, 1, 3, 3, 1,
+ 3, 3, 1, 1, 3, 3, 3, 3, 1, 3,
+ 3, 1, 1, 1, 1, 3, 1, 3, 1, 3,
+ 1, 5, 1, 3, 1, 1, 1, 1, 1, 1,
+ 3, 1, 2, 2, 4, 2, 1, 1, 2, 3,
+ 3, 2, 5, 3, 2, 3, 2, 0, 1, 1,
+ 1, 1, 1, 3, 5, 6, 5, 1, 2, 4,
+ 5, 4, 2, 1, 2, 1, 1, 1, 2, 1,
+ 1, 2, 1, 1, 1, 1, 4, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
+ 6, 0, 5, 1, 2, 3, 1, 3, 1, 4,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 2,
+ 0, 0, 5, 1, 1, 0, 2, 0, 2, 2,
+ 3, 1, 2, 1, 2, 5, 3, 1, 1, 4,
+ 0, 6, 0, 8, 0, 7, 1, 1, 1, 0,
+ 2, 3, 2, 2, 2, 3, 2, 1, 2, 1,
+ 1, 0, 3
+};
+
+/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM.
+ Performed when YYTABLE doesn't specify something else to do. Zero
+ means the default is an error. */
+static const yytype_uint8 yydefact[] =
+{
+ 0, 0, 112, 113, 114, 0, 106, 105, 120, 118,
+ 119, 124, 125, 126, 127, 128, 129, 121, 122, 123,
+ 130, 131, 132, 109, 107, 0, 117, 133, 134, 135,
+ 136, 138, 200, 201, 0, 77, 87, 0, 92, 97,
+ 0, 103, 0, 110, 115, 137, 0, 197, 199, 108,
+ 102, 0, 2, 3, 141, 0, 72, 0, 75, 87,
+ 0, 88, 89, 90, 78, 0, 87, 0, 73, 2,
+ 98, 104, 111, 0, 1, 198, 0, 0, 139, 0,
+ 202, 79, 84, 86, 91, 0, 93, 80, 0, 0,
+ 4, 7, 6, 8, 0, 0, 0, 35, 34, 33,
+ 5, 10, 29, 12, 17, 18, 0, 0, 23, 0,
+ 36, 0, 39, 42, 43, 48, 51, 52, 53, 54,
+ 56, 58, 60, 71, 0, 27, 74, 0, 0, 143,
+ 0, 0, 0, 182, 0, 0, 0, 0, 0, 160,
+ 169, 173, 36, 62, 69, 0, 151, 0, 115, 154,
+ 171, 153, 152, 0, 155, 156, 157, 158, 81, 83,
+ 85, 0, 0, 99, 0, 150, 101, 30, 31, 0,
+ 14, 15, 0, 0, 21, 20, 0, 22, 24, 26,
+ 32, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 116, 148, 0, 146, 142,
+ 144, 0, 193, 192, 167, 184, 0, 196, 194, 0,
+ 180, 159, 0, 65, 66, 67, 68, 64, 0, 0,
+ 174, 170, 172, 0, 94, 0, 96, 100, 9, 0,
+ 16, 2, 3, 13, 19, 25, 37, 38, 41, 40,
+ 46, 47, 44, 45, 49, 50, 55, 57, 59, 0,
+ 0, 0, 145, 140, 0, 0, 0, 0, 0, 195,
+ 0, 161, 63, 70, 0, 95, 11, 0, 0, 147,
+ 0, 166, 168, 187, 186, 189, 167, 178, 0, 0,
+ 0, 82, 61, 149, 0, 188, 0, 0, 177, 175,
+ 0, 0, 162, 0, 190, 0, 167, 0, 164, 181,
+ 163, 0, 191, 185, 176, 179, 183
+};
+
+/* YYDEFGOTO[NTERM-NUM]. */
+static const yytype_int16 yydefgoto[] =
+{
+ -1, 196, 100, 101, 102, 229, 103, 104, 105, 106,
+ 107, 108, 109, 142, 111, 112, 113, 114, 115, 116,
+ 117, 118, 119, 120, 121, 122, 143, 144, 218, 145,
+ 124, 146, 147, 34, 35, 36, 82, 64, 65, 83,
+ 37, 38, 39, 40, 41, 42, 43, 125, 45, 130,
+ 77, 128, 129, 197, 198, 166, 149, 150, 151, 152,
+ 212, 280, 299, 254, 255, 256, 300, 153, 154, 155,
+ 289, 279, 156, 260, 204, 257, 275, 286, 287, 157,
+ 46, 47, 48, 57
+};
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+ STATE-NUM. */
+#define YYPACT_NINF -261
+static const yytype_int16 yypact[] =
+{
+ 1327, -20, -261, -261, -261, 113, -261, -261, -261, -261,
+ -261, -261, -261, -261, -261, -261, -261, -261, -261, -261,
+ -261, -261, -261, -261, -261, -19, -261, -261, -261, -261,
+ -261, -261, -261, -61, -40, -28, 75, -7, -261, 24,
+ 1370, -261, 1444, -261, -11, -261, 1283, -261, -261, -261,
+ -261, 1444, -261, -261, -261, 6, -261, 54, -261, 88,
+ 62, -261, -261, -261, -261, 1370, 59, 91, -261, 36,
+ -50, -261, -261, 1051, -261, -261, 63, 1370, -261, 293,
+ -261, -261, -261, -261, 91, 1370, -12, -261, 856, 1051,
+ 77, -261, -261, -261, 1051, 1051, 1051, -261, -261, -261,
+ -261, -261, -14, -261, -261, -261, 84, -44, 1116, 95,
+ -261, 1051, 53, 3, -261, -36, 89, -261, -261, -261,
+ 104, 107, -45, -261, 96, -261, -261, 91, 1184, -261,
+ 1370, 92, 93, -261, 98, 101, 94, 921, 105, 102,
+ -261, -261, 72, -261, -261, 9, -261, -61, 42, -261,
+ -261, -261, -261, 376, -261, -261, -261, -261, 106, -261,
+ -261, 986, 1051, -261, 103, -261, -261, -261, -261, -41,
+ -261, -261, 1051, 1407, -261, -261, 1051, 110, -261, -261,
+ -261, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051, 1051,
+ 1051, 1051, 1051, 1051, 1051, -261, 109, 23, -261, -261,
+ -261, 1227, -261, -261, 111, -261, 1051, -261, -261, 25,
+ -261, -261, 459, -261, -261, -261, -261, -261, 1051, 1051,
+ -261, -261, -261, 1051, -261, 114, -261, -261, -261, 115,
+ 112, 77, 116, -261, -261, -261, -261, -261, 53, 53,
+ -261, -261, -261, -261, -36, -36, -261, 104, 107, 76,
+ 1051, 91, -261, -261, 145, 54, 625, 708, -6, -261,
+ 791, 459, -261, -261, 117, -261, -261, 1051, 120, -261,
+ 124, -261, -261, -261, -261, 791, 111, 112, 91, 125,
+ 122, -261, -261, -261, 1051, -261, 118, 128, 180, -261,
+ 126, 542, -261, -5, 1051, 542, 111, 1051, -261, -261,
+ -261, 123, 112, -261, -261, -261, -261
+};
+
+/* YYPGOTO[NTERM-NUM]. */
+static const yytype_int16 yypgoto[] =
+{
+ -261, -24, -261, -261, -261, -261, -261, -261, 34, -261,
+ -261, -261, -261, 32, -261, -33, -261, -27, -26, -261,
+ -261, -261, 14, 16, 18, -261, -66, -87, -261, -92,
+ -85, 11, 12, -261, -261, -261, 141, 150, 161, 143,
+ -261, -261, -231, 5, -30, 224, -18, 0, -261, -261,
+ -261, 100, -119, -261, -17, -156, -25, -145, -243, -261,
+ -261, -261, -64, -260, -261, -261, -52, 21, -22, -261,
+ -261, -39, -261, -261, -261, -261, -261, -261, -261, -261,
+ -261, 191, -261, -261
+};
+
+/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
+ positive, shift that token. If negative, reduce the rule which
+ number is the opposite. If YYTABLE_NINF, syntax error. */
+#define YYTABLE_NINF -166
+static const yytype_int16 yytable[] =
+{
+ 44, 55, 165, 164, 169, 80, 226, 123, 222, 200,
+ 71, 32, 33, 272, 193, 70, 288, 49, 185, 186,
+ 56, 178, 123, 88, 72, 50, 52, 53, 175, 278,
+ 89, 228, 58, 76, 176, 84, 304, 219, 170, 171,
+ 44, 66, 44, 86, 278, 209, 44, 127, 298, 194,
+ 59, 44, 298, 187, 188, 84, 54, 32, 33, 172,
+ 158, 161, 73, 173, 66, 44, 276, 301, 162, 69,
+ 53, 67, 219, 219, 68, 165, 225, 44, 60, 148,
+ 230, 78, 200, 6, 7, 44, 183, 219, 184, 235,
+ 220, 60, 61, 62, 63, 123, 6, 7, 127, 49,
+ 127, 251, 249, 219, 252, 110, 259, 87, 61, 62,
+ 63, 23, 24, -27, 258, 73, 222, 2, 3, 4,
+ 110, 61, 62, 63, 23, 24, 167, 168, 44, 79,
+ 44, 262, 263, 213, 214, 215, 52, 53, 264, 181,
+ 182, 305, 216, 180, 126, 189, 190, -76, -28, 233,
+ 238, 239, 217, 148, 219, 267, 174, 123, 240, 241,
+ 242, 243, 191, 244, 245, 268, 179, 192, 277, 205,
+ 195, 127, 206, 202, 203, 207, 210, 227, 211, 223,
+ 282, -117, 250, 277, 123, 270, -165, -138, 265, 266,
+ 219, 281, 293, 110, 283, 284, 296, 291, 292, 294,
+ 295, 44, 302, 271, 306, 246, 297, 234, 247, 81,
+ 165, 248, 148, 236, 237, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 159, 85, 160, 51,
+ 201, 303, 273, 261, 269, 274, 285, 75, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 290, 110, 148, 148, 0, 0,
+ 148, 148, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 148, 0, 0, 0, 0,
+ 0, 0, 110, 0, 0, 0, 0, 0, 0, 0,
+ 0, 148, 0, 0, 0, 148, 1, 2, 3, 4,
+ 5, 6, 7, 8, 9, 10, 131, 132, 133, 0,
+ 134, 135, 136, 137, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 0, 0, 0, 23,
+ 24, 25, 26, 138, 27, 28, 29, 30, 90, 31,
+ 91, 92, 93, 0, 0, 94, 95, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 96, 0, 0, 0, 139, 140,
+ 0, 0, 0, 0, 141, 97, 98, 0, 99, 1,
+ 2, 3, 4, 5, 6, 7, 8, 9, 10, 131,
+ 132, 133, 0, 134, 135, 136, 137, 11, 12, 13,
+ 14, 15, 16, 17, 18, 19, 20, 21, 22, 0,
+ 0, 0, 23, 24, 25, 26, 138, 27, 28, 29,
+ 30, 90, 31, 91, 92, 93, 0, 0, 94, 95,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 96, 0, 0,
+ 0, 139, 221, 0, 0, 0, 0, 141, 97, 98,
+ 0, 99, 1, 2, 3, 4, 5, 6, 7, 8,
+ 9, 10, 131, 132, 133, 0, 134, 135, 136, 137,
+ 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+ 21, 22, 0, 0, 0, 23, 24, 25, 26, 138,
+ 27, 28, 29, 30, 90, 31, 91, 92, 93, 0,
+ 0, 94, 95, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 96, 0, 0, 0, 139, 0, 0, 0, 0, 0,
+ 141, 97, 98, 0, 99, 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10, 131, 132, 133, 0, 134,
+ 135, 136, 137, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 0, 0, 0, 23, 24,
+ 25, 26, 138, 27, 28, 29, 30, 90, 31, 91,
+ 92, 93, 0, 0, 94, 95, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 96, 0, 0, 0, 79, 0, 0,
+ 0, 0, 0, 141, 97, 98, 0, 99, 1, 2,
+ 3, 4, 5, 6, 7, 8, 9, 10, 131, 132,
+ 133, 0, 134, 135, 136, 137, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 0, 0,
+ 0, 23, 24, 25, 26, 138, 27, 28, 29, 30,
+ 90, 31, 91, 92, 93, 0, 0, 94, 95, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 96, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 141, 97, 98, 0,
+ 99, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 0, 0, 0, 0, 0, 0, 0, 0, 11,
+ 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+ 22, 0, 0, 0, 23, 24, 25, 26, 0, 27,
+ 28, 29, 30, 90, 31, 91, 92, 93, 0, 0,
+ 94, 95, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 96,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 141,
+ 97, 98, 0, 99, 60, 2, 3, 4, 0, 6,
+ 7, 8, 9, 10, 0, 0, 0, 0, 0, 0,
+ 0, 0, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 0, 0, 0, 23, 24, 25,
+ 26, 0, 27, 28, 29, 30, 90, 31, 91, 92,
+ 93, 0, 0, 94, 95, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 96, 0, 0, 0, 8, 9, 10, 0,
+ 0, 0, 0, 97, 98, 0, 99, 11, 12, 13,
+ 14, 15, 16, 17, 18, 19, 20, 21, 22, 0,
+ 0, 0, 0, 0, 25, 26, 0, 27, 28, 29,
+ 30, 90, 31, 91, 92, 93, 0, 0, 94, 95,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 96, 0, 0,
+ 163, 8, 9, 10, 0, 0, 0, 0, 97, 98,
+ 0, 99, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 0, 0, 0, 0, 0, 25,
+ 26, 0, 27, 28, 29, 30, 90, 31, 91, 92,
+ 93, 0, 0, 94, 95, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 96, 0, 0, 0, 8, 9, 10, 0,
+ 0, 0, 208, 97, 98, 0, 99, 11, 12, 13,
+ 14, 15, 16, 17, 18, 19, 20, 21, 22, 0,
+ 0, 0, 0, 0, 25, 26, 0, 27, 28, 29,
+ 30, 90, 31, 91, 92, 93, 0, 0, 94, 95,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 96, 0, 0,
+ 224, 8, 9, 10, 0, 0, 0, 0, 97, 98,
+ 0, 99, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 0, 0, 0, 0, 0, 25,
+ 26, 0, 27, 28, 29, 30, 90, 31, 91, 92,
+ 93, 0, 0, 94, 95, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 96, 0, 0, 0, 8, 9, 10, 0,
+ 0, 0, 0, 97, 98, 0, 99, 11, 12, 13,
+ 14, 15, 16, 17, 18, 19, 20, 21, 22, 0,
+ 0, 0, 0, 0, 25, 177, 0, 27, 28, 29,
+ 30, 90, 31, 91, 92, 93, 0, 0, 94, 95,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 96, 2, 3,
+ 4, 0, 0, 0, 8, 9, 10, 0, 97, 98,
+ 0, 99, 0, 0, 0, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 0, 0, 0,
+ 0, 0, 25, 26, 0, 27, 28, 29, 30, 0,
+ 31, 2, 3, 4, 0, 0, 0, 8, 9, 10,
+ 0, 0, 0, 0, 0, 0, 0, 0, 11, 12,
+ 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
+ 199, 0, 0, 0, 0, 25, 26, 0, 27, 28,
+ 29, 30, 0, 31, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 74, 0, 0, 1, 2, 3, 4,
+ 5, 6, 7, 8, 9, 10, 0, 0, 0, 0,
+ 0, 0, 0, 253, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 0, 0, 0, 23,
+ 24, 25, 26, 0, 27, 28, 29, 30, 0, 31,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
+ 0, 0, 0, 0, 0, 0, 0, 0, 11, 12,
+ 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
+ 0, 0, 0, 23, 24, 25, 26, 0, 27, 28,
+ 29, 30, 0, 31, 2, 3, 4, 0, 0, 0,
+ 8, 9, 10, 0, 0, 0, 0, 0, 0, 0,
+ 0, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 0, 0, 0, 0, 0, 25, 26,
+ 0, 27, 28, 29, 30, 0, 31, 8, 9, 10,
+ 0, 0, 0, 0, 0, 0, 0, 0, 11, 12,
+ 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
+ 0, 0, 0, 0, 0, 25, 26, 0, 27, 28,
+ 29, 30, 231, 232, 8, 9, 10, 0, 0, 0,
+ 0, 0, 0, 0, 0, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 0, 0, 0,
+ 0, 0, 25, 26, 0, 27, 28, 29, 30, 0,
+ 31
+};
+
+#define yypact_value_is_default(Yystate) \
+ (!!((Yystate) == (-261)))
+
+#define yytable_value_is_error(Yytable_value) \
+ YYID (0)
+
+static const yytype_int16 yycheck[] =
+{
+ 0, 25, 89, 88, 96, 57, 162, 73, 153, 128,
+ 40, 0, 0, 256, 59, 39, 276, 37, 54, 55,
+ 81, 108, 88, 73, 42, 45, 45, 46, 72, 260,
+ 80, 72, 72, 51, 78, 65, 296, 78, 52, 53,
+ 40, 36, 42, 67, 275, 137, 46, 77, 291, 94,
+ 78, 51, 295, 89, 90, 85, 75, 46, 46, 73,
+ 84, 73, 73, 77, 59, 65, 72, 72, 80, 45,
+ 46, 78, 78, 78, 81, 162, 161, 77, 3, 79,
+ 172, 75, 201, 8, 9, 85, 83, 78, 85, 176,
+ 81, 3, 33, 34, 35, 161, 8, 9, 128, 37,
+ 130, 78, 194, 78, 81, 73, 81, 71, 33, 34,
+ 35, 36, 37, 71, 206, 73, 261, 4, 5, 6,
+ 88, 33, 34, 35, 36, 37, 94, 95, 128, 75,
+ 130, 218, 219, 61, 62, 63, 45, 46, 223, 86,
+ 87, 297, 70, 111, 81, 56, 57, 72, 71, 173,
+ 183, 184, 80, 153, 78, 79, 72, 223, 185, 186,
+ 187, 188, 58, 189, 190, 250, 71, 60, 260, 71,
+ 74, 201, 71, 81, 81, 81, 71, 74, 76, 73,
+ 267, 71, 73, 275, 250, 40, 75, 71, 74, 74,
+ 78, 74, 284, 161, 74, 71, 16, 72, 76, 81,
+ 72, 201, 294, 255, 81, 191, 80, 173, 192, 59,
+ 297, 193, 212, 181, 182, 183, 184, 185, 186, 187,
+ 188, 189, 190, 191, 192, 193, 85, 66, 85, 5,
+ 130, 295, 257, 212, 251, 257, 275, 46, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 278, 223, 256, 257, -1, -1,
+ 260, 261, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 275, -1, -1, -1, -1,
+ -1, -1, 250, -1, -1, -1, -1, -1, -1, -1,
+ -1, 291, -1, -1, -1, 295, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14, 15, -1,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
+ 27, 28, 29, 30, 31, 32, -1, -1, -1, 36,
+ 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
+ 47, 48, 49, -1, -1, 52, 53, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 71, -1, -1, -1, 75, 76,
+ -1, -1, -1, -1, 81, 82, 83, -1, 85, 3,
+ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
+ 14, 15, -1, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31, 32, -1,
+ -1, -1, 36, 37, 38, 39, 40, 41, 42, 43,
+ 44, 45, 46, 47, 48, 49, -1, -1, 52, 53,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 71, -1, -1,
+ -1, 75, 76, -1, -1, -1, -1, 81, 82, 83,
+ -1, 85, 3, 4, 5, 6, 7, 8, 9, 10,
+ 11, 12, 13, 14, 15, -1, 17, 18, 19, 20,
+ 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
+ 31, 32, -1, -1, -1, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, -1,
+ -1, 52, 53, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 71, -1, -1, -1, 75, -1, -1, -1, -1, -1,
+ 81, 82, 83, -1, 85, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15, -1, 17,
+ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
+ 28, 29, 30, 31, 32, -1, -1, -1, 36, 37,
+ 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, -1, -1, 52, 53, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 71, -1, -1, -1, 75, -1, -1,
+ -1, -1, -1, 81, 82, 83, -1, 85, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, -1, 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 29, 30, 31, 32, -1, -1,
+ -1, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+ 45, 46, 47, 48, 49, -1, -1, 52, 53, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 71, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 81, 82, 83, -1,
+ 85, 3, 4, 5, 6, 7, 8, 9, 10, 11,
+ 12, -1, -1, -1, -1, -1, -1, -1, -1, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, -1, -1, -1, 36, 37, 38, 39, -1, 41,
+ 42, 43, 44, 45, 46, 47, 48, 49, -1, -1,
+ 52, 53, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 71,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 81,
+ 82, 83, -1, 85, 3, 4, 5, 6, -1, 8,
+ 9, 10, 11, 12, -1, -1, -1, -1, -1, -1,
+ -1, -1, 21, 22, 23, 24, 25, 26, 27, 28,
+ 29, 30, 31, 32, -1, -1, -1, 36, 37, 38,
+ 39, -1, 41, 42, 43, 44, 45, 46, 47, 48,
+ 49, -1, -1, 52, 53, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 71, -1, -1, -1, 10, 11, 12, -1,
+ -1, -1, -1, 82, 83, -1, 85, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31, 32, -1,
+ -1, -1, -1, -1, 38, 39, -1, 41, 42, 43,
+ 44, 45, 46, 47, 48, 49, -1, -1, 52, 53,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 71, -1, -1,
+ 74, 10, 11, 12, -1, -1, -1, -1, 82, 83,
+ -1, 85, 21, 22, 23, 24, 25, 26, 27, 28,
+ 29, 30, 31, 32, -1, -1, -1, -1, -1, 38,
+ 39, -1, 41, 42, 43, 44, 45, 46, 47, 48,
+ 49, -1, -1, 52, 53, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 71, -1, -1, -1, 10, 11, 12, -1,
+ -1, -1, 81, 82, 83, -1, 85, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31, 32, -1,
+ -1, -1, -1, -1, 38, 39, -1, 41, 42, 43,
+ 44, 45, 46, 47, 48, 49, -1, -1, 52, 53,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 71, -1, -1,
+ 74, 10, 11, 12, -1, -1, -1, -1, 82, 83,
+ -1, 85, 21, 22, 23, 24, 25, 26, 27, 28,
+ 29, 30, 31, 32, -1, -1, -1, -1, -1, 38,
+ 39, -1, 41, 42, 43, 44, 45, 46, 47, 48,
+ 49, -1, -1, 52, 53, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 71, -1, -1, -1, 10, 11, 12, -1,
+ -1, -1, -1, 82, 83, -1, 85, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31, 32, -1,
+ -1, -1, -1, -1, 38, 39, -1, 41, 42, 43,
+ 44, 45, 46, 47, 48, 49, -1, -1, 52, 53,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 71, 4, 5,
+ 6, -1, -1, -1, 10, 11, 12, -1, 82, 83,
+ -1, 85, -1, -1, -1, 21, 22, 23, 24, 25,
+ 26, 27, 28, 29, 30, 31, 32, -1, -1, -1,
+ -1, -1, 38, 39, -1, 41, 42, 43, 44, -1,
+ 46, 4, 5, 6, -1, -1, -1, 10, 11, 12,
+ -1, -1, -1, -1, -1, -1, -1, -1, 21, 22,
+ 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
+ 76, -1, -1, -1, -1, 38, 39, -1, 41, 42,
+ 43, 44, -1, 46, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 0, -1, -1, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, -1, -1, -1, -1,
+ -1, -1, -1, 76, 21, 22, 23, 24, 25, 26,
+ 27, 28, 29, 30, 31, 32, -1, -1, -1, 36,
+ 37, 38, 39, -1, 41, 42, 43, 44, -1, 46,
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+ -1, -1, -1, -1, -1, -1, -1, -1, 21, 22,
+ 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
+ -1, -1, -1, 36, 37, 38, 39, -1, 41, 42,
+ 43, 44, -1, 46, 4, 5, 6, -1, -1, -1,
+ 10, 11, 12, -1, -1, -1, -1, -1, -1, -1,
+ -1, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, -1, -1, -1, -1, -1, 38, 39,
+ -1, 41, 42, 43, 44, -1, 46, 10, 11, 12,
+ -1, -1, -1, -1, -1, -1, -1, -1, 21, 22,
+ 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
+ -1, -1, -1, -1, -1, 38, 39, -1, 41, 42,
+ 43, 44, 45, 46, 10, 11, 12, -1, -1, -1,
+ -1, -1, -1, -1, -1, 21, 22, 23, 24, 25,
+ 26, 27, 28, 29, 30, 31, 32, -1, -1, -1,
+ -1, -1, 38, 39, -1, 41, 42, 43, 44, -1,
+ 46
+};
+
+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+ symbol of state STATE-NUM. */
+static const yytype_uint8 yystos[] =
+{
+ 0, 3, 4, 5, 6, 7, 8, 9, 10, 11,
+ 12, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 36, 37, 38, 39, 41, 42, 43,
+ 44, 46, 126, 127, 128, 129, 130, 135, 136, 137,
+ 138, 139, 140, 141, 142, 143, 175, 176, 177, 37,
+ 45, 140, 45, 46, 75, 96, 81, 178, 72, 78,
+ 3, 33, 34, 35, 132, 133, 138, 78, 81, 45,
+ 96, 139, 141, 73, 0, 176, 141, 145, 75, 75,
+ 161, 132, 131, 134, 139, 133, 96, 71, 73, 80,
+ 45, 47, 48, 49, 52, 53, 71, 82, 83, 85,
+ 97, 98, 99, 101, 102, 103, 104, 105, 106, 107,
+ 108, 109, 110, 111, 112, 113, 114, 115, 116, 117,
+ 118, 119, 120, 121, 125, 142, 81, 139, 146, 147,
+ 144, 13, 14, 15, 17, 18, 19, 20, 40, 75,
+ 76, 81, 108, 121, 122, 124, 126, 127, 142, 151,
+ 152, 153, 154, 162, 163, 164, 167, 174, 96, 131,
+ 134, 73, 80, 74, 125, 122, 150, 108, 108, 124,
+ 52, 53, 73, 77, 72, 72, 78, 39, 122, 71,
+ 108, 86, 87, 83, 85, 54, 55, 89, 90, 56,
+ 57, 58, 60, 59, 94, 74, 96, 148, 149, 76,
+ 147, 146, 81, 81, 169, 71, 71, 81, 81, 124,
+ 71, 76, 155, 61, 62, 63, 70, 80, 123, 78,
+ 81, 76, 152, 73, 74, 125, 150, 74, 72, 100,
+ 124, 45, 46, 96, 103, 122, 108, 108, 110, 110,
+ 112, 112, 112, 112, 113, 113, 117, 118, 119, 124,
+ 73, 78, 81, 76, 158, 159, 160, 170, 124, 81,
+ 168, 162, 122, 122, 125, 74, 74, 79, 125, 149,
+ 40, 161, 153, 151, 163, 171, 72, 124, 137, 166,
+ 156, 74, 122, 74, 71, 166, 172, 173, 158, 165,
+ 96, 72, 76, 124, 81, 72, 16, 80, 153, 157,
+ 161, 72, 124, 157, 158, 150, 81
+};
+
+#define yyerrok (yyerrstatus = 0)
+#define yyclearin (yychar = YYEMPTY)
+#define YYEMPTY (-2)
+#define YYEOF 0
+
+#define YYACCEPT goto yyacceptlab
+#define YYABORT goto yyabortlab
+#define YYERROR goto yyerrorlab
+
+
+/* Like YYERROR except do call yyerror. This remains here temporarily
+ to ease the transition to the new meaning of YYERROR, for GCC.
+ Once GCC version 2 has supplanted version 1, this can go. However,
+ YYFAIL appears to be in use. Nevertheless, it is formally deprecated
+ in Bison 2.4.2's NEWS entry, where a plan to phase it out is
+ discussed. */
+
+#define YYFAIL goto yyerrlab
+#if defined YYFAIL
+ /* This is here to suppress warnings from the GCC cpp's
+ -Wunused-macros. Normally we don't worry about that warning, but
+ some users do, and we want to make it easy for users to remove
+ YYFAIL uses, which will produce warnings from Bison 2.5. */
+#endif
+
+#define YYRECOVERING() (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value) \
+do \
+ if (yychar == YYEMPTY) \
+ { \
+ yychar = (Token); \
+ yylval = (Value); \
+ YYPOPSTACK (yylen); \
+ yystate = *yyssp; \
+ goto yybackup; \
+ } \
+ else \
+ { \
+ yyerror (&yylloc, context, YY_("syntax error: cannot back up")); \
+ YYERROR; \
+ } \
+while (YYID (0))
+
+/* Error token number */
+#define YYTERROR 1
+#define YYERRCODE 256
+
+
+/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
+ If N is 0, then set CURRENT to the empty location which ends
+ the previous symbol: RHS[0] (always defined). */
+
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N) \
+ do \
+ if (YYID (N)) \
+ { \
+ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
+ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
+ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
+ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
+ } \
+ else \
+ { \
+ (Current).first_line = (Current).last_line = \
+ YYRHSLOC (Rhs, 0).last_line; \
+ (Current).first_column = (Current).last_column = \
+ YYRHSLOC (Rhs, 0).last_column; \
+ } \
+ while (YYID (0))
+#endif
+
+#define YYRHSLOC(Rhs, K) ((Rhs)[K])
+
+
+/* YY_LOCATION_PRINT -- Print the location on the stream.
+ This macro was not mandated originally: define only if we know
+ we won't break user code: when these are the locations we know. */
+
+#ifndef YY_LOCATION_PRINT
+# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
+
+/* Print *YYLOCP on YYO. Private, do not rely on its existence. */
+
+__attribute__((__unused__))
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static unsigned
+yy_location_print_ (FILE *yyo, YYLTYPE const * const yylocp)
+#else
+static unsigned
+yy_location_print_ (yyo, yylocp)
+ FILE *yyo;
+ YYLTYPE const * const yylocp;
+#endif
+{
+ unsigned res = 0;
+ int end_col = 0 != yylocp->last_column ? yylocp->last_column - 1 : 0;
+ if (0 <= yylocp->first_line)
+ {
+ res += fprintf (yyo, "%d", yylocp->first_line);
+ if (0 <= yylocp->first_column)
+ res += fprintf (yyo, ".%d", yylocp->first_column);
+ }
+ if (0 <= yylocp->last_line)
+ {
+ if (yylocp->first_line < yylocp->last_line)
+ {
+ res += fprintf (yyo, "-%d", yylocp->last_line);
+ if (0 <= end_col)
+ res += fprintf (yyo, ".%d", end_col);
+ }
+ else if (0 <= end_col && yylocp->first_column < end_col)
+ res += fprintf (yyo, "-%d", end_col);
+ }
+ return res;
+ }
+
+# define YY_LOCATION_PRINT(File, Loc) \
+ yy_location_print_ (File, &(Loc))
+
+# else
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
+#endif
+
+
+/* YYLEX -- calling `yylex' with the right arguments. */
+#ifdef YYLEX_PARAM
+# define YYLEX yylex (&yylval, &yylloc, YYLEX_PARAM)
+#else
+# define YYLEX yylex (&yylval, &yylloc)
+#endif
+
+/* Enable debugging if requested. */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+# define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args) \
+do { \
+ if (yydebug) \
+ YYFPRINTF Args; \
+} while (YYID (0))
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
+do { \
+ if (yydebug) \
+ { \
+ YYFPRINTF (stderr, "%s ", Title); \
+ yy_symbol_print (stderr, \
+ Type, Value, Location, context); \
+ YYFPRINTF (stderr, "\n"); \
+ } \
+} while (YYID (0))
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, TParseContext* context)
+#else
+static void
+yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, context)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE const * const yyvaluep;
+ YYLTYPE const * const yylocationp;
+ TParseContext* context;
+#endif
+{
+ FILE *yyo = yyoutput;
+ YYUSE (yyo);
+ if (!yyvaluep)
+ return;
+ YYUSE (yylocationp);
+ YYUSE (context);
+# ifdef YYPRINT
+ if (yytype < YYNTOKENS)
+ YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# else
+ YYUSE (yyoutput);
+# endif
+ YYUSE (yytype);
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, TParseContext* context)
+#else
+static void
+yy_symbol_print (yyoutput, yytype, yyvaluep, yylocationp, context)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE const * const yyvaluep;
+ YYLTYPE const * const yylocationp;
+ TParseContext* context;
+#endif
+{
+ if (yytype < YYNTOKENS)
+ YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+ else
+ YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+ YY_LOCATION_PRINT (yyoutput, *yylocationp);
+ YYFPRINTF (yyoutput, ": ");
+ yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, context);
+ YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included). |
+`------------------------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
+#else
+static void
+yy_stack_print (yybottom, yytop)
+ yytype_int16 *yybottom;
+ yytype_int16 *yytop;
+#endif
+{
+ YYFPRINTF (stderr, "Stack now");
+ for (; yybottom <= yytop; yybottom++)
+ {
+ int yybot = *yybottom;
+ YYFPRINTF (stderr, " %d", yybot);
+ }
+ YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top) \
+do { \
+ if (yydebug) \
+ yy_stack_print ((Bottom), (Top)); \
+} while (YYID (0))
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced. |
+`------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_reduce_print (YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule, TParseContext* context)
+#else
+static void
+yy_reduce_print (yyvsp, yylsp, yyrule, context)
+ YYSTYPE *yyvsp;
+ YYLTYPE *yylsp;
+ int yyrule;
+ TParseContext* context;
+#endif
+{
+ int yynrhs = yyr2[yyrule];
+ int yyi;
+ unsigned long int yylno = yyrline[yyrule];
+ YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+ yyrule - 1, yylno);
+ /* The symbols being reduced. */
+ for (yyi = 0; yyi < yynrhs; yyi++)
+ {
+ YYFPRINTF (stderr, " $%d = ", yyi + 1);
+ yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
+ &(yyvsp[(yyi + 1) - (yynrhs)])
+ , &(yylsp[(yyi + 1) - (yynrhs)]) , context);
+ YYFPRINTF (stderr, "\n");
+ }
+}
+
+# define YY_REDUCE_PRINT(Rule) \
+do { \
+ if (yydebug) \
+ yy_reduce_print (yyvsp, yylsp, Rule, context); \
+} while (YYID (0))
+
+/* Nonzero means print parse trace. It is left uninitialized so that
+ multiple parsers can coexist. */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks. */
+#ifndef YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+ if the built-in stack extension method is used).
+
+ Do not make this value too large; the results are undefined if
+ YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+ evaluated with infinite-precision integer arithmetic. */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+# if defined __GLIBC__ && defined _STRING_H
+# define yystrlen strlen
+# else
+/* Return the length of YYSTR. */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static YYSIZE_T
+yystrlen (const char *yystr)
+#else
+static YYSIZE_T
+yystrlen (yystr)
+ const char *yystr;
+#endif
+{
+ YYSIZE_T yylen;
+ for (yylen = 0; yystr[yylen]; yylen++)
+ continue;
+ return yylen;
+}
+# endif
+# endif
+
+# ifndef yystpcpy
+# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+# define yystpcpy stpcpy
+# else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+ YYDEST. */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+#else
+static char *
+yystpcpy (yydest, yysrc)
+ char *yydest;
+ const char *yysrc;
+#endif
+{
+ char *yyd = yydest;
+ const char *yys = yysrc;
+
+ while ((*yyd++ = *yys++) != '\0')
+ continue;
+
+ return yyd - 1;
+}
+# endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+ quotes and backslashes, so that it's suitable for yyerror. The
+ heuristic is that double-quoting is unnecessary unless the string
+ contains an apostrophe, a comma, or backslash (other than
+ backslash-backslash). YYSTR is taken from yytname. If YYRES is
+ null, do not copy; instead, return the length of what the result
+ would have been. */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+ if (*yystr == '"')
+ {
+ YYSIZE_T yyn = 0;
+ char const *yyp = yystr;
+
+ for (;;)
+ switch (*++yyp)
+ {
+ case '\'':
+ case ',':
+ goto do_not_strip_quotes;
+
+ case '\\':
+ if (*++yyp != '\\')
+ goto do_not_strip_quotes;
+ /* Fall through. */
+ default:
+ if (yyres)
+ yyres[yyn] = *yyp;
+ yyn++;
+ break;
+
+ case '"':
+ if (yyres)
+ yyres[yyn] = '\0';
+ return yyn;
+ }
+ do_not_strip_quotes: ;
+ }
+
+ if (! yyres)
+ return yystrlen (yystr);
+
+ return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
+ about the unexpected token YYTOKEN for the state stack whose top is
+ YYSSP.
+
+ Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is
+ not large enough to hold the message. In that case, also set
+ *YYMSG_ALLOC to the required number of bytes. Return 2 if the
+ required number of bytes is too large to store. */
+static int
+yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
+ yytype_int16 *yyssp, int yytoken)
+{
+ YYSIZE_T yysize0 = yytnamerr (YY_NULL, yytname[yytoken]);
+ YYSIZE_T yysize = yysize0;
+ enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+ /* Internationalized format string. */
+ const char *yyformat = YY_NULL;
+ /* Arguments of yyformat. */
+ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+ /* Number of reported tokens (one for the "unexpected", one per
+ "expected"). */
+ int yycount = 0;
+
+ /* There are many possibilities here to consider:
+ - Assume YYFAIL is not used. It's too flawed to consider. See
+ <http://lists.gnu.org/archive/html/bison-patches/2009-12/msg00024.html>
+ for details. YYERROR is fine as it does not invoke this
+ function.
+ - If this state is a consistent state with a default action, then
+ the only way this function was invoked is if the default action
+ is an error action. In that case, don't check for expected
+ tokens because there are none.
+ - The only way there can be no lookahead present (in yychar) is if
+ this state is a consistent state with a default action. Thus,
+ detecting the absence of a lookahead is sufficient to determine
+ that there is no unexpected or expected token to report. In that
+ case, just report a simple "syntax error".
+ - Don't assume there isn't a lookahead just because this state is a
+ consistent state with a default action. There might have been a
+ previous inconsistent state, consistent state with a non-default
+ action, or user semantic action that manipulated yychar.
+ - Of course, the expected token list depends on states to have
+ correct lookahead information, and it depends on the parser not
+ to perform extra reductions after fetching a lookahead from the
+ scanner and before detecting a syntax error. Thus, state merging
+ (from LALR or IELR) and default reductions corrupt the expected
+ token list. However, the list is correct for canonical LR with
+ one exception: it will still contain any token that will not be
+ accepted due to an error action in a later state.
+ */
+ if (yytoken != YYEMPTY)
+ {
+ int yyn = yypact[*yyssp];
+ yyarg[yycount++] = yytname[yytoken];
+ if (!yypact_value_is_default (yyn))
+ {
+ /* Start YYX at -YYN if negative to avoid negative indexes in
+ YYCHECK. In other words, skip the first -YYN actions for
+ this state because they are default actions. */
+ int yyxbegin = yyn < 0 ? -yyn : 0;
+ /* Stay within bounds of both yycheck and yytname. */
+ int yychecklim = YYLAST - yyn + 1;
+ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+ int yyx;
+
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
+ && !yytable_value_is_error (yytable[yyx + yyn]))
+ {
+ if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+ {
+ yycount = 1;
+ yysize = yysize0;
+ break;
+ }
+ yyarg[yycount++] = yytname[yyx];
+ {
+ YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULL, yytname[yyx]);
+ if (! (yysize <= yysize1
+ && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+ return 2;
+ yysize = yysize1;
+ }
+ }
+ }
+ }
+
+ switch (yycount)
+ {
+# define YYCASE_(N, S) \
+ case N: \
+ yyformat = S; \
+ break
+ YYCASE_(0, YY_("syntax error"));
+ YYCASE_(1, YY_("syntax error, unexpected %s"));
+ YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
+ YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
+ YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
+ YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
+# undef YYCASE_
+ }
+
+ {
+ YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
+ if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+ return 2;
+ yysize = yysize1;
+ }
+
+ if (*yymsg_alloc < yysize)
+ {
+ *yymsg_alloc = 2 * yysize;
+ if (! (yysize <= *yymsg_alloc
+ && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
+ *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
+ return 1;
+ }
+
+ /* Avoid sprintf, as that infringes on the user's name space.
+ Don't have undefined behavior even if the translation
+ produced a string with the wrong number of "%s"s. */
+ {
+ char *yyp = *yymsg;
+ int yyi = 0;
+ while ((*yyp = *yyformat) != '\0')
+ if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
+ {
+ yyp += yytnamerr (yyp, yyarg[yyi++]);
+ yyformat += 2;
+ }
+ else
+ {
+ yyp++;
+ yyformat++;
+ }
+ }
+ return 0;
+}
+#endif /* YYERROR_VERBOSE */
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol. |
+`-----------------------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp, TParseContext* context)
+#else
+static void
+yydestruct (yymsg, yytype, yyvaluep, yylocationp, context)
+ const char *yymsg;
+ int yytype;
+ YYSTYPE *yyvaluep;
+ YYLTYPE *yylocationp;
+ TParseContext* context;
+#endif
+{
+ YYUSE (yyvaluep);
+ YYUSE (yylocationp);
+ YYUSE (context);
+
+ if (!yymsg)
+ yymsg = "Deleting";
+ YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+ YYUSE (yytype);
+}
+
+
+
+
+/*----------.
+| yyparse. |
+`----------*/
+
+#ifdef YYPARSE_PARAM
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void *YYPARSE_PARAM)
+#else
+int
+yyparse (YYPARSE_PARAM)
+ void *YYPARSE_PARAM;
+#endif
+#else /* ! YYPARSE_PARAM */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (TParseContext* context)
+#else
+int
+yyparse (context)
+ TParseContext* context;
+#endif
+#endif
+{
+/* The lookahead symbol. */
+int yychar;
+
+
+#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
+/* Suppress an incorrect diagnostic about yylval being uninitialized. */
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
+ _Pragma ("GCC diagnostic push") \
+ _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
+ _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
+ _Pragma ("GCC diagnostic pop")
+#else
+/* Default value used for initialization, for pacifying older GCCs
+ or non-GCC compilers. */
+static YYSTYPE yyval_default;
+# define YY_INITIAL_VALUE(Value) = Value
+#endif
+static YYLTYPE yyloc_default
+# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
+ = { 1, 1, 1, 1 }
+# endif
+;
+#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END
+#endif
+#ifndef YY_INITIAL_VALUE
+# define YY_INITIAL_VALUE(Value) /* Nothing. */
+#endif
+
+/* The semantic value of the lookahead symbol. */
+YYSTYPE yylval YY_INITIAL_VALUE(yyval_default);
+
+/* Location data for the lookahead symbol. */
+YYLTYPE yylloc = yyloc_default;
+
+
+ /* Number of syntax errors so far. */
+ int yynerrs;
+
+ int yystate;
+ /* Number of tokens to shift before error messages enabled. */
+ int yyerrstatus;
+
+ /* The stacks and their tools:
+ `yyss': related to states.
+ `yyvs': related to semantic values.
+ `yyls': related to locations.
+
+ Refer to the stacks through separate pointers, to allow yyoverflow
+ to reallocate them elsewhere. */
+
+ /* The state stack. */
+ yytype_int16 yyssa[YYINITDEPTH];
+ yytype_int16 *yyss;
+ yytype_int16 *yyssp;
+
+ /* The semantic value stack. */
+ YYSTYPE yyvsa[YYINITDEPTH];
+ YYSTYPE *yyvs;
+ YYSTYPE *yyvsp;
+
+ /* The location stack. */
+ YYLTYPE yylsa[YYINITDEPTH];
+ YYLTYPE *yyls;
+ YYLTYPE *yylsp;
+
+ /* The locations where the error started and ended. */
+ YYLTYPE yyerror_range[3];
+
+ YYSIZE_T yystacksize;
+
+ int yyn;
+ int yyresult;
+ /* Lookahead token as an internal (translated) token number. */
+ int yytoken = 0;
+ /* The variables used to return semantic value and location from the
+ action routines. */
+ YYSTYPE yyval;
+ YYLTYPE yyloc;
+
+#if YYERROR_VERBOSE
+ /* Buffer for error messages, and its allocated size. */
+ char yymsgbuf[128];
+ char *yymsg = yymsgbuf;
+ YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N), yylsp -= (N))
+
+ /* The number of symbols on the RHS of the reduced rule.
+ Keep to zero when no symbol should be popped. */
+ int yylen = 0;
+
+ yyssp = yyss = yyssa;
+ yyvsp = yyvs = yyvsa;
+ yylsp = yyls = yylsa;
+ yystacksize = YYINITDEPTH;
+
+ YYDPRINTF ((stderr, "Starting parse\n"));
+
+ yystate = 0;
+ yyerrstatus = 0;
+ yynerrs = 0;
+ yychar = YYEMPTY; /* Cause a token to be read. */
+ yylsp[0] = yylloc;
+ goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate. |
+`------------------------------------------------------------*/
+ yynewstate:
+ /* In all cases, when you get here, the value and location stacks
+ have just been pushed. So pushing a state here evens the stacks. */
+ yyssp++;
+
+ yysetstate:
+ *yyssp = yystate;
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ {
+ /* Get the current used size of the three stacks, in elements. */
+ YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+ {
+ /* Give user a chance to reallocate the stack. Use copies of
+ these so that the &'s don't force the real ones into
+ memory. */
+ YYSTYPE *yyvs1 = yyvs;
+ yytype_int16 *yyss1 = yyss;
+ YYLTYPE *yyls1 = yyls;
+
+ /* Each stack pointer address is followed by the size of the
+ data in use in that stack, in bytes. This used to be a
+ conditional around just the two extra args, but that might
+ be undefined if yyoverflow is a macro. */
+ yyoverflow (YY_("memory exhausted"),
+ &yyss1, yysize * sizeof (*yyssp),
+ &yyvs1, yysize * sizeof (*yyvsp),
+ &yyls1, yysize * sizeof (*yylsp),
+ &yystacksize);
+
+ yyls = yyls1;
+ yyss = yyss1;
+ yyvs = yyvs1;
+ }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+ goto yyexhaustedlab;
+# else
+ /* Extend the stack our own way. */
+ if (YYMAXDEPTH <= yystacksize)
+ goto yyexhaustedlab;
+ yystacksize *= 2;
+ if (YYMAXDEPTH < yystacksize)
+ yystacksize = YYMAXDEPTH;
+
+ {
+ yytype_int16 *yyss1 = yyss;
+ union yyalloc *yyptr =
+ (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+ if (! yyptr)
+ goto yyexhaustedlab;
+ YYSTACK_RELOCATE (yyss_alloc, yyss);
+ YYSTACK_RELOCATE (yyvs_alloc, yyvs);
+ YYSTACK_RELOCATE (yyls_alloc, yyls);
+# undef YYSTACK_RELOCATE
+ if (yyss1 != yyssa)
+ YYSTACK_FREE (yyss1);
+ }
+# endif
+#endif /* no yyoverflow */
+
+ yyssp = yyss + yysize - 1;
+ yyvsp = yyvs + yysize - 1;
+ yylsp = yyls + yysize - 1;
+
+ YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+ (unsigned long int) yystacksize));
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ YYABORT;
+ }
+
+ YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+ if (yystate == YYFINAL)
+ YYACCEPT;
+
+ goto yybackup;
+
+/*-----------.
+| yybackup. |
+`-----------*/
+yybackup:
+
+ /* Do appropriate processing given the current state. Read a
+ lookahead token if we need one and don't already have one. */
+
+ /* First try to decide what to do without reference to lookahead token. */
+ yyn = yypact[yystate];
+ if (yypact_value_is_default (yyn))
+ goto yydefault;
+
+ /* Not known => get a lookahead token if don't already have one. */
+
+ /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */
+ if (yychar == YYEMPTY)
+ {
+ YYDPRINTF ((stderr, "Reading a token: "));
+ yychar = YYLEX;
+ }
+
+ if (yychar <= YYEOF)
+ {
+ yychar = yytoken = YYEOF;
+ YYDPRINTF ((stderr, "Now at end of input.\n"));
+ }
+ else
+ {
+ yytoken = YYTRANSLATE (yychar);
+ YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+ }
+
+ /* If the proper action on seeing token YYTOKEN is to reduce or to
+ detect an error, take that action. */
+ yyn += yytoken;
+ if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+ goto yydefault;
+ yyn = yytable[yyn];
+ if (yyn <= 0)
+ {
+ if (yytable_value_is_error (yyn))
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+
+ /* Count tokens shifted since error; after three, turn off error
+ status. */
+ if (yyerrstatus)
+ yyerrstatus--;
+
+ /* Shift the lookahead token. */
+ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+ /* Discard the shifted token. */
+ yychar = YYEMPTY;
+
+ yystate = yyn;
+ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+ *++yyvsp = yylval;
+ YY_IGNORE_MAYBE_UNINITIALIZED_END
+ *++yylsp = yylloc;
+ goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state. |
+`-----------------------------------------------------------*/
+yydefault:
+ yyn = yydefact[yystate];
+ if (yyn == 0)
+ goto yyerrlab;
+ goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction. |
+`-----------------------------*/
+yyreduce:
+ /* yyn is the number of a rule to reduce with. */
+ yylen = yyr2[yyn];
+
+ /* If YYLEN is nonzero, implement the default value of the action:
+ `$$ = $1'.
+
+ Otherwise, the following line sets YYVAL to garbage.
+ This behavior is undocumented and Bison
+ users should not rely upon it. Assigning to YYVAL
+ unconditionally makes the parser a bit smaller, and it avoids a
+ GCC warning that YYVAL may be used uninitialized. */
+ yyval = yyvsp[1-yylen];
+
+ /* Default location. */
+ YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen);
+ YY_REDUCE_PRINT (yyn);
+ switch (yyn)
+ {
+ case 4:
+
+ {
+ // The symbol table search was done in the lexical phase
+ const TSymbol *symbol = (yyvsp[(1) - (1)].lex).symbol;
+ const TVariable *variable = 0;
+
+ if (!symbol)
+ {
+ context->error((yylsp[(1) - (1)]), "undeclared identifier", (yyvsp[(1) - (1)].lex).string->c_str());
+ context->recover();
+ }
+ else if (!symbol->isVariable())
+ {
+ context->error((yylsp[(1) - (1)]), "variable expected", (yyvsp[(1) - (1)].lex).string->c_str());
+ context->recover();
+ }
+ else
+ {
+ variable = static_cast<const TVariable*>(symbol);
+
+ if (context->symbolTable.findBuiltIn(variable->getName()) &&
+ !variable->getExtension().empty() &&
+ context->extensionErrorCheck((yylsp[(1) - (1)]), variable->getExtension()))
+ {
+ context->recover();
+ }
+ }
+
+ if (!variable)
+ {
+ TType type(EbtFloat, EbpUndefined);
+ TVariable *fakeVariable = new TVariable((yyvsp[(1) - (1)].lex).string, type);
+ context->symbolTable.insert(*fakeVariable);
+ variable = fakeVariable;
+ }
+
+ if (variable->getType().getQualifier() == EvqConst)
+ {
+ ConstantUnion* constArray = variable->getConstPointer();
+ TType t(variable->getType());
+ (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(constArray, t, (yylsp[(1) - (1)]));
+ }
+ else
+ {
+ (yyval.interm.intermTypedNode) = context->intermediate.addSymbol(variable->getUniqueId(),
+ variable->getName(),
+ variable->getType(),
+ (yylsp[(1) - (1)]));
+ }
+
+ // don't delete $1.string, it's used by error recovery, and the pool
+ // pop will reclaim the memory
+ }
+ break;
+
+ case 5:
+
+ {
+ (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode);
+ }
+ break;
+
+ case 6:
+
+ {
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setIConst((yyvsp[(1) - (1)].lex).i);
+ (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), (yylsp[(1) - (1)]));
+ }
+ break;
+
+ case 7:
+
+ {
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setFConst((yyvsp[(1) - (1)].lex).f);
+ (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), (yylsp[(1) - (1)]));
+ }
+ break;
+
+ case 8:
+
+ {
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setBConst((yyvsp[(1) - (1)].lex).b);
+ (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yylsp[(1) - (1)]));
+ }
+ break;
+
+ case 9:
+
+ {
+ (yyval.interm.intermTypedNode) = (yyvsp[(2) - (3)].interm.intermTypedNode);
+ }
+ break;
+
+ case 10:
+
+ {
+ (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode);
+ }
+ break;
+
+ case 11:
+
+ {
+ (yyval.interm.intermTypedNode) = context->addIndexExpression((yyvsp[(1) - (4)].interm.intermTypedNode), (yylsp[(2) - (4)]), (yyvsp[(3) - (4)].interm.intermTypedNode));
+ }
+ break;
+
+ case 12:
+
+ {
+ (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode);
+ }
+ break;
+
+ case 13:
+
+ {
+ if ((yyvsp[(1) - (3)].interm.intermTypedNode)->isArray()) {
+ context->error((yylsp[(3) - (3)]), "cannot apply dot operator to an array", ".");
+ context->recover();
+ }
+
+ if ((yyvsp[(1) - (3)].interm.intermTypedNode)->isVector()) {
+ TVectorFields fields;
+ if (! context->parseVectorFields(*(yyvsp[(3) - (3)].lex).string, (yyvsp[(1) - (3)].interm.intermTypedNode)->getNominalSize(), fields, (yylsp[(3) - (3)]))) {
+ fields.num = 1;
+ fields.offsets[0] = 0;
+ context->recover();
+ }
+
+ if ((yyvsp[(1) - (3)].interm.intermTypedNode)->getType().getQualifier() == EvqConst) { // constant folding for vector fields
+ (yyval.interm.intermTypedNode) = context->addConstVectorNode(fields, (yyvsp[(1) - (3)].interm.intermTypedNode), (yylsp[(3) - (3)]));
+ if ((yyval.interm.intermTypedNode) == 0) {
+ context->recover();
+ (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode);
+ }
+ else
+ (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (3)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (3)].interm.intermTypedNode)->getPrecision(), EvqConst, (int) (*(yyvsp[(3) - (3)].lex).string).size()));
+ } else {
+ TString vectorString = *(yyvsp[(3) - (3)].lex).string;
+ TIntermTyped* index = context->intermediate.addSwizzle(fields, (yylsp[(3) - (3)]));
+ (yyval.interm.intermTypedNode) = context->intermediate.addIndex(EOpVectorSwizzle, (yyvsp[(1) - (3)].interm.intermTypedNode), index, (yylsp[(2) - (3)]));
+ (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (3)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (3)].interm.intermTypedNode)->getPrecision(), EvqTemporary, (int) vectorString.size()));
+ }
+ } else if ((yyvsp[(1) - (3)].interm.intermTypedNode)->isMatrix()) {
+ TMatrixFields fields;
+ if (! context->parseMatrixFields(*(yyvsp[(3) - (3)].lex).string, (yyvsp[(1) - (3)].interm.intermTypedNode)->getNominalSize(), fields, (yylsp[(3) - (3)]))) {
+ fields.wholeRow = false;
+ fields.wholeCol = false;
+ fields.row = 0;
+ fields.col = 0;
+ context->recover();
+ }
+
+ if (fields.wholeRow || fields.wholeCol) {
+ context->error((yylsp[(2) - (3)]), " non-scalar fields not implemented yet", ".");
+ context->recover();
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setIConst(0);
+ TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), (yylsp[(3) - (3)]));
+ (yyval.interm.intermTypedNode) = context->intermediate.addIndex(EOpIndexDirect, (yyvsp[(1) - (3)].interm.intermTypedNode), index, (yylsp[(2) - (3)]));
+ (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (3)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (3)].interm.intermTypedNode)->getPrecision(),EvqTemporary, (yyvsp[(1) - (3)].interm.intermTypedNode)->getNominalSize()));
+ } else {
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setIConst(fields.col * (yyvsp[(1) - (3)].interm.intermTypedNode)->getNominalSize() + fields.row);
+ TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), (yylsp[(3) - (3)]));
+ (yyval.interm.intermTypedNode) = context->intermediate.addIndex(EOpIndexDirect, (yyvsp[(1) - (3)].interm.intermTypedNode), index, (yylsp[(2) - (3)]));
+ (yyval.interm.intermTypedNode)->setType(TType((yyvsp[(1) - (3)].interm.intermTypedNode)->getBasicType(), (yyvsp[(1) - (3)].interm.intermTypedNode)->getPrecision()));
+ }
+ } else if ((yyvsp[(1) - (3)].interm.intermTypedNode)->getBasicType() == EbtStruct) {
+ bool fieldFound = false;
+ const TFieldList& fields = (yyvsp[(1) - (3)].interm.intermTypedNode)->getType().getStruct()->fields();
+ unsigned int i;
+ for (i = 0; i < fields.size(); ++i) {
+ if (fields[i]->name() == *(yyvsp[(3) - (3)].lex).string) {
+ fieldFound = true;
+ break;
+ }
+ }
+ if (fieldFound) {
+ if ((yyvsp[(1) - (3)].interm.intermTypedNode)->getType().getQualifier() == EvqConst) {
+ (yyval.interm.intermTypedNode) = context->addConstStruct(*(yyvsp[(3) - (3)].lex).string, (yyvsp[(1) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)]));
+ if ((yyval.interm.intermTypedNode) == 0) {
+ context->recover();
+ (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode);
+ }
+ else {
+ (yyval.interm.intermTypedNode)->setType(*fields[i]->type());
+ // change the qualifier of the return type, not of the structure field
+ // as the structure definition is shared between various structures.
+ (yyval.interm.intermTypedNode)->getTypePointer()->setQualifier(EvqConst);
+ }
+ } else {
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setIConst(i);
+ TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, *fields[i]->type(), (yylsp[(3) - (3)]));
+ (yyval.interm.intermTypedNode) = context->intermediate.addIndex(EOpIndexDirectStruct, (yyvsp[(1) - (3)].interm.intermTypedNode), index, (yylsp[(2) - (3)]));
+ (yyval.interm.intermTypedNode)->setType(*fields[i]->type());
+ }
+ } else {
+ context->error((yylsp[(2) - (3)]), " no such field in structure", (yyvsp[(3) - (3)].lex).string->c_str());
+ context->recover();
+ (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode);
+ }
+ } else {
+ context->error((yylsp[(2) - (3)]), " field selection requires structure, vector, or matrix on left hand side", (yyvsp[(3) - (3)].lex).string->c_str());
+ context->recover();
+ (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode);
+ }
+ // don't delete $3.string, it's from the pool
+ }
+ break;
+
+ case 14:
+
+ {
+ if (context->lValueErrorCheck((yylsp[(2) - (2)]), "++", (yyvsp[(1) - (2)].interm.intermTypedNode)))
+ context->recover();
+ (yyval.interm.intermTypedNode) = context->intermediate.addUnaryMath(EOpPostIncrement, (yyvsp[(1) - (2)].interm.intermTypedNode), (yylsp[(2) - (2)]), context->symbolTable);
+ if ((yyval.interm.intermTypedNode) == 0) {
+ context->unaryOpError((yylsp[(2) - (2)]), "++", (yyvsp[(1) - (2)].interm.intermTypedNode)->getCompleteString());
+ context->recover();
+ (yyval.interm.intermTypedNode) = (yyvsp[(1) - (2)].interm.intermTypedNode);
+ }
+ }
+ break;
+
+ case 15:
+
+ {
+ if (context->lValueErrorCheck((yylsp[(2) - (2)]), "--", (yyvsp[(1) - (2)].interm.intermTypedNode)))
+ context->recover();
+ (yyval.interm.intermTypedNode) = context->intermediate.addUnaryMath(EOpPostDecrement, (yyvsp[(1) - (2)].interm.intermTypedNode), (yylsp[(2) - (2)]), context->symbolTable);
+ if ((yyval.interm.intermTypedNode) == 0) {
+ context->unaryOpError((yylsp[(2) - (2)]), "--", (yyvsp[(1) - (2)].interm.intermTypedNode)->getCompleteString());
+ context->recover();
+ (yyval.interm.intermTypedNode) = (yyvsp[(1) - (2)].interm.intermTypedNode);
+ }
+ }
+ break;
+
+ case 16:
+
+ {
+ if (context->integerErrorCheck((yyvsp[(1) - (1)].interm.intermTypedNode), "[]"))
+ context->recover();
+ (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode);
+ }
+ break;
+
+ case 17:
+
+ {
+ TFunction* fnCall = (yyvsp[(1) - (1)].interm).function;
+ TOperator op = fnCall->getBuiltInOp();
+
+ if (op != EOpNull)
+ {
+ //
+ // Then this should be a constructor.
+ // Don't go through the symbol table for constructors.
+ // Their parameters will be verified algorithmically.
+ //
+ TType type(EbtVoid, EbpUndefined); // use this to get the type back
+ if (context->constructorErrorCheck((yylsp[(1) - (1)]), (yyvsp[(1) - (1)].interm).intermNode, *fnCall, op, &type)) {
+ (yyval.interm.intermTypedNode) = 0;
+ } else {
+ //
+ // It's a constructor, of type 'type'.
+ //
+ (yyval.interm.intermTypedNode) = context->addConstructor((yyvsp[(1) - (1)].interm).intermNode, &type, op, fnCall, (yylsp[(1) - (1)]));
+ }
+
+ if ((yyval.interm.intermTypedNode) == 0) {
+ context->recover();
+ (yyval.interm.intermTypedNode) = context->intermediate.setAggregateOperator(0, op, (yylsp[(1) - (1)]));
+ }
+ (yyval.interm.intermTypedNode)->setType(type);
+ } else {
+ //
+ // Not a constructor. Find it in the symbol table.
+ //
+ const TFunction* fnCandidate;
+ bool builtIn;
+ fnCandidate = context->findFunction((yylsp[(1) - (1)]), fnCall, &builtIn);
+ if (fnCandidate) {
+ //
+ // A declared function.
+ //
+ if (builtIn && !fnCandidate->getExtension().empty() &&
+ context->extensionErrorCheck((yylsp[(1) - (1)]), fnCandidate->getExtension())) {
+ context->recover();
+ }
+ op = fnCandidate->getBuiltInOp();
+ if (builtIn && op != EOpNull) {
+ //
+ // A function call mapped to a built-in operation.
+ //
+ if (fnCandidate->getParamCount() == 1) {
+ //
+ // Treat it like a built-in unary operator.
+ //
+ (yyval.interm.intermTypedNode) = context->intermediate.addUnaryMath(op, (yyvsp[(1) - (1)].interm).intermNode, (yylsp[(1) - (1)]), context->symbolTable);
+ if ((yyval.interm.intermTypedNode) == 0) {
+ std::stringstream extraInfoStream;
+ extraInfoStream << "built in unary operator function. Type: " << static_cast<TIntermTyped*>((yyvsp[(1) - (1)].interm).intermNode)->getCompleteString();
+ std::string extraInfo = extraInfoStream.str();
+ context->error((yyvsp[(1) - (1)].interm).intermNode->getLine(), " wrong operand type", "Internal Error", extraInfo.c_str());
+ YYERROR;
+ }
+ } else {
+ (yyval.interm.intermTypedNode) = context->intermediate.setAggregateOperator((yyvsp[(1) - (1)].interm).intermAggregate, op, (yylsp[(1) - (1)]));
+ }
+ } else {
+ // This is a real function call
+
+ (yyval.interm.intermTypedNode) = context->intermediate.setAggregateOperator((yyvsp[(1) - (1)].interm).intermAggregate, EOpFunctionCall, (yylsp[(1) - (1)]));
+ (yyval.interm.intermTypedNode)->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)
+ (yyval.interm.intermTypedNode)->getAsAggregate()->setUserDefined();
+ (yyval.interm.intermTypedNode)->getAsAggregate()->setName(fnCandidate->getMangledName());
+
+ TQualifier qual;
+ for (size_t i = 0; i < fnCandidate->getParamCount(); ++i) {
+ qual = fnCandidate->getParam(i).type->getQualifier();
+ if (qual == EvqOut || qual == EvqInOut) {
+ if (context->lValueErrorCheck((yyval.interm.intermTypedNode)->getLine(), "assign", (yyval.interm.intermTypedNode)->getAsAggregate()->getSequence()[i]->getAsTyped())) {
+ context->error((yyvsp[(1) - (1)].interm).intermNode->getLine(), "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error");
+ context->recover();
+ }
+ }
+ }
+ }
+ (yyval.interm.intermTypedNode)->setType(fnCandidate->getReturnType());
+ } else {
+ // error message was put out by PaFindFunction()
+ // Put on a dummy node for error recovery
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setFConst(0.0f);
+ (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), (yylsp[(1) - (1)]));
+ context->recover();
+ }
+ }
+ delete fnCall;
+ }
+ break;
+
+ case 18:
+
+ {
+ (yyval.interm) = (yyvsp[(1) - (1)].interm);
+ }
+ break;
+
+ case 19:
+
+ {
+ context->error((yylsp[(3) - (3)]), "methods are not supported", "");
+ context->recover();
+ (yyval.interm) = (yyvsp[(3) - (3)].interm);
+ }
+ break;
+
+ case 20:
+
+ {
+ (yyval.interm) = (yyvsp[(1) - (2)].interm);
+ }
+ break;
+
+ case 21:
+
+ {
+ (yyval.interm) = (yyvsp[(1) - (2)].interm);
+ }
+ break;
+
+ case 22:
+
+ {
+ (yyval.interm).function = (yyvsp[(1) - (2)].interm.function);
+ (yyval.interm).intermNode = 0;
+ }
+ break;
+
+ case 23:
+
+ {
+ (yyval.interm).function = (yyvsp[(1) - (1)].interm.function);
+ (yyval.interm).intermNode = 0;
+ }
+ break;
+
+ case 24:
+
+ {
+ TParameter param = { 0, new TType((yyvsp[(2) - (2)].interm.intermTypedNode)->getType()) };
+ (yyvsp[(1) - (2)].interm.function)->addParameter(param);
+ (yyval.interm).function = (yyvsp[(1) - (2)].interm.function);
+ (yyval.interm).intermNode = (yyvsp[(2) - (2)].interm.intermTypedNode);
+ }
+ break;
+
+ case 25:
+
+ {
+ TParameter param = { 0, new TType((yyvsp[(3) - (3)].interm.intermTypedNode)->getType()) };
+ (yyvsp[(1) - (3)].interm).function->addParameter(param);
+ (yyval.interm).function = (yyvsp[(1) - (3)].interm).function;
+ (yyval.interm).intermNode = context->intermediate.growAggregate((yyvsp[(1) - (3)].interm).intermNode, (yyvsp[(3) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)]));
+ }
+ break;
+
+ case 26:
+
+ {
+ (yyval.interm.function) = (yyvsp[(1) - (2)].interm.function);
+ }
+ break;
+
+ case 27:
+
+ {
+ //
+ // Constructor
+ //
+ TOperator op = EOpNull;
+ if ((yyvsp[(1) - (1)].interm.type).userDef) {
+ op = EOpConstructStruct;
+ } else {
+ switch ((yyvsp[(1) - (1)].interm.type).type) {
+ case EbtFloat:
+ if ((yyvsp[(1) - (1)].interm.type).matrix) {
+ switch((yyvsp[(1) - (1)].interm.type).size) {
+ case 2: op = EOpConstructMat2; break;
+ case 3: op = EOpConstructMat3; break;
+ case 4: op = EOpConstructMat4; break;
+ }
+ } else {
+ switch((yyvsp[(1) - (1)].interm.type).size) {
+ case 1: op = EOpConstructFloat; break;
+ case 2: op = EOpConstructVec2; break;
+ case 3: op = EOpConstructVec3; break;
+ case 4: op = EOpConstructVec4; break;
+ }
+ }
+ break;
+ case EbtInt:
+ switch((yyvsp[(1) - (1)].interm.type).size) {
+ case 1: op = EOpConstructInt; break;
+ case 2: op = EOpConstructIVec2; break;
+ case 3: op = EOpConstructIVec3; break;
+ case 4: op = EOpConstructIVec4; break;
+ }
+ break;
+ case EbtBool:
+ switch((yyvsp[(1) - (1)].interm.type).size) {
+ case 1: op = EOpConstructBool; break;
+ case 2: op = EOpConstructBVec2; break;
+ case 3: op = EOpConstructBVec3; break;
+ case 4: op = EOpConstructBVec4; break;
+ }
+ break;
+ default: break;
+ }
+ if (op == EOpNull) {
+ context->error((yylsp[(1) - (1)]), "cannot construct this type", getBasicString((yyvsp[(1) - (1)].interm.type).type));
+ context->recover();
+ (yyvsp[(1) - (1)].interm.type).type = EbtFloat;
+ op = EOpConstructFloat;
+ }
+ }
+ TString tempString;
+ TType type((yyvsp[(1) - (1)].interm.type));
+ TFunction *function = new TFunction(&tempString, type, op);
+ (yyval.interm.function) = function;
+ }
+ break;
+
+ case 28:
+
+ {
+ if (context->reservedErrorCheck((yylsp[(1) - (1)]), *(yyvsp[(1) - (1)].lex).string))
+ context->recover();
+ TType type(EbtVoid, EbpUndefined);
+ TFunction *function = new TFunction((yyvsp[(1) - (1)].lex).string, type);
+ (yyval.interm.function) = function;
+ }
+ break;
+
+ case 29:
+
+ {
+ (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode);
+ }
+ break;
+
+ case 30:
+
+ {
+ if (context->lValueErrorCheck((yylsp[(1) - (2)]), "++", (yyvsp[(2) - (2)].interm.intermTypedNode)))
+ context->recover();
+ (yyval.interm.intermTypedNode) = context->intermediate.addUnaryMath(EOpPreIncrement, (yyvsp[(2) - (2)].interm.intermTypedNode), (yylsp[(1) - (2)]), context->symbolTable);
+ if ((yyval.interm.intermTypedNode) == 0) {
+ context->unaryOpError((yylsp[(1) - (2)]), "++", (yyvsp[(2) - (2)].interm.intermTypedNode)->getCompleteString());
+ context->recover();
+ (yyval.interm.intermTypedNode) = (yyvsp[(2) - (2)].interm.intermTypedNode);
+ }
+ }
+ break;
+
+ case 31:
+
+ {
+ if (context->lValueErrorCheck((yylsp[(1) - (2)]), "--", (yyvsp[(2) - (2)].interm.intermTypedNode)))
+ context->recover();
+ (yyval.interm.intermTypedNode) = context->intermediate.addUnaryMath(EOpPreDecrement, (yyvsp[(2) - (2)].interm.intermTypedNode), (yylsp[(1) - (2)]), context->symbolTable);
+ if ((yyval.interm.intermTypedNode) == 0) {
+ context->unaryOpError((yylsp[(1) - (2)]), "--", (yyvsp[(2) - (2)].interm.intermTypedNode)->getCompleteString());
+ context->recover();
+ (yyval.interm.intermTypedNode) = (yyvsp[(2) - (2)].interm.intermTypedNode);
+ }
+ }
+ break;
+
+ case 32:
+
+ {
+ if ((yyvsp[(1) - (2)].interm).op != EOpNull) {
+ (yyval.interm.intermTypedNode) = context->intermediate.addUnaryMath((yyvsp[(1) - (2)].interm).op, (yyvsp[(2) - (2)].interm.intermTypedNode), (yylsp[(1) - (2)]), context->symbolTable);
+ if ((yyval.interm.intermTypedNode) == 0) {
+ const char* errorOp = "";
+ switch((yyvsp[(1) - (2)].interm).op) {
+ case EOpNegative: errorOp = "-"; break;
+ case EOpLogicalNot: errorOp = "!"; break;
+ default: break;
+ }
+ context->unaryOpError((yylsp[(1) - (2)]), errorOp, (yyvsp[(2) - (2)].interm.intermTypedNode)->getCompleteString());
+ context->recover();
+ (yyval.interm.intermTypedNode) = (yyvsp[(2) - (2)].interm.intermTypedNode);
+ }
+ } else
+ (yyval.interm.intermTypedNode) = (yyvsp[(2) - (2)].interm.intermTypedNode);
+ }
+ break;
+
+ case 33:
+
+ { (yyval.interm).op = EOpNull; }
+ break;
+
+ case 34:
+
+ { (yyval.interm).op = EOpNegative; }
+ break;
+
+ case 35:
+
+ { (yyval.interm).op = EOpLogicalNot; }
+ break;
+
+ case 36:
+
+ { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); }
+ break;
+
+ case 37:
+
+ {
+ (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpMul, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)]), context->symbolTable);
+ if ((yyval.interm.intermTypedNode) == 0) {
+ context->binaryOpError((yylsp[(2) - (3)]), "*", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
+ context->recover();
+ (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode);
+ }
+ }
+ break;
+
+ case 38:
+
+ {
+ (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpDiv, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)]), context->symbolTable);
+ if ((yyval.interm.intermTypedNode) == 0) {
+ context->binaryOpError((yylsp[(2) - (3)]), "/", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
+ context->recover();
+ (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode);
+ }
+ }
+ break;
+
+ case 39:
+
+ { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); }
+ break;
+
+ case 40:
+
+ {
+ (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpAdd, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)]), context->symbolTable);
+ if ((yyval.interm.intermTypedNode) == 0) {
+ context->binaryOpError((yylsp[(2) - (3)]), "+", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
+ context->recover();
+ (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode);
+ }
+ }
+ break;
+
+ case 41:
+
+ {
+ (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpSub, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)]), context->symbolTable);
+ if ((yyval.interm.intermTypedNode) == 0) {
+ context->binaryOpError((yylsp[(2) - (3)]), "-", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
+ context->recover();
+ (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode);
+ }
+ }
+ break;
+
+ case 42:
+
+ { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); }
+ break;
+
+ case 43:
+
+ { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); }
+ break;
+
+ case 44:
+
+ {
+ (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpLessThan, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)]), context->symbolTable);
+ if ((yyval.interm.intermTypedNode) == 0) {
+ context->binaryOpError((yylsp[(2) - (3)]), "<", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
+ context->recover();
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setBConst(false);
+ (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yylsp[(2) - (3)]));
+ }
+ }
+ break;
+
+ case 45:
+
+ {
+ (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpGreaterThan, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)]), context->symbolTable);
+ if ((yyval.interm.intermTypedNode) == 0) {
+ context->binaryOpError((yylsp[(2) - (3)]), ">", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
+ context->recover();
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setBConst(false);
+ (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yylsp[(2) - (3)]));
+ }
+ }
+ break;
+
+ case 46:
+
+ {
+ (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpLessThanEqual, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)]), context->symbolTable);
+ if ((yyval.interm.intermTypedNode) == 0) {
+ context->binaryOpError((yylsp[(2) - (3)]), "<=", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
+ context->recover();
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setBConst(false);
+ (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yylsp[(2) - (3)]));
+ }
+ }
+ break;
+
+ case 47:
+
+ {
+ (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpGreaterThanEqual, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)]), context->symbolTable);
+ if ((yyval.interm.intermTypedNode) == 0) {
+ context->binaryOpError((yylsp[(2) - (3)]), ">=", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
+ context->recover();
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setBConst(false);
+ (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yylsp[(2) - (3)]));
+ }
+ }
+ break;
+
+ case 48:
+
+ { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); }
+ break;
+
+ case 49:
+
+ {
+ (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpEqual, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)]), context->symbolTable);
+ if ((yyval.interm.intermTypedNode) == 0) {
+ context->binaryOpError((yylsp[(2) - (3)]), "==", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
+ context->recover();
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setBConst(false);
+ (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yylsp[(2) - (3)]));
+ }
+ }
+ break;
+
+ case 50:
+
+ {
+ (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpNotEqual, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)]), context->symbolTable);
+ if ((yyval.interm.intermTypedNode) == 0) {
+ context->binaryOpError((yylsp[(2) - (3)]), "!=", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
+ context->recover();
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setBConst(false);
+ (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yylsp[(2) - (3)]));
+ }
+ }
+ break;
+
+ case 51:
+
+ { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); }
+ break;
+
+ case 52:
+
+ { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); }
+ break;
+
+ case 53:
+
+ { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); }
+ break;
+
+ case 54:
+
+ { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); }
+ break;
+
+ case 55:
+
+ {
+ (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpLogicalAnd, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)]), context->symbolTable);
+ if ((yyval.interm.intermTypedNode) == 0) {
+ context->binaryOpError((yylsp[(2) - (3)]), "&&", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
+ context->recover();
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setBConst(false);
+ (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yylsp[(2) - (3)]));
+ }
+ }
+ break;
+
+ case 56:
+
+ { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); }
+ break;
+
+ case 57:
+
+ {
+ (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpLogicalXor, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)]), context->symbolTable);
+ if ((yyval.interm.intermTypedNode) == 0) {
+ context->binaryOpError((yylsp[(2) - (3)]), "^^", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
+ context->recover();
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setBConst(false);
+ (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yylsp[(2) - (3)]));
+ }
+ }
+ break;
+
+ case 58:
+
+ { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); }
+ break;
+
+ case 59:
+
+ {
+ (yyval.interm.intermTypedNode) = context->intermediate.addBinaryMath(EOpLogicalOr, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)]), context->symbolTable);
+ if ((yyval.interm.intermTypedNode) == 0) {
+ context->binaryOpError((yylsp[(2) - (3)]), "||", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
+ context->recover();
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setBConst(false);
+ (yyval.interm.intermTypedNode) = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), (yylsp[(2) - (3)]));
+ }
+ }
+ break;
+
+ case 60:
+
+ { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); }
+ break;
+
+ case 61:
+
+ {
+ if (context->boolErrorCheck((yylsp[(2) - (5)]), (yyvsp[(1) - (5)].interm.intermTypedNode)))
+ context->recover();
+
+ (yyval.interm.intermTypedNode) = context->intermediate.addSelection((yyvsp[(1) - (5)].interm.intermTypedNode), (yyvsp[(3) - (5)].interm.intermTypedNode), (yyvsp[(5) - (5)].interm.intermTypedNode), (yylsp[(2) - (5)]));
+ if ((yyvsp[(3) - (5)].interm.intermTypedNode)->getType() != (yyvsp[(5) - (5)].interm.intermTypedNode)->getType())
+ (yyval.interm.intermTypedNode) = 0;
+
+ if ((yyval.interm.intermTypedNode) == 0) {
+ context->binaryOpError((yylsp[(2) - (5)]), ":", (yyvsp[(3) - (5)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(5) - (5)].interm.intermTypedNode)->getCompleteString());
+ context->recover();
+ (yyval.interm.intermTypedNode) = (yyvsp[(5) - (5)].interm.intermTypedNode);
+ }
+ }
+ break;
+
+ case 62:
+
+ { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); }
+ break;
+
+ case 63:
+
+ {
+ if (context->lValueErrorCheck((yylsp[(2) - (3)]), "assign", (yyvsp[(1) - (3)].interm.intermTypedNode)))
+ context->recover();
+ (yyval.interm.intermTypedNode) = context->intermediate.addAssign((yyvsp[(2) - (3)].interm).op, (yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)]));
+ if ((yyval.interm.intermTypedNode) == 0) {
+ context->assignError((yylsp[(2) - (3)]), "assign", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
+ context->recover();
+ (yyval.interm.intermTypedNode) = (yyvsp[(1) - (3)].interm.intermTypedNode);
+ }
+ }
+ break;
+
+ case 64:
+
+ { (yyval.interm).op = EOpAssign; }
+ break;
+
+ case 65:
+
+ { (yyval.interm).op = EOpMulAssign; }
+ break;
+
+ case 66:
+
+ { (yyval.interm).op = EOpDivAssign; }
+ break;
+
+ case 67:
+
+ { (yyval.interm).op = EOpAddAssign; }
+ break;
+
+ case 68:
+
+ { (yyval.interm).op = EOpSubAssign; }
+ break;
+
+ case 69:
+
+ {
+ (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode);
+ }
+ break;
+
+ case 70:
+
+ {
+ (yyval.interm.intermTypedNode) = context->intermediate.addComma((yyvsp[(1) - (3)].interm.intermTypedNode), (yyvsp[(3) - (3)].interm.intermTypedNode), (yylsp[(2) - (3)]));
+ if ((yyval.interm.intermTypedNode) == 0) {
+ context->binaryOpError((yylsp[(2) - (3)]), ",", (yyvsp[(1) - (3)].interm.intermTypedNode)->getCompleteString(), (yyvsp[(3) - (3)].interm.intermTypedNode)->getCompleteString());
+ context->recover();
+ (yyval.interm.intermTypedNode) = (yyvsp[(3) - (3)].interm.intermTypedNode);
+ }
+ }
+ break;
+
+ case 71:
+
+ {
+ if (context->constErrorCheck((yyvsp[(1) - (1)].interm.intermTypedNode)))
+ context->recover();
+ (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode);
+ }
+ break;
+
+ case 72:
+
+ {
+ TFunction &function = *((yyvsp[(1) - (2)].interm).function);
+
+ TIntermAggregate *prototype = new TIntermAggregate;
+ prototype->setType(function.getReturnType());
+ prototype->setName(function.getName());
+
+ for (size_t i = 0; i < function.getParamCount(); i++)
+ {
+ const TParameter &param = function.getParam(i);
+ if (param.name != 0)
+ {
+ TVariable variable(param.name, *param.type);
+
+ prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(variable.getUniqueId(), variable.getName(), variable.getType(), (yylsp[(1) - (2)])), (yylsp[(1) - (2)]));
+ }
+ else
+ {
+ prototype = context->intermediate.growAggregate(prototype, context->intermediate.addSymbol(0, "", *param.type, (yylsp[(1) - (2)])), (yylsp[(1) - (2)]));
+ }
+ }
+
+ prototype->setOp(EOpPrototype);
+ (yyval.interm.intermNode) = prototype;
+
+ context->symbolTable.pop();
+ }
+ break;
+
+ case 73:
+
+ {
+ if ((yyvsp[(1) - (2)].interm).intermAggregate)
+ (yyvsp[(1) - (2)].interm).intermAggregate->setOp(EOpDeclaration);
+ (yyval.interm.intermNode) = (yyvsp[(1) - (2)].interm).intermAggregate;
+ }
+ break;
+
+ case 74:
+
+ {
+ if (((yyvsp[(2) - (4)].interm.precision) == EbpHigh) && (context->shaderType == SH_FRAGMENT_SHADER) && !context->fragmentPrecisionHigh) {
+ context->error((yylsp[(1) - (4)]), "precision is not supported in fragment shader", "highp");
+ context->recover();
+ }
+ if (!context->symbolTable.setDefaultPrecision( (yyvsp[(3) - (4)].interm.type), (yyvsp[(2) - (4)].interm.precision) )) {
+ context->error((yylsp[(1) - (4)]), "illegal type argument for default precision qualifier", getBasicString((yyvsp[(3) - (4)].interm.type).type));
+ context->recover();
+ }
+ (yyval.interm.intermNode) = 0;
+ }
+ break;
+
+ case 75:
+
+ {
+ //
+ // Multiple declarations of the same function are allowed.
+ //
+ // If this is a definition, the definition production code will check for redefinitions
+ // (we don't know at this point if it's a definition or not).
+ //
+ // Redeclarations are allowed. But, return types and parameter qualifiers must match.
+ //
+ TFunction* prevDec = static_cast<TFunction*>(context->symbolTable.find((yyvsp[(1) - (2)].interm.function)->getMangledName()));
+ if (prevDec) {
+ if (prevDec->getReturnType() != (yyvsp[(1) - (2)].interm.function)->getReturnType()) {
+ context->error((yylsp[(2) - (2)]), "overloaded functions must have the same return type", (yyvsp[(1) - (2)].interm.function)->getReturnType().getBasicString());
+ context->recover();
+ }
+ for (size_t i = 0; i < prevDec->getParamCount(); ++i) {
+ if (prevDec->getParam(i).type->getQualifier() != (yyvsp[(1) - (2)].interm.function)->getParam(i).type->getQualifier()) {
+ context->error((yylsp[(2) - (2)]), "overloaded functions must have the same parameter qualifiers", (yyvsp[(1) - (2)].interm.function)->getParam(i).type->getQualifierString());
+ context->recover();
+ }
+ }
+ }
+
+ //
+ // Check for previously declared variables using the same name.
+ //
+ TSymbol *prevSym = context->symbolTable.find((yyvsp[(1) - (2)].interm.function)->getName());
+ if (prevSym)
+ {
+ if (!prevSym->isFunction())
+ {
+ context->error((yylsp[(2) - (2)]), "redefinition", (yyvsp[(1) - (2)].interm.function)->getName().c_str(), "function");
+ context->recover();
+ }
+ }
+ else
+ {
+ // Insert the unmangled name to detect potential future redefinition as a variable.
+ context->symbolTable.getOuterLevel()->insert((yyvsp[(1) - (2)].interm.function)->getName(), *(yyvsp[(1) - (2)].interm.function));
+ }
+
+ //
+ // If this is a redeclaration, it could also be a definition,
+ // in which case, we want to use the variable names from this one, and not the one that's
+ // being redeclared. So, pass back up this declaration, not the one in the symbol table.
+ //
+ (yyval.interm).function = (yyvsp[(1) - (2)].interm.function);
+
+ // We're at the inner scope level of the function's arguments and body statement.
+ // Add the function prototype to the surrounding scope instead.
+ context->symbolTable.getOuterLevel()->insert(*(yyval.interm).function);
+ }
+ break;
+
+ case 76:
+
+ {
+ (yyval.interm.function) = (yyvsp[(1) - (1)].interm.function);
+ }
+ break;
+
+ case 77:
+
+ {
+ (yyval.interm.function) = (yyvsp[(1) - (1)].interm.function);
+ }
+ break;
+
+ case 78:
+
+ {
+ // Add the parameter
+ (yyval.interm.function) = (yyvsp[(1) - (2)].interm.function);
+ if ((yyvsp[(2) - (2)].interm).param.type->getBasicType() != EbtVoid)
+ (yyvsp[(1) - (2)].interm.function)->addParameter((yyvsp[(2) - (2)].interm).param);
+ else
+ delete (yyvsp[(2) - (2)].interm).param.type;
+ }
+ break;
+
+ case 79:
+
+ {
+ //
+ // Only first parameter of one-parameter functions can be void
+ // The check for named parameters not being void is done in parameter_declarator
+ //
+ if ((yyvsp[(3) - (3)].interm).param.type->getBasicType() == EbtVoid) {
+ //
+ // This parameter > first is void
+ //
+ context->error((yylsp[(2) - (3)]), "cannot be an argument type except for '(void)'", "void");
+ context->recover();
+ delete (yyvsp[(3) - (3)].interm).param.type;
+ } else {
+ // Add the parameter
+ (yyval.interm.function) = (yyvsp[(1) - (3)].interm.function);
+ (yyvsp[(1) - (3)].interm.function)->addParameter((yyvsp[(3) - (3)].interm).param);
+ }
+ }
+ break;
+
+ case 80:
+
+ {
+ if ((yyvsp[(1) - (3)].interm.type).qualifier != EvqGlobal && (yyvsp[(1) - (3)].interm.type).qualifier != EvqTemporary) {
+ context->error((yylsp[(2) - (3)]), "no qualifiers allowed for function return", getQualifierString((yyvsp[(1) - (3)].interm.type).qualifier));
+ context->recover();
+ }
+ // make sure a sampler is not involved as well...
+ if (context->structQualifierErrorCheck((yylsp[(2) - (3)]), (yyvsp[(1) - (3)].interm.type)))
+ context->recover();
+
+ // Add the function as a prototype after parsing it (we do not support recursion)
+ TFunction *function;
+ TType type((yyvsp[(1) - (3)].interm.type));
+ function = new TFunction((yyvsp[(2) - (3)].lex).string, type);
+ (yyval.interm.function) = function;
+
+ context->symbolTable.push();
+ }
+ break;
+
+ case 81:
+
+ {
+ if ((yyvsp[(1) - (2)].interm.type).type == EbtVoid) {
+ context->error((yylsp[(2) - (2)]), "illegal use of type 'void'", (yyvsp[(2) - (2)].lex).string->c_str());
+ context->recover();
+ }
+ if (context->reservedErrorCheck((yylsp[(2) - (2)]), *(yyvsp[(2) - (2)].lex).string))
+ context->recover();
+ TParameter param = {(yyvsp[(2) - (2)].lex).string, new TType((yyvsp[(1) - (2)].interm.type))};
+ (yyval.interm).param = param;
+ }
+ break;
+
+ case 82:
+
+ {
+ // Check that we can make an array out of this type
+ if (context->arrayTypeErrorCheck((yylsp[(3) - (5)]), (yyvsp[(1) - (5)].interm.type)))
+ context->recover();
+
+ if (context->reservedErrorCheck((yylsp[(2) - (5)]), *(yyvsp[(2) - (5)].lex).string))
+ context->recover();
+
+ int size;
+ if (context->arraySizeErrorCheck((yylsp[(3) - (5)]), (yyvsp[(4) - (5)].interm.intermTypedNode), size))
+ context->recover();
+ (yyvsp[(1) - (5)].interm.type).setArray(true, size);
+
+ TType* type = new TType((yyvsp[(1) - (5)].interm.type));
+ TParameter param = { (yyvsp[(2) - (5)].lex).string, type };
+ (yyval.interm).param = param;
+ }
+ break;
+
+ case 83:
+
+ {
+ (yyval.interm) = (yyvsp[(3) - (3)].interm);
+ if (context->paramErrorCheck((yylsp[(3) - (3)]), (yyvsp[(1) - (3)].interm.type).qualifier, (yyvsp[(2) - (3)].interm.qualifier), (yyval.interm).param.type))
+ context->recover();
+ }
+ break;
+
+ case 84:
+
+ {
+ (yyval.interm) = (yyvsp[(2) - (2)].interm);
+ if (context->parameterSamplerErrorCheck((yylsp[(2) - (2)]), (yyvsp[(1) - (2)].interm.qualifier), *(yyvsp[(2) - (2)].interm).param.type))
+ context->recover();
+ if (context->paramErrorCheck((yylsp[(2) - (2)]), EvqTemporary, (yyvsp[(1) - (2)].interm.qualifier), (yyval.interm).param.type))
+ context->recover();
+ }
+ break;
+
+ case 85:
+
+ {
+ (yyval.interm) = (yyvsp[(3) - (3)].interm);
+ if (context->paramErrorCheck((yylsp[(3) - (3)]), (yyvsp[(1) - (3)].interm.type).qualifier, (yyvsp[(2) - (3)].interm.qualifier), (yyval.interm).param.type))
+ context->recover();
+ }
+ break;
+
+ case 86:
+
+ {
+ (yyval.interm) = (yyvsp[(2) - (2)].interm);
+ if (context->parameterSamplerErrorCheck((yylsp[(2) - (2)]), (yyvsp[(1) - (2)].interm.qualifier), *(yyvsp[(2) - (2)].interm).param.type))
+ context->recover();
+ if (context->paramErrorCheck((yylsp[(2) - (2)]), EvqTemporary, (yyvsp[(1) - (2)].interm.qualifier), (yyval.interm).param.type))
+ context->recover();
+ }
+ break;
+
+ case 87:
+
+ {
+ (yyval.interm.qualifier) = EvqIn;
+ }
+ break;
+
+ case 88:
+
+ {
+ (yyval.interm.qualifier) = EvqIn;
+ }
+ break;
+
+ case 89:
+
+ {
+ (yyval.interm.qualifier) = EvqOut;
+ }
+ break;
+
+ case 90:
+
+ {
+ (yyval.interm.qualifier) = EvqInOut;
+ }
+ break;
+
+ case 91:
+
+ {
+ TParameter param = { 0, new TType((yyvsp[(1) - (1)].interm.type)) };
+ (yyval.interm).param = param;
+ }
+ break;
+
+ case 92:
+
+ {
+ (yyval.interm) = (yyvsp[(1) - (1)].interm);
+ }
+ break;
+
+ case 93:
+
+ {
+ if ((yyvsp[(1) - (3)].interm).type.type == EbtInvariant && !(yyvsp[(3) - (3)].lex).symbol)
+ {
+ context->error((yylsp[(3) - (3)]), "undeclared identifier declared as invariant", (yyvsp[(3) - (3)].lex).string->c_str());
+ context->recover();
+ }
+
+ TIntermSymbol* symbol = context->intermediate.addSymbol(0, *(yyvsp[(3) - (3)].lex).string, TType((yyvsp[(1) - (3)].interm).type), (yylsp[(3) - (3)]));
+ (yyval.interm).intermAggregate = context->intermediate.growAggregate((yyvsp[(1) - (3)].interm).intermNode, symbol, (yylsp[(3) - (3)]));
+
+ if (context->structQualifierErrorCheck((yylsp[(3) - (3)]), (yyval.interm).type))
+ context->recover();
+
+ if (context->nonInitConstErrorCheck((yylsp[(3) - (3)]), *(yyvsp[(3) - (3)].lex).string, (yyval.interm).type, false))
+ context->recover();
+
+ TVariable* variable = 0;
+ if (context->nonInitErrorCheck((yylsp[(3) - (3)]), *(yyvsp[(3) - (3)].lex).string, (yyval.interm).type, variable))
+ context->recover();
+ if (symbol && variable)
+ symbol->setId(variable->getUniqueId());
+ }
+ break;
+
+ case 94:
+
+ {
+ if (context->structQualifierErrorCheck((yylsp[(3) - (5)]), (yyvsp[(1) - (5)].interm).type))
+ context->recover();
+
+ if (context->nonInitConstErrorCheck((yylsp[(3) - (5)]), *(yyvsp[(3) - (5)].lex).string, (yyvsp[(1) - (5)].interm).type, true))
+ context->recover();
+
+ (yyval.interm) = (yyvsp[(1) - (5)].interm);
+
+ if (context->arrayTypeErrorCheck((yylsp[(4) - (5)]), (yyvsp[(1) - (5)].interm).type) || context->arrayQualifierErrorCheck((yylsp[(4) - (5)]), (yyvsp[(1) - (5)].interm).type))
+ context->recover();
+ else {
+ (yyvsp[(1) - (5)].interm).type.setArray(true);
+ TVariable* variable;
+ if (context->arrayErrorCheck((yylsp[(4) - (5)]), *(yyvsp[(3) - (5)].lex).string, (yyvsp[(1) - (5)].interm).type, variable))
+ context->recover();
+ }
+ }
+ break;
+
+ case 95:
+
+ {
+ if (context->structQualifierErrorCheck((yylsp[(3) - (6)]), (yyvsp[(1) - (6)].interm).type))
+ context->recover();
+
+ if (context->nonInitConstErrorCheck((yylsp[(3) - (6)]), *(yyvsp[(3) - (6)].lex).string, (yyvsp[(1) - (6)].interm).type, true))
+ context->recover();
+
+ (yyval.interm) = (yyvsp[(1) - (6)].interm);
+
+ if (context->arrayTypeErrorCheck((yylsp[(4) - (6)]), (yyvsp[(1) - (6)].interm).type) || context->arrayQualifierErrorCheck((yylsp[(4) - (6)]), (yyvsp[(1) - (6)].interm).type))
+ context->recover();
+ else {
+ int size;
+ if (context->arraySizeErrorCheck((yylsp[(4) - (6)]), (yyvsp[(5) - (6)].interm.intermTypedNode), size))
+ context->recover();
+ (yyvsp[(1) - (6)].interm).type.setArray(true, size);
+ TVariable* variable = 0;
+ if (context->arrayErrorCheck((yylsp[(4) - (6)]), *(yyvsp[(3) - (6)].lex).string, (yyvsp[(1) - (6)].interm).type, variable))
+ context->recover();
+ TType type = TType((yyvsp[(1) - (6)].interm).type);
+ type.setArraySize(size);
+ (yyval.interm).intermAggregate = context->intermediate.growAggregate((yyvsp[(1) - (6)].interm).intermNode, context->intermediate.addSymbol(variable ? variable->getUniqueId() : 0, *(yyvsp[(3) - (6)].lex).string, type, (yylsp[(3) - (6)])), (yylsp[(3) - (6)]));
+ }
+ }
+ break;
+
+ case 96:
+
+ {
+ if (context->structQualifierErrorCheck((yylsp[(3) - (5)]), (yyvsp[(1) - (5)].interm).type))
+ context->recover();
+
+ (yyval.interm) = (yyvsp[(1) - (5)].interm);
+
+ TIntermNode* intermNode;
+ if (!context->executeInitializer((yylsp[(3) - (5)]), *(yyvsp[(3) - (5)].lex).string, (yyvsp[(1) - (5)].interm).type, (yyvsp[(5) - (5)].interm.intermTypedNode), intermNode)) {
+ //
+ // build the intermediate representation
+ //
+ if (intermNode)
+ (yyval.interm).intermAggregate = context->intermediate.growAggregate((yyvsp[(1) - (5)].interm).intermNode, intermNode, (yylsp[(4) - (5)]));
+ else
+ (yyval.interm).intermAggregate = (yyvsp[(1) - (5)].interm).intermAggregate;
+ } else {
+ context->recover();
+ (yyval.interm).intermAggregate = 0;
+ }
+ }
+ break;
+
+ case 97:
+
+ {
+ (yyval.interm).type = (yyvsp[(1) - (1)].interm.type);
+ (yyval.interm).intermAggregate = context->intermediate.makeAggregate(context->intermediate.addSymbol(0, "", TType((yyvsp[(1) - (1)].interm.type)), (yylsp[(1) - (1)])), (yylsp[(1) - (1)]));
+ }
+ break;
+
+ case 98:
+
+ {
+ TIntermSymbol* symbol = context->intermediate.addSymbol(0, *(yyvsp[(2) - (2)].lex).string, TType((yyvsp[(1) - (2)].interm.type)), (yylsp[(2) - (2)]));
+ (yyval.interm).intermAggregate = context->intermediate.makeAggregate(symbol, (yylsp[(2) - (2)]));
+
+ if (context->structQualifierErrorCheck((yylsp[(2) - (2)]), (yyval.interm).type))
+ context->recover();
+
+ if (context->nonInitConstErrorCheck((yylsp[(2) - (2)]), *(yyvsp[(2) - (2)].lex).string, (yyval.interm).type, false))
+ context->recover();
+
+ (yyval.interm).type = (yyvsp[(1) - (2)].interm.type);
+
+ TVariable* variable = 0;
+ if (context->nonInitErrorCheck((yylsp[(2) - (2)]), *(yyvsp[(2) - (2)].lex).string, (yyval.interm).type, variable))
+ context->recover();
+ if (variable && symbol)
+ symbol->setId(variable->getUniqueId());
+ }
+ break;
+
+ case 99:
+
+ {
+ context->error((yylsp[(2) - (4)]), "unsized array declarations not supported", (yyvsp[(2) - (4)].lex).string->c_str());
+ context->recover();
+
+ TIntermSymbol* symbol = context->intermediate.addSymbol(0, *(yyvsp[(2) - (4)].lex).string, TType((yyvsp[(1) - (4)].interm.type)), (yylsp[(2) - (4)]));
+ (yyval.interm).intermAggregate = context->intermediate.makeAggregate(symbol, (yylsp[(2) - (4)]));
+ (yyval.interm).type = (yyvsp[(1) - (4)].interm.type);
+ }
+ break;
+
+ case 100:
+
+ {
+ TType type = TType((yyvsp[(1) - (5)].interm.type));
+ int size;
+ if (context->arraySizeErrorCheck((yylsp[(2) - (5)]), (yyvsp[(4) - (5)].interm.intermTypedNode), size))
+ context->recover();
+ type.setArraySize(size);
+ TIntermSymbol* symbol = context->intermediate.addSymbol(0, *(yyvsp[(2) - (5)].lex).string, type, (yylsp[(2) - (5)]));
+ (yyval.interm).intermAggregate = context->intermediate.makeAggregate(symbol, (yylsp[(2) - (5)]));
+
+ if (context->structQualifierErrorCheck((yylsp[(2) - (5)]), (yyvsp[(1) - (5)].interm.type)))
+ context->recover();
+
+ if (context->nonInitConstErrorCheck((yylsp[(2) - (5)]), *(yyvsp[(2) - (5)].lex).string, (yyvsp[(1) - (5)].interm.type), true))
+ context->recover();
+
+ (yyval.interm).type = (yyvsp[(1) - (5)].interm.type);
+
+ if (context->arrayTypeErrorCheck((yylsp[(3) - (5)]), (yyvsp[(1) - (5)].interm.type)) || context->arrayQualifierErrorCheck((yylsp[(3) - (5)]), (yyvsp[(1) - (5)].interm.type)))
+ context->recover();
+ else {
+ int size;
+ if (context->arraySizeErrorCheck((yylsp[(3) - (5)]), (yyvsp[(4) - (5)].interm.intermTypedNode), size))
+ context->recover();
+
+ (yyvsp[(1) - (5)].interm.type).setArray(true, size);
+ TVariable* variable = 0;
+ if (context->arrayErrorCheck((yylsp[(3) - (5)]), *(yyvsp[(2) - (5)].lex).string, (yyvsp[(1) - (5)].interm.type), variable))
+ context->recover();
+ if (variable && symbol)
+ symbol->setId(variable->getUniqueId());
+ }
+ }
+ break;
+
+ case 101:
+
+ {
+ if (context->structQualifierErrorCheck((yylsp[(2) - (4)]), (yyvsp[(1) - (4)].interm.type)))
+ context->recover();
+
+ (yyval.interm).type = (yyvsp[(1) - (4)].interm.type);
+
+ TIntermNode* intermNode;
+ if (!context->executeInitializer((yylsp[(2) - (4)]), *(yyvsp[(2) - (4)].lex).string, (yyvsp[(1) - (4)].interm.type), (yyvsp[(4) - (4)].interm.intermTypedNode), intermNode)) {
+ //
+ // Build intermediate representation
+ //
+ if(intermNode)
+ (yyval.interm).intermAggregate = context->intermediate.makeAggregate(intermNode, (yylsp[(3) - (4)]));
+ else
+ (yyval.interm).intermAggregate = 0;
+ } else {
+ context->recover();
+ (yyval.interm).intermAggregate = 0;
+ }
+ }
+ break;
+
+ case 102:
+
+ {
+ VERTEX_ONLY("invariant declaration", (yylsp[(1) - (2)]));
+ if (context->globalErrorCheck((yylsp[(1) - (2)]), context->symbolTable.atGlobalLevel(), "invariant varying"))
+ context->recover();
+ (yyval.interm).type.setBasic(EbtInvariant, EvqInvariantVaryingOut, (yylsp[(2) - (2)]));
+ if (!(yyvsp[(2) - (2)].lex).symbol)
+ {
+ context->error((yylsp[(2) - (2)]), "undeclared identifier declared as invariant", (yyvsp[(2) - (2)].lex).string->c_str());
+ context->recover();
+
+ (yyval.interm).intermAggregate = 0;
+ }
+ else
+ {
+ TIntermSymbol *symbol = context->intermediate.addSymbol(0, *(yyvsp[(2) - (2)].lex).string, TType((yyval.interm).type), (yylsp[(2) - (2)]));
+ (yyval.interm).intermAggregate = context->intermediate.makeAggregate(symbol, (yylsp[(2) - (2)]));
+ }
+ }
+ break;
+
+ case 103:
+
+ {
+ (yyval.interm.type) = (yyvsp[(1) - (1)].interm.type);
+
+ if ((yyvsp[(1) - (1)].interm.type).array) {
+ context->error((yylsp[(1) - (1)]), "not supported", "first-class array");
+ context->recover();
+ (yyvsp[(1) - (1)].interm.type).setArray(false);
+ }
+ }
+ break;
+
+ case 104:
+
+ {
+ if ((yyvsp[(2) - (2)].interm.type).array) {
+ context->error((yylsp[(2) - (2)]), "not supported", "first-class array");
+ context->recover();
+ (yyvsp[(2) - (2)].interm.type).setArray(false);
+ }
+
+ if ((yyvsp[(1) - (2)].interm.type).qualifier == EvqAttribute &&
+ ((yyvsp[(2) - (2)].interm.type).type == EbtBool || (yyvsp[(2) - (2)].interm.type).type == EbtInt)) {
+ context->error((yylsp[(2) - (2)]), "cannot be bool or int", getQualifierString((yyvsp[(1) - (2)].interm.type).qualifier));
+ context->recover();
+ }
+ if (((yyvsp[(1) - (2)].interm.type).qualifier == EvqVaryingIn || (yyvsp[(1) - (2)].interm.type).qualifier == EvqVaryingOut) &&
+ ((yyvsp[(2) - (2)].interm.type).type == EbtBool || (yyvsp[(2) - (2)].interm.type).type == EbtInt)) {
+ context->error((yylsp[(2) - (2)]), "cannot be bool or int", getQualifierString((yyvsp[(1) - (2)].interm.type).qualifier));
+ context->recover();
+ }
+ (yyval.interm.type) = (yyvsp[(2) - (2)].interm.type);
+ (yyval.interm.type).qualifier = (yyvsp[(1) - (2)].interm.type).qualifier;
+ }
+ break;
+
+ case 105:
+
+ {
+ (yyval.interm.type).setBasic(EbtVoid, EvqConst, (yylsp[(1) - (1)]));
+ }
+ break;
+
+ case 106:
+
+ {
+ VERTEX_ONLY("attribute", (yylsp[(1) - (1)]));
+ if (context->globalErrorCheck((yylsp[(1) - (1)]), context->symbolTable.atGlobalLevel(), "attribute"))
+ context->recover();
+ (yyval.interm.type).setBasic(EbtVoid, EvqAttribute, (yylsp[(1) - (1)]));
+ }
+ break;
+
+ case 107:
+
+ {
+ if (context->globalErrorCheck((yylsp[(1) - (1)]), context->symbolTable.atGlobalLevel(), "varying"))
+ context->recover();
+ if (context->shaderType == SH_VERTEX_SHADER)
+ (yyval.interm.type).setBasic(EbtVoid, EvqVaryingOut, (yylsp[(1) - (1)]));
+ else
+ (yyval.interm.type).setBasic(EbtVoid, EvqVaryingIn, (yylsp[(1) - (1)]));
+ }
+ break;
+
+ case 108:
+
+ {
+ if (context->globalErrorCheck((yylsp[(1) - (2)]), context->symbolTable.atGlobalLevel(), "invariant varying"))
+ context->recover();
+ if (context->shaderType == SH_VERTEX_SHADER)
+ (yyval.interm.type).setBasic(EbtVoid, EvqInvariantVaryingOut, (yylsp[(1) - (2)]));
+ else
+ (yyval.interm.type).setBasic(EbtVoid, EvqInvariantVaryingIn, (yylsp[(1) - (2)]));
+ }
+ break;
+
+ case 109:
+
+ {
+ if (context->globalErrorCheck((yylsp[(1) - (1)]), context->symbolTable.atGlobalLevel(), "uniform"))
+ context->recover();
+ (yyval.interm.type).setBasic(EbtVoid, EvqUniform, (yylsp[(1) - (1)]));
+ }
+ break;
+
+ case 110:
+
+ {
+ (yyval.interm.type) = (yyvsp[(1) - (1)].interm.type);
+
+ if ((yyval.interm.type).precision == EbpUndefined) {
+ (yyval.interm.type).precision = context->symbolTable.getDefaultPrecision((yyvsp[(1) - (1)].interm.type).type);
+ if (context->precisionErrorCheck((yylsp[(1) - (1)]), (yyval.interm.type).precision, (yyvsp[(1) - (1)].interm.type).type)) {
+ context->recover();
+ }
+ }
+ }
+ break;
+
+ case 111:
+
+ {
+ (yyval.interm.type) = (yyvsp[(2) - (2)].interm.type);
+ (yyval.interm.type).precision = (yyvsp[(1) - (2)].interm.precision);
+ }
+ break;
+
+ case 112:
+
+ {
+ (yyval.interm.precision) = EbpHigh;
+ }
+ break;
+
+ case 113:
+
+ {
+ (yyval.interm.precision) = EbpMedium;
+ }
+ break;
+
+ case 114:
+
+ {
+ (yyval.interm.precision) = EbpLow;
+ }
+ break;
+
+ case 115:
+
+ {
+ (yyval.interm.type) = (yyvsp[(1) - (1)].interm.type);
+ }
+ break;
+
+ case 116:
+
+ {
+ (yyval.interm.type) = (yyvsp[(1) - (4)].interm.type);
+
+ if (context->arrayTypeErrorCheck((yylsp[(2) - (4)]), (yyvsp[(1) - (4)].interm.type)))
+ context->recover();
+ else {
+ int size;
+ if (context->arraySizeErrorCheck((yylsp[(2) - (4)]), (yyvsp[(3) - (4)].interm.intermTypedNode), size))
+ context->recover();
+ (yyval.interm.type).setArray(true, size);
+ }
+ }
+ break;
+
+ case 117:
+
+ {
+ TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ (yyval.interm.type).setBasic(EbtVoid, qual, (yylsp[(1) - (1)]));
+ }
+ break;
+
+ case 118:
+
+ {
+ TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ (yyval.interm.type).setBasic(EbtFloat, qual, (yylsp[(1) - (1)]));
+ }
+ break;
+
+ case 119:
+
+ {
+ TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ (yyval.interm.type).setBasic(EbtInt, qual, (yylsp[(1) - (1)]));
+ }
+ break;
+
+ case 120:
+
+ {
+ TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ (yyval.interm.type).setBasic(EbtBool, qual, (yylsp[(1) - (1)]));
+ }
+ break;
+
+ case 121:
+
+ {
+ TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ (yyval.interm.type).setBasic(EbtFloat, qual, (yylsp[(1) - (1)]));
+ (yyval.interm.type).setAggregate(2);
+ }
+ break;
+
+ case 122:
+
+ {
+ TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ (yyval.interm.type).setBasic(EbtFloat, qual, (yylsp[(1) - (1)]));
+ (yyval.interm.type).setAggregate(3);
+ }
+ break;
+
+ case 123:
+
+ {
+ TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ (yyval.interm.type).setBasic(EbtFloat, qual, (yylsp[(1) - (1)]));
+ (yyval.interm.type).setAggregate(4);
+ }
+ break;
+
+ case 124:
+
+ {
+ TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ (yyval.interm.type).setBasic(EbtBool, qual, (yylsp[(1) - (1)]));
+ (yyval.interm.type).setAggregate(2);
+ }
+ break;
+
+ case 125:
+
+ {
+ TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ (yyval.interm.type).setBasic(EbtBool, qual, (yylsp[(1) - (1)]));
+ (yyval.interm.type).setAggregate(3);
+ }
+ break;
+
+ case 126:
+
+ {
+ TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ (yyval.interm.type).setBasic(EbtBool, qual, (yylsp[(1) - (1)]));
+ (yyval.interm.type).setAggregate(4);
+ }
+ break;
+
+ case 127:
+
+ {
+ TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ (yyval.interm.type).setBasic(EbtInt, qual, (yylsp[(1) - (1)]));
+ (yyval.interm.type).setAggregate(2);
+ }
+ break;
+
+ case 128:
+
+ {
+ TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ (yyval.interm.type).setBasic(EbtInt, qual, (yylsp[(1) - (1)]));
+ (yyval.interm.type).setAggregate(3);
+ }
+ break;
+
+ case 129:
+
+ {
+ TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ (yyval.interm.type).setBasic(EbtInt, qual, (yylsp[(1) - (1)]));
+ (yyval.interm.type).setAggregate(4);
+ }
+ break;
+
+ case 130:
+
+ {
+ TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ (yyval.interm.type).setBasic(EbtFloat, qual, (yylsp[(1) - (1)]));
+ (yyval.interm.type).setAggregate(2, true);
+ }
+ break;
+
+ case 131:
+
+ {
+ TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ (yyval.interm.type).setBasic(EbtFloat, qual, (yylsp[(1) - (1)]));
+ (yyval.interm.type).setAggregate(3, true);
+ }
+ break;
+
+ case 132:
+
+ {
+ TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ (yyval.interm.type).setBasic(EbtFloat, qual, (yylsp[(1) - (1)]));
+ (yyval.interm.type).setAggregate(4, true);
+ }
+ break;
+
+ case 133:
+
+ {
+ TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ (yyval.interm.type).setBasic(EbtSampler2D, qual, (yylsp[(1) - (1)]));
+ }
+ break;
+
+ case 134:
+
+ {
+ TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ (yyval.interm.type).setBasic(EbtSamplerCube, qual, (yylsp[(1) - (1)]));
+ }
+ break;
+
+ case 135:
+
+ {
+ if (!context->supportsExtension("GL_OES_EGL_image_external")) {
+ context->error((yylsp[(1) - (1)]), "unsupported type", "samplerExternalOES");
+ context->recover();
+ }
+ TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ (yyval.interm.type).setBasic(EbtSamplerExternalOES, qual, (yylsp[(1) - (1)]));
+ }
+ break;
+
+ case 136:
+
+ {
+ if (!context->supportsExtension("GL_ARB_texture_rectangle")) {
+ context->error((yylsp[(1) - (1)]), "unsupported type", "sampler2DRect");
+ context->recover();
+ }
+ TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ (yyval.interm.type).setBasic(EbtSampler2DRect, qual, (yylsp[(1) - (1)]));
+ }
+ break;
+
+ case 137:
+
+ {
+ (yyval.interm.type) = (yyvsp[(1) - (1)].interm.type);
+ (yyval.interm.type).qualifier = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ }
+ break;
+
+ case 138:
+
+ {
+ //
+ // This is for user defined type names. The lexical phase looked up the
+ // type.
+ //
+ TType& structure = static_cast<TVariable*>((yyvsp[(1) - (1)].lex).symbol)->getType();
+ TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary;
+ (yyval.interm.type).setBasic(EbtStruct, qual, (yylsp[(1) - (1)]));
+ (yyval.interm.type).userDef = &structure;
+ }
+ break;
+
+ case 139:
+
+ { if (context->enterStructDeclaration((yylsp[(2) - (3)]), *(yyvsp[(2) - (3)].lex).string)) context->recover(); }
+ break;
+
+ case 140:
+
+ {
+ if (context->reservedErrorCheck((yylsp[(2) - (6)]), *(yyvsp[(2) - (6)].lex).string))
+ context->recover();
+
+ TType* structure = new TType(new TStructure((yyvsp[(2) - (6)].lex).string, (yyvsp[(5) - (6)].interm.fieldList)));
+ TVariable* userTypeDef = new TVariable((yyvsp[(2) - (6)].lex).string, *structure, true);
+ if (! context->symbolTable.insert(*userTypeDef)) {
+ context->error((yylsp[(2) - (6)]), "redefinition", (yyvsp[(2) - (6)].lex).string->c_str(), "struct");
+ context->recover();
+ }
+ (yyval.interm.type).setBasic(EbtStruct, EvqTemporary, (yylsp[(1) - (6)]));
+ (yyval.interm.type).userDef = structure;
+ context->exitStructDeclaration();
+ }
+ break;
+
+ case 141:
+
+ { if (context->enterStructDeclaration((yylsp[(2) - (2)]), *(yyvsp[(2) - (2)].lex).string)) context->recover(); }
+ break;
+
+ case 142:
+
+ {
+ TType* structure = new TType(new TStructure(NewPoolTString(""), (yyvsp[(4) - (5)].interm.fieldList)));
+ (yyval.interm.type).setBasic(EbtStruct, EvqTemporary, (yylsp[(1) - (5)]));
+ (yyval.interm.type).userDef = structure;
+ context->exitStructDeclaration();
+ }
+ break;
+
+ case 143:
+
+ {
+ (yyval.interm.fieldList) = (yyvsp[(1) - (1)].interm.fieldList);
+ }
+ break;
+
+ case 144:
+
+ {
+ (yyval.interm.fieldList) = (yyvsp[(1) - (2)].interm.fieldList);
+ for (size_t i = 0; i < (yyvsp[(2) - (2)].interm.fieldList)->size(); ++i) {
+ TField* field = (*(yyvsp[(2) - (2)].interm.fieldList))[i];
+ for (size_t j = 0; j < (yyval.interm.fieldList)->size(); ++j) {
+ if ((*(yyval.interm.fieldList))[j]->name() == field->name()) {
+ context->error((yylsp[(2) - (2)]), "duplicate field name in structure:", "struct", field->name().c_str());
+ context->recover();
+ }
+ }
+ (yyval.interm.fieldList)->push_back(field);
+ }
+ }
+ break;
+
+ case 145:
+
+ {
+ (yyval.interm.fieldList) = (yyvsp[(2) - (3)].interm.fieldList);
+
+ if (context->voidErrorCheck((yylsp[(1) - (3)]), (*(yyvsp[(2) - (3)].interm.fieldList))[0]->name(), (yyvsp[(1) - (3)].interm.type))) {
+ context->recover();
+ }
+ for (unsigned int i = 0; i < (yyval.interm.fieldList)->size(); ++i) {
+ //
+ // Careful not to replace already known aspects of type, like array-ness
+ //
+ TType* type = (*(yyval.interm.fieldList))[i]->type();
+ type->setBasicType((yyvsp[(1) - (3)].interm.type).type);
+ type->setNominalSize((yyvsp[(1) - (3)].interm.type).size);
+ type->setMatrix((yyvsp[(1) - (3)].interm.type).matrix);
+ type->setPrecision((yyvsp[(1) - (3)].interm.type).precision);
+
+ // don't allow arrays of arrays
+ if (type->isArray()) {
+ if (context->arrayTypeErrorCheck((yylsp[(1) - (3)]), (yyvsp[(1) - (3)].interm.type)))
+ context->recover();
+ }
+ if ((yyvsp[(1) - (3)].interm.type).array)
+ type->setArraySize((yyvsp[(1) - (3)].interm.type).arraySize);
+ if ((yyvsp[(1) - (3)].interm.type).userDef)
+ type->setStruct((yyvsp[(1) - (3)].interm.type).userDef->getStruct());
+
+ if (context->structNestingErrorCheck((yylsp[(1) - (3)]), *(*(yyval.interm.fieldList))[i]))
+ context->recover();
+ }
+ }
+ break;
+
+ case 146:
+
+ {
+ (yyval.interm.fieldList) = NewPoolTFieldList();
+ (yyval.interm.fieldList)->push_back((yyvsp[(1) - (1)].interm.field));
+ }
+ break;
+
+ case 147:
+
+ {
+ (yyval.interm.fieldList)->push_back((yyvsp[(3) - (3)].interm.field));
+ }
+ break;
+
+ case 148:
+
+ {
+ if (context->reservedErrorCheck((yylsp[(1) - (1)]), *(yyvsp[(1) - (1)].lex).string))
+ context->recover();
+
+ TType* type = new TType(EbtVoid, EbpUndefined);
+ (yyval.interm.field) = new TField(type, (yyvsp[(1) - (1)].lex).string);
+ }
+ break;
+
+ case 149:
+
+ {
+ if (context->reservedErrorCheck((yylsp[(1) - (4)]), *(yyvsp[(1) - (4)].lex).string))
+ context->recover();
+
+ TType* type = new TType(EbtVoid, EbpUndefined);
+ int size = 0;
+ if (context->arraySizeErrorCheck((yylsp[(3) - (4)]), (yyvsp[(3) - (4)].interm.intermTypedNode), size))
+ context->recover();
+ type->setArraySize(size);
+
+ (yyval.interm.field) = new TField(type, (yyvsp[(1) - (4)].lex).string);
+ }
+ break;
+
+ case 150:
+
+ { (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode); }
+ break;
+
+ case 151:
+
+ { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); }
+ break;
+
+ case 152:
+
+ { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermAggregate); }
+ break;
+
+ case 153:
+
+ { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); }
+ break;
+
+ case 154:
+
+ { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); }
+ break;
+
+ case 155:
+
+ { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); }
+ break;
+
+ case 156:
+
+ { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); }
+ break;
+
+ case 157:
+
+ { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); }
+ break;
+
+ case 158:
+
+ { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); }
+ break;
+
+ case 159:
+
+ { (yyval.interm.intermAggregate) = 0; }
+ break;
+
+ case 160:
+
+ { context->symbolTable.push(); }
+ break;
+
+ case 161:
+
+ { context->symbolTable.pop(); }
+ break;
+
+ case 162:
+
+ {
+ if ((yyvsp[(3) - (5)].interm.intermAggregate) != 0) {
+ (yyvsp[(3) - (5)].interm.intermAggregate)->setOp(EOpSequence);
+ (yyvsp[(3) - (5)].interm.intermAggregate)->setLine((yyloc));
+ }
+ (yyval.interm.intermAggregate) = (yyvsp[(3) - (5)].interm.intermAggregate);
+ }
+ break;
+
+ case 163:
+
+ { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); }
+ break;
+
+ case 164:
+
+ { (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode); }
+ break;
+
+ case 165:
+
+ { context->symbolTable.push(); }
+ break;
+
+ case 166:
+
+ { context->symbolTable.pop(); (yyval.interm.intermNode) = (yyvsp[(2) - (2)].interm.intermNode); }
+ break;
+
+ case 167:
+
+ { context->symbolTable.push(); }
+ break;
+
+ case 168:
+
+ { context->symbolTable.pop(); (yyval.interm.intermNode) = (yyvsp[(2) - (2)].interm.intermNode); }
+ break;
+
+ case 169:
+
+ {
+ (yyval.interm.intermNode) = 0;
+ }
+ break;
+
+ case 170:
+
+ {
+ if ((yyvsp[(2) - (3)].interm.intermAggregate)) {
+ (yyvsp[(2) - (3)].interm.intermAggregate)->setOp(EOpSequence);
+ (yyvsp[(2) - (3)].interm.intermAggregate)->setLine((yyloc));
+ }
+ (yyval.interm.intermNode) = (yyvsp[(2) - (3)].interm.intermAggregate);
+ }
+ break;
+
+ case 171:
+
+ {
+ (yyval.interm.intermAggregate) = context->intermediate.makeAggregate((yyvsp[(1) - (1)].interm.intermNode), (yyloc));
+ }
+ break;
+
+ case 172:
+
+ {
+ (yyval.interm.intermAggregate) = context->intermediate.growAggregate((yyvsp[(1) - (2)].interm.intermAggregate), (yyvsp[(2) - (2)].interm.intermNode), (yyloc));
+ }
+ break;
+
+ case 173:
+
+ { (yyval.interm.intermNode) = 0; }
+ break;
+
+ case 174:
+
+ { (yyval.interm.intermNode) = static_cast<TIntermNode*>((yyvsp[(1) - (2)].interm.intermTypedNode)); }
+ break;
+
+ case 175:
+
+ {
+ if (context->boolErrorCheck((yylsp[(1) - (5)]), (yyvsp[(3) - (5)].interm.intermTypedNode)))
+ context->recover();
+ (yyval.interm.intermNode) = context->intermediate.addSelection((yyvsp[(3) - (5)].interm.intermTypedNode), (yyvsp[(5) - (5)].interm.nodePair), (yylsp[(1) - (5)]));
+ }
+ break;
+
+ case 176:
+
+ {
+ (yyval.interm.nodePair).node1 = (yyvsp[(1) - (3)].interm.intermNode);
+ (yyval.interm.nodePair).node2 = (yyvsp[(3) - (3)].interm.intermNode);
+ }
+ break;
+
+ case 177:
+
+ {
+ (yyval.interm.nodePair).node1 = (yyvsp[(1) - (1)].interm.intermNode);
+ (yyval.interm.nodePair).node2 = 0;
+ }
+ break;
+
+ case 178:
+
+ {
+ (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode);
+ if (context->boolErrorCheck((yyvsp[(1) - (1)].interm.intermTypedNode)->getLine(), (yyvsp[(1) - (1)].interm.intermTypedNode)))
+ context->recover();
+ }
+ break;
+
+ case 179:
+
+ {
+ TIntermNode* intermNode;
+ if (context->structQualifierErrorCheck((yylsp[(2) - (4)]), (yyvsp[(1) - (4)].interm.type)))
+ context->recover();
+ if (context->boolErrorCheck((yylsp[(2) - (4)]), (yyvsp[(1) - (4)].interm.type)))
+ context->recover();
+
+ if (!context->executeInitializer((yylsp[(2) - (4)]), *(yyvsp[(2) - (4)].lex).string, (yyvsp[(1) - (4)].interm.type), (yyvsp[(4) - (4)].interm.intermTypedNode), intermNode))
+ (yyval.interm.intermTypedNode) = (yyvsp[(4) - (4)].interm.intermTypedNode);
+ else {
+ context->recover();
+ (yyval.interm.intermTypedNode) = 0;
+ }
+ }
+ break;
+
+ case 180:
+
+ { context->symbolTable.push(); ++context->loopNestingLevel; }
+ break;
+
+ case 181:
+
+ {
+ context->symbolTable.pop();
+ (yyval.interm.intermNode) = context->intermediate.addLoop(ELoopWhile, 0, (yyvsp[(4) - (6)].interm.intermTypedNode), 0, (yyvsp[(6) - (6)].interm.intermNode), (yylsp[(1) - (6)]));
+ --context->loopNestingLevel;
+ }
+ break;
+
+ case 182:
+
+ { ++context->loopNestingLevel; }
+ break;
+
+ case 183:
+
+ {
+ if (context->boolErrorCheck((yylsp[(8) - (8)]), (yyvsp[(6) - (8)].interm.intermTypedNode)))
+ context->recover();
+
+ (yyval.interm.intermNode) = context->intermediate.addLoop(ELoopDoWhile, 0, (yyvsp[(6) - (8)].interm.intermTypedNode), 0, (yyvsp[(3) - (8)].interm.intermNode), (yylsp[(4) - (8)]));
+ --context->loopNestingLevel;
+ }
+ break;
+
+ case 184:
+
+ { context->symbolTable.push(); ++context->loopNestingLevel; }
+ break;
+
+ case 185:
+
+ {
+ context->symbolTable.pop();
+ (yyval.interm.intermNode) = context->intermediate.addLoop(ELoopFor, (yyvsp[(4) - (7)].interm.intermNode), reinterpret_cast<TIntermTyped*>((yyvsp[(5) - (7)].interm.nodePair).node1), reinterpret_cast<TIntermTyped*>((yyvsp[(5) - (7)].interm.nodePair).node2), (yyvsp[(7) - (7)].interm.intermNode), (yylsp[(1) - (7)]));
+ --context->loopNestingLevel;
+ }
+ break;
+
+ case 186:
+
+ {
+ (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode);
+ }
+ break;
+
+ case 187:
+
+ {
+ (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode);
+ }
+ break;
+
+ case 188:
+
+ {
+ (yyval.interm.intermTypedNode) = (yyvsp[(1) - (1)].interm.intermTypedNode);
+ }
+ break;
+
+ case 189:
+
+ {
+ (yyval.interm.intermTypedNode) = 0;
+ }
+ break;
+
+ case 190:
+
+ {
+ (yyval.interm.nodePair).node1 = (yyvsp[(1) - (2)].interm.intermTypedNode);
+ (yyval.interm.nodePair).node2 = 0;
+ }
+ break;
+
+ case 191:
+
+ {
+ (yyval.interm.nodePair).node1 = (yyvsp[(1) - (3)].interm.intermTypedNode);
+ (yyval.interm.nodePair).node2 = (yyvsp[(3) - (3)].interm.intermTypedNode);
+ }
+ break;
+
+ case 192:
+
+ {
+ if (context->loopNestingLevel <= 0) {
+ context->error((yylsp[(1) - (2)]), "continue statement only allowed in loops", "");
+ context->recover();
+ }
+ (yyval.interm.intermNode) = context->intermediate.addBranch(EOpContinue, (yylsp[(1) - (2)]));
+ }
+ break;
+
+ case 193:
+
+ {
+ if (context->loopNestingLevel <= 0) {
+ context->error((yylsp[(1) - (2)]), "break statement only allowed in loops", "");
+ context->recover();
+ }
+ (yyval.interm.intermNode) = context->intermediate.addBranch(EOpBreak, (yylsp[(1) - (2)]));
+ }
+ break;
+
+ case 194:
+
+ {
+ (yyval.interm.intermNode) = context->intermediate.addBranch(EOpReturn, (yylsp[(1) - (2)]));
+ if (context->currentFunctionType->getBasicType() != EbtVoid) {
+ context->error((yylsp[(1) - (2)]), "non-void function must return a value", "return");
+ context->recover();
+ }
+ }
+ break;
+
+ case 195:
+
+ {
+ (yyval.interm.intermNode) = context->intermediate.addBranch(EOpReturn, (yyvsp[(2) - (3)].interm.intermTypedNode), (yylsp[(1) - (3)]));
+ context->functionReturnsValue = true;
+ if (context->currentFunctionType->getBasicType() == EbtVoid) {
+ context->error((yylsp[(1) - (3)]), "void function cannot return a value", "return");
+ context->recover();
+ } else if (*(context->currentFunctionType) != (yyvsp[(2) - (3)].interm.intermTypedNode)->getType()) {
+ context->error((yylsp[(1) - (3)]), "function return is not matching type:", "return");
+ context->recover();
+ }
+ }
+ break;
+
+ case 196:
+
+ {
+ FRAG_ONLY("discard", (yylsp[(1) - (2)]));
+ (yyval.interm.intermNode) = context->intermediate.addBranch(EOpKill, (yylsp[(1) - (2)]));
+ }
+ break;
+
+ case 197:
+
+ {
+ (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode);
+ context->treeRoot = (yyval.interm.intermNode);
+ }
+ break;
+
+ case 198:
+
+ {
+ (yyval.interm.intermNode) = context->intermediate.growAggregate((yyvsp[(1) - (2)].interm.intermNode), (yyvsp[(2) - (2)].interm.intermNode), (yyloc));
+ context->treeRoot = (yyval.interm.intermNode);
+ }
+ break;
+
+ case 199:
+
+ {
+ (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode);
+ }
+ break;
+
+ case 200:
+
+ {
+ (yyval.interm.intermNode) = (yyvsp[(1) - (1)].interm.intermNode);
+ }
+ break;
+
+ case 201:
+
+ {
+ TFunction* function = (yyvsp[(1) - (1)].interm).function;
+
+ const TSymbol *builtIn = context->symbolTable.findBuiltIn(function->getMangledName());
+
+ if (builtIn)
+ {
+ context->error((yylsp[(1) - (1)]), "built-in functions cannot be redefined", function->getName().c_str());
+ context->recover();
+ }
+
+ TFunction* prevDec = static_cast<TFunction*>(context->symbolTable.find(function->getMangledName()));
+ //
+ // Note: 'prevDec' could be 'function' if this is the first time we've seen function
+ // as it would have just been put in the symbol table. Otherwise, we're looking up
+ // an earlier occurance.
+ //
+ if (prevDec->isDefined()) {
+ //
+ // Then this function already has a body.
+ //
+ context->error((yylsp[(1) - (1)]), "function already has a body", function->getName().c_str());
+ context->recover();
+ }
+ prevDec->setDefined();
+
+ //
+ // Raise error message if main function takes any parameters or return anything other than void
+ //
+ if (function->getName() == "main") {
+ if (function->getParamCount() > 0) {
+ context->error((yylsp[(1) - (1)]), "function cannot take any parameter(s)", function->getName().c_str());
+ context->recover();
+ }
+ if (function->getReturnType().getBasicType() != EbtVoid) {
+ context->error((yylsp[(1) - (1)]), "", function->getReturnType().getBasicString(), "main function cannot return a value");
+ context->recover();
+ }
+ }
+
+ //
+ // Remember the return type for later checking for RETURN statements.
+ //
+ context->currentFunctionType = &(prevDec->getReturnType());
+ context->functionReturnsValue = false;
+
+ //
+ // Insert parameters into the symbol table.
+ // If the parameter has no name, it's not an error, just don't insert it
+ // (could be used for unused args).
+ //
+ // Also, accumulate the list of parameters into the HIL, so lower level code
+ // knows where to find parameters.
+ //
+ TIntermAggregate* paramNodes = new TIntermAggregate;
+ for (size_t i = 0; i < function->getParamCount(); i++) {
+ const TParameter& param = function->getParam(i);
+ if (param.name != 0) {
+ TVariable *variable = new TVariable(param.name, *param.type);
+ //
+ // Insert the parameters with name in the symbol table.
+ //
+ if (! context->symbolTable.insert(*variable)) {
+ context->error((yylsp[(1) - (1)]), "redefinition", variable->getName().c_str());
+ context->recover();
+ delete variable;
+ }
+
+ //
+ // Add the parameter to the HIL
+ //
+ paramNodes = context->intermediate.growAggregate(
+ paramNodes,
+ context->intermediate.addSymbol(variable->getUniqueId(),
+ variable->getName(),
+ variable->getType(),
+ (yylsp[(1) - (1)])),
+ (yylsp[(1) - (1)]));
+ } else {
+ paramNodes = context->intermediate.growAggregate(paramNodes, context->intermediate.addSymbol(0, "", *param.type, (yylsp[(1) - (1)])), (yylsp[(1) - (1)]));
+ }
+ }
+ context->intermediate.setAggregateOperator(paramNodes, EOpParameters, (yylsp[(1) - (1)]));
+ (yyvsp[(1) - (1)].interm).intermAggregate = paramNodes;
+ context->loopNestingLevel = 0;
+ }
+ break;
+
+ case 202:
+
+ {
+ //?? Check that all paths return a value if return type != void ?
+ // May be best done as post process phase on intermediate code
+ if (context->currentFunctionType->getBasicType() != EbtVoid && ! context->functionReturnsValue) {
+ context->error((yylsp[(1) - (3)]), "function does not return a value:", "", (yyvsp[(1) - (3)].interm).function->getName().c_str());
+ context->recover();
+ }
+
+ (yyval.interm.intermNode) = context->intermediate.growAggregate((yyvsp[(1) - (3)].interm).intermAggregate, (yyvsp[(3) - (3)].interm.intermNode), (yyloc));
+ context->intermediate.setAggregateOperator((yyval.interm.intermNode), EOpFunction, (yylsp[(1) - (3)]));
+ (yyval.interm.intermNode)->getAsAggregate()->setName((yyvsp[(1) - (3)].interm).function->getMangledName().c_str());
+ (yyval.interm.intermNode)->getAsAggregate()->setType((yyvsp[(1) - (3)].interm).function->getReturnType());
+
+ // store the pragma information for debug and optimize and other vendor specific
+ // information. This information can be queried from the parse tree
+ (yyval.interm.intermNode)->getAsAggregate()->setOptimize(context->pragma().optimize);
+ (yyval.interm.intermNode)->getAsAggregate()->setDebug(context->pragma().debug);
+
+ context->symbolTable.pop();
+ }
+ break;
+
+
+
+ default: break;
+ }
+ /* User semantic actions sometimes alter yychar, and that requires
+ that yytoken be updated with the new translation. We take the
+ approach of translating immediately before every use of yytoken.
+ One alternative is translating here after every semantic action,
+ but that translation would be missed if the semantic action invokes
+ YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or
+ if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an
+ incorrect destructor might then be invoked immediately. In the
+ case of YYERROR or YYBACKUP, subsequent parser actions might lead
+ to an incorrect destructor call or verbose syntax error message
+ before the lookahead is translated. */
+ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+
+ *++yyvsp = yyval;
+ *++yylsp = yyloc;
+
+ /* Now `shift' the result of the reduction. Determine what state
+ that goes to, based on the state we popped back to and the rule
+ number reduced by. */
+
+ yyn = yyr1[yyn];
+
+ yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+ if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+ yystate = yytable[yystate];
+ else
+ yystate = yydefgoto[yyn - YYNTOKENS];
+
+ goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+ /* Make sure we have latest lookahead translation. See comments at
+ user semantic actions for why this is necessary. */
+ yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
+
+ /* If not already recovering from an error, report this error. */
+ if (!yyerrstatus)
+ {
+ ++yynerrs;
+#if ! YYERROR_VERBOSE
+ yyerror (&yylloc, context, YY_("syntax error"));
+#else
+# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
+ yyssp, yytoken)
+ {
+ char const *yymsgp = YY_("syntax error");
+ int yysyntax_error_status;
+ yysyntax_error_status = YYSYNTAX_ERROR;
+ if (yysyntax_error_status == 0)
+ yymsgp = yymsg;
+ else if (yysyntax_error_status == 1)
+ {
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+ yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
+ if (!yymsg)
+ {
+ yymsg = yymsgbuf;
+ yymsg_alloc = sizeof yymsgbuf;
+ yysyntax_error_status = 2;
+ }
+ else
+ {
+ yysyntax_error_status = YYSYNTAX_ERROR;
+ yymsgp = yymsg;
+ }
+ }
+ yyerror (&yylloc, context, yymsgp);
+ if (yysyntax_error_status == 2)
+ goto yyexhaustedlab;
+ }
+# undef YYSYNTAX_ERROR
+#endif
+ }
+
+ yyerror_range[1] = yylloc;
+
+ if (yyerrstatus == 3)
+ {
+ /* If just tried and failed to reuse lookahead token after an
+ error, discard it. */
+
+ if (yychar <= YYEOF)
+ {
+ /* Return failure if at end of input. */
+ if (yychar == YYEOF)
+ YYABORT;
+ }
+ else
+ {
+ yydestruct ("Error: discarding",
+ yytoken, &yylval, &yylloc, context);
+ yychar = YYEMPTY;
+ }
+ }
+
+ /* Else will try to reuse lookahead token after shifting the error
+ token. */
+ goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR. |
+`---------------------------------------------------*/
+yyerrorlab:
+
+ /* Pacify compilers like GCC when the user code never invokes
+ YYERROR and the label yyerrorlab therefore never appears in user
+ code. */
+ if (/*CONSTCOND*/ 0)
+ goto yyerrorlab;
+
+ yyerror_range[1] = yylsp[1-yylen];
+ /* Do not reclaim the symbols of the rule which action triggered
+ this YYERROR. */
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+ yystate = *yyssp;
+ goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR. |
+`-------------------------------------------------------------*/
+yyerrlab1:
+ yyerrstatus = 3; /* Each real token shifted decrements this. */
+
+ for (;;)
+ {
+ yyn = yypact[yystate];
+ if (!yypact_value_is_default (yyn))
+ {
+ yyn += YYTERROR;
+ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+ {
+ yyn = yytable[yyn];
+ if (0 < yyn)
+ break;
+ }
+ }
+
+ /* Pop the current state because it cannot handle the error token. */
+ if (yyssp == yyss)
+ YYABORT;
+
+ yyerror_range[1] = *yylsp;
+ yydestruct ("Error: popping",
+ yystos[yystate], yyvsp, yylsp, context);
+ YYPOPSTACK (1);
+ yystate = *yyssp;
+ YY_STACK_PRINT (yyss, yyssp);
+ }
+
+ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+ *++yyvsp = yylval;
+ YY_IGNORE_MAYBE_UNINITIALIZED_END
+
+ yyerror_range[2] = yylloc;
+ /* Using YYLLOC is tempting, but would change the location of
+ the lookahead. YYLOC is available though. */
+ YYLLOC_DEFAULT (yyloc, yyerror_range, 2);
+ *++yylsp = yyloc;
+
+ /* Shift the error token. */
+ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+ yystate = yyn;
+ goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here. |
+`-------------------------------------*/
+yyacceptlab:
+ yyresult = 0;
+ goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here. |
+`-----------------------------------*/
+yyabortlab:
+ yyresult = 1;
+ goto yyreturn;
+
+#if !defined yyoverflow || YYERROR_VERBOSE
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here. |
+`-------------------------------------------------*/
+yyexhaustedlab:
+ yyerror (&yylloc, context, YY_("memory exhausted"));
+ yyresult = 2;
+ /* Fall through. */
+#endif
+
+yyreturn:
+ if (yychar != YYEMPTY)
+ {
+ /* Make sure we have latest lookahead translation. See comments at
+ user semantic actions for why this is necessary. */
+ yytoken = YYTRANSLATE (yychar);
+ yydestruct ("Cleanup: discarding lookahead",
+ yytoken, &yylval, &yylloc, context);
+ }
+ /* Do not reclaim the symbols of the rule which action triggered
+ this YYABORT or YYACCEPT. */
+ YYPOPSTACK (yylen);
+ YY_STACK_PRINT (yyss, yyssp);
+ while (yyssp != yyss)
+ {
+ yydestruct ("Cleanup: popping",
+ yystos[*yyssp], yyvsp, yylsp, context);
+ YYPOPSTACK (1);
+ }
+#ifndef yyoverflow
+ if (yyss != yyssa)
+ YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+#endif
+ /* Make sure YYID is used. */
+ return YYID (yyresult);
+}
+
+
+
+
+
+int glslang_parse(TParseContext* context) {
+ return yyparse(context);
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/glslang_tab.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorglslang_tabh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/glslang_tab.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/glslang_tab.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/glslang_tab.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,225 @@
</span><ins>+/* A Bison parser, made by GNU Bison 2.7.1. */
+
+/* Apple Note: For the avoidance of doubt, Apple elects to distribute this file under the terms of the BSD license. */
+
+/* Bison interface for Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+#ifndef YY_YY_GLSLANG_TAB_H_INCLUDED
+# define YY_YY_GLSLANG_TAB_H_INCLUDED
+/* Enabling traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+#if YYDEBUG
+extern int yydebug;
+#endif
+/* "%code requires" blocks. */
+
+
+#define YYLTYPE TSourceLoc
+#define YYLTYPE_IS_DECLARED 1
+#define SH_MAX_TOKEN_LENGTH 256 // WebGL spec.
+
+
+
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ INVARIANT = 258,
+ HIGH_PRECISION = 259,
+ MEDIUM_PRECISION = 260,
+ LOW_PRECISION = 261,
+ PRECISION = 262,
+ ATTRIBUTE = 263,
+ CONST_QUAL = 264,
+ BOOL_TYPE = 265,
+ FLOAT_TYPE = 266,
+ INT_TYPE = 267,
+ BREAK = 268,
+ CONTINUE = 269,
+ DO = 270,
+ ELSE = 271,
+ FOR = 272,
+ IF = 273,
+ DISCARD = 274,
+ RETURN = 275,
+ BVEC2 = 276,
+ BVEC3 = 277,
+ BVEC4 = 278,
+ IVEC2 = 279,
+ IVEC3 = 280,
+ IVEC4 = 281,
+ VEC2 = 282,
+ VEC3 = 283,
+ VEC4 = 284,
+ MATRIX2 = 285,
+ MATRIX3 = 286,
+ MATRIX4 = 287,
+ IN_QUAL = 288,
+ OUT_QUAL = 289,
+ INOUT_QUAL = 290,
+ UNIFORM = 291,
+ VARYING = 292,
+ STRUCT = 293,
+ VOID_TYPE = 294,
+ WHILE = 295,
+ SAMPLER2D = 296,
+ SAMPLERCUBE = 297,
+ SAMPLER_EXTERNAL_OES = 298,
+ SAMPLER2DRECT = 299,
+ IDENTIFIER = 300,
+ TYPE_NAME = 301,
+ FLOATCONSTANT = 302,
+ INTCONSTANT = 303,
+ BOOLCONSTANT = 304,
+ LEFT_OP = 305,
+ RIGHT_OP = 306,
+ INC_OP = 307,
+ DEC_OP = 308,
+ LE_OP = 309,
+ GE_OP = 310,
+ EQ_OP = 311,
+ NE_OP = 312,
+ AND_OP = 313,
+ OR_OP = 314,
+ XOR_OP = 315,
+ MUL_ASSIGN = 316,
+ DIV_ASSIGN = 317,
+ ADD_ASSIGN = 318,
+ MOD_ASSIGN = 319,
+ LEFT_ASSIGN = 320,
+ RIGHT_ASSIGN = 321,
+ AND_ASSIGN = 322,
+ XOR_ASSIGN = 323,
+ OR_ASSIGN = 324,
+ SUB_ASSIGN = 325,
+ LEFT_PAREN = 326,
+ RIGHT_PAREN = 327,
+ LEFT_BRACKET = 328,
+ RIGHT_BRACKET = 329,
+ LEFT_BRACE = 330,
+ RIGHT_BRACE = 331,
+ DOT = 332,
+ COMMA = 333,
+ COLON = 334,
+ EQUAL = 335,
+ SEMICOLON = 336,
+ BANG = 337,
+ DASH = 338,
+ TILDE = 339,
+ PLUS = 340,
+ STAR = 341,
+ SLASH = 342,
+ PERCENT = 343,
+ LEFT_ANGLE = 344,
+ RIGHT_ANGLE = 345,
+ VERTICAL_BAR = 346,
+ CARET = 347,
+ AMPERSAND = 348,
+ QUESTION = 349
+ };
+#endif
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+{
+
+
+ struct {
+ union {
+ TString *string;
+ float f;
+ int i;
+ bool b;
+ };
+ TSymbol* symbol;
+ } lex;
+ struct {
+ TOperator op;
+ union {
+ TIntermNode* intermNode;
+ TIntermNodePair nodePair;
+ TIntermTyped* intermTypedNode;
+ TIntermAggregate* intermAggregate;
+ };
+ union {
+ TPublicType type;
+ TPrecision precision;
+ TQualifier qualifier;
+ TFunction* function;
+ TParameter param;
+ TField* field;
+ TFieldList* fieldList;
+ };
+ } interm;
+
+
+
+} YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
+typedef struct YYLTYPE
+{
+ int first_line;
+ int first_column;
+ int last_line;
+ int last_column;
+} YYLTYPE;
+# define yyltype YYLTYPE /* obsolescent; will be withdrawn */
+# define YYLTYPE_IS_DECLARED 1
+# define YYLTYPE_IS_TRIVIAL 1
+#endif
+
+
+#ifdef YYPARSE_PARAM
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void *YYPARSE_PARAM);
+#else
+int yyparse ();
+#endif
+#else /* ! YYPARSE_PARAM */
+#if defined __STDC__ || defined __cplusplus
+int yyparse (TParseContext* context);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
+
+#endif /* !YY_YY_GLSLANG_TAB_H_INCLUDED */
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/glslang_tab.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorintermOutcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/intermOut.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/intermOut.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/intermOut.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,424 @@
</span><ins>+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/localintermediate.h"
+
+//
+// Two purposes:
+// 1. Show an example of how to iterate tree. Functions can
+// also directly call Traverse() on children themselves to
+// have finer grained control over the process than shown here.
+// See the last function for how to get started.
+// 2. Print out a text based description of the tree.
+//
+
+//
+// Use this class to carry along data from node to node in
+// the traversal
+//
+class TOutputTraverser : public TIntermTraverser {
+public:
+ TOutputTraverser(TInfoSinkBase& i) : sink(i) { }
+ TInfoSinkBase& sink;
+
+protected:
+ void visitSymbol(TIntermSymbol*);
+ void visitConstantUnion(TIntermConstantUnion*);
+ bool visitBinary(Visit visit, TIntermBinary*);
+ bool visitUnary(Visit visit, TIntermUnary*);
+ bool visitSelection(Visit visit, TIntermSelection*);
+ bool visitAggregate(Visit visit, TIntermAggregate*);
+ bool visitLoop(Visit visit, TIntermLoop*);
+ bool visitBranch(Visit visit, TIntermBranch*);
+};
+
+TString TType::getCompleteString() const
+{
+ TStringStream stream;
+
+ if (qualifier != EvqTemporary && qualifier != EvqGlobal)
+ stream << getQualifierString() << " " << getPrecisionString() << " ";
+ if (array)
+ stream << "array[" << getArraySize() << "] of ";
+ if (matrix)
+ stream << static_cast<int>(size) << "X" << static_cast<int>(size) << " matrix of ";
+ else if (size > 1)
+ stream << static_cast<int>(size) << "-component vector of ";
+
+ stream << getBasicString();
+ return stream.str();
+}
+
+//
+// Helper functions for printing, not part of traversing.
+//
+
+void OutputTreeText(TInfoSinkBase& sink, TIntermNode* node, const int depth)
+{
+ int i;
+
+ sink.location(node->getLine());
+
+ for (i = 0; i < depth; ++i)
+ sink << " ";
+}
+
+//
+// The rest of the file are the traversal functions. The last one
+// is the one that starts the traversal.
+//
+// Return true from interior nodes to have the external traversal
+// continue on to children. If you process children yourself,
+// return false.
+//
+
+void TOutputTraverser::visitSymbol(TIntermSymbol* node)
+{
+ OutputTreeText(sink, node, depth);
+
+ sink << "'" << node->getSymbol() << "' ";
+ sink << "(" << node->getCompleteString() << ")\n";
+}
+
+bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary* node)
+{
+ TInfoSinkBase& out = sink;
+
+ OutputTreeText(out, node, depth);
+
+ switch (node->getOp()) {
+ case EOpAssign: out << "move second child to first child"; break;
+ case EOpInitialize: out << "initialize first child with second child"; break;
+ case EOpAddAssign: out << "add second child into first child"; break;
+ case EOpSubAssign: out << "subtract second child into first child"; break;
+ case EOpMulAssign: out << "multiply second child into first child"; break;
+ case EOpVectorTimesMatrixAssign: out << "matrix mult second child into first child"; break;
+ case EOpVectorTimesScalarAssign: out << "vector scale second child into first child"; break;
+ case EOpMatrixTimesScalarAssign: out << "matrix scale second child into first child"; break;
+ case EOpMatrixTimesMatrixAssign: out << "matrix mult second child into first child"; break;
+ case EOpDivAssign: out << "divide second child into first child"; break;
+ case EOpIndexDirect: out << "direct index"; break;
+ case EOpIndexIndirect: out << "indirect index"; break;
+ case EOpIndexDirectStruct: out << "direct index for structure"; break;
+ case EOpVectorSwizzle: out << "vector swizzle"; break;
+
+ case EOpAdd: out << "add"; break;
+ case EOpSub: out << "subtract"; break;
+ case EOpMul: out << "component-wise multiply"; break;
+ case EOpDiv: out << "divide"; break;
+ case EOpEqual: out << "Compare Equal"; break;
+ case EOpNotEqual: out << "Compare Not Equal"; break;
+ case EOpLessThan: out << "Compare Less Than"; break;
+ case EOpGreaterThan: out << "Compare Greater Than"; break;
+ case EOpLessThanEqual: out << "Compare Less Than or Equal"; break;
+ case EOpGreaterThanEqual: out << "Compare Greater Than or Equal"; break;
+
+ case EOpVectorTimesScalar: out << "vector-scale"; break;
+ case EOpVectorTimesMatrix: out << "vector-times-matrix"; break;
+ case EOpMatrixTimesVector: out << "matrix-times-vector"; break;
+ case EOpMatrixTimesScalar: out << "matrix-scale"; break;
+ case EOpMatrixTimesMatrix: out << "matrix-multiply"; break;
+
+ case EOpLogicalOr: out << "logical-or"; break;
+ case EOpLogicalXor: out << "logical-xor"; break;
+ case EOpLogicalAnd: out << "logical-and"; break;
+ default: out << "<unknown op>";
+ }
+
+ out << " (" << node->getCompleteString() << ")";
+
+ out << "\n";
+
+ return true;
+}
+
+bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary* node)
+{
+ TInfoSinkBase& out = sink;
+
+ OutputTreeText(out, node, depth);
+
+ switch (node->getOp()) {
+ case EOpNegative: out << "Negate value"; break;
+ case EOpVectorLogicalNot:
+ case EOpLogicalNot: out << "Negate conditional"; break;
+
+ case EOpPostIncrement: out << "Post-Increment"; break;
+ case EOpPostDecrement: out << "Post-Decrement"; break;
+ case EOpPreIncrement: out << "Pre-Increment"; break;
+ case EOpPreDecrement: out << "Pre-Decrement"; break;
+
+ case EOpConvIntToBool: out << "Convert int to bool"; break;
+ case EOpConvFloatToBool:out << "Convert float to bool";break;
+ case EOpConvBoolToFloat:out << "Convert bool to float";break;
+ case EOpConvIntToFloat: out << "Convert int to float"; break;
+ case EOpConvFloatToInt: out << "Convert float to int"; break;
+ case EOpConvBoolToInt: out << "Convert bool to int"; break;
+
+ case EOpRadians: out << "radians"; break;
+ case EOpDegrees: out << "degrees"; break;
+ case EOpSin: out << "sine"; break;
+ case EOpCos: out << "cosine"; break;
+ case EOpTan: out << "tangent"; break;
+ case EOpAsin: out << "arc sine"; break;
+ case EOpAcos: out << "arc cosine"; break;
+ case EOpAtan: out << "arc tangent"; break;
+
+ case EOpExp: out << "exp"; break;
+ case EOpLog: out << "log"; break;
+ case EOpExp2: out << "exp2"; break;
+ case EOpLog2: out << "log2"; break;
+ case EOpSqrt: out << "sqrt"; break;
+ case EOpInverseSqrt: out << "inverse sqrt"; break;
+
+ case EOpAbs: out << "Absolute value"; break;
+ case EOpSign: out << "Sign"; break;
+ case EOpFloor: out << "Floor"; break;
+ case EOpCeil: out << "Ceiling"; break;
+ case EOpFract: out << "Fraction"; break;
+
+ case EOpLength: out << "length"; break;
+ case EOpNormalize: out << "normalize"; break;
+ // case EOpDPdx: out << "dPdx"; break;
+ // case EOpDPdy: out << "dPdy"; break;
+ // case EOpFwidth: out << "fwidth"; break;
+
+ case EOpAny: out << "any"; break;
+ case EOpAll: out << "all"; break;
+
+ default:
+ out.prefix(EPrefixError);
+ out << "Bad unary op";
+ }
+
+ out << " (" << node->getCompleteString() << ")";
+
+ out << "\n";
+
+ return true;
+}
+
+bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate* node)
+{
+ TInfoSinkBase& out = sink;
+
+ if (node->getOp() == EOpNull) {
+ out.prefix(EPrefixError);
+ out << "node is still EOpNull!";
+ return true;
+ }
+
+ OutputTreeText(out, node, depth);
+
+ switch (node->getOp()) {
+ case EOpSequence: out << "Sequence\n"; return true;
+ case EOpComma: out << "Comma\n"; return true;
+ case EOpFunction: out << "Function Definition: " << node->getName(); break;
+ case EOpFunctionCall: out << "Function Call: " << node->getName(); break;
+ case EOpParameters: out << "Function Parameters: "; break;
+
+ case EOpConstructFloat: out << "Construct float"; break;
+ case EOpConstructVec2: out << "Construct vec2"; break;
+ case EOpConstructVec3: out << "Construct vec3"; break;
+ case EOpConstructVec4: out << "Construct vec4"; break;
+ case EOpConstructBool: out << "Construct bool"; break;
+ case EOpConstructBVec2: out << "Construct bvec2"; break;
+ case EOpConstructBVec3: out << "Construct bvec3"; break;
+ case EOpConstructBVec4: out << "Construct bvec4"; break;
+ case EOpConstructInt: out << "Construct int"; break;
+ case EOpConstructIVec2: out << "Construct ivec2"; break;
+ case EOpConstructIVec3: out << "Construct ivec3"; break;
+ case EOpConstructIVec4: out << "Construct ivec4"; break;
+ case EOpConstructMat2: out << "Construct mat2"; break;
+ case EOpConstructMat3: out << "Construct mat3"; break;
+ case EOpConstructMat4: out << "Construct mat4"; break;
+ case EOpConstructStruct: out << "Construct structure"; break;
+
+ case EOpLessThan: out << "Compare Less Than"; break;
+ case EOpGreaterThan: out << "Compare Greater Than"; break;
+ case EOpLessThanEqual: out << "Compare Less Than or Equal"; break;
+ case EOpGreaterThanEqual: out << "Compare Greater Than or Equal"; break;
+ case EOpVectorEqual: out << "Equal"; break;
+ case EOpVectorNotEqual: out << "NotEqual"; break;
+
+ case EOpMod: out << "mod"; break;
+ case EOpPow: out << "pow"; break;
+
+ case EOpAtan: out << "arc tangent"; break;
+
+ case EOpMin: out << "min"; break;
+ case EOpMax: out << "max"; break;
+ case EOpClamp: out << "clamp"; break;
+ case EOpMix: out << "mix"; break;
+ case EOpStep: out << "step"; break;
+ case EOpSmoothStep: out << "smoothstep"; break;
+
+ case EOpDistance: out << "distance"; break;
+ case EOpDot: out << "dot-product"; break;
+ case EOpCross: out << "cross-product"; break;
+ case EOpFaceForward: out << "face-forward"; break;
+ case EOpReflect: out << "reflect"; break;
+ case EOpRefract: out << "refract"; break;
+ case EOpMul: out << "component-wise multiply"; break;
+
+ case EOpDeclaration: out << "Declaration: "; break;
+
+ default:
+ out.prefix(EPrefixError);
+ out << "Bad aggregation op";
+ }
+
+ if (node->getOp() != EOpSequence && node->getOp() != EOpParameters)
+ out << " (" << node->getCompleteString() << ")";
+
+ out << "\n";
+
+ return true;
+}
+
+bool TOutputTraverser::visitSelection(Visit visit, TIntermSelection* node)
+{
+ TInfoSinkBase& out = sink;
+
+ OutputTreeText(out, node, depth);
+
+ out << "Test condition and select";
+ out << " (" << node->getCompleteString() << ")\n";
+
+ ++depth;
+
+ OutputTreeText(sink, node, depth);
+ out << "Condition\n";
+ node->getCondition()->traverse(this);
+
+ OutputTreeText(sink, node, depth);
+ if (node->getTrueBlock()) {
+ out << "true case\n";
+ node->getTrueBlock()->traverse(this);
+ } else
+ out << "true case is null\n";
+
+ if (node->getFalseBlock()) {
+ OutputTreeText(sink, node, depth);
+ out << "false case\n";
+ node->getFalseBlock()->traverse(this);
+ }
+
+ --depth;
+
+ return false;
+}
+
+void TOutputTraverser::visitConstantUnion(TIntermConstantUnion* node)
+{
+ TInfoSinkBase& out = sink;
+
+ size_t size = node->getType().getObjectSize();
+
+ for (size_t i = 0; i < size; i++) {
+ OutputTreeText(out, node, depth);
+ switch (node->getUnionArrayPointer()[i].getType()) {
+ case EbtBool:
+ if (node->getUnionArrayPointer()[i].getBConst())
+ out << "true";
+ else
+ out << "false";
+
+ out << " (" << "const bool" << ")";
+ out << "\n";
+ break;
+ case EbtFloat:
+ out << node->getUnionArrayPointer()[i].getFConst();
+ out << " (const float)\n";
+ break;
+ case EbtInt:
+ out << node->getUnionArrayPointer()[i].getIConst();
+ out << " (const int)\n";
+ break;
+ default:
+ out.message(EPrefixInternalError, node->getLine(), "Unknown constant");
+ break;
+ }
+ }
+}
+
+bool TOutputTraverser::visitLoop(Visit visit, TIntermLoop* node)
+{
+ TInfoSinkBase& out = sink;
+
+ OutputTreeText(out, node, depth);
+
+ out << "Loop with condition ";
+ if (node->getType() == ELoopDoWhile)
+ out << "not ";
+ out << "tested first\n";
+
+ ++depth;
+
+ OutputTreeText(sink, node, depth);
+ if (node->getCondition()) {
+ out << "Loop Condition\n";
+ node->getCondition()->traverse(this);
+ } else
+ out << "No loop condition\n";
+
+ OutputTreeText(sink, node, depth);
+ if (node->getBody()) {
+ out << "Loop Body\n";
+ node->getBody()->traverse(this);
+ } else
+ out << "No loop body\n";
+
+ if (node->getExpression()) {
+ OutputTreeText(sink, node, depth);
+ out << "Loop Terminal Expression\n";
+ node->getExpression()->traverse(this);
+ }
+
+ --depth;
+
+ return false;
+}
+
+bool TOutputTraverser::visitBranch(Visit visit, TIntermBranch* node)
+{
+ TInfoSinkBase& out = sink;
+
+ OutputTreeText(out, node, depth);
+
+ switch (node->getFlowOp()) {
+ case EOpKill: out << "Branch: Kill"; break;
+ case EOpBreak: out << "Branch: Break"; break;
+ case EOpContinue: out << "Branch: Continue"; break;
+ case EOpReturn: out << "Branch: Return"; break;
+ default: out << "Branch: Unknown Branch"; break;
+ }
+
+ if (node->getExpression()) {
+ out << " with expression\n";
+ ++depth;
+ node->getExpression()->traverse(this);
+ --depth;
+ } else
+ out << "\n";
+
+ return false;
+}
+
+//
+// This function is the one to call externally to start the traversal.
+// Individual functions can be initialized to 0 to skip processing of that
+// type of node. It's children will still be processed.
+//
+void TIntermediate::outputTree(TIntermNode* root)
+{
+ if (root == 0)
+ return;
+
+ TOutputTraverser it(infoSink.info);
+
+ root->traverse(&it);
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/intermOut.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorintermediateh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/intermediate.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/intermediate.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/intermediate.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,635 @@
</span><ins>+//
+// Copyright (c) 2002-2013 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.
+//
+
+//
+// Definition of the in-memory high-level intermediate representation
+// of shaders. This is a tree that parser creates.
+//
+// Nodes in the tree are defined as a hierarchy of classes derived from
+// TIntermNode. Each is a node in a tree. There is no preset branching factor;
+// each node can have it's own type of list of children.
+//
+
+#ifndef __INTERMEDIATE_H
+#define __INTERMEDIATE_H
+
+#include "GLSLANG/ShaderLang.h"
+
+#include <algorithm>
+#include "compiler/translator/Common.h"
+#include "compiler/translator/Types.h"
+#include "compiler/translator/ConstantUnion.h"
+
+//
+// Operators used by the high-level (parse tree) representation.
+//
+enum TOperator {
+ EOpNull, // if in a node, should only mean a node is still being built
+ EOpSequence, // denotes a list of statements, or parameters, etc.
+ EOpFunctionCall,
+ EOpFunction, // For function definition
+ EOpParameters, // an aggregate listing the parameters to a function
+
+ EOpDeclaration,
+ EOpPrototype,
+
+ //
+ // Unary operators
+ //
+
+ EOpNegative,
+ EOpLogicalNot,
+ EOpVectorLogicalNot,
+
+ EOpPostIncrement,
+ EOpPostDecrement,
+ EOpPreIncrement,
+ EOpPreDecrement,
+
+ EOpConvIntToBool,
+ EOpConvFloatToBool,
+ EOpConvBoolToFloat,
+ EOpConvIntToFloat,
+ EOpConvFloatToInt,
+ EOpConvBoolToInt,
+
+ //
+ // binary operations
+ //
+
+ EOpAdd,
+ EOpSub,
+ EOpMul,
+ EOpDiv,
+ EOpEqual,
+ EOpNotEqual,
+ EOpVectorEqual,
+ EOpVectorNotEqual,
+ EOpLessThan,
+ EOpGreaterThan,
+ EOpLessThanEqual,
+ EOpGreaterThanEqual,
+ EOpComma,
+
+ EOpVectorTimesScalar,
+ EOpVectorTimesMatrix,
+ EOpMatrixTimesVector,
+ EOpMatrixTimesScalar,
+
+ EOpLogicalOr,
+ EOpLogicalXor,
+ EOpLogicalAnd,
+
+ EOpIndexDirect,
+ EOpIndexIndirect,
+ EOpIndexDirectStruct,
+
+ EOpVectorSwizzle,
+
+ //
+ // Built-in functions potentially mapped to operators
+ //
+
+ EOpRadians,
+ EOpDegrees,
+ EOpSin,
+ EOpCos,
+ EOpTan,
+ EOpAsin,
+ EOpAcos,
+ EOpAtan,
+
+ EOpPow,
+ EOpExp,
+ EOpLog,
+ EOpExp2,
+ EOpLog2,
+ EOpSqrt,
+ EOpInverseSqrt,
+
+ EOpAbs,
+ EOpSign,
+ EOpFloor,
+ EOpCeil,
+ EOpFract,
+ EOpMod,
+ EOpMin,
+ EOpMax,
+ EOpClamp,
+ EOpMix,
+ EOpStep,
+ EOpSmoothStep,
+
+ EOpLength,
+ EOpDistance,
+ EOpDot,
+ EOpCross,
+ EOpNormalize,
+ EOpFaceForward,
+ EOpReflect,
+ EOpRefract,
+
+ EOpDFdx, // Fragment only, OES_standard_derivatives extension
+ EOpDFdy, // Fragment only, OES_standard_derivatives extension
+ EOpFwidth, // Fragment only, OES_standard_derivatives extension
+
+ EOpMatrixTimesMatrix,
+
+ EOpAny,
+ EOpAll,
+
+ //
+ // Branch
+ //
+
+ EOpKill, // Fragment only
+ EOpReturn,
+ EOpBreak,
+ EOpContinue,
+
+ //
+ // Constructors
+ //
+
+ EOpConstructInt,
+ EOpConstructBool,
+ EOpConstructFloat,
+ EOpConstructVec2,
+ EOpConstructVec3,
+ EOpConstructVec4,
+ EOpConstructBVec2,
+ EOpConstructBVec3,
+ EOpConstructBVec4,
+ EOpConstructIVec2,
+ EOpConstructIVec3,
+ EOpConstructIVec4,
+ EOpConstructMat2,
+ EOpConstructMat3,
+ EOpConstructMat4,
+ EOpConstructStruct,
+
+ //
+ // moves
+ //
+
+ EOpAssign,
+ EOpInitialize,
+ EOpAddAssign,
+ EOpSubAssign,
+ EOpMulAssign,
+ EOpVectorTimesMatrixAssign,
+ EOpVectorTimesScalarAssign,
+ EOpMatrixTimesScalarAssign,
+ EOpMatrixTimesMatrixAssign,
+ EOpDivAssign
+};
+
+extern const char* getOperatorString(TOperator op);
+
+class TIntermTraverser;
+class TIntermAggregate;
+class TIntermBinary;
+class TIntermUnary;
+class TIntermConstantUnion;
+class TIntermSelection;
+class TIntermTyped;
+class TIntermSymbol;
+class TIntermLoop;
+class TInfoSink;
+
+//
+// Base class for the tree nodes
+//
+class TIntermNode {
+public:
+ POOL_ALLOCATOR_NEW_DELETE();
+ TIntermNode() {
+ // TODO: Move this to TSourceLoc constructor
+ // after getting rid of TPublicType.
+ line.first_file = line.last_file = 0;
+ line.first_line = line.last_line = 0;
+ }
+ virtual ~TIntermNode() { }
+
+ const TSourceLoc& getLine() const { return line; }
+ void setLine(const TSourceLoc& l) { line = l; }
+
+ virtual void traverse(TIntermTraverser*) = 0;
+ virtual TIntermTyped* getAsTyped() { return 0; }
+ virtual TIntermConstantUnion* getAsConstantUnion() { return 0; }
+ virtual TIntermAggregate* getAsAggregate() { return 0; }
+ virtual TIntermBinary* getAsBinaryNode() { return 0; }
+ virtual TIntermUnary* getAsUnaryNode() { return 0; }
+ virtual TIntermSelection* getAsSelectionNode() { return 0; }
+ virtual TIntermSymbol* getAsSymbolNode() { return 0; }
+ virtual TIntermLoop* getAsLoopNode() { return 0; }
+
+ // Replace a child node. Return true if |original| is a child
+ // node and it is replaced; otherwise, return false.
+ virtual bool replaceChildNode(
+ TIntermNode *original, TIntermNode *replacement) = 0;
+
+protected:
+ TSourceLoc line;
+};
+
+//
+// This is just to help yacc.
+//
+struct TIntermNodePair {
+ TIntermNode* node1;
+ TIntermNode* node2;
+};
+
+//
+// Intermediate class for nodes that have a type.
+//
+class TIntermTyped : public TIntermNode {
+public:
+ TIntermTyped(const TType& t) : type(t) { }
+ virtual TIntermTyped* getAsTyped() { return this; }
+
+ virtual bool hasSideEffects() const = 0;
+
+ void setType(const TType& t) { type = t; }
+ const TType& getType() const { return type; }
+ TType* getTypePointer() { return &type; }
+
+ TBasicType getBasicType() const { return type.getBasicType(); }
+ TQualifier getQualifier() const { return type.getQualifier(); }
+ TPrecision getPrecision() const { return type.getPrecision(); }
+ int getNominalSize() const { return type.getNominalSize(); }
+
+ bool isMatrix() const { return type.isMatrix(); }
+ bool isArray() const { return type.isArray(); }
+ bool isVector() const { return type.isVector(); }
+ bool isScalar() const { return type.isScalar(); }
+ const char* getBasicString() const { return type.getBasicString(); }
+ const char* getQualifierString() const { return type.getQualifierString(); }
+ TString getCompleteString() const { return type.getCompleteString(); }
+
+ int totalRegisterCount() const { return type.totalRegisterCount(); }
+ int elementRegisterCount() const { return type.elementRegisterCount(); }
+ int getArraySize() const { return type.getArraySize(); }
+
+protected:
+ TType type;
+};
+
+//
+// Handle for, do-while, and while loops.
+//
+enum TLoopType {
+ ELoopFor,
+ ELoopWhile,
+ ELoopDoWhile
+};
+
+class TIntermLoop : public TIntermNode {
+public:
+ TIntermLoop(TLoopType aType,
+ TIntermNode *aInit, TIntermTyped* aCond, TIntermTyped* aExpr,
+ TIntermNode* aBody) :
+ type(aType),
+ init(aInit),
+ cond(aCond),
+ expr(aExpr),
+ body(aBody),
+ unrollFlag(false) { }
+
+ virtual TIntermLoop* getAsLoopNode() { return this; }
+ virtual void traverse(TIntermTraverser*);
+ virtual bool replaceChildNode(
+ TIntermNode *original, TIntermNode *replacement);
+
+ TLoopType getType() const { return type; }
+ TIntermNode* getInit() { return init; }
+ TIntermTyped* getCondition() { return cond; }
+ TIntermTyped* getExpression() { return expr; }
+ TIntermNode* getBody() { return body; }
+
+ void setUnrollFlag(bool flag) { unrollFlag = flag; }
+ bool getUnrollFlag() { return unrollFlag; }
+
+protected:
+ TLoopType type;
+ TIntermNode* init; // for-loop initialization
+ TIntermTyped* cond; // loop exit condition
+ TIntermTyped* expr; // for-loop expression
+ TIntermNode* body; // loop body
+
+ bool unrollFlag; // Whether the loop should be unrolled or not.
+};
+
+//
+// Handle break, continue, return, and kill.
+//
+class TIntermBranch : public TIntermNode {
+public:
+ TIntermBranch(TOperator op, TIntermTyped* e) :
+ flowOp(op),
+ expression(e) { }
+
+ virtual void traverse(TIntermTraverser*);
+ virtual bool replaceChildNode(
+ TIntermNode *original, TIntermNode *replacement);
+
+ TOperator getFlowOp() { return flowOp; }
+ TIntermTyped* getExpression() { return expression; }
+
+protected:
+ TOperator flowOp;
+ TIntermTyped* expression; // non-zero except for "return exp;" statements
+};
+
+//
+// Nodes that correspond to symbols or constants in the source code.
+//
+class TIntermSymbol : public TIntermTyped {
+public:
+ // if symbol is initialized as symbol(sym), the memory comes from the poolallocator of sym. If sym comes from
+ // per process globalpoolallocator, then it causes increased memory usage per compile
+ // it is essential to use "symbol = sym" to assign to symbol
+ TIntermSymbol(int i, const TString& sym, const TType& t) :
+ TIntermTyped(t), id(i) { symbol = sym; originalSymbol = sym; }
+
+ virtual bool hasSideEffects() const { return false; }
+
+ int getId() const { return id; }
+ const TString& getSymbol() const { return symbol; }
+
+ void setId(int newId) { id = newId; }
+ void setSymbol(const TString& sym) { symbol = sym; }
+
+ const TString& getOriginalSymbol() const { return originalSymbol; }
+
+ virtual void traverse(TIntermTraverser*);
+ virtual TIntermSymbol* getAsSymbolNode() { return this; }
+ virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; }
+
+protected:
+ int id;
+ TString symbol;
+ TString originalSymbol;
+};
+
+class TIntermConstantUnion : public TIntermTyped {
+public:
+ TIntermConstantUnion(ConstantUnion *unionPointer, const TType& t) : TIntermTyped(t), unionArrayPointer(unionPointer) { }
+
+ virtual bool hasSideEffects() const { return false; }
+
+ ConstantUnion* getUnionArrayPointer() const { return unionArrayPointer; }
+
+ int getIConst(size_t index) const { return unionArrayPointer ? unionArrayPointer[index].getIConst() : 0; }
+ float getFConst(size_t index) const { return unionArrayPointer ? unionArrayPointer[index].getFConst() : 0.0f; }
+ bool getBConst(size_t index) const { return unionArrayPointer ? unionArrayPointer[index].getBConst() : false; }
+
+ virtual TIntermConstantUnion* getAsConstantUnion() { return this; }
+ virtual void traverse(TIntermTraverser*);
+ virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; }
+
+ TIntermTyped* fold(TOperator, TIntermTyped*, TInfoSink&);
+
+protected:
+ ConstantUnion *unionArrayPointer;
+};
+
+//
+// Intermediate class for node types that hold operators.
+//
+class TIntermOperator : public TIntermTyped {
+public:
+ TOperator getOp() const { return op; }
+ void setOp(TOperator o) { op = o; }
+
+ bool isAssignment() const;
+ bool isConstructor() const;
+
+ virtual bool hasSideEffects() const { return isAssignment(); }
+
+protected:
+ TIntermOperator(TOperator o) : TIntermTyped(TType(EbtFloat, EbpUndefined)), op(o) {}
+ TIntermOperator(TOperator o, const TType& t) : TIntermTyped(t), op(o) {}
+ TOperator op;
+};
+
+//
+// Nodes for all the basic binary math operators.
+//
+class TIntermBinary : public TIntermOperator {
+public:
+ TIntermBinary(TOperator o) : TIntermOperator(o), addIndexClamp(false) {}
+
+ virtual TIntermBinary* getAsBinaryNode() { return this; }
+ virtual void traverse(TIntermTraverser*);
+ virtual bool replaceChildNode(
+ TIntermNode *original, TIntermNode *replacement);
+
+ virtual bool hasSideEffects() const { return (isAssignment() || left->hasSideEffects() || right->hasSideEffects()); }
+
+ void setLeft(TIntermTyped* n) { left = n; }
+ void setRight(TIntermTyped* n) { right = n; }
+ TIntermTyped* getLeft() const { return left; }
+ TIntermTyped* getRight() const { return right; }
+ bool promote(TInfoSink&);
+
+ void setAddIndexClamp() { addIndexClamp = true; }
+ bool getAddIndexClamp() { return addIndexClamp; }
+
+protected:
+ TIntermTyped* left;
+ TIntermTyped* right;
+
+ // If set to true, wrap any EOpIndexIndirect with a clamp to bounds.
+ bool addIndexClamp;
+};
+
+//
+// Nodes for unary math operators.
+//
+class TIntermUnary : public TIntermOperator {
+public:
+ TIntermUnary(TOperator o, const TType& t) : TIntermOperator(o, t), operand(0), useEmulatedFunction(false) {}
+ TIntermUnary(TOperator o) : TIntermOperator(o), operand(0), useEmulatedFunction(false) {}
+
+ virtual void traverse(TIntermTraverser*);
+ virtual TIntermUnary* getAsUnaryNode() { return this; }
+ virtual bool replaceChildNode(
+ TIntermNode *original, TIntermNode *replacement);
+
+ virtual bool hasSideEffects() const { return (isAssignment() || operand->hasSideEffects()); }
+
+ void setOperand(TIntermTyped* o) { operand = o; }
+ TIntermTyped* getOperand() { return operand; }
+ bool promote(TInfoSink&);
+
+ void setUseEmulatedFunction() { useEmulatedFunction = true; }
+ bool getUseEmulatedFunction() { return useEmulatedFunction; }
+
+protected:
+ TIntermTyped* operand;
+
+ // If set to true, replace the built-in function call with an emulated one
+ // to work around driver bugs.
+ bool useEmulatedFunction;
+};
+
+typedef TVector<TIntermNode*> TIntermSequence;
+typedef TVector<int> TQualifierList;
+
+//
+// Nodes that operate on an arbitrary sized set of children.
+//
+class TIntermAggregate : public TIntermOperator {
+public:
+ TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), useEmulatedFunction(false) { }
+ TIntermAggregate(TOperator o) : TIntermOperator(o), useEmulatedFunction(false) { }
+ ~TIntermAggregate() { }
+
+ virtual TIntermAggregate* getAsAggregate() { return this; }
+ virtual void traverse(TIntermTraverser*);
+ virtual bool replaceChildNode(
+ TIntermNode *original, TIntermNode *replacement);
+
+ // Conservatively assume function calls and other aggregate operators have side-effects
+ virtual bool hasSideEffects() const { return true; }
+
+ TIntermSequence& getSequence() { return sequence; }
+
+ void setName(const TString& n) { name = n; }
+ const TString& getName() const { return name; }
+
+ void setUserDefined() { userDefined = true; }
+ bool isUserDefined() const { return userDefined; }
+
+ void setOptimize(bool o) { optimize = o; }
+ bool getOptimize() { return optimize; }
+ void setDebug(bool d) { debug = d; }
+ bool getDebug() { return debug; }
+
+ void setUseEmulatedFunction() { useEmulatedFunction = true; }
+ bool getUseEmulatedFunction() { return useEmulatedFunction; }
+
+protected:
+ TIntermAggregate(const TIntermAggregate&); // disallow copy constructor
+ TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator
+ TIntermSequence sequence;
+ TString name;
+ bool userDefined; // used for user defined function names
+
+ bool optimize;
+ bool debug;
+
+ // If set to true, replace the built-in function call with an emulated one
+ // to work around driver bugs.
+ bool useEmulatedFunction;
+};
+
+//
+// For if tests. Simplified since there is no switch statement.
+//
+class TIntermSelection : public TIntermTyped {
+public:
+ TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB) :
+ TIntermTyped(TType(EbtVoid, EbpUndefined)), condition(cond), trueBlock(trueB), falseBlock(falseB) {}
+ TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB, const TType& type) :
+ TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB) {}
+
+ virtual void traverse(TIntermTraverser*);
+ virtual bool replaceChildNode(
+ TIntermNode *original, TIntermNode *replacement);
+
+ // Conservatively assume selections have side-effects
+ virtual bool hasSideEffects() const { return true; }
+
+ bool usesTernaryOperator() const { return getBasicType() != EbtVoid; }
+ TIntermNode* getCondition() const { return condition; }
+ TIntermNode* getTrueBlock() const { return trueBlock; }
+ TIntermNode* getFalseBlock() const { return falseBlock; }
+ TIntermSelection* getAsSelectionNode() { return this; }
+
+protected:
+ TIntermTyped* condition;
+ TIntermNode* trueBlock;
+ TIntermNode* falseBlock;
+};
+
+enum Visit
+{
+ PreVisit,
+ InVisit,
+ PostVisit
+};
+
+//
+// For traversing the tree. User should derive from this,
+// put their traversal specific data in it, and then pass
+// it to a Traverse method.
+//
+// When using this, just fill in the methods for nodes you want visited.
+// Return false from a pre-visit to skip visiting that node's subtree.
+//
+class TIntermTraverser
+{
+public:
+ POOL_ALLOCATOR_NEW_DELETE();
+ TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, bool rightToLeft = false) :
+ preVisit(preVisit),
+ inVisit(inVisit),
+ postVisit(postVisit),
+ rightToLeft(rightToLeft),
+ depth(0),
+ maxDepth(0) {}
+ virtual ~TIntermTraverser() {}
+
+ virtual void visitSymbol(TIntermSymbol*) {}
+ virtual void visitConstantUnion(TIntermConstantUnion*) {}
+ virtual bool visitBinary(Visit visit, TIntermBinary*) {return true;}
+ virtual bool visitUnary(Visit visit, TIntermUnary*) {return true;}
+ virtual bool visitSelection(Visit visit, TIntermSelection*) {return true;}
+ virtual bool visitAggregate(Visit visit, TIntermAggregate*) {return true;}
+ virtual bool visitLoop(Visit visit, TIntermLoop*) {return true;}
+ virtual bool visitBranch(Visit visit, TIntermBranch*) {return true;}
+
+ int getMaxDepth() const {return maxDepth;}
+
+ void incrementDepth(TIntermNode *current)
+ {
+ depth++;
+ maxDepth = std::max(maxDepth, depth);
+ path.push_back(current);
+ }
+
+ void decrementDepth()
+ {
+ depth--;
+ path.pop_back();
+ }
+
+ TIntermNode *getParentNode()
+ {
+ return path.size() == 0 ? NULL : path.back();
+ }
+
+ // Return the original name if hash function pointer is NULL;
+ // otherwise return the hashed name.
+ static TString hash(const TString& name, ShHashFunction64 hashFunction);
+
+ const bool preVisit;
+ const bool inVisit;
+ const bool postVisit;
+ const bool rightToLeft;
+
+protected:
+ int depth;
+ int maxDepth;
+
+ // All the nodes from root to the current node's parent during traversing.
+ TVector<TIntermNode *> path;
+};
+
+#endif // __INTERMEDIATE_H
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/intermediate.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorlocalintermediateh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/localintermediate.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/localintermediate.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/localintermediate.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,57 @@
</span><ins>+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef _LOCAL_INTERMEDIATE_INCLUDED_
+#define _LOCAL_INTERMEDIATE_INCLUDED_
+
+#include "GLSLANG/ShaderLang.h"
+#include "compiler/translator/intermediate.h"
+#include "compiler/translator/SymbolTable.h"
+
+struct TVectorFields {
+ int offsets[4];
+ int num;
+};
+
+//
+// Set of helper functions to help parse and build the tree.
+//
+class TInfoSink;
+class TIntermediate {
+public:
+ POOL_ALLOCATOR_NEW_DELETE();
+ TIntermediate(TInfoSink& i) : infoSink(i) { }
+
+ TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TSourceLoc&);
+ TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*);
+ TIntermTyped* addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&, TSymbolTable&);
+ TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&);
+ TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, const TSourceLoc&);
+ TIntermTyped* addUnaryMath(TOperator op, TIntermNode* child, const TSourceLoc&, TSymbolTable&);
+ TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc&);
+ TIntermAggregate* makeAggregate(TIntermNode* node, const TSourceLoc&);
+ TIntermAggregate* setAggregateOperator(TIntermNode*, TOperator, const TSourceLoc&);
+ TIntermNode* addSelection(TIntermTyped* cond, TIntermNodePair code, const TSourceLoc&);
+ TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc&);
+ TIntermTyped* addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc&);
+ TIntermConstantUnion* addConstantUnion(ConstantUnion*, const TType&, const TSourceLoc&);
+ TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) ;
+ bool parseConstTree(const TSourceLoc&, TIntermNode*, ConstantUnion*, TOperator, TSymbolTable&, TType, bool singleConstantParam = false);
+ TIntermNode* addLoop(TLoopType, TIntermNode*, TIntermTyped*, TIntermTyped*, TIntermNode*, const TSourceLoc&);
+ TIntermBranch* addBranch(TOperator, const TSourceLoc&);
+ TIntermBranch* addBranch(TOperator, TIntermTyped*, const TSourceLoc&);
+ TIntermTyped* addSwizzle(TVectorFields&, const TSourceLoc&);
+ bool postProcess(TIntermNode*);
+ void remove(TIntermNode*);
+ void outputTree(TIntermNode*);
+
+private:
+ void operator=(TIntermediate&); // prevent assignments
+
+ TInfoSink& infoSink;
+};
+
+#endif // _LOCAL_INTERMEDIATE_INCLUDED_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/localintermediate.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorosincludeh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/osinclude.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/osinclude.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/osinclude.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,66 @@
</span><ins>+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef __OSINCLUDE_H
+#define __OSINCLUDE_H
+
+//
+// This file contains contains os-specific datatypes and
+// declares any os-specific functions.
+//
+
+#if defined(_WIN32) || defined(_WIN64)
+#define ANGLE_OS_WIN
+#elif defined(__APPLE__) || defined(__linux__) || \
+ defined(__FreeBSD__) || defined(__OpenBSD__) || \
+ defined(__NetBSD__) || defined(__DragonFly__) || \
+ defined(__sun) || defined(ANDROID) || \
+ defined(__GLIBC__) || defined(__GNU__) || \
+ defined(__QNX__)
+#define ANGLE_OS_POSIX
+#else
+#error Unsupported platform.
+#endif
+
+#if defined(ANGLE_OS_WIN)
+#define STRICT
+#define VC_EXTRALEAN 1
+#include <windows.h>
+#elif defined(ANGLE_OS_POSIX)
+#include <pthread.h>
+#include <semaphore.h>
+#include <errno.h>
+#endif // ANGLE_OS_WIN
+
+
+#include "compiler/translator/compilerdebug.h"
+
+//
+// Thread Local Storage Operations
+//
+#if defined(ANGLE_OS_WIN)
+typedef DWORD OS_TLSIndex;
+#define OS_INVALID_TLS_INDEX (TLS_OUT_OF_INDEXES)
+#elif defined(ANGLE_OS_POSIX)
+typedef pthread_key_t OS_TLSIndex;
+#define OS_INVALID_TLS_INDEX (static_cast<OS_TLSIndex>(-1))
+#endif // ANGLE_OS_WIN
+
+OS_TLSIndex OS_AllocTLSIndex();
+bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue);
+bool OS_FreeTLSIndex(OS_TLSIndex nIndex);
+
+inline void* OS_GetTLSValue(OS_TLSIndex nIndex)
+{
+ ASSERT(nIndex != OS_INVALID_TLS_INDEX);
+#if defined(ANGLE_OS_WIN)
+ return TlsGetValue(nIndex);
+#elif defined(ANGLE_OS_POSIX)
+ return pthread_getspecific(nIndex);
+#endif // ANGLE_OS_WIN
+}
+
+#endif // __OSINCLUDE_H
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/osinclude.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorossource_posixcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ossource_posix.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ossource_posix.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ossource_posix.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,64 @@
</span><ins>+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+//
+// This file contains the posix specific functions
+//
+#include "compiler/translator/osinclude.h"
+
+#if !defined(ANGLE_OS_POSIX)
+#error Trying to build a posix specific file in a non-posix build.
+#endif
+
+//
+// Thread Local Storage Operations
+//
+OS_TLSIndex OS_AllocTLSIndex()
+{
+ pthread_key_t pPoolIndex;
+
+ //
+ // Create global pool key.
+ //
+ if ((pthread_key_create(&pPoolIndex, NULL)) != 0) {
+ assert(0 && "OS_AllocTLSIndex(): Unable to allocate Thread Local Storage");
+ return false;
+ }
+ else {
+ return pPoolIndex;
+ }
+}
+
+
+bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue)
+{
+ if (nIndex == OS_INVALID_TLS_INDEX) {
+ assert(0 && "OS_SetTLSValue(): Invalid TLS Index");
+ return false;
+ }
+
+ if (pthread_setspecific(nIndex, lpvValue) == 0)
+ return true;
+ else
+ return false;
+}
+
+
+bool OS_FreeTLSIndex(OS_TLSIndex nIndex)
+{
+ if (nIndex == OS_INVALID_TLS_INDEX) {
+ assert(0 && "OS_SetTLSValue(): Invalid TLS Index");
+ return false;
+ }
+
+ //
+ // Delete the global pool key.
+ //
+ if (pthread_key_delete(nIndex) == 0)
+ return true;
+ else
+ return false;
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ossource_posix.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorossource_wincpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ossource_win.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ossource_win.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ossource_win.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,57 @@
</span><ins>+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/osinclude.h"
+//
+// This file contains contains the window's specific functions
+//
+
+#if !defined(ANGLE_OS_WIN)
+#error Trying to build a windows specific file in a non windows build.
+#endif
+
+
+//
+// Thread Local Storage Operations
+//
+OS_TLSIndex OS_AllocTLSIndex()
+{
+ DWORD dwIndex = TlsAlloc();
+ if (dwIndex == TLS_OUT_OF_INDEXES) {
+ assert(0 && "OS_AllocTLSIndex(): Unable to allocate Thread Local Storage");
+ return OS_INVALID_TLS_INDEX;
+ }
+
+ return dwIndex;
+}
+
+
+bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue)
+{
+ if (nIndex == OS_INVALID_TLS_INDEX) {
+ assert(0 && "OS_SetTLSValue(): Invalid TLS Index");
+ return false;
+ }
+
+ if (TlsSetValue(nIndex, lpvValue))
+ return true;
+ else
+ return false;
+}
+
+
+bool OS_FreeTLSIndex(OS_TLSIndex nIndex)
+{
+ if (nIndex == OS_INVALID_TLS_INDEX) {
+ assert(0 && "OS_SetTLSValue(): Invalid TLS Index");
+ return false;
+ }
+
+ if (TlsFree(nIndex))
+ return true;
+ else
+ return false;
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/ossource_win.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorparseConstcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/parseConst.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/parseConst.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/parseConst.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,245 @@
</span><ins>+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/ParseContext.h"
+
+//
+// Use this class to carry along data from node to node in
+// the traversal
+//
+class TConstTraverser : public TIntermTraverser {
+public:
+ TConstTraverser(ConstantUnion* cUnion, bool singleConstParam, TOperator constructType, TInfoSink& sink, TSymbolTable& symTable, TType& t)
+ : error(false),
+ index(0),
+ unionArray(cUnion),
+ type(t),
+ constructorType(constructType),
+ singleConstantParam(singleConstParam),
+ infoSink(sink),
+ symbolTable(symTable),
+ size(0),
+ isMatrix(false),
+ matrixSize(0) {
+ }
+
+ bool error;
+
+protected:
+ void visitSymbol(TIntermSymbol*);
+ void visitConstantUnion(TIntermConstantUnion*);
+ bool visitBinary(Visit visit, TIntermBinary*);
+ bool visitUnary(Visit visit, TIntermUnary*);
+ bool visitSelection(Visit visit, TIntermSelection*);
+ bool visitAggregate(Visit visit, TIntermAggregate*);
+ bool visitLoop(Visit visit, TIntermLoop*);
+ bool visitBranch(Visit visit, TIntermBranch*);
+
+ size_t index;
+ ConstantUnion *unionArray;
+ TType type;
+ TOperator constructorType;
+ bool singleConstantParam;
+ TInfoSink& infoSink;
+ TSymbolTable& symbolTable;
+ size_t size; // size of the constructor ( 4 for vec4)
+ bool isMatrix;
+ size_t matrixSize; // dimension of the matrix (nominal size and not the instance size)
+};
+
+//
+// The rest of the file are the traversal functions. The last one
+// is the one that starts the traversal.
+//
+// Return true from interior nodes to have the external traversal
+// continue on to children. If you process children yourself,
+// return false.
+//
+
+void TConstTraverser::visitSymbol(TIntermSymbol* node)
+{
+ infoSink.info.message(EPrefixInternalError, node->getLine(), "Symbol Node found in constant constructor");
+ return;
+
+}
+
+bool TConstTraverser::visitBinary(Visit visit, TIntermBinary* node)
+{
+ TQualifier qualifier = node->getType().getQualifier();
+
+ if (qualifier != EvqConst) {
+ TString buf;
+ buf.append("'constructor' : assigning non-constant to ");
+ buf.append(type.getCompleteString());
+ infoSink.info.message(EPrefixError, node->getLine(), buf.c_str());
+ error = true;
+ return false;
+ }
+
+ infoSink.info.message(EPrefixInternalError, node->getLine(), "Binary Node found in constant constructor");
+
+ return false;
+}
+
+bool TConstTraverser::visitUnary(Visit visit, TIntermUnary* node)
+{
+ TString buf;
+ buf.append("'constructor' : assigning non-constant to ");
+ buf.append(type.getCompleteString());
+ infoSink.info.message(EPrefixError, node->getLine(), buf.c_str());
+ error = true;
+ return false;
+}
+
+bool TConstTraverser::visitAggregate(Visit visit, TIntermAggregate* node)
+{
+ if (!node->isConstructor() && node->getOp() != EOpComma) {
+ TString buf;
+ buf.append("'constructor' : assigning non-constant to ");
+ buf.append(type.getCompleteString());
+ infoSink.info.message(EPrefixError, node->getLine(), buf.c_str());
+ error = true;
+ return false;
+ }
+
+ if (node->getSequence().size() == 0) {
+ error = true;
+ return false;
+ }
+
+ bool flag = node->getSequence().size() == 1 && node->getSequence()[0]->getAsTyped()->getAsConstantUnion();
+ if (flag)
+ {
+ singleConstantParam = true;
+ constructorType = node->getOp();
+ size = node->getType().getObjectSize();
+
+ if (node->getType().isMatrix()) {
+ isMatrix = true;
+ matrixSize = node->getType().getNominalSize();
+ }
+ }
+
+ for (TIntermSequence::iterator p = node->getSequence().begin();
+ p != node->getSequence().end(); p++) {
+
+ if (node->getOp() == EOpComma)
+ index = 0;
+
+ (*p)->traverse(this);
+ }
+ if (flag)
+ {
+ singleConstantParam = false;
+ constructorType = EOpNull;
+ size = 0;
+ isMatrix = false;
+ matrixSize = 0;
+ }
+ return false;
+}
+
+bool TConstTraverser::visitSelection(Visit visit, TIntermSelection* node)
+{
+ infoSink.info.message(EPrefixInternalError, node->getLine(), "Selection Node found in constant constructor");
+ error = true;
+ return false;
+}
+
+void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node)
+{
+ if (!node->getUnionArrayPointer())
+ {
+ // The constant was not initialized, this should already have been logged
+ assert(infoSink.info.size() != 0);
+ return;
+ }
+
+ ConstantUnion* leftUnionArray = unionArray;
+ size_t instanceSize = type.getObjectSize();
+
+ if (index >= instanceSize)
+ return;
+
+ if (!singleConstantParam) {
+ size_t size = node->getType().getObjectSize();
+
+ ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
+ for (size_t i = 0; i < size; i++) {
+ if (index >= instanceSize)
+ return;
+ leftUnionArray[index] = rightUnionArray[i];
+
+ (index)++;
+ }
+ } else {
+ size_t totalSize = index + size;
+ ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
+ if (!isMatrix) {
+ size_t count = 0;
+ for (size_t i = index; i < totalSize; i++) {
+ if (i >= instanceSize)
+ return;
+
+ leftUnionArray[i] = rightUnionArray[count];
+
+ (index)++;
+
+ if (node->getType().getObjectSize() > 1)
+ count++;
+ }
+ } else { // for matrix constructors
+ size_t count = 0;
+ size_t element = index;
+ for (size_t i = index; i < totalSize; i++) {
+ if (i >= instanceSize)
+ return;
+ if (element - i == 0 || (i - element) % (matrixSize + 1) == 0 )
+ leftUnionArray[i] = rightUnionArray[count];
+ else
+ leftUnionArray[i].setFConst(0.0f);
+
+ (index)++;
+
+ if (node->getType().getObjectSize() > 1)
+ count++;
+ }
+ }
+ }
+}
+
+bool TConstTraverser::visitLoop(Visit visit, TIntermLoop* node)
+{
+ infoSink.info.message(EPrefixInternalError, node->getLine(), "Loop Node found in constant constructor");
+ error = true;
+ return false;
+}
+
+bool TConstTraverser::visitBranch(Visit visit, TIntermBranch* node)
+{
+ infoSink.info.message(EPrefixInternalError, node->getLine(), "Branch Node found in constant constructor");
+ error = true;
+ return false;
+}
+
+//
+// This function is the one to call externally to start the traversal.
+// Individual functions can be initialized to 0 to skip processing of that
+// type of node. It's children will still be processed.
+//
+bool TIntermediate::parseConstTree(const TSourceLoc& line, TIntermNode* root, ConstantUnion* unionArray, TOperator constructorType, TSymbolTable& symbolTable, TType t, bool singleConstantParam)
+{
+ if (root == 0)
+ return false;
+
+ TConstTraverser it(unionArray, singleConstantParam, constructorType, infoSink, symbolTable, t);
+
+ root->traverse(&it);
+ if (it.error)
+ return true;
+ else
+ return false;
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/parseConst.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatortimingRestrictFragmentShaderTimingcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/timing/RestrictFragmentShaderTiming.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/timing/RestrictFragmentShaderTiming.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/timing/RestrictFragmentShaderTiming.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,127 @@
</span><ins>+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/InfoSink.h"
+#include "compiler/translator/ParseContext.h"
+#include "compiler/translator/depgraph/DependencyGraphOutput.h"
+#include "compiler/translator/timing/RestrictFragmentShaderTiming.h"
+
+RestrictFragmentShaderTiming::RestrictFragmentShaderTiming(TInfoSinkBase& sink)
+ : mSink(sink)
+ , mNumErrors(0)
+{
+ // Sampling ops found only in fragment shaders.
+ mSamplingOps.insert("texture2D(s21;vf2;f1;");
+ mSamplingOps.insert("texture2DProj(s21;vf3;f1;");
+ mSamplingOps.insert("texture2DProj(s21;vf4;f1;");
+ mSamplingOps.insert("textureCube(sC1;vf3;f1;");
+ // Sampling ops found in both vertex and fragment shaders.
+ mSamplingOps.insert("texture2D(s21;vf2;");
+ mSamplingOps.insert("texture2DProj(s21;vf3;");
+ mSamplingOps.insert("texture2DProj(s21;vf4;");
+ mSamplingOps.insert("textureCube(sC1;vf3;");
+ // Sampling ops provided by OES_EGL_image_external.
+ mSamplingOps.insert("texture2D(1;vf2;");
+ mSamplingOps.insert("texture2DProj(1;vf3;");
+ mSamplingOps.insert("texture2DProj(1;vf4;");
+ // Sampling ops provided by ARB_texture_rectangle.
+ mSamplingOps.insert("texture2DRect(1;vf2;");
+ mSamplingOps.insert("texture2DRectProj(1;vf3;");
+ mSamplingOps.insert("texture2DRectProj(1;vf4;");
+}
+
+// FIXME(mvujovic): We do not know if the execution time of built-in operations like sin, pow, etc.
+// can vary based on the value of the input arguments. If so, we should restrict those as well.
+void RestrictFragmentShaderTiming::enforceRestrictions(const TDependencyGraph& graph)
+{
+ mNumErrors = 0;
+
+ // FIXME(mvujovic): The dependency graph does not support user defined function calls right now,
+ // so we generate errors for them.
+ validateUserDefinedFunctionCallUsage(graph);
+
+ // Starting from each sampler, traverse the dependency graph and generate an error each time we
+ // hit a node where sampler dependent values are not allowed.
+ for (TGraphSymbolVector::const_iterator iter = graph.beginSamplerSymbols();
+ iter != graph.endSamplerSymbols();
+ ++iter)
+ {
+ TGraphSymbol* samplerSymbol = *iter;
+ clearVisited();
+ samplerSymbol->traverse(this);
+ }
+}
+
+void RestrictFragmentShaderTiming::validateUserDefinedFunctionCallUsage(const TDependencyGraph& graph)
+{
+ for (TFunctionCallVector::const_iterator iter = graph.beginUserDefinedFunctionCalls();
+ iter != graph.endUserDefinedFunctionCalls();
+ ++iter)
+ {
+ TGraphFunctionCall* functionCall = *iter;
+ beginError(functionCall->getIntermFunctionCall());
+ mSink << "A call to a user defined function is not permitted.\n";
+ }
+}
+
+void RestrictFragmentShaderTiming::beginError(const TIntermNode* node)
+{
+ ++mNumErrors;
+ mSink.prefix(EPrefixError);
+ mSink.location(node->getLine());
+}
+
+bool RestrictFragmentShaderTiming::isSamplingOp(const TIntermAggregate* intermFunctionCall) const
+{
+ return !intermFunctionCall->isUserDefined() &&
+ mSamplingOps.find(intermFunctionCall->getName()) != mSamplingOps.end();
+}
+
+void RestrictFragmentShaderTiming::visitArgument(TGraphArgument* parameter)
+{
+ // Texture cache access time might leak sensitive information.
+ // Thus, we restrict sampler dependent values from affecting the coordinate or LOD bias of a
+ // sampling operation.
+ if (isSamplingOp(parameter->getIntermFunctionCall())) {
+ switch (parameter->getArgumentNumber()) {
+ case 1:
+ // Second argument (coord)
+ beginError(parameter->getIntermFunctionCall());
+ mSink << "An expression dependent on a sampler is not permitted to be the"
+ << " coordinate argument of a sampling operation.\n";
+ break;
+ case 2:
+ // Third argument (bias)
+ beginError(parameter->getIntermFunctionCall());
+ mSink << "An expression dependent on a sampler is not permitted to be the"
+ << " bias argument of a sampling operation.\n";
+ break;
+ default:
+ // First argument (sampler)
+ break;
+ }
+ }
+}
+
+void RestrictFragmentShaderTiming::visitSelection(TGraphSelection* selection)
+{
+ beginError(selection->getIntermSelection());
+ mSink << "An expression dependent on a sampler is not permitted in a conditional statement.\n";
+}
+
+void RestrictFragmentShaderTiming::visitLoop(TGraphLoop* loop)
+{
+ beginError(loop->getIntermLoop());
+ mSink << "An expression dependent on a sampler is not permitted in a loop condition.\n";
+}
+
+void RestrictFragmentShaderTiming::visitLogicalOp(TGraphLogicalOp* logicalOp)
+{
+ beginError(logicalOp->getIntermLogicalOp());
+ mSink << "An expression dependent on a sampler is not permitted on the left hand side of a logical "
+ << logicalOp->getOpString()
+ << " operator.\n";
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/timing/RestrictFragmentShaderTiming.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatortimingRestrictFragmentShaderTimingh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/timing/RestrictFragmentShaderTiming.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/timing/RestrictFragmentShaderTiming.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/timing/RestrictFragmentShaderTiming.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,40 @@
</span><ins>+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TIMING_RESTRICT_FRAGMENT_SHADER_TIMING_H_
+#define COMPILER_TIMING_RESTRICT_FRAGMENT_SHADER_TIMING_H_
+
+#include "GLSLANG/ShaderLang.h"
+
+#include "compiler/translator/intermediate.h"
+#include "compiler/translator/depgraph/DependencyGraph.h"
+
+class TInfoSinkBase;
+
+class RestrictFragmentShaderTiming : TDependencyGraphTraverser {
+public:
+ RestrictFragmentShaderTiming(TInfoSinkBase& sink);
+ void enforceRestrictions(const TDependencyGraph& graph);
+ int numErrors() const { return mNumErrors; }
+
+ virtual void visitArgument(TGraphArgument* parameter);
+ virtual void visitSelection(TGraphSelection* selection);
+ virtual void visitLoop(TGraphLoop* loop);
+ virtual void visitLogicalOp(TGraphLogicalOp* logicalOp);
+
+private:
+ void beginError(const TIntermNode* node);
+ void validateUserDefinedFunctionCallUsage(const TDependencyGraph& graph);
+ bool isSamplingOp(const TIntermAggregate* intermFunctionCall) const;
+
+ TInfoSinkBase& mSink;
+ int mNumErrors;
+
+ typedef std::set<TString> StringSet;
+ StringSet mSamplingOps;
+};
+
+#endif // COMPILER_TIMING_RESTRICT_FRAGMENT_SHADER_TIMING_H_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/timing/RestrictFragmentShaderTiming.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatortimingRestrictVertexShaderTimingcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/timing/RestrictVertexShaderTiming.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/timing/RestrictVertexShaderTiming.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/timing/RestrictVertexShaderTiming.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,17 @@
</span><ins>+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/timing/RestrictVertexShaderTiming.h"
+
+void RestrictVertexShaderTiming::visitSymbol(TIntermSymbol* node)
+{
+ if (IsSampler(node->getBasicType())) {
+ ++mNumErrors;
+ mSink.message(EPrefixError,
+ node->getLine(),
+ "Samplers are not permitted in vertex shaders");
+ }
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/timing/RestrictVertexShaderTiming.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatortimingRestrictVertexShaderTimingh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/timing/RestrictVertexShaderTiming.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/timing/RestrictVertexShaderTiming.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/timing/RestrictVertexShaderTiming.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,33 @@
</span><ins>+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TIMING_RESTRICT_VERTEX_SHADER_TIMING_H_
+#define COMPILER_TIMING_RESTRICT_VERTEX_SHADER_TIMING_H_
+
+#include "GLSLANG/ShaderLang.h"
+
+#include "compiler/translator/intermediate.h"
+#include "compiler/translator/InfoSink.h"
+
+class TInfoSinkBase;
+
+class RestrictVertexShaderTiming : public TIntermTraverser {
+public:
+ RestrictVertexShaderTiming(TInfoSinkBase& sink)
+ : TIntermTraverser(true, false, false)
+ , mSink(sink)
+ , mNumErrors(0) {}
+
+ void enforceRestrictions(TIntermNode* root) { root->traverse(this); }
+ int numErrors() { return mNumErrors; }
+
+ virtual void visitSymbol(TIntermSymbol*);
+private:
+ TInfoSinkBase& mSink;
+ int mNumErrors;
+};
+
+#endif // COMPILER_TIMING_RESTRICT_VERTEX_SHADER_TIMING_H_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/timing/RestrictVertexShaderTiming.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorutilcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/util.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/util.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/util.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,28 @@
</span><ins>+//
+// Copyright (c) 2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/util.h"
+
+#include <limits>
+
+#include "compiler/preprocessor/numeric_lex.h"
+
+bool atof_clamp(const char *str, float *value)
+{
+ bool success = pp::numeric_lex_float(str, value);
+ if (!success)
+ *value = std::numeric_limits<float>::max();
+ return success;
+}
+
+bool atoi_clamp(const char *str, int *value)
+{
+ bool success = pp::numeric_lex_int(str, value);
+ if (!success)
+ *value = std::numeric_limits<int>::max();
+ return success;
+}
+
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/util.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrccompilertranslatorutilh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/util.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/compiler/translator/util.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/compiler/translator/util.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,20 @@
</span><ins>+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_UTIL_H
+#define COMPILER_UTIL_H
+
+// atof_clamp is like atof but
+// 1. it forces C locale, i.e. forcing '.' as decimal point.
+// 2. it clamps the value to -FLT_MAX or FLT_MAX if overflow happens.
+// Return false if overflow happens.
+extern bool atof_clamp(const char *str, float *value);
+
+// If overflow happens, clamp the value to INT_MIN or INT_MAX.
+// Return false if overflow happens.
+extern bool atoi_clamp(const char *str, int *value);
+
+#endif // COMPILER_UTIL_H
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/compiler/translator/util.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11BufferStorage11cpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/BufferStorage11.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/BufferStorage11.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/BufferStorage11.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,366 @@
</span><ins>+#include "precompiled.h"
+//
+// Copyright (c) 2013 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.
+//
+
+// BufferStorage11.cpp Defines the BufferStorage11 class.
+
+#include "libGLESv2/renderer/d3d11/BufferStorage11.h"
+#include "libGLESv2/main.h"
+#include "libGLESv2/renderer/d3d11/Renderer11.h"
+
+namespace rx
+{
+
+BufferStorage11::BufferStorage11(Renderer11 *renderer)
+{
+ mRenderer = renderer;
+
+ mStagingBuffer = NULL;
+ mStagingBufferSize = 0;
+
+ mSize = 0;
+
+ mResolvedData = NULL;
+ mResolvedDataSize = 0;
+ mResolvedDataValid = false;
+
+ mReadUsageCount = 0;
+ mWriteUsageCount = 0;
+}
+
+BufferStorage11::~BufferStorage11()
+{
+ SafeRelease(mStagingBuffer);
+
+ if (mResolvedData)
+ {
+ free(mResolvedData);
+ mResolvedData = NULL;
+ }
+
+ for (auto it = mDirectBuffers.begin(); it != mDirectBuffers.end(); it++)
+ {
+ SafeDelete(it->second);
+ }
+}
+
+BufferStorage11 *BufferStorage11::makeBufferStorage11(BufferStorage *bufferStorage)
+{
+ ASSERT(HAS_DYNAMIC_TYPE(BufferStorage11*, bufferStorage));
+ return static_cast<BufferStorage11*>(bufferStorage);
+}
+
+void *BufferStorage11::getData()
+{
+ ASSERT(mStagingBuffer);
+
+ if (!mResolvedDataValid)
+ {
+ ID3D11Device *device = mRenderer->getDevice();
+ ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+ HRESULT result;
+
+ if (!mResolvedData || mResolvedDataSize < mStagingBufferSize)
+ {
+ free(mResolvedData);
+ mResolvedData = malloc(mSize);
+ mResolvedDataSize = mSize;
+ }
+
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ result = context->Map(mStagingBuffer, 0, D3D11_MAP_READ, 0, &mappedResource);
+ if (FAILED(result))
+ {
+ return gl::error(GL_OUT_OF_MEMORY, (void*)NULL);
+ }
+
+ memcpy(mResolvedData, mappedResource.pData, mSize);
+
+ context->Unmap(mStagingBuffer, 0);
+
+ mResolvedDataValid = true;
+ }
+
+ mReadUsageCount = 0;
+
+ return mResolvedData;
+}
+
+void BufferStorage11::setData(const void* data, unsigned int size, unsigned int offset)
+{
+ ID3D11Device *device = mRenderer->getDevice();
+ ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+ HRESULT result;
+
+ const unsigned int requiredStagingBufferSize = size + offset;
+ const bool createStagingBuffer = !mStagingBuffer || mStagingBufferSize < requiredStagingBufferSize;
+
+ if (createStagingBuffer)
+ {
+ D3D11_BUFFER_DESC bufferDesc;
+ bufferDesc.ByteWidth = requiredStagingBufferSize;
+ bufferDesc.Usage = D3D11_USAGE_STAGING;
+ bufferDesc.BindFlags = 0;
+ bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
+ bufferDesc.MiscFlags = 0;
+ bufferDesc.StructureByteStride = 0;
+
+ HRESULT result;
+ ID3D11Device *device = mRenderer->getDevice();
+ ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+ ID3D11Buffer *newStagingBuffer;
+
+ if (data && offset == 0)
+ {
+ D3D11_SUBRESOURCE_DATA initialData;
+ initialData.pSysMem = data;
+ initialData.SysMemPitch = requiredStagingBufferSize;
+ initialData.SysMemSlicePitch = 0;
+
+ result = device->CreateBuffer(&bufferDesc, &initialData, &newStagingBuffer);
+ }
+ else
+ {
+ result = device->CreateBuffer(&bufferDesc, NULL, &newStagingBuffer);
+ }
+
+ if (FAILED(result))
+ {
+ mStagingBufferSize = 0;
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+
+ mStagingBufferSize = requiredStagingBufferSize;
+
+ if (mStagingBuffer && offset > 0)
+ {
+ // If offset is greater than zero and the buffer is non-null, need to preserve the data from
+ // the old buffer up to offset
+ D3D11_BOX srcBox;
+ srcBox.left = 0;
+ srcBox.right = std::min(offset, requiredStagingBufferSize);
+ srcBox.top = 0;
+ srcBox.bottom = 1;
+ srcBox.front = 0;
+ srcBox.back = 1;
+
+ context->CopySubresourceRegion(newStagingBuffer, 0, 0, 0, 0, mStagingBuffer, 0, &srcBox);
+ }
+
+ SafeRelease(mStagingBuffer);
+ mStagingBuffer = newStagingBuffer;
+ }
+
+ if (data && (offset != 0 || !createStagingBuffer))
+ {
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ result = context->Map(mStagingBuffer, 0, D3D11_MAP_WRITE, 0, &mappedResource);
+ if (FAILED(result))
+ {
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+
+ unsigned char *offsetBufferPointer = reinterpret_cast<unsigned char *>(mappedResource.pData) + offset;
+ memcpy(offsetBufferPointer, data, size);
+
+ context->Unmap(mStagingBuffer, 0);
+ }
+
+ for (auto it = mDirectBuffers.begin(); it != mDirectBuffers.end(); it++)
+ {
+ it->second->markDirty();
+ }
+
+ mSize = std::max(mSize, requiredStagingBufferSize);
+ mWriteUsageCount = 0;
+
+ mResolvedDataValid = false;
+}
+
+void BufferStorage11::copyData(BufferStorage* sourceStorage, unsigned int size,
+ unsigned int sourceOffset, unsigned int destOffset)
+{
+ BufferStorage11* source = makeBufferStorage11(sourceStorage);
+ if (source)
+ {
+ ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+
+ D3D11_BOX srcBox;
+ srcBox.left = sourceOffset;
+ srcBox.right = sourceOffset + size;
+ srcBox.top = 0;
+ srcBox.bottom = 1;
+ srcBox.front = 0;
+ srcBox.back = 1;
+
+ ASSERT(mStagingBuffer && source->mStagingBuffer);
+ context->CopySubresourceRegion(mStagingBuffer, 0, destOffset, 0, 0, source->mStagingBuffer, 0, &srcBox);
+ }
+}
+
+void BufferStorage11::clear()
+{
+ mResolvedDataValid = false;
+ mSize = 0;
+}
+
+unsigned int BufferStorage11::getSize() const
+{
+ return mSize;
+}
+
+bool BufferStorage11::supportsDirectBinding() const
+{
+ return true;
+}
+
+void BufferStorage11::markBufferUsage()
+{
+ mReadUsageCount++;
+ mWriteUsageCount++;
+
+ const unsigned int usageLimit = 5;
+
+ if (mReadUsageCount > usageLimit && mResolvedData)
+ {
+ free(mResolvedData);
+ mResolvedData = NULL;
+ mResolvedDataSize = 0;
+ mResolvedDataValid = false;
+ }
+}
+
+ID3D11Buffer *BufferStorage11::getBuffer(BufferUsage usage)
+{
+ markBufferUsage();
+
+ DirectBufferStorage11 *directBuffer = NULL;
+
+ auto directBufferIt = mDirectBuffers.find(usage);
+ if (directBufferIt != mDirectBuffers.end())
+ {
+ directBuffer = directBufferIt->second;
+ }
+
+ if (directBuffer)
+ {
+ if (directBuffer->isDirty())
+ {
+ // if updateFromStagingBuffer returns true, the D3D buffer has been recreated
+ // and we should update our serial
+ if (directBuffer->updateFromStagingBuffer(mStagingBuffer, mSize, 0))
+ {
+ updateSerial();
+ }
+ }
+ }
+ else
+ {
+ // buffer is not allocated, create it
+ directBuffer = new DirectBufferStorage11(mRenderer, usage);
+ directBuffer->updateFromStagingBuffer(mStagingBuffer, mSize, 0);
+
+ mDirectBuffers.insert(std::make_pair(usage, directBuffer));
+ updateSerial();
+ }
+
+ return directBuffer->getD3DBuffer();
+}
+
+DirectBufferStorage11::DirectBufferStorage11(Renderer11 *renderer, BufferUsage usage)
+ : mRenderer(renderer),
+ mUsage(usage),
+ mDirectBuffer(NULL),
+ mBufferSize(0),
+ mDirty(false)
+{
+}
+
+DirectBufferStorage11::~DirectBufferStorage11()
+{
+ SafeRelease(mDirectBuffer);
+}
+
+BufferUsage DirectBufferStorage11::getUsage() const
+{
+ return mUsage;
+}
+
+// Returns true if it recreates the direct buffer
+bool DirectBufferStorage11::updateFromStagingBuffer(ID3D11Buffer *stagingBuffer, size_t size, size_t offset)
+{
+ ID3D11Device *device = mRenderer->getDevice();
+ ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+
+ // unused for now
+ ASSERT(offset == 0);
+
+ unsigned int requiredBufferSize = size + offset;
+ bool createBuffer = !mDirectBuffer || mBufferSize < requiredBufferSize;
+
+ // (Re)initialize D3D buffer if needed
+ if (createBuffer)
+ {
+ D3D11_BUFFER_DESC bufferDesc;
+ fillBufferDesc(&bufferDesc, mRenderer, mUsage, requiredBufferSize);
+
+ ID3D11Buffer *newBuffer;
+ HRESULT result = device->CreateBuffer(&bufferDesc, NULL, &newBuffer);
+
+ if (FAILED(result))
+ {
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ // No longer need the old buffer
+ SafeRelease(mDirectBuffer);
+ mDirectBuffer = newBuffer;
+
+ mBufferSize = bufferDesc.ByteWidth;
+ }
+
+ // Copy data via staging buffer
+ D3D11_BOX srcBox;
+ srcBox.left = 0;
+ srcBox.right = size;
+ srcBox.top = 0;
+ srcBox.bottom = 1;
+ srcBox.front = 0;
+ srcBox.back = 1;
+
+ context->CopySubresourceRegion(mDirectBuffer, 0, offset, 0, 0, stagingBuffer, 0, &srcBox);
+
+ mDirty = false;
+
+ return createBuffer;
+}
+
+void DirectBufferStorage11::fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Renderer *renderer, BufferUsage usage, unsigned int bufferSize)
+{
+ bufferDesc->ByteWidth = bufferSize;
+ bufferDesc->MiscFlags = 0;
+ bufferDesc->StructureByteStride = 0;
+
+ switch (usage)
+ {
+ case BUFFER_USAGE_VERTEX:
+ bufferDesc->Usage = D3D11_USAGE_DEFAULT;
+ bufferDesc->BindFlags = D3D11_BIND_VERTEX_BUFFER;
+ bufferDesc->CPUAccessFlags = 0;
+ break;
+
+ case BUFFER_USAGE_INDEX:
+ bufferDesc->Usage = D3D11_USAGE_DEFAULT;
+ bufferDesc->BindFlags = D3D11_BIND_INDEX_BUFFER;
+ bufferDesc->CPUAccessFlags = 0;
+ break;
+
+ default:
+ UNREACHABLE();
+ }
+}
+
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/BufferStorage11.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11BufferStorage11h"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/BufferStorage11.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/BufferStorage11.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/BufferStorage11.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,92 @@
</span><ins>+//
+// Copyright (c) 2013 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.
+//
+
+// BufferStorage11.h Defines the BufferStorage11 class.
+
+#ifndef LIBGLESV2_RENDERER_BUFFERSTORAGE11_H_
+#define LIBGLESV2_RENDERER_BUFFERSTORAGE11_H_
+
+#include "libGLESv2/renderer/BufferStorage.h"
+
+namespace rx
+{
+class Renderer;
+class Renderer11;
+class DirectBufferStorage11;
+
+enum BufferUsage
+{
+ BUFFER_USAGE_VERTEX,
+ BUFFER_USAGE_INDEX,
+};
+
+class BufferStorage11 : public BufferStorage
+{
+ public:
+ explicit BufferStorage11(Renderer11 *renderer);
+ virtual ~BufferStorage11();
+
+ static BufferStorage11 *makeBufferStorage11(BufferStorage *bufferStorage);
+
+ virtual void *getData();
+ virtual void setData(const void* data, unsigned int size, unsigned int offset);
+ virtual void copyData(BufferStorage* sourceStorage, unsigned int size,
+ unsigned int sourceOffset, unsigned int destOffset);
+ virtual void clear();
+ virtual unsigned int getSize() const;
+ virtual bool supportsDirectBinding() const;
+
+ ID3D11Buffer *getBuffer(BufferUsage usage);
+
+ private:
+ Renderer11 *mRenderer;
+
+ ID3D11Buffer *mStagingBuffer;
+ unsigned int mStagingBufferSize;
+
+ std::map<BufferUsage, DirectBufferStorage11*> mDirectBuffers;
+
+ unsigned int mSize;
+
+ void *mResolvedData;
+ unsigned int mResolvedDataSize;
+ bool mResolvedDataValid;
+
+ unsigned int mReadUsageCount;
+ unsigned int mWriteUsageCount;
+
+ void markBufferUsage();
+};
+
+// Each instance of BufferStorageD3DBuffer11 is specialized for a class of D3D binding points
+// - vertex buffers
+// - index buffers
+class DirectBufferStorage11
+{
+ public:
+ DirectBufferStorage11(Renderer11 *renderer, BufferUsage usage);
+ ~DirectBufferStorage11();
+
+ BufferUsage getUsage() const;
+ bool updateFromStagingBuffer(ID3D11Buffer *stagingBuffer, size_t size, size_t offset);
+
+ ID3D11Buffer *getD3DBuffer() { return mDirectBuffer; }
+ bool isDirty() const { return mDirty; }
+ void markDirty() { mDirty = true; }
+
+ private:
+ Renderer11 *mRenderer;
+ const BufferUsage mUsage;
+ ID3D11Buffer *mDirectBuffer;
+ size_t mBufferSize;
+ bool mDirty;
+
+ static void fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Renderer *renderer, BufferUsage usage, unsigned int bufferSize);
+};
+
+}
+
+#endif // LIBGLESV2_RENDERER_BUFFERSTORAGE11_H_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/BufferStorage11.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11Fence11cpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/Fence11.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/Fence11.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/Fence11.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,134 @@
</span><ins>+#include "precompiled.h"
+//
+// Copyright (c) 2013 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.
+//
+
+// Fence11.cpp: Defines the rx::Fence11 class which implements rx::FenceImpl.
+
+#include "libGLESv2/renderer/d3d11/Fence11.h"
+#include "libGLESv2/main.h"
+#include "libGLESv2/renderer/d3d11/Renderer11.h"
+
+namespace rx
+{
+
+Fence11::Fence11(rx::Renderer11 *renderer)
+{
+ mRenderer = renderer;
+ mQuery = NULL;
+}
+
+Fence11::~Fence11()
+{
+ if (mQuery)
+ {
+ mQuery->Release();
+ mQuery = NULL;
+ }
+}
+
+GLboolean Fence11::isFence()
+{
+ // GL_NV_fence spec:
+ // A name returned by GenFencesNV, but not yet set via SetFenceNV, is not the name of an existing fence.
+ return mQuery != NULL;
+}
+
+void Fence11::setFence(GLenum condition)
+{
+ if (!mQuery)
+ {
+ D3D11_QUERY_DESC queryDesc;
+ queryDesc.Query = D3D11_QUERY_EVENT;
+ queryDesc.MiscFlags = 0;
+
+ if (FAILED(mRenderer->getDevice()->CreateQuery(&queryDesc, &mQuery)))
+ {
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+ }
+
+ mRenderer->getDeviceContext()->End(mQuery);
+
+ setCondition(condition);
+ setStatus(GL_FALSE);
+}
+
+GLboolean Fence11::testFence()
+{
+ if (mQuery == NULL)
+ {
+ return gl::error(GL_INVALID_OPERATION, GL_TRUE);
+ }
+
+ HRESULT result = mRenderer->getDeviceContext()->GetData(mQuery, NULL, 0, 0);
+
+ if (mRenderer->isDeviceLost())
+ {
+ return gl::error(GL_OUT_OF_MEMORY, GL_TRUE);
+ }
+
+ ASSERT(result == S_OK || result == S_FALSE);
+ setStatus(result == S_OK);
+ return getStatus();
+}
+
+void Fence11::finishFence()
+{
+ if (mQuery == NULL)
+ {
+ return gl::error(GL_INVALID_OPERATION);
+ }
+
+ while (!testFence())
+ {
+ Sleep(0);
+ }
+}
+
+void Fence11::getFenceiv(GLenum pname, GLint *params)
+{
+ if (mQuery == NULL)
+ {
+ return gl::error(GL_INVALID_OPERATION);
+ }
+
+ switch (pname)
+ {
+ case GL_FENCE_STATUS_NV:
+ {
+ // GL_NV_fence spec:
+ // Once the status of a fence has been finished (via FinishFenceNV) or tested and the returned status is TRUE (via either TestFenceNV
+ // or GetFenceivNV querying the FENCE_STATUS_NV), the status remains TRUE until the next SetFenceNV of the fence.
+ if (getStatus())
+ {
+ params[0] = GL_TRUE;
+ return;
+ }
+
+ HRESULT result = mRenderer->getDeviceContext()->GetData(mQuery, NULL, 0, D3D11_ASYNC_GETDATA_DONOTFLUSH);
+
+ if (mRenderer->isDeviceLost())
+ {
+ params[0] = GL_TRUE;
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+
+ ASSERT(result == S_OK || result == S_FALSE);
+ setStatus(result == S_OK);
+ params[0] = getStatus();
+
+ break;
+ }
+ case GL_FENCE_CONDITION_NV:
+ params[0] = getCondition();
+ break;
+ default:
+ return gl::error(GL_INVALID_ENUM);
+ break;
+ }
+}
+
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/Fence11.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11Fence11h"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/Fence11.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/Fence11.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/Fence11.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,39 @@
</span><ins>+//
+// Copyright (c) 2013 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.
+//
+
+// Fence11.h: Defines the rx::Fence11 class which implements rx::FenceImpl.
+
+#ifndef LIBGLESV2_RENDERER_Fence11_H_
+#define LIBGLESV2_RENDERER_Fence11_H_
+
+#include "libGLESv2/renderer/FenceImpl.h"
+
+namespace rx
+{
+class Renderer11;
+
+class Fence11 : public FenceImpl
+{
+ public:
+ explicit Fence11(rx::Renderer11 *renderer);
+ virtual ~Fence11();
+
+ GLboolean isFence();
+ void setFence(GLenum condition);
+ GLboolean testFence();
+ void finishFence();
+ void getFenceiv(GLenum pname, GLint *params);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Fence11);
+
+ rx::Renderer11 *mRenderer;
+ ID3D11Query *mQuery;
+};
+
+}
+
+#endif // LIBGLESV2_RENDERER_FENCE11_H_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/Fence11.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11Image11cpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/Image11.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/Image11.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/Image11.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,495 @@
</span><ins>+#include "precompiled.h"
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Image11.h: Implements the rx::Image11 class, which acts as the interface to
+// the actual underlying resources of a Texture
+
+#include "libGLESv2/renderer/d3d11/Renderer11.h"
+#include "libGLESv2/renderer/d3d11/Image11.h"
+#include "libGLESv2/renderer/d3d11/TextureStorage11.h"
+#include "libGLESv2/Framebuffer.h"
+#include "libGLESv2/Renderbuffer.h"
+
+#include "libGLESv2/main.h"
+#include "libGLESv2/utilities.h"
+#include "libGLESv2/renderer/d3d11/renderer11_utils.h"
+#include "libGLESv2/renderer/generatemip.h"
+
+namespace rx
+{
+
+Image11::Image11()
+{
+ mStagingTexture = NULL;
+ mRenderer = NULL;
+ mDXGIFormat = DXGI_FORMAT_UNKNOWN;
+}
+
+Image11::~Image11()
+{
+ if (mStagingTexture)
+ {
+ mStagingTexture->Release();
+ }
+}
+
+Image11 *Image11::makeImage11(Image *img)
+{
+ ASSERT(HAS_DYNAMIC_TYPE(rx::Image11*, img));
+ return static_cast<rx::Image11*>(img);
+}
+
+void Image11::generateMipmap(Image11 *dest, Image11 *src)
+{
+ ASSERT(src->getDXGIFormat() == dest->getDXGIFormat());
+ ASSERT(src->getWidth() == 1 || src->getWidth() / 2 == dest->getWidth());
+ ASSERT(src->getHeight() == 1 || src->getHeight() / 2 == dest->getHeight());
+
+ D3D11_MAPPED_SUBRESOURCE destMapped, srcMapped;
+ dest->map(D3D11_MAP_WRITE, &destMapped);
+ src->map(D3D11_MAP_READ, &srcMapped);
+
+ const unsigned char *sourceData = reinterpret_cast<const unsigned char*>(srcMapped.pData);
+ unsigned char *destData = reinterpret_cast<unsigned char*>(destMapped.pData);
+
+ if (sourceData && destData)
+ {
+ switch (src->getDXGIFormat())
+ {
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ case DXGI_FORMAT_B8G8R8A8_UNORM:
+ GenerateMip<R8G8B8A8>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch);
+ break;
+ case DXGI_FORMAT_A8_UNORM:
+ GenerateMip<A8>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch);
+ break;
+ case DXGI_FORMAT_R8_UNORM:
+ GenerateMip<R8>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch);
+ break;
+ case DXGI_FORMAT_R32G32B32A32_FLOAT:
+ GenerateMip<A32B32G32R32F>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch);
+ break;
+ case DXGI_FORMAT_R32G32B32_FLOAT:
+ GenerateMip<R32G32B32F>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch);
+ break;
+ case DXGI_FORMAT_R16G16B16A16_FLOAT:
+ GenerateMip<A16B16G16R16F>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch);
+ break;
+ case DXGI_FORMAT_R8G8_UNORM:
+ GenerateMip<R8G8>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch);
+ break;
+ case DXGI_FORMAT_R16_FLOAT:
+ GenerateMip<R16F>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch);
+ break;
+ case DXGI_FORMAT_R16G16_FLOAT:
+ GenerateMip<R16G16F>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch);
+ break;
+ case DXGI_FORMAT_R32_FLOAT:
+ GenerateMip<R32F>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch);
+ break;
+ case DXGI_FORMAT_R32G32_FLOAT:
+ GenerateMip<R32G32F>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ dest->unmap();
+ src->unmap();
+ }
+
+ dest->markDirty();
+}
+
+static bool FormatRequiresInitialization(DXGI_FORMAT dxgiFormat, GLenum internalFormat)
+{
+ return (dxgiFormat == DXGI_FORMAT_R8G8B8A8_UNORM && gl::GetAlphaSize(internalFormat) == 0) ||
+ (dxgiFormat == DXGI_FORMAT_R32G32B32A32_FLOAT && gl::GetAlphaSize(internalFormat) == 0);
+}
+
+bool Image11::isDirty() const
+{
+ return ((mStagingTexture || FormatRequiresInitialization(mDXGIFormat, mInternalFormat)) && mDirty);
+}
+
+bool Image11::updateSurface(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
+{
+ TextureStorage11_2D *storage11 = TextureStorage11_2D::makeTextureStorage11_2D(storage->getStorageInstance());
+ return storage11->updateSubresourceLevel(getStagingTexture(), getStagingSubresource(), level, 0, xoffset, yoffset, width, height);
+}
+
+bool Image11::updateSurface(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
+{
+ TextureStorage11_Cube *storage11 = TextureStorage11_Cube::makeTextureStorage11_Cube(storage->getStorageInstance());
+ return storage11->updateSubresourceLevel(getStagingTexture(), getStagingSubresource(), level, face, xoffset, yoffset, width, height);
+}
+
+bool Image11::redefine(Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, bool forceRelease)
+{
+ if (mWidth != width ||
+ mHeight != height ||
+ mInternalFormat != internalformat ||
+ forceRelease)
+ {
+ mRenderer = Renderer11::makeRenderer11(renderer);
+
+ mWidth = width;
+ mHeight = height;
+ mInternalFormat = internalformat;
+ // compute the d3d format that will be used
+ mDXGIFormat = gl_d3d11::ConvertTextureFormat(internalformat);
+ mActualFormat = d3d11_gl::ConvertTextureInternalFormat(mDXGIFormat);
+
+ if (mStagingTexture)
+ {
+ mStagingTexture->Release();
+ mStagingTexture = NULL;
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+bool Image11::isRenderableFormat() const
+{
+ return TextureStorage11::IsTextureFormatRenderable(mDXGIFormat);
+}
+
+DXGI_FORMAT Image11::getDXGIFormat() const
+{
+ // this should only happen if the image hasn't been redefined first
+ // which would be a bug by the caller
+ ASSERT(mDXGIFormat != DXGI_FORMAT_UNKNOWN);
+
+ return mDXGIFormat;
+}
+
+// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input
+// into the target pixel rectangle.
+void Image11::loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ GLint unpackAlignment, const void *input)
+{
+ D3D11_MAPPED_SUBRESOURCE mappedImage;
+ HRESULT result = map(D3D11_MAP_WRITE, &mappedImage);
+ if (FAILED(result))
+ {
+ ERR("Could not map image for loading.");
+ return;
+ }
+
+ GLsizei inputPitch = gl::ComputePitch(width, mInternalFormat, unpackAlignment);
+ size_t pixelSize = d3d11::ComputePixelSizeBits(mDXGIFormat) / 8;
+ void* offsetMappedData = (void*)((BYTE *)mappedImage.pData + (yoffset * mappedImage.RowPitch + xoffset * pixelSize));
+
+ switch (mInternalFormat)
+ {
+ case GL_ALPHA8_EXT:
+ loadAlphaDataToNative(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
+ break;
+ case GL_LUMINANCE8_EXT:
+ loadLuminanceDataToNativeOrBGRA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData, false);
+ break;
+ case GL_ALPHA32F_EXT:
+ loadAlphaFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
+ break;
+ case GL_LUMINANCE32F_EXT:
+ loadLuminanceFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
+ break;
+ case GL_ALPHA16F_EXT:
+ loadAlphaHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
+ break;
+ case GL_LUMINANCE16F_EXT:
+ loadLuminanceHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
+ break;
+ case GL_LUMINANCE8_ALPHA8_EXT:
+ loadLuminanceAlphaDataToNativeOrBGRA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData, false);
+ break;
+ case GL_LUMINANCE_ALPHA32F_EXT:
+ loadLuminanceAlphaFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
+ break;
+ case GL_LUMINANCE_ALPHA16F_EXT:
+ loadLuminanceAlphaHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
+ break;
+ case GL_RGB8_OES:
+ loadRGBUByteDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
+ break;
+ case GL_RGB565:
+ loadRGB565DataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
+ break;
+ case GL_RGBA8_OES:
+ loadRGBAUByteDataToNative(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
+ break;
+ case GL_RGBA4:
+ loadRGBA4444DataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
+ break;
+ case GL_RGB5_A1:
+ loadRGBA5551DataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
+ break;
+ case GL_BGRA8_EXT:
+ loadBGRADataToBGRA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
+ break;
+ case GL_RGB32F_EXT:
+ loadRGBFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
+ break;
+ case GL_RGB16F_EXT:
+ loadRGBHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
+ break;
+ case GL_RGBA32F_EXT:
+ loadRGBAFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
+ break;
+ case GL_RGBA16F_EXT:
+ loadRGBAHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData);
+ break;
+ default: UNREACHABLE();
+ }
+
+ unmap();
+}
+
+void Image11::loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ const void *input)
+{
+ ASSERT(xoffset % 4 == 0);
+ ASSERT(yoffset % 4 == 0);
+
+ D3D11_MAPPED_SUBRESOURCE mappedImage;
+ HRESULT result = map(D3D11_MAP_WRITE, &mappedImage);
+ if (FAILED(result))
+ {
+ ERR("Could not map image for loading.");
+ return;
+ }
+
+ // Size computation assumes a 4x4 block compressed texture format
+ size_t blockSize = d3d11::ComputeBlockSizeBits(mDXGIFormat) / 8;
+ void* offsetMappedData = (void*)((BYTE *)mappedImage.pData + ((yoffset / 4) * mappedImage.RowPitch + (xoffset / 4) * blockSize));
+
+ GLsizei inputSize = gl::ComputeCompressedSize(width, height, mInternalFormat);
+ GLsizei inputPitch = gl::ComputeCompressedPitch(width, mInternalFormat);
+ int rows = inputSize / inputPitch;
+ for (int i = 0; i < rows; ++i)
+ {
+ memcpy((void*)((BYTE*)offsetMappedData + i * mappedImage.RowPitch), (void*)((BYTE*)input + i * inputPitch), inputPitch);
+ }
+
+ unmap();
+}
+
+void Image11::copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
+{
+ gl::Renderbuffer *colorbuffer = source->getReadColorbuffer();
+
+ if (colorbuffer && colorbuffer->getActualFormat() == (GLuint)mActualFormat)
+ {
+ // No conversion needed-- use copyback fastpath
+ ID3D11Texture2D *colorBufferTexture = NULL;
+ unsigned int subresourceIndex = 0;
+
+ if (mRenderer->getRenderTargetResource(colorbuffer, &subresourceIndex, &colorBufferTexture))
+ {
+ D3D11_TEXTURE2D_DESC textureDesc;
+ colorBufferTexture->GetDesc(&textureDesc);
+
+ ID3D11Device *device = mRenderer->getDevice();
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+ ID3D11Texture2D* srcTex = NULL;
+ if (textureDesc.SampleDesc.Count > 1)
+ {
+ D3D11_TEXTURE2D_DESC resolveDesc;
+ resolveDesc.Width = textureDesc.Width;
+ resolveDesc.Height = textureDesc.Height;
+ resolveDesc.MipLevels = 1;
+ resolveDesc.ArraySize = 1;
+ resolveDesc.Format = textureDesc.Format;
+ resolveDesc.SampleDesc.Count = 1;
+ resolveDesc.SampleDesc.Quality = 0;
+ resolveDesc.Usage = D3D11_USAGE_DEFAULT;
+ resolveDesc.BindFlags = 0;
+ resolveDesc.CPUAccessFlags = 0;
+ resolveDesc.MiscFlags = 0;
+
+ HRESULT result = device->CreateTexture2D(&resolveDesc, NULL, &srcTex);
+ if (FAILED(result))
+ {
+ ERR("Failed to create resolve texture for Image11::copy, HRESULT: 0x%X.", result);
+ return;
+ }
+
+ deviceContext->ResolveSubresource(srcTex, 0, colorBufferTexture, subresourceIndex, textureDesc.Format);
+ subresourceIndex = 0;
+ }
+ else
+ {
+ srcTex = colorBufferTexture;
+ srcTex->AddRef();
+ }
+
+ D3D11_BOX srcBox;
+ srcBox.left = x;
+ srcBox.right = x + width;
+ srcBox.top = y;
+ srcBox.bottom = y + height;
+ srcBox.front = 0;
+ srcBox.back = 1;
+
+ deviceContext->CopySubresourceRegion(mStagingTexture, 0, xoffset, yoffset, 0, srcTex, subresourceIndex, &srcBox);
+
+ srcTex->Release();
+ colorBufferTexture->Release();
+ }
+ }
+ else
+ {
+ // This format requires conversion, so we must copy the texture to staging and manually convert via readPixels
+ D3D11_MAPPED_SUBRESOURCE mappedImage;
+ HRESULT result = map(D3D11_MAP_WRITE, &mappedImage);
+
+ // determine the offset coordinate into the destination buffer
+ GLsizei rowOffset = gl::ComputePixelSize(mActualFormat) * xoffset;
+ void *dataOffset = static_cast<unsigned char*>(mappedImage.pData) + mappedImage.RowPitch * yoffset + rowOffset;
+
+ mRenderer->readPixels(source, x, y, width, height, gl::ExtractFormat(mInternalFormat),
+ gl::ExtractType(mInternalFormat), mappedImage.RowPitch, false, 4, dataOffset);
+
+ unmap();
+ }
+}
+
+ID3D11Texture2D *Image11::getStagingTexture()
+{
+ createStagingTexture();
+
+ return mStagingTexture;
+}
+
+unsigned int Image11::getStagingSubresource()
+{
+ createStagingTexture();
+
+ return mStagingSubresource;
+}
+
+template <typename T, size_t N>
+static void setDefaultData(ID3D11DeviceContext *deviceContext, ID3D11Texture2D *texture, UINT subresource,
+ GLsizei width, GLsizei height, const T (&defaultData)[N])
+{
+ D3D11_MAPPED_SUBRESOURCE map;
+ deviceContext->Map(texture, subresource, D3D11_MAP_WRITE, 0, &map);
+
+ unsigned char* ptr = reinterpret_cast<unsigned char*>(map.pData);
+ size_t pixelSize = sizeof(T) * N;
+
+ for (GLsizei y = 0; y < height; y++)
+ {
+ for (GLsizei x = 0; x < width; x++)
+ {
+ memcpy(ptr + (y * map.RowPitch) + (x * pixelSize), defaultData, pixelSize);
+ }
+ }
+
+ deviceContext->Unmap(texture, subresource);
+}
+
+void Image11::createStagingTexture()
+{
+ if (mStagingTexture)
+ {
+ return;
+ }
+
+ ID3D11Texture2D *newTexture = NULL;
+ int lodOffset = 1;
+ const DXGI_FORMAT dxgiFormat = getDXGIFormat();
+ ASSERT(!d3d11::IsDepthStencilFormat(dxgiFormat)); // We should never get here for depth textures
+
+ if (mWidth != 0 && mHeight != 0)
+ {
+ GLsizei width = mWidth;
+ GLsizei height = mHeight;
+
+ // adjust size if needed for compressed textures
+ gl::MakeValidSize(false, d3d11::IsCompressed(dxgiFormat), &width, &height, &lodOffset);
+ ID3D11Device *device = mRenderer->getDevice();
+
+ D3D11_TEXTURE2D_DESC desc;
+ desc.Width = width;
+ desc.Height = height;
+ desc.MipLevels = lodOffset + 1;
+ desc.ArraySize = 1;
+ desc.Format = dxgiFormat;
+ desc.SampleDesc.Count = 1;
+ desc.SampleDesc.Quality = 0;
+ desc.Usage = D3D11_USAGE_STAGING;
+ desc.BindFlags = 0;
+ desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
+ desc.MiscFlags = 0;
+
+ HRESULT result = device->CreateTexture2D(&desc, NULL, &newTexture);
+
+ if (FAILED(result))
+ {
+ ASSERT(result == E_OUTOFMEMORY);
+ ERR("Creating image failed.");
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+ }
+
+ mStagingTexture = newTexture;
+ mStagingSubresource = D3D11CalcSubresource(lodOffset, 0, lodOffset + 1);
+ mDirty = false;
+
+ if (mDXGIFormat == DXGI_FORMAT_R8G8B8A8_UNORM && gl::GetAlphaSize(mInternalFormat) == 0)
+ {
+ unsigned char defaultPixel[4] = { 0, 0, 0, 255 };
+ setDefaultData(mRenderer->getDeviceContext(), mStagingTexture, mStagingSubresource, mWidth, mHeight, defaultPixel);
+ }
+ else if (mDXGIFormat == DXGI_FORMAT_R32G32B32A32_FLOAT && gl::GetAlphaSize(mInternalFormat) == 0)
+ {
+ float defaultPixel[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
+ setDefaultData(mRenderer->getDeviceContext(), mStagingTexture, mStagingSubresource, mWidth, mHeight, defaultPixel);
+ }
+}
+
+HRESULT Image11::map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map)
+{
+ createStagingTexture();
+
+ HRESULT result = E_FAIL;
+
+ if (mStagingTexture)
+ {
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+ result = deviceContext->Map(mStagingTexture, mStagingSubresource, mapType, 0, map);
+
+ // this can fail if the device is removed (from TDR)
+ if (d3d11::isDeviceLostError(result))
+ {
+ mRenderer->notifyDeviceLost();
+ }
+ else if (SUCCEEDED(result))
+ {
+ mDirty = true;
+ }
+ }
+
+ return result;
+}
+
+void Image11::unmap()
+{
+ if (mStagingTexture)
+ {
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+ deviceContext->Unmap(mStagingTexture, mStagingSubresource);
+ }
+}
+
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/Image11.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11Image11h"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/Image11.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/Image11.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/Image11.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,76 @@
</span><ins>+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Image11.h: Defines the rx::Image11 class, which acts as the interface to
+// the actual underlying resources of a Texture
+
+#ifndef LIBGLESV2_RENDERER_IMAGE11_H_
+#define LIBGLESV2_RENDERER_IMAGE11_H_
+
+#include "libGLESv2/renderer/Image.h"
+
+#include "common/debug.h"
+
+namespace gl
+{
+class Framebuffer;
+}
+
+namespace rx
+{
+class Renderer;
+class Renderer11;
+class TextureStorageInterface2D;
+class TextureStorageInterfaceCube;
+
+class Image11 : public Image
+{
+ public:
+ Image11();
+ virtual ~Image11();
+
+ static Image11 *makeImage11(Image *img);
+
+ static void generateMipmap(Image11 *dest, Image11 *src);
+
+ virtual bool isDirty() const;
+
+ virtual bool updateSurface(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
+ virtual bool updateSurface(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
+
+ virtual bool redefine(Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, bool forceRelease);
+
+ virtual bool isRenderableFormat() const;
+ DXGI_FORMAT getDXGIFormat() const;
+
+ virtual void loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ GLint unpackAlignment, const void *input);
+ virtual void loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ const void *input);
+
+ virtual void copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source);
+
+ protected:
+ HRESULT map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map);
+ void unmap();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Image11);
+
+ ID3D11Texture2D *getStagingTexture();
+ unsigned int getStagingSubresource();
+ void createStagingTexture();
+
+ Renderer11 *mRenderer;
+
+ DXGI_FORMAT mDXGIFormat;
+ ID3D11Texture2D *mStagingTexture;
+ unsigned int mStagingSubresource;
+};
+
+}
+
+#endif // LIBGLESV2_RENDERER_IMAGE11_H_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/Image11.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11IndexBuffer11cpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/IndexBuffer11.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/IndexBuffer11.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/IndexBuffer11.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,183 @@
</span><ins>+#include "precompiled.h"
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// IndexBuffer11.cpp: Defines the D3D11 IndexBuffer implementation.
+
+#include "libGLESv2/renderer/d3d11/IndexBuffer11.h"
+#include "libGLESv2/renderer/d3d11/Renderer11.h"
+
+namespace rx
+{
+
+IndexBuffer11::IndexBuffer11(Renderer11 *const renderer) : mRenderer(renderer)
+{
+ mBuffer = NULL;
+ mBufferSize = 0;
+ mDynamicUsage = false;
+}
+
+IndexBuffer11::~IndexBuffer11()
+{
+ if (mBuffer)
+ {
+ mBuffer->Release();
+ mBuffer = NULL;
+ }
+}
+
+bool IndexBuffer11::initialize(unsigned int bufferSize, GLenum indexType, bool dynamic)
+{
+ if (mBuffer)
+ {
+ mBuffer->Release();
+ mBuffer = NULL;
+ }
+
+ updateSerial();
+
+ if (bufferSize > 0)
+ {
+ ID3D11Device* dxDevice = mRenderer->getDevice();
+
+ D3D11_BUFFER_DESC bufferDesc;
+ bufferDesc.ByteWidth = bufferSize;
+ bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
+ bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
+ bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ bufferDesc.MiscFlags = 0;
+ bufferDesc.StructureByteStride = 0;
+
+ HRESULT result = dxDevice->CreateBuffer(&bufferDesc, NULL, &mBuffer);
+ if (FAILED(result))
+ {
+ return false;
+ }
+ }
+
+ mBufferSize = bufferSize;
+ mIndexType = indexType;
+ mDynamicUsage = dynamic;
+
+ return true;
+}
+
+IndexBuffer11 *IndexBuffer11::makeIndexBuffer11(IndexBuffer *indexBuffer)
+{
+ ASSERT(HAS_DYNAMIC_TYPE(IndexBuffer11*, indexBuffer));
+ return static_cast<IndexBuffer11*>(indexBuffer);
+}
+
+bool IndexBuffer11::mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory)
+{
+ if (mBuffer)
+ {
+ // Check for integer overflows and out-out-bounds map requests
+ if (offset + size < offset || offset + size > mBufferSize)
+ {
+ ERR("Index buffer map range is not inside the buffer.");
+ return false;
+ }
+
+ ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
+
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource);
+ if (FAILED(result))
+ {
+ ERR("Index buffer map failed with error 0x%08x", result);
+ return false;
+ }
+
+ *outMappedMemory = reinterpret_cast<char*>(mappedResource.pData) + offset;
+ return true;
+ }
+ else
+ {
+ ERR("Index buffer not initialized.");
+ return false;
+ }
+}
+
+bool IndexBuffer11::unmapBuffer()
+{
+ if (mBuffer)
+ {
+ ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
+ dxContext->Unmap(mBuffer, 0);
+ return true;
+ }
+ else
+ {
+ ERR("Index buffer not initialized.");
+ return false;
+ }
+}
+
+GLenum IndexBuffer11::getIndexType() const
+{
+ return mIndexType;
+}
+
+unsigned int IndexBuffer11::getBufferSize() const
+{
+ return mBufferSize;
+}
+
+bool IndexBuffer11::setSize(unsigned int bufferSize, GLenum indexType)
+{
+ if (bufferSize > mBufferSize || indexType != mIndexType)
+ {
+ return initialize(bufferSize, indexType, mDynamicUsage);
+ }
+ else
+ {
+ return true;
+ }
+}
+
+bool IndexBuffer11::discard()
+{
+ if (mBuffer)
+ {
+ ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
+
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+ if (FAILED(result))
+ {
+ ERR("Index buffer map failed with error 0x%08x", result);
+ return false;
+ }
+
+ dxContext->Unmap(mBuffer, 0);
+
+ return true;
+ }
+ else
+ {
+ ERR("Index buffer not initialized.");
+ return false;
+ }
+}
+
+DXGI_FORMAT IndexBuffer11::getIndexFormat() const
+{
+ switch (mIndexType)
+ {
+ case GL_UNSIGNED_BYTE: return DXGI_FORMAT_R16_UINT;
+ case GL_UNSIGNED_SHORT: return DXGI_FORMAT_R16_UINT;
+ case GL_UNSIGNED_INT: return DXGI_FORMAT_R32_UINT;
+ default: UNREACHABLE(); return DXGI_FORMAT_UNKNOWN;
+ }
+}
+
+ID3D11Buffer *IndexBuffer11::getBuffer() const
+{
+ return mBuffer;
+}
+
+}
</ins><span class="cx">\ No newline at end of file
</span><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/IndexBuffer11.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11IndexBuffer11h"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/IndexBuffer11.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/IndexBuffer11.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/IndexBuffer11.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,53 @@
</span><ins>+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// IndexBuffer11.h: Defines the D3D11 IndexBuffer implementation.
+
+#ifndef LIBGLESV2_RENDERER_INDEXBUFFER11_H_
+#define LIBGLESV2_RENDERER_INDEXBUFFER11_H_
+
+#include "libGLESv2/renderer/IndexBuffer.h"
+
+namespace rx
+{
+class Renderer11;
+
+class IndexBuffer11 : public IndexBuffer
+{
+ public:
+ explicit IndexBuffer11(Renderer11 *const renderer);
+ virtual ~IndexBuffer11();
+
+ virtual bool initialize(unsigned int bufferSize, GLenum indexType, bool dynamic);
+
+ static IndexBuffer11 *makeIndexBuffer11(IndexBuffer *indexBuffer);
+
+ virtual bool mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory);
+ virtual bool unmapBuffer();
+
+ virtual GLenum getIndexType() const;
+ virtual unsigned int getBufferSize() const;
+ virtual bool setSize(unsigned int bufferSize, GLenum indexType);
+
+ virtual bool discard();
+
+ DXGI_FORMAT getIndexFormat() const;
+ ID3D11Buffer *getBuffer() const;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(IndexBuffer11);
+
+ rx::Renderer11 *const mRenderer;
+
+ ID3D11Buffer *mBuffer;
+ unsigned int mBufferSize;
+ GLenum mIndexType;
+ bool mDynamicUsage;
+};
+
+}
+
+#endif // LIBGLESV2_RENDERER_INDEXBUFFER11_H_
</ins><span class="cx">\ No newline at end of file
</span><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/IndexBuffer11.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11InputLayoutCachecpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/InputLayoutCache.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/InputLayoutCache.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/InputLayoutCache.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,213 @@
</span><ins>+#include "precompiled.h"
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// InputLayoutCache.cpp: Defines InputLayoutCache, a class that builds and caches
+// D3D11 input layouts.
+
+#include "libGLESv2/renderer/d3d11/InputLayoutCache.h"
+#include "libGLESv2/renderer/d3d11/VertexBuffer11.h"
+#include "libGLESv2/renderer/d3d11/BufferStorage11.h"
+#include "libGLESv2/renderer/d3d11/ShaderExecutable11.h"
+#include "libGLESv2/ProgramBinary.h"
+#include "libGLESv2/Context.h"
+#include "libGLESv2/renderer/VertexDataManager.h"
+
+#include "third_party/murmurhash/MurmurHash3.h"
+
+namespace rx
+{
+
+const unsigned int InputLayoutCache::kMaxInputLayouts = 1024;
+
+InputLayoutCache::InputLayoutCache() : mInputLayoutMap(kMaxInputLayouts, hashInputLayout, compareInputLayouts)
+{
+ mCounter = 0;
+ mDevice = NULL;
+ mDeviceContext = NULL;
+ mCurrentIL = NULL;
+ for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
+ {
+ mCurrentBuffers[i] = -1;
+ mCurrentVertexStrides[i] = -1;
+ mCurrentVertexOffsets[i] = -1;
+ }
+}
+
+InputLayoutCache::~InputLayoutCache()
+{
+ clear();
+}
+
+void InputLayoutCache::initialize(ID3D11Device *device, ID3D11DeviceContext *context)
+{
+ clear();
+ mDevice = device;
+ mDeviceContext = context;
+}
+
+void InputLayoutCache::clear()
+{
+ for (InputLayoutMap::iterator i = mInputLayoutMap.begin(); i != mInputLayoutMap.end(); i++)
+ {
+ i->second.inputLayout->Release();
+ }
+ mInputLayoutMap.clear();
+ markDirty();
+}
+
+void InputLayoutCache::markDirty()
+{
+ mCurrentIL = NULL;
+ for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
+ {
+ mCurrentBuffers[i] = -1;
+ mCurrentVertexStrides[i] = -1;
+ mCurrentVertexOffsets[i] = -1;
+ }
+}
+
+GLenum InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS],
+ gl::ProgramBinary *programBinary)
+{
+ int sortedSemanticIndices[gl::MAX_VERTEX_ATTRIBS];
+ programBinary->sortAttributesByLayout(attributes, sortedSemanticIndices);
+
+ if (!mDevice || !mDeviceContext)
+ {
+ ERR("InputLayoutCache is not initialized.");
+ return GL_INVALID_OPERATION;
+ }
+
+ InputLayoutKey ilKey = { 0 };
+
+ ID3D11Buffer *vertexBuffers[gl::MAX_VERTEX_ATTRIBS] = { NULL };
+ unsigned int vertexBufferSerials[gl::MAX_VERTEX_ATTRIBS] = { 0 };
+ UINT vertexStrides[gl::MAX_VERTEX_ATTRIBS] = { 0 };
+ UINT vertexOffsets[gl::MAX_VERTEX_ATTRIBS] = { 0 };
+
+ static const char* semanticName = "TEXCOORD";
+
+ for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
+ {
+ if (attributes[i].active)
+ {
+ VertexBuffer11 *vertexBuffer = VertexBuffer11::makeVertexBuffer11(attributes[i].vertexBuffer);
+ BufferStorage11 *bufferStorage = attributes[i].storage ? BufferStorage11::makeBufferStorage11(attributes[i].storage) : NULL;
+
+ D3D11_INPUT_CLASSIFICATION inputClass = attributes[i].divisor > 0 ? D3D11_INPUT_PER_INSTANCE_DATA : D3D11_INPUT_PER_VERTEX_DATA;
+
+ // Record the type of the associated vertex shader vector in our key
+ // This will prevent mismatched vertex shaders from using the same input layout
+ GLint attributeSize;
+ programBinary->getActiveAttribute(ilKey.elementCount, 0, NULL, &attributeSize, &ilKey.elements[ilKey.elementCount].glslElementType, NULL);
+
+ ilKey.elements[ilKey.elementCount].desc.SemanticName = semanticName;
+ ilKey.elements[ilKey.elementCount].desc.SemanticIndex = sortedSemanticIndices[i];
+ ilKey.elements[ilKey.elementCount].desc.Format = attributes[i].attribute->mArrayEnabled ? vertexBuffer->getDXGIFormat(*attributes[i].attribute) : DXGI_FORMAT_R32G32B32A32_FLOAT;
+ ilKey.elements[ilKey.elementCount].desc.InputSlot = i;
+ ilKey.elements[ilKey.elementCount].desc.AlignedByteOffset = 0;
+ ilKey.elements[ilKey.elementCount].desc.InputSlotClass = inputClass;
+ ilKey.elements[ilKey.elementCount].desc.InstanceDataStepRate = attributes[i].divisor;
+ ilKey.elementCount++;
+
+ vertexBuffers[i] = bufferStorage ? bufferStorage->getBuffer(BUFFER_USAGE_VERTEX) : vertexBuffer->getBuffer();
+ vertexBufferSerials[i] = bufferStorage ? bufferStorage->getSerial() : vertexBuffer->getSerial();
+ vertexStrides[i] = attributes[i].stride;
+ vertexOffsets[i] = attributes[i].offset;
+ }
+ }
+
+ ID3D11InputLayout *inputLayout = NULL;
+
+ InputLayoutMap::iterator i = mInputLayoutMap.find(ilKey);
+ if (i != mInputLayoutMap.end())
+ {
+ inputLayout = i->second.inputLayout;
+ i->second.lastUsedTime = mCounter++;
+ }
+ else
+ {
+ ShaderExecutable11 *shader = ShaderExecutable11::makeShaderExecutable11(programBinary->getVertexExecutable());
+
+ D3D11_INPUT_ELEMENT_DESC descs[gl::MAX_VERTEX_ATTRIBS];
+ for (unsigned int j = 0; j < ilKey.elementCount; ++j)
+ {
+ descs[j] = ilKey.elements[j].desc;
+ }
+
+ HRESULT result = mDevice->CreateInputLayout(descs, ilKey.elementCount, shader->getFunction(), shader->getLength(), &inputLayout);
+ if (FAILED(result))
+ {
+ ERR("Failed to crate input layout, result: 0x%08x", result);
+ return GL_INVALID_OPERATION;
+ }
+
+ if (mInputLayoutMap.size() >= kMaxInputLayouts)
+ {
+ TRACE("Overflowed the limit of %u input layouts, removing the least recently used "
+ "to make room.", kMaxInputLayouts);
+
+ InputLayoutMap::iterator leastRecentlyUsed = mInputLayoutMap.begin();
+ for (InputLayoutMap::iterator i = mInputLayoutMap.begin(); i != mInputLayoutMap.end(); i++)
+ {
+ if (i->second.lastUsedTime < leastRecentlyUsed->second.lastUsedTime)
+ {
+ leastRecentlyUsed = i;
+ }
+ }
+ leastRecentlyUsed->second.inputLayout->Release();
+ mInputLayoutMap.erase(leastRecentlyUsed);
+ }
+
+ InputLayoutCounterPair inputCounterPair;
+ inputCounterPair.inputLayout = inputLayout;
+ inputCounterPair.lastUsedTime = mCounter++;
+
+ mInputLayoutMap.insert(std::make_pair(ilKey, inputCounterPair));
+ }
+
+ if (inputLayout != mCurrentIL)
+ {
+ mDeviceContext->IASetInputLayout(inputLayout);
+ mCurrentIL = inputLayout;
+ }
+
+ for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
+ {
+ if (vertexBufferSerials[i] != mCurrentBuffers[i] || vertexStrides[i] != mCurrentVertexStrides[i] ||
+ vertexOffsets[i] != mCurrentVertexOffsets[i])
+ {
+ mDeviceContext->IASetVertexBuffers(i, 1, &vertexBuffers[i], &vertexStrides[i], &vertexOffsets[i]);
+ mCurrentBuffers[i] = vertexBufferSerials[i];
+ mCurrentVertexStrides[i] = vertexStrides[i];
+ mCurrentVertexOffsets[i] = vertexOffsets[i];
+ }
+ }
+
+ return GL_NO_ERROR;
+}
+
+std::size_t InputLayoutCache::hashInputLayout(const InputLayoutKey &inputLayout)
+{
+ static const unsigned int seed = 0xDEADBEEF;
+
+ std::size_t hash = 0;
+ MurmurHash3_x86_32(inputLayout.begin(), inputLayout.end() - inputLayout.begin(), seed, &hash);
+ return hash;
+}
+
+bool InputLayoutCache::compareInputLayouts(const InputLayoutKey &a, const InputLayoutKey &b)
+{
+ if (a.elementCount != b.elementCount)
+ {
+ return false;
+ }
+
+ return std::equal(a.begin(), a.end(), b.begin());
+}
+
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/InputLayoutCache.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11InputLayoutCacheh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/InputLayoutCache.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/InputLayoutCache.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/InputLayoutCache.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,95 @@
</span><ins>+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// InputLayoutCache.h: Defines InputLayoutCache, a class that builds and caches
+// D3D11 input layouts.
+
+#ifndef LIBGLESV2_RENDERER_INPUTLAYOUTCACHE_H_
+#define LIBGLESV2_RENDERER_INPUTLAYOUTCACHE_H_
+
+#include "libGLESv2/Constants.h"
+#include "common/angleutils.h"
+
+namespace gl
+{
+class ProgramBinary;
+}
+
+namespace rx
+{
+struct TranslatedAttribute;
+
+class InputLayoutCache
+{
+ public:
+ InputLayoutCache();
+ virtual ~InputLayoutCache();
+
+ void initialize(ID3D11Device *device, ID3D11DeviceContext *context);
+ void clear();
+ void markDirty();
+
+ GLenum applyVertexBuffers(TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS],
+ gl::ProgramBinary *programBinary);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(InputLayoutCache);
+
+ struct InputLayoutElement
+ {
+ D3D11_INPUT_ELEMENT_DESC desc;
+ GLenum glslElementType;
+ };
+
+ struct InputLayoutKey
+ {
+ unsigned int elementCount;
+ InputLayoutElement elements[gl::MAX_VERTEX_ATTRIBS];
+
+ const char *begin() const
+ {
+ return reinterpret_cast<const char*>(&elementCount);
+ }
+
+ const char *end() const
+ {
+ return reinterpret_cast<const char*>(&elements[elementCount]);
+ }
+ };
+
+ struct InputLayoutCounterPair
+ {
+ ID3D11InputLayout *inputLayout;
+ unsigned long long lastUsedTime;
+ };
+
+ ID3D11InputLayout *mCurrentIL;
+ unsigned int mCurrentBuffers[gl::MAX_VERTEX_ATTRIBS];
+ UINT mCurrentVertexStrides[gl::MAX_VERTEX_ATTRIBS];
+ UINT mCurrentVertexOffsets[gl::MAX_VERTEX_ATTRIBS];
+
+ static std::size_t hashInputLayout(const InputLayoutKey &inputLayout);
+ static bool compareInputLayouts(const InputLayoutKey &a, const InputLayoutKey &b);
+
+ typedef std::size_t (*InputLayoutHashFunction)(const InputLayoutKey &);
+ typedef bool (*InputLayoutEqualityFunction)(const InputLayoutKey &, const InputLayoutKey &);
+ typedef std::unordered_map<InputLayoutKey,
+ InputLayoutCounterPair,
+ InputLayoutHashFunction,
+ InputLayoutEqualityFunction> InputLayoutMap;
+ InputLayoutMap mInputLayoutMap;
+
+ static const unsigned int kMaxInputLayouts;
+
+ unsigned long long mCounter;
+
+ ID3D11Device *mDevice;
+ ID3D11DeviceContext *mDeviceContext;
+};
+
+}
+
+#endif // LIBGLESV2_RENDERER_INPUTLAYOUTCACHE_H_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/InputLayoutCache.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11Query11cpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/Query11.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/Query11.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/Query11.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,122 @@
</span><ins>+#include "precompiled.h"
+//
+// Copyright (c) 2013 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.
+//
+
+// Query11.cpp: Defines the rx::Query11 class which implements rx::QueryImpl.
+
+#include "libGLESv2/renderer/d3d11/Query11.h"
+#include "libGLESv2/renderer/d3d11/Renderer11.h"
+#include "libGLESv2/main.h"
+
+namespace rx
+{
+
+Query11::Query11(rx::Renderer11 *renderer, GLenum type) : QueryImpl(type)
+{
+ mRenderer = renderer;
+ mQuery = NULL;
+}
+
+Query11::~Query11()
+{
+ if (mQuery)
+ {
+ mQuery->Release();
+ mQuery = NULL;
+ }
+}
+
+void Query11::begin()
+{
+ if (mQuery == NULL)
+ {
+ D3D11_QUERY_DESC queryDesc;
+ queryDesc.Query = D3D11_QUERY_OCCLUSION;
+ queryDesc.MiscFlags = 0;
+
+ if (FAILED(mRenderer->getDevice()->CreateQuery(&queryDesc, &mQuery)))
+ {
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+ }
+
+ mRenderer->getDeviceContext()->Begin(mQuery);
+}
+
+void Query11::end()
+{
+ if (mQuery == NULL)
+ {
+ return gl::error(GL_INVALID_OPERATION);
+ }
+
+ mRenderer->getDeviceContext()->End(mQuery);
+
+ mStatus = GL_FALSE;
+ mResult = GL_FALSE;
+}
+
+GLuint Query11::getResult()
+{
+ if (mQuery != NULL)
+ {
+ while (!testQuery())
+ {
+ Sleep(0);
+ // explicitly check for device loss, some drivers seem to return S_FALSE
+ // if the device is lost
+ if (mRenderer->testDeviceLost(true))
+ {
+ return gl::error(GL_OUT_OF_MEMORY, 0);
+ }
+ }
+ }
+
+ return mResult;
+}
+
+GLboolean Query11::isResultAvailable()
+{
+ if (mQuery != NULL)
+ {
+ testQuery();
+ }
+
+ return mStatus;
+}
+
+GLboolean Query11::testQuery()
+{
+ if (mQuery != NULL && mStatus != GL_TRUE)
+ {
+ UINT64 numPixels = 0;
+ HRESULT result = mRenderer->getDeviceContext()->GetData(mQuery, &numPixels, sizeof(UINT64), 0);
+ if (result == S_OK)
+ {
+ mStatus = GL_TRUE;
+
+ switch (getType())
+ {
+ case GL_ANY_SAMPLES_PASSED_EXT:
+ case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
+ mResult = (numPixels > 0) ? GL_TRUE : GL_FALSE;
+ break;
+ default:
+ UNREACHABLE();
+ }
+ }
+ else if (mRenderer->testDeviceLost(true))
+ {
+ return gl::error(GL_OUT_OF_MEMORY, GL_TRUE);
+ }
+
+ return mStatus;
+ }
+
+ return GL_TRUE; // prevent blocking when query is null
+}
+
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/Query11.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11Query11h"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/Query11.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/Query11.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/Query11.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,40 @@
</span><ins>+//
+// Copyright (c) 2013 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.
+//
+
+// Query11.h: Defines the rx::Query11 class which implements rx::QueryImpl.
+
+#ifndef LIBGLESV2_RENDERER_QUERY11_H_
+#define LIBGLESV2_RENDERER_QUERY11_H_
+
+#include "libGLESv2/renderer/QueryImpl.h"
+
+namespace rx
+{
+class Renderer11;
+
+class Query11 : public QueryImpl
+{
+ public:
+ Query11(rx::Renderer11 *renderer, GLenum type);
+ virtual ~Query11();
+
+ void begin();
+ void end();
+ GLuint getResult();
+ GLboolean isResultAvailable();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Query11);
+
+ GLboolean testQuery();
+
+ rx::Renderer11 *mRenderer;
+ ID3D11Query *mQuery;
+};
+
+}
+
+#endif // LIBGLESV2_RENDERER_QUERY11_H_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/Query11.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11RenderStateCachecpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/RenderStateCache.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/RenderStateCache.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/RenderStateCache.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,438 @@
</span><ins>+#include "precompiled.h"
+//
+// Copyright (c) 2012-2013 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.
+//
+
+// RenderStateCache.cpp: Defines rx::RenderStateCache, a cache of Direct3D render
+// state objects.
+
+#include "libGLESv2/renderer/d3d11/RenderStateCache.h"
+#include "libGLESv2/renderer/d3d11/renderer11_utils.h"
+
+#include "libGLESv2/Framebuffer.h"
+#include "libGLESv2/Renderbuffer.h"
+#include "libGLESv2/utilities.h"
+#include "common/debug.h"
+#include "third_party/murmurhash/MurmurHash3.h"
+
+namespace rx
+{
+
+// MSDN's documentation of ID3D11Device::CreateBlendState, ID3D11Device::CreateRasterizerState,
+// ID3D11Device::CreateDepthStencilState and ID3D11Device::CreateSamplerState claims the maximum
+// number of unique states of each type an application can create is 4096
+const unsigned int RenderStateCache::kMaxBlendStates = 4096;
+const unsigned int RenderStateCache::kMaxRasterizerStates = 4096;
+const unsigned int RenderStateCache::kMaxDepthStencilStates = 4096;
+const unsigned int RenderStateCache::kMaxSamplerStates = 4096;
+
+RenderStateCache::RenderStateCache() : mDevice(NULL), mCounter(0),
+ mBlendStateCache(kMaxBlendStates, hashBlendState, compareBlendStates),
+ mRasterizerStateCache(kMaxRasterizerStates, hashRasterizerState, compareRasterizerStates),
+ mDepthStencilStateCache(kMaxDepthStencilStates, hashDepthStencilState, compareDepthStencilStates),
+ mSamplerStateCache(kMaxSamplerStates, hashSamplerState, compareSamplerStates)
+{
+}
+
+RenderStateCache::~RenderStateCache()
+{
+ clear();
+}
+
+void RenderStateCache::initialize(ID3D11Device *device)
+{
+ clear();
+ mDevice = device;
+}
+
+void RenderStateCache::clear()
+{
+ for (BlendStateMap::iterator i = mBlendStateCache.begin(); i != mBlendStateCache.end(); i++)
+ {
+ i->second.first->Release();
+ }
+ mBlendStateCache.clear();
+
+ for (RasterizerStateMap::iterator i = mRasterizerStateCache.begin(); i != mRasterizerStateCache.end(); i++)
+ {
+ i->second.first->Release();
+ }
+ mRasterizerStateCache.clear();
+
+ for (DepthStencilStateMap::iterator i = mDepthStencilStateCache.begin(); i != mDepthStencilStateCache.end(); i++)
+ {
+ i->second.first->Release();
+ }
+ mDepthStencilStateCache.clear();
+
+ for (SamplerStateMap::iterator i = mSamplerStateCache.begin(); i != mSamplerStateCache.end(); i++)
+ {
+ i->second.first->Release();
+ }
+ mSamplerStateCache.clear();
+}
+
+std::size_t RenderStateCache::hashBlendState(const BlendStateKey &blendState)
+{
+ static const unsigned int seed = 0xABCDEF98;
+
+ std::size_t hash = 0;
+ MurmurHash3_x86_32(&blendState, sizeof(BlendStateKey), seed, &hash);
+ return hash;
+}
+
+bool RenderStateCache::compareBlendStates(const BlendStateKey &a, const BlendStateKey &b)
+{
+ return memcmp(&a, &b, sizeof(gl::BlendState)) == 0;
+}
+
+ID3D11BlendState *RenderStateCache::getBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState)
+{
+ if (!mDevice)
+ {
+ ERR("RenderStateCache is not initialized.");
+ return NULL;
+ }
+
+ bool mrt = false;
+
+ BlendStateKey key = { 0 };
+ key.blendState = blendState;
+ for (unsigned int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++)
+ {
+ gl::Renderbuffer *renderBuffer = framebuffer->getColorbuffer(i);
+ if (renderBuffer)
+ {
+ if (i > 0)
+ {
+ mrt = true;
+ }
+
+ GLenum internalFormat = renderBuffer->getInternalFormat();
+ key.rtChannels[i][0] = gl::GetRedSize(internalFormat) > 0;
+ key.rtChannels[i][1] = gl::GetGreenSize(internalFormat) > 0;
+ key.rtChannels[i][2] = gl::GetBlueSize(internalFormat) > 0;;
+ key.rtChannels[i][3] = gl::GetAlphaSize(internalFormat) > 0;
+ }
+ else
+ {
+ key.rtChannels[i][0] = false;
+ key.rtChannels[i][1] = false;
+ key.rtChannels[i][2] = false;
+ key.rtChannels[i][3] = false;
+ }
+ }
+
+ BlendStateMap::iterator i = mBlendStateCache.find(key);
+ if (i != mBlendStateCache.end())
+ {
+ BlendStateCounterPair &state = i->second;
+ state.second = mCounter++;
+ return state.first;
+ }
+ else
+ {
+ if (mBlendStateCache.size() >= kMaxBlendStates)
+ {
+ TRACE("Overflowed the limit of %u blend states, removing the least recently used "
+ "to make room.", kMaxBlendStates);
+
+ BlendStateMap::iterator leastRecentlyUsed = mBlendStateCache.begin();
+ for (BlendStateMap::iterator i = mBlendStateCache.begin(); i != mBlendStateCache.end(); i++)
+ {
+ if (i->second.second < leastRecentlyUsed->second.second)
+ {
+ leastRecentlyUsed = i;
+ }
+ }
+ leastRecentlyUsed->second.first->Release();
+ mBlendStateCache.erase(leastRecentlyUsed);
+ }
+
+ // Create a new blend state and insert it into the cache
+ D3D11_BLEND_DESC blendDesc = { 0 };
+ blendDesc.AlphaToCoverageEnable = blendState.sampleAlphaToCoverage;
+ blendDesc.IndependentBlendEnable = mrt ? TRUE : FALSE;
+
+ for (unsigned int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++)
+ {
+ D3D11_RENDER_TARGET_BLEND_DESC &rtBlend = blendDesc.RenderTarget[i];
+
+ rtBlend.BlendEnable = blendState.blend;
+ if (blendState.blend)
+ {
+ rtBlend.SrcBlend = gl_d3d11::ConvertBlendFunc(blendState.sourceBlendRGB, false);
+ rtBlend.DestBlend = gl_d3d11::ConvertBlendFunc(blendState.destBlendRGB, false);
+ rtBlend.BlendOp = gl_d3d11::ConvertBlendOp(blendState.blendEquationRGB);
+
+ rtBlend.SrcBlendAlpha = gl_d3d11::ConvertBlendFunc(blendState.sourceBlendAlpha, true);
+ rtBlend.DestBlendAlpha = gl_d3d11::ConvertBlendFunc(blendState.destBlendAlpha, true);
+ rtBlend.BlendOpAlpha = gl_d3d11::ConvertBlendOp(blendState.blendEquationAlpha);
+ }
+
+ rtBlend.RenderTargetWriteMask = gl_d3d11::ConvertColorMask(key.rtChannels[i][0] && blendState.colorMaskRed,
+ key.rtChannels[i][1] && blendState.colorMaskGreen,
+ key.rtChannels[i][2] && blendState.colorMaskBlue,
+ key.rtChannels[i][3] && blendState.colorMaskAlpha);
+ }
+
+ ID3D11BlendState *dx11BlendState = NULL;
+ HRESULT result = mDevice->CreateBlendState(&blendDesc, &dx11BlendState);
+ if (FAILED(result) || !dx11BlendState)
+ {
+ ERR("Unable to create a ID3D11BlendState, HRESULT: 0x%X.", result);
+ return NULL;
+ }
+
+ mBlendStateCache.insert(std::make_pair(key, std::make_pair(dx11BlendState, mCounter++)));
+
+ return dx11BlendState;
+ }
+}
+
+std::size_t RenderStateCache::hashRasterizerState(const RasterizerStateKey &rasterState)
+{
+ static const unsigned int seed = 0xABCDEF98;
+
+ std::size_t hash = 0;
+ MurmurHash3_x86_32(&rasterState, sizeof(RasterizerStateKey), seed, &hash);
+ return hash;
+}
+
+bool RenderStateCache::compareRasterizerStates(const RasterizerStateKey &a, const RasterizerStateKey &b)
+{
+ return memcmp(&a, &b, sizeof(RasterizerStateKey)) == 0;
+}
+
+ID3D11RasterizerState *RenderStateCache::getRasterizerState(const gl::RasterizerState &rasterState,
+ bool scissorEnabled, unsigned int depthSize)
+{
+ if (!mDevice)
+ {
+ ERR("RenderStateCache is not initialized.");
+ return NULL;
+ }
+
+ RasterizerStateKey key;
+ key.rasterizerState = rasterState;
+ key.scissorEnabled = scissorEnabled;
+ key.depthSize = depthSize;
+
+ RasterizerStateMap::iterator i = mRasterizerStateCache.find(key);
+ if (i != mRasterizerStateCache.end())
+ {
+ RasterizerStateCounterPair &state = i->second;
+ state.second = mCounter++;
+ return state.first;
+ }
+ else
+ {
+ if (mRasterizerStateCache.size() >= kMaxRasterizerStates)
+ {
+ TRACE("Overflowed the limit of %u rasterizer states, removing the least recently used "
+ "to make room.", kMaxRasterizerStates);
+
+ RasterizerStateMap::iterator leastRecentlyUsed = mRasterizerStateCache.begin();
+ for (RasterizerStateMap::iterator i = mRasterizerStateCache.begin(); i != mRasterizerStateCache.end(); i++)
+ {
+ if (i->second.second < leastRecentlyUsed->second.second)
+ {
+ leastRecentlyUsed = i;
+ }
+ }
+ leastRecentlyUsed->second.first->Release();
+ mRasterizerStateCache.erase(leastRecentlyUsed);
+ }
+
+ D3D11_CULL_MODE cullMode = gl_d3d11::ConvertCullMode(rasterState.cullFace, rasterState.cullMode);
+
+ // Disable culling if drawing points
+ if (rasterState.pointDrawMode)
+ {
+ cullMode = D3D11_CULL_NONE;
+ }
+
+ D3D11_RASTERIZER_DESC rasterDesc;
+ rasterDesc.FillMode = D3D11_FILL_SOLID;
+ rasterDesc.CullMode = cullMode;
+ rasterDesc.FrontCounterClockwise = (rasterState.frontFace == GL_CCW) ? FALSE: TRUE;
+ rasterDesc.DepthBias = ldexp(rasterState.polygonOffsetUnits, -static_cast<int>(depthSize));
+ rasterDesc.DepthBiasClamp = 0.0f; // MSDN documentation of DepthBiasClamp implies a value of zero will preform no clamping, must be tested though.
+ rasterDesc.SlopeScaledDepthBias = rasterState.polygonOffsetFactor;
+ rasterDesc.DepthClipEnable = TRUE;
+ rasterDesc.ScissorEnable = scissorEnabled ? TRUE : FALSE;
+ rasterDesc.MultisampleEnable = rasterState.multiSample;
+ rasterDesc.AntialiasedLineEnable = FALSE;
+
+ ID3D11RasterizerState *dx11RasterizerState = NULL;
+ HRESULT result = mDevice->CreateRasterizerState(&rasterDesc, &dx11RasterizerState);
+ if (FAILED(result) || !dx11RasterizerState)
+ {
+ ERR("Unable to create a ID3D11RasterizerState, HRESULT: 0x%X.", result);
+ return NULL;
+ }
+
+ mRasterizerStateCache.insert(std::make_pair(key, std::make_pair(dx11RasterizerState, mCounter++)));
+
+ return dx11RasterizerState;
+ }
+}
+
+std::size_t RenderStateCache::hashDepthStencilState(const gl::DepthStencilState &dsState)
+{
+ static const unsigned int seed = 0xABCDEF98;
+
+ std::size_t hash = 0;
+ MurmurHash3_x86_32(&dsState, sizeof(gl::DepthStencilState), seed, &hash);
+ return hash;
+}
+
+bool RenderStateCache::compareDepthStencilStates(const gl::DepthStencilState &a, const gl::DepthStencilState &b)
+{
+ return memcmp(&a, &b, sizeof(gl::DepthStencilState)) == 0;
+}
+
+ID3D11DepthStencilState *RenderStateCache::getDepthStencilState(const gl::DepthStencilState &dsState)
+{
+ if (!mDevice)
+ {
+ ERR("RenderStateCache is not initialized.");
+ return NULL;
+ }
+
+ DepthStencilStateMap::iterator i = mDepthStencilStateCache.find(dsState);
+ if (i != mDepthStencilStateCache.end())
+ {
+ DepthStencilStateCounterPair &state = i->second;
+ state.second = mCounter++;
+ return state.first;
+ }
+ else
+ {
+ if (mDepthStencilStateCache.size() >= kMaxDepthStencilStates)
+ {
+ TRACE("Overflowed the limit of %u depth stencil states, removing the least recently used "
+ "to make room.", kMaxDepthStencilStates);
+
+ DepthStencilStateMap::iterator leastRecentlyUsed = mDepthStencilStateCache.begin();
+ for (DepthStencilStateMap::iterator i = mDepthStencilStateCache.begin(); i != mDepthStencilStateCache.end(); i++)
+ {
+ if (i->second.second < leastRecentlyUsed->second.second)
+ {
+ leastRecentlyUsed = i;
+ }
+ }
+ leastRecentlyUsed->second.first->Release();
+ mDepthStencilStateCache.erase(leastRecentlyUsed);
+ }
+
+ D3D11_DEPTH_STENCIL_DESC dsDesc = { 0 };
+ dsDesc.DepthEnable = dsState.depthTest ? TRUE : FALSE;
+ dsDesc.DepthWriteMask = gl_d3d11::ConvertDepthMask(dsState.depthMask);
+ dsDesc.DepthFunc = gl_d3d11::ConvertComparison(dsState.depthFunc);
+ dsDesc.StencilEnable = dsState.stencilTest ? TRUE : FALSE;
+ dsDesc.StencilReadMask = gl_d3d11::ConvertStencilMask(dsState.stencilMask);
+ dsDesc.StencilWriteMask = gl_d3d11::ConvertStencilMask(dsState.stencilWritemask);
+ dsDesc.FrontFace.StencilFailOp = gl_d3d11::ConvertStencilOp(dsState.stencilFail);
+ dsDesc.FrontFace.StencilDepthFailOp = gl_d3d11::ConvertStencilOp(dsState.stencilPassDepthFail);
+ dsDesc.FrontFace.StencilPassOp = gl_d3d11::ConvertStencilOp(dsState.stencilPassDepthPass);
+ dsDesc.FrontFace.StencilFunc = gl_d3d11::ConvertComparison(dsState.stencilFunc);
+ dsDesc.BackFace.StencilFailOp = gl_d3d11::ConvertStencilOp(dsState.stencilBackFail);
+ dsDesc.BackFace.StencilDepthFailOp = gl_d3d11::ConvertStencilOp(dsState.stencilBackPassDepthFail);
+ dsDesc.BackFace.StencilPassOp = gl_d3d11::ConvertStencilOp(dsState.stencilBackPassDepthPass);
+ dsDesc.BackFace.StencilFunc = gl_d3d11::ConvertComparison(dsState.stencilBackFunc);
+
+ ID3D11DepthStencilState *dx11DepthStencilState = NULL;
+ HRESULT result = mDevice->CreateDepthStencilState(&dsDesc, &dx11DepthStencilState);
+ if (FAILED(result) || !dx11DepthStencilState)
+ {
+ ERR("Unable to create a ID3D11DepthStencilState, HRESULT: 0x%X.", result);
+ return NULL;
+ }
+
+ mDepthStencilStateCache.insert(std::make_pair(dsState, std::make_pair(dx11DepthStencilState, mCounter++)));
+
+ return dx11DepthStencilState;
+ }
+}
+
+std::size_t RenderStateCache::hashSamplerState(const gl::SamplerState &samplerState)
+{
+ static const unsigned int seed = 0xABCDEF98;
+
+ std::size_t hash = 0;
+ MurmurHash3_x86_32(&samplerState, sizeof(gl::SamplerState), seed, &hash);
+ return hash;
+}
+
+bool RenderStateCache::compareSamplerStates(const gl::SamplerState &a, const gl::SamplerState &b)
+{
+ return memcmp(&a, &b, sizeof(gl::SamplerState)) == 0;
+}
+
+ID3D11SamplerState *RenderStateCache::getSamplerState(const gl::SamplerState &samplerState)
+{
+ if (!mDevice)
+ {
+ ERR("RenderStateCache is not initialized.");
+ return NULL;
+ }
+
+ SamplerStateMap::iterator i = mSamplerStateCache.find(samplerState);
+ if (i != mSamplerStateCache.end())
+ {
+ SamplerStateCounterPair &state = i->second;
+ state.second = mCounter++;
+ return state.first;
+ }
+ else
+ {
+ if (mSamplerStateCache.size() >= kMaxSamplerStates)
+ {
+ TRACE("Overflowed the limit of %u sampler states, removing the least recently used "
+ "to make room.", kMaxSamplerStates);
+
+ SamplerStateMap::iterator leastRecentlyUsed = mSamplerStateCache.begin();
+ for (SamplerStateMap::iterator i = mSamplerStateCache.begin(); i != mSamplerStateCache.end(); i++)
+ {
+ if (i->second.second < leastRecentlyUsed->second.second)
+ {
+ leastRecentlyUsed = i;
+ }
+ }
+ leastRecentlyUsed->second.first->Release();
+ mSamplerStateCache.erase(leastRecentlyUsed);
+ }
+
+ D3D11_SAMPLER_DESC samplerDesc;
+ samplerDesc.Filter = gl_d3d11::ConvertFilter(samplerState.minFilter, samplerState.magFilter, samplerState.maxAnisotropy);
+ samplerDesc.AddressU = gl_d3d11::ConvertTextureWrap(samplerState.wrapS);
+ samplerDesc.AddressV = gl_d3d11::ConvertTextureWrap(samplerState.wrapT);
+ samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
+ samplerDesc.MipLODBias = static_cast<float>(samplerState.lodOffset);
+ samplerDesc.MaxAnisotropy = samplerState.maxAnisotropy;
+ samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
+ samplerDesc.BorderColor[0] = 0.0f;
+ samplerDesc.BorderColor[1] = 0.0f;
+ samplerDesc.BorderColor[2] = 0.0f;
+ samplerDesc.BorderColor[3] = 0.0f;
+ samplerDesc.MinLOD = gl_d3d11::ConvertMinLOD(samplerState.minFilter, samplerState.lodOffset);
+ samplerDesc.MaxLOD = gl_d3d11::ConvertMaxLOD(samplerState.minFilter, samplerState.lodOffset);
+
+ ID3D11SamplerState *dx11SamplerState = NULL;
+ HRESULT result = mDevice->CreateSamplerState(&samplerDesc, &dx11SamplerState);
+ if (FAILED(result) || !dx11SamplerState)
+ {
+ ERR("Unable to create a ID3D11DepthStencilState, HRESULT: 0x%X.", result);
+ return NULL;
+ }
+
+ mSamplerStateCache.insert(std::make_pair(samplerState, std::make_pair(dx11SamplerState, mCounter++)));
+
+ return dx11SamplerState;
+ }
+}
+
+}
</ins><span class="cx">\ No newline at end of file
</span><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/RenderStateCache.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11RenderStateCacheh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/RenderStateCache.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/RenderStateCache.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/RenderStateCache.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,111 @@
</span><ins>+//
+// Copyright (c) 2012-2013 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.
+//
+
+// RenderStateCache.h: Defines rx::RenderStateCache, a cache of Direct3D render
+// state objects.
+
+#ifndef LIBGLESV2_RENDERER_RENDERSTATECACHE_H_
+#define LIBGLESV2_RENDERER_RENDERSTATECACHE_H_
+
+#include "libGLESv2/angletypes.h"
+#include "common/angleutils.h"
+
+namespace gl
+{
+class Framebuffer;
+}
+
+namespace rx
+{
+
+class RenderStateCache
+{
+ public:
+ RenderStateCache();
+ virtual ~RenderStateCache();
+
+ void initialize(ID3D11Device *device);
+ void clear();
+
+ // Increments refcount on the returned blend state, Release() must be called.
+ ID3D11BlendState *getBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState);
+ ID3D11RasterizerState *getRasterizerState(const gl::RasterizerState &rasterState,
+ bool scissorEnabled, unsigned int depthSize);
+ ID3D11DepthStencilState *getDepthStencilState(const gl::DepthStencilState &dsState);
+ ID3D11SamplerState *getSamplerState(const gl::SamplerState &samplerState);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(RenderStateCache);
+
+ unsigned long long mCounter;
+
+ // Blend state cache
+ struct BlendStateKey
+ {
+ gl::BlendState blendState;
+ bool rtChannels[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT][4];
+ };
+ static std::size_t hashBlendState(const BlendStateKey &blendState);
+ static bool compareBlendStates(const BlendStateKey &a, const BlendStateKey &b);
+ static const unsigned int kMaxBlendStates;
+
+ typedef std::size_t (*BlendStateHashFunction)(const BlendStateKey &);
+ typedef bool (*BlendStateEqualityFunction)(const BlendStateKey &, const BlendStateKey &);
+ typedef std::pair<ID3D11BlendState*, unsigned long long> BlendStateCounterPair;
+ typedef std::unordered_map<BlendStateKey, BlendStateCounterPair, BlendStateHashFunction, BlendStateEqualityFunction> BlendStateMap;
+ BlendStateMap mBlendStateCache;
+
+ // Rasterizer state cache
+ struct RasterizerStateKey
+ {
+ gl::RasterizerState rasterizerState;
+ bool scissorEnabled;
+ unsigned int depthSize;
+ };
+ static std::size_t hashRasterizerState(const RasterizerStateKey &rasterState);
+ static bool compareRasterizerStates(const RasterizerStateKey &a, const RasterizerStateKey &b);
+ static const unsigned int kMaxRasterizerStates;
+
+ typedef std::size_t (*RasterizerStateHashFunction)(const RasterizerStateKey &);
+ typedef bool (*RasterizerStateEqualityFunction)(const RasterizerStateKey &, const RasterizerStateKey &);
+ typedef std::pair<ID3D11RasterizerState*, unsigned long long> RasterizerStateCounterPair;
+ typedef std::unordered_map<RasterizerStateKey, RasterizerStateCounterPair, RasterizerStateHashFunction, RasterizerStateEqualityFunction> RasterizerStateMap;
+ RasterizerStateMap mRasterizerStateCache;
+
+ // Depth stencil state cache
+ static std::size_t hashDepthStencilState(const gl::DepthStencilState &dsState);
+ static bool compareDepthStencilStates(const gl::DepthStencilState &a, const gl::DepthStencilState &b);
+ static const unsigned int kMaxDepthStencilStates;
+
+ typedef std::size_t (*DepthStencilStateHashFunction)(const gl::DepthStencilState &);
+ typedef bool (*DepthStencilStateEqualityFunction)(const gl::DepthStencilState &, const gl::DepthStencilState &);
+ typedef std::pair<ID3D11DepthStencilState*, unsigned long long> DepthStencilStateCounterPair;
+ typedef std::unordered_map<gl::DepthStencilState,
+ DepthStencilStateCounterPair,
+ DepthStencilStateHashFunction,
+ DepthStencilStateEqualityFunction> DepthStencilStateMap;
+ DepthStencilStateMap mDepthStencilStateCache;
+
+ // Sample state cache
+ static std::size_t hashSamplerState(const gl::SamplerState &samplerState);
+ static bool compareSamplerStates(const gl::SamplerState &a, const gl::SamplerState &b);
+ static const unsigned int kMaxSamplerStates;
+
+ typedef std::size_t (*SamplerStateHashFunction)(const gl::SamplerState &);
+ typedef bool (*SamplerStateEqualityFunction)(const gl::SamplerState &, const gl::SamplerState &);
+ typedef std::pair<ID3D11SamplerState*, unsigned long long> SamplerStateCounterPair;
+ typedef std::unordered_map<gl::SamplerState,
+ SamplerStateCounterPair,
+ SamplerStateHashFunction,
+ SamplerStateEqualityFunction> SamplerStateMap;
+ SamplerStateMap mSamplerStateCache;
+
+ ID3D11Device *mDevice;
+};
+
+}
+
+#endif // LIBGLESV2_RENDERER_RENDERSTATECACHE_H_
</ins><span class="cx">\ No newline at end of file
</span><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/RenderStateCache.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11RenderTarget11cpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/RenderTarget11.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/RenderTarget11.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/RenderTarget11.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,355 @@
</span><ins>+#include "precompiled.h"
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RenderTarget11.cpp: Implements a DX11-specific wrapper for ID3D11View pointers
+// retained by Renderbuffers.
+
+#include "libGLESv2/renderer/d3d11/RenderTarget11.h"
+#include "libGLESv2/renderer/d3d11/Renderer11.h"
+
+#include "libGLESv2/renderer/d3d11/renderer11_utils.h"
+#include "libGLESv2/main.h"
+
+namespace rx
+{
+
+static unsigned int getRTVSubresourceIndex(ID3D11Texture2D *texture, ID3D11RenderTargetView *view)
+{
+ D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+ view->GetDesc(&rtvDesc);
+
+ D3D11_TEXTURE2D_DESC texDesc;
+ texture->GetDesc(&texDesc);
+
+ unsigned int mipSlice = 0;
+ unsigned int arraySlice = 0;
+ unsigned int mipLevels = texDesc.MipLevels;
+
+ switch (rtvDesc.ViewDimension)
+ {
+ case D3D11_RTV_DIMENSION_TEXTURE1D:
+ mipSlice = rtvDesc.Texture1D.MipSlice;
+ arraySlice = 0;
+ break;
+
+ case D3D11_RTV_DIMENSION_TEXTURE1DARRAY:
+ mipSlice = rtvDesc.Texture1DArray.MipSlice;
+ arraySlice = rtvDesc.Texture1DArray.FirstArraySlice;
+ break;
+
+ case D3D11_RTV_DIMENSION_TEXTURE2D:
+ mipSlice = rtvDesc.Texture2D.MipSlice;
+ arraySlice = 0;
+ break;
+
+ case D3D11_RTV_DIMENSION_TEXTURE2DARRAY:
+ mipSlice = rtvDesc.Texture2DArray.MipSlice;
+ arraySlice = rtvDesc.Texture2DArray.FirstArraySlice;
+ break;
+
+ case D3D11_RTV_DIMENSION_TEXTURE2DMS:
+ mipSlice = 0;
+ arraySlice = 0;
+ break;
+
+ case D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY:
+ mipSlice = 0;
+ arraySlice = rtvDesc.Texture2DMSArray.FirstArraySlice;
+ break;
+
+ case D3D11_RTV_DIMENSION_TEXTURE3D:
+ mipSlice = rtvDesc.Texture3D.MipSlice;
+ arraySlice = 0;
+ break;
+
+ case D3D11_RTV_DIMENSION_UNKNOWN:
+ case D3D11_RTV_DIMENSION_BUFFER:
+ UNIMPLEMENTED();
+ break;
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ return D3D11CalcSubresource(mipSlice, arraySlice, mipLevels);
+}
+
+static unsigned int getDSVSubresourceIndex(ID3D11Texture2D *texture, ID3D11DepthStencilView *view)
+{
+ D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
+ view->GetDesc(&dsvDesc);
+
+ D3D11_TEXTURE2D_DESC texDesc;
+ texture->GetDesc(&texDesc);
+
+ unsigned int mipSlice = 0;
+ unsigned int arraySlice = 0;
+ unsigned int mipLevels = texDesc.MipLevels;
+
+ switch (dsvDesc.ViewDimension)
+ {
+ case D3D11_DSV_DIMENSION_TEXTURE1D:
+ mipSlice = dsvDesc.Texture1D.MipSlice;
+ arraySlice = 0;
+ break;
+
+ case D3D11_DSV_DIMENSION_TEXTURE1DARRAY:
+ mipSlice = dsvDesc.Texture1DArray.MipSlice;
+ arraySlice = dsvDesc.Texture1DArray.FirstArraySlice;
+ break;
+
+ case D3D11_DSV_DIMENSION_TEXTURE2D:
+ mipSlice = dsvDesc.Texture2D.MipSlice;
+ arraySlice = 0;
+ break;
+
+ case D3D11_DSV_DIMENSION_TEXTURE2DARRAY:
+ mipSlice = dsvDesc.Texture2DArray.MipSlice;
+ arraySlice = dsvDesc.Texture2DArray.FirstArraySlice;
+ break;
+
+ case D3D11_DSV_DIMENSION_TEXTURE2DMS:
+ mipSlice = 0;
+ arraySlice = 0;
+ break;
+
+ case D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY:
+ mipSlice = 0;
+ arraySlice = dsvDesc.Texture2DMSArray.FirstArraySlice;
+ break;
+
+ case D3D11_RTV_DIMENSION_UNKNOWN:
+ UNIMPLEMENTED();
+ break;
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ return D3D11CalcSubresource(mipSlice, arraySlice, mipLevels);
+}
+
+RenderTarget11::RenderTarget11(Renderer *renderer, ID3D11RenderTargetView *rtv, ID3D11Texture2D *tex, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height)
+{
+ mRenderer = Renderer11::makeRenderer11(renderer);
+ mTexture = tex;
+ mRenderTarget = rtv;
+ mDepthStencil = NULL;
+ mShaderResource = srv;
+ mSubresourceIndex = 0;
+
+ if (mRenderTarget && mTexture)
+ {
+ D3D11_RENDER_TARGET_VIEW_DESC desc;
+ mRenderTarget->GetDesc(&desc);
+
+ D3D11_TEXTURE2D_DESC texDesc;
+ mTexture->GetDesc(&texDesc);
+
+ mSubresourceIndex = getRTVSubresourceIndex(mTexture, mRenderTarget);
+ mWidth = width;
+ mHeight = height;
+ mSamples = (texDesc.SampleDesc.Count > 1) ? texDesc.SampleDesc.Count : 0;
+
+ mInternalFormat = d3d11_gl::ConvertTextureInternalFormat(desc.Format);
+ mActualFormat = d3d11_gl::ConvertTextureInternalFormat(desc.Format);
+ }
+}
+
+RenderTarget11::RenderTarget11(Renderer *renderer, ID3D11DepthStencilView *dsv, ID3D11Texture2D *tex, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height)
+{
+ mRenderer = Renderer11::makeRenderer11(renderer);
+ mTexture = tex;
+ mRenderTarget = NULL;
+ mDepthStencil = dsv;
+ mShaderResource = srv;
+ mSubresourceIndex = 0;
+
+ if (mDepthStencil && mTexture)
+ {
+ D3D11_DEPTH_STENCIL_VIEW_DESC desc;
+ mDepthStencil->GetDesc(&desc);
+
+ D3D11_TEXTURE2D_DESC texDesc;
+ mTexture->GetDesc(&texDesc);
+
+ mSubresourceIndex = getDSVSubresourceIndex(mTexture, mDepthStencil);
+ mWidth = width;
+ mHeight = height;
+ mSamples = (texDesc.SampleDesc.Count > 1) ? texDesc.SampleDesc.Count : 0;
+
+ mInternalFormat = d3d11_gl::ConvertTextureInternalFormat(desc.Format);
+ mActualFormat = d3d11_gl::ConvertTextureInternalFormat(desc.Format);
+ }
+}
+
+RenderTarget11::RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height, GLenum format, GLsizei samples, bool depth)
+{
+ mRenderer = Renderer11::makeRenderer11(renderer);
+ mTexture = NULL;
+ mRenderTarget = NULL;
+ mDepthStencil = NULL;
+ mShaderResource = NULL;
+
+ DXGI_FORMAT requestedFormat = gl_d3d11::ConvertRenderbufferFormat(format);
+
+ int supportedSamples = mRenderer->getNearestSupportedSamples(requestedFormat, samples);
+ if (supportedSamples < 0)
+ {
+ gl::error(GL_OUT_OF_MEMORY);
+ return;
+ }
+
+ if (width > 0 && height > 0)
+ {
+ // Create texture resource
+ D3D11_TEXTURE2D_DESC desc;
+ desc.Width = width;
+ desc.Height = height;
+ desc.MipLevels = 1;
+ desc.ArraySize = 1;
+ desc.Format = requestedFormat;
+ desc.SampleDesc.Count = (supportedSamples == 0) ? 1 : supportedSamples;
+ desc.SampleDesc.Quality = 0;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.CPUAccessFlags = 0;
+ desc.MiscFlags = 0;
+ desc.BindFlags = (depth ? D3D11_BIND_DEPTH_STENCIL : (D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE));
+
+ ID3D11Device *device = mRenderer->getDevice();
+ HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
+
+ if (result == E_OUTOFMEMORY)
+ {
+ gl::error(GL_OUT_OF_MEMORY);
+ return;
+ }
+ ASSERT(SUCCEEDED(result));
+
+ if (depth)
+ {
+ D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
+ dsvDesc.Format = requestedFormat;
+ dsvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_DSV_DIMENSION_TEXTURE2D : D3D11_DSV_DIMENSION_TEXTURE2DMS;
+ dsvDesc.Texture2D.MipSlice = 0;
+ dsvDesc.Flags = 0;
+ result = device->CreateDepthStencilView(mTexture, &dsvDesc, &mDepthStencil);
+
+ if (result == E_OUTOFMEMORY)
+ {
+ mTexture->Release();
+ mTexture = NULL;
+ gl::error(GL_OUT_OF_MEMORY);
+ }
+ ASSERT(SUCCEEDED(result));
+ }
+ else
+ {
+ D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+ rtvDesc.Format = requestedFormat;
+ rtvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_RTV_DIMENSION_TEXTURE2D : D3D11_RTV_DIMENSION_TEXTURE2DMS;
+ rtvDesc.Texture2D.MipSlice = 0;
+ result = device->CreateRenderTargetView(mTexture, &rtvDesc, &mRenderTarget);
+
+ if (result == E_OUTOFMEMORY)
+ {
+ mTexture->Release();
+ mTexture = NULL;
+ gl::error(GL_OUT_OF_MEMORY);
+ return;
+ }
+ ASSERT(SUCCEEDED(result));
+
+ D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+ srvDesc.Format = requestedFormat;
+ srvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_SRV_DIMENSION_TEXTURE2D : D3D11_SRV_DIMENSION_TEXTURE2DMS;
+ srvDesc.Texture2D.MostDetailedMip = 0;
+ srvDesc.Texture2D.MipLevels = 1;
+ result = device->CreateShaderResourceView(mTexture, &srvDesc, &mShaderResource);
+
+ if (result == E_OUTOFMEMORY)
+ {
+ mTexture->Release();
+ mTexture = NULL;
+ mRenderTarget->Release();
+ mRenderTarget = NULL;
+ gl::error(GL_OUT_OF_MEMORY);
+ return;
+ }
+ ASSERT(SUCCEEDED(result));
+ }
+ }
+
+ mWidth = width;
+ mHeight = height;
+ mInternalFormat = format;
+ mSamples = supportedSamples;
+ mActualFormat = d3d11_gl::ConvertTextureInternalFormat(requestedFormat);
+ mSubresourceIndex = D3D11CalcSubresource(0, 0, 1);
+}
+
+RenderTarget11::~RenderTarget11()
+{
+ if (mTexture)
+ {
+ mTexture->Release();
+ mTexture = NULL;
+ }
+
+ if (mRenderTarget)
+ {
+ mRenderTarget->Release();
+ mRenderTarget = NULL;
+ }
+
+ if (mDepthStencil)
+ {
+ mDepthStencil->Release();
+ mDepthStencil = NULL;
+ }
+
+ if (mShaderResource)
+ {
+ mShaderResource->Release();
+ mShaderResource = NULL;
+ }
+}
+
+RenderTarget11 *RenderTarget11::makeRenderTarget11(RenderTarget *target)
+{
+ ASSERT(HAS_DYNAMIC_TYPE(rx::RenderTarget11*, target));
+ return static_cast<rx::RenderTarget11*>(target);
+}
+
+ID3D11Texture2D *RenderTarget11::getTexture() const
+{
+ return mTexture;
+}
+
+ID3D11RenderTargetView *RenderTarget11::getRenderTargetView() const
+{
+ return mRenderTarget;
+}
+
+ID3D11DepthStencilView *RenderTarget11::getDepthStencilView() const
+{
+ return mDepthStencil;
+}
+
+ID3D11ShaderResourceView *RenderTarget11::getShaderResourceView() const
+{
+ return mShaderResource;
+}
+
+unsigned int RenderTarget11::getSubresourceIndex() const
+{
+ return mSubresourceIndex;
+}
+
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/RenderTarget11.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11RenderTarget11h"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/RenderTarget11.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/RenderTarget11.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/RenderTarget11.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,51 @@
</span><ins>+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RenderTarget11.h: Defines a DX11-specific wrapper for ID3D11View pointers
+// retained by Renderbuffers.
+
+#ifndef LIBGLESV2_RENDERER_RENDERTARGET11_H_
+#define LIBGLESV2_RENDERER_RENDERTARGET11_H_
+
+#include "libGLESv2/renderer/RenderTarget.h"
+
+namespace rx
+{
+class Renderer;
+class Renderer11;
+
+class RenderTarget11 : public RenderTarget
+{
+ public:
+ RenderTarget11(Renderer *renderer, ID3D11RenderTargetView *rtv, ID3D11Texture2D *tex, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height);
+ RenderTarget11(Renderer *renderer, ID3D11DepthStencilView *dsv, ID3D11Texture2D *tex, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height);
+ RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height, GLenum format, GLsizei samples, bool depth);
+ virtual ~RenderTarget11();
+
+ static RenderTarget11 *makeRenderTarget11(RenderTarget *renderTarget);
+
+ ID3D11Texture2D *getTexture() const;
+ ID3D11RenderTargetView *getRenderTargetView() const;
+ ID3D11DepthStencilView *getDepthStencilView() const;
+ ID3D11ShaderResourceView *getShaderResourceView() const;
+
+ unsigned int getSubresourceIndex() const;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(RenderTarget11);
+
+ unsigned int mSubresourceIndex;
+ ID3D11Texture2D *mTexture;
+ ID3D11RenderTargetView *mRenderTarget;
+ ID3D11DepthStencilView *mDepthStencil;
+ ID3D11ShaderResourceView *mShaderResource;
+
+ Renderer11 *mRenderer;
+};
+
+}
+
+#endif LIBGLESV2_RENDERER_RENDERTARGET11_H_
</ins><span class="cx">\ No newline at end of file
</span><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/RenderTarget11.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11Renderer11cpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/Renderer11.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/Renderer11.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/Renderer11.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,3623 @@
</span><ins>+#include "precompiled.h"
+//
+// Copyright (c) 2012-2013 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.
+//
+
+// Renderer11.cpp: Implements a back-end specific class for the D3D11 renderer.
+
+#include "libGLESv2/main.h"
+#include "libGLESv2/utilities.h"
+#include "libGLESv2/Buffer.h"
+#include "libGLESv2/ProgramBinary.h"
+#include "libGLESv2/Framebuffer.h"
+#include "libGLESv2/Renderbuffer.h"
+#include "libGLESv2/renderer/d3d11/Renderer11.h"
+#include "libGLESv2/renderer/d3d11/RenderTarget11.h"
+#include "libGLESv2/renderer/d3d11/renderer11_utils.h"
+#include "libGLESv2/renderer/d3d11/ShaderExecutable11.h"
+#include "libGLESv2/renderer/d3d11/SwapChain11.h"
+#include "libGLESv2/renderer/d3d11/Image11.h"
+#include "libGLESv2/renderer/d3d11/VertexBuffer11.h"
+#include "libGLESv2/renderer/d3d11/IndexBuffer11.h"
+#include "libGLESv2/renderer/d3d11/BufferStorage11.h"
+#include "libGLESv2/renderer/VertexDataManager.h"
+#include "libGLESv2/renderer/IndexDataManager.h"
+#include "libGLESv2/renderer/d3d11/TextureStorage11.h"
+#include "libGLESv2/renderer/d3d11/Query11.h"
+#include "libGLESv2/renderer/d3d11/Fence11.h"
+
+#include "libGLESv2/renderer/d3d11/shaders/compiled/passthrough11vs.h"
+#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgba11ps.h"
+#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgb11ps.h"
+#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughlum11ps.h"
+#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughlumalpha11ps.h"
+
+#include "libGLESv2/renderer/d3d11/shaders/compiled/clear11vs.h"
+#include "libGLESv2/renderer/d3d11/shaders/compiled/clearsingle11ps.h"
+#include "libGLESv2/renderer/d3d11/shaders/compiled/clearmultiple11ps.h"
+
+#include "libEGL/Display.h"
+
+// Enable ANGLE_SKIP_DXGI_1_2_CHECK if there is not a possibility of using cross-process
+// HWNDs or the Windows 7 Platform Update (KB2670838) is expected to be installed.
+#ifndef ANGLE_SKIP_DXGI_1_2_CHECK
+#define ANGLE_SKIP_DXGI_1_2_CHECK 0
+#endif
+
+#ifdef _DEBUG
+// this flag enables suppressing some spurious warnings that pop up in certain WebGL samples
+// and conformance tests. to enable all warnings, remove this define.
+#define ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS 1
+#endif
+
+namespace rx
+{
+static const DXGI_FORMAT RenderTargetFormats[] =
+ {
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM
+ };
+
+static const DXGI_FORMAT DepthStencilFormats[] =
+ {
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_D24_UNORM_S8_UINT,
+ DXGI_FORMAT_D16_UNORM
+ };
+
+enum
+{
+ MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 = 16
+};
+
+Renderer11::Renderer11(egl::Display *display, HDC hDc) : Renderer(display), mDc(hDc)
+{
+ mVertexDataManager = NULL;
+ mIndexDataManager = NULL;
+
+ mLineLoopIB = NULL;
+ mTriangleFanIB = NULL;
+
+ mCopyResourcesInitialized = false;
+ mCopyVB = NULL;
+ mCopySampler = NULL;
+ mCopyIL = NULL;
+ mCopyVS = NULL;
+ mCopyRGBAPS = NULL;
+ mCopyRGBPS = NULL;
+ mCopyLumPS = NULL;
+ mCopyLumAlphaPS = NULL;
+
+ mClearResourcesInitialized = false;
+ mClearVB = NULL;
+ mClearIL = NULL;
+ mClearVS = NULL;
+ mClearSinglePS = NULL;
+ mClearMultiplePS = NULL;
+ mClearScissorRS = NULL;
+ mClearNoScissorRS = NULL;
+
+ mSyncQuery = NULL;
+
+ mD3d11Module = NULL;
+ mDxgiModule = NULL;
+
+ mDeviceLost = false;
+
+ mMaxSupportedSamples = 0;
+
+ mDevice = NULL;
+ mDeviceContext = NULL;
+ mDxgiAdapter = NULL;
+ mDxgiFactory = NULL;
+
+ mDriverConstantBufferVS = NULL;
+ mDriverConstantBufferPS = NULL;
+
+ mBGRATextureSupport = false;
+
+ mIsGeometryShaderActive = false;
+}
+
+Renderer11::~Renderer11()
+{
+ release();
+}
+
+Renderer11 *Renderer11::makeRenderer11(Renderer *renderer)
+{
+ ASSERT(HAS_DYNAMIC_TYPE(rx::Renderer11*, renderer));
+ return static_cast<rx::Renderer11*>(renderer);
+}
+
+#ifndef __d3d11_1_h__
+#define D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET ((D3D11_MESSAGE_ID)3146081)
+#endif
+
+EGLint Renderer11::initialize()
+{
+ if (!initializeCompiler())
+ {
+ return EGL_NOT_INITIALIZED;
+ }
+
+ mDxgiModule = LoadLibrary(TEXT("dxgi.dll"));
+ mD3d11Module = LoadLibrary(TEXT("d3d11.dll"));
+
+ if (mD3d11Module == NULL || mDxgiModule == NULL)
+ {
+ ERR("Could not load D3D11 or DXGI library - aborting!\n");
+ return EGL_NOT_INITIALIZED;
+ }
+
+ // create the D3D11 device
+ ASSERT(mDevice == NULL);
+ PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice");
+
+ if (D3D11CreateDevice == NULL)
+ {
+ ERR("Could not retrieve D3D11CreateDevice address - aborting!\n");
+ return EGL_NOT_INITIALIZED;
+ }
+
+ D3D_FEATURE_LEVEL featureLevels[] =
+ {
+ D3D_FEATURE_LEVEL_11_0,
+ D3D_FEATURE_LEVEL_10_1,
+ D3D_FEATURE_LEVEL_10_0,
+ };
+
+ HRESULT result = S_OK;
+
+#ifdef _DEBUG
+ result = D3D11CreateDevice(NULL,
+ D3D_DRIVER_TYPE_HARDWARE,
+ NULL,
+ D3D11_CREATE_DEVICE_DEBUG,
+ featureLevels,
+ ArraySize(featureLevels),
+ D3D11_SDK_VERSION,
+ &mDevice,
+ &mFeatureLevel,
+ &mDeviceContext);
+
+ if (!mDevice || FAILED(result))
+ {
+ ERR("Failed creating Debug D3D11 device - falling back to release runtime.\n");
+ }
+
+ if (!mDevice || FAILED(result))
+#endif
+ {
+ result = D3D11CreateDevice(NULL,
+ D3D_DRIVER_TYPE_HARDWARE,
+ NULL,
+ 0,
+ featureLevels,
+ ArraySize(featureLevels),
+ D3D11_SDK_VERSION,
+ &mDevice,
+ &mFeatureLevel,
+ &mDeviceContext);
+
+ if (!mDevice || FAILED(result))
+ {
+ ERR("Could not create D3D11 device - aborting!\n");
+ return EGL_NOT_INITIALIZED; // Cleanup done by destructor through glDestroyRenderer
+ }
+ }
+
+#if !ANGLE_SKIP_DXGI_1_2_CHECK
+ // In order to create a swap chain for an HWND owned by another process, DXGI 1.2 is required.
+ // The easiest way to check is to query for a IDXGIDevice2.
+ bool requireDXGI1_2 = false;
+ HWND hwnd = WindowFromDC(mDc);
+ if (hwnd)
+ {
+ DWORD currentProcessId = GetCurrentProcessId();
+ DWORD wndProcessId;
+ GetWindowThreadProcessId(hwnd, &wndProcessId);
+ requireDXGI1_2 = (currentProcessId != wndProcessId);
+ }
+ else
+ {
+ requireDXGI1_2 = true;
+ }
+
+ if (requireDXGI1_2)
+ {
+ IDXGIDevice2 *dxgiDevice2 = NULL;
+ result = mDevice->QueryInterface(__uuidof(IDXGIDevice2), (void**)&dxgiDevice2);
+ if (FAILED(result))
+ {
+ ERR("DXGI 1.2 required to present to HWNDs owned by another process.\n");
+ return EGL_NOT_INITIALIZED;
+ }
+ SafeRelease(dxgiDevice2);
+ }
+#endif
+
+ IDXGIDevice *dxgiDevice = NULL;
+ result = mDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgiDevice);
+
+ if (FAILED(result))
+ {
+ ERR("Could not query DXGI device - aborting!\n");
+ return EGL_NOT_INITIALIZED;
+ }
+
+ result = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&mDxgiAdapter);
+
+ if (FAILED(result))
+ {
+ ERR("Could not retrieve DXGI adapter - aborting!\n");
+ return EGL_NOT_INITIALIZED;
+ }
+
+ dxgiDevice->Release();
+
+ mDxgiAdapter->GetDesc(&mAdapterDescription);
+ memset(mDescription, 0, sizeof(mDescription));
+ wcstombs(mDescription, mAdapterDescription.Description, sizeof(mDescription) - 1);
+
+ result = mDxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void**)&mDxgiFactory);
+
+ if (!mDxgiFactory || FAILED(result))
+ {
+ ERR("Could not create DXGI factory - aborting!\n");
+ return EGL_NOT_INITIALIZED;
+ }
+
+ // Disable some spurious D3D11 debug warnings to prevent them from flooding the output log
+#if defined(ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS) && defined(_DEBUG)
+ ID3D11InfoQueue *infoQueue;
+ result = mDevice->QueryInterface(__uuidof(ID3D11InfoQueue), (void **)&infoQueue);
+
+ if (SUCCEEDED(result))
+ {
+ D3D11_MESSAGE_ID hideMessages[] =
+ {
+ D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET
+ };
+
+ D3D11_INFO_QUEUE_FILTER filter = {0};
+ filter.DenyList.NumIDs = ArraySize(hideMessages);
+ filter.DenyList.pIDList = hideMessages;
+
+ infoQueue->AddStorageFilterEntries(&filter);
+
+ infoQueue->Release();
+ }
+#endif
+
+ unsigned int maxSupportedSamples = 0;
+ unsigned int rtFormatCount = ArraySize(RenderTargetFormats);
+ unsigned int dsFormatCount = ArraySize(DepthStencilFormats);
+ for (unsigned int i = 0; i < rtFormatCount + dsFormatCount; ++i)
+ {
+ DXGI_FORMAT format = (i < rtFormatCount) ? RenderTargetFormats[i] : DepthStencilFormats[i - rtFormatCount];
+ if (format != DXGI_FORMAT_UNKNOWN)
+ {
+ UINT formatSupport;
+ result = mDevice->CheckFormatSupport(format, &formatSupport);
+ if (SUCCEEDED(result) && (formatSupport & D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET))
+ {
+ MultisampleSupportInfo supportInfo;
+
+ for (unsigned int j = 1; j <= D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; j++)
+ {
+ result = mDevice->CheckMultisampleQualityLevels(format, j, &supportInfo.qualityLevels[j - 1]);
+ if (SUCCEEDED(result) && supportInfo.qualityLevels[j - 1] > 0)
+ {
+ maxSupportedSamples = std::max(j, maxSupportedSamples);
+ }
+ else
+ {
+ supportInfo.qualityLevels[j - 1] = 0;
+ }
+ }
+
+ mMultisampleSupportMap.insert(std::make_pair(format, supportInfo));
+ }
+ }
+ }
+ mMaxSupportedSamples = maxSupportedSamples;
+
+ initializeDevice();
+
+ // BGRA texture support is optional in feature levels 10 and 10_1
+ UINT formatSupport;
+ result = mDevice->CheckFormatSupport(DXGI_FORMAT_B8G8R8A8_UNORM, &formatSupport);
+ if (FAILED(result))
+ {
+ ERR("Error checking BGRA format support: 0x%08X", result);
+ }
+ else
+ {
+ const int flags = (D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_RENDER_TARGET);
+ mBGRATextureSupport = (formatSupport & flags) == flags;
+ }
+
+ // Check floating point texture support
+ static const unsigned int requiredTextureFlags = D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_TEXTURECUBE;
+ static const unsigned int requiredRenderableFlags = D3D11_FORMAT_SUPPORT_RENDER_TARGET;
+ static const unsigned int requiredFilterFlags = D3D11_FORMAT_SUPPORT_SHADER_SAMPLE;
+
+ DXGI_FORMAT float16Formats[] =
+ {
+ DXGI_FORMAT_R16_FLOAT,
+ DXGI_FORMAT_R16G16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ };
+
+ DXGI_FORMAT float32Formats[] =
+ {
+ DXGI_FORMAT_R32_FLOAT,
+ DXGI_FORMAT_R32G32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ };
+
+ mFloat16TextureSupport = true;
+ mFloat16FilterSupport = true;
+ mFloat16RenderSupport = true;
+ for (unsigned int i = 0; i < ArraySize(float16Formats); i++)
+ {
+ if (SUCCEEDED(mDevice->CheckFormatSupport(float16Formats[i], &formatSupport)))
+ {
+ mFloat16TextureSupport = mFloat16TextureSupport && (formatSupport & requiredTextureFlags) == requiredTextureFlags;
+ mFloat16FilterSupport = mFloat16FilterSupport && (formatSupport & requiredFilterFlags) == requiredFilterFlags;
+ mFloat16RenderSupport = mFloat16RenderSupport && (formatSupport & requiredRenderableFlags) == requiredRenderableFlags;
+ }
+ else
+ {
+ mFloat16TextureSupport = false;
+ mFloat16RenderSupport = false;
+ mFloat16FilterSupport = false;
+ }
+ }
+
+ mFloat32TextureSupport = true;
+ mFloat32FilterSupport = true;
+ mFloat32RenderSupport = true;
+ for (unsigned int i = 0; i < ArraySize(float32Formats); i++)
+ {
+ if (SUCCEEDED(mDevice->CheckFormatSupport(float32Formats[i], &formatSupport)))
+ {
+ mFloat32TextureSupport = mFloat32TextureSupport && (formatSupport & requiredTextureFlags) == requiredTextureFlags;
+ mFloat32FilterSupport = mFloat32FilterSupport && (formatSupport & requiredFilterFlags) == requiredFilterFlags;
+ mFloat32RenderSupport = mFloat32RenderSupport && (formatSupport & requiredRenderableFlags) == requiredRenderableFlags;
+ }
+ else
+ {
+ mFloat32TextureSupport = false;
+ mFloat32FilterSupport = false;
+ mFloat32RenderSupport = false;
+ }
+ }
+
+ // Check compressed texture support
+ const unsigned int requiredCompressedTextureFlags = D3D11_FORMAT_SUPPORT_TEXTURE2D;
+
+ if (SUCCEEDED(mDevice->CheckFormatSupport(DXGI_FORMAT_BC1_UNORM, &formatSupport)))
+ {
+ mDXT1TextureSupport = (formatSupport & requiredCompressedTextureFlags) == requiredCompressedTextureFlags;
+ }
+ else
+ {
+ mDXT1TextureSupport = false;
+ }
+
+ if (SUCCEEDED(mDevice->CheckFormatSupport(DXGI_FORMAT_BC3_UNORM, &formatSupport)))
+ {
+ mDXT3TextureSupport = (formatSupport & requiredCompressedTextureFlags) == requiredCompressedTextureFlags;
+ }
+ else
+ {
+ mDXT3TextureSupport = false;
+ }
+
+ if (SUCCEEDED(mDevice->CheckFormatSupport(DXGI_FORMAT_BC5_UNORM, &formatSupport)))
+ {
+ mDXT5TextureSupport = (formatSupport & requiredCompressedTextureFlags) == requiredCompressedTextureFlags;
+ }
+ else
+ {
+ mDXT5TextureSupport = false;
+ }
+
+ // Check depth texture support
+ DXGI_FORMAT depthTextureFormats[] =
+ {
+ DXGI_FORMAT_D16_UNORM,
+ DXGI_FORMAT_D24_UNORM_S8_UINT,
+ };
+
+ static const unsigned int requiredDepthTextureFlags = D3D11_FORMAT_SUPPORT_DEPTH_STENCIL |
+ D3D11_FORMAT_SUPPORT_TEXTURE2D;
+
+ mDepthTextureSupport = true;
+ for (unsigned int i = 0; i < ArraySize(depthTextureFormats); i++)
+ {
+ if (SUCCEEDED(mDevice->CheckFormatSupport(depthTextureFormats[i], &formatSupport)))
+ {
+ mDepthTextureSupport = mDepthTextureSupport && ((formatSupport & requiredDepthTextureFlags) == requiredDepthTextureFlags);
+ }
+ else
+ {
+ mDepthTextureSupport = false;
+ }
+ }
+
+ return EGL_SUCCESS;
+}
+
+// do any one-time device initialization
+// NOTE: this is also needed after a device lost/reset
+// to reset the scene status and ensure the default states are reset.
+void Renderer11::initializeDevice()
+{
+ mStateCache.initialize(mDevice);
+ mInputLayoutCache.initialize(mDevice, mDeviceContext);
+
+ ASSERT(!mVertexDataManager && !mIndexDataManager);
+ mVertexDataManager = new VertexDataManager(this);
+ mIndexDataManager = new IndexDataManager(this);
+
+ markAllStateDirty();
+}
+
+int Renderer11::generateConfigs(ConfigDesc **configDescList)
+{
+ unsigned int numRenderFormats = ArraySize(RenderTargetFormats);
+ unsigned int numDepthFormats = ArraySize(DepthStencilFormats);
+ (*configDescList) = new ConfigDesc[numRenderFormats * numDepthFormats];
+ int numConfigs = 0;
+
+ for (unsigned int formatIndex = 0; formatIndex < numRenderFormats; formatIndex++)
+ {
+ for (unsigned int depthStencilIndex = 0; depthStencilIndex < numDepthFormats; depthStencilIndex++)
+ {
+ DXGI_FORMAT renderTargetFormat = RenderTargetFormats[formatIndex];
+
+ UINT formatSupport = 0;
+ HRESULT result = mDevice->CheckFormatSupport(renderTargetFormat, &formatSupport);
+
+ if (SUCCEEDED(result) && (formatSupport & D3D11_FORMAT_SUPPORT_RENDER_TARGET))
+ {
+ DXGI_FORMAT depthStencilFormat = DepthStencilFormats[depthStencilIndex];
+
+ bool depthStencilFormatOK = true;
+
+ if (depthStencilFormat != DXGI_FORMAT_UNKNOWN)
+ {
+ UINT formatSupport = 0;
+ result = mDevice->CheckFormatSupport(depthStencilFormat, &formatSupport);
+ depthStencilFormatOK = SUCCEEDED(result) && (formatSupport & D3D11_FORMAT_SUPPORT_DEPTH_STENCIL);
+ }
+
+ if (depthStencilFormatOK)
+ {
+ ConfigDesc newConfig;
+ newConfig.renderTargetFormat = d3d11_gl::ConvertBackBufferFormat(renderTargetFormat);
+ newConfig.depthStencilFormat = d3d11_gl::ConvertDepthStencilFormat(depthStencilFormat);
+ newConfig.multiSample = 0; // FIXME: enumerate multi-sampling
+ newConfig.fastConfig = true; // Assume all DX11 format conversions to be fast
+
+ (*configDescList)[numConfigs++] = newConfig;
+ }
+ }
+ }
+ }
+
+ return numConfigs;
+}
+
+void Renderer11::deleteConfigs(ConfigDesc *configDescList)
+{
+ delete [] (configDescList);
+}
+
+void Renderer11::sync(bool block)
+{
+ if (block)
+ {
+ HRESULT result;
+
+ if (!mSyncQuery)
+ {
+ D3D11_QUERY_DESC queryDesc;
+ queryDesc.Query = D3D11_QUERY_EVENT;
+ queryDesc.MiscFlags = 0;
+
+ result = mDevice->CreateQuery(&queryDesc, &mSyncQuery);
+ ASSERT(SUCCEEDED(result));
+ }
+
+ mDeviceContext->End(mSyncQuery);
+ mDeviceContext->Flush();
+
+ do
+ {
+ result = mDeviceContext->GetData(mSyncQuery, NULL, 0, D3D11_ASYNC_GETDATA_DONOTFLUSH);
+
+ // Keep polling, but allow other threads to do something useful first
+ Sleep(0);
+
+ if (testDeviceLost(true))
+ {
+ return;
+ }
+ }
+ while (result == S_FALSE);
+ }
+ else
+ {
+ mDeviceContext->Flush();
+ }
+}
+
+SwapChain *Renderer11::createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat)
+{
+ return new rx::SwapChain11(this, window, shareHandle, backBufferFormat, depthBufferFormat);
+}
+
+void Renderer11::setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &samplerState)
+{
+ if (type == gl::SAMPLER_PIXEL)
+ {
+ if (index < 0 || index >= gl::MAX_TEXTURE_IMAGE_UNITS)
+ {
+ ERR("Pixel shader sampler index %i is not valid.", index);
+ return;
+ }
+
+ if (mForceSetPixelSamplerStates[index] || memcmp(&samplerState, &mCurPixelSamplerStates[index], sizeof(gl::SamplerState)) != 0)
+ {
+ ID3D11SamplerState *dxSamplerState = mStateCache.getSamplerState(samplerState);
+
+ if (!dxSamplerState)
+ {
+ ERR("NULL sampler state returned by RenderStateCache::getSamplerState, setting the default"
+ "sampler state for pixel shaders at slot %i.", index);
+ }
+
+ mDeviceContext->PSSetSamplers(index, 1, &dxSamplerState);
+
+ mCurPixelSamplerStates[index] = samplerState;
+ }
+
+ mForceSetPixelSamplerStates[index] = false;
+ }
+ else if (type == gl::SAMPLER_VERTEX)
+ {
+ if (index < 0 || index >= (int)getMaxVertexTextureImageUnits())
+ {
+ ERR("Vertex shader sampler index %i is not valid.", index);
+ return;
+ }
+
+ if (mForceSetVertexSamplerStates[index] || memcmp(&samplerState, &mCurVertexSamplerStates[index], sizeof(gl::SamplerState)) != 0)
+ {
+ ID3D11SamplerState *dxSamplerState = mStateCache.getSamplerState(samplerState);
+
+ if (!dxSamplerState)
+ {
+ ERR("NULL sampler state returned by RenderStateCache::getSamplerState, setting the default"
+ "sampler state for vertex shaders at slot %i.", index);
+ }
+
+ mDeviceContext->VSSetSamplers(index, 1, &dxSamplerState);
+
+ mCurVertexSamplerStates[index] = samplerState;
+ }
+
+ mForceSetVertexSamplerStates[index] = false;
+ }
+ else UNREACHABLE();
+}
+
+void Renderer11::setTexture(gl::SamplerType type, int index, gl::Texture *texture)
+{
+ ID3D11ShaderResourceView *textureSRV = NULL;
+ unsigned int serial = 0;
+ bool forceSetTexture = false;
+
+ if (texture)
+ {
+ TextureStorageInterface *texStorage = texture->getNativeTexture();
+ if (texStorage)
+ {
+ TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(texStorage->getStorageInstance());
+ textureSRV = storage11->getSRV();
+ }
+
+ // If we get NULL back from getSRV here, something went wrong in the texture class and we're unexpectedly
+ // missing the shader resource view
+ ASSERT(textureSRV != NULL);
+
+ serial = texture->getTextureSerial();
+ forceSetTexture = texture->hasDirtyImages();
+ }
+
+ if (type == gl::SAMPLER_PIXEL)
+ {
+ if (index < 0 || index >= gl::MAX_TEXTURE_IMAGE_UNITS)
+ {
+ ERR("Pixel shader sampler index %i is not valid.", index);
+ return;
+ }
+
+ if (forceSetTexture || mCurPixelTextureSerials[index] != serial)
+ {
+ mDeviceContext->PSSetShaderResources(index, 1, &textureSRV);
+ }
+
+ mCurPixelTextureSerials[index] = serial;
+ }
+ else if (type == gl::SAMPLER_VERTEX)
+ {
+ if (index < 0 || index >= (int)getMaxVertexTextureImageUnits())
+ {
+ ERR("Vertex shader sampler index %i is not valid.", index);
+ return;
+ }
+
+ if (forceSetTexture || mCurVertexTextureSerials[index] != serial)
+ {
+ mDeviceContext->VSSetShaderResources(index, 1, &textureSRV);
+ }
+
+ mCurVertexTextureSerials[index] = serial;
+ }
+ else UNREACHABLE();
+}
+
+void Renderer11::setRasterizerState(const gl::RasterizerState &rasterState)
+{
+ if (mForceSetRasterState || memcmp(&rasterState, &mCurRasterState, sizeof(gl::RasterizerState)) != 0)
+ {
+ ID3D11RasterizerState *dxRasterState = mStateCache.getRasterizerState(rasterState, mScissorEnabled,
+ mCurDepthSize);
+ if (!dxRasterState)
+ {
+ ERR("NULL rasterizer state returned by RenderStateCache::getRasterizerState, setting the default"
+ "rasterizer state.");
+ }
+
+ mDeviceContext->RSSetState(dxRasterState);
+
+ mCurRasterState = rasterState;
+ }
+
+ mForceSetRasterState = false;
+}
+
+void Renderer11::setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::Color &blendColor,
+ unsigned int sampleMask)
+{
+ if (mForceSetBlendState ||
+ memcmp(&blendState, &mCurBlendState, sizeof(gl::BlendState)) != 0 ||
+ memcmp(&blendColor, &mCurBlendColor, sizeof(gl::Color)) != 0 ||
+ sampleMask != mCurSampleMask)
+ {
+ ID3D11BlendState *dxBlendState = mStateCache.getBlendState(framebuffer, blendState);
+ if (!dxBlendState)
+ {
+ ERR("NULL blend state returned by RenderStateCache::getBlendState, setting the default "
+ "blend state.");
+ }
+
+ float blendColors[4] = {0.0f};
+ if (blendState.sourceBlendRGB != GL_CONSTANT_ALPHA && blendState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA &&
+ blendState.destBlendRGB != GL_CONSTANT_ALPHA && blendState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA)
+ {
+ blendColors[0] = blendColor.red;
+ blendColors[1] = blendColor.green;
+ blendColors[2] = blendColor.blue;
+ blendColors[3] = blendColor.alpha;
+ }
+ else
+ {
+ blendColors[0] = blendColor.alpha;
+ blendColors[1] = blendColor.alpha;
+ blendColors[2] = blendColor.alpha;
+ blendColors[3] = blendColor.alpha;
+ }
+
+ mDeviceContext->OMSetBlendState(dxBlendState, blendColors, sampleMask);
+
+ mCurBlendState = blendState;
+ mCurBlendColor = blendColor;
+ mCurSampleMask = sampleMask;
+ }
+
+ mForceSetBlendState = false;
+}
+
+void Renderer11::setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef,
+ int stencilBackRef, bool frontFaceCCW)
+{
+ if (mForceSetDepthStencilState ||
+ memcmp(&depthStencilState, &mCurDepthStencilState, sizeof(gl::DepthStencilState)) != 0 ||
+ stencilRef != mCurStencilRef || stencilBackRef != mCurStencilBackRef)
+ {
+ if (depthStencilState.stencilWritemask != depthStencilState.stencilBackWritemask ||
+ stencilRef != stencilBackRef ||
+ depthStencilState.stencilMask != depthStencilState.stencilBackMask)
+ {
+ ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are "
+ "invalid under WebGL.");
+ return gl::error(GL_INVALID_OPERATION);
+ }
+
+ ID3D11DepthStencilState *dxDepthStencilState = mStateCache.getDepthStencilState(depthStencilState);
+ if (!dxDepthStencilState)
+ {
+ ERR("NULL depth stencil state returned by RenderStateCache::getDepthStencilState, "
+ "setting the default depth stencil state.");
+ }
+
+ mDeviceContext->OMSetDepthStencilState(dxDepthStencilState, static_cast<UINT>(stencilRef));
+
+ mCurDepthStencilState = depthStencilState;
+ mCurStencilRef = stencilRef;
+ mCurStencilBackRef = stencilBackRef;
+ }
+
+ mForceSetDepthStencilState = false;
+}
+
+void Renderer11::setScissorRectangle(const gl::Rectangle &scissor, bool enabled)
+{
+ if (mForceSetScissor || memcmp(&scissor, &mCurScissor, sizeof(gl::Rectangle)) != 0 ||
+ enabled != mScissorEnabled)
+ {
+ if (enabled)
+ {
+ D3D11_RECT rect;
+ rect.left = std::max(0, scissor.x);
+ rect.top = std::max(0, scissor.y);
+ rect.right = scissor.x + std::max(0, scissor.width);
+ rect.bottom = scissor.y + std::max(0, scissor.height);
+
+ mDeviceContext->RSSetScissorRects(1, &rect);
+ }
+
+ if (enabled != mScissorEnabled)
+ {
+ mForceSetRasterState = true;
+ }
+
+ mCurScissor = scissor;
+ mScissorEnabled = enabled;
+ }
+
+ mForceSetScissor = false;
+}
+
+bool Renderer11::setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace,
+ bool ignoreViewport)
+{
+ gl::Rectangle actualViewport = viewport;
+ float actualZNear = gl::clamp01(zNear);
+ float actualZFar = gl::clamp01(zFar);
+ if (ignoreViewport)
+ {
+ actualViewport.x = 0;
+ actualViewport.y = 0;
+ actualViewport.width = mRenderTargetDesc.width;
+ actualViewport.height = mRenderTargetDesc.height;
+ actualZNear = 0.0f;
+ actualZFar = 1.0f;
+ }
+
+ // Get D3D viewport bounds, which depends on the feature level
+ const Range& viewportBounds = getViewportBounds();
+
+ // Clamp width and height first to the gl maximum, then clamp further if we extend past the D3D maximum bounds
+ D3D11_VIEWPORT dxViewport;
+ dxViewport.TopLeftX = gl::clamp(actualViewport.x, viewportBounds.start, viewportBounds.end);
+ dxViewport.TopLeftY = gl::clamp(actualViewport.y, viewportBounds.start, viewportBounds.end);
+ dxViewport.Width = gl::clamp(actualViewport.width, 0, getMaxViewportDimension());
+ dxViewport.Height = gl::clamp(actualViewport.height, 0, getMaxViewportDimension());
+ dxViewport.Width = std::min((int)dxViewport.Width, viewportBounds.end - static_cast<int>(dxViewport.TopLeftX));
+ dxViewport.Height = std::min((int)dxViewport.Height, viewportBounds.end - static_cast<int>(dxViewport.TopLeftY));
+ dxViewport.MinDepth = actualZNear;
+ dxViewport.MaxDepth = actualZFar;
+
+ if (dxViewport.Width <= 0 || dxViewport.Height <= 0)
+ {
+ return false; // Nothing to render
+ }
+
+ bool viewportChanged = mForceSetViewport || memcmp(&actualViewport, &mCurViewport, sizeof(gl::Rectangle)) != 0 ||
+ actualZNear != mCurNear || actualZFar != mCurFar;
+
+ if (viewportChanged)
+ {
+ mDeviceContext->RSSetViewports(1, &dxViewport);
+
+ mCurViewport = actualViewport;
+ mCurNear = actualZNear;
+ mCurFar = actualZFar;
+
+ mPixelConstants.viewCoords[0] = actualViewport.width * 0.5f;
+ mPixelConstants.viewCoords[1] = actualViewport.height * 0.5f;
+ mPixelConstants.viewCoords[2] = actualViewport.x + (actualViewport.width * 0.5f);
+ mPixelConstants.viewCoords[3] = actualViewport.y + (actualViewport.height * 0.5f);
+
+ mPixelConstants.depthFront[0] = (actualZFar - actualZNear) * 0.5f;
+ mPixelConstants.depthFront[1] = (actualZNear + actualZFar) * 0.5f;
+
+ mVertexConstants.depthRange[0] = actualZNear;
+ mVertexConstants.depthRange[1] = actualZFar;
+ mVertexConstants.depthRange[2] = actualZFar - actualZNear;
+
+ mPixelConstants.depthRange[0] = actualZNear;
+ mPixelConstants.depthRange[1] = actualZFar;
+ mPixelConstants.depthRange[2] = actualZFar - actualZNear;
+ }
+
+ mForceSetViewport = false;
+ return true;
+}
+
+bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count)
+{
+ D3D11_PRIMITIVE_TOPOLOGY primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
+
+ GLsizei minCount = 0;
+
+ switch (mode)
+ {
+ case GL_POINTS: primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST; minCount = 1; break;
+ case GL_LINES: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINELIST; minCount = 2; break;
+ case GL_LINE_LOOP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; minCount = 2; break;
+ case GL_LINE_STRIP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; minCount = 2; break;
+ case GL_TRIANGLES: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; minCount = 3; break;
+ case GL_TRIANGLE_STRIP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; minCount = 3; break;
+ // emulate fans via rewriting index buffer
+ case GL_TRIANGLE_FAN: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; minCount = 3; break;
+ default:
+ return gl::error(GL_INVALID_ENUM, false);
+ }
+
+ if (primitiveTopology != mCurrentPrimitiveTopology)
+ {
+ mDeviceContext->IASetPrimitiveTopology(primitiveTopology);
+ mCurrentPrimitiveTopology = primitiveTopology;
+ }
+
+ return count >= minCount;
+}
+
+bool Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer)
+{
+ // Get the color render buffer and serial
+ // Also extract the render target dimensions and view
+ unsigned int renderTargetWidth = 0;
+ unsigned int renderTargetHeight = 0;
+ GLenum renderTargetFormat = 0;
+ unsigned int renderTargetSerials[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {0};
+ ID3D11RenderTargetView* framebufferRTVs[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {NULL};
+ bool missingColorRenderTarget = true;
+
+ for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
+ {
+ const GLenum drawBufferState = framebuffer->getDrawBufferState(colorAttachment);
+
+ if (framebuffer->getColorbufferType(colorAttachment) != GL_NONE && drawBufferState != GL_NONE)
+ {
+ // the draw buffer must be either "none", "back" for the default buffer or the same index as this color (in order)
+ ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + colorAttachment));
+
+ gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer(colorAttachment);
+
+ if (!colorbuffer)
+ {
+ ERR("render target pointer unexpectedly null.");
+ return false;
+ }
+
+ // check for zero-sized default framebuffer, which is a special case.
+ // in this case we do not wish to modify any state and just silently return false.
+ // this will not report any gl error but will cause the calling method to return.
+ if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0)
+ {
+ return false;
+ }
+
+ renderTargetSerials[colorAttachment] = colorbuffer->getSerial();
+
+ // Extract the render target dimensions and view
+ RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget());
+ if (!renderTarget)
+ {
+ ERR("render target pointer unexpectedly null.");
+ return false;
+ }
+
+ framebufferRTVs[colorAttachment] = renderTarget->getRenderTargetView();
+ if (!framebufferRTVs[colorAttachment])
+ {
+ ERR("render target view pointer unexpectedly null.");
+ return false;
+ }
+
+ if (missingColorRenderTarget)
+ {
+ renderTargetWidth = colorbuffer->getWidth();
+ renderTargetHeight = colorbuffer->getHeight();
+ renderTargetFormat = colorbuffer->getActualFormat();
+ missingColorRenderTarget = false;
+ }
+
+#ifdef _DEBUG
+ // Workaround for Debug SETSHADERRESOURCES_HAZARD D3D11 warnings
+ for (unsigned int vertexSerialIndex = 0; vertexSerialIndex < gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; vertexSerialIndex++)
+ {
+ if (colorbuffer->getTextureSerial() != 0 && mCurVertexTextureSerials[vertexSerialIndex] == colorbuffer->getTextureSerial())
+ {
+ setTexture(gl::SAMPLER_VERTEX, vertexSerialIndex, NULL);
+ }
+ }
+
+ for (unsigned int pixelSerialIndex = 0; pixelSerialIndex < gl::MAX_TEXTURE_IMAGE_UNITS; pixelSerialIndex++)
+ {
+ if (colorbuffer->getTextureSerial() != 0 && mCurPixelTextureSerials[pixelSerialIndex] == colorbuffer->getTextureSerial())
+ {
+ setTexture(gl::SAMPLER_PIXEL, pixelSerialIndex, NULL);
+ }
+ }
+#endif
+ }
+ }
+
+ // Get the depth stencil render buffer and serials
+ gl::Renderbuffer *depthStencil = NULL;
+ unsigned int depthbufferSerial = 0;
+ unsigned int stencilbufferSerial = 0;
+ if (framebuffer->getDepthbufferType() != GL_NONE)
+ {
+ depthStencil = framebuffer->getDepthbuffer();
+ if (!depthStencil)
+ {
+ ERR("Depth stencil pointer unexpectedly null.");
+ SafeRelease(framebufferRTVs);
+ return false;
+ }
+
+ depthbufferSerial = depthStencil->getSerial();
+ }
+ else if (framebuffer->getStencilbufferType() != GL_NONE)
+ {
+ depthStencil = framebuffer->getStencilbuffer();
+ if (!depthStencil)
+ {
+ ERR("Depth stencil pointer unexpectedly null.");
+ SafeRelease(framebufferRTVs);
+ return false;
+ }
+
+ stencilbufferSerial = depthStencil->getSerial();
+ }
+
+ // Extract the depth stencil sizes and view
+ unsigned int depthSize = 0;
+ unsigned int stencilSize = 0;
+ ID3D11DepthStencilView* framebufferDSV = NULL;
+ if (depthStencil)
+ {
+ RenderTarget11 *depthStencilRenderTarget = RenderTarget11::makeRenderTarget11(depthStencil->getDepthStencil());
+ if (!depthStencilRenderTarget)
+ {
+ ERR("render target pointer unexpectedly null.");
+ SafeRelease(framebufferRTVs);
+ return false;
+ }
+
+ framebufferDSV = depthStencilRenderTarget->getDepthStencilView();
+ if (!framebufferDSV)
+ {
+ ERR("depth stencil view pointer unexpectedly null.");
+ SafeRelease(framebufferRTVs);
+ return false;
+ }
+
+ // If there is no render buffer, the width, height and format values come from
+ // the depth stencil
+ if (missingColorRenderTarget)
+ {
+ renderTargetWidth = depthStencil->getWidth();
+ renderTargetHeight = depthStencil->getHeight();
+ renderTargetFormat = depthStencil->getActualFormat();
+ }
+
+ depthSize = depthStencil->getDepthSize();
+ stencilSize = depthStencil->getStencilSize();
+ }
+
+ // Apply the render target and depth stencil
+ if (!mRenderTargetDescInitialized || !mDepthStencilInitialized ||
+ memcmp(renderTargetSerials, mAppliedRenderTargetSerials, sizeof(renderTargetSerials)) != 0 ||
+ depthbufferSerial != mAppliedDepthbufferSerial ||
+ stencilbufferSerial != mAppliedStencilbufferSerial)
+ {
+ mDeviceContext->OMSetRenderTargets(getMaxRenderTargets(), framebufferRTVs, framebufferDSV);
+
+ mRenderTargetDesc.width = renderTargetWidth;
+ mRenderTargetDesc.height = renderTargetHeight;
+ mRenderTargetDesc.format = renderTargetFormat;
+ mForceSetViewport = true;
+ mForceSetScissor = true;
+
+ if (!mDepthStencilInitialized || depthSize != mCurDepthSize)
+ {
+ mCurDepthSize = depthSize;
+ mForceSetRasterState = true;
+ }
+
+ mCurStencilSize = stencilSize;
+
+ for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++)
+ {
+ mAppliedRenderTargetSerials[rtIndex] = renderTargetSerials[rtIndex];
+ }
+ mAppliedDepthbufferSerial = depthbufferSerial;
+ mAppliedStencilbufferSerial = stencilbufferSerial;
+ mRenderTargetDescInitialized = true;
+ mDepthStencilInitialized = true;
+ }
+
+ return true;
+}
+
+GLenum Renderer11::applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances)
+{
+ TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS];
+ GLenum err = mVertexDataManager->prepareVertexData(vertexAttributes, programBinary, first, count, attributes, instances);
+ if (err != GL_NO_ERROR)
+ {
+ return err;
+ }
+
+ return mInputLayoutCache.applyVertexBuffers(attributes, programBinary);
+}
+
+GLenum Renderer11::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo)
+{
+ GLenum err = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo);
+
+ if (err == GL_NO_ERROR)
+ {
+ if (indexInfo->storage)
+ {
+ if (indexInfo->serial != mAppliedStorageIBSerial || indexInfo->startOffset != mAppliedIBOffset)
+ {
+ BufferStorage11 *storage = BufferStorage11::makeBufferStorage11(indexInfo->storage);
+ IndexBuffer11* indexBuffer = IndexBuffer11::makeIndexBuffer11(indexInfo->indexBuffer);
+
+ mDeviceContext->IASetIndexBuffer(storage->getBuffer(BUFFER_USAGE_INDEX), indexBuffer->getIndexFormat(), indexInfo->startOffset);
+
+ mAppliedIBSerial = 0;
+ mAppliedStorageIBSerial = storage->getSerial();
+ mAppliedIBOffset = indexInfo->startOffset;
+ }
+ }
+ else if (indexInfo->serial != mAppliedIBSerial || indexInfo->startOffset != mAppliedIBOffset)
+ {
+ IndexBuffer11* indexBuffer = IndexBuffer11::makeIndexBuffer11(indexInfo->indexBuffer);
+
+ mDeviceContext->IASetIndexBuffer(indexBuffer->getBuffer(), indexBuffer->getIndexFormat(), indexInfo->startOffset);
+
+ mAppliedIBSerial = indexInfo->serial;
+ mAppliedStorageIBSerial = 0;
+ mAppliedIBOffset = indexInfo->startOffset;
+ }
+ }
+
+ return err;
+}
+
+void Renderer11::drawArrays(GLenum mode, GLsizei count, GLsizei instances)
+{
+ if (mode == GL_LINE_LOOP)
+ {
+ drawLineLoop(count, GL_NONE, NULL, 0, NULL);
+ }
+ else if (mode == GL_TRIANGLE_FAN)
+ {
+ drawTriangleFan(count, GL_NONE, NULL, 0, NULL, instances);
+ }
+ else if (instances > 0)
+ {
+ mDeviceContext->DrawInstanced(count, instances, 0, 0);
+ }
+ else
+ {
+ mDeviceContext->Draw(count, 0);
+ }
+}
+
+void Renderer11::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances)
+{
+ if (mode == GL_LINE_LOOP)
+ {
+ drawLineLoop(count, type, indices, indexInfo.minIndex, elementArrayBuffer);
+ }
+ else if (mode == GL_TRIANGLE_FAN)
+ {
+ drawTriangleFan(count, type, indices, indexInfo.minIndex, elementArrayBuffer, instances);
+ }
+ else if (instances > 0)
+ {
+ mDeviceContext->DrawIndexedInstanced(count, instances, 0, -static_cast<int>(indexInfo.minIndex), 0);
+ }
+ else
+ {
+ mDeviceContext->DrawIndexed(count, 0, -static_cast<int>(indexInfo.minIndex));
+ }
+}
+
+void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer)
+{
+ // Get the raw indices for an indexed draw
+ if (type != GL_NONE && elementArrayBuffer)
+ {
+ gl::Buffer *indexBuffer = elementArrayBuffer;
+ BufferStorage *storage = indexBuffer->getStorage();
+ intptr_t offset = reinterpret_cast<intptr_t>(indices);
+ indices = static_cast<const GLubyte*>(storage->getData()) + offset;
+ }
+
+ if (!mLineLoopIB)
+ {
+ mLineLoopIB = new StreamingIndexBufferInterface(this);
+ if (!mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT))
+ {
+ delete mLineLoopIB;
+ mLineLoopIB = NULL;
+
+ ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP.");
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+ }
+
+ // Checked by Renderer11::applyPrimitiveType
+ ASSERT(count >= 0);
+
+ if (static_cast<unsigned int>(count) + 1 > (std::numeric_limits<unsigned int>::max() / sizeof(unsigned int)))
+ {
+ ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required.");
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+
+ const unsigned int spaceNeeded = (static_cast<unsigned int>(count) + 1) * sizeof(unsigned int);
+ if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT))
+ {
+ ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP.");
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+
+ void* mappedMemory = NULL;
+ unsigned int offset;
+ if (!mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset))
+ {
+ ERR("Could not map index buffer for GL_LINE_LOOP.");
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+
+ unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory);
+ unsigned int indexBufferOffset = offset;
+
+ switch (type)
+ {
+ case GL_NONE: // Non-indexed draw
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = i;
+ }
+ data[count] = 0;
+ break;
+ case GL_UNSIGNED_BYTE:
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = static_cast<const GLubyte*>(indices)[i];
+ }
+ data[count] = static_cast<const GLubyte*>(indices)[0];
+ break;
+ case GL_UNSIGNED_SHORT:
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = static_cast<const GLushort*>(indices)[i];
+ }
+ data[count] = static_cast<const GLushort*>(indices)[0];
+ break;
+ case GL_UNSIGNED_INT:
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = static_cast<const GLuint*>(indices)[i];
+ }
+ data[count] = static_cast<const GLuint*>(indices)[0];
+ break;
+ default: UNREACHABLE();
+ }
+
+ if (!mLineLoopIB->unmapBuffer())
+ {
+ ERR("Could not unmap index buffer for GL_LINE_LOOP.");
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+
+ if (mAppliedIBSerial != mLineLoopIB->getSerial() || mAppliedIBOffset != indexBufferOffset)
+ {
+ IndexBuffer11 *indexBuffer = IndexBuffer11::makeIndexBuffer11(mLineLoopIB->getIndexBuffer());
+
+ mDeviceContext->IASetIndexBuffer(indexBuffer->getBuffer(), indexBuffer->getIndexFormat(), indexBufferOffset);
+ mAppliedIBSerial = mLineLoopIB->getSerial();
+ mAppliedStorageIBSerial = 0;
+ mAppliedIBOffset = indexBufferOffset;
+ }
+
+ mDeviceContext->DrawIndexed(count + 1, 0, -minIndex);
+}
+
+void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer, int instances)
+{
+ // Get the raw indices for an indexed draw
+ if (type != GL_NONE && elementArrayBuffer)
+ {
+ gl::Buffer *indexBuffer = elementArrayBuffer;
+ BufferStorage *storage = indexBuffer->getStorage();
+ intptr_t offset = reinterpret_cast<intptr_t>(indices);
+ indices = static_cast<const GLubyte*>(storage->getData()) + offset;
+ }
+
+ if (!mTriangleFanIB)
+ {
+ mTriangleFanIB = new StreamingIndexBufferInterface(this);
+ if (!mTriangleFanIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT))
+ {
+ delete mTriangleFanIB;
+ mTriangleFanIB = NULL;
+
+ ERR("Could not create a scratch index buffer for GL_TRIANGLE_FAN.");
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+ }
+
+ // Checked by Renderer11::applyPrimitiveType
+ ASSERT(count >= 3);
+
+ const unsigned int numTris = count - 2;
+
+ if (numTris > (std::numeric_limits<unsigned int>::max() / (sizeof(unsigned int) * 3)))
+ {
+ ERR("Could not create a scratch index buffer for GL_TRIANGLE_FAN, too many indices required.");
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+
+ const unsigned int spaceNeeded = (numTris * 3) * sizeof(unsigned int);
+ if (!mTriangleFanIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT))
+ {
+ ERR("Could not reserve enough space in scratch index buffer for GL_TRIANGLE_FAN.");
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+
+ void* mappedMemory = NULL;
+ unsigned int offset;
+ if (!mTriangleFanIB->mapBuffer(spaceNeeded, &mappedMemory, &offset))
+ {
+ ERR("Could not map scratch index buffer for GL_TRIANGLE_FAN.");
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+
+ unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory);
+ unsigned int indexBufferOffset = offset;
+
+ switch (type)
+ {
+ case GL_NONE: // Non-indexed draw
+ for (unsigned int i = 0; i < numTris; i++)
+ {
+ data[i*3 + 0] = 0;
+ data[i*3 + 1] = i + 1;
+ data[i*3 + 2] = i + 2;
+ }
+ break;
+ case GL_UNSIGNED_BYTE:
+ for (unsigned int i = 0; i < numTris; i++)
+ {
+ data[i*3 + 0] = static_cast<const GLubyte*>(indices)[0];
+ data[i*3 + 1] = static_cast<const GLubyte*>(indices)[i + 1];
+ data[i*3 + 2] = static_cast<const GLubyte*>(indices)[i + 2];
+ }
+ break;
+ case GL_UNSIGNED_SHORT:
+ for (unsigned int i = 0; i < numTris; i++)
+ {
+ data[i*3 + 0] = static_cast<const GLushort*>(indices)[0];
+ data[i*3 + 1] = static_cast<const GLushort*>(indices)[i + 1];
+ data[i*3 + 2] = static_cast<const GLushort*>(indices)[i + 2];
+ }
+ break;
+ case GL_UNSIGNED_INT:
+ for (unsigned int i = 0; i < numTris; i++)
+ {
+ data[i*3 + 0] = static_cast<const GLuint*>(indices)[0];
+ data[i*3 + 1] = static_cast<const GLuint*>(indices)[i + 1];
+ data[i*3 + 2] = static_cast<const GLuint*>(indices)[i + 2];
+ }
+ break;
+ default: UNREACHABLE();
+ }
+
+ if (!mTriangleFanIB->unmapBuffer())
+ {
+ ERR("Could not unmap scratch index buffer for GL_TRIANGLE_FAN.");
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+
+ if (mAppliedIBSerial != mTriangleFanIB->getSerial() || mAppliedIBOffset != indexBufferOffset)
+ {
+ IndexBuffer11 *indexBuffer = IndexBuffer11::makeIndexBuffer11(mTriangleFanIB->getIndexBuffer());
+
+ mDeviceContext->IASetIndexBuffer(indexBuffer->getBuffer(), indexBuffer->getIndexFormat(), indexBufferOffset);
+ mAppliedIBSerial = mTriangleFanIB->getSerial();
+ mAppliedStorageIBSerial = 0;
+ mAppliedIBOffset = indexBufferOffset;
+ }
+
+ if (instances > 0)
+ {
+ mDeviceContext->DrawIndexedInstanced(numTris * 3, instances, 0, -minIndex, 0);
+ }
+ else
+ {
+ mDeviceContext->DrawIndexed(numTris * 3, 0, -minIndex);
+ }
+}
+
+void Renderer11::applyShaders(gl::ProgramBinary *programBinary)
+{
+ unsigned int programBinarySerial = programBinary->getSerial();
+ const bool updateProgramState = (programBinarySerial != mAppliedProgramBinarySerial);
+
+ if (updateProgramState)
+ {
+ ShaderExecutable *vertexExe = programBinary->getVertexExecutable();
+ ShaderExecutable *pixelExe = programBinary->getPixelExecutable();
+
+ ID3D11VertexShader *vertexShader = NULL;
+ if (vertexExe) vertexShader = ShaderExecutable11::makeShaderExecutable11(vertexExe)->getVertexShader();
+
+ ID3D11PixelShader *pixelShader = NULL;
+ if (pixelExe) pixelShader = ShaderExecutable11::makeShaderExecutable11(pixelExe)->getPixelShader();
+
+ mDeviceContext->PSSetShader(pixelShader, NULL, 0);
+ mDeviceContext->VSSetShader(vertexShader, NULL, 0);
+
+ programBinary->dirtyAllUniforms();
+
+ mAppliedProgramBinarySerial = programBinarySerial;
+ }
+
+ // Only use the geometry shader currently for point sprite drawing
+ const bool usesGeometryShader = (programBinary->usesGeometryShader() && mCurRasterState.pointDrawMode);
+
+ if (updateProgramState || usesGeometryShader != mIsGeometryShaderActive)
+ {
+ if (usesGeometryShader)
+ {
+ ShaderExecutable *geometryExe = programBinary->getGeometryExecutable();
+ ID3D11GeometryShader *geometryShader = ShaderExecutable11::makeShaderExecutable11(geometryExe)->getGeometryShader();
+ mDeviceContext->GSSetShader(geometryShader, NULL, 0);
+ }
+ else
+ {
+ mDeviceContext->GSSetShader(NULL, NULL, 0);
+ }
+
+ mIsGeometryShaderActive = usesGeometryShader;
+ }
+}
+
+void Renderer11::applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray *uniformArray)
+{
+ ShaderExecutable11 *vertexExecutable = ShaderExecutable11::makeShaderExecutable11(programBinary->getVertexExecutable());
+ ShaderExecutable11 *pixelExecutable = ShaderExecutable11::makeShaderExecutable11(programBinary->getPixelExecutable());
+
+ unsigned int totalRegisterCountVS = 0;
+ unsigned int totalRegisterCountPS = 0;
+
+ bool vertexUniformsDirty = false;
+ bool pixelUniformsDirty = false;
+
+ for (gl::UniformArray::const_iterator uniform_iterator = uniformArray->begin(); uniform_iterator != uniformArray->end(); uniform_iterator++)
+ {
+ const gl::Uniform *uniform = *uniform_iterator;
+
+ if (uniform->vsRegisterIndex >= 0)
+ {
+ totalRegisterCountVS += uniform->registerCount;
+ vertexUniformsDirty = vertexUniformsDirty || uniform->dirty;
+ }
+
+ if (uniform->psRegisterIndex >= 0)
+ {
+ totalRegisterCountPS += uniform->registerCount;
+ pixelUniformsDirty = pixelUniformsDirty || uniform->dirty;
+ }
+ }
+
+ ID3D11Buffer *vertexConstantBuffer = vertexExecutable->getConstantBuffer(mDevice, totalRegisterCountVS);
+ ID3D11Buffer *pixelConstantBuffer = pixelExecutable->getConstantBuffer(mDevice, totalRegisterCountPS);
+
+ float (*mapVS)[4] = NULL;
+ float (*mapPS)[4] = NULL;
+
+ if (totalRegisterCountVS > 0 && vertexUniformsDirty)
+ {
+ D3D11_MAPPED_SUBRESOURCE map = {0};
+ HRESULT result = mDeviceContext->Map(vertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
+ ASSERT(SUCCEEDED(result));
+ mapVS = (float(*)[4])map.pData;
+ }
+
+ if (totalRegisterCountPS > 0 && pixelUniformsDirty)
+ {
+ D3D11_MAPPED_SUBRESOURCE map = {0};
+ HRESULT result = mDeviceContext->Map(pixelConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
+ ASSERT(SUCCEEDED(result));
+ mapPS = (float(*)[4])map.pData;
+ }
+
+ for (gl::UniformArray::iterator uniform_iterator = uniformArray->begin(); uniform_iterator != uniformArray->end(); uniform_iterator++)
+ {
+ gl::Uniform *uniform = *uniform_iterator;
+
+ if (uniform->type != GL_SAMPLER_2D && uniform->type != GL_SAMPLER_CUBE)
+ {
+ if (uniform->vsRegisterIndex >= 0 && mapVS)
+ {
+ memcpy(mapVS + uniform->vsRegisterIndex, uniform->data, uniform->registerCount * sizeof(float[4]));
+ }
+
+ if (uniform->psRegisterIndex >= 0 && mapPS)
+ {
+ memcpy(mapPS + uniform->psRegisterIndex, uniform->data, uniform->registerCount * sizeof(float[4]));
+ }
+ }
+
+ uniform->dirty = false;
+ }
+
+ if (mapVS)
+ {
+ mDeviceContext->Unmap(vertexConstantBuffer, 0);
+ }
+
+ if (mapPS)
+ {
+ mDeviceContext->Unmap(pixelConstantBuffer, 0);
+ }
+
+ if (mCurrentVertexConstantBuffer != vertexConstantBuffer)
+ {
+ mDeviceContext->VSSetConstantBuffers(0, 1, &vertexConstantBuffer);
+ mCurrentVertexConstantBuffer = vertexConstantBuffer;
+ }
+
+ if (mCurrentPixelConstantBuffer != pixelConstantBuffer)
+ {
+ mDeviceContext->PSSetConstantBuffers(0, 1, &pixelConstantBuffer);
+ mCurrentPixelConstantBuffer = pixelConstantBuffer;
+ }
+
+ // Driver uniforms
+ if (!mDriverConstantBufferVS)
+ {
+ D3D11_BUFFER_DESC constantBufferDescription = {0};
+ constantBufferDescription.ByteWidth = sizeof(dx_VertexConstants);
+ constantBufferDescription.Usage = D3D11_USAGE_DEFAULT;
+ constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
+ constantBufferDescription.CPUAccessFlags = 0;
+ constantBufferDescription.MiscFlags = 0;
+ constantBufferDescription.StructureByteStride = 0;
+
+ HRESULT result = mDevice->CreateBuffer(&constantBufferDescription, NULL, &mDriverConstantBufferVS);
+ ASSERT(SUCCEEDED(result));
+
+ mDeviceContext->VSSetConstantBuffers(1, 1, &mDriverConstantBufferVS);
+ }
+
+ if (!mDriverConstantBufferPS)
+ {
+ D3D11_BUFFER_DESC constantBufferDescription = {0};
+ constantBufferDescription.ByteWidth = sizeof(dx_PixelConstants);
+ constantBufferDescription.Usage = D3D11_USAGE_DEFAULT;
+ constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
+ constantBufferDescription.CPUAccessFlags = 0;
+ constantBufferDescription.MiscFlags = 0;
+ constantBufferDescription.StructureByteStride = 0;
+
+ HRESULT result = mDevice->CreateBuffer(&constantBufferDescription, NULL, &mDriverConstantBufferPS);
+ ASSERT(SUCCEEDED(result));
+
+ mDeviceContext->PSSetConstantBuffers(1, 1, &mDriverConstantBufferPS);
+ }
+
+ if (memcmp(&mVertexConstants, &mAppliedVertexConstants, sizeof(dx_VertexConstants)) != 0)
+ {
+ mDeviceContext->UpdateSubresource(mDriverConstantBufferVS, 0, NULL, &mVertexConstants, 16, 0);
+ memcpy(&mAppliedVertexConstants, &mVertexConstants, sizeof(dx_VertexConstants));
+ }
+
+ if (memcmp(&mPixelConstants, &mAppliedPixelConstants, sizeof(dx_PixelConstants)) != 0)
+ {
+ mDeviceContext->UpdateSubresource(mDriverConstantBufferPS, 0, NULL, &mPixelConstants, 16, 0);
+ memcpy(&mAppliedPixelConstants, &mPixelConstants, sizeof(dx_PixelConstants));
+ }
+
+ // needed for the point sprite geometry shader
+ if (mCurrentGeometryConstantBuffer != mDriverConstantBufferPS)
+ {
+ mDeviceContext->GSSetConstantBuffers(0, 1, &mDriverConstantBufferPS);
+ mCurrentGeometryConstantBuffer = mDriverConstantBufferPS;
+ }
+}
+
+void Renderer11::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer)
+{
+ gl::Renderbuffer *firstRenderbuffer = frameBuffer->getFirstColorbuffer();
+ GLenum internalFormat = firstRenderbuffer ? firstRenderbuffer->getInternalFormat() : GL_NONE;
+
+ bool needMaskedColorClear = (clearParams.mask & GL_COLOR_BUFFER_BIT) &&
+ ((!clearParams.colorMaskRed && gl::GetRedSize(internalFormat) > 0) ||
+ (!clearParams.colorMaskGreen && gl::GetGreenSize(internalFormat) > 0) ||
+ (!clearParams.colorMaskBlue && gl::GetBlueSize(internalFormat) > 0) ||
+ (!clearParams.colorMaskAlpha && gl::GetAlphaSize(internalFormat) > 0));
+
+ unsigned int stencilUnmasked = 0x0;
+ if (frameBuffer->hasStencil())
+ {
+ unsigned int stencilSize = gl::GetStencilSize(frameBuffer->getStencilbuffer()->getActualFormat());
+ stencilUnmasked = (0x1 << stencilSize) - 1;
+ }
+ bool needMaskedStencilClear = (clearParams.mask & GL_STENCIL_BUFFER_BIT) &&
+ (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked;
+
+ bool needScissoredClear = mScissorEnabled && (mCurScissor.x > 0 || mCurScissor.y > 0 ||
+ mCurScissor.x + mCurScissor.width < mRenderTargetDesc.width ||
+ mCurScissor.y + mCurScissor.height < mRenderTargetDesc.height);
+
+ if (needMaskedColorClear || needMaskedStencilClear || needScissoredClear)
+ {
+ maskedClear(clearParams, frameBuffer);
+ }
+ else
+ {
+ if (clearParams.mask & GL_COLOR_BUFFER_BIT)
+ {
+ for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
+ {
+ if (frameBuffer->isEnabledColorAttachment(colorAttachment))
+ {
+ gl::Renderbuffer *renderbufferObject = frameBuffer->getColorbuffer(colorAttachment);
+ if (renderbufferObject)
+ {
+ RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(renderbufferObject->getRenderTarget());
+ if (!renderTarget)
+ {
+ ERR("render target pointer unexpectedly null.");
+ return;
+ }
+
+ ID3D11RenderTargetView *framebufferRTV = renderTarget->getRenderTargetView();
+ if (!framebufferRTV)
+ {
+ ERR("render target view pointer unexpectedly null.");
+ return;
+ }
+
+ GLenum format = renderbufferObject->getInternalFormat();
+
+ const float clearValues[4] = { (gl::GetRedSize(format) > 0) ? clearParams.colorClearValue.red : 0.0f,
+ (gl::GetGreenSize(format) > 0) ? clearParams.colorClearValue.green : 0.0f,
+ (gl::GetBlueSize(format) > 0) ? clearParams.colorClearValue.blue : 0.0f,
+ (gl::GetAlphaSize(format) > 0) ? clearParams.colorClearValue.alpha : 1.0f };
+ mDeviceContext->ClearRenderTargetView(framebufferRTV, clearValues);
+ }
+ }
+ }
+ }
+ if (clearParams.mask & GL_DEPTH_BUFFER_BIT || clearParams.mask & GL_STENCIL_BUFFER_BIT)
+ {
+ gl::Renderbuffer *renderbufferObject = frameBuffer->getDepthOrStencilbuffer();
+ if (renderbufferObject)
+ {
+ RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(renderbufferObject->getDepthStencil());
+ if (!renderTarget)
+ {
+ ERR("render target pointer unexpectedly null.");
+ return;
+ }
+
+ ID3D11DepthStencilView *framebufferDSV = renderTarget->getDepthStencilView();
+ if (!framebufferDSV)
+ {
+ ERR("depth stencil view pointer unexpectedly null.");
+ return;
+ }
+
+ UINT clearFlags = 0;
+ if (clearParams.mask & GL_DEPTH_BUFFER_BIT)
+ {
+ clearFlags |= D3D11_CLEAR_DEPTH;
+ }
+ if (clearParams.mask & GL_STENCIL_BUFFER_BIT)
+ {
+ clearFlags |= D3D11_CLEAR_STENCIL;
+ }
+
+ float depthClear = gl::clamp01(clearParams.depthClearValue);
+ UINT8 stencilClear = clearParams.stencilClearValue & 0x000000FF;
+
+ mDeviceContext->ClearDepthStencilView(framebufferDSV, clearFlags, depthClear, stencilClear);
+ }
+ }
+ }
+}
+
+void Renderer11::maskedClear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer)
+{
+ HRESULT result;
+
+ if (!mClearResourcesInitialized)
+ {
+ ASSERT(!mClearVB && !mClearVS && !mClearSinglePS && !mClearMultiplePS && !mClearScissorRS && !mClearNoScissorRS);
+
+ D3D11_BUFFER_DESC vbDesc;
+ vbDesc.ByteWidth = sizeof(d3d11::PositionDepthColorVertex) * 4;
+ vbDesc.Usage = D3D11_USAGE_DYNAMIC;
+ vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
+ vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ vbDesc.MiscFlags = 0;
+ vbDesc.StructureByteStride = 0;
+
+ result = mDevice->CreateBuffer(&vbDesc, NULL, &mClearVB);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mClearVB, "Renderer11 masked clear vertex buffer");
+
+ D3D11_INPUT_ELEMENT_DESC quadLayout[] =
+ {
+ { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
+ { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
+ };
+
+ result = mDevice->CreateInputLayout(quadLayout, 2, g_VS_Clear, sizeof(g_VS_Clear), &mClearIL);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mClearIL, "Renderer11 masked clear input layout");
+
+ result = mDevice->CreateVertexShader(g_VS_Clear, sizeof(g_VS_Clear), NULL, &mClearVS);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mClearVS, "Renderer11 masked clear vertex shader");
+
+ result = mDevice->CreatePixelShader(g_PS_ClearSingle, sizeof(g_PS_ClearSingle), NULL, &mClearSinglePS);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mClearSinglePS, "Renderer11 masked clear pixel shader (1 RT)");
+
+ result = mDevice->CreatePixelShader(g_PS_ClearMultiple, sizeof(g_PS_ClearMultiple), NULL, &mClearMultiplePS);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mClearMultiplePS, "Renderer11 masked clear pixel shader (MRT)");
+
+ D3D11_RASTERIZER_DESC rsScissorDesc;
+ rsScissorDesc.FillMode = D3D11_FILL_SOLID;
+ rsScissorDesc.CullMode = D3D11_CULL_NONE;
+ rsScissorDesc.FrontCounterClockwise = FALSE;
+ rsScissorDesc.DepthBias = 0;
+ rsScissorDesc.DepthBiasClamp = 0.0f;
+ rsScissorDesc.SlopeScaledDepthBias = 0.0f;
+ rsScissorDesc.DepthClipEnable = FALSE;
+ rsScissorDesc.ScissorEnable = TRUE;
+ rsScissorDesc.MultisampleEnable = FALSE;
+ rsScissorDesc.AntialiasedLineEnable = FALSE;
+
+ result = mDevice->CreateRasterizerState(&rsScissorDesc, &mClearScissorRS);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mClearScissorRS, "Renderer11 masked clear scissor rasterizer state");
+
+ D3D11_RASTERIZER_DESC rsNoScissorDesc;
+ rsNoScissorDesc.FillMode = D3D11_FILL_SOLID;
+ rsNoScissorDesc.CullMode = D3D11_CULL_NONE;
+ rsNoScissorDesc.FrontCounterClockwise = FALSE;
+ rsNoScissorDesc.DepthBias = 0;
+ rsNoScissorDesc.DepthBiasClamp = 0.0f;
+ rsNoScissorDesc.SlopeScaledDepthBias = 0.0f;
+ rsNoScissorDesc.DepthClipEnable = FALSE;
+ rsNoScissorDesc.ScissorEnable = FALSE;
+ rsNoScissorDesc.MultisampleEnable = FALSE;
+ rsNoScissorDesc.AntialiasedLineEnable = FALSE;
+
+ result = mDevice->CreateRasterizerState(&rsNoScissorDesc, &mClearNoScissorRS);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mClearNoScissorRS, "Renderer11 masked clear no scissor rasterizer state");
+
+ mClearResourcesInitialized = true;
+ }
+
+ // Prepare the depth stencil state to write depth values if the depth should be cleared
+ // and stencil values if the stencil should be cleared
+ gl::DepthStencilState glDSState;
+ glDSState.depthTest = (clearParams.mask & GL_DEPTH_BUFFER_BIT) != 0;
+ glDSState.depthFunc = GL_ALWAYS;
+ glDSState.depthMask = (clearParams.mask & GL_DEPTH_BUFFER_BIT) != 0;
+ glDSState.stencilTest = (clearParams.mask & GL_STENCIL_BUFFER_BIT) != 0;
+ glDSState.stencilFunc = GL_ALWAYS;
+ glDSState.stencilMask = 0;
+ glDSState.stencilFail = GL_REPLACE;
+ glDSState.stencilPassDepthFail = GL_REPLACE;
+ glDSState.stencilPassDepthPass = GL_REPLACE;
+ glDSState.stencilWritemask = clearParams.stencilWriteMask;
+ glDSState.stencilBackFunc = GL_ALWAYS;
+ glDSState.stencilBackMask = 0;
+ glDSState.stencilBackFail = GL_REPLACE;
+ glDSState.stencilBackPassDepthFail = GL_REPLACE;
+ glDSState.stencilBackPassDepthPass = GL_REPLACE;
+ glDSState.stencilBackWritemask = clearParams.stencilWriteMask;
+
+ int stencilClear = clearParams.stencilClearValue & 0x000000FF;
+
+ ID3D11DepthStencilState *dsState = mStateCache.getDepthStencilState(glDSState);
+
+ // Prepare the blend state to use a write mask if the color buffer should be cleared
+ gl::BlendState glBlendState;
+ glBlendState.blend = false;
+ glBlendState.sourceBlendRGB = GL_ONE;
+ glBlendState.destBlendRGB = GL_ZERO;
+ glBlendState.sourceBlendAlpha = GL_ONE;
+ glBlendState.destBlendAlpha = GL_ZERO;
+ glBlendState.blendEquationRGB = GL_FUNC_ADD;
+ glBlendState.blendEquationAlpha = GL_FUNC_ADD;
+ glBlendState.colorMaskRed = (clearParams.mask & GL_COLOR_BUFFER_BIT) ? clearParams.colorMaskRed : false;
+ glBlendState.colorMaskGreen = (clearParams.mask & GL_COLOR_BUFFER_BIT) ? clearParams.colorMaskGreen : false;
+ glBlendState.colorMaskBlue = (clearParams.mask & GL_COLOR_BUFFER_BIT) ? clearParams.colorMaskBlue : false;
+ glBlendState.colorMaskAlpha = (clearParams.mask & GL_COLOR_BUFFER_BIT) ? clearParams.colorMaskAlpha : false;
+ glBlendState.sampleAlphaToCoverage = false;
+ glBlendState.dither = false;
+
+ static const float blendFactors[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
+ static const UINT sampleMask = 0xFFFFFFFF;
+
+ ID3D11BlendState *blendState = mStateCache.getBlendState(frameBuffer, glBlendState);
+
+ // Set the vertices
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ result = mDeviceContext->Map(mClearVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+ if (FAILED(result))
+ {
+ ERR("Failed to map masked clear vertex buffer, HRESULT: 0x%X.", result);
+ return;
+ }
+
+ d3d11::PositionDepthColorVertex *vertices = reinterpret_cast<d3d11::PositionDepthColorVertex*>(mappedResource.pData);
+
+ float depthClear = gl::clamp01(clearParams.depthClearValue);
+ d3d11::SetPositionDepthColorVertex(&vertices[0], -1.0f, 1.0f, depthClear, clearParams.colorClearValue);
+ d3d11::SetPositionDepthColorVertex(&vertices[1], -1.0f, -1.0f, depthClear, clearParams.colorClearValue);
+ d3d11::SetPositionDepthColorVertex(&vertices[2], 1.0f, 1.0f, depthClear, clearParams.colorClearValue);
+ d3d11::SetPositionDepthColorVertex(&vertices[3], 1.0f, -1.0f, depthClear, clearParams.colorClearValue);
+
+ mDeviceContext->Unmap(mClearVB, 0);
+
+ // Apply state
+ mDeviceContext->OMSetBlendState(blendState, blendFactors, sampleMask);
+ mDeviceContext->OMSetDepthStencilState(dsState, stencilClear);
+ mDeviceContext->RSSetState(mScissorEnabled ? mClearScissorRS : mClearNoScissorRS);
+
+ // Apply shaders
+ ID3D11PixelShader *pixelShader = frameBuffer->usingExtendedDrawBuffers() ? mClearMultiplePS : mClearSinglePS;
+
+ mDeviceContext->IASetInputLayout(mClearIL);
+ mDeviceContext->VSSetShader(mClearVS, NULL, 0);
+ mDeviceContext->PSSetShader(pixelShader, NULL, 0);
+ mDeviceContext->GSSetShader(NULL, NULL, 0);
+
+ // Apply vertex buffer
+ static UINT stride = sizeof(d3d11::PositionDepthColorVertex);
+ static UINT startIdx = 0;
+ mDeviceContext->IASetVertexBuffers(0, 1, &mClearVB, &stride, &startIdx);
+ mDeviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
+
+ // Draw the clear quad
+ mDeviceContext->Draw(4, 0);
+
+ // Clean up
+ markAllStateDirty();
+}
+
+void Renderer11::markAllStateDirty()
+{
+ for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++)
+ {
+ mAppliedRenderTargetSerials[rtIndex] = 0;
+ }
+ mAppliedDepthbufferSerial = 0;
+ mAppliedStencilbufferSerial = 0;
+ mDepthStencilInitialized = false;
+ mRenderTargetDescInitialized = false;
+
+ for (int i = 0; i < gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; i++)
+ {
+ mForceSetVertexSamplerStates[i] = true;
+ mCurVertexTextureSerials[i] = 0;
+ }
+ for (int i = 0; i < gl::MAX_TEXTURE_IMAGE_UNITS; i++)
+ {
+ mForceSetPixelSamplerStates[i] = true;
+ mCurPixelTextureSerials[i] = 0;
+ }
+
+ mForceSetBlendState = true;
+ mForceSetRasterState = true;
+ mForceSetDepthStencilState = true;
+ mForceSetScissor = true;
+ mForceSetViewport = true;
+
+ mAppliedIBSerial = 0;
+ mAppliedStorageIBSerial = 0;
+ mAppliedIBOffset = 0;
+
+ mAppliedProgramBinarySerial = 0;
+ memset(&mAppliedVertexConstants, 0, sizeof(dx_VertexConstants));
+ memset(&mAppliedPixelConstants, 0, sizeof(dx_PixelConstants));
+
+ mInputLayoutCache.markDirty();
+
+ mCurrentVertexConstantBuffer = NULL;
+ mCurrentPixelConstantBuffer = NULL;
+ mCurrentGeometryConstantBuffer = NULL;
+
+ mCurrentPrimitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
+}
+
+void Renderer11::releaseDeviceResources()
+{
+ mStateCache.clear();
+ mInputLayoutCache.clear();
+
+ delete mVertexDataManager;
+ mVertexDataManager = NULL;
+
+ delete mIndexDataManager;
+ mIndexDataManager = NULL;
+
+ delete mLineLoopIB;
+ mLineLoopIB = NULL;
+
+ delete mTriangleFanIB;
+ mTriangleFanIB = NULL;
+
+ SafeRelease(mCopyVB);
+ SafeRelease(mCopySampler);
+ SafeRelease(mCopyIL);
+ SafeRelease(mCopyIL);
+ SafeRelease(mCopyVS);
+ SafeRelease(mCopyRGBAPS);
+ SafeRelease(mCopyRGBPS);
+ SafeRelease(mCopyLumPS);
+ SafeRelease(mCopyLumAlphaPS);
+
+ mCopyResourcesInitialized = false;
+
+ SafeRelease(mClearVB);
+ SafeRelease(mClearIL);
+ SafeRelease(mClearVS);
+ SafeRelease(mClearSinglePS);
+ SafeRelease(mClearMultiplePS);
+ SafeRelease(mClearScissorRS);
+ SafeRelease(mClearNoScissorRS);
+
+ mClearResourcesInitialized = false;
+
+ SafeRelease(mDriverConstantBufferVS);
+ SafeRelease(mDriverConstantBufferPS);
+ SafeRelease(mSyncQuery);
+}
+
+void Renderer11::notifyDeviceLost()
+{
+ mDeviceLost = true;
+ mDisplay->notifyDeviceLost();
+}
+
+bool Renderer11::isDeviceLost()
+{
+ return mDeviceLost;
+}
+
+// set notify to true to broadcast a message to all contexts of the device loss
+bool Renderer11::testDeviceLost(bool notify)
+{
+ bool isLost = false;
+
+ // GetRemovedReason is used to test if the device is removed
+ HRESULT result = mDevice->GetDeviceRemovedReason();
+ isLost = d3d11::isDeviceLostError(result);
+
+ if (isLost)
+ {
+ // Log error if this is a new device lost event
+ if (mDeviceLost == false)
+ {
+ ERR("The D3D11 device was removed: 0x%08X", result);
+ }
+
+ // ensure we note the device loss --
+ // we'll probably get this done again by notifyDeviceLost
+ // but best to remember it!
+ // Note that we don't want to clear the device loss status here
+ // -- this needs to be done by resetDevice
+ mDeviceLost = true;
+ if (notify)
+ {
+ notifyDeviceLost();
+ }
+ }
+
+ return isLost;
+}
+
+bool Renderer11::testDeviceResettable()
+{
+ // determine if the device is resettable by creating a dummy device
+ PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice");
+
+ if (D3D11CreateDevice == NULL)
+ {
+ return false;
+ }
+
+ D3D_FEATURE_LEVEL featureLevels[] =
+ {
+ D3D_FEATURE_LEVEL_11_0,
+ D3D_FEATURE_LEVEL_10_1,
+ D3D_FEATURE_LEVEL_10_0,
+ };
+
+ ID3D11Device* dummyDevice;
+ D3D_FEATURE_LEVEL dummyFeatureLevel;
+ ID3D11DeviceContext* dummyContext;
+
+ HRESULT result = D3D11CreateDevice(NULL,
+ D3D_DRIVER_TYPE_HARDWARE,
+ NULL,
+ #if defined(_DEBUG)
+ D3D11_CREATE_DEVICE_DEBUG,
+ #else
+ 0,
+ #endif
+ featureLevels,
+ ArraySize(featureLevels),
+ D3D11_SDK_VERSION,
+ &dummyDevice,
+ &dummyFeatureLevel,
+ &dummyContext);
+
+ if (!mDevice || FAILED(result))
+ {
+ return false;
+ }
+
+ dummyContext->Release();
+ dummyDevice->Release();
+
+ return true;
+}
+
+void Renderer11::release()
+{
+ releaseDeviceResources();
+
+ if (mDxgiFactory)
+ {
+ mDxgiFactory->Release();
+ mDxgiFactory = NULL;
+ }
+
+ if (mDxgiAdapter)
+ {
+ mDxgiAdapter->Release();
+ mDxgiAdapter = NULL;
+ }
+
+ if (mDeviceContext)
+ {
+ mDeviceContext->ClearState();
+ mDeviceContext->Flush();
+ mDeviceContext->Release();
+ mDeviceContext = NULL;
+ }
+
+ if (mDevice)
+ {
+ mDevice->Release();
+ mDevice = NULL;
+ }
+
+ if (mD3d11Module)
+ {
+ FreeLibrary(mD3d11Module);
+ mD3d11Module = NULL;
+ }
+
+ if (mDxgiModule)
+ {
+ FreeLibrary(mDxgiModule);
+ mDxgiModule = NULL;
+ }
+}
+
+bool Renderer11::resetDevice()
+{
+ // recreate everything
+ release();
+ EGLint result = initialize();
+
+ if (result != EGL_SUCCESS)
+ {
+ ERR("Could not reinitialize D3D11 device: %08X", result);
+ return false;
+ }
+
+ mDeviceLost = false;
+
+ return true;
+}
+
+DWORD Renderer11::getAdapterVendor() const
+{
+ return mAdapterDescription.VendorId;
+}
+
+std::string Renderer11::getRendererDescription() const
+{
+ std::ostringstream rendererString;
+
+ rendererString << mDescription;
+ rendererString << " Direct3D11";
+
+ rendererString << " vs_" << getMajorShaderModel() << "_" << getMinorShaderModel();
+ rendererString << " ps_" << getMajorShaderModel() << "_" << getMinorShaderModel();
+
+ return rendererString.str();
+}
+
+GUID Renderer11::getAdapterIdentifier() const
+{
+ // Use the adapter LUID as our adapter ID
+ // This number is local to a machine is only guaranteed to be unique between restarts
+ META_ASSERT(sizeof(LUID) <= sizeof(GUID));
+ GUID adapterId = {0};
+ memcpy(&adapterId, &mAdapterDescription.AdapterLuid, sizeof(LUID));
+ return adapterId;
+}
+
+bool Renderer11::getBGRATextureSupport() const
+{
+ return mBGRATextureSupport;
+}
+
+bool Renderer11::getDXT1TextureSupport()
+{
+ return mDXT1TextureSupport;
+}
+
+bool Renderer11::getDXT3TextureSupport()
+{
+ return mDXT3TextureSupport;
+}
+
+bool Renderer11::getDXT5TextureSupport()
+{
+ return mDXT5TextureSupport;
+}
+
+bool Renderer11::getDepthTextureSupport() const
+{
+ return mDepthTextureSupport;
+}
+
+bool Renderer11::getFloat32TextureSupport(bool *filtering, bool *renderable)
+{
+ *renderable = mFloat32RenderSupport;
+ *filtering = mFloat32FilterSupport;
+ return mFloat32TextureSupport;
+}
+
+bool Renderer11::getFloat16TextureSupport(bool *filtering, bool *renderable)
+{
+ *renderable = mFloat16RenderSupport;
+ *filtering = mFloat16FilterSupport;
+ return mFloat16TextureSupport;
+}
+
+bool Renderer11::getLuminanceTextureSupport()
+{
+ return false;
+}
+
+bool Renderer11::getLuminanceAlphaTextureSupport()
+{
+ return false;
+}
+
+bool Renderer11::getTextureFilterAnisotropySupport() const
+{
+ return true;
+}
+
+float Renderer11::getTextureMaxAnisotropy() const
+{
+ switch (mFeatureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_MAX_MAXANISOTROPY;
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return D3D10_MAX_MAXANISOTROPY;
+ default: UNREACHABLE();
+ return 0;
+ }
+}
+
+bool Renderer11::getEventQuerySupport()
+{
+ return true;
+}
+
+Range Renderer11::getViewportBounds() const
+{
+ switch (mFeatureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_0:
+ return Range(D3D11_VIEWPORT_BOUNDS_MIN, D3D11_VIEWPORT_BOUNDS_MAX);
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return Range(D3D10_VIEWPORT_BOUNDS_MIN, D3D10_VIEWPORT_BOUNDS_MAX);
+ default: UNREACHABLE();
+ return Range(0, 0);
+ }
+}
+
+unsigned int Renderer11::getMaxVertexTextureImageUnits() const
+{
+ META_ASSERT(MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 <= gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS);
+ switch (mFeatureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return MAX_TEXTURE_IMAGE_UNITS_VTF_SM4;
+ default: UNREACHABLE();
+ return 0;
+ }
+}
+
+unsigned int Renderer11::getMaxCombinedTextureImageUnits() const
+{
+ return gl::MAX_TEXTURE_IMAGE_UNITS + getMaxVertexTextureImageUnits();
+}
+
+unsigned int Renderer11::getReservedVertexUniformVectors() const
+{
+ return 0; // Driver uniforms are stored in a separate constant buffer
+}
+
+unsigned int Renderer11::getReservedFragmentUniformVectors() const
+{
+ return 0; // Driver uniforms are stored in a separate constant buffer
+}
+
+unsigned int Renderer11::getMaxVertexUniformVectors() const
+{
+ META_ASSERT(MAX_VERTEX_UNIFORM_VECTORS_D3D11 <= D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT);
+ ASSERT(mFeatureLevel >= D3D_FEATURE_LEVEL_10_0);
+ return MAX_VERTEX_UNIFORM_VECTORS_D3D11;
+}
+
+unsigned int Renderer11::getMaxFragmentUniformVectors() const
+{
+ META_ASSERT(MAX_FRAGMENT_UNIFORM_VECTORS_D3D11 <= D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT);
+ ASSERT(mFeatureLevel >= D3D_FEATURE_LEVEL_10_0);
+ return MAX_FRAGMENT_UNIFORM_VECTORS_D3D11;
+}
+
+unsigned int Renderer11::getMaxVaryingVectors() const
+{
+ META_ASSERT(gl::IMPLEMENTATION_MAX_VARYING_VECTORS == D3D11_VS_OUTPUT_REGISTER_COUNT);
+ switch (mFeatureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_VS_OUTPUT_REGISTER_COUNT;
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return D3D10_VS_OUTPUT_REGISTER_COUNT;
+ default: UNREACHABLE();
+ return 0;
+ }
+}
+
+bool Renderer11::getNonPower2TextureSupport() const
+{
+ switch (mFeatureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return true;
+ default: UNREACHABLE();
+ return false;
+ }
+}
+
+bool Renderer11::getOcclusionQuerySupport() const
+{
+ switch (mFeatureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return true;
+ default: UNREACHABLE();
+ return false;
+ }
+}
+
+bool Renderer11::getInstancingSupport() const
+{
+ switch (mFeatureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return true;
+ default: UNREACHABLE();
+ return false;
+ }
+}
+
+bool Renderer11::getShareHandleSupport() const
+{
+ // We only currently support share handles with BGRA surfaces, because
+ // chrome needs BGRA. Once chrome fixes this, we should always support them.
+ // PIX doesn't seem to support using share handles, so disable them.
+ return getBGRATextureSupport() && !gl::perfActive();
+}
+
+bool Renderer11::getDerivativeInstructionSupport() const
+{
+ switch (mFeatureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return true;
+ default: UNREACHABLE();
+ return false;
+ }
+}
+
+bool Renderer11::getPostSubBufferSupport() const
+{
+ // D3D11 does not support present with dirty rectangles until D3D11.1 and DXGI 1.2.
+ return false;
+}
+
+int Renderer11::getMajorShaderModel() const
+{
+ switch (mFeatureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_0: return D3D11_SHADER_MAJOR_VERSION; // 5
+ case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SHADER_MAJOR_VERSION; // 4
+ case D3D_FEATURE_LEVEL_10_0: return D3D10_SHADER_MAJOR_VERSION; // 4
+ default: UNREACHABLE(); return 0;
+ }
+}
+
+int Renderer11::getMinorShaderModel() const
+{
+ switch (mFeatureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_0: return D3D11_SHADER_MINOR_VERSION; // 0
+ case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SHADER_MINOR_VERSION; // 1
+ case D3D_FEATURE_LEVEL_10_0: return D3D10_SHADER_MINOR_VERSION; // 0
+ default: UNREACHABLE(); return 0;
+ }
+}
+
+float Renderer11::getMaxPointSize() const
+{
+ // choose a reasonable maximum. we enforce this in the shader.
+ // (nb: on a Radeon 2600xt, DX9 reports a 256 max point size)
+ return 1024.0f;
+}
+
+int Renderer11::getMaxViewportDimension() const
+{
+ // Maximum viewport size must be at least as large as the largest render buffer (or larger).
+ // In our case return the maximum texture size, which is the maximum render buffer size.
+ META_ASSERT(D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION * 2 - 1 <= D3D11_VIEWPORT_BOUNDS_MAX);
+ META_ASSERT(D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION * 2 - 1 <= D3D10_VIEWPORT_BOUNDS_MAX);
+
+ switch (mFeatureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 16384
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 8192
+ default: UNREACHABLE();
+ return 0;
+ }
+}
+
+int Renderer11::getMaxTextureWidth() const
+{
+ switch (mFeatureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 16384
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 8192
+ default: UNREACHABLE(); return 0;
+ }
+}
+
+int Renderer11::getMaxTextureHeight() const
+{
+ switch (mFeatureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 16384
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 8192
+ default: UNREACHABLE(); return 0;
+ }
+}
+
+bool Renderer11::get32BitIndexSupport() const
+{
+ switch (mFeatureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP >= 32; // true
+ default: UNREACHABLE(); return false;
+ }
+}
+
+int Renderer11::getMinSwapInterval() const
+{
+ return 0;
+}
+
+int Renderer11::getMaxSwapInterval() const
+{
+ return 4;
+}
+
+int Renderer11::getMaxSupportedSamples() const
+{
+ return mMaxSupportedSamples;
+}
+
+int Renderer11::getNearestSupportedSamples(DXGI_FORMAT format, unsigned int requested) const
+{
+ if (requested == 0)
+ {
+ return 0;
+ }
+
+ MultisampleSupportMap::const_iterator iter = mMultisampleSupportMap.find(format);
+ if (iter != mMultisampleSupportMap.end())
+ {
+ const MultisampleSupportInfo& info = iter->second;
+ for (unsigned int i = requested - 1; i < D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; i++)
+ {
+ if (info.qualityLevels[i] > 0)
+ {
+ return i + 1;
+ }
+ }
+ }
+
+ return -1;
+}
+
+unsigned int Renderer11::getMaxRenderTargets() const
+{
+ META_ASSERT(D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT <= gl::IMPLEMENTATION_MAX_DRAW_BUFFERS);
+ META_ASSERT(D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT <= gl::IMPLEMENTATION_MAX_DRAW_BUFFERS);
+
+ switch (mFeatureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; // 8
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ // Feature level 10.0 and 10.1 cards perform very poorly when the pixel shader
+ // outputs to multiple RTs that are not bound.
+ // TODO: Remove pixel shader outputs for render targets that are not bound.
+ return 1;
+ default:
+ UNREACHABLE();
+ return 1;
+ }
+}
+
+bool Renderer11::copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source)
+{
+ if (source && dest)
+ {
+ TextureStorage11_2D *source11 = TextureStorage11_2D::makeTextureStorage11_2D(source->getStorageInstance());
+ TextureStorage11_2D *dest11 = TextureStorage11_2D::makeTextureStorage11_2D(dest->getStorageInstance());
+
+ mDeviceContext->CopyResource(dest11->getBaseTexture(), source11->getBaseTexture());
+ return true;
+ }
+
+ return false;
+}
+
+bool Renderer11::copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source)
+{
+ if (source && dest)
+ {
+ TextureStorage11_Cube *source11 = TextureStorage11_Cube::makeTextureStorage11_Cube(source->getStorageInstance());
+ TextureStorage11_Cube *dest11 = TextureStorage11_Cube::makeTextureStorage11_Cube(dest->getStorageInstance());
+
+ mDeviceContext->CopyResource(dest11->getBaseTexture(), source11->getBaseTexture());
+ return true;
+ }
+
+ return false;
+}
+
+bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level)
+{
+ gl::Renderbuffer *colorbuffer = framebuffer->getReadColorbuffer();
+ if (!colorbuffer)
+ {
+ ERR("Failed to retrieve the color buffer from the frame buffer.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ RenderTarget11 *sourceRenderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget());
+ if (!sourceRenderTarget)
+ {
+ ERR("Failed to retrieve the render target from the frame buffer.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView();
+ if (!source)
+ {
+ ERR("Failed to retrieve the render target view from the render target.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ TextureStorage11_2D *storage11 = TextureStorage11_2D::makeTextureStorage11_2D(storage->getStorageInstance());
+ if (!storage11)
+ {
+ ERR("Failed to retrieve the texture storage from the destination.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTarget(level));
+ if (!destRenderTarget)
+ {
+ ERR("Failed to retrieve the render target from the destination storage.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView();
+ if (!dest)
+ {
+ ERR("Failed to retrieve the render target view from the destination render target.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ gl::Rectangle destRect;
+ destRect.x = xoffset;
+ destRect.y = yoffset;
+ destRect.width = sourceRect.width;
+ destRect.height = sourceRect.height;
+
+ bool ret = copyTexture(source, sourceRect, sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(),
+ dest, destRect, destRenderTarget->getWidth(), destRenderTarget->getHeight(), destFormat);
+
+ return ret;
+}
+
+bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level)
+{
+ gl::Renderbuffer *colorbuffer = framebuffer->getReadColorbuffer();
+ if (!colorbuffer)
+ {
+ ERR("Failed to retrieve the color buffer from the frame buffer.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ RenderTarget11 *sourceRenderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget());
+ if (!sourceRenderTarget)
+ {
+ ERR("Failed to retrieve the render target from the frame buffer.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView();
+ if (!source)
+ {
+ ERR("Failed to retrieve the render target view from the render target.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ TextureStorage11_Cube *storage11 = TextureStorage11_Cube::makeTextureStorage11_Cube(storage->getStorageInstance());
+ if (!storage11)
+ {
+ ERR("Failed to retrieve the texture storage from the destination.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTarget(target, level));
+ if (!destRenderTarget)
+ {
+ ERR("Failed to retrieve the render target from the destination storage.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView();
+ if (!dest)
+ {
+ ERR("Failed to retrieve the render target view from the destination render target.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ gl::Rectangle destRect;
+ destRect.x = xoffset;
+ destRect.y = yoffset;
+ destRect.width = sourceRect.width;
+ destRect.height = sourceRect.height;
+
+ bool ret = copyTexture(source, sourceRect, sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(),
+ dest, destRect, destRenderTarget->getWidth(), destRenderTarget->getHeight(), destFormat);
+
+ return ret;
+}
+
+bool Renderer11::copyTexture(ID3D11ShaderResourceView *source, const gl::Rectangle &sourceArea, unsigned int sourceWidth, unsigned int sourceHeight,
+ ID3D11RenderTargetView *dest, const gl::Rectangle &destArea, unsigned int destWidth, unsigned int destHeight, GLenum destFormat)
+{
+ HRESULT result;
+
+ if (!mCopyResourcesInitialized)
+ {
+ ASSERT(!mCopyVB && !mCopySampler && !mCopyIL && !mCopyVS && !mCopyRGBAPS && !mCopyRGBPS && !mCopyLumPS && !mCopyLumAlphaPS);
+
+ D3D11_BUFFER_DESC vbDesc;
+ vbDesc.ByteWidth = sizeof(d3d11::PositionTexCoordVertex) * 4;
+ vbDesc.Usage = D3D11_USAGE_DYNAMIC;
+ vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
+ vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ vbDesc.MiscFlags = 0;
+ vbDesc.StructureByteStride = 0;
+
+ result = mDevice->CreateBuffer(&vbDesc, NULL, &mCopyVB);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mCopyVB, "Renderer11 copy texture vertex buffer");
+
+ D3D11_SAMPLER_DESC samplerDesc;
+ samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
+ samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
+ samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
+ samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
+ samplerDesc.MipLODBias = 0.0f;
+ samplerDesc.MaxAnisotropy = 0;
+ samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
+ samplerDesc.BorderColor[0] = 0.0f;
+ samplerDesc.BorderColor[1] = 0.0f;
+ samplerDesc.BorderColor[2] = 0.0f;
+ samplerDesc.BorderColor[3] = 0.0f;
+ samplerDesc.MinLOD = 0.0f;
+ samplerDesc.MaxLOD = 0.0f;
+
+ result = mDevice->CreateSamplerState(&samplerDesc, &mCopySampler);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mCopySampler, "Renderer11 copy sampler");
+
+ D3D11_INPUT_ELEMENT_DESC quadLayout[] =
+ {
+ { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
+ { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 },
+ };
+
+ result = mDevice->CreateInputLayout(quadLayout, 2, g_VS_Passthrough, sizeof(g_VS_Passthrough), &mCopyIL);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mCopyIL, "Renderer11 copy texture input layout");
+
+ result = mDevice->CreateVertexShader(g_VS_Passthrough, sizeof(g_VS_Passthrough), NULL, &mCopyVS);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mCopyVS, "Renderer11 copy texture vertex shader");
+
+ result = mDevice->CreatePixelShader(g_PS_PassthroughRGBA, sizeof(g_PS_PassthroughRGBA), NULL, &mCopyRGBAPS);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mCopyRGBAPS, "Renderer11 copy texture RGBA pixel shader");
+
+ result = mDevice->CreatePixelShader(g_PS_PassthroughRGB, sizeof(g_PS_PassthroughRGB), NULL, &mCopyRGBPS);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mCopyRGBPS, "Renderer11 copy texture RGB pixel shader");
+
+ result = mDevice->CreatePixelShader(g_PS_PassthroughLum, sizeof(g_PS_PassthroughLum), NULL, &mCopyLumPS);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mCopyLumPS, "Renderer11 copy texture luminance pixel shader");
+
+ result = mDevice->CreatePixelShader(g_PS_PassthroughLumAlpha, sizeof(g_PS_PassthroughLumAlpha), NULL, &mCopyLumAlphaPS);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mCopyLumAlphaPS, "Renderer11 copy texture luminance alpha pixel shader");
+
+ mCopyResourcesInitialized = true;
+ }
+
+ // Verify the source and destination area sizes
+ if (sourceArea.x < 0 || sourceArea.x + sourceArea.width > static_cast<int>(sourceWidth) ||
+ sourceArea.y < 0 || sourceArea.y + sourceArea.height > static_cast<int>(sourceHeight) ||
+ destArea.x < 0 || destArea.x + destArea.width > static_cast<int>(destWidth) ||
+ destArea.y < 0 || destArea.y + destArea.height > static_cast<int>(destHeight))
+ {
+ return gl::error(GL_INVALID_VALUE, false);
+ }
+
+ // Set vertices
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ result = mDeviceContext->Map(mCopyVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+ if (FAILED(result))
+ {
+ ERR("Failed to map vertex buffer for texture copy, HRESULT: 0x%X.", result);
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ d3d11::PositionTexCoordVertex *vertices = static_cast<d3d11::PositionTexCoordVertex*>(mappedResource.pData);
+
+ // Create a quad in homogeneous coordinates
+ float x1 = (destArea.x / float(destWidth)) * 2.0f - 1.0f;
+ float y1 = ((destHeight - destArea.y - destArea.height) / float(destHeight)) * 2.0f - 1.0f;
+ float x2 = ((destArea.x + destArea.width) / float(destWidth)) * 2.0f - 1.0f;
+ float y2 = ((destHeight - destArea.y) / float(destHeight)) * 2.0f - 1.0f;
+
+ float u1 = sourceArea.x / float(sourceWidth);
+ float v1 = sourceArea.y / float(sourceHeight);
+ float u2 = (sourceArea.x + sourceArea.width) / float(sourceWidth);
+ float v2 = (sourceArea.y + sourceArea.height) / float(sourceHeight);
+
+ d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v2);
+ d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v1);
+ d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v2);
+ d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v1);
+
+ mDeviceContext->Unmap(mCopyVB, 0);
+
+ static UINT stride = sizeof(d3d11::PositionTexCoordVertex);
+ static UINT startIdx = 0;
+ mDeviceContext->IASetVertexBuffers(0, 1, &mCopyVB, &stride, &startIdx);
+
+ // Apply state
+ mDeviceContext->OMSetBlendState(NULL, NULL, 0xFFFFFFF);
+ mDeviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF);
+ mDeviceContext->RSSetState(NULL);
+
+ // Apply shaders
+ mDeviceContext->IASetInputLayout(mCopyIL);
+ mDeviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
+ mDeviceContext->VSSetShader(mCopyVS, NULL, 0);
+
+ ID3D11PixelShader *ps = NULL;
+ switch(destFormat)
+ {
+ case GL_RGBA: ps = mCopyRGBAPS; break;
+ case GL_RGB: ps = mCopyRGBPS; break;
+ case GL_ALPHA: ps = mCopyRGBAPS; break;
+ case GL_BGRA_EXT: ps = mCopyRGBAPS; break;
+ case GL_LUMINANCE: ps = mCopyLumPS; break;
+ case GL_LUMINANCE_ALPHA: ps = mCopyLumAlphaPS; break;
+ default: UNREACHABLE(); ps = NULL; break;
+ }
+
+ mDeviceContext->PSSetShader(ps, NULL, 0);
+ mDeviceContext->GSSetShader(NULL, NULL, 0);
+
+ // Unset the currently bound shader resource to avoid conflicts
+ static ID3D11ShaderResourceView *const nullSRV = NULL;
+ mDeviceContext->PSSetShaderResources(0, 1, &nullSRV);
+
+ // Apply render target
+ setOneTimeRenderTarget(dest);
+
+ // Set the viewport
+ D3D11_VIEWPORT viewport;
+ viewport.TopLeftX = 0;
+ viewport.TopLeftY = 0;
+ viewport.Width = destWidth;
+ viewport.Height = destHeight;
+ viewport.MinDepth = 0.0f;
+ viewport.MaxDepth = 1.0f;
+ mDeviceContext->RSSetViewports(1, &viewport);
+
+ // Apply textures
+ mDeviceContext->PSSetShaderResources(0, 1, &source);
+ mDeviceContext->PSSetSamplers(0, 1, &mCopySampler);
+
+ // Draw the quad
+ mDeviceContext->Draw(4, 0);
+
+ // Unbind textures and render targets and vertex buffer
+ mDeviceContext->PSSetShaderResources(0, 1, &nullSRV);
+
+ unapplyRenderTargets();
+
+ UINT zero = 0;
+ ID3D11Buffer *const nullBuffer = NULL;
+ mDeviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero);
+
+ markAllStateDirty();
+
+ return true;
+}
+
+void Renderer11::unapplyRenderTargets()
+{
+ setOneTimeRenderTarget(NULL);
+}
+
+void Renderer11::setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView)
+{
+ ID3D11RenderTargetView *rtvArray[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {NULL};
+
+ rtvArray[0] = renderTargetView;
+
+ mDeviceContext->OMSetRenderTargets(getMaxRenderTargets(), rtvArray, NULL);
+
+ // Do not preserve the serial for this one-time-use render target
+ for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++)
+ {
+ mAppliedRenderTargetSerials[rtIndex] = 0;
+ }
+}
+
+RenderTarget *Renderer11::createRenderTarget(SwapChain *swapChain, bool depth)
+{
+ SwapChain11 *swapChain11 = SwapChain11::makeSwapChain11(swapChain);
+ RenderTarget11 *renderTarget = NULL;
+
+ if (depth)
+ {
+ // Note: depth stencil may be NULL for 0 sized surfaces
+ renderTarget = new RenderTarget11(this, swapChain11->getDepthStencil(),
+ swapChain11->getDepthStencilTexture(), NULL,
+ swapChain11->getWidth(), swapChain11->getHeight());
+ }
+ else
+ {
+ // Note: render target may be NULL for 0 sized surfaces
+ renderTarget = new RenderTarget11(this, swapChain11->getRenderTarget(),
+ swapChain11->getOffscreenTexture(),
+ swapChain11->getRenderTargetShaderResource(),
+ swapChain11->getWidth(), swapChain11->getHeight());
+ }
+ return renderTarget;
+}
+
+RenderTarget *Renderer11::createRenderTarget(int width, int height, GLenum format, GLsizei samples, bool depth)
+{
+ RenderTarget11 *renderTarget = new RenderTarget11(this, width, height, format, samples, depth);
+ return renderTarget;
+}
+
+ShaderExecutable *Renderer11::loadExecutable(const void *function, size_t length, rx::ShaderType type)
+{
+ ShaderExecutable11 *executable = NULL;
+
+ switch (type)
+ {
+ case rx::SHADER_VERTEX:
+ {
+ ID3D11VertexShader *vshader = NULL;
+ HRESULT result = mDevice->CreateVertexShader(function, length, NULL, &vshader);
+ ASSERT(SUCCEEDED(result));
+
+ if (vshader)
+ {
+ executable = new ShaderExecutable11(function, length, vshader);
+ }
+ }
+ break;
+ case rx::SHADER_PIXEL:
+ {
+ ID3D11PixelShader *pshader = NULL;
+ HRESULT result = mDevice->CreatePixelShader(function, length, NULL, &pshader);
+ ASSERT(SUCCEEDED(result));
+
+ if (pshader)
+ {
+ executable = new ShaderExecutable11(function, length, pshader);
+ }
+ }
+ break;
+ case rx::SHADER_GEOMETRY:
+ {
+ ID3D11GeometryShader *gshader = NULL;
+ HRESULT result = mDevice->CreateGeometryShader(function, length, NULL, &gshader);
+ ASSERT(SUCCEEDED(result));
+
+ if (gshader)
+ {
+ executable = new ShaderExecutable11(function, length, gshader);
+ }
+ }
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ return executable;
+}
+
+ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, D3DWorkaroundType workaround)
+{
+ const char *profile = NULL;
+
+ switch (type)
+ {
+ case rx::SHADER_VERTEX:
+ profile = "vs_4_0";
+ break;
+ case rx::SHADER_PIXEL:
+ profile = "ps_4_0";
+ break;
+ case rx::SHADER_GEOMETRY:
+ profile = "gs_4_0";
+ break;
+ default:
+ UNREACHABLE();
+ return NULL;
+ }
+
+ ID3DBlob *binary = (ID3DBlob*)compileToBinary(infoLog, shaderHLSL, profile, D3DCOMPILE_OPTIMIZATION_LEVEL0, false);
+ if (!binary)
+ return NULL;
+
+ ShaderExecutable *executable = loadExecutable((DWORD *)binary->GetBufferPointer(), binary->GetBufferSize(), type);
+ binary->Release();
+
+ return executable;
+}
+
+VertexBuffer *Renderer11::createVertexBuffer()
+{
+ return new VertexBuffer11(this);
+}
+
+IndexBuffer *Renderer11::createIndexBuffer()
+{
+ return new IndexBuffer11(this);
+}
+
+BufferStorage *Renderer11::createBufferStorage()
+{
+ return new BufferStorage11(this);
+}
+
+QueryImpl *Renderer11::createQuery(GLenum type)
+{
+ return new Query11(this, type);
+}
+
+FenceImpl *Renderer11::createFence()
+{
+ return new Fence11(this);
+}
+
+bool Renderer11::getRenderTargetResource(gl::Renderbuffer *colorbuffer, unsigned int *subresourceIndex, ID3D11Texture2D **resource)
+{
+ ASSERT(colorbuffer != NULL);
+
+ RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget());
+ if (renderTarget)
+ {
+ *subresourceIndex = renderTarget->getSubresourceIndex();
+
+ ID3D11RenderTargetView *colorBufferRTV = renderTarget->getRenderTargetView();
+ if (colorBufferRTV)
+ {
+ ID3D11Resource *textureResource = NULL;
+ colorBufferRTV->GetResource(&textureResource);
+
+ if (textureResource)
+ {
+ HRESULT result = textureResource->QueryInterface(IID_ID3D11Texture2D, (void**)resource);
+ textureResource->Release();
+
+ if (SUCCEEDED(result))
+ {
+ return true;
+ }
+ else
+ {
+ ERR("Failed to extract the ID3D11Texture2D from the render target resource, "
+ "HRESULT: 0x%X.", result);
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+bool Renderer11::blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect,
+ bool blitRenderTarget, bool blitDepthStencil)
+{
+ if (blitRenderTarget)
+ {
+ gl::Renderbuffer *readBuffer = readTarget->getReadColorbuffer();
+
+ if (!readBuffer)
+ {
+ ERR("Failed to retrieve the read buffer from the read framebuffer.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ RenderTarget *readRenderTarget = readBuffer->getRenderTarget();
+
+ for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
+ {
+ if (drawTarget->isEnabledColorAttachment(colorAttachment))
+ {
+ gl::Renderbuffer *drawBuffer = drawTarget->getColorbuffer(colorAttachment);
+
+ if (!drawBuffer)
+ {
+ ERR("Failed to retrieve the draw buffer from the draw framebuffer.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ RenderTarget *drawRenderTarget = drawBuffer->getRenderTarget();
+
+ if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, false))
+ {
+ return false;
+ }
+ }
+ }
+ }
+
+ if (blitDepthStencil)
+ {
+ gl::Renderbuffer *readBuffer = readTarget->getDepthOrStencilbuffer();
+ gl::Renderbuffer *drawBuffer = drawTarget->getDepthOrStencilbuffer();
+
+ if (!readBuffer)
+ {
+ ERR("Failed to retrieve the read depth-stencil buffer from the read framebuffer.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ if (!drawBuffer)
+ {
+ ERR("Failed to retrieve the draw depth-stencil buffer from the draw framebuffer.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ RenderTarget *readRenderTarget = readBuffer->getDepthStencil();
+ RenderTarget *drawRenderTarget = drawBuffer->getDepthStencil();
+
+ if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, true))
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void Renderer11::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type,
+ GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels)
+{
+ ID3D11Texture2D *colorBufferTexture = NULL;
+ unsigned int subresourceIndex = 0;
+
+ gl::Renderbuffer *colorbuffer = framebuffer->getReadColorbuffer();
+
+ if (colorbuffer && getRenderTargetResource(colorbuffer, &subresourceIndex, &colorBufferTexture))
+ {
+ gl::Rectangle area;
+ area.x = x;
+ area.y = y;
+ area.width = width;
+ area.height = height;
+
+ readTextureData(colorBufferTexture, subresourceIndex, area, colorbuffer->getActualFormat(), format, type, outputPitch,
+ packReverseRowOrder, packAlignment, pixels);
+
+ colorBufferTexture->Release();
+ colorBufferTexture = NULL;
+ }
+}
+
+Image *Renderer11::createImage()
+{
+ return new Image11();
+}
+
+void Renderer11::generateMipmap(Image *dest, Image *src)
+{
+ Image11 *dest11 = Image11::makeImage11(dest);
+ Image11 *src11 = Image11::makeImage11(src);
+ Image11::generateMipmap(dest11, src11);
+}
+
+TextureStorage *Renderer11::createTextureStorage2D(SwapChain *swapChain)
+{
+ SwapChain11 *swapChain11 = SwapChain11::makeSwapChain11(swapChain);
+ return new TextureStorage11_2D(this, swapChain11);
+}
+
+TextureStorage *Renderer11::createTextureStorage2D(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height)
+{
+ return new TextureStorage11_2D(this, levels, internalformat, usage, forceRenderable, width, height);
+}
+
+TextureStorage *Renderer11::createTextureStorageCube(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size)
+{
+ return new TextureStorage11_Cube(this, levels, internalformat, usage, forceRenderable, size);
+}
+
+static inline unsigned int getFastPixelCopySize(DXGI_FORMAT sourceFormat, GLenum sourceGLFormat, GLenum destFormat, GLenum destType)
+{
+ if (sourceFormat == DXGI_FORMAT_A8_UNORM &&
+ destFormat == GL_ALPHA &&
+ destType == GL_UNSIGNED_BYTE)
+ {
+ return 1;
+ }
+ else if (sourceFormat == DXGI_FORMAT_R8G8B8A8_UNORM &&
+ sourceGLFormat == GL_RGBA8_OES &&
+ destFormat == GL_RGBA &&
+ destType == GL_UNSIGNED_BYTE)
+ {
+ return 4;
+ }
+ else if (sourceFormat == DXGI_FORMAT_B8G8R8A8_UNORM &&
+ destFormat == GL_BGRA_EXT &&
+ destType == GL_UNSIGNED_BYTE)
+ {
+ return 4;
+ }
+ else if (sourceFormat == DXGI_FORMAT_R16G16B16A16_FLOAT &&
+ sourceGLFormat == GL_RGBA16F_EXT &&
+ destFormat == GL_RGBA &&
+ destType == GL_HALF_FLOAT_OES)
+ {
+ return 8;
+ }
+ else if (sourceFormat == DXGI_FORMAT_R32G32B32_FLOAT &&
+ destFormat == GL_RGB &&
+ destType == GL_FLOAT)
+ {
+ return 12;
+ }
+ else if (sourceFormat == DXGI_FORMAT_R32G32B32A32_FLOAT &&
+ sourceGLFormat == GL_RGBA32F_EXT &&
+ destFormat == GL_RGBA &&
+ destType == GL_FLOAT)
+ {
+ return 16;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+static inline void readPixelColor(const unsigned char *data, DXGI_FORMAT format, GLenum glFormat, unsigned int x,
+ unsigned int y, int inputPitch, gl::Color *outColor)
+{
+ switch (format)
+ {
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ {
+ unsigned int rgba = *reinterpret_cast<const unsigned int*>(data + 4 * x + y * inputPitch);
+ outColor->red = (rgba & 0x000000FF) * (1.0f / 0x000000FF);
+ outColor->green = (rgba & 0x0000FF00) * (1.0f / 0x0000FF00);
+ outColor->blue = (rgba & 0x00FF0000) * (1.0f / 0x00FF0000);
+
+ if (gl::GetAlphaSize(glFormat) > 0)
+ {
+ outColor->alpha = (rgba & 0xFF000000) * (1.0f / 0xFF000000);
+ }
+ else
+ {
+ outColor->alpha = 1.0f;
+ }
+ }
+ break;
+
+ case DXGI_FORMAT_A8_UNORM:
+ {
+ outColor->red = 0.0f;
+ outColor->green = 0.0f;
+ outColor->blue = 0.0f;
+ outColor->alpha = *(data + x + y * inputPitch) / 255.0f;
+ }
+ break;
+
+ case DXGI_FORMAT_R32G32B32A32_FLOAT:
+ {
+ outColor->red = *(reinterpret_cast<const float*>(data + 16 * x + y * inputPitch) + 0);
+ outColor->green = *(reinterpret_cast<const float*>(data + 16 * x + y * inputPitch) + 1);
+ outColor->blue = *(reinterpret_cast<const float*>(data + 16 * x + y * inputPitch) + 2);
+
+ if (gl::GetAlphaSize(glFormat) > 0)
+ {
+ outColor->alpha = *(reinterpret_cast<const float*>(data + 16 * x + y * inputPitch) + 3);
+ }
+ else
+ {
+ outColor->alpha = 1.0f;
+ }
+ }
+ break;
+
+ case DXGI_FORMAT_R32G32B32_FLOAT:
+ {
+ outColor->red = *(reinterpret_cast<const float*>(data + 12 * x + y * inputPitch) + 0);
+ outColor->green = *(reinterpret_cast<const float*>(data + 12 * x + y * inputPitch) + 1);
+ outColor->blue = *(reinterpret_cast<const float*>(data + 12 * x + y * inputPitch) + 2);
+ outColor->alpha = 1.0f;
+ }
+ break;
+
+ case DXGI_FORMAT_R16G16B16A16_FLOAT:
+ {
+ outColor->red = gl::float16ToFloat32(*(reinterpret_cast<const unsigned short*>(data + 8 * x + y * inputPitch) + 0));
+ outColor->green = gl::float16ToFloat32(*(reinterpret_cast<const unsigned short*>(data + 8 * x + y * inputPitch) + 1));
+ outColor->blue = gl::float16ToFloat32(*(reinterpret_cast<const unsigned short*>(data + 8 * x + y * inputPitch) + 2));
+
+ if (gl::GetAlphaSize(glFormat) > 0)
+ {
+ outColor->alpha = gl::float16ToFloat32(*(reinterpret_cast<const unsigned short*>(data + 8 * x + y * inputPitch) + 3));
+ }
+ else
+ {
+ outColor->alpha = 1.0f;
+ }
+ }
+ break;
+
+ case DXGI_FORMAT_B8G8R8A8_UNORM:
+ {
+ unsigned int bgra = *reinterpret_cast<const unsigned int*>(data + 4 * x + y * inputPitch);
+ outColor->red = (bgra & 0x00FF0000) * (1.0f / 0x00FF0000);
+ outColor->blue = (bgra & 0x000000FF) * (1.0f / 0x000000FF);
+ outColor->green = (bgra & 0x0000FF00) * (1.0f / 0x0000FF00);
+ outColor->alpha = (bgra & 0xFF000000) * (1.0f / 0xFF000000);
+ }
+ break;
+
+ case DXGI_FORMAT_R8_UNORM:
+ {
+ outColor->red = *(data + x + y * inputPitch) / 255.0f;
+ outColor->green = 0.0f;
+ outColor->blue = 0.0f;
+ outColor->alpha = 1.0f;
+ }
+ break;
+
+ case DXGI_FORMAT_R8G8_UNORM:
+ {
+ unsigned short rg = *reinterpret_cast<const unsigned short*>(data + 2 * x + y * inputPitch);
+
+ outColor->red = (rg & 0xFF00) * (1.0f / 0xFF00);
+ outColor->green = (rg & 0x00FF) * (1.0f / 0x00FF);
+ outColor->blue = 0.0f;
+ outColor->alpha = 1.0f;
+ }
+ break;
+
+ case DXGI_FORMAT_R16_FLOAT:
+ {
+ outColor->red = gl::float16ToFloat32(*reinterpret_cast<const unsigned short*>(data + 2 * x + y * inputPitch));
+ outColor->green = 0.0f;
+ outColor->blue = 0.0f;
+ outColor->alpha = 1.0f;
+ }
+ break;
+
+ case DXGI_FORMAT_R16G16_FLOAT:
+ {
+ outColor->red = gl::float16ToFloat32(*(reinterpret_cast<const unsigned short*>(data + 4 * x + y * inputPitch) + 0));
+ outColor->green = gl::float16ToFloat32(*(reinterpret_cast<const unsigned short*>(data + 4 * x + y * inputPitch) + 1));
+ outColor->blue = 0.0f;
+ outColor->alpha = 1.0f;
+ }
+ break;
+
+ default:
+ ERR("ReadPixelColor not implemented for DXGI format %u.", format);
+ UNIMPLEMENTED();
+ break;
+ }
+}
+
+static inline void writePixelColor(const gl::Color &color, GLenum format, GLenum type, unsigned int x,
+ unsigned int y, int outputPitch, void *outData)
+{
+ unsigned char* byteData = reinterpret_cast<unsigned char*>(outData);
+ unsigned short* shortData = reinterpret_cast<unsigned short*>(outData);
+
+ switch (format)
+ {
+ case GL_RGBA:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ byteData[4 * x + y * outputPitch + 0] = static_cast<unsigned char>(255 * color.red + 0.5f);
+ byteData[4 * x + y * outputPitch + 1] = static_cast<unsigned char>(255 * color.green + 0.5f);
+ byteData[4 * x + y * outputPitch + 2] = static_cast<unsigned char>(255 * color.blue + 0.5f);
+ byteData[4 * x + y * outputPitch + 3] = static_cast<unsigned char>(255 * color.alpha + 0.5f);
+ break;
+
+ default:
+ ERR("WritePixelColor not implemented for format GL_RGBA and type 0x%X.", type);
+ UNIMPLEMENTED();
+ break;
+ }
+ break;
+
+ case GL_BGRA_EXT:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ byteData[4 * x + y * outputPitch + 0] = static_cast<unsigned char>(255 * color.blue + 0.5f);
+ byteData[4 * x + y * outputPitch + 1] = static_cast<unsigned char>(255 * color.green + 0.5f);
+ byteData[4 * x + y * outputPitch + 2] = static_cast<unsigned char>(255 * color.red + 0.5f);
+ byteData[4 * x + y * outputPitch + 3] = static_cast<unsigned char>(255 * color.alpha + 0.5f);
+ break;
+
+ case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
+ // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section
+ // this type is packed as follows:
+ // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+ // --------------------------------------------------------------------------------
+ // | 4th | 3rd | 2nd | 1st component |
+ // --------------------------------------------------------------------------------
+ // in the case of BGRA_EXT, B is the first component, G the second, and so forth.
+ shortData[x + y * outputPitch / sizeof(unsigned short)] =
+ (static_cast<unsigned short>(15 * color.alpha + 0.5f) << 12) |
+ (static_cast<unsigned short>(15 * color.red + 0.5f) << 8) |
+ (static_cast<unsigned short>(15 * color.green + 0.5f) << 4) |
+ (static_cast<unsigned short>(15 * color.blue + 0.5f) << 0);
+ break;
+
+ case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
+ // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section
+ // this type is packed as follows:
+ // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+ // --------------------------------------------------------------------------------
+ // | 4th | 3rd | 2nd | 1st component |
+ // --------------------------------------------------------------------------------
+ // in the case of BGRA_EXT, B is the first component, G the second, and so forth.
+ shortData[x + y * outputPitch / sizeof(unsigned short)] =
+ (static_cast<unsigned short>( color.alpha + 0.5f) << 15) |
+ (static_cast<unsigned short>(31 * color.red + 0.5f) << 10) |
+ (static_cast<unsigned short>(31 * color.green + 0.5f) << 5) |
+ (static_cast<unsigned short>(31 * color.blue + 0.5f) << 0);
+ break;
+
+ default:
+ ERR("WritePixelColor not implemented for format GL_BGRA_EXT and type 0x%X.", type);
+ UNIMPLEMENTED();
+ break;
+ }
+ break;
+
+ case GL_RGB:
+ switch (type)
+ {
+ case GL_UNSIGNED_SHORT_5_6_5:
+ shortData[x + y * outputPitch / sizeof(unsigned short)] =
+ (static_cast<unsigned short>(31 * color.blue + 0.5f) << 0) |
+ (static_cast<unsigned short>(63 * color.green + 0.5f) << 5) |
+ (static_cast<unsigned short>(31 * color.red + 0.5f) << 11);
+ break;
+
+ case GL_UNSIGNED_BYTE:
+ byteData[3 * x + y * outputPitch + 0] = static_cast<unsigned char>(255 * color.red + 0.5f);
+ byteData[3 * x + y * outputPitch + 1] = static_cast<unsigned char>(255 * color.green + 0.5f);
+ byteData[3 * x + y * outputPitch + 2] = static_cast<unsigned char>(255 * color.blue + 0.5f);
+ break;
+
+ default:
+ ERR("WritePixelColor not implemented for format GL_RGB and type 0x%X.", type);
+ UNIMPLEMENTED();
+ break;
+ }
+ break;
+
+ default:
+ ERR("WritePixelColor not implemented for format 0x%X.", format);
+ UNIMPLEMENTED();
+ break;
+ }
+}
+
+void Renderer11::readTextureData(ID3D11Texture2D *texture, unsigned int subResource, const gl::Rectangle &area,
+ GLenum sourceFormat, GLenum format, GLenum type, GLsizei outputPitch, bool packReverseRowOrder,
+ GLint packAlignment, void *pixels)
+{
+ D3D11_TEXTURE2D_DESC textureDesc;
+ texture->GetDesc(&textureDesc);
+
+ D3D11_TEXTURE2D_DESC stagingDesc;
+ stagingDesc.Width = area.width;
+ stagingDesc.Height = area.height;
+ stagingDesc.MipLevels = 1;
+ stagingDesc.ArraySize = 1;
+ stagingDesc.Format = textureDesc.Format;
+ stagingDesc.SampleDesc.Count = 1;
+ stagingDesc.SampleDesc.Quality = 0;
+ stagingDesc.Usage = D3D11_USAGE_STAGING;
+ stagingDesc.BindFlags = 0;
+ stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
+ stagingDesc.MiscFlags = 0;
+
+ ID3D11Texture2D* stagingTex = NULL;
+ HRESULT result = mDevice->CreateTexture2D(&stagingDesc, NULL, &stagingTex);
+ if (FAILED(result))
+ {
+ ERR("Failed to create staging texture for readPixels, HRESULT: 0x%X.", result);
+ return;
+ }
+
+ ID3D11Texture2D* srcTex = NULL;
+ if (textureDesc.SampleDesc.Count > 1)
+ {
+ D3D11_TEXTURE2D_DESC resolveDesc;
+ resolveDesc.Width = textureDesc.Width;
+ resolveDesc.Height = textureDesc.Height;
+ resolveDesc.MipLevels = 1;
+ resolveDesc.ArraySize = 1;
+ resolveDesc.Format = textureDesc.Format;
+ resolveDesc.SampleDesc.Count = 1;
+ resolveDesc.SampleDesc.Quality = 0;
+ resolveDesc.Usage = D3D11_USAGE_DEFAULT;
+ resolveDesc.BindFlags = 0;
+ resolveDesc.CPUAccessFlags = 0;
+ resolveDesc.MiscFlags = 0;
+
+ result = mDevice->CreateTexture2D(&resolveDesc, NULL, &srcTex);
+ if (FAILED(result))
+ {
+ ERR("Failed to create resolve texture for readPixels, HRESULT: 0x%X.", result);
+ stagingTex->Release();
+ return;
+ }
+
+ mDeviceContext->ResolveSubresource(srcTex, 0, texture, subResource, textureDesc.Format);
+ subResource = 0;
+ }
+ else
+ {
+ srcTex = texture;
+ srcTex->AddRef();
+ }
+
+ D3D11_BOX srcBox;
+ srcBox.left = area.x;
+ srcBox.right = area.x + area.width;
+ srcBox.top = area.y;
+ srcBox.bottom = area.y + area.height;
+ srcBox.front = 0;
+ srcBox.back = 1;
+
+ mDeviceContext->CopySubresourceRegion(stagingTex, 0, 0, 0, 0, srcTex, subResource, &srcBox);
+
+ srcTex->Release();
+ srcTex = NULL;
+
+ D3D11_MAPPED_SUBRESOURCE mapping;
+ mDeviceContext->Map(stagingTex, 0, D3D11_MAP_READ, 0, &mapping);
+
+ unsigned char *source;
+ int inputPitch;
+ if (packReverseRowOrder)
+ {
+ source = static_cast<unsigned char*>(mapping.pData) + mapping.RowPitch * (area.height - 1);
+ inputPitch = -static_cast<int>(mapping.RowPitch);
+ }
+ else
+ {
+ source = static_cast<unsigned char*>(mapping.pData);
+ inputPitch = static_cast<int>(mapping.RowPitch);
+ }
+
+ unsigned int fastPixelSize = getFastPixelCopySize(textureDesc.Format, sourceFormat, format, type);
+ if (fastPixelSize != 0)
+ {
+ unsigned char *dest = static_cast<unsigned char*>(pixels);
+ for (int j = 0; j < area.height; j++)
+ {
+ memcpy(dest + j * outputPitch, source + j * inputPitch, area.width * fastPixelSize);
+ }
+ }
+ else if (textureDesc.Format == DXGI_FORMAT_B8G8R8A8_UNORM &&
+ format == GL_RGBA &&
+ type == GL_UNSIGNED_BYTE)
+ {
+ // Fast path for swapping red with blue
+ unsigned char *dest = static_cast<unsigned char*>(pixels);
+
+ for (int j = 0; j < area.height; j++)
+ {
+ for (int i = 0; i < area.width; i++)
+ {
+ unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch);
+ *(unsigned int*)(dest + 4 * i + j * outputPitch) =
+ (argb & 0xFF00FF00) | // Keep alpha and green
+ (argb & 0x00FF0000) >> 16 | // Move red to blue
+ (argb & 0x000000FF) << 16; // Move blue to red
+ }
+ }
+ }
+ else
+ {
+ gl::Color pixelColor;
+ for (int j = 0; j < area.height; j++)
+ {
+ for (int i = 0; i < area.width; i++)
+ {
+ readPixelColor(source, textureDesc.Format, sourceFormat, i, j, inputPitch, &pixelColor);
+ writePixelColor(pixelColor, format, type, i, j, outputPitch, pixels);
+ }
+ }
+ }
+
+ mDeviceContext->Unmap(stagingTex, 0);
+
+ stagingTex->Release();
+ stagingTex = NULL;
+}
+
+bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget,
+ RenderTarget *drawRenderTarget, bool wholeBufferCopy)
+{
+ ASSERT(readRect.width == drawRect.width && readRect.height == drawRect.height);
+
+ RenderTarget11 *drawRenderTarget11 = RenderTarget11::makeRenderTarget11(drawRenderTarget);
+ if (!drawRenderTarget)
+ {
+ ERR("Failed to retrieve the draw render target from the draw framebuffer.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ ID3D11Texture2D *drawTexture = drawRenderTarget11->getTexture();
+ unsigned int drawSubresource = drawRenderTarget11->getSubresourceIndex();
+
+ RenderTarget11 *readRenderTarget11 = RenderTarget11::makeRenderTarget11(readRenderTarget);
+ if (!readRenderTarget)
+ {
+ ERR("Failed to retrieve the read render target from the read framebuffer.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ ID3D11Texture2D *readTexture = NULL;
+ unsigned int readSubresource = 0;
+ if (readRenderTarget->getSamples() > 0)
+ {
+ readTexture = resolveMultisampledTexture(readRenderTarget11->getTexture(), readRenderTarget11->getSubresourceIndex());
+ readSubresource = 0;
+ }
+ else
+ {
+ readTexture = readRenderTarget11->getTexture();
+ readTexture->AddRef();
+ readSubresource = readRenderTarget11->getSubresourceIndex();
+ }
+
+ if (!readTexture)
+ {
+ ERR("Failed to retrieve the read render target view from the read render target.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ D3D11_BOX readBox;
+ readBox.left = readRect.x;
+ readBox.right = readRect.x + readRect.width;
+ readBox.top = readRect.y;
+ readBox.bottom = readRect.y + readRect.height;
+ readBox.front = 0;
+ readBox.back = 1;
+
+ // D3D11 needs depth-stencil CopySubresourceRegions to have a NULL pSrcBox
+ // We also require complete framebuffer copies for depth-stencil blit.
+ D3D11_BOX *pSrcBox = wholeBufferCopy ? NULL : &readBox;
+
+ mDeviceContext->CopySubresourceRegion(drawTexture, drawSubresource, drawRect.x, drawRect.y, 0,
+ readTexture, readSubresource, pSrcBox);
+
+ SafeRelease(readTexture);
+
+ return true;
+}
+
+ID3D11Texture2D *Renderer11::resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource)
+{
+ D3D11_TEXTURE2D_DESC textureDesc;
+ source->GetDesc(&textureDesc);
+
+ if (textureDesc.SampleDesc.Count > 1)
+ {
+ D3D11_TEXTURE2D_DESC resolveDesc;
+ resolveDesc.Width = textureDesc.Width;
+ resolveDesc.Height = textureDesc.Height;
+ resolveDesc.MipLevels = 1;
+ resolveDesc.ArraySize = 1;
+ resolveDesc.Format = textureDesc.Format;
+ resolveDesc.SampleDesc.Count = 1;
+ resolveDesc.SampleDesc.Quality = 0;
+ resolveDesc.Usage = textureDesc.Usage;
+ resolveDesc.BindFlags = textureDesc.BindFlags;
+ resolveDesc.CPUAccessFlags = 0;
+ resolveDesc.MiscFlags = 0;
+
+ ID3D11Texture2D *resolveTexture = NULL;
+ HRESULT result = mDevice->CreateTexture2D(&resolveDesc, NULL, &resolveTexture);
+ if (FAILED(result))
+ {
+ ERR("Failed to create a multisample resolve texture, HRESULT: 0x%X.", result);
+ return NULL;
+ }
+
+ mDeviceContext->ResolveSubresource(resolveTexture, 0, source, subresource, textureDesc.Format);
+ return resolveTexture;
+ }
+ else
+ {
+ source->AddRef();
+ return source;
+ }
+}
+
+bool Renderer11::getLUID(LUID *adapterLuid) const
+{
+ adapterLuid->HighPart = 0;
+ adapterLuid->LowPart = 0;
+
+ if (!mDxgiAdapter)
+ {
+ return false;
+ }
+
+ DXGI_ADAPTER_DESC adapterDesc;
+ if (FAILED(mDxgiAdapter->GetDesc(&adapterDesc)))
+ {
+ return false;
+ }
+
+ *adapterLuid = adapterDesc.AdapterLuid;
+ return true;
+}
+
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/Renderer11.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11Renderer11h"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/Renderer11.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/Renderer11.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/Renderer11.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,358 @@
</span><ins>+//
+// Copyright (c) 2012-2013 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.
+//
+
+// Renderer11.h: Defines a back-end specific class for the D3D11 renderer.
+
+#ifndef LIBGLESV2_RENDERER_RENDERER11_H_
+#define LIBGLESV2_RENDERER_RENDERER11_H_
+
+#include "common/angleutils.h"
+#include "libGLESv2/angletypes.h"
+#include "libGLESv2/mathutil.h"
+
+#include "libGLESv2/renderer/Renderer.h"
+#include "libGLESv2/renderer/d3d11/RenderStateCache.h"
+#include "libGLESv2/renderer/d3d11/InputLayoutCache.h"
+#include "libGLESv2/renderer/RenderTarget.h"
+
+namespace gl
+{
+class Renderbuffer;
+}
+
+namespace rx
+{
+
+class VertexDataManager;
+class IndexDataManager;
+class StreamingIndexBufferInterface;
+
+enum
+{
+ MAX_VERTEX_UNIFORM_VECTORS_D3D11 = 1024,
+ MAX_FRAGMENT_UNIFORM_VECTORS_D3D11 = 1024
+};
+
+class Renderer11 : public Renderer
+{
+ public:
+ Renderer11(egl::Display *display, HDC hDc);
+ virtual ~Renderer11();
+
+ static Renderer11 *makeRenderer11(Renderer *renderer);
+
+ virtual EGLint initialize();
+ virtual bool resetDevice();
+
+ virtual int generateConfigs(ConfigDesc **configDescList);
+ virtual void deleteConfigs(ConfigDesc *configDescList);
+
+ virtual void sync(bool block);
+
+ virtual SwapChain *createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat);
+
+ virtual void setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &sampler);
+ virtual void setTexture(gl::SamplerType type, int index, gl::Texture *texture);
+
+ virtual void setRasterizerState(const gl::RasterizerState &rasterState);
+ virtual void setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::Color &blendColor,
+ unsigned int sampleMask);
+ virtual void setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef,
+ int stencilBackRef, bool frontFaceCCW);
+
+ virtual void setScissorRectangle(const gl::Rectangle &scissor, bool enabled);
+ virtual bool setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace,
+ bool ignoreViewport);
+
+ virtual bool applyPrimitiveType(GLenum mode, GLsizei count);
+ virtual bool applyRenderTarget(gl::Framebuffer *frameBuffer);
+ virtual void applyShaders(gl::ProgramBinary *programBinary);
+ virtual void applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray *uniformArray);
+ virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances);
+ virtual GLenum applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo);
+
+ virtual void drawArrays(GLenum mode, GLsizei count, GLsizei instances);
+ virtual void drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances);
+
+ virtual void clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer);
+
+ virtual void markAllStateDirty();
+
+ // lost device
+ void notifyDeviceLost();
+ virtual bool isDeviceLost();
+ virtual bool testDeviceLost(bool notify);
+ virtual bool testDeviceResettable();
+
+ // Renderer capabilities
+ virtual DWORD getAdapterVendor() const;
+ virtual std::string getRendererDescription() const;
+ virtual GUID getAdapterIdentifier() const;
+
+ virtual bool getBGRATextureSupport() const;
+ virtual bool getDXT1TextureSupport();
+ virtual bool getDXT3TextureSupport();
+ virtual bool getDXT5TextureSupport();
+ virtual bool getEventQuerySupport();
+ virtual bool getFloat32TextureSupport(bool *filtering, bool *renderable);
+ virtual bool getFloat16TextureSupport(bool *filtering, bool *renderable);
+ virtual bool getLuminanceTextureSupport();
+ virtual bool getLuminanceAlphaTextureSupport();
+ virtual unsigned int getMaxVertexTextureImageUnits() const;
+ virtual unsigned int getMaxCombinedTextureImageUnits() const;
+ virtual unsigned int getReservedVertexUniformVectors() const;
+ virtual unsigned int getReservedFragmentUniformVectors() const;
+ virtual unsigned int getMaxVertexUniformVectors() const;
+ virtual unsigned int getMaxFragmentUniformVectors() const;
+ virtual unsigned int getMaxVaryingVectors() const;
+ virtual bool getNonPower2TextureSupport() const;
+ virtual bool getDepthTextureSupport() const;
+ virtual bool getOcclusionQuerySupport() const;
+ virtual bool getInstancingSupport() const;
+ virtual bool getTextureFilterAnisotropySupport() const;
+ virtual float getTextureMaxAnisotropy() const;
+ virtual bool getShareHandleSupport() const;
+ virtual bool getDerivativeInstructionSupport() const;
+ virtual bool getPostSubBufferSupport() const;
+
+ virtual int getMajorShaderModel() const;
+ virtual float getMaxPointSize() const;
+ virtual int getMaxViewportDimension() const;
+ virtual int getMaxTextureWidth() const;
+ virtual int getMaxTextureHeight() const;
+ virtual bool get32BitIndexSupport() const;
+ virtual int getMinSwapInterval() const;
+ virtual int getMaxSwapInterval() const;
+
+ virtual GLsizei getMaxSupportedSamples() const;
+ int getNearestSupportedSamples(DXGI_FORMAT format, unsigned int requested) const;
+
+ virtual unsigned int getMaxRenderTargets() const;
+
+ // Pixel operations
+ virtual bool copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source);
+ virtual bool copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source);
+
+ virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level);
+ virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level);
+
+ bool copyTexture(ID3D11ShaderResourceView *source, const gl::Rectangle &sourceArea, unsigned int sourceWidth, unsigned int sourceHeight,
+ ID3D11RenderTargetView *dest, const gl::Rectangle &destArea, unsigned int destWidth, unsigned int destHeight, GLenum destFormat);
+
+ virtual bool blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect,
+ bool blitRenderTarget, bool blitDepthStencil);
+ virtual void readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type,
+ GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels);
+
+ // RenderTarget creation
+ virtual RenderTarget *createRenderTarget(SwapChain *swapChain, bool depth);
+ virtual RenderTarget *createRenderTarget(int width, int height, GLenum format, GLsizei samples, bool depth);
+
+ // Shader operations
+ virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type);
+ virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, D3DWorkaroundType workaround);
+
+ // Image operations
+ virtual Image *createImage();
+ virtual void generateMipmap(Image *dest, Image *source);
+ virtual TextureStorage *createTextureStorage2D(SwapChain *swapChain);
+ virtual TextureStorage *createTextureStorage2D(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height);
+ virtual TextureStorage *createTextureStorageCube(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size);
+
+ // Buffer creation
+ virtual VertexBuffer *createVertexBuffer();
+ virtual IndexBuffer *createIndexBuffer();
+ virtual BufferStorage *createBufferStorage();
+
+ // Query and Fence creation
+ virtual QueryImpl *createQuery(GLenum type);
+ virtual FenceImpl *createFence();
+
+ // D3D11-renderer specific methods
+ ID3D11Device *getDevice() { return mDevice; }
+ ID3D11DeviceContext *getDeviceContext() { return mDeviceContext; };
+ IDXGIFactory *getDxgiFactory() { return mDxgiFactory; };
+
+ bool getRenderTargetResource(gl::Renderbuffer *colorbuffer, unsigned int *subresourceIndex, ID3D11Texture2D **resource);
+ void unapplyRenderTargets();
+ void setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView);
+
+ virtual bool getLUID(LUID *adapterLuid) const;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Renderer11);
+
+ void drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer);
+ void drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer, int instances);
+
+ void readTextureData(ID3D11Texture2D *texture, unsigned int subResource, const gl::Rectangle &area,
+ GLenum sourceFormat, GLenum format, GLenum type, GLsizei outputPitch, bool packReverseRowOrder,
+ GLint packAlignment, void *pixels);
+
+ void maskedClear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer);
+ rx::Range getViewportBounds() const;
+
+ bool blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget,
+ RenderTarget *drawRenderTarget, bool wholeBufferCopy);
+ ID3D11Texture2D *resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource);
+
+ HMODULE mD3d11Module;
+ HMODULE mDxgiModule;
+ HDC mDc;
+
+ bool mDeviceLost;
+
+ void initializeDevice();
+ void releaseDeviceResources();
+ int getMinorShaderModel() const;
+ void release();
+
+ RenderStateCache mStateCache;
+
+ // Support flags
+ bool mFloat16TextureSupport;
+ bool mFloat16FilterSupport;
+ bool mFloat16RenderSupport;
+
+ bool mFloat32TextureSupport;
+ bool mFloat32FilterSupport;
+ bool mFloat32RenderSupport;
+
+ bool mDXT1TextureSupport;
+ bool mDXT3TextureSupport;
+ bool mDXT5TextureSupport;
+
+ bool mDepthTextureSupport;
+
+ // Multisample format support
+ struct MultisampleSupportInfo
+ {
+ unsigned int qualityLevels[D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT];
+ };
+
+ typedef std::unordered_map<DXGI_FORMAT, MultisampleSupportInfo, std::hash<int> > MultisampleSupportMap;
+ MultisampleSupportMap mMultisampleSupportMap;
+
+ unsigned int mMaxSupportedSamples;
+
+ // current render target states
+ unsigned int mAppliedRenderTargetSerials[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS];
+ unsigned int mAppliedDepthbufferSerial;
+ unsigned int mAppliedStencilbufferSerial;
+ bool mDepthStencilInitialized;
+ bool mRenderTargetDescInitialized;
+ rx::RenderTarget::Desc mRenderTargetDesc;
+ unsigned int mCurDepthSize;
+ unsigned int mCurStencilSize;
+
+ // Currently applied sampler states
+ bool mForceSetVertexSamplerStates[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS];
+ gl::SamplerState mCurVertexSamplerStates[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS];
+
+ bool mForceSetPixelSamplerStates[gl::MAX_TEXTURE_IMAGE_UNITS];
+ gl::SamplerState mCurPixelSamplerStates[gl::MAX_TEXTURE_IMAGE_UNITS];
+
+ // Currently applied textures
+ unsigned int mCurVertexTextureSerials[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS];
+ unsigned int mCurPixelTextureSerials[gl::MAX_TEXTURE_IMAGE_UNITS];
+
+ // Currently applied blend state
+ bool mForceSetBlendState;
+ gl::BlendState mCurBlendState;
+ gl::Color mCurBlendColor;
+ unsigned int mCurSampleMask;
+
+ // Currently applied rasterizer state
+ bool mForceSetRasterState;
+ gl::RasterizerState mCurRasterState;
+
+ // Currently applied depth stencil state
+ bool mForceSetDepthStencilState;
+ gl::DepthStencilState mCurDepthStencilState;
+ int mCurStencilRef;
+ int mCurStencilBackRef;
+
+ // Currently applied scissor rectangle
+ bool mForceSetScissor;
+ bool mScissorEnabled;
+ gl::Rectangle mCurScissor;
+
+ // Currently applied viewport
+ bool mForceSetViewport;
+ gl::Rectangle mCurViewport;
+ float mCurNear;
+ float mCurFar;
+
+ // Currently applied primitive topology
+ D3D11_PRIMITIVE_TOPOLOGY mCurrentPrimitiveTopology;
+
+ unsigned int mAppliedIBSerial;
+ unsigned int mAppliedStorageIBSerial;
+ unsigned int mAppliedIBOffset;
+
+ unsigned int mAppliedProgramBinarySerial;
+ bool mIsGeometryShaderActive;
+
+ dx_VertexConstants mVertexConstants;
+ dx_VertexConstants mAppliedVertexConstants;
+ ID3D11Buffer *mDriverConstantBufferVS;
+ ID3D11Buffer *mCurrentVertexConstantBuffer;
+
+ dx_PixelConstants mPixelConstants;
+ dx_PixelConstants mAppliedPixelConstants;
+ ID3D11Buffer *mDriverConstantBufferPS;
+ ID3D11Buffer *mCurrentPixelConstantBuffer;
+
+ ID3D11Buffer *mCurrentGeometryConstantBuffer;
+
+ // Vertex, index and input layouts
+ VertexDataManager *mVertexDataManager;
+ IndexDataManager *mIndexDataManager;
+ InputLayoutCache mInputLayoutCache;
+
+ StreamingIndexBufferInterface *mLineLoopIB;
+ StreamingIndexBufferInterface *mTriangleFanIB;
+
+ // Texture copy resources
+ bool mCopyResourcesInitialized;
+ ID3D11Buffer *mCopyVB;
+ ID3D11SamplerState *mCopySampler;
+ ID3D11InputLayout *mCopyIL;
+ ID3D11VertexShader *mCopyVS;
+ ID3D11PixelShader *mCopyRGBAPS;
+ ID3D11PixelShader *mCopyRGBPS;
+ ID3D11PixelShader *mCopyLumPS;
+ ID3D11PixelShader *mCopyLumAlphaPS;
+
+ // Masked clear resources
+ bool mClearResourcesInitialized;
+ ID3D11Buffer *mClearVB;
+ ID3D11InputLayout *mClearIL;
+ ID3D11VertexShader *mClearVS;
+ ID3D11PixelShader *mClearSinglePS;
+ ID3D11PixelShader *mClearMultiplePS;
+ ID3D11RasterizerState *mClearScissorRS;
+ ID3D11RasterizerState *mClearNoScissorRS;
+
+ // Sync query
+ ID3D11Query *mSyncQuery;
+
+ ID3D11Device *mDevice;
+ D3D_FEATURE_LEVEL mFeatureLevel;
+ ID3D11DeviceContext *mDeviceContext;
+ IDXGIAdapter *mDxgiAdapter;
+ DXGI_ADAPTER_DESC mAdapterDescription;
+ char mDescription[128];
+ IDXGIFactory *mDxgiFactory;
+
+ // Cached device caps
+ bool mBGRATextureSupport;
+};
+
+}
+#endif // LIBGLESV2_RENDERER_RENDERER11_H_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/Renderer11.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11ShaderExecutable11cpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/ShaderExecutable11.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/ShaderExecutable11.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/ShaderExecutable11.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,109 @@
</span><ins>+#include "precompiled.h"
+//
+// Copyright (c) 2012-2013 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.
+//
+
+// ShaderExecutable11.cpp: Implements a D3D11-specific class to contain shader
+// executable implementation details.
+
+#include "libGLESv2/renderer/d3d11/ShaderExecutable11.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11PixelShader *executable)
+ : ShaderExecutable(function, length)
+{
+ mPixelExecutable = executable;
+ mVertexExecutable = NULL;
+ mGeometryExecutable = NULL;
+
+ mConstantBuffer = NULL;
+}
+
+ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11VertexShader *executable)
+ : ShaderExecutable(function, length)
+{
+ mVertexExecutable = executable;
+ mPixelExecutable = NULL;
+ mGeometryExecutable = NULL;
+
+ mConstantBuffer = NULL;
+}
+
+ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11GeometryShader *executable)
+ : ShaderExecutable(function, length)
+{
+ mGeometryExecutable = executable;
+ mVertexExecutable = NULL;
+ mPixelExecutable = NULL;
+
+ mConstantBuffer = NULL;
+}
+
+ShaderExecutable11::~ShaderExecutable11()
+{
+ if (mVertexExecutable)
+ {
+ mVertexExecutable->Release();
+ }
+ if (mPixelExecutable)
+ {
+ mPixelExecutable->Release();
+ }
+ if (mGeometryExecutable)
+ {
+ mGeometryExecutable->Release();
+ }
+
+ if (mConstantBuffer)
+ {
+ mConstantBuffer->Release();
+ }
+}
+
+ShaderExecutable11 *ShaderExecutable11::makeShaderExecutable11(ShaderExecutable *executable)
+{
+ ASSERT(HAS_DYNAMIC_TYPE(ShaderExecutable11*, executable));
+ return static_cast<ShaderExecutable11*>(executable);
+}
+
+ID3D11VertexShader *ShaderExecutable11::getVertexShader() const
+{
+ return mVertexExecutable;
+}
+
+ID3D11PixelShader *ShaderExecutable11::getPixelShader() const
+{
+ return mPixelExecutable;
+}
+
+ID3D11GeometryShader *ShaderExecutable11::getGeometryShader() const
+{
+ return mGeometryExecutable;
+}
+
+ID3D11Buffer *ShaderExecutable11::getConstantBuffer(ID3D11Device *device, unsigned int registerCount)
+{
+ if (!mConstantBuffer && registerCount > 0)
+ {
+ D3D11_BUFFER_DESC constantBufferDescription = {0};
+ constantBufferDescription.ByteWidth = registerCount * sizeof(float[4]);
+ constantBufferDescription.Usage = D3D11_USAGE_DYNAMIC;
+ constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
+ constantBufferDescription.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ constantBufferDescription.MiscFlags = 0;
+ constantBufferDescription.StructureByteStride = 0;
+
+ HRESULT result = device->CreateBuffer(&constantBufferDescription, NULL, &mConstantBuffer);
+ ASSERT(SUCCEEDED(result));
+ }
+
+ return mConstantBuffer;
+}
+
+}
</ins><span class="cx">\ No newline at end of file
</span><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/ShaderExecutable11.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11ShaderExecutable11h"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/ShaderExecutable11.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/ShaderExecutable11.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/ShaderExecutable11.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,47 @@
</span><ins>+//
+// Copyright (c) 2012-2013 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.
+//
+
+// ShaderExecutable11.h: Defines a D3D11-specific class to contain shader
+// executable implementation details.
+
+#ifndef LIBGLESV2_RENDERER_SHADEREXECUTABLE11_H_
+#define LIBGLESV2_RENDERER_SHADEREXECUTABLE11_H_
+
+#include "libGLESv2/renderer/ShaderExecutable.h"
+
+namespace rx
+{
+
+class ShaderExecutable11 : public ShaderExecutable
+{
+ public:
+ ShaderExecutable11(const void *function, size_t length, ID3D11PixelShader *executable);
+ ShaderExecutable11(const void *function, size_t length, ID3D11VertexShader *executable);
+ ShaderExecutable11(const void *function, size_t length, ID3D11GeometryShader *executable);
+
+ virtual ~ShaderExecutable11();
+
+ static ShaderExecutable11 *makeShaderExecutable11(ShaderExecutable *executable);
+
+ ID3D11PixelShader *getPixelShader() const;
+ ID3D11VertexShader *getVertexShader() const;
+ ID3D11GeometryShader *getGeometryShader() const;
+
+ ID3D11Buffer *getConstantBuffer(ID3D11Device *device, unsigned int registerCount);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ShaderExecutable11);
+
+ ID3D11PixelShader *mPixelExecutable;
+ ID3D11VertexShader *mVertexExecutable;
+ ID3D11GeometryShader *mGeometryExecutable;
+
+ ID3D11Buffer *mConstantBuffer;
+};
+
+}
+
+#endif // LIBGLESV2_RENDERER_SHADEREXECUTABLE11_H_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/ShaderExecutable11.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11SwapChain11cpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/SwapChain11.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/SwapChain11.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/SwapChain11.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,657 @@
</span><ins>+#include "precompiled.h"
+//
+// Copyright (c) 2012-2013 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.
+//
+
+// SwapChain11.cpp: Implements a back-end specific class for the D3D11 swap chain.
+
+#include "libGLESv2/renderer/d3d11/SwapChain11.h"
+
+#include "libGLESv2/renderer/d3d11/renderer11_utils.h"
+#include "libGLESv2/renderer/d3d11/Renderer11.h"
+
+#include "libGLESv2/renderer/d3d11/shaders/compiled/passthrough11vs.h"
+#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgba11ps.h"
+
+namespace rx
+{
+
+SwapChain11::SwapChain11(Renderer11 *renderer, HWND window, HANDLE shareHandle,
+ GLenum backBufferFormat, GLenum depthBufferFormat)
+ : mRenderer(renderer), SwapChain(window, shareHandle, backBufferFormat, depthBufferFormat)
+{
+ mSwapChain = NULL;
+ mBackBufferTexture = NULL;
+ mBackBufferRTView = NULL;
+ mOffscreenTexture = NULL;
+ mOffscreenRTView = NULL;
+ mOffscreenSRView = NULL;
+ mDepthStencilTexture = NULL;
+ mDepthStencilDSView = NULL;
+ mQuadVB = NULL;
+ mPassThroughSampler = NULL;
+ mPassThroughIL = NULL;
+ mPassThroughVS = NULL;
+ mPassThroughPS = NULL;
+ mWidth = -1;
+ mHeight = -1;
+ mSwapInterval = 0;
+ mAppCreatedShareHandle = mShareHandle != NULL;
+ mPassThroughResourcesInit = false;
+}
+
+SwapChain11::~SwapChain11()
+{
+ release();
+}
+
+void SwapChain11::release()
+{
+ SafeRelease(mSwapChain);
+ SafeRelease(mBackBufferTexture);
+ SafeRelease(mBackBufferRTView);
+ SafeRelease(mOffscreenTexture);
+ SafeRelease(mOffscreenRTView);
+ SafeRelease(mOffscreenSRView);
+ SafeRelease(mDepthStencilTexture);
+ SafeRelease(mDepthStencilDSView);
+ SafeRelease(mQuadVB);
+ SafeRelease(mPassThroughSampler);
+ SafeRelease(mPassThroughIL);
+ SafeRelease(mPassThroughVS);
+ SafeRelease(mPassThroughPS);
+
+ if (!mAppCreatedShareHandle)
+ {
+ mShareHandle = NULL;
+ }
+}
+
+void SwapChain11::releaseOffscreenTexture()
+{
+ SafeRelease(mOffscreenTexture);
+ SafeRelease(mOffscreenRTView);
+ SafeRelease(mOffscreenSRView);
+ SafeRelease(mDepthStencilTexture);
+ SafeRelease(mDepthStencilDSView);
+}
+
+EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHeight)
+{
+ ID3D11Device *device = mRenderer->getDevice();
+
+ ASSERT(device != NULL);
+
+ // D3D11 does not allow zero size textures
+ ASSERT(backbufferWidth >= 1);
+ ASSERT(backbufferHeight >= 1);
+
+ // Preserve the render target content
+ ID3D11Texture2D *previousOffscreenTexture = mOffscreenTexture;
+ if (previousOffscreenTexture)
+ {
+ previousOffscreenTexture->AddRef();
+ }
+ const int previousWidth = mWidth;
+ const int previousHeight = mHeight;
+
+ releaseOffscreenTexture();
+
+ // If the app passed in a share handle, open the resource
+ // See EGL_ANGLE_d3d_share_handle_client_buffer
+ if (mAppCreatedShareHandle)
+ {
+ ID3D11Resource *tempResource11;
+ HRESULT result = device->OpenSharedResource(mShareHandle, __uuidof(ID3D11Resource), (void**)&tempResource11);
+
+ if (FAILED(result))
+ {
+ ERR("Failed to open the swap chain pbuffer share handle: %08lX", result);
+ release();
+ return EGL_BAD_PARAMETER;
+ }
+
+ result = tempResource11->QueryInterface(__uuidof(ID3D11Texture2D), (void**)&mOffscreenTexture);
+ tempResource11->Release();
+
+ if (FAILED(result))
+ {
+ ERR("Failed to query texture2d interface in pbuffer share handle: %08lX", result);
+ release();
+ return EGL_BAD_PARAMETER;
+ }
+
+ // Validate offscreen texture parameters
+ D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0};
+ mOffscreenTexture->GetDesc(&offscreenTextureDesc);
+
+ if (offscreenTextureDesc.Width != (UINT)backbufferWidth
+ || offscreenTextureDesc.Height != (UINT)backbufferHeight
+ || offscreenTextureDesc.Format != gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat)
+ || offscreenTextureDesc.MipLevels != 1
+ || offscreenTextureDesc.ArraySize != 1)
+ {
+ ERR("Invalid texture parameters in the shared offscreen texture pbuffer");
+ release();
+ return EGL_BAD_PARAMETER;
+ }
+ }
+ else
+ {
+ const bool useSharedResource = !mWindow && mRenderer->getShareHandleSupport();
+
+ D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0};
+ offscreenTextureDesc.Width = backbufferWidth;
+ offscreenTextureDesc.Height = backbufferHeight;
+ offscreenTextureDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat);
+ offscreenTextureDesc.MipLevels = 1;
+ offscreenTextureDesc.ArraySize = 1;
+ offscreenTextureDesc.SampleDesc.Count = 1;
+ offscreenTextureDesc.SampleDesc.Quality = 0;
+ offscreenTextureDesc.Usage = D3D11_USAGE_DEFAULT;
+ offscreenTextureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
+ offscreenTextureDesc.CPUAccessFlags = 0;
+ offscreenTextureDesc.MiscFlags = useSharedResource ? D3D11_RESOURCE_MISC_SHARED : 0;
+
+ HRESULT result = device->CreateTexture2D(&offscreenTextureDesc, NULL, &mOffscreenTexture);
+
+ if (FAILED(result))
+ {
+ ERR("Could not create offscreen texture: %08lX", result);
+ release();
+
+ if (d3d11::isDeviceLostError(result))
+ {
+ return EGL_CONTEXT_LOST;
+ }
+ else
+ {
+ return EGL_BAD_ALLOC;
+ }
+ }
+
+ d3d11::SetDebugName(mOffscreenTexture, "Offscreen texture");
+
+ // EGL_ANGLE_surface_d3d_texture_2d_share_handle requires that we store a share handle for the client
+ if (useSharedResource)
+ {
+ IDXGIResource *offscreenTextureResource = NULL;
+ result = mOffscreenTexture->QueryInterface(__uuidof(IDXGIResource), (void**)&offscreenTextureResource);
+
+ // Fall back to no share handle on failure
+ if (FAILED(result))
+ {
+ ERR("Could not query offscreen texture resource: %08lX", result);
+ }
+ else
+ {
+ result = offscreenTextureResource->GetSharedHandle(&mShareHandle);
+ offscreenTextureResource->Release();
+
+ if (FAILED(result))
+ {
+ mShareHandle = NULL;
+ ERR("Could not get offscreen texture shared handle: %08lX", result);
+ }
+ }
+ }
+ }
+
+ HRESULT result = device->CreateRenderTargetView(mOffscreenTexture, NULL, &mOffscreenRTView);
+
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mOffscreenRTView, "Offscreen render target");
+
+ result = device->CreateShaderResourceView(mOffscreenTexture, NULL, &mOffscreenSRView);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mOffscreenSRView, "Offscreen shader resource");
+
+ if (mDepthBufferFormat != GL_NONE)
+ {
+ D3D11_TEXTURE2D_DESC depthStencilDesc = {0};
+ depthStencilDesc.Width = backbufferWidth;
+ depthStencilDesc.Height = backbufferHeight;
+ depthStencilDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mDepthBufferFormat);
+ depthStencilDesc.MipLevels = 1;
+ depthStencilDesc.ArraySize = 1;
+ depthStencilDesc.SampleDesc.Count = 1;
+ depthStencilDesc.SampleDesc.Quality = 0;
+ depthStencilDesc.Usage = D3D11_USAGE_DEFAULT;
+ depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
+ depthStencilDesc.CPUAccessFlags = 0;
+ depthStencilDesc.MiscFlags = 0;
+
+ result = device->CreateTexture2D(&depthStencilDesc, NULL, &mDepthStencilTexture);
+ if (FAILED(result))
+ {
+ ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result);
+ release();
+
+ if (d3d11::isDeviceLostError(result))
+ {
+ return EGL_CONTEXT_LOST;
+ }
+ else
+ {
+ return EGL_BAD_ALLOC;
+ }
+ }
+ d3d11::SetDebugName(mDepthStencilTexture, "Depth stencil texture");
+
+ result = device->CreateDepthStencilView(mDepthStencilTexture, NULL, &mDepthStencilDSView);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mDepthStencilDSView, "Depth stencil view");
+ }
+
+ mWidth = backbufferWidth;
+ mHeight = backbufferHeight;
+
+ if (previousOffscreenTexture != NULL)
+ {
+ D3D11_BOX sourceBox = {0};
+ sourceBox.left = 0;
+ sourceBox.right = std::min(previousWidth, mWidth);
+ sourceBox.top = std::max(previousHeight - mHeight, 0);
+ sourceBox.bottom = previousHeight;
+ sourceBox.front = 0;
+ sourceBox.back = 1;
+
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+ const int yoffset = std::max(mHeight - previousHeight, 0);
+ deviceContext->CopySubresourceRegion(mOffscreenTexture, 0, 0, yoffset, 0, previousOffscreenTexture, 0, &sourceBox);
+
+ previousOffscreenTexture->Release();
+
+ if (mSwapChain)
+ {
+ swapRect(0, 0, mWidth, mHeight);
+ }
+ }
+
+ return EGL_SUCCESS;
+}
+
+EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight)
+{
+ ID3D11Device *device = mRenderer->getDevice();
+
+ if (device == NULL)
+ {
+ return EGL_BAD_ACCESS;
+ }
+
+ // EGL allows creating a surface with 0x0 dimension, however, DXGI does not like 0x0 swapchains
+ if (backbufferWidth < 1 || backbufferHeight < 1)
+ {
+ return EGL_SUCCESS;
+ }
+
+ // Can only call resize if we have already created our swap buffer and resources
+ ASSERT(mSwapChain && mBackBufferTexture && mBackBufferRTView);
+
+ SafeRelease(mBackBufferTexture);
+ SafeRelease(mBackBufferRTView);
+
+ // Resize swap chain
+ DXGI_FORMAT backbufferDXGIFormat = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat);
+ HRESULT result = mSwapChain->ResizeBuffers(2, backbufferWidth, backbufferHeight, backbufferDXGIFormat, 0);
+
+ if (FAILED(result))
+ {
+ ERR("Error resizing swap chain buffers: 0x%08X", result);
+ release();
+
+ if (d3d11::isDeviceLostError(result))
+ {
+ return EGL_CONTEXT_LOST;
+ }
+ else
+ {
+ return EGL_BAD_ALLOC;
+ }
+ }
+
+ result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture);
+ ASSERT(SUCCEEDED(result));
+ if (SUCCEEDED(result))
+ {
+ d3d11::SetDebugName(mBackBufferTexture, "Back buffer texture");
+ }
+
+ result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView);
+ ASSERT(SUCCEEDED(result));
+ if (SUCCEEDED(result))
+ {
+ d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target");
+ }
+
+ return resetOffscreenTexture(backbufferWidth, backbufferHeight);
+}
+
+EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval)
+{
+ ID3D11Device *device = mRenderer->getDevice();
+
+ if (device == NULL)
+ {
+ return EGL_BAD_ACCESS;
+ }
+
+ // Release specific resources to free up memory for the new render target, while the
+ // old render target still exists for the purpose of preserving its contents.
+ SafeRelease(mSwapChain);
+ SafeRelease(mBackBufferTexture);
+ SafeRelease(mBackBufferRTView);
+
+ mSwapInterval = static_cast<unsigned int>(swapInterval);
+ if (mSwapInterval > 4)
+ {
+ // IDXGISwapChain::Present documentation states that valid sync intervals are in the [0,4] range
+ return EGL_BAD_PARAMETER;
+ }
+
+ // EGL allows creating a surface with 0x0 dimension, however, DXGI does not like 0x0 swapchains
+ if (backbufferWidth < 1 || backbufferHeight < 1)
+ {
+ releaseOffscreenTexture();
+ return EGL_SUCCESS;
+ }
+
+ if (mWindow)
+ {
+ IDXGIFactory *factory = mRenderer->getDxgiFactory();
+
+ DXGI_SWAP_CHAIN_DESC swapChainDesc = {0};
+ swapChainDesc.BufferCount = 2;
+ swapChainDesc.BufferDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat);
+ swapChainDesc.BufferDesc.Width = backbufferWidth;
+ swapChainDesc.BufferDesc.Height = backbufferHeight;
+ 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;
+ swapChainDesc.Flags = 0;
+ swapChainDesc.OutputWindow = mWindow;
+ swapChainDesc.SampleDesc.Count = 1;
+ swapChainDesc.SampleDesc.Quality = 0;
+ swapChainDesc.Windowed = TRUE;
+
+ HRESULT result = factory->CreateSwapChain(device, &swapChainDesc, &mSwapChain);
+
+ if (FAILED(result))
+ {
+ ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result);
+ release();
+
+ if (d3d11::isDeviceLostError(result))
+ {
+ return EGL_CONTEXT_LOST;
+ }
+ else
+ {
+ return EGL_BAD_ALLOC;
+ }
+ }
+
+ result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mBackBufferTexture, "Back buffer texture");
+
+ result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target");
+ }
+
+ // If we are resizing the swap chain, we don't wish to recreate all the static resources
+ if (!mPassThroughResourcesInit)
+ {
+ mPassThroughResourcesInit = true;
+ initPassThroughResources();
+ }
+
+ return resetOffscreenTexture(backbufferWidth, backbufferHeight);
+}
+
+void SwapChain11::initPassThroughResources()
+{
+ ID3D11Device *device = mRenderer->getDevice();
+
+ ASSERT(device != NULL);
+
+ // Make sure our resources are all not allocated, when we create
+ ASSERT(mQuadVB == NULL && mPassThroughSampler == NULL);
+ ASSERT(mPassThroughIL == NULL && mPassThroughVS == NULL && mPassThroughPS == NULL);
+
+ D3D11_BUFFER_DESC vbDesc;
+ vbDesc.ByteWidth = sizeof(d3d11::PositionTexCoordVertex) * 4;
+ vbDesc.Usage = D3D11_USAGE_DYNAMIC;
+ vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
+ vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ vbDesc.MiscFlags = 0;
+ vbDesc.StructureByteStride = 0;
+
+ HRESULT result = device->CreateBuffer(&vbDesc, NULL, &mQuadVB);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mQuadVB, "Swap chain quad vertex buffer");
+
+ D3D11_SAMPLER_DESC samplerDesc;
+ samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
+ samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
+ samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
+ samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
+ samplerDesc.MipLODBias = 0.0f;
+ samplerDesc.MaxAnisotropy = 0;
+ samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
+ samplerDesc.BorderColor[0] = 0.0f;
+ samplerDesc.BorderColor[1] = 0.0f;
+ samplerDesc.BorderColor[2] = 0.0f;
+ samplerDesc.BorderColor[3] = 0.0f;
+ samplerDesc.MinLOD = 0;
+ samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
+
+ result = device->CreateSamplerState(&samplerDesc, &mPassThroughSampler);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mPassThroughSampler, "Swap chain pass through sampler");
+
+ D3D11_INPUT_ELEMENT_DESC quadLayout[] =
+ {
+ { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
+ { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 },
+ };
+
+ result = device->CreateInputLayout(quadLayout, 2, g_VS_Passthrough, sizeof(g_VS_Passthrough), &mPassThroughIL);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mPassThroughIL, "Swap chain pass through layout");
+
+ result = device->CreateVertexShader(g_VS_Passthrough, sizeof(g_VS_Passthrough), NULL, &mPassThroughVS);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mPassThroughVS, "Swap chain pass through vertex shader");
+
+ result = device->CreatePixelShader(g_PS_PassthroughRGBA, sizeof(g_PS_PassthroughRGBA), NULL, &mPassThroughPS);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mPassThroughPS, "Swap chain pass through pixel shader");
+}
+
+// parameters should be validated/clamped by caller
+EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
+{
+ if (!mSwapChain)
+ {
+ return EGL_SUCCESS;
+ }
+
+ ID3D11Device *device = mRenderer->getDevice();
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+ // Set vertices
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ HRESULT result = deviceContext->Map(mQuadVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+ if (FAILED(result))
+ {
+ return EGL_BAD_ACCESS;
+ }
+
+ d3d11::PositionTexCoordVertex *vertices = static_cast<d3d11::PositionTexCoordVertex*>(mappedResource.pData);
+
+ // Create a quad in homogeneous coordinates
+ float x1 = (x / float(mWidth)) * 2.0f - 1.0f;
+ float y1 = (y / float(mHeight)) * 2.0f - 1.0f;
+ float x2 = ((x + width) / float(mWidth)) * 2.0f - 1.0f;
+ float y2 = ((y + height) / float(mHeight)) * 2.0f - 1.0f;
+
+ float u1 = x / float(mWidth);
+ float v1 = y / float(mHeight);
+ float u2 = (x + width) / float(mWidth);
+ float v2 = (y + height) / float(mHeight);
+
+ d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v1);
+ d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v2);
+ d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v1);
+ d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v2);
+
+ deviceContext->Unmap(mQuadVB, 0);
+
+ static UINT stride = sizeof(d3d11::PositionTexCoordVertex);
+ static UINT startIdx = 0;
+ deviceContext->IASetVertexBuffers(0, 1, &mQuadVB, &stride, &startIdx);
+
+ // Apply state
+ deviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF);
+
+ static const float blendFactor[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
+ deviceContext->OMSetBlendState(NULL, blendFactor, 0xFFFFFFF);
+
+ deviceContext->RSSetState(NULL);
+
+ // Apply shaders
+ deviceContext->IASetInputLayout(mPassThroughIL);
+ deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
+ deviceContext->VSSetShader(mPassThroughVS, NULL, 0);
+ deviceContext->PSSetShader(mPassThroughPS, NULL, 0);
+ deviceContext->GSSetShader(NULL, NULL, 0);
+
+ // Apply render targets
+ mRenderer->setOneTimeRenderTarget(mBackBufferRTView);
+
+ // Set the viewport
+ D3D11_VIEWPORT viewport;
+ viewport.TopLeftX = 0;
+ viewport.TopLeftY = 0;
+ viewport.Width = mWidth;
+ viewport.Height = mHeight;
+ viewport.MinDepth = 0.0f;
+ viewport.MaxDepth = 1.0f;
+ deviceContext->RSSetViewports(1, &viewport);
+
+ // Apply textures
+ deviceContext->PSSetShaderResources(0, 1, &mOffscreenSRView);
+ deviceContext->PSSetSamplers(0, 1, &mPassThroughSampler);
+
+ // Draw
+ deviceContext->Draw(4, 0);
+
+#if ANGLE_FORCE_VSYNC_OFF
+ result = mSwapChain->Present(0, 0);
+#else
+ result = mSwapChain->Present(mSwapInterval, 0);
+#endif
+
+ if (result == DXGI_ERROR_DEVICE_REMOVED)
+ {
+ HRESULT removedReason = device->GetDeviceRemovedReason();
+ ERR("Present failed: the D3D11 device was removed: 0x%08X", removedReason);
+ return EGL_CONTEXT_LOST;
+ }
+ else if (result == DXGI_ERROR_DEVICE_RESET)
+ {
+ ERR("Present failed: the D3D11 device was reset from a bad command.");
+ return EGL_CONTEXT_LOST;
+ }
+ else if (FAILED(result))
+ {
+ ERR("Present failed with error code 0x%08X", result);
+ }
+
+ // Unbind
+ static ID3D11ShaderResourceView *const nullSRV = NULL;
+ deviceContext->PSSetShaderResources(0, 1, &nullSRV);
+
+ mRenderer->unapplyRenderTargets();
+ mRenderer->markAllStateDirty();
+
+ return EGL_SUCCESS;
+}
+
+// Increments refcount on texture.
+// caller must Release() the returned texture
+ID3D11Texture2D *SwapChain11::getOffscreenTexture()
+{
+ if (mOffscreenTexture)
+ {
+ mOffscreenTexture->AddRef();
+ }
+
+ return mOffscreenTexture;
+}
+
+// Increments refcount on view.
+// caller must Release() the returned view
+ID3D11RenderTargetView *SwapChain11::getRenderTarget()
+{
+ if (mOffscreenRTView)
+ {
+ mOffscreenRTView->AddRef();
+ }
+
+ return mOffscreenRTView;
+}
+
+// Increments refcount on view.
+// caller must Release() the returned view
+ID3D11ShaderResourceView *SwapChain11::getRenderTargetShaderResource()
+{
+ if (mOffscreenSRView)
+ {
+ mOffscreenSRView->AddRef();
+ }
+
+ return mOffscreenSRView;
+}
+
+// Increments refcount on view.
+// caller must Release() the returned view
+ID3D11DepthStencilView *SwapChain11::getDepthStencil()
+{
+ if (mDepthStencilDSView)
+ {
+ mDepthStencilDSView->AddRef();
+ }
+
+ return mDepthStencilDSView;
+}
+
+ID3D11Texture2D *SwapChain11::getDepthStencilTexture()
+{
+ if (mDepthStencilTexture)
+ {
+ mDepthStencilTexture->AddRef();
+ }
+
+ return mDepthStencilTexture;
+}
+
+SwapChain11 *SwapChain11::makeSwapChain11(SwapChain *swapChain)
+{
+ ASSERT(HAS_DYNAMIC_TYPE(rx::SwapChain11*, swapChain));
+ return static_cast<rx::SwapChain11*>(swapChain);
+}
+
+void SwapChain11::recreate()
+{
+ // possibly should use this method instead of reset
+}
+
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/SwapChain11.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11SwapChain11h"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/SwapChain11.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/SwapChain11.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/SwapChain11.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,78 @@
</span><ins>+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// SwapChain11.h: Defines a back-end specific class for the D3D11 swap chain.
+
+#ifndef LIBGLESV2_RENDERER_SWAPCHAIN11_H_
+#define LIBGLESV2_RENDERER_SWAPCHAIN11_H_
+
+#include "common/angleutils.h"
+#include "libGLESv2/renderer/SwapChain.h"
+
+namespace rx
+{
+class Renderer11;
+
+class SwapChain11 : public SwapChain
+{
+ public:
+ SwapChain11(Renderer11 *renderer, HWND window, HANDLE shareHandle,
+ GLenum backBufferFormat, GLenum depthBufferFormat);
+ virtual ~SwapChain11();
+
+ EGLint resize(EGLint backbufferWidth, EGLint backbufferHeight);
+ virtual EGLint reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval);
+ virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height);
+ virtual void recreate();
+
+ virtual ID3D11Texture2D *getOffscreenTexture();
+ virtual ID3D11RenderTargetView *getRenderTarget();
+ virtual ID3D11ShaderResourceView *getRenderTargetShaderResource();
+
+ virtual ID3D11Texture2D *getDepthStencilTexture();
+ virtual ID3D11DepthStencilView *getDepthStencil();
+
+ EGLint getWidth() const { return mWidth; }
+ EGLint getHeight() const { return mHeight; }
+
+ static SwapChain11 *makeSwapChain11(SwapChain *swapChain);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(SwapChain11);
+
+ void release();
+ void initPassThroughResources();
+ void releaseOffscreenTexture();
+ EGLint resetOffscreenTexture(int backbufferWidth, int backbufferHeight);
+
+ Renderer11 *mRenderer;
+ EGLint mHeight;
+ EGLint mWidth;
+ bool mAppCreatedShareHandle;
+ unsigned int mSwapInterval;
+ bool mPassThroughResourcesInit;
+
+ IDXGISwapChain *mSwapChain;
+
+ ID3D11Texture2D *mBackBufferTexture;
+ ID3D11RenderTargetView *mBackBufferRTView;
+
+ ID3D11Texture2D *mOffscreenTexture;
+ ID3D11RenderTargetView *mOffscreenRTView;
+ ID3D11ShaderResourceView *mOffscreenSRView;
+
+ ID3D11Texture2D *mDepthStencilTexture;
+ ID3D11DepthStencilView *mDepthStencilDSView;
+
+ ID3D11Buffer *mQuadVB;
+ ID3D11SamplerState *mPassThroughSampler;
+ ID3D11InputLayout *mPassThroughIL;
+ ID3D11VertexShader *mPassThroughVS;
+ ID3D11PixelShader *mPassThroughPS;
+};
+
+}
+#endif // LIBGLESV2_RENDERER_SWAPCHAIN11_H_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/SwapChain11.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11TextureStorage11cpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/TextureStorage11.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/TextureStorage11.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/TextureStorage11.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,667 @@
</span><ins>+#include "precompiled.h"
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// TextureStorage11.cpp: Implements the abstract rx::TextureStorage11 class and its concrete derived
+// classes TextureStorage11_2D and TextureStorage11_Cube, which act as the interface to the D3D11 texture.
+
+#include "libGLESv2/renderer/d3d11/TextureStorage11.h"
+
+#include "libGLESv2/renderer/d3d11/Renderer11.h"
+#include "libGLESv2/renderer/d3d11/RenderTarget11.h"
+#include "libGLESv2/renderer/d3d11/SwapChain11.h"
+#include "libGLESv2/renderer/d3d11/renderer11_utils.h"
+
+#include "libGLESv2/utilities.h"
+#include "libGLESv2/main.h"
+
+namespace rx
+{
+
+TextureStorage11::TextureStorage11(Renderer *renderer, UINT bindFlags)
+ : mBindFlags(bindFlags),
+ mLodOffset(0),
+ mMipLevels(0),
+ mTexture(NULL),
+ mTextureFormat(DXGI_FORMAT_UNKNOWN),
+ mShaderResourceFormat(DXGI_FORMAT_UNKNOWN),
+ mRenderTargetFormat(DXGI_FORMAT_UNKNOWN),
+ mDepthStencilFormat(DXGI_FORMAT_UNKNOWN),
+ mSRV(NULL),
+ mTextureWidth(0),
+ mTextureHeight(0)
+{
+ mRenderer = Renderer11::makeRenderer11(renderer);
+}
+
+TextureStorage11::~TextureStorage11()
+{
+}
+
+TextureStorage11 *TextureStorage11::makeTextureStorage11(TextureStorage *storage)
+{
+ ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11*, storage));
+ return static_cast<TextureStorage11*>(storage);
+}
+
+DWORD TextureStorage11::GetTextureBindFlags(DXGI_FORMAT format, GLenum glusage, bool forceRenderable)
+{
+ UINT bindFlags = D3D11_BIND_SHADER_RESOURCE;
+
+ if (d3d11::IsDepthStencilFormat(format))
+ {
+ bindFlags |= D3D11_BIND_DEPTH_STENCIL;
+ }
+ else if(forceRenderable || (TextureStorage11::IsTextureFormatRenderable(format) && (glusage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE)))
+ {
+ bindFlags |= D3D11_BIND_RENDER_TARGET;
+ }
+ return bindFlags;
+}
+
+bool TextureStorage11::IsTextureFormatRenderable(DXGI_FORMAT format)
+{
+ switch(format)
+ {
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ case DXGI_FORMAT_A8_UNORM:
+ case DXGI_FORMAT_R32G32B32A32_FLOAT:
+ case DXGI_FORMAT_R16G16B16A16_FLOAT:
+ case DXGI_FORMAT_B8G8R8A8_UNORM:
+ case DXGI_FORMAT_R8_UNORM:
+ case DXGI_FORMAT_R8G8_UNORM:
+ case DXGI_FORMAT_R16_FLOAT:
+ case DXGI_FORMAT_R16G16_FLOAT:
+ return true;
+ case DXGI_FORMAT_BC1_UNORM:
+ case DXGI_FORMAT_BC2_UNORM:
+ case DXGI_FORMAT_BC3_UNORM:
+ case DXGI_FORMAT_R32G32B32_FLOAT: // not renderable on all devices
+ return false;
+ default:
+ UNREACHABLE();
+ return false;
+ }
+}
+
+UINT TextureStorage11::getBindFlags() const
+{
+ return mBindFlags;
+}
+
+ID3D11Texture2D *TextureStorage11::getBaseTexture() const
+{
+ return mTexture;
+}
+
+int TextureStorage11::getLodOffset() const
+{
+ return mLodOffset;
+}
+
+bool TextureStorage11::isRenderTarget() const
+{
+ return (mBindFlags & (D3D11_BIND_RENDER_TARGET | D3D11_BIND_DEPTH_STENCIL)) != 0;
+}
+
+bool TextureStorage11::isManaged() const
+{
+ return false;
+}
+
+int TextureStorage11::levelCount()
+{
+ int levels = 0;
+ if (getBaseTexture())
+ {
+ levels = mMipLevels - getLodOffset();
+ }
+ return levels;
+}
+
+UINT TextureStorage11::getSubresourceIndex(int level, int faceIndex)
+{
+ UINT index = 0;
+ if (getBaseTexture())
+ {
+ index = D3D11CalcSubresource(level, faceIndex, mMipLevels);
+ }
+ return index;
+}
+
+bool TextureStorage11::updateSubresourceLevel(ID3D11Texture2D *srcTexture, unsigned int sourceSubresource,
+ int level, int face, GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height)
+{
+ if (srcTexture)
+ {
+ // Round up the width and height to the nearest multiple of dimension alignment
+ unsigned int dimensionAlignment = d3d11::GetTextureFormatDimensionAlignment(mTextureFormat);
+ width = width + dimensionAlignment - 1 - (width - 1) % dimensionAlignment;
+ height = height + dimensionAlignment - 1 - (height - 1) % dimensionAlignment;
+
+ D3D11_BOX srcBox;
+ srcBox.left = xoffset;
+ srcBox.top = yoffset;
+ srcBox.right = xoffset + width;
+ srcBox.bottom = yoffset + height;
+ srcBox.front = 0;
+ srcBox.back = 1;
+
+ ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+
+ ASSERT(getBaseTexture());
+ context->CopySubresourceRegion(getBaseTexture(), getSubresourceIndex(level + mLodOffset, face),
+ xoffset, yoffset, 0, srcTexture, sourceSubresource, &srcBox);
+ return true;
+ }
+
+ return false;
+}
+
+void TextureStorage11::generateMipmapLayer(RenderTarget11 *source, RenderTarget11 *dest)
+{
+ if (source && dest)
+ {
+ ID3D11ShaderResourceView *sourceSRV = source->getShaderResourceView();
+ ID3D11RenderTargetView *destRTV = dest->getRenderTargetView();
+
+ if (sourceSRV && destRTV)
+ {
+ gl::Rectangle sourceArea;
+ sourceArea.x = 0;
+ sourceArea.y = 0;
+ sourceArea.width = source->getWidth();
+ sourceArea.height = source->getHeight();
+
+ gl::Rectangle destArea;
+ destArea.x = 0;
+ destArea.y = 0;
+ destArea.width = dest->getWidth();
+ destArea.height = dest->getHeight();
+
+ mRenderer->copyTexture(sourceSRV, sourceArea, source->getWidth(), source->getHeight(),
+ destRTV, destArea, dest->getWidth(), dest->getHeight(),
+ GL_RGBA);
+ }
+ }
+}
+
+TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapchain)
+ : TextureStorage11(renderer, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE)
+{
+ mTexture = swapchain->getOffscreenTexture();
+ mSRV = swapchain->getRenderTargetShaderResource();
+
+ for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
+ {
+ mRenderTarget[i] = NULL;
+ }
+
+ D3D11_TEXTURE2D_DESC texDesc;
+ mTexture->GetDesc(&texDesc);
+ mMipLevels = texDesc.MipLevels;
+ mTextureFormat = texDesc.Format;
+ mTextureWidth = texDesc.Width;
+ mTextureHeight = texDesc.Height;
+
+ D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+ mSRV->GetDesc(&srvDesc);
+ mShaderResourceFormat = srvDesc.Format;
+
+ ID3D11RenderTargetView* offscreenRTV = swapchain->getRenderTarget();
+ D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+ offscreenRTV->GetDesc(&rtvDesc);
+ mRenderTargetFormat = rtvDesc.Format;
+ offscreenRTV->Release();
+
+ mDepthStencilFormat = DXGI_FORMAT_UNKNOWN;
+}
+
+TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height)
+ : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat), usage, forceRenderable))
+{
+ for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
+ {
+ mRenderTarget[i] = NULL;
+ }
+
+ DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat);
+ if (d3d11::IsDepthStencilFormat(convertedFormat))
+ {
+ mTextureFormat = d3d11::GetDepthTextureFormat(convertedFormat);
+ mShaderResourceFormat = d3d11::GetDepthShaderResourceFormat(convertedFormat);
+ mDepthStencilFormat = convertedFormat;
+ mRenderTargetFormat = DXGI_FORMAT_UNKNOWN;
+ }
+ else
+ {
+ mTextureFormat = convertedFormat;
+ mShaderResourceFormat = convertedFormat;
+ mDepthStencilFormat = DXGI_FORMAT_UNKNOWN;
+ mRenderTargetFormat = convertedFormat;
+ }
+
+ // if the width or height is not positive this should be treated as an incomplete texture
+ // we handle that here by skipping the d3d texture creation
+ if (width > 0 && height > 0)
+ {
+ // adjust size if needed for compressed textures
+ gl::MakeValidSize(false, gl::IsCompressed(internalformat), &width, &height, &mLodOffset);
+
+ ID3D11Device *device = mRenderer->getDevice();
+
+ D3D11_TEXTURE2D_DESC desc;
+ desc.Width = width; // Compressed texture size constraints?
+ desc.Height = height;
+ desc.MipLevels = (levels > 0) ? levels + mLodOffset : 0;
+ desc.ArraySize = 1;
+ desc.Format = mTextureFormat;
+ desc.SampleDesc.Count = 1;
+ desc.SampleDesc.Quality = 0;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = getBindFlags();
+ desc.CPUAccessFlags = 0;
+ desc.MiscFlags = 0;
+
+ HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
+
+ // this can happen from windows TDR
+ if (d3d11::isDeviceLostError(result))
+ {
+ mRenderer->notifyDeviceLost();
+ gl::error(GL_OUT_OF_MEMORY);
+ }
+ else if (FAILED(result))
+ {
+ ASSERT(result == E_OUTOFMEMORY);
+ ERR("Creating image failed.");
+ gl::error(GL_OUT_OF_MEMORY);
+ }
+ else
+ {
+ mTexture->GetDesc(&desc);
+ mMipLevels = desc.MipLevels;
+ mTextureWidth = desc.Width;
+ mTextureHeight = desc.Height;
+ }
+ }
+}
+
+TextureStorage11_2D::~TextureStorage11_2D()
+{
+ if (mTexture)
+ {
+ mTexture->Release();
+ mTexture = NULL;
+ }
+
+ if (mSRV)
+ {
+ mSRV->Release();
+ mSRV = NULL;
+ }
+
+ for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
+ {
+ delete mRenderTarget[i];
+ mRenderTarget[i] = NULL;
+ }
+}
+
+TextureStorage11_2D *TextureStorage11_2D::makeTextureStorage11_2D(TextureStorage *storage)
+{
+ ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_2D*, storage));
+ return static_cast<TextureStorage11_2D*>(storage);
+}
+
+RenderTarget *TextureStorage11_2D::getRenderTarget(int level)
+{
+ if (level >= 0 && level < static_cast<int>(mMipLevels))
+ {
+ if (!mRenderTarget[level])
+ {
+ ID3D11Device *device = mRenderer->getDevice();
+ HRESULT result;
+
+ D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+ srvDesc.Format = mShaderResourceFormat;
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
+ srvDesc.Texture2D.MostDetailedMip = level;
+ srvDesc.Texture2D.MipLevels = 1;
+
+ ID3D11ShaderResourceView *srv;
+ result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv);
+
+ if (result == E_OUTOFMEMORY)
+ {
+ return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
+ }
+ ASSERT(SUCCEEDED(result));
+
+ if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
+ {
+ D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+ rtvDesc.Format = mRenderTargetFormat;
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
+ rtvDesc.Texture2D.MipSlice = level;
+
+ ID3D11RenderTargetView *rtv;
+ result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
+
+ if (result == E_OUTOFMEMORY)
+ {
+ srv->Release();
+ return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
+ }
+ ASSERT(SUCCEEDED(result));
+
+ // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
+ // also needs to keep a reference to the texture.
+ mTexture->AddRef();
+
+ mRenderTarget[level] = new RenderTarget11(mRenderer, rtv, mTexture, srv,
+ std::max(mTextureWidth >> level, 1U),
+ std::max(mTextureHeight >> level, 1U));
+ }
+ else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN)
+ {
+ D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
+ dsvDesc.Format = mDepthStencilFormat;
+ dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
+ dsvDesc.Texture2D.MipSlice = level;
+ dsvDesc.Flags = 0;
+
+ ID3D11DepthStencilView *dsv;
+ result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv);
+
+ if (result == E_OUTOFMEMORY)
+ {
+ srv->Release();
+ return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
+ }
+ ASSERT(SUCCEEDED(result));
+
+ // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
+ // also needs to keep a reference to the texture.
+ mTexture->AddRef();
+
+ mRenderTarget[level] = new RenderTarget11(mRenderer, dsv, mTexture, srv,
+ std::max(mTextureWidth >> level, 1U),
+ std::max(mTextureHeight >> level, 1U));
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+ }
+
+ return mRenderTarget[level];
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+ID3D11ShaderResourceView *TextureStorage11_2D::getSRV()
+{
+ if (!mSRV)
+ {
+ ID3D11Device *device = mRenderer->getDevice();
+
+ D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+ srvDesc.Format = mShaderResourceFormat;
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
+ srvDesc.Texture2D.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels);
+ srvDesc.Texture2D.MostDetailedMip = 0;
+
+ HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV);
+
+ if (result == E_OUTOFMEMORY)
+ {
+ return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11ShaderResourceView*>(NULL));
+ }
+ ASSERT(SUCCEEDED(result));
+ }
+
+ return mSRV;
+}
+
+void TextureStorage11_2D::generateMipmap(int level)
+{
+ RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(level - 1));
+ RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(level));
+
+ generateMipmapLayer(source, dest);
+}
+
+TextureStorage11_Cube::TextureStorage11_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size)
+ : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat), usage, forceRenderable))
+{
+ for (unsigned int i = 0; i < 6; i++)
+ {
+ for (unsigned int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; j++)
+ {
+ mRenderTarget[i][j] = NULL;
+ }
+ }
+
+ DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat);
+ if (d3d11::IsDepthStencilFormat(convertedFormat))
+ {
+ mTextureFormat = d3d11::GetDepthTextureFormat(convertedFormat);
+ mShaderResourceFormat = d3d11::GetDepthShaderResourceFormat(convertedFormat);
+ mDepthStencilFormat = convertedFormat;
+ mRenderTargetFormat = DXGI_FORMAT_UNKNOWN;
+ }
+ else
+ {
+ mTextureFormat = convertedFormat;
+ mShaderResourceFormat = convertedFormat;
+ mDepthStencilFormat = DXGI_FORMAT_UNKNOWN;
+ mRenderTargetFormat = convertedFormat;
+ }
+
+ // if the size is not positive this should be treated as an incomplete texture
+ // we handle that here by skipping the d3d texture creation
+ if (size > 0)
+ {
+ // adjust size if needed for compressed textures
+ int height = size;
+ gl::MakeValidSize(false, gl::IsCompressed(internalformat), &size, &height, &mLodOffset);
+
+ ID3D11Device *device = mRenderer->getDevice();
+
+ D3D11_TEXTURE2D_DESC desc;
+ desc.Width = size;
+ desc.Height = size;
+ desc.MipLevels = (levels > 0) ? levels + mLodOffset : 0;
+ desc.ArraySize = 6;
+ desc.Format = mTextureFormat;
+ desc.SampleDesc.Count = 1;
+ desc.SampleDesc.Quality = 0;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = getBindFlags();
+ desc.CPUAccessFlags = 0;
+ desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
+
+ HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
+
+ if (FAILED(result))
+ {
+ ASSERT(result == E_OUTOFMEMORY);
+ ERR("Creating image failed.");
+ gl::error(GL_OUT_OF_MEMORY);
+ }
+ else
+ {
+ mTexture->GetDesc(&desc);
+ mMipLevels = desc.MipLevels;
+ mTextureWidth = desc.Width;
+ mTextureHeight = desc.Height;
+ }
+ }
+}
+
+TextureStorage11_Cube::~TextureStorage11_Cube()
+{
+ if (mTexture)
+ {
+ mTexture->Release();
+ mTexture = NULL;
+ }
+
+ if (mSRV)
+ {
+ mSRV->Release();
+ mSRV = NULL;
+ }
+
+ for (unsigned int i = 0; i < 6; i++)
+ {
+ for (unsigned int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; j++)
+ {
+ delete mRenderTarget[i][j];
+ mRenderTarget[i][j] = NULL;
+ }
+ }
+}
+
+TextureStorage11_Cube *TextureStorage11_Cube::makeTextureStorage11_Cube(TextureStorage *storage)
+{
+ ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_Cube*, storage));
+ return static_cast<TextureStorage11_Cube*>(storage);
+}
+
+RenderTarget *TextureStorage11_Cube::getRenderTarget(GLenum faceTarget, int level)
+{
+ unsigned int faceIdx = gl::TextureCubeMap::faceIndex(faceTarget);
+ if (level >= 0 && level < static_cast<int>(mMipLevels))
+ {
+ if (!mRenderTarget[faceIdx][level])
+ {
+ ID3D11Device *device = mRenderer->getDevice();
+ HRESULT result;
+
+ D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+ srvDesc.Format = mShaderResourceFormat;
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; // Will be used with Texture2D sampler, not TextureCube
+ srvDesc.Texture2DArray.MostDetailedMip = level;
+ srvDesc.Texture2DArray.MipLevels = 1;
+ srvDesc.Texture2DArray.FirstArraySlice = faceIdx;
+ srvDesc.Texture2DArray.ArraySize = 1;
+
+ ID3D11ShaderResourceView *srv;
+ result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv);
+
+ if (result == E_OUTOFMEMORY)
+ {
+ return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
+ }
+ ASSERT(SUCCEEDED(result));
+
+ if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
+ {
+ D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+ rtvDesc.Format = mRenderTargetFormat;
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
+ rtvDesc.Texture2DArray.MipSlice = level;
+ rtvDesc.Texture2DArray.FirstArraySlice = faceIdx;
+ rtvDesc.Texture2DArray.ArraySize = 1;
+
+ ID3D11RenderTargetView *rtv;
+ result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv);
+
+ if (result == E_OUTOFMEMORY)
+ {
+ srv->Release();
+ return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
+ }
+ ASSERT(SUCCEEDED(result));
+
+ // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
+ // also needs to keep a reference to the texture.
+ mTexture->AddRef();
+
+ mRenderTarget[faceIdx][level] = new RenderTarget11(mRenderer, rtv, mTexture, srv,
+ std::max(mTextureWidth >> level, 1U),
+ std::max(mTextureHeight >> level, 1U));
+ }
+ else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN)
+ {
+ D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
+ dsvDesc.Format = mRenderTargetFormat;
+ dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
+ dsvDesc.Texture2DArray.MipSlice = level;
+ dsvDesc.Texture2DArray.FirstArraySlice = faceIdx;
+ dsvDesc.Texture2DArray.ArraySize = 1;
+
+ ID3D11DepthStencilView *dsv;
+ result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv);
+
+ if (result == E_OUTOFMEMORY)
+ {
+ srv->Release();
+ return gl::error(GL_OUT_OF_MEMORY, static_cast<RenderTarget*>(NULL));
+ }
+ ASSERT(SUCCEEDED(result));
+
+ // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11
+ // also needs to keep a reference to the texture.
+ mTexture->AddRef();
+
+ mRenderTarget[faceIdx][level] = new RenderTarget11(mRenderer, dsv, mTexture, srv,
+ std::max(mTextureWidth >> level, 1U),
+ std::max(mTextureHeight >> level, 1U));
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+ }
+
+ return mRenderTarget[faceIdx][level];
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+ID3D11ShaderResourceView *TextureStorage11_Cube::getSRV()
+{
+ if (!mSRV)
+ {
+ ID3D11Device *device = mRenderer->getDevice();
+
+ D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+ srvDesc.Format = mShaderResourceFormat;
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
+ srvDesc.TextureCube.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels);
+ srvDesc.TextureCube.MostDetailedMip = 0;
+
+ HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV);
+
+ if (result == E_OUTOFMEMORY)
+ {
+ return gl::error(GL_OUT_OF_MEMORY, static_cast<ID3D11ShaderResourceView*>(NULL));
+ }
+ ASSERT(SUCCEEDED(result));
+ }
+
+ return mSRV;
+}
+
+void TextureStorage11_Cube::generateMipmap(int face, int level)
+{
+ RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level - 1));
+ RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level));
+
+ generateMipmapLayer(source, dest);
+}
+
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/TextureStorage11.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11TextureStorage11h"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/TextureStorage11.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/TextureStorage11.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/TextureStorage11.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,120 @@
</span><ins>+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// TextureStorage11.h: Defines the abstract rx::TextureStorage11 class and its concrete derived
+// classes TextureStorage11_2D and TextureStorage11_Cube, which act as the interface to the D3D11 texture.
+
+#ifndef LIBGLESV2_RENDERER_TEXTURESTORAGE11_H_
+#define LIBGLESV2_RENDERER_TEXTURESTORAGE11_H_
+
+#include "libGLESv2/Texture.h"
+#include "libGLESv2/renderer/TextureStorage.h"
+
+namespace rx
+{
+class RenderTarget;
+class RenderTarget11;
+class Renderer;
+class Renderer11;
+class SwapChain11;
+
+class TextureStorage11 : public TextureStorage
+{
+ public:
+ TextureStorage11(Renderer *renderer, UINT bindFlags);
+ virtual ~TextureStorage11();
+
+ static TextureStorage11 *makeTextureStorage11(TextureStorage *storage);
+
+ static DWORD GetTextureBindFlags(DXGI_FORMAT d3dfmt, GLenum glusage, bool forceRenderable);
+ static bool IsTextureFormatRenderable(DXGI_FORMAT format);
+
+ UINT getBindFlags() const;
+
+ virtual ID3D11Texture2D *getBaseTexture() const;
+ virtual ID3D11ShaderResourceView *getSRV() = 0;
+ virtual RenderTarget *getRenderTarget() { return getRenderTarget(0); }
+ virtual RenderTarget *getRenderTarget(int level) { return NULL; }
+ virtual RenderTarget *getRenderTarget(GLenum faceTarget) { return getRenderTarget(faceTarget, 0); }
+ virtual RenderTarget *getRenderTarget(GLenum faceTarget, int level) { return NULL; }
+
+ virtual void generateMipmap(int level) {};
+ virtual void generateMipmap(int face, int level) {};
+
+ virtual int getLodOffset() const;
+ virtual bool isRenderTarget() const;
+ virtual bool isManaged() const;
+ virtual int levelCount();
+ UINT getSubresourceIndex(int level, int faceTarget);
+
+ bool updateSubresourceLevel(ID3D11Texture2D *texture, unsigned int sourceSubresource, int level,
+ int faceTarget, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
+
+ protected:
+ void generateMipmapLayer(RenderTarget11 *source, RenderTarget11 *dest);
+
+ Renderer11 *mRenderer;
+ int mLodOffset;
+ unsigned int mMipLevels;
+
+ ID3D11Texture2D *mTexture;
+ DXGI_FORMAT mTextureFormat;
+ DXGI_FORMAT mShaderResourceFormat;
+ DXGI_FORMAT mRenderTargetFormat;
+ DXGI_FORMAT mDepthStencilFormat;
+ unsigned int mTextureWidth;
+ unsigned int mTextureHeight;
+
+ ID3D11ShaderResourceView *mSRV;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TextureStorage11);
+
+ const UINT mBindFlags;
+};
+
+class TextureStorage11_2D : public TextureStorage11
+{
+ public:
+ TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapchain);
+ TextureStorage11_2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height);
+ virtual ~TextureStorage11_2D();
+
+ static TextureStorage11_2D *makeTextureStorage11_2D(TextureStorage *storage);
+
+ virtual ID3D11ShaderResourceView *getSRV();
+ virtual RenderTarget *getRenderTarget(int level);
+
+ virtual void generateMipmap(int level);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TextureStorage11_2D);
+
+ RenderTarget11 *mRenderTarget[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+};
+
+class TextureStorage11_Cube : public TextureStorage11
+{
+ public:
+ TextureStorage11_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size);
+ virtual ~TextureStorage11_Cube();
+
+ static TextureStorage11_Cube *makeTextureStorage11_Cube(TextureStorage *storage);
+
+ virtual ID3D11ShaderResourceView *getSRV();
+ virtual RenderTarget *getRenderTarget(GLenum faceTarget, int level);
+
+ virtual void generateMipmap(int face, int level);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TextureStorage11_Cube);
+
+ RenderTarget11 *mRenderTarget[6][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+};
+
+}
+
+#endif // LIBGLESV2_RENDERER_TEXTURESTORAGE11_H_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/TextureStorage11.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11VertexBuffer11cpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/VertexBuffer11.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/VertexBuffer11.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/VertexBuffer11.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,440 @@
</span><ins>+#include "precompiled.h"
+//
+// Copyright (c) 2013 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.
+//
+
+// VertexBuffer11.cpp: Defines the D3D11 VertexBuffer implementation.
+
+#include "libGLESv2/renderer/d3d11/VertexBuffer11.h"
+#include "libGLESv2/renderer/BufferStorage.h"
+
+#include "libGLESv2/Buffer.h"
+#include "libGLESv2/renderer/d3d11/Renderer11.h"
+#include "libGLESv2/Context.h"
+
+namespace rx
+{
+
+VertexBuffer11::VertexBuffer11(rx::Renderer11 *const renderer) : mRenderer(renderer)
+{
+ mBuffer = NULL;
+ mBufferSize = 0;
+ mDynamicUsage = false;
+}
+
+VertexBuffer11::~VertexBuffer11()
+{
+ if (mBuffer)
+ {
+ mBuffer->Release();
+ mBuffer = NULL;
+ }
+}
+
+bool VertexBuffer11::initialize(unsigned int size, bool dynamicUsage)
+{
+ if (mBuffer)
+ {
+ mBuffer->Release();
+ mBuffer = NULL;
+ }
+
+ updateSerial();
+
+ if (size > 0)
+ {
+ ID3D11Device* dxDevice = mRenderer->getDevice();
+
+ D3D11_BUFFER_DESC bufferDesc;
+ bufferDesc.ByteWidth = size;
+ bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
+ bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
+ bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ bufferDesc.MiscFlags = 0;
+ bufferDesc.StructureByteStride = 0;
+
+ HRESULT result = dxDevice->CreateBuffer(&bufferDesc, NULL, &mBuffer);
+ if (FAILED(result))
+ {
+ return false;
+ }
+ }
+
+ mBufferSize = size;
+ mDynamicUsage = dynamicUsage;
+ return true;
+}
+
+VertexBuffer11 *VertexBuffer11::makeVertexBuffer11(VertexBuffer *vetexBuffer)
+{
+ ASSERT(HAS_DYNAMIC_TYPE(VertexBuffer11*, vetexBuffer));
+ return static_cast<VertexBuffer11*>(vetexBuffer);
+}
+
+bool VertexBuffer11::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count,
+ GLsizei instances, unsigned int offset)
+{
+ if (mBuffer)
+ {
+ gl::Buffer *buffer = attrib.mBoundBuffer.get();
+
+ int inputStride = attrib.stride();
+ const VertexConverter &converter = getVertexConversion(attrib);
+
+ ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
+
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource);
+ if (FAILED(result))
+ {
+ ERR("Vertex buffer map failed with error 0x%08x", result);
+ return false;
+ }
+
+ char* output = reinterpret_cast<char*>(mappedResource.pData) + offset;
+
+ const char *input = NULL;
+ if (buffer)
+ {
+ BufferStorage *storage = buffer->getStorage();
+ input = static_cast<const char*>(storage->getData()) + static_cast<int>(attrib.mOffset);
+ }
+ else
+ {
+ input = static_cast<const char*>(attrib.mPointer);
+ }
+
+ if (instances == 0 || attrib.mDivisor == 0)
+ {
+ input += inputStride * start;
+ }
+
+ converter.conversionFunc(input, inputStride, count, output);
+
+ dxContext->Unmap(mBuffer, 0);
+
+ return true;
+ }
+ else
+ {
+ ERR("Vertex buffer not initialized.");
+ return false;
+ }
+}
+
+bool VertexBuffer11::storeRawData(const void* data, unsigned int size, unsigned int offset)
+{
+ if (mBuffer)
+ {
+ ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
+
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource);
+ if (FAILED(result))
+ {
+ ERR("Vertex buffer map failed with error 0x%08x", result);
+ return false;
+ }
+
+ char* bufferData = static_cast<char*>(mappedResource.pData);
+ memcpy(bufferData + offset, data, size);
+
+ dxContext->Unmap(mBuffer, 0);
+
+ return true;
+ }
+ else
+ {
+ ERR("Vertex buffer not initialized.");
+ return false;
+ }
+}
+
+bool VertexBuffer11::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count,
+ GLsizei instances, unsigned int *outSpaceRequired) const
+{
+ unsigned int elementSize = getVertexConversion(attrib).outputElementSize;
+
+ unsigned int elementCount = 0;
+ if (instances == 0 || attrib.mDivisor == 0)
+ {
+ elementCount = count;
+ }
+ else
+ {
+ if (static_cast<unsigned int>(instances) < std::numeric_limits<unsigned int>::max() - (attrib.mDivisor - 1))
+ {
+ // Round up
+ elementCount = (static_cast<unsigned int>(instances) + (attrib.mDivisor - 1)) / attrib.mDivisor;
+ }
+ else
+ {
+ elementCount = instances / attrib.mDivisor;
+ }
+ }
+
+ if (elementSize <= std::numeric_limits<unsigned int>::max() / elementCount)
+ {
+ if (outSpaceRequired)
+ {
+ *outSpaceRequired = elementSize * elementCount;
+ }
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+bool VertexBuffer11::requiresConversion(const gl::VertexAttribute &attrib) const
+{
+ return !getVertexConversion(attrib).identity;
+}
+
+unsigned int VertexBuffer11::getBufferSize() const
+{
+ return mBufferSize;
+}
+
+bool VertexBuffer11::setBufferSize(unsigned int size)
+{
+ if (size > mBufferSize)
+ {
+ return initialize(size, mDynamicUsage);
+ }
+ else
+ {
+ return true;
+ }
+}
+
+bool VertexBuffer11::discard()
+{
+ if (mBuffer)
+ {
+ ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
+
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+ if (FAILED(result))
+ {
+ ERR("Vertex buffer map failed with error 0x%08x", result);
+ return false;
+ }
+
+ dxContext->Unmap(mBuffer, 0);
+
+ return true;
+ }
+ else
+ {
+ ERR("Vertex buffer not initialized.");
+ return false;
+ }
+}
+
+unsigned int VertexBuffer11::getVertexSize(const gl::VertexAttribute &attrib) const
+{
+ return getVertexConversion(attrib).outputElementSize;
+}
+
+DXGI_FORMAT VertexBuffer11::getDXGIFormat(const gl::VertexAttribute &attrib) const
+{
+ return getVertexConversion(attrib).dxgiFormat;
+}
+
+ID3D11Buffer *VertexBuffer11::getBuffer() const
+{
+ return mBuffer;
+}
+
+template <typename T, unsigned int componentCount, bool widen, bool normalized>
+static void copyVertexData(const void *input, unsigned int stride, unsigned int count, void *output)
+{
+ unsigned int attribSize = sizeof(T) * componentCount;
+
+ if (attribSize == stride && !widen)
+ {
+ memcpy(output, input, count * attribSize);
+ }
+ else
+ {
+ unsigned int outputStride = widen ? 4 : componentCount;
+ T defaultVal = normalized ? std::numeric_limits<T>::max() : T(1);
+
+ for (unsigned int i = 0; i < count; i++)
+ {
+ const T *offsetInput = reinterpret_cast<const T*>(reinterpret_cast<const char*>(input) + i * stride);
+ T *offsetOutput = reinterpret_cast<T*>(output) + i * outputStride;
+
+ for (unsigned int j = 0; j < componentCount; j++)
+ {
+ offsetOutput[j] = offsetInput[j];
+ }
+
+ if (widen)
+ {
+ offsetOutput[3] = defaultVal;
+ }
+ }
+ }
+}
+
+template <unsigned int componentCount>
+static void copyFixedVertexData(const void* input, unsigned int stride, unsigned int count, void* output)
+{
+ static const float divisor = 1.0f / (1 << 16);
+
+ for (unsigned int i = 0; i < count; i++)
+ {
+ const GLfixed* offsetInput = reinterpret_cast<const GLfixed*>(reinterpret_cast<const char*>(input) + stride * i);
+ float* offsetOutput = reinterpret_cast<float*>(output) + i * componentCount;
+
+ for (unsigned int j = 0; j < componentCount; j++)
+ {
+ offsetOutput[j] = static_cast<float>(offsetInput[j]) * divisor;
+ }
+ }
+}
+
+template <typename T, unsigned int componentCount, bool normalized>
+static void copyToFloatVertexData(const void* input, unsigned int stride, unsigned int count, void* output)
+{
+ typedef std::numeric_limits<T> NL;
+
+ for (unsigned int i = 0; i < count; i++)
+ {
+ const T *offsetInput = reinterpret_cast<const T*>(reinterpret_cast<const char*>(input) + stride * i);
+ float *offsetOutput = reinterpret_cast<float*>(output) + i * componentCount;
+
+ for (unsigned int j = 0; j < componentCount; j++)
+ {
+ if (normalized)
+ {
+ if (NL::is_signed)
+ {
+ const float divisor = 1.0f / (2 * static_cast<float>(NL::max()) + 1);
+ offsetOutput[j] = (2 * static_cast<float>(offsetInput[j]) + 1) * divisor;
+ }
+ else
+ {
+ offsetOutput[j] = static_cast<float>(offsetInput[j]) / NL::max();
+ }
+ }
+ else
+ {
+ offsetOutput[j] = static_cast<float>(offsetInput[j]);
+ }
+ }
+ }
+}
+
+const VertexBuffer11::VertexConverter VertexBuffer11::mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4] =
+{
+ { // GL_BYTE
+ { // unnormalized
+ { &copyToFloatVertexData<GLbyte, 1, false>, false, DXGI_FORMAT_R32_FLOAT, 4 },
+ { &copyToFloatVertexData<GLbyte, 2, false>, false, DXGI_FORMAT_R32G32_FLOAT, 8 },
+ { &copyToFloatVertexData<GLbyte, 3, false>, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 },
+ { &copyToFloatVertexData<GLbyte, 4, false>, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 },
+ },
+ { // normalized
+ { &copyVertexData<GLbyte, 1, false, true>, true, DXGI_FORMAT_R8_SNORM, 1 },
+ { &copyVertexData<GLbyte, 2, false, true>, true, DXGI_FORMAT_R8G8_SNORM, 2 },
+ { &copyVertexData<GLbyte, 3, true, true>, false, DXGI_FORMAT_R8G8B8A8_SNORM, 4 },
+ { &copyVertexData<GLbyte, 4, false, true>, true, DXGI_FORMAT_R8G8B8A8_SNORM, 4 },
+ },
+ },
+ { // GL_UNSIGNED_BYTE
+ { // unnormalized
+ { &copyToFloatVertexData<GLubyte, 1, false>, false, DXGI_FORMAT_R32_FLOAT, 4 },
+ { &copyToFloatVertexData<GLubyte, 2, false>, false, DXGI_FORMAT_R32G32_FLOAT, 8 },
+ { &copyToFloatVertexData<GLubyte, 3, false>, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 },
+ { &copyToFloatVertexData<GLubyte, 4, false>, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 },
+ },
+ { // normalized
+ { &copyVertexData<GLubyte, 1, false, true>, true, DXGI_FORMAT_R8_UNORM, 1 },
+ { &copyVertexData<GLubyte, 2, false, true>, true, DXGI_FORMAT_R8G8_UNORM, 2 },
+ { &copyVertexData<GLubyte, 3, true, true>, false, DXGI_FORMAT_R8G8B8A8_UNORM, 4 },
+ { &copyVertexData<GLubyte, 4, false, true>, true, DXGI_FORMAT_R8G8B8A8_UNORM, 4 },
+ },
+ },
+ { // GL_SHORT
+ { // unnormalized
+ { &copyToFloatVertexData<GLshort, 1, false>, false, DXGI_FORMAT_R32_FLOAT, 4 },
+ { &copyToFloatVertexData<GLshort, 2, false>, false, DXGI_FORMAT_R32G32_FLOAT, 8 },
+ { &copyToFloatVertexData<GLshort, 3, false>, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 },
+ { &copyToFloatVertexData<GLshort, 4, false>, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 },
+ },
+ { // normalized
+ { &copyVertexData<GLshort, 1, false, true>, true, DXGI_FORMAT_R16_SNORM, 2 },
+ { &copyVertexData<GLshort, 2, false, true>, true, DXGI_FORMAT_R16G16_SNORM, 4 },
+ { &copyVertexData<GLshort, 3, true, true>, false, DXGI_FORMAT_R16G16B16A16_SNORM, 8 },
+ { &copyVertexData<GLshort, 4, false, true>, true, DXGI_FORMAT_R16G16B16A16_SNORM, 8 },
+ },
+ },
+ { // GL_UNSIGNED_SHORT
+ { // unnormalized
+ { &copyToFloatVertexData<GLushort, 1, false>, false, DXGI_FORMAT_R32_FLOAT, 4 },
+ { &copyToFloatVertexData<GLushort, 2, false>, false, DXGI_FORMAT_R32G32_FLOAT, 8 },
+ { &copyToFloatVertexData<GLushort, 3, false>, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 },
+ { &copyToFloatVertexData<GLushort, 4, false>, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 },
+ },
+ { // normalized
+ { &copyVertexData<GLushort, 1, false, true>, true, DXGI_FORMAT_R16_UNORM, 2 },
+ { &copyVertexData<GLushort, 2, false, true>, true, DXGI_FORMAT_R16G16_UNORM, 4 },
+ { &copyVertexData<GLushort, 3, true, true>, false, DXGI_FORMAT_R16G16B16A16_UNORM, 8 },
+ { &copyVertexData<GLushort, 4, false, true>, true, DXGI_FORMAT_R16G16B16A16_UNORM, 8 },
+ },
+ },
+ { // GL_FIXED
+ { // unnormalized
+ { &copyFixedVertexData<1>, false, DXGI_FORMAT_R32_FLOAT, 4 },
+ { &copyFixedVertexData<2>, false, DXGI_FORMAT_R32G32_FLOAT, 8 },
+ { &copyFixedVertexData<3>, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 },
+ { &copyFixedVertexData<4>, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 },
+ },
+ { // normalized
+ { &copyFixedVertexData<1>, false, DXGI_FORMAT_R32_FLOAT, 4 },
+ { &copyFixedVertexData<2>, false, DXGI_FORMAT_R32G32_FLOAT, 8 },
+ { &copyFixedVertexData<3>, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 },
+ { &copyFixedVertexData<4>, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 },
+ },
+ },
+ { // GL_FLOAT
+ { // unnormalized
+ { &copyVertexData<GLfloat, 1, false, false>, true, DXGI_FORMAT_R32_FLOAT, 4 },
+ { &copyVertexData<GLfloat, 2, false, false>, true, DXGI_FORMAT_R32G32_FLOAT, 8 },
+ { &copyVertexData<GLfloat, 3, false, false>, true, DXGI_FORMAT_R32G32B32_FLOAT, 12 },
+ { &copyVertexData<GLfloat, 4, false, false>, true, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 },
+ },
+ { // normalized
+ { &copyVertexData<GLfloat, 1, false, false>, true, DXGI_FORMAT_R32_FLOAT, 4 },
+ { &copyVertexData<GLfloat, 2, false, false>, true, DXGI_FORMAT_R32G32_FLOAT, 8 },
+ { &copyVertexData<GLfloat, 3, false, false>, true, DXGI_FORMAT_R32G32B32_FLOAT, 12 },
+ { &copyVertexData<GLfloat, 4, false, false>, true, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 },
+ },
+ },
+};
+
+const VertexBuffer11::VertexConverter &VertexBuffer11::getVertexConversion(const gl::VertexAttribute &attribute)
+{
+ unsigned int typeIndex = 0;
+ switch (attribute.mType)
+ {
+ case GL_BYTE: typeIndex = 0; break;
+ case GL_UNSIGNED_BYTE: typeIndex = 1; break;
+ case GL_SHORT: typeIndex = 2; break;
+ case GL_UNSIGNED_SHORT: typeIndex = 3; break;
+ case GL_FIXED: typeIndex = 4; break;
+ case GL_FLOAT: typeIndex = 5; break;
+ default: UNREACHABLE(); break;
+ }
+
+ return mPossibleTranslations[typeIndex][attribute.mNormalized ? 1 : 0][attribute.mSize - 1];
+}
+
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/VertexBuffer11.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11VertexBuffer11h"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/VertexBuffer11.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/VertexBuffer11.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/VertexBuffer11.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,74 @@
</span><ins>+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// VertexBuffer11.h: Defines the D3D11 VertexBuffer implementation.
+
+#ifndef LIBGLESV2_RENDERER_VERTEXBUFFER11_H_
+#define LIBGLESV2_RENDERER_VERTEXBUFFER11_H_
+
+#include "libGLESv2/renderer/VertexBuffer.h"
+
+namespace rx
+{
+class Renderer11;
+
+class VertexBuffer11 : public VertexBuffer
+{
+ public:
+ explicit VertexBuffer11(rx::Renderer11 *const renderer);
+ virtual ~VertexBuffer11();
+
+ virtual bool initialize(unsigned int size, bool dynamicUsage);
+
+ static VertexBuffer11 *makeVertexBuffer11(VertexBuffer *vetexBuffer);
+
+ virtual bool storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances,
+ unsigned int offset);
+ virtual bool storeRawData(const void* data, unsigned int size, unsigned int offset);
+
+ virtual bool getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances,
+ unsigned int *outSpaceRequired) const;
+
+ virtual bool requiresConversion(const gl::VertexAttribute &attrib) const;
+
+ virtual unsigned int getBufferSize() const;
+ virtual bool setBufferSize(unsigned int size);
+ virtual bool discard();
+
+ unsigned int getVertexSize(const gl::VertexAttribute &attrib) const;
+ DXGI_FORMAT getDXGIFormat(const gl::VertexAttribute &attrib) const;
+
+ ID3D11Buffer *getBuffer() const;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(VertexBuffer11);
+
+ rx::Renderer11 *const mRenderer;
+
+ ID3D11Buffer *mBuffer;
+ unsigned int mBufferSize;
+ bool mDynamicUsage;
+
+ typedef void (*VertexConversionFunction)(const void *, unsigned int, unsigned int, void *);
+ struct VertexConverter
+ {
+ VertexConversionFunction conversionFunc;
+ bool identity;
+ DXGI_FORMAT dxgiFormat;
+ unsigned int outputElementSize;
+ };
+
+ enum { NUM_GL_VERTEX_ATTRIB_TYPES = 6 };
+
+ // This table is used to generate mAttributeTypes.
+ static const VertexConverter mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; // [GL types as enumerated by typeIndex()][normalized][size - 1]
+
+ static const VertexConverter &getVertexConversion(const gl::VertexAttribute &attribute);
+};
+
+}
+
+#endif // LIBGLESV2_RENDERER_VERTEXBUFFER11_H_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/VertexBuffer11.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11renderer11_utilscpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/renderer11_utils.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/renderer11_utils.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/renderer11_utils.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,688 @@
</span><ins>+#include "precompiled.h"
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// renderer11_utils.cpp: Conversion functions and other utility routines
+// specific to the D3D11 renderer.
+
+#include "libGLESv2/renderer/d3d11/renderer11_utils.h"
+
+#include "common/debug.h"
+
+namespace gl_d3d11
+{
+
+D3D11_BLEND ConvertBlendFunc(GLenum glBlend, bool isAlpha)
+{
+ D3D11_BLEND d3dBlend = D3D11_BLEND_ZERO;
+
+ switch (glBlend)
+ {
+ case GL_ZERO: d3dBlend = D3D11_BLEND_ZERO; break;
+ case GL_ONE: d3dBlend = D3D11_BLEND_ONE; break;
+ case GL_SRC_COLOR: d3dBlend = (isAlpha ? D3D11_BLEND_SRC_ALPHA : D3D11_BLEND_SRC_COLOR); break;
+ case GL_ONE_MINUS_SRC_COLOR: d3dBlend = (isAlpha ? D3D11_BLEND_INV_SRC_ALPHA : D3D11_BLEND_INV_SRC_COLOR); break;
+ case GL_DST_COLOR: d3dBlend = (isAlpha ? D3D11_BLEND_DEST_ALPHA : D3D11_BLEND_DEST_COLOR); break;
+ case GL_ONE_MINUS_DST_COLOR: d3dBlend = (isAlpha ? D3D11_BLEND_INV_DEST_ALPHA : D3D11_BLEND_INV_DEST_COLOR); break;
+ case GL_SRC_ALPHA: d3dBlend = D3D11_BLEND_SRC_ALPHA; break;
+ case GL_ONE_MINUS_SRC_ALPHA: d3dBlend = D3D11_BLEND_INV_SRC_ALPHA; break;
+ case GL_DST_ALPHA: d3dBlend = D3D11_BLEND_DEST_ALPHA; break;
+ case GL_ONE_MINUS_DST_ALPHA: d3dBlend = D3D11_BLEND_INV_DEST_ALPHA; break;
+ case GL_CONSTANT_COLOR: d3dBlend = D3D11_BLEND_BLEND_FACTOR; break;
+ case GL_ONE_MINUS_CONSTANT_COLOR: d3dBlend = D3D11_BLEND_INV_BLEND_FACTOR; break;
+ case GL_CONSTANT_ALPHA: d3dBlend = D3D11_BLEND_BLEND_FACTOR; break;
+ case GL_ONE_MINUS_CONSTANT_ALPHA: d3dBlend = D3D11_BLEND_INV_BLEND_FACTOR; break;
+ case GL_SRC_ALPHA_SATURATE: d3dBlend = D3D11_BLEND_SRC_ALPHA_SAT; break;
+ default: UNREACHABLE();
+ }
+
+ return d3dBlend;
+}
+
+D3D11_BLEND_OP ConvertBlendOp(GLenum glBlendOp)
+{
+ D3D11_BLEND_OP d3dBlendOp = D3D11_BLEND_OP_ADD;
+
+ switch (glBlendOp)
+ {
+ case GL_FUNC_ADD: d3dBlendOp = D3D11_BLEND_OP_ADD; break;
+ case GL_FUNC_SUBTRACT: d3dBlendOp = D3D11_BLEND_OP_SUBTRACT; break;
+ case GL_FUNC_REVERSE_SUBTRACT: d3dBlendOp = D3D11_BLEND_OP_REV_SUBTRACT; break;
+ default: UNREACHABLE();
+ }
+
+ return d3dBlendOp;
+}
+
+UINT8 ConvertColorMask(bool red, bool green, bool blue, bool alpha)
+{
+ UINT8 mask = 0;
+ if (red)
+ {
+ mask |= D3D11_COLOR_WRITE_ENABLE_RED;
+ }
+ if (green)
+ {
+ mask |= D3D11_COLOR_WRITE_ENABLE_GREEN;
+ }
+ if (blue)
+ {
+ mask |= D3D11_COLOR_WRITE_ENABLE_BLUE;
+ }
+ if (alpha)
+ {
+ mask |= D3D11_COLOR_WRITE_ENABLE_ALPHA;
+ }
+ return mask;
+}
+
+D3D11_CULL_MODE ConvertCullMode(bool cullEnabled, GLenum cullMode)
+{
+ D3D11_CULL_MODE cull = D3D11_CULL_NONE;
+
+ if (cullEnabled)
+ {
+ switch (cullMode)
+ {
+ case GL_FRONT: cull = D3D11_CULL_FRONT; break;
+ case GL_BACK: cull = D3D11_CULL_BACK; break;
+ case GL_FRONT_AND_BACK: cull = D3D11_CULL_NONE; break;
+ default: UNREACHABLE();
+ }
+ }
+ else
+ {
+ cull = D3D11_CULL_NONE;
+ }
+
+ return cull;
+}
+
+D3D11_COMPARISON_FUNC ConvertComparison(GLenum comparison)
+{
+ D3D11_COMPARISON_FUNC d3dComp = D3D11_COMPARISON_NEVER;
+ switch (comparison)
+ {
+ case GL_NEVER: d3dComp = D3D11_COMPARISON_NEVER; break;
+ case GL_ALWAYS: d3dComp = D3D11_COMPARISON_ALWAYS; break;
+ case GL_LESS: d3dComp = D3D11_COMPARISON_LESS; break;
+ case GL_LEQUAL: d3dComp = D3D11_COMPARISON_LESS_EQUAL; break;
+ case GL_EQUAL: d3dComp = D3D11_COMPARISON_EQUAL; break;
+ case GL_GREATER: d3dComp = D3D11_COMPARISON_GREATER; break;
+ case GL_GEQUAL: d3dComp = D3D11_COMPARISON_GREATER_EQUAL; break;
+ case GL_NOTEQUAL: d3dComp = D3D11_COMPARISON_NOT_EQUAL; break;
+ default: UNREACHABLE();
+ }
+
+ return d3dComp;
+}
+
+D3D11_DEPTH_WRITE_MASK ConvertDepthMask(bool depthWriteEnabled)
+{
+ return depthWriteEnabled ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;
+}
+
+UINT8 ConvertStencilMask(GLuint stencilmask)
+{
+ return static_cast<UINT8>(stencilmask);
+}
+
+D3D11_STENCIL_OP ConvertStencilOp(GLenum stencilOp)
+{
+ D3D11_STENCIL_OP d3dStencilOp = D3D11_STENCIL_OP_KEEP;
+
+ switch (stencilOp)
+ {
+ case GL_ZERO: d3dStencilOp = D3D11_STENCIL_OP_ZERO; break;
+ case GL_KEEP: d3dStencilOp = D3D11_STENCIL_OP_KEEP; break;
+ case GL_REPLACE: d3dStencilOp = D3D11_STENCIL_OP_REPLACE; break;
+ case GL_INCR: d3dStencilOp = D3D11_STENCIL_OP_INCR_SAT; break;
+ case GL_DECR: d3dStencilOp = D3D11_STENCIL_OP_DECR_SAT; break;
+ case GL_INVERT: d3dStencilOp = D3D11_STENCIL_OP_INVERT; break;
+ case GL_INCR_WRAP: d3dStencilOp = D3D11_STENCIL_OP_INCR; break;
+ case GL_DECR_WRAP: d3dStencilOp = D3D11_STENCIL_OP_DECR; break;
+ default: UNREACHABLE();
+ }
+
+ return d3dStencilOp;
+}
+
+D3D11_FILTER ConvertFilter(GLenum minFilter, GLenum magFilter, float maxAnisotropy)
+{
+ if (maxAnisotropy > 1.0f)
+ {
+ return D3D11_ENCODE_ANISOTROPIC_FILTER(false);
+ }
+ else
+ {
+ D3D11_FILTER_TYPE dxMin = D3D11_FILTER_TYPE_POINT;
+ D3D11_FILTER_TYPE dxMip = D3D11_FILTER_TYPE_POINT;
+ switch (minFilter)
+ {
+ case GL_NEAREST: dxMin = D3D11_FILTER_TYPE_POINT; dxMip = D3D11_FILTER_TYPE_POINT; break;
+ case GL_LINEAR: dxMin = D3D11_FILTER_TYPE_LINEAR; dxMip = D3D11_FILTER_TYPE_POINT; break;
+ case GL_NEAREST_MIPMAP_NEAREST: dxMin = D3D11_FILTER_TYPE_POINT; dxMip = D3D11_FILTER_TYPE_POINT; break;
+ case GL_LINEAR_MIPMAP_NEAREST: dxMin = D3D11_FILTER_TYPE_LINEAR; dxMip = D3D11_FILTER_TYPE_POINT; break;
+ case GL_NEAREST_MIPMAP_LINEAR: dxMin = D3D11_FILTER_TYPE_POINT; dxMip = D3D11_FILTER_TYPE_LINEAR; break;
+ case GL_LINEAR_MIPMAP_LINEAR: dxMin = D3D11_FILTER_TYPE_LINEAR; dxMip = D3D11_FILTER_TYPE_LINEAR; break;
+ default: UNREACHABLE();
+ }
+
+ D3D11_FILTER_TYPE dxMag = D3D11_FILTER_TYPE_POINT;
+ switch (magFilter)
+ {
+ case GL_NEAREST: dxMag = D3D11_FILTER_TYPE_POINT; break;
+ case GL_LINEAR: dxMag = D3D11_FILTER_TYPE_LINEAR; break;
+ default: UNREACHABLE();
+ }
+
+ return D3D11_ENCODE_BASIC_FILTER(dxMin, dxMag, dxMip, false);
+ }
+}
+
+D3D11_TEXTURE_ADDRESS_MODE ConvertTextureWrap(GLenum wrap)
+{
+ switch (wrap)
+ {
+ case GL_REPEAT: return D3D11_TEXTURE_ADDRESS_WRAP;
+ case GL_CLAMP_TO_EDGE: return D3D11_TEXTURE_ADDRESS_CLAMP;
+ case GL_MIRRORED_REPEAT: return D3D11_TEXTURE_ADDRESS_MIRROR;
+ default: UNREACHABLE();
+ }
+
+ return D3D11_TEXTURE_ADDRESS_WRAP;
+}
+
+FLOAT ConvertMinLOD(GLenum minFilter, unsigned int lodOffset)
+{
+ return (minFilter == GL_NEAREST || minFilter == GL_LINEAR) ? static_cast<float>(lodOffset) : -FLT_MAX;
+}
+
+FLOAT ConvertMaxLOD(GLenum minFilter, unsigned int lodOffset)
+{
+ return (minFilter == GL_NEAREST || minFilter == GL_LINEAR) ? static_cast<float>(lodOffset) : FLT_MAX;
+}
+
+}
+
+namespace d3d11_gl
+{
+
+GLenum ConvertBackBufferFormat(DXGI_FORMAT format)
+{
+ switch (format)
+ {
+ case DXGI_FORMAT_R8G8B8A8_UNORM: return GL_RGBA8_OES;
+ case DXGI_FORMAT_B8G8R8A8_UNORM: return GL_BGRA8_EXT;
+ default:
+ UNREACHABLE();
+ }
+
+ return GL_RGBA8_OES;
+}
+
+GLenum ConvertDepthStencilFormat(DXGI_FORMAT format)
+{
+ switch (format)
+ {
+ case DXGI_FORMAT_UNKNOWN: return GL_NONE;
+ case DXGI_FORMAT_D16_UNORM: return GL_DEPTH_COMPONENT16;
+ case DXGI_FORMAT_D24_UNORM_S8_UINT: return GL_DEPTH24_STENCIL8_OES;
+ default:
+ UNREACHABLE();
+ }
+
+ return GL_DEPTH24_STENCIL8_OES;
+}
+
+GLenum ConvertRenderbufferFormat(DXGI_FORMAT format)
+{
+ switch (format)
+ {
+ case DXGI_FORMAT_B8G8R8A8_UNORM:
+ return GL_BGRA8_EXT;
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ return GL_RGBA8_OES;
+ case DXGI_FORMAT_D16_UNORM:
+ return GL_DEPTH_COMPONENT16;
+ case DXGI_FORMAT_D24_UNORM_S8_UINT:
+ return GL_DEPTH24_STENCIL8_OES;
+ default:
+ UNREACHABLE();
+ }
+
+ return GL_RGBA8_OES;
+}
+
+GLenum ConvertTextureInternalFormat(DXGI_FORMAT format)
+{
+ switch (format)
+ {
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ return GL_RGBA8_OES;
+ case DXGI_FORMAT_A8_UNORM:
+ return GL_ALPHA8_EXT;
+ case DXGI_FORMAT_BC1_UNORM:
+ return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
+ case DXGI_FORMAT_BC2_UNORM:
+ return GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE;
+ case DXGI_FORMAT_BC3_UNORM:
+ return GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE;
+ case DXGI_FORMAT_R32G32B32A32_FLOAT:
+ return GL_RGBA32F_EXT;
+ case DXGI_FORMAT_R32G32B32_FLOAT:
+ return GL_RGB32F_EXT;
+ case DXGI_FORMAT_R16G16B16A16_FLOAT:
+ return GL_RGBA16F_EXT;
+ case DXGI_FORMAT_B8G8R8A8_UNORM:
+ return GL_BGRA8_EXT;
+ case DXGI_FORMAT_R8_UNORM:
+ return GL_R8_EXT;
+ case DXGI_FORMAT_R8G8_UNORM:
+ return GL_RG8_EXT;
+ case DXGI_FORMAT_R16_FLOAT:
+ return GL_R16F_EXT;
+ case DXGI_FORMAT_R16G16_FLOAT:
+ return GL_RG16F_EXT;
+ case DXGI_FORMAT_D16_UNORM:
+ return GL_DEPTH_COMPONENT16;
+ case DXGI_FORMAT_D24_UNORM_S8_UINT:
+ return GL_DEPTH24_STENCIL8_OES;
+ case DXGI_FORMAT_UNKNOWN:
+ return GL_NONE;
+ default:
+ UNREACHABLE();
+ }
+
+ return GL_RGBA8_OES;
+}
+
+}
+
+namespace gl_d3d11
+{
+
+DXGI_FORMAT ConvertRenderbufferFormat(GLenum format)
+{
+ switch (format)
+ {
+ case GL_RGBA4:
+ case GL_RGB5_A1:
+ case GL_RGBA8_OES:
+ case GL_RGB565:
+ case GL_RGB8_OES:
+ return DXGI_FORMAT_R8G8B8A8_UNORM;
+ case GL_BGRA8_EXT:
+ return DXGI_FORMAT_B8G8R8A8_UNORM;
+ case GL_DEPTH_COMPONENT16:
+ return DXGI_FORMAT_D16_UNORM;
+ case GL_STENCIL_INDEX8:
+ case GL_DEPTH24_STENCIL8_OES:
+ return DXGI_FORMAT_D24_UNORM_S8_UINT;
+ default:
+ UNREACHABLE();
+ }
+
+ return DXGI_FORMAT_R8G8B8A8_UNORM;
+}
+
+DXGI_FORMAT ConvertTextureFormat(GLenum internalformat)
+{
+ switch (internalformat)
+ {
+ case GL_RGB565:
+ case GL_RGBA4:
+ case GL_RGB5_A1:
+ case GL_RGB8_OES:
+ case GL_RGBA8_OES:
+ case GL_LUMINANCE8_EXT:
+ case GL_LUMINANCE8_ALPHA8_EXT:
+ return DXGI_FORMAT_R8G8B8A8_UNORM;
+ case GL_ALPHA8_EXT:
+ return DXGI_FORMAT_A8_UNORM;
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ return DXGI_FORMAT_BC1_UNORM;
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+ return DXGI_FORMAT_BC2_UNORM;
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+ return DXGI_FORMAT_BC3_UNORM;
+ case GL_RGBA32F_EXT:
+ case GL_ALPHA32F_EXT:
+ case GL_LUMINANCE_ALPHA32F_EXT:
+ return DXGI_FORMAT_R32G32B32A32_FLOAT;
+ case GL_RGB32F_EXT:
+ case GL_LUMINANCE32F_EXT:
+ return DXGI_FORMAT_R32G32B32A32_FLOAT;
+ case GL_RGBA16F_EXT:
+ case GL_ALPHA16F_EXT:
+ case GL_LUMINANCE_ALPHA16F_EXT:
+ case GL_RGB16F_EXT:
+ case GL_LUMINANCE16F_EXT:
+ return DXGI_FORMAT_R16G16B16A16_FLOAT;
+ case GL_BGRA8_EXT:
+ return DXGI_FORMAT_B8G8R8A8_UNORM;
+ case GL_R8_EXT:
+ return DXGI_FORMAT_R8_UNORM;
+ case GL_RG8_EXT:
+ return DXGI_FORMAT_R8G8_UNORM;
+ case GL_R16F_EXT:
+ return DXGI_FORMAT_R16_FLOAT;
+ case GL_RG16F_EXT:
+ return DXGI_FORMAT_R16G16_FLOAT;
+ case GL_DEPTH_COMPONENT16:
+ return DXGI_FORMAT_D16_UNORM;
+ case GL_DEPTH_COMPONENT32_OES:
+ case GL_DEPTH24_STENCIL8_OES:
+ return DXGI_FORMAT_D24_UNORM_S8_UINT;
+ case GL_NONE:
+ return DXGI_FORMAT_UNKNOWN;
+ default:
+ UNREACHABLE();
+ }
+
+ return DXGI_FORMAT_R8G8B8A8_UNORM;
+}
+
+}
+
+namespace d3d11
+{
+
+void SetPositionTexCoordVertex(PositionTexCoordVertex* vertex, float x, float y, float u, float v)
+{
+ vertex->x = x;
+ vertex->y = y;
+ vertex->u = u;
+ vertex->v = v;
+}
+
+void SetPositionDepthColorVertex(PositionDepthColorVertex* vertex, float x, float y, float z,
+ const gl::Color &color)
+{
+ vertex->x = x;
+ vertex->y = y;
+ vertex->z = z;
+ vertex->r = color.red;
+ vertex->g = color.green;
+ vertex->b = color.blue;
+ vertex->a = color.alpha;
+}
+
+size_t ComputePixelSizeBits(DXGI_FORMAT format)
+{
+ switch (format)
+ {
+ case DXGI_FORMAT_R1_UNORM:
+ return 1;
+
+ case DXGI_FORMAT_A8_UNORM:
+ case DXGI_FORMAT_R8_SINT:
+ case DXGI_FORMAT_R8_SNORM:
+ case DXGI_FORMAT_R8_TYPELESS:
+ case DXGI_FORMAT_R8_UINT:
+ case DXGI_FORMAT_R8_UNORM:
+ return 8;
+
+ case DXGI_FORMAT_B5G5R5A1_UNORM:
+ case DXGI_FORMAT_B5G6R5_UNORM:
+ case DXGI_FORMAT_D16_UNORM:
+ case DXGI_FORMAT_R16_FLOAT:
+ case DXGI_FORMAT_R16_SINT:
+ case DXGI_FORMAT_R16_SNORM:
+ case DXGI_FORMAT_R16_TYPELESS:
+ case DXGI_FORMAT_R16_UINT:
+ case DXGI_FORMAT_R16_UNORM:
+ case DXGI_FORMAT_R8G8_SINT:
+ case DXGI_FORMAT_R8G8_SNORM:
+ case DXGI_FORMAT_R8G8_TYPELESS:
+ case DXGI_FORMAT_R8G8_UINT:
+ case DXGI_FORMAT_R8G8_UNORM:
+ return 16;
+
+ case DXGI_FORMAT_B8G8R8X8_TYPELESS:
+ case DXGI_FORMAT_B8G8R8X8_UNORM:
+ case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
+ case DXGI_FORMAT_D24_UNORM_S8_UINT:
+ case DXGI_FORMAT_D32_FLOAT:
+ case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
+ case DXGI_FORMAT_G8R8_G8B8_UNORM:
+ case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
+ case DXGI_FORMAT_R10G10B10A2_TYPELESS:
+ case DXGI_FORMAT_R10G10B10A2_UINT:
+ case DXGI_FORMAT_R10G10B10A2_UNORM:
+ case DXGI_FORMAT_R11G11B10_FLOAT:
+ case DXGI_FORMAT_R16G16_FLOAT:
+ case DXGI_FORMAT_R16G16_SINT:
+ case DXGI_FORMAT_R16G16_SNORM:
+ case DXGI_FORMAT_R16G16_TYPELESS:
+ case DXGI_FORMAT_R16G16_UINT:
+ case DXGI_FORMAT_R16G16_UNORM:
+ case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
+ case DXGI_FORMAT_R24G8_TYPELESS:
+ case DXGI_FORMAT_R32_FLOAT:
+ case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
+ case DXGI_FORMAT_R32_SINT:
+ case DXGI_FORMAT_R32_TYPELESS:
+ case DXGI_FORMAT_R32_UINT:
+ case DXGI_FORMAT_R8G8_B8G8_UNORM:
+ case DXGI_FORMAT_R8G8B8A8_SINT:
+ case DXGI_FORMAT_R8G8B8A8_SNORM:
+ case DXGI_FORMAT_R8G8B8A8_TYPELESS:
+ case DXGI_FORMAT_R8G8B8A8_UINT:
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+ case DXGI_FORMAT_B8G8R8A8_TYPELESS:
+ case DXGI_FORMAT_B8G8R8A8_UNORM:
+ case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
+ case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
+ case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
+ case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
+ return 32;
+
+ case DXGI_FORMAT_R16G16B16A16_FLOAT:
+ case DXGI_FORMAT_R16G16B16A16_SINT:
+ case DXGI_FORMAT_R16G16B16A16_SNORM:
+ case DXGI_FORMAT_R16G16B16A16_TYPELESS:
+ case DXGI_FORMAT_R16G16B16A16_UINT:
+ case DXGI_FORMAT_R16G16B16A16_UNORM:
+ case DXGI_FORMAT_R32G32_FLOAT:
+ case DXGI_FORMAT_R32G32_SINT:
+ case DXGI_FORMAT_R32G32_TYPELESS:
+ case DXGI_FORMAT_R32G32_UINT:
+ case DXGI_FORMAT_R32G8X24_TYPELESS:
+ return 64;
+
+ case DXGI_FORMAT_R32G32B32_FLOAT:
+ case DXGI_FORMAT_R32G32B32_SINT:
+ case DXGI_FORMAT_R32G32B32_TYPELESS:
+ case DXGI_FORMAT_R32G32B32_UINT:
+ return 96;
+
+ case DXGI_FORMAT_R32G32B32A32_FLOAT:
+ case DXGI_FORMAT_R32G32B32A32_SINT:
+ case DXGI_FORMAT_R32G32B32A32_TYPELESS:
+ case DXGI_FORMAT_R32G32B32A32_UINT:
+ return 128;
+
+ case DXGI_FORMAT_BC1_TYPELESS:
+ case DXGI_FORMAT_BC1_UNORM:
+ case DXGI_FORMAT_BC1_UNORM_SRGB:
+ case DXGI_FORMAT_BC4_SNORM:
+ case DXGI_FORMAT_BC4_TYPELESS:
+ case DXGI_FORMAT_BC4_UNORM:
+ return 4;
+
+ case DXGI_FORMAT_BC2_TYPELESS:
+ case DXGI_FORMAT_BC2_UNORM:
+ case DXGI_FORMAT_BC2_UNORM_SRGB:
+ case DXGI_FORMAT_BC3_TYPELESS:
+ case DXGI_FORMAT_BC3_UNORM:
+ case DXGI_FORMAT_BC3_UNORM_SRGB:
+ case DXGI_FORMAT_BC5_SNORM:
+ case DXGI_FORMAT_BC5_TYPELESS:
+ case DXGI_FORMAT_BC5_UNORM:
+ case DXGI_FORMAT_BC6H_SF16:
+ case DXGI_FORMAT_BC6H_TYPELESS:
+ case DXGI_FORMAT_BC6H_UF16:
+ case DXGI_FORMAT_BC7_TYPELESS:
+ case DXGI_FORMAT_BC7_UNORM:
+ case DXGI_FORMAT_BC7_UNORM_SRGB:
+ return 8;
+
+ default:
+ return 0;
+ }
+}
+
+size_t ComputeBlockSizeBits(DXGI_FORMAT format)
+{
+ switch (format)
+ {
+ case DXGI_FORMAT_BC1_TYPELESS:
+ case DXGI_FORMAT_BC1_UNORM:
+ case DXGI_FORMAT_BC1_UNORM_SRGB:
+ case DXGI_FORMAT_BC4_SNORM:
+ case DXGI_FORMAT_BC4_TYPELESS:
+ case DXGI_FORMAT_BC4_UNORM:
+ case DXGI_FORMAT_BC2_TYPELESS:
+ case DXGI_FORMAT_BC2_UNORM:
+ case DXGI_FORMAT_BC2_UNORM_SRGB:
+ case DXGI_FORMAT_BC3_TYPELESS:
+ case DXGI_FORMAT_BC3_UNORM:
+ case DXGI_FORMAT_BC3_UNORM_SRGB:
+ case DXGI_FORMAT_BC5_SNORM:
+ case DXGI_FORMAT_BC5_TYPELESS:
+ case DXGI_FORMAT_BC5_UNORM:
+ case DXGI_FORMAT_BC6H_SF16:
+ case DXGI_FORMAT_BC6H_TYPELESS:
+ case DXGI_FORMAT_BC6H_UF16:
+ case DXGI_FORMAT_BC7_TYPELESS:
+ case DXGI_FORMAT_BC7_UNORM:
+ case DXGI_FORMAT_BC7_UNORM_SRGB:
+ return ComputePixelSizeBits(format) * 16;
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+bool IsCompressed(DXGI_FORMAT format)
+{
+ switch (format)
+ {
+ case DXGI_FORMAT_BC1_TYPELESS:
+ case DXGI_FORMAT_BC1_UNORM:
+ case DXGI_FORMAT_BC1_UNORM_SRGB:
+ case DXGI_FORMAT_BC4_SNORM:
+ case DXGI_FORMAT_BC4_TYPELESS:
+ case DXGI_FORMAT_BC4_UNORM:
+ case DXGI_FORMAT_BC2_TYPELESS:
+ case DXGI_FORMAT_BC2_UNORM:
+ case DXGI_FORMAT_BC2_UNORM_SRGB:
+ case DXGI_FORMAT_BC3_TYPELESS:
+ case DXGI_FORMAT_BC3_UNORM:
+ case DXGI_FORMAT_BC3_UNORM_SRGB:
+ case DXGI_FORMAT_BC5_SNORM:
+ case DXGI_FORMAT_BC5_TYPELESS:
+ case DXGI_FORMAT_BC5_UNORM:
+ case DXGI_FORMAT_BC6H_SF16:
+ case DXGI_FORMAT_BC6H_TYPELESS:
+ case DXGI_FORMAT_BC6H_UF16:
+ case DXGI_FORMAT_BC7_TYPELESS:
+ case DXGI_FORMAT_BC7_UNORM:
+ case DXGI_FORMAT_BC7_UNORM_SRGB:
+ return true;
+ case DXGI_FORMAT_UNKNOWN:
+ UNREACHABLE();
+ return false;
+ default:
+ return false;
+ }
+}
+
+unsigned int GetTextureFormatDimensionAlignment(DXGI_FORMAT format)
+{
+ switch (format)
+ {
+ case DXGI_FORMAT_BC1_TYPELESS:
+ case DXGI_FORMAT_BC1_UNORM:
+ case DXGI_FORMAT_BC1_UNORM_SRGB:
+ case DXGI_FORMAT_BC4_SNORM:
+ case DXGI_FORMAT_BC4_TYPELESS:
+ case DXGI_FORMAT_BC4_UNORM:
+ case DXGI_FORMAT_BC2_TYPELESS:
+ case DXGI_FORMAT_BC2_UNORM:
+ case DXGI_FORMAT_BC2_UNORM_SRGB:
+ case DXGI_FORMAT_BC3_TYPELESS:
+ case DXGI_FORMAT_BC3_UNORM:
+ case DXGI_FORMAT_BC3_UNORM_SRGB:
+ case DXGI_FORMAT_BC5_SNORM:
+ case DXGI_FORMAT_BC5_TYPELESS:
+ case DXGI_FORMAT_BC5_UNORM:
+ case DXGI_FORMAT_BC6H_SF16:
+ case DXGI_FORMAT_BC6H_TYPELESS:
+ case DXGI_FORMAT_BC6H_UF16:
+ case DXGI_FORMAT_BC7_TYPELESS:
+ case DXGI_FORMAT_BC7_UNORM:
+ case DXGI_FORMAT_BC7_UNORM_SRGB:
+ return 4;
+ case DXGI_FORMAT_UNKNOWN:
+ UNREACHABLE();
+ return 1;
+ default:
+ return 1;
+ }
+}
+
+bool IsDepthStencilFormat(DXGI_FORMAT format)
+{
+ switch (format)
+ {
+ case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
+ case DXGI_FORMAT_D32_FLOAT:
+ case DXGI_FORMAT_D24_UNORM_S8_UINT:
+ case DXGI_FORMAT_D16_UNORM:
+ return true;
+ default:
+ return false;
+ }
+}
+
+DXGI_FORMAT GetDepthTextureFormat(DXGI_FORMAT format)
+{
+ switch (format)
+ {
+ case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: return DXGI_FORMAT_R32G8X24_TYPELESS;
+ case DXGI_FORMAT_D32_FLOAT: return DXGI_FORMAT_R32_TYPELESS;
+ case DXGI_FORMAT_D24_UNORM_S8_UINT: return DXGI_FORMAT_R24G8_TYPELESS;
+ case DXGI_FORMAT_D16_UNORM: return DXGI_FORMAT_R16_TYPELESS;
+ default: UNREACHABLE(); return DXGI_FORMAT_UNKNOWN;
+ }
+}
+
+DXGI_FORMAT GetDepthShaderResourceFormat(DXGI_FORMAT format)
+{
+ switch (format)
+ {
+ case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: return DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS;
+ case DXGI_FORMAT_D32_FLOAT: return DXGI_FORMAT_R32_UINT;
+ case DXGI_FORMAT_D24_UNORM_S8_UINT: return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
+ case DXGI_FORMAT_D16_UNORM: return DXGI_FORMAT_R16_UNORM;
+ default: UNREACHABLE(); return DXGI_FORMAT_UNKNOWN;
+ }
+}
+
+HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name)
+{
+#if defined(_DEBUG)
+ return resource->SetPrivateData(WKPDID_D3DDebugObjectName, strlen(name), name);
+#else
+ return S_OK;
+#endif
+}
+
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/renderer11_utils.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11renderer11_utilsh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/renderer11_utils.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/renderer11_utils.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/renderer11_utils.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,95 @@
</span><ins>+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// renderer11_utils.h: Conversion functions and other utility routines
+// specific to the D3D11 renderer.
+
+#ifndef LIBGLESV2_RENDERER_RENDERER11_UTILS_H
+#define LIBGLESV2_RENDERER_RENDERER11_UTILS_H
+
+#include "libGLESv2/angletypes.h"
+
+namespace gl_d3d11
+{
+
+D3D11_BLEND ConvertBlendFunc(GLenum glBlend, bool isAlpha);
+D3D11_BLEND_OP ConvertBlendOp(GLenum glBlendOp);
+UINT8 ConvertColorMask(bool maskRed, bool maskGreen, bool maskBlue, bool maskAlpha);
+
+D3D11_CULL_MODE ConvertCullMode(bool cullEnabled, GLenum cullMode);
+
+D3D11_COMPARISON_FUNC ConvertComparison(GLenum comparison);
+D3D11_DEPTH_WRITE_MASK ConvertDepthMask(bool depthWriteEnabled);
+UINT8 ConvertStencilMask(GLuint stencilmask);
+D3D11_STENCIL_OP ConvertStencilOp(GLenum stencilOp);
+
+D3D11_FILTER ConvertFilter(GLenum minFilter, GLenum magFilter, float maxAnisotropy);
+D3D11_TEXTURE_ADDRESS_MODE ConvertTextureWrap(GLenum wrap);
+FLOAT ConvertMinLOD(GLenum minFilter, unsigned int lodOffset);
+FLOAT ConvertMaxLOD(GLenum minFilter, unsigned int lodOffset);
+
+DXGI_FORMAT ConvertRenderbufferFormat(GLenum format);
+DXGI_FORMAT ConvertTextureFormat(GLenum format);
+}
+
+namespace d3d11_gl
+{
+
+GLenum ConvertBackBufferFormat(DXGI_FORMAT format);
+GLenum ConvertDepthStencilFormat(DXGI_FORMAT format);
+GLenum ConvertRenderbufferFormat(DXGI_FORMAT format);
+GLenum ConvertTextureInternalFormat(DXGI_FORMAT format);
+
+}
+
+namespace d3d11
+{
+
+struct PositionTexCoordVertex
+{
+ float x, y;
+ float u, v;
+};
+void SetPositionTexCoordVertex(PositionTexCoordVertex* vertex, float x, float y, float u, float v);
+
+struct PositionDepthColorVertex
+{
+ float x, y, z;
+ float r, g, b, a;
+};
+void SetPositionDepthColorVertex(PositionDepthColorVertex* vertex, float x, float y, float z,
+ const gl::Color &color);
+
+size_t ComputePixelSizeBits(DXGI_FORMAT format);
+size_t ComputeBlockSizeBits(DXGI_FORMAT format);
+
+bool IsCompressed(DXGI_FORMAT format);
+unsigned int GetTextureFormatDimensionAlignment(DXGI_FORMAT format);
+
+bool IsDepthStencilFormat(DXGI_FORMAT format);
+DXGI_FORMAT GetDepthTextureFormat(DXGI_FORMAT format);
+DXGI_FORMAT GetDepthShaderResourceFormat(DXGI_FORMAT format);
+
+HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name);
+
+inline bool isDeviceLostError(HRESULT errorCode)
+{
+ switch (errorCode)
+ {
+ case DXGI_ERROR_DEVICE_HUNG:
+ case DXGI_ERROR_DEVICE_REMOVED:
+ case DXGI_ERROR_DEVICE_RESET:
+ case DXGI_ERROR_DRIVER_INTERNAL_ERROR:
+ case DXGI_ERROR_NOT_CURRENTLY_AVAILABLE:
+ return true;
+ default:
+ return false;
+ }
+}
+
+}
+
+#endif // LIBGLESV2_RENDERER_RENDERER11_UTILS_H
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/renderer11_utils.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11shadersClear11hlsl"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/Clear11.hlsl (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/Clear11.hlsl         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/Clear11.hlsl        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,38 @@
</span><ins>+void VS_Clear( in float3 inPosition : POSITION, in float4 inColor : COLOR,
+ out float4 outPosition : SV_POSITION, out float4 outColor : COLOR)
+{
+ outPosition = float4(inPosition, 1.0f);
+ outColor = inColor;
+}
+
+// Assume we are in SM4+, which has 8 color outputs
+struct PS_OutputMultiple
+{
+        float4 color0 : SV_TARGET0;
+        float4 color1 : SV_TARGET1;
+        float4 color2 : SV_TARGET2;
+        float4 color3 : SV_TARGET3;
+        float4 color4 : SV_TARGET4;
+        float4 color5 : SV_TARGET5;
+        float4 color6 : SV_TARGET6;
+        float4 color7 : SV_TARGET7;
+};
+
+PS_OutputMultiple PS_ClearMultiple(in float4 inPosition : SV_POSITION, in float4 inColor : COLOR)
+{
+        PS_OutputMultiple outColor;
+        outColor.color0 = inColor;
+        outColor.color1 = inColor;
+        outColor.color2 = inColor;
+        outColor.color3 = inColor;
+        outColor.color4 = inColor;
+        outColor.color5 = inColor;
+        outColor.color6 = inColor;
+        outColor.color7 = inColor;
+        return outColor;
+}
+
+float4 PS_ClearSingle(in float4 inPosition : SV_Position, in float4 inColor : COLOR) : SV_Target0
+{
+        return inColor;
+}
</ins></span></pre></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11shadersPassthrough11hlsl"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/Passthrough11.hlsl (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/Passthrough11.hlsl         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/Passthrough11.hlsl        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,29 @@
</span><ins>+Texture2D Texture : register(t0);
+SamplerState Sampler : register(s0);
+
+void VS_Passthrough( in float2 inPosition : POSITION, in float2 inTexCoord : TEXCOORD0,
+ out float4 outPosition : SV_POSITION, out float2 outTexCoord : TEXCOORD0)
+{
+ outPosition = float4(inPosition, 0.0f, 1.0f);
+ outTexCoord = inTexCoord;
+}
+
+float4 PS_PassthroughRGBA(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+ return Texture.Sample(Sampler, inTexCoord).rgba;
+}
+
+float4 PS_PassthroughRGB(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+ return float4(Texture.Sample(Sampler, inTexCoord).rgb, 1.0f);
+}
+
+float4 PS_PassthroughLum(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+ return float4(Texture.Sample(Sampler, inTexCoord).rrr, 1.0f);
+}
+
+float4 PS_PassthroughLumAlpha(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0
+{
+ return Texture.Sample(Sampler, inTexCoord).rrra;
+}
</ins></span></pre></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11shaderscompiledclear11vsh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/compiled/clear11vs.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/compiled/clear11vs.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/compiled/clear11vs.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,131 @@
</span><ins>+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 9.30.9200.16384
+//
+//
+///
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// POSITION 0 xyz 0 NONE float xyz
+// COLOR 0 xyzw 1 NONE float xyzw
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float xyzw
+// COLOR 0 xyzw 1 NONE float xyzw
+//
+vs_4_0
+dcl_input v0.xyz
+dcl_input v1.xyzw
+dcl_output_siv o0.xyzw, position
+dcl_output o1.xyzw
+mov o0.xyz, v0.xyzx
+mov o0.w, l(1.000000)
+mov o1.xyzw, v1.xyzw
+ret
+// Approximately 4 instruction slots used
+#endif
+
+const BYTE g_VS_Clear[] =
+{
+ 68, 88, 66, 67, 97, 5,
+ 13, 163, 160, 254, 95, 127,
+ 30, 194, 121, 144, 236, 185,
+ 59, 29, 1, 0, 0, 0,
+ 48, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 140, 0, 0, 0, 220, 0,
+ 0, 0, 48, 1, 0, 0,
+ 180, 1, 0, 0, 82, 68,
+ 69, 70, 80, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 254, 255, 0, 1, 0, 0,
+ 28, 0, 0, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102,
+ 116, 32, 40, 82, 41, 32,
+ 72, 76, 83, 76, 32, 83,
+ 104, 97, 100, 101, 114, 32,
+ 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 57, 46, 51,
+ 48, 46, 57, 50, 48, 48,
+ 46, 49, 54, 51, 56, 52,
+ 0, 171, 73, 83, 71, 78,
+ 72, 0, 0, 0, 2, 0,
+ 0, 0, 8, 0, 0, 0,
+ 56, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0,
+ 0, 0, 7, 7, 0, 0,
+ 65, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 1, 0,
+ 0, 0, 15, 15, 0, 0,
+ 80, 79, 83, 73, 84, 73,
+ 79, 78, 0, 67, 79, 76,
+ 79, 82, 0, 171, 79, 83,
+ 71, 78, 76, 0, 0, 0,
+ 2, 0, 0, 0, 8, 0,
+ 0, 0, 56, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0,
+ 0, 0, 68, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0,
+ 1, 0, 0, 0, 15, 0,
+ 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79,
+ 78, 0, 67, 79, 76, 79,
+ 82, 0, 171, 171, 83, 72,
+ 68, 82, 124, 0, 0, 0,
+ 64, 0, 1, 0, 31, 0,
+ 0, 0, 95, 0, 0, 3,
+ 114, 16, 16, 0, 0, 0,
+ 0, 0, 95, 0, 0, 3,
+ 242, 16, 16, 0, 1, 0,
+ 0, 0, 103, 0, 0, 4,
+ 242, 32, 16, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 101, 0, 0, 3, 242, 32,
+ 16, 0, 1, 0, 0, 0,
+ 54, 0, 0, 5, 114, 32,
+ 16, 0, 0, 0, 0, 0,
+ 70, 18, 16, 0, 0, 0,
+ 0, 0, 54, 0, 0, 5,
+ 130, 32, 16, 0, 0, 0,
+ 0, 0, 1, 64, 0, 0,
+ 0, 0, 128, 63, 54, 0,
+ 0, 5, 242, 32, 16, 0,
+ 1, 0, 0, 0, 70, 30,
+ 16, 0, 1, 0, 0, 0,
+ 62, 0, 0, 1, 83, 84,
+ 65, 84, 116, 0, 0, 0,
+ 4, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 4, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 4, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0
+};
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/compiled/clear11vs.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11shaderscompiledclearmultiple11psh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/compiled/clearmultiple11ps.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/compiled/clearmultiple11ps.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/compiled/clearmultiple11ps.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,196 @@
</span><ins>+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 9.30.9200.16384
+//
+//
+///
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// COLOR 0 xyzw 1 NONE float xyzw
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+// SV_TARGET 1 xyzw 1 TARGET float xyzw
+// SV_TARGET 2 xyzw 2 TARGET float xyzw
+// SV_TARGET 3 xyzw 3 TARGET float xyzw
+// SV_TARGET 4 xyzw 4 TARGET float xyzw
+// SV_TARGET 5 xyzw 5 TARGET float xyzw
+// SV_TARGET 6 xyzw 6 TARGET float xyzw
+// SV_TARGET 7 xyzw 7 TARGET float xyzw
+//
+ps_4_0
+dcl_input_ps linear v1.xyzw
+dcl_output o0.xyzw
+dcl_output o1.xyzw
+dcl_output o2.xyzw
+dcl_output o3.xyzw
+dcl_output o4.xyzw
+dcl_output o5.xyzw
+dcl_output o6.xyzw
+dcl_output o7.xyzw
+mov o0.xyzw, v1.xyzw
+mov o1.xyzw, v1.xyzw
+mov o2.xyzw, v1.xyzw
+mov o3.xyzw, v1.xyzw
+mov o4.xyzw, v1.xyzw
+mov o5.xyzw, v1.xyzw
+mov o6.xyzw, v1.xyzw
+mov o7.xyzw, v1.xyzw
+ret
+// Approximately 9 instruction slots used
+#endif
+
+const BYTE g_PS_ClearMultiple[] =
+{
+ 68, 88, 66, 67, 92, 54,
+ 120, 105, 166, 196, 132, 158,
+ 209, 33, 185, 122, 8, 189,
+ 145, 114, 1, 0, 0, 0,
+ 88, 3, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 140, 0, 0, 0, 224, 0,
+ 0, 0, 188, 1, 0, 0,
+ 220, 2, 0, 0, 82, 68,
+ 69, 70, 80, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 255, 255, 0, 1, 0, 0,
+ 28, 0, 0, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102,
+ 116, 32, 40, 82, 41, 32,
+ 72, 76, 83, 76, 32, 83,
+ 104, 97, 100, 101, 114, 32,
+ 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 57, 46, 51,
+ 48, 46, 57, 50, 48, 48,
+ 46, 49, 54, 51, 56, 52,
+ 0, 171, 73, 83, 71, 78,
+ 76, 0, 0, 0, 2, 0,
+ 0, 0, 8, 0, 0, 0,
+ 56, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0,
+ 68, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 1, 0,
+ 0, 0, 15, 15, 0, 0,
+ 83, 86, 95, 80, 79, 83,
+ 73, 84, 73, 79, 78, 0,
+ 67, 79, 76, 79, 82, 0,
+ 171, 171, 79, 83, 71, 78,
+ 212, 0, 0, 0, 8, 0,
+ 0, 0, 8, 0, 0, 0,
+ 200, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0,
+ 200, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 1, 0,
+ 0, 0, 15, 0, 0, 0,
+ 200, 0, 0, 0, 2, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 2, 0,
+ 0, 0, 15, 0, 0, 0,
+ 200, 0, 0, 0, 3, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 3, 0,
+ 0, 0, 15, 0, 0, 0,
+ 200, 0, 0, 0, 4, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 4, 0,
+ 0, 0, 15, 0, 0, 0,
+ 200, 0, 0, 0, 5, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 5, 0,
+ 0, 0, 15, 0, 0, 0,
+ 200, 0, 0, 0, 6, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 6, 0,
+ 0, 0, 15, 0, 0, 0,
+ 200, 0, 0, 0, 7, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 7, 0,
+ 0, 0, 15, 0, 0, 0,
+ 83, 86, 95, 84, 65, 82,
+ 71, 69, 84, 0, 171, 171,
+ 83, 72, 68, 82, 24, 1,
+ 0, 0, 64, 0, 0, 0,
+ 70, 0, 0, 0, 98, 16,
+ 0, 3, 242, 16, 16, 0,
+ 1, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 0, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 1, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 2, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 3, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 4, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 5, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 6, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 7, 0, 0, 0, 54, 0,
+ 0, 5, 242, 32, 16, 0,
+ 0, 0, 0, 0, 70, 30,
+ 16, 0, 1, 0, 0, 0,
+ 54, 0, 0, 5, 242, 32,
+ 16, 0, 1, 0, 0, 0,
+ 70, 30, 16, 0, 1, 0,
+ 0, 0, 54, 0, 0, 5,
+ 242, 32, 16, 0, 2, 0,
+ 0, 0, 70, 30, 16, 0,
+ 1, 0, 0, 0, 54, 0,
+ 0, 5, 242, 32, 16, 0,
+ 3, 0, 0, 0, 70, 30,
+ 16, 0, 1, 0, 0, 0,
+ 54, 0, 0, 5, 242, 32,
+ 16, 0, 4, 0, 0, 0,
+ 70, 30, 16, 0, 1, 0,
+ 0, 0, 54, 0, 0, 5,
+ 242, 32, 16, 0, 5, 0,
+ 0, 0, 70, 30, 16, 0,
+ 1, 0, 0, 0, 54, 0,
+ 0, 5, 242, 32, 16, 0,
+ 6, 0, 0, 0, 70, 30,
+ 16, 0, 1, 0, 0, 0,
+ 54, 0, 0, 5, 242, 32,
+ 16, 0, 7, 0, 0, 0,
+ 70, 30, 16, 0, 1, 0,
+ 0, 0, 62, 0, 0, 1,
+ 83, 84, 65, 84, 116, 0,
+ 0, 0, 9, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 9, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 9, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0
+};
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/compiled/clearmultiple11ps.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11shaderscompiledclearsingle11psh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/compiled/clearsingle11ps.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/compiled/clearsingle11ps.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/compiled/clearsingle11ps.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,110 @@
</span><ins>+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 9.30.9200.16384
+//
+//
+///
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Position 0 xyzw 0 POS float
+// COLOR 0 xyzw 1 NONE float xyzw
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Target 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_input_ps linear v1.xyzw
+dcl_output o0.xyzw
+mov o0.xyzw, v1.xyzw
+ret
+// Approximately 2 instruction slots used
+#endif
+
+const BYTE g_PS_ClearSingle[] =
+{
+ 68, 88, 66, 67, 13, 152,
+ 32, 49, 222, 236, 92, 20,
+ 188, 71, 88, 46, 163, 241,
+ 188, 238, 1, 0, 0, 0,
+ 208, 1, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 140, 0, 0, 0, 224, 0,
+ 0, 0, 20, 1, 0, 0,
+ 84, 1, 0, 0, 82, 68,
+ 69, 70, 80, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 255, 255, 0, 1, 0, 0,
+ 28, 0, 0, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102,
+ 116, 32, 40, 82, 41, 32,
+ 72, 76, 83, 76, 32, 83,
+ 104, 97, 100, 101, 114, 32,
+ 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 57, 46, 51,
+ 48, 46, 57, 50, 48, 48,
+ 46, 49, 54, 51, 56, 52,
+ 0, 171, 73, 83, 71, 78,
+ 76, 0, 0, 0, 2, 0,
+ 0, 0, 8, 0, 0, 0,
+ 56, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0,
+ 68, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 1, 0,
+ 0, 0, 15, 15, 0, 0,
+ 83, 86, 95, 80, 111, 115,
+ 105, 116, 105, 111, 110, 0,
+ 67, 79, 76, 79, 82, 0,
+ 171, 171, 79, 83, 71, 78,
+ 44, 0, 0, 0, 1, 0,
+ 0, 0, 8, 0, 0, 0,
+ 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0,
+ 83, 86, 95, 84, 97, 114,
+ 103, 101, 116, 0, 171, 171,
+ 83, 72, 68, 82, 56, 0,
+ 0, 0, 64, 0, 0, 0,
+ 14, 0, 0, 0, 98, 16,
+ 0, 3, 242, 16, 16, 0,
+ 1, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 5, 242, 32, 16, 0,
+ 0, 0, 0, 0, 70, 30,
+ 16, 0, 1, 0, 0, 0,
+ 62, 0, 0, 1, 83, 84,
+ 65, 84, 116, 0, 0, 0,
+ 2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0
+};
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/compiled/clearsingle11ps.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11shaderscompiledpassthrough11vsh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/compiled/passthrough11vs.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/compiled/passthrough11vs.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/compiled/passthrough11vs.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,134 @@
</span><ins>+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 9.30.9200.16384
+//
+//
+///
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// POSITION 0 xy 0 NONE float xy
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float xyzw
+// TEXCOORD 0 xy 1 NONE float xy
+//
+vs_4_0
+dcl_input v0.xy
+dcl_input v1.xy
+dcl_output_siv o0.xyzw, position
+dcl_output o1.xy
+mov o0.xy, v0.xyxx
+mov o0.zw, l(0,0,0,1.000000)
+mov o1.xy, v1.xyxx
+ret
+// Approximately 4 instruction slots used
+#endif
+
+const BYTE g_VS_Passthrough[] =
+{
+ 68, 88, 66, 67, 197, 214,
+ 184, 85, 240, 94, 71, 48,
+ 165, 34, 142, 233, 0, 135,
+ 193, 178, 1, 0, 0, 0,
+ 68, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 140, 0, 0, 0, 224, 0,
+ 0, 0, 56, 1, 0, 0,
+ 200, 1, 0, 0, 82, 68,
+ 69, 70, 80, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 254, 255, 0, 1, 0, 0,
+ 28, 0, 0, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102,
+ 116, 32, 40, 82, 41, 32,
+ 72, 76, 83, 76, 32, 83,
+ 104, 97, 100, 101, 114, 32,
+ 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 57, 46, 51,
+ 48, 46, 57, 50, 48, 48,
+ 46, 49, 54, 51, 56, 52,
+ 0, 171, 73, 83, 71, 78,
+ 76, 0, 0, 0, 2, 0,
+ 0, 0, 8, 0, 0, 0,
+ 56, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0,
+ 0, 0, 3, 3, 0, 0,
+ 65, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 1, 0,
+ 0, 0, 3, 3, 0, 0,
+ 80, 79, 83, 73, 84, 73,
+ 79, 78, 0, 84, 69, 88,
+ 67, 79, 79, 82, 68, 0,
+ 171, 171, 79, 83, 71, 78,
+ 80, 0, 0, 0, 2, 0,
+ 0, 0, 8, 0, 0, 0,
+ 56, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0,
+ 68, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 1, 0,
+ 0, 0, 3, 12, 0, 0,
+ 83, 86, 95, 80, 79, 83,
+ 73, 84, 73, 79, 78, 0,
+ 84, 69, 88, 67, 79, 79,
+ 82, 68, 0, 171, 171, 171,
+ 83, 72, 68, 82, 136, 0,
+ 0, 0, 64, 0, 1, 0,
+ 34, 0, 0, 0, 95, 0,
+ 0, 3, 50, 16, 16, 0,
+ 0, 0, 0, 0, 95, 0,
+ 0, 3, 50, 16, 16, 0,
+ 1, 0, 0, 0, 103, 0,
+ 0, 4, 242, 32, 16, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 101, 0, 0, 3,
+ 50, 32, 16, 0, 1, 0,
+ 0, 0, 54, 0, 0, 5,
+ 50, 32, 16, 0, 0, 0,
+ 0, 0, 70, 16, 16, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 8, 194, 32, 16, 0,
+ 0, 0, 0, 0, 2, 64,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 128, 63,
+ 54, 0, 0, 5, 50, 32,
+ 16, 0, 1, 0, 0, 0,
+ 70, 16, 16, 0, 1, 0,
+ 0, 0, 62, 0, 0, 1,
+ 83, 84, 65, 84, 116, 0,
+ 0, 0, 4, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 4, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 4, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0
+};
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/compiled/passthrough11vs.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11shaderscompiledpassthroughlum11psh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughlum11ps.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughlum11ps.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughlum11ps.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,152 @@
</span><ins>+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 9.30.9200.16384
+//
+//
+///
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Sampler sampler NA NA 0 1
+// Texture texture float4 2d 0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v1.xyxx, t0.xyzw, s0
+mov o0.xyz, r0.xxxx
+mov o0.w, l(1.000000)
+ret
+// Approximately 4 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughLum[] =
+{
+ 68, 88, 66, 67, 244, 9,
+ 213, 147, 19, 249, 70, 111,
+ 157, 92, 243, 160, 40, 144,
+ 238, 221, 1, 0, 0, 0,
+ 128, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 220, 0, 0, 0, 52, 1,
+ 0, 0, 104, 1, 0, 0,
+ 4, 2, 0, 0, 82, 68,
+ 69, 70, 160, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 255, 255, 0, 1, 0, 0,
+ 108, 0, 0, 0, 92, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0,
+ 100, 0, 0, 0, 2, 0,
+ 0, 0, 5, 0, 0, 0,
+ 4, 0, 0, 0, 255, 255,
+ 255, 255, 0, 0, 0, 0,
+ 1, 0, 0, 0, 13, 0,
+ 0, 0, 83, 97, 109, 112,
+ 108, 101, 114, 0, 84, 101,
+ 120, 116, 117, 114, 101, 0,
+ 77, 105, 99, 114, 111, 115,
+ 111, 102, 116, 32, 40, 82,
+ 41, 32, 72, 76, 83, 76,
+ 32, 83, 104, 97, 100, 101,
+ 114, 32, 67, 111, 109, 112,
+ 105, 108, 101, 114, 32, 57,
+ 46, 51, 48, 46, 57, 50,
+ 48, 48, 46, 49, 54, 51,
+ 56, 52, 0, 171, 73, 83,
+ 71, 78, 80, 0, 0, 0,
+ 2, 0, 0, 0, 8, 0,
+ 0, 0, 56, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0,
+ 0, 0, 68, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0,
+ 1, 0, 0, 0, 3, 3,
+ 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79,
+ 78, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171,
+ 171, 171, 79, 83, 71, 78,
+ 44, 0, 0, 0, 1, 0,
+ 0, 0, 8, 0, 0, 0,
+ 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0,
+ 83, 86, 95, 84, 65, 82,
+ 71, 69, 84, 0, 171, 171,
+ 83, 72, 68, 82, 148, 0,
+ 0, 0, 64, 0, 0, 0,
+ 37, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0,
+ 0, 0, 0, 0, 88, 24,
+ 0, 4, 0, 112, 16, 0,
+ 0, 0, 0, 0, 85, 85,
+ 0, 0, 98, 16, 0, 3,
+ 50, 16, 16, 0, 1, 0,
+ 0, 0, 101, 0, 0, 3,
+ 242, 32, 16, 0, 0, 0,
+ 0, 0, 104, 0, 0, 2,
+ 1, 0, 0, 0, 69, 0,
+ 0, 9, 242, 0, 16, 0,
+ 0, 0, 0, 0, 70, 16,
+ 16, 0, 1, 0, 0, 0,
+ 70, 126, 16, 0, 0, 0,
+ 0, 0, 0, 96, 16, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 5, 114, 32, 16, 0,
+ 0, 0, 0, 0, 6, 0,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 5, 130, 32,
+ 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 128, 63, 62, 0, 0, 1,
+ 83, 84, 65, 84, 116, 0,
+ 0, 0, 4, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0
+};
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughlum11ps.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11shaderscompiledpassthroughlumalpha11psh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughlumalpha11ps.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughlumalpha11ps.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughlumalpha11ps.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,148 @@
</span><ins>+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 9.30.9200.16384
+//
+//
+///
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Sampler sampler NA NA 0 1
+// Texture texture float4 2d 0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v1.xyxx, t0.xyzw, s0
+mov o0.xyzw, r0.xxxw
+ret
+// Approximately 3 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughLumAlpha[] =
+{
+ 68, 88, 66, 67, 185, 14,
+ 84, 223, 192, 42, 16, 133,
+ 46, 100, 95, 221, 183, 97,
+ 192, 23, 1, 0, 0, 0,
+ 108, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 220, 0, 0, 0, 52, 1,
+ 0, 0, 104, 1, 0, 0,
+ 240, 1, 0, 0, 82, 68,
+ 69, 70, 160, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 255, 255, 0, 1, 0, 0,
+ 108, 0, 0, 0, 92, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0,
+ 100, 0, 0, 0, 2, 0,
+ 0, 0, 5, 0, 0, 0,
+ 4, 0, 0, 0, 255, 255,
+ 255, 255, 0, 0, 0, 0,
+ 1, 0, 0, 0, 13, 0,
+ 0, 0, 83, 97, 109, 112,
+ 108, 101, 114, 0, 84, 101,
+ 120, 116, 117, 114, 101, 0,
+ 77, 105, 99, 114, 111, 115,
+ 111, 102, 116, 32, 40, 82,
+ 41, 32, 72, 76, 83, 76,
+ 32, 83, 104, 97, 100, 101,
+ 114, 32, 67, 111, 109, 112,
+ 105, 108, 101, 114, 32, 57,
+ 46, 51, 48, 46, 57, 50,
+ 48, 48, 46, 49, 54, 51,
+ 56, 52, 0, 171, 73, 83,
+ 71, 78, 80, 0, 0, 0,
+ 2, 0, 0, 0, 8, 0,
+ 0, 0, 56, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0,
+ 0, 0, 68, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0,
+ 1, 0, 0, 0, 3, 3,
+ 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79,
+ 78, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171,
+ 171, 171, 79, 83, 71, 78,
+ 44, 0, 0, 0, 1, 0,
+ 0, 0, 8, 0, 0, 0,
+ 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0,
+ 83, 86, 95, 84, 65, 82,
+ 71, 69, 84, 0, 171, 171,
+ 83, 72, 68, 82, 128, 0,
+ 0, 0, 64, 0, 0, 0,
+ 32, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0,
+ 0, 0, 0, 0, 88, 24,
+ 0, 4, 0, 112, 16, 0,
+ 0, 0, 0, 0, 85, 85,
+ 0, 0, 98, 16, 0, 3,
+ 50, 16, 16, 0, 1, 0,
+ 0, 0, 101, 0, 0, 3,
+ 242, 32, 16, 0, 0, 0,
+ 0, 0, 104, 0, 0, 2,
+ 1, 0, 0, 0, 69, 0,
+ 0, 9, 242, 0, 16, 0,
+ 0, 0, 0, 0, 70, 16,
+ 16, 0, 1, 0, 0, 0,
+ 70, 126, 16, 0, 0, 0,
+ 0, 0, 0, 96, 16, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 5, 242, 32, 16, 0,
+ 0, 0, 0, 0, 6, 12,
+ 16, 0, 0, 0, 0, 0,
+ 62, 0, 0, 1, 83, 84,
+ 65, 84, 116, 0, 0, 0,
+ 3, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0
+};
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughlumalpha11ps.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11shaderscompiledpassthroughrgb11psh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgb11ps.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgb11ps.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgb11ps.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,152 @@
</span><ins>+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 9.30.9200.16384
+//
+//
+///
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Sampler sampler NA NA 0 1
+// Texture texture float4 2d 0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v1.xyxx, t0.xyzw, s0
+mov o0.xyz, r0.xyzx
+mov o0.w, l(1.000000)
+ret
+// Approximately 4 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRGB[] =
+{
+ 68, 88, 66, 67, 125, 186,
+ 250, 242, 113, 255, 59, 239,
+ 119, 158, 237, 78, 220, 43,
+ 160, 46, 1, 0, 0, 0,
+ 128, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 220, 0, 0, 0, 52, 1,
+ 0, 0, 104, 1, 0, 0,
+ 4, 2, 0, 0, 82, 68,
+ 69, 70, 160, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 255, 255, 0, 1, 0, 0,
+ 108, 0, 0, 0, 92, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0,
+ 100, 0, 0, 0, 2, 0,
+ 0, 0, 5, 0, 0, 0,
+ 4, 0, 0, 0, 255, 255,
+ 255, 255, 0, 0, 0, 0,
+ 1, 0, 0, 0, 13, 0,
+ 0, 0, 83, 97, 109, 112,
+ 108, 101, 114, 0, 84, 101,
+ 120, 116, 117, 114, 101, 0,
+ 77, 105, 99, 114, 111, 115,
+ 111, 102, 116, 32, 40, 82,
+ 41, 32, 72, 76, 83, 76,
+ 32, 83, 104, 97, 100, 101,
+ 114, 32, 67, 111, 109, 112,
+ 105, 108, 101, 114, 32, 57,
+ 46, 51, 48, 46, 57, 50,
+ 48, 48, 46, 49, 54, 51,
+ 56, 52, 0, 171, 73, 83,
+ 71, 78, 80, 0, 0, 0,
+ 2, 0, 0, 0, 8, 0,
+ 0, 0, 56, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0,
+ 0, 0, 68, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0,
+ 1, 0, 0, 0, 3, 3,
+ 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79,
+ 78, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171,
+ 171, 171, 79, 83, 71, 78,
+ 44, 0, 0, 0, 1, 0,
+ 0, 0, 8, 0, 0, 0,
+ 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0,
+ 83, 86, 95, 84, 65, 82,
+ 71, 69, 84, 0, 171, 171,
+ 83, 72, 68, 82, 148, 0,
+ 0, 0, 64, 0, 0, 0,
+ 37, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0,
+ 0, 0, 0, 0, 88, 24,
+ 0, 4, 0, 112, 16, 0,
+ 0, 0, 0, 0, 85, 85,
+ 0, 0, 98, 16, 0, 3,
+ 50, 16, 16, 0, 1, 0,
+ 0, 0, 101, 0, 0, 3,
+ 242, 32, 16, 0, 0, 0,
+ 0, 0, 104, 0, 0, 2,
+ 1, 0, 0, 0, 69, 0,
+ 0, 9, 242, 0, 16, 0,
+ 0, 0, 0, 0, 70, 16,
+ 16, 0, 1, 0, 0, 0,
+ 70, 126, 16, 0, 0, 0,
+ 0, 0, 0, 96, 16, 0,
+ 0, 0, 0, 0, 54, 0,
+ 0, 5, 114, 32, 16, 0,
+ 0, 0, 0, 0, 70, 2,
+ 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 5, 130, 32,
+ 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0,
+ 128, 63, 62, 0, 0, 1,
+ 83, 84, 65, 84, 116, 0,
+ 0, 0, 4, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0
+};
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgb11ps.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11shaderscompiledpassthroughrgba11psh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgba11ps.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgba11ps.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgba11ps.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,141 @@
</span><ins>+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 9.30.9200.16384
+//
+//
+///
+// Resource Bindings:
+//
+// Name Type Format Dim Slot Elements
+// ------------------------------ ---------- ------- ----------- ---- --------
+// Sampler sampler NA NA 0 1
+// Texture texture float4 2d 0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+sample o0.xyzw, v1.xyxx, t0.xyzw, s0
+ret
+// Approximately 2 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRGBA[] =
+{
+ 68, 88, 66, 67, 151, 152,
+ 8, 102, 174, 135, 76, 57,
+ 100, 146, 59, 74, 205, 35,
+ 206, 21, 1, 0, 0, 0,
+ 80, 2, 0, 0, 5, 0,
+ 0, 0, 52, 0, 0, 0,
+ 220, 0, 0, 0, 52, 1,
+ 0, 0, 104, 1, 0, 0,
+ 212, 1, 0, 0, 82, 68,
+ 69, 70, 160, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4,
+ 255, 255, 0, 1, 0, 0,
+ 108, 0, 0, 0, 92, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0,
+ 100, 0, 0, 0, 2, 0,
+ 0, 0, 5, 0, 0, 0,
+ 4, 0, 0, 0, 255, 255,
+ 255, 255, 0, 0, 0, 0,
+ 1, 0, 0, 0, 13, 0,
+ 0, 0, 83, 97, 109, 112,
+ 108, 101, 114, 0, 84, 101,
+ 120, 116, 117, 114, 101, 0,
+ 77, 105, 99, 114, 111, 115,
+ 111, 102, 116, 32, 40, 82,
+ 41, 32, 72, 76, 83, 76,
+ 32, 83, 104, 97, 100, 101,
+ 114, 32, 67, 111, 109, 112,
+ 105, 108, 101, 114, 32, 57,
+ 46, 51, 48, 46, 57, 50,
+ 48, 48, 46, 49, 54, 51,
+ 56, 52, 0, 171, 73, 83,
+ 71, 78, 80, 0, 0, 0,
+ 2, 0, 0, 0, 8, 0,
+ 0, 0, 56, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0,
+ 0, 0, 68, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0,
+ 1, 0, 0, 0, 3, 3,
+ 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79,
+ 78, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171,
+ 171, 171, 79, 83, 71, 78,
+ 44, 0, 0, 0, 1, 0,
+ 0, 0, 8, 0, 0, 0,
+ 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0,
+ 83, 86, 95, 84, 65, 82,
+ 71, 69, 84, 0, 171, 171,
+ 83, 72, 68, 82, 100, 0,
+ 0, 0, 64, 0, 0, 0,
+ 25, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0,
+ 0, 0, 0, 0, 88, 24,
+ 0, 4, 0, 112, 16, 0,
+ 0, 0, 0, 0, 85, 85,
+ 0, 0, 98, 16, 0, 3,
+ 50, 16, 16, 0, 1, 0,
+ 0, 0, 101, 0, 0, 3,
+ 242, 32, 16, 0, 0, 0,
+ 0, 0, 69, 0, 0, 9,
+ 242, 32, 16, 0, 0, 0,
+ 0, 0, 70, 16, 16, 0,
+ 1, 0, 0, 0, 70, 126,
+ 16, 0, 0, 0, 0, 0,
+ 0, 96, 16, 0, 0, 0,
+ 0, 0, 62, 0, 0, 1,
+ 83, 84, 65, 84, 116, 0,
+ 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0
+};
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgba11ps.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d11shadersgenerate_shadersbat"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/generate_shaders.bat (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/generate_shaders.bat         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/generate_shaders.bat        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,18 @@
</span><ins>+@ECHO OFF
+REM
+REM Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+REM Use of this source code is governed by a BSD-style license that can be
+REM found in the LICENSE file.
+REM
+
+PATH %PATH%;%ProgramFiles(x86)%\Windows Kits\8.0\bin\x86;%DXSDK_DIR%\Utilities\bin\x86
+
+fxc /E VS_Passthrough /T vs_4_0 /Fh compiled/passthrough11vs.h Passthrough11.hlsl
+fxc /E PS_PassthroughRGBA /T ps_4_0 /Fh compiled/passthroughrgba11ps.h Passthrough11.hlsl
+fxc /E PS_PassthroughRGB /T ps_4_0 /Fh compiled/passthroughrgb11ps.h Passthrough11.hlsl
+fxc /E PS_PassthroughLum /T ps_4_0 /Fh compiled/passthroughlum11ps.h Passthrough11.hlsl
+fxc /E PS_PassthroughLumAlpha /T ps_4_0 /Fh compiled/passthroughlumalpha11ps.h Passthrough11.hlsl
+
+fxc /E VS_Clear /T vs_4_0 /Fh compiled/clear11vs.h Clear11.hlsl
+fxc /E PS_ClearSingle /T ps_4_0 /Fh compiled/clearsingle11ps.h Clear11.hlsl
+fxc /E PS_ClearMultiple /T ps_4_0 /Fh compiled/clearmultiple11ps.h Clear11.hlsl
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d11/shaders/generate_shaders.bat
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnmimetype"></a>
<div class="addfile"><h4>Added: svn:mime-type</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9Blitcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Blit.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Blit.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Blit.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,595 @@
</span><ins>+#include "precompiled.h"
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Blit.cpp: Surface copy utility class.
+
+#include "libGLESv2/renderer/d3d9/Blit.h"
+
+#include "libGLESv2/main.h"
+#include "libGLESv2/renderer/d3d9/renderer9_utils.h"
+#include "libGLESv2/renderer/d3d9/TextureStorage9.h"
+#include "libGLESv2/renderer/d3d9/RenderTarget9.h"
+#include "libGLESv2/renderer/d3d9/Renderer9.h"
+#include "libGLESv2/Framebuffer.h"
+#include "libGLESv2/Renderbuffer.h"
+
+namespace
+{
+#include "libGLESv2/renderer/d3d9/shaders/compiled/standardvs.h"
+#include "libGLESv2/renderer/d3d9/shaders/compiled/flipyvs.h"
+#include "libGLESv2/renderer/d3d9/shaders/compiled/passthroughps.h"
+#include "libGLESv2/renderer/d3d9/shaders/compiled/luminanceps.h"
+#include "libGLESv2/renderer/d3d9/shaders/compiled/componentmaskps.h"
+
+const BYTE* const g_shaderCode[] =
+{
+ g_vs20_standardvs,
+ g_vs20_flipyvs,
+ g_ps20_passthroughps,
+ g_ps20_luminanceps,
+ g_ps20_componentmaskps
+};
+
+const size_t g_shaderSize[] =
+{
+ sizeof(g_vs20_standardvs),
+ sizeof(g_vs20_flipyvs),
+ sizeof(g_ps20_passthroughps),
+ sizeof(g_ps20_luminanceps),
+ sizeof(g_ps20_componentmaskps)
+};
+}
+
+namespace rx
+{
+Blit::Blit(rx::Renderer9 *renderer)
+ : mRenderer(renderer), mQuadVertexBuffer(NULL), mQuadVertexDeclaration(NULL), mSavedStateBlock(NULL), mSavedRenderTarget(NULL), mSavedDepthStencil(NULL)
+{
+ initGeometry();
+ memset(mCompiledShaders, 0, sizeof(mCompiledShaders));
+}
+
+Blit::~Blit()
+{
+ if (mSavedStateBlock) mSavedStateBlock->Release();
+ if (mQuadVertexBuffer) mQuadVertexBuffer->Release();
+ if (mQuadVertexDeclaration) mQuadVertexDeclaration->Release();
+
+ for (int i = 0; i < SHADER_COUNT; i++)
+ {
+ if (mCompiledShaders[i])
+ {
+ mCompiledShaders[i]->Release();
+ }
+ }
+}
+
+void Blit::initGeometry()
+{
+ static const float quad[] =
+ {
+ -1, -1,
+ -1, 1,
+ 1, -1,
+ 1, 1
+ };
+
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+
+ HRESULT result = device->CreateVertexBuffer(sizeof(quad), D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &mQuadVertexBuffer, NULL);
+
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+
+ void *lockPtr = NULL;
+ result = mQuadVertexBuffer->Lock(0, 0, &lockPtr, 0);
+
+ if (FAILED(result) || lockPtr == NULL)
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+
+ memcpy(lockPtr, quad, sizeof(quad));
+ mQuadVertexBuffer->Unlock();
+
+ static const D3DVERTEXELEMENT9 elements[] =
+ {
+ { 0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
+ D3DDECL_END()
+ };
+
+ result = device->CreateVertexDeclaration(elements, &mQuadVertexDeclaration);
+
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+}
+
+template <class D3DShaderType>
+bool Blit::setShader(ShaderId source, const char *profile,
+ D3DShaderType *(rx::Renderer9::*createShader)(const DWORD *, size_t length),
+ HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType*))
+{
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+
+ D3DShaderType *shader;
+
+ if (mCompiledShaders[source] != NULL)
+ {
+ shader = static_cast<D3DShaderType*>(mCompiledShaders[source]);
+ }
+ else
+ {
+ const BYTE* shaderCode = g_shaderCode[source];
+ size_t shaderSize = g_shaderSize[source];
+
+ shader = (mRenderer->*createShader)(reinterpret_cast<const DWORD*>(shaderCode), shaderSize);
+ if (!shader)
+ {
+ ERR("Failed to create shader for blit operation");
+ return false;
+ }
+
+ mCompiledShaders[source] = shader;
+ }
+
+ HRESULT hr = (device->*setShader)(shader);
+
+ if (FAILED(hr))
+ {
+ ERR("Failed to set shader for blit operation");
+ return false;
+ }
+
+ return true;
+}
+
+bool Blit::setVertexShader(ShaderId shader)
+{
+ return setShader<IDirect3DVertexShader9>(shader, "vs_2_0", &rx::Renderer9::createVertexShader, &IDirect3DDevice9::SetVertexShader);
+}
+
+bool Blit::setPixelShader(ShaderId shader)
+{
+ return setShader<IDirect3DPixelShader9>(shader, "ps_2_0", &rx::Renderer9::createPixelShader, &IDirect3DDevice9::SetPixelShader);
+}
+
+RECT Blit::getSurfaceRect(IDirect3DSurface9 *surface) const
+{
+ D3DSURFACE_DESC desc;
+ surface->GetDesc(&desc);
+
+ RECT rect;
+ rect.left = 0;
+ rect.top = 0;
+ rect.right = desc.Width;
+ rect.bottom = desc.Height;
+
+ return rect;
+}
+
+bool Blit::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest)
+{
+ IDirect3DTexture9 *texture = copySurfaceToTexture(source, getSurfaceRect(source));
+ if (!texture)
+ {
+ return false;
+ }
+
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+
+ saveState();
+
+ device->SetTexture(0, texture);
+ device->SetRenderTarget(0, dest);
+
+ setVertexShader(SHADER_VS_STANDARD);
+ setPixelShader(SHADER_PS_PASSTHROUGH);
+
+ setCommonBlitState();
+ device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
+ device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
+
+ setViewport(getSurfaceRect(dest), 0, 0);
+
+ render();
+
+ texture->Release();
+
+ restoreState();
+
+ return true;
+}
+
+bool Blit::copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level)
+{
+ RenderTarget9 *renderTarget = NULL;
+ IDirect3DSurface9 *source = NULL;
+ gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer(0);
+
+ if (colorbuffer)
+ {
+ renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget());
+ }
+
+ if (renderTarget)
+ {
+ source = renderTarget->getSurface();
+ }
+
+ if (!source)
+ {
+ ERR("Failed to retrieve the render target.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage->getStorageInstance());
+ IDirect3DSurface9 *destSurface = storage9->getSurfaceLevel(level, true);
+ bool result = false;
+
+ if (destSurface)
+ {
+ result = copy(source, sourceRect, destFormat, xoffset, yoffset, destSurface);
+ destSurface->Release();
+ }
+
+ source->Release();
+ return result;
+}
+
+bool Blit::copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level)
+{
+ RenderTarget9 *renderTarget = NULL;
+ IDirect3DSurface9 *source = NULL;
+ gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer(0);
+
+ if (colorbuffer)
+ {
+ renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget());
+ }
+
+ if (renderTarget)
+ {
+ source = renderTarget->getSurface();
+ }
+
+ if (!source)
+ {
+ ERR("Failed to retrieve the render target.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage->getStorageInstance());
+ IDirect3DSurface9 *destSurface = storage9->getCubeMapSurface(target, level, true);
+ bool result = false;
+
+ if (destSurface)
+ {
+ result = copy(source, sourceRect, destFormat, xoffset, yoffset, destSurface);
+ destSurface->Release();
+ }
+
+ source->Release();
+ return result;
+}
+
+bool Blit::copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest)
+{
+ if (!dest)
+ {
+ return false;
+ }
+
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+
+ D3DSURFACE_DESC sourceDesc;
+ D3DSURFACE_DESC destDesc;
+ source->GetDesc(&sourceDesc);
+ dest->GetDesc(&destDesc);
+
+ if (sourceDesc.Format == destDesc.Format && destDesc.Usage & D3DUSAGE_RENDERTARGET &&
+ d3d9_gl::IsFormatChannelEquivalent(destDesc.Format, destFormat)) // Can use StretchRect
+ {
+ RECT destRect = {xoffset, yoffset, xoffset + (sourceRect.right - sourceRect.left), yoffset + (sourceRect.bottom - sourceRect.top)};
+ HRESULT result = device->StretchRect(source, &sourceRect, dest, &destRect, D3DTEXF_POINT);
+
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+ }
+ else
+ {
+ return formatConvert(source, sourceRect, destFormat, xoffset, yoffset, dest);
+ }
+ return true;
+}
+
+bool Blit::formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest)
+{
+ IDirect3DTexture9 *texture = copySurfaceToTexture(source, sourceRect);
+ if (!texture)
+ {
+ return false;
+ }
+
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+
+ saveState();
+
+ device->SetTexture(0, texture);
+ device->SetRenderTarget(0, dest);
+
+ setViewport(sourceRect, xoffset, yoffset);
+
+ setCommonBlitState();
+ if (setFormatConvertShaders(destFormat))
+ {
+ render();
+ }
+
+ texture->Release();
+
+ restoreState();
+
+ return true;
+}
+
+bool Blit::setFormatConvertShaders(GLenum destFormat)
+{
+ bool okay = setVertexShader(SHADER_VS_STANDARD);
+
+ switch (destFormat)
+ {
+ default: UNREACHABLE();
+ case GL_RGBA:
+ case GL_BGRA_EXT:
+ case GL_RGB:
+ case GL_ALPHA:
+ okay = okay && setPixelShader(SHADER_PS_COMPONENTMASK);
+ break;
+
+ case GL_LUMINANCE:
+ case GL_LUMINANCE_ALPHA:
+ okay = okay && setPixelShader(SHADER_PS_LUMINANCE);
+ break;
+ }
+
+ if (!okay)
+ {
+ return false;
+ }
+
+ enum { X = 0, Y = 1, Z = 2, W = 3 };
+
+ // The meaning of this constant depends on the shader that was selected.
+ // See the shader assembly code above for details.
+ float psConst0[4] = { 0, 0, 0, 0 };
+
+ switch (destFormat)
+ {
+ default: UNREACHABLE();
+ case GL_RGBA:
+ case GL_BGRA_EXT:
+ psConst0[X] = 1;
+ psConst0[Z] = 1;
+ break;
+
+ case GL_RGB:
+ psConst0[X] = 1;
+ psConst0[W] = 1;
+ break;
+
+ case GL_ALPHA:
+ psConst0[Z] = 1;
+ break;
+
+ case GL_LUMINANCE:
+ psConst0[Y] = 1;
+ break;
+
+ case GL_LUMINANCE_ALPHA:
+ psConst0[X] = 1;
+ break;
+ }
+
+ mRenderer->getDevice()->SetPixelShaderConstantF(0, psConst0, 1);
+
+ return true;
+}
+
+IDirect3DTexture9 *Blit::copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect)
+{
+ if (!surface)
+ {
+ return NULL;
+ }
+
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+
+ D3DSURFACE_DESC sourceDesc;
+ surface->GetDesc(&sourceDesc);
+
+ // Copy the render target into a texture
+ IDirect3DTexture9 *texture;
+ HRESULT result = device->CreateTexture(sourceRect.right - sourceRect.left, sourceRect.bottom - sourceRect.top, 1, D3DUSAGE_RENDERTARGET, sourceDesc.Format, D3DPOOL_DEFAULT, &texture, NULL);
+
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+ return gl::error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL);
+ }
+
+ IDirect3DSurface9 *textureSurface;
+ result = texture->GetSurfaceLevel(0, &textureSurface);
+
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+ texture->Release();
+ return gl::error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL);
+ }
+
+ mRenderer->endScene();
+ result = device->StretchRect(surface, &sourceRect, textureSurface, NULL, D3DTEXF_NONE);
+
+ textureSurface->Release();
+
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+ texture->Release();
+ return gl::error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL);
+ }
+
+ return texture;
+}
+
+void Blit::setViewport(const RECT &sourceRect, GLint xoffset, GLint yoffset)
+{
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+
+ D3DVIEWPORT9 vp;
+ vp.X = xoffset;
+ vp.Y = yoffset;
+ vp.Width = sourceRect.right - sourceRect.left;
+ vp.Height = sourceRect.bottom - sourceRect.top;
+ vp.MinZ = 0.0f;
+ vp.MaxZ = 1.0f;
+ device->SetViewport(&vp);
+
+ float halfPixelAdjust[4] = { -1.0f/vp.Width, 1.0f/vp.Height, 0, 0 };
+ device->SetVertexShaderConstantF(0, halfPixelAdjust, 1);
+}
+
+void Blit::setCommonBlitState()
+{
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+
+ device->SetDepthStencilSurface(NULL);
+
+ device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
+ device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
+ device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
+ device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
+ device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
+ device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED);
+ device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE);
+ device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
+
+ device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
+ device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
+ device->SetSamplerState(0, D3DSAMP_SRGBTEXTURE, FALSE);
+ device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
+ device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
+
+ RECT scissorRect = {0}; // Scissoring is disabled for flipping, but we need this to capture and restore the old rectangle
+ device->SetScissorRect(&scissorRect);
+
+ for(int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
+ {
+ device->SetStreamSourceFreq(i, 1);
+ }
+}
+
+void Blit::render()
+{
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+
+ HRESULT hr = device->SetStreamSource(0, mQuadVertexBuffer, 0, 2 * sizeof(float));
+ hr = device->SetVertexDeclaration(mQuadVertexDeclaration);
+
+ mRenderer->startScene();
+ hr = device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
+}
+
+void Blit::saveState()
+{
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+
+ HRESULT hr;
+
+ device->GetDepthStencilSurface(&mSavedDepthStencil);
+ device->GetRenderTarget(0, &mSavedRenderTarget);
+
+ if (mSavedStateBlock == NULL)
+ {
+ hr = device->BeginStateBlock();
+ ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
+
+ setCommonBlitState();
+
+ static const float dummyConst[4] = { 0, 0, 0, 0 };
+
+ device->SetVertexShader(NULL);
+ device->SetVertexShaderConstantF(0, dummyConst, 1);
+ device->SetPixelShader(NULL);
+ device->SetPixelShaderConstantF(0, dummyConst, 1);
+
+ D3DVIEWPORT9 dummyVp;
+ dummyVp.X = 0;
+ dummyVp.Y = 0;
+ dummyVp.Width = 1;
+ dummyVp.Height = 1;
+ dummyVp.MinZ = 0;
+ dummyVp.MaxZ = 1;
+
+ device->SetViewport(&dummyVp);
+
+ device->SetTexture(0, NULL);
+
+ device->SetStreamSource(0, mQuadVertexBuffer, 0, 0);
+
+ device->SetVertexDeclaration(mQuadVertexDeclaration);
+
+ hr = device->EndStateBlock(&mSavedStateBlock);
+ ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
+ }
+
+ ASSERT(mSavedStateBlock != NULL);
+
+ if (mSavedStateBlock != NULL)
+ {
+ hr = mSavedStateBlock->Capture();
+ ASSERT(SUCCEEDED(hr));
+ }
+}
+
+void Blit::restoreState()
+{
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+
+ device->SetDepthStencilSurface(mSavedDepthStencil);
+ if (mSavedDepthStencil != NULL)
+ {
+ mSavedDepthStencil->Release();
+ mSavedDepthStencil = NULL;
+ }
+
+ device->SetRenderTarget(0, mSavedRenderTarget);
+ if (mSavedRenderTarget != NULL)
+ {
+ mSavedRenderTarget->Release();
+ mSavedRenderTarget = NULL;
+ }
+
+ ASSERT(mSavedStateBlock != NULL);
+
+ if (mSavedStateBlock != NULL)
+ {
+ mSavedStateBlock->Apply();
+ }
+}
+
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Blit.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9Blith"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Blit.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Blit.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Blit.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,94 @@
</span><ins>+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Blit.cpp: Surface copy utility class.
+
+#ifndef LIBGLESV2_BLIT_H_
+#define LIBGLESV2_BLIT_H_
+
+#include "common/angleutils.h"
+
+namespace gl
+{
+class Framebuffer;
+}
+
+namespace rx
+{
+class Renderer9;
+class TextureStorageInterface2D;
+class TextureStorageInterfaceCube;
+
+class Blit
+{
+ public:
+ explicit Blit(Renderer9 *renderer);
+ ~Blit();
+
+ // Copy from source surface to dest surface.
+ // sourceRect, xoffset, yoffset are in D3D coordinates (0,0 in upper-left)
+ bool copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level);
+ bool copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level);
+
+ // Copy from source surface to dest surface.
+ // sourceRect, xoffset, yoffset are in D3D coordinates (0,0 in upper-left)
+ // source is interpreted as RGBA and destFormat specifies the desired result format. For example, if destFormat = GL_RGB, the alpha channel will be forced to 0.
+ bool formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest);
+
+ // 2x2 box filter sample from source to dest.
+ // Requires that source is RGB(A) and dest has the same format as source.
+ bool boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest);
+
+ private:
+ rx::Renderer9 *mRenderer;
+
+ IDirect3DVertexBuffer9 *mQuadVertexBuffer;
+ IDirect3DVertexDeclaration9 *mQuadVertexDeclaration;
+
+ void initGeometry();
+
+ bool setFormatConvertShaders(GLenum destFormat);
+
+ bool copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest);
+ IDirect3DTexture9 *copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect);
+ void setViewport(const RECT &sourceRect, GLint xoffset, GLint yoffset);
+ void setCommonBlitState();
+ RECT getSurfaceRect(IDirect3DSurface9 *surface) const;
+
+ // This enum is used to index mCompiledShaders and mShaderSource.
+ enum ShaderId
+ {
+ SHADER_VS_STANDARD,
+ SHADER_VS_FLIPY,
+ SHADER_PS_PASSTHROUGH,
+ SHADER_PS_LUMINANCE,
+ SHADER_PS_COMPONENTMASK,
+ SHADER_COUNT
+ };
+
+ // This actually contains IDirect3DVertexShader9 or IDirect3DPixelShader9 casted to IUnknown.
+ IUnknown *mCompiledShaders[SHADER_COUNT];
+
+ template <class D3DShaderType>
+ bool setShader(ShaderId source, const char *profile,
+ D3DShaderType *(Renderer9::*createShader)(const DWORD *, size_t length),
+ HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType*));
+
+ bool setVertexShader(ShaderId shader);
+ bool setPixelShader(ShaderId shader);
+ void render();
+
+ void saveState();
+ void restoreState();
+ IDirect3DStateBlock9 *mSavedStateBlock;
+ IDirect3DSurface9 *mSavedRenderTarget;
+ IDirect3DSurface9 *mSavedDepthStencil;
+
+ DISALLOW_COPY_AND_ASSIGN(Blit);
+};
+}
+
+#endif // LIBGLESV2_BLIT_H_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Blit.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9BufferStorage9cpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/BufferStorage9.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/BufferStorage9.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/BufferStorage9.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,78 @@
</span><ins>+#include "precompiled.h"
+//
+// Copyright (c) 2013 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.
+//
+
+// BufferStorage9.cpp Defines the BufferStorage9 class.
+
+#include "libGLESv2/renderer/d3d9/BufferStorage9.h"
+#include "common/debug.h"
+
+namespace rx
+{
+
+BufferStorage9::BufferStorage9()
+{
+ mMemory = NULL;
+ mAllocatedSize = 0;
+ mSize = 0;
+}
+
+BufferStorage9::~BufferStorage9()
+{
+ delete[] mMemory;
+}
+
+BufferStorage9 *BufferStorage9::makeBufferStorage9(BufferStorage *bufferStorage)
+{
+ ASSERT(HAS_DYNAMIC_TYPE(BufferStorage9*, bufferStorage));
+ return static_cast<BufferStorage9*>(bufferStorage);
+}
+
+void *BufferStorage9::getData()
+{
+ return mMemory;
+}
+
+void BufferStorage9::setData(const void* data, unsigned int size, unsigned int offset)
+{
+ if (!mMemory || offset + size > mAllocatedSize)
+ {
+ unsigned int newAllocatedSize = offset + size;
+ void *newMemory = new char[newAllocatedSize];
+
+ if (offset > 0 && mMemory && mAllocatedSize > 0)
+ {
+ memcpy(newMemory, mMemory, std::min(offset, mAllocatedSize));
+ }
+
+ delete[] mMemory;
+ mMemory = newMemory;
+ mAllocatedSize = newAllocatedSize;
+ }
+
+ mSize = std::max(mSize, offset + size);
+ if (data)
+ {
+ memcpy(reinterpret_cast<char*>(mMemory) + offset, data, size);
+ }
+}
+
+void BufferStorage9::clear()
+{
+ mSize = 0;
+}
+
+unsigned int BufferStorage9::getSize() const
+{
+ return mSize;
+}
+
+bool BufferStorage9::supportsDirectBinding() const
+{
+ return false;
+}
+
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/BufferStorage9.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9BufferStorage9h"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/BufferStorage9.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/BufferStorage9.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/BufferStorage9.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,42 @@
</span><ins>+//
+// Copyright (c) 2013 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.
+//
+
+// BufferStorage9.h Defines the BufferStorage9 class.
+
+#ifndef LIBGLESV2_RENDERER_BUFFERSTORAGE9_H_
+#define LIBGLESV2_RENDERER_BUFFERSTORAGE9_H_
+
+#include "libGLESv2/renderer/BufferStorage.h"
+
+namespace rx
+{
+
+class BufferStorage9 : public BufferStorage
+{
+ public:
+ BufferStorage9();
+ virtual ~BufferStorage9();
+
+ static BufferStorage9 *makeBufferStorage9(BufferStorage *bufferStorage);
+
+ virtual void *getData();
+ virtual void setData(const void* data, unsigned int size, unsigned int offset);
+ virtual void clear();
+ virtual unsigned int getSize() const;
+ virtual bool supportsDirectBinding() const;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(BufferStorage9);
+
+ void *mMemory;
+ unsigned int mAllocatedSize;
+
+ unsigned int mSize;
+};
+
+}
+
+#endif // LIBGLESV2_RENDERER_BUFFERSTORAGE9_H_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/BufferStorage9.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9Fence9cpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Fence9.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Fence9.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Fence9.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,135 @@
</span><ins>+#include "precompiled.h"
+//
+// Copyright (c) 2013 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.
+//
+
+// Fence9.cpp: Defines the rx::Fence9 class.
+
+#include "libGLESv2/renderer/d3d9/Fence9.h"
+#include "libGLESv2/main.h"
+#include "libGLESv2/renderer/d3d9/renderer9_utils.h"
+#include "libGLESv2/renderer/d3d9/Renderer9.h"
+
+namespace rx
+{
+
+Fence9::Fence9(rx::Renderer9 *renderer)
+{
+ mRenderer = renderer;
+ mQuery = NULL;
+}
+
+Fence9::~Fence9()
+{
+ if (mQuery)
+ {
+ mRenderer->freeEventQuery(mQuery);
+ mQuery = NULL;
+ }
+}
+
+GLboolean Fence9::isFence()
+{
+ // GL_NV_fence spec:
+ // A name returned by GenFencesNV, but not yet set via SetFenceNV, is not the name of an existing fence.
+ return mQuery != NULL;
+}
+
+void Fence9::setFence(GLenum condition)
+{
+ if (!mQuery)
+ {
+ mQuery = mRenderer->allocateEventQuery();
+ if (!mQuery)
+ {
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+ }
+
+ HRESULT result = mQuery->Issue(D3DISSUE_END);
+ ASSERT(SUCCEEDED(result));
+
+ setCondition(condition);
+ setStatus(GL_FALSE);
+}
+
+GLboolean Fence9::testFence()
+{
+ if (mQuery == NULL)
+ {
+ return gl::error(GL_INVALID_OPERATION, GL_TRUE);
+ }
+
+ HRESULT result = mQuery->GetData(NULL, 0, D3DGETDATA_FLUSH);
+
+ if (d3d9::isDeviceLostError(result))
+ {
+ mRenderer->notifyDeviceLost();
+ return gl::error(GL_OUT_OF_MEMORY, GL_TRUE);
+ }
+
+ ASSERT(result == S_OK || result == S_FALSE);
+ setStatus(result == S_OK);
+ return getStatus();
+}
+
+void Fence9::finishFence()
+{
+ if (mQuery == NULL)
+ {
+ return gl::error(GL_INVALID_OPERATION);
+ }
+
+ while (!testFence())
+ {
+ Sleep(0);
+ }
+}
+
+void Fence9::getFenceiv(GLenum pname, GLint *params)
+{
+ if (mQuery == NULL)
+ {
+ return gl::error(GL_INVALID_OPERATION);
+ }
+
+ switch (pname)
+ {
+ case GL_FENCE_STATUS_NV:
+ {
+ // GL_NV_fence spec:
+ // Once the status of a fence has been finished (via FinishFenceNV) or tested and the returned status is TRUE (via either TestFenceNV
+ // or GetFenceivNV querying the FENCE_STATUS_NV), the status remains TRUE until the next SetFenceNV of the fence.
+ if (getStatus())
+ {
+ params[0] = GL_TRUE;
+ return;
+ }
+
+ HRESULT result = mQuery->GetData(NULL, 0, 0);
+
+ if (d3d9::isDeviceLostError(result))
+ {
+ params[0] = GL_TRUE;
+ mRenderer->notifyDeviceLost();
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+
+ ASSERT(result == S_OK || result == S_FALSE);
+ setStatus(result == S_OK);
+ params[0] = getStatus();
+
+ break;
+ }
+ case GL_FENCE_CONDITION_NV:
+ params[0] = getCondition();
+ break;
+ default:
+ return gl::error(GL_INVALID_ENUM);
+ break;
+ }
+}
+
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Fence9.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9Fence9h"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Fence9.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Fence9.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Fence9.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,39 @@
</span><ins>+//
+// Copyright (c) 2013 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.
+//
+
+// Fence9.h: Defines the rx::Fence9 class which implements rx::FenceImpl.
+
+#ifndef LIBGLESV2_RENDERER_FENCE9_H_
+#define LIBGLESV2_RENDERER_FENCE9_H_
+
+#include "libGLESv2/renderer/FenceImpl.h"
+
+namespace rx
+{
+class Renderer9;
+
+class Fence9 : public FenceImpl
+{
+ public:
+ explicit Fence9(rx::Renderer9 *renderer);
+ virtual ~Fence9();
+
+ GLboolean isFence();
+ void setFence(GLenum condition);
+ GLboolean testFence();
+ void finishFence();
+ void getFenceiv(GLenum pname, GLint *params);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Fence9);
+
+ rx::Renderer9 *mRenderer;
+ IDirect3DQuery9 *mQuery;
+};
+
+}
+
+#endif // LIBGLESV2_RENDERER_FENCE9_H_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Fence9.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9Image9cpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Image9.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Image9.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Image9.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,732 @@
</span><ins>+#include "precompiled.h"
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Image9.cpp: Implements the rx::Image9 class, which acts as the interface to
+// the actual underlying surfaces of a Texture.
+
+#include "libGLESv2/renderer/d3d9/Image9.h"
+
+#include "libGLESv2/main.h"
+#include "libGLESv2/Framebuffer.h"
+#include "libGLESv2/Renderbuffer.h"
+#include "libGLESv2/renderer/d3d9/Renderer9.h"
+#include "libGLESv2/renderer/d3d9/RenderTarget9.h"
+#include "libGLESv2/renderer/d3d9/TextureStorage9.h"
+
+#include "libGLESv2/renderer/d3d9/renderer9_utils.h"
+#include "libGLESv2/renderer/generatemip.h"
+
+namespace rx
+{
+
+Image9::Image9()
+{
+ mSurface = NULL;
+ mRenderer = NULL;
+
+ mD3DPool = D3DPOOL_SYSTEMMEM;
+ mD3DFormat = D3DFMT_UNKNOWN;
+}
+
+Image9::~Image9()
+{
+ if (mSurface)
+ {
+ mSurface->Release();
+ }
+}
+
+void Image9::generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sourceSurface)
+{
+ D3DSURFACE_DESC destDesc;
+ HRESULT result = destSurface->GetDesc(&destDesc);
+ ASSERT(SUCCEEDED(result));
+
+ D3DSURFACE_DESC sourceDesc;
+ result = sourceSurface->GetDesc(&sourceDesc);
+ ASSERT(SUCCEEDED(result));
+
+ ASSERT(sourceDesc.Format == destDesc.Format);
+ ASSERT(sourceDesc.Width == 1 || sourceDesc.Width / 2 == destDesc.Width);
+ ASSERT(sourceDesc.Height == 1 || sourceDesc.Height / 2 == destDesc.Height);
+
+ D3DLOCKED_RECT sourceLocked = {0};
+ result = sourceSurface->LockRect(&sourceLocked, NULL, D3DLOCK_READONLY);
+ ASSERT(SUCCEEDED(result));
+
+ D3DLOCKED_RECT destLocked = {0};
+ result = destSurface->LockRect(&destLocked, NULL, 0);
+ ASSERT(SUCCEEDED(result));
+
+ const unsigned char *sourceData = reinterpret_cast<const unsigned char*>(sourceLocked.pBits);
+ unsigned char *destData = reinterpret_cast<unsigned char*>(destLocked.pBits);
+
+ if (sourceData && destData)
+ {
+ switch (sourceDesc.Format)
+ {
+ case D3DFMT_L8:
+ GenerateMip<L8>(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch);
+ break;
+ case D3DFMT_A8L8:
+ GenerateMip<A8L8>(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch);
+ break;
+ case D3DFMT_A8R8G8B8:
+ case D3DFMT_X8R8G8B8:
+ GenerateMip<A8R8G8B8>(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch);
+ break;
+ case D3DFMT_A16B16G16R16F:
+ GenerateMip<A16B16G16R16F>(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch);
+ break;
+ case D3DFMT_A32B32G32R32F:
+ GenerateMip<A32B32G32R32F>(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ destSurface->UnlockRect();
+ sourceSurface->UnlockRect();
+ }
+}
+
+Image9 *Image9::makeImage9(Image *img)
+{
+ ASSERT(HAS_DYNAMIC_TYPE(rx::Image9*, img));
+ return static_cast<rx::Image9*>(img);
+}
+
+void Image9::generateMipmap(Image9 *dest, Image9 *source)
+{
+ IDirect3DSurface9 *sourceSurface = source->getSurface();
+ if (sourceSurface == NULL)
+ return gl::error(GL_OUT_OF_MEMORY);
+
+ IDirect3DSurface9 *destSurface = dest->getSurface();
+ generateMip(destSurface, sourceSurface);
+
+ dest->markDirty();
+}
+
+void Image9::copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *source)
+{
+ D3DLOCKED_RECT sourceLock = {0};
+ D3DLOCKED_RECT destLock = {0};
+
+ source->LockRect(&sourceLock, NULL, 0);
+ dest->LockRect(&destLock, NULL, 0);
+
+ if (sourceLock.pBits && destLock.pBits)
+ {
+ D3DSURFACE_DESC desc;
+ source->GetDesc(&desc);
+
+ int rows = d3d9::IsCompressedFormat(desc.Format) ? desc.Height / 4 : desc.Height;
+ int bytes = d3d9::ComputeRowSize(desc.Format, desc.Width);
+ ASSERT(bytes <= sourceLock.Pitch && bytes <= destLock.Pitch);
+
+ for(int i = 0; i < rows; i++)
+ {
+ memcpy((char*)destLock.pBits + destLock.Pitch * i, (char*)sourceLock.pBits + sourceLock.Pitch * i, bytes);
+ }
+
+ source->UnlockRect();
+ dest->UnlockRect();
+ }
+ else UNREACHABLE();
+}
+
+bool Image9::redefine(rx::Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, bool forceRelease)
+{
+ if (mWidth != width ||
+ mHeight != height ||
+ mInternalFormat != internalformat ||
+ forceRelease)
+ {
+ mRenderer = Renderer9::makeRenderer9(renderer);
+
+ mWidth = width;
+ mHeight = height;
+ mInternalFormat = internalformat;
+ // compute the d3d format that will be used
+ mD3DFormat = mRenderer->ConvertTextureInternalFormat(internalformat);
+ mActualFormat = d3d9_gl::GetEquivalentFormat(mD3DFormat);
+
+ if (mSurface)
+ {
+ mSurface->Release();
+ mSurface = NULL;
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+void Image9::createSurface()
+{
+ if(mSurface)
+ {
+ return;
+ }
+
+ IDirect3DTexture9 *newTexture = NULL;
+ IDirect3DSurface9 *newSurface = NULL;
+ const D3DPOOL poolToUse = D3DPOOL_SYSTEMMEM;
+ const D3DFORMAT d3dFormat = getD3DFormat();
+ ASSERT(d3dFormat != D3DFMT_INTZ); // We should never get here for depth textures
+
+ if (mWidth != 0 && mHeight != 0)
+ {
+ int levelToFetch = 0;
+ GLsizei requestWidth = mWidth;
+ GLsizei requestHeight = mHeight;
+ gl::MakeValidSize(true, gl::IsCompressed(mInternalFormat), &requestWidth, &requestHeight, &levelToFetch);
+
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+
+ HRESULT result = device->CreateTexture(requestWidth, requestHeight, levelToFetch + 1, 0, d3dFormat,
+ poolToUse, &newTexture, NULL);
+
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+ ERR("Creating image surface failed.");
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+
+ newTexture->GetSurfaceLevel(levelToFetch, &newSurface);
+ newTexture->Release();
+ }
+
+ mSurface = newSurface;
+ mDirty = false;
+ mD3DPool = poolToUse;
+}
+
+HRESULT Image9::lock(D3DLOCKED_RECT *lockedRect, const RECT *rect)
+{
+ createSurface();
+
+ HRESULT result = D3DERR_INVALIDCALL;
+
+ if (mSurface)
+ {
+ result = mSurface->LockRect(lockedRect, rect, 0);
+ ASSERT(SUCCEEDED(result));
+
+ mDirty = true;
+ }
+
+ return result;
+}
+
+void Image9::unlock()
+{
+ if (mSurface)
+ {
+ HRESULT result = mSurface->UnlockRect();
+ ASSERT(SUCCEEDED(result));
+ }
+}
+
+bool Image9::isRenderableFormat() const
+{
+ return TextureStorage9::IsTextureFormatRenderable(getD3DFormat());
+}
+
+D3DFORMAT Image9::getD3DFormat() const
+{
+ // this should only happen if the image hasn't been redefined first
+ // which would be a bug by the caller
+ ASSERT(mD3DFormat != D3DFMT_UNKNOWN);
+
+ return mD3DFormat;
+}
+
+IDirect3DSurface9 *Image9::getSurface()
+{
+ createSurface();
+
+ return mSurface;
+}
+
+void Image9::setManagedSurface(TextureStorageInterface2D *storage, int level)
+{
+ TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage->getStorageInstance());
+ setManagedSurface(storage9->getSurfaceLevel(level, false));
+}
+
+void Image9::setManagedSurface(TextureStorageInterfaceCube *storage, int face, int level)
+{
+ TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage->getStorageInstance());
+ setManagedSurface(storage9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, false));
+}
+
+void Image9::setManagedSurface(IDirect3DSurface9 *surface)
+{
+ D3DSURFACE_DESC desc;
+ surface->GetDesc(&desc);
+ ASSERT(desc.Pool == D3DPOOL_MANAGED);
+
+ if ((GLsizei)desc.Width == mWidth && (GLsizei)desc.Height == mHeight)
+ {
+ if (mSurface)
+ {
+ copyLockableSurfaces(surface, mSurface);
+ mSurface->Release();
+ }
+
+ mSurface = surface;
+ mD3DPool = desc.Pool;
+ }
+}
+
+bool Image9::updateSurface(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
+{
+ ASSERT(getSurface() != NULL);
+ TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage->getStorageInstance());
+ return updateSurface(storage9->getSurfaceLevel(level, true), xoffset, yoffset, width, height);
+}
+
+bool Image9::updateSurface(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
+{
+ ASSERT(getSurface() != NULL);
+ TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage->getStorageInstance());
+ return updateSurface(storage9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, true), xoffset, yoffset, width, height);
+}
+
+bool Image9::updateSurface(IDirect3DSurface9 *destSurface, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
+{
+ if (!destSurface)
+ return false;
+
+ IDirect3DSurface9 *sourceSurface = getSurface();
+
+ if (sourceSurface && sourceSurface != destSurface)
+ {
+ RECT rect;
+ rect.left = xoffset;
+ rect.top = yoffset;
+ rect.right = xoffset + width;
+ rect.bottom = yoffset + height;
+
+ POINT point = {rect.left, rect.top};
+
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+
+ if (mD3DPool == D3DPOOL_MANAGED)
+ {
+ D3DSURFACE_DESC desc;
+ sourceSurface->GetDesc(&desc);
+
+ IDirect3DSurface9 *surf = 0;
+ HRESULT result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surf, NULL);
+
+ if (SUCCEEDED(result))
+ {
+ copyLockableSurfaces(surf, sourceSurface);
+ result = device->UpdateSurface(surf, &rect, destSurface, &point);
+ ASSERT(SUCCEEDED(result));
+ surf->Release();
+ }
+ }
+ else
+ {
+ // UpdateSurface: source must be SYSTEMMEM, dest must be DEFAULT pools
+ HRESULT result = device->UpdateSurface(sourceSurface, &rect, destSurface, &point);
+ ASSERT(SUCCEEDED(result));
+ }
+ }
+
+ destSurface->Release();
+ return true;
+}
+
+// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input
+// into the target pixel rectangle.
+void Image9::loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ GLint unpackAlignment, const void *input)
+{
+ RECT lockRect =
+ {
+ xoffset, yoffset,
+ xoffset + width, yoffset + height
+ };
+
+ D3DLOCKED_RECT locked;
+ HRESULT result = lock(&locked, &lockRect);
+ if (FAILED(result))
+ {
+ return;
+ }
+
+
+ GLsizei inputPitch = gl::ComputePitch(width, mInternalFormat, unpackAlignment);
+
+ switch (mInternalFormat)
+ {
+ case GL_ALPHA8_EXT:
+ if (gl::supportsSSE2())
+ {
+ loadAlphaDataToBGRASSE2(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+ }
+ else
+ {
+ loadAlphaDataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+ }
+ break;
+ case GL_LUMINANCE8_EXT:
+ loadLuminanceDataToNativeOrBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits, getD3DFormat() == D3DFMT_L8);
+ break;
+ case GL_ALPHA32F_EXT:
+ loadAlphaFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+ break;
+ case GL_LUMINANCE32F_EXT:
+ loadLuminanceFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+ break;
+ case GL_ALPHA16F_EXT:
+ loadAlphaHalfFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+ break;
+ case GL_LUMINANCE16F_EXT:
+ loadLuminanceHalfFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+ break;
+ case GL_LUMINANCE8_ALPHA8_EXT:
+ loadLuminanceAlphaDataToNativeOrBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits, getD3DFormat() == D3DFMT_A8L8);
+ break;
+ case GL_LUMINANCE_ALPHA32F_EXT:
+ loadLuminanceAlphaFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+ break;
+ case GL_LUMINANCE_ALPHA16F_EXT:
+ loadLuminanceAlphaHalfFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+ break;
+ case GL_RGB8_OES:
+ loadRGBUByteDataToBGRX(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+ break;
+ case GL_RGB565:
+ loadRGB565DataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+ break;
+ case GL_RGBA8_OES:
+ if (gl::supportsSSE2())
+ {
+ loadRGBAUByteDataToBGRASSE2(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+ }
+ else
+ {
+ loadRGBAUByteDataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+ }
+ break;
+ case GL_RGBA4:
+ loadRGBA4444DataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+ break;
+ case GL_RGB5_A1:
+ loadRGBA5551DataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+ break;
+ case GL_BGRA8_EXT:
+ loadBGRADataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+ break;
+ // float textures are converted to RGBA, not BGRA, as they're stored that way in D3D
+ case GL_RGB32F_EXT:
+ loadRGBFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+ break;
+ case GL_RGB16F_EXT:
+ loadRGBHalfFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+ break;
+ case GL_RGBA32F_EXT:
+ loadRGBAFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+ break;
+ case GL_RGBA16F_EXT:
+ loadRGBAHalfFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits);
+ break;
+ default: UNREACHABLE();
+ }
+
+ unlock();
+}
+
+void Image9::loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ const void *input)
+{
+ ASSERT(xoffset % 4 == 0);
+ ASSERT(yoffset % 4 == 0);
+
+ RECT lockRect = {
+ xoffset, yoffset,
+ xoffset + width, yoffset + height
+ };
+
+ D3DLOCKED_RECT locked;
+ HRESULT result = lock(&locked, &lockRect);
+ if (FAILED(result))
+ {
+ return;
+ }
+
+ GLsizei inputSize = gl::ComputeCompressedSize(width, height, mInternalFormat);
+ GLsizei inputPitch = gl::ComputeCompressedPitch(width, mInternalFormat);
+ int rows = inputSize / inputPitch;
+ for (int i = 0; i < rows; ++i)
+ {
+ memcpy((void*)((BYTE*)locked.pBits + i * locked.Pitch), (void*)((BYTE*)input + i * inputPitch), inputPitch);
+ }
+
+ unlock();
+}
+
+// This implements glCopyTex[Sub]Image2D for non-renderable internal texture formats and incomplete textures
+void Image9::copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
+{
+ RenderTarget9 *renderTarget = NULL;
+ IDirect3DSurface9 *surface = NULL;
+ gl::Renderbuffer *colorbuffer = source->getColorbuffer(0);
+
+ if (colorbuffer)
+ {
+ renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget());
+ }
+
+ if (renderTarget)
+ {
+ surface = renderTarget->getSurface();
+ }
+
+ if (!surface)
+ {
+ ERR("Failed to retrieve the render target.");
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+
+ IDirect3DSurface9 *renderTargetData = NULL;
+ D3DSURFACE_DESC description;
+ surface->GetDesc(&description);
+
+ HRESULT result = device->CreateOffscreenPlainSurface(description.Width, description.Height, description.Format, D3DPOOL_SYSTEMMEM, &renderTargetData, NULL);
+
+ if (FAILED(result))
+ {
+ ERR("Could not create matching destination surface.");
+ surface->Release();
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+
+ result = device->GetRenderTargetData(surface, renderTargetData);
+
+ if (FAILED(result))
+ {
+ ERR("GetRenderTargetData unexpectedly failed.");
+ renderTargetData->Release();
+ surface->Release();
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+
+ RECT sourceRect = {x, y, x + width, y + height};
+ RECT destRect = {xoffset, yoffset, xoffset + width, yoffset + height};
+
+ D3DLOCKED_RECT sourceLock = {0};
+ result = renderTargetData->LockRect(&sourceLock, &sourceRect, 0);
+
+ if (FAILED(result))
+ {
+ ERR("Failed to lock the source surface (rectangle might be invalid).");
+ renderTargetData->Release();
+ surface->Release();
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+
+ D3DLOCKED_RECT destLock = {0};
+ result = lock(&destLock, &destRect);
+
+ if (FAILED(result))
+ {
+ ERR("Failed to lock the destination surface (rectangle might be invalid).");
+ renderTargetData->UnlockRect();
+ renderTargetData->Release();
+ surface->Release();
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+
+ if (destLock.pBits && sourceLock.pBits)
+ {
+ unsigned char *source = (unsigned char*)sourceLock.pBits;
+ unsigned char *dest = (unsigned char*)destLock.pBits;
+
+ switch (description.Format)
+ {
+ case D3DFMT_X8R8G8B8:
+ case D3DFMT_A8R8G8B8:
+ switch(getD3DFormat())
+ {
+ case D3DFMT_X8R8G8B8:
+ case D3DFMT_A8R8G8B8:
+ for(int y = 0; y < height; y++)
+ {
+ memcpy(dest, source, 4 * width);
+
+ source += sourceLock.Pitch;
+ dest += destLock.Pitch;
+ }
+ break;
+ case D3DFMT_L8:
+ for(int y = 0; y < height; y++)
+ {
+ for(int x = 0; x < width; x++)
+ {
+ dest[x] = source[x * 4 + 2];
+ }
+
+ source += sourceLock.Pitch;
+ dest += destLock.Pitch;
+ }
+ break;
+ case D3DFMT_A8L8:
+ for(int y = 0; y < height; y++)
+ {
+ for(int x = 0; x < width; x++)
+ {
+ dest[x * 2 + 0] = source[x * 4 + 2];
+ dest[x * 2 + 1] = source[x * 4 + 3];
+ }
+
+ source += sourceLock.Pitch;
+ dest += destLock.Pitch;
+ }
+ break;
+ default:
+ UNREACHABLE();
+ }
+ break;
+ case D3DFMT_R5G6B5:
+ switch(getD3DFormat())
+ {
+ case D3DFMT_X8R8G8B8:
+ for(int y = 0; y < height; y++)
+ {
+ for(int x = 0; x < width; x++)
+ {
+ unsigned short rgb = ((unsigned short*)source)[x];
+ unsigned char red = (rgb & 0xF800) >> 8;
+ unsigned char green = (rgb & 0x07E0) >> 3;
+ unsigned char blue = (rgb & 0x001F) << 3;
+ dest[x + 0] = blue | (blue >> 5);
+ dest[x + 1] = green | (green >> 6);
+ dest[x + 2] = red | (red >> 5);
+ dest[x + 3] = 0xFF;
+ }
+
+ source += sourceLock.Pitch;
+ dest += destLock.Pitch;
+ }
+ break;
+ case D3DFMT_L8:
+ for(int y = 0; y < height; y++)
+ {
+ for(int x = 0; x < width; x++)
+ {
+ unsigned char red = source[x * 2 + 1] & 0xF8;
+ dest[x] = red | (red >> 5);
+ }
+
+ source += sourceLock.Pitch;
+ dest += destLock.Pitch;
+ }
+ break;
+ default:
+ UNREACHABLE();
+ }
+ break;
+ case D3DFMT_A1R5G5B5:
+ switch(getD3DFormat())
+ {
+ case D3DFMT_X8R8G8B8:
+ for(int y = 0; y < height; y++)
+ {
+ for(int x = 0; x < width; x++)
+ {
+ unsigned short argb = ((unsigned short*)source)[x];
+ unsigned char red = (argb & 0x7C00) >> 7;
+ unsigned char green = (argb & 0x03E0) >> 2;
+ unsigned char blue = (argb & 0x001F) << 3;
+ dest[x + 0] = blue | (blue >> 5);
+ dest[x + 1] = green | (green >> 5);
+ dest[x + 2] = red | (red >> 5);
+ dest[x + 3] = 0xFF;
+ }
+
+ source += sourceLock.Pitch;
+ dest += destLock.Pitch;
+ }
+ break;
+ case D3DFMT_A8R8G8B8:
+ for(int y = 0; y < height; y++)
+ {
+ for(int x = 0; x < width; x++)
+ {
+ unsigned short argb = ((unsigned short*)source)[x];
+ unsigned char red = (argb & 0x7C00) >> 7;
+ unsigned char green = (argb & 0x03E0) >> 2;
+ unsigned char blue = (argb & 0x001F) << 3;
+ unsigned char alpha = (signed short)argb >> 15;
+ dest[x + 0] = blue | (blue >> 5);
+ dest[x + 1] = green | (green >> 5);
+ dest[x + 2] = red | (red >> 5);
+ dest[x + 3] = alpha;
+ }
+
+ source += sourceLock.Pitch;
+ dest += destLock.Pitch;
+ }
+ break;
+ case D3DFMT_L8:
+ for(int y = 0; y < height; y++)
+ {
+ for(int x = 0; x < width; x++)
+ {
+ unsigned char red = source[x * 2 + 1] & 0x7C;
+ dest[x] = (red << 1) | (red >> 4);
+ }
+
+ source += sourceLock.Pitch;
+ dest += destLock.Pitch;
+ }
+ break;
+ case D3DFMT_A8L8:
+ for(int y = 0; y < height; y++)
+ {
+ for(int x = 0; x < width; x++)
+ {
+ unsigned char red = source[x * 2 + 1] & 0x7C;
+ dest[x * 2 + 0] = (red << 1) | (red >> 4);
+ dest[x * 2 + 1] = (signed char)source[x * 2 + 1] >> 7;
+ }
+
+ source += sourceLock.Pitch;
+ dest += destLock.Pitch;
+ }
+ break;
+ default:
+ UNREACHABLE();
+ }
+ break;
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ unlock();
+ renderTargetData->UnlockRect();
+
+ renderTargetData->Release();
+ surface->Release();
+
+ mDirty = true;
+}
+
+}
</ins><span class="cx">\ No newline at end of file
</span><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Image9.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9Image9h"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Image9.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Image9.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Image9.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,79 @@
</span><ins>+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Image9.h: Defines the rx::Image9 class, which acts as the interface to
+// the actual underlying surfaces of a Texture.
+
+#ifndef LIBGLESV2_RENDERER_IMAGE9_H_
+#define LIBGLESV2_RENDERER_IMAGE9_H_
+
+#include "libGLESv2/renderer/Image.h"
+#include "common/debug.h"
+
+namespace gl
+{
+class Framebuffer;
+}
+
+namespace rx
+{
+class Renderer;
+class Renderer9;
+class TextureStorageInterface2D;
+class TextureStorageInterfaceCube;
+
+class Image9 : public Image
+{
+ public:
+ Image9();
+ ~Image9();
+
+ static Image9 *makeImage9(Image *img);
+
+ static void generateMipmap(Image9 *dest, Image9 *source);
+ static void generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sourceSurface);
+ static void copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *source);
+
+ virtual bool redefine(Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, bool forceRelease);
+
+ virtual bool isRenderableFormat() const;
+ D3DFORMAT getD3DFormat() const;
+
+ virtual bool isDirty() const {return mSurface && mDirty;}
+ IDirect3DSurface9 *getSurface();
+
+ virtual void setManagedSurface(TextureStorageInterface2D *storage, int level);
+ virtual void setManagedSurface(TextureStorageInterfaceCube *storage, int face, int level);
+ virtual bool updateSurface(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
+ virtual bool updateSurface(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
+
+ virtual void loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ GLint unpackAlignment, const void *input);
+ virtual void loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ const void *input);
+
+ virtual void copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Image9);
+
+ void createSurface();
+ void setManagedSurface(IDirect3DSurface9 *surface);
+ bool updateSurface(IDirect3DSurface9 *dest, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
+
+ HRESULT lock(D3DLOCKED_RECT *lockedRect, const RECT *rect);
+ void unlock();
+
+ Renderer9 *mRenderer;
+
+ D3DPOOL mD3DPool; // can only be D3DPOOL_SYSTEMMEM or D3DPOOL_MANAGED since it needs to be lockable.
+ D3DFORMAT mD3DFormat;
+
+ IDirect3DSurface9 *mSurface;
+};
+}
+
+#endif // LIBGLESV2_RENDERER_IMAGE9_H_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Image9.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9IndexBuffer9cpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/IndexBuffer9.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/IndexBuffer9.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/IndexBuffer9.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,207 @@
</span><ins>+#include "precompiled.h"
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Indexffer9.cpp: Defines the D3D9 IndexBuffer implementation.
+
+#include "libGLESv2/renderer/d3d9/IndexBuffer9.h"
+#include "libGLESv2/renderer/d3d9/Renderer9.h"
+
+namespace rx
+{
+
+IndexBuffer9::IndexBuffer9(Renderer9 *const renderer) : mRenderer(renderer)
+{
+ mIndexBuffer = NULL;
+ mBufferSize = 0;
+ mIndexType = 0;
+ mDynamic = false;
+}
+
+IndexBuffer9::~IndexBuffer9()
+{
+ if (mIndexBuffer)
+ {
+ mIndexBuffer->Release();
+ mIndexBuffer = NULL;
+ }
+}
+
+bool IndexBuffer9::initialize(unsigned int bufferSize, GLenum indexType, bool dynamic)
+{
+ if (mIndexBuffer)
+ {
+ mIndexBuffer->Release();
+ mIndexBuffer = NULL;
+ }
+
+ updateSerial();
+
+ if (bufferSize > 0)
+ {
+ D3DFORMAT format;
+ if (indexType == GL_UNSIGNED_SHORT || indexType == GL_UNSIGNED_BYTE)
+ {
+ format = D3DFMT_INDEX16;
+ }
+ else if (indexType == GL_UNSIGNED_INT)
+ {
+ if (mRenderer->get32BitIndexSupport())
+ {
+ format = D3DFMT_INDEX32;
+ }
+ else
+ {
+ ERR("Attempted to create a 32-bit index buffer but renderer does not support 32-bit indices.");
+ return false;
+ }
+ }
+ else
+ {
+ ERR("Invalid index type %u.", indexType);
+ return false;
+ }
+
+ DWORD usageFlags = D3DUSAGE_WRITEONLY;
+ if (dynamic)
+ {
+ usageFlags |= D3DUSAGE_DYNAMIC;
+ }
+
+ HRESULT result = mRenderer->createIndexBuffer(bufferSize, usageFlags, format, &mIndexBuffer);
+ if (FAILED(result))
+ {
+ ERR("Failed to create an index buffer of size %u, result: 0x%08x.", mBufferSize, result);
+ return false;
+ }
+ }
+
+ mBufferSize = bufferSize;
+ mIndexType = indexType;
+ mDynamic = dynamic;
+
+ return true;
+}
+
+IndexBuffer9 *IndexBuffer9::makeIndexBuffer9(IndexBuffer *indexBuffer)
+{
+ ASSERT(HAS_DYNAMIC_TYPE(IndexBuffer9*, indexBuffer));
+ return static_cast<IndexBuffer9*>(indexBuffer);
+}
+
+bool IndexBuffer9::mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory)
+{
+ if (mIndexBuffer)
+ {
+ DWORD lockFlags = mDynamic ? D3DLOCK_NOOVERWRITE : 0;
+
+ void *mapPtr = NULL;
+ HRESULT result = mIndexBuffer->Lock(offset, size, &mapPtr, lockFlags);
+ if (FAILED(result))
+ {
+ ERR("Index buffer lock failed with error 0x%08x", result);
+ return false;
+ }
+
+ *outMappedMemory = mapPtr;
+ return true;
+ }
+ else
+ {
+ ERR("Index buffer not initialized.");
+ return false;
+ }
+}
+
+bool IndexBuffer9::unmapBuffer()
+{
+ if (mIndexBuffer)
+ {
+ HRESULT result = mIndexBuffer->Unlock();
+ if (FAILED(result))
+ {
+ ERR("Index buffer unlock failed with error 0x%08x", result);
+ return false;
+ }
+
+ return true;
+ }
+ else
+ {
+ ERR("Index buffer not initialized.");
+ return false;
+ }
+}
+
+GLenum IndexBuffer9::getIndexType() const
+{
+ return mIndexType;
+}
+
+unsigned int IndexBuffer9::getBufferSize() const
+{
+ return mBufferSize;
+}
+
+bool IndexBuffer9::setSize(unsigned int bufferSize, GLenum indexType)
+{
+ if (bufferSize > mBufferSize || indexType != mIndexType)
+ {
+ return initialize(bufferSize, indexType, mDynamic);
+ }
+ else
+ {
+ return true;
+ }
+}
+
+bool IndexBuffer9::discard()
+{
+ if (mIndexBuffer)
+ {
+ void *dummy;
+ HRESULT result;
+
+ result = mIndexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD);
+ if (FAILED(result))
+ {
+ ERR("Discard lock failed with error 0x%08x", result);
+ return false;
+ }
+
+ result = mIndexBuffer->Unlock();
+ if (FAILED(result))
+ {
+ ERR("Discard unlock failed with error 0x%08x", result);
+ return false;
+ }
+
+ return true;
+ }
+ else
+ {
+ ERR("Index buffer not initialized.");
+ return false;
+ }
+}
+
+D3DFORMAT IndexBuffer9::getIndexFormat() const
+{
+ switch (mIndexType)
+ {
+ case GL_UNSIGNED_BYTE: return D3DFMT_INDEX16;
+ case GL_UNSIGNED_SHORT: return D3DFMT_INDEX16;
+ case GL_UNSIGNED_INT: return D3DFMT_INDEX32;
+ default: UNREACHABLE(); return D3DFMT_UNKNOWN;
+ }
+}
+
+IDirect3DIndexBuffer9 * IndexBuffer9::getBuffer() const
+{
+ return mIndexBuffer;
+}
+
+}
</ins><span class="cx">\ No newline at end of file
</span><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/IndexBuffer9.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9IndexBuffer9h"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/IndexBuffer9.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/IndexBuffer9.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/IndexBuffer9.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,53 @@
</span><ins>+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Indexffer9.h: Defines the D3D9 IndexBuffer implementation.
+
+#ifndef LIBGLESV2_RENDERER_INDEXBUFFER9_H_
+#define LIBGLESV2_RENDERER_INDEXBUFFER9_H_
+
+#include "libGLESv2/renderer/IndexBuffer.h"
+
+namespace rx
+{
+class Renderer9;
+
+class IndexBuffer9 : public IndexBuffer
+{
+ public:
+ explicit IndexBuffer9(Renderer9 *const renderer);
+ virtual ~IndexBuffer9();
+
+ virtual bool initialize(unsigned int bufferSize, GLenum indexType, bool dynamic);
+
+ static IndexBuffer9 *makeIndexBuffer9(IndexBuffer *indexBuffer);
+
+ virtual bool mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory);
+ virtual bool unmapBuffer();
+
+ virtual GLenum getIndexType() const;
+ virtual unsigned int getBufferSize() const;
+ virtual bool setSize(unsigned int bufferSize, GLenum indexType);
+
+ virtual bool discard();
+
+ D3DFORMAT getIndexFormat() const;
+ IDirect3DIndexBuffer9 *getBuffer() const;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(IndexBuffer9);
+
+ rx::Renderer9 *const mRenderer;
+
+ IDirect3DIndexBuffer9 *mIndexBuffer;
+ unsigned int mBufferSize;
+ GLenum mIndexType;
+ bool mDynamic;
+};
+
+}
+
+#endif // LIBGLESV2_RENDERER_INDEXBUFFER9_H_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/IndexBuffer9.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9Query9cpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Query9.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Query9.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Query9.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,125 @@
</span><ins>+#include "precompiled.h"
+//
+// Copyright (c) 2013 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.
+//
+
+// Query9.cpp: Defines the rx::Query9 class which implements rx::QueryImpl.
+
+
+#include "libGLESv2/renderer/d3d9/Query9.h"
+#include "libGLESv2/main.h"
+#include "libGLESv2/renderer/d3d9/renderer9_utils.h"
+#include "libGLESv2/renderer/d3d9/Renderer9.h"
+
+namespace rx
+{
+
+Query9::Query9(rx::Renderer9 *renderer, GLenum type) : QueryImpl(type)
+{
+ mRenderer = renderer;
+ mQuery = NULL;
+}
+
+Query9::~Query9()
+{
+ if (mQuery)
+ {
+ mQuery->Release();
+ mQuery = NULL;
+ }
+}
+
+void Query9::begin()
+{
+ if (mQuery == NULL)
+ {
+ if (FAILED(mRenderer->getDevice()->CreateQuery(D3DQUERYTYPE_OCCLUSION, &mQuery)))
+ {
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+ }
+
+ HRESULT result = mQuery->Issue(D3DISSUE_BEGIN);
+ ASSERT(SUCCEEDED(result));
+}
+
+void Query9::end()
+{
+ if (mQuery == NULL)
+ {
+ return gl::error(GL_INVALID_OPERATION);
+ }
+
+ HRESULT result = mQuery->Issue(D3DISSUE_END);
+ ASSERT(SUCCEEDED(result));
+
+ mStatus = GL_FALSE;
+ mResult = GL_FALSE;
+}
+
+GLuint Query9::getResult()
+{
+ if (mQuery != NULL)
+ {
+ while (!testQuery())
+ {
+ Sleep(0);
+ // explicitly check for device loss
+ // some drivers seem to return S_FALSE even if the device is lost
+ // instead of D3DERR_DEVICELOST like they should
+ if (mRenderer->testDeviceLost(true))
+ {
+ return gl::error(GL_OUT_OF_MEMORY, 0);
+ }
+ }
+ }
+
+ return mResult;
+}
+
+GLboolean Query9::isResultAvailable()
+{
+ if (mQuery != NULL)
+ {
+ testQuery();
+ }
+
+ return mStatus;
+}
+
+GLboolean Query9::testQuery()
+{
+ if (mQuery != NULL && mStatus != GL_TRUE)
+ {
+ DWORD numPixels = 0;
+
+ HRESULT hres = mQuery->GetData(&numPixels, sizeof(DWORD), D3DGETDATA_FLUSH);
+ if (hres == S_OK)
+ {
+ mStatus = GL_TRUE;
+
+ switch (getType())
+ {
+ case GL_ANY_SAMPLES_PASSED_EXT:
+ case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
+ mResult = (numPixels > 0) ? GL_TRUE : GL_FALSE;
+ break;
+ default:
+ ASSERT(false);
+ }
+ }
+ else if (d3d9::isDeviceLostError(hres))
+ {
+ mRenderer->notifyDeviceLost();
+ return gl::error(GL_OUT_OF_MEMORY, GL_TRUE);
+ }
+
+ return mStatus;
+ }
+
+ return GL_TRUE; // prevent blocking when query is null
+}
+
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Query9.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9Query9h"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Query9.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Query9.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Query9.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,40 @@
</span><ins>+//
+// Copyright (c) 2013 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.
+//
+
+// Query9.h: Defines the rx::Query9 class which implements rx::QueryImpl.
+
+#ifndef LIBGLESV2_RENDERER_QUERY9_H_
+#define LIBGLESV2_RENDERER_QUERY9_H_
+
+#include "libGLESv2/renderer/QueryImpl.h"
+
+namespace rx
+{
+class Renderer9;
+
+class Query9 : public QueryImpl
+{
+ public:
+ Query9(rx::Renderer9 *renderer, GLenum type);
+ virtual ~Query9();
+
+ void begin();
+ void end();
+ GLuint getResult();
+ GLboolean isResultAvailable();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Query9);
+
+ GLboolean testQuery();
+
+ rx::Renderer9 *mRenderer;
+ IDirect3DQuery9 *mQuery;
+};
+
+}
+
+#endif // LIBGLESV2_RENDERER_QUERY9_H_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Query9.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9RenderTarget9cpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/RenderTarget9.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/RenderTarget9.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/RenderTarget9.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,113 @@
</span><ins>+#include "precompiled.h"
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RenderTarget9.cpp: Implements a D3D9-specific wrapper for IDirect3DSurface9
+// pointers retained by renderbuffers.
+
+#include "libGLESv2/renderer/d3d9/RenderTarget9.h"
+#include "libGLESv2/renderer/d3d9/Renderer9.h"
+
+#include "libGLESv2/renderer/d3d9/renderer9_utils.h"
+#include "libGLESv2/main.h"
+
+namespace rx
+{
+
+RenderTarget9::RenderTarget9(Renderer *renderer, IDirect3DSurface9 *surface)
+{
+ mRenderer = Renderer9::makeRenderer9(renderer);
+ mRenderTarget = surface;
+
+ if (mRenderTarget)
+ {
+ D3DSURFACE_DESC description;
+ mRenderTarget->GetDesc(&description);
+
+ mWidth = description.Width;
+ mHeight = description.Height;
+
+ mInternalFormat = d3d9_gl::GetEquivalentFormat(description.Format);
+ mActualFormat = d3d9_gl::GetEquivalentFormat(description.Format);
+ mSamples = d3d9_gl::GetSamplesFromMultisampleType(description.MultiSampleType);
+ }
+}
+
+RenderTarget9::RenderTarget9(Renderer *renderer, GLsizei width, GLsizei height, GLenum format, GLsizei samples)
+{
+ mRenderer = Renderer9::makeRenderer9(renderer);
+ mRenderTarget = NULL;
+
+ D3DFORMAT requestedFormat = gl_d3d9::ConvertRenderbufferFormat(format);
+ int supportedSamples = mRenderer->getNearestSupportedSamples(requestedFormat, samples);
+
+ if (supportedSamples == -1)
+ {
+ gl::error(GL_OUT_OF_MEMORY);
+
+ return;
+ }
+
+ HRESULT result = D3DERR_INVALIDCALL;
+
+ if (width > 0 && height > 0)
+ {
+ if (requestedFormat == D3DFMT_D24S8)
+ {
+ result = mRenderer->getDevice()->CreateDepthStencilSurface(width, height, requestedFormat,
+ gl_d3d9::GetMultisampleTypeFromSamples(supportedSamples),
+ 0, FALSE, &mRenderTarget, NULL);
+ }
+ else
+ {
+ result = mRenderer->getDevice()->CreateRenderTarget(width, height, requestedFormat,
+ gl_d3d9::GetMultisampleTypeFromSamples(supportedSamples),
+ 0, FALSE, &mRenderTarget, NULL);
+ }
+
+ if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
+ {
+ gl::error(GL_OUT_OF_MEMORY);
+
+ return;
+ }
+
+ ASSERT(SUCCEEDED(result));
+ }
+
+ mWidth = width;
+ mHeight = height;
+ mInternalFormat = format;
+ mSamples = supportedSamples;
+ mActualFormat = d3d9_gl::GetEquivalentFormat(requestedFormat);
+}
+
+RenderTarget9::~RenderTarget9()
+{
+ if (mRenderTarget)
+ {
+ mRenderTarget->Release();
+ }
+}
+
+RenderTarget9 *RenderTarget9::makeRenderTarget9(RenderTarget *target)
+{
+ ASSERT(HAS_DYNAMIC_TYPE(rx::RenderTarget9*, target));
+ return static_cast<rx::RenderTarget9*>(target);
+}
+
+IDirect3DSurface9 *RenderTarget9::getSurface()
+{
+ // Caller is responsible for releasing the returned surface reference.
+ if (mRenderTarget)
+ {
+ mRenderTarget->AddRef();
+ }
+
+ return mRenderTarget;
+}
+
+}
</ins><span class="cx">\ No newline at end of file
</span><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/RenderTarget9.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9RenderTarget9h"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/RenderTarget9.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/RenderTarget9.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/RenderTarget9.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,40 @@
</span><ins>+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RenderTarget9.h: Defines a D3D9-specific wrapper for IDirect3DSurface9 pointers
+// retained by Renderbuffers.
+
+#ifndef LIBGLESV2_RENDERER_RENDERTARGET9_H_
+#define LIBGLESV2_RENDERER_RENDERTARGET9_H_
+
+#include "libGLESv2/renderer/RenderTarget.h"
+
+namespace rx
+{
+class Renderer;
+class Renderer9;
+
+class RenderTarget9 : public RenderTarget
+{
+ public:
+ RenderTarget9(Renderer *renderer, IDirect3DSurface9 *surface);
+ RenderTarget9(Renderer *renderer, GLsizei width, GLsizei height, GLenum format, GLsizei samples);
+ virtual ~RenderTarget9();
+
+ static RenderTarget9 *makeRenderTarget9(RenderTarget *renderTarget);
+ IDirect3DSurface9 *getSurface();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(RenderTarget9);
+
+ IDirect3DSurface9 *mRenderTarget;
+
+ Renderer9 *mRenderer;
+};
+
+}
+
+#endif // LIBGLESV2_RENDERER_RENDERTARGET9_H_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/RenderTarget9.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9Renderer9cpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Renderer9.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Renderer9.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Renderer9.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,3287 @@
</span><ins>+#include "precompiled.h"
+//
+// Copyright (c) 2012-2013 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.
+//
+
+// Renderer9.cpp: Implements a back-end specific class for the D3D9 renderer.
+
+#include "libGLESv2/main.h"
+#include "libGLESv2/Buffer.h"
+#include "libGLESv2/Texture.h"
+#include "libGLESv2/Framebuffer.h"
+#include "libGLESv2/Renderbuffer.h"
+#include "libGLESv2/ProgramBinary.h"
+#include "libGLESv2/renderer/IndexDataManager.h"
+#include "libGLESv2/renderer/d3d9/Renderer9.h"
+#include "libGLESv2/renderer/d3d9/renderer9_utils.h"
+#include "libGLESv2/renderer/d3d9/ShaderExecutable9.h"
+#include "libGLESv2/renderer/d3d9/SwapChain9.h"
+#include "libGLESv2/renderer/d3d9/TextureStorage9.h"
+#include "libGLESv2/renderer/d3d9/Image9.h"
+#include "libGLESv2/renderer/d3d9/Blit.h"
+#include "libGLESv2/renderer/d3d9/RenderTarget9.h"
+#include "libGLESv2/renderer/d3d9/VertexBuffer9.h"
+#include "libGLESv2/renderer/d3d9/IndexBuffer9.h"
+#include "libGLESv2/renderer/d3d9/BufferStorage9.h"
+#include "libGLESv2/renderer/d3d9/Query9.h"
+#include "libGLESv2/renderer/d3d9/Fence9.h"
+
+#include "libEGL/Display.h"
+
+#include "third_party/trace_event/trace_event.h"
+
+// Can also be enabled by defining FORCE_REF_RAST in the project's predefined macros
+#define REF_RAST 0
+
+// 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_ENABLE_D3D9EX=0" in your project file.
+#if !defined(ANGLE_ENABLE_D3D9EX)
+// Enables use of the IDirect3D9Ex interface, when available
+#define ANGLE_ENABLE_D3D9EX 1
+#endif // !defined(ANGLE_ENABLE_D3D9EX)
+
+namespace rx
+{
+static const D3DFORMAT RenderTargetFormats[] =
+ {
+ D3DFMT_A1R5G5B5,
+ // D3DFMT_A2R10G10B10, // The color_ramp conformance test uses ReadPixels with UNSIGNED_BYTE causing it to think that rendering skipped a colour value.
+ D3DFMT_A8R8G8B8,
+ D3DFMT_R5G6B5,
+ // D3DFMT_X1R5G5B5, // Has no compatible OpenGL ES renderbuffer format
+ D3DFMT_X8R8G8B8
+ };
+
+static const D3DFORMAT DepthStencilFormats[] =
+ {
+ D3DFMT_UNKNOWN,
+ // D3DFMT_D16_LOCKABLE,
+ D3DFMT_D32,
+ // D3DFMT_D15S1,
+ D3DFMT_D24S8,
+ D3DFMT_D24X8,
+ // D3DFMT_D24X4S4,
+ D3DFMT_D16,
+ // D3DFMT_D32F_LOCKABLE,
+ // D3DFMT_D24FS8
+ };
+
+enum
+{
+ MAX_VERTEX_CONSTANT_VECTORS_D3D9 = 256,
+ MAX_PIXEL_CONSTANT_VECTORS_SM2 = 32,
+ MAX_PIXEL_CONSTANT_VECTORS_SM3 = 224,
+ MAX_VARYING_VECTORS_SM2 = 8,
+ MAX_VARYING_VECTORS_SM3 = 10,
+
+ MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 = 4
+};
+
+Renderer9::Renderer9(egl::Display *display, HDC hDc, bool softwareDevice) : Renderer(display), mDc(hDc), mSoftwareDevice(softwareDevice)
+{
+ mD3d9Module = NULL;
+
+ mD3d9 = NULL;
+ mD3d9Ex = NULL;
+ mDevice = NULL;
+ mDeviceEx = NULL;
+ mDeviceWindow = NULL;
+ mBlit = NULL;
+
+ mAdapter = D3DADAPTER_DEFAULT;
+
+ #if REF_RAST == 1 || defined(FORCE_REF_RAST)
+ mDeviceType = D3DDEVTYPE_REF;
+ #else
+ mDeviceType = D3DDEVTYPE_HAL;
+ #endif
+
+ mDeviceLost = false;
+
+ mMaxSupportedSamples = 0;
+
+ mMaskedClearSavedState = NULL;
+
+ mVertexDataManager = NULL;
+ mIndexDataManager = NULL;
+ mLineLoopIB = NULL;
+
+ mMaxNullColorbufferLRU = 0;
+ for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++)
+ {
+ mNullColorbufferCache[i].lruCount = 0;
+ mNullColorbufferCache[i].width = 0;
+ mNullColorbufferCache[i].height = 0;
+ mNullColorbufferCache[i].buffer = NULL;
+ }
+}
+
+Renderer9::~Renderer9()
+{
+ if (mDevice)
+ {
+ // If the device is lost, reset it first to prevent leaving the driver in an unstable state
+ if (testDeviceLost(false))
+ {
+ resetDevice();
+ }
+ }
+
+ deinitialize();
+}
+
+void Renderer9::deinitialize()
+{
+ releaseDeviceResources();
+
+ SafeRelease(mDevice);
+ SafeRelease(mDeviceEx);
+ SafeRelease(mD3d9);
+ SafeRelease(mD3d9Ex);
+
+ if (mDeviceWindow)
+ {
+ DestroyWindow(mDeviceWindow);
+ mDeviceWindow = NULL;
+ }
+
+ if (mD3d9Module)
+ {
+ mD3d9Module = NULL;
+ }
+
+ while (!mMultiSampleSupport.empty())
+ {
+ delete [] mMultiSampleSupport.begin()->second;
+ mMultiSampleSupport.erase(mMultiSampleSupport.begin());
+ }
+}
+
+Renderer9 *Renderer9::makeRenderer9(Renderer *renderer)
+{
+ ASSERT(HAS_DYNAMIC_TYPE(rx::Renderer9*, renderer));
+ return static_cast<rx::Renderer9*>(renderer);
+}
+
+EGLint Renderer9::initialize()
+{
+ if (!initializeCompiler())
+ {
+ return EGL_NOT_INITIALIZED;
+ }
+
+ if (mSoftwareDevice)
+ {
+ TRACE_EVENT0("gpu", "GetModuleHandle_swiftshader");
+ mD3d9Module = GetModuleHandle(TEXT("swiftshader_d3d9.dll"));
+ }
+ else
+ {
+ TRACE_EVENT0("gpu", "GetModuleHandle_d3d9");
+ mD3d9Module = GetModuleHandle(TEXT("d3d9.dll"));
+ }
+
+ if (mD3d9Module == NULL)
+ {
+ ERR("No D3D9 module found - aborting!\n");
+ return EGL_NOT_INITIALIZED;
+ }
+
+ typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex**);
+ Direct3DCreate9ExFunc Direct3DCreate9ExPtr = reinterpret_cast<Direct3DCreate9ExFunc>(GetProcAddress(mD3d9Module, "Direct3DCreate9Ex"));
+
+ // Use Direct3D9Ex if available. Among other things, this version is less
+ // inclined to report a lost context, for example when the user switches
+ // desktop. Direct3D9Ex is available in Windows Vista and later if suitable drivers are available.
+ if (ANGLE_ENABLE_D3D9EX && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex)))
+ {
+ TRACE_EVENT0("gpu", "D3d9Ex_QueryInterface");
+ ASSERT(mD3d9Ex);
+ mD3d9Ex->QueryInterface(IID_IDirect3D9, reinterpret_cast<void**>(&mD3d9));
+ ASSERT(mD3d9);
+ }
+ else
+ {
+ TRACE_EVENT0("gpu", "Direct3DCreate9");
+ mD3d9 = Direct3DCreate9(D3D_SDK_VERSION);
+ }
+
+ if (!mD3d9)
+ {
+ ERR("Could not create D3D9 device - aborting!\n");
+ return EGL_NOT_INITIALIZED;
+ }
+
+ if (mDc != NULL)
+ {
+ // UNIMPLEMENTED(); // FIXME: Determine which adapter index the device context corresponds to
+ }
+
+ HRESULT result;
+
+ // Give up on getting device caps after about one second.
+ {
+ TRACE_EVENT0("gpu", "GetDeviceCaps");
+ for (int i = 0; i < 10; ++i)
+ {
+ result = mD3d9->GetDeviceCaps(mAdapter, mDeviceType, &mDeviceCaps);
+ if (SUCCEEDED(result))
+ {
+ break;
+ }
+ else if (result == D3DERR_NOTAVAILABLE)
+ {
+ Sleep(100); // Give the driver some time to initialize/recover
+ }
+ else if (FAILED(result)) // D3DERR_OUTOFVIDEOMEMORY, E_OUTOFMEMORY, D3DERR_INVALIDDEVICE, or another error we can't recover from
+ {
+ ERR("failed to get device caps (0x%x)\n", result);
+ return EGL_NOT_INITIALIZED;
+ }
+ }
+ }
+
+ if (mDeviceCaps.PixelShaderVersion < D3DPS_VERSION(2, 0))
+ {
+ ERR("Renderer does not support PS 2.0. aborting!\n");
+ return EGL_NOT_INITIALIZED;
+ }
+
+ // When DirectX9 is running with an older DirectX8 driver, a StretchRect from a regular texture to a render target texture is not supported.
+ // This is required by Texture2D::convertToRenderTarget.
+ if ((mDeviceCaps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES) == 0)
+ {
+ ERR("Renderer does not support stretctrect from textures!\n");
+ return EGL_NOT_INITIALIZED;
+ }
+
+ {
+ TRACE_EVENT0("gpu", "GetAdapterIdentifier");
+ mD3d9->GetAdapterIdentifier(mAdapter, 0, &mAdapterIdentifier);
+ }
+
+ // ATI cards on XP have problems with non-power-of-two textures.
+ mSupportsNonPower2Textures = !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_POW2) &&
+ !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) &&
+ !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) &&
+ !(getComparableOSVersion() < versionWindowsVista && mAdapterIdentifier.VendorId == VENDOR_ID_AMD);
+
+ // Must support a minimum of 2:1 anisotropy for max anisotropy to be considered supported, per the spec
+ mSupportsTextureFilterAnisotropy = ((mDeviceCaps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) && (mDeviceCaps.MaxAnisotropy >= 2));
+
+ mMinSwapInterval = 4;
+ mMaxSwapInterval = 0;
+
+ if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE)
+ {
+ mMinSwapInterval = std::min(mMinSwapInterval, 0);
+ mMaxSwapInterval = std::max(mMaxSwapInterval, 0);
+ }
+ if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_ONE)
+ {
+ mMinSwapInterval = std::min(mMinSwapInterval, 1);
+ mMaxSwapInterval = std::max(mMaxSwapInterval, 1);
+ }
+ if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_TWO)
+ {
+ mMinSwapInterval = std::min(mMinSwapInterval, 2);
+ mMaxSwapInterval = std::max(mMaxSwapInterval, 2);
+ }
+ if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_THREE)
+ {
+ mMinSwapInterval = std::min(mMinSwapInterval, 3);
+ mMaxSwapInterval = std::max(mMaxSwapInterval, 3);
+ }
+ if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_FOUR)
+ {
+ mMinSwapInterval = std::min(mMinSwapInterval, 4);
+ mMaxSwapInterval = std::max(mMaxSwapInterval, 4);
+ }
+
+ int max = 0;
+ {
+ TRACE_EVENT0("gpu", "getMultiSampleSupport");
+ for (unsigned int i = 0; i < ArraySize(RenderTargetFormats); ++i)
+ {
+ bool *multisampleArray = new bool[D3DMULTISAMPLE_16_SAMPLES + 1];
+ getMultiSampleSupport(RenderTargetFormats[i], multisampleArray);
+ mMultiSampleSupport[RenderTargetFormats[i]] = multisampleArray;
+
+ for (int j = D3DMULTISAMPLE_16_SAMPLES; j >= 0; --j)
+ {
+ if (multisampleArray[j] && j != D3DMULTISAMPLE_NONMASKABLE && j > max)
+ {
+ max = j;
+ }
+ }
+ }
+ }
+
+ {
+ TRACE_EVENT0("gpu", "getMultiSampleSupport2");
+ for (unsigned int i = 0; i < ArraySize(DepthStencilFormats); ++i)
+ {
+ if (DepthStencilFormats[i] == D3DFMT_UNKNOWN)
+ continue;
+
+ bool *multisampleArray = new bool[D3DMULTISAMPLE_16_SAMPLES + 1];
+ getMultiSampleSupport(DepthStencilFormats[i], multisampleArray);
+ mMultiSampleSupport[DepthStencilFormats[i]] = multisampleArray;
+
+ for (int j = D3DMULTISAMPLE_16_SAMPLES; j >= 0; --j)
+ {
+ if (multisampleArray[j] && j != D3DMULTISAMPLE_NONMASKABLE && j > max)
+ {
+ max = j;
+ }
+ }
+ }
+ }
+
+ mMaxSupportedSamples = max;
+
+ static const TCHAR windowName[] = TEXT("AngleHiddenWindow");
+ static const TCHAR className[] = TEXT("STATIC");
+
+ {
+ TRACE_EVENT0("gpu", "CreateWindowEx");
+ mDeviceWindow = CreateWindowEx(WS_EX_NOACTIVATE, className, windowName, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL);
+ }
+
+ D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters();
+ DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES;
+
+ {
+ TRACE_EVENT0("gpu", "D3d9_CreateDevice");
+ result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &presentParameters, &mDevice);
+ }
+ if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DEVICELOST)
+ {
+ return EGL_BAD_ALLOC;
+ }
+
+ if (FAILED(result))
+ {
+ TRACE_EVENT0("gpu", "D3d9_CreateDevice2");
+ result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParameters, &mDevice);
+
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_NOTAVAILABLE || result == D3DERR_DEVICELOST);
+ return EGL_BAD_ALLOC;
+ }
+ }
+
+ if (mD3d9Ex)
+ {
+ TRACE_EVENT0("gpu", "mDevice_QueryInterface");
+ result = mDevice->QueryInterface(IID_IDirect3DDevice9Ex, (void**) &mDeviceEx);
+ ASSERT(SUCCEEDED(result));
+ }
+
+ {
+ TRACE_EVENT0("gpu", "ShaderCache initialize");
+ mVertexShaderCache.initialize(mDevice);
+ mPixelShaderCache.initialize(mDevice);
+ }
+
+ // Check occlusion query support
+ IDirect3DQuery9 *occlusionQuery = NULL;
+ {
+ TRACE_EVENT0("gpu", "device_CreateQuery");
+ if (SUCCEEDED(mDevice->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery)) && occlusionQuery)
+ {
+ occlusionQuery->Release();
+ mOcclusionQuerySupport = true;
+ }
+ else
+ {
+ mOcclusionQuerySupport = false;
+ }
+ }
+
+ // Check event query support
+ IDirect3DQuery9 *eventQuery = NULL;
+ {
+ TRACE_EVENT0("gpu", "device_CreateQuery2");
+ if (SUCCEEDED(mDevice->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery)) && eventQuery)
+ {
+ eventQuery->Release();
+ mEventQuerySupport = true;
+ }
+ else
+ {
+ mEventQuerySupport = false;
+ }
+ }
+
+ D3DDISPLAYMODE currentDisplayMode;
+ mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
+
+ // Check vertex texture support
+ // Only Direct3D 10 ready devices support all the necessary vertex texture formats.
+ // We test this using D3D9 by checking support for the R16F format.
+ mVertexTextureSupport = mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0) &&
+ SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format,
+ D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, D3DFMT_R16F));
+
+ // Check depth texture support
+ // we use INTZ for depth textures in Direct3D9
+ // we also want NULL texture support to ensure the we can make depth-only FBOs
+ // see http://aras-p.info/texts/D3D9GPUHacks.html
+ mDepthTextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format,
+ D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, D3DFMT_INTZ)) &&
+ SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format,
+ D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, D3DFMT_NULL));
+
+ // Check 32 bit floating point texture support
+ mFloat32FilterSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
+ D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) &&
+ SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
+ D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F));
+
+ mFloat32RenderSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
+ D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) &&
+ SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
+ D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F));
+
+ if (!mFloat32FilterSupport && !mFloat32RenderSupport)
+ {
+ mFloat32TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
+ D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) &&
+ SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
+ D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F));
+ }
+ else
+ {
+ mFloat32TextureSupport = true;
+ }
+
+ // Check 16 bit floating point texture support
+ mFloat16FilterSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
+ D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) &&
+ SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER,
+ D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F));
+
+ mFloat16RenderSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
+ D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) &&
+ SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET,
+ D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F));
+
+ if (!mFloat16FilterSupport && !mFloat16RenderSupport)
+ {
+ mFloat16TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
+ D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) &&
+ SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0,
+ D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F));
+ }
+ else
+ {
+ mFloat16TextureSupport = true;
+ }
+
+ // Check DXT texture support
+ mDXT1TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT1));
+ mDXT3TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT3));
+ mDXT5TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT5));
+
+ // Check luminance[alpha] texture support
+ mLuminanceTextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_L8));
+ mLuminanceAlphaTextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_A8L8));
+
+ initializeDevice();
+
+ return EGL_SUCCESS;
+}
+
+// do any one-time device initialization
+// NOTE: this is also needed after a device lost/reset
+// to reset the scene status and ensure the default states are reset.
+void Renderer9::initializeDevice()
+{
+ // Permanent non-default states
+ mDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE);
+ mDevice->SetRenderState(D3DRS_LASTPIXEL, FALSE);
+
+ if (mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0))
+ {
+ mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, (DWORD&)mDeviceCaps.MaxPointSize);
+ }
+ else
+ {
+ mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, 0x3F800000); // 1.0f
+ }
+
+ markAllStateDirty();
+
+ mSceneStarted = false;
+
+ ASSERT(!mBlit && !mVertexDataManager && !mIndexDataManager);
+ mBlit = new Blit(this);
+ mVertexDataManager = new rx::VertexDataManager(this);
+ mIndexDataManager = new rx::IndexDataManager(this);
+}
+
+D3DPRESENT_PARAMETERS Renderer9::getDefaultPresentParameters()
+{
+ D3DPRESENT_PARAMETERS presentParameters = {0};
+
+ // The default swap chain is never actually used. Surface will create a new swap chain with the proper parameters.
+ presentParameters.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
+ presentParameters.BackBufferCount = 1;
+ presentParameters.BackBufferFormat = D3DFMT_UNKNOWN;
+ presentParameters.BackBufferWidth = 1;
+ presentParameters.BackBufferHeight = 1;
+ presentParameters.EnableAutoDepthStencil = FALSE;
+ presentParameters.Flags = 0;
+ presentParameters.hDeviceWindow = mDeviceWindow;
+ presentParameters.MultiSampleQuality = 0;
+ presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE;
+ presentParameters.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
+ presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
+ presentParameters.Windowed = TRUE;
+
+ return presentParameters;
+}
+
+int Renderer9::generateConfigs(ConfigDesc **configDescList)
+{
+ D3DDISPLAYMODE currentDisplayMode;
+ mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
+
+ unsigned int numRenderFormats = ArraySize(RenderTargetFormats);
+ unsigned int numDepthFormats = ArraySize(DepthStencilFormats);
+ (*configDescList) = new ConfigDesc[numRenderFormats * numDepthFormats];
+ int numConfigs = 0;
+
+ for (unsigned int formatIndex = 0; formatIndex < numRenderFormats; formatIndex++)
+ {
+ D3DFORMAT renderTargetFormat = RenderTargetFormats[formatIndex];
+
+ HRESULT result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, renderTargetFormat);
+
+ if (SUCCEEDED(result))
+ {
+ for (unsigned int depthStencilIndex = 0; depthStencilIndex < numDepthFormats; depthStencilIndex++)
+ {
+ D3DFORMAT depthStencilFormat = DepthStencilFormats[depthStencilIndex];
+ HRESULT result = D3D_OK;
+
+ if(depthStencilFormat != D3DFMT_UNKNOWN)
+ {
+ result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, depthStencilFormat);
+ }
+
+ if (SUCCEEDED(result))
+ {
+ if(depthStencilFormat != D3DFMT_UNKNOWN)
+ {
+ result = mD3d9->CheckDepthStencilMatch(mAdapter, mDeviceType, currentDisplayMode.Format, renderTargetFormat, depthStencilFormat);
+ }
+
+ if (SUCCEEDED(result))
+ {
+ ConfigDesc newConfig;
+ newConfig.renderTargetFormat = d3d9_gl::ConvertBackBufferFormat(renderTargetFormat);
+ newConfig.depthStencilFormat = d3d9_gl::ConvertDepthStencilFormat(depthStencilFormat);
+ newConfig.multiSample = 0; // FIXME: enumerate multi-sampling
+ newConfig.fastConfig = (currentDisplayMode.Format == renderTargetFormat);
+
+ (*configDescList)[numConfigs++] = newConfig;
+ }
+ }
+ }
+ }
+ }
+
+ return numConfigs;
+}
+
+void Renderer9::deleteConfigs(ConfigDesc *configDescList)
+{
+ delete [] (configDescList);
+}
+
+void Renderer9::startScene()
+{
+ if (!mSceneStarted)
+ {
+ long result = mDevice->BeginScene();
+ if (SUCCEEDED(result)) {
+ // This is defensive checking against the device being
+ // lost at unexpected times.
+ mSceneStarted = true;
+ }
+ }
+}
+
+void Renderer9::endScene()
+{
+ if (mSceneStarted)
+ {
+ // EndScene can fail if the device was lost, for example due
+ // to a TDR during a draw call.
+ mDevice->EndScene();
+ mSceneStarted = false;
+ }
+}
+
+void Renderer9::sync(bool block)
+{
+ HRESULT result;
+
+ IDirect3DQuery9* query = allocateEventQuery();
+ if (!query)
+ {
+ return;
+ }
+
+ result = query->Issue(D3DISSUE_END);
+ ASSERT(SUCCEEDED(result));
+
+ do
+ {
+ result = query->GetData(NULL, 0, D3DGETDATA_FLUSH);
+
+ if(block && result == S_FALSE)
+ {
+ // Keep polling, but allow other threads to do something useful first
+ Sleep(0);
+ // explicitly check for device loss
+ // some drivers seem to return S_FALSE even if the device is lost
+ // instead of D3DERR_DEVICELOST like they should
+ if (testDeviceLost(false))
+ {
+ result = D3DERR_DEVICELOST;
+ }
+ }
+ }
+ while(block && result == S_FALSE);
+
+ freeEventQuery(query);
+
+ if (d3d9::isDeviceLostError(result))
+ {
+ notifyDeviceLost();
+ }
+}
+
+SwapChain *Renderer9::createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat)
+{
+ return new rx::SwapChain9(this, window, shareHandle, backBufferFormat, depthBufferFormat);
+}
+
+IDirect3DQuery9* Renderer9::allocateEventQuery()
+{
+ IDirect3DQuery9 *query = NULL;
+
+ if (mEventQueryPool.empty())
+ {
+ HRESULT result = mDevice->CreateQuery(D3DQUERYTYPE_EVENT, &query);
+ ASSERT(SUCCEEDED(result));
+ }
+ else
+ {
+ query = mEventQueryPool.back();
+ mEventQueryPool.pop_back();
+ }
+
+ return query;
+}
+
+void Renderer9::freeEventQuery(IDirect3DQuery9* query)
+{
+ if (mEventQueryPool.size() > 1000)
+ {
+ query->Release();
+ }
+ else
+ {
+ mEventQueryPool.push_back(query);
+ }
+}
+
+IDirect3DVertexShader9 *Renderer9::createVertexShader(const DWORD *function, size_t length)
+{
+ return mVertexShaderCache.create(function, length);
+}
+
+IDirect3DPixelShader9 *Renderer9::createPixelShader(const DWORD *function, size_t length)
+{
+ return mPixelShaderCache.create(function, length);
+}
+
+HRESULT Renderer9::createVertexBuffer(UINT Length, DWORD Usage, IDirect3DVertexBuffer9 **ppVertexBuffer)
+{
+ D3DPOOL Pool = getBufferPool(Usage);
+ return mDevice->CreateVertexBuffer(Length, Usage, 0, Pool, ppVertexBuffer, NULL);
+}
+
+VertexBuffer *Renderer9::createVertexBuffer()
+{
+ return new VertexBuffer9(this);
+}
+
+HRESULT Renderer9::createIndexBuffer(UINT Length, DWORD Usage, D3DFORMAT Format, IDirect3DIndexBuffer9 **ppIndexBuffer)
+{
+ D3DPOOL Pool = getBufferPool(Usage);
+ return mDevice->CreateIndexBuffer(Length, Usage, Format, Pool, ppIndexBuffer, NULL);
+}
+
+IndexBuffer *Renderer9::createIndexBuffer()
+{
+ return new IndexBuffer9(this);
+}
+
+BufferStorage *Renderer9::createBufferStorage()
+{
+ return new BufferStorage9();
+}
+
+QueryImpl *Renderer9::createQuery(GLenum type)
+{
+ return new Query9(this, type);
+}
+
+FenceImpl *Renderer9::createFence()
+{
+ return new Fence9(this);
+}
+
+void Renderer9::setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &samplerState)
+{
+ bool *forceSetSamplers = (type == gl::SAMPLER_PIXEL) ? mForceSetPixelSamplerStates : mForceSetVertexSamplerStates;
+ gl::SamplerState *appliedSamplers = (type == gl::SAMPLER_PIXEL) ? mCurPixelSamplerStates: mCurVertexSamplerStates;
+
+ if (forceSetSamplers[index] || memcmp(&samplerState, &appliedSamplers[index], sizeof(gl::SamplerState)) != 0)
+ {
+ int d3dSamplerOffset = (type == gl::SAMPLER_PIXEL) ? 0 : D3DVERTEXTEXTURESAMPLER0;
+ int d3dSampler = index + d3dSamplerOffset;
+
+ mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSU, gl_d3d9::ConvertTextureWrap(samplerState.wrapS));
+ mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSV, gl_d3d9::ConvertTextureWrap(samplerState.wrapT));
+
+ mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAGFILTER, gl_d3d9::ConvertMagFilter(samplerState.magFilter, samplerState.maxAnisotropy));
+ D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter;
+ gl_d3d9::ConvertMinFilter(samplerState.minFilter, &d3dMinFilter, &d3dMipFilter, samplerState.maxAnisotropy);
+ mDevice->SetSamplerState(d3dSampler, D3DSAMP_MINFILTER, d3dMinFilter);
+ mDevice->SetSamplerState(d3dSampler, D3DSAMP_MIPFILTER, d3dMipFilter);
+ mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXMIPLEVEL, samplerState.lodOffset);
+ if (mSupportsTextureFilterAnisotropy)
+ {
+ mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXANISOTROPY, (DWORD)samplerState.maxAnisotropy);
+ }
+ }
+
+ forceSetSamplers[index] = false;
+ appliedSamplers[index] = samplerState;
+}
+
+void Renderer9::setTexture(gl::SamplerType type, int index, gl::Texture *texture)
+{
+ int d3dSamplerOffset = (type == gl::SAMPLER_PIXEL) ? 0 : D3DVERTEXTEXTURESAMPLER0;
+ int d3dSampler = index + d3dSamplerOffset;
+ IDirect3DBaseTexture9 *d3dTexture = NULL;
+ unsigned int serial = 0;
+ bool forceSetTexture = false;
+
+ unsigned int *appliedSerials = (type == gl::SAMPLER_PIXEL) ? mCurPixelTextureSerials : mCurVertexTextureSerials;
+
+ if (texture)
+ {
+ TextureStorageInterface *texStorage = texture->getNativeTexture();
+ if (texStorage)
+ {
+ TextureStorage9 *storage9 = TextureStorage9::makeTextureStorage9(texStorage->getStorageInstance());
+ d3dTexture = storage9->getBaseTexture();
+ }
+ // If we get NULL back from getBaseTexture here, something went wrong
+ // in the texture class and we're unexpectedly missing the d3d texture
+ ASSERT(d3dTexture != NULL);
+
+ serial = texture->getTextureSerial();
+ forceSetTexture = texture->hasDirtyImages();
+ }
+
+ if (forceSetTexture || appliedSerials[index] != serial)
+ {
+ mDevice->SetTexture(d3dSampler, d3dTexture);
+ }
+
+ appliedSerials[index] = serial;
+}
+
+void Renderer9::setRasterizerState(const gl::RasterizerState &rasterState)
+{
+ bool rasterStateChanged = mForceSetRasterState || memcmp(&rasterState, &mCurRasterState, sizeof(gl::RasterizerState)) != 0;
+
+ if (rasterStateChanged)
+ {
+ // Set the cull mode
+ if (rasterState.cullFace)
+ {
+ mDevice->SetRenderState(D3DRS_CULLMODE, gl_d3d9::ConvertCullMode(rasterState.cullMode, rasterState.frontFace));
+ }
+ else
+ {
+ mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
+ }
+
+ if (rasterState.polygonOffsetFill)
+ {
+ if (mCurDepthSize > 0)
+ {
+ mDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *(DWORD*)&rasterState.polygonOffsetFactor);
+
+ float depthBias = ldexp(rasterState.polygonOffsetUnits, -static_cast<int>(mCurDepthSize));
+ mDevice->SetRenderState(D3DRS_DEPTHBIAS, *(DWORD*)&depthBias);
+ }
+ }
+ else
+ {
+ mDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0);
+ mDevice->SetRenderState(D3DRS_DEPTHBIAS, 0);
+ }
+
+ mCurRasterState = rasterState;
+ }
+
+ mForceSetRasterState = false;
+}
+
+void Renderer9::setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::Color &blendColor, unsigned int sampleMask)
+{
+ bool blendStateChanged = mForceSetBlendState || memcmp(&blendState, &mCurBlendState, sizeof(gl::BlendState)) != 0;
+ bool blendColorChanged = mForceSetBlendState || memcmp(&blendColor, &mCurBlendColor, sizeof(gl::Color)) != 0;
+ bool sampleMaskChanged = mForceSetBlendState || sampleMask != mCurSampleMask;
+
+ if (blendStateChanged || blendColorChanged)
+ {
+ if (blendState.blend)
+ {
+ mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
+
+ if (blendState.sourceBlendRGB != GL_CONSTANT_ALPHA && blendState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA &&
+ blendState.destBlendRGB != GL_CONSTANT_ALPHA && blendState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA)
+ {
+ mDevice->SetRenderState(D3DRS_BLENDFACTOR, gl_d3d9::ConvertColor(blendColor));
+ }
+ else
+ {
+ mDevice->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA(gl::unorm<8>(blendColor.alpha),
+ gl::unorm<8>(blendColor.alpha),
+ gl::unorm<8>(blendColor.alpha),
+ gl::unorm<8>(blendColor.alpha)));
+ }
+
+ mDevice->SetRenderState(D3DRS_SRCBLEND, gl_d3d9::ConvertBlendFunc(blendState.sourceBlendRGB));
+ mDevice->SetRenderState(D3DRS_DESTBLEND, gl_d3d9::ConvertBlendFunc(blendState.destBlendRGB));
+ mDevice->SetRenderState(D3DRS_BLENDOP, gl_d3d9::ConvertBlendOp(blendState.blendEquationRGB));
+
+ if (blendState.sourceBlendRGB != blendState.sourceBlendAlpha ||
+ blendState.destBlendRGB != blendState.destBlendAlpha ||
+ blendState.blendEquationRGB != blendState.blendEquationAlpha)
+ {
+ mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
+
+ mDevice->SetRenderState(D3DRS_SRCBLENDALPHA, gl_d3d9::ConvertBlendFunc(blendState.sourceBlendAlpha));
+ mDevice->SetRenderState(D3DRS_DESTBLENDALPHA, gl_d3d9::ConvertBlendFunc(blendState.destBlendAlpha));
+ mDevice->SetRenderState(D3DRS_BLENDOPALPHA, gl_d3d9::ConvertBlendOp(blendState.blendEquationAlpha));
+ }
+ else
+ {
+ mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
+ }
+ }
+ else
+ {
+ mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
+ }
+
+ if (blendState.sampleAlphaToCoverage)
+ {
+ FIXME("Sample alpha to coverage is unimplemented.");
+ }
+
+ // Set the color mask
+ bool zeroColorMaskAllowed = getAdapterVendor() != VENDOR_ID_AMD;
+ // Apparently some ATI cards have a bug where a draw with a zero color
+ // write mask can cause later draws to have incorrect results. Instead,
+ // set a nonzero color write mask but modify the blend state so that no
+ // drawing is done.
+ // http://code.google.com/p/angleproject/issues/detail?id=169
+
+ DWORD colorMask = gl_d3d9::ConvertColorMask(blendState.colorMaskRed, blendState.colorMaskGreen,
+ blendState.colorMaskBlue, blendState.colorMaskAlpha);
+ if (colorMask == 0 && !zeroColorMaskAllowed)
+ {
+ // Enable green channel, but set blending so nothing will be drawn.
+ mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_GREEN);
+ mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
+
+ mDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
+ mDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
+ mDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
+ }
+ else
+ {
+ mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, colorMask);
+ }
+
+ mDevice->SetRenderState(D3DRS_DITHERENABLE, blendState.dither ? TRUE : FALSE);
+
+ mCurBlendState = blendState;
+ mCurBlendColor = blendColor;
+ }
+
+ if (sampleMaskChanged)
+ {
+ // Set the multisample mask
+ mDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE);
+ mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, static_cast<DWORD>(sampleMask));
+
+ mCurSampleMask = sampleMask;
+ }
+
+ mForceSetBlendState = false;
+}
+
+void Renderer9::setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef,
+ int stencilBackRef, bool frontFaceCCW)
+{
+ bool depthStencilStateChanged = mForceSetDepthStencilState ||
+ memcmp(&depthStencilState, &mCurDepthStencilState, sizeof(gl::DepthStencilState)) != 0;
+ bool stencilRefChanged = mForceSetDepthStencilState || stencilRef != mCurStencilRef ||
+ stencilBackRef != mCurStencilBackRef;
+ bool frontFaceCCWChanged = mForceSetDepthStencilState || frontFaceCCW != mCurFrontFaceCCW;
+
+ if (depthStencilStateChanged)
+ {
+ if (depthStencilState.depthTest)
+ {
+ mDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
+ mDevice->SetRenderState(D3DRS_ZFUNC, gl_d3d9::ConvertComparison(depthStencilState.depthFunc));
+ }
+ else
+ {
+ mDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
+ }
+
+ mCurDepthStencilState = depthStencilState;
+ }
+
+ if (depthStencilStateChanged || stencilRefChanged || frontFaceCCWChanged)
+ {
+ if (depthStencilState.stencilTest && mCurStencilSize > 0)
+ {
+ mDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE);
+ mDevice->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE);
+
+ // FIXME: Unsupported by D3D9
+ const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF;
+ const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK;
+ const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK;
+ if (depthStencilState.stencilWritemask != depthStencilState.stencilBackWritemask ||
+ stencilRef != stencilBackRef ||
+ depthStencilState.stencilMask != depthStencilState.stencilBackMask)
+ {
+ ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are invalid under WebGL.");
+ return gl::error(GL_INVALID_OPERATION);
+ }
+
+ // get the maximum size of the stencil ref
+ unsigned int maxStencil = (1 << mCurStencilSize) - 1;
+
+ mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK,
+ depthStencilState.stencilWritemask);
+ mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
+ gl_d3d9::ConvertComparison(depthStencilState.stencilFunc));
+
+ mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF,
+ (stencilRef < (int)maxStencil) ? stencilRef : maxStencil);
+ mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK,
+ depthStencilState.stencilMask);
+
+ mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
+ gl_d3d9::ConvertStencilOp(depthStencilState.stencilFail));
+ mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
+ gl_d3d9::ConvertStencilOp(depthStencilState.stencilPassDepthFail));
+ mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
+ gl_d3d9::ConvertStencilOp(depthStencilState.stencilPassDepthPass));
+
+ mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK,
+ depthStencilState.stencilBackWritemask);
+ mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
+ gl_d3d9::ConvertComparison(depthStencilState.stencilBackFunc));
+
+ mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF,
+ (stencilBackRef < (int)maxStencil) ? stencilBackRef : maxStencil);
+ mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK,
+ depthStencilState.stencilBackMask);
+
+ mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
+ gl_d3d9::ConvertStencilOp(depthStencilState.stencilBackFail));
+ mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
+ gl_d3d9::ConvertStencilOp(depthStencilState.stencilBackPassDepthFail));
+ mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
+ gl_d3d9::ConvertStencilOp(depthStencilState.stencilBackPassDepthPass));
+ }
+ else
+ {
+ mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
+ }
+
+ mDevice->SetRenderState(D3DRS_ZWRITEENABLE, depthStencilState.depthMask ? TRUE : FALSE);
+
+ mCurStencilRef = stencilRef;
+ mCurStencilBackRef = stencilBackRef;
+ mCurFrontFaceCCW = frontFaceCCW;
+ }
+
+ mForceSetDepthStencilState = false;
+}
+
+void Renderer9::setScissorRectangle(const gl::Rectangle &scissor, bool enabled)
+{
+ bool scissorChanged = mForceSetScissor ||
+ memcmp(&scissor, &mCurScissor, sizeof(gl::Rectangle)) != 0 ||
+ enabled != mScissorEnabled;
+
+ if (scissorChanged)
+ {
+ if (enabled)
+ {
+ RECT rect;
+ rect.left = gl::clamp(scissor.x, 0, static_cast<int>(mRenderTargetDesc.width));
+ rect.top = gl::clamp(scissor.y, 0, static_cast<int>(mRenderTargetDesc.height));
+ rect.right = gl::clamp(scissor.x + scissor.width, 0, static_cast<int>(mRenderTargetDesc.width));
+ rect.bottom = gl::clamp(scissor.y + scissor.height, 0, static_cast<int>(mRenderTargetDesc.height));
+ mDevice->SetScissorRect(&rect);
+ }
+
+ mDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, enabled ? TRUE : FALSE);
+
+ mScissorEnabled = enabled;
+ mCurScissor = scissor;
+ }
+
+ mForceSetScissor = false;
+}
+
+bool Renderer9::setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace,
+ bool ignoreViewport)
+{
+ gl::Rectangle actualViewport = viewport;
+ float actualZNear = gl::clamp01(zNear);
+ float actualZFar = gl::clamp01(zFar);
+ if (ignoreViewport)
+ {
+ actualViewport.x = 0;
+ actualViewport.y = 0;
+ actualViewport.width = mRenderTargetDesc.width;
+ actualViewport.height = mRenderTargetDesc.height;
+ actualZNear = 0.0f;
+ actualZFar = 1.0f;
+ }
+
+ D3DVIEWPORT9 dxViewport;
+ dxViewport.X = gl::clamp(actualViewport.x, 0, static_cast<int>(mRenderTargetDesc.width));
+ dxViewport.Y = gl::clamp(actualViewport.y, 0, static_cast<int>(mRenderTargetDesc.height));
+ dxViewport.Width = gl::clamp(actualViewport.width, 0, static_cast<int>(mRenderTargetDesc.width) - static_cast<int>(dxViewport.X));
+ dxViewport.Height = gl::clamp(actualViewport.height, 0, static_cast<int>(mRenderTargetDesc.height) - static_cast<int>(dxViewport.Y));
+ dxViewport.MinZ = actualZNear;
+ dxViewport.MaxZ = actualZFar;
+
+ if (dxViewport.Width <= 0 || dxViewport.Height <= 0)
+ {
+ return false; // Nothing to render
+ }
+
+ float depthFront = !gl::IsTriangleMode(drawMode) ? 0.0f : (frontFace == GL_CCW ? 1.0f : -1.0f);
+
+ bool viewportChanged = mForceSetViewport || memcmp(&actualViewport, &mCurViewport, sizeof(gl::Rectangle)) != 0 ||
+ actualZNear != mCurNear || actualZFar != mCurFar || mCurDepthFront != depthFront;
+ if (viewportChanged)
+ {
+ mDevice->SetViewport(&dxViewport);
+
+ mCurViewport = actualViewport;
+ mCurNear = actualZNear;
+ mCurFar = actualZFar;
+ mCurDepthFront = depthFront;
+
+ dx_VertexConstants vc = {0};
+ dx_PixelConstants pc = {0};
+
+ vc.viewAdjust[0] = (float)((actualViewport.width - (int)dxViewport.Width) + 2 * (actualViewport.x - (int)dxViewport.X) - 1) / dxViewport.Width;
+ vc.viewAdjust[1] = (float)((actualViewport.height - (int)dxViewport.Height) + 2 * (actualViewport.y - (int)dxViewport.Y) - 1) / dxViewport.Height;
+ vc.viewAdjust[2] = (float)actualViewport.width / dxViewport.Width;
+ vc.viewAdjust[3] = (float)actualViewport.height / dxViewport.Height;
+
+ pc.viewCoords[0] = actualViewport.width * 0.5f;
+ pc.viewCoords[1] = actualViewport.height * 0.5f;
+ pc.viewCoords[2] = actualViewport.x + (actualViewport.width * 0.5f);
+ pc.viewCoords[3] = actualViewport.y + (actualViewport.height * 0.5f);
+
+ pc.depthFront[0] = (actualZFar - actualZNear) * 0.5f;
+ pc.depthFront[1] = (actualZNear + actualZFar) * 0.5f;
+ pc.depthFront[2] = depthFront;
+
+ vc.depthRange[0] = actualZNear;
+ vc.depthRange[1] = actualZFar;
+ vc.depthRange[2] = actualZFar - actualZNear;
+
+ pc.depthRange[0] = actualZNear;
+ pc.depthRange[1] = actualZFar;
+ pc.depthRange[2] = actualZFar - actualZNear;
+
+ if (memcmp(&vc, &mVertexConstants, sizeof(dx_VertexConstants)) != 0)
+ {
+ mVertexConstants = vc;
+ mDxUniformsDirty = true;
+ }
+
+ if (memcmp(&pc, &mPixelConstants, sizeof(dx_PixelConstants)) != 0)
+ {
+ mPixelConstants = pc;
+ mDxUniformsDirty = true;
+ }
+ }
+
+ mForceSetViewport = false;
+ return true;
+}
+
+bool Renderer9::applyPrimitiveType(GLenum mode, GLsizei count)
+{
+ switch (mode)
+ {
+ case GL_POINTS:
+ mPrimitiveType = D3DPT_POINTLIST;
+ mPrimitiveCount = count;
+ break;
+ case GL_LINES:
+ mPrimitiveType = D3DPT_LINELIST;
+ mPrimitiveCount = count / 2;
+ break;
+ case GL_LINE_LOOP:
+ mPrimitiveType = D3DPT_LINESTRIP;
+ mPrimitiveCount = count - 1; // D3D doesn't support line loops, so we draw the last line separately
+ break;
+ case GL_LINE_STRIP:
+ mPrimitiveType = D3DPT_LINESTRIP;
+ mPrimitiveCount = count - 1;
+ break;
+ case GL_TRIANGLES:
+ mPrimitiveType = D3DPT_TRIANGLELIST;
+ mPrimitiveCount = count / 3;
+ break;
+ case GL_TRIANGLE_STRIP:
+ mPrimitiveType = D3DPT_TRIANGLESTRIP;
+ mPrimitiveCount = count - 2;
+ break;
+ case GL_TRIANGLE_FAN:
+ mPrimitiveType = D3DPT_TRIANGLEFAN;
+ mPrimitiveCount = count - 2;
+ break;
+ default:
+ return gl::error(GL_INVALID_ENUM, false);
+ }
+
+ return mPrimitiveCount > 0;
+}
+
+
+gl::Renderbuffer *Renderer9::getNullColorbuffer(gl::Renderbuffer *depthbuffer)
+{
+ if (!depthbuffer)
+ {
+ ERR("Unexpected null depthbuffer for depth-only FBO.");
+ return NULL;
+ }
+
+ GLsizei width = depthbuffer->getWidth();
+ GLsizei height = depthbuffer->getHeight();
+
+ // search cached nullcolorbuffers
+ for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++)
+ {
+ if (mNullColorbufferCache[i].buffer != NULL &&
+ mNullColorbufferCache[i].width == width &&
+ mNullColorbufferCache[i].height == height)
+ {
+ mNullColorbufferCache[i].lruCount = ++mMaxNullColorbufferLRU;
+ return mNullColorbufferCache[i].buffer;
+ }
+ }
+
+ gl::Renderbuffer *nullbuffer = new gl::Renderbuffer(this, 0, new gl::Colorbuffer(this, width, height, GL_NONE, 0));
+
+ // add nullbuffer to the cache
+ NullColorbufferCacheEntry *oldest = &mNullColorbufferCache[0];
+ for (int i = 1; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++)
+ {
+ if (mNullColorbufferCache[i].lruCount < oldest->lruCount)
+ {
+ oldest = &mNullColorbufferCache[i];
+ }
+ }
+
+ delete oldest->buffer;
+ oldest->buffer = nullbuffer;
+ oldest->lruCount = ++mMaxNullColorbufferLRU;
+ oldest->width = width;
+ oldest->height = height;
+
+ return nullbuffer;
+}
+
+bool Renderer9::applyRenderTarget(gl::Framebuffer *framebuffer)
+{
+ // if there is no color attachment we must synthesize a NULL colorattachment
+ // to keep the D3D runtime happy. This should only be possible if depth texturing.
+ gl::Renderbuffer *renderbufferObject = NULL;
+ if (framebuffer->getColorbufferType(0) != GL_NONE)
+ {
+ renderbufferObject = framebuffer->getColorbuffer(0);
+ }
+ else
+ {
+ renderbufferObject = getNullColorbuffer(framebuffer->getDepthbuffer());
+ }
+ if (!renderbufferObject)
+ {
+ ERR("unable to locate renderbuffer for FBO.");
+ return false;
+ }
+
+ bool renderTargetChanged = false;
+ unsigned int renderTargetSerial = renderbufferObject->getSerial();
+ if (renderTargetSerial != mAppliedRenderTargetSerial)
+ {
+ // Apply the render target on the device
+ IDirect3DSurface9 *renderTargetSurface = NULL;
+
+ RenderTarget *renderTarget = renderbufferObject->getRenderTarget();
+ if (renderTarget)
+ {
+ renderTargetSurface = RenderTarget9::makeRenderTarget9(renderTarget)->getSurface();
+ }
+
+ if (!renderTargetSurface)
+ {
+ ERR("render target pointer unexpectedly null.");
+ return false; // Context must be lost
+ }
+
+ mDevice->SetRenderTarget(0, renderTargetSurface);
+ renderTargetSurface->Release();
+
+ mAppliedRenderTargetSerial = renderTargetSerial;
+ renderTargetChanged = true;
+ }
+
+ gl::Renderbuffer *depthStencil = NULL;
+ unsigned int depthbufferSerial = 0;
+ unsigned int stencilbufferSerial = 0;
+ if (framebuffer->getDepthbufferType() != GL_NONE)
+ {
+ depthStencil = framebuffer->getDepthbuffer();
+ if (!depthStencil)
+ {
+ ERR("Depth stencil pointer unexpectedly null.");
+ return false;
+ }
+
+ depthbufferSerial = depthStencil->getSerial();
+ }
+ else if (framebuffer->getStencilbufferType() != GL_NONE)
+ {
+ depthStencil = framebuffer->getStencilbuffer();
+ if (!depthStencil)
+ {
+ ERR("Depth stencil pointer unexpectedly null.");
+ return false;
+ }
+
+ stencilbufferSerial = depthStencil->getSerial();
+ }
+
+ if (depthbufferSerial != mAppliedDepthbufferSerial ||
+ stencilbufferSerial != mAppliedStencilbufferSerial ||
+ !mDepthStencilInitialized)
+ {
+ unsigned int depthSize = 0;
+ unsigned int stencilSize = 0;
+
+ // Apply the depth stencil on the device
+ if (depthStencil)
+ {
+ IDirect3DSurface9 *depthStencilSurface = NULL;
+ RenderTarget *depthStencilRenderTarget = depthStencil->getDepthStencil();
+
+ if (depthStencilRenderTarget)
+ {
+ depthStencilSurface = RenderTarget9::makeRenderTarget9(depthStencilRenderTarget)->getSurface();
+ }
+
+ if (!depthStencilSurface)
+ {
+ ERR("depth stencil pointer unexpectedly null.");
+ return false; // Context must be lost
+ }
+
+ mDevice->SetDepthStencilSurface(depthStencilSurface);
+ depthStencilSurface->Release();
+
+ depthSize = depthStencil->getDepthSize();
+ stencilSize = depthStencil->getStencilSize();
+ }
+ else
+ {
+ mDevice->SetDepthStencilSurface(NULL);
+ }
+
+ if (!mDepthStencilInitialized || depthSize != mCurDepthSize)
+ {
+ mCurDepthSize = depthSize;
+ mForceSetRasterState = true;
+ }
+
+ if (!mDepthStencilInitialized || stencilSize != mCurStencilSize)
+ {
+ mCurStencilSize = stencilSize;
+ mForceSetDepthStencilState = true;
+ }
+
+ mAppliedDepthbufferSerial = depthbufferSerial;
+ mAppliedStencilbufferSerial = stencilbufferSerial;
+ mDepthStencilInitialized = true;
+ }
+
+ if (renderTargetChanged || !mRenderTargetDescInitialized)
+ {
+ mForceSetScissor = true;
+ mForceSetViewport = true;
+
+ mRenderTargetDesc.width = renderbufferObject->getWidth();
+ mRenderTargetDesc.height = renderbufferObject->getHeight();
+ mRenderTargetDesc.format = renderbufferObject->getActualFormat();
+ mRenderTargetDescInitialized = true;
+ }
+
+ return true;
+}
+
+GLenum Renderer9::applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances)
+{
+ TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS];
+ GLenum err = mVertexDataManager->prepareVertexData(vertexAttributes, programBinary, first, count, attributes, instances);
+ if (err != GL_NO_ERROR)
+ {
+ return err;
+ }
+
+ return mVertexDeclarationCache.applyDeclaration(mDevice, attributes, programBinary, instances, &mRepeatDraw);
+}
+
+// Applies the indices and element array bindings to the Direct3D 9 device
+GLenum Renderer9::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo)
+{
+ GLenum err = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo);
+
+ if (err == GL_NO_ERROR)
+ {
+ // Directly binding the storage buffer is not supported for d3d9
+ ASSERT(indexInfo->storage == NULL);
+
+ if (indexInfo->serial != mAppliedIBSerial)
+ {
+ IndexBuffer9* indexBuffer = IndexBuffer9::makeIndexBuffer9(indexInfo->indexBuffer);
+
+ mDevice->SetIndices(indexBuffer->getBuffer());
+ mAppliedIBSerial = indexInfo->serial;
+ }
+ }
+
+ return err;
+}
+
+void Renderer9::drawArrays(GLenum mode, GLsizei count, GLsizei instances)
+{
+ startScene();
+
+ if (mode == GL_LINE_LOOP)
+ {
+ drawLineLoop(count, GL_NONE, NULL, 0, NULL);
+ }
+ else if (instances > 0)
+ {
+ StaticIndexBufferInterface *countingIB = mIndexDataManager->getCountingIndices(count);
+ if (countingIB)
+ {
+ if (mAppliedIBSerial != countingIB->getSerial())
+ {
+ IndexBuffer9 *indexBuffer = IndexBuffer9::makeIndexBuffer9(countingIB->getIndexBuffer());
+
+ mDevice->SetIndices(indexBuffer->getBuffer());
+ mAppliedIBSerial = countingIB->getSerial();
+ }
+
+ for (int i = 0; i < mRepeatDraw; i++)
+ {
+ mDevice->DrawIndexedPrimitive(mPrimitiveType, 0, 0, count, 0, mPrimitiveCount);
+ }
+ }
+ else
+ {
+ ERR("Could not create a counting index buffer for glDrawArraysInstanced.");
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+ }
+ else // Regular case
+ {
+ mDevice->DrawPrimitive(mPrimitiveType, 0, mPrimitiveCount);
+ }
+}
+
+void Renderer9::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei /*instances*/)
+{
+ startScene();
+
+ if (mode == GL_POINTS)
+ {
+ drawIndexedPoints(count, type, indices, indexInfo.minIndex, elementArrayBuffer);
+ }
+ else if (mode == GL_LINE_LOOP)
+ {
+ drawLineLoop(count, type, indices, indexInfo.minIndex, elementArrayBuffer);
+ }
+ else
+ {
+ for (int i = 0; i < mRepeatDraw; i++)
+ {
+ GLsizei vertexCount = indexInfo.maxIndex - indexInfo.minIndex + 1;
+ mDevice->DrawIndexedPrimitive(mPrimitiveType, -(INT)indexInfo.minIndex, indexInfo.minIndex, vertexCount, indexInfo.startIndex, mPrimitiveCount);
+ }
+ }
+}
+
+void Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer)
+{
+ // Get the raw indices for an indexed draw
+ if (type != GL_NONE && elementArrayBuffer)
+ {
+ gl::Buffer *indexBuffer = elementArrayBuffer;
+ BufferStorage *storage = indexBuffer->getStorage();
+ intptr_t offset = reinterpret_cast<intptr_t>(indices);
+ indices = static_cast<const GLubyte*>(storage->getData()) + offset;
+ }
+
+ unsigned int startIndex = 0;
+
+ if (get32BitIndexSupport())
+ {
+ if (!mLineLoopIB)
+ {
+ mLineLoopIB = new StreamingIndexBufferInterface(this);
+ if (!mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT))
+ {
+ delete mLineLoopIB;
+ mLineLoopIB = NULL;
+
+ ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP.");
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+ }
+
+ if (static_cast<unsigned int>(count) + 1 > (std::numeric_limits<unsigned int>::max() / sizeof(unsigned int)))
+ {
+ ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required.");
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+
+ // Checked by Renderer9::applyPrimitiveType
+ ASSERT(count >= 0);
+
+ const unsigned int spaceNeeded = (static_cast<unsigned int>(count) + 1) * sizeof(unsigned int);
+ if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT))
+ {
+ ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP.");
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+
+ void* mappedMemory = NULL;
+ unsigned int offset = 0;
+ if (!mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset))
+ {
+ ERR("Could not map index buffer for GL_LINE_LOOP.");
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+
+ startIndex = static_cast<unsigned int>(offset) / 4;
+ unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory);
+
+ switch (type)
+ {
+ case GL_NONE: // Non-indexed draw
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = i;
+ }
+ data[count] = 0;
+ break;
+ case GL_UNSIGNED_BYTE:
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = static_cast<const GLubyte*>(indices)[i];
+ }
+ data[count] = static_cast<const GLubyte*>(indices)[0];
+ break;
+ case GL_UNSIGNED_SHORT:
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = static_cast<const GLushort*>(indices)[i];
+ }
+ data[count] = static_cast<const GLushort*>(indices)[0];
+ break;
+ case GL_UNSIGNED_INT:
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = static_cast<const GLuint*>(indices)[i];
+ }
+ data[count] = static_cast<const GLuint*>(indices)[0];
+ break;
+ default: UNREACHABLE();
+ }
+
+ if (!mLineLoopIB->unmapBuffer())
+ {
+ ERR("Could not unmap index buffer for GL_LINE_LOOP.");
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+ }
+ else
+ {
+ if (!mLineLoopIB)
+ {
+ mLineLoopIB = new StreamingIndexBufferInterface(this);
+ if (!mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT))
+ {
+ delete mLineLoopIB;
+ mLineLoopIB = NULL;
+
+ ERR("Could not create a 16-bit looping index buffer for GL_LINE_LOOP.");
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+ }
+
+ // Checked by Renderer9::applyPrimitiveType
+ ASSERT(count >= 0);
+
+ if (static_cast<unsigned int>(count) + 1 > (std::numeric_limits<unsigned short>::max() / sizeof(unsigned short)))
+ {
+ ERR("Could not create a 16-bit looping index buffer for GL_LINE_LOOP, too many indices required.");
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+
+ const unsigned int spaceNeeded = (static_cast<unsigned int>(count) + 1) * sizeof(unsigned short);
+ if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_SHORT))
+ {
+ ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP.");
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+
+ void* mappedMemory = NULL;
+ unsigned int offset;
+ if (mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset))
+ {
+ ERR("Could not map index buffer for GL_LINE_LOOP.");
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+
+ startIndex = static_cast<unsigned int>(offset) / 2;
+ unsigned short *data = reinterpret_cast<unsigned short*>(mappedMemory);
+
+ switch (type)
+ {
+ case GL_NONE: // Non-indexed draw
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = i;
+ }
+ data[count] = 0;
+ break;
+ case GL_UNSIGNED_BYTE:
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = static_cast<const GLubyte*>(indices)[i];
+ }
+ data[count] = static_cast<const GLubyte*>(indices)[0];
+ break;
+ case GL_UNSIGNED_SHORT:
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = static_cast<const GLushort*>(indices)[i];
+ }
+ data[count] = static_cast<const GLushort*>(indices)[0];
+ break;
+ case GL_UNSIGNED_INT:
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = static_cast<const GLuint*>(indices)[i];
+ }
+ data[count] = static_cast<const GLuint*>(indices)[0];
+ break;
+ default: UNREACHABLE();
+ }
+
+ if (!mLineLoopIB->unmapBuffer())
+ {
+ ERR("Could not unmap index buffer for GL_LINE_LOOP.");
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+ }
+
+ if (mAppliedIBSerial != mLineLoopIB->getSerial())
+ {
+ IndexBuffer9 *indexBuffer = IndexBuffer9::makeIndexBuffer9(mLineLoopIB->getIndexBuffer());
+
+ mDevice->SetIndices(indexBuffer->getBuffer());
+ mAppliedIBSerial = mLineLoopIB->getSerial();
+ }
+
+ mDevice->DrawIndexedPrimitive(D3DPT_LINESTRIP, -minIndex, minIndex, count, startIndex, count);
+}
+
+template <typename T>
+static void drawPoints(IDirect3DDevice9* device, GLsizei count, const GLvoid *indices, int minIndex)
+{
+ for (int i = 0; i < count; i++)
+ {
+ unsigned int indexValue = static_cast<unsigned int>(static_cast<const T*>(indices)[i]) - minIndex;
+ device->DrawPrimitive(D3DPT_POINTLIST, indexValue, 1);
+ }
+}
+
+void Renderer9::drawIndexedPoints(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer)
+{
+ // Drawing index point lists is unsupported in d3d9, fall back to a regular DrawPrimitive call
+ // for each individual point. This call is not expected to happen often.
+
+ if (elementArrayBuffer)
+ {
+ BufferStorage *storage = elementArrayBuffer->getStorage();
+ intptr_t offset = reinterpret_cast<intptr_t>(indices);
+ indices = static_cast<const GLubyte*>(storage->getData()) + offset;
+ }
+
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE: drawPoints<GLubyte>(mDevice, count, indices, minIndex); break;
+ case GL_UNSIGNED_SHORT: drawPoints<GLushort>(mDevice, count, indices, minIndex); break;
+ case GL_UNSIGNED_INT: drawPoints<GLuint>(mDevice, count, indices, minIndex); break;
+ default: UNREACHABLE();
+ }
+}
+
+void Renderer9::applyShaders(gl::ProgramBinary *programBinary)
+{
+ unsigned int programBinarySerial = programBinary->getSerial();
+ if (programBinarySerial != mAppliedProgramBinarySerial)
+ {
+ ShaderExecutable *vertexExe = programBinary->getVertexExecutable();
+ ShaderExecutable *pixelExe = programBinary->getPixelExecutable();
+
+ IDirect3DVertexShader9 *vertexShader = NULL;
+ if (vertexExe) vertexShader = ShaderExecutable9::makeShaderExecutable9(vertexExe)->getVertexShader();
+
+ IDirect3DPixelShader9 *pixelShader = NULL;
+ if (pixelExe) pixelShader = ShaderExecutable9::makeShaderExecutable9(pixelExe)->getPixelShader();
+
+ mDevice->SetPixelShader(pixelShader);
+ mDevice->SetVertexShader(vertexShader);
+ programBinary->dirtyAllUniforms();
+ mDxUniformsDirty = true;
+
+ mAppliedProgramBinarySerial = programBinarySerial;
+ }
+}
+
+void Renderer9::applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray *uniformArray)
+{
+ for (std::vector<gl::Uniform*>::const_iterator ub = uniformArray->begin(), ue = uniformArray->end(); ub != ue; ++ub)
+ {
+ gl::Uniform *targetUniform = *ub;
+
+ if (targetUniform->dirty)
+ {
+ GLfloat *f = (GLfloat*)targetUniform->data;
+ GLint *i = (GLint*)targetUniform->data;
+
+ switch (targetUniform->type)
+ {
+ case GL_SAMPLER_2D:
+ case GL_SAMPLER_CUBE:
+ break;
+ case GL_BOOL:
+ case GL_BOOL_VEC2:
+ case GL_BOOL_VEC3:
+ case GL_BOOL_VEC4:
+ applyUniformnbv(targetUniform, i);
+ break;
+ case GL_FLOAT:
+ case GL_FLOAT_VEC2:
+ case GL_FLOAT_VEC3:
+ case GL_FLOAT_VEC4:
+ case GL_FLOAT_MAT2:
+ case GL_FLOAT_MAT3:
+ case GL_FLOAT_MAT4:
+ applyUniformnfv(targetUniform, f);
+ break;
+ case GL_INT:
+ case GL_INT_VEC2:
+ case GL_INT_VEC3:
+ case GL_INT_VEC4:
+ applyUniformniv(targetUniform, i);
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ targetUniform->dirty = false;
+ }
+ }
+
+ // Driver uniforms
+ if (mDxUniformsDirty)
+ {
+ mDevice->SetVertexShaderConstantF(0, (float*)&mVertexConstants, sizeof(dx_VertexConstants) / sizeof(float[4]));
+ mDevice->SetPixelShaderConstantF(0, (float*)&mPixelConstants, sizeof(dx_PixelConstants) / sizeof(float[4]));
+ mDxUniformsDirty = false;
+ }
+}
+
+void Renderer9::applyUniformnfv(gl::Uniform *targetUniform, const GLfloat *v)
+{
+ if (targetUniform->psRegisterIndex >= 0)
+ {
+ mDevice->SetPixelShaderConstantF(targetUniform->psRegisterIndex, v, targetUniform->registerCount);
+ }
+
+ if (targetUniform->vsRegisterIndex >= 0)
+ {
+ mDevice->SetVertexShaderConstantF(targetUniform->vsRegisterIndex, v, targetUniform->registerCount);
+ }
+}
+
+void Renderer9::applyUniformniv(gl::Uniform *targetUniform, const GLint *v)
+{
+ ASSERT(targetUniform->registerCount <= MAX_VERTEX_CONSTANT_VECTORS_D3D9);
+ GLfloat vector[MAX_VERTEX_CONSTANT_VECTORS_D3D9][4];
+
+ for (unsigned int i = 0; i < targetUniform->registerCount; i++)
+ {
+ vector[i][0] = (GLfloat)v[4 * i + 0];
+ vector[i][1] = (GLfloat)v[4 * i + 1];
+ vector[i][2] = (GLfloat)v[4 * i + 2];
+ vector[i][3] = (GLfloat)v[4 * i + 3];
+ }
+
+ applyUniformnfv(targetUniform, (GLfloat*)vector);
+}
+
+void Renderer9::applyUniformnbv(gl::Uniform *targetUniform, const GLint *v)
+{
+ ASSERT(targetUniform->registerCount <= MAX_VERTEX_CONSTANT_VECTORS_D3D9);
+ GLfloat vector[MAX_VERTEX_CONSTANT_VECTORS_D3D9][4];
+
+ for (unsigned int i = 0; i < targetUniform->registerCount; i++)
+ {
+ vector[i][0] = (v[4 * i + 0] == GL_FALSE) ? 0.0f : 1.0f;
+ vector[i][1] = (v[4 * i + 1] == GL_FALSE) ? 0.0f : 1.0f;
+ vector[i][2] = (v[4 * i + 2] == GL_FALSE) ? 0.0f : 1.0f;
+ vector[i][3] = (v[4 * i + 3] == GL_FALSE) ? 0.0f : 1.0f;
+ }
+
+ applyUniformnfv(targetUniform, (GLfloat*)vector);
+}
+
+void Renderer9::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer)
+{
+ D3DCOLOR color = D3DCOLOR_ARGB(gl::unorm<8>(clearParams.colorClearValue.alpha),
+ gl::unorm<8>(clearParams.colorClearValue.red),
+ gl::unorm<8>(clearParams.colorClearValue.green),
+ gl::unorm<8>(clearParams.colorClearValue.blue));
+ float depth = gl::clamp01(clearParams.depthClearValue);
+ int stencil = clearParams.stencilClearValue & 0x000000FF;
+
+ unsigned int stencilUnmasked = 0x0;
+ if ((clearParams.mask & GL_STENCIL_BUFFER_BIT) && frameBuffer->hasStencil())
+ {
+ unsigned int stencilSize = gl::GetStencilSize(frameBuffer->getStencilbuffer()->getActualFormat());
+ stencilUnmasked = (0x1 << stencilSize) - 1;
+ }
+
+ bool alphaUnmasked = (gl::GetAlphaSize(mRenderTargetDesc.format) == 0) || clearParams.colorMaskAlpha;
+
+ const bool needMaskedStencilClear = (clearParams.mask & GL_STENCIL_BUFFER_BIT) &&
+ (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked;
+ const bool needMaskedColorClear = (clearParams.mask & GL_COLOR_BUFFER_BIT) &&
+ !(clearParams.colorMaskRed && clearParams.colorMaskGreen &&
+ clearParams.colorMaskBlue && alphaUnmasked);
+
+ if (needMaskedColorClear || needMaskedStencilClear)
+ {
+ // State which is altered in all paths from this point to the clear call is saved.
+ // State which is altered in only some paths will be flagged dirty in the case that
+ // that path is taken.
+ HRESULT hr;
+ if (mMaskedClearSavedState == NULL)
+ {
+ hr = mDevice->BeginStateBlock();
+ ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
+
+ mDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
+ mDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
+ mDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
+ mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
+ mDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
+ mDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
+ mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
+ mDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
+ mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
+ mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
+ mDevice->SetPixelShader(NULL);
+ mDevice->SetVertexShader(NULL);
+ mDevice->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
+ mDevice->SetStreamSource(0, NULL, 0, 0);
+ mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
+ mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
+ mDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR);
+ mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
+ mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR);
+ mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color);
+ mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
+
+ for(int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
+ {
+ mDevice->SetStreamSourceFreq(i, 1);
+ }
+
+ hr = mDevice->EndStateBlock(&mMaskedClearSavedState);
+ ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
+ }
+
+ ASSERT(mMaskedClearSavedState != NULL);
+
+ if (mMaskedClearSavedState != NULL)
+ {
+ hr = mMaskedClearSavedState->Capture();
+ ASSERT(SUCCEEDED(hr));
+ }
+
+ mDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
+ mDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
+ mDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
+ mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
+ mDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
+ mDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
+ mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
+ mDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
+
+ if (clearParams.mask & GL_COLOR_BUFFER_BIT)
+ {
+ mDevice->SetRenderState(D3DRS_COLORWRITEENABLE,
+ gl_d3d9::ConvertColorMask(clearParams.colorMaskRed,
+ clearParams.colorMaskGreen,
+ clearParams.colorMaskBlue,
+ clearParams.colorMaskAlpha));
+ }
+ else
+ {
+ mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
+ }
+
+ if (stencilUnmasked != 0x0 && (clearParams.mask & GL_STENCIL_BUFFER_BIT))
+ {
+ mDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE);
+ mDevice->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
+ mDevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
+ mDevice->SetRenderState(D3DRS_STENCILREF, stencil);
+ mDevice->SetRenderState(D3DRS_STENCILWRITEMASK, clearParams.stencilWriteMask);
+ mDevice->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE);
+ mDevice->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE);
+ mDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
+ }
+ else
+ {
+ mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
+ }
+
+ mDevice->SetPixelShader(NULL);
+ mDevice->SetVertexShader(NULL);
+ mDevice->SetFVF(D3DFVF_XYZRHW);
+ mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
+ mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
+ mDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR);
+ mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
+ mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR);
+ mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color);
+ mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
+
+ for(int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
+ {
+ mDevice->SetStreamSourceFreq(i, 1);
+ }
+
+ float quad[4][4]; // A quadrilateral covering the target, aligned to match the edges
+ quad[0][0] = -0.5f;
+ quad[0][1] = mRenderTargetDesc.height - 0.5f;
+ quad[0][2] = 0.0f;
+ quad[0][3] = 1.0f;
+
+ quad[1][0] = mRenderTargetDesc.width - 0.5f;
+ quad[1][1] = mRenderTargetDesc.height - 0.5f;
+ quad[1][2] = 0.0f;
+ quad[1][3] = 1.0f;
+
+ quad[2][0] = -0.5f;
+ quad[2][1] = -0.5f;
+ quad[2][2] = 0.0f;
+ quad[2][3] = 1.0f;
+
+ quad[3][0] = mRenderTargetDesc.width - 0.5f;
+ quad[3][1] = -0.5f;
+ quad[3][2] = 0.0f;
+ quad[3][3] = 1.0f;
+
+ startScene();
+ mDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float[4]));
+
+ if (clearParams.mask & GL_DEPTH_BUFFER_BIT)
+ {
+ mDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
+ mDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
+ mDevice->Clear(0, NULL, D3DCLEAR_ZBUFFER, color, depth, stencil);
+ }
+
+ if (mMaskedClearSavedState != NULL)
+ {
+ mMaskedClearSavedState->Apply();
+ }
+ }
+ else if (clearParams.mask)
+ {
+ DWORD dxClearFlags = 0;
+ if (clearParams.mask & GL_COLOR_BUFFER_BIT)
+ {
+ dxClearFlags |= D3DCLEAR_TARGET;
+ }
+ if (clearParams.mask & GL_DEPTH_BUFFER_BIT)
+ {
+ dxClearFlags |= D3DCLEAR_ZBUFFER;
+ }
+ if (clearParams.mask & GL_STENCIL_BUFFER_BIT)
+ {
+ dxClearFlags |= D3DCLEAR_STENCIL;
+ }
+
+ mDevice->Clear(0, NULL, dxClearFlags, color, depth, stencil);
+ }
+}
+
+void Renderer9::markAllStateDirty()
+{
+ mAppliedRenderTargetSerial = 0;
+ mAppliedDepthbufferSerial = 0;
+ mAppliedStencilbufferSerial = 0;
+ mDepthStencilInitialized = false;
+ mRenderTargetDescInitialized = false;
+
+ mForceSetDepthStencilState = true;
+ mForceSetRasterState = true;
+ mForceSetScissor = true;
+ mForceSetViewport = true;
+ mForceSetBlendState = true;
+
+ for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; i++)
+ {
+ mForceSetVertexSamplerStates[i] = true;
+ mCurVertexTextureSerials[i] = 0;
+ }
+ for (unsigned int i = 0; i < gl::MAX_TEXTURE_IMAGE_UNITS; i++)
+ {
+ mForceSetPixelSamplerStates[i] = true;
+ mCurPixelTextureSerials[i] = 0;
+ }
+
+ mAppliedIBSerial = 0;
+ mAppliedProgramBinarySerial = 0;
+ mDxUniformsDirty = true;
+
+ mVertexDeclarationCache.markStateDirty();
+}
+
+void Renderer9::releaseDeviceResources()
+{
+ while (!mEventQueryPool.empty())
+ {
+ mEventQueryPool.back()->Release();
+ mEventQueryPool.pop_back();
+ }
+
+ SafeRelease(mMaskedClearSavedState);
+
+ mVertexShaderCache.clear();
+ mPixelShaderCache.clear();
+
+ SafeDelete(mBlit);
+ SafeDelete(mVertexDataManager);
+ SafeDelete(mIndexDataManager);
+ SafeDelete(mLineLoopIB);
+
+ for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++)
+ {
+ SafeDelete(mNullColorbufferCache[i].buffer);
+ }
+
+}
+
+
+void Renderer9::notifyDeviceLost()
+{
+ mDeviceLost = true;
+ mDisplay->notifyDeviceLost();
+}
+
+bool Renderer9::isDeviceLost()
+{
+ return mDeviceLost;
+}
+
+// set notify to true to broadcast a message to all contexts of the device loss
+bool Renderer9::testDeviceLost(bool notify)
+{
+ HRESULT status = getDeviceStatusCode();
+ bool isLost = FAILED(status);
+
+ if (isLost)
+ {
+ // ensure we note the device loss --
+ // we'll probably get this done again by notifyDeviceLost
+ // but best to remember it!
+ // Note that we don't want to clear the device loss status here
+ // -- this needs to be done by resetDevice
+ mDeviceLost = true;
+ if (notify)
+ {
+ notifyDeviceLost();
+ }
+ }
+
+ return isLost;
+}
+
+HRESULT Renderer9::getDeviceStatusCode()
+{
+ HRESULT status = D3D_OK;
+
+ if (mDeviceEx)
+ {
+ status = mDeviceEx->CheckDeviceState(NULL);
+ }
+ else if (mDevice)
+ {
+ status = mDevice->TestCooperativeLevel();
+ }
+
+ return status;
+}
+
+bool Renderer9::testDeviceResettable()
+{
+ // On D3D9Ex, DEVICELOST represents a hung device that needs to be restarted
+ // DEVICEREMOVED indicates the device has been stopped and must be recreated
+ switch (getDeviceStatusCode())
+ {
+ case D3DERR_DEVICENOTRESET:
+ case D3DERR_DEVICEHUNG:
+ return true;
+ case D3DERR_DEVICELOST:
+ return (mDeviceEx != NULL);
+ case D3DERR_DEVICEREMOVED:
+ ASSERT(mDeviceEx != NULL);
+ return isRemovedDeviceResettable();
+ default:
+ return false;
+ }
+}
+
+bool Renderer9::resetDevice()
+{
+ releaseDeviceResources();
+
+ D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters();
+
+ HRESULT result = D3D_OK;
+ bool lost = testDeviceLost(false);
+ bool removedDevice = (getDeviceStatusCode() == D3DERR_DEVICEREMOVED);
+
+ // Device Removed is a feature which is only present with D3D9Ex
+ ASSERT(mDeviceEx != NULL || !removedDevice);
+
+ for (int attempts = 3; lost && attempts > 0; attempts--)
+ {
+ if (removedDevice)
+ {
+ // Device removed, which may trigger on driver reinstallation,
+ // may cause a longer wait other reset attempts before the
+ // system is ready to handle creating a new device.
+ Sleep(800);
+ lost = !resetRemovedDevice();
+ }
+ else if (mDeviceEx)
+ {
+ Sleep(500); // Give the graphics driver some CPU time
+ result = mDeviceEx->ResetEx(&presentParameters, NULL);
+ lost = testDeviceLost(false);
+ }
+ else
+ {
+ result = mDevice->TestCooperativeLevel();
+ while (result == D3DERR_DEVICELOST)
+ {
+ Sleep(100); // Give the graphics driver some CPU time
+ result = mDevice->TestCooperativeLevel();
+ }
+
+ if (result == D3DERR_DEVICENOTRESET)
+ {
+ result = mDevice->Reset(&presentParameters);
+ }
+ lost = testDeviceLost(false);
+ }
+ }
+
+ if (FAILED(result))
+ {
+ ERR("Reset/ResetEx failed multiple times: 0x%08X", result);
+ return false;
+ }
+
+ if (removedDevice && lost)
+ {
+ ERR("Device lost reset failed multiple times");
+ return false;
+ }
+
+ // If the device was removed, we already finished re-initialization in resetRemovedDevice
+ if (!removedDevice)
+ {
+ // reset device defaults
+ initializeDevice();
+ }
+
+ mDeviceLost = false;
+
+ return true;
+}
+
+bool Renderer9::isRemovedDeviceResettable() const
+{
+ bool success = false;
+
+#ifdef ANGLE_ENABLE_D3D9EX
+ IDirect3D9Ex *d3d9Ex = NULL;
+ typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex**);
+ Direct3DCreate9ExFunc Direct3DCreate9ExPtr = reinterpret_cast<Direct3DCreate9ExFunc>(GetProcAddress(mD3d9Module, "Direct3DCreate9Ex"));
+
+ if (Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &d3d9Ex)))
+ {
+ D3DCAPS9 deviceCaps;
+ HRESULT result = d3d9Ex->GetDeviceCaps(mAdapter, mDeviceType, &deviceCaps);
+ success = SUCCEEDED(result);
+ }
+
+ SafeRelease(d3d9Ex);
+#else
+ ASSERT(UNREACHABLE());
+#endif
+
+ return success;
+}
+
+bool Renderer9::resetRemovedDevice()
+{
+ // From http://msdn.microsoft.com/en-us/library/windows/desktop/bb172554(v=vs.85).aspx:
+ // The hardware adapter has been removed. Application must destroy the device, do enumeration of
+ // adapters and create another Direct3D device. If application continues rendering without
+ // calling Reset, the rendering calls will succeed. Applies to Direct3D 9Ex only.
+ deinitialize();
+ return (initialize() == EGL_SUCCESS);
+}
+
+DWORD Renderer9::getAdapterVendor() const
+{
+ return mAdapterIdentifier.VendorId;
+}
+
+std::string Renderer9::getRendererDescription() const
+{
+ std::ostringstream rendererString;
+
+ rendererString << mAdapterIdentifier.Description;
+ if (getShareHandleSupport())
+ {
+ rendererString << " Direct3D9Ex";
+ }
+ else
+ {
+ rendererString << " Direct3D9";
+ }
+
+ rendererString << " vs_" << D3DSHADER_VERSION_MAJOR(mDeviceCaps.VertexShaderVersion) << "_" << D3DSHADER_VERSION_MINOR(mDeviceCaps.VertexShaderVersion);
+ rendererString << " ps_" << D3DSHADER_VERSION_MAJOR(mDeviceCaps.PixelShaderVersion) << "_" << D3DSHADER_VERSION_MINOR(mDeviceCaps.PixelShaderVersion);
+
+ return rendererString.str();
+}
+
+GUID Renderer9::getAdapterIdentifier() const
+{
+ return mAdapterIdentifier.DeviceIdentifier;
+}
+
+void Renderer9::getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray)
+{
+ for (int multiSampleIndex = 0; multiSampleIndex <= D3DMULTISAMPLE_16_SAMPLES; multiSampleIndex++)
+ {
+ HRESULT result = mD3d9->CheckDeviceMultiSampleType(mAdapter, mDeviceType, format,
+ TRUE, (D3DMULTISAMPLE_TYPE)multiSampleIndex, NULL);
+
+ multiSampleArray[multiSampleIndex] = SUCCEEDED(result);
+ }
+}
+
+bool Renderer9::getBGRATextureSupport() const
+{
+ // DirectX 9 always supports BGRA
+ return true;
+}
+
+bool Renderer9::getDXT1TextureSupport()
+{
+ return mDXT1TextureSupport;
+}
+
+bool Renderer9::getDXT3TextureSupport()
+{
+ return mDXT3TextureSupport;
+}
+
+bool Renderer9::getDXT5TextureSupport()
+{
+ return mDXT5TextureSupport;
+}
+
+bool Renderer9::getDepthTextureSupport() const
+{
+ return mDepthTextureSupport;
+}
+
+bool Renderer9::getFloat32TextureSupport(bool *filtering, bool *renderable)
+{
+ *filtering = mFloat32FilterSupport;
+ *renderable = mFloat32RenderSupport;
+ return mFloat32TextureSupport;
+}
+
+bool Renderer9::getFloat16TextureSupport(bool *filtering, bool *renderable)
+{
+ *filtering = mFloat16FilterSupport;
+ *renderable = mFloat16RenderSupport;
+ return mFloat16TextureSupport;
+}
+
+bool Renderer9::getLuminanceTextureSupport()
+{
+ return mLuminanceTextureSupport;
+}
+
+bool Renderer9::getLuminanceAlphaTextureSupport()
+{
+ return mLuminanceAlphaTextureSupport;
+}
+
+bool Renderer9::getTextureFilterAnisotropySupport() const
+{
+ return mSupportsTextureFilterAnisotropy;
+}
+
+float Renderer9::getTextureMaxAnisotropy() const
+{
+ if (mSupportsTextureFilterAnisotropy)
+ {
+ return static_cast<float>(mDeviceCaps.MaxAnisotropy);
+ }
+ return 1.0f;
+}
+
+bool Renderer9::getEventQuerySupport()
+{
+ return mEventQuerySupport;
+}
+
+unsigned int Renderer9::getMaxVertexTextureImageUnits() const
+{
+ META_ASSERT(MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 <= gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS);
+ return mVertexTextureSupport ? MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 : 0;
+}
+
+unsigned int Renderer9::getMaxCombinedTextureImageUnits() const
+{
+ return gl::MAX_TEXTURE_IMAGE_UNITS + getMaxVertexTextureImageUnits();
+}
+
+unsigned int Renderer9::getReservedVertexUniformVectors() const
+{
+ return 2; // dx_ViewAdjust and dx_DepthRange.
+}
+
+unsigned int Renderer9::getReservedFragmentUniformVectors() const
+{
+ return 3; // dx_ViewCoords, dx_DepthFront and dx_DepthRange.
+}
+
+unsigned int Renderer9::getMaxVertexUniformVectors() const
+{
+ return MAX_VERTEX_CONSTANT_VECTORS_D3D9 - getReservedVertexUniformVectors();
+}
+
+unsigned int Renderer9::getMaxFragmentUniformVectors() const
+{
+ const int maxPixelConstantVectors = (getMajorShaderModel() >= 3) ? MAX_PIXEL_CONSTANT_VECTORS_SM3 : MAX_PIXEL_CONSTANT_VECTORS_SM2;
+
+ return maxPixelConstantVectors - getReservedFragmentUniformVectors();
+}
+
+unsigned int Renderer9::getMaxVaryingVectors() const
+{
+ return (getMajorShaderModel() >= 3) ? MAX_VARYING_VECTORS_SM3 : MAX_VARYING_VECTORS_SM2;
+}
+
+bool Renderer9::getNonPower2TextureSupport() const
+{
+ return mSupportsNonPower2Textures;
+}
+
+bool Renderer9::getOcclusionQuerySupport() const
+{
+ return mOcclusionQuerySupport;
+}
+
+bool Renderer9::getInstancingSupport() const
+{
+ return mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0);
+}
+
+bool Renderer9::getShareHandleSupport() const
+{
+ // PIX doesn't seem to support using share handles, so disable them.
+ return (mD3d9Ex != NULL) && !gl::perfActive();
+}
+
+bool Renderer9::getDerivativeInstructionSupport() const
+{
+ return (mDeviceCaps.PS20Caps.Caps & D3DPS20CAPS_GRADIENTINSTRUCTIONS) != 0;
+}
+
+bool Renderer9::getPostSubBufferSupport() const
+{
+ return true;
+}
+
+int Renderer9::getMajorShaderModel() const
+{
+ return D3DSHADER_VERSION_MAJOR(mDeviceCaps.PixelShaderVersion);
+}
+
+float Renderer9::getMaxPointSize() const
+{
+ // Point size clamped at 1.0f for SM2
+ return getMajorShaderModel() == 3 ? mDeviceCaps.MaxPointSize : 1.0f;
+}
+
+int Renderer9::getMaxViewportDimension() const
+{
+ int maxTextureDimension = std::min(std::min(getMaxTextureWidth(), getMaxTextureHeight()),
+ (int)gl::IMPLEMENTATION_MAX_TEXTURE_SIZE);
+ return maxTextureDimension;
+}
+
+int Renderer9::getMaxTextureWidth() const
+{
+ return (int)mDeviceCaps.MaxTextureWidth;
+}
+
+int Renderer9::getMaxTextureHeight() const
+{
+ return (int)mDeviceCaps.MaxTextureHeight;
+}
+
+bool Renderer9::get32BitIndexSupport() const
+{
+ return mDeviceCaps.MaxVertexIndex >= (1 << 16);
+}
+
+DWORD Renderer9::getCapsDeclTypes() const
+{
+ return mDeviceCaps.DeclTypes;
+}
+
+int Renderer9::getMinSwapInterval() const
+{
+ return mMinSwapInterval;
+}
+
+int Renderer9::getMaxSwapInterval() const
+{
+ return mMaxSwapInterval;
+}
+
+int Renderer9::getMaxSupportedSamples() const
+{
+ return mMaxSupportedSamples;
+}
+
+int Renderer9::getNearestSupportedSamples(D3DFORMAT format, int requested) const
+{
+ if (requested == 0)
+ {
+ return requested;
+ }
+
+ std::map<D3DFORMAT, bool *>::const_iterator itr = mMultiSampleSupport.find(format);
+ if (itr == mMultiSampleSupport.end())
+ {
+ if (format == D3DFMT_UNKNOWN)
+ return 0;
+ return -1;
+ }
+
+ for (int i = requested; i <= D3DMULTISAMPLE_16_SAMPLES; ++i)
+ {
+ if (itr->second[i] && i != D3DMULTISAMPLE_NONMASKABLE)
+ {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+unsigned int Renderer9::getMaxRenderTargets() const
+{
+ // we do not support MRT in d3d9
+ return 1;
+}
+
+D3DFORMAT Renderer9::ConvertTextureInternalFormat(GLint internalformat)
+{
+ switch (internalformat)
+ {
+ case GL_DEPTH_COMPONENT16:
+ case GL_DEPTH_COMPONENT32_OES:
+ case GL_DEPTH24_STENCIL8_OES:
+ return D3DFMT_INTZ;
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ return D3DFMT_DXT1;
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+ return D3DFMT_DXT3;
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+ return D3DFMT_DXT5;
+ case GL_RGBA32F_EXT:
+ case GL_RGB32F_EXT:
+ case GL_ALPHA32F_EXT:
+ case GL_LUMINANCE32F_EXT:
+ case GL_LUMINANCE_ALPHA32F_EXT:
+ return D3DFMT_A32B32G32R32F;
+ case GL_RGBA16F_EXT:
+ case GL_RGB16F_EXT:
+ case GL_ALPHA16F_EXT:
+ case GL_LUMINANCE16F_EXT:
+ case GL_LUMINANCE_ALPHA16F_EXT:
+ return D3DFMT_A16B16G16R16F;
+ case GL_LUMINANCE8_EXT:
+ if (getLuminanceTextureSupport())
+ {
+ return D3DFMT_L8;
+ }
+ break;
+ case GL_LUMINANCE8_ALPHA8_EXT:
+ if (getLuminanceAlphaTextureSupport())
+ {
+ return D3DFMT_A8L8;
+ }
+ break;
+ case GL_RGB8_OES:
+ case GL_RGB565:
+ return D3DFMT_X8R8G8B8;
+ }
+
+ return D3DFMT_A8R8G8B8;
+}
+
+bool Renderer9::copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source)
+{
+ bool result = false;
+
+ if (source && dest)
+ {
+ TextureStorage9_2D *source9 = TextureStorage9_2D::makeTextureStorage9_2D(source->getStorageInstance());
+ TextureStorage9_2D *dest9 = TextureStorage9_2D::makeTextureStorage9_2D(dest->getStorageInstance());
+
+ int levels = source9->levelCount();
+ for (int i = 0; i < levels; ++i)
+ {
+ IDirect3DSurface9 *srcSurf = source9->getSurfaceLevel(i, false);
+ IDirect3DSurface9 *dstSurf = dest9->getSurfaceLevel(i, false);
+
+ result = copyToRenderTarget(dstSurf, srcSurf, source9->isManaged());
+
+ if (srcSurf) srcSurf->Release();
+ if (dstSurf) dstSurf->Release();
+
+ if (!result)
+ return false;
+ }
+ }
+
+ return result;
+}
+
+bool Renderer9::copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source)
+{
+ bool result = false;
+
+ if (source && dest)
+ {
+ TextureStorage9_Cube *source9 = TextureStorage9_Cube::makeTextureStorage9_Cube(source->getStorageInstance());
+ TextureStorage9_Cube *dest9 = TextureStorage9_Cube::makeTextureStorage9_Cube(dest->getStorageInstance());
+ int levels = source9->levelCount();
+ for (int f = 0; f < 6; f++)
+ {
+ for (int i = 0; i < levels; i++)
+ {
+ IDirect3DSurface9 *srcSurf = source9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, false);
+ IDirect3DSurface9 *dstSurf = dest9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, true);
+
+ result = copyToRenderTarget(dstSurf, srcSurf, source9->isManaged());
+
+ if (srcSurf) srcSurf->Release();
+ if (dstSurf) dstSurf->Release();
+
+ if (!result)
+ return false;
+ }
+ }
+ }
+
+ return result;
+}
+
+D3DPOOL Renderer9::getBufferPool(DWORD usage) const
+{
+ if (mD3d9Ex != NULL)
+ {
+ return D3DPOOL_DEFAULT;
+ }
+ else
+ {
+ if (!(usage & D3DUSAGE_DYNAMIC))
+ {
+ return D3DPOOL_MANAGED;
+ }
+ }
+
+ return D3DPOOL_DEFAULT;
+}
+
+bool Renderer9::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level)
+{
+ RECT rect;
+ rect.left = sourceRect.x;
+ rect.top = sourceRect.y;
+ rect.right = sourceRect.x + sourceRect.width;
+ rect.bottom = sourceRect.y + sourceRect.height;
+
+ return mBlit->copy(framebuffer, rect, destFormat, xoffset, yoffset, storage, level);
+}
+
+bool Renderer9::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level)
+{
+ RECT rect;
+ rect.left = sourceRect.x;
+ rect.top = sourceRect.y;
+ rect.right = sourceRect.x + sourceRect.width;
+ rect.bottom = sourceRect.y + sourceRect.height;
+
+ return mBlit->copy(framebuffer, rect, destFormat, xoffset, yoffset, storage, target, level);
+}
+
+bool Renderer9::blitRect(gl::Framebuffer *readFramebuffer, const gl::Rectangle &readRect, gl::Framebuffer *drawFramebuffer, const gl::Rectangle &drawRect,
+ bool blitRenderTarget, bool blitDepthStencil)
+{
+ endScene();
+
+ if (blitRenderTarget)
+ {
+ gl::Renderbuffer *readBuffer = readFramebuffer->getColorbuffer(0);
+ gl::Renderbuffer *drawBuffer = drawFramebuffer->getColorbuffer(0);
+ RenderTarget9 *readRenderTarget = NULL;
+ RenderTarget9 *drawRenderTarget = NULL;
+ IDirect3DSurface9* readSurface = NULL;
+ IDirect3DSurface9* drawSurface = NULL;
+
+ if (readBuffer)
+ {
+ readRenderTarget = RenderTarget9::makeRenderTarget9(readBuffer->getRenderTarget());
+ }
+ if (drawBuffer)
+ {
+ drawRenderTarget = RenderTarget9::makeRenderTarget9(drawBuffer->getRenderTarget());
+ }
+
+ if (readRenderTarget)
+ {
+ readSurface = readRenderTarget->getSurface();
+ }
+ if (drawRenderTarget)
+ {
+ drawSurface = drawRenderTarget->getSurface();
+ }
+
+ if (!readSurface || !drawSurface)
+ {
+ ERR("Failed to retrieve the render target.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ RECT srcRect;
+ srcRect.left = readRect.x;
+ srcRect.right = readRect.x + readRect.width;
+ srcRect.top = readRect.y;
+ srcRect.bottom = readRect.y + readRect.height;
+
+ RECT dstRect;
+ dstRect.left = drawRect.x;
+ dstRect.right = drawRect.x + drawRect.width;
+ dstRect.top = drawRect.y;
+ dstRect.bottom = drawRect.y + drawRect.height;
+
+ HRESULT result = mDevice->StretchRect(readSurface, &srcRect, drawSurface, &dstRect, D3DTEXF_NONE);
+
+ readSurface->Release();
+ drawSurface->Release();
+
+ if (FAILED(result))
+ {
+ ERR("BlitFramebufferANGLE failed: StretchRect returned %x.", result);
+ return false;
+ }
+ }
+
+ if (blitDepthStencil)
+ {
+ gl::Renderbuffer *readBuffer = readFramebuffer->getDepthOrStencilbuffer();
+ gl::Renderbuffer *drawBuffer = drawFramebuffer->getDepthOrStencilbuffer();
+ RenderTarget9 *readDepthStencil = NULL;
+ RenderTarget9 *drawDepthStencil = NULL;
+ IDirect3DSurface9* readSurface = NULL;
+ IDirect3DSurface9* drawSurface = NULL;
+
+ if (readBuffer)
+ {
+ readDepthStencil = RenderTarget9::makeRenderTarget9(readBuffer->getDepthStencil());
+ }
+ if (drawBuffer)
+ {
+ drawDepthStencil = RenderTarget9::makeRenderTarget9(drawBuffer->getDepthStencil());
+ }
+
+ if (readDepthStencil)
+ {
+ readSurface = readDepthStencil->getSurface();
+ }
+ if (drawDepthStencil)
+ {
+ drawSurface = drawDepthStencil->getSurface();
+ }
+
+ if (!readSurface || !drawSurface)
+ {
+ ERR("Failed to retrieve the render target.");
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ HRESULT result = mDevice->StretchRect(readSurface, NULL, drawSurface, NULL, D3DTEXF_NONE);
+
+ readSurface->Release();
+ drawSurface->Release();
+
+ if (FAILED(result))
+ {
+ ERR("BlitFramebufferANGLE failed: StretchRect returned %x.", result);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void Renderer9::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type,
+ GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels)
+{
+ RenderTarget9 *renderTarget = NULL;
+ IDirect3DSurface9 *surface = NULL;
+ gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer(0);
+
+ if (colorbuffer)
+ {
+ renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget());
+ }
+
+ if (renderTarget)
+ {
+ surface = renderTarget->getSurface();
+ }
+
+ if (!surface)
+ {
+ // context must be lost
+ return;
+ }
+
+ D3DSURFACE_DESC desc;
+ surface->GetDesc(&desc);
+
+ if (desc.MultiSampleType != D3DMULTISAMPLE_NONE)
+ {
+ UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render target
+ surface->Release();
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+
+ HRESULT result;
+ IDirect3DSurface9 *systemSurface = NULL;
+ bool directToPixels = !packReverseRowOrder && packAlignment <= 4 && getShareHandleSupport() &&
+ x == 0 && y == 0 && UINT(width) == desc.Width && UINT(height) == desc.Height &&
+ desc.Format == D3DFMT_A8R8G8B8 && format == GL_BGRA_EXT && type == GL_UNSIGNED_BYTE;
+ if (directToPixels)
+ {
+ // Use the pixels ptr as a shared handle to write directly into client's memory
+ result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format,
+ D3DPOOL_SYSTEMMEM, &systemSurface, &pixels);
+ if (FAILED(result))
+ {
+ // Try again without the shared handle
+ directToPixels = false;
+ }
+ }
+
+ if (!directToPixels)
+ {
+ result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format,
+ D3DPOOL_SYSTEMMEM, &systemSurface, NULL);
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+ surface->Release();
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+ }
+
+ result = mDevice->GetRenderTargetData(surface, systemSurface);
+ surface->Release();
+ surface = NULL;
+
+ if (FAILED(result))
+ {
+ systemSurface->Release();
+
+ // It turns out that D3D will sometimes produce more error
+ // codes than those documented.
+ if (d3d9::isDeviceLostError(result))
+ {
+ notifyDeviceLost();
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+ else
+ {
+ UNREACHABLE();
+ return;
+ }
+
+ }
+
+ if (directToPixels)
+ {
+ systemSurface->Release();
+ return;
+ }
+
+ RECT rect;
+ rect.left = gl::clamp(x, 0L, static_cast<LONG>(desc.Width));
+ rect.top = gl::clamp(y, 0L, static_cast<LONG>(desc.Height));
+ rect.right = gl::clamp(x + width, 0L, static_cast<LONG>(desc.Width));
+ rect.bottom = gl::clamp(y + height, 0L, static_cast<LONG>(desc.Height));
+
+ D3DLOCKED_RECT lock;
+ result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY);
+
+ if (FAILED(result))
+ {
+ UNREACHABLE();
+ systemSurface->Release();
+
+ return; // No sensible error to generate
+ }
+
+ unsigned char *dest = (unsigned char*)pixels;
+ unsigned short *dest16 = (unsigned short*)pixels;
+
+ unsigned char *source;
+ int inputPitch;
+ if (packReverseRowOrder)
+ {
+ source = ((unsigned char*)lock.pBits) + lock.Pitch * (rect.bottom - rect.top - 1);
+ inputPitch = -lock.Pitch;
+ }
+ else
+ {
+ source = (unsigned char*)lock.pBits;
+ inputPitch = lock.Pitch;
+ }
+
+ unsigned int fastPixelSize = 0;
+
+ if (desc.Format == D3DFMT_A8R8G8B8 &&
+ format == GL_BGRA_EXT &&
+ type == GL_UNSIGNED_BYTE)
+ {
+ fastPixelSize = 4;
+ }
+ else if ((desc.Format == D3DFMT_A4R4G4B4 &&
+ format == GL_BGRA_EXT &&
+ type == GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT) ||
+ (desc.Format == D3DFMT_A1R5G5B5 &&
+ format == GL_BGRA_EXT &&
+ type == GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT))
+ {
+ fastPixelSize = 2;
+ }
+ else if (desc.Format == D3DFMT_A16B16G16R16F &&
+ format == GL_RGBA &&
+ type == GL_HALF_FLOAT_OES)
+ {
+ fastPixelSize = 8;
+ }
+ else if (desc.Format == D3DFMT_A32B32G32R32F &&
+ format == GL_RGBA &&
+ type == GL_FLOAT)
+ {
+ fastPixelSize = 16;
+ }
+
+ for (int j = 0; j < rect.bottom - rect.top; j++)
+ {
+ if (fastPixelSize != 0)
+ {
+ // Fast path for formats which require no translation:
+ // D3DFMT_A8R8G8B8 to BGRA/UNSIGNED_BYTE
+ // D3DFMT_A4R4G4B4 to BGRA/UNSIGNED_SHORT_4_4_4_4_REV_EXT
+ // D3DFMT_A1R5G5B5 to BGRA/UNSIGNED_SHORT_1_5_5_5_REV_EXT
+ // D3DFMT_A16B16G16R16F to RGBA/HALF_FLOAT_OES
+ // D3DFMT_A32B32G32R32F to RGBA/FLOAT
+ //
+ // Note that buffers with no alpha go through the slow path below.
+ memcpy(dest + j * outputPitch,
+ source + j * inputPitch,
+ (rect.right - rect.left) * fastPixelSize);
+ continue;
+ }
+ else if (desc.Format == D3DFMT_A8R8G8B8 &&
+ format == GL_RGBA &&
+ type == GL_UNSIGNED_BYTE)
+ {
+ // Fast path for swapping red with blue
+ for (int i = 0; i < rect.right - rect.left; i++)
+ {
+ unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch);
+ *(unsigned int*)(dest + 4 * i + j * outputPitch) =
+ (argb & 0xFF00FF00) | // Keep alpha and green
+ (argb & 0x00FF0000) >> 16 | // Move red to blue
+ (argb & 0x000000FF) << 16; // Move blue to red
+ }
+ continue;
+ }
+
+ for (int i = 0; i < rect.right - rect.left; i++)
+ {
+ float r;
+ float g;
+ float b;
+ float a;
+
+ switch (desc.Format)
+ {
+ case D3DFMT_R5G6B5:
+ {
+ unsigned short rgb = *(unsigned short*)(source + 2 * i + j * inputPitch);
+
+ a = 1.0f;
+ b = (rgb & 0x001F) * (1.0f / 0x001F);
+ g = (rgb & 0x07E0) * (1.0f / 0x07E0);
+ r = (rgb & 0xF800) * (1.0f / 0xF800);
+ }
+ break;
+ case D3DFMT_A1R5G5B5:
+ {
+ unsigned short argb = *(unsigned short*)(source + 2 * i + j * inputPitch);
+
+ a = (argb & 0x8000) ? 1.0f : 0.0f;
+ b = (argb & 0x001F) * (1.0f / 0x001F);
+ g = (argb & 0x03E0) * (1.0f / 0x03E0);
+ r = (argb & 0x7C00) * (1.0f / 0x7C00);
+ }
+ break;
+ case D3DFMT_A8R8G8B8:
+ {
+ unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch);
+
+ a = (argb & 0xFF000000) * (1.0f / 0xFF000000);
+ b = (argb & 0x000000FF) * (1.0f / 0x000000FF);
+ g = (argb & 0x0000FF00) * (1.0f / 0x0000FF00);
+ r = (argb & 0x00FF0000) * (1.0f / 0x00FF0000);
+ }
+ break;
+ case D3DFMT_X8R8G8B8:
+ {
+ unsigned int xrgb = *(unsigned int*)(source + 4 * i + j * inputPitch);
+
+ a = 1.0f;
+ b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF);
+ g = (xrgb & 0x0000FF00) * (1.0f / 0x0000FF00);
+ r = (xrgb & 0x00FF0000) * (1.0f / 0x00FF0000);
+ }
+ break;
+ case D3DFMT_A2R10G10B10:
+ {
+ unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch);
+
+ a = (argb & 0xC0000000) * (1.0f / 0xC0000000);
+ b = (argb & 0x000003FF) * (1.0f / 0x000003FF);
+ g = (argb & 0x000FFC00) * (1.0f / 0x000FFC00);
+ r = (argb & 0x3FF00000) * (1.0f / 0x3FF00000);
+ }
+ break;
+ case D3DFMT_A32B32G32R32F:
+ {
+ // float formats in D3D are stored rgba, rather than the other way round
+ r = *((float*)(source + 16 * i + j * inputPitch) + 0);
+ g = *((float*)(source + 16 * i + j * inputPitch) + 1);
+ b = *((float*)(source + 16 * i + j * inputPitch) + 2);
+ a = *((float*)(source + 16 * i + j * inputPitch) + 3);
+ }
+ break;
+ case D3DFMT_A16B16G16R16F:
+ {
+ // float formats in D3D are stored rgba, rather than the other way round
+ r = gl::float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 0));
+ g = gl::float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 1));
+ b = gl::float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 2));
+ a = gl::float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 3));
+ }
+ break;
+ default:
+ UNIMPLEMENTED(); // FIXME
+ UNREACHABLE();
+ return;
+ }
+
+ switch (format)
+ {
+ case GL_RGBA:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f);
+ dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);
+ dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f);
+ dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f);
+ break;
+ default: UNREACHABLE();
+ }
+ break;
+ case GL_BGRA_EXT:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * b + 0.5f);
+ dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);
+ dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * r + 0.5f);
+ dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f);
+ break;
+ case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
+ // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section
+ // this type is packed as follows:
+ // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+ // --------------------------------------------------------------------------------
+ // | 4th | 3rd | 2nd | 1st component |
+ // --------------------------------------------------------------------------------
+ // in the case of BGRA_EXT, B is the first component, G the second, and so forth.
+ dest16[i + j * outputPitch / sizeof(unsigned short)] =
+ ((unsigned short)(15 * a + 0.5f) << 12)|
+ ((unsigned short)(15 * r + 0.5f) << 8) |
+ ((unsigned short)(15 * g + 0.5f) << 4) |
+ ((unsigned short)(15 * b + 0.5f) << 0);
+ break;
+ case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
+ // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section
+ // this type is packed as follows:
+ // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+ // --------------------------------------------------------------------------------
+ // | 4th | 3rd | 2nd | 1st component |
+ // --------------------------------------------------------------------------------
+ // in the case of BGRA_EXT, B is the first component, G the second, and so forth.
+ dest16[i + j * outputPitch / sizeof(unsigned short)] =
+ ((unsigned short)( a + 0.5f) << 15) |
+ ((unsigned short)(31 * r + 0.5f) << 10) |
+ ((unsigned short)(31 * g + 0.5f) << 5) |
+ ((unsigned short)(31 * b + 0.5f) << 0);
+ break;
+ default: UNREACHABLE();
+ }
+ break;
+ case GL_RGB:
+ switch (type)
+ {
+ case GL_UNSIGNED_SHORT_5_6_5:
+ dest16[i + j * outputPitch / sizeof(unsigned short)] =
+ ((unsigned short)(31 * b + 0.5f) << 0) |
+ ((unsigned short)(63 * g + 0.5f) << 5) |
+ ((unsigned short)(31 * r + 0.5f) << 11);
+ break;
+ case GL_UNSIGNED_BYTE:
+ dest[3 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f);
+ dest[3 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);
+ dest[3 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f);
+ break;
+ default: UNREACHABLE();
+ }
+ break;
+ default: UNREACHABLE();
+ }
+ }
+ }
+
+ systemSurface->UnlockRect();
+
+ systemSurface->Release();
+}
+
+RenderTarget *Renderer9::createRenderTarget(SwapChain *swapChain, bool depth)
+{
+ SwapChain9 *swapChain9 = SwapChain9::makeSwapChain9(swapChain);
+ IDirect3DSurface9 *surface = NULL;
+ if (depth)
+ {
+ surface = swapChain9->getDepthStencil();
+ }
+ else
+ {
+ surface = swapChain9->getRenderTarget();
+ }
+
+ RenderTarget9 *renderTarget = new RenderTarget9(this, surface);
+
+ return renderTarget;
+}
+
+RenderTarget *Renderer9::createRenderTarget(int width, int height, GLenum format, GLsizei samples, bool depth)
+{
+ RenderTarget9 *renderTarget = new RenderTarget9(this, width, height, format, samples);
+ return renderTarget;
+}
+
+ShaderExecutable *Renderer9::loadExecutable(const void *function, size_t length, rx::ShaderType type)
+{
+ ShaderExecutable9 *executable = NULL;
+
+ switch (type)
+ {
+ case rx::SHADER_VERTEX:
+ {
+ IDirect3DVertexShader9 *vshader = createVertexShader((DWORD*)function, length);
+ if (vshader)
+ {
+ executable = new ShaderExecutable9(function, length, vshader);
+ }
+ }
+ break;
+ case rx::SHADER_PIXEL:
+ {
+ IDirect3DPixelShader9 *pshader = createPixelShader((DWORD*)function, length);
+ if (pshader)
+ {
+ executable = new ShaderExecutable9(function, length, pshader);
+ }
+ }
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ return executable;
+}
+
+ShaderExecutable *Renderer9::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, D3DWorkaroundType workaround)
+{
+ const char *profile = NULL;
+
+ switch (type)
+ {
+ case rx::SHADER_VERTEX:
+ profile = getMajorShaderModel() >= 3 ? "vs_3_0" : "vs_2_0";
+ break;
+ case rx::SHADER_PIXEL:
+ profile = getMajorShaderModel() >= 3 ? "ps_3_0" : "ps_2_0";
+ break;
+ default:
+ UNREACHABLE();
+ return NULL;
+ }
+
+ // ANGLE issue 486:
+ // Work-around a D3D9 compiler bug that presents itself when using conditional discard, by disabling optimization
+ UINT optimizationFlags = (workaround == ANGLE_D3D_WORKAROUND_SM3_OPTIMIZER ? D3DCOMPILE_SKIP_OPTIMIZATION : ANGLE_COMPILE_OPTIMIZATION_LEVEL);
+
+ ID3DBlob *binary = (ID3DBlob*)compileToBinary(infoLog, shaderHLSL, profile, optimizationFlags, true);
+ if (!binary)
+ return NULL;
+
+ ShaderExecutable *executable = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type);
+ binary->Release();
+
+ return executable;
+}
+
+bool Renderer9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest)
+{
+ return mBlit->boxFilter(source, dest);
+}
+
+D3DPOOL Renderer9::getTexturePool(DWORD usage) const
+{
+ if (mD3d9Ex != NULL)
+ {
+ return D3DPOOL_DEFAULT;
+ }
+ else
+ {
+ if (!(usage & (D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_RENDERTARGET)))
+ {
+ return D3DPOOL_MANAGED;
+ }
+ }
+
+ return D3DPOOL_DEFAULT;
+}
+
+bool Renderer9::copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged)
+{
+ if (source && dest)
+ {
+ HRESULT result = D3DERR_OUTOFVIDEOMEMORY;
+
+ if (fromManaged)
+ {
+ D3DSURFACE_DESC desc;
+ source->GetDesc(&desc);
+
+ IDirect3DSurface9 *surf = 0;
+ result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surf, NULL);
+
+ if (SUCCEEDED(result))
+ {
+ Image9::copyLockableSurfaces(surf, source);
+ result = mDevice->UpdateSurface(surf, NULL, dest, NULL);
+ surf->Release();
+ }
+ }
+ else
+ {
+ endScene();
+ result = mDevice->StretchRect(source, NULL, dest, NULL, D3DTEXF_NONE);
+ }
+
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+Image *Renderer9::createImage()
+{
+ return new Image9();
+}
+
+void Renderer9::generateMipmap(Image *dest, Image *src)
+{
+ Image9 *src9 = Image9::makeImage9(src);
+ Image9 *dst9 = Image9::makeImage9(dest);
+ Image9::generateMipmap(dst9, src9);
+}
+
+TextureStorage *Renderer9::createTextureStorage2D(SwapChain *swapChain)
+{
+ SwapChain9 *swapChain9 = SwapChain9::makeSwapChain9(swapChain);
+ return new TextureStorage9_2D(this, swapChain9);
+}
+
+TextureStorage *Renderer9::createTextureStorage2D(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height)
+{
+ return new TextureStorage9_2D(this, levels, internalformat, usage, forceRenderable, width, height);
+}
+
+TextureStorage *Renderer9::createTextureStorageCube(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size)
+{
+ return new TextureStorage9_Cube(this, levels, internalformat, usage, forceRenderable, size);
+}
+
+bool Renderer9::getLUID(LUID *adapterLuid) const
+{
+ adapterLuid->HighPart = 0;
+ adapterLuid->LowPart = 0;
+
+ if (mD3d9Ex)
+ {
+ mD3d9Ex->GetAdapterLUID(mAdapter, adapterLuid);
+ return true;
+ }
+
+ return false;
+}
+
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Renderer9.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9Renderer9h"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Renderer9.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Renderer9.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Renderer9.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,356 @@
</span><ins>+//
+// Copyright (c) 2012-2013 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.
+//
+
+// Renderer9.h: Defines a back-end specific class for the D3D9 renderer.
+
+#ifndef LIBGLESV2_RENDERER_RENDERER9_H_
+#define LIBGLESV2_RENDERER_RENDERER9_H_
+
+#include "common/angleutils.h"
+#include "libGLESv2/mathutil.h"
+#include "libGLESv2/renderer/ShaderCache.h"
+#include "libGLESv2/renderer/d3d9/VertexDeclarationCache.h"
+#include "libGLESv2/renderer/Renderer.h"
+#include "libGLESv2/renderer/RenderTarget.h"
+
+namespace gl
+{
+class Renderbuffer;
+}
+
+namespace rx
+{
+class VertexDataManager;
+class IndexDataManager;
+class StreamingIndexBufferInterface;
+struct TranslatedAttribute;
+
+class Renderer9 : public Renderer
+{
+ public:
+ Renderer9(egl::Display *display, HDC hDc, bool softwareDevice);
+ virtual ~Renderer9();
+
+ static Renderer9 *makeRenderer9(Renderer *renderer);
+
+ virtual EGLint initialize();
+ virtual bool resetDevice();
+
+ virtual int generateConfigs(ConfigDesc **configDescList);
+ virtual void deleteConfigs(ConfigDesc *configDescList);
+
+ void startScene();
+ void endScene();
+
+ virtual void sync(bool block);
+
+ virtual SwapChain *createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat);
+
+ IDirect3DQuery9* allocateEventQuery();
+ void freeEventQuery(IDirect3DQuery9* query);
+
+ // resource creation
+ IDirect3DVertexShader9 *createVertexShader(const DWORD *function, size_t length);
+ IDirect3DPixelShader9 *createPixelShader(const DWORD *function, size_t length);
+ HRESULT createVertexBuffer(UINT Length, DWORD Usage, IDirect3DVertexBuffer9 **ppVertexBuffer);
+ HRESULT createIndexBuffer(UINT Length, DWORD Usage, D3DFORMAT Format, IDirect3DIndexBuffer9 **ppIndexBuffer);
+#if 0
+ void *createTexture2D();
+ void *createTextureCube();
+ void *createQuery();
+ void *createIndexBuffer();
+ void *createVertexbuffer();
+
+ // state setup
+ void applyShaders();
+ void applyConstants();
+#endif
+ virtual void setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &sampler);
+ virtual void setTexture(gl::SamplerType type, int index, gl::Texture *texture);
+
+ virtual void setRasterizerState(const gl::RasterizerState &rasterState);
+ virtual void setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::Color &blendColor,
+ unsigned int sampleMask);
+ virtual void setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef,
+ int stencilBackRef, bool frontFaceCCW);
+
+ virtual void setScissorRectangle(const gl::Rectangle &scissor, bool enabled);
+ virtual bool setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace,
+ bool ignoreViewport);
+
+ virtual bool applyRenderTarget(gl::Framebuffer *frameBuffer);
+ virtual void applyShaders(gl::ProgramBinary *programBinary);
+ virtual void applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray *uniformArray);
+ virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount);
+ virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances);
+ virtual GLenum applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo);
+
+ virtual void drawArrays(GLenum mode, GLsizei count, GLsizei instances);
+ virtual void drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances);
+
+ virtual void clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer);
+
+ virtual void markAllStateDirty();
+
+ // lost device
+ void notifyDeviceLost();
+ virtual bool isDeviceLost();
+ virtual bool testDeviceLost(bool notify);
+ virtual bool testDeviceResettable();
+
+ // Renderer capabilities
+ IDirect3DDevice9 *getDevice() { return mDevice; }
+ virtual DWORD getAdapterVendor() const;
+ virtual std::string getRendererDescription() const;
+ virtual GUID getAdapterIdentifier() const;
+
+ virtual bool getBGRATextureSupport() const;
+ virtual bool getDXT1TextureSupport();
+ virtual bool getDXT3TextureSupport();
+ virtual bool getDXT5TextureSupport();
+ virtual bool getEventQuerySupport();
+ virtual bool getFloat32TextureSupport(bool *filtering, bool *renderable);
+ virtual bool getFloat16TextureSupport(bool *filtering, bool *renderable);
+ virtual bool getLuminanceTextureSupport();
+ virtual bool getLuminanceAlphaTextureSupport();
+ virtual unsigned int getMaxVertexTextureImageUnits() const;
+ virtual unsigned int getMaxCombinedTextureImageUnits() const;
+ virtual unsigned int getReservedVertexUniformVectors() const;
+ virtual unsigned int getReservedFragmentUniformVectors() const;
+ virtual unsigned int getMaxVertexUniformVectors() const;
+ virtual unsigned int getMaxFragmentUniformVectors() const;
+ virtual unsigned int getMaxVaryingVectors() const;
+ virtual bool getNonPower2TextureSupport() const;
+ virtual bool getDepthTextureSupport() const;
+ virtual bool getOcclusionQuerySupport() const;
+ virtual bool getInstancingSupport() const;
+ virtual bool getTextureFilterAnisotropySupport() const;
+ virtual float getTextureMaxAnisotropy() const;
+ virtual bool getShareHandleSupport() const;
+ virtual bool getDerivativeInstructionSupport() const;
+ virtual bool getPostSubBufferSupport() const;
+
+ virtual int getMajorShaderModel() const;
+ virtual float getMaxPointSize() const;
+ virtual int getMaxViewportDimension() const;
+ virtual int getMaxTextureWidth() const;
+ virtual int getMaxTextureHeight() const;
+ virtual bool get32BitIndexSupport() const;
+ DWORD getCapsDeclTypes() const;
+ virtual int getMinSwapInterval() const;
+ virtual int getMaxSwapInterval() const;
+
+ virtual GLsizei getMaxSupportedSamples() const;
+ int getNearestSupportedSamples(D3DFORMAT format, int requested) const;
+
+ virtual unsigned int getMaxRenderTargets() const;
+
+ D3DFORMAT ConvertTextureInternalFormat(GLint internalformat);
+
+ // Pixel operations
+ virtual bool copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source);
+ virtual bool copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source);
+
+ virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level);
+ virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level);
+
+ virtual bool blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect,
+ bool blitRenderTarget, bool blitDepthStencil);
+ virtual void readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type,
+ GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels);
+
+ // RenderTarget creation
+ virtual RenderTarget *createRenderTarget(SwapChain *swapChain, bool depth);
+ virtual RenderTarget *createRenderTarget(int width, int height, GLenum format, GLsizei samples, bool depth);
+
+ // Shader operations
+ virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type);
+ virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, D3DWorkaroundType workaround);
+
+ // Image operations
+ virtual Image *createImage();
+ virtual void generateMipmap(Image *dest, Image *source);
+ virtual TextureStorage *createTextureStorage2D(SwapChain *swapChain);
+ virtual TextureStorage *createTextureStorage2D(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height);
+ virtual TextureStorage *createTextureStorageCube(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size);
+
+ // Buffer creation
+ virtual VertexBuffer *createVertexBuffer();
+ virtual IndexBuffer *createIndexBuffer();
+ virtual BufferStorage *createBufferStorage();
+
+ // Query and Fence creation
+ virtual QueryImpl *createQuery(GLenum type);
+ virtual FenceImpl *createFence();
+
+ // D3D9-renderer specific methods
+ bool boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest);
+
+ D3DPOOL getTexturePool(DWORD usage) const;
+
+ virtual bool getLUID(LUID *adapterLuid) const;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Renderer9);
+
+ void deinitialize();
+
+ void applyUniformnfv(gl::Uniform *targetUniform, const GLfloat *v);
+ void applyUniformniv(gl::Uniform *targetUniform, const GLint *v);
+ void applyUniformnbv(gl::Uniform *targetUniform, const GLint *v);
+
+ void drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer);
+ void drawIndexedPoints(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer);
+
+ void getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray);
+ bool copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged);
+ gl::Renderbuffer *getNullColorbuffer(gl::Renderbuffer *depthbuffer);
+
+ D3DPOOL getBufferPool(DWORD usage) const;
+
+ HMODULE mD3d9Module;
+ HDC mDc;
+
+ void initializeDevice();
+ D3DPRESENT_PARAMETERS getDefaultPresentParameters();
+ void releaseDeviceResources();
+
+ HRESULT getDeviceStatusCode();
+ bool isRemovedDeviceResettable() const;
+ bool resetRemovedDevice();
+
+ UINT mAdapter;
+ D3DDEVTYPE mDeviceType;
+ bool mSoftwareDevice; // FIXME: Deprecate
+ IDirect3D9 *mD3d9; // Always valid after successful initialization.
+ IDirect3D9Ex *mD3d9Ex; // Might be null if D3D9Ex is not supported.
+ IDirect3DDevice9 *mDevice;
+ IDirect3DDevice9Ex *mDeviceEx; // Might be null if D3D9Ex is not supported.
+
+ Blit *mBlit;
+
+ HWND mDeviceWindow;
+
+ bool mDeviceLost;
+ D3DCAPS9 mDeviceCaps;
+ D3DADAPTER_IDENTIFIER9 mAdapterIdentifier;
+
+ D3DPRIMITIVETYPE mPrimitiveType;
+ int mPrimitiveCount;
+ GLsizei mRepeatDraw;
+
+ bool mSceneStarted;
+ bool mSupportsNonPower2Textures;
+ bool mSupportsTextureFilterAnisotropy;
+ int mMinSwapInterval;
+ int mMaxSwapInterval;
+
+ bool mOcclusionQuerySupport;
+ bool mEventQuerySupport;
+ bool mVertexTextureSupport;
+
+ bool mDepthTextureSupport;
+
+ bool mFloat32TextureSupport;
+ bool mFloat32FilterSupport;
+ bool mFloat32RenderSupport;
+
+ bool mFloat16TextureSupport;
+ bool mFloat16FilterSupport;
+ bool mFloat16RenderSupport;
+
+ bool mDXT1TextureSupport;
+ bool mDXT3TextureSupport;
+ bool mDXT5TextureSupport;
+
+ bool mLuminanceTextureSupport;
+ bool mLuminanceAlphaTextureSupport;
+
+ std::map<D3DFORMAT, bool *> mMultiSampleSupport;
+ GLsizei mMaxSupportedSamples;
+
+ // current render target states
+ unsigned int mAppliedRenderTargetSerial;
+ unsigned int mAppliedDepthbufferSerial;
+ unsigned int mAppliedStencilbufferSerial;
+ bool mDepthStencilInitialized;
+ bool mRenderTargetDescInitialized;
+ rx::RenderTarget::Desc mRenderTargetDesc;
+ unsigned int mCurStencilSize;
+ unsigned int mCurDepthSize;
+
+ IDirect3DStateBlock9 *mMaskedClearSavedState;
+
+ // previously set render states
+ bool mForceSetDepthStencilState;
+ gl::DepthStencilState mCurDepthStencilState;
+ int mCurStencilRef;
+ int mCurStencilBackRef;
+ bool mCurFrontFaceCCW;
+
+ bool mForceSetRasterState;
+ gl::RasterizerState mCurRasterState;
+
+ bool mForceSetScissor;
+ gl::Rectangle mCurScissor;
+ bool mScissorEnabled;
+
+ bool mForceSetViewport;
+ gl::Rectangle mCurViewport;
+ float mCurNear;
+ float mCurFar;
+ float mCurDepthFront;
+
+ bool mForceSetBlendState;
+ gl::BlendState mCurBlendState;
+ gl::Color mCurBlendColor;
+ GLuint mCurSampleMask;
+
+ // Currently applied sampler states
+ bool mForceSetVertexSamplerStates[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS];
+ gl::SamplerState mCurVertexSamplerStates[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS];
+
+ bool mForceSetPixelSamplerStates[gl::MAX_TEXTURE_IMAGE_UNITS];
+ gl::SamplerState mCurPixelSamplerStates[gl::MAX_TEXTURE_IMAGE_UNITS];
+
+ // Currently applied textures
+ unsigned int mCurVertexTextureSerials[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS];
+ unsigned int mCurPixelTextureSerials[gl::MAX_TEXTURE_IMAGE_UNITS];
+
+ unsigned int mAppliedIBSerial;
+ unsigned int mAppliedProgramBinarySerial;
+
+ rx::dx_VertexConstants mVertexConstants;
+ rx::dx_PixelConstants mPixelConstants;
+ bool mDxUniformsDirty;
+
+ // A pool of event queries that are currently unused.
+ std::vector<IDirect3DQuery9*> mEventQueryPool;
+ VertexShaderCache mVertexShaderCache;
+ PixelShaderCache mPixelShaderCache;
+
+ VertexDataManager *mVertexDataManager;
+ VertexDeclarationCache mVertexDeclarationCache;
+
+ IndexDataManager *mIndexDataManager;
+ StreamingIndexBufferInterface *mLineLoopIB;
+
+ enum { NUM_NULL_COLORBUFFER_CACHE_ENTRIES = 12 };
+ struct NullColorbufferCacheEntry
+ {
+ UINT lruCount;
+ int width;
+ int height;
+ gl::Renderbuffer *buffer;
+ } mNullColorbufferCache[NUM_NULL_COLORBUFFER_CACHE_ENTRIES];
+ UINT mMaxNullColorbufferLRU;
+
+};
+
+}
+#endif // LIBGLESV2_RENDERER_RENDERER9_H_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/Renderer9.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9ShaderExecutable9cpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/ShaderExecutable9.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/ShaderExecutable9.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/ShaderExecutable9.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,60 @@
</span><ins>+#include "precompiled.h"
+//
+// Copyright (c) 2012-2013 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.
+//
+
+// ShaderExecutable9.cpp: Implements a D3D9-specific class to contain shader
+// executable implementation details.
+
+#include "libGLESv2/renderer/d3d9/ShaderExecutable9.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+ShaderExecutable9::ShaderExecutable9(const void *function, size_t length, IDirect3DPixelShader9 *executable)
+ : ShaderExecutable(function, length)
+{
+ mPixelExecutable = executable;
+ mVertexExecutable = NULL;
+}
+
+ShaderExecutable9::ShaderExecutable9(const void *function, size_t length, IDirect3DVertexShader9 *executable)
+ : ShaderExecutable(function, length)
+{
+ mVertexExecutable = executable;
+ mPixelExecutable = NULL;
+}
+
+ShaderExecutable9::~ShaderExecutable9()
+{
+ if (mVertexExecutable)
+ {
+ mVertexExecutable->Release();
+ }
+ if (mPixelExecutable)
+ {
+ mPixelExecutable->Release();
+ }
+}
+
+ShaderExecutable9 *ShaderExecutable9::makeShaderExecutable9(ShaderExecutable *executable)
+{
+ ASSERT(HAS_DYNAMIC_TYPE(ShaderExecutable9*, executable));
+ return static_cast<ShaderExecutable9*>(executable);
+}
+
+IDirect3DVertexShader9 *ShaderExecutable9::getVertexShader() const
+{
+ return mVertexExecutable;
+}
+
+IDirect3DPixelShader9 *ShaderExecutable9::getPixelShader() const
+{
+ return mPixelExecutable;
+}
+
+}
</ins><span class="cx">\ No newline at end of file
</span><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/ShaderExecutable9.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9ShaderExecutable9h"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/ShaderExecutable9.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/ShaderExecutable9.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/ShaderExecutable9.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,39 @@
</span><ins>+//
+// Copyright (c) 2012-2013 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.
+//
+
+// ShaderExecutable9.h: Defines a D3D9-specific class to contain shader
+// executable implementation details.
+
+#ifndef LIBGLESV2_RENDERER_SHADEREXECUTABLE9_H_
+#define LIBGLESV2_RENDERER_SHADEREXECUTABLE9_H_
+
+#include "libGLESv2/renderer/ShaderExecutable.h"
+
+namespace rx
+{
+
+class ShaderExecutable9 : public ShaderExecutable
+{
+ public:
+ ShaderExecutable9(const void *function, size_t length, IDirect3DPixelShader9 *executable);
+ ShaderExecutable9(const void *function, size_t length, IDirect3DVertexShader9 *executable);
+ virtual ~ShaderExecutable9();
+
+ static ShaderExecutable9 *makeShaderExecutable9(ShaderExecutable *executable);
+
+ IDirect3DPixelShader9 *getPixelShader() const;
+ IDirect3DVertexShader9 *getVertexShader() const;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ShaderExecutable9);
+
+ IDirect3DPixelShader9 *mPixelExecutable;
+ IDirect3DVertexShader9 *mVertexExecutable;
+};
+
+}
+
+#endif // LIBGLESV2_RENDERER_SHADEREXECUTABLE9_H_
</ins><span class="cx">\ No newline at end of file
</span><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/ShaderExecutable9.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9SwapChain9cpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/SwapChain9.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/SwapChain9.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/SwapChain9.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,445 @@
</span><ins>+#include "precompiled.h"
+//
+// Copyright (c) 2012-2013 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.
+//
+
+// SwapChain9.cpp: Implements a back-end specific class for the D3D9 swap chain.
+
+#include "libGLESv2/renderer/d3d9/SwapChain9.h"
+#include "libGLESv2/renderer/d3d9/renderer9_utils.h"
+#include "libGLESv2/renderer/d3d9/Renderer9.h"
+
+namespace rx
+{
+
+SwapChain9::SwapChain9(Renderer9 *renderer, HWND window, HANDLE shareHandle,
+ GLenum backBufferFormat, GLenum depthBufferFormat)
+ : mRenderer(renderer), SwapChain(window, shareHandle, backBufferFormat, depthBufferFormat)
+{
+ mSwapChain = NULL;
+ mBackBuffer = NULL;
+ mDepthStencil = NULL;
+ mRenderTarget = NULL;
+ mOffscreenTexture = NULL;
+ mWidth = -1;
+ mHeight = -1;
+ mSwapInterval = -1;
+}
+
+SwapChain9::~SwapChain9()
+{
+ release();
+}
+
+void SwapChain9::release()
+{
+ if (mSwapChain)
+ {
+ mSwapChain->Release();
+ mSwapChain = NULL;
+ }
+
+ if (mBackBuffer)
+ {
+ mBackBuffer->Release();
+ mBackBuffer = NULL;
+ }
+
+ if (mDepthStencil)
+ {
+ mDepthStencil->Release();
+ mDepthStencil = NULL;
+ }
+
+ if (mRenderTarget)
+ {
+ mRenderTarget->Release();
+ mRenderTarget = NULL;
+ }
+
+ if (mOffscreenTexture)
+ {
+ mOffscreenTexture->Release();
+ mOffscreenTexture = NULL;
+ }
+
+ if (mWindow)
+ mShareHandle = NULL;
+}
+
+static DWORD convertInterval(EGLint interval)
+{
+#if ANGLE_FORCE_VSYNC_OFF
+ return D3DPRESENT_INTERVAL_IMMEDIATE;
+#else
+ switch(interval)
+ {
+ case 0: return D3DPRESENT_INTERVAL_IMMEDIATE;
+ case 1: return D3DPRESENT_INTERVAL_ONE;
+ case 2: return D3DPRESENT_INTERVAL_TWO;
+ case 3: return D3DPRESENT_INTERVAL_THREE;
+ case 4: return D3DPRESENT_INTERVAL_FOUR;
+ default: UNREACHABLE();
+ }
+
+ return D3DPRESENT_INTERVAL_DEFAULT;
+#endif
+}
+
+EGLint SwapChain9::resize(int backbufferWidth, int backbufferHeight)
+{
+ // D3D9 does not support resizing swap chains without recreating them
+ return reset(backbufferWidth, backbufferHeight, mSwapInterval);
+}
+
+EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval)
+{
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+
+ if (device == NULL)
+ {
+ return EGL_BAD_ACCESS;
+ }
+
+ // Evict all non-render target textures to system memory and release all resources
+ // before reallocating them to free up as much video memory as possible.
+ device->EvictManagedResources();
+
+ HRESULT result;
+
+ // Release specific resources to free up memory for the new render target, while the
+ // old render target still exists for the purpose of preserving its contents.
+ if (mSwapChain)
+ {
+ mSwapChain->Release();
+ mSwapChain = NULL;
+ }
+
+ if (mBackBuffer)
+ {
+ mBackBuffer->Release();
+ mBackBuffer = NULL;
+ }
+
+ if (mOffscreenTexture)
+ {
+ mOffscreenTexture->Release();
+ mOffscreenTexture = NULL;
+ }
+
+ if (mDepthStencil)
+ {
+ mDepthStencil->Release();
+ mDepthStencil = NULL;
+ }
+
+ HANDLE *pShareHandle = NULL;
+ if (!mWindow && mRenderer->getShareHandleSupport())
+ {
+ pShareHandle = &mShareHandle;
+ }
+
+ result = device->CreateTexture(backbufferWidth, backbufferHeight, 1, D3DUSAGE_RENDERTARGET,
+ gl_d3d9::ConvertRenderbufferFormat(mBackBufferFormat), D3DPOOL_DEFAULT,
+ &mOffscreenTexture, pShareHandle);
+ if (FAILED(result))
+ {
+ ERR("Could not create offscreen texture: %08lX", result);
+ release();
+
+ if (d3d9::isDeviceLostError(result))
+ {
+ return EGL_CONTEXT_LOST;
+ }
+ else
+ {
+ return EGL_BAD_ALLOC;
+ }
+ }
+
+ IDirect3DSurface9 *oldRenderTarget = mRenderTarget;
+
+ result = mOffscreenTexture->GetSurfaceLevel(0, &mRenderTarget);
+ ASSERT(SUCCEEDED(result));
+
+ if (oldRenderTarget)
+ {
+ RECT rect =
+ {
+ 0, 0,
+ mWidth, mHeight
+ };
+
+ if (rect.right > static_cast<LONG>(backbufferWidth))
+ {
+ rect.right = backbufferWidth;
+ }
+
+ if (rect.bottom > static_cast<LONG>(backbufferHeight))
+ {
+ rect.bottom = backbufferHeight;
+ }
+
+ mRenderer->endScene();
+
+ result = device->StretchRect(oldRenderTarget, &rect, mRenderTarget, &rect, D3DTEXF_NONE);
+ ASSERT(SUCCEEDED(result));
+
+ oldRenderTarget->Release();
+ }
+
+ if (mWindow)
+ {
+ D3DPRESENT_PARAMETERS presentParameters = {0};
+ presentParameters.AutoDepthStencilFormat = gl_d3d9::ConvertRenderbufferFormat(mDepthBufferFormat);
+ presentParameters.BackBufferCount = 1;
+ presentParameters.BackBufferFormat = gl_d3d9::ConvertRenderbufferFormat(mBackBufferFormat);
+ presentParameters.EnableAutoDepthStencil = FALSE;
+ presentParameters.Flags = 0;
+ presentParameters.hDeviceWindow = mWindow;
+ presentParameters.MultiSampleQuality = 0; // FIXME: Unimplemented
+ presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE; // FIXME: Unimplemented
+ presentParameters.PresentationInterval = convertInterval(swapInterval);
+ presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
+ presentParameters.Windowed = TRUE;
+ presentParameters.BackBufferWidth = backbufferWidth;
+ presentParameters.BackBufferHeight = backbufferHeight;
+
+ // http://crbug.com/140239
+ // http://crbug.com/143434
+ //
+ // Some AMD/Intel switchable systems / drivers appear to round swap chain surfaces to a multiple of 64 pixels in width
+ // when using the integrated Intel. This rounds the width up rather than down.
+ //
+ // Some non-switchable AMD GPUs / drivers do not respect the source rectangle to Present. Therefore, when the vendor ID
+ // is not Intel, the back buffer width must be exactly the same width as the window or horizontal scaling will occur.
+ if (mRenderer->getAdapterVendor() == VENDOR_ID_INTEL)
+ {
+ presentParameters.BackBufferWidth = (presentParameters.BackBufferWidth + 63) / 64 * 64;
+ }
+
+ result = device->CreateAdditionalSwapChain(&presentParameters, &mSwapChain);
+
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_INVALIDCALL || result == D3DERR_DEVICELOST);
+
+ ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result);
+ release();
+
+ if (d3d9::isDeviceLostError(result))
+ {
+ return EGL_CONTEXT_LOST;
+ }
+ else
+ {
+ return EGL_BAD_ALLOC;
+ }
+ }
+
+ result = mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer);
+ ASSERT(SUCCEEDED(result));
+ InvalidateRect(mWindow, NULL, FALSE);
+ }
+
+ if (mDepthBufferFormat != GL_NONE)
+ {
+ result = device->CreateDepthStencilSurface(backbufferWidth, backbufferHeight,
+ gl_d3d9::ConvertRenderbufferFormat(mDepthBufferFormat),
+ D3DMULTISAMPLE_NONE, 0, FALSE, &mDepthStencil, NULL);
+
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_INVALIDCALL);
+
+ ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result);
+ release();
+
+ if (d3d9::isDeviceLostError(result))
+ {
+ return EGL_CONTEXT_LOST;
+ }
+ else
+ {
+ return EGL_BAD_ALLOC;
+ }
+ }
+ }
+
+ mWidth = backbufferWidth;
+ mHeight = backbufferHeight;
+ mSwapInterval = swapInterval;
+
+ return EGL_SUCCESS;
+}
+
+// parameters should be validated/clamped by caller
+EGLint SwapChain9::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
+{
+ if (!mSwapChain)
+ {
+ return EGL_SUCCESS;
+ }
+
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+
+ // Disable all pipeline operations
+ device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
+ device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
+ device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
+ device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
+ device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
+ device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
+ device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
+ device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED);
+ device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE);
+ device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
+ device->SetPixelShader(NULL);
+ device->SetVertexShader(NULL);
+
+ device->SetRenderTarget(0, mBackBuffer);
+ device->SetDepthStencilSurface(NULL);
+
+ device->SetTexture(0, mOffscreenTexture);
+ device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
+ device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+ device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
+ device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
+ device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
+ device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
+ device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
+ device->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
+
+ for (UINT streamIndex = 0; streamIndex < gl::MAX_VERTEX_ATTRIBS; streamIndex++)
+ {
+ device->SetStreamSourceFreq(streamIndex, 1);
+ }
+
+ D3DVIEWPORT9 viewport = {0, 0, mWidth, mHeight, 0.0f, 1.0f};
+ device->SetViewport(&viewport);
+
+ float x1 = x - 0.5f;
+ float y1 = (mHeight - y - height) - 0.5f;
+ float x2 = (x + width) - 0.5f;
+ float y2 = (mHeight - y) - 0.5f;
+
+ float u1 = x / float(mWidth);
+ float v1 = y / float(mHeight);
+ float u2 = (x + width) / float(mWidth);
+ float v2 = (y + height) / float(mHeight);
+
+ float quad[4][6] = {{x1, y1, 0.0f, 1.0f, u1, v2},
+ {x2, y1, 0.0f, 1.0f, u2, v2},
+ {x2, y2, 0.0f, 1.0f, u2, v1},
+ {x1, y2, 0.0f, 1.0f, u1, v1}}; // x, y, z, rhw, u, v
+
+ mRenderer->startScene();
+ device->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, quad, 6 * sizeof(float));
+ mRenderer->endScene();
+
+ device->SetTexture(0, NULL);
+
+ RECT rect =
+ {
+ x, mHeight - y - height,
+ x + width, mHeight - y
+ };
+
+ HRESULT result = mSwapChain->Present(&rect, &rect, NULL, NULL, 0);
+
+ mRenderer->markAllStateDirty();
+
+ if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DRIVERINTERNALERROR)
+ {
+ return EGL_BAD_ALLOC;
+ }
+
+ // http://crbug.com/313210
+ // If our swap failed, trigger a device lost event. Resetting will work around an AMD-specific
+ // device removed bug with lost contexts when reinstalling drivers.
+ if (FAILED(result))
+ {
+ mRenderer->notifyDeviceLost();
+ return EGL_CONTEXT_LOST;
+ }
+
+ return EGL_SUCCESS;
+}
+
+// Increments refcount on surface.
+// caller must Release() the returned surface
+IDirect3DSurface9 *SwapChain9::getRenderTarget()
+{
+ if (mRenderTarget)
+ {
+ mRenderTarget->AddRef();
+ }
+
+ return mRenderTarget;
+}
+
+// Increments refcount on surface.
+// caller must Release() the returned surface
+IDirect3DSurface9 *SwapChain9::getDepthStencil()
+{
+ if (mDepthStencil)
+ {
+ mDepthStencil->AddRef();
+ }
+
+ return mDepthStencil;
+}
+
+// Increments refcount on texture.
+// caller must Release() the returned texture
+IDirect3DTexture9 *SwapChain9::getOffscreenTexture()
+{
+ if (mOffscreenTexture)
+ {
+ mOffscreenTexture->AddRef();
+ }
+
+ return mOffscreenTexture;
+}
+
+SwapChain9 *SwapChain9::makeSwapChain9(SwapChain *swapChain)
+{
+ ASSERT(HAS_DYNAMIC_TYPE(rx::SwapChain9*, swapChain));
+ return static_cast<rx::SwapChain9*>(swapChain);
+}
+
+void SwapChain9::recreate()
+{
+ if (!mSwapChain)
+ {
+ return;
+ }
+
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+ if (device == NULL)
+ {
+ return;
+ }
+
+ D3DPRESENT_PARAMETERS presentParameters;
+ HRESULT result = mSwapChain->GetPresentParameters(&presentParameters);
+ ASSERT(SUCCEEDED(result));
+
+ IDirect3DSwapChain9* newSwapChain = NULL;
+ result = device->CreateAdditionalSwapChain(&presentParameters, &newSwapChain);
+ if (FAILED(result))
+ {
+ return;
+ }
+
+ mSwapChain->Release();
+ mSwapChain = newSwapChain;
+
+ mBackBuffer->Release();
+ result = mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer);
+ ASSERT(SUCCEEDED(result));
+}
+
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/SwapChain9.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9SwapChain9h"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/SwapChain9.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/SwapChain9.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/SwapChain9.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,55 @@
</span><ins>+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// SwapChain9.h: Defines a back-end specific class for the D3D9 swap chain.
+
+#ifndef LIBGLESV2_RENDERER_SWAPCHAIN9_H_
+#define LIBGLESV2_RENDERER_SWAPCHAIN9_H_
+
+#include "common/angleutils.h"
+#include "libGLESv2/renderer/SwapChain.h"
+
+namespace rx
+{
+class Renderer9;
+
+class SwapChain9 : public SwapChain
+{
+ public:
+ SwapChain9(Renderer9 *renderer, HWND window, HANDLE shareHandle,
+ GLenum backBufferFormat, GLenum depthBufferFormat);
+ virtual ~SwapChain9();
+
+ EGLint resize(EGLint backbufferWidth, EGLint backbufferHeight);
+ virtual EGLint reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval);
+ virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height);
+ virtual void recreate();
+
+ virtual IDirect3DSurface9 *getRenderTarget();
+ virtual IDirect3DSurface9 *getDepthStencil();
+ virtual IDirect3DTexture9 *getOffscreenTexture();
+
+ static SwapChain9 *makeSwapChain9(SwapChain *swapChain);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(SwapChain9);
+
+ void release();
+
+ Renderer9 *mRenderer;
+ EGLint mHeight;
+ EGLint mWidth;
+ EGLint mSwapInterval;
+
+ IDirect3DSwapChain9 *mSwapChain;
+ IDirect3DSurface9 *mBackBuffer;
+ IDirect3DSurface9 *mRenderTarget;
+ IDirect3DSurface9 *mDepthStencil;
+ IDirect3DTexture9* mOffscreenTexture;
+};
+
+}
+#endif // LIBGLESV2_RENDERER_SWAPCHAIN9_H_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/SwapChain9.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9TextureStorage9cpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/TextureStorage9.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/TextureStorage9.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/TextureStorage9.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,328 @@
</span><ins>+#include "precompiled.h"
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// TextureStorage9.cpp: Implements the abstract rx::TextureStorage9 class and its concrete derived
+// classes TextureStorage9_2D and TextureStorage9_Cube, which act as the interface to the
+// D3D9 texture.
+
+#include "libGLESv2/main.h"
+#include "libGLESv2/renderer/d3d9/Renderer9.h"
+#include "libGLESv2/renderer/d3d9/TextureStorage9.h"
+#include "libGLESv2/renderer/d3d9/SwapChain9.h"
+#include "libGLESv2/renderer/d3d9/RenderTarget9.h"
+#include "libGLESv2/renderer/d3d9/renderer9_utils.h"
+#include "libGLESv2/Texture.h"
+
+namespace rx
+{
+TextureStorage9::TextureStorage9(Renderer *renderer, DWORD usage)
+ : mLodOffset(0),
+ mRenderer(Renderer9::makeRenderer9(renderer)),
+ mD3DUsage(usage),
+ mD3DPool(mRenderer->getTexturePool(usage))
+{
+}
+
+TextureStorage9::~TextureStorage9()
+{
+}
+
+TextureStorage9 *TextureStorage9::makeTextureStorage9(TextureStorage *storage)
+{
+ ASSERT(HAS_DYNAMIC_TYPE(TextureStorage9*, storage));
+ return static_cast<TextureStorage9*>(storage);
+}
+
+DWORD TextureStorage9::GetTextureUsage(D3DFORMAT d3dfmt, GLenum glusage, bool forceRenderable)
+{
+ DWORD d3dusage = 0;
+
+ if (d3dfmt == D3DFMT_INTZ)
+ {
+ d3dusage |= D3DUSAGE_DEPTHSTENCIL;
+ }
+ else if(forceRenderable || (TextureStorage9::IsTextureFormatRenderable(d3dfmt) && (glusage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE)))
+ {
+ d3dusage |= D3DUSAGE_RENDERTARGET;
+ }
+ return d3dusage;
+}
+
+bool TextureStorage9::IsTextureFormatRenderable(D3DFORMAT format)
+{
+ if (format == D3DFMT_INTZ)
+ {
+ return true;
+ }
+ switch(format)
+ {
+ case D3DFMT_L8:
+ case D3DFMT_A8L8:
+ case D3DFMT_DXT1:
+ case D3DFMT_DXT3:
+ case D3DFMT_DXT5:
+ return false;
+ case D3DFMT_A8R8G8B8:
+ case D3DFMT_X8R8G8B8:
+ case D3DFMT_A16B16G16R16F:
+ case D3DFMT_A32B32G32R32F:
+ return true;
+ default:
+ UNREACHABLE();
+ }
+
+ return false;
+}
+
+bool TextureStorage9::isRenderTarget() const
+{
+ return (mD3DUsage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL)) != 0;
+}
+
+bool TextureStorage9::isManaged() const
+{
+ return (mD3DPool == D3DPOOL_MANAGED);
+}
+
+D3DPOOL TextureStorage9::getPool() const
+{
+ return mD3DPool;
+}
+
+DWORD TextureStorage9::getUsage() const
+{
+ return mD3DUsage;
+}
+
+int TextureStorage9::getLodOffset() const
+{
+ return mLodOffset;
+}
+
+int TextureStorage9::levelCount()
+{
+ return getBaseTexture() ? getBaseTexture()->GetLevelCount() - getLodOffset() : 0;
+}
+
+TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, SwapChain9 *swapchain) : TextureStorage9(renderer, D3DUSAGE_RENDERTARGET)
+{
+ IDirect3DTexture9 *surfaceTexture = swapchain->getOffscreenTexture();
+ mTexture = surfaceTexture;
+ mRenderTarget = NULL;
+
+ initializeRenderTarget();
+}
+
+TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height)
+ : TextureStorage9(renderer, GetTextureUsage(Renderer9::makeRenderer9(renderer)->ConvertTextureInternalFormat(internalformat), usage, forceRenderable))
+{
+ mTexture = NULL;
+ mRenderTarget = NULL;
+ // if the width or height is not positive this should be treated as an incomplete texture
+ // we handle that here by skipping the d3d texture creation
+ if (width > 0 && height > 0)
+ {
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+ gl::MakeValidSize(false, gl::IsCompressed(internalformat), &width, &height, &mLodOffset);
+ HRESULT result = device->CreateTexture(width, height, levels ? levels + mLodOffset : 0, getUsage(),
+ mRenderer->ConvertTextureInternalFormat(internalformat), getPool(), &mTexture, NULL);
+
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+ gl::error(GL_OUT_OF_MEMORY);
+ }
+ }
+
+ initializeRenderTarget();
+}
+
+TextureStorage9_2D::~TextureStorage9_2D()
+{
+ if (mTexture)
+ {
+ mTexture->Release();
+ }
+
+ delete mRenderTarget;
+}
+
+TextureStorage9_2D *TextureStorage9_2D::makeTextureStorage9_2D(TextureStorage *storage)
+{
+ ASSERT(HAS_DYNAMIC_TYPE(TextureStorage9_2D*, storage));
+ return static_cast<TextureStorage9_2D*>(storage);
+}
+
+// Increments refcount on surface.
+// caller must Release() the returned surface
+IDirect3DSurface9 *TextureStorage9_2D::getSurfaceLevel(int level, bool dirty)
+{
+ IDirect3DSurface9 *surface = NULL;
+
+ if (mTexture)
+ {
+ HRESULT result = mTexture->GetSurfaceLevel(level + mLodOffset, &surface);
+ ASSERT(SUCCEEDED(result));
+
+ // With managed textures the driver needs to be informed of updates to the lower mipmap levels
+ if (level + mLodOffset != 0 && isManaged() && dirty)
+ {
+ mTexture->AddDirtyRect(NULL);
+ }
+ }
+
+ return surface;
+}
+
+RenderTarget *TextureStorage9_2D::getRenderTarget()
+{
+ return mRenderTarget;
+}
+
+void TextureStorage9_2D::generateMipmap(int level)
+{
+ IDirect3DSurface9 *upper = getSurfaceLevel(level - 1, false);
+ IDirect3DSurface9 *lower = getSurfaceLevel(level, true);
+
+ if (upper != NULL && lower != NULL)
+ {
+ mRenderer->boxFilter(upper, lower);
+ }
+
+ if (upper != NULL) upper->Release();
+ if (lower != NULL) lower->Release();
+}
+
+IDirect3DBaseTexture9 *TextureStorage9_2D::getBaseTexture() const
+{
+ return mTexture;
+}
+
+void TextureStorage9_2D::initializeRenderTarget()
+{
+ ASSERT(mRenderTarget == NULL);
+
+ if (mTexture != NULL && isRenderTarget())
+ {
+ IDirect3DSurface9 *surface = getSurfaceLevel(0, false);
+
+ mRenderTarget = new RenderTarget9(mRenderer, surface);
+ }
+}
+
+TextureStorage9_Cube::TextureStorage9_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size)
+ : TextureStorage9(renderer, GetTextureUsage(Renderer9::makeRenderer9(renderer)->ConvertTextureInternalFormat(internalformat), usage, forceRenderable))
+{
+ mTexture = NULL;
+ for (int i = 0; i < 6; ++i)
+ {
+ mRenderTarget[i] = NULL;
+ }
+
+ // if the size is not positive this should be treated as an incomplete texture
+ // we handle that here by skipping the d3d texture creation
+ if (size > 0)
+ {
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+ int height = size;
+ gl::MakeValidSize(false, gl::IsCompressed(internalformat), &size, &height, &mLodOffset);
+ HRESULT result = device->CreateCubeTexture(size, levels ? levels + mLodOffset : 0, getUsage(),
+ mRenderer->ConvertTextureInternalFormat(internalformat), getPool(), &mTexture, NULL);
+
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+ gl::error(GL_OUT_OF_MEMORY);
+ }
+ }
+
+ initializeRenderTarget();
+}
+
+TextureStorage9_Cube::~TextureStorage9_Cube()
+{
+ if (mTexture)
+ {
+ mTexture->Release();
+ }
+
+ for (int i = 0; i < 6; ++i)
+ {
+ delete mRenderTarget[i];
+ }
+}
+
+TextureStorage9_Cube *TextureStorage9_Cube::makeTextureStorage9_Cube(TextureStorage *storage)
+{
+ ASSERT(HAS_DYNAMIC_TYPE(TextureStorage9_Cube*, storage));
+ return static_cast<TextureStorage9_Cube*>(storage);
+}
+
+// Increments refcount on surface.
+// caller must Release() the returned surface
+IDirect3DSurface9 *TextureStorage9_Cube::getCubeMapSurface(GLenum faceTarget, int level, bool dirty)
+{
+ IDirect3DSurface9 *surface = NULL;
+
+ if (mTexture)
+ {
+ D3DCUBEMAP_FACES face = gl_d3d9::ConvertCubeFace(faceTarget);
+ HRESULT result = mTexture->GetCubeMapSurface(face, level + mLodOffset, &surface);
+ ASSERT(SUCCEEDED(result));
+
+ // With managed textures the driver needs to be informed of updates to the lower mipmap levels
+ if (level != 0 && isManaged() && dirty)
+ {
+ mTexture->AddDirtyRect(face, NULL);
+ }
+ }
+
+ return surface;
+}
+
+RenderTarget *TextureStorage9_Cube::getRenderTarget(GLenum faceTarget)
+{
+ return mRenderTarget[gl::TextureCubeMap::faceIndex(faceTarget)];
+}
+
+void TextureStorage9_Cube::generateMipmap(int face, int level)
+{
+ IDirect3DSurface9 *upper = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level - 1, false);
+ IDirect3DSurface9 *lower = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, true);
+
+ if (upper != NULL && lower != NULL)
+ {
+ mRenderer->boxFilter(upper, lower);
+ }
+
+ if (upper != NULL) upper->Release();
+ if (lower != NULL) lower->Release();
+}
+
+IDirect3DBaseTexture9 *TextureStorage9_Cube::getBaseTexture() const
+{
+ return mTexture;
+}
+
+void TextureStorage9_Cube::initializeRenderTarget()
+{
+ if (mTexture != NULL && isRenderTarget())
+ {
+ IDirect3DSurface9 *surface = NULL;
+
+ for (int i = 0; i < 6; ++i)
+ {
+ ASSERT(mRenderTarget[i] == NULL);
+
+ surface = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, false);
+
+ mRenderTarget[i] = new RenderTarget9(mRenderer, surface);
+ }
+ }
+}
+
+}
</ins><span class="cx">\ No newline at end of file
</span><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/TextureStorage9.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9TextureStorage9h"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/TextureStorage9.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/TextureStorage9.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/TextureStorage9.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,109 @@
</span><ins>+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// TextureStorage9.h: Defines the abstract rx::TextureStorage9 class and its concrete derived
+// classes TextureStorage9_2D and TextureStorage9_Cube, which act as the interface to the
+// D3D9 texture.
+
+#ifndef LIBGLESV2_RENDERER_TEXTURESTORAGE9_H_
+#define LIBGLESV2_RENDERER_TEXTURESTORAGE9_H_
+
+#include "libGLESv2/renderer/TextureStorage.h"
+#include "common/debug.h"
+
+namespace rx
+{
+class Renderer9;
+class SwapChain9;
+class RenderTarget;
+class RenderTarget9;
+class Blit;
+
+class TextureStorage9 : public TextureStorage
+{
+ public:
+ TextureStorage9(Renderer *renderer, DWORD usage);
+ virtual ~TextureStorage9();
+
+ static TextureStorage9 *makeTextureStorage9(TextureStorage *storage);
+
+ static DWORD GetTextureUsage(D3DFORMAT d3dfmt, GLenum glusage, bool forceRenderable);
+ static bool IsTextureFormatRenderable(D3DFORMAT format);
+
+ D3DPOOL getPool() const;
+ DWORD getUsage() const;
+
+ virtual IDirect3DBaseTexture9 *getBaseTexture() const = 0;
+ virtual RenderTarget *getRenderTarget() { return NULL; }
+ virtual RenderTarget *getRenderTarget(GLenum faceTarget) { return NULL; }
+ virtual void generateMipmap(int level) {};
+ virtual void generateMipmap(int face, int level) {};
+
+ virtual int getLodOffset() const;
+ virtual bool isRenderTarget() const;
+ virtual bool isManaged() const;
+ virtual int levelCount();
+
+ protected:
+ int mLodOffset;
+ Renderer9 *mRenderer;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TextureStorage9);
+
+ const DWORD mD3DUsage;
+ const D3DPOOL mD3DPool;
+};
+
+class TextureStorage9_2D : public TextureStorage9
+{
+ public:
+ TextureStorage9_2D(Renderer *renderer, SwapChain9 *swapchain);
+ TextureStorage9_2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height);
+ virtual ~TextureStorage9_2D();
+
+ static TextureStorage9_2D *makeTextureStorage9_2D(TextureStorage *storage);
+
+ IDirect3DSurface9 *getSurfaceLevel(int level, bool dirty);
+ virtual RenderTarget *getRenderTarget();
+ virtual IDirect3DBaseTexture9 *getBaseTexture() const;
+ virtual void generateMipmap(int level);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TextureStorage9_2D);
+
+ void initializeRenderTarget();
+
+ IDirect3DTexture9 *mTexture;
+ RenderTarget9 *mRenderTarget;
+};
+
+class TextureStorage9_Cube : public TextureStorage9
+{
+ public:
+ TextureStorage9_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size);
+ virtual ~TextureStorage9_Cube();
+
+ static TextureStorage9_Cube *makeTextureStorage9_Cube(TextureStorage *storage);
+
+ IDirect3DSurface9 *getCubeMapSurface(GLenum faceTarget, int level, bool dirty);
+ virtual RenderTarget *getRenderTarget(GLenum faceTarget);
+ virtual IDirect3DBaseTexture9 *getBaseTexture() const;
+ virtual void generateMipmap(int face, int level);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TextureStorage9_Cube);
+
+ void initializeRenderTarget();
+
+ IDirect3DCubeTexture9 *mTexture;
+ RenderTarget9 *mRenderTarget[6];
+};
+
+}
+
+#endif // LIBGLESV2_RENDERER_TEXTURESTORAGE9_H_
+
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/TextureStorage9.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9VertexBuffer9cpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/VertexBuffer9.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/VertexBuffer9.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/VertexBuffer9.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,530 @@
</span><ins>+#include "precompiled.h"
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// VertexBuffer9.cpp: Defines the D3D9 VertexBuffer implementation.
+
+#include "libGLESv2/renderer/d3d9/VertexBuffer9.h"
+#include "libGLESv2/renderer/d3d9/vertexconversion.h"
+#include "libGLESv2/renderer/BufferStorage.h"
+#include "libGLESv2/Context.h"
+#include "libGLESv2/renderer/d3d9/Renderer9.h"
+
+#include "libGLESv2/Buffer.h"
+
+namespace rx
+{
+
+bool VertexBuffer9::mTranslationsInitialized = false;
+VertexBuffer9::FormatConverter VertexBuffer9::mFormatConverters[NUM_GL_VERTEX_ATTRIB_TYPES][2][4];
+
+VertexBuffer9::VertexBuffer9(rx::Renderer9 *const renderer) : mRenderer(renderer)
+{
+ mVertexBuffer = NULL;
+ mBufferSize = 0;
+ mDynamicUsage = false;
+
+ if (!mTranslationsInitialized)
+ {
+ initializeTranslations(renderer->getCapsDeclTypes());
+ mTranslationsInitialized = true;
+ }
+}
+
+VertexBuffer9::~VertexBuffer9()
+{
+ if (mVertexBuffer)
+ {
+ mVertexBuffer->Release();
+ mVertexBuffer = NULL;
+ }
+}
+
+bool VertexBuffer9::initialize(unsigned int size, bool dynamicUsage)
+{
+ if (mVertexBuffer)
+ {
+ mVertexBuffer->Release();
+ mVertexBuffer = NULL;
+ }
+
+ updateSerial();
+
+ if (size > 0)
+ {
+ DWORD flags = D3DUSAGE_WRITEONLY;
+ if (dynamicUsage)
+ {
+ flags |= D3DUSAGE_DYNAMIC;
+ }
+
+ HRESULT result = mRenderer->createVertexBuffer(size, flags, &mVertexBuffer);
+
+ if (FAILED(result))
+ {
+ ERR("Out of memory allocating a vertex buffer of size %lu.", size);
+ return false;
+ }
+ }
+
+ mBufferSize = size;
+ mDynamicUsage = dynamicUsage;
+ return true;
+}
+
+VertexBuffer9 *VertexBuffer9::makeVertexBuffer9(VertexBuffer *vertexBuffer)
+{
+ ASSERT(HAS_DYNAMIC_TYPE(VertexBuffer9*, vertexBuffer));
+ return static_cast<VertexBuffer9*>(vertexBuffer);
+}
+
+bool VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count,
+ GLsizei instances, unsigned int offset)
+{
+ if (mVertexBuffer)
+ {
+ gl::Buffer *buffer = attrib.mBoundBuffer.get();
+
+ int inputStride = attrib.stride();
+ int elementSize = attrib.typeSize();
+ const FormatConverter &converter = formatConverter(attrib);
+
+ DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0;
+
+ void *mapPtr = NULL;
+
+ unsigned int mapSize;
+ if (!spaceRequired(attrib, count, instances, &mapSize))
+ {
+ return false;
+ }
+
+ HRESULT result = mVertexBuffer->Lock(offset, mapSize, &mapPtr, lockFlags);
+
+ if (FAILED(result))
+ {
+ ERR("Lock failed with error 0x%08x", result);
+ return false;
+ }
+
+ const char *input = NULL;
+ if (buffer)
+ {
+ BufferStorage *storage = buffer->getStorage();
+ input = static_cast<const char*>(storage->getData()) + static_cast<int>(attrib.mOffset);
+ }
+ else
+ {
+ input = static_cast<const char*>(attrib.mPointer);
+ }
+
+ if (instances == 0 || attrib.mDivisor == 0)
+ {
+ input += inputStride * start;
+ }
+
+ if (converter.identity && inputStride == elementSize)
+ {
+ memcpy(mapPtr, input, count * inputStride);
+ }
+ else
+ {
+ converter.convertArray(input, inputStride, count, mapPtr);
+ }
+
+ mVertexBuffer->Unlock();
+
+ return true;
+ }
+ else
+ {
+ ERR("Vertex buffer not initialized.");
+ return false;
+ }
+}
+
+bool VertexBuffer9::storeRawData(const void* data, unsigned int size, unsigned int offset)
+{
+ if (mVertexBuffer)
+ {
+ DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0;
+
+ void *mapPtr = NULL;
+ HRESULT result = mVertexBuffer->Lock(offset, size, &mapPtr, lockFlags);
+
+ if (FAILED(result))
+ {
+ ERR("Lock failed with error 0x%08x", result);
+ return false;
+ }
+
+ memcpy(mapPtr, data, size);
+
+ mVertexBuffer->Unlock();
+
+ return true;
+ }
+ else
+ {
+ ERR("Vertex buffer not initialized.");
+ return false;
+ }
+}
+
+bool VertexBuffer9::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances,
+ unsigned int *outSpaceRequired) const
+{
+ return spaceRequired(attrib, count, instances, outSpaceRequired);
+}
+
+bool VertexBuffer9::requiresConversion(const gl::VertexAttribute &attrib) const
+{
+ return !formatConverter(attrib).identity;
+}
+
+unsigned int VertexBuffer9::getVertexSize(const gl::VertexAttribute &attrib) const
+{
+ unsigned int spaceRequired;
+ return getSpaceRequired(attrib, 1, 0, &spaceRequired) ? spaceRequired : 0;
+}
+
+D3DDECLTYPE VertexBuffer9::getDeclType(const gl::VertexAttribute &attrib) const
+{
+ return formatConverter(attrib).d3dDeclType;
+}
+
+unsigned int VertexBuffer9::getBufferSize() const
+{
+ return mBufferSize;
+}
+
+bool VertexBuffer9::setBufferSize(unsigned int size)
+{
+ if (size > mBufferSize)
+ {
+ return initialize(size, mDynamicUsage);
+ }
+ else
+ {
+ return true;
+ }
+}
+
+bool VertexBuffer9::discard()
+{
+ if (mVertexBuffer)
+ {
+ void *dummy;
+ HRESULT result;
+
+ result = mVertexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD);
+ if (FAILED(result))
+ {
+ ERR("Discard lock failed with error 0x%08x", result);
+ return false;
+ }
+
+ result = mVertexBuffer->Unlock();
+ if (FAILED(result))
+ {
+ ERR("Discard unlock failed with error 0x%08x", result);
+ return false;
+ }
+
+ return true;
+ }
+ else
+ {
+ ERR("Vertex buffer not initialized.");
+ return false;
+ }
+}
+
+IDirect3DVertexBuffer9 * VertexBuffer9::getBuffer() const
+{
+ return mVertexBuffer;
+}
+
+// Mapping from OpenGL-ES vertex attrib type to D3D decl type:
+//
+// BYTE SHORT (Cast)
+// BYTE-norm FLOAT (Normalize) (can't be exactly represented as SHORT-norm)
+// UNSIGNED_BYTE UBYTE4 (Identity) or SHORT (Cast)
+// UNSIGNED_BYTE-norm UBYTE4N (Identity) or FLOAT (Normalize)
+// SHORT SHORT (Identity)
+// SHORT-norm SHORT-norm (Identity) or FLOAT (Normalize)
+// UNSIGNED_SHORT FLOAT (Cast)
+// UNSIGNED_SHORT-norm USHORT-norm (Identity) or FLOAT (Normalize)
+// FIXED (not in WebGL) FLOAT (FixedToFloat)
+// FLOAT FLOAT (Identity)
+
+// GLToCType maps from GL type (as GLenum) to the C typedef.
+template <GLenum GLType> struct GLToCType { };
+
+template <> struct GLToCType<GL_BYTE> { typedef GLbyte type; };
+template <> struct GLToCType<GL_UNSIGNED_BYTE> { typedef GLubyte type; };
+template <> struct GLToCType<GL_SHORT> { typedef GLshort type; };
+template <> struct GLToCType<GL_UNSIGNED_SHORT> { typedef GLushort type; };
+template <> struct GLToCType<GL_FIXED> { typedef GLuint type; };
+template <> struct GLToCType<GL_FLOAT> { typedef GLfloat type; };
+
+// This differs from D3DDECLTYPE in that it is unsized. (Size expansion is applied last.)
+enum D3DVertexType
+{
+ D3DVT_FLOAT,
+ D3DVT_SHORT,
+ D3DVT_SHORT_NORM,
+ D3DVT_UBYTE,
+ D3DVT_UBYTE_NORM,
+ D3DVT_USHORT_NORM
+};
+
+// D3DToCType maps from D3D vertex type (as enum D3DVertexType) to the corresponding C type.
+template <unsigned int D3DType> struct D3DToCType { };
+
+template <> struct D3DToCType<D3DVT_FLOAT> { typedef float type; };
+template <> struct D3DToCType<D3DVT_SHORT> { typedef short type; };
+template <> struct D3DToCType<D3DVT_SHORT_NORM> { typedef short type; };
+template <> struct D3DToCType<D3DVT_UBYTE> { typedef unsigned char type; };
+template <> struct D3DToCType<D3DVT_UBYTE_NORM> { typedef unsigned char type; };
+template <> struct D3DToCType<D3DVT_USHORT_NORM> { typedef unsigned short type; };
+
+// Encode the type/size combinations that D3D permits. For each type/size it expands to a widener that will provide the appropriate final size.
+template <unsigned int type, int size> struct WidenRule { };
+
+template <int size> struct WidenRule<D3DVT_FLOAT, size> : NoWiden<size> { };
+template <int size> struct WidenRule<D3DVT_SHORT, size> : WidenToEven<size> { };
+template <int size> struct WidenRule<D3DVT_SHORT_NORM, size> : WidenToEven<size> { };
+template <int size> struct WidenRule<D3DVT_UBYTE, size> : WidenToFour<size> { };
+template <int size> struct WidenRule<D3DVT_UBYTE_NORM, size> : WidenToFour<size> { };
+template <int size> struct WidenRule<D3DVT_USHORT_NORM, size> : WidenToEven<size> { };
+
+// VertexTypeFlags encodes the D3DCAPS9::DeclType flag and vertex declaration flag for each D3D vertex type & size combination.
+template <unsigned int d3dtype, int size> struct VertexTypeFlags { };
+
+template <unsigned int _capflag, unsigned int _declflag>
+struct VertexTypeFlagsHelper
+{
+ enum { capflag = _capflag };
+ enum { declflag = _declflag };
+};
+
+template <> struct VertexTypeFlags<D3DVT_FLOAT, 1> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT1> { };
+template <> struct VertexTypeFlags<D3DVT_FLOAT, 2> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT2> { };
+template <> struct VertexTypeFlags<D3DVT_FLOAT, 3> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT3> { };
+template <> struct VertexTypeFlags<D3DVT_FLOAT, 4> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT4> { };
+template <> struct VertexTypeFlags<D3DVT_SHORT, 2> : VertexTypeFlagsHelper<0, D3DDECLTYPE_SHORT2> { };
+template <> struct VertexTypeFlags<D3DVT_SHORT, 4> : VertexTypeFlagsHelper<0, D3DDECLTYPE_SHORT4> { };
+template <> struct VertexTypeFlags<D3DVT_SHORT_NORM, 2> : VertexTypeFlagsHelper<D3DDTCAPS_SHORT2N, D3DDECLTYPE_SHORT2N> { };
+template <> struct VertexTypeFlags<D3DVT_SHORT_NORM, 4> : VertexTypeFlagsHelper<D3DDTCAPS_SHORT4N, D3DDECLTYPE_SHORT4N> { };
+template <> struct VertexTypeFlags<D3DVT_UBYTE, 4> : VertexTypeFlagsHelper<D3DDTCAPS_UBYTE4, D3DDECLTYPE_UBYTE4> { };
+template <> struct VertexTypeFlags<D3DVT_UBYTE_NORM, 4> : VertexTypeFlagsHelper<D3DDTCAPS_UBYTE4N, D3DDECLTYPE_UBYTE4N> { };
+template <> struct VertexTypeFlags<D3DVT_USHORT_NORM, 2> : VertexTypeFlagsHelper<D3DDTCAPS_USHORT2N, D3DDECLTYPE_USHORT2N> { };
+template <> struct VertexTypeFlags<D3DVT_USHORT_NORM, 4> : VertexTypeFlagsHelper<D3DDTCAPS_USHORT4N, D3DDECLTYPE_USHORT4N> { };
+
+
+// VertexTypeMapping maps GL type & normalized flag to preferred and fallback D3D vertex types (as D3DVertexType enums).
+template <GLenum GLtype, bool normalized> struct VertexTypeMapping { };
+
+template <D3DVertexType Preferred, D3DVertexType Fallback = Preferred>
+struct VertexTypeMappingBase
+{
+ enum { preferred = Preferred };
+ enum { fallback = Fallback };
+};
+
+template <> struct VertexTypeMapping<GL_BYTE, false> : VertexTypeMappingBase<D3DVT_SHORT> { }; // Cast
+template <> struct VertexTypeMapping<GL_BYTE, true> : VertexTypeMappingBase<D3DVT_FLOAT> { }; // Normalize
+template <> struct VertexTypeMapping<GL_UNSIGNED_BYTE, false> : VertexTypeMappingBase<D3DVT_UBYTE, D3DVT_FLOAT> { }; // Identity, Cast
+template <> struct VertexTypeMapping<GL_UNSIGNED_BYTE, true> : VertexTypeMappingBase<D3DVT_UBYTE_NORM, D3DVT_FLOAT> { }; // Identity, Normalize
+template <> struct VertexTypeMapping<GL_SHORT, false> : VertexTypeMappingBase<D3DVT_SHORT> { }; // Identity
+template <> struct VertexTypeMapping<GL_SHORT, true> : VertexTypeMappingBase<D3DVT_SHORT_NORM, D3DVT_FLOAT> { }; // Cast, Normalize
+template <> struct VertexTypeMapping<GL_UNSIGNED_SHORT, false> : VertexTypeMappingBase<D3DVT_FLOAT> { }; // Cast
+template <> struct VertexTypeMapping<GL_UNSIGNED_SHORT, true> : VertexTypeMappingBase<D3DVT_USHORT_NORM, D3DVT_FLOAT> { }; // Cast, Normalize
+template <bool normalized> struct VertexTypeMapping<GL_FIXED, normalized> : VertexTypeMappingBase<D3DVT_FLOAT> { }; // FixedToFloat
+template <bool normalized> struct VertexTypeMapping<GL_FLOAT, normalized> : VertexTypeMappingBase<D3DVT_FLOAT> { }; // Identity
+
+
+// Given a GL type & norm flag and a D3D type, ConversionRule provides the type conversion rule (Cast, Normalize, Identity, FixedToFloat).
+// The conversion rules themselves are defined in vertexconversion.h.
+
+// Almost all cases are covered by Cast (including those that are actually Identity since Cast<T,T> knows it's an identity mapping).
+template <GLenum fromType, bool normalized, unsigned int toType>
+struct ConversionRule : Cast<typename GLToCType<fromType>::type, typename D3DToCType<toType>::type> { };
+
+// All conversions from normalized types to float use the Normalize operator.
+template <GLenum fromType> struct ConversionRule<fromType, true, D3DVT_FLOAT> : Normalize<typename GLToCType<fromType>::type> { };
+
+// Use a full specialization for this so that it preferentially matches ahead of the generic normalize-to-float rules.
+template <> struct ConversionRule<GL_FIXED, true, D3DVT_FLOAT> : FixedToFloat<GLint, 16> { };
+template <> struct ConversionRule<GL_FIXED, false, D3DVT_FLOAT> : FixedToFloat<GLint, 16> { };
+
+// A 2-stage construction is used for DefaultVertexValues because float must use SimpleDefaultValues (i.e. 0/1)
+// whether it is normalized or not.
+template <class T, bool normalized> struct DefaultVertexValuesStage2 { };
+
+template <class T> struct DefaultVertexValuesStage2<T, true> : NormalizedDefaultValues<T> { };
+template <class T> struct DefaultVertexValuesStage2<T, false> : SimpleDefaultValues<T> { };
+
+// Work out the default value rule for a D3D type (expressed as the C type) and
+template <class T, bool normalized> struct DefaultVertexValues : DefaultVertexValuesStage2<T, normalized> { };
+template <bool normalized> struct DefaultVertexValues<float, normalized> : SimpleDefaultValues<float> { };
+
+// Policy rules for use with Converter, to choose whether to use the preferred or fallback conversion.
+// The fallback conversion produces an output that all D3D9 devices must support.
+template <class T> struct UsePreferred { enum { type = T::preferred }; };
+template <class T> struct UseFallback { enum { type = T::fallback }; };
+
+// Converter ties it all together. Given an OpenGL type/norm/size and choice of preferred/fallback conversion,
+// it provides all the members of the appropriate VertexDataConverter, the D3DCAPS9::DeclTypes flag in cap flag
+// and the D3DDECLTYPE member needed for the vertex declaration in declflag.
+template <GLenum fromType, bool normalized, int size, template <class T> class PreferenceRule>
+struct Converter
+ : VertexDataConverter<typename GLToCType<fromType>::type,
+ WidenRule<PreferenceRule< VertexTypeMapping<fromType, normalized> >::type, size>,
+ ConversionRule<fromType,
+ normalized,
+ PreferenceRule< VertexTypeMapping<fromType, normalized> >::type>,
+ DefaultVertexValues<typename D3DToCType<PreferenceRule< VertexTypeMapping<fromType, normalized> >::type>::type, normalized > >
+{
+private:
+ enum { d3dtype = PreferenceRule< VertexTypeMapping<fromType, normalized> >::type };
+ enum { d3dsize = WidenRule<d3dtype, size>::finalWidth };
+
+public:
+ enum { capflag = VertexTypeFlags<d3dtype, d3dsize>::capflag };
+ enum { declflag = VertexTypeFlags<d3dtype, d3dsize>::declflag };
+};
+
+// Initialize a TranslationInfo
+#define TRANSLATION(type, norm, size, preferred) \
+ { \
+ Converter<type, norm, size, preferred>::identity, \
+ Converter<type, norm, size, preferred>::finalSize, \
+ Converter<type, norm, size, preferred>::convertArray, \
+ static_cast<D3DDECLTYPE>(Converter<type, norm, size, preferred>::declflag) \
+ }
+
+#define TRANSLATION_FOR_TYPE_NORM_SIZE(type, norm, size) \
+ { \
+ Converter<type, norm, size, UsePreferred>::capflag, \
+ TRANSLATION(type, norm, size, UsePreferred), \
+ TRANSLATION(type, norm, size, UseFallback) \
+ }
+
+#define TRANSLATIONS_FOR_TYPE(type) \
+ { \
+ { TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \
+ { TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 4) }, \
+ }
+
+#define TRANSLATIONS_FOR_TYPE_NO_NORM(type) \
+ { \
+ { TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \
+ { TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \
+ }
+
+const VertexBuffer9::TranslationDescription VertexBuffer9::mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4] = // [GL types as enumerated by typeIndex()][normalized][size-1]
+{
+ TRANSLATIONS_FOR_TYPE(GL_BYTE),
+ TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_BYTE),
+ TRANSLATIONS_FOR_TYPE(GL_SHORT),
+ TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_SHORT),
+ TRANSLATIONS_FOR_TYPE_NO_NORM(GL_FIXED),
+ TRANSLATIONS_FOR_TYPE_NO_NORM(GL_FLOAT)
+};
+
+void VertexBuffer9::initializeTranslations(DWORD declTypes)
+{
+ for (unsigned int i = 0; i < NUM_GL_VERTEX_ATTRIB_TYPES; i++)
+ {
+ for (unsigned int j = 0; j < 2; j++)
+ {
+ for (unsigned int k = 0; k < 4; k++)
+ {
+ if (mPossibleTranslations[i][j][k].capsFlag == 0 || (declTypes & mPossibleTranslations[i][j][k].capsFlag) != 0)
+ {
+ mFormatConverters[i][j][k] = mPossibleTranslations[i][j][k].preferredConversion;
+ }
+ else
+ {
+ mFormatConverters[i][j][k] = mPossibleTranslations[i][j][k].fallbackConversion;
+ }
+ }
+ }
+ }
+}
+
+unsigned int VertexBuffer9::typeIndex(GLenum type)
+{
+ switch (type)
+ {
+ case GL_BYTE: return 0;
+ case GL_UNSIGNED_BYTE: return 1;
+ case GL_SHORT: return 2;
+ case GL_UNSIGNED_SHORT: return 3;
+ case GL_FIXED: return 4;
+ case GL_FLOAT: return 5;
+
+ default: UNREACHABLE(); return 5;
+ }
+}
+
+const VertexBuffer9::FormatConverter &VertexBuffer9::formatConverter(const gl::VertexAttribute &attribute)
+{
+ return mFormatConverters[typeIndex(attribute.mType)][attribute.mNormalized][attribute.mSize - 1];
+}
+
+bool VertexBuffer9::spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances,
+ unsigned int *outSpaceRequired)
+{
+ unsigned int elementSize = formatConverter(attrib).outputElementSize;
+
+ if (attrib.mArrayEnabled)
+ {
+ unsigned int elementCount = 0;
+ if (instances == 0 || attrib.mDivisor == 0)
+ {
+ elementCount = count;
+ }
+ else
+ {
+ if (static_cast<unsigned int>(instances) < std::numeric_limits<unsigned int>::max() - (attrib.mDivisor - 1))
+ {
+ // Round up
+ elementCount = (static_cast<unsigned int>(instances) + (attrib.mDivisor - 1)) / attrib.mDivisor;
+ }
+ else
+ {
+ elementCount = static_cast<unsigned int>(instances) / attrib.mDivisor;
+ }
+ }
+
+ if (elementSize <= std::numeric_limits<unsigned int>::max() / elementCount)
+ {
+ if (outSpaceRequired)
+ {
+ *outSpaceRequired = elementSize * elementCount;
+ }
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ {
+ const unsigned int elementSize = 4;
+ if (outSpaceRequired)
+ {
+ *outSpaceRequired = elementSize * 4;
+ }
+ return true;
+ }
+}
+
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/VertexBuffer9.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9VertexBuffer9h"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/VertexBuffer9.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/VertexBuffer9.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/VertexBuffer9.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,91 @@
</span><ins>+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// VertexBuffer9.h: Defines the D3D9 VertexBuffer implementation.
+
+#ifndef LIBGLESV2_RENDERER_VERTEXBUFFER9_H_
+#define LIBGLESV2_RENDERER_VERTEXBUFFER9_H_
+
+#include "libGLESv2/renderer/VertexBuffer.h"
+
+namespace rx
+{
+class Renderer9;
+
+class VertexBuffer9 : public VertexBuffer
+{
+ public:
+ explicit VertexBuffer9(rx::Renderer9 *const renderer);
+ virtual ~VertexBuffer9();
+
+ virtual bool initialize(unsigned int size, bool dynamicUsage);
+
+ static VertexBuffer9 *makeVertexBuffer9(VertexBuffer *vertexBuffer);
+
+ virtual bool storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances,
+ unsigned int offset);
+ virtual bool storeRawData(const void* data, unsigned int size, unsigned int offset);
+
+ virtual bool getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, unsigned int *outSpaceRequired) const;
+
+ virtual bool requiresConversion(const gl::VertexAttribute &attrib) const;
+
+ unsigned int getVertexSize(const gl::VertexAttribute &attrib) const;
+ D3DDECLTYPE getDeclType(const gl::VertexAttribute &attrib) const;
+
+ virtual unsigned int getBufferSize() const;
+ virtual bool setBufferSize(unsigned int size);
+ virtual bool discard();
+
+ IDirect3DVertexBuffer9 *getBuffer() const;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(VertexBuffer9);
+
+ rx::Renderer9 *const mRenderer;
+
+ IDirect3DVertexBuffer9 *mVertexBuffer;
+ unsigned int mBufferSize;
+ bool mDynamicUsage;
+
+ // Attribute format conversion
+ enum { NUM_GL_VERTEX_ATTRIB_TYPES = 6 };
+
+ struct FormatConverter
+ {
+ bool identity;
+ std::size_t outputElementSize;
+ void (*convertArray)(const void *in, std::size_t stride, std::size_t n, void *out);
+ D3DDECLTYPE d3dDeclType;
+ };
+
+ static bool mTranslationsInitialized;
+ static void initializeTranslations(DWORD declTypes);
+
+ // [GL types as enumerated by typeIndex()][normalized][size - 1]
+ static FormatConverter mFormatConverters[NUM_GL_VERTEX_ATTRIB_TYPES][2][4];
+
+ struct TranslationDescription
+ {
+ DWORD capsFlag;
+ FormatConverter preferredConversion;
+ FormatConverter fallbackConversion;
+ };
+
+ // This table is used to generate mFormatConverters.
+ // [GL types as enumerated by typeIndex()][normalized][size - 1]
+ static const TranslationDescription mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4];
+
+ static unsigned int typeIndex(GLenum type);
+ static const FormatConverter &formatConverter(const gl::VertexAttribute &attribute);
+
+ static bool spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances,
+ unsigned int *outSpaceRequired);
+};
+
+}
+
+#endif // LIBGLESV2_RENDERER_VERTEXBUFFER9_H_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/VertexBuffer9.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9VertexDeclarationCachecpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/VertexDeclarationCache.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/VertexDeclarationCache.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/VertexDeclarationCache.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,217 @@
</span><ins>+#include "precompiled.h"
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// VertexDeclarationCache.cpp: Implements a helper class to construct and cache vertex declarations.
+
+#include "libGLESv2/ProgramBinary.h"
+#include "libGLESv2/Context.h"
+#include "libGLESv2/renderer/d3d9/VertexBuffer9.h"
+#include "libGLESv2/renderer/d3d9/VertexDeclarationCache.h"
+
+namespace rx
+{
+
+VertexDeclarationCache::VertexDeclarationCache() : mMaxLru(0)
+{
+ for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
+ {
+ mVertexDeclCache[i].vertexDeclaration = NULL;
+ mVertexDeclCache[i].lruCount = 0;
+ }
+
+ for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
+ {
+ mAppliedVBs[i].serial = 0;
+ }
+
+ mLastSetVDecl = NULL;
+ mInstancingEnabled = true;
+}
+
+VertexDeclarationCache::~VertexDeclarationCache()
+{
+ for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
+ {
+ if (mVertexDeclCache[i].vertexDeclaration)
+ {
+ mVertexDeclCache[i].vertexDeclaration->Release();
+ }
+ }
+}
+
+GLenum VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], gl::ProgramBinary *programBinary, GLsizei instances, GLsizei *repeatDraw)
+{
+ *repeatDraw = 1;
+
+ int indexedAttribute = gl::MAX_VERTEX_ATTRIBS;
+ int instancedAttribute = gl::MAX_VERTEX_ATTRIBS;
+
+ if (instances > 0)
+ {
+ // Find an indexed attribute to be mapped to D3D stream 0
+ for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
+ {
+ if (attributes[i].active)
+ {
+ if (indexedAttribute == gl::MAX_VERTEX_ATTRIBS && attributes[i].divisor == 0)
+ {
+ indexedAttribute = i;
+ }
+ else if (instancedAttribute == gl::MAX_VERTEX_ATTRIBS && attributes[i].divisor != 0)
+ {
+ instancedAttribute = i;
+ }
+ if (indexedAttribute != gl::MAX_VERTEX_ATTRIBS && instancedAttribute != gl::MAX_VERTEX_ATTRIBS)
+ break; // Found both an indexed and instanced attribute
+ }
+ }
+
+ if (indexedAttribute == gl::MAX_VERTEX_ATTRIBS)
+ {
+ return GL_INVALID_OPERATION;
+ }
+ }
+
+ D3DVERTEXELEMENT9 elements[gl::MAX_VERTEX_ATTRIBS + 1];
+ D3DVERTEXELEMENT9 *element = &elements[0];
+
+ for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
+ {
+ if (attributes[i].active)
+ {
+ // Directly binding the storage buffer is not supported for d3d9
+ ASSERT(attributes[i].storage == NULL);
+
+ int stream = i;
+
+ if (instances > 0)
+ {
+ // Due to a bug on ATI cards we can't enable instancing when none of the attributes are instanced.
+ if (instancedAttribute == gl::MAX_VERTEX_ATTRIBS)
+ {
+ *repeatDraw = instances;
+ }
+ else
+ {
+ if (i == indexedAttribute)
+ {
+ stream = 0;
+ }
+ else if (i == 0)
+ {
+ stream = indexedAttribute;
+ }
+
+ UINT frequency = 1;
+
+ if (attributes[i].divisor == 0)
+ {
+ frequency = D3DSTREAMSOURCE_INDEXEDDATA | instances;
+ }
+ else
+ {
+ frequency = D3DSTREAMSOURCE_INSTANCEDATA | attributes[i].divisor;
+ }
+
+ device->SetStreamSourceFreq(stream, frequency);
+ mInstancingEnabled = true;
+ }
+ }
+
+ VertexBuffer9 *vertexBuffer = VertexBuffer9::makeVertexBuffer9(attributes[i].vertexBuffer);
+
+ if (mAppliedVBs[stream].serial != attributes[i].serial ||
+ mAppliedVBs[stream].stride != attributes[i].stride ||
+ mAppliedVBs[stream].offset != attributes[i].offset)
+ {
+ device->SetStreamSource(stream, vertexBuffer->getBuffer(), attributes[i].offset, attributes[i].stride);
+ mAppliedVBs[stream].serial = attributes[i].serial;
+ mAppliedVBs[stream].stride = attributes[i].stride;
+ mAppliedVBs[stream].offset = attributes[i].offset;
+ }
+
+ element->Stream = stream;
+ element->Offset = 0;
+ element->Type = attributes[i].attribute->mArrayEnabled ? vertexBuffer->getDeclType(*attributes[i].attribute) : D3DDECLTYPE_FLOAT4;
+ element->Method = D3DDECLMETHOD_DEFAULT;
+ element->Usage = D3DDECLUSAGE_TEXCOORD;
+ element->UsageIndex = programBinary->getSemanticIndex(i);
+ element++;
+ }
+ }
+
+ if (instances == 0 || instancedAttribute == gl::MAX_VERTEX_ATTRIBS)
+ {
+ if (mInstancingEnabled)
+ {
+ for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
+ {
+ device->SetStreamSourceFreq(i, 1);
+ }
+
+ mInstancingEnabled = false;
+ }
+ }
+
+ static const D3DVERTEXELEMENT9 end = D3DDECL_END();
+ *(element++) = end;
+
+ for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
+ {
+ VertexDeclCacheEntry *entry = &mVertexDeclCache[i];
+ if (memcmp(entry->cachedElements, elements, (element - elements) * sizeof(D3DVERTEXELEMENT9)) == 0 && entry->vertexDeclaration)
+ {
+ entry->lruCount = ++mMaxLru;
+ if(entry->vertexDeclaration != mLastSetVDecl)
+ {
+ device->SetVertexDeclaration(entry->vertexDeclaration);
+ mLastSetVDecl = entry->vertexDeclaration;
+ }
+
+ return GL_NO_ERROR;
+ }
+ }
+
+ VertexDeclCacheEntry *lastCache = mVertexDeclCache;
+
+ for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
+ {
+ if (mVertexDeclCache[i].lruCount < lastCache->lruCount)
+ {
+ lastCache = &mVertexDeclCache[i];
+ }
+ }
+
+ if (lastCache->vertexDeclaration != NULL)
+ {
+ lastCache->vertexDeclaration->Release();
+ lastCache->vertexDeclaration = NULL;
+ // mLastSetVDecl is set to the replacement, so we don't have to worry
+ // about it.
+ }
+
+ memcpy(lastCache->cachedElements, elements, (element - elements) * sizeof(D3DVERTEXELEMENT9));
+ device->CreateVertexDeclaration(elements, &lastCache->vertexDeclaration);
+ device->SetVertexDeclaration(lastCache->vertexDeclaration);
+ mLastSetVDecl = lastCache->vertexDeclaration;
+ lastCache->lruCount = ++mMaxLru;
+
+ return GL_NO_ERROR;
+}
+
+void VertexDeclarationCache::markStateDirty()
+{
+ for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
+ {
+ mAppliedVBs[i].serial = 0;
+ }
+
+ mLastSetVDecl = NULL;
+ mInstancingEnabled = true; // Forces it to be disabled when not used
+}
+
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/VertexDeclarationCache.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9VertexDeclarationCacheh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/VertexDeclarationCache.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/VertexDeclarationCache.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/VertexDeclarationCache.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,58 @@
</span><ins>+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// VertexDeclarationCache.h: Defines a helper class to construct and cache vertex declarations.
+
+#ifndef LIBGLESV2_RENDERER_VERTEXDECLARATIONCACHE_H_
+#define LIBGLESV2_RENDERER_VERTEXDECLARATIONCACHE_H_
+
+#include "libGLESv2/renderer/VertexDataManager.h"
+
+namespace gl
+{
+class VertexDataManager;
+}
+
+namespace rx
+{
+
+class VertexDeclarationCache
+{
+ public:
+ VertexDeclarationCache();
+ ~VertexDeclarationCache();
+
+ GLenum applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], gl::ProgramBinary *programBinary, GLsizei instances, GLsizei *repeatDraw);
+
+ void markStateDirty();
+
+ private:
+ UINT mMaxLru;
+
+ enum { NUM_VERTEX_DECL_CACHE_ENTRIES = 32 };
+
+ struct VBData
+ {
+ unsigned int serial;
+ unsigned int stride;
+ unsigned int offset;
+ };
+
+ VBData mAppliedVBs[gl::MAX_VERTEX_ATTRIBS];
+ IDirect3DVertexDeclaration9 *mLastSetVDecl;
+ bool mInstancingEnabled;
+
+ struct VertexDeclCacheEntry
+ {
+ D3DVERTEXELEMENT9 cachedElements[gl::MAX_VERTEX_ATTRIBS + 1];
+ UINT lruCount;
+ IDirect3DVertexDeclaration9 *vertexDeclaration;
+ } mVertexDeclCache[NUM_VERTEX_DECL_CACHE_ENTRIES];
+};
+
+}
+
+#endif // LIBGLESV2_RENDERER_VERTEXDECLARATIONCACHE_H_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/VertexDeclarationCache.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9renderer9_utilscpp"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/renderer9_utils.cpp (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/renderer9_utils.cpp         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/renderer9_utils.cpp        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,500 @@
</span><ins>+#include "precompiled.h"
+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// renderer9_utils.cpp: Conversion functions and other utility routines
+// specific to the D3D9 renderer.
+
+#include "libGLESv2/renderer/d3d9/renderer9_utils.h"
+#include "libGLESv2/mathutil.h"
+#include "libGLESv2/Context.h"
+
+#include "common/debug.h"
+
+namespace gl_d3d9
+{
+
+D3DCMPFUNC ConvertComparison(GLenum comparison)
+{
+ D3DCMPFUNC d3dComp = D3DCMP_ALWAYS;
+ switch (comparison)
+ {
+ case GL_NEVER: d3dComp = D3DCMP_NEVER; break;
+ case GL_ALWAYS: d3dComp = D3DCMP_ALWAYS; break;
+ case GL_LESS: d3dComp = D3DCMP_LESS; break;
+ case GL_LEQUAL: d3dComp = D3DCMP_LESSEQUAL; break;
+ case GL_EQUAL: d3dComp = D3DCMP_EQUAL; break;
+ case GL_GREATER: d3dComp = D3DCMP_GREATER; break;
+ case GL_GEQUAL: d3dComp = D3DCMP_GREATEREQUAL; break;
+ case GL_NOTEQUAL: d3dComp = D3DCMP_NOTEQUAL; break;
+ default: UNREACHABLE();
+ }
+
+ return d3dComp;
+}
+
+D3DCOLOR ConvertColor(gl::Color color)
+{
+ return D3DCOLOR_RGBA(gl::unorm<8>(color.red),
+ gl::unorm<8>(color.green),
+ gl::unorm<8>(color.blue),
+ gl::unorm<8>(color.alpha));
+}
+
+D3DBLEND ConvertBlendFunc(GLenum blend)
+{
+ D3DBLEND d3dBlend = D3DBLEND_ZERO;
+
+ switch (blend)
+ {
+ case GL_ZERO: d3dBlend = D3DBLEND_ZERO; break;
+ case GL_ONE: d3dBlend = D3DBLEND_ONE; break;
+ case GL_SRC_COLOR: d3dBlend = D3DBLEND_SRCCOLOR; break;
+ case GL_ONE_MINUS_SRC_COLOR: d3dBlend = D3DBLEND_INVSRCCOLOR; break;
+ case GL_DST_COLOR: d3dBlend = D3DBLEND_DESTCOLOR; break;
+ case GL_ONE_MINUS_DST_COLOR: d3dBlend = D3DBLEND_INVDESTCOLOR; break;
+ case GL_SRC_ALPHA: d3dBlend = D3DBLEND_SRCALPHA; break;
+ case GL_ONE_MINUS_SRC_ALPHA: d3dBlend = D3DBLEND_INVSRCALPHA; break;
+ case GL_DST_ALPHA: d3dBlend = D3DBLEND_DESTALPHA; break;
+ case GL_ONE_MINUS_DST_ALPHA: d3dBlend = D3DBLEND_INVDESTALPHA; break;
+ case GL_CONSTANT_COLOR: d3dBlend = D3DBLEND_BLENDFACTOR; break;
+ case GL_ONE_MINUS_CONSTANT_COLOR: d3dBlend = D3DBLEND_INVBLENDFACTOR; break;
+ case GL_CONSTANT_ALPHA: d3dBlend = D3DBLEND_BLENDFACTOR; break;
+ case GL_ONE_MINUS_CONSTANT_ALPHA: d3dBlend = D3DBLEND_INVBLENDFACTOR; break;
+ case GL_SRC_ALPHA_SATURATE: d3dBlend = D3DBLEND_SRCALPHASAT; break;
+ default: UNREACHABLE();
+ }
+
+ return d3dBlend;
+}
+
+D3DBLENDOP ConvertBlendOp(GLenum blendOp)
+{
+ D3DBLENDOP d3dBlendOp = D3DBLENDOP_ADD;
+
+ switch (blendOp)
+ {
+ case GL_FUNC_ADD: d3dBlendOp = D3DBLENDOP_ADD; break;
+ case GL_FUNC_SUBTRACT: d3dBlendOp = D3DBLENDOP_SUBTRACT; break;
+ case GL_FUNC_REVERSE_SUBTRACT: d3dBlendOp = D3DBLENDOP_REVSUBTRACT; break;
+ default: UNREACHABLE();
+ }
+
+ return d3dBlendOp;
+}
+
+D3DSTENCILOP ConvertStencilOp(GLenum stencilOp)
+{
+ D3DSTENCILOP d3dStencilOp = D3DSTENCILOP_KEEP;
+
+ switch (stencilOp)
+ {
+ case GL_ZERO: d3dStencilOp = D3DSTENCILOP_ZERO; break;
+ case GL_KEEP: d3dStencilOp = D3DSTENCILOP_KEEP; break;
+ case GL_REPLACE: d3dStencilOp = D3DSTENCILOP_REPLACE; break;
+ case GL_INCR: d3dStencilOp = D3DSTENCILOP_INCRSAT; break;
+ case GL_DECR: d3dStencilOp = D3DSTENCILOP_DECRSAT; break;
+ case GL_INVERT: d3dStencilOp = D3DSTENCILOP_INVERT; break;
+ case GL_INCR_WRAP: d3dStencilOp = D3DSTENCILOP_INCR; break;
+ case GL_DECR_WRAP: d3dStencilOp = D3DSTENCILOP_DECR; break;
+ default: UNREACHABLE();
+ }
+
+ return d3dStencilOp;
+}
+
+D3DTEXTUREADDRESS ConvertTextureWrap(GLenum wrap)
+{
+ D3DTEXTUREADDRESS d3dWrap = D3DTADDRESS_WRAP;
+
+ switch (wrap)
+ {
+ case GL_REPEAT: d3dWrap = D3DTADDRESS_WRAP; break;
+ case GL_CLAMP_TO_EDGE: d3dWrap = D3DTADDRESS_CLAMP; break;
+ case GL_MIRRORED_REPEAT: d3dWrap = D3DTADDRESS_MIRROR; break;
+ default: UNREACHABLE();
+ }
+
+ return d3dWrap;
+}
+
+D3DCULL ConvertCullMode(GLenum cullFace, GLenum frontFace)
+{
+ D3DCULL cull = D3DCULL_CCW;
+ switch (cullFace)
+ {
+ case GL_FRONT:
+ cull = (frontFace == GL_CCW ? D3DCULL_CW : D3DCULL_CCW);
+ break;
+ case GL_BACK:
+ cull = (frontFace == GL_CCW ? D3DCULL_CCW : D3DCULL_CW);
+ break;
+ case GL_FRONT_AND_BACK:
+ cull = D3DCULL_NONE; // culling will be handled during draw
+ break;
+ default: UNREACHABLE();
+ }
+
+ return cull;
+}
+
+D3DCUBEMAP_FACES ConvertCubeFace(GLenum cubeFace)
+{
+ D3DCUBEMAP_FACES face = D3DCUBEMAP_FACE_POSITIVE_X;
+
+ switch (cubeFace)
+ {
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+ face = D3DCUBEMAP_FACE_POSITIVE_X;
+ break;
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+ face = D3DCUBEMAP_FACE_NEGATIVE_X;
+ break;
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+ face = D3DCUBEMAP_FACE_POSITIVE_Y;
+ break;
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+ face = D3DCUBEMAP_FACE_NEGATIVE_Y;
+ break;
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+ face = D3DCUBEMAP_FACE_POSITIVE_Z;
+ break;
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+ face = D3DCUBEMAP_FACE_NEGATIVE_Z;
+ break;
+ default: UNREACHABLE();
+ }
+
+ return face;
+}
+
+DWORD ConvertColorMask(bool red, bool green, bool blue, bool alpha)
+{
+ return (red ? D3DCOLORWRITEENABLE_RED : 0) |
+ (green ? D3DCOLORWRITEENABLE_GREEN : 0) |
+ (blue ? D3DCOLORWRITEENABLE_BLUE : 0) |
+ (alpha ? D3DCOLORWRITEENABLE_ALPHA : 0);
+}
+
+D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter, float maxAnisotropy)
+{
+ if (maxAnisotropy > 1.0f)
+ {
+ return D3DTEXF_ANISOTROPIC;
+ }
+
+ D3DTEXTUREFILTERTYPE d3dMagFilter = D3DTEXF_POINT;
+ switch (magFilter)
+ {
+ case GL_NEAREST: d3dMagFilter = D3DTEXF_POINT; break;
+ case GL_LINEAR: d3dMagFilter = D3DTEXF_LINEAR; break;
+ default: UNREACHABLE();
+ }
+
+ return d3dMagFilter;
+}
+
+void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter, float maxAnisotropy)
+{
+ switch (minFilter)
+ {
+ case GL_NEAREST:
+ *d3dMinFilter = D3DTEXF_POINT;
+ *d3dMipFilter = D3DTEXF_NONE;
+ break;
+ case GL_LINEAR:
+ *d3dMinFilter = D3DTEXF_LINEAR;
+ *d3dMipFilter = D3DTEXF_NONE;
+ break;
+ case GL_NEAREST_MIPMAP_NEAREST:
+ *d3dMinFilter = D3DTEXF_POINT;
+ *d3dMipFilter = D3DTEXF_POINT;
+ break;
+ case GL_LINEAR_MIPMAP_NEAREST:
+ *d3dMinFilter = D3DTEXF_LINEAR;
+ *d3dMipFilter = D3DTEXF_POINT;
+ break;
+ case GL_NEAREST_MIPMAP_LINEAR:
+ *d3dMinFilter = D3DTEXF_POINT;
+ *d3dMipFilter = D3DTEXF_LINEAR;
+ break;
+ case GL_LINEAR_MIPMAP_LINEAR:
+ *d3dMinFilter = D3DTEXF_LINEAR;
+ *d3dMipFilter = D3DTEXF_LINEAR;
+ break;
+ default:
+ *d3dMinFilter = D3DTEXF_POINT;
+ *d3dMipFilter = D3DTEXF_NONE;
+ UNREACHABLE();
+ }
+
+ if (maxAnisotropy > 1.0f)
+ {
+ *d3dMinFilter = D3DTEXF_ANISOTROPIC;
+ }
+}
+
+D3DFORMAT ConvertRenderbufferFormat(GLenum format)
+{
+ switch (format)
+ {
+ case GL_NONE: return D3DFMT_NULL;
+ case GL_RGBA4:
+ case GL_RGB5_A1:
+ case GL_RGBA8_OES: return D3DFMT_A8R8G8B8;
+ case GL_RGB565: return D3DFMT_R5G6B5;
+ case GL_RGB8_OES: return D3DFMT_X8R8G8B8;
+ case GL_DEPTH_COMPONENT16:
+ case GL_STENCIL_INDEX8:
+ case GL_DEPTH24_STENCIL8_OES: return D3DFMT_D24S8;
+ default: UNREACHABLE(); return D3DFMT_A8R8G8B8;
+ }
+}
+
+D3DMULTISAMPLE_TYPE GetMultisampleTypeFromSamples(GLsizei samples)
+{
+ if (samples <= 1)
+ return D3DMULTISAMPLE_NONE;
+ else
+ return (D3DMULTISAMPLE_TYPE)samples;
+}
+
+}
+
+namespace d3d9_gl
+{
+
+unsigned int GetStencilSize(D3DFORMAT stencilFormat)
+{
+ if (stencilFormat == D3DFMT_INTZ)
+ {
+ return 8;
+ }
+ switch(stencilFormat)
+ {
+ case D3DFMT_D24FS8:
+ case D3DFMT_D24S8:
+ return 8;
+ case D3DFMT_D24X4S4:
+ return 4;
+ case D3DFMT_D15S1:
+ return 1;
+ case D3DFMT_D16_LOCKABLE:
+ case D3DFMT_D32:
+ case D3DFMT_D24X8:
+ case D3DFMT_D32F_LOCKABLE:
+ case D3DFMT_D16:
+ return 0;
+ //case D3DFMT_D32_LOCKABLE: return 0; // DirectX 9Ex only
+ //case D3DFMT_S8_LOCKABLE: return 8; // DirectX 9Ex only
+ default:
+ return 0;
+ }
+}
+
+unsigned int GetAlphaSize(D3DFORMAT colorFormat)
+{
+ switch (colorFormat)
+ {
+ case D3DFMT_A16B16G16R16F:
+ return 16;
+ case D3DFMT_A32B32G32R32F:
+ return 32;
+ case D3DFMT_A2R10G10B10:
+ return 2;
+ case D3DFMT_A8R8G8B8:
+ return 8;
+ case D3DFMT_A1R5G5B5:
+ return 1;
+ case D3DFMT_X8R8G8B8:
+ case D3DFMT_R5G6B5:
+ return 0;
+ default:
+ return 0;
+ }
+}
+
+GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type)
+{
+ if (type == D3DMULTISAMPLE_NONMASKABLE)
+ return 0;
+ else
+ return type;
+}
+
+bool IsFormatChannelEquivalent(D3DFORMAT d3dformat, GLenum format)
+{
+ switch (d3dformat)
+ {
+ case D3DFMT_L8:
+ return (format == GL_LUMINANCE);
+ case D3DFMT_A8L8:
+ return (format == GL_LUMINANCE_ALPHA);
+ case D3DFMT_DXT1:
+ return (format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT || format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT);
+ case D3DFMT_DXT3:
+ return (format == GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE);
+ case D3DFMT_DXT5:
+ return (format == GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE);
+ case D3DFMT_A8R8G8B8:
+ case D3DFMT_A16B16G16R16F:
+ case D3DFMT_A32B32G32R32F:
+ return (format == GL_RGBA || format == GL_BGRA_EXT);
+ case D3DFMT_X8R8G8B8:
+ return (format == GL_RGB);
+ default:
+ if (d3dformat == D3DFMT_INTZ && gl::IsDepthTexture(format))
+ return true;
+ return false;
+ }
+}
+
+GLenum ConvertBackBufferFormat(D3DFORMAT format)
+{
+ switch (format)
+ {
+ case D3DFMT_A4R4G4B4: return GL_RGBA4;
+ case D3DFMT_A8R8G8B8: return GL_RGBA8_OES;
+ case D3DFMT_A1R5G5B5: return GL_RGB5_A1;
+ case D3DFMT_R5G6B5: return GL_RGB565;
+ case D3DFMT_X8R8G8B8: return GL_RGB8_OES;
+ default:
+ UNREACHABLE();
+ }
+
+ return GL_RGBA4;
+}
+
+GLenum ConvertDepthStencilFormat(D3DFORMAT format)
+{
+ if (format == D3DFMT_INTZ)
+ {
+ return GL_DEPTH24_STENCIL8_OES;
+ }
+ switch (format)
+ {
+ case D3DFMT_D16:
+ case D3DFMT_D24X8:
+ return GL_DEPTH_COMPONENT16;
+ case D3DFMT_D24S8:
+ return GL_DEPTH24_STENCIL8_OES;
+ case D3DFMT_UNKNOWN:
+ return GL_NONE;
+ default:
+ UNREACHABLE();
+ }
+
+ return GL_DEPTH24_STENCIL8_OES;
+}
+
+GLenum ConvertRenderTargetFormat(D3DFORMAT format)
+{
+ if (format == D3DFMT_INTZ)
+ {
+ return GL_DEPTH24_STENCIL8_OES;
+ }
+
+ switch (format)
+ {
+ case D3DFMT_A4R4G4B4: return GL_RGBA4;
+ case D3DFMT_A8R8G8B8: return GL_RGBA8_OES;
+ case D3DFMT_A1R5G5B5: return GL_RGB5_A1;
+ case D3DFMT_R5G6B5: return GL_RGB565;
+ case D3DFMT_X8R8G8B8: return GL_RGB8_OES;
+ case D3DFMT_D16:
+ case D3DFMT_D24X8:
+ return GL_DEPTH_COMPONENT16;
+ case D3DFMT_D24S8:
+ return GL_DEPTH24_STENCIL8_OES;
+ case D3DFMT_UNKNOWN:
+ return GL_NONE;
+ default:
+ UNREACHABLE();
+ }
+
+ return GL_RGBA4;
+}
+
+GLenum GetEquivalentFormat(D3DFORMAT format)
+{
+ if (format == D3DFMT_INTZ)
+ return GL_DEPTH24_STENCIL8_OES;
+ if (format == D3DFMT_NULL)
+ return GL_NONE;
+
+ switch (format)
+ {
+ case D3DFMT_A4R4G4B4: return GL_RGBA4;
+ case D3DFMT_A8R8G8B8: return GL_RGBA8_OES;
+ case D3DFMT_A1R5G5B5: return GL_RGB5_A1;
+ case D3DFMT_R5G6B5: return GL_RGB565;
+ case D3DFMT_X8R8G8B8: return GL_RGB8_OES;
+ case D3DFMT_D16: return GL_DEPTH_COMPONENT16;
+ case D3DFMT_D24S8: return GL_DEPTH24_STENCIL8_OES;
+ case D3DFMT_UNKNOWN: return GL_NONE;
+ case D3DFMT_DXT1: return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
+ case D3DFMT_DXT3: return GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE;
+ case D3DFMT_DXT5: return GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE;
+ case D3DFMT_A32B32G32R32F: return GL_RGBA32F_EXT;
+ case D3DFMT_A16B16G16R16F: return GL_RGBA16F_EXT;
+ case D3DFMT_L8: return GL_LUMINANCE8_EXT;
+ case D3DFMT_A8L8: return GL_LUMINANCE8_ALPHA8_EXT;
+ default: UNREACHABLE();
+ return GL_NONE;
+ }
+}
+
+}
+
+namespace d3d9
+{
+
+bool IsCompressedFormat(D3DFORMAT surfaceFormat)
+{
+ switch(surfaceFormat)
+ {
+ case D3DFMT_DXT1:
+ case D3DFMT_DXT2:
+ case D3DFMT_DXT3:
+ case D3DFMT_DXT4:
+ case D3DFMT_DXT5:
+ return true;
+ default:
+ return false;
+ }
+}
+
+size_t ComputeRowSize(D3DFORMAT format, unsigned int width)
+{
+ if (format == D3DFMT_INTZ)
+ {
+ return 4 * width;
+ }
+ switch (format)
+ {
+ case D3DFMT_L8:
+ return 1 * width;
+ case D3DFMT_A8L8:
+ return 2 * width;
+ case D3DFMT_X8R8G8B8:
+ case D3DFMT_A8R8G8B8:
+ return 4 * width;
+ case D3DFMT_A16B16G16R16F:
+ return 8 * width;
+ case D3DFMT_A32B32G32R32F:
+ return 16 * width;
+ case D3DFMT_DXT1:
+ return 8 * ((width + 3) / 4);
+ case D3DFMT_DXT3:
+ case D3DFMT_DXT5:
+ return 16 * ((width + 3) / 4);
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+}
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/renderer9_utils.cpp
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9renderer9_utilsh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/renderer9_utils.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/renderer9_utils.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/renderer9_utils.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,74 @@
</span><ins>+//
+// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// renderer9_utils.h: Conversion functions and other utility routines
+// specific to the D3D9 renderer
+
+#ifndef LIBGLESV2_RENDERER_RENDERER9_UTILS_H
+#define LIBGLESV2_RENDERER_RENDERER9_UTILS_H
+
+#include "libGLESv2/utilities.h"
+
+const D3DFORMAT D3DFMT_INTZ = ((D3DFORMAT)(MAKEFOURCC('I','N','T','Z')));
+const D3DFORMAT D3DFMT_NULL = ((D3DFORMAT)(MAKEFOURCC('N','U','L','L')));
+
+namespace gl_d3d9
+{
+
+D3DCMPFUNC ConvertComparison(GLenum comparison);
+D3DCOLOR ConvertColor(gl::Color color);
+D3DBLEND ConvertBlendFunc(GLenum blend);
+D3DBLENDOP ConvertBlendOp(GLenum blendOp);
+D3DSTENCILOP ConvertStencilOp(GLenum stencilOp);
+D3DTEXTUREADDRESS ConvertTextureWrap(GLenum wrap);
+D3DCULL ConvertCullMode(GLenum cullFace, GLenum frontFace);
+D3DCUBEMAP_FACES ConvertCubeFace(GLenum cubeFace);
+DWORD ConvertColorMask(bool red, bool green, bool blue, bool alpha);
+D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter, float maxAnisotropy);
+void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter, float maxAnisotropy);
+D3DFORMAT ConvertRenderbufferFormat(GLenum format);
+D3DMULTISAMPLE_TYPE GetMultisampleTypeFromSamples(GLsizei samples);
+
+}
+
+namespace d3d9_gl
+{
+
+GLuint GetAlphaSize(D3DFORMAT colorFormat);
+GLuint GetStencilSize(D3DFORMAT stencilFormat);
+
+GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type);
+
+bool IsFormatChannelEquivalent(D3DFORMAT d3dformat, GLenum format);
+GLenum ConvertBackBufferFormat(D3DFORMAT format);
+GLenum ConvertDepthStencilFormat(D3DFORMAT format);
+GLenum ConvertRenderTargetFormat(D3DFORMAT format);
+GLenum GetEquivalentFormat(D3DFORMAT format);
+
+}
+
+namespace d3d9
+{
+bool IsCompressedFormat(D3DFORMAT format);
+size_t ComputeRowSize(D3DFORMAT format, unsigned int width);
+
+inline bool isDeviceLostError(HRESULT errorCode)
+{
+ switch (errorCode)
+ {
+ case D3DERR_DRIVERINTERNALERROR:
+ case D3DERR_DEVICELOST:
+ case D3DERR_DEVICEHUNG:
+ case D3DERR_DEVICEREMOVED:
+ return true;
+ default:
+ return false;
+ }
+}
+
+}
+
+#endif // LIBGLESV2_RENDERER_RENDERER9_UTILS_H
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/renderer9_utils.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9shadersBlitps"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/shaders/Blit.ps (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/shaders/Blit.ps         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/shaders/Blit.ps        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,39 @@
</span><ins>+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+sampler2D tex : s0;
+
+uniform float4 mode : c0;
+
+// Passthrough Pixel Shader
+// Outputs texture 0 sampled at texcoord 0.
+float4 passthroughps(float4 texcoord : TEXCOORD0) : COLOR
+{
+        return tex2D(tex, texcoord.xy);
+};
+
+// Luminance Conversion Pixel Shader
+// Outputs sample(tex0, tc0).rrra.
+// For LA output (pass A) set C0.X = 1, C0.Y = 0.
+// For L output (A = 1) set C0.X = 0, C0.Y = 1.
+float4 luminanceps(float4 texcoord : TEXCOORD0) : COLOR
+{
+        float4 tmp = tex2D(tex, texcoord.xy);
+        tmp.w = tmp.w * mode.x + mode.y;
+        return tmp.xxxw;
+};
+
+// RGB/A Component Mask Pixel Shader
+// Outputs sample(tex0, tc0) with options to force RGB = 0 and/or A = 1.
+// To force RGB = 0, set C0.X = 0, otherwise C0.X = 1.
+// To force A = 1, set C0.Z = 0, C0.W = 1, otherwise C0.Z = 1, C0.W = 0.
+float4 componentmaskps(float4 texcoord : TEXCOORD0) : COLOR
+{
+        float4 tmp = tex2D(tex, texcoord.xy);
+        tmp.xyz = tmp.xyz * mode.x;
+        tmp.w = tmp.w * mode.z + mode.w;
+        return tmp;
+};
</ins></span></pre></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9shadersBlitvs"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/shaders/Blit.vs (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/shaders/Blit.vs         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/shaders/Blit.vs        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,43 @@
</span><ins>+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+struct VS_OUTPUT
+{
+ float4 position : POSITION;
+ float4 texcoord : TEXCOORD0;
+};
+
+uniform float4 halfPixelSize : c0;
+
+// Standard Vertex Shader
+// Input 0 is the homogenous position.
+// Outputs the homogenous position as-is.
+// Outputs a tex coord with (0,0) in the upper-left corner of the screen and (1,1) in the bottom right.
+// C0.X must be negative half-pixel width, C0.Y must be half-pixel height. C0.ZW must be 0.
+VS_OUTPUT standardvs(in float4 position : POSITION)
+{
+ VS_OUTPUT Out;
+
+ Out.position = position + halfPixelSize;
+ Out.texcoord = position * float4(0.5, -0.5, 1.0, 1.0) + float4(0.5, 0.5, 0, 0);
+
+ return Out;
+};
+
+// Flip Y Vertex Shader
+// Input 0 is the homogenous position.
+// Outputs the homogenous position as-is.
+// Outputs a tex coord with (0,1) in the upper-left corner of the screen and (1,0) in the bottom right.
+// C0.XY must be the half-pixel width and height. C0.ZW must be 0.
+VS_OUTPUT flipyvs(in float4 position : POSITION)
+{
+ VS_OUTPUT Out;
+
+ Out.position = position + halfPixelSize;
+ Out.texcoord = position * float4(0.5, 0.5, 1.0, 1.0) + float4(0.5, 0.5, 0, 0);
+
+ return Out;
+};
</ins></span></pre></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9shaderscompiledcomponentmaskpsh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/shaders/compiled/componentmaskps.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/shaders/compiled/componentmaskps.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/shaders/compiled/componentmaskps.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,79 @@
</span><ins>+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 9.30.9200.16384
+//
+///
+// Parameters:
+//
+// float4 mode;
+// sampler2D tex;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// ------------ ----- ----
+// mode c0 1
+// tex s0 1
+//
+
+ ps_2_0
+ dcl t0.xy
+ dcl_2d s0
+ texld r0, t0, s0
+ mul r1.xyz, r0, c0.x
+ mad r1.w, r0.w, c0.z, c0.w
+ mov oC0, r1
+
+// approximately 4 instruction slots used (1 texture, 3 arithmetic)
+#endif
+
+const BYTE g_ps20_componentmaskps[] =
+{
+ 0, 2, 255, 255, 254, 255,
+ 44, 0, 67, 84, 65, 66,
+ 28, 0, 0, 0, 119, 0,
+ 0, 0, 0, 2, 255, 255,
+ 2, 0, 0, 0, 28, 0,
+ 0, 0, 0, 1, 0, 0,
+ 112, 0, 0, 0, 68, 0,
+ 0, 0, 2, 0, 0, 0,
+ 1, 0, 0, 0, 76, 0,
+ 0, 0, 0, 0, 0, 0,
+ 92, 0, 0, 0, 3, 0,
+ 0, 0, 1, 0, 0, 0,
+ 96, 0, 0, 0, 0, 0,
+ 0, 0, 109, 111, 100, 101,
+ 0, 171, 171, 171, 1, 0,
+ 3, 0, 1, 0, 4, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 116, 101, 120, 0,
+ 4, 0, 12, 0, 1, 0,
+ 1, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 112, 115,
+ 95, 50, 95, 48, 0, 77,
+ 105, 99, 114, 111, 115, 111,
+ 102, 116, 32, 40, 82, 41,
+ 32, 72, 76, 83, 76, 32,
+ 83, 104, 97, 100, 101, 114,
+ 32, 67, 111, 109, 112, 105,
+ 108, 101, 114, 32, 57, 46,
+ 51, 48, 46, 57, 50, 48,
+ 48, 46, 49, 54, 51, 56,
+ 52, 0, 171, 171, 31, 0,
+ 0, 2, 0, 0, 0, 128,
+ 0, 0, 3, 176, 31, 0,
+ 0, 2, 0, 0, 0, 144,
+ 0, 8, 15, 160, 66, 0,
+ 0, 3, 0, 0, 15, 128,
+ 0, 0, 228, 176, 0, 8,
+ 228, 160, 5, 0, 0, 3,
+ 1, 0, 7, 128, 0, 0,
+ 228, 128, 0, 0, 0, 160,
+ 4, 0, 0, 4, 1, 0,
+ 8, 128, 0, 0, 255, 128,
+ 0, 0, 170, 160, 0, 0,
+ 255, 160, 1, 0, 0, 2,
+ 0, 8, 15, 128, 1, 0,
+ 228, 128, 255, 255, 0, 0
+};
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/shaders/compiled/componentmaskps.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9shaderscompiledflipyvsh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/shaders/compiled/flipyvs.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/shaders/compiled/flipyvs.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/shaders/compiled/flipyvs.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,67 @@
</span><ins>+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 9.30.9200.16384
+//
+///
+// Parameters:
+//
+// float4 halfPixelSize;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// ------------- ----- ----
+// halfPixelSize c0 1
+//
+
+ vs_2_0
+ def c1, 0.5, 1, 0, 0
+ dcl_position v0
+ add oPos, v0, c0
+ mad oT0, v0, c1.xxyy, c1.xxzz
+
+// approximately 2 instruction slots used
+#endif
+
+const BYTE g_vs20_flipyvs[] =
+{
+ 0, 2, 254, 255, 254, 255,
+ 36, 0, 67, 84, 65, 66,
+ 28, 0, 0, 0, 87, 0,
+ 0, 0, 0, 2, 254, 255,
+ 1, 0, 0, 0, 28, 0,
+ 0, 0, 0, 1, 0, 0,
+ 80, 0, 0, 0, 48, 0,
+ 0, 0, 2, 0, 0, 0,
+ 1, 0, 0, 0, 64, 0,
+ 0, 0, 0, 0, 0, 0,
+ 104, 97, 108, 102, 80, 105,
+ 120, 101, 108, 83, 105, 122,
+ 101, 0, 171, 171, 1, 0,
+ 3, 0, 1, 0, 4, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 118, 115, 95, 50,
+ 95, 48, 0, 77, 105, 99,
+ 114, 111, 115, 111, 102, 116,
+ 32, 40, 82, 41, 32, 72,
+ 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67,
+ 111, 109, 112, 105, 108, 101,
+ 114, 32, 57, 46, 51, 48,
+ 46, 57, 50, 48, 48, 46,
+ 49, 54, 51, 56, 52, 0,
+ 171, 171, 81, 0, 0, 5,
+ 1, 0, 15, 160, 0, 0,
+ 0, 63, 0, 0, 128, 63,
+ 0, 0, 0, 0, 0, 0,
+ 0, 0, 31, 0, 0, 2,
+ 0, 0, 0, 128, 0, 0,
+ 15, 144, 2, 0, 0, 3,
+ 0, 0, 15, 192, 0, 0,
+ 228, 144, 0, 0, 228, 160,
+ 4, 0, 0, 4, 0, 0,
+ 15, 224, 0, 0, 228, 144,
+ 1, 0, 80, 160, 1, 0,
+ 160, 160, 255, 255, 0, 0
+};
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/shaders/compiled/flipyvs.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9shaderscompiledluminancepsh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/shaders/compiled/luminanceps.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/shaders/compiled/luminanceps.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/shaders/compiled/luminanceps.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,79 @@
</span><ins>+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 9.30.9200.16384
+//
+///
+// Parameters:
+//
+// float4 mode;
+// sampler2D tex;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// ------------ ----- ----
+// mode c0 1
+// tex s0 1
+//
+
+ ps_2_0
+ dcl t0.xy
+ dcl_2d s0
+ texld r0, t0, s0
+ mad r1.w, r0.w, c0.x, c0.y
+ mov r1.xyz, r0.x
+ mov oC0, r1
+
+// approximately 4 instruction slots used (1 texture, 3 arithmetic)
+#endif
+
+const BYTE g_ps20_luminanceps[] =
+{
+ 0, 2, 255, 255, 254, 255,
+ 44, 0, 67, 84, 65, 66,
+ 28, 0, 0, 0, 119, 0,
+ 0, 0, 0, 2, 255, 255,
+ 2, 0, 0, 0, 28, 0,
+ 0, 0, 0, 1, 0, 0,
+ 112, 0, 0, 0, 68, 0,
+ 0, 0, 2, 0, 0, 0,
+ 1, 0, 0, 0, 76, 0,
+ 0, 0, 0, 0, 0, 0,
+ 92, 0, 0, 0, 3, 0,
+ 0, 0, 1, 0, 0, 0,
+ 96, 0, 0, 0, 0, 0,
+ 0, 0, 109, 111, 100, 101,
+ 0, 171, 171, 171, 1, 0,
+ 3, 0, 1, 0, 4, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 116, 101, 120, 0,
+ 4, 0, 12, 0, 1, 0,
+ 1, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 112, 115,
+ 95, 50, 95, 48, 0, 77,
+ 105, 99, 114, 111, 115, 111,
+ 102, 116, 32, 40, 82, 41,
+ 32, 72, 76, 83, 76, 32,
+ 83, 104, 97, 100, 101, 114,
+ 32, 67, 111, 109, 112, 105,
+ 108, 101, 114, 32, 57, 46,
+ 51, 48, 46, 57, 50, 48,
+ 48, 46, 49, 54, 51, 56,
+ 52, 0, 171, 171, 31, 0,
+ 0, 2, 0, 0, 0, 128,
+ 0, 0, 3, 176, 31, 0,
+ 0, 2, 0, 0, 0, 144,
+ 0, 8, 15, 160, 66, 0,
+ 0, 3, 0, 0, 15, 128,
+ 0, 0, 228, 176, 0, 8,
+ 228, 160, 4, 0, 0, 4,
+ 1, 0, 8, 128, 0, 0,
+ 255, 128, 0, 0, 0, 160,
+ 0, 0, 85, 160, 1, 0,
+ 0, 2, 1, 0, 7, 128,
+ 0, 0, 0, 128, 1, 0,
+ 0, 2, 0, 8, 15, 128,
+ 1, 0, 228, 128, 255, 255,
+ 0, 0
+};
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/shaders/compiled/luminanceps.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9shaderscompiledpassthroughpsh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/shaders/compiled/passthroughps.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/shaders/compiled/passthroughps.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/shaders/compiled/passthroughps.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,62 @@
</span><ins>+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 9.30.9200.16384
+//
+///
+// Parameters:
+//
+// sampler2D tex;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// ------------ ----- ----
+// tex s0 1
+//
+
+ ps_2_0
+ dcl t0.xy
+ dcl_2d s0
+ texld r0, t0, s0
+ mov oC0, r0
+
+// approximately 2 instruction slots used (1 texture, 1 arithmetic)
+#endif
+
+const BYTE g_ps20_passthroughps[] =
+{
+ 0, 2, 255, 255, 254, 255,
+ 33, 0, 67, 84, 65, 66,
+ 28, 0, 0, 0, 75, 0,
+ 0, 0, 0, 2, 255, 255,
+ 1, 0, 0, 0, 28, 0,
+ 0, 0, 0, 1, 0, 0,
+ 68, 0, 0, 0, 48, 0,
+ 0, 0, 3, 0, 0, 0,
+ 1, 0, 0, 0, 52, 0,
+ 0, 0, 0, 0, 0, 0,
+ 116, 101, 120, 0, 4, 0,
+ 12, 0, 1, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 112, 115, 95, 50,
+ 95, 48, 0, 77, 105, 99,
+ 114, 111, 115, 111, 102, 116,
+ 32, 40, 82, 41, 32, 72,
+ 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67,
+ 111, 109, 112, 105, 108, 101,
+ 114, 32, 57, 46, 51, 48,
+ 46, 57, 50, 48, 48, 46,
+ 49, 54, 51, 56, 52, 0,
+ 171, 171, 31, 0, 0, 2,
+ 0, 0, 0, 128, 0, 0,
+ 3, 176, 31, 0, 0, 2,
+ 0, 0, 0, 144, 0, 8,
+ 15, 160, 66, 0, 0, 3,
+ 0, 0, 15, 128, 0, 0,
+ 228, 176, 0, 8, 228, 160,
+ 1, 0, 0, 2, 0, 8,
+ 15, 128, 0, 0, 228, 128,
+ 255, 255, 0, 0
+};
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/shaders/compiled/passthroughps.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9shaderscompiledstandardvsh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/shaders/compiled/standardvs.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/shaders/compiled/standardvs.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/shaders/compiled/standardvs.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,67 @@
</span><ins>+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 9.30.9200.16384
+//
+///
+// Parameters:
+//
+// float4 halfPixelSize;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// ------------- ----- ----
+// halfPixelSize c0 1
+//
+
+ vs_2_0
+ def c1, 0.5, -0.5, 1, 0
+ dcl_position v0
+ add oPos, v0, c0
+ mad oT0, v0, c1.xyzz, c1.xxww
+
+// approximately 2 instruction slots used
+#endif
+
+const BYTE g_vs20_standardvs[] =
+{
+ 0, 2, 254, 255, 254, 255,
+ 36, 0, 67, 84, 65, 66,
+ 28, 0, 0, 0, 87, 0,
+ 0, 0, 0, 2, 254, 255,
+ 1, 0, 0, 0, 28, 0,
+ 0, 0, 0, 1, 0, 0,
+ 80, 0, 0, 0, 48, 0,
+ 0, 0, 2, 0, 0, 0,
+ 1, 0, 0, 0, 64, 0,
+ 0, 0, 0, 0, 0, 0,
+ 104, 97, 108, 102, 80, 105,
+ 120, 101, 108, 83, 105, 122,
+ 101, 0, 171, 171, 1, 0,
+ 3, 0, 1, 0, 4, 0,
+ 1, 0, 0, 0, 0, 0,
+ 0, 0, 118, 115, 95, 50,
+ 95, 48, 0, 77, 105, 99,
+ 114, 111, 115, 111, 102, 116,
+ 32, 40, 82, 41, 32, 72,
+ 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67,
+ 111, 109, 112, 105, 108, 101,
+ 114, 32, 57, 46, 51, 48,
+ 46, 57, 50, 48, 48, 46,
+ 49, 54, 51, 56, 52, 0,
+ 171, 171, 81, 0, 0, 5,
+ 1, 0, 15, 160, 0, 0,
+ 0, 63, 0, 0, 0, 191,
+ 0, 0, 128, 63, 0, 0,
+ 0, 0, 31, 0, 0, 2,
+ 0, 0, 0, 128, 0, 0,
+ 15, 144, 2, 0, 0, 3,
+ 0, 0, 15, 192, 0, 0,
+ 228, 144, 0, 0, 228, 160,
+ 4, 0, 0, 4, 0, 0,
+ 15, 224, 0, 0, 228, 144,
+ 1, 0, 164, 160, 1, 0,
+ 240, 160, 255, 255, 0, 0
+};
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/shaders/compiled/standardvs.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9shadersgenerate_shadersbat"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/shaders/generate_shaders.bat (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/shaders/generate_shaders.bat         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/shaders/generate_shaders.bat        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,14 @@
</span><ins>+@ECHO OFF
+REM
+REM Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+REM Use of this source code is governed by a BSD-style license that can be
+REM found in the LICENSE file.
+REM
+
+PATH %PATH%;%ProgramFiles(x86)%\Windows Kits\8.0\bin\x86;%DXSDK_DIR%\Utilities\bin\x86
+
+fxc /E standardvs /T vs_2_0 /Fh compiled/standardvs.h Blit.vs
+fxc /E flipyvs /T vs_2_0 /Fh compiled/flipyvs.h Blit.vs
+fxc /E passthroughps /T ps_2_0 /Fh compiled/passthroughps.h Blit.ps
+fxc /E luminanceps /T ps_2_0 /Fh compiled/luminanceps.h Blit.ps
+fxc /E componentmaskps /T ps_2_0 /Fh compiled/componentmaskps.h Blit.ps
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/shaders/generate_shaders.bat
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnmimetype"></a>
<div class="addfile"><h4>Added: svn:mime-type</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
<a id="trunkSourceThirdPartyANGLEsrclibGLESv2rendererd3d9vertexconversionh"></a>
<div class="addfile"><h4>Added: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/vertexconversion.h (0 => 164567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/vertexconversion.h         (rev 0)
+++ trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/vertexconversion.h        2014-02-24 00:58:19 UTC (rev 164567)
</span><span class="lines">@@ -0,0 +1,203 @@
</span><ins>+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// vertexconversion.h: A library of vertex conversion classes that can be used to build
+// the FormatConverter objects used by the buffer conversion system.
+
+#ifndef LIBGLESV2_VERTEXCONVERSION_H_
+#define LIBGLESV2_VERTEXCONVERSION_H_
+
+namespace rx
+{
+
+// Conversion types:
+// static const bool identity: true if this is an identity transform, false otherwise
+// static U convert(T): convert a single element from the input type to the output type
+// typedef ... OutputType: the type produced by this conversion
+
+template <class T>
+struct Identity
+{
+ static const bool identity = true;
+
+ typedef T OutputType;
+
+ static T convert(T x)
+ {
+ return x;
+ }
+};
+
+template <class FromT, class ToT>
+struct Cast
+{
+ static const bool identity = false;
+
+ typedef ToT OutputType;
+
+ static ToT convert(FromT x)
+ {
+ return static_cast<ToT>(x);
+ }
+};
+
+template <class T>
+struct Cast<T, T>
+{
+ static const bool identity = true;
+
+ typedef T OutputType;
+
+ static T convert(T x)
+ {
+ return static_cast<T>(x);
+ }
+};
+
+template <class T>
+struct Normalize
+{
+ static const bool identity = false;
+
+ typedef float OutputType;
+
+ static float convert(T x)
+ {
+ typedef std::numeric_limits<T> NL;
+ float f = static_cast<float>(x);
+
+ if (NL::is_signed)
+ {
+ // const float => VC2008 computes it at compile time
+ // static const float => VC2008 computes it the first time we get here, stores it to memory with static guard and all that.
+ const float divisor = 1.0f/(2*static_cast<float>(NL::max())+1);
+ return (2*f+1)*divisor;
+ }
+ else
+ {
+ return f/NL::max();
+ }
+ }
+};
+
+template <class FromType, std::size_t ScaleBits>
+struct FixedToFloat
+{
+ static const bool identity = false;
+
+ typedef float OutputType;
+
+ static float convert(FromType x)
+ {
+ const float divisor = 1.0f / static_cast<float>(static_cast<FromType>(1) << ScaleBits);
+ return static_cast<float>(x) * divisor;
+ }
+};
+
+// Widen types:
+// static const unsigned int initialWidth: number of components before conversion
+// static const unsigned int finalWidth: number of components after conversion
+
+// Float is supported at any size.
+template <std::size_t N>
+struct NoWiden
+{
+ static const std::size_t initialWidth = N;
+ static const std::size_t finalWidth = N;
+};
+
+// SHORT, norm-SHORT, norm-UNSIGNED_SHORT are supported but only with 2 or 4 components
+template <std::size_t N>
+struct WidenToEven
+{
+ static const std::size_t initialWidth = N;
+ static const std::size_t finalWidth = N+(N&1);
+};
+
+template <std::size_t N>
+struct WidenToFour
+{
+ static const std::size_t initialWidth = N;
+ static const std::size_t finalWidth = 4;
+};
+
+// Most types have 0 and 1 that are just that.
+template <class T>
+struct SimpleDefaultValues
+{
+ static T zero() { return static_cast<T>(0); }
+ static T one() { return static_cast<T>(1); }
+};
+
+// But normalised types only store [0,1] or [-1,1] so 1.0 is represented by the max value.
+template <class T>
+struct NormalizedDefaultValues
+{
+ static T zero() { return static_cast<T>(0); }
+ static T one() { return std::numeric_limits<T>::max(); }
+};
+
+// Converter:
+// static const bool identity: true if this is an identity transform (with no widening)
+// static const std::size_t finalSize: number of bytes per output vertex
+// static void convertArray(const void *in, std::size_t stride, std::size_t n, void *out): convert an array of vertices. Input may be strided, but output will be unstrided.
+
+template <class InT, class WidenRule, class Converter, class DefaultValueRule = SimpleDefaultValues<InT> >
+struct VertexDataConverter
+{
+ typedef typename Converter::OutputType OutputType;
+ typedef InT InputType;
+
+ static const bool identity = (WidenRule::initialWidth == WidenRule::finalWidth) && Converter::identity;
+ static const std::size_t finalSize = WidenRule::finalWidth * sizeof(OutputType);
+
+ static void convertArray(const InputType *in, std::size_t stride, std::size_t n, OutputType *out)
+ {
+ for (std::size_t i = 0; i < n; i++)
+ {
+ const InputType *ein = pointerAddBytes(in, i * stride);
+
+ copyComponent(out, ein, 0, static_cast<OutputType>(DefaultValueRule::zero()));
+ copyComponent(out, ein, 1, static_cast<OutputType>(DefaultValueRule::zero()));
+ copyComponent(out, ein, 2, static_cast<OutputType>(DefaultValueRule::zero()));
+ copyComponent(out, ein, 3, static_cast<OutputType>(DefaultValueRule::one()));
+
+ out += WidenRule::finalWidth;
+ }
+ }
+
+ static void convertArray(const void *in, std::size_t stride, std::size_t n, void *out)
+ {
+ return convertArray(static_cast<const InputType*>(in), stride, n, static_cast<OutputType*>(out));
+ }
+
+ private:
+ // Advance the given pointer by a number of bytes (not pointed-to elements).
+ template <class T>
+ static T *pointerAddBytes(T *basePtr, std::size_t numBytes)
+ {
+ return reinterpret_cast<T *>(reinterpret_cast<uintptr_t>(basePtr) + numBytes);
+ }
+
+ static void copyComponent(OutputType *out, const InputType *in, std::size_t elementindex, OutputType defaultvalue)
+ {
+ if (WidenRule::finalWidth > elementindex)
+ {
+ if (WidenRule::initialWidth > elementindex)
+ {
+ out[elementindex] = Converter::convert(in[elementindex]);
+ }
+ else
+ {
+ out[elementindex] = defaultvalue;
+ }
+ }
+ }
+};
+
+}
+
+#endif // LIBGLESV2_VERTEXCONVERSION_H_
</ins><span class="cx">Property changes on: trunk/Source/ThirdParty/ANGLE/src/libGLESv2/renderer/d3d9/vertexconversion.h
</span><span class="cx">___________________________________________________________________
</span></span></pre></div>
<a id="svnkeywords"></a>
<div class="addfile"><h4>Added: svn:keywords</h4></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4>Added: svn:eol-style</h4></div>
</div>
</body>
</html>