diff options
author | Dmitry Osipenko <digetx@gmail.com> | 2018-01-04 16:48:21 +0300 |
---|---|---|
committer | Dmitry Osipenko <digetx@gmail.com> | 2018-01-04 18:34:09 +0300 |
commit | 683c81e6cdc9c705886a8f74b69be32cf5ad62ca (patch) | |
tree | e5090500df42f98015d1a145366cdcbbb473e453 | |
parent | 3ef8c07ce939d0755cb538863d4f009b7fdfc6ab (diff) |
Utilize DRI output
When players window is overlapped by some other window, the DRI output
will be used. The overlap detection is a hack that hijacks players X11 events,
but probably the best of what could be done. Two new environment variables are
added, the VDPAU_TEGRA_FORCE_XV and VDPAU_TEGRA_FORCE_DRI.
-rw-r--r-- | src/presentation_queue.c | 216 | ||||
-rw-r--r-- | src/presentation_queue_target.c | 441 | ||||
-rw-r--r-- | src/surface_mixer.c | 2 | ||||
-rw-r--r-- | src/vdpau_tegra.c | 22 | ||||
-rw-r--r-- | src/vdpau_tegra.h | 21 |
5 files changed, 487 insertions, 215 deletions
diff --git a/src/presentation_queue.c b/src/presentation_queue.c index e30cc94..58fd4ec 100644 --- a/src/presentation_queue.c +++ b/src/presentation_queue.c @@ -19,196 +19,11 @@ #include "vdpau_tegra.h" -static VdpTime get_time(void) -{ - struct timespec tp; - - if (clock_gettime(CLOCK_MONOTONIC, &tp) == -1) - abort(); - - return (VdpTime)tp.tv_sec * 1000000000ULL + (VdpTime)tp.tv_nsec; -} - -static void pqt_display_surface_to_idle_state(tegra_pqt *pqt) -{ - tegra_surface *surf = pqt->disp_surf; - - if (!surf) { - return; - } - - pthread_mutex_lock(&surf->lock); - if (surf->status == VDP_PRESENTATION_QUEUE_STATUS_VISIBLE) { - surf->status = VDP_PRESENTATION_QUEUE_STATUS_IDLE; - pthread_cond_signal(&surf->idle_cond); - pqt->disp_surf = NULL; - - DebugMsg("visible surface %u became idle\n", - surf->surface_id); - } else { - DebugMsg("trying to set invisible surface %u to idle\n", - surf->surface_id); - } - pthread_mutex_unlock(&surf->lock); - - unref_surface(surf); -} - -static void pqt_display_surface(tegra_pqt *pqt, tegra_surface *surf) -{ - tegra_device *dev = pqt->dev; - CARD64 count; - - DebugMsg("surface %u earliest_presentation_time %llu+\n", - surf->surface_id, surf->earliest_presentation_time); - - if (!DRI_OUTPUT) { - if (surf->set_bg && surf->bg_color != pqt->bg_color) { - XSetWindowBackground(dev->display, pqt->drawable, surf->bg_color); - XClearWindow(dev->display, pqt->drawable); - - pqt->bg_color = surf->bg_color; - } - - if (surf->shared) { - DebugMsg("surface %u YUV overlay\n", surf->surface_id); - - XvPutImage(dev->display, dev->xv_port, - pqt->drawable, pqt->gc, - surf->shared->xv_img, - surf->shared->src_x0, - surf->shared->src_y0, - surf->shared->src_width, - surf->shared->src_height, - surf->shared->dst_x0, - surf->shared->dst_y0, - surf->shared->dst_width, - surf->shared->dst_height); - } else if (surf->xv_img) { - DebugMsg("surface %u RGB overlay\n", surf->surface_id); - - XvPutImage(dev->display, dev->xv_port, - pqt->drawable, pqt->gc, - surf->xv_img, - 0, - 0, - surf->disp_width, - surf->disp_height, - 0, - 0, - surf->disp_width, - surf->disp_height); - } - - XSync(dev->display, 0); - } else if (pqt->dri_pixbuf) { - DebugMsg("surface %u DRI\n", surf->surface_id); - - DRI2SwapBuffers(dev->display, pqt->drawable, 0, 0, 0, &count); - } - - pthread_mutex_lock(&surf->lock); - surf->first_presentation_time = get_time(); - surf->status = VDP_PRESENTATION_QUEUE_STATUS_VISIBLE; - - if (pqt->disp_surf != surf) { - pqt_display_surface_to_idle_state(pqt); - pqt->disp_surf = surf; - } - pthread_mutex_unlock(&surf->lock); - - DebugMsg("surface %u-\n", surf->surface_id); -} - -static void pqt_update_dri_buffer(tegra_pqt *pqt, tegra_surface *surf) -{ - int ret; - - if (!DRI_OUTPUT) { - return; - } - - if (surf->disp_width != pqt->dri_pixbuf->width || - surf->disp_height != pqt->dri_pixbuf->height) { - pqt_update_dri_pixbuf(pqt); - } - - if (!pqt->dri_pixbuf) { - return; - } - - DebugMsg("surface %u+\n", surf->surface_id); - - pthread_mutex_lock(&surf->lock); - pthread_mutex_lock(&pqt->dev->lock); - - if (surf->shared) { - DebugMsg("surface %u transfer YUV\n", surf->surface_id); - - if (surf->set_bg) { - ret = host1x_gr2d_clear_rect_clipped(surf->dev->stream, - pqt->dri_pixbuf, - surf->bg_color, - 0, - 0, - pqt->dri_pixbuf->width, - pqt->dri_pixbuf->height, - surf->shared->dst_x0, - surf->shared->dst_y0, - surf->shared->dst_x0 + surf->shared->dst_width, - surf->shared->dst_y0 + surf->shared->dst_height, - true); - if (ret) { - ErrorMsg("setting BG failed %d\n", ret); - } - } - - ret = host1x_gr2d_surface_blit(pqt->dev->stream, - surf->shared->video->pixbuf, - pqt->dri_pixbuf, - &surf->shared->csc, - surf->shared->src_x0, - surf->shared->src_y0, - surf->shared->src_width, - surf->shared->src_height, - surf->shared->dst_x0, - surf->shared->dst_y0, - surf->shared->dst_width, - surf->shared->dst_height); - if (ret) { - ErrorMsg("video transfer failed %d\n", ret); - } - } else if (surf->pixbuf) { - DebugMsg("surface %u transfer RGB\n", surf->surface_id); - - ret = host1x_gr2d_surface_blit(pqt->dev->stream, - surf->pixbuf, - pqt->dri_pixbuf, - &csc_rgb_default, - 0, - 0, - surf->disp_width, - surf->disp_height, - 0, - 0, - pqt->dri_pixbuf->width, - pqt->dri_pixbuf->height); - if (ret) { - ErrorMsg("video transfer failed %d\n", ret); - } - } - - pthread_mutex_unlock(&pqt->dev->lock); - pthread_mutex_unlock(&surf->lock); - - DebugMsg("surface %u-\n", surf->surface_id); -} - static void * presentation_queue_thr(void *opaque) { tegra_pq *pq = opaque; tegra_pqt *pqt = pq->pqt; - tegra_surface *surf, *tmp; + tegra_surface *surf, *tmp, *next; VdpTime earliest_time = UINT64_MAX; VdpTime time = UINT64_MAX; struct timespec tp; @@ -227,6 +42,8 @@ static void * presentation_queue_thr(void *opaque) ret = pthread_cond_wait(&pq->cond, &pq->lock); } + DebugMsg("wakeup %d\n", ret); + if (pq->exit) { LIST_FOR_EACH_ENTRY_SAFE(surf, tmp, &pq->surf_list, list_item) { pthread_mutex_lock(&surf->lock); @@ -266,6 +83,7 @@ static void * presentation_queue_thr(void *opaque) if (surf->earliest_presentation_time < earliest_time) { DebugMsg("surface %u in queue\n", surf->surface_id); earliest_time = surf->earliest_presentation_time; + next = surf; } pthread_mutex_unlock(&surf->lock); @@ -275,13 +93,16 @@ static void * presentation_queue_thr(void *opaque) LIST_DEL(&surf->list_item); pthread_mutex_unlock(&surf->lock); - pqt_update_dri_buffer(pqt, surf); - pqt_display_surface(pqt, surf); + DebugMsg("displaying surface %u\n", surf->surface_id); + + pqt_display_surface(pqt, surf, false); } time = earliest_time; if (time != UINT64_MAX) { + pqt_prepare_dri_surface(pqt, next); + DebugMsg("next wake on %llu\n", time); } else { DebugMsg("going to sleep.. zZZ\n"); @@ -398,11 +219,6 @@ VdpStatus unref_presentation_queue(tegra_pq *pq) pqt = pq->pqt; dev = pqt->dev; - pthread_mutex_lock(&pq->lock); - pq->exit = true; - pthread_cond_signal(&pq->cond); - pthread_mutex_unlock(&pq->lock); - pthread_join(pq->disp_thread, NULL); unref_queue_target(pqt); @@ -424,6 +240,11 @@ VdpStatus vdp_presentation_queue_destroy( set_presentation_queue(presentation_queue, NULL); put_presentation_queue(pq); + pthread_mutex_lock(&pq->lock); + pq->exit = true; + pthread_cond_signal(&pq->cond); + pthread_mutex_unlock(&pq->lock); + unref_presentation_queue(pq); return VDP_STATUS_OK; @@ -511,12 +332,9 @@ VdpStatus vdp_presentation_queue_display( surf->disp_width = clip_width ?: surf->width; surf->disp_height = clip_height ?: surf->height; - if (earliest_presentation_time == 0) { + if (earliest_presentation_time == 0 || !_Xglobal_lock) { pthread_mutex_lock(&pq->lock); - - pqt_update_dri_buffer(pq->pqt, surf); - pqt_display_surface(pq->pqt, surf); - + pqt_display_surface(pq->pqt, surf, false); pthread_mutex_unlock(&pq->lock); goto unlock_surf; @@ -529,10 +347,8 @@ VdpStatus vdp_presentation_queue_display( surf->earliest_presentation_time = earliest_presentation_time; pthread_mutex_lock(&pq->lock); - LIST_ADDTAIL(&surf->list_item, &pq->surf_list); pthread_cond_signal(&pq->cond); - pthread_mutex_unlock(&pq->lock); unlock_surf: diff --git a/src/presentation_queue_target.c b/src/presentation_queue_target.c index 03bec38..ccd554e 100644 --- a/src/presentation_queue_target.c +++ b/src/presentation_queue_target.c @@ -19,7 +19,38 @@ #include "vdpau_tegra.h" -void pqt_update_dri_pixbuf(tegra_pqt *pqt) +void pqt_display_surface_to_idle_state(tegra_pqt *pqt) +{ + tegra_surface *surf; + + pthread_mutex_lock(&pqt->lock); + + surf = pqt->disp_surf; + if (!surf) { + pthread_mutex_unlock(&pqt->lock); + return; + } + + pthread_mutex_lock(&surf->lock); + if (surf->status == VDP_PRESENTATION_QUEUE_STATUS_VISIBLE) { + surf->status = VDP_PRESENTATION_QUEUE_STATUS_IDLE; + pthread_cond_signal(&surf->idle_cond); + pqt->disp_surf = NULL; + + DebugMsg("visible surface %u became idle\n", + surf->surface_id); + } else { + DebugMsg("trying to set invisible surface %u to idle\n", + surf->surface_id); + } + pthread_mutex_unlock(&surf->lock); + + pthread_mutex_unlock(&pqt->lock); + + unref_surface(surf); +} + +static void pqt_update_dri_pixbuf(tegra_pqt *pqt) { tegra_device *dev = pqt->dev; struct drm_tegra_bo *bo; @@ -64,6 +95,353 @@ void pqt_update_dri_pixbuf(tegra_pqt *pqt) } } +static void pqt_display_dri(tegra_pqt *pqt, tegra_surface *surf) +{ + tegra_device *dev = pqt->dev; + CARD64 count; + + DebugMsg("surface %u DRI\n", surf->surface_id); + + pthread_mutex_lock(&dev->lock); + DRI2SwapBuffers(dev->display, pqt->drawable, 0, 0, 0, &count); + pthread_mutex_unlock(&dev->lock); + + if (pqt->dri_prep_surf == surf) { + pqt->dri_prep_surf = NULL; + } +} + +static void pqt_display_xv(tegra_pqt *pqt, tegra_surface *surf) +{ + tegra_device *dev = pqt->dev; + + if (surf->set_bg && surf->bg_color != pqt->bg_color) { + XSetWindowBackground(dev->display, pqt->drawable, surf->bg_color); + XClearWindow(dev->display, pqt->drawable); + + pqt->bg_color = surf->bg_color; + } + + if (surf->shared) { + DebugMsg("surface %u YUV overlay\n", surf->surface_id); + + XvPutImage(dev->display, dev->xv_port, + pqt->drawable, pqt->gc, + surf->shared->xv_img, + surf->shared->src_x0, + surf->shared->src_y0, + surf->shared->src_width, + surf->shared->src_height, + surf->shared->dst_x0, + surf->shared->dst_y0, + surf->shared->dst_width, + surf->shared->dst_height); + } else if (surf->xv_img) { + DebugMsg("surface %u RGB overlay\n", surf->surface_id); + + XvPutImage(dev->display, dev->xv_port, + pqt->drawable, pqt->gc, + surf->xv_img, + 0, + 0, + surf->disp_width, + surf->disp_height, + 0, + 0, + surf->disp_width, + surf->disp_height); + } else { + DebugMsg("surface %u is absent\n", surf->surface_id); + } + + XSync(dev->display, 0); +} + +static void transit_display_to_xv(tegra_pqt *pqt) +{ + tegra_surface *surf = pqt->disp_surf; + tegra_device *dev = pqt->dev; + CARD64 ust, msc, sbc; + + DebugMsg("surface %u\n", surf->surface_id); + + XSync(dev->display, 0); + + DRI2GetMSC(dev->display, pqt->drawable, &ust, &msc, &sbc); + DRI2WaitMSC(dev->display, pqt->drawable, msc + 1, 1, 1, &ust, &msc, &sbc); + + XSetWindowBackground(dev->display, pqt->drawable, surf->bg_color); + XClearWindow(dev->display, pqt->drawable); +} + +static void transit_display_to_dri(tegra_pqt *pqt) +{ + tegra_surface *surf = pqt->disp_surf; + tegra_device *dev = pqt->dev; + + DebugMsg("surface %u\n", surf->surface_id); + + XvStopVideo(dev->display, dev->xv_port, pqt->drawable); +} + +static void pqt_update_dri_buffer(tegra_pqt *pqt, tegra_surface *surf) +{ + bool new_buffer; + int ret; + + if (!pqt->dri_pixbuf || + surf->disp_width != pqt->dri_pixbuf->width || + surf->disp_height != pqt->dri_pixbuf->height) + { + pqt_update_dri_pixbuf(pqt); + new_buffer = true; + } else { + new_buffer = false; + } + + if (!pqt->dri_pixbuf) { + return; + } + + if (!new_buffer && pqt->dri_prep_surf == surf) { + DebugMsg("using prepared surface %u\n", surf->surface_id); + pqt->dri_prep_surf = NULL; + return; + } + + DebugMsg("surface %u+\n", surf->surface_id); + + pthread_mutex_lock(&surf->lock); + pthread_mutex_lock(&pqt->dev->lock); + + if (surf->shared) { + DebugMsg("surface %u transfer YUV\n", surf->surface_id); + + if (surf->set_bg) { + ret = host1x_gr2d_clear_rect_clipped(surf->dev->stream, + pqt->dri_pixbuf, + surf->bg_color, + 0, + 0, + pqt->dri_pixbuf->width, + pqt->dri_pixbuf->height, + surf->shared->dst_x0, + surf->shared->dst_y0, + surf->shared->dst_x0 + surf->shared->dst_width, + surf->shared->dst_y0 + surf->shared->dst_height, + true); + if (ret) { + ErrorMsg("setting BG failed %d\n", ret); + } + } + + ret = host1x_gr2d_surface_blit(pqt->dev->stream, + surf->shared->video->pixbuf, + pqt->dri_pixbuf, + &surf->shared->csc, + surf->shared->src_x0, + surf->shared->src_y0, + surf->shared->src_width, + surf->shared->src_height, + surf->shared->dst_x0, + surf->shared->dst_y0, + surf->shared->dst_width, + surf->shared->dst_height); + if (ret) { + ErrorMsg("video transfer failed %d\n", ret); + } + } else if (surf->pixbuf) { + DebugMsg("surface %u transfer RGB\n", surf->surface_id); + + ret = host1x_gr2d_surface_blit(pqt->dev->stream, + surf->pixbuf, + pqt->dri_pixbuf, + &csc_rgb_default, + 0, + 0, + surf->disp_width, + surf->disp_height, + 0, + 0, + pqt->dri_pixbuf->width, + pqt->dri_pixbuf->height); + if (ret) { + ErrorMsg("video transfer failed %d\n", ret); + } + } else { + DebugMsg("surface %u is absent\n", surf->surface_id); + } + + pthread_mutex_unlock(&pqt->dev->lock); + pthread_mutex_unlock(&surf->lock); + + DebugMsg("surface %u-\n", surf->surface_id); +} + +void pqt_prepare_dri_surface(tegra_pqt *pqt, tegra_surface *surf) +{ + pthread_mutex_lock(&pqt->lock); + pthread_mutex_lock(&surf->lock); + + if (tegra_vdpau_force_dri || pqt->overlapped_current) { + pqt_update_dri_buffer(pqt, surf); + pqt->dri_prep_surf = surf; + + DebugMsg("surface %u\n", surf->surface_id); + } + + pthread_mutex_unlock(&surf->lock); + pthread_mutex_unlock(&pqt->lock); +} + +void pqt_display_surface(tegra_pqt *pqt, tegra_surface *surf, + bool update_state) +{ + DebugMsg("surface %u earliest_presentation_time %llu+\n", + surf->surface_id, surf->earliest_presentation_time); + + pthread_mutex_lock(&pqt->lock); + pthread_mutex_lock(&surf->lock); + + surf->first_presentation_time = get_time(); + surf->status = VDP_PRESENTATION_QUEUE_STATUS_VISIBLE; + + if (tegra_vdpau_force_dri || pqt->overlapped_current) { + pqt_update_dri_buffer(pqt, surf); + pqt_display_dri(pqt, surf); + + if (update_state) { + transit_display_to_dri(pqt); + } + } else { + if (update_state) { + transit_display_to_xv(pqt); + } + + pqt_display_xv(pqt, surf); + } + + if (pqt->disp_surf != surf) { + pqt_display_surface_to_idle_state(pqt); + pqt->disp_surf = surf; + } + + pthread_mutex_unlock(&surf->lock); + pthread_mutex_unlock(&pqt->lock); + + DebugMsg("surface %u-\n", surf->surface_id); +} + +static void * pqt_display_thr(void *opaque) +{ + tegra_pqt *pqt = opaque; + bool overlapped; + + while (!pqt->exit) { + pthread_mutex_lock(&pqt->disp_lock); + if (pqt->overlapped_current == pqt->overlapped_new && !pqt->win_move) { + pthread_cond_wait(&pqt->disp_cond, &pqt->disp_lock); + + if (pqt->exit) + break; + } + overlapped = pqt->overlapped_new; + pthread_mutex_unlock(&pqt->disp_lock); + + pthread_mutex_lock(&pqt->lock); + if (pqt->overlapped_current != overlapped) { + DebugMsg("updating overlap state\n"); + + pqt->overlapped_current = overlapped; + + if (pqt->disp_surf) { + pqt_display_surface(pqt, pqt->disp_surf, true); + } + } + if (pqt->win_move) { + pqt->win_move = false; + + if (pqt->disp_surf) { + pqt_display_surface(pqt, pqt->disp_surf, false); + } + } + pthread_mutex_unlock(&pqt->lock); + } + + return NULL; +} + +static void * pqt_x11_event_thr(void *opaque) +{ + tegra_pqt *pqt = opaque; + tegra_device *dev = pqt->dev; + bool overlapped; + bool win_move; + int x = 0, y = 0; + XEvent event; + struct timeval tv; + fd_set in_fds; + int fd; + + fd = ConnectionNumber(dev->display); + + while (!pqt->exit) { + memset(&tv, 0, sizeof(tv)); + tv.tv_usec = 300000; + + FD_ZERO(&in_fds); + FD_SET(fd, &in_fds); + + if (select(fd + 1, &in_fds, NULL, NULL, &tv) <= 0) { + continue; + } + + if (XCheckWindowEvent(dev->display, pqt->drawable, + VisibilityChangeMask, &event)) { + + overlapped = (event.xvisibility.state == VisibilityPartiallyObscured || + event.xvisibility.state == VisibilityFullyObscured); + + if (pqt->overlapped_new != overlapped) { + pthread_mutex_lock(&pqt->disp_lock); + + DebugMsg("window overlapped %d\n", overlapped); + + pqt->overlapped_new = overlapped; + pthread_cond_signal(&pqt->disp_cond); + + pthread_mutex_unlock(&pqt->disp_lock); + } + } else if (XCheckWindowEvent(dev->display, pqt->drawable, + StructureNotifyMask, &event)) { + + if (event.type == ConfigureNotify && + (x != event.xconfigure.x || + y != event.xconfigure.y)) + { + x = event.xconfigure.x; + y = event.xconfigure.y; + win_move = true; + } else { + win_move = false; + } + + if (win_move) { + pthread_mutex_lock(&pqt->disp_lock); + + DebugMsg("window move (%d, %d)\n", x, y); + + pqt->win_move = true; + pthread_cond_signal(&pqt->disp_cond); + + pthread_mutex_unlock(&pqt->disp_lock); + } + } + } + + return NULL; +} + static bool initialize_dri2(tegra_pqt *pqt) { tegra_device *dev = pqt->dev; @@ -96,8 +474,19 @@ VdpStatus unref_queue_target(tegra_pqt *pqt) if (!atomic_dec_and_test(&pqt->refcnt)) return VDP_STATUS_OK; - if (pqt->gc != None) + if (_Xglobal_lock && !(tegra_vdpau_force_xv || tegra_vdpau_force_dri)) { + pthread_join(pqt->x11_thread, NULL); + + pthread_mutex_lock(&pqt->disp_lock); + pthread_cond_signal(&pqt->disp_cond); + pthread_mutex_unlock(&pqt->disp_lock); + + pthread_join(pqt->disp_thread, NULL); + } + + if (pqt->gc != None) { XFreeGC(dev->display, pqt->gc); + } unref_device(dev); free(pqt); @@ -117,6 +506,8 @@ VdpStatus vdp_presentation_queue_target_destroy( set_presentation_queue_target(presentation_queue_target, NULL); put_queue_target(pqt); + pqt->exit = true; + unref_queue_target(pqt); return VDP_STATUS_OK; @@ -131,6 +522,10 @@ VdpStatus vdp_presentation_queue_target_create_x11( VdpPresentationQueueTarget i; XGCValues values; tegra_pqt *pqt; + pthread_mutexattr_t mutex_attrs; + pthread_attr_t thread_attrs; + XSetWindowAttributes set; + XWindowAttributes get; if (dev == NULL) { return VDP_STATUS_INVALID_HANDLE; @@ -155,21 +550,45 @@ VdpStatus vdp_presentation_queue_target_create_x11( return VDP_STATUS_RESOURCES; } + pthread_mutexattr_init(&mutex_attrs); + pthread_mutexattr_settype(&mutex_attrs, PTHREAD_MUTEX_RECURSIVE); + + pthread_mutex_init(&pqt->lock, &mutex_attrs); atomic_set(&pqt->refcnt, 1); ref_device(dev); pqt->dev = dev; pqt->drawable = drawable; pqt->gc = XCreateGC(dev->display, drawable, 0, &values); - if (!DRI_OUTPUT) { - XSetWindowBackground(dev->display, drawable, pqt->bg_color); - XClearWindow(dev->display, drawable); - } else { - if (!initialize_dri2(pqt)) { - put_queue_target(pqt); - put_device(dev); - return VDP_STATUS_RESOURCES; - } + XGetWindowAttributes(dev->display, drawable, &get); + set.event_mask = get.all_event_masks; + set.event_mask |= VisibilityChangeMask; + set.event_mask |= StructureNotifyMask; + XChangeWindowAttributes(dev->display, drawable, CWEventMask, &set); + + XSetWindowBackground(dev->display, drawable, pqt->bg_color); + XClearWindow(dev->display, drawable); + + if (!initialize_dri2(pqt)) { + put_queue_target(pqt); + put_device(dev); + free(pqt); + return VDP_STATUS_RESOURCES; + } + + if (_Xglobal_lock && !(tegra_vdpau_force_xv || tegra_vdpau_force_dri)) { + pthread_attr_init(&thread_attrs); + pthread_attr_setdetachstate(&thread_attrs, PTHREAD_CREATE_JOINABLE); + pthread_create(&pqt->x11_thread, &thread_attrs, + pqt_x11_event_thr, pqt); + + pthread_mutex_init(&pqt->disp_lock, NULL); + pthread_cond_init(&pqt->disp_cond, NULL); + + pthread_attr_init(&thread_attrs); + pthread_attr_setdetachstate(&thread_attrs, PTHREAD_CREATE_JOINABLE); + pthread_create(&pqt->disp_thread, &thread_attrs, + pqt_display_thr, pqt); } *target = i; diff --git a/src/surface_mixer.c b/src/surface_mixer.c index e9ee6d7..6919dee 100644 --- a/src/surface_mixer.c +++ b/src/surface_mixer.c @@ -621,7 +621,7 @@ VdpStatus vdp_video_mixer_render( } if (!draw_background) { - if (DRI_OUTPUT || !mix->custom_csc) { + if (tegra_vdpau_force_dri || !mix->custom_csc) { shared = create_shared_surface(dest_surf, video_surf, &mix->csc, diff --git a/src/vdpau_tegra.c b/src/vdpau_tegra.c index e5441e6..627651b 100644 --- a/src/vdpau_tegra.c +++ b/src/vdpau_tegra.c @@ -22,6 +22,8 @@ pthread_mutex_t global_lock = PTHREAD_MUTEX_INITIALIZER; bool tegra_vdpau_debug; +bool tegra_vdpau_force_xv; +bool tegra_vdpau_force_dri; static tegra_device * tegra_devices[MAX_DEVICES_NB]; static tegra_decoder * tegra_decoders[MAX_DECODERS_NB]; @@ -42,6 +44,16 @@ VdpCSCMatrix CSC_BT_709 = { { 1.164384f, 2.112402f, 0.000000f }, }; +VdpTime get_time(void) +{ + struct timespec tp; + + if (clock_gettime(CLOCK_MONOTONIC, &tp) != 0) + ErrorMsg("failed\n"); + + return (VdpTime)tp.tv_sec * 1000000000ULL + (VdpTime)tp.tv_nsec; +} + tegra_decoder * __get_decoder(VdpDecoder decoder) { if (decoder >= MAX_DECODERS_NB) { @@ -563,6 +575,16 @@ EXPORTED VdpStatus vdp_imp_device_create_x11(Display *display, tegra_vdpau_debug = true; } + debug_str = getenv("VDPAU_TEGRA_FORCE_XV"); + if (debug_str && strcmp(debug_str, "0")) { + tegra_vdpau_force_xv = true; + } + + debug_str = getenv("VDPAU_TEGRA_FORCE_DRI"); + if (debug_str && strcmp(debug_str, "0")) { + tegra_vdpau_force_dri = true; + } + drm_fd = drmOpen("tegra", NULL); if (drm_fd < 0) { perror("Failed to open tegra DRM\n"); diff --git a/src/vdpau_tegra.h b/src/vdpau_tegra.h index 0bedf10..dd0be45 100644 --- a/src/vdpau_tegra.h +++ b/src/vdpau_tegra.h @@ -114,9 +114,9 @@ do { \ #define UNIFIED_BUFFER 0 -#define DRI_OUTPUT 0 - extern bool tegra_vdpau_debug; +extern bool tegra_vdpau_force_xv; +extern bool tegra_vdpau_force_dri; extern VdpCSCMatrix CSC_BT_601; extern VdpCSCMatrix CSC_BT_709; @@ -223,7 +223,17 @@ typedef struct tegra_pqt { Drawable drawable; GC gc; atomic_t refcnt; + pthread_t x11_thread; + pthread_t disp_thread; + pthread_cond_t disp_cond; + pthread_mutex_t disp_lock; + pthread_mutex_t lock; uint32_t bg_color; + bool overlapped_current; + bool overlapped_new; + bool win_move; + bool exit; + tegra_surface *dri_prep_surf; } tegra_pqt; typedef struct tegra_pq { @@ -285,7 +295,10 @@ VdpStatus unref_queue_target(tegra_pqt *pqt); #define put_queue_target(__pqt) ({ if (__pqt) unref_queue_target(__pqt); }) void set_presentation_queue_target(VdpPresentationQueueTarget target, tegra_pqt *pqt); -void pqt_update_dri_pixbuf(tegra_pqt *pqt); +void pqt_display_surface_to_idle_state(tegra_pqt *pqt); +void pqt_display_surface(tegra_pqt *pqt, tegra_surface *surf, + bool update_state); +void pqt_prepare_dri_surface(tegra_pqt *pqt, tegra_surface *surf); tegra_pq * __get_presentation_queue(VdpPresentationQueue presentation_queue); tegra_pq * get_presentation_queue(VdpPresentationQueue presentation_queue); @@ -326,6 +339,8 @@ tegra_surface * shared_surface_swap_video(tegra_surface *old); int shared_surface_transfer_video(tegra_surface *disp); void shared_surface_kill_disp(tegra_surface *disp); +VdpTime get_time(void); + VdpGetErrorString vdp_get_error_string; VdpGetProcAddress vdp_get_proc_address; VdpGetApiVersion vdp_get_api_version; |