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 android::RSC::Element; 30using android::RSC::RS; 31using android::RSC::Type; 32using android::RSC::sp; 33 34void 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 71Type::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 81void 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 112sp<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 129Type::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 140void 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 147void 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 154void 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 161void 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 178void Type::Builder::setMipmaps(bool value) { 179 mDimMipmaps = value; 180} 181 182void Type::Builder::setFaces(bool value) { 183 mDimFaces = value; 184} 185 186sp<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