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