/* * 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; }