<commit_before>
/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "SkColorMatrixFilter.h"
#include "SkColorMatrix.h"
#include "SkColorPriv.h"
#include "SkUnPreMultiply.h"

static int32_t rowmul4(const int32_t array[], unsigned r, unsigned g,
                          unsigned b, unsigned a) {
    return array[0] * r + array[1] * g  + array[2] * b + array[3] * a + array[4];
}

static int32_t rowmul3(const int32_t array[], unsigned r, unsigned g,
                       unsigned b) {
    return array[0] * r + array[1] * g  + array[2] * b + array[4];
}

static void General(SkColorMatrixFilter::State* state,
                    unsigned r, unsigned g, unsigned b, unsigned a) {
    const int32_t* SK_RESTRICT array = state->fArray;
    const int shift = state->fShift;
    int32_t* SK_RESTRICT result = state->fResult;

    result[0] = rowmul4(&array[0], r, g, b, a) >> shift;
    result[1] = rowmul4(&array[5], r, g, b, a) >> shift;
    result[2] = rowmul4(&array[10], r, g, b, a) >> shift;
    result[3] = rowmul4(&array[15], r, g, b, a) >> shift;
}

static void General16(SkColorMatrixFilter::State* state,
                      unsigned r, unsigned g, unsigned b, unsigned a) {
    const int32_t* SK_RESTRICT array = state->fArray;
    int32_t* SK_RESTRICT result = state->fResult;

    result[0] = rowmul4(&array[0], r, g, b, a) >> 16;
    result[1] = rowmul4(&array[5], r, g, b, a) >> 16;
    result[2] = rowmul4(&array[10], r, g, b, a) >> 16;
    result[3] = rowmul4(&array[15], r, g, b, a) >> 16;
}

static void AffineAdd(SkColorMatrixFilter::State* state,
                      unsigned r, unsigned g, unsigned b, unsigned a) {
    const int32_t* SK_RESTRICT array = state->fArray;
    const int shift = state->fShift;
    int32_t* SK_RESTRICT result = state->fResult;

    result[0] = rowmul3(&array[0], r, g, b) >> shift;
    result[1] = rowmul3(&array[5], r, g, b) >> shift;
    result[2] = rowmul3(&array[10], r, g, b) >> shift;
    result[3] = a;
}

static void AffineAdd16(SkColorMatrixFilter::State* state,
                        unsigned r, unsigned g, unsigned b, unsigned a) {
    const int32_t* SK_RESTRICT array = state->fArray;
    int32_t* SK_RESTRICT result = state->fResult;

    result[0] = rowmul3(&array[0], r, g, b) >> 16;
    result[1] = rowmul3(&array[5], r, g, b) >> 16;
    result[2] = rowmul3(&array[10], r, g, b) >> 16;
    result[3] = a;
}

static void ScaleAdd(SkColorMatrixFilter::State* state,
                     unsigned r, unsigned g, unsigned b, unsigned a) {
    const int32_t* SK_RESTRICT array = state->fArray;
    const int shift = state->fShift;
    int32_t* SK_RESTRICT result = state->fResult;

    // cast to (int) to keep the expression signed for the shift
    result[0] = (array[0] * (int)r + array[4]) >> shift;
    result[1] = (array[6] * (int)g + array[9]) >> shift;
    result[2] = (array[12] * (int)b + array[14]) >> shift;
    result[3] = a;
}

static void ScaleAdd16(SkColorMatrixFilter::State* state,
                       unsigned r, unsigned g, unsigned b, unsigned a) {
    const int32_t* SK_RESTRICT array = state->fArray;
    int32_t* SK_RESTRICT result = state->fResult;

    // cast to (int) to keep the expression signed for the shift
    result[0] = (array[0] * (int)r + array[4]) >> 16;
    result[1] = (array[6] * (int)g + array[9]) >> 16;
    result[2] = (array[12] * (int)b + array[14]) >> 16;
    result[3] = a;
}

static void Add(SkColorMatrixFilter::State* state,
                unsigned r, unsigned g, unsigned b, unsigned a) {
    const int32_t* SK_RESTRICT array = state->fArray;
    const int shift = state->fShift;
    int32_t* SK_RESTRICT result = state->fResult;

    result[0] = r + (array[4] >> shift);
    result[1] = g + (array[9] >> shift);
    result[2] = b + (array[14] >> shift);
    result[3] = a;
}

static void Add16(SkColorMatrixFilter::State* state,
                  unsigned r, unsigned g, unsigned b, unsigned a) {
    const int32_t* SK_RESTRICT array = state->fArray;
    int32_t* SK_RESTRICT result = state->fResult;

    result[0] = r + (array[4] >> 16);
    result[1] = g + (array[9] >> 16);
    result[2] = b + (array[14] >> 16);
    result[3] = a;
}

#define kNO_ALPHA_FLAGS (SkColorFilter::kAlphaUnchanged_Flag |  \
                         SkColorFilter::kHasFilter16_Flag)

// src is [20] but some compilers won't accept __restrict__ on anything
// but an raw pointer or reference
void SkColorMatrixFilter::setup(const SkScalar* SK_RESTRICT src) {
    if (NULL == src) {
        fProc = NULL;   // signals identity
        fFlags  = kNO_ALPHA_FLAGS;
        // fState is undefined, but that is OK, since we shouldn't look at it
        return;
    }

    int32_t* SK_RESTRICT array = fState.fArray;

    int i;
    SkFixed max = 0;

    for (int i = 0; i < 20; i++) {
        SkFixed value = SkScalarToFixed(src[i]);
        array[i] = value;
        value = SkAbs32(value);
        max = SkMax32(max, value);
    }

    /*  All of fArray[] values must fit in 23 bits, to safely allow me to
        multiply them by 8bit unsigned values, and get a signed answer without
        overflow. This means clz needs to be 9 or bigger
    */
    int bits = SkCLZ(max);
    int32_t one = SK_Fixed1;

    fState.fShift = 16; // we are starting out as fixed 16.16
    if (bits < 9) {
        bits = 9 - bits;
        fState.fShift -= bits;
        for (i = 0; i < 20; i++) {
            array[i] >>= bits;
        }
        one >>= bits;
    }

    // check if we have to munge Alpha
    int32_t changesAlpha = (array[15] | array[16] | array[17] |
                            (array[18] - one) | array[19]);
    int32_t usesAlpha = (array[3] | array[8] | array[13]);
    bool shiftIs16 = (16 == fState.fShift);

    if (changesAlpha | usesAlpha) {
        fProc = shiftIs16 ? General16 : General;
        fFlags = changesAlpha ? 0 : SkColorFilter::kAlphaUnchanged_Flag;
    } else {
        fFlags = kNO_ALPHA_FLAGS;

        int32_t needsScale = (array[0] - one) |       // red axis
                             (array[6] - one) |       // green axis
                             (array[12] - one);       // blue axis

        int32_t needs3x3 =  array[1] | array[2] |     // red off-axis
                            array[5] | array[7] |     // green off-axis
                            array[10] | array[11];    // blue off-axis

        if (needs3x3) {
            fProc = shiftIs16 ? AffineAdd16 : AffineAdd;
        } else if (needsScale) {
            fProc = shiftIs16 ? ScaleAdd16 : ScaleAdd;
        } else if (array[4] | array[9] | array[14]) {   // needs add
            fProc = shiftIs16 ? Add16 : Add;
        } else {
            fProc = NULL;   // identity
        }
    }

    /*  preround our add values so we get a rounded shift. We do this after we
        analyze the array, so we don't miss the case where the caller has zeros
        which could make us accidentally take the General or Add case.
    */
    if (NULL != fProc) {
        int32_t add = 1 << (fState.fShift - 1);
        array[4] += add;
        array[9] += add;
        array[14] += add;
        array[19] += add;
    }
}

///////////////////////////////////////////////////////////////////////////////

static int32_t pin(int32_t value, int32_t max) {
    if (value < 0) {
        value = 0;
    }
    if (value > max) {
        value = max;
    }
    return value;
}

SkColorMatrixFilter::SkColorMatrixFilter() {
    this->setup(NULL);
}

SkColorMatrixFilter::SkColorMatrixFilter(const SkColorMatrix& cm) {
    this->setup(cm.fMat);
}

SkColorMatrixFilter::SkColorMatrixFilter(const SkScalar array[20]) {
    this->setup(array);
}

uint32_t SkColorMatrixFilter::getFlags() {
    return this->INHERITED::getFlags() | fFlags;
}

void SkColorMatrixFilter::filterSpan(const SkPMColor src[], int count,
                                     SkPMColor dst[]) {
    Proc proc = fProc;
    State* state = &fState;
    int32_t* SK_RESTRICT result = state->fResult;

    if (NULL == proc) {
        if (src != dst) {
            memcpy(dst, src, count * sizeof(SkPMColor));
        }
        return;
    }

    const SkUnPreMultiply::Scale* table = SkUnPreMultiply::GetScaleTable();

    for (int i = 0; i < count; i++) {
        SkPMColor c = src[i];

        unsigned r = SkGetPackedR32(c);
        unsigned g = SkGetPackedG32(c);
        unsigned b = SkGetPackedB32(c);
        unsigned a = SkGetPackedA32(c);

        // need our components to be un-premultiplied
        if (255 != a) {
            SkUnPreMultiply::Scale scale = table[a];
            r = SkUnPreMultiply::ApplyScale(scale, r);
            g = SkUnPreMultiply::ApplyScale(scale, g);
            b = SkUnPreMultiply::ApplyScale(scale, b);

            SkASSERT(r <= 255);
            SkASSERT(g <= 255);
            SkASSERT(b <= 255);
        }

        proc(state, r, g, b, a);

        r = pin(result[0], SK_R32_MASK);
        g = pin(result[1], SK_G32_MASK);
        b = pin(result[2], SK_B32_MASK);
        a = pin(result[3], SK_A32_MASK);
        // re-prepremultiply if needed
        if (255 != a) {
            int scale = SkAlpha255To256(a);
            r = SkAlphaMul(r, scale);
            g = SkAlphaMul(g, scale);
            b = SkAlphaMul(b, scale);
        }
        dst[i] = SkPackARGB32(a, r, g, b);
    }
}

void SkColorMatrixFilter::filterSpan16(const uint16_t src[], int count,
                                       uint16_t dst[]) {
    SkASSERT(fFlags & SkColorFilter::kHasFilter16_Flag);

    Proc   proc = fProc;
    State* state = &fState;
    int32_t* SK_RESTRICT result = state->fResult;

    if (NULL == proc) {
        if (src != dst) {
            memcpy(dst, src, count * sizeof(uint16_t));
        }
        return;
    }

    for (int i = 0; i < count; i++) {
        uint16_t c = src[i];

        // expand to 8bit components (since our matrix translate is 8bit biased
        unsigned r = SkPacked16ToR32(c);
        unsigned g = SkPacked16ToG32(c);
        unsigned b = SkPacked16ToB32(c);

        proc(state, r, g, b, 0);

        r = pin(result[0], SK_R32_MASK);
        g = pin(result[1], SK_G32_MASK);
        b = pin(result[2], SK_B32_MASK);

        // now packed it back down to 16bits (hmmm, could dither...)
        dst[i] = SkPack888ToRGB16(r, g, b);
    }
}

