1#include <android/native_window.h>
2#include <android/log.h>
3
4#include "rsCompatibilityLib.h"
5
6#include "rsdCore.h"
7#include "rsdAllocation.h"
8#include "rsAllocation.h"
9
10#define LOG_API(...)
11
12using namespace android;
13using namespace android::renderscript;
14
15static bool IoGetBuffer(const Context *rsc, Allocation *alloc, ANativeWindow *nw) {
16    DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
17    // Must lock the whole surface
18    if(drv->wndBuffer == NULL) {
19        drv->wndBuffer = new ANativeWindow_Buffer;
20    }
21    int32_t r = ANativeWindow_lock(nw, drv->wndBuffer, NULL);
22    if (r) {
23        LOG_API("Error Locking IO output buffer.");
24        return false;
25    }
26
27    void *dst = drv->wndBuffer->bits;
28    alloc->mHal.drvState.lod[0].mallocPtr = dst;
29    alloc->mHal.drvState.lod[0].stride = drv->wndBuffer->stride * alloc->mHal.state.elementSizeBytes;
30    return true;
31}
32
33extern "C" void rscAllocationSetSurface(RsContext rscR, RsAllocation allocR, ANativeWindow *nw) {
34    Context *rsc = (Context *)rscR;
35    Allocation *alloc = (Allocation *)allocR;
36    DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
37
38    // Cleanup old surface if there is one.
39    if (drv->wndSurface) {
40        ANativeWindow *old = drv->wndSurface;
41        ANativeWindow_unlockAndPost(old);
42        drv->wndSurface = NULL;
43        ANativeWindow_release(old);
44        old = NULL;
45    }
46
47    if (nw != NULL) {
48        int32_t r;
49        r = ANativeWindow_setBuffersGeometry(nw, alloc->mHal.drvState.lod[0].dimX,
50                                                 alloc->mHal.drvState.lod[0].dimY,
51                                                 WINDOW_FORMAT_RGBA_8888);
52        if (r) {
53            LOG_API("Error setting IO output buffer geometry.");
54            goto errorcmp;
55        }
56
57        IoGetBuffer(rsc, alloc, nw);
58        drv->wndSurface = nw;
59    }
60
61    return;
62
63 errorcmp:
64
65    if (nw) {
66        nw = NULL;
67    }
68
69}
70
71extern "C" void rscAllocationDestroy(const Context *rsc, Allocation *alloc) {
72    DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
73    if (alloc->mHal.drvState.lod[0].mallocPtr) {
74        // don't free user-allocated ptrs or IO_OUTPUT buffers
75        if (!(drv->useUserProvidedPtr) &&
76            !(alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_INPUT) &&
77            !(alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_OUTPUT)) {
78                free(alloc->mHal.drvState.lod[0].mallocPtr);
79        }
80        alloc->mHal.drvState.lod[0].mallocPtr = NULL;
81    }
82
83    if ((alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_IO_OUTPUT) &&
84        (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT)) {
85        ANativeWindow *nw = drv->wndSurface;
86        if (nw) {
87            //If we have an attached surface, need to release it.
88            ANativeWindow_unlockAndPost(nw);
89            drv->wndSurface = NULL;
90            ANativeWindow_release(nw);
91            nw = NULL;
92        }
93    }
94}
95
96extern "C" void rscAllocationIoSend(const Context *rsc, Allocation *alloc) {
97    DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
98    ANativeWindow *nw = drv->wndSurface;
99    if (nw) {
100        if (alloc->mHal.state.usageFlags & RS_ALLOCATION_USAGE_SCRIPT) {
101            int32_t r = ANativeWindow_unlockAndPost(nw);
102            if (r) {
103                LOG_API("Error sending IO output buffer.");
104                return;
105            }
106            IoGetBuffer(rsc, alloc, nw);
107        }
108    } else {
109        LOG_API("Sent IO buffer with no attached surface.");
110        return;
111    }
112}
113
114