summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Osipenko <digetx@gmail.com>2017-12-28 20:35:51 +0300
committerDmitry Osipenko <digetx@gmail.com>2017-12-28 22:17:05 +0300
commit4741440150aa0f81f394b0a559c977cd5a795dd9 (patch)
tree06ab4cff0bccb25f9621f793ba6204fe33981ba8
parent81bfb8145d08e63e748dd957ceab4558f97e7f6a (diff)
Cleanup shared surface
-rw-r--r--src/surface.c6
-rw-r--r--src/surface_shared.c82
2 files changed, 60 insertions, 28 deletions
diff --git a/src/surface.c b/src/surface.c
index 5ab6a9c..6d513d3 100644
--- a/src/surface.c
+++ b/src/surface.c
@@ -447,9 +447,6 @@ VdpStatus unref_surface(tegra_surface *surf)
}
pthread_mutex_lock(&surf->lock);
- if (surf->flags & SURFACE_OUTPUT) {
- shared_surface_kill_disp(surf);
- }
dynamic_release_surface_data(surf);
unref_device(surf->dev);
pthread_mutex_unlock(&surf->lock);
@@ -464,6 +461,9 @@ VdpStatus unref_surface(tegra_surface *surf)
VdpStatus destroy_surface(tegra_surface *surf)
{
pthread_mutex_lock(&surf->lock);
+ if (surf->flags & SURFACE_OUTPUT) {
+ shared_surface_kill_disp(surf);
+ }
surf->earliest_presentation_time = 0;
pthread_mutex_unlock(&surf->lock);
diff --git a/src/surface_shared.c b/src/surface_shared.c
index 4e584ba..1176ff4 100644
--- a/src/surface_shared.c
+++ b/src/surface_shared.c
@@ -76,17 +76,25 @@ tegra_shared_surface *create_shared_surface(tegra_surface *disp,
tegra_shared_surface *shared;
int ret;
- if (disp->data_dirty) {
+ pthread_mutex_unlock(&shared_lock);
+ pthread_mutex_lock(&video->lock);
+ pthread_mutex_lock(&disp->lock);
+
+ if (disp->data_dirty || disp->shared || video->shared) {
+ pthread_mutex_unlock(&disp->lock);
+ pthread_mutex_unlock(&video->lock);
+ pthread_mutex_unlock(&shared_lock);
return NULL;
}
shared = calloc(1, sizeof(tegra_shared_surface));
if (!shared) {
+ pthread_mutex_unlock(&disp->lock);
+ pthread_mutex_unlock(&video->lock);
+ pthread_mutex_unlock(&shared_lock);
return NULL;
}
- assert(disp->shared == NULL);
-
atomic_set(&shared->refcnt, 1);
memcpy(&shared->csc, csc, sizeof(*csc));
@@ -104,6 +112,10 @@ tegra_shared_surface *create_shared_surface(tegra_surface *disp,
if (!shared->xv_img) {
free(shared);
+
+ pthread_mutex_unlock(&disp->lock);
+ pthread_mutex_unlock(&video->lock);
+ pthread_mutex_unlock(&shared_lock);
return NULL;
}
@@ -111,13 +123,23 @@ tegra_shared_surface *create_shared_surface(tegra_surface *disp,
if (ret) {
free(shared->xv_img);
free(shared);
+
+ pthread_mutex_unlock(&disp->lock);
+ pthread_mutex_unlock(&video->lock);
+ pthread_mutex_unlock(&shared_lock);
return NULL;
}
+ ref_surface(disp);
ref_surface(video);
+
video->shared = shared;
disp->shared = shared;
+ pthread_mutex_unlock(&disp->lock);
+ pthread_mutex_unlock(&video->lock);
+ pthread_mutex_unlock(&shared_lock);
+
return shared;
}
@@ -132,11 +154,20 @@ void unref_shared_surface(tegra_shared_surface *shared)
return;
}
+ unref_surface(shared->video);
+ unref_surface(shared->disp);
+
free(shared->xv_img->data);
XFree(shared->xv_img);
free(shared);
}
+static void shared_surface_break_link_locked(tegra_shared_surface *shared)
+{
+ shared->disp->shared = NULL;
+ shared->video->shared = NULL;
+}
+
tegra_surface * shared_surface_swap_video(tegra_surface *old)
{
tegra_shared_surface *shared;
@@ -144,13 +175,14 @@ tegra_surface * shared_surface_swap_video(tegra_surface *old)
assert(old->flags & SURFACE_VIDEO);
- pthread_mutex_lock(&old->lock);
pthread_mutex_lock(&shared_lock);
shared = old->shared;
+ if (shared) {
+ ref_surface(old);
+ }
pthread_mutex_unlock(&shared_lock);
if (!shared) {
- pthread_mutex_unlock(&old->lock);
return old;
}
@@ -160,13 +192,13 @@ tegra_surface * shared_surface_swap_video(tegra_surface *old)
replace_surface(old, new);
pthread_mutex_unlock(&global_lock);
- pthread_mutex_unlock(&old->lock);
unref_surface(old);
} else {
- pthread_mutex_unlock(&old->lock);
new = old;
}
+ unref_surface(old);
+
return new;
}
@@ -178,20 +210,20 @@ int shared_surface_transfer_video(tegra_surface *disp)
assert(disp->flags & SURFACE_OUTPUT);
+ pthread_mutex_lock(&disp->lock);
+
pthread_mutex_lock(&shared_lock);
shared = disp->shared;
if (shared) {
- ref_surface(disp);
- disp->shared = NULL;
+ ref_shared_surface(shared);
video = shared->video;
}
pthread_mutex_unlock(&shared_lock);
- pthread_mutex_lock(&disp->lock);
ret = dynamic_alloc_surface_data(disp);
if (ret) {
if (shared) {
- goto unref;
+ goto unshare;
}
pthread_mutex_unlock(&disp->lock);
return ret;
@@ -203,7 +235,7 @@ int shared_surface_transfer_video(tegra_surface *disp)
}
if (disp->set_bg) {
- host1x_gr2d_clear_rect_clipped(video->dev->stream,
+ host1x_gr2d_clear_rect_clipped(disp->dev->stream,
disp->pixbuf,
disp->bg_color,
0, 0,
@@ -229,10 +261,14 @@ int shared_surface_transfer_video(tegra_surface *disp)
shared->dst_y0,
shared->dst_width,
shared->dst_height);
-unref:
+unshare:
+ pthread_mutex_lock(&shared_lock);
+ shared_surface_break_link_locked(shared);
+ pthread_mutex_unlock(&shared_lock);
+
+ unref_shared_surface(shared);
pthread_mutex_unlock(&disp->lock);
- unref_surface(disp);
- unref_surface(video);
+
unref_shared_surface(shared);
return 0;
@@ -249,18 +285,14 @@ void shared_surface_kill_disp(tegra_surface *disp)
pthread_mutex_lock(&shared_lock);
shared = disp->shared;
- if (!shared) {
- goto out;
- }
-
- if (shared->video) {
- unref_surface(shared->video);
+ if (shared) {
+ shared_surface_break_link_locked(shared);
}
- disp->shared = NULL;
- unref_shared_surface(shared);
-
-out:
pthread_mutex_unlock(&shared_lock);
pthread_mutex_unlock(&disp->lock);
+
+ if (shared) {
+ unref_shared_surface(shared);
+ }
}