From 4741440150aa0f81f394b0a559c977cd5a795dd9 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Thu, 28 Dec 2017 20:35:51 +0300 Subject: Cleanup shared surface --- src/surface.c | 6 ++-- src/surface_shared.c | 82 ++++++++++++++++++++++++++++++++++++---------------- 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); + } } -- cgit v1.2.3