///////////////////////////////////////////////////////////////////////////////

void SkColorMatrixFilter::flatten(SkFlattenableWriteBuffer& buffer)  {
    this->INHERITED::flatten(buffer);

    buffer.writeFunctionPtr((void*)fProc);
    buffer.writeMul4(&fState, sizeof(fState));
    buffer.write32(fFlags);
}

SkFlattenable::Factory SkColorMatrixFilter::getFactory() { return CreateProc;  }

SkColorMatrixFilter::SkColorMatrixFilter(SkFlattenableReadBuffer& buffer)
        : INHERITED(buffer) {
    fProc = (Proc)buffer.readFunctionPtr();
    buffer.read(&fState, sizeof(fState));
    fFlags = buffer.readU32();
}

bool SkColorMatrixFilter::asColorMatrix(SkScalar matrix[20]) {
    int32_t* SK_RESTRICT array = fState.fArray;
    int unshift = 16 - fState.fShift;
    for (int i = 0; i < 20; i++) {
        matrix[i] = SkFixedToScalar(array[i] << unshift);
    }
    if (NULL != fProc) {
        // Undo the offset applied to the constant column in setup().
        SkFixed offset = 1 << (fState.fShift - 1);
        matrix[4] = SkFixedToScalar((array[4] - offset) << unshift);
        matrix[9] = SkFixedToScalar((array[9] - offset) << unshift);
        matrix[14] = SkFixedToScalar((array[14] - offset) << unshift);
        matrix[19] = SkFixedToScalar((array[19] - offset) << unshift);
    }
    return true;
}

SkFlattenable* SkColorMatrixFilter::CreateProc(SkFlattenableReadBuffer& buf) {
    return SkNEW_ARGS(SkColorMatrixFilter, (buf));
}

void SkColorMatrixFilter::setMatrix(const SkColorMatrix& matrix) {
    setup(matrix.fMat);
}

void SkColorMatrixFilter::setArray(const SkScalar array[20]) {
    setup(array);
}

SK_DEFINE_FLATTENABLE_REGISTRAR(SkColorMatrixFilter)
<commit_msg>Improve the quality of color matrix filters by using SkPremultiplyARGBInline. This is closer (but not exactly the same as) WebKit's implementation.<commit_after>
/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "SkColorMatrixFilter.h"
#include "SkColorMatrix.h"
#include "SkColorPriv.h"
#include "SkUnPreMultiply.h"

static int32_t rowmul4(const int32_t array[], unsigned r, unsigned g,
                          unsigned b, unsigned a) {
    return array[0] * r + array[1] * g  + array[2] * b + array[3] * a + array[4];
}

static int32_t rowmul3(const int32_t array[], unsigned r, unsigned g,
                       unsigned b) {
    return array[0] * r + array[1] * g  + array[2] * b + array[4];
}

static void General(SkColorMatrixFilter::State* state,
                    unsigned r, unsigned g, unsigned b, unsigned a) {
    const int32_t* SK_RESTRICT array = state->fArray;
    const int shift = state->fShift;
    int32_t* SK_RESTRICT result = state->fResult;

    result[0] = rowmul4(&array[0], r, g, b, a) >> shift;
    result[1] = rowmul4(&array[5], r, g, b, a) >> shift;
    result[2] = rowmul4(&array[10], r, g, b, a) >> shift;
    result[3] = rowmul4(&array[15], r, g, b, a) >> shift;
}

static void General16(SkColorMatrixFilter::State* state,
                      unsigned r, unsigned g, unsigned b, unsigned a) {
    const int32_t* SK_RESTRICT array = state->fArray;
    int32_t* SK_RESTRICT result = state->fResult;

    result[0] = rowmul4(&array[0], r, g, b, a) >> 16;
    result[1] = rowmul4(&array[5], r, g, b, a) >> 16;
    result[2] = rowmul4(&array[10], r, g, b, a) >> 16;
    result[3] = rowmul4(&array[15], r, g, b, a) >> 16;
}

static void AffineAdd(SkColorMatrixFilter::State* state,
                      unsigned r, unsigned g, unsigned b, unsigned a) {
    const int32_t* SK_RESTRICT array = state->fArray;
    const int shift = state->fShift;
    int32_t* SK_RESTRICT result = state->fResult;

    result[0] = rowmul3(&array[0], r, g, b) >> shift;
    result[1] = rowmul3(&array[5], r, g, b) >> shift;
    result[2] = rowmul3(&array[10], r, g, b) >> shift;
    result[3] = a;
}

static void AffineAdd16(SkColorMatrixFilter::State* state,
                        unsigned r, unsigned g, unsigned b, unsigned a) {
    const int32_t* SK_RESTRICT array = state->fArray;
    int32_t* SK_RESTRICT result = state->fResult;

    result[0] = rowmul3(&array[0], r, g, b) >> 16;
    result[1] = rowmul3(&array[5], r, g, b) >> 16;
    result[2] = rowmul3(&array[10], r, g, b) >> 16;
    result[3] = a;
}

static void ScaleAdd(SkColorMatrixFilter::State* state,
                     unsigned r, unsigned g, unsigned b, unsigned a) {
    const int32_t* SK_RESTRICT array = state->fArray;
    const int shift = state->fShift;
    int32_t* SK_RESTRICT result = state->fResult;

    // cast to (int) to keep the expression signed for the shift
    result[0] = (array[0] * (int)r + array[4]) >> shift;
    result[1] = (array[6] * (int)g + array[9]) >> shift;
    result[2] = (array[12] * (int)b + array[14]) >> shift;
    result[3] = a;
}

static void ScaleAdd16(SkColorMatrixFilter::State* state,
                       unsigned r, unsigned g, unsigned b, unsigned a) {
    const int32_t* SK_RESTRICT array = state->fArray;
    int32_t* SK_RESTRICT result = state->fResult;

    // cast to (int) to keep the expression signed for the shift
    result[0] = (array[0] * (int)r + array[4]) >> 16;
    result[1] = (array[6] * (int)g + array[9]) >> 16;
    result[2] = (array[12] * (int)b + array[14]) >> 16;
    result[3] = a;
}

static void Add(SkColorMatrixFilter::State* state,
                unsigned r, unsigned g, unsigned b, unsigned a) {
    const int32_t* SK_RESTRICT array = state->fArray;
    const int shift = state->fShift;
    int32_t* SK_RESTRICT result = state->fResult;

    result[0] = r + (array[4] >> shift);
    result[1] = g + (array[9] >> shift);
    result[2] = b + (array[14] >> shift);
    result[3] = a;
}

static void Add16(SkColorMatrixFilter::State* state,
                  unsigned r, unsigned g, unsigned b, unsigned a) {
    const int32_t* SK_RESTRICT array = state->fArray;
    int32_t* SK_RESTRICT result = state->fResult;

    result[0] = r + (array[4] >> 16);
    result[1] = g + (array[9] >> 16);
    result[2] = b + (array[14] >> 16);
    result[3] = a;
}

#define kNO_ALPHA_FLAGS (SkColorFilter::kAlphaUnchanged_Flag |  \
                         SkColorFilter::kHasFilter16_Flag)

// src is [20] but some compilers won't accept __restrict__ on anything
// but an raw pointer or reference
void SkColorMatrixFilter::setup(const SkScalar* SK_RESTRICT src) {
    if (NULL == src) {
        fProc = NULL;   // signals identity
        fFlags  = kNO_ALPHA_FLAGS;
        // fState is undefined, but that is OK, since we shouldn't look at it
        return;
    }

    int32_t* SK_RESTRICT array = fState.fArray;

    int i;
    SkFixed max = 0;

    for (int i = 0; i < 20; i++) {
        SkFixed value = SkScalarToFixed(src[i]);
        array[i] = value;
        value = SkAbs32(value);
        max = SkMax32(max, value);
    }

    /*  All of fArray[] values must fit in 23 bits, to safely allow me to
        multiply them by 8bit unsigned values, and get a signed answer without
        overflow. This means clz needs to be 9 or bigger
    */
    int bits = SkCLZ(max);
    int32_t one = SK_Fixed1;

    fState.fShift = 16; // we are starting out as fixed 16.16
    if (bits < 9) {
        bits = 9 - bits;
        fState.fShift -= bits;
        for (i = 0; i < 20; i++) {
            array[i] >>= bits;
        }
        one >>= bits;
    }

    // check if we have to munge Alpha
    int32_t changesAlpha = (array[15] | array[16] | array[17] |
                            (array[18] - one) | array[19]);
    int32_t usesAlpha = (array[3] | array[8] | array[13]);
    bool shiftIs16 = (16 == fState.fShift);

    if (changesAlpha | usesAlpha) {
        fProc = shiftIs16 ? General16 : General;
        fFlags = changesAlpha ? 0 : SkColorFilter::kAlphaUnchanged_Flag;
    } else {
        fFlags = kNO_ALPHA_FLAGS;

        int32_t needsScale = (array[0] - one) |       // red axis
                             (array[6] - one) |       // green axis
                             (array[12] - one);       // blue axis

        int32_t needs3x3 =  array[1] | array[2] |     // red off-axis
                            array[5] | array[7] |     // green off-axis
                            array[10] | array[11];    // blue off-axis

        if (needs3x3) {
            fProc = shiftIs16 ? AffineAdd16 : AffineAdd;
        } else if (needsScale) {
            fProc = shiftIs16 ? ScaleAdd16 : ScaleAdd;
        } else if (array[4] | array[9] | array[14]) {   // needs add
            fProc = shiftIs16 ? Add16 : Add;
        } else {
            fProc = NULL;   // identity
        }
    }

    /*  preround our add values so we get a rounded shift. We do this after we
        analyze the array, so we don't miss the case where the caller has zeros
        which could make us accidentally take the General or Add case.
    */
    if (NULL != fProc) {
        int32_t add = 1 << (fState.fShift - 1);
        array[4] += add;
        array[9] += add;
        array[14] += add;
        array[19] += add;
    }
}

///////////////////////////////////////////////////////////////////////////////

static int32_t pin(int32_t value, int32_t max) {
    if (value < 0) {
        value = 0;
    }
    if (value > max) {
        value = max;
    }
    return value;
}

SkColorMatrixFilter::SkColorMatrixFilter() {
    this->setup(NULL);
}

