rsAllocation.cpp revision 5f0c84cf464dda719cef65fdc9b4d0980e86b98f
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#ifndef ANDROID_RS_BUILD_FOR_HOST 17#include "rsContext.h" 18 19#include <GLES/gl.h> 20#include <GLES2/gl2.h> 21#include <GLES/glext.h> 22#else 23#include "rsContextHostStub.h" 24 25#include <OpenGL/gl.h> 26#include <OpenGl/glext.h> 27#endif 28 29using namespace android; 30using namespace android::renderscript; 31 32Allocation::Allocation(Context *rsc, const Type *type) : ObjectBase(rsc) 33{ 34 init(rsc, type); 35 36 mPtr = malloc(mType->getSizeBytes()); 37 if (mType->getElement()->getHasReferences()) { 38 memset(mPtr, 0, mType->getSizeBytes()); 39 } 40 if (!mPtr) { 41 LOGE("Allocation::Allocation, alloc failure"); 42 } 43} 44 45Allocation::Allocation(Context *rsc, const Type *type, void *bmp, 46 void *callbackData, RsBitmapCallback_t callback) 47: ObjectBase(rsc) 48{ 49 init(rsc, type); 50 51 mPtr = bmp; 52 mUserBitmapCallback = callback; 53 mUserBitmapCallbackData = callbackData; 54} 55 56void Allocation::init(Context *rsc, const Type *type) 57{ 58 mAllocFile = __FILE__; 59 mAllocLine = __LINE__; 60 mPtr = NULL; 61 62 mCpuWrite = false; 63 mCpuRead = false; 64 mGpuWrite = false; 65 mGpuRead = false; 66 67 mReadWriteRatio = 0; 68 mUpdateSize = 0; 69 70 mIsTexture = false; 71 mTextureID = 0; 72 mIsVertexBuffer = false; 73 mBufferID = 0; 74 mUploadDefered = false; 75 76 mUserBitmapCallback = NULL; 77 mUserBitmapCallbackData = NULL; 78 79 mType.set(type); 80 rsAssert(type); 81 82 mPtr = NULL; 83} 84 85Allocation::~Allocation() 86{ 87 if (mUserBitmapCallback != NULL) { 88 mUserBitmapCallback(mUserBitmapCallbackData); 89 } else { 90 free(mPtr); 91 } 92 mPtr = NULL; 93 94 if (mBufferID) { 95 // Causes a SW crash.... 96 //LOGV(" mBufferID %i", mBufferID); 97 //glDeleteBuffers(1, &mBufferID); 98 //mBufferID = 0; 99 } 100 if (mTextureID) { 101 glDeleteTextures(1, &mTextureID); 102 mTextureID = 0; 103 } 104} 105 106void Allocation::setCpuWritable(bool) 107{ 108} 109 110void Allocation::setGpuWritable(bool) 111{ 112} 113 114void Allocation::setCpuReadable(bool) 115{ 116} 117 118void Allocation::setGpuReadable(bool) 119{ 120} 121 122bool Allocation::fixAllocation() 123{ 124 return false; 125} 126 127void Allocation::deferedUploadToTexture(const Context *rsc, bool genMipmap, uint32_t lodOffset) 128{ 129 rsAssert(lodOffset < mType->getLODCount()); 130 mIsTexture = true; 131 mTextureLOD = lodOffset; 132 mUploadDefered = true; 133 mTextureGenMipmap = !mType->getDimLOD() && genMipmap; 134} 135 136void Allocation::uploadToTexture(const Context *rsc) 137{ 138 //rsAssert(!mTextureId); 139 140 mIsTexture = true; 141 if (!rsc->checkDriver()) { 142 mUploadDefered = true; 143 return; 144 } 145 146 GLenum type = mType->getElement()->getComponent().getGLType(); 147 GLenum format = mType->getElement()->getComponent().getGLFormat(); 148 149 if (!type || !format) { 150 return; 151 } 152 153 if (!mTextureID) { 154 glGenTextures(1, &mTextureID); 155 156 if (!mTextureID) { 157 // This should not happen, however, its likely the cause of the 158 // white sqare bug. 159 // Force a crash to 1: restart the app, 2: make sure we get a bugreport. 160 LOGE("Upload to texture failed to gen mTextureID"); 161 rsc->dumpDebug(); 162 mUploadDefered = true; 163 return; 164 } 165 } 166 glBindTexture(GL_TEXTURE_2D, mTextureID); 167 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 168 169 Adapter2D adapt(getContext(), this); 170 for(uint32_t lod = 0; (lod + mTextureLOD) < mType->getLODCount(); lod++) { 171 adapt.setLOD(lod+mTextureLOD); 172 173 uint16_t * ptr = static_cast<uint16_t *>(adapt.getElement(0,0)); 174 glTexImage2D(GL_TEXTURE_2D, lod, format, 175 adapt.getDimX(), adapt.getDimY(), 176 0, format, type, ptr); 177 } 178 if (mTextureGenMipmap) { 179#ifndef ANDROID_RS_BUILD_FOR_HOST 180 glGenerateMipmap(GL_TEXTURE_2D); 181#endif //ANDROID_RS_BUILD_FOR_HOST 182 } 183 184 rsc->checkError("Allocation::uploadToTexture"); 185} 186 187void Allocation::deferedUploadToBufferObject(const Context *rsc) 188{ 189 mIsVertexBuffer = true; 190 mUploadDefered = true; 191} 192 193void Allocation::uploadToBufferObject(const Context *rsc) 194{ 195 rsAssert(!mType->getDimY()); 196 rsAssert(!mType->getDimZ()); 197 198 mIsVertexBuffer = true; 199 if (!rsc->checkDriver()) { 200 mUploadDefered = true; 201 return; 202 } 203 204 if (!mBufferID) { 205 glGenBuffers(1, &mBufferID); 206 } 207 if (!mBufferID) { 208 LOGE("Upload to buffer object failed"); 209 mUploadDefered = true; 210 return; 211 } 212 213 glBindBuffer(GL_ARRAY_BUFFER, mBufferID); 214 glBufferData(GL_ARRAY_BUFFER, mType->getSizeBytes(), getPtr(), GL_DYNAMIC_DRAW); 215 glBindBuffer(GL_ARRAY_BUFFER, 0); 216 rsc->checkError("Allocation::uploadToBufferObject"); 217} 218 219void Allocation::uploadCheck(const Context *rsc) 220{ 221 if (mUploadDefered) { 222 mUploadDefered = false; 223 if (mIsVertexBuffer) { 224 uploadToBufferObject(rsc); 225 } 226 if (mIsTexture) { 227 uploadToTexture(rsc); 228 } 229 } 230} 231 232 233void Allocation::data(Context *rsc, const void *data, uint32_t sizeBytes) 234{ 235 uint32_t size = mType->getSizeBytes(); 236 if (size != sizeBytes) { 237 LOGE("Allocation::data called with mismatched size expected %i, got %i", size, sizeBytes); 238 return; 239 } 240 241 if (mType->getElement()->getHasReferences()) { 242 incRefs(data, sizeBytes / mType->getElement()->getSizeBytes()); 243 decRefs(mPtr, sizeBytes / mType->getElement()->getSizeBytes()); 244 } 245 246 memcpy(mPtr, data, size); 247 sendDirty(); 248 mUploadDefered = true; 249} 250 251void Allocation::read(void *data) 252{ 253 memcpy(data, mPtr, mType->getSizeBytes()); 254} 255 256void Allocation::subData(Context *rsc, uint32_t xoff, uint32_t count, const void *data, uint32_t sizeBytes) 257{ 258 uint32_t eSize = mType->getElementSizeBytes(); 259 uint8_t * ptr = static_cast<uint8_t *>(mPtr); 260 ptr += eSize * xoff; 261 uint32_t size = count * eSize; 262 263 if (size != sizeBytes) { 264 LOGE("Allocation::subData called with mismatched size expected %i, got %i", size, sizeBytes); 265 mType->dumpLOGV("type info"); 266 return; 267 } 268 269 if (mType->getElement()->getHasReferences()) { 270 incRefs(data, count); 271 decRefs(ptr, count); 272 } 273 274 memcpy(ptr, data, size); 275 sendDirty(); 276 mUploadDefered = true; 277} 278 279void Allocation::subData(Context *rsc, uint32_t xoff, uint32_t yoff, 280 uint32_t w, uint32_t h, const void *data, uint32_t sizeBytes) 281{ 282 uint32_t eSize = mType->getElementSizeBytes(); 283 uint32_t lineSize = eSize * w; 284 uint32_t destW = mType->getDimX(); 285 286 const uint8_t *src = static_cast<const uint8_t *>(data); 287 uint8_t *dst = static_cast<uint8_t *>(mPtr); 288 dst += eSize * (xoff + yoff * destW); 289 290 if ((lineSize * eSize * h) != sizeBytes) { 291 rsAssert(!"Allocation::subData called with mismatched size"); 292 return; 293 } 294 295 for (uint32_t line=yoff; line < (yoff+h); line++) { 296 uint8_t * ptr = static_cast<uint8_t *>(mPtr); 297 if (mType->getElement()->getHasReferences()) { 298 incRefs(src, w); 299 decRefs(dst, w); 300 } 301 memcpy(dst, src, lineSize); 302 src += lineSize; 303 dst += destW * eSize; 304 } 305 sendDirty(); 306 mUploadDefered = true; 307} 308 309void Allocation::subData(Context *rsc, uint32_t xoff, uint32_t yoff, uint32_t zoff, 310 uint32_t w, uint32_t h, uint32_t d, const void *data, uint32_t sizeBytes) 311{ 312} 313 314void Allocation::subElementData(Context *rsc, uint32_t x, const void *data, 315 uint32_t cIdx, uint32_t sizeBytes) 316{ 317 uint32_t eSize = mType->getElementSizeBytes(); 318 uint8_t * ptr = static_cast<uint8_t *>(mPtr); 319 ptr += eSize * x; 320 321 if (cIdx >= mType->getElement()->getFieldCount()) { 322 LOGE("Error Allocation::subElementData component %i out of range.", cIdx); 323 rsc->setError(RS_ERROR_BAD_VALUE, "subElementData component out of range."); 324 return; 325 } 326 327 if (x >= mType->getDimX()) { 328 LOGE("Error Allocation::subElementData X offset %i out of range.", x); 329 rsc->setError(RS_ERROR_BAD_VALUE, "subElementData X offset out of range."); 330 return; 331 } 332 333 const Element * e = mType->getElement()->getField(cIdx); 334 ptr += mType->getElement()->getFieldOffsetBytes(cIdx); 335 336 if (sizeBytes != e->getSizeBytes()) { 337 LOGE("Error Allocation::subElementData data size %i does not match field size %i.", sizeBytes, e->getSizeBytes()); 338 rsc->setError(RS_ERROR_BAD_VALUE, "subElementData bad size."); 339 return; 340 } 341 342 if (e->getHasReferences()) { 343 e->incRefs(data); 344 e->decRefs(ptr); 345 } 346 347 memcpy(ptr, data, sizeBytes); 348 sendDirty(); 349 mUploadDefered = true; 350} 351 352void Allocation::subElementData(Context *rsc, uint32_t x, uint32_t y, 353 const void *data, uint32_t cIdx, uint32_t sizeBytes) 354{ 355 uint32_t eSize = mType->getElementSizeBytes(); 356 uint8_t * ptr = static_cast<uint8_t *>(mPtr); 357 ptr += eSize * (x + y * mType->getDimX()); 358 359 if (x >= mType->getDimX()) { 360 LOGE("Error Allocation::subElementData X offset %i out of range.", x); 361 rsc->setError(RS_ERROR_BAD_VALUE, "subElementData X offset out of range."); 362 return; 363 } 364 365 if (y >= mType->getDimY()) { 366 LOGE("Error Allocation::subElementData X offset %i out of range.", x); 367 rsc->setError(RS_ERROR_BAD_VALUE, "subElementData X offset out of range."); 368 return; 369 } 370 371 if (cIdx >= mType->getElement()->getFieldCount()) { 372 LOGE("Error Allocation::subElementData component %i out of range.", cIdx); 373 rsc->setError(RS_ERROR_BAD_VALUE, "subElementData component out of range."); 374 return; 375 } 376 377 const Element * e = mType->getElement()->getField(cIdx); 378 ptr += mType->getElement()->getFieldOffsetBytes(cIdx); 379 380 if (sizeBytes != e->getSizeBytes()) { 381 LOGE("Error Allocation::subElementData data size %i does not match field size %i.", sizeBytes, e->getSizeBytes()); 382 rsc->setError(RS_ERROR_BAD_VALUE, "subElementData bad size."); 383 return; 384 } 385 386 if (e->getHasReferences()) { 387 e->incRefs(data); 388 e->decRefs(ptr); 389 } 390 391 memcpy(ptr, data, sizeBytes); 392 sendDirty(); 393 mUploadDefered = true; 394} 395 396void Allocation::addProgramToDirty(const Program *p) 397{ 398 mToDirtyList.push(p); 399} 400 401void Allocation::removeProgramToDirty(const Program *p) 402{ 403 for (size_t ct=0; ct < mToDirtyList.size(); ct++) { 404 if (mToDirtyList[ct] == p) { 405 mToDirtyList.removeAt(ct); 406 return; 407 } 408 } 409 rsAssert(0); 410} 411 412void Allocation::dumpLOGV(const char *prefix) const 413{ 414 ObjectBase::dumpLOGV(prefix); 415 416 String8 s(prefix); 417 s.append(" type "); 418 if (mType.get()) { 419 mType->dumpLOGV(s.string()); 420 } 421 422 LOGV("%s allocation ptr=%p mCpuWrite=%i, mCpuRead=%i, mGpuWrite=%i, mGpuRead=%i", 423 prefix, mPtr, mCpuWrite, mCpuRead, mGpuWrite, mGpuRead); 424 425 LOGV("%s allocation mIsTexture=%i mTextureID=%i, mIsVertexBuffer=%i, mBufferID=%i", 426 prefix, mIsTexture, mTextureID, mIsVertexBuffer, mBufferID); 427 428} 429 430void Allocation::serialize(OStream *stream) const 431{ 432 // Need to identify ourselves 433 stream->addU32((uint32_t)getClassId()); 434 435 String8 name(getName()); 436 stream->addString(&name); 437 438 // First thing we need to serialize is the type object since it will be needed 439 // to initialize the class 440 mType->serialize(stream); 441 442 uint32_t dataSize = mType->getSizeBytes(); 443 // Write how much data we are storing 444 stream->addU32(dataSize); 445 // Now write the data 446 stream->addByteArray(mPtr, dataSize); 447} 448 449Allocation *Allocation::createFromStream(Context *rsc, IStream *stream) 450{ 451 // First make sure we are reading the correct object 452 RsA3DClassID classID = (RsA3DClassID)stream->loadU32(); 453 if(classID != RS_A3D_CLASS_ID_ALLOCATION) { 454 LOGE("allocation loading skipped due to invalid class id\n"); 455 return NULL; 456 } 457 458 String8 name; 459 stream->loadString(&name); 460 461 Type *type = Type::createFromStream(rsc, stream); 462 if(!type) { 463 return NULL; 464 } 465 type->compute(); 466 467 // Number of bytes we wrote out for this allocation 468 uint32_t dataSize = stream->loadU32(); 469 if(dataSize != type->getSizeBytes()) { 470 LOGE("failed to read allocation because numbytes written is not the same loaded type wants\n"); 471 delete type; 472 return NULL; 473 } 474 475 Allocation *alloc = new Allocation(rsc, type); 476 alloc->setName(name.string(), name.size()); 477 478 // Read in all of our allocation data 479 alloc->data(rsc, stream->getPtr() + stream->getPos(), dataSize); 480 stream->reset(stream->getPos() + dataSize); 481 482 return alloc; 483} 484 485void Allocation::sendDirty() const 486{ 487 for (size_t ct=0; ct < mToDirtyList.size(); ct++) { 488 mToDirtyList[ct]->forceDirty(); 489 } 490} 491 492void Allocation::incRefs(const void *ptr, size_t ct) const 493{ 494 const uint8_t *p = static_cast<const uint8_t *>(ptr); 495 const Element *e = mType->getElement(); 496 uint32_t stride = e->getSizeBytes(); 497 498 while (ct > 0) { 499 e->incRefs(p); 500 ct --; 501 p += stride; 502 } 503} 504 505void Allocation::decRefs(const void *ptr, size_t ct) const 506{ 507 const uint8_t *p = static_cast<const uint8_t *>(ptr); 508 const Element *e = mType->getElement(); 509 uint32_t stride = e->getSizeBytes(); 510 511 while (ct > 0) { 512 e->decRefs(p); 513 ct --; 514 p += stride; 515 } 516} 517 518///////////////// 519// 520 521 522namespace android { 523namespace renderscript { 524 525RsAllocation rsi_AllocationCreateTyped(Context *rsc, RsType vtype) 526{ 527 const Type * type = static_cast<const Type *>(vtype); 528 529 Allocation * alloc = new Allocation(rsc, type); 530 alloc->incUserRef(); 531 return alloc; 532} 533 534RsAllocation rsi_AllocationCreateSized(Context *rsc, RsElement e, size_t count) 535{ 536 Type * type = new Type(rsc); 537 type->setDimX(count); 538 type->setElement(static_cast<Element *>(e)); 539 type->compute(); 540 return rsi_AllocationCreateTyped(rsc, type); 541} 542 543void rsi_AllocationUploadToTexture(Context *rsc, RsAllocation va, bool genmip, uint32_t baseMipLevel) 544{ 545 Allocation *alloc = static_cast<Allocation *>(va); 546 alloc->deferedUploadToTexture(rsc, genmip, baseMipLevel); 547} 548 549void rsi_AllocationUploadToBufferObject(Context *rsc, RsAllocation va) 550{ 551 Allocation *alloc = static_cast<Allocation *>(va); 552 alloc->deferedUploadToBufferObject(rsc); 553} 554 555static void mip565(const Adapter2D &out, const Adapter2D &in) 556{ 557 uint32_t w = out.getDimX(); 558 uint32_t h = out.getDimY(); 559 560 for (uint32_t y=0; y < h; y++) { 561 uint16_t *oPtr = static_cast<uint16_t *>(out.getElement(0, y)); 562 const uint16_t *i1 = static_cast<uint16_t *>(in.getElement(0, y*2)); 563 const uint16_t *i2 = static_cast<uint16_t *>(in.getElement(0, y*2+1)); 564 565 for (uint32_t x=0; x < w; x++) { 566 *oPtr = rsBoxFilter565(i1[0], i1[1], i2[0], i2[1]); 567 oPtr ++; 568 i1 += 2; 569 i2 += 2; 570 } 571 } 572} 573 574static void mip8888(const Adapter2D &out, const Adapter2D &in) 575{ 576 uint32_t w = out.getDimX(); 577 uint32_t h = out.getDimY(); 578 579 for (uint32_t y=0; y < h; y++) { 580 uint32_t *oPtr = static_cast<uint32_t *>(out.getElement(0, y)); 581 const uint32_t *i1 = static_cast<uint32_t *>(in.getElement(0, y*2)); 582 const uint32_t *i2 = static_cast<uint32_t *>(in.getElement(0, y*2+1)); 583 584 for (uint32_t x=0; x < w; x++) { 585 *oPtr = rsBoxFilter8888(i1[0], i1[1], i2[0], i2[1]); 586 oPtr ++; 587 i1 += 2; 588 i2 += 2; 589 } 590 } 591} 592 593static void mip8(const Adapter2D &out, const Adapter2D &in) 594{ 595 uint32_t w = out.getDimX(); 596 uint32_t h = out.getDimY(); 597 598 for (uint32_t y=0; y < h; y++) { 599 uint8_t *oPtr = static_cast<uint8_t *>(out.getElement(0, y)); 600 const uint8_t *i1 = static_cast<uint8_t *>(in.getElement(0, y*2)); 601 const uint8_t *i2 = static_cast<uint8_t *>(in.getElement(0, y*2+1)); 602 603 for (uint32_t x=0; x < w; x++) { 604 *oPtr = (uint8_t)(((uint32_t)i1[0] + i1[1] + i2[0] + i2[1]) * 0.25f); 605 oPtr ++; 606 i1 += 2; 607 i2 += 2; 608 } 609 } 610} 611 612static void mip(const Adapter2D &out, const Adapter2D &in) 613{ 614 switch(out.getBaseType()->getElement()->getSizeBits()) { 615 case 32: 616 mip8888(out, in); 617 break; 618 case 16: 619 mip565(out, in); 620 break; 621 case 8: 622 mip8(out, in); 623 break; 624 625 } 626 627} 628 629typedef void (*ElementConverter_t)(void *dst, const void *src, uint32_t count); 630 631static void elementConverter_cpy_16(void *dst, const void *src, uint32_t count) 632{ 633 memcpy(dst, src, count * 2); 634} 635static void elementConverter_cpy_8(void *dst, const void *src, uint32_t count) 636{ 637 memcpy(dst, src, count); 638} 639static void elementConverter_cpy_32(void *dst, const void *src, uint32_t count) 640{ 641 memcpy(dst, src, count * 4); 642} 643 644 645static void elementConverter_888_to_565(void *dst, const void *src, uint32_t count) 646{ 647 uint16_t *d = static_cast<uint16_t *>(dst); 648 const uint8_t *s = static_cast<const uint8_t *>(src); 649 650 while(count--) { 651 *d = rs888to565(s[0], s[1], s[2]); 652 d++; 653 s+= 3; 654 } 655} 656 657static void elementConverter_8888_to_565(void *dst, const void *src, uint32_t count) 658{ 659 uint16_t *d = static_cast<uint16_t *>(dst); 660 const uint8_t *s = static_cast<const uint8_t *>(src); 661 662 while(count--) { 663 *d = rs888to565(s[0], s[1], s[2]); 664 d++; 665 s+= 4; 666 } 667} 668 669static ElementConverter_t pickConverter(const Element *dst, const Element *src) 670{ 671 GLenum srcGLType = src->getComponent().getGLType(); 672 GLenum srcGLFmt = src->getComponent().getGLFormat(); 673 GLenum dstGLType = dst->getComponent().getGLType(); 674 GLenum dstGLFmt = dst->getComponent().getGLFormat(); 675 676 if (srcGLFmt == dstGLFmt && srcGLType == dstGLType) { 677 switch(dst->getSizeBytes()) { 678 case 4: 679 return elementConverter_cpy_32; 680 case 2: 681 return elementConverter_cpy_16; 682 case 1: 683 return elementConverter_cpy_8; 684 } 685 } 686 687 if (srcGLType == GL_UNSIGNED_BYTE && 688 srcGLFmt == GL_RGB && 689 dstGLType == GL_UNSIGNED_SHORT_5_6_5 && 690 dstGLFmt == GL_RGB) { 691 692 return elementConverter_888_to_565; 693 } 694 695 if (srcGLType == GL_UNSIGNED_BYTE && 696 srcGLFmt == GL_RGBA && 697 dstGLType == GL_UNSIGNED_SHORT_5_6_5 && 698 dstGLFmt == GL_RGB) { 699 700 return elementConverter_8888_to_565; 701 } 702 703 LOGE("pickConverter, unsuported combo, src %p, dst %p", src, dst); 704 LOGE("pickConverter, srcGLType = %x, srcGLFmt = %x", srcGLType, srcGLFmt); 705 LOGE("pickConverter, dstGLType = %x, dstGLFmt = %x", dstGLType, dstGLFmt); 706 src->dumpLOGV("SRC "); 707 dst->dumpLOGV("DST "); 708 return 0; 709} 710 711#ifndef ANDROID_RS_BUILD_FOR_HOST 712 713RsAllocation rsi_AllocationCreateBitmapRef(Context *rsc, RsType vtype, 714 void *bmp, void *callbackData, RsBitmapCallback_t callback) 715{ 716 const Type * type = static_cast<const Type *>(vtype); 717 Allocation * alloc = new Allocation(rsc, type, bmp, callbackData, callback); 718 alloc->incUserRef(); 719 return alloc; 720} 721 722RsAllocation rsi_AllocationCreateFromBitmap(Context *rsc, uint32_t w, uint32_t h, RsElement _dst, RsElement _src, bool genMips, const void *data) 723{ 724 const Element *src = static_cast<const Element *>(_src); 725 const Element *dst = static_cast<const Element *>(_dst); 726 727 // Check for pow2 on pre es 2.0 versions. 728 rsAssert(rsc->checkVersion2_0() || (!(w & (w-1)) && !(h & (h-1)))); 729 730 //LOGE("rsi_AllocationCreateFromBitmap %i %i %i %i %i", w, h, dstFmt, srcFmt, genMips); 731 rsi_TypeBegin(rsc, _dst); 732 rsi_TypeAdd(rsc, RS_DIMENSION_X, w); 733 rsi_TypeAdd(rsc, RS_DIMENSION_Y, h); 734 if (genMips) { 735 rsi_TypeAdd(rsc, RS_DIMENSION_LOD, 1); 736 } 737 RsType type = rsi_TypeCreate(rsc); 738 739 RsAllocation vTexAlloc = rsi_AllocationCreateTyped(rsc, type); 740 Allocation *texAlloc = static_cast<Allocation *>(vTexAlloc); 741 if (texAlloc == NULL) { 742 LOGE("Memory allocation failure"); 743 return NULL; 744 } 745 746 ElementConverter_t cvt = pickConverter(dst, src); 747 if (cvt) { 748 cvt(texAlloc->getPtr(), data, w * h); 749 if (genMips) { 750 Adapter2D adapt(rsc, texAlloc); 751 Adapter2D adapt2(rsc, texAlloc); 752 for(uint32_t lod=0; lod < (texAlloc->getType()->getLODCount() -1); lod++) { 753 adapt.setLOD(lod); 754 adapt2.setLOD(lod + 1); 755 mip(adapt2, adapt); 756 } 757 } 758 } else { 759 rsc->setError(RS_ERROR_BAD_VALUE, "Unsupported bitmap format"); 760 } 761 762 return texAlloc; 763} 764 765RsAllocation rsi_AllocationCreateFromBitmapBoxed(Context *rsc, uint32_t w, uint32_t h, RsElement _dst, RsElement _src, bool genMips, const void *data) 766{ 767 const Element *srcE = static_cast<const Element *>(_src); 768 const Element *dstE = static_cast<const Element *>(_dst); 769 uint32_t w2 = rsHigherPow2(w); 770 uint32_t h2 = rsHigherPow2(h); 771 772 if ((w2 == w) && (h2 == h)) { 773 return rsi_AllocationCreateFromBitmap(rsc, w, h, _dst, _src, genMips, data); 774 } 775 776 uint32_t bpp = srcE->getSizeBytes(); 777 size_t size = w2 * h2 * bpp; 778 uint8_t *tmp = static_cast<uint8_t *>(malloc(size)); 779 memset(tmp, 0, size); 780 781 const uint8_t * src = static_cast<const uint8_t *>(data); 782 for (uint32_t y = 0; y < h; y++) { 783 uint8_t * ydst = &tmp[(y + ((h2 - h) >> 1)) * w2 * bpp]; 784 memcpy(&ydst[((w2 - w) >> 1) * bpp], src, w * bpp); 785 src += w * bpp; 786 } 787 788 RsAllocation ret = rsi_AllocationCreateFromBitmap(rsc, w2, h2, _dst, _src, genMips, tmp); 789 free(tmp); 790 return ret; 791} 792 793void rsi_AllocationData(Context *rsc, RsAllocation va, const void *data, uint32_t sizeBytes) 794{ 795 Allocation *a = static_cast<Allocation *>(va); 796 a->data(rsc, data, sizeBytes); 797} 798 799void rsi_Allocation1DSubData(Context *rsc, RsAllocation va, uint32_t xoff, uint32_t count, const void *data, uint32_t sizeBytes) 800{ 801 Allocation *a = static_cast<Allocation *>(va); 802 a->subData(rsc, xoff, count, data, sizeBytes); 803} 804 805void rsi_Allocation2DSubElementData(Context *rsc, RsAllocation va, uint32_t x, uint32_t y, const void *data, uint32_t eoff, uint32_t sizeBytes) 806{ 807 Allocation *a = static_cast<Allocation *>(va); 808 a->subElementData(rsc, x, y, data, eoff, sizeBytes); 809} 810 811void rsi_Allocation1DSubElementData(Context *rsc, RsAllocation va, uint32_t x, const void *data, uint32_t eoff, uint32_t sizeBytes) 812{ 813 Allocation *a = static_cast<Allocation *>(va); 814 a->subElementData(rsc, x, data, eoff, sizeBytes); 815} 816 817void rsi_Allocation2DSubData(Context *rsc, RsAllocation va, uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, const void *data, uint32_t sizeBytes) 818{ 819 Allocation *a = static_cast<Allocation *>(va); 820 a->subData(rsc, xoff, yoff, w, h, data, sizeBytes); 821} 822 823void rsi_AllocationRead(Context *rsc, RsAllocation va, void *data) 824{ 825 Allocation *a = static_cast<Allocation *>(va); 826 a->read(data); 827} 828 829const void* rsi_AllocationGetType(Context *rsc, RsAllocation va) 830{ 831 Allocation *a = static_cast<Allocation *>(va); 832 a->getType()->incUserRef(); 833 834 return a->getType(); 835} 836 837#endif //ANDROID_RS_BUILD_FOR_HOST 838 839} 840} 841