Home | History | Annotate | Download | only in cpp
      1 /*
      2  * Copyright (C) 2012 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 #include <malloc.h>
     18 #include <string.h>
     19 
     20 #include "RenderScript.h"
     21 #include "rsCppInternal.h"
     22 
     23 // From system/graphics.h
     24 enum {
     25     HAL_PIXEL_FORMAT_YV12               = 0x32315659, // YCrCb 4:2:0 Planar
     26     HAL_PIXEL_FORMAT_YCrCb_420_SP       = 0x11,       // NV21
     27 };
     28 
     29 using android::RSC::Element;
     30 using android::RSC::RS;
     31 using android::RSC::Type;
     32 using android::RSC::sp;
     33 
     34 void Type::calcElementCount() {
     35     bool hasLod = hasMipmaps();
     36     uint32_t x = getX();
     37     uint32_t y = getY();
     38     uint32_t z = getZ();
     39     uint32_t faces = 1;
     40     if (hasFaces()) {
     41         faces = 6;
     42     }
     43     if (x == 0) {
     44         x = 1;
     45     }
     46     if (y == 0) {
     47         y = 1;
     48     }
     49     if (z == 0) {
     50         z = 1;
     51     }
     52 
     53     uint32_t count = x * y * z * faces;
     54     while (hasLod && ((x > 1) || (y > 1) || (z > 1))) {
     55         if(x > 1) {
     56             x >>= 1;
     57         }
     58         if(y > 1) {
     59             y >>= 1;
     60         }
     61         if(z > 1) {
     62             z >>= 1;
     63         }
     64 
     65         count += x * y * z * faces;
     66     }
     67     mElementCount = count;
     68 }
     69 
     70 
     71 Type::Type(void *id, sp<RS> rs) : BaseObj(id, rs) {
     72     mDimX = 0;
     73     mDimY = 0;
     74     mDimZ = 0;
     75     mDimMipmaps = false;
     76     mDimFaces = false;
     77     mElement = nullptr;
     78     mYuvFormat = RS_YUV_NONE;
     79 }
     80 
     81 void Type::updateFromNative() {
     82     BaseObj::updateFromNative();
     83 
     84     /*
     85      * We have 6 integers / pointers (uintptr_t) to obtain from the return buffer:
     86      * mDimX     (buffer[0]);
     87      * mDimY     (buffer[1]);
     88      * mDimZ     (buffer[2]);
     89      * mDimLOD   (buffer[3]);
     90      * mDimFaces (buffer[4]);
     91      * mElement  (buffer[5]);
     92      */
     93     uintptr_t dataBuffer[6];
     94     RS::dispatch->TypeGetNativeData(mRS->getContext(), getID(), dataBuffer, 6);
     95 
     96     mDimX = (uint32_t)dataBuffer[0];
     97     mDimY = (uint32_t)dataBuffer[1];
     98     mDimZ = (uint32_t)dataBuffer[2];
     99     mDimMipmaps = dataBuffer[3] == 1 ? true : false;
    100     mDimFaces = dataBuffer[4] == 1 ? true : false;
    101 
    102     uintptr_t elementID = dataBuffer[5];
    103     if(elementID != 0) {
    104         // Just create a new Element and update it from native.
    105         sp<Element> e = new Element((void *)elementID, mRS);
    106         e->updateFromNative();
    107         mElement = e;
    108     }
    109     calcElementCount();
    110 }
    111 
    112 sp<const Type> Type::create(const sp<RS>& rs, const sp<const Element>& e, uint32_t dimX, uint32_t dimY, uint32_t dimZ) {
    113     void * id = RS::dispatch->TypeCreate(rs->getContext(), e->getID(), dimX, dimY, dimZ, false, false, 0);
    114     Type *t = new Type(id, rs);
    115 
    116     t->mElement = e;
    117     t->mDimX = dimX;
    118     t->mDimY = dimY;
    119     t->mDimZ = dimZ;
    120     t->mDimMipmaps = false;
    121     t->mDimFaces = false;
    122     t->mYuvFormat = RS_YUV_NONE;
    123 
    124     t->calcElementCount();
    125 
    126     return t;
    127 }
    128 
    129 Type::Builder::Builder(sp<RS> rs, sp<const Element> e) {
    130     mRS = rs.get();
    131     mElement = e;
    132     mDimX = 0;
    133     mDimY = 0;
    134     mDimZ = 0;
    135     mDimMipmaps = false;
    136     mDimFaces = false;
    137     mYuvFormat = RS_YUV_NONE;
    138 }
    139 
    140 void Type::Builder::setX(uint32_t value) {
    141     if(value < 1) {
    142         ALOGE("Values of less than 1 for Dimension X are not valid.");
    143     }
    144     mDimX = value;
    145 }
    146 
    147 void Type::Builder::setY(uint32_t value) {
    148     if(value < 1) {
    149         ALOGE("Values of less than 1 for Dimension Y are not valid.");
    150     }
    151     mDimY = value;
    152 }
    153 
    154 void Type::Builder::setZ(uint32_t value) {
    155     if(value < 1) {
    156         ALOGE("Values of less than 1 for Dimension Z are not valid.");
    157     }
    158     mDimZ = value;
    159 }
    160 
    161 void Type::Builder::setYuvFormat(RsYuvFormat format) {
    162     if (format != RS_YUV_NONE && !(mElement->isCompatible(Element::YUV(mRS)))) {
    163         ALOGE("Invalid element for use with YUV.");
    164         return;
    165     }
    166 
    167     if (format != RS_YUV_NONE &&
    168         format != RS_YUV_YV12 &&
    169         format != RS_YUV_NV21 &&
    170         format != RS_YUV_420_888) {
    171         ALOGE("Invalid YUV format.");
    172         return;
    173     }
    174     mYuvFormat = format;
    175 }
    176 
    177 
    178 void Type::Builder::setMipmaps(bool value) {
    179     mDimMipmaps = value;
    180 }
    181 
    182 void Type::Builder::setFaces(bool value) {
    183     mDimFaces = value;
    184 }
    185 
    186 sp<const Type> Type::Builder::create() {
    187     if (mDimZ > 0) {
    188         if ((mDimX < 1) || (mDimY < 1)) {
    189             ALOGE("Both X and Y dimension required when Z is present.");
    190             return nullptr;
    191         }
    192         if (mDimFaces) {
    193             ALOGE("Cube maps not supported with 3D types.");
    194             return nullptr;
    195         }
    196     }
    197     if (mDimY > 0) {
    198         if (mDimX < 1) {
    199             ALOGE("X dimension required when Y is present.");
    200             return nullptr;
    201         }
    202     }
    203     if (mDimFaces) {
    204         if (mDimY < 1) {
    205             ALOGE("Cube maps require 2D Types.");
    206             return nullptr;
    207         }
    208     }
    209 
    210     if (mYuvFormat != RS_YUV_NONE) {
    211         if (mDimZ || mDimFaces || mDimMipmaps) {
    212             ALOGE("YUV only supports basic 2D.");
    213             return nullptr;
    214         }
    215     }
    216 
    217     if (mYuvFormat == RS_YUV_420_888) {
    218         ALOGE("YUV_420_888 not supported.");
    219         return nullptr;
    220     }
    221 
    222     void * id = RS::dispatch->TypeCreate(mRS->getContext(), mElement->getID(), mDimX, mDimY, mDimZ,
    223                                          mDimMipmaps, mDimFaces, mYuvFormat);
    224     Type *t = new Type(id, mRS);
    225     t->mElement = mElement;
    226     t->mDimX = mDimX;
    227     t->mDimY = mDimY;
    228     t->mDimZ = mDimZ;
    229     t->mDimMipmaps = mDimMipmaps;
    230     t->mDimFaces = mDimFaces;
    231     t->mYuvFormat = mYuvFormat;
    232 
    233     t->calcElementCount();
    234     return t;
    235 }
    236 
    237