Implementations of various blend intrinsics.
Bug: 7190126
Change-Id: I84cd8b861b63489313b9c2827f43aa7391a62607
diff --git a/driver/rsdIntrinsicBlend.cpp b/driver/rsdIntrinsicBlend.cpp
index a5647e4..b427e55 100644
--- a/driver/rsdIntrinsicBlend.cpp
+++ b/driver/rsdIntrinsicBlend.cpp
@@ -111,6 +111,8 @@
uint32_t xstart, uint32_t xend,
uint32_t instep, uint32_t outstep) {
ConvolveParams *cp = (ConvolveParams *)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;
@@ -127,21 +129,225 @@
break;
case BLEND_SRC:
for (;x1 < x2; x1++, out++, in++) {
- uchar4 t = *in;
- t.rgb = (t.rgb * t.a) >> 8;
- *out = t;
+ *out = *in;
}
break;
+ //BLEND_DST is a NOP
case BLEND_DST:
+ break;
+ case BLEND_SRC_OVER:
for (;x1 < x2; x1++, out++, in++) {
- uchar4 t = *in;
- t.rgb = (t.rgb * t.a) >> 8;
- *out = t;
+ short4 in_s = convert_short4(*in);
+ short4 out_s = convert_short4(*out);
+ in_s = in_s + ((out_s * (short4)(255 - in_s.a)) >> (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.a)) >> (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->a) >> (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->a) >> (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->a)) >> (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->a)) >> (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.rgb = ((in_s.rgb * out_s.a) >> (short3)8) +
+ ((out_s.rgb * ((short3)255 - (short3)in_s.a)) >> (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.rgb = ((out_s.rgb * in_s.a) >> (short3)8) +
+ ((in_s.rgb * ((short3)255 - (short3)out_s.a)) >> (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->r, iG = in->g, iB = in->b, iA = in->a,
+ oR = out->r, oG = out->g, oB = out->b, oA = out->a;
+ out->r = (oR + iR) > 255 ? 255 : oR + iR;
+ out->g = (oG + iG) > 255 ? 255 : oG + iG;
+ out->b = (oB + iB) > 255 ? 255 : oB + iB;
+ out->a = (oA + iA) > 255 ? 255 : oA + iA;
+ }
+ break;
+ case BLEND_SUBTRACT:
+ for (;x1 < x2; x1++, out++, in++) {
+ int32_t iR = in->r, iG = in->g, iB = in->b, iA = in->a,
+ oR = out->r, oG = out->g, oB = out->b, oA = out->a;
+ out->r = (oR - iR) < 0 ? 0 : oR - iR;
+ out->g = (oG - iG) < 0 ? 0 : oG - iG;
+ out->b = (oB - iB) < 0 ? 0 : oB - iB;
+ out->a = (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);
}
diff --git a/driver/rsdIntrinsicInlines.h b/driver/rsdIntrinsicInlines.h
index 9e74c33..ab11b4f 100644
--- a/driver/rsdIntrinsicInlines.h
+++ b/driver/rsdIntrinsicInlines.h
@@ -67,6 +67,11 @@
return f4;
}
+static inline uchar4 convert_uchar4(short4 i) {
+ uchar4 f4 = {(uchar)i.x, (uchar)i.y, (uchar)i.z, (uchar)i.w};
+ return f4;
+}
+
static inline uchar4 convert_uchar4(int4 i) {
uchar4 f4 = {(uchar)i.x, (uchar)i.y, (uchar)i.z, (uchar)i.w};
return f4;
diff --git a/driver/rsdIntrinsics.cpp b/driver/rsdIntrinsics.cpp
index 84d527f..348bcf1 100644
--- a/driver/rsdIntrinsics.cpp
+++ b/driver/rsdIntrinsics.cpp
@@ -22,13 +22,13 @@
using namespace android;
using namespace android::renderscript;
-
void * rsdIntrinsic_InitBlur(const Context *, Script *, RsdIntriniscFuncs_t *);
void * rsdIntrinsic_InitConvolve3x3(const Context *, Script *, RsdIntriniscFuncs_t *);
void * rsdIntrinsic_InitConvolve5x5(const Context *, Script *, RsdIntriniscFuncs_t *);
void * rsdIntrinsic_InitColorMatrix(const Context *, Script *, RsdIntriniscFuncs_t *);
void * rsdIntrinsic_InitLUT(const Context *, Script *, RsdIntriniscFuncs_t *);
void * rsdIntrinsic_InitYuvToRGB(const Context *, Script *, RsdIntriniscFuncs_t *);
+void * rsdIntrinsic_InitBlend(const Context *, Script *, RsdIntriniscFuncs_t *);
static void Bind(const Context *, const Script *, void *, uint32_t, Allocation *) {
rsAssert(!"Intrinsic_Bind unexpectedly called");
@@ -62,8 +62,10 @@
return rsdIntrinsic_InitLUT(dc, script, funcs);
case RS_SCRIPT_INTRINSIC_ID_BLUR:
return rsdIntrinsic_InitBlur(dc, script, funcs);
- case RS_SCRIPT_INTRINSIC_YUV_TO_RGB:
+ case RS_SCRIPT_INTRINSIC_ID_YUV_TO_RGB:
return rsdIntrinsic_InitYuvToRGB(dc, script, funcs);
+ case RS_SCRIPT_INTRINSIC_ID_BLEND:
+ return rsdIntrinsic_InitBlend(dc, script, funcs);
default:
return NULL;
diff --git a/driver/rsdIntrinsics.h b/driver/rsdIntrinsics.h
index a494d76..221a81a 100644
--- a/driver/rsdIntrinsics.h
+++ b/driver/rsdIntrinsics.h
@@ -24,7 +24,5 @@
android::renderscript::Script *script,
RsScriptIntrinsicID id, RsdIntriniscFuncs_t *funcs);
-
-
#endif // RSD_INTRINSICS_H
diff --git a/rsDefines.h b/rsDefines.h
index 3e46d0c..cccff86 100644
--- a/rsDefines.h
+++ b/rsDefines.h
@@ -348,7 +348,8 @@
RS_SCRIPT_INTRINSIC_ID_LUT = 3,
RS_SCRIPT_INTRINSIC_ID_CONVOLVE_5x5 = 4,
RS_SCRIPT_INTRINSIC_ID_BLUR = 5,
- RS_SCRIPT_INTRINSIC_YUV_TO_RGB = 6
+ RS_SCRIPT_INTRINSIC_ID_YUV_TO_RGB = 6,
+ RS_SCRIPT_INTRINSIC_ID_BLEND = 7
};
typedef struct {