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.
513 lines
16 KiB
513 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
|