Home | History | Annotate | Download | only in driver
      1 /*
      2  * Copyright (C) 2011-2012 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 "rsdRuntime.h"
     20 #include "rsdAllocation.h"
     21 #include "rsdFrameBufferObj.h"
     22 
     23 #include "rsAllocation.h"
     24 
     25 #include "system/window.h"
     26 #include "hardware/gralloc.h"
     27 #include "ui/Rect.h"
     28 #include "ui/GraphicBufferMapper.h"
     29 #include "gui/SurfaceTexture.h"
     30 
     31 #include <GLES/gl.h>
     32 #include <GLES2/gl2.h>
     33 #include <GLES/glext.h>
     34 
     35 using namespace android;
     36 using namespace android::renderscript;
     37 
     38 
     39 
     40 const static GLenum gFaceOrder[] = {
     41     GL_TEXTURE_CUBE_MAP_POSITIVE_X,
     42     GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
     43     GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
     44     GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
     45     GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
     46     GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
     47 };
     48 
     49 
     50 GLenum rsdTypeToGLType(RsDataType t) {
     51     switch (t) {
     52     case RS_TYPE_UNSIGNED_5_6_5:    return GL_UNSIGNED_SHORT_5_6_5;
     53     case RS_TYPE_UNSIGNED_5_5_5_1:  return GL_UNSIGNED_SHORT_5_5_5_1;
     54     case RS_TYPE_UNSIGNED_4_4_4_4:  return GL_UNSIGNED_SHORT_4_4_4_4;
     55 
     56     //case RS_TYPE_FLOAT_16:      return GL_HALF_FLOAT;
     57     case RS_TYPE_FLOAT_32:      return GL_FLOAT;
     58     case RS_TYPE_UNSIGNED_8:    return GL_UNSIGNED_BYTE;
     59     case RS_TYPE_UNSIGNED_16:   return GL_UNSIGNED_SHORT;
     60     case RS_TYPE_SIGNED_8:      return GL_BYTE;
     61     case RS_TYPE_SIGNED_16:     return GL_SHORT;
     62     default:    break;
     63     }
     64     return 0;
     65 }
     66 
     67 GLenum rsdKindToGLFormat(RsDataKind k) {
     68     switch (k) {
     69     case RS_KIND_PIXEL_L: return GL_LUMINANCE;
     70     case RS_KIND_PIXEL_A: return GL_ALPHA;
     71     case RS_KIND_PIXEL_LA: return GL_LUMINANCE_ALPHA;
     72     case RS_KIND_PIXEL_RGB: return GL_RGB;
     73     case RS_KIND_PIXEL_RGBA: return GL_RGBA;
     74     case RS_KIND_PIXEL_DEPTH: return GL_DEPTH_COMPONENT16;
     75     default: break;
     76     }
     77     return 0;
     78 }
     79 
     80 uint8_t *GetOffsetPtr(const android::renderscript::Allocation *alloc,
     81                       uint32_t xoff, uint32_t yoff, uint32_t lod,
     82                       RsAllocationCubemapFace face) {
     83     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
     84     uint8_t *ptr = (uint8_t *)drv->lod[lod].mallocPtr;
     85     ptr += face * drv->faceOffset;
     86     ptr += yoff * drv->lod[lod].stride;
     87     ptr += xoff * alloc->mHal.state.elementSizeBytes;
     88     return ptr;
     89 }
     90 
     91 
     92 static void Update2DTexture(const Context *rsc, const Allocation *alloc, const void *ptr,
     93                             uint32_t xoff, uint32_t yoff, uint32_t lod,
     94                             RsAllocationCubemapFace face, uint32_t w, uint32_t h) {
     95     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
     96 
     97     rsAssert(drv->textureID);
     98     RSD_CALL_GL(glBindTexture, drv->glTarget, drv->textureID);
     99     RSD_CALL_GL(glPixelStorei, GL_UNPACK_ALIGNMENT, 1);
    100     GLenum t = GL_TEXTURE_2D;
    101     if (alloc->mHal.state.hasFaces) {
    102         t = gFaceOrder[face];
    103     }
    104     RSD_CALL_GL(glTexSubImage2D, t, lod, xoff, yoff, w, h, drv->glFormat, drv->glType, ptr);
    105 }
    106 
    107 
    108 static void Upload2DTexture(const Context *rsc, const Allocation *alloc, bool isFirstUpload) {
    109     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
    110 
    111     RSD_CALL_GL(glBindTexture, drv->glTarget, drv->textureID);
    112     RSD_CALL_GL(glPixelStorei, GL_UNPACK_ALIGNMENT, 1);
    113 
    114     uint32_t faceCount = 1;
    115     if (alloc->mHal.state.hasFaces) {
    116         faceCount = 6;
    117     }
    118 
    119     rsdGLCheckError(rsc, "Upload2DTexture 1 ");
    120     for (uint32_t face = 0; face < faceCount; face ++) {
    121         for (uint32_t lod = 0; lod < alloc->mHal.state.type->getLODCount(); lod++) {
    122             const uint8_t *p = GetOffsetPtr(alloc, 0, 0, lod, (RsAllocationCubemapFace)face);
    123 
    124             GLenum t = GL_TEXTURE_2D;
    125             if (alloc->mHal.state.hasFaces) {
    126                 t = gFaceOrder[face];
    127             }
    128 
    129             if (isFirstUpload) {
    130                 RSD_CALL_GL(glTexImage2D, t, lod, drv->glFormat,
    131                              alloc->mHal.state.type->getLODDimX(lod),
    132                              alloc->mHal.state.type->getLODDimY(lod),
    133                              0, drv->glFormat, drv->glType, p);
    134             } else {
    135                 RSD_CALL_GL(glTexSubImage2D, t, lod, 0, 0,
    136                                 alloc->mHal.state.type->getLODDimX(lod),
    137                                 alloc->mHal.state.type->getLODDimY(lod),
    138                                 drv->glFormat, drv->glType, p);
    139             }
    140         }
    141     }
    142 
    143     if (alloc->mHal.state.mipmapControl == RS_ALLOCATION_MIPMAP_ON_SYNC_TO_TEXTURE) {
    144         RSD_CALL_GL(glGenerateMipmap, drv->glTarget);
    145     }
    146     rsdGLCheckError(rsc, "Upload2DTexture");
    147 }
    148 
    149 static void UploadToTexture(const Context *rsc, const Allocation *alloc) {
    150     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
    151 
    152     if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_INPUT) {
    153         if (!drv->textureID) {
    154             RSD_CALL_GL(glGenTextures, 1, &drv->textureID);
    155         }
    156         return;
    157     }
    158 
    159     if (!drv->glType || !drv->glFormat) {
    160         return;
    161     }
    162 
    163     if (!drv->lod[0].mallocPtr) {
    164         return;
    165     }
    166 
    167     bool isFirstUpload = false;
    168 
    169     if (!drv->textureID) {
    170         RSD_CALL_GL(glGenTextures, 1, &drv->textureID);
    171         isFirstUpload = true;
    172     }
    173 
    174     Upload2DTexture(rsc, alloc, isFirstUpload);
    175 
    176     if (!(alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT)) {
    177         if (alloc->mHal.drvState.mallocPtrLOD0) {
    178             free(alloc->mHal.drvState.mallocPtrLOD0);
    179             alloc->mHal.drvState.mallocPtrLOD0 = NULL;
    180             drv->lod[0].mallocPtr = NULL;
    181         }
    182     }
    183     rsdGLCheckError(rsc, "UploadToTexture");
    184 }
    185 
    186 static void AllocateRenderTarget(const Context *rsc, const Allocation *alloc) {
    187     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
    188 
    189     if (!drv->glFormat) {
    190         return;
    191     }
    192 
    193     if (!drv->renderTargetID) {
    194         RSD_CALL_GL(glGenRenderbuffers, 1, &drv->renderTargetID);
    195 
    196         if (!drv->renderTargetID) {
    197             // This should generally not happen
    198             ALOGE("allocateRenderTarget failed to gen mRenderTargetID");
    199             rsc->dumpDebug();
    200             return;
    201         }
    202         RSD_CALL_GL(glBindRenderbuffer, GL_RENDERBUFFER, drv->renderTargetID);
    203         RSD_CALL_GL(glRenderbufferStorage, GL_RENDERBUFFER, drv->glFormat,
    204                               alloc->mHal.state.dimensionX, alloc->mHal.state.dimensionY);
    205     }
    206     rsdGLCheckError(rsc, "AllocateRenderTarget");
    207 }
    208 
    209 static void UploadToBufferObject(const Context *rsc, const Allocation *alloc) {
    210     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
    211 
    212     rsAssert(!alloc->mHal.state.type->getDimY());
    213     rsAssert(!alloc->mHal.state.type->getDimZ());
    214 
    215     //alloc->mHal.state.usageFlags |= RS_ALLOCATION_USAGE_GRAPHICS_VERTEX;
    216 
    217     if (!drv->bufferID) {
    218         RSD_CALL_GL(glGenBuffers, 1, &drv->bufferID);
    219     }
    220     if (!drv->bufferID) {
    221         ALOGE("Upload to buffer object failed");
    222         drv->uploadDeferred = true;
    223         return;
    224     }
    225     RSD_CALL_GL(glBindBuffer, drv->glTarget, drv->bufferID);
    226     RSD_CALL_GL(glBufferData, drv->glTarget, alloc->mHal.state.type->getSizeBytes(),
    227                  alloc->mHal.drvState.mallocPtrLOD0, GL_DYNAMIC_DRAW);
    228     RSD_CALL_GL(glBindBuffer, drv->glTarget, 0);
    229     rsdGLCheckError(rsc, "UploadToBufferObject");
    230 }
    231 
    232 static size_t AllocationBuildPointerTable(const Context *rsc, const Allocation *alloc,
    233         const Type *type, uint8_t *ptr) {
    234 
    235     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
    236 
    237     drv->lod[0].dimX = type->getDimX();
    238     drv->lod[0].dimY = type->getDimY();
    239     drv->lod[0].mallocPtr = 0;
    240     drv->lod[0].stride = drv->lod[0].dimX * type->getElementSizeBytes();
    241     drv->lodCount = type->getLODCount();
    242     drv->faceCount = type->getDimFaces();
    243 
    244     size_t offsets[Allocation::MAX_LOD];
    245     memset(offsets, 0, sizeof(offsets));
    246 
    247     size_t o = drv->lod[0].stride * rsMax(drv->lod[0].dimY, 1u) * rsMax(drv->lod[0].dimZ, 1u);
    248     if(drv->lodCount > 1) {
    249         uint32_t tx = drv->lod[0].dimX;
    250         uint32_t ty = drv->lod[0].dimY;
    251         uint32_t tz = drv->lod[0].dimZ;
    252         for (uint32_t lod=1; lod < drv->lodCount; lod++) {
    253             drv->lod[lod].dimX = tx;
    254             drv->lod[lod].dimY = ty;
    255             drv->lod[lod].dimZ = tz;
    256             drv->lod[lod].stride = tx * type->getElementSizeBytes();
    257             offsets[lod] = o;
    258             o += drv->lod[lod].stride * rsMax(ty, 1u) * rsMax(tz, 1u);
    259             if (tx > 1) tx >>= 1;
    260             if (ty > 1) ty >>= 1;
    261             if (tz > 1) tz >>= 1;
    262         }
    263     }
    264     drv->faceOffset = o;
    265 
    266     drv->lod[0].mallocPtr = ptr;
    267     for (uint32_t lod=1; lod < drv->lodCount; lod++) {
    268         drv->lod[lod].mallocPtr = ptr + offsets[lod];
    269     }
    270     alloc->mHal.drvState.strideLOD0 = drv->lod[0].stride;
    271     alloc->mHal.drvState.mallocPtrLOD0 = ptr;
    272 
    273     size_t allocSize = drv->faceOffset;
    274     if(drv->faceCount) {
    275         allocSize *= 6;
    276     }
    277 
    278     return allocSize;
    279 }
    280 
    281 bool rsdAllocationInit(const Context *rsc, Allocation *alloc, bool forceZero) {
    282     DrvAllocation *drv = (DrvAllocation *)calloc(1, sizeof(DrvAllocation));
    283     if (!drv) {
    284         return false;
    285     }
    286     alloc->mHal.drv = drv;
    287 
    288     // Calculate the object size.
    289     size_t allocSize = AllocationBuildPointerTable(rsc, alloc, alloc->getType(), NULL);
    290 
    291     uint8_t * ptr = NULL;
    292     if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_OUTPUT) {
    293     } else {
    294 
    295         ptr = (uint8_t *)malloc(allocSize);
    296         if (!ptr) {
    297             free(drv);
    298             return false;
    299         }
    300     }
    301     // Build the pointer tables
    302     size_t verifySize = AllocationBuildPointerTable(rsc, alloc, alloc->getType(), ptr);
    303     if(allocSize != verifySize) {
    304         rsAssert(!"Size mismatch");
    305     }
    306 
    307     drv->glTarget = GL_NONE;
    308     if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE) {
    309         if (alloc->mHal.state.hasFaces) {
    310             drv->glTarget = GL_TEXTURE_CUBE_MAP;
    311         } else {
    312             drv->glTarget = GL_TEXTURE_2D;
    313         }
    314     } else {
    315         if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_VERTEX) {
    316             drv->glTarget = GL_ARRAY_BUFFER;
    317         }
    318     }
    319 
    320     drv->glType = rsdTypeToGLType(alloc->mHal.state.type->getElement()->getComponent().getType());
    321     drv->glFormat = rsdKindToGLFormat(alloc->mHal.state.type->getElement()->getComponent().getKind());
    322 
    323     if (forceZero && ptr) {
    324         memset(ptr, 0, alloc->mHal.state.type->getSizeBytes());
    325     }
    326 
    327     if (alloc->mHal.state.usageFlags & ~RS_ALLOCATION_USAGE_SCRIPT) {
    328         drv->uploadDeferred = true;
    329     }
    330 
    331 
    332     drv->readBackFBO = NULL;
    333 
    334     return true;
    335 }
    336 
    337 void rsdAllocationDestroy(const Context *rsc, Allocation *alloc) {
    338     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
    339 
    340     if (drv->bufferID) {
    341         // Causes a SW crash....
    342         //ALOGV(" mBufferID %i", mBufferID);
    343         //glDeleteBuffers(1, &mBufferID);
    344         //mBufferID = 0;
    345     }
    346     if (drv->textureID) {
    347         RSD_CALL_GL(glDeleteTextures, 1, &drv->textureID);
    348         drv->textureID = 0;
    349     }
    350     if (drv->renderTargetID) {
    351         RSD_CALL_GL(glDeleteRenderbuffers, 1, &drv->renderTargetID);
    352         drv->renderTargetID = 0;
    353     }
    354 
    355     if (alloc->mHal.drvState.mallocPtrLOD0) {
    356         free(alloc->mHal.drvState.mallocPtrLOD0);
    357         alloc->mHal.drvState.mallocPtrLOD0 = NULL;
    358     }
    359     if (drv->readBackFBO != NULL) {
    360         delete drv->readBackFBO;
    361         drv->readBackFBO = NULL;
    362     }
    363     free(drv);
    364     alloc->mHal.drv = NULL;
    365 }
    366 
    367 void rsdAllocationResize(const Context *rsc, const Allocation *alloc,
    368                          const Type *newType, bool zeroNew) {
    369     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
    370 
    371     void * oldPtr = drv->lod[0].mallocPtr;
    372     // Calculate the object size
    373     size_t s = AllocationBuildPointerTable(rsc, alloc, newType, NULL);
    374     uint8_t *ptr = (uint8_t *)realloc(oldPtr, s);
    375     // Build the relative pointer tables.
    376     size_t verifySize = AllocationBuildPointerTable(rsc, alloc, newType, ptr);
    377     if(s != verifySize) {
    378         rsAssert(!"Size mismatch");
    379     }
    380 
    381     const uint32_t oldDimX = alloc->mHal.state.dimensionX;
    382     const uint32_t dimX = newType->getDimX();
    383 
    384     if (dimX > oldDimX) {
    385         uint32_t stride = alloc->mHal.state.elementSizeBytes;
    386         memset(((uint8_t *)alloc->mHal.drvState.mallocPtrLOD0) + stride * oldDimX,
    387                  0, stride * (dimX - oldDimX));
    388     }
    389 }
    390 
    391 static void rsdAllocationSyncFromFBO(const Context *rsc, const Allocation *alloc) {
    392     if (!alloc->getIsScript()) {
    393         return; // nothing to sync
    394     }
    395 
    396     RsdHal *dc = (RsdHal *)rsc->mHal.drv;
    397     RsdFrameBufferObj *lastFbo = dc->gl.currentFrameBuffer;
    398 
    399     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
    400     if (!drv->textureID && !drv->renderTargetID) {
    401         return; // nothing was rendered here yet, so nothing to sync
    402     }
    403     if (drv->readBackFBO == NULL) {
    404         drv->readBackFBO = new RsdFrameBufferObj();
    405         drv->readBackFBO->setColorTarget(drv, 0);
    406         drv->readBackFBO->setDimensions(alloc->getType()->getDimX(),
    407                                         alloc->getType()->getDimY());
    408     }
    409 
    410     // Bind the framebuffer object so we can read back from it
    411     drv->readBackFBO->setActive(rsc);
    412 
    413     // Do the readback
    414     RSD_CALL_GL(glReadPixels, 0, 0, drv->lod[0].dimX, drv->lod[0].dimY,
    415                 drv->glFormat, drv->glType, drv->lod[0].mallocPtr);
    416 
    417     // Revert framebuffer to its original
    418     lastFbo->setActive(rsc);
    419 }
    420 
    421 
    422 void rsdAllocationSyncAll(const Context *rsc, const Allocation *alloc,
    423                          RsAllocationUsageType src) {
    424     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
    425 
    426     if (src == RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) {
    427         if(!alloc->getIsRenderTarget()) {
    428             rsc->setError(RS_ERROR_FATAL_DRIVER,
    429                           "Attempting to sync allocation from render target, "
    430                           "for non-render target allocation");
    431         } else if (alloc->getType()->getElement()->getKind() != RS_KIND_PIXEL_RGBA) {
    432             rsc->setError(RS_ERROR_FATAL_DRIVER, "Cannot only sync from RGBA"
    433                                                  "render target");
    434         } else {
    435             rsdAllocationSyncFromFBO(rsc, alloc);
    436         }
    437         return;
    438     }
    439 
    440     rsAssert(src == RS_ALLOCATION_USAGE_SCRIPT);
    441 
    442     if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE) {
    443         UploadToTexture(rsc, alloc);
    444     } else {
    445         if ((alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) &&
    446             !(alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_OUTPUT)) {
    447             AllocateRenderTarget(rsc, alloc);
    448         }
    449     }
    450     if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_VERTEX) {
    451         UploadToBufferObject(rsc, alloc);
    452     }
    453 
    454     drv->uploadDeferred = false;
    455 }
    456 
    457 void rsdAllocationMarkDirty(const Context *rsc, const Allocation *alloc) {
    458     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
    459     drv->uploadDeferred = true;
    460 }
    461 
    462 int32_t rsdAllocationInitSurfaceTexture(const Context *rsc, const Allocation *alloc) {
    463     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
    464     UploadToTexture(rsc, alloc);
    465     return drv->textureID;
    466 }
    467 
    468 static bool IoGetBuffer(const Context *rsc, Allocation *alloc, ANativeWindow *nw) {
    469     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
    470 
    471     int32_t r = native_window_dequeue_buffer_and_wait(nw, &drv->wndBuffer);
    472     if (r) {
    473         rsc->setError(RS_ERROR_DRIVER, "Error getting next IO output buffer.");
    474         return false;
    475     }
    476 
    477     // Must lock the whole surface
    478     GraphicBufferMapper &mapper = GraphicBufferMapper::get();
    479     Rect bounds(drv->wndBuffer->width, drv->wndBuffer->height);
    480 
    481     void *dst = NULL;
    482     mapper.lock(drv->wndBuffer->handle,
    483             GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_OFTEN,
    484             bounds, &dst);
    485     drv->lod[0].mallocPtr = dst;
    486     alloc->mHal.drvState.mallocPtrLOD0 = dst;
    487     drv->lod[0].stride = drv->wndBuffer->stride * alloc->mHal.state.elementSizeBytes;
    488 
    489     return true;
    490 }
    491 
    492 void rsdAllocationSetSurfaceTexture(const Context *rsc, Allocation *alloc, ANativeWindow *nw) {
    493     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
    494 
    495     //ALOGE("rsdAllocationSetSurfaceTexture %p  %p", alloc, nw);
    496 
    497     if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) {
    498         //TODO finish support for render target + script
    499         drv->wnd = nw;
    500         return;
    501     }
    502 
    503 
    504     // Cleanup old surface if there is one.
    505     if (alloc->mHal.state.wndSurface) {
    506         ANativeWindow *old = alloc->mHal.state.wndSurface;
    507         GraphicBufferMapper &mapper = GraphicBufferMapper::get();
    508         mapper.unlock(drv->wndBuffer->handle);
    509         old->queueBuffer(old, drv->wndBuffer, -1);
    510     }
    511 
    512     if (nw != NULL) {
    513         int32_t r;
    514         uint32_t flags = 0;
    515         if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT) {
    516             flags |= GRALLOC_USAGE_SW_READ_RARELY | GRALLOC_USAGE_SW_WRITE_OFTEN;
    517         }
    518         if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) {
    519             flags |= GRALLOC_USAGE_HW_RENDER;
    520         }
    521 
    522         r = native_window_set_usage(nw, flags);
    523         if (r) {
    524             rsc->setError(RS_ERROR_DRIVER, "Error setting IO output buffer usage.");
    525             return;
    526         }
    527 
    528         r = native_window_set_buffers_dimensions(nw, alloc->mHal.state.dimensionX,
    529                                                  alloc->mHal.state.dimensionY);
    530         if (r) {
    531             rsc->setError(RS_ERROR_DRIVER, "Error setting IO output buffer dimensions.");
    532             return;
    533         }
    534 
    535         r = native_window_set_buffer_count(nw, 3);
    536         if (r) {
    537             rsc->setError(RS_ERROR_DRIVER, "Error setting IO output buffer count.");
    538             return;
    539         }
    540 
    541         IoGetBuffer(rsc, alloc, nw);
    542     }
    543 }
    544 
    545 void rsdAllocationIoSend(const Context *rsc, Allocation *alloc) {
    546     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
    547     ANativeWindow *nw = alloc->mHal.state.wndSurface;
    548 
    549     if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET) {
    550         RsdHal *dc = (RsdHal *)rsc->mHal.drv;
    551         RSD_CALL_GL(eglSwapBuffers, dc->gl.egl.display, dc->gl.egl.surface);
    552         return;
    553     }
    554 
    555     if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT) {
    556         GraphicBufferMapper &mapper = GraphicBufferMapper::get();
    557         mapper.unlock(drv->wndBuffer->handle);
    558         int32_t r = nw->queueBuffer(nw, drv->wndBuffer, -1);
    559         if (r) {
    560             rsc->setError(RS_ERROR_DRIVER, "Error sending IO output buffer.");
    561             return;
    562         }
    563 
    564         IoGetBuffer(rsc, alloc, nw);
    565     }
    566 }
    567 
    568 void rsdAllocationIoReceive(const Context *rsc, Allocation *alloc) {
    569     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
    570     alloc->mHal.state.surfaceTexture->updateTexImage();
    571 }
    572 
    573 
    574 void rsdAllocationData1D(const Context *rsc, const Allocation *alloc,
    575                          uint32_t xoff, uint32_t lod, uint32_t count,
    576                          const void *data, size_t sizeBytes) {
    577     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
    578 
    579     const uint32_t eSize = alloc->mHal.state.type->getElementSizeBytes();
    580     uint8_t * ptr = GetOffsetPtr(alloc, xoff, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
    581     uint32_t size = count * eSize;
    582 
    583     if (alloc->mHal.state.hasReferences) {
    584         alloc->incRefs(data, count);
    585         alloc->decRefs(ptr, count);
    586     }
    587 
    588     memcpy(ptr, data, size);
    589     drv->uploadDeferred = true;
    590 }
    591 
    592 void rsdAllocationData2D(const Context *rsc, const Allocation *alloc,
    593                          uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face,
    594                          uint32_t w, uint32_t h, const void *data, size_t sizeBytes) {
    595     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
    596 
    597     uint32_t eSize = alloc->mHal.state.elementSizeBytes;
    598     uint32_t lineSize = eSize * w;
    599 
    600     if (drv->lod[0].mallocPtr) {
    601         const uint8_t *src = static_cast<const uint8_t *>(data);
    602         uint8_t *dst = GetOffsetPtr(alloc, xoff, yoff, lod, face);
    603 
    604         for (uint32_t line=yoff; line < (yoff+h); line++) {
    605             if (alloc->mHal.state.hasReferences) {
    606                 alloc->incRefs(src, w);
    607                 alloc->decRefs(dst, w);
    608             }
    609             memcpy(dst, src, lineSize);
    610             src += lineSize;
    611             dst += drv->lod[lod].stride;
    612         }
    613         drv->uploadDeferred = true;
    614     } else {
    615         Update2DTexture(rsc, alloc, data, xoff, yoff, lod, face, w, h);
    616     }
    617 }
    618 
    619 void rsdAllocationData3D(const Context *rsc, const Allocation *alloc,
    620                          uint32_t xoff, uint32_t yoff, uint32_t zoff,
    621                          uint32_t lod, RsAllocationCubemapFace face,
    622                          uint32_t w, uint32_t h, uint32_t d, const void *data, uint32_t sizeBytes) {
    623 
    624 }
    625 
    626 void rsdAllocationRead1D(const Context *rsc, const Allocation *alloc,
    627                          uint32_t xoff, uint32_t lod, uint32_t count,
    628                          void *data, size_t sizeBytes) {
    629     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
    630 
    631     const uint32_t eSize = alloc->mHal.state.type->getElementSizeBytes();
    632     const uint8_t * ptr = GetOffsetPtr(alloc, xoff, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
    633     memcpy(data, ptr, count * eSize);
    634 }
    635 
    636 void rsdAllocationRead2D(const Context *rsc, const Allocation *alloc,
    637                          uint32_t xoff, uint32_t yoff, uint32_t lod, RsAllocationCubemapFace face,
    638                          uint32_t w, uint32_t h, void *data, size_t sizeBytes) {
    639     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
    640 
    641     uint32_t eSize = alloc->mHal.state.elementSizeBytes;
    642     uint32_t lineSize = eSize * w;
    643 
    644     if (drv->lod[0].mallocPtr) {
    645         uint8_t *dst = static_cast<uint8_t *>(data);
    646         const uint8_t *src = GetOffsetPtr(alloc, xoff, yoff, lod, face);
    647 
    648         for (uint32_t line=yoff; line < (yoff+h); line++) {
    649             memcpy(dst, src, lineSize);
    650             dst += lineSize;
    651             src += drv->lod[lod].stride;
    652         }
    653     } else {
    654         ALOGE("Add code to readback from non-script memory");
    655     }
    656 }
    657 
    658 void rsdAllocationRead3D(const Context *rsc, const Allocation *alloc,
    659                          uint32_t xoff, uint32_t yoff, uint32_t zoff,
    660                          uint32_t lod, RsAllocationCubemapFace face,
    661                          uint32_t w, uint32_t h, uint32_t d, void *data, uint32_t sizeBytes) {
    662 
    663 }
    664 
    665 void * rsdAllocationLock1D(const android::renderscript::Context *rsc,
    666                           const android::renderscript::Allocation *alloc) {
    667     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
    668     return drv->lod[0].mallocPtr;
    669 }
    670 
    671 void rsdAllocationUnlock1D(const android::renderscript::Context *rsc,
    672                           const android::renderscript::Allocation *alloc) {
    673 
    674 }
    675 
    676 void rsdAllocationData1D_alloc(const android::renderscript::Context *rsc,
    677                                const android::renderscript::Allocation *dstAlloc,
    678                                uint32_t dstXoff, uint32_t dstLod, uint32_t count,
    679                                const android::renderscript::Allocation *srcAlloc,
    680                                uint32_t srcXoff, uint32_t srcLod) {
    681 }
    682 
    683 
    684 void rsdAllocationData2D_alloc_script(const android::renderscript::Context *rsc,
    685                                       const android::renderscript::Allocation *dstAlloc,
    686                                       uint32_t dstXoff, uint32_t dstYoff, uint32_t dstLod,
    687                                       RsAllocationCubemapFace dstFace, uint32_t w, uint32_t h,
    688                                       const android::renderscript::Allocation *srcAlloc,
    689                                       uint32_t srcXoff, uint32_t srcYoff, uint32_t srcLod,
    690                                       RsAllocationCubemapFace srcFace) {
    691     uint32_t elementSize = dstAlloc->getType()->getElementSizeBytes();
    692     for (uint32_t i = 0; i < h; i ++) {
    693         uint8_t *dstPtr = GetOffsetPtr(dstAlloc, dstXoff, dstYoff + i, dstLod, dstFace);
    694         uint8_t *srcPtr = GetOffsetPtr(srcAlloc, srcXoff, srcYoff + i, srcLod, srcFace);
    695         memcpy(dstPtr, srcPtr, w * elementSize);
    696 
    697         //ALOGE("COPIED dstXoff(%u), dstYoff(%u), dstLod(%u), dstFace(%u), w(%u), h(%u), srcXoff(%u), srcYoff(%u), srcLod(%u), srcFace(%u)",
    698         //     dstXoff, dstYoff, dstLod, dstFace, w, h, srcXoff, srcYoff, srcLod, srcFace);
    699     }
    700 }
    701 
    702 void rsdAllocationData2D_alloc(const android::renderscript::Context *rsc,
    703                                const android::renderscript::Allocation *dstAlloc,
    704                                uint32_t dstXoff, uint32_t dstYoff, uint32_t dstLod,
    705                                RsAllocationCubemapFace dstFace, uint32_t w, uint32_t h,
    706                                const android::renderscript::Allocation *srcAlloc,
    707                                uint32_t srcXoff, uint32_t srcYoff, uint32_t srcLod,
    708                                RsAllocationCubemapFace srcFace) {
    709     if (!dstAlloc->getIsScript() && !srcAlloc->getIsScript()) {
    710         rsc->setError(RS_ERROR_FATAL_DRIVER, "Non-script allocation copies not "
    711                                              "yet implemented.");
    712         return;
    713     }
    714     rsdAllocationData2D_alloc_script(rsc, dstAlloc, dstXoff, dstYoff,
    715                                      dstLod, dstFace, w, h, srcAlloc,
    716                                      srcXoff, srcYoff, srcLod, srcFace);
    717 }
    718 
    719 void rsdAllocationData3D_alloc(const android::renderscript::Context *rsc,
    720                                const android::renderscript::Allocation *dstAlloc,
    721                                uint32_t dstXoff, uint32_t dstYoff, uint32_t dstZoff,
    722                                uint32_t dstLod, RsAllocationCubemapFace dstFace,
    723                                uint32_t w, uint32_t h, uint32_t d,
    724                                const android::renderscript::Allocation *srcAlloc,
    725                                uint32_t srcXoff, uint32_t srcYoff, uint32_t srcZoff,
    726                                uint32_t srcLod, RsAllocationCubemapFace srcFace) {
    727 }
    728 
    729 void rsdAllocationElementData1D(const Context *rsc, const Allocation *alloc,
    730                                 uint32_t x,
    731                                 const void *data, uint32_t cIdx, uint32_t sizeBytes) {
    732     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
    733 
    734     uint32_t eSize = alloc->mHal.state.elementSizeBytes;
    735     uint8_t * ptr = GetOffsetPtr(alloc, x, 0, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
    736 
    737     const Element * e = alloc->mHal.state.type->getElement()->getField(cIdx);
    738     ptr += alloc->mHal.state.type->getElement()->getFieldOffsetBytes(cIdx);
    739 
    740     if (alloc->mHal.state.hasReferences) {
    741         e->incRefs(data);
    742         e->decRefs(ptr);
    743     }
    744 
    745     memcpy(ptr, data, sizeBytes);
    746     drv->uploadDeferred = true;
    747 }
    748 
    749 void rsdAllocationElementData2D(const Context *rsc, const Allocation *alloc,
    750                                 uint32_t x, uint32_t y,
    751                                 const void *data, uint32_t cIdx, uint32_t sizeBytes) {
    752     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
    753 
    754     uint32_t eSize = alloc->mHal.state.elementSizeBytes;
    755     uint8_t * ptr = GetOffsetPtr(alloc, x, y, 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X);
    756 
    757     const Element * e = alloc->mHal.state.type->getElement()->getField(cIdx);
    758     ptr += alloc->mHal.state.type->getElement()->getFieldOffsetBytes(cIdx);
    759 
    760     if (alloc->mHal.state.hasReferences) {
    761         e->incRefs(data);
    762         e->decRefs(ptr);
    763     }
    764 
    765     memcpy(ptr, data, sizeBytes);
    766     drv->uploadDeferred = true;
    767 }
    768 
    769 static void mip565(const Allocation *alloc, int lod, RsAllocationCubemapFace face) {
    770     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
    771     uint32_t w = drv->lod[lod + 1].dimX;
    772     uint32_t h = drv->lod[lod + 1].dimY;
    773 
    774     for (uint32_t y=0; y < h; y++) {
    775         uint16_t *oPtr = (uint16_t *)GetOffsetPtr(alloc, 0, y, lod + 1, face);
    776         const uint16_t *i1 = (uint16_t *)GetOffsetPtr(alloc, 0, y*2, lod, face);
    777         const uint16_t *i2 = (uint16_t *)GetOffsetPtr(alloc, 0, y*2+1, lod, face);
    778 
    779         for (uint32_t x=0; x < w; x++) {
    780             *oPtr = rsBoxFilter565(i1[0], i1[1], i2[0], i2[1]);
    781             oPtr ++;
    782             i1 += 2;
    783             i2 += 2;
    784         }
    785     }
    786 }
    787 
    788 static void mip8888(const Allocation *alloc, int lod, RsAllocationCubemapFace face) {
    789     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
    790     uint32_t w = drv->lod[lod + 1].dimX;
    791     uint32_t h = drv->lod[lod + 1].dimY;
    792 
    793     for (uint32_t y=0; y < h; y++) {
    794         uint32_t *oPtr = (uint32_t *)GetOffsetPtr(alloc, 0, y, lod + 1, face);
    795         const uint32_t *i1 = (uint32_t *)GetOffsetPtr(alloc, 0, y*2, lod, face);
    796         const uint32_t *i2 = (uint32_t *)GetOffsetPtr(alloc, 0, y*2+1, lod, face);
    797 
    798         for (uint32_t x=0; x < w; x++) {
    799             *oPtr = rsBoxFilter8888(i1[0], i1[1], i2[0], i2[1]);
    800             oPtr ++;
    801             i1 += 2;
    802             i2 += 2;
    803         }
    804     }
    805 }
    806 
    807 static void mip8(const Allocation *alloc, int lod, RsAllocationCubemapFace face) {
    808     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
    809     uint32_t w = drv->lod[lod + 1].dimX;
    810     uint32_t h = drv->lod[lod + 1].dimY;
    811 
    812     for (uint32_t y=0; y < h; y++) {
    813         uint8_t *oPtr = GetOffsetPtr(alloc, 0, y, lod + 1, face);
    814         const uint8_t *i1 = GetOffsetPtr(alloc, 0, y*2, lod, face);
    815         const uint8_t *i2 = GetOffsetPtr(alloc, 0, y*2+1, lod, face);
    816 
    817         for (uint32_t x=0; x < w; x++) {
    818             *oPtr = (uint8_t)(((uint32_t)i1[0] + i1[1] + i2[0] + i2[1]) * 0.25f);
    819             oPtr ++;
    820             i1 += 2;
    821             i2 += 2;
    822         }
    823     }
    824 }
    825 
    826 void rsdAllocationGenerateMipmaps(const Context *rsc, const Allocation *alloc) {
    827     DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
    828     if(!drv->lod[0].mallocPtr) {
    829         return;
    830     }
    831     uint32_t numFaces = alloc->getType()->getDimFaces() ? 6 : 1;
    832     for (uint32_t face = 0; face < numFaces; face ++) {
    833         for (uint32_t lod=0; lod < (alloc->getType()->getLODCount() -1); lod++) {
    834             switch (alloc->getType()->getElement()->getSizeBits()) {
    835             case 32:
    836                 mip8888(alloc, lod, (RsAllocationCubemapFace)face);
    837                 break;
    838             case 16:
    839                 mip565(alloc, lod, (RsAllocationCubemapFace)face);
    840                 break;
    841             case 8:
    842                 mip8(alloc, lod, (RsAllocationCubemapFace)face);
    843                 break;
    844             }
    845         }
    846     }
    847 }
    848 
    849 
    850