You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
512 lines
16 KiB
512 lines
16 KiB
/* |
|
* 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" |
|
|
|
namespace android { |
|
namespace renderscript { |
|
|
|
|
|
class RsdCpuScriptIntrinsicBlend : public RsdCpuScriptIntrinsic { |
|
public: |
|
void populateScript(Script *) override; |
|
|
|
~RsdCpuScriptIntrinsicBlend() override; |
|
RsdCpuScriptIntrinsicBlend(RsdCpuReferenceImpl *ctx, const Script *s, const Element *e); |
|
|
|
protected: |
|
static void kernel(const RsExpandKernelDriverInfo *info, uint32_t xstart, |
|
uint32_t xend, uint32_t outstep); |
|
}; |
|
|
|
} // namespace renderscript |
|
} // namespace android |
|
|
|
|
|
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 |
|
}; |
|
|
|
#if defined(ARCH_ARM_USE_INTRINSICS) |
|
extern "C" int rsdIntrinsicBlend_K(uchar4 *out, uchar4 const *in, int slot, |
|
uint32_t xstart, uint32_t xend); |
|
#endif |
|
|
|
#if defined(ARCH_X86_HAVE_SSSE3) |
|
extern void rsdIntrinsicBlendSrcOver_K(void *dst, const void *src, uint32_t count8); |
|
extern void rsdIntrinsicBlendDstOver_K(void *dst, const void *src, uint32_t count8); |
|
extern void rsdIntrinsicBlendSrcIn_K(void *dst, const void *src, uint32_t count8); |
|
extern void rsdIntrinsicBlendDstIn_K(void *dst, const void *src, uint32_t count8); |
|
extern void rsdIntrinsicBlendSrcOut_K(void *dst, const void *src, uint32_t count8); |
|
extern void rsdIntrinsicBlendDstOut_K(void *dst, const void *src, uint32_t count8); |
|
extern void rsdIntrinsicBlendSrcAtop_K(void *dst, const void *src, uint32_t count8); |
|
extern void rsdIntrinsicBlendDstAtop_K(void *dst, const void *src, uint32_t count8); |
|
extern void rsdIntrinsicBlendXor_K(void *dst, const void *src, uint32_t count8); |
|
extern void rsdIntrinsicBlendMultiply_K(void *dst, const void *src, uint32_t count8); |
|
extern void rsdIntrinsicBlendAdd_K(void *dst, const void *src, uint32_t count8); |
|
extern void rsdIntrinsicBlendSub_K(void *dst, const void *src, uint32_t count8); |
|
#endif |
|
|
|
namespace android { |
|
namespace renderscript { |
|
|
|
void RsdCpuScriptIntrinsicBlend::kernel(const RsExpandKernelDriverInfo *info, |
|
uint32_t xstart, uint32_t xend, |
|
uint32_t outstep) { |
|
// instep/outstep can be ignored--sizeof(uchar4) known at compile time |
|
uchar4 *out = (uchar4 *)info->outPtr[0]; |
|
uchar4 *in = (uchar4 *)info->inPtr[0]; |
|
uint32_t x1 = xstart; |
|
uint32_t x2 = xend; |
|
|
|
#if defined(ARCH_ARM_USE_INTRINSICS) |
|
if (gArchUseSIMD) { |
|
if (rsdIntrinsicBlend_K(out, in, info->slot, x1, x2) >= 0) |
|
return; |
|
} |
|
#endif |
|
switch (info->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: |
|
#if defined(ARCH_X86_HAVE_SSSE3) |
|
if (gArchUseSIMD) { |
|
if ((x1 + 8) < x2) { |
|
uint32_t len = (x2 - x1) >> 3; |
|
rsdIntrinsicBlendSrcOver_K(out, in, len); |
|
x1 += len << 3; |
|
out += len << 3; |
|
in += len << 3; |
|
} |
|
} |
|
#endif |
|
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: |
|
#if defined(ARCH_X86_HAVE_SSSE3) |
|
if (gArchUseSIMD) { |
|
if ((x1 + 8) < x2) { |
|
uint32_t len = (x2 - x1) >> 3; |
|
rsdIntrinsicBlendDstOver_K(out, in, len); |
|
x1 += len << 3; |
|
out += len << 3; |
|
in += len << 3; |
|
} |
|
} |
|
#endif |
|
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: |
|
#if defined(ARCH_X86_HAVE_SSSE3) |
|
if (gArchUseSIMD) { |
|
if ((x1 + 8) < x2) { |
|
uint32_t len = (x2 - x1) >> 3; |
|
rsdIntrinsicBlendSrcIn_K(out, in, len); |
|
x1 += len << 3; |
|
out += len << 3; |
|
in += len << 3; |
|
} |
|
} |
|
#endif |
|
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: |
|
#if defined(ARCH_X86_HAVE_SSSE3) |
|
if (gArchUseSIMD) { |
|
if ((x1 + 8) < x2) { |
|
uint32_t len = (x2 - x1) >> 3; |
|
rsdIntrinsicBlendDstIn_K(out, in, len); |
|
x1 += len << 3; |
|
out += len << 3; |
|
in += len << 3; |
|
} |
|
} |
|
#endif |
|
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: |
|
#if defined(ARCH_X86_HAVE_SSSE3) |
|
if (gArchUseSIMD) { |
|
if ((x1 + 8) < x2) { |
|
uint32_t len = (x2 - x1) >> 3; |
|
rsdIntrinsicBlendSrcOut_K(out, in, len); |
|
x1 += len << 3; |
|
out += len << 3; |
|
in += len << 3; |
|
} |
|
} |
|
#endif |
|
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: |
|
#if defined(ARCH_X86_HAVE_SSSE3) |
|
if (gArchUseSIMD) { |
|
if ((x1 + 8) < x2) { |
|
uint32_t len = (x2 - x1) >> 3; |
|
rsdIntrinsicBlendDstOut_K(out, in, len); |
|
x1 += len << 3; |
|
out += len << 3; |
|
in += len << 3; |
|
} |
|
} |
|
#endif |
|
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: |
|
#if defined(ARCH_X86_HAVE_SSSE3) |
|
if (gArchUseSIMD) { |
|
if ((x1 + 8) < x2) { |
|
uint32_t len = (x2 - x1) >> 3; |
|
rsdIntrinsicBlendSrcAtop_K(out, in, len); |
|
x1 += len << 3; |
|
out += len << 3; |
|
in += len << 3; |
|
} |
|
} |
|
#endif |
|
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: |
|
#if defined(ARCH_X86_HAVE_SSSE3) |
|
if (gArchUseSIMD) { |
|
if ((x1 + 8) < x2) { |
|
uint32_t len = (x2 - x1) >> 3; |
|
rsdIntrinsicBlendDstAtop_K(out, in, len); |
|
x1 += len << 3; |
|
out += len << 3; |
|
in += len << 3; |
|
} |
|
} |
|
#endif |
|
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_s.w = in_s.w; |
|
*out = convert_uchar4(out_s); |
|
} |
|
break; |
|
case BLEND_XOR: |
|
#if defined(ARCH_X86_HAVE_SSSE3) |
|
if (gArchUseSIMD) { |
|
if ((x1 + 8) < x2) { |
|
uint32_t len = (x2 - x1) >> 3; |
|
rsdIntrinsicBlendXor_K(out, in, len); |
|
x1 += len << 3; |
|
out += len << 3; |
|
in += len << 3; |
|
} |
|
} |
|
#endif |
|
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: |
|
#if defined(ARCH_X86_HAVE_SSSE3) |
|
if (gArchUseSIMD) { |
|
if ((x1 + 8) < x2) { |
|
uint32_t len = (x2 - x1) >> 3; |
|
rsdIntrinsicBlendMultiply_K(out, in, len); |
|
x1 += len << 3; |
|
out += len << 3; |
|
in += len << 3; |
|
} |
|
} |
|
#endif |
|
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: |
|
#if defined(ARCH_X86_HAVE_SSSE3) |
|
if (gArchUseSIMD) { |
|
if((x1 + 8) < x2) { |
|
uint32_t len = (x2 - x1) >> 3; |
|
rsdIntrinsicBlendAdd_K(out, in, len); |
|
x1 += len << 3; |
|
out += len << 3; |
|
in += len << 3; |
|
} |
|
} |
|
#endif |
|
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: |
|
#if defined(ARCH_X86_HAVE_SSSE3) |
|
if (gArchUseSIMD) { |
|
if((x1 + 8) < x2) { |
|
uint32_t len = (x2 - x1) >> 3; |
|
rsdIntrinsicBlendSub_K(out, in, len); |
|
x1 += len << 3; |
|
out += len << 3; |
|
in += len << 3; |
|
} |
|
} |
|
#endif |
|
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", info->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); |
|
} |
|
|
|
} // namespace renderscript |
|
} // namespace android
|
|
|