| /* | 
 |  * 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 "rsCpuIntrinsic.h" | 
 | #include "rsCpuIntrinsicInlines.h" | 
 |  | 
 | using namespace android; | 
 | using namespace android::renderscript; | 
 |  | 
 | namespace android { | 
 | namespace renderscript { | 
 |  | 
 |  | 
 | class RsdCpuScriptIntrinsicBlend : public RsdCpuScriptIntrinsic { | 
 | public: | 
 |     virtual void populateScript(Script *); | 
 |  | 
 |     virtual ~RsdCpuScriptIntrinsicBlend(); | 
 |     RsdCpuScriptIntrinsicBlend(RsdCpuReferenceImpl *ctx, const Script *s, const Element *e); | 
 |  | 
 | protected: | 
 |     static void kernel(const RsForEachStubParamStruct *p, | 
 |                           uint32_t xstart, uint32_t xend, | 
 |                           uint32_t instep, uint32_t outstep); | 
 | }; | 
 |  | 
 | } | 
 | } | 
 |  | 
 |  | 
 | enum { | 
 |     BLEND_CLEAR = 0, | 
 |     BLEND_SRC = 1, | 
 |     BLEND_DST = 2, | 
 |     BLEND_SRC_OVER = 3, | 
 |     BLEND_DST_OVER = 4, | 
 |     BLEND_SRC_IN = 5, | 
 |     BLEND_DST_IN = 6, | 
 |     BLEND_SRC_OUT = 7, | 
 |     BLEND_DST_OUT = 8, | 
 |     BLEND_SRC_ATOP = 9, | 
 |     BLEND_DST_ATOP = 10, | 
 |     BLEND_XOR = 11, | 
 |  | 
 |     BLEND_NORMAL = 12, | 
 |     BLEND_AVERAGE = 13, | 
 |     BLEND_MULTIPLY = 14, | 
 |     BLEND_SCREEN = 15, | 
 |     BLEND_DARKEN = 16, | 
 |     BLEND_LIGHTEN = 17, | 
 |     BLEND_OVERLAY = 18, | 
 |     BLEND_HARDLIGHT = 19, | 
 |     BLEND_SOFTLIGHT = 20, | 
 |     BLEND_DIFFERENCE = 21, | 
 |     BLEND_NEGATION = 22, | 
 |     BLEND_EXCLUSION = 23, | 
 |     BLEND_COLOR_DODGE = 24, | 
 |     BLEND_INVERSE_COLOR_DODGE = 25, | 
 |     BLEND_SOFT_DODGE = 26, | 
 |     BLEND_COLOR_BURN = 27, | 
 |     BLEND_INVERSE_COLOR_BURN = 28, | 
 |     BLEND_SOFT_BURN = 29, | 
 |     BLEND_REFLECT = 30, | 
 |     BLEND_GLOW = 31, | 
 |     BLEND_FREEZE = 32, | 
 |     BLEND_HEAT = 33, | 
 |     BLEND_ADD = 34, | 
 |     BLEND_SUBTRACT = 35, | 
 |     BLEND_STAMP = 36, | 
 |     BLEND_RED = 37, | 
 |     BLEND_GREEN = 38, | 
 |     BLEND_BLUE = 39, | 
 |     BLEND_HUE = 40, | 
 |     BLEND_SATURATION = 41, | 
 |     BLEND_COLOR = 42, | 
 |     BLEND_LUMINOSITY = 43 | 
 | }; | 
 |  | 
 | extern "C" int rsdIntrinsicBlend_K(uchar4 *out, uchar4 const *in, int slot, | 
 |                     uint32_t xstart, uint32_t xend); | 
 |  | 
 | void RsdCpuScriptIntrinsicBlend::kernel(const RsForEachStubParamStruct *p, | 
 |                                         uint32_t xstart, uint32_t xend, | 
 |                                         uint32_t instep, uint32_t outstep) { | 
 |     RsdCpuScriptIntrinsicBlend *cp = (RsdCpuScriptIntrinsicBlend *)p->usr; | 
 |  | 
 |     // instep/outstep can be ignored--sizeof(uchar4) known at compile time | 
 |     uchar4 *out = (uchar4 *)p->out; | 
 |     uchar4 *in = (uchar4 *)p->in; | 
 |     uint32_t x1 = xstart; | 
 |     uint32_t x2 = xend; | 
 |  | 
 | #if defined(ARCH_ARM_HAVE_VFP) | 
 |     if (gArchUseSIMD) { | 
 |         if (rsdIntrinsicBlend_K(out, in, p->slot, x1, x2) >= 0) | 
 |             return; | 
 |     } | 
 | #endif | 
 |     switch (p->slot) { | 
 |     case BLEND_CLEAR: | 
 |         for (;x1 < x2; x1++, out++) { | 
 |             *out = 0; | 
 |         } | 
 |         break; | 
 |     case BLEND_SRC: | 
 |         for (;x1 < x2; x1++, out++, in++) { | 
 |           *out = *in; | 
 |         } | 
 |         break; | 
 |     //BLEND_DST is a NOP | 
 |     case BLEND_DST: | 
 |         break; | 
 |     case BLEND_SRC_OVER: | 
 |         for (;x1 < x2; x1++, out++, in++) { | 
 |             short4 in_s = convert_short4(*in); | 
 |             short4 out_s = convert_short4(*out); | 
 |             in_s = in_s + ((out_s * (short4)(255 - in_s.w)) >> (short4)8); | 
 |             *out = convert_uchar4(in_s); | 
 |         } | 
 |         break; | 
 |     case BLEND_DST_OVER: | 
 |         for (;x1 < x2; x1++, out++, in++) { | 
 |             short4 in_s = convert_short4(*in); | 
 |             short4 out_s = convert_short4(*out); | 
 |             in_s = out_s + ((in_s * (short4)(255 - out_s.w)) >> (short4)8); | 
 |             *out = convert_uchar4(in_s); | 
 |         } | 
 |         break; | 
 |     case BLEND_SRC_IN: | 
 |         for (;x1 < x2; x1++, out++, in++) { | 
 |             short4 in_s = convert_short4(*in); | 
 |             in_s = (in_s * out->w) >> (short4)8; | 
 |             *out = convert_uchar4(in_s); | 
 |         } | 
 |         break; | 
 |     case BLEND_DST_IN: | 
 |         for (;x1 < x2; x1++, out++, in++) { | 
 |             short4 out_s = convert_short4(*out); | 
 |             out_s = (out_s * in->w) >> (short4)8; | 
 |             *out = convert_uchar4(out_s); | 
 |         } | 
 |         break; | 
 |     case BLEND_SRC_OUT: | 
 |         for (;x1 < x2; x1++, out++, in++) { | 
 |             short4 in_s = convert_short4(*in); | 
 |             in_s = (in_s * (short4)(255 - out->w)) >> (short4)8; | 
 |             *out = convert_uchar4(in_s); | 
 |         } | 
 |         break; | 
 |     case BLEND_DST_OUT: | 
 |         for (;x1 < x2; x1++, out++, in++) { | 
 |             short4 out_s = convert_short4(*out); | 
 |             out_s = (out_s * (short4)(255 - in->w)) >> (short4)8; | 
 |             *out = convert_uchar4(out_s); | 
 |         } | 
 |         break; | 
 |     case BLEND_SRC_ATOP: | 
 |         for (;x1 < x2; x1++, out++, in++) { | 
 |             short4 in_s = convert_short4(*in); | 
 |             short4 out_s = convert_short4(*out); | 
 |             out_s.xyz = ((in_s.xyz * out_s.w) + | 
 |               (out_s.xyz * ((short3)255 - (short3)in_s.w))) >> (short3)8; | 
 |             *out = convert_uchar4(out_s); | 
 |         } | 
 |         break; | 
 |     case BLEND_DST_ATOP: | 
 |         for (;x1 < x2; x1++, out++, in++) { | 
 |             short4 in_s = convert_short4(*in); | 
 |             short4 out_s = convert_short4(*out); | 
 |             out_s.xyz = ((out_s.xyz * in_s.w) + | 
 |               (in_s.xyz * ((short3)255 - (short3)out_s.w))) >> (short3)8; | 
 |             *out = convert_uchar4(out_s); | 
 |         } | 
 |         break; | 
 |     case BLEND_XOR: | 
 |         for (;x1 < x2; x1++, out++, in++) { | 
 |             *out = *in ^ *out; | 
 |         } | 
 |         break; | 
 |     case BLEND_NORMAL: | 
 |         ALOGE("Called unimplemented blend intrinsic BLEND_NORMAL"); | 
 |         rsAssert(false); | 
 |         break; | 
 |     case BLEND_AVERAGE: | 
 |         ALOGE("Called unimplemented blend intrinsic BLEND_AVERAGE"); | 
 |         rsAssert(false); | 
 |         break; | 
 |     case BLEND_MULTIPLY: | 
 |         for (;x1 < x2; x1++, out++, in++) { | 
 |           *out = convert_uchar4((convert_short4(*in) * convert_short4(*out)) | 
 |                                 >> (short4)8); | 
 |         } | 
 |         break; | 
 |     case BLEND_SCREEN: | 
 |         ALOGE("Called unimplemented blend intrinsic BLEND_SCREEN"); | 
 |         rsAssert(false); | 
 |         break; | 
 |     case BLEND_DARKEN: | 
 |         ALOGE("Called unimplemented blend intrinsic BLEND_DARKEN"); | 
 |         rsAssert(false); | 
 |         break; | 
 |     case BLEND_LIGHTEN: | 
 |         ALOGE("Called unimplemented blend intrinsic BLEND_LIGHTEN"); | 
 |         rsAssert(false); | 
 |         break; | 
 |     case BLEND_OVERLAY: | 
 |         ALOGE("Called unimplemented blend intrinsic BLEND_OVERLAY"); | 
 |         rsAssert(false); | 
 |         break; | 
 |     case BLEND_HARDLIGHT: | 
 |         ALOGE("Called unimplemented blend intrinsic BLEND_HARDLIGHT"); | 
 |         rsAssert(false); | 
 |         break; | 
 |     case BLEND_SOFTLIGHT: | 
 |         ALOGE("Called unimplemented blend intrinsic BLEND_SOFTLIGHT"); | 
 |         rsAssert(false); | 
 |         break; | 
 |     case BLEND_DIFFERENCE: | 
 |         ALOGE("Called unimplemented blend intrinsic BLEND_DIFFERENCE"); | 
 |         rsAssert(false); | 
 |         break; | 
 |     case BLEND_NEGATION: | 
 |         ALOGE("Called unimplemented blend intrinsic BLEND_NEGATION"); | 
 |         rsAssert(false); | 
 |         break; | 
 |     case BLEND_EXCLUSION: | 
 |         ALOGE("Called unimplemented blend intrinsic BLEND_EXCLUSION"); | 
 |         rsAssert(false); | 
 |         break; | 
 |     case BLEND_COLOR_DODGE: | 
 |         ALOGE("Called unimplemented blend intrinsic BLEND_COLOR_DODGE"); | 
 |         rsAssert(false); | 
 |         break; | 
 |     case BLEND_INVERSE_COLOR_DODGE: | 
 |         ALOGE("Called unimplemented blend intrinsic BLEND_INVERSE_COLOR_DODGE"); | 
 |         rsAssert(false); | 
 |         break; | 
 |     case BLEND_SOFT_DODGE: | 
 |         ALOGE("Called unimplemented blend intrinsic BLEND_SOFT_DODGE"); | 
 |         rsAssert(false); | 
 |         break; | 
 |     case BLEND_COLOR_BURN: | 
 |         ALOGE("Called unimplemented blend intrinsic BLEND_COLOR_BURN"); | 
 |         rsAssert(false); | 
 |         break; | 
 |     case BLEND_INVERSE_COLOR_BURN: | 
 |         ALOGE("Called unimplemented blend intrinsic BLEND_INVERSE_COLOR_BURN"); | 
 |         rsAssert(false); | 
 |         break; | 
 |     case BLEND_SOFT_BURN: | 
 |         ALOGE("Called unimplemented blend intrinsic BLEND_SOFT_BURN"); | 
 |         rsAssert(false); | 
 |         break; | 
 |     case BLEND_REFLECT: | 
 |         ALOGE("Called unimplemented blend intrinsic BLEND_REFLECT"); | 
 |         rsAssert(false); | 
 |         break; | 
 |     case BLEND_GLOW: | 
 |         ALOGE("Called unimplemented blend intrinsic BLEND_GLOW"); | 
 |         rsAssert(false); | 
 |         break; | 
 |     case BLEND_FREEZE: | 
 |         ALOGE("Called unimplemented blend intrinsic BLEND_FREEZE"); | 
 |         rsAssert(false); | 
 |         break; | 
 |     case BLEND_HEAT: | 
 |         ALOGE("Called unimplemented blend intrinsic BLEND_HEAT"); | 
 |         rsAssert(false); | 
 |         break; | 
 |     case BLEND_ADD: | 
 |         for (;x1 < x2; x1++, out++, in++) { | 
 |             uint32_t iR = in->x, iG = in->y, iB = in->z, iA = in->w, | 
 |                 oR = out->x, oG = out->y, oB = out->z, oA = out->w; | 
 |             out->x = (oR + iR) > 255 ? 255 : oR + iR; | 
 |             out->y = (oG + iG) > 255 ? 255 : oG + iG; | 
 |             out->z = (oB + iB) > 255 ? 255 : oB + iB; | 
 |             out->w = (oA + iA) > 255 ? 255 : oA + iA; | 
 |         } | 
 |         break; | 
 |     case BLEND_SUBTRACT: | 
 |         for (;x1 < x2; x1++, out++, in++) { | 
 |             int32_t iR = in->x, iG = in->y, iB = in->z, iA = in->w, | 
 |                 oR = out->x, oG = out->y, oB = out->z, oA = out->w; | 
 |             out->x = (oR - iR) < 0 ? 0 : oR - iR; | 
 |             out->y = (oG - iG) < 0 ? 0 : oG - iG; | 
 |             out->z = (oB - iB) < 0 ? 0 : oB - iB; | 
 |             out->w = (oA - iA) < 0 ? 0 : oA - iA; | 
 |         } | 
 |         break; | 
 |     case BLEND_STAMP: | 
 |         ALOGE("Called unimplemented blend intrinsic BLEND_STAMP"); | 
 |         rsAssert(false); | 
 |         break; | 
 |     case BLEND_RED: | 
 |         ALOGE("Called unimplemented blend intrinsic BLEND_RED"); | 
 |         rsAssert(false); | 
 |         break; | 
 |     case BLEND_GREEN: | 
 |         ALOGE("Called unimplemented blend intrinsic BLEND_GREEN"); | 
 |         rsAssert(false); | 
 |         break; | 
 |     case BLEND_BLUE: | 
 |         ALOGE("Called unimplemented blend intrinsic BLEND_BLUE"); | 
 |         rsAssert(false); | 
 |         break; | 
 |     case BLEND_HUE: | 
 |         ALOGE("Called unimplemented blend intrinsic BLEND_HUE"); | 
 |         rsAssert(false); | 
 |         break; | 
 |     case BLEND_SATURATION: | 
 |         ALOGE("Called unimplemented blend intrinsic BLEND_SATURATION"); | 
 |         rsAssert(false); | 
 |         break; | 
 |     case BLEND_COLOR: | 
 |         ALOGE("Called unimplemented blend intrinsic BLEND_COLOR"); | 
 |         rsAssert(false); | 
 |         break; | 
 |     case BLEND_LUMINOSITY: | 
 |         ALOGE("Called unimplemented blend intrinsic BLEND_LUMINOSITY"); | 
 |         rsAssert(false); | 
 |         break; | 
 |  | 
 |     default: | 
 |         ALOGE("Called unimplemented value %d", p->slot); | 
 |         rsAssert(false); | 
 |  | 
 |     } | 
 | } | 
 |  | 
 |  | 
 | RsdCpuScriptIntrinsicBlend::RsdCpuScriptIntrinsicBlend(RsdCpuReferenceImpl *ctx, | 
 |                                                        const Script *s, const Element *e) | 
 |             : RsdCpuScriptIntrinsic(ctx, s, e, RS_SCRIPT_INTRINSIC_ID_BLEND) { | 
 |  | 
 |     mRootPtr = &kernel; | 
 | } | 
 |  | 
 | RsdCpuScriptIntrinsicBlend::~RsdCpuScriptIntrinsicBlend() { | 
 | } | 
 |  | 
 | void RsdCpuScriptIntrinsicBlend::populateScript(Script *s) { | 
 |     s->mHal.info.exportedVariableCount = 0; | 
 | } | 
 |  | 
 | RsdCpuScriptImpl * rsdIntrinsic_Blend(RsdCpuReferenceImpl *ctx, | 
 |                                       const Script *s, const Element *e) { | 
 |     return new RsdCpuScriptIntrinsicBlend(ctx, s, e); | 
 | } | 
 |  | 
 |  | 
 |  |