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