Commit | Line | Data |
---|---|---|
d42e7319 JB |
1 | #include <ws.h> |
2 | #include <stdlib.h> | |
3 | #include <dlfcn.h> | |
4 | #include <string.h> | |
5 | #include <android/hardware/gralloc.h> | |
6 | #include <stdio.h> | |
7 | #include <assert.h> | |
8 | #include "config.h" | |
9 | #include <time.h> | |
10 | #include <sys/types.h> | |
11 | #include <sys/stat.h> | |
12 | #include <fcntl.h> | |
13 | #include <unistd.h> | |
14 | #include "logging.h" | |
15 | ||
16 | #ifdef WANT_WAYLAND | |
17 | #include <wayland-client.h> | |
18 | #include "server_wlegl.h" | |
19 | #include "server_wlegl_buffer.h" | |
20 | #endif | |
21 | ||
22 | #include "windowbuffer.h" | |
23 | ||
24 | static gralloc_module_t *my_gralloc = 0; | |
25 | static alloc_device_t *my_alloc = 0; | |
26 | ||
27 | extern "C" void eglplatformcommon_init(gralloc_module_t *gralloc, alloc_device_t *allocdevice) | |
28 | { | |
29 | my_gralloc = gralloc; | |
30 | my_alloc = allocdevice; | |
31 | } | |
32 | ||
33 | extern "C" int hybris_register_buffer_handle(buffer_handle_t handle) | |
34 | { | |
35 | if (!my_gralloc) | |
36 | return -1; | |
37 | ||
38 | return my_gralloc->registerBuffer(my_gralloc, handle); | |
39 | } | |
40 | ||
41 | extern "C" int hybris_unregister_buffer_handle(buffer_handle_t handle) | |
42 | { | |
43 | if (!my_gralloc) | |
44 | return -1; | |
45 | ||
46 | return my_gralloc->unregisterBuffer(my_gralloc, handle); | |
47 | } | |
48 | ||
49 | extern "C" void hybris_dump_buffer_to_file(ANativeWindowBuffer *buf) | |
50 | { | |
51 | static int cnt = 0; | |
52 | void *vaddr; | |
53 | int ret = my_gralloc->lock(my_gralloc, buf->handle, buf->usage, 0, 0, buf->width, buf->height, &vaddr); | |
54 | TRACE("buf:%p gralloc lock returns %i", buf, ret); | |
55 | TRACE("buf:%p lock to vaddr %p", buf, vaddr); | |
56 | char b[1024]; | |
57 | int bytes_pp = 0; | |
58 | ||
59 | if (buf->format == HAL_PIXEL_FORMAT_RGBA_8888) | |
60 | bytes_pp = 4; | |
61 | else if (buf->format == HAL_PIXEL_FORMAT_RGB_565) | |
62 | bytes_pp = 2; | |
63 | ||
64 | snprintf(b, 1020, "vaddr.%p.%p.%i.%is%ix%ix%i", buf, vaddr, cnt, buf->width, buf->stride, buf->height, bytes_pp); | |
65 | cnt++; | |
66 | int fd = ::open(b, O_WRONLY|O_CREAT, S_IRWXU); | |
67 | ||
68 | ::write(fd, vaddr, buf->stride * buf->height * bytes_pp); | |
69 | ::close(fd); | |
70 | my_gralloc->unlock(my_gralloc, buf->handle); | |
71 | } | |
72 | ||
73 | #ifdef WANT_WAYLAND | |
74 | ||
75 | extern "C" EGLBoolean eglplatformcommon_eglBindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display) | |
76 | { | |
77 | assert(my_gralloc != NULL); | |
78 | server_wlegl_create(display, my_gralloc); | |
79 | return EGL_TRUE; | |
80 | } | |
81 | ||
82 | extern "C" EGLBoolean eglplatformcommon_eglUnbindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display) | |
83 | { | |
84 | return EGL_TRUE; | |
85 | } | |
86 | ||
87 | extern "C" EGLBoolean eglplatformcommon_eglQueryWaylandBufferWL(EGLDisplay dpy, | |
88 | struct wl_buffer *buffer, EGLint attribute, EGLint *value) | |
89 | { | |
90 | server_wlegl_buffer *buf = server_wlegl_buffer_from(buffer); | |
91 | ANativeWindowBuffer* anwb = (ANativeWindowBuffer *) buf->buf; | |
92 | ||
93 | if (attribute == EGL_TEXTURE_FORMAT) { | |
94 | switch(anwb->format) { | |
95 | case HAL_PIXEL_FORMAT_RGB_565: | |
96 | *value = EGL_TEXTURE_RGB; | |
97 | break; | |
98 | case HAL_PIXEL_FORMAT_RGBA_8888: | |
99 | *value = EGL_TEXTURE_RGBA; | |
100 | break; | |
101 | default: | |
102 | *value = EGL_TEXTURE_EXTERNAL_WL; | |
103 | } | |
104 | return EGL_TRUE; | |
105 | } | |
106 | if (attribute == EGL_WIDTH) { | |
107 | *value = anwb->width; | |
108 | return EGL_TRUE; | |
109 | } | |
110 | if (attribute == EGL_HEIGHT) { | |
111 | *value = anwb->height; | |
112 | return EGL_TRUE; | |
113 | } | |
114 | return EGL_FALSE ; | |
115 | } | |
116 | ||
117 | #endif | |
118 | ||
119 | extern "C" EGLBoolean eglplatformcommon_eglHybrisCreateNativeBuffer(EGLint width, EGLint height, EGLint usage, EGLint format, EGLint *stride, EGLClientBuffer *buffer) | |
120 | { | |
121 | int ret; | |
122 | buffer_handle_t _handle; | |
123 | int _stride; | |
124 | ||
125 | assert(my_gralloc != NULL); | |
126 | assert(my_alloc != NULL); | |
127 | ||
128 | ret = my_alloc->alloc(my_alloc, width, height, format, usage, &_handle, &_stride); | |
129 | ||
130 | if (ret == 0) | |
131 | { | |
132 | RemoteWindowBuffer *buf = new RemoteWindowBuffer(width, height, _stride, format, usage, _handle, my_gralloc); | |
133 | buf->common.incRef(&buf->common); | |
134 | *buffer = (EGLClientBuffer) static_cast<ANativeWindowBuffer *>(buf); | |
135 | *stride = _stride; | |
136 | return EGL_TRUE; | |
137 | } | |
138 | else | |
139 | return EGL_FALSE; | |
140 | } | |
141 | ||
142 | extern "C" EGLBoolean eglplatformcommon_eglHybrisLockNativeBuffer(EGLClientBuffer buffer, EGLint usage, EGLint l, EGLint t, EGLint w, EGLint h, void **vaddr) | |
143 | { | |
144 | int ret; | |
145 | RemoteWindowBuffer *buf = static_cast<RemoteWindowBuffer *>((ANativeWindowBuffer *) buffer); | |
146 | ||
147 | assert(my_gralloc != NULL); | |
148 | ||
149 | ret = my_gralloc->lock(my_gralloc, buf->handle, usage, l, t, w, h, vaddr); | |
150 | if (ret == 0) | |
151 | return EGL_TRUE; | |
152 | else | |
153 | return EGL_FALSE; | |
154 | } | |
155 | ||
156 | extern "C" EGLBoolean eglplatformcommon_eglHybrisUnlockNativeBuffer(EGLClientBuffer buffer) | |
157 | { | |
158 | int ret; | |
159 | RemoteWindowBuffer *buf = static_cast<RemoteWindowBuffer *>((ANativeWindowBuffer *) buffer); | |
160 | ||
161 | assert(my_gralloc != NULL); | |
162 | ||
163 | ret = my_gralloc->unlock(my_gralloc, buf->handle); | |
164 | if (ret == 0) | |
165 | return EGL_TRUE; | |
166 | else | |
167 | return EGL_FALSE; | |
168 | } | |
169 | ||
170 | ||
171 | extern "C" EGLBoolean eglplatformcommon_eglHybrisReleaseNativeBuffer(EGLClientBuffer buffer) | |
172 | { | |
173 | RemoteWindowBuffer *buf = static_cast<RemoteWindowBuffer *>((ANativeWindowBuffer *) buffer); | |
174 | ||
175 | buf->common.decRef(&buf->common); | |
176 | return EGL_TRUE; | |
177 | } | |
178 | ||
179 | ||
180 | ||
181 | extern "C" void | |
182 | eglplatformcommon_passthroughImageKHR(EGLContext *ctx, EGLenum *target, EGLClientBuffer *buffer, const EGLint **attrib_list) | |
183 | { | |
184 | #ifdef WANT_WAYLAND | |
185 | static int debugenvchecked = 0; | |
186 | if (*target == EGL_WAYLAND_BUFFER_WL) | |
187 | { | |
188 | server_wlegl_buffer *buf = server_wlegl_buffer_from((struct wl_buffer *)*buffer); | |
189 | HYBRIS_TRACE_BEGIN("eglplatformcommon", "Wayland_eglImageKHR", "-resource@%i", ((struct wl_buffer *)*buffer)->resource.object.id); | |
190 | HYBRIS_TRACE_END("eglplatformcommon", "Wayland_eglImageKHR", "-resource@%i", ((struct wl_buffer *)*buffer)->resource.object.id); | |
191 | if (debugenvchecked == 0) | |
192 | { | |
193 | if (getenv("HYBRIS_WAYLAND_KHR_DUMP_BUFFERS") != NULL) | |
194 | debugenvchecked = 2; | |
195 | else | |
196 | debugenvchecked = 1; | |
197 | } else if (debugenvchecked == 2) | |
198 | { | |
199 | hybris_dump_buffer_to_file((ANativeWindowBuffer *) buf->buf); | |
200 | } | |
201 | *buffer = (EGLClientBuffer) (ANativeWindowBuffer *) buf->buf; | |
202 | *target = EGL_NATIVE_BUFFER_ANDROID; | |
203 | *ctx = EGL_NO_CONTEXT; | |
204 | *attrib_list = NULL; | |
205 | } | |
206 | #endif | |
207 | } | |
208 | ||
209 | extern "C" __eglMustCastToProperFunctionPointerType eglplatformcommon_eglGetProcAddress(const char *procname) | |
210 | { | |
211 | #ifdef WANT_WAYLAND | |
212 | if (strcmp(procname, "eglBindWaylandDisplayWL") == 0) | |
213 | { | |
214 | return (__eglMustCastToProperFunctionPointerType)eglplatformcommon_eglBindWaylandDisplayWL; | |
215 | } | |
216 | else | |
217 | if (strcmp(procname, "eglUnbindWaylandDisplayWL") == 0) | |
218 | { | |
219 | return (__eglMustCastToProperFunctionPointerType)eglplatformcommon_eglUnbindWaylandDisplayWL; | |
220 | }else | |
221 | if (strcmp(procname, "eglQueryWaylandBufferWL") == 0) | |
222 | { | |
223 | return (__eglMustCastToProperFunctionPointerType)eglplatformcommon_eglQueryWaylandBufferWL; | |
224 | } | |
225 | else | |
226 | #endif | |
227 | if (strcmp(procname, "eglHybrisCreateNativeBuffer") == 0) | |
228 | { | |
229 | return (__eglMustCastToProperFunctionPointerType)eglplatformcommon_eglHybrisCreateNativeBuffer; | |
230 | } | |
231 | else | |
232 | if (strcmp(procname, "eglHybrisLockNativeBuffer") == 0) | |
233 | { | |
234 | return (__eglMustCastToProperFunctionPointerType)eglplatformcommon_eglHybrisLockNativeBuffer; | |
235 | } | |
236 | else | |
237 | if (strcmp(procname, "eglHybrisUnlockNativeBuffer") == 0) | |
238 | { | |
239 | return (__eglMustCastToProperFunctionPointerType)eglplatformcommon_eglHybrisUnlockNativeBuffer; | |
240 | } | |
241 | else | |
242 | if (strcmp(procname, "eglHybrisReleaseNativeBuffer") == 0) | |
243 | { | |
244 | return (__eglMustCastToProperFunctionPointerType)eglplatformcommon_eglHybrisReleaseNativeBuffer; | |
245 | } | |
246 | return NULL; | |
247 | } | |
248 | ||
249 | extern "C" const char *eglplatformcommon_eglQueryString(EGLDisplay dpy, EGLint name, const char *(*real_eglQueryString)(EGLDisplay dpy, EGLint name)) | |
250 | { | |
251 | #ifdef WANT_WAYLAND | |
252 | if (name == EGL_EXTENSIONS) | |
253 | { | |
254 | const char *ret = (*real_eglQueryString)(dpy, name); | |
255 | static char eglextensionsbuf[512]; | |
256 | assert(ret != NULL); | |
257 | snprintf(eglextensionsbuf, 510, "%sEGL_HYBRIS_native_buffer %s", ret, | |
258 | #ifdef WANT_WAYLAND | |
259 | "EGL_WL_bind_wayland_display " | |
260 | #else | |
261 | "" | |
262 | #endif | |
263 | ); | |
264 | ret = eglextensionsbuf; | |
265 | return ret; | |
266 | } | |
267 | #endif | |
268 | return (*real_eglQueryString)(dpy, name); | |
269 | } |