SkColorMatrixFilter::SkColorMatrixFilter(const SkColorMatrix& cm) {
    this->setup(cm.fMat);
}

SkColorMatrixFilter::SkColorMatrixFilter(const SkScalar array[20]) {
    this->setup(array);
}

uint32_t SkColorMatrixFilter::getFlags() {
    return this->INHERITED::getFlags() | fFlags;
}

void SkColorMatrixFilter::filterSpan(const SkPMColor src[], int count,
                                     SkPMColor dst[]) {
    Proc proc = fProc;
    State* state = &fState;
    int32_t* SK_RESTRICT result = state->fResult;

    if (NULL == proc) {
        if (src != dst) {
            memcpy(dst, src, count * sizeof(SkPMColor));
        }
        return;
    }

    const SkUnPreMultiply::Scale* table = SkUnPreMultiply::GetScaleTable();

    for (int i = 0; i < count; i++) {
        SkPMColor c = src[i];

        unsigned r = SkGetPackedR32(c);
        unsigned g = SkGetPackedG32(c);
        unsigned b = SkGetPackedB32(c);
        unsigned a = SkGetPackedA32(c);

        // need our components to be un-premultiplied
        if (255 != a) {
            SkUnPreMultiply::Scale scale = table[a];
            r = SkUnPreMultiply::ApplyScale(scale, r);
            g = SkUnPreMultiply::ApplyScale(scale, g);
            b = SkUnPreMultiply::ApplyScale(scale, b);

            SkASSERT(r <= 255);
            SkASSERT(g <= 255);
            SkASSERT(b <= 255);
        }

        proc(state, r, g, b, a);

        r = pin(result[0], SK_R32_MASK);
        g = pin(result[1], SK_G32_MASK);
        b = pin(result[2], SK_B32_MASK);
        a = pin(result[3], SK_A32_MASK);
        // re-prepremultiply if needed
        dst[i] = SkPremultiplyARGBInline(a, r, g, b);
    }
}

void SkColorMatrixFilter::filterSpan16(const uint16_t src[], int count,
                                       uint16_t dst[]) {
    SkASSERT(fFlags & SkColorFilter::kHasFilter16_Flag);

    Proc   proc = fProc;
    State* state = &fState;
    int32_t* SK_RESTRICT result = state->fResult;

    if (NULL == proc) {
        if (src != dst) {
            memcpy(dst, src, count * sizeof(uint16_t));
        }
        return;
    }

    for (int i = 0; i < count; i++) {
        uint16_t c = src[i];

        // expand to 8bit components (since our matrix translate is 8bit biased
        unsigned r = SkPacked16ToR32(c);
        unsigned g = SkPacked16ToG32(c);
        unsigned b = SkPacked16ToB32(c);

        proc(state, r, g, b, 0);

        r = pin(result[0], SK_R32_MASK);
        g = pin(result[1], SK_G32_MASK);
        b = pin(result[2], SK_B32_MASK);

        // now packed it back down to 16bits (hmmm, could dither...)
        dst[i] = SkPack888ToRGB16(r, g, b);
    }
}

///////////////////////////////////////////////////////////////////////////////

void SkColorMatrixFilter::flatten(SkFlattenableWriteBuffer& buffer)  {
    this->INHERITED::flatten(buffer);

    buffer.writeFunctionPtr((void*)fProc);
    buffer.writeMul4(&fState, sizeof(fState));
    buffer.write32(fFlags);
}

SkFlattenable::Factory SkColorMatrixFilter::getFactory() { return CreateProc;  }

SkColorMatrixFilter::SkColorMatrixFilter(SkFlattenableReadBuffer& buffer)
        : INHERITED(buffer) {
    fProc = (Proc)buffer.readFunctionPtr();
    buffer.read(&fState, sizeof(fState));
    fFlags = buffer.readU32();
}

bool SkColorMatrixFilter::asColorMatrix(SkScalar matrix[20]) {
    int32_t* SK_RESTRICT array = fState.fArray;
    int unshift = 16 - fState.fShift;
    for (int i = 0; i < 20; i++) {
        matrix[i] = SkFixedToScalar(array[i] << unshift);
    }
    if (NULL != fProc) {
        // Undo the offset applied to the constant column in setup().
        SkFixed offset = 1 << (fState.fShift - 1);
        matrix[4] = SkFixedToScalar((array[4] - offset) << unshift);
        matrix[9] = SkFixedToScalar((array[9] - offset) << unshift);
        matrix[14] = SkFixedToScalar((array[14] - offset) << unshift);
        matrix[19] = SkFixedToScalar((array[19] - offset) << unshift);
    }
    return true;
}

SkFlattenable* SkColorMatrixFilter::CreateProc(SkFlattenableReadBuffer& buf) {
    return SkNEW_ARGS(SkColorMatrixFilter, (buf));
}

void SkColorMatrixFilter::setMatrix(const SkColorMatrix& matrix) {
    setup(matrix.fMat);
}

void SkColorMatrixFilter::setArray(const SkScalar array[20]) {
    setup(array);
}

SK_DEFINE_FLATTENABLE_REGISTRAR(SkColorMatrixFilter)
<|endoftext|>


<commit_before>/*
 * ARMEmulator.cpp
 *
 *  Created on: Oct 10, 2015
 *      Author: anon
 */

#include "debug.h"
#include "ARMEmulator.h"
#include "ARMDisassembler.h"

using namespace std;
using namespace Register;
using namespace Disassembler;

namespace Emulator {
    ARMEmulator::ARMEmulator(ARMContext *context, Memory::AbstractMemory *memory, ARMMode mode, ARMVariants variant) :
		m_mode{mode}, m_contex{context}, m_memory{memory} {
			m_dis = new ARMDisassembler(variant);
			m_interpreter = new ARMInterpreter(*m_contex);
    }

    ARMEmulator::~ARMEmulator() {
    }

    void ARMEmulator::start(unsigned count) {
    	bool stop = false;
    	unsigned n_executed = 0;

    	uint32_t cur_pc = 0;
    	uint32_t cur_opcode = 0;
    	ARMMode cur_mode = m_mode;

    	m_contex->getRegister(ARM_REG_PC, cur_pc);

		while (!stop && n_executed < count) {
		    // 1. Fetch an instruction from main memory.
			m_memory->read_value(cur_pc, cur_opcode);

			// 2. Decode it.
			ARMInstruction ins = m_dis->disassemble(cur_opcode, cur_mode);
			LOG_INFO("Emulating instruction @ cur_pc=0x%.8x cur_opcode=0x%.8x string='%s' size=%d decoder='%s'",
			        cur_pc, cur_opcode, ins.toString().c_str(), ins.ins_size, ins.m_decoded_by.c_str());

			// 3. Execute the instruction.
			m_interpreter->execute(ins);

			// 4. Print the status of the registers.
			m_contex->dump();

			if (cur_pc == m_contex->PC()) {
				cur_pc += ins.ins_size / 8;
				m_contex->PC(cur_pc);
			}

			n_executed++;
		}
    }
}
<commit_msg>Removes overly verbose debug print<commit_after>/*
 * ARMEmulator.cpp
 *
 *  Created on: Oct 10, 2015
 *      Author: anon
 */

#include "debug.h"
#include "ARMEmulator.h"
#include "ARMDisassembler.h"

using namespace std;
using namespace Register;
using namespace Disassembler;

namespace Emulator {
    ARMEmulator::ARMEmulator(ARMContext *context, Memory::AbstractMemory *memory, ARMMode mode, ARMVariants variant) :
		m_mode{mode}, m_contex{context}, m_memory{memory} {
			m_dis = new ARMDisassembler(variant);
			m_interpreter = new ARMInterpreter(*m_contex);
    }

    ARMEmulator::~ARMEmulator() {
    }

    void ARMEmulator::start(unsigned count) {
    	bool stop = false;
    	unsigned n_executed = 0;

    	uint32_t cur_pc = 0;
    	uint32_t cur_opcode = 0;
    	ARMMode cur_mode = m_mode;

    	m_contex->getRegister(ARM_REG_PC, cur_pc);

		while (!stop && n_executed < count) {
		    // 1. Fetch an instruction from main memory.
			m_memory->read_value(cur_pc, cur_opcode);

			// 2. Decode it.
			ARMInstruction ins = m_dis->disassemble(cur_opcode, cur_mode);

			// 3. Execute the instruction.
			m_interpreter->execute(ins);

			// 4. Print the status of the registers.
			m_contex->dump();

			if (cur_pc == m_contex->PC()) {
				cur_pc += ins.ins_size / 8;
				m_contex->PC(cur_pc);
			}

			n_executed++;
		}
    }
}
<|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/

#include "qmljsscopeastpath.h"

#include "parser/qmljsast_p.h"

using namespace QmlJS;
using namespace AST;

ScopeAstPath::ScopeAstPath(Document::Ptr doc)
    : _doc(doc)
{
}

QList<Node *> ScopeAstPath::operator()(quint32 offset)
{
    _result.clear();
    _offset = offset;
    if (_doc)
        Node::accept(_doc->ast(), this);
    return _result;
}

void ScopeAstPath::accept(Node *node)
{ Node::acceptChild(node, this); }

bool ScopeAstPath::preVisit(Node *node)
{
    if (Statement *stmt = node->statementCast()) {
        return containsOffset(stmt->firstSourceLocation(), stmt->lastSourceLocation());
    } else if (ExpressionNode *exp = node->expressionCast()) {
        return containsOffset(exp->firstSourceLocation(), exp->lastSourceLocation());
    } else if (UiObjectMember *ui = node->uiObjectMemberCast()) {
        return containsOffset(ui->firstSourceLocation(), ui->lastSourceLocation());
    }
    return true;
}

bool ScopeAstPath::visit(UiPublicMember *node)
{
    if (node && node->statement && node->statement->kind == node->Kind_Block
            && containsOffset(node->statement->firstSourceLocation(),
                              node->statement->lastSourceLocation())) {
        _result.append(node);
        Node::accept(node->statement, this);
        return false;
    }
    return true;
}

bool ScopeAstPath::visit(UiScriptBinding *node)
{
    if (node && node->statement && node->statement->kind == node->Kind_Block
            && containsOffset(node->statement->firstSourceLocation(),
                              node->statement->lastSourceLocation()))
    {
        _result.append(node);
        Node::accept(node->statement, this);
        return false;
    }
    return true;
}

bool ScopeAstPath::visit(UiObjectDefinition *node)
{
    _result.append(node);
    Node::accept(node->initializer, this);
    return false;
}

bool ScopeAstPath::visit(UiObjectBinding *node)
{
    _result.append(node);
    Node::accept(node->initializer, this);
    return false;
}

bool ScopeAstPath::visit(FunctionDeclaration *node)
{
    return visit(static_cast<FunctionExpression *>(node));
}

