rsAllocation.cpp revision e579df42e85d9e00f53c42ef1b78dbd209dba989
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 19#include <GLES/gl.h> 20#include <GLES/glext.h> 21 22using namespace android; 23using namespace android::renderscript; 24 25Allocation::Allocation(const Type *type) 26{ 27 mPtr = NULL; 28 29 mCpuWrite = false; 30 mCpuRead = false; 31 mGpuWrite = false; 32 mGpuRead = false; 33 34 mReadWriteRatio = 0; 35 mUpdateSize = 0; 36 37 mIsTexture = false; 38 mTextureID = 0; 39 40 mIsVertexBuffer = false; 41 mBufferID = 0; 42 43 mType.set(type); 44 rsAssert(type); 45 mPtr = malloc(mType->getSizeBytes()); 46 if (!mPtr) { 47 LOGE("Allocation::Allocation, alloc failure"); 48 } 49} 50 51Allocation::~Allocation() 52{ 53} 54 55void Allocation::setCpuWritable(bool) 56{ 57} 58 59void Allocation::setGpuWritable(bool) 60{ 61} 62 63void Allocation::setCpuReadable(bool) 64{ 65} 66 67void Allocation::setGpuReadable(bool) 68{ 69} 70 71bool Allocation::fixAllocation() 72{ 73 return false; 74} 75 76void Allocation::uploadToTexture(uint32_t lodOffset) 77{ 78 //rsAssert(!mTextureId); 79 rsAssert(lodOffset < mType->getLODCount()); 80 81 GLenum type = mType->getElement()->getGLType(); 82 GLenum format = mType->getElement()->getGLFormat(); 83 84 if (!type || !format) { 85 return; 86 } 87 88 if (!mTextureID) { 89 glGenTextures(1, &mTextureID); 90 } 91 glBindTexture(GL_TEXTURE_2D, mTextureID); 92 93 Adapter2D adapt(this); 94 for(uint32_t lod = 0; (lod + lodOffset) < mType->getLODCount(); lod++) { 95 adapt.setLOD(lod+lodOffset); 96 97 uint16_t * ptr = static_cast<uint16_t *>(adapt.getElement(0,0)); 98 glTexImage2D(GL_TEXTURE_2D, lod, format, 99 adapt.getDimX(), adapt.getDimY(), 100 0, format, type, ptr); 101 } 102} 103 104void Allocation::uploadToBufferObject() 105{ 106 rsAssert(!mType->getDimY()); 107 rsAssert(!mType->getDimZ()); 108 109 if (!mBufferID) { 110 glGenBuffers(1, &mBufferID); 111 } 112 glBindBuffer(GL_ARRAY_BUFFER, mBufferID); 113 glBufferData(GL_ARRAY_BUFFER, mType->getSizeBytes(), getPtr(), GL_DYNAMIC_DRAW); 114 glBindBuffer(GL_ARRAY_BUFFER, 0); 115} 116 117 118void Allocation::data(const void *data) 119{ 120 memcpy(mPtr, data, mType->getSizeBytes()); 121} 122 123void Allocation::read(void *data) 124{ 125 memcpy(data, mPtr, mType->getSizeBytes()); 126} 127 128void Allocation::subData(uint32_t xoff, uint32_t count, const void *data) 129{ 130 uint32_t eSize = mType->getElementSizeBytes(); 131 uint8_t * ptr = static_cast<uint8_t *>(mPtr); 132 ptr += eSize * xoff; 133 memcpy(ptr, data, count * eSize); 134} 135 136void Allocation::subData(uint32_t xoff, uint32_t yoff, 137 uint32_t w, uint32_t h, const void *data) 138{ 139 uint32_t eSize = mType->getElementSizeBytes(); 140 uint32_t lineSize = eSize * w; 141 uint32_t destW = mType->getDimX(); 142 143 const uint8_t *src = static_cast<const uint8_t *>(data); 144 uint8_t *dst = static_cast<uint8_t *>(mPtr); 145 dst += eSize * (xoff + yoff * destW); 146 for (uint32_t line=yoff; line < (yoff+h); line++) { 147 uint8_t * ptr = static_cast<uint8_t *>(mPtr); 148 memcpy(dst, src, lineSize); 149 src += lineSize; 150 dst += destW * eSize; 151 } 152} 153 154void Allocation::subData(uint32_t xoff, uint32_t yoff, uint32_t zoff, 155 uint32_t w, uint32_t h, uint32_t d, const void *data) 156{ 157} 158 159 160 161///////////////// 162// 163 164 165namespace android { 166namespace renderscript { 167 168RsAllocation rsi_AllocationCreateTyped(Context *rsc, RsType vtype) 169{ 170 const Type * type = static_cast<const Type *>(vtype); 171 172 Allocation * alloc = new Allocation(type); 173 alloc->incRef(); 174 return alloc; 175} 176 177RsAllocation rsi_AllocationCreatePredefSized(Context *rsc, RsElementPredefined t, size_t count) 178{ 179 RsElement e = rsi_ElementGetPredefined(rsc, t); 180 return rsi_AllocationCreateSized(rsc, e, count); 181} 182 183RsAllocation rsi_AllocationCreateSized(Context *rsc, RsElement e, size_t count) 184{ 185 Type * type = new Type(); 186 type->setDimX(count); 187 type->setElement(static_cast<Element *>(e)); 188 type->compute(); 189 return rsi_AllocationCreateTyped(rsc, type); 190} 191 192void rsi_AllocationUploadToTexture(Context *rsc, RsAllocation va, uint32_t baseMipLevel) 193{ 194 Allocation *alloc = static_cast<Allocation *>(va); 195 alloc->uploadToTexture(baseMipLevel); 196} 197 198void rsi_AllocationUploadToBufferObject(Context *rsc, RsAllocation va) 199{ 200 Allocation *alloc = static_cast<Allocation *>(va); 201 alloc->uploadToBufferObject(); 202} 203 204void rsi_AllocationDestroy(Context *rsc, RsAllocation) 205{ 206} 207 208static void mip565(const Adapter2D &out, const Adapter2D &in) 209{ 210 uint32_t w = out.getDimX(); 211 uint32_t h = out.getDimY(); 212 213 for (uint32_t y=0; y < h; y++) { 214 uint16_t *oPtr = static_cast<uint16_t *>(out.getElement(0, y)); 215 const uint16_t *i1 = static_cast<uint16_t *>(in.getElement(0, y*2)); 216 const uint16_t *i2 = static_cast<uint16_t *>(in.getElement(0, y*2+1)); 217 218 for (uint32_t x=0; x < w; x++) { 219 *oPtr = rsBoxFilter565(i1[0], i1[1], i2[0], i2[1]); 220 oPtr ++; 221 i1 += 2; 222 i2 += 2; 223 } 224 } 225} 226 227static void mip8888(const Adapter2D &out, const Adapter2D &in) 228{ 229 uint32_t w = out.getDimX(); 230 uint32_t h = out.getDimY(); 231 232 for (uint32_t y=0; y < h; y++) { 233 uint32_t *oPtr = static_cast<uint32_t *>(out.getElement(0, y)); 234 const uint32_t *i1 = static_cast<uint32_t *>(in.getElement(0, y*2)); 235 const uint32_t *i2 = static_cast<uint32_t *>(in.getElement(0, y*2+1)); 236 237 for (uint32_t x=0; x < w; x++) { 238 *oPtr = rsBoxFilter8888(i1[0], i1[1], i2[0], i2[1]); 239 oPtr ++; 240 i1 += 2; 241 i2 += 2; 242 } 243 } 244} 245 246static void mip(const Adapter2D &out, const Adapter2D &in) 247{ 248 switch(out.getBaseType()->getElement()->getSizeBits()) { 249 case 32: 250 mip8888(out, in); 251 break; 252 case 16: 253 mip565(out, in); 254 break; 255 256 } 257 258} 259 260typedef void (*ElementConverter_t)(void *dst, const void *src, uint32_t count); 261 262static void elementConverter_cpy_16(void *dst, const void *src, uint32_t count) 263{ 264 memcpy(dst, src, count * 2); 265} 266static void elementConverter_cpy_8(void *dst, const void *src, uint32_t count) 267{ 268 memcpy(dst, src, count); 269} 270static void elementConverter_cpy_32(void *dst, const void *src, uint32_t count) 271{ 272 memcpy(dst, src, count * 4); 273} 274 275 276static void elementConverter_888_to_565(void *dst, const void *src, uint32_t count) 277{ 278 uint16_t *d = static_cast<uint16_t *>(dst); 279 const uint8_t *s = static_cast<const uint8_t *>(src); 280 281 while(count--) { 282 *d = rs888to565(s[0], s[1], s[2]); 283 d++; 284 s+= 3; 285 } 286} 287 288static void elementConverter_8888_to_565(void *dst, const void *src, uint32_t count) 289{ 290 uint16_t *d = static_cast<uint16_t *>(dst); 291 const uint8_t *s = static_cast<const uint8_t *>(src); 292 293 while(count--) { 294 *d = rs888to565(s[0], s[1], s[2]); 295 d++; 296 s+= 4; 297 } 298} 299 300static ElementConverter_t pickConverter(RsElementPredefined dstFmt, RsElementPredefined srcFmt) 301{ 302 if ((dstFmt == RS_ELEMENT_RGB_565) && 303 (srcFmt == RS_ELEMENT_RGB_565)) { 304 return elementConverter_cpy_16; 305 } 306 307 if ((dstFmt == RS_ELEMENT_RGB_565) && 308 (srcFmt == RS_ELEMENT_RGB_888)) { 309 return elementConverter_888_to_565; 310 } 311 312 if ((dstFmt == RS_ELEMENT_RGB_565) && 313 (srcFmt == RS_ELEMENT_RGBA_8888)) { 314 return elementConverter_8888_to_565; 315 } 316 317 if ((dstFmt == RS_ELEMENT_RGBA_8888) && 318 (srcFmt == RS_ELEMENT_RGBA_8888)) { 319 return elementConverter_cpy_32; 320 } 321 322 LOGE("pickConverter, unsuported combo, src %i, dst %i", srcFmt, dstFmt); 323 return 0; 324} 325 326 327RsAllocation rsi_AllocationCreateFromBitmap(Context *rsc, uint32_t w, uint32_t h, RsElementPredefined dstFmt, RsElementPredefined srcFmt, bool genMips, const void *data) 328{ 329 rsAssert(!(w & (w-1))); 330 rsAssert(!(h & (h-1))); 331 332 //LOGE("rsi_AllocationCreateFromBitmap %i %i %i %i %i", w, h, dstFmt, srcFmt, genMips); 333 rsi_TypeBegin(rsc, rsi_ElementGetPredefined(rsc, dstFmt)); 334 rsi_TypeAdd(rsc, RS_DIMENSION_X, w); 335 rsi_TypeAdd(rsc, RS_DIMENSION_Y, h); 336 if (genMips) { 337 rsi_TypeAdd(rsc, RS_DIMENSION_LOD, 1); 338 } 339 RsType type = rsi_TypeCreate(rsc); 340 341 RsAllocation vTexAlloc = rsi_AllocationCreateTyped(rsc, type); 342 Allocation *texAlloc = static_cast<Allocation *>(vTexAlloc); 343 if (texAlloc == NULL) { 344 LOGE("Memory allocation failure"); 345 return NULL; 346 } 347 texAlloc->incRef(); 348 349 ElementConverter_t cvt = pickConverter(dstFmt, srcFmt); 350 cvt(texAlloc->getPtr(), data, w * h); 351 352 if (genMips) { 353 Adapter2D adapt(texAlloc); 354 Adapter2D adapt2(texAlloc); 355 for(uint32_t lod=0; lod < (texAlloc->getType()->getLODCount() -1); lod++) { 356 adapt.setLOD(lod); 357 adapt2.setLOD(lod + 1); 358 mip(adapt2, adapt); 359 } 360 } 361 362 return texAlloc; 363} 364 365static uint32_t fmtToBits(RsElementPredefined fmt) 366{ 367 return 16; 368} 369 370RsAllocation rsi_AllocationCreateFromBitmapBoxed(Context *rsc, uint32_t w, uint32_t h, RsElementPredefined dstFmt, RsElementPredefined srcFmt, bool genMips, const void *data) 371{ 372 uint32_t w2 = rsHigherPow2(w); 373 uint32_t h2 = rsHigherPow2(h); 374 375 if ((w2 == w) && (h2 == h)) { 376 return rsi_AllocationCreateFromBitmap(rsc, w, h, dstFmt, srcFmt, genMips, data); 377 } 378 379 uint32_t bpp = fmtToBits(srcFmt) >> 3; 380 size_t size = w2 * h2 * bpp; 381 uint8_t *tmp = static_cast<uint8_t *>(malloc(size)); 382 memset(tmp, 0, size); 383 384 const uint8_t * src = static_cast<const uint8_t *>(data); 385 for (uint32_t y = 0; y < h; y++) { 386 uint8_t * ydst = &tmp[(y + ((h2 - h) >> 1)) * w2 * bpp]; 387 memcpy(&ydst[(w2 - w) >> 1], src, w * bpp); 388 src += w * bpp; 389 } 390 391 RsAllocation ret = rsi_AllocationCreateFromBitmap(rsc, w2, h2, dstFmt, srcFmt, genMips, tmp); 392 free(tmp); 393 return ret; 394 395 396 397 398} 399 400 401RsAllocation rsi_AllocationCreateFromFile(Context *rsc, const char *file, bool genMips) 402{ 403 bool use32bpp = false; 404 405 typedef struct _Win3xBitmapHeader 406 { 407 uint16_t type; 408 uint32_t totalSize; 409 uint32_t reserved; 410 uint32_t offset; 411 int32_t hdrSize; /* Size of this header in bytes */ 412 int32_t width; /* Image width in pixels */ 413 int32_t height; /* Image height in pixels */ 414 int16_t planes; /* Number of color planes */ 415 int16_t bpp; /* Number of bits per pixel */ 416 /* Fields added for Windows 3.x follow this line */ 417 int32_t compression; /* Compression methods used */ 418 int32_t sizeOfBitmap; /* Size of bitmap in bytes */ 419 int32_t horzResolution; /* Horizontal resolution in pixels per meter */ 420 int32_t vertResolution; /* Vertical resolution in pixels per meter */ 421 int32_t colorsUsed; /* Number of colors in the image */ 422 int32_t colorsImportant; /* Minimum number of important colors */ 423 } __attribute__((__packed__)) WIN3XBITMAPHEADER; 424 425 _Win3xBitmapHeader hdr; 426 427 FILE *f = fopen(file, "rb"); 428 if (f == NULL) { 429 LOGE("rsAllocationCreateFromBitmap failed to open file %s", file); 430 return NULL; 431 } 432 memset(&hdr, 0, sizeof(hdr)); 433 fread(&hdr, sizeof(hdr), 1, f); 434 435 if (hdr.bpp != 24) { 436 LOGE("Unsuported BMP type"); 437 fclose(f); 438 return NULL; 439 } 440 441 int32_t texWidth = rsHigherPow2(hdr.width); 442 int32_t texHeight = rsHigherPow2(hdr.height); 443 444 if (use32bpp) { 445 rsi_TypeBegin(rsc, rsi_ElementGetPredefined(rsc, RS_ELEMENT_RGBA_8888)); 446 } else { 447 rsi_TypeBegin(rsc, rsi_ElementGetPredefined(rsc, RS_ELEMENT_RGB_565)); 448 } 449 rsi_TypeAdd(rsc, RS_DIMENSION_X, texWidth); 450 rsi_TypeAdd(rsc, RS_DIMENSION_Y, texHeight); 451 if (genMips) { 452 rsi_TypeAdd(rsc, RS_DIMENSION_LOD, 1); 453 } 454 RsType type = rsi_TypeCreate(rsc); 455 456 RsAllocation vTexAlloc = rsi_AllocationCreateTyped(rsc, type); 457 Allocation *texAlloc = static_cast<Allocation *>(vTexAlloc); 458 texAlloc->incRef(); 459 if (texAlloc == NULL) { 460 LOGE("Memory allocation failure"); 461 fclose(f); 462 return NULL; 463 } 464 465 // offset to letterbox if height is not pow2 466 Adapter2D adapt(texAlloc); 467 uint8_t * fileInBuf = new uint8_t[texWidth * 3]; 468 uint32_t yOffset = (hdr.width - hdr.height) / 2; 469 470 if (use32bpp) { 471 uint8_t *tmp = static_cast<uint8_t *>(adapt.getElement(0, yOffset)); 472 for (int y=0; y < hdr.height; y++) { 473 fseek(f, hdr.offset + (y*hdr.width*3), SEEK_SET); 474 fread(fileInBuf, 1, hdr.width * 3, f); 475 for(int x=0; x < hdr.width; x++) { 476 tmp[0] = fileInBuf[x*3 + 2]; 477 tmp[1] = fileInBuf[x*3 + 1]; 478 tmp[2] = fileInBuf[x*3]; 479 tmp[3] = 0xff; 480 tmp += 4; 481 } 482 } 483 } else { 484 uint16_t *tmp = static_cast<uint16_t *>(adapt.getElement(0, yOffset)); 485 for (int y=0; y < hdr.height; y++) { 486 fseek(f, hdr.offset + (y*hdr.width*3), SEEK_SET); 487 fread(fileInBuf, 1, hdr.width * 3, f); 488 for(int x=0; x < hdr.width; x++) { 489 *tmp = rs888to565(fileInBuf[x*3 + 2], fileInBuf[x*3 + 1], fileInBuf[x*3]); 490 tmp++; 491 } 492 } 493 } 494 495 fclose(f); 496 delete [] fileInBuf; 497 498 if (genMips) { 499 Adapter2D adapt2(texAlloc); 500 for(uint32_t lod=0; lod < (texAlloc->getType()->getLODCount() -1); lod++) { 501 adapt.setLOD(lod); 502 adapt2.setLOD(lod + 1); 503 mip(adapt2, adapt); 504 } 505 } 506 507 return texAlloc; 508} 509 510void rsi_AllocationData(Context *rsc, RsAllocation va, const void *data) 511{ 512 Allocation *a = static_cast<Allocation *>(va); 513 a->data(data); 514 rsc->allocationCheck(a); 515} 516 517void rsi_Allocation1DSubData(Context *rsc, RsAllocation va, uint32_t xoff, uint32_t count, const void *data) 518{ 519 Allocation *a = static_cast<Allocation *>(va); 520 a->subData(xoff, count, data); 521 rsc->allocationCheck(a); 522} 523 524void rsi_Allocation2DSubData(Context *rsc, RsAllocation va, uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, const void *data) 525{ 526 Allocation *a = static_cast<Allocation *>(va); 527 a->subData(xoff, yoff, w, h, data); 528 rsc->allocationCheck(a); 529} 530 531void rsi_AllocationRead(Context *rsc, RsAllocation va, void *data) 532{ 533 Allocation *a = static_cast<Allocation *>(va); 534 a->read(data); 535} 536 537 538} 539} 540