rsdAllocation.cpp revision a614ae175bbf97201b5e18984d814a1d3e86faa8
1/* 2 * Copyright (C) 2011 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 18#include "rsdCore.h" 19#include "rsdBcc.h" 20#include "rsdRuntime.h" 21#include "rsdAllocation.h" 22 23#include "rsAllocation.h" 24 25#include <GLES/gl.h> 26#include <GLES2/gl2.h> 27#include <GLES/glext.h> 28 29using namespace android; 30using namespace android::renderscript; 31 32 33 34const static GLenum gFaceOrder[] = { 35 GL_TEXTURE_CUBE_MAP_POSITIVE_X, 36 GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 37 GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 38 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 39 GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 40 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 41}; 42 43 44GLenum rsdTypeToGLType(RsDataType t) { 45 switch (t) { 46 case RS_TYPE_UNSIGNED_5_6_5: return GL_UNSIGNED_SHORT_5_6_5; 47 case RS_TYPE_UNSIGNED_5_5_5_1: return GL_UNSIGNED_SHORT_5_5_5_1; 48 case RS_TYPE_UNSIGNED_4_4_4_4: return GL_UNSIGNED_SHORT_4_4_4_4; 49 50 //case RS_TYPE_FLOAT_16: return GL_HALF_FLOAT; 51 case RS_TYPE_FLOAT_32: return GL_FLOAT; 52 case RS_TYPE_UNSIGNED_8: return GL_UNSIGNED_BYTE; 53 case RS_TYPE_UNSIGNED_16: return GL_UNSIGNED_SHORT; 54 case RS_TYPE_SIGNED_8: return GL_BYTE; 55 case RS_TYPE_SIGNED_16: return GL_SHORT; 56 default: break; 57 } 58 return 0; 59} 60 61GLenum rsdKindToGLFormat(RsDataKind k) { 62 switch (k) { 63 case RS_KIND_PIXEL_L: return GL_LUMINANCE; 64 case RS_KIND_PIXEL_A: return GL_ALPHA; 65 case RS_KIND_PIXEL_LA: return GL_LUMINANCE_ALPHA; 66 case RS_KIND_PIXEL_RGB: return GL_RGB; 67 case RS_KIND_PIXEL_RGBA: return GL_RGBA; 68 case RS_KIND_PIXEL_DEPTH: return GL_DEPTH_COMPONENT16; 69 default: break; 70 } 71 return 0; 72} 73 74 75static void Update2DTexture(const Allocation *alloc, const void *ptr, uint32_t xoff, uint32_t yoff, 76 uint32_t lod, RsAllocationCubemapFace face, 77 uint32_t w, uint32_t h) { 78 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 79 80 rsAssert(drv->textureID); 81 glBindTexture(drv->glTarget, drv->textureID); 82 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 83 GLenum t = GL_TEXTURE_2D; 84 if (alloc->mHal.state.hasFaces) { 85 t = gFaceOrder[face]; 86 } 87 glTexSubImage2D(t, lod, xoff, yoff, w, h, drv->glFormat, drv->glType, ptr); 88} 89 90 91static void Upload2DTexture(const Context *rsc, const Allocation *alloc, bool isFirstUpload) { 92 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 93 94 glBindTexture(drv->glTarget, drv->textureID); 95 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 96 97 uint32_t faceCount = 1; 98 if (alloc->mHal.state.hasFaces) { 99 faceCount = 6; 100 } 101 102 rsdGLCheckError(rsc, "Upload2DTexture 1 "); 103 for (uint32_t face = 0; face < faceCount; face ++) { 104 for (uint32_t lod = 0; lod < alloc->mHal.state.type->getLODCount(); lod++) { 105 const uint8_t *p = (const uint8_t *)drv->mallocPtr; 106 p += alloc->mHal.state.type->getLODFaceOffset(lod, (RsAllocationCubemapFace)face, 0, 0); 107 108 GLenum t = GL_TEXTURE_2D; 109 if (alloc->mHal.state.hasFaces) { 110 t = gFaceOrder[face]; 111 } 112 113 if (isFirstUpload) { 114 glTexImage2D(t, lod, drv->glFormat, 115 alloc->mHal.state.type->getLODDimX(lod), 116 alloc->mHal.state.type->getLODDimY(lod), 117 0, drv->glFormat, drv->glType, p); 118 } else { 119 glTexSubImage2D(t, lod, 0, 0, 120 alloc->mHal.state.type->getLODDimX(lod), 121 alloc->mHal.state.type->getLODDimY(lod), 122 drv->glFormat, drv->glType, p); 123 } 124 } 125 } 126 127 if (alloc->mHal.state.mipmapControl == RS_ALLOCATION_MIPMAP_ON_SYNC_TO_TEXTURE) { 128 glGenerateMipmap(drv->glTarget); 129 } 130 rsdGLCheckError(rsc, "Upload2DTexture"); 131} 132 133static void UploadToTexture(const Context *rsc, const Allocation *alloc) { 134 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 135 136 if (!drv->glType || !drv->glFormat) { 137 return; 138 } 139 140 if (!alloc->getPtr()) { 141 return; 142 } 143 144 bool isFirstUpload = false; 145 146 if (!drv->textureID) { 147 glGenTextures(1, &drv->textureID); 148 isFirstUpload = true; 149 } 150 151 Upload2DTexture(rsc, alloc, isFirstUpload); 152 153 if (!(alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT)) { 154 if (drv->mallocPtr) { 155 free(drv->mallocPtr); 156 drv->mallocPtr = NULL; 157 } 158 } 159 rsdGLCheckError(rsc, "UploadToTexture"); 160} 161 162static void AllocateRenderTarget(const Context *rsc, const Allocation *alloc) { 163 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 164 165 if (!drv->glFormat) { 166 return; 167 } 168 169 if (!drv->renderTargetID) { 170 glGenRenderbuffers(1, &drv->renderTargetID); 171 172 if (!drv->renderTargetID) { 173 // This should generally not happen 174 LOGE("allocateRenderTarget failed to gen mRenderTargetID"); 175 rsc->dumpDebug(); 176 return; 177 } 178 glBindRenderbuffer(GL_RENDERBUFFER, drv->renderTargetID); 179 glRenderbufferStorage(GL_RENDERBUFFER, drv->glFormat, 180 alloc->mHal.state.dimensionX, alloc->mHal.state.dimensionY); 181 } 182 rsdGLCheckError(rsc, "AllocateRenderTarget"); 183} 184 185static void UploadToBufferObject(const Context *rsc, const Allocation *alloc) { 186 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 187 188 rsAssert(!alloc->mHal.state.type->getDimY()); 189 rsAssert(!alloc->mHal.state.type->getDimZ()); 190 191 //alloc->mHal.state.usageFlags |= RS_ALLOCATION_USAGE_GRAPHICS_VERTEX; 192 193 if (!drv->bufferID) { 194 glGenBuffers(1, &drv->bufferID); 195 } 196 if (!drv->bufferID) { 197 LOGE("Upload to buffer object failed"); 198 drv->uploadDeferred = true; 199 return; 200 } 201 glBindBuffer(drv->glTarget, drv->bufferID); 202 glBufferData(drv->glTarget, alloc->mHal.state.type->getSizeBytes(), 203 drv->mallocPtr, GL_DYNAMIC_DRAW); 204 glBindBuffer(drv->glTarget, 0); 205 rsdGLCheckError(rsc, "UploadToBufferObject"); 206} 207 208bool rsdAllocationInit(const Context *rsc, Allocation *alloc, bool forceZero) { 209 DrvAllocation *drv = (DrvAllocation *)calloc(1, sizeof(DrvAllocation)); 210 if (!drv) { 211 return false; 212 } 213 214 void * ptr = malloc(alloc->mHal.state.type->getSizeBytes()); 215 if (!ptr) { 216 free(drv); 217 return false; 218 } 219 220 drv->glTarget = GL_NONE; 221 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE) { 222 if (alloc->mHal.state.hasFaces) { 223 drv->glTarget = GL_TEXTURE_CUBE_MAP; 224 } else { 225 drv->glTarget = GL_TEXTURE_2D; 226 } 227 } else { 228 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_VERTEX) { 229 drv->glTarget = GL_ARRAY_BUFFER; 230 } 231 } 232 233 drv->glType = rsdTypeToGLType(alloc->mHal.state.type->getElement()->getComponent().getType()); 234 drv->glFormat = rsdKindToGLFormat(alloc->mHal.state.type->getElement()->getComponent().getKind()); 235 236 237 alloc->mHal.drvState.mallocPtr = ptr; 238 drv->mallocPtr = (uint8_t *)ptr; 239 alloc->mHal.drv = drv; 240 if (forceZero) { 241 memset(ptr, 0, alloc->mHal.state.type->getSizeBytes()); 242 } 243 244 if (alloc->mHal.state.usageFlags & ~RS_ALLOCATION_USAGE_SCRIPT) { 245 drv->uploadDeferred = true; 246 } 247 return true; 248} 249 250void rsdAllocationDestroy(const Context *rsc, Allocation *alloc) { 251 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 252 253 if (drv->bufferID) { 254 // Causes a SW crash.... 255 //LOGV(" mBufferID %i", mBufferID); 256 //glDeleteBuffers(1, &mBufferID); 257 //mBufferID = 0; 258 } 259 if (drv->textureID) { 260 glDeleteTextures(1, &drv->textureID); 261 drv->textureID = 0; 262 } 263 if (drv->renderTargetID) { 264 glDeleteRenderbuffers(1, &drv->renderTargetID); 265 drv->renderTargetID = 0; 266 } 267 268 if (drv->mallocPtr) { 269 free(drv->mallocPtr); 270 drv->mallocPtr = NULL; 271 } 272 free(drv); 273 alloc->mHal.drv = NULL; 274} 275 276void rsdAllocationResize(const Context *rsc, const Allocation *alloc, 277 const Type *newType, bool zeroNew) { 278 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 279 280 drv->mallocPtr = (uint8_t *)realloc(drv->mallocPtr, newType->getSizeBytes()); 281 282 // fixme 283 ((Allocation *)alloc)->mHal.drvState.mallocPtr = drv->mallocPtr; 284 285 const uint32_t oldDimX = alloc->mHal.state.dimensionX; 286 const uint32_t dimX = newType->getDimX(); 287 288 if (dimX > oldDimX) { 289 const Element *e = alloc->mHal.state.type->getElement(); 290 uint32_t stride = e->getSizeBytes(); 291 memset(((uint8_t *)drv->mallocPtr) + stride * oldDimX, 0, stride * (dimX - oldDimX)); 292 } 293} 294 295 296 297void rsdAllocationSyncAll(const Context *rsc, const Allocation *alloc, 298 RsAllocationUsageType src) { 299 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 300 301 if (!drv->uploadDeferred) { 302 return; 303 } 304 305 rsAssert(src == RS_ALLOCATION_USAGE_SCRIPT); 306 307 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE) { 308 UploadToTexture(rsc, alloc); 309 } else { 310 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) { 311 AllocateRenderTarget(rsc, alloc); 312 } 313 } 314 if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_VERTEX) { 315 UploadToBufferObject(rsc, alloc); 316 } 317 318 drv->uploadDeferred = false; 319} 320 321void rsdAllocationMarkDirty(const Context *rsc, const Allocation *alloc) { 322 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 323 drv->uploadDeferred = true; 324} 325 326void rsdAllocationData1D(const Context *rsc, const Allocation *alloc, 327 uint32_t xoff, uint32_t lod, uint32_t count, 328 const void *data, uint32_t sizeBytes) { 329 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 330 331 const uint32_t eSize = alloc->mHal.state.type->getElementSizeBytes(); 332 uint8_t * ptr = drv->mallocPtr; 333 ptr += eSize * xoff; 334 uint32_t size = count * eSize; 335 336 if (alloc->mHal.state.hasReferences) { 337 alloc->incRefs(data, count); 338 alloc->decRefs(ptr, count); 339 } 340 341 memcpy(ptr, data, size); 342 drv->uploadDeferred = true; 343} 344 345void rsdAllocationData2D(const Context *rsc, const Allocation *alloc, 346 uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face, 347 uint32_t w, uint32_t h, const void *data, uint32_t sizeBytes) { 348 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 349 350 uint32_t eSize = alloc->mHal.state.elementSizeBytes; 351 uint32_t lineSize = eSize * w; 352 uint32_t destW = alloc->mHal.state.dimensionX; 353 354 if (drv->mallocPtr) { 355 const uint8_t *src = static_cast<const uint8_t *>(data); 356 uint8_t *dst = drv->mallocPtr; 357 dst += alloc->mHal.state.type->getLODFaceOffset(lod, face, xoff, yoff); 358 359 for (uint32_t line=yoff; line < (yoff+h); line++) { 360 if (alloc->mHal.state.hasReferences) { 361 alloc->incRefs(src, w); 362 alloc->decRefs(dst, w); 363 } 364 memcpy(dst, src, lineSize); 365 src += lineSize; 366 dst += destW * eSize; 367 } 368 drv->uploadDeferred = true; 369 } else { 370 Update2DTexture(alloc, data, xoff, yoff, lod, face, w, h); 371 } 372} 373 374void rsdAllocationData3D(const Context *rsc, const Allocation *alloc, 375 uint32_t xoff, uint32_t yoff, uint32_t zoff, 376 uint32_t lod, RsAllocationCubemapFace face, 377 uint32_t w, uint32_t h, uint32_t d, const void *data, uint32_t sizeBytes) { 378 379} 380 381void rsdAllocationElementData1D(const Context *rsc, const Allocation *alloc, 382 uint32_t x, 383 const void *data, uint32_t cIdx, uint32_t sizeBytes) { 384 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 385 386 uint32_t eSize = alloc->mHal.state.elementSizeBytes; 387 uint8_t * ptr = drv->mallocPtr; 388 ptr += eSize * x; 389 390 const Element * e = alloc->mHal.state.type->getElement()->getField(cIdx); 391 ptr += alloc->mHal.state.type->getElement()->getFieldOffsetBytes(cIdx); 392 393 if (alloc->mHal.state.hasReferences) { 394 e->incRefs(data); 395 e->decRefs(ptr); 396 } 397 398 memcpy(ptr, data, sizeBytes); 399 drv->uploadDeferred = true; 400} 401 402void rsdAllocationElementData2D(const Context *rsc, const Allocation *alloc, 403 uint32_t x, uint32_t y, 404 const void *data, uint32_t cIdx, uint32_t sizeBytes) { 405 DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv; 406 407 uint32_t eSize = alloc->mHal.state.elementSizeBytes; 408 uint8_t * ptr = drv->mallocPtr; 409 ptr += eSize * (x + y * alloc->mHal.state.dimensionX); 410 411 const Element * e = alloc->mHal.state.type->getElement()->getField(cIdx); 412 ptr += alloc->mHal.state.type->getElement()->getFieldOffsetBytes(cIdx); 413 414 if (alloc->mHal.state.hasReferences) { 415 e->incRefs(data); 416 e->decRefs(ptr); 417 } 418 419 memcpy(ptr, data, sizeBytes); 420 drv->uploadDeferred = true; 421} 422 423 424