rsAllocation.cpp revision b81a0eb8180791e4eaab1253b59fa8bd562b046b
1/* 2 * Copyright (C) 2009 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 "rsContext.h" 18#include "rs_hal.h" 19 20 21using namespace android; 22using namespace android::renderscript; 23 24Allocation::Allocation(Context *rsc, const Type *type, uint32_t usages, 25 RsAllocationMipmapControl mc) 26 : ObjectBase(rsc) { 27 28 memset(&mHal, 0, sizeof(mHal)); 29 mHal.state.mipmapControl = RS_ALLOCATION_MIPMAP_NONE; 30 mHal.state.usageFlags = usages; 31 mHal.state.mipmapControl = mc; 32 33 mHal.state.type.set(type); 34 updateCache(); 35} 36 37Allocation * Allocation::createAllocation(Context *rsc, const Type *type, uint32_t usages, 38 RsAllocationMipmapControl mc) { 39 Allocation *a = new Allocation(rsc, type, usages, mc); 40 41 if (!rsc->mHal.funcs.allocation.init(rsc, a, type->getElement()->getHasReferences())) { 42 rsc->setError(RS_ERROR_FATAL_DRIVER, "Allocation::Allocation, alloc failure"); 43 delete a; 44 return NULL; 45 } 46 return a; 47} 48 49void Allocation::updateCache() { 50 const Type *type = mHal.state.type.get(); 51 mHal.state.dimensionX = type->getDimX(); 52 mHal.state.dimensionY = type->getDimY(); 53 mHal.state.dimensionZ = type->getDimZ(); 54 mHal.state.hasFaces = type->getDimFaces(); 55 mHal.state.hasMipmaps = type->getDimLOD(); 56 mHal.state.elementSizeBytes = type->getElementSizeBytes(); 57 mHal.state.hasReferences = mHal.state.type->getElement()->getHasReferences(); 58} 59 60Allocation::~Allocation() { 61 mRSC->mHal.funcs.allocation.destroy(mRSC, this); 62} 63 64void Allocation::syncAll(Context *rsc, RsAllocationUsageType src) { 65 rsc->mHal.funcs.allocation.syncAll(rsc, this, src); 66} 67 68void Allocation::read(void *data) { 69 memcpy(data, getPtr(), mHal.state.type->getSizeBytes()); 70} 71 72void Allocation::data(Context *rsc, uint32_t xoff, uint32_t lod, 73 uint32_t count, const void *data, uint32_t sizeBytes) { 74 const uint32_t eSize = mHal.state.type->getElementSizeBytes(); 75 76 if ((count * eSize) != sizeBytes) { 77 LOGE("Allocation::subData called with mismatched size expected %i, got %i", 78 (count * eSize), sizeBytes); 79 mHal.state.type->dumpLOGV("type info"); 80 return; 81 } 82 83 rsc->mHal.funcs.allocation.data1D(rsc, this, xoff, lod, count, data, sizeBytes); 84 sendDirty(rsc); 85} 86 87void Allocation::data(Context *rsc, uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face, 88 uint32_t w, uint32_t h, const void *data, uint32_t sizeBytes) { 89 const uint32_t eSize = mHal.state.elementSizeBytes; 90 const uint32_t lineSize = eSize * w; 91 92 //LOGE("data2d %p, %i %i %i %i %i %i %p %i", this, xoff, yoff, lod, face, w, h, data, sizeBytes); 93 94 if ((lineSize * h) != sizeBytes) { 95 LOGE("Allocation size mismatch, expected %i, got %i", (lineSize * h), sizeBytes); 96 rsAssert(!"Allocation::subData called with mismatched size"); 97 return; 98 } 99 100 rsc->mHal.funcs.allocation.data2D(rsc, this, xoff, yoff, lod, face, w, h, data, sizeBytes); 101 sendDirty(rsc); 102} 103 104void Allocation::data(Context *rsc, uint32_t xoff, uint32_t yoff, uint32_t zoff, 105 uint32_t lod, RsAllocationCubemapFace face, 106 uint32_t w, uint32_t h, uint32_t d, const void *data, uint32_t sizeBytes) { 107} 108 109void Allocation::elementData(Context *rsc, uint32_t x, const void *data, 110 uint32_t cIdx, uint32_t sizeBytes) { 111 uint32_t eSize = mHal.state.elementSizeBytes; 112 113 if (cIdx >= mHal.state.type->getElement()->getFieldCount()) { 114 LOGE("Error Allocation::subElementData component %i out of range.", cIdx); 115 rsc->setError(RS_ERROR_BAD_VALUE, "subElementData component out of range."); 116 return; 117 } 118 119 if (x >= mHal.state.dimensionX) { 120 LOGE("Error Allocation::subElementData X offset %i out of range.", x); 121 rsc->setError(RS_ERROR_BAD_VALUE, "subElementData X offset out of range."); 122 return; 123 } 124 125 const Element * e = mHal.state.type->getElement()->getField(cIdx); 126 if (sizeBytes != e->getSizeBytes()) { 127 LOGE("Error Allocation::subElementData data size %i does not match field size %zu.", sizeBytes, e->getSizeBytes()); 128 rsc->setError(RS_ERROR_BAD_VALUE, "subElementData bad size."); 129 return; 130 } 131 132 rsc->mHal.funcs.allocation.elementData1D(rsc, this, x, data, cIdx, sizeBytes); 133 sendDirty(rsc); 134} 135 136void Allocation::elementData(Context *rsc, uint32_t x, uint32_t y, 137 const void *data, uint32_t cIdx, uint32_t sizeBytes) { 138 uint32_t eSize = mHal.state.elementSizeBytes; 139 140 if (x >= mHal.state.dimensionX) { 141 LOGE("Error Allocation::subElementData X offset %i out of range.", x); 142 rsc->setError(RS_ERROR_BAD_VALUE, "subElementData X offset out of range."); 143 return; 144 } 145 146 if (y >= mHal.state.dimensionY) { 147 LOGE("Error Allocation::subElementData X offset %i out of range.", x); 148 rsc->setError(RS_ERROR_BAD_VALUE, "subElementData X offset out of range."); 149 return; 150 } 151 152 if (cIdx >= mHal.state.type->getElement()->getFieldCount()) { 153 LOGE("Error Allocation::subElementData component %i out of range.", cIdx); 154 rsc->setError(RS_ERROR_BAD_VALUE, "subElementData component out of range."); 155 return; 156 } 157 158 const Element * e = mHal.state.type->getElement()->getField(cIdx); 159 160 if (sizeBytes != e->getSizeBytes()) { 161 LOGE("Error Allocation::subElementData data size %i does not match field size %zu.", sizeBytes, e->getSizeBytes()); 162 rsc->setError(RS_ERROR_BAD_VALUE, "subElementData bad size."); 163 return; 164 } 165 166 rsc->mHal.funcs.allocation.elementData2D(rsc, this, x, y, data, cIdx, sizeBytes); 167 sendDirty(rsc); 168} 169 170void Allocation::addProgramToDirty(const Program *p) { 171 mToDirtyList.push(p); 172} 173 174void Allocation::removeProgramToDirty(const Program *p) { 175 for (size_t ct=0; ct < mToDirtyList.size(); ct++) { 176 if (mToDirtyList[ct] == p) { 177 mToDirtyList.removeAt(ct); 178 return; 179 } 180 } 181 rsAssert(0); 182} 183 184void Allocation::dumpLOGV(const char *prefix) const { 185 ObjectBase::dumpLOGV(prefix); 186 187 String8 s(prefix); 188 s.append(" type "); 189 if (mHal.state.type.get()) { 190 mHal.state.type->dumpLOGV(s.string()); 191 } 192 193 LOGV("%s allocation ptr=%p mUsageFlags=0x04%x, mMipmapControl=0x%04x", 194 prefix, getPtr(), mHal.state.usageFlags, mHal.state.mipmapControl); 195} 196 197void Allocation::serialize(OStream *stream) const { 198 // Need to identify ourselves 199 stream->addU32((uint32_t)getClassId()); 200 201 String8 name(getName()); 202 stream->addString(&name); 203 204 // First thing we need to serialize is the type object since it will be needed 205 // to initialize the class 206 mHal.state.type->serialize(stream); 207 208 uint32_t dataSize = mHal.state.type->getSizeBytes(); 209 // Write how much data we are storing 210 stream->addU32(dataSize); 211 // Now write the data 212 stream->addByteArray(getPtr(), dataSize); 213} 214 215Allocation *Allocation::createFromStream(Context *rsc, IStream *stream) { 216 // First make sure we are reading the correct object 217 RsA3DClassID classID = (RsA3DClassID)stream->loadU32(); 218 if (classID != RS_A3D_CLASS_ID_ALLOCATION) { 219 LOGE("allocation loading skipped due to invalid class id\n"); 220 return NULL; 221 } 222 223 String8 name; 224 stream->loadString(&name); 225 226 Type *type = Type::createFromStream(rsc, stream); 227 if (!type) { 228 return NULL; 229 } 230 type->compute(); 231 232 // Number of bytes we wrote out for this allocation 233 uint32_t dataSize = stream->loadU32(); 234 if (dataSize != type->getSizeBytes()) { 235 LOGE("failed to read allocation because numbytes written is not the same loaded type wants\n"); 236 ObjectBase::checkDelete(type); 237 return NULL; 238 } 239 240 Allocation *alloc = Allocation::createAllocation(rsc, type, RS_ALLOCATION_USAGE_SCRIPT); 241 alloc->setName(name.string(), name.size()); 242 243 uint32_t count = dataSize / type->getElementSizeBytes(); 244 245 // Read in all of our allocation data 246 alloc->data(rsc, 0, 0, count, stream->getPtr() + stream->getPos(), dataSize); 247 stream->reset(stream->getPos() + dataSize); 248 249 return alloc; 250} 251 252void Allocation::sendDirty(const Context *rsc) const { 253 for (size_t ct=0; ct < mToDirtyList.size(); ct++) { 254 mToDirtyList[ct]->forceDirty(); 255 } 256 mRSC->mHal.funcs.allocation.markDirty(rsc, this); 257} 258 259void Allocation::incRefs(const void *ptr, size_t ct, size_t startOff) const { 260 const uint8_t *p = static_cast<const uint8_t *>(ptr); 261 const Element *e = mHal.state.type->getElement(); 262 uint32_t stride = e->getSizeBytes(); 263 264 p += stride * startOff; 265 while (ct > 0) { 266 e->incRefs(p); 267 ct --; 268 p += stride; 269 } 270} 271 272void Allocation::decRefs(const void *ptr, size_t ct, size_t startOff) const { 273 const uint8_t *p = static_cast<const uint8_t *>(ptr); 274 const Element *e = mHal.state.type->getElement(); 275 uint32_t stride = e->getSizeBytes(); 276 277 p += stride * startOff; 278 while (ct > 0) { 279 e->decRefs(p); 280 ct --; 281 p += stride; 282 } 283} 284 285void Allocation::copyRange1D(Context *rsc, const Allocation *src, int32_t srcOff, int32_t destOff, int32_t len) { 286} 287 288void Allocation::resize1D(Context *rsc, uint32_t dimX) { 289 uint32_t oldDimX = mHal.state.dimensionX; 290 if (dimX == oldDimX) { 291 return; 292 } 293 294 Type *t = mHal.state.type->cloneAndResize1D(rsc, dimX); 295 if (dimX < oldDimX) { 296 decRefs(getPtr(), oldDimX - dimX, dimX); 297 } 298 rsc->mHal.funcs.allocation.resize(rsc, this, t, mHal.state.hasReferences); 299 mHal.state.type.set(t); 300 updateCache(); 301} 302 303void Allocation::resize2D(Context *rsc, uint32_t dimX, uint32_t dimY) { 304 LOGE("not implemented"); 305} 306 307///////////////// 308// 309 310namespace android { 311namespace renderscript { 312 313static void AllocationGenerateScriptMips(RsContext con, RsAllocation va); 314 315static void mip565(const Adapter2D &out, const Adapter2D &in) { 316 uint32_t w = out.getDimX(); 317 uint32_t h = out.getDimY(); 318 319 for (uint32_t y=0; y < h; y++) { 320 uint16_t *oPtr = static_cast<uint16_t *>(out.getElement(0, y)); 321 const uint16_t *i1 = static_cast<uint16_t *>(in.getElement(0, y*2)); 322 const uint16_t *i2 = static_cast<uint16_t *>(in.getElement(0, y*2+1)); 323 324 for (uint32_t x=0; x < w; x++) { 325 *oPtr = rsBoxFilter565(i1[0], i1[1], i2[0], i2[1]); 326 oPtr ++; 327 i1 += 2; 328 i2 += 2; 329 } 330 } 331} 332 333static void mip8888(const Adapter2D &out, const Adapter2D &in) { 334 uint32_t w = out.getDimX(); 335 uint32_t h = out.getDimY(); 336 337 for (uint32_t y=0; y < h; y++) { 338 uint32_t *oPtr = static_cast<uint32_t *>(out.getElement(0, y)); 339 const uint32_t *i1 = static_cast<uint32_t *>(in.getElement(0, y*2)); 340 const uint32_t *i2 = static_cast<uint32_t *>(in.getElement(0, y*2+1)); 341 342 for (uint32_t x=0; x < w; x++) { 343 *oPtr = rsBoxFilter8888(i1[0], i1[1], i2[0], i2[1]); 344 oPtr ++; 345 i1 += 2; 346 i2 += 2; 347 } 348 } 349} 350 351static void mip8(const Adapter2D &out, const Adapter2D &in) { 352 uint32_t w = out.getDimX(); 353 uint32_t h = out.getDimY(); 354 355 for (uint32_t y=0; y < h; y++) { 356 uint8_t *oPtr = static_cast<uint8_t *>(out.getElement(0, y)); 357 const uint8_t *i1 = static_cast<uint8_t *>(in.getElement(0, y*2)); 358 const uint8_t *i2 = static_cast<uint8_t *>(in.getElement(0, y*2+1)); 359 360 for (uint32_t x=0; x < w; x++) { 361 *oPtr = (uint8_t)(((uint32_t)i1[0] + i1[1] + i2[0] + i2[1]) * 0.25f); 362 oPtr ++; 363 i1 += 2; 364 i2 += 2; 365 } 366 } 367} 368 369static void mip(const Adapter2D &out, const Adapter2D &in) { 370 switch (out.getBaseType()->getElement()->getSizeBits()) { 371 case 32: 372 mip8888(out, in); 373 break; 374 case 16: 375 mip565(out, in); 376 break; 377 case 8: 378 mip8(out, in); 379 break; 380 } 381} 382 383void rsi_AllocationSyncAll(Context *rsc, RsAllocation va, RsAllocationUsageType src) { 384 Allocation *a = static_cast<Allocation *>(va); 385 a->sendDirty(rsc); 386 a->syncAll(rsc, src); 387} 388 389void rsi_AllocationGenerateMipmaps(Context *rsc, RsAllocation va) { 390 Allocation *texAlloc = static_cast<Allocation *>(va); 391 AllocationGenerateScriptMips(rsc, texAlloc); 392} 393 394void rsi_AllocationCopyToBitmap(Context *rsc, RsAllocation va, void *data, size_t dataLen) { 395 Allocation *texAlloc = static_cast<Allocation *>(va); 396 const Type * t = texAlloc->getType(); 397 398 size_t s = t->getDimX() * t->getDimY() * t->getElementSizeBytes(); 399 if (s != dataLen) { 400 rsc->setError(RS_ERROR_BAD_VALUE, "Bitmap size didn't match allocation size"); 401 return; 402 } 403 404 memcpy(data, texAlloc->getPtr(), s); 405} 406 407void rsi_Allocation1DData(Context *rsc, RsAllocation va, uint32_t xoff, uint32_t lod, 408 uint32_t count, const void *data, size_t sizeBytes) { 409 Allocation *a = static_cast<Allocation *>(va); 410 a->data(rsc, xoff, lod, count, data, sizeBytes); 411} 412 413void rsi_Allocation2DElementData(Context *rsc, RsAllocation va, uint32_t x, uint32_t y, uint32_t lod, RsAllocationCubemapFace face, 414 const void *data, size_t eoff, uint32_t sizeBytes) { // TODO: this seems wrong, eoff and sizeBytes may be swapped 415 Allocation *a = static_cast<Allocation *>(va); 416 a->elementData(rsc, x, y, data, eoff, sizeBytes); 417} 418 419void rsi_Allocation1DElementData(Context *rsc, RsAllocation va, uint32_t x, uint32_t lod, 420 const void *data, size_t eoff, uint32_t sizeBytes) { // TODO: this seems wrong, eoff and sizeBytes may be swapped 421 Allocation *a = static_cast<Allocation *>(va); 422 a->elementData(rsc, x, data, eoff, sizeBytes); 423} 424 425void rsi_Allocation2DData(Context *rsc, RsAllocation va, uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face, 426 uint32_t w, uint32_t h, const void *data, size_t sizeBytes) { 427 Allocation *a = static_cast<Allocation *>(va); 428 a->data(rsc, xoff, yoff, lod, face, w, h, data, sizeBytes); 429} 430 431void rsi_AllocationRead(Context *rsc, RsAllocation va, void *data, size_t data_length) { 432 Allocation *a = static_cast<Allocation *>(va); 433 a->read(data); 434} 435 436void rsi_AllocationResize1D(Context *rsc, RsAllocation va, uint32_t dimX) { 437 Allocation *a = static_cast<Allocation *>(va); 438 a->resize1D(rsc, dimX); 439} 440 441void rsi_AllocationResize2D(Context *rsc, RsAllocation va, uint32_t dimX, uint32_t dimY) { 442 Allocation *a = static_cast<Allocation *>(va); 443 a->resize2D(rsc, dimX, dimY); 444} 445 446static void AllocationGenerateScriptMips(RsContext con, RsAllocation va) { 447 Context *rsc = static_cast<Context *>(con); 448 Allocation *texAlloc = static_cast<Allocation *>(va); 449 uint32_t numFaces = texAlloc->getType()->getDimFaces() ? 6 : 1; 450 for (uint32_t face = 0; face < numFaces; face ++) { 451 Adapter2D adapt(rsc, texAlloc); 452 Adapter2D adapt2(rsc, texAlloc); 453 adapt.setFace(face); 454 adapt2.setFace(face); 455 for (uint32_t lod=0; lod < (texAlloc->getType()->getLODCount() -1); lod++) { 456 adapt.setLOD(lod); 457 adapt2.setLOD(lod + 1); 458 mip(adapt2, adapt); 459 } 460 } 461} 462 463RsAllocation rsi_AllocationCreateTyped(Context *rsc, RsType vtype, 464 RsAllocationMipmapControl mips, 465 uint32_t usages) { 466 Allocation * alloc = Allocation::createAllocation(rsc, static_cast<Type *>(vtype), usages, mips); 467 if (!alloc) { 468 return NULL; 469 } 470 alloc->incUserRef(); 471 return alloc; 472} 473 474RsAllocation rsi_AllocationCreateFromBitmap(Context *rsc, RsType vtype, 475 RsAllocationMipmapControl mips, 476 const void *data, size_t data_length, uint32_t usages) { 477 Type *t = static_cast<Type *>(vtype); 478 479 RsAllocation vTexAlloc = rsi_AllocationCreateTyped(rsc, vtype, mips, usages); 480 Allocation *texAlloc = static_cast<Allocation *>(vTexAlloc); 481 if (texAlloc == NULL) { 482 LOGE("Memory allocation failure"); 483 return NULL; 484 } 485 486 memcpy(texAlloc->getPtr(), data, t->getDimX() * t->getDimY() * t->getElementSizeBytes()); 487 if (mips == RS_ALLOCATION_MIPMAP_FULL) { 488 AllocationGenerateScriptMips(rsc, texAlloc); 489 } 490 491 texAlloc->sendDirty(rsc); 492 return texAlloc; 493} 494 495RsAllocation rsi_AllocationCubeCreateFromBitmap(Context *rsc, RsType vtype, 496 RsAllocationMipmapControl mips, 497 const void *data, size_t data_length, uint32_t usages) { 498 Type *t = static_cast<Type *>(vtype); 499 500 // Cubemap allocation's faces should be Width by Width each. 501 // Source data should have 6 * Width by Width pixels 502 // Error checking is done in the java layer 503 RsAllocation vTexAlloc = rsi_AllocationCreateTyped(rsc, vtype, mips, usages); 504 Allocation *texAlloc = static_cast<Allocation *>(vTexAlloc); 505 if (texAlloc == NULL) { 506 LOGE("Memory allocation failure"); 507 return NULL; 508 } 509 510 uint32_t faceSize = t->getDimX(); 511 uint32_t strideBytes = faceSize * 6 * t->getElementSizeBytes(); 512 uint32_t copySize = faceSize * t->getElementSizeBytes(); 513 514 uint8_t *sourcePtr = (uint8_t*)data; 515 for (uint32_t face = 0; face < 6; face ++) { 516 Adapter2D faceAdapter(rsc, texAlloc); 517 faceAdapter.setFace(face); 518 519 for (uint32_t dI = 0; dI < faceSize; dI ++) { 520 memcpy(faceAdapter.getElement(0, dI), sourcePtr + strideBytes * dI, copySize); 521 } 522 523 // Move the data pointer to the next cube face 524 sourcePtr += copySize; 525 } 526 527 if (mips == RS_ALLOCATION_MIPMAP_FULL) { 528 AllocationGenerateScriptMips(rsc, texAlloc); 529 } 530 531 texAlloc->sendDirty(rsc); 532 return texAlloc; 533} 534 535} 536} 537 538const void * rsaAllocationGetType(RsContext con, RsAllocation va) { 539 Allocation *a = static_cast<Allocation *>(va); 540 a->getType()->incUserRef(); 541 542 return a->getType(); 543} 544