Home | History | Annotate | Download | only in driver
      1 /*
      2  * Copyright (C) 2013 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 "rsdCore.h"
     18 #include "rsdAllocation.h"
     19 
     20 #include "rsAllocation.h"
     21 
     22 #if !defined(RS_SERVER) && !defined(RS_COMPATIBILITY_LIB)
     23 #include "system/window.h"
     24 #include "ui/Rect.h"
     25 #include "ui/GraphicBufferMapper.h"
     26 #else
     27 #include "system/graphics.h"
     28 #endif
     29 
     30 #ifndef RS_COMPATIBILITY_LIB
     31 #include "rsdFrameBufferObj.h"
     32 #include "gui/GLConsumer.h"
     33 #include "gui/CpuConsumer.h"
     34 #include "gui/Surface.h"
     35 #include "hardware/gralloc.h"
     36 
     37 #include <GLES/gl.h>
     38 #include <GLES2/gl2.h>
     39 #include <GLES/glext.h>
     40 #endif
     41 
     42 #ifdef RS_SERVER
     43 // server requires malloc.h for memalign
     44 #include <malloc.h>
     45 #endif
     46 
     47 using namespace android;
     48 using namespace android::renderscript;
     49 
     50 
     51 #ifndef RS_COMPATIBILITY_LIB
     52 const static GLenum gFaceOrder[] = {
     53     GL_TEXTURE_CUBE_MAP_POSITIVE_X,
     54     GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
     55     GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
     56     GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
     57     GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
     58     GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
     59 };
     60 
     61 GLenum rsdTypeToGLType(RsDataType t) {
     62     switch (t) {
     63     case RS_TYPE_UNSIGNED_5_6_5:    return GL_UNSIGNED_SHORT_5_6_5;
     64     case RS_TYPE_UNSIGNED_5_5_5_1:  return GL_UNSIGNED_SHORT_5_5_5_1;
     65     case RS_TYPE_UNSIGNED_4_4_4_4:  return GL_UNSIGNED_SHORT_4_4_4_4;
     66 
     67     //case RS_TYPE_FLOAT_16:      return GL_HALF_FLOAT;
     68     case RS_TYPE_FLOAT_32:      return GL_FLOAT;
     69     case RS_TYPE_UNSIGNED_8:    return GL_UNSIGNED_BYTE;
     70     case RS_TYPE_UNSIGNED_16:   return GL_UNSIGNED_SHORT;
     71     case RS_TYPE_SIGNED_8:      return GL_BYTE;
     72     case RS_TYPE_SIGNED_16:     return GL_SHORT;
     73     default:    break;
     74     }
     75     return 0;
     76 }
     77 
     78 GLenum rsdKindToGLFormat(RsDataKind k) {
     79     switch (k) {
     80     case RS_KIND_PIXEL_L: return GL_LUMINANCE;
     81     case RS_KIND_PIXEL_A: return GL_ALPHA;
     82     case RS_KIND_PIXEL_LA: return GL_LUMINANCE_ALPHA;
     83     case RS_KIND_PIXEL_RGB: return GL_RGB;
     84     case RS_KIND_PIXEL_RGBA: return GL_RGBA;
     85     case RS_KIND_PIXEL_DEPTH: return GL_DEPTH_COMPONENT16;
     86     default: break;
     87     }
     88     return 0;
     89 }
     90 #endif
     91 
     92 uint8_t *GetOffsetPtr(const android::renderscript::Allocation *alloc,
     93                       uint32_t xoff, uint32_t yoff, uint32_t zoff,
     94                       uint32_t lod, RsAllocationCubemapFace face) {
     95     uint8_t *ptr = (uint8_t *)alloc->mHal.drvState.lod[lod].mallocPtr;
     96     ptr += face * alloc->mHal.drvState.faceOffset;
     97     ptr += zoff * alloc->mHal.drvState.lod[lod].dimY * alloc->mHal.drvState.lod[lod].stride;
     98     ptr += yoff * alloc->mHal.drvState.lod[lod].stride;
     99     ptr += xoff * alloc->mHal.state.elementSizeBytes;
    100     return ptr;
    101 }
    102 
    103 
    104 static void Update2DTexture(const Context *rsc, const Allocation *alloc, const void *ptr,
    105                             uint32_t xoff, uint32_t yoff, uint32_t lod,
    106                             RsAllocationCubemapFace face, uint32_t w, uint32_t h) {
    107 #ifndef RS_COMPATIBILITY_LIB
    108     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
    109 
    110     rsAssert(drv->textureID);
    111     RSD_CALL_GL(glBindTexture, drv->glTarget, drv->textureID);
    112     RSD_CALL_GL(glPixelStorei, GL_UNPACK_ALIGNMENT, 1);
    113     GLenum t = GL_TEXTURE_2D;
    114     if (alloc->mHal.state.hasFaces) {
    115         t = gFaceOrder[face];
    116     }
    117     RSD_CALL_GL(glTexSubImage2D, t, lod, xoff, yoff, w, h, drv->glFormat, drv->glType, ptr);
    118 #endif
    119 }
    120 
    121 
    122 #ifndef RS_COMPATIBILITY_LIB
    123 static void Upload2DTexture(const Context *rsc, const Allocation *alloc, bool isFirstUpload) {
    124     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
    125 
    126     RSD_CALL_GL(glBindTexture, drv->glTarget, drv->textureID);
    127     RSD_CALL_GL(glPixelStorei, GL_UNPACK_ALIGNMENT, 1);
    128 
    129     uint32_t faceCount = 1;
    130     if (alloc->mHal.state.hasFaces) {
    131         faceCount = 6;
    132     }
    133 
    134     rsdGLCheckError(rsc, "Upload2DTexture 1 ");
    135     for (uint32_t face = 0; face < faceCount; face ++) {
    136         for (uint32_t lod = 0; lod < alloc->mHal.state.type->getLODCount(); lod++) {
    137             const uint8_t *p = GetOffsetPtr(alloc, 0, 0, 0, lod, (RsAllocationCubemapFace)face);
    138 
    139             GLenum t = GL_TEXTURE_2D;
    140             if (alloc->mHal.state.hasFaces) {
    141                 t = gFaceOrder[face];
    142             }
    143 
    144             if (isFirstUpload) {
    145                 RSD_CALL_GL(glTexImage2D, t, lod, drv->glFormat,
    146                              alloc->mHal.state.type->getLODDimX(lod),
    147                              alloc->mHal.state.type->getLODDimY(lod),
    148                              0, drv->glFormat, drv->glType, p);
    149             } else {
    150                 RSD_CALL_GL(glTexSubImage2D, t, lod, 0, 0,
    151                                 alloc->mHal.state.type->getLODDimX(lod),
    152                                 alloc->mHal.state.type->getLODDimY(lod),
    153                                 drv->glFormat, drv->glType, p);
    154             }
    155         }
    156     }
    157 
    158     if (alloc->mHal.state.mipmapControl == RS_ALLOCATION_MIPMAP_ON_SYNC_TO_TEXTURE) {
    159         RSD_CALL_GL(glGenerateMipmap, drv->glTarget);
    160     }
    161     rsdGLCheckError(rsc, "Upload2DTexture");
    162 }
    163 #endif
    164 
    165 static void UploadToTexture(const Context *rsc, const Allocation *alloc) {
    166 #ifndef RS_COMPATIBILITY_LIB
    167     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
    168 
    169     if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_INPUT) {
    170         if (!drv->textureID) {
    171             RSD_CALL_GL(glGenTextures, 1, &drv->textureID);
    172         }
    173         return;
    174     }
    175 
    176     if (!drv->glType || !drv->glFormat) {
    177         return;
    178     }
    179 
    180     if (!alloc->mHal.drvState.lod[0].mallocPtr) {
    181         return;
    182     }
    183 
    184     bool isFirstUpload = false;
    185 
    186     if (!drv->textureID) {
    187         RSD_CALL_GL(glGenTextures, 1, &drv->textureID);
    188         isFirstUpload = true;
    189     }
    190 
    191     Upload2DTexture(rsc, alloc, isFirstUpload);
    192 
    193     if (!(alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT)) {
    194         if (alloc->mHal.drvState.lod[0].mallocPtr) {
    195             free(alloc->mHal.drvState.lod[0].mallocPtr);
    196             alloc->mHal.drvState.lod[0].mallocPtr = NULL;
    197         }
    198     }
    199     rsdGLCheckError(rsc, "UploadToTexture");
    200 #endif
    201 }
    202 
    203 static void AllocateRenderTarget(const Context *rsc, const Allocation *alloc) {
    204 #ifndef RS_COMPATIBILITY_LIB
    205     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
    206 
    207     if (!drv->glFormat) {
    208         return;
    209     }
    210 
    211     if (!drv->renderTargetID) {
    212         RSD_CALL_GL(glGenRenderbuffers, 1, &drv->renderTargetID);
    213 
    214         if (!drv->renderTargetID) {
    215             // This should generally not happen
    216             ALOGE("allocateRenderTarget failed to gen mRenderTargetID");
    217             rsc->dumpDebug();
    218             return;
    219         }
    220         RSD_CALL_GL(glBindRenderbuffer, GL_RENDERBUFFER, drv->renderTargetID);
    221         RSD_CALL_GL(glRenderbufferStorage, GL_RENDERBUFFER, drv->glFormat,
    222                     alloc->mHal.drvState.lod[0].dimX, alloc->mHal.drvState.lod[0].dimY);
    223     }
    224     rsdGLCheckError(rsc, "AllocateRenderTarget");
    225 #endif
    226 }
    227 
    228 static void UploadToBufferObject(const Context *rsc, const Allocation *alloc) {
    229 #ifndef RS_COMPATIBILITY_LIB
    230     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
    231 
    232     rsAssert(!alloc->mHal.state.type->getDimY());
    233     rsAssert(!alloc->mHal.state.type->getDimZ());
    234 
    235     //alloc->mHal.state.usageFlags |= RS_ALLOCATION_USAGE_GRAPHICS_VERTEX;
    236 
    237     if (!drv->bufferID) {
    238         RSD_CALL_GL(glGenBuffers, 1, &drv->bufferID);
    239     }
    240     if (!drv->bufferID) {
    241         ALOGE("Upload to buffer object failed");
    242         drv->uploadDeferred = true;
    243         return;
    244     }
    245     RSD_CALL_GL(glBindBuffer, drv->glTarget, drv->bufferID);
    246     RSD_CALL_GL(glBufferData, drv->glTarget, alloc->mHal.state.type->getSizeBytes(),
    247                  alloc->mHal.drvState.lod[0].mallocPtr, GL_DYNAMIC_DRAW);
    248     RSD_CALL_GL(glBindBuffer, drv->glTarget, 0);
    249     rsdGLCheckError(rsc, "UploadToBufferObject");
    250 #endif
    251 }
    252 
    253 
    254 static size_t DeriveYUVLayout(int yuv, Allocation::Hal::DrvState *state) {
    255     // YUV only supports basic 2d
    256     // so we can stash the plane pointers in the mipmap levels.
    257     size_t uvSize = 0;
    258 #ifndef RS_SERVER
    259     switch(yuv) {
    260     case HAL_PIXEL_FORMAT_YV12:
    261         state->lod[2].dimX = state->lod[0].dimX / 2;
    262         state->lod[2].dimY = state->lod[0].dimY / 2;
    263         state->lod[2].stride = rsRound(state->lod[0].stride >> 1, 16);
    264         state->lod[2].mallocPtr = ((uint8_t *)state->lod[0].mallocPtr) +
    265                 (state->lod[0].stride * state->lod[0].dimY);
    266         uvSize += state->lod[2].stride * state->lod[2].dimY;
    267 
    268         state->lod[1].dimX = state->lod[2].dimX;
    269         state->lod[1].dimY = state->lod[2].dimY;
    270         state->lod[1].stride = state->lod[2].stride;
    271         state->lod[1].mallocPtr = ((uint8_t *)state->lod[2].mallocPtr) +
    272                 (state->lod[2].stride * state->lod[2].dimY);
    273         uvSize += state->lod[1].stride * state->lod[2].dimY;
    274 
    275         state->lodCount = 3;
    276         break;
    277     case HAL_PIXEL_FORMAT_YCrCb_420_SP:  // NV21
    278         state->lod[1].dimX = state->lod[0].dimX;
    279         state->lod[1].dimY = state->lod[0].dimY / 2;
    280         state->lod[1].stride = state->lod[0].stride;
    281         state->lod[1].mallocPtr = ((uint8_t *)state->lod[0].mallocPtr) +
    282                 (state->lod[0].stride * state->lod[0].dimY);
    283         uvSize += state->lod[1].stride * state->lod[1].dimY;
    284         state->lodCount = 2;
    285         break;
    286     default:
    287         rsAssert(0);
    288     }
    289 #endif
    290     return uvSize;
    291 }
    292 
    293 
    294 static size_t AllocationBuildPointerTable(const Context *rsc, const Allocation *alloc,
    295         const Type *type, uint8_t *ptr) {
    296     alloc->mHal.drvState.lod[0].dimX = type->getDimX();
    297     alloc->mHal.drvState.lod[0].dimY = type->getDimY();
    298     alloc->mHal.drvState.lod[0].dimZ = type->getDimZ();
    299     alloc->mHal.drvState.lod[0].mallocPtr = 0;
    300     // Stride needs to be 16-byte aligned too!
    301     size_t stride = alloc->mHal.drvState.lod[0].dimX * type->getElementSizeBytes();
    302     alloc->mHal.drvState.lod[0].stride = rsRound(stride, 16);
    303     alloc->mHal.drvState.lodCount = type->getLODCount();
    304     alloc->mHal.drvState.faceCount = type->getDimFaces();
    305 
    306     size_t offsets[Allocation::MAX_LOD];
    307     memset(offsets, 0, sizeof(offsets));
    308 
    309     size_t o = alloc->mHal.drvState.lod[0].stride * rsMax(alloc->mHal.drvState.lod[0].dimY, 1u) *
    310             rsMax(alloc->mHal.drvState.lod[0].dimZ, 1u);
    311     if(alloc->mHal.drvState.lodCount > 1) {
    312         uint32_t tx = alloc->mHal.drvState.lod[0].dimX;
    313         uint32_t ty = alloc->mHal.drvState.lod[0].dimY;
    314         uint32_t tz = alloc->mHal.drvState.lod[0].dimZ;
    315         for (uint32_t lod=1; lod < alloc->mHal.drvState.lodCount; lod++) {
    316             alloc->mHal.drvState.lod[lod].dimX = tx;
    317             alloc->mHal.drvState.lod[lod].dimY = ty;
    318             alloc->mHal.drvState.lod[lod].dimZ = tz;
    319             alloc->mHal.drvState.lod[lod].stride =
    320                     rsRound(tx * type->getElementSizeBytes(), 16);
    321             offsets[lod] = o;
    322             o += alloc->mHal.drvState.lod[lod].stride * rsMax(ty, 1u) * rsMax(tz, 1u);
    323             if (tx > 1) tx >>= 1;
    324             if (ty > 1) ty >>= 1;
    325             if (tz > 1) tz >>= 1;
    326         }
    327     } else if (alloc->mHal.state.yuv) {
    328         o += DeriveYUVLayout(alloc->mHal.state.yuv, &alloc->mHal.drvState);
    329 
    330         for (uint32_t ct = 1; ct < alloc->mHal.drvState.lodCount; ct++) {
    331             offsets[ct] = (size_t)alloc->mHal.drvState.lod[ct].mallocPtr;
    332         }
    333     }
    334 
    335     alloc->mHal.drvState.faceOffset = o;
    336 
    337     alloc->mHal.drvState.lod[0].mallocPtr = ptr;
    338     for (uint32_t lod=1; lod < alloc->mHal.drvState.lodCount; lod++) {
    339         alloc->mHal.drvState.lod[lod].mallocPtr = ptr + offsets[lod];
    340     }
    341 
    342     size_t allocSize = alloc->mHal.drvState.faceOffset;
    343     if(alloc->mHal.drvState.faceCount) {
    344         allocSize *= 6;
    345     }
    346 
    347     return allocSize;
    348 }
    349 
    350 static uint8_t* allocAlignedMemory(size_t allocSize, bool forceZero) {
    351     // We align all allocations to a 16-byte boundary.
    352     uint8_t* ptr = (uint8_t *)memalign(16, allocSize);
    353     if (!ptr) {
    354         return NULL;
    355     }
    356     if (forceZero) {
    357         memset(ptr, 0, allocSize);
    358     }
    359     return ptr;
    360 }
    361 
    362 bool rsdAllocationInit(const Context *rsc, Allocation *alloc, bool forceZero) {
    363     DrvAllocation *drv = (DrvAllocation *)calloc(1, sizeof(DrvAllocation));
    364     if (!drv) {
    365         return false;
    366     }
    367     alloc->mHal.drv = drv;
    368 
    369     // Calculate the object size.
    370     size_t allocSize = AllocationBuildPointerTable(rsc, alloc, alloc->getType(), NULL);
    371 
    372     uint8_t * ptr = NULL;
    373     if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_OUTPUT) {
    374 
    375     } else if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_INPUT) {
    376         // Allocation is allocated when the surface is created
    377         // in getSurface
    378     } else if (alloc->mHal.state.userProvidedPtr != NULL) {
    379         // user-provided allocation
    380         // limitations: no faces, no LOD, USAGE_SCRIPT or SCRIPT+TEXTURE only
    381         if (!(alloc->mHal.state.usageFlags == (RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_SHARED) ||
    382               alloc->mHal.state.usageFlags == (RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_SHARED | RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE))) {
    383             ALOGE("Can't use user-allocated buffers if usage is not USAGE_SCRIPT | USAGE_SHARED or USAGE_SCRIPT | USAGE_SHARED | USAGE_GRAPHICS_TEXTURE");
    384             return false;
    385         }
    386         if (alloc->getType()->getDimLOD() || alloc->getType()->getDimFaces()) {
    387             ALOGE("User-allocated buffers must not have multiple faces or LODs");
    388             return false;
    389         }
    390 
    391         // rows must be 16-byte aligned
    392         // validate that here, otherwise fall back to not use the user-backed allocation
    393         if (((alloc->getType()->getDimX() * alloc->getType()->getElement()->getSizeBytes()) % 16) != 0) {
    394             ALOGV("User-backed allocation failed stride requirement, falling back to separate allocation");
    395             drv->useUserProvidedPtr = false;
    396 
    397             ptr = allocAlignedMemory(allocSize, forceZero);
    398             if (!ptr) {
    399                 alloc->mHal.drv = NULL;
    400                 free(drv);
    401                 return false;
    402             }
    403 
    404         } else {
    405             drv->useUserProvidedPtr = true;
    406             ptr = (uint8_t*)alloc->mHal.state.userProvidedPtr;
    407         }
    408     } else {
    409         ptr = allocAlignedMemory(allocSize, forceZero);
    410         if (!ptr) {
    411             alloc->mHal.drv = NULL;
    412             free(drv);
    413             return false;
    414         }
    415     }
    416     // Build the pointer tables
    417     size_t verifySize = AllocationBuildPointerTable(rsc, alloc, alloc->getType(), ptr);
    418     if(allocSize != verifySize) {
    419         rsAssert(!"Size mismatch");
    420     }
    421 
    422 #ifndef RS_SERVER
    423     drv->glTarget = GL_NONE;
    424     if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE) {
    425         if (alloc->mHal.state.hasFaces) {
    426             drv->glTarget = GL_TEXTURE_CUBE_MAP;
    427         } else {
    428             drv->glTarget = GL_TEXTURE_2D;
    429         }
    430     } else {
    431         if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_VERTEX) {
    432             drv->glTarget = GL_ARRAY_BUFFER;
    433         }
    434     }
    435 #endif
    436 
    437 #ifndef RS_COMPATIBILITY_LIB
    438     drv->glType = rsdTypeToGLType(alloc->mHal.state.type->getElement()->getComponent().getType());
    439     drv->glFormat = rsdKindToGLFormat(alloc->mHal.state.type->getElement()->getComponent().getKind());
    440 #else
    441     drv->glType = 0;
    442     drv->glFormat = 0;
    443 #endif
    444 
    445     if (alloc->mHal.state.usageFlags & ~RS_ALLOCATION_USAGE_SCRIPT) {
    446         drv->uploadDeferred = true;
    447     }
    448 
    449 
    450     drv->readBackFBO = NULL;
    451 
    452     // fill out the initial state of the buffer if we couldn't use the user-provided ptr and USAGE_SHARED was accepted
    453     if ((alloc->mHal.state.userProvidedPtr != 0) && (drv->useUserProvidedPtr == false)) {
    454         rsdAllocationData2D(rsc, alloc, 0, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X, alloc->getType()->getDimX(), alloc->getType()->getDimY(), alloc->mHal.state.userProvidedPtr, allocSize, 0);
    455     }
    456 
    457     return true;
    458 }
    459 
    460 void rsdAllocationDestroy(const Context *rsc, Allocation *alloc) {
    461     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
    462 
    463 #ifndef RS_COMPATIBILITY_LIB
    464     if (drv->bufferID) {
    465         // Causes a SW crash....
    466         //ALOGV(" mBufferID %i", mBufferID);
    467         //glDeleteBuffers(1, &mBufferID);
    468         //mBufferID = 0;
    469     }
    470     if (drv->textureID) {
    471         RSD_CALL_GL(glDeleteTextures, 1, &drv->textureID);
    472         drv->textureID = 0;
    473     }
    474     if (drv->renderTargetID) {
    475         RSD_CALL_GL(glDeleteRenderbuffers, 1, &drv->renderTargetID);
    476         drv->renderTargetID = 0;
    477     }
    478 #endif
    479 
    480     if (alloc->mHal.drvState.lod[0].mallocPtr) {
    481         // don't free user-allocated ptrs or IO_OUTPUT buffers
    482         if (!(drv->useUserProvidedPtr) &&
    483             !(alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_INPUT) &&
    484             !(alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_OUTPUT)) {
    485                 free(alloc->mHal.drvState.lod[0].mallocPtr);
    486         }
    487         alloc->mHal.drvState.lod[0].mallocPtr = NULL;
    488     }
    489 
    490 #ifndef RS_COMPATIBILITY_LIB
    491     if (drv->readBackFBO != NULL) {
    492         delete drv->readBackFBO;
    493         drv->readBackFBO = NULL;
    494     }
    495 
    496     if ((alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_OUTPUT) &&
    497         (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT)) {
    498 
    499         DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
    500         ANativeWindow *nw = drv->wndSurface;
    501         if (nw) {
    502             GraphicBufferMapper &mapper = GraphicBufferMapper::get();
    503             mapper.unlock(drv->wndBuffer->handle);
    504             int32_t r = nw->queueBuffer(nw, drv->wndBuffer, -1);
    505         }
    506     }
    507 #endif
    508 
    509     free(drv);
    510     alloc->mHal.drv = NULL;
    511 }
    512 
    513 void rsdAllocationResize(const Context *rsc, const Allocation *alloc,
    514                          const Type *newType, bool zeroNew) {
    515     const uint32_t oldDimX = alloc->mHal.drvState.lod[0].dimX;
    516     const uint32_t dimX = newType->getDimX();
    517 
    518     // can't resize Allocations with user-allocated buffers
    519     if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SHARED) {
    520         ALOGE("Resize cannot be called on a USAGE_SHARED allocation");
    521         return;
    522     }
    523     void * oldPtr = alloc->mHal.drvState.lod[0].mallocPtr;
    524     // Calculate the object size
    525     size_t s = AllocationBuildPointerTable(rsc, alloc, newType, NULL);
    526     uint8_t *ptr = (uint8_t *)realloc(oldPtr, s);
    527     // Build the relative pointer tables.
    528     size_t verifySize = AllocationBuildPointerTable(rsc, alloc, newType, ptr);
    529     if(s != verifySize) {
    530         rsAssert(!"Size mismatch");
    531     }
    532 
    533 
    534     if (dimX > oldDimX) {
    535         size_t stride = alloc->mHal.state.elementSizeBytes;
    536         memset(((uint8_t *)alloc->mHal.drvState.lod[0].mallocPtr) + stride * oldDimX,
    537                  0, stride * (dimX - oldDimX));
    538     }
    539 }
    540 
    541 static void rsdAllocationSyncFromFBO(const Context *rsc, const Allocation *alloc) {
    542 #ifndef RS_COMPATIBILITY_LIB
    543     if (!alloc->getIsScript()) {
    544         return; // nothing to sync
    545     }
    546 
    547     RsdHal *dc = (RsdHal *)rsc->mHal.drv;
    548     RsdFrameBufferObj *lastFbo = dc->gl.currentFrameBuffer;
    549 
    550     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
    551     if (!drv->textureID && !drv->renderTargetID) {
    552         return; // nothing was rendered here yet, so nothing to sync
    553     }
    554     if (drv->readBackFBO == NULL) {
    555         drv->readBackFBO = new RsdFrameBufferObj();
    556         drv->readBackFBO->setColorTarget(drv, 0);
    557         drv->readBackFBO->setDimensions(alloc->getType()->getDimX(),
    558                                         alloc->getType()->getDimY());
    559     }
    560 
    561     // Bind the framebuffer object so we can read back from it
    562     drv->readBackFBO->setActive(rsc);
    563 
    564     // Do the readback
    565     RSD_CALL_GL(glReadPixels, 0, 0, alloc->mHal.drvState.lod[0].dimX,
    566                 alloc->mHal.drvState.lod[0].dimY,
    567                 drv->glFormat, drv->glType, alloc->mHal.drvState.lod[0].mallocPtr);
    568 
    569     // Revert framebuffer to its original
    570     lastFbo->setActive(rsc);
    571 #endif
    572 }
    573 
    574 
    575 void rsdAllocationSyncAll(const Context *rsc, const Allocation *alloc,
    576                          RsAllocationUsageType src) {
    577     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
    578 
    579     if (src == RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) {
    580         if(!alloc->getIsRenderTarget()) {
    581             rsc->setError(RS_ERROR_FATAL_DRIVER,
    582                           "Attempting to sync allocation from render target, "
    583                           "for non-render target allocation");
    584         } else if (alloc->getType()->getElement()->getKind() != RS_KIND_PIXEL_RGBA) {
    585             rsc->setError(RS_ERROR_FATAL_DRIVER, "Cannot only sync from RGBA"
    586                                                  "render target");
    587         } else {
    588             rsdAllocationSyncFromFBO(rsc, alloc);
    589         }
    590         return;
    591     }
    592 
    593     rsAssert(src == RS_ALLOCATION_USAGE_SCRIPT);
    594 
    595     if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE) {
    596         UploadToTexture(rsc, alloc);
    597     } else {
    598         if ((alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) &&
    599             !(alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_OUTPUT)) {
    600             AllocateRenderTarget(rsc, alloc);
    601         }
    602     }
    603     if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_VERTEX) {
    604         UploadToBufferObject(rsc, alloc);
    605     }
    606 
    607     if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SHARED) {
    608         // NOP in CPU driver for now
    609     }
    610 
    611     drv->uploadDeferred = false;
    612 }
    613 
    614 void rsdAllocationMarkDirty(const Context *rsc, const Allocation *alloc) {
    615     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
    616     drv->uploadDeferred = true;
    617 }
    618 
    619 #ifndef RS_COMPATIBILITY_LIB
    620 void DrvAllocation::NewBufferListener::onFrameAvailable() {
    621     intptr_t ip = (intptr_t)alloc;
    622     rsc->sendMessageToClient(NULL, RS_MESSAGE_TO_CLIENT_NEW_BUFFER, ip, 0, true);
    623 }
    624 #endif
    625 
    626 void* rsdAllocationGetSurface(const Context *rsc, const Allocation *alloc) {
    627 #ifndef RS_COMPATIBILITY_LIB
    628     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
    629 
    630     // Configure CpuConsumer to be in asynchronous mode
    631     drv->cpuConsumer = new CpuConsumer(2, false);
    632     sp<IGraphicBufferProducer> bp = drv->cpuConsumer->getProducerInterface();
    633     bp->incStrong(NULL);
    634 
    635     drv->mBufferListener = new DrvAllocation::NewBufferListener();
    636     drv->mBufferListener->rsc = rsc;
    637     drv->mBufferListener->alloc = alloc;
    638 
    639     drv->cpuConsumer->setFrameAvailableListener(drv->mBufferListener);
    640 
    641     return bp.get();
    642 #else
    643     return NULL;
    644 #endif
    645 }
    646 
    647 #ifndef RS_COMPATIBILITY_LIB
    648 static bool IoGetBuffer(const Context *rsc, Allocation *alloc, ANativeWindow *nw) {
    649     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
    650 
    651     int32_t r = native_window_dequeue_buffer_and_wait(nw, &drv->wndBuffer);
    652     if (r) {
    653         rsc->setError(RS_ERROR_DRIVER, "Error getting next IO output buffer.");
    654         return false;
    655     }
    656 
    657     // Must lock the whole surface
    658     GraphicBufferMapper &mapper = GraphicBufferMapper::get();
    659     Rect bounds(drv->wndBuffer->width, drv->wndBuffer->height);
    660 
    661     void *dst = NULL;
    662     mapper.lock(drv->wndBuffer->handle,
    663             GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_OFTEN,
    664             bounds, &dst);
    665     alloc->mHal.drvState.lod[0].mallocPtr = dst;
    666     alloc->mHal.drvState.lod[0].stride = drv->wndBuffer->stride * alloc->mHal.state.elementSizeBytes;
    667     rsAssert((alloc->mHal.drvState.lod[0].stride & 0xf) == 0);
    668 
    669     return true;
    670 }
    671 #endif
    672 
    673 void rsdAllocationSetSurface(const Context *rsc, Allocation *alloc, ANativeWindow *nw) {
    674 #ifndef RS_COMPATIBILITY_LIB
    675     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
    676     ANativeWindow *old = drv->wndSurface;
    677 
    678     if (nw) {
    679         nw->incStrong(NULL);
    680     }
    681 
    682     if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) {
    683         //TODO finish support for render target + script
    684         drv->wnd = nw;
    685         return;
    686     }
    687 
    688     // Cleanup old surface if there is one.
    689     if (drv->wndSurface) {
    690         ANativeWindow *old = drv->wndSurface;
    691         GraphicBufferMapper &mapper = GraphicBufferMapper::get();
    692         mapper.unlock(drv->wndBuffer->handle);
    693         old->cancelBuffer(old, drv->wndBuffer, -1);
    694         drv->wndSurface = NULL;
    695         old->decStrong(NULL);
    696     }
    697 
    698     if (nw != NULL) {
    699         int32_t r;
    700         uint32_t flags = 0;
    701 
    702         if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT) {
    703             flags |= GRALLOC_USAGE_SW_READ_RARELY | GRALLOC_USAGE_SW_WRITE_OFTEN;
    704         }
    705         if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) {
    706             flags |= GRALLOC_USAGE_HW_RENDER;
    707         }
    708 
    709         r = native_window_set_usage(nw, flags);
    710         if (r) {
    711             rsc->setError(RS_ERROR_DRIVER, "Error setting IO output buffer usage.");
    712             goto error;
    713         }
    714 
    715         r = native_window_set_buffers_dimensions(nw, alloc->mHal.drvState.lod[0].dimX,
    716                                                  alloc->mHal.drvState.lod[0].dimY);
    717         if (r) {
    718             rsc->setError(RS_ERROR_DRIVER, "Error setting IO output buffer dimensions.");
    719             goto error;
    720         }
    721 
    722         int format = 0;
    723         const Element *e = alloc->mHal.state.type->getElement();
    724         switch(e->getType()) {
    725         case RS_TYPE_UNSIGNED_8:
    726             switch (e->getVectorSize()) {
    727             case 1:
    728                 rsAssert(e->getKind() == RS_KIND_PIXEL_A);
    729                 format = PIXEL_FORMAT_A_8;
    730                 break;
    731             case 4:
    732                 rsAssert(e->getKind() == RS_KIND_PIXEL_RGBA);
    733                 format = PIXEL_FORMAT_RGBA_8888;
    734                 break;
    735             default:
    736                 rsAssert(0);
    737             }
    738             break;
    739         default:
    740             rsAssert(0);
    741         }
    742 
    743         r = native_window_set_buffers_format(nw, format);
    744         if (r) {
    745             rsc->setError(RS_ERROR_DRIVER, "Error setting IO output buffer format.");
    746             goto error;
    747         }
    748 
    749         IoGetBuffer(rsc, alloc, nw);
    750         drv->wndSurface = nw;
    751     }
    752 
    753     return;
    754 
    755  error:
    756 
    757     if (nw) {
    758         nw->decStrong(NULL);
    759     }
    760 
    761 
    762 #endif
    763 }
    764 
    765 void rsdAllocationIoSend(const Context *rsc, Allocation *alloc) {
    766 #ifndef RS_COMPATIBILITY_LIB
    767     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
    768     ANativeWindow *nw = drv->wndSurface;
    769     if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) {
    770         RsdHal *dc = (RsdHal *)rsc->mHal.drv;
    771         RSD_CALL_GL(eglSwapBuffers, dc->gl.egl.display, dc->gl.egl.surface);
    772         return;
    773     }
    774     if (nw) {
    775         if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT) {
    776             GraphicBufferMapper &mapper = GraphicBufferMapper::get();
    777             mapper.unlock(drv->wndBuffer->handle);
    778             int32_t r = nw->queueBuffer(nw, drv->wndBuffer, -1);
    779             if (r) {
    780                 rsc->setError(RS_ERROR_DRIVER, "Error sending IO output buffer.");
    781                 return;
    782             }
    783 
    784             IoGetBuffer(rsc, alloc, nw);
    785         }
    786     } else {
    787         rsc->setError(RS_ERROR_DRIVER, "Sent IO buffer with no attached surface.");
    788         return;
    789     }
    790 #endif
    791 }
    792 
    793 void rsdAllocationIoReceive(const Context *rsc, Allocation *alloc) {
    794 #ifndef RS_COMPATIBILITY_LIB
    795     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
    796 
    797     if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT) {
    798         CpuConsumer::LockedBuffer lb;
    799         status_t ret = drv->cpuConsumer->lockNextBuffer(&lb);
    800         if (ret == OK) {
    801             if (drv->lb.data != NULL) {
    802                 drv->cpuConsumer->unlockBuffer(drv->lb);
    803             }
    804             drv->lb = lb;
    805             alloc->mHal.drvState.lod[0].mallocPtr = drv->lb.data;
    806             alloc->mHal.drvState.lod[0].stride = drv->lb.stride *
    807                     alloc->mHal.state.elementSizeBytes;
    808 
    809             if (alloc->mHal.state.yuv) {
    810                 DeriveYUVLayout(alloc->mHal.state.yuv, &alloc->mHal.drvState);
    811             }
    812         } else if (ret == BAD_VALUE) {
    813             // No new frame, don't do anything
    814         } else {
    815             rsc->setError(RS_ERROR_DRIVER, "Error receiving IO input buffer.");
    816         }
    817 
    818     } else {
    819         drv->surfaceTexture->updateTexImage();
    820     }
    821 
    822 
    823 #endif
    824 }
    825 
    826 
    827 void rsdAllocationData1D(const Context *rsc, const Allocation *alloc,
    828                          uint32_t xoff, uint32_t lod, size_t count,
    829                          const void *data, size_t sizeBytes) {
    830     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
    831 
    832     const size_t eSize = alloc->mHal.state.type->getElementSizeBytes();
    833     uint8_t * ptr = GetOffsetPtr(alloc, xoff, 0, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
    834     size_t size = count * eSize;
    835 
    836     if (ptr != data) {
    837         // Skip the copy if we are the same allocation. This can arise from
    838         // our Bitmap optimization, where we share the same storage.
    839         if (alloc->mHal.state.hasReferences) {
    840             alloc->incRefs(data, count);
    841             alloc->decRefs(ptr, count);
    842         }
    843         memcpy(ptr, data, size);
    844     }
    845     drv->uploadDeferred = true;
    846 }
    847 
    848 void rsdAllocationData2D(const Context *rsc, const Allocation *alloc,
    849                          uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face,
    850                          uint32_t w, uint32_t h, const void *data, size_t sizeBytes, size_t stride) {
    851     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
    852 
    853     size_t eSize = alloc->mHal.state.elementSizeBytes;
    854     size_t lineSize = eSize * w;
    855     if (!stride) {
    856         stride = lineSize;
    857     }
    858 
    859     if (alloc->mHal.drvState.lod[0].mallocPtr) {
    860         const uint8_t *src = static_cast<const uint8_t *>(data);
    861         uint8_t *dst = GetOffsetPtr(alloc, xoff, yoff, 0, lod, face);
    862         if (dst == src) {
    863             // Skip the copy if we are the same allocation. This can arise from
    864             // our Bitmap optimization, where we share the same storage.
    865             drv->uploadDeferred = true;
    866             return;
    867         }
    868 
    869         for (uint32_t line=yoff; line < (yoff+h); line++) {
    870             if (alloc->mHal.state.hasReferences) {
    871                 alloc->incRefs(src, w);
    872                 alloc->decRefs(dst, w);
    873             }
    874             memcpy(dst, src, lineSize);
    875             src += stride;
    876             dst += alloc->mHal.drvState.lod[lod].stride;
    877         }
    878         if (alloc->mHal.state.yuv) {
    879             int lod = 1;
    880             while (alloc->mHal.drvState.lod[lod].mallocPtr) {
    881                 size_t lineSize = alloc->mHal.drvState.lod[lod].dimX;
    882                 uint8_t *dst = GetOffsetPtr(alloc, xoff, yoff, 0, lod, face);
    883 
    884                 for (uint32_t line=(yoff >> 1); line < ((yoff+h)>>1); line++) {
    885                     memcpy(dst, src, lineSize);
    886                     src += lineSize;
    887                     dst += alloc->mHal.drvState.lod[lod].stride;
    888                 }
    889                 lod++;
    890             }
    891 
    892         }
    893         drv->uploadDeferred = true;
    894     } else {
    895         Update2DTexture(rsc, alloc, data, xoff, yoff, lod, face, w, h);
    896     }
    897 }
    898 
    899 void rsdAllocationData3D(const Context *rsc, const Allocation *alloc,
    900                          uint32_t xoff, uint32_t yoff, uint32_t zoff,
    901                          uint32_t lod,
    902                          uint32_t w, uint32_t h, uint32_t d, const void *data,
    903                          size_t sizeBytes, size_t stride) {
    904     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
    905 
    906     uint32_t eSize = alloc->mHal.state.elementSizeBytes;
    907     uint32_t lineSize = eSize * w;
    908     if (!stride) {
    909         stride = lineSize;
    910     }
    911 
    912     if (alloc->mHal.drvState.lod[0].mallocPtr) {
    913         const uint8_t *src = static_cast<const uint8_t *>(data);
    914         for (uint32_t z = zoff; z < d; z++) {
    915             uint8_t *dst = GetOffsetPtr(alloc, xoff, yoff, z, lod,
    916                                         RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
    917             if (dst == src) {
    918                 // Skip the copy if we are the same allocation. This can arise from
    919                 // our Bitmap optimization, where we share the same storage.
    920                 drv->uploadDeferred = true;
    921                 return;
    922             }
    923 
    924             for (uint32_t line=yoff; line < (yoff+h); line++) {
    925                 if (alloc->mHal.state.hasReferences) {
    926                     alloc->incRefs(src, w);
    927                     alloc->decRefs(dst, w);
    928                 }
    929                 memcpy(dst, src, lineSize);
    930                 src += stride;
    931                 dst += alloc->mHal.drvState.lod[lod].stride;
    932             }
    933         }
    934         drv->uploadDeferred = true;
    935     }
    936 }
    937 
    938 void rsdAllocationRead1D(const Context *rsc, const Allocation *alloc,
    939                          uint32_t xoff, uint32_t lod, size_t count,
    940                          void *data, size_t sizeBytes) {
    941     const size_t eSize = alloc->mHal.state.type->getElementSizeBytes();
    942     const uint8_t * ptr = GetOffsetPtr(alloc, xoff, 0, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
    943     if (data != ptr) {
    944         // Skip the copy if we are the same allocation. This can arise from
    945         // our Bitmap optimization, where we share the same storage.
    946         memcpy(data, ptr, count * eSize);
    947     }
    948 }
    949 
    950 void rsdAllocationRead2D(const Context *rsc, const Allocation *alloc,
    951                                 uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face,
    952                                 uint32_t w, uint32_t h, void *data, size_t sizeBytes, size_t stride) {
    953     size_t eSize = alloc->mHal.state.elementSizeBytes;
    954     size_t lineSize = eSize * w;
    955     if (!stride) {
    956         stride = lineSize;
    957     }
    958 
    959     if (alloc->mHal.drvState.lod[0].mallocPtr) {
    960         uint8_t *dst = static_cast<uint8_t *>(data);
    961         const uint8_t *src = GetOffsetPtr(alloc, xoff, yoff, 0, lod, face);
    962         if (dst == src) {
    963             // Skip the copy if we are the same allocation. This can arise from
    964             // our Bitmap optimization, where we share the same storage.
    965             return;
    966         }
    967 
    968         for (uint32_t line=yoff; line < (yoff+h); line++) {
    969             memcpy(dst, src, lineSize);
    970             dst += stride;
    971             src += alloc->mHal.drvState.lod[lod].stride;
    972         }
    973     } else {
    974         ALOGE("Add code to readback from non-script memory");
    975     }
    976 }
    977 
    978 
    979 void rsdAllocationRead3D(const Context *rsc, const Allocation *alloc,
    980                          uint32_t xoff, uint32_t yoff, uint32_t zoff,
    981                          uint32_t lod,
    982                          uint32_t w, uint32_t h, uint32_t d, void *data, size_t sizeBytes, size_t stride) {
    983     uint32_t eSize = alloc->mHal.state.elementSizeBytes;
    984     uint32_t lineSize = eSize * w;
    985     if (!stride) {
    986         stride = lineSize;
    987     }
    988 
    989     if (alloc->mHal.drvState.lod[0].mallocPtr) {
    990         uint8_t *dst = static_cast<uint8_t *>(data);
    991         for (uint32_t z = zoff; z < d; z++) {
    992             const uint8_t *src = GetOffsetPtr(alloc, xoff, yoff, z, lod,
    993                                               RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
    994             if (dst == src) {
    995                 // Skip the copy if we are the same allocation. This can arise from
    996                 // our Bitmap optimization, where we share the same storage.
    997                 return;
    998             }
    999 
   1000             for (uint32_t line=yoff; line < (yoff+h); line++) {
   1001                 memcpy(dst, src, lineSize);
   1002                 dst += stride;
   1003                 src += alloc->mHal.drvState.lod[lod].stride;
   1004             }
   1005         }
   1006     }
   1007 }
   1008 
   1009 void * rsdAllocationLock1D(const android::renderscript::Context *rsc,
   1010                           const android::renderscript::Allocation *alloc) {
   1011     return alloc->mHal.drvState.lod[0].mallocPtr;
   1012 }
   1013 
   1014 void rsdAllocationUnlock1D(const android::renderscript::Context *rsc,
   1015                           const android::renderscript::Allocation *alloc) {
   1016 
   1017 }
   1018 
   1019 void rsdAllocationData1D_alloc(const android::renderscript::Context *rsc,
   1020                                const android::renderscript::Allocation *dstAlloc,
   1021                                uint32_t dstXoff, uint32_t dstLod, size_t count,
   1022                                const android::renderscript::Allocation *srcAlloc,
   1023                                uint32_t srcXoff, uint32_t srcLod) {
   1024 }
   1025 
   1026 
   1027 void rsdAllocationData2D_alloc_script(const android::renderscript::Context *rsc,
   1028                                       const android::renderscript::Allocation *dstAlloc,
   1029                                       uint32_t dstXoff, uint32_t dstYoff, uint32_t dstLod,
   1030                                       RsAllocationCubemapFace dstFace, uint32_t w, uint32_t h,
   1031                                       const android::renderscript::Allocation *srcAlloc,
   1032                                       uint32_t srcXoff, uint32_t srcYoff, uint32_t srcLod,
   1033                                       RsAllocationCubemapFace srcFace) {
   1034     size_t elementSize = dstAlloc->getType()->getElementSizeBytes();
   1035     for (uint32_t i = 0; i < h; i ++) {
   1036         uint8_t *dstPtr = GetOffsetPtr(dstAlloc, dstXoff, dstYoff + i, 0, dstLod, dstFace);
   1037         uint8_t *srcPtr = GetOffsetPtr(srcAlloc, srcXoff, srcYoff + i, 0, srcLod, srcFace);
   1038         memcpy(dstPtr, srcPtr, w * elementSize);
   1039 
   1040         //ALOGE("COPIED dstXoff(%u), dstYoff(%u), dstLod(%u), dstFace(%u), w(%u), h(%u), srcXoff(%u), srcYoff(%u), srcLod(%u), srcFace(%u)",
   1041         //     dstXoff, dstYoff, dstLod, dstFace, w, h, srcXoff, srcYoff, srcLod, srcFace);
   1042     }
   1043 }
   1044 
   1045 void rsdAllocationData3D_alloc_script(const android::renderscript::Context *rsc,
   1046                                       const android::renderscript::Allocation *dstAlloc,
   1047                                       uint32_t dstXoff, uint32_t dstYoff, uint32_t dstZoff, uint32_t dstLod,
   1048                                       uint32_t w, uint32_t h, uint32_t d,
   1049                                       const android::renderscript::Allocation *srcAlloc,
   1050                                       uint32_t srcXoff, uint32_t srcYoff, uint32_t srcZoff, uint32_t srcLod) {
   1051     uint32_t elementSize = dstAlloc->getType()->getElementSizeBytes();
   1052     for (uint32_t j = 0; j < d; j++) {
   1053         for (uint32_t i = 0; i < h; i ++) {
   1054             uint8_t *dstPtr = GetOffsetPtr(dstAlloc, dstXoff, dstYoff + i, dstZoff + j,
   1055                                            dstLod, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
   1056             uint8_t *srcPtr = GetOffsetPtr(srcAlloc, srcXoff, srcYoff + i, srcZoff + j,
   1057                                            srcLod, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
   1058             memcpy(dstPtr, srcPtr, w * elementSize);
   1059 
   1060             //ALOGE("COPIED dstXoff(%u), dstYoff(%u), dstLod(%u), dstFace(%u), w(%u), h(%u), srcXoff(%u), srcYoff(%u), srcLod(%u), srcFace(%u)",
   1061             //     dstXoff, dstYoff, dstLod, dstFace, w, h, srcXoff, srcYoff, srcLod, srcFace);
   1062         }
   1063     }
   1064 }
   1065 
   1066 void rsdAllocationData2D_alloc(const android::renderscript::Context *rsc,
   1067                                const android::renderscript::Allocation *dstAlloc,
   1068                                uint32_t dstXoff, uint32_t dstYoff, uint32_t dstLod,
   1069                                RsAllocationCubemapFace dstFace, uint32_t w, uint32_t h,
   1070                                const android::renderscript::Allocation *srcAlloc,
   1071                                uint32_t srcXoff, uint32_t srcYoff, uint32_t srcLod,
   1072                                RsAllocationCubemapFace srcFace) {
   1073     if (!dstAlloc->getIsScript() && !srcAlloc->getIsScript()) {
   1074         rsc->setError(RS_ERROR_FATAL_DRIVER, "Non-script allocation copies not "
   1075                                              "yet implemented.");
   1076         return;
   1077     }
   1078     rsdAllocationData2D_alloc_script(rsc, dstAlloc, dstXoff, dstYoff,
   1079                                      dstLod, dstFace, w, h, srcAlloc,
   1080                                      srcXoff, srcYoff, srcLod, srcFace);
   1081 }
   1082 
   1083 void rsdAllocationData3D_alloc(const android::renderscript::Context *rsc,
   1084                                const android::renderscript::Allocation *dstAlloc,
   1085                                uint32_t dstXoff, uint32_t dstYoff, uint32_t dstZoff,
   1086                                uint32_t dstLod,
   1087                                uint32_t w, uint32_t h, uint32_t d,
   1088                                const android::renderscript::Allocation *srcAlloc,
   1089                                uint32_t srcXoff, uint32_t srcYoff, uint32_t srcZoff,
   1090                                uint32_t srcLod) {
   1091     if (!dstAlloc->getIsScript() && !srcAlloc->getIsScript()) {
   1092         rsc->setError(RS_ERROR_FATAL_DRIVER, "Non-script allocation copies not "
   1093                                              "yet implemented.");
   1094         return;
   1095     }
   1096     rsdAllocationData3D_alloc_script(rsc, dstAlloc, dstXoff, dstYoff, dstZoff,
   1097                                      dstLod, w, h, d, srcAlloc,
   1098                                      srcXoff, srcYoff, srcZoff, srcLod);
   1099 }
   1100 
   1101 void rsdAllocationElementData1D(const Context *rsc, const Allocation *alloc,
   1102                                 uint32_t x,
   1103                                 const void *data, uint32_t cIdx, size_t sizeBytes) {
   1104     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
   1105 
   1106     size_t eSize = alloc->mHal.state.elementSizeBytes;
   1107     uint8_t * ptr = GetOffsetPtr(alloc, x, 0, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
   1108 
   1109     const Element * e = alloc->mHal.state.type->getElement()->getField(cIdx);
   1110     ptr += alloc->mHal.state.type->getElement()->getFieldOffsetBytes(cIdx);
   1111 
   1112     if (alloc->mHal.state.hasReferences) {
   1113         e->incRefs(data);
   1114         e->decRefs(ptr);
   1115     }
   1116 
   1117     memcpy(ptr, data, sizeBytes);
   1118     drv->uploadDeferred = true;
   1119 }
   1120 
   1121 void rsdAllocationElementData2D(const Context *rsc, const Allocation *alloc,
   1122                                 uint32_t x, uint32_t y,
   1123                                 const void *data, uint32_t cIdx, size_t sizeBytes) {
   1124     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
   1125 
   1126     size_t eSize = alloc->mHal.state.elementSizeBytes;
   1127     uint8_t * ptr = GetOffsetPtr(alloc, x, y, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
   1128 
   1129     const Element * e = alloc->mHal.state.type->getElement()->getField(cIdx);
   1130     ptr += alloc->mHal.state.type->getElement()->getFieldOffsetBytes(cIdx);
   1131 
   1132     if (alloc->mHal.state.hasReferences) {
   1133         e->incRefs(data);
   1134         e->decRefs(ptr);
   1135     }
   1136 
   1137     memcpy(ptr, data, sizeBytes);
   1138     drv->uploadDeferred = true;
   1139 }
   1140 
   1141 static void mip565(const Allocation *alloc, int lod, RsAllocationCubemapFace face) {
   1142     uint32_t w = alloc->mHal.drvState.lod[lod + 1].dimX;
   1143     uint32_t h = alloc->mHal.drvState.lod[lod + 1].dimY;
   1144 
   1145     for (uint32_t y=0; y < h; y++) {
   1146         uint16_t *oPtr = (uint16_t *)GetOffsetPtr(alloc, 0, y, 0, lod + 1, face);
   1147         const uint16_t *i1 = (uint16_t *)GetOffsetPtr(alloc, 0, 0, y*2, lod, face);
   1148         const uint16_t *i2 = (uint16_t *)GetOffsetPtr(alloc, 0, 0, y*2+1, lod, face);
   1149 
   1150         for (uint32_t x=0; x < w; x++) {
   1151             *oPtr = rsBoxFilter565(i1[0], i1[1], i2[0], i2[1]);
   1152             oPtr ++;
   1153             i1 += 2;
   1154             i2 += 2;
   1155         }
   1156     }
   1157 }
   1158 
   1159 static void mip8888(const Allocation *alloc, int lod, RsAllocationCubemapFace face) {
   1160     uint32_t w = alloc->mHal.drvState.lod[lod + 1].dimX;
   1161     uint32_t h = alloc->mHal.drvState.lod[lod + 1].dimY;
   1162 
   1163     for (uint32_t y=0; y < h; y++) {
   1164         uint32_t *oPtr = (uint32_t *)GetOffsetPtr(alloc, 0, y, 0, lod + 1, face);
   1165         const uint32_t *i1 = (uint32_t *)GetOffsetPtr(alloc, 0, y*2, 0, lod, face);
   1166         const uint32_t *i2 = (uint32_t *)GetOffsetPtr(alloc, 0, y*2+1, 0, lod, face);
   1167 
   1168         for (uint32_t x=0; x < w; x++) {
   1169             *oPtr = rsBoxFilter8888(i1[0], i1[1], i2[0], i2[1]);
   1170             oPtr ++;
   1171             i1 += 2;
   1172             i2 += 2;
   1173         }
   1174     }
   1175 }
   1176 
   1177 static void mip8(const Allocation *alloc, int lod, RsAllocationCubemapFace face) {
   1178     uint32_t w = alloc->mHal.drvState.lod[lod + 1].dimX;
   1179     uint32_t h = alloc->mHal.drvState.lod[lod + 1].dimY;
   1180 
   1181     for (uint32_t y=0; y < h; y++) {
   1182         uint8_t *oPtr = GetOffsetPtr(alloc, 0, y, 0, lod + 1, face);
   1183         const uint8_t *i1 = GetOffsetPtr(alloc, 0, y*2, 0, lod, face);
   1184         const uint8_t *i2 = GetOffsetPtr(alloc, 0, y*2+1, 0, lod, face);
   1185 
   1186         for (uint32_t x=0; x < w; x++) {
   1187             *oPtr = (uint8_t)(((uint32_t)i1[0] + i1[1] + i2[0] + i2[1]) * 0.25f);
   1188             oPtr ++;
   1189             i1 += 2;
   1190             i2 += 2;
   1191         }
   1192     }
   1193 }
   1194 
   1195 void rsdAllocationGenerateMipmaps(const Context *rsc, const Allocation *alloc) {
   1196     if(!alloc->mHal.drvState.lod[0].mallocPtr) {
   1197         return;
   1198     }
   1199     uint32_t numFaces = alloc->getType()->getDimFaces() ? 6 : 1;
   1200     for (uint32_t face = 0; face < numFaces; face ++) {
   1201         for (uint32_t lod=0; lod < (alloc->getType()->getLODCount() -1); lod++) {
   1202             switch (alloc->getType()->getElement()->getSizeBits()) {
   1203             case 32:
   1204                 mip8888(alloc, lod, (RsAllocationCubemapFace)face);
   1205                 break;
   1206             case 16:
   1207                 mip565(alloc, lod, (RsAllocationCubemapFace)face);
   1208                 break;
   1209             case 8:
   1210                 mip8(alloc, lod, (RsAllocationCubemapFace)face);
   1211                 break;
   1212             }
   1213         }
   1214     }
   1215 }
   1216