summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDmitry Osipenko <digetx@gmail.com>2017-12-30 18:52:46 +0300
committerDmitry Osipenko <digetx@gmail.com>2017-12-30 21:32:56 +0300
commitf14c13f922f8d9a93ff1ab524e856d2ff0e3c3c6 (patch)
tree39e00b8339bf25e44c449d0eddbfa7dbd2578164 /src
parentaec3f29353b98c07f813a6ea4c64e1a3e02c9d3d (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.c19
-rw-r--r--src/host1x-pixelbuffer.c37
-rw-r--r--src/host1x.h9
-rw-r--r--src/presentation_queue.c255
-rw-r--r--src/presentation_queue_target.c75
-rw-r--r--src/surface.c2
-rw-r--r--src/surface_mixer.c21
-rw-r--r--src/surface_output.c10
-rw-r--r--src/surface_shared.c5
-rw-r--r--src/vdpau_tegra.c2
-rw-r--r--src/vdpau_tegra.h5
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);