void drive_operation() { // Uint64 tests CQLValue a1(Uint64(10)); CQLValue a2(Uint64(15)); CQLValue a3(Uint64(25)); CQLValue a4(Uint64(30)); CQLValue a5(Uint64(150)); PEGASUS_TEST_ASSERT(a1 != a2); PEGASUS_TEST_ASSERT(a5 == a5); PEGASUS_TEST_ASSERT(a1 < a2); PEGASUS_TEST_ASSERT(a2 >= a1); PEGASUS_TEST_ASSERT(a1 <= a2); PEGASUS_TEST_ASSERT(a2 > a1); // Sint64 tests CQLValue b1(Sint64(10)); CQLValue b2(Sint64(15)); CQLValue b3(Sint64(25)); CQLValue b4(Sint64(30)); CQLValue b5(Sint64(150)); PEGASUS_TEST_ASSERT(b1 != b2); PEGASUS_TEST_ASSERT(b5 == b5); PEGASUS_TEST_ASSERT(b1 < b2); PEGASUS_TEST_ASSERT(b2 >= b1); PEGASUS_TEST_ASSERT(b1 <= b2); PEGASUS_TEST_ASSERT(b2 > b1); // Real64 tests CQLValue c1(Real64(10.00)); CQLValue c2(Real64(15.00)); CQLValue c3(Real64(25.00)); CQLValue c4(Real64(30.00)); CQLValue c5(Real64(150.00)); PEGASUS_TEST_ASSERT(c1 != c2); PEGASUS_TEST_ASSERT(c5 == c5); PEGASUS_TEST_ASSERT(c1 < c2); PEGASUS_TEST_ASSERT(c2 >= c1); PEGASUS_TEST_ASSERT(c1 <= c2); PEGASUS_TEST_ASSERT(c2 > c1); // Misc PEGASUS_TEST_ASSERT(a1 == b1); PEGASUS_TEST_ASSERT(a1 == c1); PEGASUS_TEST_ASSERT(b1 == a1); PEGASUS_TEST_ASSERT(b1 == c1); PEGASUS_TEST_ASSERT(c1 == a1); PEGASUS_TEST_ASSERT(c1 == b1); PEGASUS_TEST_ASSERT(a2 != b1); PEGASUS_TEST_ASSERT(a2 != c1); PEGASUS_TEST_ASSERT(b2 != a1); PEGASUS_TEST_ASSERT(b2 != c1); PEGASUS_TEST_ASSERT(c2 != a1); PEGASUS_TEST_ASSERT(c2 != b1); PEGASUS_TEST_ASSERT(a2 >= b1); PEGASUS_TEST_ASSERT(a2 >= c1); PEGASUS_TEST_ASSERT(b2 >= a1); PEGASUS_TEST_ASSERT(b2 >= c1); PEGASUS_TEST_ASSERT(c2 >= a1); PEGASUS_TEST_ASSERT(c2 >= b1); PEGASUS_TEST_ASSERT(a2 <= b3); PEGASUS_TEST_ASSERT(a2 <= c3); PEGASUS_TEST_ASSERT(b2 <= a3); PEGASUS_TEST_ASSERT(b2 <= c3); PEGASUS_TEST_ASSERT(c2 <= a3); PEGASUS_TEST_ASSERT(c2 <= b3); PEGASUS_TEST_ASSERT(a2 > b1); PEGASUS_TEST_ASSERT(a2 > c1); PEGASUS_TEST_ASSERT(b2 > a1); PEGASUS_TEST_ASSERT(b2 > c1); PEGASUS_TEST_ASSERT(c2 > a1); PEGASUS_TEST_ASSERT(c2 > b1); PEGASUS_TEST_ASSERT(a2 < b3); PEGASUS_TEST_ASSERT(a2 < c3); PEGASUS_TEST_ASSERT(b2 < a3); PEGASUS_TEST_ASSERT(b2 < c3); PEGASUS_TEST_ASSERT(c2 < a3); PEGASUS_TEST_ASSERT(c2 < b3); //Overflow testing CQLValue real1(Real64(0.00000001)); CQLValue sint1(Sint64(-1)); CQLValue uint1(Sint64(1)); CQLValue uint2(Uint64(0)); PEGASUS_TEST_ASSERT(uint1 > sint1); PEGASUS_TEST_ASSERT(real1 > sint1); PEGASUS_TEST_ASSERT(uint2 > sint1); PEGASUS_TEST_ASSERT(real1 > uint2); CQLValue real2(Real64(25.00000000000001)); CQLValue real3(Real64(24.99999999999999)); CQLValue sint2(Sint64(25)); CQLValue uint3(Uint64(25)); PEGASUS_TEST_ASSERT(real2 > real3); PEGASUS_TEST_ASSERT(real2 > sint2); PEGASUS_TEST_ASSERT(real2 > uint3); PEGASUS_TEST_ASSERT(real3 < sint2); PEGASUS_TEST_ASSERT(real3 < uint3); // String tests CQLValue d1(String("HELLO")); CQLValue d2(String("HEL")); CQLValue d3(String("LO")); CQLValue d4(String("AHELLO")); CQLValue d5(String("ZHELLO")); PEGASUS_TEST_ASSERT(d1 == d2 + d3); PEGASUS_TEST_ASSERT(d1 != d2 + d4); PEGASUS_TEST_ASSERT(d1 <= d5); PEGASUS_TEST_ASSERT(d1 < d5); PEGASUS_TEST_ASSERT(d1 >= d4); PEGASUS_TEST_ASSERT(d1 > d4); String str1("0x10"); String str2("10"); String str3("10B"); String str4("10.10"); CQLValue e1( str1, CQLValue::Hex); CQLValue e2( str2, CQLValue::Decimal); CQLValue e3( str3, CQLValue::Binary); CQLValue e4( str4, CQLValue::Real); CQLValue e5(Uint64(16)); CQLValue e6(Uint64(10)); CQLValue e7(Uint64(2)); CQLValue e8(Real64(10.10)); PEGASUS_TEST_ASSERT(e1 == e5); PEGASUS_TEST_ASSERT(e2 == e6); PEGASUS_TEST_ASSERT(e3 == e7); PEGASUS_TEST_ASSERT(e4 == e8); Array<Uint64> array1; array1.append(1); array1.append(2); array1.append(3); array1.append(4); array1.append(5); array1.append(6); array1.append(7); array1.append(8); array1.append(9); array1.append(10); Array<Sint64> array2; array2.append(1); array2.append(2); array2.append(3); array2.append(4); array2.append(5); array2.append(6); array2.append(7); array2.append(8); array2.append(9); array2.append(10); array2.append(3); Array<Real64> array3; array3.append(1.00); array3.append(2.00); array3.append(3.00); array3.append(9.00); array3.append(10.00); array3.append(3.00); array3.append(4.00); array3.append(5.00); array3.append(6.00); array3.append(7.00); array3.append(8.00); Array<Uint64> array4; array4.append(1); array4.append(23); array4.append(3); array4.append(4); array4.append(5); array4.append(6); array4.append(7); array4.append(88); array4.append(9); array4.append(10); Array<Sint64> array5; array5.append(-1); array5.append(2); array5.append(3); array5.append(4); array5.append(5); array5.append(-6); array5.append(7); array5.append(8); array5.append(9); array5.append(10); array5.append(-3); Array<Real64> array6; array6.append(1.23); array6.append(2.00); array6.append(3.00); array6.append(9.00); array6.append(10.00); array6.append(3.00); array6.append(4.14); array6.append(5.00); array6.append(6.00); array6.append(7.00); array6.append(8.00); CIMValue cv1(array1); CIMValue cv2(array2); CIMValue cv3(array3); CIMValue cv4(array4); CIMValue cv5(array5); CIMValue cv6(array6); CQLValue vr1(cv1); CQLValue vr2(cv1); CQLValue vr3(cv2); CQLValue vr4(cv3); CQLValue vr5(cv4); CQLValue vr6(cv5); CQLValue vr7(cv6); PEGASUS_TEST_ASSERT(vr1 == vr2); PEGASUS_TEST_ASSERT(vr1 == vr3); PEGASUS_TEST_ASSERT(vr1 == vr4); PEGASUS_TEST_ASSERT(vr4 == vr3); PEGASUS_TEST_ASSERT(vr1 != vr5); PEGASUS_TEST_ASSERT(vr3 != vr6); PEGASUS_TEST_ASSERT(vr4 != vr7); const CIMName _cimName(String("CIM_OperatingSystem")); CIMInstance _i1(_cimName); CIMProperty _p1(CIMName("Description"),CIMValue(String("Dave Rules"))); CIMProperty _p2(CIMName("EnabledState"),CIMValue(Uint16(2))); CIMProperty _p3(CIMName("CurrentTimeZone"),CIMValue(Sint16(-600))); CIMProperty _p4(CIMName("TimeOfLastStateChange"), CIMValue(CIMDateTime(String("20040811105625.000000-360")))); _i1.addProperty(_p1); _i1.addProperty(_p2); _i1.addProperty(_p3); _i1.addProperty(_p4); CIMInstance _i2(_cimName); CIMProperty _p5(CIMName("Description"), CIMValue(String("Dave Rules Everything"))); CIMProperty _p6(CIMName("EnabledState"),CIMValue(Uint16(2))); CIMProperty _p7(CIMName("CurrentTimeZone"),CIMValue(Sint16(-600))); CIMProperty _p8(CIMName("TimeOfLastStateChange"), CIMValue(CIMDateTime(String("20040811105625.000000-360")))); _i2.addProperty(_p5); _i2.addProperty(_p6); _i2.addProperty(_p7); _i2.addProperty(_p8); CQLValue cql1(_i1); CQLValue cql2(_i1); CQLValue cql3(_i2); CQLValue cql4(_i2); //PEGASUS_TEST_ASSERT(cql1 == cql1); return; }
void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu) { TType float1(EbtFloat); TType float2(EbtFloat, 2); TType float3(EbtFloat, 3); TType float4(EbtFloat, 4); emu->addEmulatedFunction(EOpMod, float1, float1, "float webgl_mod_emu(float x, float y)\n" "{\n" " return x - y * floor(x / y);\n" "}\n" "\n"); emu->addEmulatedFunction(EOpMod, float2, float2, "float2 webgl_mod_emu(float2 x, float2 y)\n" "{\n" " return x - y * floor(x / y);\n" "}\n" "\n"); emu->addEmulatedFunction(EOpMod, float2, float1, "float2 webgl_mod_emu(float2 x, float y)\n" "{\n" " return x - y * floor(x / y);\n" "}\n" "\n"); emu->addEmulatedFunction(EOpMod, float3, float3, "float3 webgl_mod_emu(float3 x, float3 y)\n" "{\n" " return x - y * floor(x / y);\n" "}\n" "\n"); emu->addEmulatedFunction(EOpMod, float3, float1, "float3 webgl_mod_emu(float3 x, float y)\n" "{\n" " return x - y * floor(x / y);\n" "}\n" "\n"); emu->addEmulatedFunction(EOpMod, float4, float4, "float4 webgl_mod_emu(float4 x, float4 y)\n" "{\n" " return x - y * floor(x / y);\n" "}\n" "\n"); emu->addEmulatedFunction(EOpMod, float4, float1, "float4 webgl_mod_emu(float4 x, float y)\n" "{\n" " return x - y * floor(x / y);\n" "}\n" "\n"); emu->addEmulatedFunction(EOpFaceForward, float1, float1, float1, "float webgl_faceforward_emu(float N, float I, float Nref)\n" "{\n" " if(dot(Nref, I) >= 0)\n" " {\n" " return -N;\n" " }\n" " else\n" " {\n" " return N;\n" " }\n" "}\n" "\n"); emu->addEmulatedFunction(EOpFaceForward, float2, float2, float2, "float2 webgl_faceforward_emu(float2 N, float2 I, float2 Nref)\n" "{\n" " if(dot(Nref, I) >= 0)\n" " {\n" " return -N;\n" " }\n" " else\n" " {\n" " return N;\n" " }\n" "}\n" "\n"); emu->addEmulatedFunction(EOpFaceForward, float3, float3, float3, "float3 webgl_faceforward_emu(float3 N, float3 I, float3 Nref)\n" "{\n" " if(dot(Nref, I) >= 0)\n" " {\n" " return -N;\n" " }\n" " else\n" " {\n" " return N;\n" " }\n" "}\n" "\n"); emu->addEmulatedFunction(EOpFaceForward, float4, float4, float4, "float4 webgl_faceforward_emu(float4 N, float4 I, float4 Nref)\n" "{\n" " if(dot(Nref, I) >= 0)\n" " {\n" " return -N;\n" " }\n" " else\n" " {\n" " return N;\n" " }\n" "}\n" "\n"); emu->addEmulatedFunction(EOpAtan, float1, float1, "float webgl_atan_emu(float y, float x)\n" "{\n" " if(x == 0 && y == 0) x = 1;\n" // Avoid producing a NaN " return atan2(y, x);\n" "}\n"); emu->addEmulatedFunction(EOpAtan, float2, float2, "float2 webgl_atan_emu(float2 y, float2 x)\n" "{\n" " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n" " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n" " return float2(atan2(y[0], x[0]), atan2(y[1], x[1]));\n" "}\n"); emu->addEmulatedFunction(EOpAtan, float3, float3, "float3 webgl_atan_emu(float3 y, float3 x)\n" "{\n" " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n" " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n" " if(x[2] == 0 && y[2] == 0) x[2] = 1;\n" " return float3(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]));\n" "}\n"); emu->addEmulatedFunction(EOpAtan, float4, float4, "float4 webgl_atan_emu(float4 y, float4 x)\n" "{\n" " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n" " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n" " if(x[2] == 0 && y[2] == 0) x[2] = 1;\n" " if(x[3] == 0 && y[3] == 0) x[3] = 1;\n" " return float4(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]), atan2(y[3], x[3]));\n" "}\n"); emu->addEmulatedFunction(EOpAsinh, float1, "float webgl_asinh_emu(in float x) {\n" " return log(x + sqrt(pow(x, 2.0) + 1.0));\n" "}\n"); emu->addEmulatedFunction(EOpAsinh, float2, "float2 webgl_asinh_emu(in float2 x) {\n" " return log(x + sqrt(pow(x, 2.0) + 1.0));\n" "}\n"); emu->addEmulatedFunction(EOpAsinh, float3, "float3 webgl_asinh_emu(in float3 x) {\n" " return log(x + sqrt(pow(x, 2.0) + 1.0));\n" "}\n"); emu->addEmulatedFunction(EOpAsinh, float4, "float4 webgl_asinh_emu(in float4 x) {\n" " return log(x + sqrt(pow(x, 2.0) + 1.0));\n" "}\n"); emu->addEmulatedFunction(EOpAcosh, float1, "float webgl_acosh_emu(in float x) {\n" " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n" "}\n"); emu->addEmulatedFunction(EOpAcosh, float2, "float2 webgl_acosh_emu(in float2 x) {\n" " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n" "}\n"); emu->addEmulatedFunction(EOpAcosh, float3, "float3 webgl_acosh_emu(in float3 x) {\n" " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n" "}\n"); emu->addEmulatedFunction(EOpAcosh, float4, "float4 webgl_acosh_emu(in float4 x) {\n" " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n" "}\n"); emu->addEmulatedFunction(EOpAtanh, float1, "float webgl_atanh_emu(in float x) {\n" " return 0.5 * log((1.0 + x) / (1.0 - x));\n" "}\n"); emu->addEmulatedFunction(EOpAtanh, float2, "float2 webgl_atanh_emu(in float2 x) {\n" " return 0.5 * log((1.0 + x) / (1.0 - x));\n" "}\n"); emu->addEmulatedFunction(EOpAtanh, float3, "float3 webgl_atanh_emu(in float3 x) {\n" " return 0.5 * log((1.0 + x) / (1.0 - x));\n" "}\n"); emu->addEmulatedFunction(EOpAtanh, float4, "float4 webgl_atanh_emu(in float4 x) {\n" " return 0.5 * log((1.0 + x) / (1.0 - x));\n" "}\n"); emu->addEmulatedFunction(EOpRoundEven, float1, "float webgl_roundEven_emu(in float x) {\n" " return (frac(x) == 0.5 && trunc(x) % 2.0 == 0.0) ? trunc(x) : round(x);\n" "}\n"); emu->addEmulatedFunction(EOpRoundEven, float2, "float2 webgl_roundEven_emu(in float2 x) {\n" " float2 v;\n" " v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);\n" " v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);\n" " return v;\n" "}\n"); emu->addEmulatedFunction(EOpRoundEven, float3, "float3 webgl_roundEven_emu(in float3 x) {\n" " float3 v;\n" " v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);\n" " v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);\n" " v[2] = (frac(x[2]) == 0.5 && trunc(x[2]) % 2.0 == 0.0) ? trunc(x[2]) : round(x[2]);\n" " return v;\n" "}\n"); emu->addEmulatedFunction(EOpRoundEven, float4, "float4 webgl_roundEven_emu(in float4 x) {\n" " float4 v;\n" " v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);\n" " v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);\n" " v[2] = (frac(x[2]) == 0.5 && trunc(x[2]) % 2.0 == 0.0) ? trunc(x[2]) : round(x[2]);\n" " v[3] = (frac(x[3]) == 0.5 && trunc(x[3]) % 2.0 == 0.0) ? trunc(x[3]) : round(x[3]);\n" " return v;\n" "}\n"); emu->addEmulatedFunction(EOpPackSnorm2x16, float2, "int webgl_toSnorm(in float x) {\n" " return int(round(clamp(x, -1.0, 1.0) * 32767.0));\n" "}\n" "\n" "uint webgl_packSnorm2x16_emu(in float2 v) {\n" " int x = webgl_toSnorm(v.x);\n" " int y = webgl_toSnorm(v.y);\n" " return (asuint(y) << 16) | (asuint(x) & 0xffffu);\n" "}\n"); emu->addEmulatedFunction(EOpPackUnorm2x16, float2, "uint webgl_toUnorm(in float x) {\n" " return uint(round(clamp(x, 0.0, 1.0) * 65535.0));\n" "}\n" "\n" "uint webgl_packUnorm2x16_emu(in float2 v) {\n" " uint x = webgl_toUnorm(v.x);\n" " uint y = webgl_toUnorm(v.y);\n" " return (y << 16) | x;\n" "}\n"); emu->addEmulatedFunction(EOpPackHalf2x16, float2, "uint webgl_packHalf2x16_emu(in float2 v) {\n" " uint x = f32tof16(v.x);\n" " uint y = f32tof16(v.y);\n" " return (y << 16) | x;\n" "}\n"); TType uint1(EbtUInt); emu->addEmulatedFunction(EOpUnpackSnorm2x16, uint1, "float webgl_fromSnorm(in uint x) {\n" " int xi = asint(x & 0x7fffu) - asint(x & 0x8000u);\n" " return clamp(float(xi) / 32767.0, -1.0, 1.0);\n" "}\n" "\n" "float2 webgl_unpackSnorm2x16_emu(in uint u) {\n" " uint y = (u >> 16);\n" " uint x = u;\n" " return float2(webgl_fromSnorm(x), webgl_fromSnorm(y));\n" "}\n"); emu->addEmulatedFunction(EOpUnpackUnorm2x16, uint1, "float webgl_fromUnorm(in uint x) {\n" " return float(x) / 65535.0;\n" "}\n" "\n" "float2 webgl_unpackUnorm2x16_emu(in uint u) {\n" " uint y = (u >> 16);\n" " uint x = u & 0xffffu;\n" " return float2(webgl_fromUnorm(x), webgl_fromUnorm(y));\n" "}\n"); emu->addEmulatedFunction(EOpUnpackHalf2x16, uint1, "float2 webgl_unpackHalf2x16_emu(in uint u) {\n" " uint y = (u >> 16);\n" " uint x = u & 0xffffu;\n" " return float2(f16tof32(x), f16tof32(y));\n" "}\n"); // The matrix resulting from outer product needs to be transposed // (matrices are stored as transposed to simplify element access in HLSL). // So the function should return transpose(c * r) where c is a column vector // and r is a row vector. This can be simplified by using the following // formula: // transpose(c * r) = transpose(r) * transpose(c) // transpose(r) and transpose(c) are in a sense free, since to get the // transpose of r, we simply can build a column matrix out of the original // vector instead of a row matrix. emu->addEmulatedFunction(EOpOuterProduct, float2, float2, "float2x2 webgl_outerProduct_emu(in float2 c, in float2 r) {\n" " return mul(float2x1(r), float1x2(c));\n" "}\n"); emu->addEmulatedFunction(EOpOuterProduct, float3, float3, "float3x3 webgl_outerProduct_emu(in float3 c, in float3 r) {\n" " return mul(float3x1(r), float1x3(c));\n" "}\n"); emu->addEmulatedFunction(EOpOuterProduct, float4, float4, "float4x4 webgl_outerProduct_emu(in float4 c, in float4 r) {\n" " return mul(float4x1(r), float1x4(c));\n" "}\n"); emu->addEmulatedFunction(EOpOuterProduct, float3, float2, "float2x3 webgl_outerProduct_emu(in float3 c, in float2 r) {\n" " return mul(float2x1(r), float1x3(c));\n" "}\n"); emu->addEmulatedFunction(EOpOuterProduct, float2, float3, "float3x2 webgl_outerProduct_emu(in float2 c, in float3 r) {\n" " return mul(float3x1(r), float1x2(c));\n" "}\n"); emu->addEmulatedFunction(EOpOuterProduct, float4, float2, "float2x4 webgl_outerProduct_emu(in float4 c, in float2 r) {\n" " return mul(float2x1(r), float1x4(c));\n" "}\n"); emu->addEmulatedFunction(EOpOuterProduct, float2, float4, "float4x2 webgl_outerProduct_emu(in float2 c, in float4 r) {\n" " return mul(float4x1(r), float1x2(c));\n" "}\n"); emu->addEmulatedFunction(EOpOuterProduct, float4, float3, "float3x4 webgl_outerProduct_emu(in float4 c, in float3 r) {\n" " return mul(float3x1(r), float1x4(c));\n" "}\n"); emu->addEmulatedFunction(EOpOuterProduct, float3, float4, "float4x3 webgl_outerProduct_emu(in float3 c, in float4 r) {\n" " return mul(float4x1(r), float1x3(c));\n" "}\n"); TType mat2(EbtFloat, 2, 2); TType mat3(EbtFloat, 3, 3); TType mat4(EbtFloat, 4, 4); // Remember here that the parameter matrix is actually the transpose // of the matrix that we're trying to invert, and the resulting matrix // should also be the transpose of the inverse. // When accessing the parameter matrix with m[a][b] it can be thought of so // that a is the column and b is the row of the matrix that we're inverting. // We calculate the inverse as the adjugate matrix divided by the // determinant of the matrix being inverted. However, as the result needs // to be transposed, we actually use of the transpose of the adjugate matrix // which happens to be the cofactor matrix. That's stored in "cof". // We don't need to care about divide-by-zero since results are undefined // for singular or poorly-conditioned matrices. emu->addEmulatedFunction(EOpInverse, mat2, "float2x2 webgl_inverse_emu(in float2x2 m) {\n" " float2x2 cof = { m[1][1], -m[0][1], -m[1][0], m[0][0] };\n" " return cof / determinant(transpose(m));\n" "}\n"); // cofAB is the cofactor for column A and row B. emu->addEmulatedFunction(EOpInverse, mat3, "float3x3 webgl_inverse_emu(in float3x3 m) {\n" " float cof00 = m[1][1] * m[2][2] - m[2][1] * m[1][2];\n" " float cof01 = -(m[1][0] * m[2][2] - m[2][0] * m[1][2]);\n" " float cof02 = m[1][0] * m[2][1] - m[2][0] * m[1][1];\n" " float cof10 = -(m[0][1] * m[2][2] - m[2][1] * m[0][2]);\n" " float cof11 = m[0][0] * m[2][2] - m[2][0] * m[0][2];\n" " float cof12 = -(m[0][0] * m[2][1] - m[2][0] * m[0][1]);\n" " float cof20 = m[0][1] * m[1][2] - m[1][1] * m[0][2];\n" " float cof21 = -(m[0][0] * m[1][2] - m[1][0] * m[0][2]);\n" " float cof22 = m[0][0] * m[1][1] - m[1][0] * m[0][1];\n" " float3x3 cof = { cof00, cof10, cof20, cof01, cof11, cof21, cof02, cof12, cof22 };\n" " return cof / determinant(transpose(m));\n" "}\n"); emu->addEmulatedFunction(EOpInverse, mat4, "float4x4 webgl_inverse_emu(in float4x4 m) {\n" " float cof00 = m[1][1] * m[2][2] * m[3][3] + m[2][1] * m[3][2] * m[1][3] + m[3][1] * m[1][2] * m[2][3]" " - m[1][1] * m[3][2] * m[2][3] - m[2][1] * m[1][2] * m[3][3] - m[3][1] * m[2][2] * m[1][3];\n" " float cof01 = -(m[1][0] * m[2][2] * m[3][3] + m[2][0] * m[3][2] * m[1][3] + m[3][0] * m[1][2] * m[2][3]" " - m[1][0] * m[3][2] * m[2][3] - m[2][0] * m[1][2] * m[3][3] - m[3][0] * m[2][2] * m[1][3]);\n" " float cof02 = m[1][0] * m[2][1] * m[3][3] + m[2][0] * m[3][1] * m[1][3] + m[3][0] * m[1][1] * m[2][3]" " - m[1][0] * m[3][1] * m[2][3] - m[2][0] * m[1][1] * m[3][3] - m[3][0] * m[2][1] * m[1][3];\n" " float cof03 = -(m[1][0] * m[2][1] * m[3][2] + m[2][0] * m[3][1] * m[1][2] + m[3][0] * m[1][1] * m[2][2]" " - m[1][0] * m[3][1] * m[2][2] - m[2][0] * m[1][1] * m[3][2] - m[3][0] * m[2][1] * m[1][2]);\n" " float cof10 = -(m[0][1] * m[2][2] * m[3][3] + m[2][1] * m[3][2] * m[0][3] + m[3][1] * m[0][2] * m[2][3]" " - m[0][1] * m[3][2] * m[2][3] - m[2][1] * m[0][2] * m[3][3] - m[3][1] * m[2][2] * m[0][3]);\n" " float cof11 = m[0][0] * m[2][2] * m[3][3] + m[2][0] * m[3][2] * m[0][3] + m[3][0] * m[0][2] * m[2][3]" " - m[0][0] * m[3][2] * m[2][3] - m[2][0] * m[0][2] * m[3][3] - m[3][0] * m[2][2] * m[0][3];\n" " float cof12 = -(m[0][0] * m[2][1] * m[3][3] + m[2][0] * m[3][1] * m[0][3] + m[3][0] * m[0][1] * m[2][3]" " - m[0][0] * m[3][1] * m[2][3] - m[2][0] * m[0][1] * m[3][3] - m[3][0] * m[2][1] * m[0][3]);\n" " float cof13 = m[0][0] * m[2][1] * m[3][2] + m[2][0] * m[3][1] * m[0][2] + m[3][0] * m[0][1] * m[2][2]" " - m[0][0] * m[3][1] * m[2][2] - m[2][0] * m[0][1] * m[3][2] - m[3][0] * m[2][1] * m[0][2];\n" " float cof20 = m[0][1] * m[1][2] * m[3][3] + m[1][1] * m[3][2] * m[0][3] + m[3][1] * m[0][2] * m[1][3]" " - m[0][1] * m[3][2] * m[1][3] - m[1][1] * m[0][2] * m[3][3] - m[3][1] * m[1][2] * m[0][3];\n" " float cof21 = -(m[0][0] * m[1][2] * m[3][3] + m[1][0] * m[3][2] * m[0][3] + m[3][0] * m[0][2] * m[1][3]" " - m[0][0] * m[3][2] * m[1][3] - m[1][0] * m[0][2] * m[3][3] - m[3][0] * m[1][2] * m[0][3]);\n" " float cof22 = m[0][0] * m[1][1] * m[3][3] + m[1][0] * m[3][1] * m[0][3] + m[3][0] * m[0][1] * m[1][3]" " - m[0][0] * m[3][1] * m[1][3] - m[1][0] * m[0][1] * m[3][3] - m[3][0] * m[1][1] * m[0][3];\n" " float cof23 = -(m[0][0] * m[1][1] * m[3][2] + m[1][0] * m[3][1] * m[0][2] + m[3][0] * m[0][1] * m[1][2]" " - m[0][0] * m[3][1] * m[1][2] - m[1][0] * m[0][1] * m[3][2] - m[3][0] * m[1][1] * m[0][2]);\n" " float cof30 = -(m[0][1] * m[1][2] * m[2][3] + m[1][1] * m[2][2] * m[0][3] + m[2][1] * m[0][2] * m[1][3]" " - m[0][1] * m[2][2] * m[1][3] - m[1][1] * m[0][2] * m[2][3] - m[2][1] * m[1][2] * m[0][3]);\n" " float cof31 = m[0][0] * m[1][2] * m[2][3] + m[1][0] * m[2][2] * m[0][3] + m[2][0] * m[0][2] * m[1][3]" " - m[0][0] * m[2][2] * m[1][3] - m[1][0] * m[0][2] * m[2][3] - m[2][0] * m[1][2] * m[0][3];\n" " float cof32 = -(m[0][0] * m[1][1] * m[2][3] + m[1][0] * m[2][1] * m[0][3] + m[2][0] * m[0][1] * m[1][3]" " - m[0][0] * m[2][1] * m[1][3] - m[1][0] * m[0][1] * m[2][3] - m[2][0] * m[1][1] * m[0][3]);\n" " float cof33 = m[0][0] * m[1][1] * m[2][2] + m[1][0] * m[2][1] * m[0][2] + m[2][0] * m[0][1] * m[1][2]" " - m[0][0] * m[2][1] * m[1][2] - m[1][0] * m[0][1] * m[2][2] - m[2][0] * m[1][1] * m[0][2];\n" " float4x4 cof = { cof00, cof10, cof20, cof30, cof01, cof11, cof21, cof31," " cof02, cof12, cof22, cof32, cof03, cof13, cof23, cof33 };\n" " return cof / determinant(transpose(m));\n" "}\n"); }
void MCStack::effectrect(const MCRectangle& p_area, Boolean& r_abort) { // Get the list of effects. MCEffectList *t_effects = MCcur_effects; MCcur_effects = NULL; // If the window isn't opened or hasn't been attached (plugin) or if we have no // snapshot to use, this is a no-op. if (!opened || !haswindow() || m_snapshot == nil) { while(t_effects != NULL) { MCEffectList *t_effect; t_effect = t_effects; t_effects = t_effects -> next; delete t_effect; } return; } // Mark the stack as being in an effect. state |= CS_EFFECT; // Lock messages while the effect is happening. Boolean t_old_lockmessages; t_old_lockmessages = MClockmessages; MClockmessages = True; // Calculate the area of interest. MCRectangle t_effect_area; t_effect_area = curcard -> getrect(); t_effect_area . y = getscroll(); t_effect_area . height -= t_effect_area . y; t_effect_area = MCU_intersect_rect(t_effect_area, p_area); // IM-2013-08-21: [[ ResIndependence ]] Scale effect area to device coords // Align snapshot rect to device pixels // IM-2013-09-30: [[ FullscreenMode ]] Use stack transform to get device coords MCGAffineTransform t_transform; t_transform = getdevicetransform(); // MW-2013-10-29: [[ Bug 11330 ]] Make sure the effect area is cropped to the visible // area. t_effect_area = MCRectangleGetTransformedBounds(t_effect_area, getviewtransform()); t_effect_area = MCU_intersect_rect(t_effect_area, MCU_make_rect(0, 0, view_getrect() . width, view_getrect() . height)); // IM-2014-01-24: [[ HiDPI ]] scale effect region to backing surface coords MCGFloat t_scale; t_scale = view_getbackingscale(); MCRectangle t_device_rect, t_user_rect; t_device_rect = MCRectangleGetScaledBounds(t_effect_area, t_scale); t_user_rect = MCRectangleGetTransformedBounds(t_device_rect, MCGAffineTransformInvert(t_transform)); // IM-2013-08-29: [[ RefactorGraphics ]] get device height for CoreImage effects // IM-2013-09-30: [[ FullscreenMode ]] Use view rect to get device height uint32_t t_device_height; t_device_height = floor(view_getrect().height * t_scale); // Make a region of the effect area // IM-2013-08-29: [[ ResIndependence ]] scale effect region to device coords MCRegionRef t_effect_region; t_effect_region = nil; /* UNCHECKED */ MCRegionCreate(t_effect_region); /* UNCHECKED */ MCRegionSetRect(t_effect_region, t_effect_area); #ifndef FEATURE_PLATFORM_PLAYER #if defined(FEATURE_QUICKTIME) // MW-2010-07-07: Make sure QT is only loaded if we actually are doing an effect if (t_effects != nil) if (!MCdontuseQTeffects) if (!MCtemplateplayer -> isQTinitted()) MCtemplateplayer -> initqt(); #endif #endif // Lock the screen to prevent any updates occuring until we want them. MCRedrawLockScreen(); // By default, we have not aborted. r_abort = False; MCGImageRef t_initial_image; t_initial_image = MCGImageRetain(m_snapshot); while(t_effects != nil) { uint32_t t_duration; t_duration = MCU_max(1, MCeffectrate / (t_effects -> speed - VE_VERY)); if (t_effects -> type == VE_DISSOLVE) t_duration *= 2; uint32_t t_delta; t_delta = 0; // Create surface at effect_area size. // Render into surface based on t_effects -> image MCGImageRef t_final_image = nil; // If this isn't a plain effect, then we must fetch first and last images. if (t_effects -> type != VE_PLAIN) { // Render the final image. MCGContextRef t_context = nil; // IM-2014-05-20: [[ GraphicsPerformance ]] Create opaque context for snapshot /* UNCHECKED */ MCGContextCreate(t_device_rect.width, t_device_rect.height, false, t_context); MCGContextTranslateCTM(t_context, -t_device_rect.x, -t_device_rect.y); // IM-2013-10-03: [[ FullscreenMode ]] Apply device transform to context MCGContextConcatCTM(t_context, t_transform); // Configure the context. MCGContextClipToRect(t_context, MCRectangleToMCGRectangle(t_user_rect)); // Render an appropriate image switch(t_effects -> image) { case VE_INVERSE: { MCContext *t_old_context = nil; /* UNCHECKED */ t_old_context = new MCGraphicsContext(t_context); curcard->draw(t_old_context, t_user_rect, false); delete t_old_context; MCGContextSetFillRGBAColor(t_context, 1.0, 1.0, 1.0, 1.0); MCGContextSetBlendMode(t_context, kMCGBlendModeDifference); MCGContextAddRectangle(t_context, MCRectangleToMCGRectangle(t_user_rect)); MCGContextFill(t_context); } break; case VE_BLACK: MCGContextSetFillRGBAColor(t_context, 0.0, 0.0, 0.0, 1.0); MCGContextAddRectangle(t_context, MCRectangleToMCGRectangle(t_user_rect)); MCGContextFill(t_context); break; case VE_WHITE: MCGContextSetFillRGBAColor(t_context, 1.0, 1.0, 1.0, 1.0); MCGContextAddRectangle(t_context, MCRectangleToMCGRectangle(t_user_rect)); MCGContextFill(t_context); break; case VE_GRAY: MCGContextSetFillRGBAColor(t_context, 0.5, 0.5, 0.5, 1.0); MCGContextAddRectangle(t_context, MCRectangleToMCGRectangle(t_user_rect)); MCGContextFill(t_context); break; default: { MCContext *t_old_context = nil; /* UNCHECKED */ t_old_context = new MCGraphicsContext(t_context); curcard->draw(t_old_context, t_user_rect, false); delete t_old_context; } } /* UNCHECKED */ MCGContextCopyImage(t_context, t_final_image); MCGContextRelease(t_context); } MCStackEffectContext t_context; t_context.delta = t_delta; t_context.duration = t_duration; t_context.effect = t_effects; t_context.effect_area = t_device_rect; t_context.initial_image = t_initial_image; t_context.final_image = t_final_image; // MW-2011-10-20: [[ Bug 9824 ]] Make sure dst point is correct. // Initialize the destination with the start image. view_platform_updatewindowwithcallback(t_effect_region, MCStackRenderInitial, &t_context); // If there is a sound, then start playing it. if (t_effects -> sound != NULL) { MCAudioClip *acptr; MCNewAutoNameRef t_sound; /* UNCHECKED */ MCNameCreate(t_effects->sound, &t_sound); if ((acptr = (MCAudioClip *)getobjname(CT_AUDIO_CLIP, *t_sound)) == NULL) { IO_handle stream; if ((stream = MCS_open(t_effects->sound, kMCOpenFileModeRead, True, False, 0)) != NULL) { acptr = new MCAudioClip; acptr->setdisposable(); if (!acptr->import(t_effects->sound, stream)) { delete acptr; acptr = NULL; } MCS_close(stream); } } if (acptr != NULL) { MCU_play_stop(); MCacptr = acptr; MCU_play(); #ifndef FEATURE_PLATFORM_AUDIO if (MCacptr != NULL) MCscreen->addtimer(MCacptr, MCM_internal, PLAY_RATE); #endif } if (MCscreen->wait((real8)MCsyncrate / 1000.0, False, True)) { r_abort = True; break; } } // Initialize CoreImage of QTEffects if needed. if (t_effects -> type != VE_PLAIN) { MCAutoPointer<char> t_name; /* UNCHECKED */ MCStringConvertToCString(t_effects -> name, &t_name); #ifdef _MAC_DESKTOP // IM-2013-08-29: [[ ResIndependence ]] use scaled effect rect for CI effects if (t_effects -> type == VE_UNDEFINED && MCCoreImageEffectBegin(*t_name, t_initial_image, t_final_image, t_device_rect, t_device_height, t_effects -> arguments)) t_effects -> type = VE_CIEFFECT; else #endif #ifdef FEATURE_QUICKTIME_EFFECTS // IM-2013-08-29: [[ ResIndependence ]] use scaled effect rect for QT effects if (t_effects -> type == VE_UNDEFINED && MCQTEffectBegin(t_effects -> type, *t_name, t_effects -> direction, t_initial_image, t_final_image, t_device_rect)) t_effects -> type = VE_QTEFFECT; #else ; #endif } // Run effect // Now perform the effect loop, but only if there is something to do. if (t_effects -> type != VE_PLAIN || old_blendlevel != blendlevel) { // Calculate timing parameters. double t_start_time; t_start_time = 0.0; for(;;) { t_context.delta = t_delta; Boolean t_drawn = False; view_platform_updatewindowwithcallback(t_effect_region, MCStackRenderEffect, &t_context); // Now redraw the window with the new image. // if (t_drawn) { MCscreen -> sync(getw()); } // Update the window's blendlevel (if needed) if (old_blendlevel != blendlevel) { float t_fraction = float(t_delta) / t_duration; setopacity(uint1((old_blendlevel * 255 + (float(blendlevel) - old_blendlevel) * 255 * t_fraction) / 100)); } // If the start time is zero, then start counting from here. if (t_start_time == 0.0) t_start_time = MCS_time(); // If we've reached the end of the transition, we are done. if (t_delta == t_duration) { #ifdef _ANDROID_MOBILE // MW-2011-12-12: [[ Bug 9907 ]] Make sure we let the screen sync at this point MCscreen -> wait(0.01, False, False); #endif break; } // Get the time now. double t_now; t_now = MCS_time(); // Compute the new delta value. uint32_t t_new_delta; t_new_delta = (uint32_t)ceil((t_now - t_start_time) * 1000.0); // If the new value is same as the old, then advance one step. if (t_new_delta == t_delta) t_delta = t_new_delta + 1; else t_delta = t_new_delta; // If the new delta is beyond the end point, set it to the end. if (t_delta > t_duration) t_delta = t_duration; // Wait until the next boundary, making sure we break for no reason // other than abort. if (MCscreen -> wait((t_start_time + (t_delta / 1000.0)) - t_now, False, False)) r_abort = True; // If we aborted, we render the final step and are thus done. if (r_abort) t_delta = t_duration; } } #ifdef _MAC_DESKTOP if (t_effects -> type == VE_CIEFFECT) MCCoreImageEffectEnd(); else #endif #ifdef FEATURE_QUICKTIME_EFFECTS if (t_effects -> type == VE_QTEFFECT) MCQTEffectEnd(); #endif // Free initial surface. MCGImageRelease(t_initial_image); // initial surface becomes final surface. t_initial_image = t_final_image; t_final_image = nil; // Move to the next effect. MCEffectList *t_current_effect; t_current_effect = t_effects; t_effects = t_effects -> next; delete t_current_effect; } // Make sure the pixmaps are freed and any dangling effects // are cleaned up. if (t_effects != NULL) { /* OVERHAUL - REVISIT: error cleanup needs revised */ MCGImageRelease(t_initial_image); // MCGSurfaceRelease(t_final_image); while(t_effects != NULL) { MCEffectList *t_current_effect; t_current_effect = t_effects; t_effects = t_effects -> next; delete t_current_effect; } } MCRegionDestroy(t_effect_region); MCGImageRelease(m_snapshot); m_snapshot = nil; m_snapshot = t_initial_image; // Unlock the screen. MCRedrawUnlockScreen(); // Unlock messages. MClockmessages = t_old_lockmessages; // Turn off effect mode. state &= ~CS_EFFECT; // The stack's blendlevel is now the new one. old_blendlevel = blendlevel; // Finally, mark the affected area of the stack for a redraw. dirtyrect(p_area); }