bool ScopeAstPath::visit(FunctionExpression *node)
{
    Node::accept(node->formals, this);
    _result.append(node);
    Node::accept(node->body, this);
    return false;
}

bool ScopeAstPath::containsOffset(SourceLocation start, SourceLocation end)
{
    return _offset >= start.begin() && _offset <= end.end();
}
<commit_msg>QmlJS: Clean up ScopeAstPath visitor.<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/

#include "qmljsscopeastpath.h"

#include "parser/qmljsast_p.h"

using namespace QmlJS;
using namespace AST;

ScopeAstPath::ScopeAstPath(Document::Ptr doc)
    : _doc(doc)
{
}

QList<Node *> ScopeAstPath::operator()(quint32 offset)
{
    _result.clear();
    _offset = offset;
    if (_doc)
        accept(_doc->ast());
    return _result;
}

void ScopeAstPath::accept(Node *node)
{
    Node::accept(node, this);
}

bool ScopeAstPath::preVisit(Node *node)
{
    if (Statement *stmt = node->statementCast()) {
        return containsOffset(stmt->firstSourceLocation(), stmt->lastSourceLocation());
    } else if (ExpressionNode *exp = node->expressionCast()) {
        return containsOffset(exp->firstSourceLocation(), exp->lastSourceLocation());
    } else if (UiObjectMember *ui = node->uiObjectMemberCast()) {
        return containsOffset(ui->firstSourceLocation(), ui->lastSourceLocation());
    }
    return true;
}

bool ScopeAstPath::visit(UiPublicMember *node)
{
    if (node && node->statement && node->statement->kind == node->Kind_Block
            && containsOffset(node->statement->firstSourceLocation(),
                              node->statement->lastSourceLocation())) {
        _result.append(node);
        accept(node->statement);
        return false;
    }
    return true;
}

bool ScopeAstPath::visit(UiScriptBinding *node)
{
    if (node && node->statement && node->statement->kind == node->Kind_Block
            && containsOffset(node->statement->firstSourceLocation(),
                              node->statement->lastSourceLocation()))
    {
        _result.append(node);
        accept(node->statement);
        return false;
    }
    return true;
}

bool ScopeAstPath::visit(UiObjectDefinition *node)
{
    _result.append(node);
    accept(node->initializer);
    return false;
}

bool ScopeAstPath::visit(UiObjectBinding *node)
{
    _result.append(node);
    accept(node->initializer);
    return false;
}

bool ScopeAstPath::visit(FunctionDeclaration *node)
{
    return visit(static_cast<FunctionExpression *>(node));
}

bool ScopeAstPath::visit(FunctionExpression *node)
{
    accept(node->formals);
    _result.append(node);
    accept(node->body);
    return false;
}

bool ScopeAstPath::containsOffset(SourceLocation start, SourceLocation end)
{
    return _offset >= start.begin() && _offset <= end.end();
}
<|endoftext|>


<commit_before>#include "change_map.h"

#include "logconsole.h"
#include "entity_system.h"
#include "cli_normal_chat.h"
#include "srv_normal_chat.h"
#include "components/basic_info.h"
#include "whisper_char.h"

using namespace RoseCommon;
using namespace RoseCommon::Packet;

void Map::change_map_request(EntitySystem& entitySystem, Entity entity, const CliChangeMapReq&) {
    auto logger = Core::CLog::GetLogger(Core::log_type::GENERAL).lock();
    logger->trace("Map::change_map_request");
    logger->trace("entity {}", entity);
    entitySystem.send_to(entity, SrvChangeMapReply::create());
    const auto& basicInfo = entitySystem.get_component<Component::BasicInfo>(entity);
    Chat::send_whisper(entitySystem, entity, fmt::format("You are client {}", basicInfo.id));
    entitySystem.send_nearby_except_me(SrvPlayerChar::create());
    const auto& nearby_entities = entitySystem.get_nearby(entity);
    for (auto e : nearby_entities) {
        if (e != entity) {
        entitySystem.send_to(entity, SrvPlayerChar::create());
        }
    }
    if (const auto client_ptr = registry.try_get<const Component::Client>(entity)) {
        if (auto client = client_ptr->client.lock()) {
            client->set_logged_in();
        }
    }
}
<commit_msg>Update change_map.cpp<commit_after>#include "change_map.h"

#include "logconsole.h"
#include "entity_system.h"
#include "cli_normal_chat.h"
#include "srv_normal_chat.h"
#include "cli_change_map_req.h"
#include "components/basic_info.h"
#include "whisper_char.h"

using namespace RoseCommon;
using namespace RoseCommon::Packet;

void Map::change_map_request(EntitySystem& entitySystem, Entity entity, const CliChangeMapReq&) {
    auto logger = Core::CLog::GetLogger(Core::log_type::GENERAL).lock();
    logger->trace("Map::change_map_request");
    logger->trace("entity {}", entity);
    entitySystem.send_to(entity, SrvChangeMapReply::create());
    const auto& basicInfo = entitySystem.get_component<Component::BasicInfo>(entity);
    Chat::send_whisper(entitySystem, entity, fmt::format("You are client {}", basicInfo.id));
    entitySystem.send_nearby_except_me(SrvPlayerChar::create());
    const auto& nearby_entities = entitySystem.get_nearby(entity);
    for (auto e : nearby_entities) {
        if (e != entity) {
        entitySystem.send_to(entity, SrvPlayerChar::create());
        }
    }
    if (const auto client_ptr = registry.try_get<const Component::Client>(entity)) {
        if (auto client = client_ptr->client.lock()) {
            client->set_logged_in();
        }
    }
}
<|endoftext|>


<commit_before>#include "Ext.h"

#include "preprocessor/llvm_includes_start.h"
#include <llvm/IR/IntrinsicInst.h>
#include "preprocessor/llvm_includes_end.h"

#include "RuntimeManager.h"
#include "Memory.h"
#include "Type.h"
#include "Endianness.h"

