Commit | Line | Data |
---|---|---|
d42e7319 JB |
1 | /**************************************************************************************** |
2 | ** | |
3 | ** Copyright (C) 2013 Jolla Ltd. | |
4 | ** Contact: Carsten Munk <carsten.munk@jollamobile.com> | |
5 | ** All rights reserved. | |
6 | ** | |
7 | ** This file is part of Wayland enablement for libhybris | |
8 | ** | |
9 | ** You may use this file under the terms of the GNU Lesser General | |
10 | ** Public License version 2.1 as published by the Free Software Foundation | |
11 | ** and appearing in the file license.lgpl included in the packaging | |
12 | ** of this file. | |
13 | ** | |
14 | ** This library is free software; you can redistribute it and/or | |
15 | ** modify it under the terms of the GNU Lesser General Public | |
16 | ** License version 2.1 as published by the Free Software Foundation | |
17 | ** and appearing in the file license.lgpl included in the packaging | |
18 | ** of this file. | |
19 | ** | |
20 | ** This library is distributed in the hope that it will be useful, | |
21 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of | |
22 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
23 | ** Lesser General Public License for more details. | |
24 | ** | |
25 | ****************************************************************************************/ | |
26 | ||
27 | ||
28 | #include "wayland_window.h" | |
29 | #include "wayland-egl-priv.h" | |
30 | #include <assert.h> | |
31 | #include <stdlib.h> | |
32 | #include <errno.h> | |
33 | ||
34 | #include "logging.h" | |
35 | #include <android/android-version.h> | |
36 | #include <eglhybris.h> | |
37 | ||
38 | #if ANDROID_VERSION_MAJOR>=4 && ANDROID_VERSION_MINOR>=2 | |
39 | extern "C" { | |
40 | #include <android/sync/sync.h> | |
41 | } | |
42 | #endif | |
43 | ||
44 | ||
45 | ||
46 | void WaylandNativeWindowBuffer::wlbuffer_from_native_handle(struct android_wlegl *android_wlegl) | |
47 | { | |
48 | struct wl_array ints; | |
49 | int *ints_data; | |
50 | struct android_wlegl_handle *wlegl_handle; | |
51 | ||
52 | wl_array_init(&ints); | |
53 | ints_data = (int*) wl_array_add(&ints, handle->numInts*sizeof(int)); | |
54 | memcpy(ints_data, handle->data + handle->numFds, handle->numInts*sizeof(int)); | |
55 | ||
56 | wlegl_handle = android_wlegl_create_handle(android_wlegl, handle->numFds, &ints); | |
57 | ||
58 | wl_array_release(&ints); | |
59 | ||
60 | for (int i = 0; i < handle->numFds; i++) { | |
61 | android_wlegl_handle_add_fd(wlegl_handle, handle->data[i]); | |
62 | } | |
63 | ||
64 | wlbuffer = android_wlegl_create_buffer(android_wlegl, | |
65 | width, height, stride, | |
66 | format, usage, wlegl_handle); | |
67 | ||
68 | android_wlegl_handle_destroy(wlegl_handle); | |
69 | } | |
70 | ||
71 | void WaylandNativeWindow::resize_callback(struct wl_egl_window *egl_window, void *) | |
72 | { | |
73 | TRACE("%dx%d",egl_window->width,egl_window->height); | |
74 | native_window_set_buffers_dimensions( | |
75 | (WaylandNativeWindow*)egl_window->nativewindow, | |
76 | egl_window->width,egl_window->height); | |
77 | } | |
78 | ||
79 | void WaylandNativeWindow::lock() | |
80 | { | |
81 | pthread_mutex_lock(&this->mutex); | |
82 | } | |
83 | ||
84 | void WaylandNativeWindow::unlock() | |
85 | { | |
86 | pthread_mutex_unlock(&this->mutex); | |
87 | } | |
88 | ||
89 | void | |
90 | WaylandNativeWindow::registry_handle_global(void *data, struct wl_registry *registry, uint32_t name, | |
91 | const char *interface, uint32_t version) | |
92 | { | |
93 | WaylandNativeWindow *nw = static_cast<WaylandNativeWindow *>(data); | |
94 | ||
95 | if (strcmp(interface, "android_wlegl") == 0) { | |
96 | nw->m_android_wlegl = static_cast<struct android_wlegl *>(wl_registry_bind(registry, name, &android_wlegl_interface, 1)); | |
97 | } | |
98 | } | |
99 | ||
100 | static const struct wl_registry_listener registry_listener = { | |
101 | WaylandNativeWindow::registry_handle_global | |
102 | }; | |
103 | ||
104 | ||
105 | void | |
106 | WaylandNativeWindow::sync_callback(void *data, struct wl_callback *callback, uint32_t serial) | |
107 | { | |
108 | int *done = static_cast<int *>(data); | |
109 | ||
110 | *done = 1; | |
111 | wl_callback_destroy(callback); | |
112 | } | |
113 | ||
114 | static const struct wl_callback_listener sync_listener = { | |
115 | WaylandNativeWindow::sync_callback | |
116 | }; | |
117 | ||
118 | int | |
119 | WaylandNativeWindow::wayland_roundtrip(WaylandNativeWindow *display) | |
120 | { | |
121 | struct wl_callback *callback; | |
122 | int done = 0, ret = 0; | |
123 | wl_display_dispatch_queue_pending(display->m_display, display->wl_queue); | |
124 | ||
125 | callback = wl_display_sync(display->m_display); | |
126 | wl_callback_add_listener(callback, &sync_listener, &done); | |
127 | wl_proxy_set_queue((struct wl_proxy *) callback, display->wl_queue); | |
128 | while (ret == 0 && !done) | |
129 | ret = wl_display_dispatch_queue(display->m_display, display->wl_queue); | |
130 | ||
131 | return ret; | |
132 | } | |
133 | ||
134 | static void check_fatal_error(struct wl_display *display) | |
135 | { | |
136 | int error = wl_display_get_error(display); | |
137 | ||
138 | if (error == 0) | |
139 | return; | |
140 | ||
141 | fprintf(stderr, "Wayland display got fatal error %i: %s\n", error, strerror(error)); | |
142 | ||
143 | if (errno != 0) | |
144 | fprintf(stderr, "Additionally, errno was set to %i: %s\n", errno, strerror(errno)); | |
145 | ||
146 | fprintf(stderr, "The display is now unusable, aborting.\n"); | |
147 | abort(); | |
148 | } | |
149 | ||
150 | static void | |
151 | wayland_frame_callback(void *data, struct wl_callback *callback, uint32_t time) | |
152 | { | |
153 | WaylandNativeWindow *surface = static_cast<WaylandNativeWindow *>(data); | |
154 | surface->frame(); | |
155 | wl_callback_destroy(callback); | |
156 | } | |
157 | ||
158 | static const struct wl_callback_listener frame_listener = { | |
159 | wayland_frame_callback | |
160 | }; | |
161 | ||
162 | WaylandNativeWindow::WaylandNativeWindow(struct wl_egl_window *window, struct wl_display *display, const gralloc_module_t* gralloc, alloc_device_t* alloc_device) | |
163 | { | |
164 | int wayland_ok; | |
165 | ||
166 | HYBRIS_TRACE_BEGIN("wayland-platform", "create_window", ""); | |
167 | this->m_window = window; | |
168 | this->m_window->nativewindow = (void *) this; | |
169 | this->m_display = display; | |
170 | this->m_width = window->width; | |
171 | this->m_height = window->height; | |
172 | this->m_defaultWidth = window->width; | |
173 | this->m_defaultHeight = window->height; | |
174 | this->m_window->resize_callback = resize_callback; | |
175 | this->m_format = 1; | |
176 | this->wl_queue = wl_display_create_queue(display); | |
177 | this->frame_callback = NULL; | |
178 | this->registry = wl_display_get_registry(display); | |
179 | wl_proxy_set_queue((struct wl_proxy *) this->registry, | |
180 | this->wl_queue); | |
181 | wl_registry_add_listener(this->registry, ®istry_listener, this); | |
182 | ||
183 | wayland_ok = wayland_roundtrip(this); | |
184 | assert(wayland_ok >= 0); | |
185 | assert(this->m_android_wlegl != NULL); | |
186 | ||
187 | this->m_gralloc = gralloc; | |
188 | this->m_alloc = alloc_device; | |
189 | ||
190 | m_usage=GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE; | |
191 | pthread_mutex_init(&mutex, NULL); | |
192 | pthread_cond_init(&cond, NULL); | |
193 | m_freeBufs = 0; | |
194 | setBufferCount(3); | |
195 | HYBRIS_TRACE_END("wayland-platform", "create_window", ""); | |
196 | } | |
197 | ||
198 | WaylandNativeWindow::~WaylandNativeWindow() | |
199 | { | |
200 | std::list<WaylandNativeWindowBuffer *>::iterator it = m_bufList.begin(); | |
201 | for (; it != m_bufList.end(); it++) | |
202 | { | |
203 | WaylandNativeWindowBuffer* buf=*it; | |
204 | if (buf->wlbuffer) | |
205 | wl_buffer_destroy(buf->wlbuffer); | |
206 | buf->wlbuffer = NULL; | |
207 | buf->common.decRef(&buf->common); | |
208 | } | |
209 | if (frame_callback) | |
210 | wl_callback_destroy(frame_callback); | |
211 | wl_registry_destroy(registry); | |
212 | wl_event_queue_destroy(wl_queue); | |
213 | android_wlegl_destroy(m_android_wlegl); | |
214 | } | |
215 | ||
216 | void WaylandNativeWindow::frame() { | |
217 | HYBRIS_TRACE_BEGIN("wayland-platform", "frame_event", ""); | |
218 | ||
219 | this->frame_callback = NULL; | |
220 | ||
221 | HYBRIS_TRACE_END("wayland-platform", "frame_event", ""); | |
222 | } | |
223 | ||
224 | ||
225 | // overloads from BaseNativeWindow | |
226 | int WaylandNativeWindow::setSwapInterval(int interval) { | |
227 | TRACE("interval:%i", interval); | |
228 | return 0; | |
229 | } | |
230 | ||
231 | static void | |
232 | wl_buffer_release(void *data, struct wl_buffer *buffer) | |
233 | { | |
234 | WaylandNativeWindow *win = static_cast<WaylandNativeWindow *>(data); | |
235 | win->releaseBuffer(buffer); | |
236 | } | |
237 | ||
238 | static struct wl_buffer_listener wl_buffer_listener = { | |
239 | wl_buffer_release | |
240 | }; | |
241 | ||
242 | void WaylandNativeWindow::releaseBuffer(struct wl_buffer *buffer) | |
243 | { | |
244 | lock(); | |
245 | std::list<WaylandNativeWindowBuffer *>::iterator it = posted.begin(); | |
246 | ||
247 | for (; it != posted.end(); it++) | |
248 | { | |
249 | if ((*it)->wlbuffer == buffer) | |
250 | break; | |
251 | } | |
252 | ||
253 | if (it != posted.end()) | |
254 | { | |
255 | WaylandNativeWindowBuffer* pwnb = *it; | |
256 | posted.erase(it); | |
257 | TRACE("released posted buffer: %p", buffer); | |
258 | pwnb->busy = 0; | |
259 | pthread_cond_signal(&cond); | |
260 | unlock(); | |
261 | return; | |
262 | } | |
263 | ||
264 | it = fronted.begin(); | |
265 | ||
266 | for (; it != fronted.end(); it++) | |
267 | { | |
268 | if ((*it)->wlbuffer == buffer) | |
269 | break; | |
270 | } | |
271 | assert(it != fronted.end()); | |
272 | ||
273 | ||
274 | ||
275 | WaylandNativeWindowBuffer* wnb = *it; | |
276 | fronted.erase(it); | |
277 | HYBRIS_TRACE_COUNTER("wayland-platform", "fronted.size", "%i", fronted.size()); | |
278 | ||
279 | for (it = m_bufList.begin(); it != m_bufList.end(); it++) | |
280 | { | |
281 | if ((*it) == wnb) | |
282 | break; | |
283 | } | |
284 | assert(it != m_bufList.end()); | |
285 | HYBRIS_TRACE_BEGIN("wayland-platform", "releaseBuffer", "-%p", wnb); | |
286 | wnb->busy = 0; | |
287 | ||
288 | ++m_freeBufs; | |
289 | HYBRIS_TRACE_COUNTER("wayland-platform", "m_freeBufs", "%i", m_freeBufs); | |
290 | for (it = m_bufList.begin(); it != m_bufList.end(); it++) | |
291 | { | |
292 | (*it)->youngest = 0; | |
293 | } | |
294 | wnb->youngest = 1; | |
295 | ||
296 | ||
297 | pthread_cond_signal(&cond); | |
298 | HYBRIS_TRACE_END("wayland-platform", "releaseBuffer", "-%p", wnb); | |
299 | unlock(); | |
300 | } | |
301 | ||
302 | ||
303 | int WaylandNativeWindow::dequeueBuffer(BaseNativeWindowBuffer **buffer, int *fenceFd){ | |
304 | HYBRIS_TRACE_BEGIN("wayland-platform", "dequeueBuffer", ""); | |
305 | ||
306 | WaylandNativeWindowBuffer *wnb=NULL; | |
307 | TRACE("%p", buffer); | |
308 | ||
309 | lock(); | |
310 | HYBRIS_TRACE_BEGIN("wayland-platform", "dequeueBuffer_wait_for_buffer", ""); | |
311 | ||
312 | HYBRIS_TRACE_COUNTER("wayland-platform", "m_freeBufs", "%i", m_freeBufs); | |
313 | ||
314 | while (m_freeBufs==0) { | |
315 | HYBRIS_TRACE_COUNTER("wayland-platform", "m_freeBufs", "%i", m_freeBufs); | |
316 | ||
317 | pthread_cond_wait(&cond,&mutex); | |
318 | } | |
319 | std::list<WaylandNativeWindowBuffer *>::iterator it = m_bufList.begin(); | |
320 | for (; it != m_bufList.end(); it++) | |
321 | { | |
322 | if ((*it)->busy) | |
323 | continue; | |
324 | if ((*it)->youngest == 1) | |
325 | continue; | |
326 | break; | |
327 | } | |
328 | ||
329 | if (it==m_bufList.end()) { | |
330 | HYBRIS_TRACE_BEGIN("wayland-platform", "dequeueBuffer_worst_case_scenario", ""); | |
331 | HYBRIS_TRACE_END("wayland-platform", "dequeueBuffer_worst_case_scenario", ""); | |
332 | ||
333 | it = m_bufList.begin(); | |
334 | for (; it != m_bufList.end() && (*it)->busy; it++) | |
335 | {} | |
336 | ||
337 | } | |
338 | if (it==m_bufList.end()) { | |
339 | unlock(); | |
340 | HYBRIS_TRACE_BEGIN("wayland-platform", "dequeueBuffer_no_free_buffers", ""); | |
341 | HYBRIS_TRACE_END("wayland-platform", "dequeueBuffer_no_free_buffers", ""); | |
342 | TRACE("%p: no free buffers", buffer); | |
343 | return NO_ERROR; | |
344 | } | |
345 | ||
346 | wnb = *it; | |
347 | assert(wnb!=NULL); | |
348 | HYBRIS_TRACE_END("wayland-platform", "dequeueBuffer_wait_for_buffer", ""); | |
349 | ||
350 | /* If the buffer doesn't match the window anymore, re-allocate */ | |
351 | if (wnb->width != m_window->width || wnb->height != m_window->height | |
352 | || wnb->format != m_format || wnb->usage != m_usage) | |
353 | { | |
354 | TRACE("wnb:%p,win:%p %i,%i %i,%i x%x,x%x x%x,x%x", | |
355 | wnb,m_window, | |
356 | wnb->width,m_window->width, wnb->height,m_window->height, | |
357 | wnb->format,m_format, wnb->usage,m_usage); | |
358 | destroyBuffer(wnb); | |
359 | m_bufList.erase(it); | |
360 | wnb = addBuffer(); | |
361 | } | |
362 | ||
363 | wnb->busy = 1; | |
364 | *buffer = wnb; | |
365 | --m_freeBufs; | |
366 | ||
367 | HYBRIS_TRACE_COUNTER("wayland-platform", "m_freeBufs", "%i", m_freeBufs); | |
368 | HYBRIS_TRACE_BEGIN("wayland-platform", "dequeueBuffer_gotBuffer", "-%p", wnb); | |
369 | HYBRIS_TRACE_END("wayland-platform", "dequeueBuffer_gotBuffer", "-%p", wnb); | |
370 | HYBRIS_TRACE_END("wayland-platform", "dequeueBuffer_wait_for_buffer", ""); | |
371 | ||
372 | unlock(); | |
373 | return NO_ERROR; | |
374 | } | |
375 | ||
376 | int WaylandNativeWindow::lockBuffer(BaseNativeWindowBuffer* buffer){ | |
377 | WaylandNativeWindowBuffer *wnb = (WaylandNativeWindowBuffer*) buffer; | |
378 | HYBRIS_TRACE_BEGIN("wayland-platform", "lockBuffer", "-%p", wnb); | |
379 | HYBRIS_TRACE_END("wayland-platform", "lockBuffer", "-%p", wnb); | |
380 | return NO_ERROR; | |
381 | } | |
382 | ||
383 | int WaylandNativeWindow::postBuffer(ANativeWindowBuffer* buffer) | |
384 | { | |
385 | TRACE(""); | |
386 | WaylandNativeWindowBuffer *wnb = NULL; | |
387 | ||
388 | lock(); | |
389 | std::list<WaylandNativeWindowBuffer *>::iterator it = post_registered.begin(); | |
390 | for (; it != post_registered.end(); it++) | |
391 | { | |
392 | if ((*it)->other == buffer) | |
393 | { | |
394 | wnb = (*it); | |
395 | break; | |
396 | } | |
397 | } | |
398 | unlock(); | |
399 | if (!wnb) | |
400 | { | |
401 | wnb = new WaylandNativeWindowBuffer(buffer); | |
402 | ||
403 | wnb->common.incRef(&wnb->common); | |
404 | buffer->common.incRef(&buffer->common); | |
405 | } | |
406 | ||
407 | int ret = 0; | |
408 | ||
409 | lock(); | |
410 | wnb->busy = 1; | |
411 | unlock(); | |
412 | /* XXX locking/something is a bit fishy here */ | |
413 | while (this->frame_callback && ret != -1) { | |
414 | ret = wl_display_dispatch_queue(m_display, this->wl_queue); | |
415 | } | |
416 | ||
417 | if (ret < 0) { | |
418 | TRACE("wl_display_dispatch_queue returned an error:%i", ret); | |
419 | check_fatal_error(m_display); | |
420 | return ret; | |
421 | } | |
422 | ||
423 | lock(); | |
424 | this->frame_callback = wl_surface_frame(m_window->surface); | |
425 | wl_callback_add_listener(this->frame_callback, &frame_listener, this); | |
426 | wl_proxy_set_queue((struct wl_proxy *) this->frame_callback, this->wl_queue); | |
427 | ||
428 | if (wnb->wlbuffer == NULL) | |
429 | { | |
430 | wnb->wlbuffer_from_native_handle(m_android_wlegl); | |
431 | TRACE("%p add listener with %p inside", wnb, wnb->wlbuffer); | |
432 | wl_buffer_add_listener(wnb->wlbuffer, &wl_buffer_listener, this); | |
433 | wl_proxy_set_queue((struct wl_proxy *) wnb->wlbuffer, this->wl_queue); | |
434 | post_registered.push_back(wnb); | |
435 | } | |
436 | TRACE("%p DAMAGE AREA: %dx%d", wnb, wnb->width, wnb->height); | |
437 | wl_surface_attach(m_window->surface, wnb->wlbuffer, 0, 0); | |
438 | wl_surface_damage(m_window->surface, 0, 0, wnb->width, wnb->height); | |
439 | wl_surface_commit(m_window->surface); | |
440 | //--m_freeBufs; | |
441 | //pthread_cond_signal(&cond); | |
442 | posted.push_back(wnb); | |
443 | unlock(); | |
444 | ||
445 | return NO_ERROR; | |
446 | } | |
447 | ||
448 | static int debugenvchecked = 0; | |
449 | ||
450 | int WaylandNativeWindow::queueBuffer(BaseNativeWindowBuffer* buffer, int fenceFd) | |
451 | { | |
452 | WaylandNativeWindowBuffer *wnb = (WaylandNativeWindowBuffer*) buffer; | |
453 | int ret = 0; | |
454 | ||
455 | HYBRIS_TRACE_BEGIN("wayland-platform", "queueBuffer", "-%p", wnb); | |
456 | lock(); | |
457 | wnb->busy = 1; | |
458 | unlock(); | |
459 | /* XXX locking/something is a bit fishy here */ | |
460 | HYBRIS_TRACE_BEGIN("wayland-platform", "queueBuffer_wait_for_frame_callback", "-%p", wnb); | |
461 | ||
462 | while (this->frame_callback && ret != -1) { | |
463 | ret = wl_display_dispatch_queue(m_display, this->wl_queue); | |
464 | } | |
465 | ||
466 | ||
467 | if (ret < 0) { | |
468 | TRACE("wl_display_dispatch_queue returned an error"); | |
469 | HYBRIS_TRACE_END("wayland-platform", "queueBuffer_wait_for_frame_callback", "-%p", wnb); | |
470 | check_fatal_error(m_display); | |
471 | return ret; | |
472 | } | |
473 | ||
474 | HYBRIS_TRACE_END("wayland-platform", "queueBuffer_wait_for_frame_callback", "-%p", wnb); | |
475 | ||
476 | ||
477 | lock(); | |
478 | ||
479 | if (debugenvchecked == 0) | |
480 | { | |
481 | if (getenv("HYBRIS_WAYLAND_DUMP_BUFFERS") != NULL) | |
482 | debugenvchecked = 2; | |
483 | else | |
484 | debugenvchecked = 1; | |
485 | } | |
486 | if (debugenvchecked == 2) | |
487 | { | |
488 | HYBRIS_TRACE_BEGIN("wayland-platform", "queueBuffer_dumping_buffer", "-%p", wnb); | |
489 | hybris_dump_buffer_to_file(wnb->getNativeBuffer()); | |
490 | HYBRIS_TRACE_END("wayland-platform", "queueBuffer_dumping_buffer", "-%p", wnb); | |
491 | ||
492 | } | |
493 | ||
494 | #if ANDROID_VERSION_MAJOR>=4 && ANDROID_VERSION_MINOR>=2 | |
495 | HYBRIS_TRACE_BEGIN("wayland-platform", "queueBuffer_waiting_for_fence", "-%p", wnb); | |
496 | sync_wait(fenceFd, -1); | |
497 | close(fenceFd); | |
498 | HYBRIS_TRACE_END("wayland-platform", "queueBuffer_waiting_for_fence", "-%p", wnb); | |
499 | #endif | |
500 | ||
501 | this->frame_callback = wl_surface_frame(m_window->surface); | |
502 | wl_callback_add_listener(this->frame_callback, &frame_listener, this); | |
503 | wl_proxy_set_queue((struct wl_proxy *) this->frame_callback, this->wl_queue); | |
504 | ||
505 | if (wnb->wlbuffer == NULL) | |
506 | { | |
507 | wnb->wlbuffer_from_native_handle(m_android_wlegl); | |
508 | TRACE("%p add listener with %p inside", wnb, wnb->wlbuffer); | |
509 | wl_buffer_add_listener(wnb->wlbuffer, &wl_buffer_listener, this); | |
510 | wl_proxy_set_queue((struct wl_proxy *) wnb->wlbuffer, this->wl_queue); | |
511 | } | |
512 | TRACE("%p DAMAGE AREA: %dx%d", wnb, wnb->width, wnb->height); | |
513 | HYBRIS_TRACE_BEGIN("wayland-platform", "queueBuffer_attachdamagecommit", "-resource@%i", wl_proxy_get_id((struct wl_proxy *) wnb->wlbuffer)); | |
514 | ||
515 | wl_surface_attach(m_window->surface, wnb->wlbuffer, 0, 0); | |
516 | wl_surface_damage(m_window->surface, 0, 0, wnb->width, wnb->height); | |
517 | wl_surface_commit(m_window->surface); | |
518 | wl_display_flush(m_display); | |
519 | HYBRIS_TRACE_END("wayland-platform", "queueBuffer_attachdamagecommit", "-resource@%i", wl_proxy_get_id((struct wl_proxy *) wnb->wlbuffer)); | |
520 | ||
521 | //--m_freeBufs; | |
522 | //pthread_cond_signal(&cond); | |
523 | fronted.push_back(wnb); | |
524 | HYBRIS_TRACE_COUNTER("wayland-platform", "fronted.size", "%i", fronted.size()); | |
525 | ||
526 | if (fronted.size() == m_bufList.size()) | |
527 | { | |
528 | HYBRIS_TRACE_BEGIN("wayland-platform", "queueBuffer_wait_for_nonfronted_buffer", "-%p", wnb); | |
529 | ||
530 | /* We have fronted all our buffers, let's wait for one of them to be free */ | |
531 | do { | |
532 | unlock(); | |
533 | ret = wl_display_dispatch_queue(m_display, this->wl_queue); | |
534 | lock(); | |
535 | if (ret == -1) | |
536 | { | |
537 | check_fatal_error(m_display); | |
538 | break; | |
539 | } | |
540 | HYBRIS_TRACE_COUNTER("wayland-platform", "fronted.size", "%i", fronted.size()); | |
541 | ||
542 | if (fronted.size() != m_bufList.size()) | |
543 | break; | |
544 | } while (1); | |
545 | HYBRIS_TRACE_END("wayland-platform", "queueBuffer_wait_for_nonfronted_buffer", "-%p", wnb); | |
546 | } | |
547 | HYBRIS_TRACE_END("wayland-platform", "queueBuffer", "-%p", wnb); | |
548 | unlock(); | |
549 | ||
550 | return NO_ERROR; | |
551 | } | |
552 | ||
553 | int WaylandNativeWindow::cancelBuffer(BaseNativeWindowBuffer* buffer, int fenceFd){ | |
554 | std::list<WaylandNativeWindowBuffer *>::iterator it; | |
555 | WaylandNativeWindowBuffer *wnb = (WaylandNativeWindowBuffer*) buffer; | |
556 | ||
557 | lock(); | |
558 | HYBRIS_TRACE_BEGIN("wayland-platform", "cancelBuffer", "-%p", wnb); | |
559 | ||
560 | /* Check first that it really is our buffer */ | |
561 | for (it = m_bufList.begin(); it != m_bufList.end(); it++) | |
562 | { | |
563 | if ((*it) == wnb) | |
564 | break; | |
565 | } | |
566 | assert(it != m_bufList.end()); | |
567 | ||
568 | wnb->busy = 0; | |
569 | ++m_freeBufs; | |
570 | HYBRIS_TRACE_COUNTER("wayland-platform", "m_freeBufs", "%i", m_freeBufs); | |
571 | ||
572 | for (it = m_bufList.begin(); it != m_bufList.end(); it++) | |
573 | { | |
574 | (*it)->youngest = 0; | |
575 | } | |
576 | wnb->youngest = 1; | |
577 | ||
578 | pthread_cond_signal(&cond); | |
579 | ||
580 | HYBRIS_TRACE_END("wayland-platform", "cancelBuffer", "-%p", wnb); | |
581 | unlock(); | |
582 | return 0; | |
583 | } | |
584 | ||
585 | unsigned int WaylandNativeWindow::width() const { | |
586 | TRACE("value:%i", m_width); | |
587 | return m_width; | |
588 | } | |
589 | ||
590 | unsigned int WaylandNativeWindow::height() const { | |
591 | TRACE("value:%i", m_height); | |
592 | return m_height; | |
593 | } | |
594 | ||
595 | unsigned int WaylandNativeWindow::format() const { | |
596 | TRACE("value:%i", m_format); | |
597 | return m_format; | |
598 | } | |
599 | ||
600 | unsigned int WaylandNativeWindow::defaultWidth() const { | |
601 | TRACE("value:%i", m_defaultWidth); | |
602 | return m_defaultWidth; | |
603 | } | |
604 | ||
605 | unsigned int WaylandNativeWindow::defaultHeight() const { | |
606 | TRACE("value:%i", m_defaultHeight); | |
607 | return m_defaultHeight; | |
608 | } | |
609 | ||
610 | unsigned int WaylandNativeWindow::queueLength() const { | |
611 | TRACE("WARN: stub"); | |
612 | return 1; | |
613 | } | |
614 | ||
615 | unsigned int WaylandNativeWindow::type() const { | |
616 | TRACE(""); | |
617 | #if ANDROID_VERSION_MAJOR>=4 && ANDROID_VERSION_MINOR>=3 | |
618 | /* https://android.googlesource.com/platform/system/core/+/bcfa910611b42018db580b3459101c564f802552%5E!/ */ | |
619 | return NATIVE_WINDOW_SURFACE; | |
620 | #else | |
621 | return NATIVE_WINDOW_SURFACE_TEXTURE_CLIENT; | |
622 | #endif | |
623 | } | |
624 | ||
625 | unsigned int WaylandNativeWindow::transformHint() const { | |
626 | TRACE("WARN: stub"); | |
627 | return 0; | |
628 | } | |
629 | ||
630 | int WaylandNativeWindow::setBuffersFormat(int format) { | |
631 | if (format != m_format) | |
632 | { | |
633 | TRACE("old-format:x%x new-format:x%x", m_format, format); | |
634 | m_format = format; | |
635 | /* Buffers will be re-allocated when dequeued */ | |
636 | } else { | |
637 | TRACE("format:x%x", format); | |
638 | } | |
639 | return NO_ERROR; | |
640 | } | |
641 | ||
642 | void WaylandNativeWindow::destroyBuffer(WaylandNativeWindowBuffer* wnb) | |
643 | { | |
644 | TRACE("wnb:%p", wnb); | |
645 | ||
646 | assert(wnb != NULL); | |
647 | if (wnb->wlbuffer) | |
648 | wl_buffer_destroy(wnb->wlbuffer); | |
649 | wnb->wlbuffer = NULL; | |
650 | wnb->common.decRef(&wnb->common); | |
651 | m_freeBufs--; | |
652 | } | |
653 | ||
654 | void WaylandNativeWindow::destroyBuffers() | |
655 | { | |
656 | TRACE(""); | |
657 | ||
658 | std::list<WaylandNativeWindowBuffer*>::iterator it = m_bufList.begin(); | |
659 | for (; it!=m_bufList.end(); ++it) | |
660 | { | |
661 | destroyBuffer(*it); | |
662 | } | |
663 | m_bufList.clear(); | |
664 | m_freeBufs = 0; | |
665 | } | |
666 | ||
667 | WaylandNativeWindowBuffer *WaylandNativeWindow::addBuffer() { | |
668 | ||
669 | WaylandNativeWindowBuffer *wnb = new WaylandNativeWindowBuffer(m_alloc, m_width, m_height, m_format, m_usage); | |
670 | m_bufList.push_back(wnb); | |
671 | wnb->common.incRef(&wnb->common); | |
672 | ++m_freeBufs; | |
673 | ||
674 | TRACE("wnb:%p width:%i height:%i format:x%x usage:x%x", | |
675 | wnb, wnb->width, wnb->height, wnb->format, wnb->usage); | |
676 | ||
677 | return wnb; | |
678 | } | |
679 | ||
680 | ||
681 | int WaylandNativeWindow::setBufferCount(int cnt) { | |
682 | int start = 0; | |
683 | ||
684 | TRACE("cnt:%d", cnt); | |
685 | ||
686 | if (m_bufList.size() == cnt) | |
687 | return NO_ERROR; | |
688 | ||
689 | lock(); | |
690 | ||
691 | if (m_bufList.size() > cnt) { | |
692 | /* Decreasing buffer count, remove from beginning */ | |
693 | std::list<WaylandNativeWindowBuffer*>::iterator it = m_bufList.begin(); | |
694 | for (int i = 0; i <= m_bufList.size() - cnt; i++ ) | |
695 | { | |
696 | destroyBuffer(*it); | |
697 | ++it; | |
698 | m_bufList.pop_front(); | |
699 | } | |
700 | ||
701 | } else { | |
702 | /* Increasing buffer count, start from current size */ | |
703 | for (int i = m_bufList.size(); i < cnt; i++) | |
704 | WaylandNativeWindowBuffer *unused = addBuffer(); | |
705 | ||
706 | } | |
707 | ||
708 | unlock(); | |
709 | ||
710 | return NO_ERROR; | |
711 | } | |
712 | ||
713 | ||
714 | ||
715 | ||
716 | int WaylandNativeWindow::setBuffersDimensions(int width, int height) { | |
717 | if (m_width != width || m_height != height) | |
718 | { | |
719 | TRACE("old-size:%ix%i new-size:%ix%i", m_width, m_height, width, height); | |
720 | m_width = m_defaultWidth = width; | |
721 | m_height = m_defaultHeight = height; | |
722 | /* Buffers will be re-allocated when dequeued */ | |
723 | } else { | |
724 | TRACE("size:%ix%i", width, height); | |
725 | } | |
726 | return NO_ERROR; | |
727 | } | |
728 | ||
729 | int WaylandNativeWindow::setUsage(int usage) { | |
730 | if ((usage | GRALLOC_USAGE_HW_TEXTURE) != m_usage) | |
731 | { | |
732 | TRACE("old-usage:x%x new-usage:x%x", m_usage, usage); | |
733 | m_usage = usage | GRALLOC_USAGE_HW_TEXTURE; | |
734 | /* Buffers will be re-allocated when dequeued */ | |
735 | } else { | |
736 | TRACE("usage:x%x", usage); | |
737 | } | |
738 | return NO_ERROR; | |
739 | } | |
740 | // vim: noai:ts=4:sw=4:ss=4:expandtab |