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