namespace dev
{
namespace eth
{
namespace jit
{

Ext::Ext(RuntimeManager& _runtimeManager, Memory& _memoryMan):
	RuntimeHelper(_runtimeManager),
	m_memoryMan(_memoryMan)
{
	m_funcs = decltype(m_funcs)();
	m_argAllocas = decltype(m_argAllocas)();
	m_size = m_builder.CreateAlloca(Type::Size, nullptr, "env.size");
}

using FuncDesc = std::tuple<char const*, llvm::FunctionType*>;

llvm::FunctionType* getFunctionType(llvm::Type* _returnType, std::initializer_list<llvm::Type*> const& _argsTypes)
{
	return llvm::FunctionType::get(_returnType, llvm::ArrayRef<llvm::Type*>{_argsTypes.begin(), _argsTypes.size()}, false);
}

std::array<FuncDesc, sizeOf<EnvFunc>::value> const& getEnvFuncDescs()
{
	static std::array<FuncDesc, sizeOf<EnvFunc>::value> descs{{
		FuncDesc{"env_sload",   getFunctionType(Type::Void, {Type::EnvPtr, Type::WordPtr, Type::WordPtr})},
		FuncDesc{"env_sstore",  getFunctionType(Type::Void, {Type::EnvPtr, Type::WordPtr, Type::WordPtr})},
		FuncDesc{"env_sha3", getFunctionType(Type::Void, {Type::BytePtr, Type::Size, Type::WordPtr})},
		FuncDesc{"env_balance", getFunctionType(Type::Void, {Type::EnvPtr, Type::WordPtr, Type::WordPtr})},
		FuncDesc{"env_create", getFunctionType(Type::Void, {Type::EnvPtr, Type::GasPtr, Type::WordPtr, Type::BytePtr, Type::Size, Type::WordPtr})},
		FuncDesc{"env_call", getFunctionType(Type::Bool, {Type::EnvPtr, Type::GasPtr, Type::Gas, Type::WordPtr, Type::WordPtr, Type::BytePtr, Type::Size, Type::BytePtr, Type::Size, Type::WordPtr})},
		FuncDesc{"env_log", getFunctionType(Type::Void, {Type::EnvPtr, Type::BytePtr, Type::Size, Type::WordPtr, Type::WordPtr, Type::WordPtr, Type::WordPtr})},
		FuncDesc{"env_blockhash", getFunctionType(Type::Void, {Type::EnvPtr, Type::WordPtr, Type::WordPtr})},
		FuncDesc{"env_extcode", getFunctionType(Type::BytePtr, {Type::EnvPtr, Type::WordPtr, Type::Size->getPointerTo()})},
	}};

	return descs;
}

llvm::Function* createFunc(EnvFunc _id, llvm::Module* _module)
{
	auto&& desc = getEnvFuncDescs()[static_cast<size_t>(_id)];
	return llvm::Function::Create(std::get<1>(desc), llvm::Function::ExternalLinkage, std::get<0>(desc), _module);
}

llvm::Value* Ext::getArgAlloca()
{
	auto& a = m_argAllocas[m_argCounter];
	if (!a)
	{
		InsertPointGuard g{getBuilder()};
		auto allocaIt = getMainFunction()->front().begin();
		std::advance(allocaIt, m_argCounter); // Skip already created allocas
		getBuilder().SetInsertPoint(allocaIt);
		a = getBuilder().CreateAlloca(Type::Word, nullptr, {"a.", std::to_string(m_argCounter)});
	}
	++m_argCounter;
	return a;
}

llvm::Value* Ext::byPtr(llvm::Value* _value)
{
	auto a = getArgAlloca();
	getBuilder().CreateStore(_value, a);
	return a;
}

llvm::CallInst* Ext::createCall(EnvFunc _funcId, std::initializer_list<llvm::Value*> const& _args)
{
	auto& func = m_funcs[static_cast<size_t>(_funcId)];
	if (!func)
		func = createFunc(_funcId, getModule());

	m_argCounter = 0;
	return getBuilder().CreateCall(func, {_args.begin(), _args.size()});
}

llvm::Value* Ext::sload(llvm::Value* _index)
{
	auto ret = getArgAlloca();
	createCall(EnvFunc::sload, {getRuntimeManager().getEnvPtr(), byPtr(_index), ret}); // Uses native endianness
	return m_builder.CreateLoad(ret);
}

void Ext::sstore(llvm::Value* _index, llvm::Value* _value)
{
	createCall(EnvFunc::sstore, {getRuntimeManager().getEnvPtr(), byPtr(_index), byPtr(_value)}); // Uses native endianness
}

llvm::Value* Ext::calldataload(llvm::Value* _idx)
{
	auto ret = getArgAlloca();
	auto result = m_builder.CreateBitCast(ret, Type::BytePtr);

	auto callDataSize = getRuntimeManager().getCallDataSize();
	auto callDataSize64 = m_builder.CreateTrunc(callDataSize, Type::Size);
	auto idxValid = m_builder.CreateICmpULT(_idx, callDataSize);
	auto idx = m_builder.CreateTrunc(m_builder.CreateSelect(idxValid, _idx, callDataSize), Type::Size, "idx");

	auto end = m_builder.CreateNUWAdd(idx, m_builder.getInt64(32));
	end = m_builder.CreateSelect(m_builder.CreateICmpULE(end, callDataSize64), end, callDataSize64);
	auto copySize = m_builder.CreateNUWSub(end, idx);
	auto padSize = m_builder.CreateNUWSub(m_builder.getInt64(32), copySize);
	auto dataBegin = m_builder.CreateGEP(Type::Byte, getRuntimeManager().getCallData(), idx);
	m_builder.CreateMemCpy(result, dataBegin, copySize, 1);
	auto pad = m_builder.CreateGEP(Type::Byte, result, copySize);
	m_builder.CreateMemSet(pad, m_builder.getInt8(0), padSize, 1);

	return Endianness::toNative(m_builder, m_builder.CreateLoad(ret));
}

llvm::Value* Ext::balance(llvm::Value* _address)
{
	auto address = Endianness::toBE(m_builder, _address);
	auto ret = getArgAlloca();
	createCall(EnvFunc::balance, {getRuntimeManager().getEnvPtr(), byPtr(address), ret});
	return m_builder.CreateLoad(ret);
}

llvm::Value* Ext::blockhash(llvm::Value* _number)
{
	auto hash = getArgAlloca();
	createCall(EnvFunc::blockhash, {getRuntimeManager().getEnvPtr(), byPtr(_number), hash});
	hash =  m_builder.CreateLoad(hash);
	return Endianness::toNative(getBuilder(), hash);
}

llvm::Value* Ext::create(llvm::Value* _endowment, llvm::Value* _initOff, llvm::Value* _initSize)
{
	auto ret = getArgAlloca();
	auto begin = m_memoryMan.getBytePtr(_initOff);
	auto size = m_builder.CreateTrunc(_initSize, Type::Size, "size");
	createCall(EnvFunc::create, {getRuntimeManager().getEnvPtr(), getRuntimeManager().getGasPtr(), byPtr(_endowment), begin, size, ret});
	llvm::Value* address = m_builder.CreateLoad(ret);
	address = Endianness::toNative(m_builder, address);
	return address;
}

llvm::Value* Ext::call(llvm::Value* _callGas, llvm::Value* _receiveAddress, llvm::Value* _value, llvm::Value* _inOff, llvm::Value* _inSize, llvm::Value* _outOff, llvm::Value* _outSize, llvm::Value* _codeAddress)
{
	auto receiveAddress = Endianness::toBE(m_builder, _receiveAddress);
	auto inBeg = m_memoryMan.getBytePtr(_inOff);
	auto inSize = m_builder.CreateTrunc(_inSize, Type::Size, "in.size");
	auto outBeg = m_memoryMan.getBytePtr(_outOff);
	auto outSize = m_builder.CreateTrunc(_outSize, Type::Size, "out.size");
	auto codeAddress = Endianness::toBE(m_builder, _codeAddress);
	auto callGas = m_builder.CreateSelect(
			m_builder.CreateICmpULE(_callGas, m_builder.CreateZExt(Constant::gasMax, Type::Word)),
			m_builder.CreateTrunc(_callGas, Type::Gas),
			Constant::gasMax);
	auto ret = createCall(EnvFunc::call, {getRuntimeManager().getEnvPtr(), getRuntimeManager().getGasPtr(), callGas, byPtr(receiveAddress), byPtr(_value), inBeg, inSize, outBeg, outSize, byPtr(codeAddress)});
	return m_builder.CreateZExt(ret, Type::Word, "ret");
}

llvm::Value* Ext::sha3(llvm::Value* _inOff, llvm::Value* _inSize)
{
	auto begin = m_memoryMan.getBytePtr(_inOff);
	auto size = m_builder.CreateTrunc(_inSize, Type::Size, "size");
	auto ret = getArgAlloca();
	createCall(EnvFunc::sha3, {begin, size, ret});
	llvm::Value* hash = m_builder.CreateLoad(ret);
	hash = Endianness::toNative(m_builder, hash);
	return hash;
}

MemoryRef Ext::extcode(llvm::Value* _addr)
{
	auto addr = Endianness::toBE(m_builder, _addr);
	auto code = createCall(EnvFunc::extcode, {getRuntimeManager().getEnvPtr(), byPtr(addr), m_size});
	auto codeSize = m_builder.CreateLoad(m_size);
	auto codeSize256 = m_builder.CreateZExt(codeSize, Type::Word);
	return {code, codeSize256};
}

void Ext::log(llvm::Value* _memIdx, llvm::Value* _numBytes, std::array<llvm::Value*,4> const& _topics)
{
	auto begin = m_memoryMan.getBytePtr(_memIdx);
	auto size = m_builder.CreateTrunc(_numBytes, Type::Size, "size");
	llvm::Value* args[] = {getRuntimeManager().getEnvPtr(), begin, size, getArgAlloca(), getArgAlloca(), getArgAlloca(), getArgAlloca()};

	auto topicArgPtr = &args[3];
	for (auto&& topic : _topics)
	{
		if (topic)
			m_builder.CreateStore(Endianness::toBE(m_builder, topic), *topicArgPtr);
		else
			*topicArgPtr = llvm::ConstantPointerNull::get(Type::WordPtr);
		++topicArgPtr;
	}

	createCall(EnvFunc::log, {args[0], args[1], args[2], args[3], args[4], args[5], args[6]});  // TODO: use std::initializer_list<>
}

}
}
}
<commit_msg>Release aquired arg allocas in Ext::calldataload.<commit_after>#include "Ext.h"

#include "preprocessor/llvm_includes_start.h"
#include <llvm/IR/IntrinsicInst.h>
#include "preprocessor/llvm_includes_end.h"

#include "RuntimeManager.h"
#include "Memory.h"
#include "Type.h"
#include "Endianness.h"

