Home | History | Annotate | Download | only in cpu_ref
      1 /*
      2  * Copyright (C) 2013 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 
     18 #include "rsCpuIntrinsic.h"
     19 #include "rsCpuIntrinsicInlines.h"
     20 
     21 #ifndef RS_COMPATIBILITY_LIB
     22 #include "hardware/gralloc.h"
     23 #endif
     24 
     25 using namespace android;
     26 using namespace android::renderscript;
     27 
     28 namespace android {
     29 namespace renderscript {
     30 
     31 
     32 class RsdCpuScriptIntrinsicYuvToRGB : public RsdCpuScriptIntrinsic {
     33 public:
     34     virtual void populateScript(Script *);
     35     virtual void invokeFreeChildren();
     36 
     37     virtual void setGlobalObj(uint32_t slot, ObjectBase *data);
     38 
     39     virtual ~RsdCpuScriptIntrinsicYuvToRGB();
     40     RsdCpuScriptIntrinsicYuvToRGB(RsdCpuReferenceImpl *ctx, const Script *s, const Element *e);
     41 
     42 protected:
     43     ObjectBaseRef<Allocation> alloc;
     44 
     45     static void kernel(const RsForEachStubParamStruct *p,
     46                        uint32_t xstart, uint32_t xend,
     47                        uint32_t instep, uint32_t outstep);
     48 };
     49 
     50 }
     51 }
     52 
     53 
     54 void RsdCpuScriptIntrinsicYuvToRGB::setGlobalObj(uint32_t slot, ObjectBase *data) {
     55     rsAssert(slot == 0);
     56     alloc.set(static_cast<Allocation *>(data));
     57 }
     58 
     59 
     60 
     61 
     62 static uchar4 rsYuvToRGBA_uchar4(uchar y, uchar u, uchar v) {
     63     short Y = ((short)y) - 16;
     64     short U = ((short)u) - 128;
     65     short V = ((short)v) - 128;
     66 
     67     short4 p;
     68     p.x = (Y * 298 + V * 409 + 128) >> 8;
     69     p.y = (Y * 298 - U * 100 - V * 208 + 128) >> 8;
     70     p.z = (Y * 298 + U * 516 + 128) >> 8;
     71     p.w = 255;
     72     if(p.x < 0) {
     73         p.x = 0;
     74     }
     75     if(p.x > 255) {
     76         p.x = 255;
     77     }
     78     if(p.y < 0) {
     79         p.y = 0;
     80     }
     81     if(p.y > 255) {
     82         p.y = 255;
     83     }
     84     if(p.z < 0) {
     85         p.z = 0;
     86     }
     87     if(p.z > 255) {
     88         p.z = 255;
     89     }
     90 
     91     return (uchar4){p.x, p.y, p.z, p.w};
     92 }
     93 
     94 
     95 static short YuvCoeff[] = {
     96     298, 409, -100, 516,   -208, 255, 0, 0,
     97     16, 16, 16, 16,        16, 16, 16, 16,
     98     128, 128, 128, 128, 128, 128, 128, 128,
     99     298, 298, 298, 298, 298, 298, 298, 298,
    100     255, 255, 255, 255, 255, 255, 255, 255
    101 
    102 
    103 };
    104 
    105 extern "C" void rsdIntrinsicYuv_K(void *dst, const uchar *Y, const uchar *uv, uint32_t count, const short *param);
    106 extern "C" void rsdIntrinsicYuv2_K(void *dst, const uchar *Y, const uchar *u, const uchar *v, uint32_t count, const short *param);
    107 
    108 void RsdCpuScriptIntrinsicYuvToRGB::kernel(const RsForEachStubParamStruct *p,
    109                                            uint32_t xstart, uint32_t xend,
    110                                            uint32_t instep, uint32_t outstep) {
    111     RsdCpuScriptIntrinsicYuvToRGB *cp = (RsdCpuScriptIntrinsicYuvToRGB *)p->usr;
    112     if (!cp->alloc.get()) {
    113         ALOGE("YuvToRGB executed without input, skipping");
    114         return;
    115     }
    116     const uchar *pinY = (const uchar *)cp->alloc->mHal.drvState.lod[0].mallocPtr;
    117 
    118     size_t strideY = cp->alloc->mHal.drvState.lod[0].stride;
    119 
    120     // calculate correct stride in legacy case
    121     if (cp->alloc->mHal.drvState.lod[0].dimY == 0) {
    122         strideY = p->dimX;
    123     }
    124     const uchar *Y = pinY + (p->y * strideY);
    125 
    126     //    ALOGE("pinY, %p, Y, %p, p->y, %d, strideY, %d", pinY, Y, p->y, strideY);
    127     //    ALOGE("dimX, %d, dimY, %d", cp->alloc->mHal.drvState.lod[0].dimX, cp->alloc->mHal.drvState.lod[0].dimY);
    128     //    ALOGE("p->dimX, %d, p->dimY, %d", p->dimX, p->dimY);
    129 
    130     uchar4 *out = (uchar4 *)p->out;
    131     uint32_t x1 = xstart;
    132     uint32_t x2 = xend;
    133 
    134     switch (cp->alloc->mHal.state.yuv) {
    135     // In API 17 there was no yuv format and the intrinsic treated everything as NV21
    136     case 0:
    137 #if !defined(RS_SERVER) && !defined(RS_COMPATIBILITY_LIB)
    138     case HAL_PIXEL_FORMAT_YCrCb_420_SP:  // NV21
    139 #endif
    140         {
    141             const uchar *pinUV = (const uchar *)cp->alloc->mHal.drvState.lod[1].mallocPtr;
    142             size_t strideUV = cp->alloc->mHal.drvState.lod[1].stride;
    143             const uchar *uv = pinUV + ((p->y >> 1) * strideUV);
    144 
    145             if (pinUV == NULL) {
    146                 // Legacy yuv support didn't fill in uv
    147                 strideUV = strideY;
    148                 uv = ((uint8_t *)cp->alloc->mHal.drvState.lod[0].mallocPtr) +
    149                     (strideY * p->dimY) +
    150                     ((p->y >> 1) * strideUV);
    151             }
    152 
    153             if(x2 > x1) {
    154         #if defined(ARCH_ARM_HAVE_NEON)
    155                 int32_t len = (x2 - x1 - 1) >> 3;
    156                 if(len > 0) {
    157                     //                    ALOGE("%p, %p, %p, %d, %p", out, Y, uv, len, YuvCoeff);
    158                     rsdIntrinsicYuv_K(out, Y, uv, len, YuvCoeff);
    159                     x1 += len << 3;
    160                     out += len << 3;
    161                 }
    162         #endif
    163 
    164                // ALOGE("y %i  %i  %i", p->y, x1, x2);
    165                 while(x1 < x2) {
    166                     uchar u = uv[(x1 & 0xffffe) + 1];
    167                     uchar v = uv[(x1 & 0xffffe) + 0];
    168                     *out = rsYuvToRGBA_uchar4(Y[x1], u, v);
    169                     out++;
    170                     x1++;
    171                     *out = rsYuvToRGBA_uchar4(Y[x1], u, v);
    172                     out++;
    173                     x1++;
    174                 }
    175             }
    176         }
    177         break;
    178 
    179 #if !defined(RS_SERVER) && !defined(RS_COMPATIBILITY_LIB)
    180     case HAL_PIXEL_FORMAT_YV12:
    181         {
    182             const uchar *pinU = (const uchar *)cp->alloc->mHal.drvState.lod[1].mallocPtr;
    183             const size_t strideU = cp->alloc->mHal.drvState.lod[1].stride;
    184             const uchar *u = pinU + ((p->y >> 1) * strideU);
    185 
    186             const uchar *pinV = (const uchar *)cp->alloc->mHal.drvState.lod[2].mallocPtr;
    187             const size_t strideV = cp->alloc->mHal.drvState.lod[2].stride;
    188             const uchar *v = pinV + ((p->y >> 1) * strideV);
    189 
    190             if(x2 > x1) {
    191         #if defined(ARCH_ARM_HAVE_NEON)
    192                 int32_t len = (x2 - x1 - 1) >> 3;
    193                 if(len > 0) {
    194                     rsdIntrinsicYuv2_K(out, Y, u, v, len, YuvCoeff);
    195                     x1 += len << 3;
    196                     out += len << 3;
    197                 }
    198         #endif
    199 
    200                // ALOGE("y %i  %i  %i", p->y, x1, x2);
    201                 while(x1 < x2) {
    202                     uchar ut = u[x1];
    203                     uchar vt = v[x1];
    204                     *out = rsYuvToRGBA_uchar4(Y[x1], ut, vt);
    205                     out++;
    206                     x1++;
    207                     *out = rsYuvToRGBA_uchar4(Y[x1], ut, vt);
    208                     out++;
    209                     x1++;
    210                 }
    211             }
    212         }
    213         break;
    214 #endif
    215     }
    216 
    217 }
    218 
    219 RsdCpuScriptIntrinsicYuvToRGB::RsdCpuScriptIntrinsicYuvToRGB(
    220             RsdCpuReferenceImpl *ctx, const Script *s, const Element *e)
    221             : RsdCpuScriptIntrinsic(ctx, s, e, RS_SCRIPT_INTRINSIC_ID_YUV_TO_RGB) {
    222 
    223     mRootPtr = &kernel;
    224 }
    225 
    226 RsdCpuScriptIntrinsicYuvToRGB::~RsdCpuScriptIntrinsicYuvToRGB() {
    227 }
    228 
    229 void RsdCpuScriptIntrinsicYuvToRGB::populateScript(Script *s) {
    230     s->mHal.info.exportedVariableCount = 1;
    231 }
    232 
    233 void RsdCpuScriptIntrinsicYuvToRGB::invokeFreeChildren() {
    234     alloc.clear();
    235 }
    236 
    237 
    238 RsdCpuScriptImpl * rsdIntrinsic_YuvToRGB(RsdCpuReferenceImpl *ctx,
    239                                          const Script *s, const Element *e) {
    240     return new RsdCpuScriptIntrinsicYuvToRGB(ctx, s, e);
    241 }
    242 
    243 
    244