diff options
author | Dmitry Osipenko <digetx@gmail.com> | 2017-12-30 18:52:46 +0300 |
---|---|---|
committer | Dmitry Osipenko <digetx@gmail.com> | 2017-12-30 21:32:56 +0300 |
commit | f14c13f922f8d9a93ff1ab524e856d2ff0e3c3c6 (patch) | |
tree | 39e00b8339bf25e44c449d0eddbfa7dbd2578164 /src | |
parent | aec3f29353b98c07f813a6ea4c64e1a3e02c9d3d (diff) |
Implement DRI output
DRI output will be used when Xv overlay isn't available or not suitable.
Lot's of locking fixes in this patch as well.
Diffstat (limited to 'src')
-rw-r--r-- | src/host1x-gr2d.c | 19 | ||||
-rw-r--r-- | src/host1x-pixelbuffer.c | 37 | ||||
-rw-r--r-- | src/host1x.h | 9 | ||||
-rw-r--r-- | src/presentation_queue.c | 255 | ||||
-rw-r--r-- | src/presentation_queue_target.c | 75 | ||||
-rw-r--r-- | src/surface.c | 2 | ||||
-rw-r--r-- | src/surface_mixer.c | 21 | ||||
-rw-r--r-- | src/surface_output.c | 10 | ||||
-rw-r--r-- | src/surface_shared.c | 5 | ||||
-rw-r--r-- | src/vdpau_tegra.c | 2 | ||||
-rw-r--r-- | src/vdpau_tegra.h | 5 |
11 files changed, 340 insertions, 100 deletions
diff --git a/src/host1x-gr2d.c b/src/host1x-gr2d.c index a459bac..07bf82b 100644 --- a/src/host1x-gr2d.c +++ b/src/host1x-gr2d.c @@ -117,6 +117,25 @@ int host1x_gr2d_clear_rect_clipped(struct tegra_stream *stream, if (y + height > pixbuf->height) return -EINVAL; + if (clip_x0 > pixbuf->width) + return -EINVAL; + + if (clip_y0 > pixbuf->height) + return -EINVAL; + + if (clip_x1 > pixbuf->width) + return -EINVAL; + + if (clip_y1 > pixbuf->height) + return -EINVAL; + + if (draw_outside && + x == clip_x0 && + y == clip_y0 && + x + width == clip_x1 && + y + height == clip_y1) + return 0; + switch (pixbuf->layout) { case PIX_BUF_LAYOUT_TILED_16x16: tiled = 1; diff --git a/src/host1x-pixelbuffer.c b/src/host1x-pixelbuffer.c index fbe51d2..a201bd6 100644 --- a/src/host1x-pixelbuffer.c +++ b/src/host1x-pixelbuffer.c @@ -148,6 +148,8 @@ struct host1x_pixelbuffer *host1x_pixelbuffer_create(struct drm_tegra *drm, } } + pixbuf->guard_enabled = !pixbuf_guard_disabled; + host1x_pixelbuffer_setup_guard(pixbuf); return pixbuf; @@ -161,6 +163,37 @@ error_cleanup: return NULL; } +struct host1x_pixelbuffer *host1x_pixelbuffer_wrap(struct drm_tegra_bo **bos, + unsigned width, + unsigned height, + unsigned pitch, + unsigned pitch_uv, + enum pixel_format format, + enum layout_format layout) +{ + struct host1x_pixelbuffer *pixbuf; + + pixbuf = calloc(1, sizeof(*pixbuf)); + if (!pixbuf) + return NULL; + + pixbuf->pitch = pitch; + pixbuf->pitch_uv = pitch_uv; + pixbuf->width = width; + pixbuf->height = height; + pixbuf->format = format; + pixbuf->layout = layout; + + pixbuf->bo = bos[0]; + + if (format == PIX_BUF_FMT_YV12) { + pixbuf->bos[1] = bos[1]; + pixbuf->bos[2] = bos[2]; + } + + return pixbuf; +} + void host1x_pixelbuffer_free(struct host1x_pixelbuffer *pixbuf) { drm_tegra_bo_unref(pixbuf->bos[0]); @@ -249,7 +282,7 @@ int host1x_pixelbuffer_setup_guard(struct host1x_pixelbuffer *pixbuf) unsigned i; int ret; - if (pixbuf_guard_disabled) + if (pixbuf_guard_disabled || !pixbuf->guard_enabled) return 0; for (i = 0; i < PIX_BUF_FORMAT_PLANES_NB(pixbuf->format); i++) { @@ -310,7 +343,7 @@ int host1x_pixelbuffer_check_guard(struct host1x_pixelbuffer *pixbuf) unsigned i; int ret; - if (pixbuf_guard_disabled) + if (pixbuf_guard_disabled || !pixbuf->guard_enabled) return 0; for (i = 0; i < PIX_BUF_FORMAT_PLANES_NB(pixbuf->format); i++) { diff --git a/src/host1x.h b/src/host1x.h index 15125f0..27d3839 100644 --- a/src/host1x.h +++ b/src/host1x.h @@ -111,6 +111,7 @@ struct host1x_pixelbuffer { unsigned pitch_uv; uint32_t guard_offset[3]; uint32_t bo_offset[3]; + bool guard_enabled; }; #define PIXBUF_GUARD_AREA_SIZE 0x4000 @@ -123,6 +124,14 @@ struct host1x_pixelbuffer *host1x_pixelbuffer_create(struct drm_tegra *drm, enum pixel_format format, enum layout_format layout); +struct host1x_pixelbuffer *host1x_pixelbuffer_wrap(struct drm_tegra_bo **bos, + unsigned width, + unsigned height, + unsigned pitch, + unsigned pitch_uv, + enum pixel_format format, + enum layout_format layout); + void host1x_pixelbuffer_free(struct host1x_pixelbuffer *pixbuf); int host1x_pixelbuffer_load_data(struct drm_tegra *drm, diff --git a/src/presentation_queue.c b/src/presentation_queue.c index 46f56df..d995257 100644 --- a/src/presentation_queue.c +++ b/src/presentation_queue.c @@ -41,46 +41,58 @@ static void pqt_display_surface_to_idle_state(tegra_pqt *pqt) 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; } pthread_mutex_unlock(&surf->lock); unref_surface(surf); - pqt->disp_surf = NULL; } static void pqt_display_surface(tegra_pqt *pqt, tegra_surface *surf) { tegra_device *dev = pqt->dev; + CARD64 count; - if (surf->set_bg && surf->bg_color != pqt->bg_color) { - XSetWindowBackground(dev->display, pqt->drawable, surf->bg_color); - XClearWindow(dev->display, pqt->drawable); + 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; - } + pqt->bg_color = surf->bg_color; + } - if (surf->shared) { - 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) { - 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); - } + if (surf->shared) { + 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) { + 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); + XSync(dev->display, 0); + } else if (pqt->dri_pixbuf) { + 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; @@ -88,6 +100,72 @@ static void pqt_display_surface(tegra_pqt *pqt, tegra_surface *surf) pqt_display_surface_to_idle_state(pqt); pqt->disp_surf = surf; } + pthread_mutex_unlock(&surf->lock); +} + +static void pqt_update_dri_buffer(tegra_pqt *pqt, tegra_surface *surf) +{ + 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; + } + + pthread_mutex_lock(&surf->lock); + pthread_mutex_lock(&pqt->dev->lock); + + if (surf->shared) { + if (surf->set_bg) { + 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); + } + + 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); + } else if (surf->pixbuf) { + 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); + } + + pthread_mutex_unlock(&pqt->dev->lock); + pthread_mutex_unlock(&surf->lock); } static void * presentation_queue_thr(void *opaque) @@ -95,13 +173,14 @@ static void * presentation_queue_thr(void *opaque) tegra_pq *pq = opaque; tegra_pqt *pqt = pq->pqt; tegra_surface *surf, *tmp; - struct timespec tp; + VdpTime earliest_time = UINT64_MAX; VdpTime time = UINT64_MAX; + struct timespec tp; int ret; - while (true) { - pthread_mutex_lock(&pq->lock); + pthread_mutex_lock(&pq->lock); + while (true) { if (time == UINT64_MAX) { clock_gettime(CLOCK_MONOTONIC, &tp); tp.tv_sec += 9999999; @@ -134,44 +213,41 @@ static void * presentation_queue_thr(void *opaque) return NULL; } - if (ret == ETIMEDOUT) { - time = (VdpTime)tp.tv_sec * 1000000000ULL + (VdpTime)tp.tv_nsec; + if (ret != ETIMEDOUT) { + time = get_time(); + } - LIST_FOR_EACH_ENTRY_SAFE(surf, tmp, &pq->surf_list, list_item) { - pthread_mutex_lock(&surf->lock); + earliest_time = UINT64_MAX; - if (surf->earliest_presentation_time > time) { - pthread_mutex_unlock(&surf->lock); - continue; - } + LIST_FOR_EACH_ENTRY_SAFE(surf, tmp, &pq->surf_list, list_item) { + pthread_mutex_lock(&surf->lock); - if (surf->earliest_presentation_time < time) { - surf->status = VDP_PRESENTATION_QUEUE_STATUS_IDLE; - surf->first_presentation_time = 0; - pthread_cond_signal(&surf->idle_cond); + if (surf->status != VDP_PRESENTATION_QUEUE_STATUS_QUEUED) { + pthread_mutex_unlock(&surf->lock); + continue; + } - goto del_surface; - } + if (surf->earliest_presentation_time < earliest_time) { + earliest_time = surf->earliest_presentation_time; + } - pqt_display_surface(pqt, surf); - ref_surface(surf); -del_surface: - LIST_DEL(&surf->list_item); + if (surf->earliest_presentation_time > time) { pthread_mutex_unlock(&surf->lock); - unref_surface(surf); + continue; } - } - time = UINT64_MAX; + LIST_DEL(&surf->list_item); + pthread_mutex_unlock(&surf->lock); - LIST_FOR_EACH_ENTRY(surf, &pq->surf_list, list_item) { - if (surf->earliest_presentation_time < time) - time = surf->earliest_presentation_time; + pqt_update_dri_buffer(pqt, surf); + pqt_display_surface(pqt, surf); } - pthread_mutex_unlock(&pq->lock); + time = earliest_time; } + pthread_mutex_unlock(&pq->lock); + return NULL; } @@ -184,6 +260,7 @@ VdpStatus vdp_presentation_queue_create( tegra_pqt *pqt = get_presentation_queue_target(presentation_queue_target); tegra_pq *pq; VdpPresentationQueue i; + pthread_mutexattr_t mutex_attrs; pthread_condattr_t cond_attrs; pthread_attr_t thread_attrs; int ret; @@ -214,7 +291,10 @@ VdpStatus vdp_presentation_queue_create( return VDP_STATUS_RESOURCES; } - ret = pthread_mutex_init(&pq->lock, NULL); + pthread_mutexattr_init(&mutex_attrs); + pthread_mutexattr_settype(&mutex_attrs, PTHREAD_MUTEX_RECURSIVE); + + ret = pthread_mutex_init(&pq->lock, &mutex_attrs); if (ret != 0) { ErrorMsg("pthread_mutex_init failed\n"); put_device(dev); @@ -233,8 +313,6 @@ VdpStatus vdp_presentation_queue_create( return VDP_STATUS_RESOURCES; } - pthread_condattr_destroy(&cond_attrs); - LIST_INITHEAD(&pq->surf_list); atomic_set(&pq->refcnt, 1); pq->pqt = pqt; @@ -251,8 +329,6 @@ VdpStatus vdp_presentation_queue_create( return VDP_STATUS_RESOURCES; } - pthread_attr_destroy(&thread_attrs); - ref_queue_target(pqt); ref_device(dev); @@ -367,41 +443,23 @@ VdpStatus vdp_presentation_queue_display( { tegra_pq *pq = get_presentation_queue(presentation_queue); tegra_surface *surf; - tegra_pqt *pqt; - VdpTime time; + VdpStatus ret = VDP_STATUS_OK; if (pq == NULL) { return VDP_STATUS_INVALID_HANDLE; } - pqt = pq->pqt; - surf = get_surface(surface); if (surf == NULL) { /* This will happen on surface allocation failure. */ - time = get_time(); - - if (earliest_presentation_time > time) { - usleep((earliest_presentation_time - time) / 1000); - } - - pthread_mutex_lock(&pq->lock); - - pqt_display_surface_to_idle_state(pqt); - - pthread_cond_signal(&pq->cond); - pthread_mutex_unlock(&pq->lock); - - put_presentation_queue(pq); - return VDP_STATUS_RESOURCES; } - pthread_mutex_lock(&pq->lock); pthread_mutex_lock(&surf->lock); if (surf->status == VDP_PRESENTATION_QUEUE_STATUS_QUEUED) { - LIST_DEL(&surf->list_item); + ret = VDP_STATUS_ERROR; + goto unlock_surf; } ref_surface(surf); @@ -409,31 +467,33 @@ VdpStatus vdp_presentation_queue_display( surf->disp_height = clip_height ?: surf->height; if (earliest_presentation_time == 0) { - pqt_display_surface(pqt, surf); + pthread_mutex_lock(&pq->lock); - pthread_mutex_unlock(&surf->lock); - pthread_mutex_unlock(&pq->lock); + pqt_update_dri_buffer(pq->pqt, surf); + pqt_display_surface(pq->pqt, surf); - put_surface(surf); - put_presentation_queue(pq); + pthread_mutex_unlock(&pq->lock); - return VDP_STATUS_OK; + goto unlock_surf; } - LIST_ADDTAIL(&surf->list_item, &pq->surf_list); - surf->status = VDP_PRESENTATION_QUEUE_STATUS_QUEUED; surf->earliest_presentation_time = earliest_presentation_time; - pthread_mutex_unlock(&surf->lock); + 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: + pthread_mutex_unlock(&surf->lock); + put_surface(surf); put_presentation_queue(pq); - return VDP_STATUS_OK; + return ret; } VdpStatus vdp_presentation_queue_block_until_surface_idle( @@ -444,6 +504,7 @@ VdpStatus vdp_presentation_queue_block_until_surface_idle( tegra_surface *itr, *surf = get_surface(surface); tegra_pq *pq = get_presentation_queue(presentation_queue); VdpStatus ret = VDP_STATUS_ERROR; + int err; if (surf == NULL || pq == NULL) { put_surface(surf); @@ -452,12 +513,19 @@ VdpStatus vdp_presentation_queue_block_until_surface_idle( return VDP_STATUS_INVALID_HANDLE; } +retry: pthread_mutex_lock(&surf->lock); if (surf->status == VDP_PRESENTATION_QUEUE_STATUS_IDLE) { *first_presentation_time = surf->first_presentation_time; ret = VDP_STATUS_OK; - goto unlock; + goto unlock_surf; + } + + err = pthread_mutex_trylock(&pq->lock); + if (err) { + pthread_mutex_unlock(&surf->lock); + goto retry; } LIST_FOR_EACH_ENTRY(itr, &pq->surf_list, list_item) { @@ -466,15 +534,16 @@ VdpStatus vdp_presentation_queue_block_until_surface_idle( break; } } + pthread_mutex_unlock(&pq->lock); if (ret == VDP_STATUS_OK) { - pthread_cond_wait(&surf->idle_cond, &surf->lock); + pthread_cond_wait(&surf->idle_cond, &surf->lock); *first_presentation_time = surf->first_presentation_time; } else { *first_presentation_time = 0; } -unlock: +unlock_surf: pthread_mutex_unlock(&surf->lock); put_surface(surf); diff --git a/src/presentation_queue_target.c b/src/presentation_queue_target.c index 829ed4f..86b2725 100644 --- a/src/presentation_queue_target.c +++ b/src/presentation_queue_target.c @@ -19,6 +19,69 @@ #include "vdpau_tegra.h" +void pqt_update_dri_pixbuf(tegra_pqt *pqt) +{ + tegra_device *dev = pqt->dev; + struct drm_tegra_bo *bo; + DRI2Buffer *buf; + unsigned int attachment = DRI2BufferBackLeft; + int width, height; + int outCount; + int err; + + if (pqt->dri_pixbuf) { + host1x_pixelbuffer_free(pqt->dri_pixbuf); + pqt->dri_pixbuf = NULL; + } + + buf = DRI2GetBuffers(dev->display, pqt->drawable, &width, &height, + &attachment, 1, &outCount); + if (!buf || outCount != 1) { + ErrorMsg("Failed to get DRI2 buffer\n"); + return; + } + + err = drm_tegra_bo_from_name(&bo, dev->drm, buf[0].names[0], 0); + if (err) { + return; + } + + err = drm_tegra_bo_forbid_caching(bo); + if (err) { + drm_tegra_bo_unref(bo); + return; + } + + pqt->dri_pixbuf = host1x_pixelbuffer_wrap(&bo, width, height, + buf[0].pitch[0], 0, + PIX_BUF_FMT_ARGB8888, + PIX_BUF_LAYOUT_LINEAR); + if (!pqt->dri_pixbuf) { + drm_tegra_bo_unref(bo); + return; + } +} + +static bool initialize_dri2(tegra_pqt *pqt) +{ + tegra_device *dev = pqt->dev; + char *driverName, *deviceName; + Bool ret; + + ret = DRI2Connect(dev->display, pqt->drawable, DRI2DriverVDPAU, + &driverName, &deviceName); + if (!ret) { + ErrorMsg("DRI2 connect failed\n"); + return false; + } + + DRI2CreateDrawable(dev->display, pqt->drawable); + + pqt_update_dri_pixbuf(pqt); + + return true; +} + void ref_queue_target(tegra_pqt *pqt) { atomic_inc(&pqt->refcnt); @@ -96,8 +159,16 @@ VdpStatus vdp_presentation_queue_target_create_x11( pqt->drawable = drawable; pqt->gc = XCreateGC(dev->display, drawable, 0, &values); - XSetWindowBackground(dev->display, drawable, pqt->bg_color); - XClearWindow(dev->display, drawable); + 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; + } + } *target = i; diff --git a/src/surface.c b/src/surface.c index 6d513d3..32798b4 100644 --- a/src/surface.c +++ b/src/surface.c @@ -446,10 +446,8 @@ VdpStatus unref_surface(tegra_surface *surf) return VDP_STATUS_OK; } - pthread_mutex_lock(&surf->lock); dynamic_release_surface_data(surf); unref_device(surf->dev); - pthread_mutex_unlock(&surf->lock); set_surface(surf->surface_id, NULL); free(surf->frame); diff --git a/src/surface_mixer.c b/src/surface_mixer.c index 46b24f9..65e94b4 100644 --- a/src/surface_mixer.c +++ b/src/surface_mixer.c @@ -556,6 +556,8 @@ VdpStatus vdp_video_mixer_render( return VDP_STATUS_RESOURCES; } + pthread_mutex_lock(&mix->dev->lock); + host1x_gr2d_clear_rect_clipped(mix->dev->stream, dest_surf->pixbuf, bg_color, @@ -565,6 +567,8 @@ VdpStatus vdp_video_mixer_render( dst_vid_x0 + dst_vid_width, dst_vid_y0 + dst_vid_height, true); + + pthread_mutex_unlock(&mix->dev->lock); } else { dest_surf->bg_color = bg_color; dest_surf->set_bg = true; @@ -585,6 +589,8 @@ VdpStatus vdp_video_mixer_render( return VDP_STATUS_RESOURCES; } + pthread_mutex_lock(&mix->dev->lock); + host1x_gr2d_surface_blit(mix->dev->stream, bg_surf->pixbuf, dest_surf->pixbuf, @@ -595,6 +601,8 @@ VdpStatus vdp_video_mixer_render( 0, dest_surf->width, dest_surf->height); + + pthread_mutex_unlock(&mix->dev->lock); } if (bg_surf) { @@ -602,7 +610,7 @@ VdpStatus vdp_video_mixer_render( } if (!draw_background) { - if (!mix->custom_csc) + if (DRI_OUTPUT || !mix->custom_csc) { shared = create_shared_surface(dest_surf, video_surf, &mix->csc, @@ -614,6 +622,8 @@ VdpStatus vdp_video_mixer_render( dst_vid_y0, dst_vid_width, dst_vid_height); + } + if (!shared) { ret = dynamic_alloc_surface_data(dest_surf); if (ret) { @@ -626,6 +636,8 @@ VdpStatus vdp_video_mixer_render( return VDP_STATUS_RESOURCES; } + pthread_mutex_lock(&mix->dev->lock); + host1x_gr2d_clear_rect_clipped(mix->dev->stream, dest_surf->pixbuf, bg_color, @@ -635,11 +647,16 @@ VdpStatus vdp_video_mixer_render( dst_vid_x0 + dst_vid_width, dst_vid_y0 + dst_vid_height, true); + + pthread_mutex_unlock(&mix->dev->lock); + dest_surf->set_bg = false; } } if (!shared) { + pthread_mutex_lock(&mix->dev->lock); + host1x_gr2d_surface_blit(mix->dev->stream, video_surf->pixbuf, dest_surf->pixbuf, @@ -652,6 +669,8 @@ VdpStatus vdp_video_mixer_render( dst_vid_y0, dst_vid_width, dst_vid_height); + + pthread_mutex_unlock(&mix->dev->lock); } while (layer_count--) { diff --git a/src/surface_output.c b/src/surface_output.c index 343cef9..60f90b7 100644 --- a/src/surface_output.c +++ b/src/surface_output.c @@ -266,11 +266,16 @@ VdpStatus vdp_output_surface_render_bitmap_surface( } if (source_surface == VDP_INVALID_HANDLE) { + pthread_mutex_lock(&dst_surf->dev->lock); + ret = host1x_gr2d_clear_rect(dst_surf->dev->stream, dst_surf->pixbuf, 0xFFFFFFFF, dst_x0, dst_y0, dst_width, dst_height); + + pthread_mutex_unlock(&dst_surf->dev->lock); + if (ret == 0) { put_surface(dst_surf); put_surface(src_surf); @@ -336,6 +341,8 @@ VdpStatus vdp_output_surface_render_bitmap_surface( } if (!need_rotate) { + pthread_mutex_lock(&dst_surf->dev->lock); + host1x_gr2d_surface_blit(dst_surf->dev->stream, src_surf->pixbuf, dst_surf->pixbuf, @@ -344,6 +351,9 @@ VdpStatus vdp_output_surface_render_bitmap_surface( src_width, src_height, dst_x0, dst_y0, dst_width, dst_height); + + pthread_mutex_unlock(&dst_surf->dev->lock); + put_surface(dst_surf); put_surface(src_surf); return VDP_STATUS_OK; diff --git a/src/surface_shared.c b/src/surface_shared.c index 7ce621f..c63487f 100644 --- a/src/surface_shared.c +++ b/src/surface_shared.c @@ -234,6 +234,8 @@ int shared_surface_transfer_video(tegra_surface *disp) assert(disp->flags & SURFACE_OUTPUT); + pthread_mutex_lock(&disp->dev->lock); + if (disp->set_bg) { host1x_gr2d_clear_rect_clipped(disp->dev->stream, disp->pixbuf, @@ -261,6 +263,9 @@ int shared_surface_transfer_video(tegra_surface *disp) shared->dst_y0, shared->dst_width, shared->dst_height); + + pthread_mutex_unlock(&disp->dev->lock); + unshare: pthread_mutex_lock(&shared_lock); shared_surface_break_link_locked(shared); diff --git a/src/vdpau_tegra.c b/src/vdpau_tegra.c index 762f78f..5fa11b4 100644 --- a/src/vdpau_tegra.c +++ b/src/vdpau_tegra.c @@ -650,7 +650,9 @@ xv_detected: goto err_cleanup; } + pthread_mutex_init(&tegra_devices[i]->lock, NULL); atomic_set(&tegra_devices[i]->refcnt, 1); + tegra_devices[i]->xv_port = adaptor_info[num_adaptors].base_id; tegra_devices[i]->display = display; tegra_devices[i]->screen = screen; diff --git a/src/vdpau_tegra.h b/src/vdpau_tegra.h index 114f513..90e41d7 100644 --- a/src/vdpau_tegra.h +++ b/src/vdpau_tegra.h @@ -107,6 +107,8 @@ #define UNIFIED_BUFFER 0 +#define DRI_OUTPUT 0 + extern VdpCSCMatrix CSC_BT_601; extern VdpCSCMatrix CSC_BT_709; @@ -120,6 +122,7 @@ typedef struct tegra_device { struct drm_tegra *drm; struct drm_tegra_channel *gr2d; struct tegra_stream *stream; + pthread_mutex_t lock; Display *display; XvPortID xv_port; atomic_t refcnt; @@ -207,6 +210,7 @@ typedef struct tegra_mixer { typedef struct tegra_pqt { tegra_device *dev; tegra_surface *disp_surf; + struct host1x_pixelbuffer *dri_pixbuf; Drawable drawable; GC gc; atomic_t refcnt; @@ -272,6 +276,7 @@ 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); tegra_pq * __get_presentation_queue(VdpPresentationQueue presentation_queue); tegra_pq * get_presentation_queue(VdpPresentationQueue presentation_queue); |