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