summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Osipenko <digetx@gmail.com>2018-01-04 16:48:21 +0300
committerDmitry Osipenko <digetx@gmail.com>2018-01-04 18:34:09 +0300
commit683c81e6cdc9c705886a8f74b69be32cf5ad62ca (patch)
treee5090500df42f98015d1a145366cdcbbb473e453
parent3ef8c07ce939d0755cb538863d4f009b7fdfc6ab (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.c216
-rw-r--r--src/presentation_queue_target.c441
-rw-r--r--src/surface_mixer.c2
-rw-r--r--src/vdpau_tegra.c22
-rw-r--r--src/vdpau_tegra.h21
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;