rsAllocation.cpp revision 5f0b4e19811e7e0ba59888939a3d0761297099fb
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(Context *rsc, const Type *type) : ObjectBase(rsc) 26{ 27 mAllocFile = __FILE__; 28 mAllocLine = __LINE__; 29 mPtr = NULL; 30 31 mCpuWrite = false; 32 mCpuRead = false; 33 mGpuWrite = false; 34 mGpuRead = false; 35 36 mReadWriteRatio = 0; 37 mUpdateSize = 0; 38 39 mIsTexture = false; 40 mTextureID = 0; 41 42 mIsVertexBuffer = false; 43 mBufferID = 0; 44 45 mType.set(type); 46 rsAssert(type); 47 mPtr = malloc(mType->getSizeBytes()); 48 if (!mPtr) { 49 LOGE("Allocation::Allocation, alloc failure"); 50 } 51} 52 53Allocation::~Allocation() 54{ 55 free(mPtr); 56 mPtr = NULL; 57 58 if (mBufferID) { 59 // Causes a SW crash.... 60 //LOGV(" mBufferID %i", mBufferID); 61 //glDeleteBuffers(1, &mBufferID); 62 //mBufferID = 0; 63 } 64 if (mTextureID) { 65 glDeleteTextures(1, &mTextureID); 66 mTextureID = 0; 67 } 68} 69 70void Allocation::setCpuWritable(bool) 71{ 72} 73 74void Allocation::setGpuWritable(bool) 75{ 76} 77 78void Allocation::setCpuReadable(bool) 79{ 80} 81 82void Allocation::setGpuReadable(bool) 83{ 84} 85 86bool Allocation::fixAllocation() 87{ 88 return false; 89} 90 91void Allocation::uploadToTexture(uint32_t lodOffset) 92{ 93 //rsAssert(!mTextureId); 94 rsAssert(lodOffset < mType->getLODCount()); 95 96 GLenum type = mType->getElement()->getGLType(); 97 GLenum format = mType->getElement()->getGLFormat(); 98 99 if (!type || !format) { 100 return; 101 } 102 103 if (!mTextureID) { 104 glGenTextures(1, &mTextureID); 105 } 106 glBindTexture(GL_TEXTURE_2D, mTextureID); 107 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 108 109 Adapter2D adapt(getContext(), this); 110 for(uint32_t lod = 0; (lod + lodOffset) < mType->getLODCount(); lod++) { 111 adapt.setLOD(lod+lodOffset); 112 113 uint16_t * ptr = static_cast<uint16_t *>(adapt.getElement(0,0)); 114 glTexImage2D(GL_TEXTURE_2D, lod, format, 115 adapt.getDimX(), adapt.getDimY(), 116 0, format, type, ptr); 117 } 118} 119 120void Allocation::uploadToBufferObject() 121{ 122 rsAssert(!mType->getDimY()); 123 rsAssert(!mType->getDimZ()); 124 125 if (!mBufferID) { 126 glGenBuffers(1, &mBufferID); 127 } 128 glBindBuffer(GL_ARRAY_BUFFER, mBufferID); 129 glBufferData(GL_ARRAY_BUFFER, mType->getSizeBytes(), getPtr(), GL_DYNAMIC_DRAW); 130 glBindBuffer(GL_ARRAY_BUFFER, 0); 131} 132 133 134void Allocation::data(const void *data, uint32_t sizeBytes) 135{ 136 uint32_t size = mType->getSizeBytes(); 137 if (size != sizeBytes) { 138 LOGE("Allocation::data called with mismatched size expected %i, got %i", size, sizeBytes); 139 return; 140 } 141 memcpy(mPtr, data, size); 142} 143 144void Allocation::read(void *data) 145{ 146 memcpy(data, mPtr, mType->getSizeBytes()); 147} 148 149void Allocation::subData(uint32_t xoff, uint32_t count, const void *data, uint32_t sizeBytes) 150{ 151 uint32_t eSize = mType->getElementSizeBytes(); 152 uint8_t * ptr = static_cast<uint8_t *>(mPtr); 153 ptr += eSize * xoff; 154 uint32_t size = count * eSize; 155 156 if (size != sizeBytes) { 157 LOGE("Allocation::subData called with mismatched size expected %i, got %i", size, sizeBytes); 158 mType->dumpLOGV("type info"); 159 return; 160 } 161 memcpy(ptr, data, size); 162} 163 164void Allocation::subData(uint32_t xoff, uint32_t yoff, 165 uint32_t w, uint32_t h, const void *data, uint32_t sizeBytes) 166{ 167 uint32_t eSize = mType->getElementSizeBytes(); 168 uint32_t lineSize = eSize * w; 169 uint32_t destW = mType->getDimX(); 170 171 const uint8_t *src = static_cast<const uint8_t *>(data); 172 uint8_t *dst = static_cast<uint8_t *>(mPtr); 173 dst += eSize * (xoff + yoff * destW); 174 175 if ((lineSize * eSize * h) != sizeBytes) { 176 rsAssert(!"Allocation::subData called with mismatched size"); 177 return; 178 } 179 180 for (uint32_t line=yoff; line < (yoff+h); line++) { 181 uint8_t * ptr = static_cast<uint8_t *>(mPtr); 182 memcpy(dst, src, lineSize); 183 src += lineSize; 184 dst += destW * eSize; 185 } 186} 187 188void Allocation::subData(uint32_t xoff, uint32_t yoff, uint32_t zoff, 189 uint32_t w, uint32_t h, uint32_t d, const void *data, uint32_t sizeBytes) 190{ 191} 192 193 194 195///////////////// 196// 197 198 199namespace android { 200namespace renderscript { 201 202RsAllocation rsi_AllocationCreateTyped(Context *rsc, RsType vtype) 203{ 204 const Type * type = static_cast<const Type *>(vtype); 205 206 Allocation * alloc = new Allocation(rsc, type); 207 alloc->incUserRef(); 208 return alloc; 209} 210 211RsAllocation rsi_AllocationCreateSized(Context *rsc, RsElement e, size_t count) 212{ 213 Type * type = new Type(rsc); 214 type->setDimX(count); 215 type->setElement(static_cast<Element *>(e)); 216 type->compute(); 217 return rsi_AllocationCreateTyped(rsc, type); 218} 219 220void rsi_AllocationUploadToTexture(Context *rsc, RsAllocation va, uint32_t baseMipLevel) 221{ 222 Allocation *alloc = static_cast<Allocation *>(va); 223 alloc->uploadToTexture(baseMipLevel); 224} 225 226void rsi_AllocationUploadToBufferObject(Context *rsc, RsAllocation va) 227{ 228 Allocation *alloc = static_cast<Allocation *>(va); 229 alloc->uploadToBufferObject(); 230} 231 232static void mip565(const Adapter2D &out, const Adapter2D &in) 233{ 234 uint32_t w = out.getDimX(); 235 uint32_t h = out.getDimY(); 236 237 for (uint32_t y=0; y < h; y++) { 238 uint16_t *oPtr = static_cast<uint16_t *>(out.getElement(0, y)); 239 const uint16_t *i1 = static_cast<uint16_t *>(in.getElement(0, y*2)); 240 const uint16_t *i2 = static_cast<uint16_t *>(in.getElement(0, y*2+1)); 241 242 for (uint32_t x=0; x < w; x++) { 243 *oPtr = rsBoxFilter565(i1[0], i1[1], i2[0], i2[1]); 244 oPtr ++; 245 i1 += 2; 246 i2 += 2; 247 } 248 } 249} 250 251static void mip8888(const Adapter2D &out, const Adapter2D &in) 252{ 253 uint32_t w = out.getDimX(); 254 uint32_t h = out.getDimY(); 255 256 for (uint32_t y=0; y < h; y++) { 257 uint32_t *oPtr = static_cast<uint32_t *>(out.getElement(0, y)); 258 const uint32_t *i1 = static_cast<uint32_t *>(in.getElement(0, y*2)); 259 const uint32_t *i2 = static_cast<uint32_t *>(in.getElement(0, y*2+1)); 260 261 for (uint32_t x=0; x < w; x++) { 262 *oPtr = rsBoxFilter8888(i1[0], i1[1], i2[0], i2[1]); 263 oPtr ++; 264 i1 += 2; 265 i2 += 2; 266 } 267 } 268} 269 270static void mip(const Adapter2D &out, const Adapter2D &in) 271{ 272 switch(out.getBaseType()->getElement()->getSizeBits()) { 273 case 32: 274 mip8888(out, in); 275 break; 276 case 16: 277 mip565(out, in); 278 break; 279 280 } 281 282} 283 284typedef void (*ElementConverter_t)(void *dst, const void *src, uint32_t count); 285 286static void elementConverter_cpy_16(void *dst, const void *src, uint32_t count) 287{ 288 memcpy(dst, src, count * 2); 289} 290static void elementConverter_cpy_8(void *dst, const void *src, uint32_t count) 291{ 292 memcpy(dst, src, count); 293} 294static void elementConverter_cpy_32(void *dst, const void *src, uint32_t count) 295{ 296 memcpy(dst, src, count * 4); 297} 298 299 300static void elementConverter_888_to_565(void *dst, const void *src, uint32_t count) 301{ 302 uint16_t *d = static_cast<uint16_t *>(dst); 303 const uint8_t *s = static_cast<const uint8_t *>(src); 304 305 while(count--) { 306 *d = rs888to565(s[0], s[1], s[2]); 307 d++; 308 s+= 3; 309 } 310} 311 312static void elementConverter_8888_to_565(void *dst, const void *src, uint32_t count) 313{ 314 uint16_t *d = static_cast<uint16_t *>(dst); 315 const uint8_t *s = static_cast<const uint8_t *>(src); 316 317 while(count--) { 318 *d = rs888to565(s[0], s[1], s[2]); 319 d++; 320 s+= 4; 321 } 322} 323 324static ElementConverter_t pickConverter(const Element *dst, const Element *src) 325{ 326 GLenum srcGLType = src->getGLType(); 327 GLenum srcGLFmt = src->getGLFormat(); 328 GLenum dstGLType = dst->getGLType(); 329 GLenum dstGLFmt = dst->getGLFormat(); 330 331 if (srcGLFmt == dstGLFmt && srcGLType == dstGLType) { 332 switch(dst->getSizeBytes()) { 333 case 4: 334 return elementConverter_cpy_32; 335 case 2: 336 return elementConverter_cpy_16; 337 case 1: 338 return elementConverter_cpy_8; 339 } 340 } 341 342 if (srcGLType == GL_UNSIGNED_BYTE && 343 srcGLFmt == GL_RGB && 344 dstGLType == GL_UNSIGNED_SHORT_5_6_5 && 345 dstGLType == GL_RGB) { 346 347 return elementConverter_888_to_565; 348 } 349 350 if (srcGLType == GL_UNSIGNED_BYTE && 351 srcGLFmt == GL_RGBA && 352 dstGLType == GL_UNSIGNED_SHORT_5_6_5 && 353 dstGLType == GL_RGB) { 354 355 return elementConverter_8888_to_565; 356 } 357 358 LOGE("pickConverter, unsuported combo, src %p, dst %p", src, dst); 359 return 0; 360} 361 362 363RsAllocation rsi_AllocationCreateFromBitmap(Context *rsc, uint32_t w, uint32_t h, RsElement _dst, RsElement _src, bool genMips, const void *data) 364{ 365 const Element *src = static_cast<const Element *>(_src); 366 const Element *dst = static_cast<const Element *>(_dst); 367 rsAssert(!(w & (w-1))); 368 rsAssert(!(h & (h-1))); 369 370 //LOGE("rsi_AllocationCreateFromBitmap %i %i %i %i %i", w, h, dstFmt, srcFmt, genMips); 371 rsi_TypeBegin(rsc, _dst); 372 rsi_TypeAdd(rsc, RS_DIMENSION_X, w); 373 rsi_TypeAdd(rsc, RS_DIMENSION_Y, h); 374 if (genMips) { 375 rsi_TypeAdd(rsc, RS_DIMENSION_LOD, 1); 376 } 377 RsType type = rsi_TypeCreate(rsc); 378 379 RsAllocation vTexAlloc = rsi_AllocationCreateTyped(rsc, type); 380 Allocation *texAlloc = static_cast<Allocation *>(vTexAlloc); 381 if (texAlloc == NULL) { 382 LOGE("Memory allocation failure"); 383 return NULL; 384 } 385 texAlloc->incUserRef(); 386 387 ElementConverter_t cvt = pickConverter(dst, src); 388 cvt(texAlloc->getPtr(), data, w * h); 389 390 if (genMips) { 391 Adapter2D adapt(rsc, texAlloc); 392 Adapter2D adapt2(rsc, texAlloc); 393 for(uint32_t lod=0; lod < (texAlloc->getType()->getLODCount() -1); lod++) { 394 adapt.setLOD(lod); 395 adapt2.setLOD(lod + 1); 396 mip(adapt2, adapt); 397 } 398 } 399 400 return texAlloc; 401} 402 403RsAllocation rsi_AllocationCreateFromBitmapBoxed(Context *rsc, uint32_t w, uint32_t h, RsElement _dst, RsElement _src, bool genMips, const void *data) 404{ 405 const Element *srcE = static_cast<const Element *>(_src); 406 const Element *dstE = static_cast<const Element *>(_dst); 407 uint32_t w2 = rsHigherPow2(w); 408 uint32_t h2 = rsHigherPow2(h); 409 410 if ((w2 == w) && (h2 == h)) { 411 return rsi_AllocationCreateFromBitmap(rsc, w, h, _dst, _src, genMips, data); 412 } 413 414 uint32_t bpp = srcE->getSizeBytes(); 415 size_t size = w2 * h2 * bpp; 416 uint8_t *tmp = static_cast<uint8_t *>(malloc(size)); 417 memset(tmp, 0, size); 418 419 const uint8_t * src = static_cast<const uint8_t *>(data); 420 for (uint32_t y = 0; y < h; y++) { 421 uint8_t * ydst = &tmp[(y + ((h2 - h) >> 1)) * w2 * bpp]; 422 memcpy(&ydst[((w2 - w) >> 1) * bpp], src, w * bpp); 423 src += w * bpp; 424 } 425 426 RsAllocation ret = rsi_AllocationCreateFromBitmap(rsc, w2, h2, _dst, _src, genMips, tmp); 427 free(tmp); 428 return ret; 429 430 431 432 433} 434 435void rsi_AllocationData(Context *rsc, RsAllocation va, const void *data, uint32_t sizeBytes) 436{ 437 Allocation *a = static_cast<Allocation *>(va); 438 a->data(data, sizeBytes); 439 rsc->allocationCheck(a); 440} 441 442void rsi_Allocation1DSubData(Context *rsc, RsAllocation va, uint32_t xoff, uint32_t count, const void *data, uint32_t sizeBytes) 443{ 444 Allocation *a = static_cast<Allocation *>(va); 445 a->subData(xoff, count, data, sizeBytes); 446 rsc->allocationCheck(a); 447} 448 449void rsi_Allocation2DSubData(Context *rsc, RsAllocation va, uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, const void *data, uint32_t sizeBytes) 450{ 451 Allocation *a = static_cast<Allocation *>(va); 452 a->subData(xoff, yoff, w, h, data, sizeBytes); 453 rsc->allocationCheck(a); 454} 455 456void rsi_AllocationRead(Context *rsc, RsAllocation va, void *data) 457{ 458 Allocation *a = static_cast<Allocation *>(va); 459 a->read(data); 460} 461 462 463} 464} 465