summaryrefslogtreecommitdiffstats
path: root/src/gallium/state_trackers
diff options
context:
space:
mode:
authorThomas Hellstrom <[email protected]>2016-04-01 07:31:18 +0200
committerThomas Hellstrom <[email protected]>2017-02-22 10:20:37 +0100
commitf1e5dfbe3c8951a6c8acf41bf5e6c2d090098b2c (patch)
tree6347bce9a02612bac53764312b886b49e6956a1d /src/gallium/state_trackers
parentbcc9fd378d07bb635ef9386e1542cbeaf7312461 (diff)
st/vdpau: Fix multithreading
The vdpau state tracker allows multiple threads access to the same gallium context simultaneously. We can fix this either by locking the same mutex each time the context is used or by using a different gallium context for each mutex domain. Here we do the latter, although I'm not sure that's really the best option. Signed-off-by: Thomas Hellstrom <[email protected]> Acked-by: Sinclair Yeh <[email protected]> Reviewed-by: Christian König <[email protected]>
Diffstat (limited to 'src/gallium/state_trackers')
-rw-r--r--src/gallium/state_trackers/vdpau/decode.c22
1 files changed, 21 insertions, 1 deletions
diff --git a/src/gallium/state_trackers/vdpau/decode.c b/src/gallium/state_trackers/vdpau/decode.c
index f85bce823bb..2a07d17ba10 100644
--- a/src/gallium/state_trackers/vdpau/decode.c
+++ b/src/gallium/state_trackers/vdpau/decode.c
@@ -68,7 +68,6 @@ vlVdpDecoderCreate(VdpDevice device,
if (!dev)
return VDP_STATUS_INVALID_HANDLE;
- pipe = dev->context;
screen = dev->vscreen->pscreen;
pipe_mutex_lock(dev->mutex);
@@ -123,6 +122,12 @@ vlVdpDecoderCreate(VdpDevice device,
templat.level = u_get_h264_level(templat.width, templat.height,
&templat.max_references);
+ pipe = screen->context_create(screen, dev->vscreen, 0);
+ if (!pipe) {
+ ret = VDP_STATUS_RESOURCES;
+ goto error_context;
+ }
+
vldecoder->decoder = pipe->create_video_codec(pipe, &templat);
if (!vldecoder->decoder) {
@@ -145,6 +150,8 @@ error_handle:
vldecoder->decoder->destroy(vldecoder->decoder);
error_decoder:
+ pipe->destroy(pipe);
+error_context:
pipe_mutex_unlock(dev->mutex);
DeviceReference(&vldecoder->device, NULL);
FREE(vldecoder);
@@ -158,15 +165,18 @@ VdpStatus
vlVdpDecoderDestroy(VdpDecoder decoder)
{
vlVdpDecoder *vldecoder;
+ struct pipe_context *pipe;
vldecoder = (vlVdpDecoder *)vlGetDataHTAB(decoder);
if (!vldecoder)
return VDP_STATUS_INVALID_HANDLE;
+ pipe = vldecoder->decoder->context;
pipe_mutex_lock(vldecoder->mutex);
vldecoder->decoder->destroy(vldecoder->decoder);
pipe_mutex_unlock(vldecoder->mutex);
pipe_mutex_destroy(vldecoder->mutex);
+ pipe->destroy(pipe);
vlRemoveDataHTAB(decoder);
DeviceReference(&vldecoder->device, NULL);
@@ -674,10 +684,20 @@ vlVdpDecoderRender(VdpDecoder decoder,
if (ret != VDP_STATUS_OK)
return ret;
+ /*
+ * Since we use separate contexts for the two mutex domains, we need
+ * to flush to make sure rendering operations happen in order.
+ * In particular, so that a frame is rendered before it is presented.
+ */
+ pipe_mutex_lock(vldecoder->device->mutex);
+ vldecoder->device->context->flush(vldecoder->device->context, NULL, 0);
+ pipe_mutex_unlock(vldecoder->device->mutex);
+
pipe_mutex_lock(vldecoder->mutex);
dec->begin_frame(dec, vlsurf->video_buffer, &desc.base);
dec->decode_bitstream(dec, vlsurf->video_buffer, &desc.base, bitstream_buffer_count, buffers, sizes);
dec->end_frame(dec, vlsurf->video_buffer, &desc.base);
+ dec->flush(dec);
pipe_mutex_unlock(vldecoder->mutex);
return ret;
}