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