namespace dev
{
namespace eth
{
namespace jit
{

Ext::Ext(RuntimeManager& _runtimeManager, Memory& _memoryMan):
	RuntimeHelper(_runtimeManager),
	m_memoryMan(_memoryMan)
{
	m_funcs = decltype(m_funcs)();
	m_argAllocas = decltype(m_argAllocas)();
	m_size = m_builder.CreateAlloca(Type::Size, nullptr, "env.size");
}

using FuncDesc = std::tuple<char const*, llvm::FunctionType*>;

llvm::FunctionType* getFunctionType(llvm::Type* _returnType, std::initializer_list<llvm::Type*> const& _argsTypes)
{
	return llvm::FunctionType::get(_returnType, llvm::ArrayRef<llvm::Type*>{_argsTypes.begin(), _argsTypes.size()}, false);
}

std::array<FuncDesc, sizeOf<EnvFunc>::value> const& getEnvFuncDescs()
{
	static std::array<FuncDesc, sizeOf<EnvFunc>::value> descs{{
		FuncDesc{"env_sload",   getFunctionType(Type::Void, {Type::EnvPtr, Type::WordPtr, Type::WordPtr})},
		FuncDesc{"env_sstore",  getFunctionType(Type::Void, {Type::EnvPtr, Type::WordPtr, Type::WordPtr})},
		FuncDesc{"env_sha3", getFunctionType(Type::Void, {Type::BytePtr, Type::Size, Type::WordPtr})},
		FuncDesc{"env_balance", getFunctionType(Type::Void, {Type::EnvPtr, Type::WordPtr, Type::WordPtr})},
		FuncDesc{"env_create", getFunctionType(Type::Void, {Type::EnvPtr, Type::GasPtr, Type::WordPtr, Type::BytePtr, Type::Size, Type::WordPtr})},
		FuncDesc{"env_call", getFunctionType(Type::Bool, {Type::EnvPtr, Type::GasPtr, Type::Gas, Type::WordPtr, Type::WordPtr, Type::BytePtr, Type::Size, Type::BytePtr, Type::Size, Type::WordPtr})},
		FuncDesc{"env_log", getFunctionType(Type::Void, {Type::EnvPtr, Type::BytePtr, Type::Size, Type::WordPtr, Type::WordPtr, Type::WordPtr, Type::WordPtr})},
		FuncDesc{"env_blockhash", getFunctionType(Type::Void, {Type::EnvPtr, Type::WordPtr, Type::WordPtr})},
		FuncDesc{"env_extcode", getFunctionType(Type::BytePtr, {Type::EnvPtr, Type::WordPtr, Type::Size->getPointerTo()})},
	}};

	return descs;
}

llvm::Function* createFunc(EnvFunc _id, llvm::Module* _module)
{
	auto&& desc = getEnvFuncDescs()[static_cast<size_t>(_id)];
	return llvm::Function::Create(std::get<1>(desc), llvm::Function::ExternalLinkage, std::get<0>(desc), _module);
}

llvm::Value* Ext::getArgAlloca()
{
	auto& a = m_argAllocas[m_argCounter];
	if (!a)
	{
		InsertPointGuard g{getBuilder()};
		auto allocaIt = getMainFunction()->front().begin();
		std::advance(allocaIt, m_argCounter); // Skip already created allocas
		getBuilder().SetInsertPoint(allocaIt);
		a = getBuilder().CreateAlloca(Type::Word, nullptr, {"a.", std::to_string(m_argCounter)});
	}
	++m_argCounter;
	return a;
}

llvm::Value* Ext::byPtr(llvm::Value* _value)
{
	auto a = getArgAlloca();
	getBuilder().CreateStore(_value, a);
	return a;
}

llvm::CallInst* Ext::createCall(EnvFunc _funcId, std::initializer_list<llvm::Value*> const& _args)
{
	auto& func = m_funcs[static_cast<size_t>(_funcId)];
	if (!func)
		func = createFunc(_funcId, getModule());

	m_argCounter = 0;
	return getBuilder().CreateCall(func, {_args.begin(), _args.size()});
}

llvm::Value* Ext::sload(llvm::Value* _index)
{
	auto ret = getArgAlloca();
	createCall(EnvFunc::sload, {getRuntimeManager().getEnvPtr(), byPtr(_index), ret}); // Uses native endianness
	return m_builder.CreateLoad(ret);
}

void Ext::sstore(llvm::Value* _index, llvm::Value* _value)
{
	createCall(EnvFunc::sstore, {getRuntimeManager().getEnvPtr(), byPtr(_index), byPtr(_value)}); // Uses native endianness
}

llvm::Value* Ext::calldataload(llvm::Value* _idx)
{
	auto ret = getArgAlloca();
	auto result = m_builder.CreateBitCast(ret, Type::BytePtr);

	auto callDataSize = getRuntimeManager().getCallDataSize();
	auto callDataSize64 = m_builder.CreateTrunc(callDataSize, Type::Size);
	auto idxValid = m_builder.CreateICmpULT(_idx, callDataSize);
	auto idx = m_builder.CreateTrunc(m_builder.CreateSelect(idxValid, _idx, callDataSize), Type::Size, "idx");

	auto end = m_builder.CreateNUWAdd(idx, m_builder.getInt64(32));
	end = m_builder.CreateSelect(m_builder.CreateICmpULE(end, callDataSize64), end, callDataSize64);
	auto copySize = m_builder.CreateNUWSub(end, idx);
	auto padSize = m_builder.CreateNUWSub(m_builder.getInt64(32), copySize);
	auto dataBegin = m_builder.CreateGEP(Type::Byte, getRuntimeManager().getCallData(), idx);
	m_builder.CreateMemCpy(result, dataBegin, copySize, 1);
	auto pad = m_builder.CreateGEP(Type::Byte, result, copySize);
	m_builder.CreateMemSet(pad, m_builder.getInt8(0), padSize, 1);

	m_argCounter = 0; // Release args allocas. TODO: This is a bad design
	return Endianness::toNative(m_builder, m_builder.CreateLoad(ret));
}

llvm::Value* Ext::balance(llvm::Value* _address)
{
	auto address = Endianness::toBE(m_builder, _address);
	auto ret = getArgAlloca();
	createCall(EnvFunc::balance, {getRuntimeManager().getEnvPtr(), byPtr(address), ret});
	return m_builder.CreateLoad(ret);
}

llvm::Value* Ext::blockhash(llvm::Value* _number)
{
	auto hash = getArgAlloca();
	createCall(EnvFunc::blockhash, {getRuntimeManager().getEnvPtr(), byPtr(_number), hash});
	hash =  m_builder.CreateLoad(hash);
	return Endianness::toNative(getBuilder(), hash);
}

llvm::Value* Ext::create(llvm::Value* _endowment, llvm::Value* _initOff, llvm::Value* _initSize)
{
	auto ret = getArgAlloca();
	auto begin = m_memoryMan.getBytePtr(_initOff);
	auto size = m_builder.CreateTrunc(_initSize, Type::Size, "size");
	createCall(EnvFunc::create, {getRuntimeManager().getEnvPtr(), getRuntimeManager().getGasPtr(), byPtr(_endowment), begin, size, ret});
	llvm::Value* address = m_builder.CreateLoad(ret);
	address = Endianness::toNative(m_builder, address);
	return address;
}

llvm::Value* Ext::call(llvm::Value* _callGas, llvm::Value* _receiveAddress, llvm::Value* _value, llvm::Value* _inOff, llvm::Value* _inSize, llvm::Value* _outOff, llvm::Value* _outSize, llvm::Value* _codeAddress)
{
	auto receiveAddress = Endianness::toBE(m_builder, _receiveAddress);
	auto inBeg = m_memoryMan.getBytePtr(_inOff);
	auto inSize = m_builder.CreateTrunc(_inSize, Type::Size, "in.size");
	auto outBeg = m_memoryMan.getBytePtr(_outOff);
	auto outSize = m_builder.CreateTrunc(_outSize, Type::Size, "out.size");
	auto codeAddress = Endianness::toBE(m_builder, _codeAddress);
	auto callGas = m_builder.CreateSelect(
			m_builder.CreateICmpULE(_callGas, m_builder.CreateZExt(Constant::gasMax, Type::Word)),
			m_builder.CreateTrunc(_callGas, Type::Gas),
			Constant::gasMax);
	auto ret = createCall(EnvFunc::call, {getRuntimeManager().getEnvPtr(), getRuntimeManager().getGasPtr(), callGas, byPtr(receiveAddress), byPtr(_value), inBeg, inSize, outBeg, outSize, byPtr(codeAddress)});
	return m_builder.CreateZExt(ret, Type::Word, "ret");
}

llvm::Value* Ext::sha3(llvm::Value* _inOff, llvm::Value* _inSize)
{
	auto begin = m_memoryMan.getBytePtr(_inOff);
	auto size = m_builder.CreateTrunc(_inSize, Type::Size, "size");
	auto ret = getArgAlloca();
	createCall(EnvFunc::sha3, {begin, size, ret});
	llvm::Value* hash = m_builder.CreateLoad(ret);
	hash = Endianness::toNative(m_builder, hash);
	return hash;
}

MemoryRef Ext::extcode(llvm::Value* _addr)
{
	auto addr = Endianness::toBE(m_builder, _addr);
	auto code = createCall(EnvFunc::extcode, {getRuntimeManager().getEnvPtr(), byPtr(addr), m_size});
	auto codeSize = m_builder.CreateLoad(m_size);
	auto codeSize256 = m_builder.CreateZExt(codeSize, Type::Word);
	return {code, codeSize256};
}

void Ext::log(llvm::Value* _memIdx, llvm::Value* _numBytes, std::array<llvm::Value*,4> const& _topics)
{
	auto begin = m_memoryMan.getBytePtr(_memIdx);
	auto size = m_builder.CreateTrunc(_numBytes, Type::Size, "size");
	llvm::Value* args[] = {getRuntimeManager().getEnvPtr(), begin, size, getArgAlloca(), getArgAlloca(), getArgAlloca(), getArgAlloca()};

	auto topicArgPtr = &args[3];
	for (auto&& topic : _topics)
	{
		if (topic)
			m_builder.CreateStore(Endianness::toBE(m_builder, topic), *topicArgPtr);
		else
			*topicArgPtr = llvm::ConstantPointerNull::get(Type::WordPtr);
		++topicArgPtr;
	}

	createCall(EnvFunc::log, {args[0], args[1], args[2], args[3], args[4], args[5], args[6]});  // TODO: use std::initializer_list<>
}

}
}
}
<|endoftext|>


<commit_before>#include "Node.h"
#include "NodePart.h"
#include "Animation.h"
#include "NodeAnimation.h"
#include "Keyframe.h"
#include "Material.h"
#include "Attributes.h"
#include "MeshPart.h"
#include "Mesh.h"
#include "Model.h"
#include "Reference.h"
#include "FileIO.h"
 #include "Reference.h"
namespace fbxconv {
namespace modeldata {
    static const char* getTextureUseString(const Material::Texture::Usage &textureUse) {
	switch(textureUse){
	case Material::Texture::Ambient:
		return "AMBIENT";
	case Material::Texture::Bump:
		return "BUMP";
	case Material::Texture::Diffuse:
		return "DIFFUSE";
	case Material::Texture::Emissive:
		return "EMISSIVE";
	case Material::Texture::None:
		return "NONE";
	case Material::Texture::Normal:
		return "NORMAL";
	case Material::Texture::Reflection:
		return "REFLECTION";
	case Material::Texture::Shininess:
		return "SHININESS";
	case Material::Texture::Specular:
		return "SPECULAR";
	case Material::Texture::Transparency:
		return "TRANSPARENCY";
	default:
		return "UNKNOWN";
	}
}
    static const char* getWrapModeUseString(const FbxFileTexture::EWrapMode &textureUse)
    {
        switch(textureUse){
        case FbxFileTexture::eRepeat:
            return "REPEAT";
        case FbxFileTexture::eClamp:
            return "CLAMP";
        default:
            return "UNKNOWN";
        }
    }
	void Model::writeBinary(FILE* file)
	{
        std::list<std::string> _bonenames;
        for (std::vector<Node *>::const_iterator itr = nodes.begin(); itr != nodes.end(); ++itr)
        {
            (*itr)->loadBoneNames(_bonenames);
        }
        for (std::vector<Node *>::const_iterator itr = nodes.begin(); itr != nodes.end(); ++itr)
        {
            bool skeleton=false;
            (*itr)->checkIsSkeleton(skeleton,_bonenames);
            (*itr)->setSkeleton(skeleton);
        }
		unsigned int size = meshes.size();
        if(size>0)
        {
            meshes[0]->object.fPosition = ftell(file);
        }
		write(size, file);
        // write mesh
		for(auto itr = meshes.begin(); itr != meshes.end(); itr++)
		{
			(*itr)->writeBinary(file);
		}

		// write material
	    size = materials.size();
        if(size>0)
        {
            materials[0]->object.fPosition = ftell(file);
        }
		write(size, file);
		for(auto itr = materials.begin(); itr != materials.end(); itr++)
		{
			(*itr)->writeBinary(file);
		}
		// node num
        size = nodes.size();
        if(size>0)
        {
            nodes[0]->object.fPosition = ftell(file);
        }
        write(size, file);
        for(auto itr = nodes.begin(); itr != nodes.end(); itr++)
        {
            (*itr)->writeBinary(file);
        }

		// animations
        write(size, file);
        for(auto itr : animations)
        {
            itr->object.fPosition = ftell(file);
            itr->writeBinary(file);
        }
	}

	void Mesh::writeBinary(FILE* file)
	{
		// attribute
		attributes.writeBinary(file);

		// write vertices
		if(vertices.size() > 0)
		{
			unsigned int size = vertices.size();
			write(size, file);
			write(&vertices[0],size,file);
		}
		else
		{
			write((unsigned int)0, file);
		}

		// write parts.
		unsigned int size = parts.size();
		write(size, file);
		for(auto itr = parts.begin(); itr != parts.end(); itr++)
		{
            (*itr)->writeBinary(file);

		}
	}
    void  MeshPart::writeBinary(FILE* file)
    {
        write(id, file);
        //aabb
        write((unsigned int)6, file);
        write(aabb, 6, file);
        // indices size
        unsigned int size = indices.size();
        write(size, file);
        // indices.
        for(auto itr1 = indices.begin(); itr1 != indices.end(); itr1++)
            write(*itr1,file);
    }
	void Attributes::writeBinary(FILE* file)
	{

		std::vector<MeshVertexAttrib> attribs;
		MeshVertexAttrib attrib;
        for (unsigned int i = 0; i < length(); i++)
        {
            std::string key = name(i);
            attrib = attributemap.find(key)->second;
            attribs.push_back(attrib);
            if(key == "VERTEX_ATTRIB_BLEND_INDEX")
            {
                break;
            }
        }
		unsigned int size = attribs.size();
        write(size, file);
        for( int i = 0 ; i < size ; i++ )
        {
            write(attribs[i].size, file);
            write(attribs[i].type, file);
            write(attribs[i].name, file);
        }
	}

