2 * Copyright (C) 2013 libhybris
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "fbdev_window.h"
25 #include <android/android-version.h>
27 #define FRAMEBUFFER_PARTITIONS 2
29 static pthread_cond_t _cond
= PTHREAD_COND_INITIALIZER
;
30 static pthread_mutex_t _mutex
= PTHREAD_MUTEX_INITIALIZER
;
33 FbDevNativeWindowBuffer::FbDevNativeWindowBuffer(alloc_device_t
* alloc_device
,
39 ANativeWindowBuffer::width
= width
;
40 ANativeWindowBuffer::height
= height
;
41 ANativeWindowBuffer::format
= format
;
42 ANativeWindowBuffer::usage
= usage
;
45 m_alloc
= alloc_device
;
48 status
= m_alloc
->alloc(m_alloc
,
49 width
, height
, format
, usage
,
53 TRACE("width=%d height=%d stride=%d format=x%x usage=x%x status=%s this=%p",
54 width
, height
, stride
, format
, usage
, strerror(-status
), this);
59 FbDevNativeWindowBuffer::~FbDevNativeWindowBuffer()
62 if (m_alloc
&& handle
)
63 m_alloc
->free(m_alloc
, handle
);
67 ////////////////////////////////////////////////////////////////////////////////
68 FbDevNativeWindow::FbDevNativeWindow(gralloc_module_t
* gralloc
,
69 alloc_device_t
* alloc
,
70 framebuffer_device_t
* fbDev
)
74 m_bufFormat
= m_fbDev
->format
;
75 m_usage
= GRALLOC_USAGE_HW_FB
;
77 #if ANDROID_VERSION_MAJOR>=4 && ANDROID_VERSION_MINOR>=2
78 if (m_fbDev
->numFramebuffers
>0)
79 setBufferCount(m_fbDev
->numFramebuffers
);
81 setBufferCount(FRAMEBUFFER_PARTITIONS
);
83 setBufferCount(FRAMEBUFFER_PARTITIONS
);
91 FbDevNativeWindow::~FbDevNativeWindow()
98 void FbDevNativeWindow::destroyBuffers()
102 std::list
<FbDevNativeWindowBuffer
*>::iterator it
= m_bufList
.begin();
103 for (; it
!=m_bufList
.end(); ++it
)
105 FbDevNativeWindowBuffer
* fbnb
= *it
;
106 fbnb
->common
.decRef(&fbnb
->common
);
117 * Set the swap interval for this surface.
119 * Returns 0 on success or -errno on error.
121 int FbDevNativeWindow::setSwapInterval(int interval
)
123 TRACE("interval=%i", interval
);
124 return m_fbDev
->setSwapInterval(m_fbDev
, interval
);
129 * Hook called by EGL to acquire a buffer. This call may block if no
130 * buffers are available.
132 * The window holds a reference to the buffer between dequeueBuffer and
133 * either queueBuffer or cancelBuffer, so clients only need their own
134 * reference if they might use the buffer after queueing or canceling it.
135 * Holding a reference to a buffer after queueing or canceling it is only
136 * allowed if a specific buffer count has been set.
138 * The libsync fence file descriptor returned in the int pointed to by the
139 * fenceFd argument will refer to the fence that must signal before the
140 * dequeued buffer may be written to. A value of -1 indicates that the
141 * caller may access the buffer immediately without waiting on a fence. If
142 * a valid file descriptor is returned (i.e. any value except -1) then the
143 * caller is responsible for closing the file descriptor.
145 * Returns 0 on success or -errno on error.
147 int FbDevNativeWindow::dequeueBuffer(BaseNativeWindowBuffer
** buffer
, int *fenceFd
)
149 HYBRIS_TRACE_BEGIN("fbdev-platform", "dequeueBuffer", "");
150 FbDevNativeWindowBuffer
* fbnb
=NULL
;
152 pthread_mutex_lock(&_mutex
);
154 HYBRIS_TRACE_BEGIN("fbdev-platform", "dequeueBuffer-wait", "");
158 TRACE("Status: Has front buf %p", m_frontBuf
);
160 std::list
<FbDevNativeWindowBuffer
*>::iterator cit
= m_bufList
.begin();
161 for (; cit
!= m_bufList
.end(); ++cit
)
163 TRACE("Status: Buffer %p with busy %i\n", (*cit
), (*cit
)->busy
);
167 while (m_freeBufs
==0)
169 pthread_cond_wait(&_cond
, &_mutex
);
174 std::list
<FbDevNativeWindowBuffer
*>::iterator it
= m_bufList
.begin();
175 for (; it
!= m_bufList
.end(); ++it
)
181 TRACE("Found a free non-front buffer");
186 if (it
== m_bufList
.end())
188 #if ANDROID_VERSION_MAJOR<=4 && ANDROID_VERSION_MINOR<2
190 * This is acceptable in case you are on a stack that calls lock() before starting to render into buffer
191 * When you are using fences (>= 2) you'll be waiting on the fence to signal instead.
193 * This optimization allows eglSwapBuffers to return and you can begin to utilize the GPU for rendering.
194 * The actual lock() probably first comes at glFlush/eglSwapBuffers
196 if (m_frontBuf
&& m_frontBuf
->busy
== 0)
198 TRACE("Used front buffer as buffer");
203 // have to wait once again
204 pthread_cond_wait(&_cond
, &_mutex
);
212 HYBRIS_TRACE_END("fbdev-platform", "dequeueBuffer-wait", "");
220 TRACE("%lu DONE --> %p", pthread_self(), fbnb
);
221 pthread_mutex_unlock(&_mutex
);
222 HYBRIS_TRACE_END("fbdev-platform", "dequeueBuffer", "");
227 * Hook called by EGL when modifications to the render buffer are done.
228 * This unlocks and post the buffer.
230 * The window holds a reference to the buffer between dequeueBuffer and
231 * either queueBuffer or cancelBuffer, so clients only need their own
232 * reference if they might use the buffer after queueing or canceling it.
233 * Holding a reference to a buffer after queueing or canceling it is only
234 * allowed if a specific buffer count has been set.
236 * The fenceFd argument specifies a libsync fence file descriptor for a
237 * fence that must signal before the buffer can be accessed. If the buffer
238 * can be accessed immediately then a value of -1 should be used. The
239 * caller must not use the file descriptor after it is passed to
240 * queueBuffer, and the ANativeWindow implementation is responsible for
243 * Returns 0 on success or -errno on error.
245 int FbDevNativeWindow::queueBuffer(BaseNativeWindowBuffer
* buffer
, int fenceFd
)
248 FbDevNativeWindowBuffer
* fbnb
= (FbDevNativeWindowBuffer
*) buffer
;
250 HYBRIS_TRACE_BEGIN("fbdev-platform", "queueBuffer", "-%p", fbnb
);
252 pthread_mutex_lock(&_mutex
);
254 assert(fbnb
->busy
==1);
258 pthread_mutex_unlock(&_mutex
);
260 HYBRIS_TRACE_BEGIN("fbdev-platform", "queueBuffer-post", "-%p", fbnb
);
262 int rv
= m_fbDev
->post(m_fbDev
, fbnb
->handle
);
265 fprintf(stderr
,"ERROR: fb->post(%s)\n",strerror(-rv
));
267 HYBRIS_TRACE_END("fbdev-platform", "queueBuffer-post", "-%p", fbnb
);
269 pthread_mutex_lock(&_mutex
);
276 TRACE("%lu %p %p",pthread_self(), m_frontBuf
, fbnb
);
278 pthread_cond_signal(&_cond
);
279 pthread_mutex_unlock(&_mutex
);
281 HYBRIS_TRACE_END("fbdev-platform", "queueBuffer", "-%p", fbnb
);
287 * Hook used to cancel a buffer that has been dequeued.
288 * No synchronization is performed between dequeue() and cancel(), so
289 * either external synchronization is needed, or these functions must be
290 * called from the same thread.
292 * The window holds a reference to the buffer between dequeueBuffer and
293 * either queueBuffer or cancelBuffer, so clients only need their own
294 * reference if they might use the buffer after queueing or canceling it.
295 * Holding a reference to a buffer after queueing or canceling it is only
296 * allowed if a specific buffer count has been set.
298 * The fenceFd argument specifies a libsync fence file decsriptor for a
299 * fence that must signal before the buffer can be accessed. If the buffer
300 * can be accessed immediately then a value of -1 should be used.
302 * Note that if the client has not waited on the fence that was returned
303 * from dequeueBuffer, that same fence should be passed to cancelBuffer to
304 * ensure that future uses of the buffer are preceded by a wait on that
305 * fence. The caller must not use the file descriptor after it is passed
306 * to cancelBuffer, and the ANativeWindow implementation is responsible for
309 * Returns 0 on success or -errno on error.
311 int FbDevNativeWindow::cancelBuffer(BaseNativeWindowBuffer
* buffer
, int fenceFd
)
314 FbDevNativeWindowBuffer
* fbnb
= (FbDevNativeWindowBuffer
*)buffer
;
316 pthread_mutex_lock(&_mutex
);
322 pthread_cond_signal(&_cond
);
323 pthread_mutex_unlock(&_mutex
);
330 int FbDevNativeWindow::lockBuffer(BaseNativeWindowBuffer
* buffer
)
333 FbDevNativeWindowBuffer
* fbnb
= (FbDevNativeWindowBuffer
*)buffer
;
335 HYBRIS_TRACE_BEGIN("fbdev-platform", "lockBuffer", "-%p", fbnb
);
337 pthread_mutex_lock(&_mutex
);
339 // wait that the buffer we're locking is not front anymore
340 while (m_frontBuf
==fbnb
)
342 TRACE("waiting %p %p", m_frontBuf
, fbnb
);
343 pthread_cond_wait(&_cond
, &_mutex
);
346 pthread_mutex_unlock(&_mutex
);
347 HYBRIS_TRACE_END("fbdev-platform", "lockBuffer", "-%p", fbnb
);
353 * see NATIVE_WINDOW_FORMAT
355 unsigned int FbDevNativeWindow::width() const
357 unsigned int rv
= m_fbDev
->width
;
358 TRACE("width=%i", rv
);
364 * see NATIVE_WINDOW_HEIGHT
366 unsigned int FbDevNativeWindow::height() const
368 unsigned int rv
= m_fbDev
->height
;
369 TRACE("height=%i", rv
);
375 * see NATIVE_WINDOW_FORMAT
377 unsigned int FbDevNativeWindow::format() const
379 unsigned int rv
= m_fbDev
->format
;
380 TRACE("format=x%x", rv
);
386 * Default width and height of ANativeWindow buffers, these are the
387 * dimensions of the window buffers irrespective of the
388 * NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS call and match the native window
389 * size unless overridden by NATIVE_WINDOW_SET_BUFFERS_USER_DIMENSIONS.
392 * see NATIVE_WINDOW_DEFAULT_HEIGHT
394 unsigned int FbDevNativeWindow::defaultHeight() const
396 unsigned int rv
= m_fbDev
->height
;
397 TRACE("height=%i", rv
);
403 * see BaseNativeWindow::_query(NATIVE_WINDOW_DEFAULT_WIDTH)
405 unsigned int FbDevNativeWindow::defaultWidth() const
407 unsigned int rv
= m_fbDev
->width
;
408 TRACE("width=%i", rv
);
414 * see NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER
416 unsigned int FbDevNativeWindow::queueLength() const
424 * see NATIVE_WINDOW_CONCRETE_TYPE
426 unsigned int FbDevNativeWindow::type() const
429 return NATIVE_WINDOW_FRAMEBUFFER
;
434 * see NATIVE_WINDOW_TRANSFORM_HINT
436 unsigned int FbDevNativeWindow::transformHint() const
445 * native_window_set_usage(..., usage)
446 * Sets the intended usage flags for the next buffers
447 * acquired with (*lockBuffer)() and on.
448 * By default (if this function is never called), a usage of
449 * GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE
451 * Calling this function will usually cause following buffers to be
454 int FbDevNativeWindow::setUsage(int usage
)
456 int need_realloc
= (m_usage
!= usage
);
457 TRACE("usage=x%x realloc=%d", usage
, need_realloc
);
460 this->setBufferCount(m_bufList
.size());
467 * native_window_set_buffers_format(..., int format)
468 * All buffers dequeued after this call will have the format specified.
470 * If the specified format is 0, the default buffer format will be used.
472 int FbDevNativeWindow::setBuffersFormat(int format
)
474 int need_realloc
= (format
!= m_bufFormat
);
475 TRACE("format=x%x realloc=%d", format
, need_realloc
);
476 m_bufFormat
= format
;
478 this->setBufferCount(m_bufList
.size());
484 * native_window_set_buffer_count(..., count)
485 * Sets the number of buffers associated with this native window.
487 int FbDevNativeWindow::setBufferCount(int cnt
)
489 TRACE("cnt=%d", cnt
);
491 pthread_mutex_lock(&_mutex
);
495 for(unsigned int i
= 0; i
< cnt
; i
++)
497 FbDevNativeWindowBuffer
*fbnb
= new FbDevNativeWindowBuffer(m_alloc
,
498 m_fbDev
->width
, m_fbDev
->height
, m_fbDev
->format
,
499 m_usage
|GRALLOC_USAGE_HW_FB
);
501 fbnb
->common
.incRef(&fbnb
->common
);
503 TRACE("buffer %i is at %p (native %p) err=%s handle=%p stride=%i",
504 i
, fbnb
, (ANativeWindowBuffer
*)fbnb
,
505 strerror(-fbnb
->status
), fbnb
->handle
, fbnb
->stride
);
509 fbnb
->common
.decRef(&fbnb
->common
);
510 fprintf(stderr
,"WARNING: %s: allocated only %d buffers out of %d\n", __PRETTY_FUNCTION__
, m_freeBufs
, cnt
);
515 m_bufList
.push_back(fbnb
);
517 pthread_mutex_unlock(&_mutex
);
523 * native_window_set_buffers_dimensions(..., int w, int h)
524 * All buffers dequeued after this call will have the dimensions specified.
525 * In particular, all buffers will have a fixed-size, independent from the
526 * native-window size. They will be scaled according to the scaling mode
527 * (see native_window_set_scaling_mode) upon window composition.
529 * If w and h are 0, the normal behavior is restored. That is, dequeued buffers
530 * following this call will be sized to match the window's size.
532 * Calling this function will reset the window crop to a NULL value, which
533 * disables cropping of the buffers.
535 int FbDevNativeWindow::setBuffersDimensions(int width
, int height
)
537 TRACE("WARN: stub. size=%ix%i", width
, height
);
540 // vim: noai:ts=4:sw=4:ss=4:expandtab