Type.cpp revision 70d8995254ee38173129e4ae4c9372f43716eb4e
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 24enum { 25 HAL_PIXEL_FORMAT_YV12 = 0x32315659, // YCrCb 4:2:0 Planar 26 HAL_PIXEL_FORMAT_YCrCb_420_SP = 0x11, // NV21 27}; 28 29using namespace android; 30using namespace RSC; 31 32void 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 69Type::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 79void 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 110sp<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 127Type::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 138void 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 145void 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 152void 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 159void 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_MAX) { 166 ALOGE("Invalid YUV format."); 167 return; 168 } 169 mYuvFormat = format; 170} 171 172 173void Type::Builder::setMipmaps(bool value) { 174 mDimMipmaps = value; 175} 176 177void Type::Builder::setFaces(bool value) { 178 mDimFaces = value; 179} 180 181sp<const Type> Type::Builder::create() { 182 if (mDimZ > 0) { 183 if ((mDimX < 1) || (mDimY < 1)) { 184 ALOGE("Both X and Y dimension required when Z is present."); 185 return nullptr; 186 } 187 if (mDimFaces) { 188 ALOGE("Cube maps not supported with 3D types."); 189 return nullptr; 190 } 191 } 192 if (mDimY > 0) { 193 if (mDimX < 1) { 194 ALOGE("X dimension required when Y is present."); 195 return nullptr; 196 } 197 } 198 if (mDimFaces) { 199 if (mDimY < 1) { 200 ALOGE("Cube maps require 2D Types."); 201 return nullptr; 202 } 203 } 204 205 if (mYuvFormat) { 206 if (mDimZ || mDimFaces || mDimMipmaps) { 207 ALOGE("YUV only supports basic 2D."); 208 return nullptr; 209 } 210 } 211 212 uint32_t nativeYuv; 213 switch(mYuvFormat) { 214 case(RS_YUV_YV12): 215 nativeYuv = HAL_PIXEL_FORMAT_YV12; 216 break; 217 case (RS_YUV_NV21): 218 nativeYuv = HAL_PIXEL_FORMAT_YCrCb_420_SP; 219 break; 220 default: 221 nativeYuv = 0; 222 } 223 224 void * id = RS::dispatch->TypeCreate(mRS->getContext(), mElement->getID(), mDimX, mDimY, mDimZ, 225 mDimMipmaps, mDimFaces, nativeYuv); 226 Type *t = new Type(id, mRS); 227 t->mElement = mElement; 228 t->mDimX = mDimX; 229 t->mDimY = mDimY; 230 t->mDimZ = mDimZ; 231 t->mDimMipmaps = mDimMipmaps; 232 t->mDimFaces = mDimFaces; 233 t->mYuvFormat = mYuvFormat; 234 235 t->calcElementCount(); 236 return t; 237} 238 239