C++程序  |  146行  |  4.55 KB

/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


#include "rsdCore.h"
#include "rsdIntrinsics.h"
#include "rsdAllocation.h"

#include "rsdIntrinsicInlines.h"

using namespace android;
using namespace android::renderscript;

struct ConvolveParams {
    float fp[16];
    short ip[16];
    bool use3x3;
    bool useDot;
};

static void ColorMatrix_SetVar(const Context *dc, const Script *script, void * intrinsicData,
                               uint32_t slot, void *data, size_t dataLength) {
    ConvolveParams *cp = (ConvolveParams *)intrinsicData;

    rsAssert(slot == 0);
    memcpy (cp->fp, data, dataLength);
    for(int ct=0; ct < 16; ct++) {
        cp->ip[ct] = (short)(cp->fp[ct] * 255.f + 0.5f);
    }

    if ((cp->ip[3] == 0) && (cp->ip[7] == 0) && (cp->ip[11] == 0) &&
        (cp->ip[12] == 0) && (cp->ip[13] == 0) && (cp->ip[14] == 0) &&
        (cp->ip[15] == 255)) {
        cp->use3x3 = true;

        if ((cp->ip[0] == cp->ip[1]) && (cp->ip[0] == cp->ip[2]) &&
            (cp->ip[4] == cp->ip[5]) && (cp->ip[4] == cp->ip[6]) &&
            (cp->ip[8] == cp->ip[9]) && (cp->ip[8] == cp->ip[10])) {
            cp->useDot = true;
        }
    }
}

extern "C" void rsdIntrinsicColorMatrix4x4_K(void *dst, const void *src, const short *coef, uint32_t count);
extern "C" void rsdIntrinsicColorMatrix3x3_K(void *dst, const void *src, const short *coef, uint32_t count);
extern "C" void rsdIntrinsicColorMatrixDot_K(void *dst, const void *src, const short *coef, uint32_t count);

static void One(const RsForEachStubParamStruct *p, uchar4 *out,
                const uchar4 *py, const float* coeff) {
    float4 i = convert_float4(py[0]);

    float4 sum;
    sum.x = i.x * coeff[0] +
            i.y * coeff[4] +
            i.z * coeff[8] +
            i.w * coeff[12];
    sum.y = i.x * coeff[1] +
            i.y * coeff[5] +
            i.z * coeff[9] +
            i.w * coeff[13];
    sum.z = i.x * coeff[2] +
            i.y * coeff[6] +
            i.z * coeff[10] +
            i.w * coeff[14];
    sum.w = i.x * coeff[3] +
            i.y * coeff[7] +
            i.z * coeff[11] +
            i.w * coeff[15];

    sum.x = sum.x < 0 ? 0 : (sum.x > 255 ? 255 : sum.x);
    sum.y = sum.y < 0 ? 0 : (sum.y > 255 ? 255 : sum.y);
    sum.z = sum.z < 0 ? 0 : (sum.z > 255 ? 255 : sum.z);
    sum.w = sum.w < 0 ? 0 : (sum.w > 255 ? 255 : sum.w);

    *out = convert_uchar4(sum);
}

static void ColorMatrix_uchar4(const RsForEachStubParamStruct *p,
                                    uint32_t xstart, uint32_t xend,
                                    uint32_t instep, uint32_t outstep) {
    ConvolveParams *cp = (ConvolveParams *)p->usr;
    uchar4 *out = (uchar4 *)p->out;
    uchar4 *in = (uchar4 *)p->in;
    uint32_t x1 = xstart;
    uint32_t x2 = xend;

    if(x2 > x1) {
#if defined(ARCH_ARM_HAVE_NEON)
        int32_t len = (x2 - x1) >> 2;
        if(len > 0) {
            if (cp->use3x3) {
                if (cp->useDot) {
                    rsdIntrinsicColorMatrixDot_K(out, in, cp->ip, len);
                } else {
                    rsdIntrinsicColorMatrix3x3_K(out, in, cp->ip, len);
                }
            } else {
                rsdIntrinsicColorMatrix4x4_K(out, in, cp->ip, len);
            }
            x1 += len << 2;
            out += len << 2;
            in += len << 2;
        }
#endif

        while(x1 != x2) {
            One(p, out++, in++, cp->fp);
            x1++;
        }
    }
}

void * rsdIntrinsic_InitColorMatrix(const android::renderscript::Context *dc,
                                    android::renderscript::Script *script,
                                    RsdIntriniscFuncs_t *funcs) {

    script->mHal.info.exportedVariableCount = 1;
    funcs->setVar = ColorMatrix_SetVar;
    funcs->root = ColorMatrix_uchar4;

    ConvolveParams *cp = (ConvolveParams *)calloc(1, sizeof(ConvolveParams));
    cp->fp[0] = 1.f;
    cp->fp[5] = 1.f;
    cp->fp[10] = 1.f;
    cp->fp[15] = 1.f;
    for(int ct=0; ct < 16; ct++) {
        cp->ip[ct] = (short)(cp->fp[ct] * 255.f + 0.5f);
    }
    return cp;
}