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