Imported Upstream version 0.1.0+git20131207+e452e83
[deb_libhybris.git] / hybris / egl / platforms / wayland / wayland_window.cpp
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, &registry_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