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