	void Material::writeBinary(FILE* file)
	{
		write(id, file);
        write(diffuse.value, 3, file);
        write(ambient.value, 3, file);
        write(emissive.value, 3, file);
        write(opacity.value,file);
        write(specular.value, 3, file);
        write(shininess.value,file);
        unsigned int size = textures.size();
        write(size, file);
        for(auto itr = textures.begin(); itr != textures.end(); itr++)
        {
             write((*itr)->id, file);
             write((*itr)->path, file);
             write((*itr)->uvTranslation, 2, file);
             write((*itr)->uvScale, 2, file);
             std::string  wrapModeU=getWrapModeUseString((*itr)->wrapModeU);
             std::string  wrapModeV=getWrapModeUseString((*itr)->wrapModeV);
             std::string  type= getTextureUseString((*itr)->usage);
             write(type,file);
             write(wrapModeU,file);
             write(wrapModeV,file);
        }
	}

	void Node::writeBinary(FILE* file)
	{
		write(id, file);
        write(_skeleton, file);
        // rotation scale translation
        write(transforms, 16, file);
		//write(transform.scale, 3, file);
		//write(transform.translation, 3, file);
        // node part
        unsigned int partsSize = parts.size();
		write(partsSize,file);
		if(parts.size()>0)
		{
            for(int i = 0 ; i < parts.size() ; i++ )
            {
                NodePart* nodepart = parts[i];
                if(nodepart)
                {
                    if(nodepart->meshPart)
                    {
                        //meshpartid
                        write(nodepart->meshPart->id, file);
                    }
                    else
                    {
                         write("null", file);
                    }
                    //materialid
                    if(nodepart->material)
                    {
                        write(nodepart->material->id, file);
                    }
                    else
                    {
                         write("null", file);
                    }
                    // bone num
                    unsigned int size = nodepart->bones.size();
                    write(size, file);
                    for(auto itr = nodepart->bones.begin(); itr != nodepart->bones.end(); itr++)
                    {
                        // write name
                        write(itr->first->id, file);
                        // write transform
                        float tmp[16];
                        for(int i = 0; i < 4; i++)
                        {
                            for(int j = 0; j < 4; j++)
                            {
                                tmp[i*4 + j] = itr->second.Double44()[i][j];
                            }
                        }
                        write(tmp, 16, file);
                    }
                    // uvMapping
                    size = nodepart->uvMapping.size();
                    write(size, file);
                    for(auto itr = nodepart->uvMapping.begin(); itr != nodepart->uvMapping.end(); itr++)
                    {
                        unsigned int size = itr->size();
                        write(size, file);
                        //TextureIndex
                        for (auto tt = (*itr).begin(); tt != (*itr).end(); ++tt)
                        {
                            unsigned int index = nodepart->material->getTextureIndex(*tt);
                            write(index, file);
                        }
                    }
                }
            }
		}
        // children
        unsigned int childrenSize = children.size();
        write(childrenSize,file);
		for(auto itr = children.begin(); itr != children.end(); itr++)
		{
			Node* node = *itr;
            if(node)
            {
                node->writeBinary(file);
            }
		}
	}
	void Animation::writeBinary(FILE* file)
	{
	    write(id, file);
		write(length, file);
		write(static_cast<unsigned int>(nodeAnimations.size()), file);

		for(auto itr = nodeAnimations.begin(); itr != nodeAnimations.end(); itr++)
		{
			NodeAnimation* nodeanim = *itr;
			write(nodeanim->node->id, file);

			write(static_cast<unsigned int>(nodeanim->keyframes.size()), file);

			for(auto itr1 = nodeanim->keyframes.begin(); itr1 != nodeanim->keyframes.end(); itr1++)
			{
				Keyframe* keyframe = *itr1;

				// write time
				write(keyframe->time, file);

                // write transform flag
                unsigned char transformflag(0);
                if (keyframe->hasRotation)
                    transformflag |= 0x01;
                if (keyframe->hasScale)
                    transformflag |= (0x01 << 1);
                if (keyframe->hasTranslation)
                    transformflag |= (0x01 << 2);

                write(transformflag, file);

                // write rotation val
                if (keyframe->hasRotation)
                    write(keyframe->rotation, 4, file);

                // write scale val
                if (keyframe->hasScale)
                    write(keyframe->scale, 3, file);

                // write translation val
                if (keyframe->hasTranslation)
                    write(keyframe->translation, 3, file);
			}
		}
    }
}
}<commit_msg>change AABB write order<commit_after>#include "Node.h"
#include "NodePart.h"
#include "Animation.h"
#include "NodeAnimation.h"
#include "Keyframe.h"
#include "Material.h"
#include "Attributes.h"
#include "MeshPart.h"
#include "Mesh.h"
#include "Model.h"
#include "Reference.h"
#include "FileIO.h"
 #include "Reference.h"
namespace fbxconv {
namespace modeldata {
    static const char* getTextureUseString(const Material::Texture::Usage &textureUse) {
	switch(textureUse){
	case Material::Texture::Ambient:
		return "AMBIENT";
	case Material::Texture::Bump:
		return "BUMP";
	case Material::Texture::Diffuse:
		return "DIFFUSE";
	case Material::Texture::Emissive:
		return "EMISSIVE";
	case Material::Texture::None:
		return "NONE";
	case Material::Texture::Normal:
		return "NORMAL";
	case Material::Texture::Reflection:
		return "REFLECTION";
	case Material::Texture::Shininess:
		return "SHININESS";
	case Material::Texture::Specular:
		return "SPECULAR";
	case Material::Texture::Transparency:
		return "TRANSPARENCY";
	default:
		return "UNKNOWN";
	}
}
    static const char* getWrapModeUseString(const FbxFileTexture::EWrapMode &textureUse)
    {
        switch(textureUse){
        case FbxFileTexture::eRepeat:
            return "REPEAT";
        case FbxFileTexture::eClamp:
            return "CLAMP";
        default:
            return "UNKNOWN";
        }
    }
	void Model::writeBinary(FILE* file)
	{
        std::list<std::string> _bonenames;
        for (std::vector<Node *>::const_iterator itr = nodes.begin(); itr != nodes.end(); ++itr)
        {
            (*itr)->loadBoneNames(_bonenames);
        }
        for (std::vector<Node *>::const_iterator itr = nodes.begin(); itr != nodes.end(); ++itr)
        {
            bool skeleton=false;
            (*itr)->checkIsSkeleton(skeleton,_bonenames);
            (*itr)->setSkeleton(skeleton);
        }
		unsigned int size = meshes.size();
        if(size>0)
        {
            meshes[0]->object.fPosition = ftell(file);
        }
		write(size, file);
        // write mesh
		for(auto itr = meshes.begin(); itr != meshes.end(); itr++)
		{
			(*itr)->writeBinary(file);
		}

		// write material
	    size = materials.size();
        if(size>0)
        {
            materials[0]->object.fPosition = ftell(file);
        }
		write(size, file);
		for(auto itr = materials.begin(); itr != materials.end(); itr++)
		{
			(*itr)->writeBinary(file);
		}
		// node num
        size = nodes.size();
        if(size>0)
        {
            nodes[0]->object.fPosition = ftell(file);
        }
        write(size, file);
        for(auto itr = nodes.begin(); itr != nodes.end(); itr++)
        {
            (*itr)->writeBinary(file);
        }

		// animations
        write(size, file);
        for(auto itr : animations)
        {
            itr->object.fPosition = ftell(file);
            itr->writeBinary(file);
        }
	}

	void Mesh::writeBinary(FILE* file)
	{
		// attribute
		attributes.writeBinary(file);

		// write vertices
		if(vertices.size() > 0)
		{
			unsigned int size = vertices.size();
			write(size, file);
			write(&vertices[0],size,file);
		}
		else
		{
			write((unsigned int)0, file);
		}

		// write parts.
		unsigned int size = parts.size();
		write(size, file);
		for(auto itr = parts.begin(); itr != parts.end(); itr++)
		{
            (*itr)->writeBinary(file);

		}
	}
    void  MeshPart::writeBinary(FILE* file)
    {
        write(id, file);
        // indices size
        unsigned int size = indices.size();
        write(size, file);
        // indices.
        for(auto itr1 = indices.begin(); itr1 != indices.end(); itr1++)
            write(*itr1,file);
        //aabb
        write(aabb, 6, file);
    }
	void Attributes::writeBinary(FILE* file)
	{

		std::vector<MeshVertexAttrib> attribs;
		MeshVertexAttrib attrib;
        for (unsigned int i = 0; i < length(); i++)
        {
            std::string key = name(i);
            attrib = attributemap.find(key)->second;
            attribs.push_back(attrib);
            if(key == "VERTEX_ATTRIB_BLEND_INDEX")
            {
                break;
            }
        }
		unsigned int size = attribs.size();
        write(size, file);
        for( int i = 0 ; i < size ; i++ )
        {
            write(attribs[i].size, file);
            write(attribs[i].type, file);
            write(attribs[i].name, file);
        }
	}

	void Material::writeBinary(FILE* file)
	{
		write(id, file);
        write(diffuse.value, 3, file);
        write(ambient.value, 3, file);
        write(emissive.value, 3, file);
        write(opacity.value,file);
        write(specular.value, 3, file);
        write(shininess.value,file);
        unsigned int size = textures.size();
        write(size, file);
        for(auto itr = textures.begin(); itr != textures.end(); itr++)
        {
             write((*itr)->id, file);
             write((*itr)->path, file);
             write((*itr)->uvTranslation, 2, file);
             write((*itr)->uvScale, 2, file);
             std::string  wrapModeU=getWrapModeUseString((*itr)->wrapModeU);
             std::string  wrapModeV=getWrapModeUseString((*itr)->wrapModeV);
             std::string  type= getTextureUseString((*itr)->usage);
             write(type,file);
             write(wrapModeU,file);
             write(wrapModeV,file);
        }
	}

