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