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