Imported Upstream version 0.1.0+git20131207+e452e83
[deb_libhybris.git] / hybris / egl / platforms / hwcomposer / hwcomposer_window.cpp
1 /*
2 * Copyright (C) 2013 libhybris
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "hwcomposer_window.h"
18 #include "logging.h"
19
20 #include <errno.h>
21 #include <assert.h>
22 #include <pthread.h>
23 #include <stdio.h>
24 #include <unistd.h>
25
26 #include <android/android-version.h>
27
28 extern "C" {
29 #include <android/sync/sync.h>
30 };
31
32 static pthread_cond_t _cond = PTHREAD_COND_INITIALIZER;
33 static pthread_mutex_t _mutex = PTHREAD_MUTEX_INITIALIZER;
34
35
36 HWComposerNativeWindowBuffer::HWComposerNativeWindowBuffer(alloc_device_t* alloc_device,
37 unsigned int width,
38 unsigned int height,
39 unsigned int format,
40 unsigned int usage)
41 {
42 ANativeWindowBuffer::width = width;
43 ANativeWindowBuffer::height = height;
44 ANativeWindowBuffer::format = format;
45 ANativeWindowBuffer::usage = usage;
46 fenceFd = -1;
47 busy = 0;
48 status = 0;
49 m_alloc = alloc_device;
50
51 if (m_alloc) {
52 status = m_alloc->alloc(m_alloc,
53 width, height, format, usage,
54 &handle, &stride);
55 }
56
57 TRACE("width=%d height=%d stride=%d format=x%x usage=x%x status=%s this=%p",
58 width, height, stride, format, usage, strerror(-status), this);
59 }
60
61
62
63 HWComposerNativeWindowBuffer::~HWComposerNativeWindowBuffer()
64 {
65 TRACE("%p", this);
66 if (m_alloc && handle)
67 m_alloc->free(m_alloc, handle);
68
69 }
70
71
72 ////////////////////////////////////////////////////////////////////////////////
73 HWComposerNativeWindow::HWComposerNativeWindow(unsigned int width, unsigned int height, unsigned int format)
74 {
75 m_alloc = NULL;
76 m_width = width;
77 m_height = height;
78 m_bufFormat = format;
79 m_usage = GRALLOC_USAGE_HW_COMPOSER;
80 m_frontBuf = NULL;
81 }
82
83 void HWComposerNativeWindow::setup(gralloc_module_t* gralloc, alloc_device_t* alloc)
84 {
85 m_alloc = alloc;
86 setBufferCount(2);
87 }
88
89 HWComposerNativeWindow::~HWComposerNativeWindow()
90 {
91 destroyBuffers();
92 }
93
94
95
96 void HWComposerNativeWindow::destroyBuffers()
97 {
98 TRACE("");
99
100 std::list<HWComposerNativeWindowBuffer*>::iterator it = m_bufList.begin();
101 for (; it!=m_bufList.end(); ++it)
102 {
103 HWComposerNativeWindowBuffer* fbnb = *it;
104 fbnb->common.decRef(&fbnb->common);
105 }
106 m_bufList.clear();
107 m_freeBufs = 0;
108 m_frontBuf = NULL;
109 }
110
111
112
113
114 /*
115 * Set the swap interval for this surface.
116 *
117 * Returns 0 on success or -errno on error.
118 */
119 int HWComposerNativeWindow::setSwapInterval(int interval)
120 {
121 TRACE("interval=%i WARN STUB", interval);
122 return 0;
123 }
124
125
126 /*
127 * Hook called by EGL to acquire a buffer. This call may block if no
128 * buffers are available.
129 *
130 * The window holds a reference to the buffer between dequeueBuffer and
131 * either queueBuffer or cancelBuffer, so clients only need their own
132 * reference if they might use the buffer after queueing or canceling it.
133 * Holding a reference to a buffer after queueing or canceling it is only
134 * allowed if a specific buffer count has been set.
135 *
136 * The libsync fence file descriptor returned in the int pointed to by the
137 * fenceFd argument will refer to the fence that must signal before the
138 * dequeued buffer may be written to. A value of -1 indicates that the
139 * caller may access the buffer immediately without waiting on a fence. If
140 * a valid file descriptor is returned (i.e. any value except -1) then the
141 * caller is responsible for closing the file descriptor.
142 *
143 * Returns 0 on success or -errno on error.
144 */
145 int HWComposerNativeWindow::dequeueBuffer(BaseNativeWindowBuffer** buffer, int *fenceFd)
146 {
147 HYBRIS_TRACE_BEGIN("hwcomposer-platform", "dequeueBuffer", "");
148
149 HWComposerNativeWindowBuffer* fbnb=NULL;
150
151 pthread_mutex_lock(&_mutex);
152
153 HYBRIS_TRACE_BEGIN("hwcomposer-platform", "dequeueBuffer-wait", "");
154 #if defined(DEBUG)
155
156 if (m_frontBuf)
157 TRACE("Status: Has front buf %p", m_frontBuf);
158
159 std::list<HWComposerNativeWindowBuffer*>::iterator cit = m_bufList.begin();
160 for (; cit != m_bufList.end(); ++cit)
161 {
162 TRACE("Status: Buffer %p with busy %i\n", (*cit), (*cit)->busy);
163 }
164 #endif
165
166
167 while (m_freeBufs==0)
168 {
169 pthread_cond_wait(&_cond, &_mutex);
170 }
171
172 while (1)
173 {
174 std::list<HWComposerNativeWindowBuffer*>::iterator it = m_bufList.begin();
175 for (; it != m_bufList.end(); ++it)
176 {
177 if (*it==m_frontBuf)
178 continue;
179 if ((*it)->busy==0)
180 {
181 TRACE("Found a free non-front buffer");
182 break;
183 }
184 }
185 if (it == m_bufList.end())
186 {
187 // have to wait once again
188 pthread_cond_wait(&_cond, &_mutex);
189 continue;
190 }
191
192 fbnb = *it;
193 break;
194 }
195 HYBRIS_TRACE_END("hwcomposer-platform", "dequeueBuffer-wait", "");
196
197 assert(fbnb!=NULL);
198 fbnb->busy = 1;
199 m_freeBufs--;
200
201 *buffer = fbnb;
202 *fenceFd = -1;
203
204 TRACE("%lu DONE --> %p", pthread_self(), fbnb);
205 pthread_mutex_unlock(&_mutex);
206 HYBRIS_TRACE_END("hwcomposer-platform", "dequeueBuffer", "");
207
208 return 0;
209 }
210
211 /*
212 * Hook called by EGL when modifications to the render buffer are done.
213 * This unlocks and post the buffer.
214 *
215 * The window holds a reference to the buffer between dequeueBuffer and
216 * either queueBuffer or cancelBuffer, so clients only need their own
217 * reference if they might use the buffer after queueing or canceling it.
218 * Holding a reference to a buffer after queueing or canceling it is only
219 * allowed if a specific buffer count has been set.
220 *
221 * The fenceFd argument specifies a libsync fence file descriptor for a
222 * fence that must signal before the buffer can be accessed. If the buffer
223 * can be accessed immediately then a value of -1 should be used. The
224 * caller must not use the file descriptor after it is passed to
225 * queueBuffer, and the ANativeWindow implementation is responsible for
226 * closing it.
227 *
228 * Returns 0 on success or -errno on error.
229 */
230 int HWComposerNativeWindow::queueBuffer(BaseNativeWindowBuffer* buffer, int fenceFd)
231 {
232 TRACE("%lu %d", pthread_self(), fenceFd);
233 HWComposerNativeWindowBuffer* fbnb = (HWComposerNativeWindowBuffer*) buffer;
234
235 HYBRIS_TRACE_BEGIN("hwcomposer-platform", "queueBuffer", "-%p", fbnb);
236 fbnb->fenceFd = fenceFd;
237
238 pthread_mutex_lock(&_mutex);
239
240 /* Front buffer hasn't yet been picked up for posting */
241 while (m_frontBuf && m_frontBuf->busy >= 2)
242 {
243 pthread_cond_wait(&_cond, &_mutex);
244 }
245
246 assert(fbnb->busy==1);
247 fbnb->busy = 2;
248 m_frontBuf = fbnb;
249 m_freeBufs++;
250
251 sync_wait(fenceFd, -1);
252 ::close(fenceFd);
253
254 pthread_cond_signal(&_cond);
255
256 TRACE("%lu %p %p",pthread_self(), m_frontBuf, fbnb);
257 pthread_mutex_unlock(&_mutex);
258 HYBRIS_TRACE_END("hwcomposer-platform", "queueBuffer", "-%p", fbnb);
259
260 return 0;
261 }
262
263 void HWComposerNativeWindow::lockFrontBuffer(HWComposerNativeWindowBuffer **buffer)
264 {
265 TRACE("");
266 HWComposerNativeWindowBuffer *buf;
267 pthread_mutex_lock(&_mutex);
268
269 while (!m_frontBuf)
270 {
271 pthread_cond_wait(&_cond, &_mutex);
272 }
273
274 assert(m_frontBuf->busy == 2);
275
276 m_frontBuf->busy = 3;
277 buf = m_frontBuf;
278 pthread_mutex_unlock(&_mutex);
279
280 *buffer = buf;
281 return;
282
283 }
284
285 void HWComposerNativeWindow::unlockFrontBuffer(HWComposerNativeWindowBuffer *buffer)
286 {
287 TRACE("");
288 pthread_mutex_lock(&_mutex);
289
290 assert(buffer == m_frontBuf);
291 m_frontBuf->busy = 0;
292
293 pthread_cond_signal(&_cond);
294 pthread_mutex_unlock(&_mutex);
295
296 return;
297 }
298
299 /*
300 * Hook used to cancel a buffer that has been dequeued.
301 * No synchronization is performed between dequeue() and cancel(), so
302 * either external synchronization is needed, or these functions must be
303 * called from the same thread.
304 *
305 * The window holds a reference to the buffer between dequeueBuffer and
306 * either queueBuffer or cancelBuffer, so clients only need their own
307 * reference if they might use the buffer after queueing or canceling it.
308 * Holding a reference to a buffer after queueing or canceling it is only
309 * allowed if a specific buffer count has been set.
310 *
311 * The fenceFd argument specifies a libsync fence file decsriptor for a
312 * fence that must signal before the buffer can be accessed. If the buffer
313 * can be accessed immediately then a value of -1 should be used.
314 *
315 * Note that if the client has not waited on the fence that was returned
316 * from dequeueBuffer, that same fence should be passed to cancelBuffer to
317 * ensure that future uses of the buffer are preceded by a wait on that
318 * fence. The caller must not use the file descriptor after it is passed
319 * to cancelBuffer, and the ANativeWindow implementation is responsible for
320 * closing it.
321 *
322 * Returns 0 on success or -errno on error.
323 */
324 int HWComposerNativeWindow::cancelBuffer(BaseNativeWindowBuffer* buffer, int fenceFd)
325 {
326 TRACE("");
327 HWComposerNativeWindowBuffer* fbnb = (HWComposerNativeWindowBuffer*)buffer;
328
329 pthread_mutex_lock(&_mutex);
330
331 fbnb->busy=0;
332
333 m_freeBufs++;
334
335 pthread_cond_signal(&_cond);
336 pthread_mutex_unlock(&_mutex);
337
338 return 0;
339 }
340
341
342
343 int HWComposerNativeWindow::lockBuffer(BaseNativeWindowBuffer* buffer)
344 {
345 TRACE("%lu STUB", pthread_self());
346 return NO_ERROR;
347 }
348
349
350 /*
351 * see NATIVE_WINDOW_FORMAT
352 */
353 unsigned int HWComposerNativeWindow::width() const
354 {
355 unsigned int rv = m_width;
356 TRACE("width=%i", rv);
357 return rv;
358 }
359
360
361 /*
362 * see NATIVE_WINDOW_HEIGHT
363 */
364 unsigned int HWComposerNativeWindow::height() const
365 {
366 unsigned int rv = m_height;
367 TRACE("height=%i", rv);
368 return rv;
369 }
370
371
372 /*
373 * see NATIVE_WINDOW_FORMAT
374 */
375 unsigned int HWComposerNativeWindow::format() const
376 {
377 unsigned int rv = m_bufFormat;
378 TRACE("format=x%x", rv);
379 return rv;
380 }
381
382
383 /*
384 * Default width and height of ANativeWindow buffers, these are the
385 * dimensions of the window buffers irrespective of the
386 * NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS call and match the native window
387 * size unless overridden by NATIVE_WINDOW_SET_BUFFERS_USER_DIMENSIONS.
388 */
389 /*
390 * see NATIVE_WINDOW_DEFAULT_HEIGHT
391 */
392 unsigned int HWComposerNativeWindow::defaultHeight() const
393 {
394 unsigned int rv = m_height;
395 TRACE("height=%i", rv);
396 return rv;
397 }
398
399
400 /*
401 * see BaseNativeWindow::_query(NATIVE_WINDOW_DEFAULT_WIDTH)
402 */
403 unsigned int HWComposerNativeWindow::defaultWidth() const
404 {
405 unsigned int rv = m_width;
406 TRACE("width=%i", rv);
407 return rv;
408 }
409
410
411 /*
412 * see NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER
413 */
414 unsigned int HWComposerNativeWindow::queueLength() const
415 {
416 TRACE("");
417 return 0;
418 }
419
420
421 /*
422 * see NATIVE_WINDOW_CONCRETE_TYPE
423 */
424 unsigned int HWComposerNativeWindow::type() const
425 {
426 TRACE("");
427 return NATIVE_WINDOW_FRAMEBUFFER;
428 }
429
430
431 /*
432 * see NATIVE_WINDOW_TRANSFORM_HINT
433 */
434 unsigned int HWComposerNativeWindow::transformHint() const
435 {
436 TRACE("");
437 return 0;
438 }
439
440
441
442 /*
443 * native_window_set_usage(..., usage)
444 * Sets the intended usage flags for the next buffers
445 * acquired with (*lockBuffer)() and on.
446 * By default (if this function is never called), a usage of
447 * GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE
448 * is assumed.
449 * Calling this function will usually cause following buffers to be
450 * reallocated.
451 */
452 int HWComposerNativeWindow::setUsage(int usage)
453 {
454 int need_realloc = (m_usage != usage);
455 TRACE("usage=x%x realloc=%d", usage, need_realloc);
456 m_usage = usage;
457 if (need_realloc)
458 this->setBufferCount(m_bufList.size());
459
460 return NO_ERROR;
461 }
462
463
464 /*
465 * native_window_set_buffers_format(..., int format)
466 * All buffers dequeued after this call will have the format specified.
467 *
468 * If the specified format is 0, the default buffer format will be used.
469 */
470 int HWComposerNativeWindow::setBuffersFormat(int format)
471 {
472 int need_realloc = (format != m_bufFormat);
473 TRACE("format=x%x realloc=%d", format, need_realloc);
474 m_bufFormat = format;
475 if (need_realloc)
476 this->setBufferCount(m_bufList.size());
477 return NO_ERROR;
478 }
479
480
481 /*
482 * native_window_set_buffer_count(..., count)
483 * Sets the number of buffers associated with this native window.
484 */
485 int HWComposerNativeWindow::setBufferCount(int cnt)
486 {
487 TRACE("cnt=%d", cnt);
488 int err=NO_ERROR;
489 pthread_mutex_lock(&_mutex);
490
491 destroyBuffers();
492
493 for(unsigned int i = 0; i < cnt; i++)
494 {
495 HWComposerNativeWindowBuffer *fbnb = new HWComposerNativeWindowBuffer(m_alloc,
496 m_width, m_height, m_bufFormat,
497 m_usage|GRALLOC_USAGE_HW_COMPOSER);
498
499 fbnb->common.incRef(&fbnb->common);
500
501 TRACE("buffer %i is at %p (native %p),err=%s, handle=%p stride=%i",
502 i, fbnb, (ANativeWindowBuffer*)fbnb,
503 strerror(-fbnb->status), fbnb->handle, fbnb->stride);
504
505 if (fbnb->status)
506 {
507 fbnb->common.decRef(&fbnb->common);
508 fprintf(stderr,"WARNING: %s: allocated only %d buffers out of %d\n", __PRETTY_FUNCTION__, m_freeBufs, cnt);
509 break;
510 }
511
512 m_freeBufs++;
513 m_bufList.push_back(fbnb);
514 }
515 pthread_mutex_unlock(&_mutex);
516
517 return err;
518 }
519
520 /*
521 * native_window_set_buffers_dimensions(..., int w, int h)
522 * All buffers dequeued after this call will have the dimensions specified.
523 * In particular, all buffers will have a fixed-size, independent from the
524 * native-window size. They will be scaled according to the scaling mode
525 * (see native_window_set_scaling_mode) upon window composition.
526 *
527 * If w and h are 0, the normal behavior is restored. That is, dequeued buffers
528 * following this call will be sized to match the window's size.
529 *
530 * Calling this function will reset the window crop to a NULL value, which
531 * disables cropping of the buffers.
532 */
533 int HWComposerNativeWindow::setBuffersDimensions(int width, int height)
534 {
535 TRACE("WARN: stub. size=%ix%i", width, height);
536 return NO_ERROR;
537 }
538 // vim: noai:ts=4:sw=4:ss=4:expandtab