summaryrefslogtreecommitdiff
path: root/src/presentation_queue.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/presentation_queue.c')
-rw-r--r--src/presentation_queue.c100
1 files changed, 81 insertions, 19 deletions
diff --git a/src/presentation_queue.c b/src/presentation_queue.c
index 19fb167..9fbb9fd 100644
--- a/src/presentation_queue.c
+++ b/src/presentation_queue.c
@@ -175,6 +175,11 @@ del_surface:
return NULL;
}
+void ref_queue_target(tegra_pqt *pqt)
+{
+ atomic_inc(&pqt->refcnt);
+}
+
VdpStatus unref_queue_target(tegra_pqt *pqt)
{
tegra_device *dev = pqt->dev;
@@ -185,6 +190,7 @@ VdpStatus unref_queue_target(tegra_pqt *pqt)
if (pqt->gc != None)
XFreeGC(dev->display, pqt->gc);
+ unref_device(dev);
free(pqt);
return VDP_STATUS_OK;
@@ -201,7 +207,9 @@ VdpStatus vdp_presentation_queue_target_destroy(
set_presentation_queue_target(presentation_queue_target, NULL);
- return unref_queue_target(pqt);
+ put_queue_target(pqt);
+
+ return VDP_STATUS_OK;
}
VdpStatus vdp_presentation_queue_create(
@@ -218,13 +226,15 @@ VdpStatus vdp_presentation_queue_create(
int ret;
if (dev == NULL || pqt == NULL) {
+ put_device(dev);
+ put_queue_target(pqt);
return VDP_STATUS_INVALID_HANDLE;
}
pthread_mutex_lock(&global_lock);
for (i = 0; i < MAX_PRESENTATION_QUEUES_NB; i++) {
- pq = get_presentation_queue(i);
+ pq = __get_presentation_queue(i);
if (pq == NULL) {
pq = calloc(1, sizeof(tegra_pq));
@@ -236,12 +246,16 @@ VdpStatus vdp_presentation_queue_create(
pthread_mutex_unlock(&global_lock);
if (i == MAX_PRESENTATION_QUEUES_NB || pq == NULL) {
+ put_device(dev);
+ put_queue_target(pqt);
return VDP_STATUS_RESOURCES;
}
ret = pthread_mutex_init(&pq->lock, NULL);
if (ret != 0) {
ErrorMsg("pthread_mutex_init failed\n");
+ put_device(dev);
+ put_queue_target(pqt);
return VDP_STATUS_RESOURCES;
}
@@ -251,12 +265,15 @@ VdpStatus vdp_presentation_queue_create(
ret = pthread_cond_init(&pq->cond, &cond_attrs);
if (ret != 0) {
ErrorMsg("pthread_cond_init failed\n");
+ put_device(dev);
+ put_queue_target(pqt);
return VDP_STATUS_RESOURCES;
}
pthread_condattr_destroy(&cond_attrs);
LIST_INITHEAD(&pq->surf_list);
+ atomic_set(&pq->refcnt, 1);
pq->pqt = pqt;
pthread_attr_init(&thread_attrs);
@@ -266,40 +283,45 @@ VdpStatus vdp_presentation_queue_create(
presentation_queue_thr, pq);
if (ret != 0) {
ErrorMsg("pthread_create failed\n");
+ put_device(dev);
+ put_queue_target(pqt);
return VDP_STATUS_RESOURCES;
}
pthread_attr_destroy(&thread_attrs);
- atomic_inc(&pqt->refcnt);
+ ref_queue_target(pqt);
ref_device(dev);
*presentation_queue = i;
+ put_device(dev);
+ put_queue_target(pqt);
+
return VDP_STATUS_OK;
}
-VdpStatus vdp_presentation_queue_destroy(
- VdpPresentationQueue presentation_queue)
+void ref_presentation_queue(tegra_pq *pq)
+{
+ atomic_inc(&pq->refcnt);
+}
+
+VdpStatus unref_presentation_queue(tegra_pq *pq)
{
- tegra_pq *pq = get_presentation_queue(presentation_queue);
- tegra_pqt *pqt;
tegra_device *dev;
+ tegra_pqt *pqt;
- if (pq == NULL) {
- return VDP_STATUS_INVALID_HANDLE;
- }
+ if (!atomic_dec_and_test(&pq->refcnt))
+ return VDP_STATUS_OK;
pqt = pq->pqt;
dev = pqt->dev;
- set_presentation_queue(presentation_queue, NULL);
-
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);
@@ -309,6 +331,21 @@ VdpStatus vdp_presentation_queue_destroy(
return VDP_STATUS_OK;
}
+VdpStatus vdp_presentation_queue_destroy(
+ VdpPresentationQueue presentation_queue)
+{
+ tegra_pq *pq = get_presentation_queue(presentation_queue);
+
+ if (pq == NULL) {
+ return VDP_STATUS_INVALID_HANDLE;
+ }
+
+ set_presentation_queue(presentation_queue, NULL);
+ put_presentation_queue(pq);
+
+ return VDP_STATUS_OK;
+}
+
VdpStatus vdp_presentation_queue_set_background_color(
VdpPresentationQueue presentation_queue,
VdpColor *const background_color)
@@ -319,6 +356,8 @@ VdpStatus vdp_presentation_queue_set_background_color(
return VDP_STATUS_INVALID_HANDLE;
}
+ put_presentation_queue(pq);
+
return VDP_STATUS_OK;
}
@@ -332,6 +371,8 @@ VdpStatus vdp_presentation_queue_get_background_color(
return VDP_STATUS_INVALID_HANDLE;
}
+ put_presentation_queue(pq);
+
return VDP_STATUS_OK;
}
@@ -347,6 +388,8 @@ VdpStatus vdp_presentation_queue_get_time(
*current_time = get_time();
+ put_presentation_queue(pq);
+
return VDP_STATUS_OK;
}
@@ -357,8 +400,8 @@ VdpStatus vdp_presentation_queue_display(
uint32_t clip_height,
VdpTime earliest_presentation_time)
{
- tegra_surface *surf = get_surface(surface);
tegra_pq *pq = get_presentation_queue(presentation_queue);
+ tegra_surface *surf;
tegra_pqt *pqt;
VdpTime time;
@@ -368,8 +411,9 @@ VdpStatus vdp_presentation_queue_display(
pqt = pq->pqt;
- /* This will happen on surface allocation failure. */
+ surf = get_surface(surface);
if (surf == NULL) {
+ /* This will happen on surface allocation failure. */
time = get_time();
if (earliest_presentation_time > time) {
@@ -383,6 +427,8 @@ VdpStatus vdp_presentation_queue_display(
pthread_cond_signal(&pq->cond);
pthread_mutex_unlock(&pq->lock);
+ put_presentation_queue(pq);
+
return VDP_STATUS_RESOURCES;
}
@@ -405,6 +451,9 @@ VdpStatus vdp_presentation_queue_display(
pthread_mutex_unlock(&surf->lock);
pthread_mutex_unlock(&pq->lock);
+ put_surface(surf);
+ put_presentation_queue(pq);
+
return VDP_STATUS_OK;
}
@@ -418,6 +467,9 @@ VdpStatus vdp_presentation_queue_display(
pthread_cond_signal(&pq->cond);
pthread_mutex_unlock(&pq->lock);
+ put_surface(surf);
+ put_presentation_queue(pq);
+
return VDP_STATUS_OK;
}
@@ -431,12 +483,12 @@ VdpStatus vdp_presentation_queue_block_until_surface_idle(
VdpStatus ret = VDP_STATUS_ERROR;
if (surf == NULL || pq == NULL) {
+ put_surface(surf);
+ put_presentation_queue(pq);
*first_presentation_time = get_time();
return VDP_STATUS_INVALID_HANDLE;
}
- ref_surface(surf);
-
pthread_mutex_lock(&surf->lock);
if (surf->idle_hack ||
@@ -463,7 +515,8 @@ VdpStatus vdp_presentation_queue_block_until_surface_idle(
unlock:
pthread_mutex_unlock(&surf->lock);
- unref_surface(surf);
+ put_surface(surf);
+ put_presentation_queue(pq);
return ret;
}
@@ -478,6 +531,8 @@ VdpStatus vdp_presentation_queue_query_surface_status(
tegra_pq *pq = get_presentation_queue(presentation_queue);
if (surf == NULL || pq == NULL) {
+ put_surface(surf);
+ put_presentation_queue(pq);
*first_presentation_time = get_time();
return VDP_STATUS_INVALID_HANDLE;
}
@@ -485,6 +540,9 @@ VdpStatus vdp_presentation_queue_query_surface_status(
*status = surf->status;
*first_presentation_time = surf->first_presentation_time;
+ put_surface(surf);
+ put_presentation_queue(pq);
+
return VDP_STATUS_OK;
}
@@ -505,7 +563,7 @@ VdpStatus vdp_presentation_queue_target_create_x11(
pthread_mutex_lock(&global_lock);
for (i = 0; i < MAX_PRESENTATION_QUEUE_TARGETS_NB; i++) {
- pqt = get_presentation_queue_target(i);
+ pqt = __get_presentation_queue_target(i);
if (pqt == NULL) {
pqt = calloc(1, sizeof(tegra_pqt));
@@ -517,10 +575,12 @@ VdpStatus vdp_presentation_queue_target_create_x11(
pthread_mutex_unlock(&global_lock);
if (i == MAX_PRESENTATION_QUEUE_TARGETS_NB || pqt == NULL) {
+ put_device(dev);
return VDP_STATUS_RESOURCES;
}
atomic_set(&pqt->refcnt, 1);
+ ref_device(dev);
pqt->dev = dev;
pqt->drawable = drawable;
pqt->gc = XCreateGC(dev->display, drawable, 0, &values);
@@ -530,5 +590,7 @@ VdpStatus vdp_presentation_queue_target_create_x11(
*target = i;
+ put_device(dev);
+
return VDP_STATUS_OK;
}