#include <android/native_window.h>
-#if ANDROID_API <= 13
+#define ANDROID_HC_OR_LATER (ANDROID_API >= 11)
+#define ANDROID_ICS_OR_LATER (ANDROID_API >= 14)
+#define ANDROID_JBMR2_OR_LATER (ANDROID_API >= 18)
+
+#if ANDROID_JBMR2_OR_LATER
+/* for waiting for fence_fd returned by dequeueBuffer */
+#include <linux/ioctl.h>
+#include <linux/types.h>
+#define SYNC_IOC_MAGIC '>'
+#define SYNC_IOC_WAIT _IOW(SYNC_IOC_MAGIC, 0, __s32)
+#endif
+
+#if ANDROID_ICS_OR_LATER
+#include <system/window.h>
+#else
#include <ui/android_native_buffer.h>
#include <ui/egl/android_natives.h>
-#else
-#include <system/window.h>
#endif
#include <hardware/gralloc.h>
#define NO_ERROR 0
typedef int32_t status_t;
-#if ANDROID_API <= 13
+#if !ANDROID_ICS_OR_LATER
typedef android_native_buffer_t ANativeWindowBuffer_t;
#endif
typedef struct native_window_priv native_window_priv;
static int window_connect( ANativeWindow *anw )
{
-#if ANDROID_API >= 14
+#if ANDROID_ICS_OR_LATER
return native_window_api_connect( anw, NATIVE_WINDOW_API_MEDIA );
#endif
}
static int window_disconnect( ANativeWindow *anw )
{
-#if ANDROID_API >= 14
+#if ANDROID_ICS_OR_LATER
return native_window_api_disconnect( anw, NATIVE_WINDOW_API_MEDIA );
#endif
}
LOGD( "setup: %p, %d, %d, %X, %X\n",
priv->anw, w, h, hal_format, hw_usage );
- if (is_hw)
+ if( is_hw )
+ {
priv->usage = hw_usage | GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
- else
- priv->usage= GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_OFTEN;
-#if ANDROID_API >= 11
- priv->usage |= GRALLOC_USAGE_EXTERNAL_DISP;
+#if ANDROID_HC_OR_LATER
+ priv->usage |= GRALLOC_USAGE_EXTERNAL_DISP;
#endif
+ }
+ else
+ priv->usage = GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_OFTEN;
err = native_window_set_usage( priv->anw, priv->usage );
CHECK_ERR();
-#if ANDROID_API <= 13
- err = native_window_set_buffers_geometry( priv->anw, w, h, hal_format );
- CHECK_ERR();
-#else
- err = native_window_set_scaling_mode( priv->anw, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW );
+#if ANDROID_ICS_OR_LATER
+ err = native_window_set_buffers_format( priv->anw, hal_format );
CHECK_ERR();
+#if ANDROID_JBMR2_OR_LATER
+ err = native_window_set_buffers_user_dimensions( priv->anw, w, h );
+#else
err = native_window_set_buffers_dimensions( priv->anw, w, h );
+#endif
CHECK_ERR();
- err = native_window_set_buffers_format( priv->anw, hal_format );
+ err = native_window_set_scaling_mode( priv->anw, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW );
+ CHECK_ERR();
+#else
+ err = native_window_set_buffers_geometry( priv->anw, w, h, hal_format );
CHECK_ERR();
#endif
{
status_t err;
-#if ANDROID_API >= 11
+#if ANDROID_HC_OR_LATER
err = priv->anw->query( priv->anw, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, min_undequeued );
CHECK_ERR();
#endif
int ANativeWindowPriv_getMaxBufferCount( native_window_priv *priv, unsigned int *max_buffer_count )
{
-#if ANDROID_API >= 14
+#if ANDROID_ICS_OR_LATER
*max_buffer_count = 32;
#else
*max_buffer_count = 15;
return native_window_set_crop( priv->anw, &crop );
}
-int ANativeWindowPriv_dequeue( native_window_priv *priv, void **pp_handle )
+static int dequeue_fence( native_window_priv *priv, void **pp_handle,
+ int *p_fence_fd )
{
ANativeWindowBuffer_t *anb;
status_t err = NO_ERROR;
+ int i_fence_fd = -1;
-#if ANDROID_API >= 18
- err = priv->anw->dequeueBuffer_DEPRECATED( priv->anw, &anb );
+#if ANDROID_JBMR2_OR_LATER
+ err = priv->anw->dequeueBuffer( priv->anw, &anb, &i_fence_fd );
+ CHECK_ERR();
+ if( !p_fence_fd && i_fence_fd != -1 )
+ {
+ __s32 timeout = 5000;
+ if( ioctl( i_fence_fd, SYNC_IOC_WAIT, &timeout ) != 0 )
+ {
+ priv->anw->queueBuffer( priv->anw, anb, i_fence_fd );
+ return -1;
+ }
+ close( i_fence_fd );
+ i_fence_fd = -1;
+ }
#else
err = priv->anw->dequeueBuffer( priv->anw, &anb );
-#endif
CHECK_ERR();
+#endif
+ if( p_fence_fd )
+ *p_fence_fd = i_fence_fd;
*pp_handle = anb;
return 0;
}
+int ANativeWindowPriv_dequeue( native_window_priv *priv, void **pp_handle )
+{
+ return dequeue_fence( priv, pp_handle, NULL );
+}
+
int ANativeWindowPriv_lock( native_window_priv *priv, void *p_handle )
{
+#if !ANDROID_JBMR2_OR_LATER
ANativeWindowBuffer_t *anb = (ANativeWindowBuffer_t *)p_handle;
status_t err = NO_ERROR;
CHECK_ANB();
-#if ANDROID_API >= 18
- err = priv->anw->lockBuffer_DEPRECATED( priv->anw, anb );
-#else
err = priv->anw->lockBuffer( priv->anw, anb );
-#endif
CHECK_ERR();
+#endif
return 0;
}
-int ANativeWindowPriv_lockData( native_window_priv *priv, void *p_handle,
- ANativeWindow_Buffer *p_out_anb )
+static int queue_fence( native_window_priv *priv, void *p_handle,
+ int i_fence_fd )
{
ANativeWindowBuffer_t *anb = (ANativeWindowBuffer_t *)p_handle;
status_t err = NO_ERROR;
- void *p_data;
CHECK_ANB();
- err = priv->gralloc->lock( priv->gralloc, anb->handle, priv->usage,
- 0, 0, anb->width, anb->height, &p_data );
+#if ANDROID_JBMR2_OR_LATER
+ err = priv->anw->queueBuffer( priv->anw, anb, i_fence_fd );
+#else
+ err = priv->anw->queueBuffer( priv->anw, anb );
+#endif
CHECK_ERR();
- if( p_out_anb ) {
- p_out_anb->bits = p_data;
- p_out_anb->width = anb->width;
- p_out_anb->height = anb->height;
- p_out_anb->stride = anb->stride;
- p_out_anb->format = anb->format;
- }
return 0;
}
-int ANativeWindowPriv_unlockData( native_window_priv *priv, void *p_handle )
+int ANativeWindowPriv_queue( native_window_priv *priv, void *p_handle )
+{
+ return queue_fence( priv, p_handle, -1 );
+}
+
+static int cancel_fence( native_window_priv *priv, void *p_handle,
+ int i_fence_fd )
{
ANativeWindowBuffer_t *anb = (ANativeWindowBuffer_t *)p_handle;
status_t err = NO_ERROR;
CHECK_ANB();
- err = priv->gralloc->unlock(priv->gralloc, anb->handle);
+#if ANDROID_JBMR2_OR_LATER
+ err = priv->anw->cancelBuffer( priv->anw, anb, i_fence_fd );
+#else
+ err = priv->anw->cancelBuffer( priv->anw, anb );
+#endif
CHECK_ERR();
return 0;
}
-int ANativeWindowPriv_queue( native_window_priv *priv, void *p_handle )
+int ANativeWindowPriv_cancel( native_window_priv *priv, void *p_handle )
{
- ANativeWindowBuffer_t *anb = (ANativeWindowBuffer_t *)p_handle;
+ return cancel_fence( priv, p_handle, -1 );
+}
+
+int ANativeWindowPriv_lockData( native_window_priv *priv, void **pp_handle,
+ ANativeWindow_Buffer *p_out_anb )
+{
+ ANativeWindowBuffer_t *anb;
status_t err = NO_ERROR;
+ void *p_data;
+ err = dequeue_fence( priv, pp_handle, NULL );
+ CHECK_ERR();
+
+ anb = (ANativeWindowBuffer_t *)*pp_handle;
CHECK_ANB();
-#if ANDROID_API >= 18
- err = priv->anw->queueBuffer_DEPRECATED( priv->anw, anb );
-#else
- err = priv->anw->queueBuffer( priv->anw, anb );
-#endif
+ err = ANativeWindowPriv_lock( priv, *pp_handle );
CHECK_ERR();
+ err = priv->gralloc->lock( priv->gralloc, anb->handle, priv->usage,
+ 0, 0, anb->width, anb->height, &p_data );
+ CHECK_ERR();
+ if( p_out_anb ) {
+ p_out_anb->bits = p_data;
+ p_out_anb->width = anb->width;
+ p_out_anb->height = anb->height;
+ p_out_anb->stride = anb->stride;
+ p_out_anb->format = anb->format;
+ }
+
return 0;
}
-int ANativeWindowPriv_cancel( native_window_priv *priv, void *p_handle )
+int ANativeWindowPriv_unlockData( native_window_priv *priv, void *p_handle,
+ bool b_render )
{
ANativeWindowBuffer_t *anb = (ANativeWindowBuffer_t *)p_handle;
status_t err = NO_ERROR;
CHECK_ANB();
-#if ANDROID_API >= 18
- err = priv->anw->cancelBuffer_DEPRECATED( priv->anw, anb );
-#else
- err = priv->anw->cancelBuffer( priv->anw, anb );
-#endif
+ err = priv->gralloc->unlock( priv->gralloc, anb->handle );
CHECK_ERR();
+ if( b_render )
+ queue_fence( priv, p_handle, -1 );
+ else
+ cancel_fence( priv, p_handle, -1 );
+
return 0;
}