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