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