	void Node::writeBinary(FILE* file)
	{
		write(id, file);
        write(_skeleton, file);
        // rotation scale translation
        write(transforms, 16, file);
		//write(transform.scale, 3, file);
		//write(transform.translation, 3, file);
        // node part
        unsigned int partsSize = parts.size();
		write(partsSize,file);
		if(parts.size()>0)
		{
            for(int i = 0 ; i < parts.size() ; i++ )
            {
                NodePart* nodepart = parts[i];
                if(nodepart)
                {
                    if(nodepart->meshPart)
                    {
                        //meshpartid
                        write(nodepart->meshPart->id, file);
                    }
                    else
                    {
                         write("null", file);
                    }
                    //materialid
                    if(nodepart->material)
                    {
                        write(nodepart->material->id, file);
                    }
                    else
                    {
                         write("null", file);
                    }
                    // bone num
                    unsigned int size = nodepart->bones.size();
                    write(size, file);
                    for(auto itr = nodepart->bones.begin(); itr != nodepart->bones.end(); itr++)
                    {
                        // write name
                        write(itr->first->id, file);
                        // write transform
                        float tmp[16];
                        for(int i = 0; i < 4; i++)
                        {
                            for(int j = 0; j < 4; j++)
                            {
                                tmp[i*4 + j] = itr->second.Double44()[i][j];
                            }
                        }
                        write(tmp, 16, file);
                    }
                    // uvMapping
                    size = nodepart->uvMapping.size();
                    write(size, file);
                    for(auto itr = nodepart->uvMapping.begin(); itr != nodepart->uvMapping.end(); itr++)
                    {
                        unsigned int size = itr->size();
                        write(size, file);
                        //TextureIndex
                        for (auto tt = (*itr).begin(); tt != (*itr).end(); ++tt)
                        {
                            unsigned int index = nodepart->material->getTextureIndex(*tt);
                            write(index, file);
                        }
                    }
                }
            }
		}
        // children
        unsigned int childrenSize = children.size();
        write(childrenSize,file);
		for(auto itr = children.begin(); itr != children.end(); itr++)
		{
			Node* node = *itr;
            if(node)
            {
                node->writeBinary(file);
            }
		}
	}
	void Animation::writeBinary(FILE* file)
	{
	    write(id, file);
		write(length, file);
		write(static_cast<unsigned int>(nodeAnimations.size()), file);

		for(auto itr = nodeAnimations.begin(); itr != nodeAnimations.end(); itr++)
		{
			NodeAnimation* nodeanim = *itr;
			write(nodeanim->node->id, file);

			write(static_cast<unsigned int>(nodeanim->keyframes.size()), file);

			for(auto itr1 = nodeanim->keyframes.begin(); itr1 != nodeanim->keyframes.end(); itr1++)
			{
				Keyframe* keyframe = *itr1;

				// write time
				write(keyframe->time, file);

                // write transform flag
                unsigned char transformflag(0);
                if (keyframe->hasRotation)
                    transformflag |= 0x01;
                if (keyframe->hasScale)
                    transformflag |= (0x01 << 1);
                if (keyframe->hasTranslation)
                    transformflag |= (0x01 << 2);

                write(transformflag, file);

                // write rotation val
                if (keyframe->hasRotation)
                    write(keyframe->rotation, 4, file);

                // write scale val
                if (keyframe->hasScale)
                    write(keyframe->scale, 3, file);

                // write translation val
                if (keyframe->hasTranslation)
                    write(keyframe->translation, 3, file);
			}
		}
    }
}
}<|endoftext|>


<commit_before>// Copyright (c) 2014 Ratcoin dev-team
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "processNetwork.h"

#include "common/nodesManager.h"
#include "common/communicationProtocol.h"
#include "common/actionHandler.h"

#include "common/nodeMedium.h"

#include "configureMonitorActionHandler.h"
#include "monitor/connectNodeAction.h"
#include "monitor/reputationTracer.h"
#include "monitor/monitorNodeMedium.h"

namespace monitor
{

CProcessNetwork * CProcessNetwork::ms_instance = NULL;

CProcessNetwork*
CProcessNetwork::getInstance()
{
	if ( !ms_instance )
	{
		ms_instance = new CProcessNetwork();
	};
	return ms_instance;
}

bool
CProcessNetwork::processMessage(common::CSelfNode* pfrom, CDataStream& vRecv)
{
	std::vector< common::CMessage > messages;
	vRecv >> messages;

// it is  stupid  to call this over and over again
	if ( !CReputationTracker::getInstance()->getMediumForNode( pfrom ) )
	{
		CReputationTracker::getInstance()->addNode( new CMonitorNodeMedium( pfrom ) );
	}

	BOOST_FOREACH( common::CMessage const & message, messages )
	{

		if (
				   message.m_header.m_payloadKind == common::CPayloadKind::RoleInfo
				|| message.m_header.m_payloadKind == common::CPayloadKind::Result
				|| message.m_header.m_payloadKind == common::CPayloadKind::NetworkInfo
				|| message.m_header.m_payloadKind == common::CPayloadKind::NetworkInfo
				)
		{
			common::CNodeMedium< MonitorResponses > * nodeMedium = CReputationTracker::getInstance()->getMediumForNode( pfrom );

			if ( common::CNetworkActionRegister::getInstance()->isServicedByAction( message.m_header.m_actionKey ) )
			{
				nodeMedium->setResponse( message.m_header.m_actionKey, common::CMessageResult( message, convertToInt( nodeMedium->getNode() ) ) );
			}
			else
			{
			}
		}
		/*	{
		CPubKey pubKey;
			if( !CTrackerNodesManager::getInstance()->getPublicKey( pfrom->addr, pubKey ) )
			{
				assert( !"for now assert this" );
				return true;
			}
		}*/
		else if ( message.m_header.m_payloadKind == common::CPayloadKind::InfoReq )
		{
			//
		}
		else if ( message.m_header.m_payloadKind == common::CPayloadKind::IntroductionReq )
		{
			common::CIdentifyMessage identifyMessage;
			convertPayload( message, identifyMessage );

			common::CNodeMedium< MonitorResponses > * nodeMedium = CReputationTracker::getInstance()->getMediumForNode( pfrom );

			if ( common::CNetworkActionRegister::getInstance()->isServicedByAction( message.m_header.m_actionKey ) )
			{
				nodeMedium->setResponse( message.m_header.m_actionKey, common::CIdentificationResult( identifyMessage.m_payload, identifyMessage.m_signed, identifyMessage.m_key, pfrom->addr  ) );
			}
			else
			{
				CConnectNodeAction * connectNodeAction= new CConnectNodeAction(
							  nodeMedium->getNode()->addr
							, message.m_header.m_actionKey
							, identifyMessage.m_payload
							, convertToInt( nodeMedium->getNode() ) );

				common::CActionHandler< MonitorResponses >::getInstance()->executeAction( connectNodeAction );
			}

		}
		else if (  message.m_header.m_payloadKind == common::CPayloadKind::Ack )
		{
			common::CAck ack;

			common::convertPayload( message, ack );

			common::CNodeMedium< MonitorResponses > * nodeMedium = CReputationTracker::getInstance()->getMediumForNode( pfrom );

			if ( common::CNetworkActionRegister::getInstance()->isServicedByAction( message.m_header.m_actionKey ) )
			{
				nodeMedium->setResponse( message.m_header.m_actionKey, common::CAckResult( convertToInt( nodeMedium->getNode() ) ) );
			}
		}
		else if ( message.m_header.m_payloadKind == common::CPayloadKind::Uninitiated )
		{
			//
		}
	}
	/*

*/
	return true;
}

bool
CProcessNetwork::sendMessages(common::CSelfNode* pto, bool fSendTrickle)
{
	pto->sendMessages();

	return true;
}

}

<commit_msg>info exchange<commit_after>// Copyright (c) 2014 Ratcoin dev-team
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "processNetwork.h"

#include "common/nodesManager.h"
#include "common/communicationProtocol.h"
#include "common/actionHandler.h"

#include "common/nodeMedium.h"

#include "configureMonitorActionHandler.h"
#include "monitor/connectNodeAction.h"
#include "monitor/reputationTracer.h"
#include "monitor/monitorNodeMedium.h"

namespace monitor
{

CProcessNetwork * CProcessNetwork::ms_instance = NULL;

CProcessNetwork*
CProcessNetwork::getInstance()
{
	if ( !ms_instance )
	{
		ms_instance = new CProcessNetwork();
	};
	return ms_instance;
}

bool
CProcessNetwork::processMessage(common::CSelfNode* pfrom, CDataStream& vRecv)
{
	std::vector< common::CMessage > messages;
	vRecv >> messages;

// it is  stupid  to call this over and over again
	if ( !CReputationTracker::getInstance()->getMediumForNode( pfrom ) )
	{
		CReputationTracker::getInstance()->addNode( new CMonitorNodeMedium( pfrom ) );
	}

	BOOST_FOREACH( common::CMessage const & message, messages )
	{

		if (
				   message.m_header.m_payloadKind == common::CPayloadKind::RoleInfo
				|| message.m_header.m_payloadKind == common::CPayloadKind::Result
				|| message.m_header.m_payloadKind == common::CPayloadKind::NetworkInfo
				|| message.m_header.m_payloadKind == common::CPayloadKind::InfoRes
				)
		{
			common::CNodeMedium< MonitorResponses > * nodeMedium = CReputationTracker::getInstance()->getMediumForNode( pfrom );

			if ( common::CNetworkActionRegister::getInstance()->isServicedByAction( message.m_header.m_actionKey ) )
			{
				nodeMedium->setResponse( message.m_header.m_actionKey, common::CMessageResult( message, convertToInt( nodeMedium->getNode() ) ) );
			}
			else
			{
			}
		}
		/*	{
		CPubKey pubKey;
			if( !CTrackerNodesManager::getInstance()->getPublicKey( pfrom->addr, pubKey ) )
			{
				assert( !"for now assert this" );
				return true;
			}
		}*/
		else if ( message.m_header.m_payloadKind == common::CPayloadKind::InfoReq )
		{
			//
		}
		else if ( message.m_header.m_payloadKind == common::CPayloadKind::IntroductionReq )
		{
			common::CIdentifyMessage identifyMessage;
			convertPayload( message, identifyMessage );

			common::CNodeMedium< MonitorResponses > * nodeMedium = CReputationTracker::getInstance()->getMediumForNode( pfrom );

			if ( common::CNetworkActionRegister::getInstance()->isServicedByAction( message.m_header.m_actionKey ) )
			{
				nodeMedium->setResponse( message.m_header.m_actionKey, common::CIdentificationResult( identifyMessage.m_payload, identifyMessage.m_signed, identifyMessage.m_key, pfrom->addr  ) );
			}
			else
			{
				CConnectNodeAction * connectNodeAction= new CConnectNodeAction(
							  nodeMedium->getNode()->addr
							, message.m_header.m_actionKey
							, identifyMessage.m_payload
							, convertToInt( nodeMedium->getNode() ) );

				common::CActionHandler< MonitorResponses >::getInstance()->executeAction( connectNodeAction );
			}

		}
		else if (  message.m_header.m_payloadKind == common::CPayloadKind::Ack )
		{
			common::CAck ack;

			common::convertPayload( message, ack );

			common::CNodeMedium< MonitorResponses > * nodeMedium = CReputationTracker::getInstance()->getMediumForNode( pfrom );

			if ( common::CNetworkActionRegister::getInstance()->isServicedByAction( message.m_header.m_actionKey ) )
			{
				nodeMedium->setResponse( message.m_header.m_actionKey, common::CAckResult( convertToInt( nodeMedium->getNode() ) ) );
			}
		}
		else if ( message.m_header.m_payloadKind == common::CPayloadKind::Uninitiated )
		{
			//
		}
	}
	/*

*/
	return true;
}

bool
CProcessNetwork::sendMessages(common::CSelfNode* pto, bool fSendTrickle)
{
	pto->sendMessages();

	return true;
}

}

<|endoftext|>