Exemplo n.º 1
0
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");
}
Exemplo n.º 3
0
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);
}