Commit 430f5e0c by maxvujovic@gmail.com

Add the SH_CSS_SHADERS_SPEC flag.

Review URL: https://codereview.appspot.com/6270050/ git-svn-id: https://angleproject.googlecode.com/svn/trunk@1145 736b8ea6-26fd-11df-bfd4-992fa37f6226
parent ea09f9b4
......@@ -34,7 +34,7 @@ extern "C" {
// Version number for shader translation API.
// It is incremented everytime the API changes.
#define SH_VERSION 106
#define SH_VERSION 107
//
// The names of the following enums have been derived by replacing GL prefix
......@@ -49,7 +49,29 @@ typedef enum {
typedef enum {
SH_GLES2_SPEC = 0x8B40,
SH_WEBGL_SPEC = 0x8B41
SH_WEBGL_SPEC = 0x8B41,
// The CSS Shaders spec is a subset of the WebGL spec.
//
// In both CSS vertex and fragment shaders, ANGLE:
// (1) Reserves the "css_" prefix.
// (2) Renames the main function to css_main.
// (3) Disables the gl_MaxDrawBuffers built-in.
//
// In CSS fragment shaders, ANGLE:
// (1) Disables the gl_FragColor built-in.
// (2) Disables the gl_FragData built-in.
// (3) Enables the css_MixColor built-in.
// (4) Enables the css_ColorMatrix built-in.
//
// After passing a CSS shader through ANGLE, the browser is expected to append
// a new main function to it.
// This new main function will call the css_main function.
// It may also perform additional operations like varying assignment, texture
// access, and gl_FragColor assignment in order to implement the CSS Shaders
// blend modes.
//
SH_CSS_SHADERS_SPEC = 0x8B42
} ShShaderSpec;
typedef enum {
......
......@@ -93,8 +93,11 @@ int main(int argc, char* argv[])
switch (argv[0][3]) {
case 'e': spec = SH_GLES2_SPEC; break;
case 'w': spec = SH_WEBGL_SPEC; break;
case 'c': spec = SH_CSS_SHADERS_SPEC; break;
default: failCode = EFailUsage;
}
} else {
failCode = EFailUsage;
}
break;
case 'b':
......@@ -212,6 +215,7 @@ void usage()
" -d : print dependency graph used to enforce timing restrictions\n"
" -s=e : use GLES2 spec (this is by default)\n"
" -s=w : use WebGL spec\n"
" -s=c : use CSS Shaders spec\n"
" -b=e : output GLSL ES code (this is by default)\n"
" -b=g : output GLSL code\n"
" -b=h : output HLSL code\n"
......
......@@ -95,6 +95,7 @@
'compiler/QualifierAlive.h',
'compiler/RemoveTree.cpp',
'compiler/RemoveTree.h',
'compiler/RenameFunction.h',
'compiler/ShHandle.h',
'compiler/SymbolTable.cpp',
'compiler/SymbolTable.h',
......
......@@ -10,6 +10,7 @@
#include "compiler/Initialize.h"
#include "compiler/MapLongVariableNames.h"
#include "compiler/ParseHelper.h"
#include "compiler/RenameFunction.h"
#include "compiler/ShHandle.h"
#include "compiler/ValidateLimitations.h"
#include "compiler/depgraph/DependencyGraph.h"
......@@ -17,6 +18,11 @@
#include "compiler/timing/RestrictFragmentShaderTiming.h"
#include "compiler/timing/RestrictVertexShaderTiming.h"
bool isWebGLBasedSpec(ShShaderSpec spec)
{
return spec == SH_WEBGL_SPEC || spec == SH_CSS_SHADERS_SPEC;
}
namespace {
bool InitializeSymbolTable(
const TBuiltInStrings& builtInStrings,
......@@ -127,7 +133,7 @@ bool TCompiler::compile(const char* const shaderStrings[],
return true;
// If compiling for WebGL, validate loop and indexing as well.
if (shaderSpec == SH_WEBGL_SPEC)
if (isWebGLBasedSpec(shaderSpec))
compileOptions |= SH_VALIDATE_LOOP_INDEXING;
// First string is path of source file if flag is set. The actual source follows.
......@@ -168,6 +174,9 @@ bool TCompiler::compile(const char* const shaderStrings[],
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);
......@@ -242,6 +251,12 @@ bool TCompiler::detectRecursion(TIntermNode* root)
}
}
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);
......
......@@ -475,7 +475,7 @@ static TString DefaultPrecisionFragment()
// Implementation dependent built-in constants.
//
//============================================================================
static TString BuiltInConstants(const ShBuiltInResources &resources)
static TString BuiltInConstants(ShShaderSpec spec, const ShBuiltInResources &resources)
{
TStringStream s;
......@@ -487,7 +487,9 @@ static TString BuiltInConstants(const ShBuiltInResources &resources)
s << "const int gl_MaxCombinedTextureImageUnits = " << resources.MaxCombinedTextureImageUnits << ";";
s << "const int gl_MaxTextureImageUnits = " << resources.MaxTextureImageUnits << ";";
s << "const int gl_MaxFragmentUniformVectors = " << resources.MaxFragmentUniformVectors << ";";
s << "const int gl_MaxDrawBuffers = " << resources.MaxDrawBuffers << ";";
if (spec != SH_CSS_SHADERS_SPEC)
s << "const int gl_MaxDrawBuffers = " << resources.MaxDrawBuffers << ";";
return s.str();
}
......@@ -513,7 +515,7 @@ void TBuiltIns::initialize(ShShaderType type, ShShaderSpec spec,
default: assert(false && "Language not supported");
}
builtInStrings.push_back(BuiltInConstants(resources));
builtInStrings.push_back(BuiltInConstants(spec, resources));
}
void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec,
......@@ -526,11 +528,22 @@ void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec,
//
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_FragColor"), TType(EbtFloat, EbpMedium, EvqFragColor, 4)));
symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData[gl_MaxDrawBuffers]"), TType(EbtFloat, EbpMedium, EvqFragData, 4)));
symbolTable.insert(*new TVariable(NewPoolTString("gl_PointCoord"), TType(EbtFloat, EbpMedium, EvqPointCoord, 2)));
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)));
} 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:
......@@ -620,7 +633,8 @@ void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec,
// Finally add resource-specific variables.
switch(type) {
case SH_FRAGMENT_SHADER: {
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);
......
......@@ -452,7 +452,7 @@ bool TParseContext::reservedErrorCheck(int line, const TString& identifier)
error(line, reservedErrMsg, "gl_", "");
return true;
}
if (shaderSpec == SH_WEBGL_SPEC) {
if (isWebGLBasedSpec(shaderSpec)) {
if (identifier.compare(0, 6, "webgl_") == 0) {
error(line, reservedErrMsg, "webgl_", "");
return true;
......@@ -461,6 +461,10 @@ bool TParseContext::reservedErrorCheck(int line, const TString& identifier)
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(), "", "");
......@@ -1451,7 +1455,7 @@ const int kWebGLMaxStructNesting = 4;
bool TParseContext::structNestingErrorCheck(TSourceLoc line, const TType& fieldType)
{
if (shaderSpec != SH_WEBGL_SPEC) {
if (!isWebGLBasedSpec(shaderSpec)) {
return false;
}
......
//
// 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/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
......@@ -27,6 +27,12 @@ class TCompiler;
class TDependencyGraph;
//
// 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 {
......@@ -71,6 +77,8 @@ protected:
void clearResults();
// Return true if function recursion is detected.
bool detectRecursion(TIntermNode* root);
// 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);
......
......@@ -641,6 +641,10 @@
>
</File>
<File
RelativePath=".\RenameFunction.h"
>
</File>
<File
RelativePath="..\..\include\GLSLANG\ResourceLimits.h"
>
</File>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment