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