diff -r 000000000000 -r 6474c204b198 gfx/angle/angle-faceforward-emu.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gfx/angle/angle-faceforward-emu.patch Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,314 @@ +From: Jeff Gilbert +Bug 771406 - Add emulation for GLSL faceforward() to ANGLE - r=bjacob + +diff --git a/gfx/angle/src/compiler/BuiltInFunctionEmulator.cpp b/gfx/angle/src/compiler/BuiltInFunctionEmulator.cpp +--- a/gfx/angle/src/compiler/BuiltInFunctionEmulator.cpp ++++ b/gfx/angle/src/compiler/BuiltInFunctionEmulator.cpp +@@ -26,16 +26,22 @@ const char* kFunctionEmulationVertexSour + "#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)", + ++ // |faceforward(N, I, Nref)| is |dot(NRef, I) < 0 ? N : -N| ++ "#define webgl_faceforward_emu(N, I, Nref) (((Nref) * (I) < 0.0) ? (N) : -(N))", ++ "#error no emulation for faceforward(vec2, vec2, vec2)", ++ "#error no emulation for faceforward(vec3, vec3, vec3)", ++ "#error no emulation for faceforward(vec4, 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)", +@@ -58,16 +64,22 @@ const char* kFunctionEmulationFragmentSo + "#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)", + ++ // |faceforward(N, I, Nref)| is |dot(NRef, I) < 0 ? N : -N| ++ "#define webgl_faceforward_emu(N, I, Nref) (((Nref) * (I) < 0.0) ? (N) : -(N))", ++ "#error no emulation for faceforward(vec2, vec2, vec2)", ++ "#error no emulation for faceforward(vec3, vec3, vec3)", ++ "#error no emulation for faceforward(vec4, 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)", +@@ -89,16 +101,20 @@ const bool kFunctionEmulationVertexMask[ + 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, // TFunctionFaceForward1_1_1 ++ false, // TFunctionFaceForward2_2_2 ++ false, // TFunctionFaceForward3_3_3 ++ false, // TFunctionFaceForward4_4_4 + true, // TFunctionLength1 + false, // TFunctionLength2 + false, // TFunctionLength3 + false, // TFunctionLength4 + true, // TFunctionNormalize1 + false, // TFunctionNormalize2 + false, // TFunctionNormalize3 + false, // TFunctionNormalize4 +@@ -115,16 +131,20 @@ const bool kFunctionEmulationVertexMask[ + 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, // TFunctionFaceForward1_1_1 ++ false, // TFunctionFaceForward2_2_2 ++ false, // TFunctionFaceForward3_3_3 ++ false, // TFunctionFaceForward4_4_4 + false, // TFunctionLength1 + false, // TFunctionLength2 + false, // TFunctionLength3 + false, // TFunctionLength4 + false, // TFunctionNormalize1 + false, // TFunctionNormalize2 + false, // TFunctionNormalize3 + false, // TFunctionNormalize4 +@@ -146,16 +166,20 @@ const bool kFunctionEmulationFragmentMas + 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, // TFunctionFaceForward1_1_1 ++ false, // TFunctionFaceForward2_2_2 ++ false, // TFunctionFaceForward3_3_3 ++ false, // TFunctionFaceForward4_4_4 + true, // TFunctionLength1 + false, // TFunctionLength2 + false, // TFunctionLength3 + false, // TFunctionLength4 + true, // TFunctionNormalize1 + false, // TFunctionNormalize2 + false, // TFunctionNormalize3 + false, // TFunctionNormalize4 +@@ -172,16 +196,20 @@ const bool kFunctionEmulationFragmentMas + 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, // TFunctionFaceForward1_1_1 ++ false, // TFunctionFaceForward2_2_2 ++ false, // TFunctionFaceForward3_3_3 ++ false, // TFunctionFaceForward4_4_4 + false, // TFunctionLength1 + false, // TFunctionLength2 + false, // TFunctionLength3 + false, // TFunctionLength4 + false, // TFunctionNormalize1 + false, // TFunctionNormalize2 + false, // TFunctionNormalize3 + false, // TFunctionNormalize4 +@@ -239,25 +267,37 @@ public: + 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) ++ bool needToEmulate = false; ++ ++ if (sequence.size() == 2) { ++ TIntermTyped* param1 = sequence[0]->getAsTyped(); ++ TIntermTyped* param2 = sequence[1]->getAsTyped(); ++ if (!param1 || !param2) ++ return true; ++ needToEmulate = mEmulator.SetFunctionCalled( ++ node->getOp(), param1->getType(), param2->getType()); ++ } else if (sequence.size() == 3) { ++ TIntermTyped* param1 = sequence[0]->getAsTyped(); ++ TIntermTyped* param2 = sequence[1]->getAsTyped(); ++ TIntermTyped* param3 = sequence[2]->getAsTyped(); ++ if (!param1 || !param2 || !param3) ++ return true; ++ needToEmulate = mEmulator.SetFunctionCalled( ++ node->getOp(), param1->getType(), param2->getType(), param3->getType()); ++ } else { + return true; +- TIntermTyped* param1 = sequence[0]->getAsTyped(); +- TIntermTyped* param2 = sequence[1]->getAsTyped(); +- if (!param1 || !param2) +- return true; +- bool needToEmulate = mEmulator.SetFunctionCalled( +- node->getOp(), param1->getType(), param2->getType()); ++ } ++ + if (needToEmulate) + node->setUseEmulatedFunction(); + } + return true; + } + + private: + BuiltInFunctionEmulator& mEmulator; +@@ -286,16 +326,23 @@ bool BuiltInFunctionEmulator::SetFunctio + bool BuiltInFunctionEmulator::SetFunctionCalled( + TOperator op, const TType& param1, const TType& param2) + { + TBuiltInFunction function = IdentifyFunction(op, param1, param2); + return SetFunctionCalled(function); + } + + bool BuiltInFunctionEmulator::SetFunctionCalled( ++ TOperator op, const TType& param1, const TType& param2, const TType& param3) ++{ ++ TBuiltInFunction function = IdentifyFunction(op, param1, param2, param3); ++ 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); +@@ -377,16 +424,44 @@ BuiltInFunctionEmulator::IdentifyFunctio + } + if (function == TFunctionUnknown) + return TFunctionUnknown; + if (param1.isVector()) + function += param1.getNominalSize() - 1; + return static_cast(function); + } + ++BuiltInFunctionEmulator::TBuiltInFunction ++BuiltInFunctionEmulator::IdentifyFunction( ++ TOperator op, const TType& param1, const TType& param2, const TType& param3) ++{ ++ // Check that all params have the same type, length, ++ // and that they're not too large. ++ if (param1.isVector() != param2.isVector() || ++ param2.isVector() != param3.isVector() || ++ param1.getNominalSize() != param2.getNominalSize() || ++ param2.getNominalSize() != param3.getNominalSize() || ++ param1.getNominalSize() > 4) ++ return TFunctionUnknown; ++ ++ unsigned int function = TFunctionUnknown; ++ switch (op) { ++ case EOpFaceForward: ++ function = TFunctionFaceForward1_1_1; ++ break; ++ default: ++ break; ++ } ++ if (function == TFunctionUnknown) ++ return TFunctionUnknown; ++ if (param1.isVector()) ++ function += param1.getNominalSize() - 1; ++ return static_cast(function); ++} ++ + void BuiltInFunctionEmulator::MarkBuiltInFunctionsForEmulation( + TIntermNode* root) + { + ASSERT(root); + + BuiltInFunctionEmulationMarker marker(*this); + root->traverse(&marker); + } +diff --git a/gfx/angle/src/compiler/BuiltInFunctionEmulator.h b/gfx/angle/src/compiler/BuiltInFunctionEmulator.h +--- a/gfx/angle/src/compiler/BuiltInFunctionEmulator.h ++++ b/gfx/angle/src/compiler/BuiltInFunctionEmulator.h +@@ -23,16 +23,18 @@ public: + // 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); ++ bool SetFunctionCalled( ++ TOperator op, const TType& param1, const TType& param2, const TType& param3); + + // 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(); +@@ -55,16 +57,21 @@ private: + 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); + ++ TFunctionFaceForward1_1_1, // float faceforward(float, float, float); ++ TFunctionFaceForward2_2_2, // vec2 faceforward(vec2, vec2, vec2); ++ TFunctionFaceForward3_3_3, // vec3 faceforward(vec3, vec3, vec3); ++ TFunctionFaceForward4_4_4, // vec4 faceforward(vec4, 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); +@@ -76,16 +83,18 @@ private: + TFunctionReflect4_4, // vec4 reflect(vec4, vec4); + + TFunctionUnknown + }; + + TBuiltInFunction IdentifyFunction(TOperator op, const TType& param); + TBuiltInFunction IdentifyFunction( + TOperator op, const TType& param1, const TType& param2); ++ TBuiltInFunction IdentifyFunction( ++ TOperator op, const TType& param1, const TType& param2, const TType& param3); + + bool SetFunctionCalled(TBuiltInFunction function); + + std::vector mFunctions; + + const bool* mFunctionMask; // a boolean flag for each function. + const char** mFunctionSource; + };