summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian König <christian.koenig@amd.com>2014-08-13 15:49:18 +0200
committerChristian König <christian.koenig@amd.com>2014-08-14 11:57:07 +0200
commit6fb42ee7a632e181160ac4be234b30e50a1b91d5 (patch)
tree962b6f4da56cdc0d8791f65177a4ce111dc0a966
parentc1df492d03862f75698ba5d50d4f46cd528ffc0d (diff)
st/vdpau: add device reference counting
This fixes an issue with flash where it tries to destroy a decoder after already destroying the device associated with the decoder. Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=82517 Signed-off-by: Christian König <christian.koenig@amd.com> Acked-by: Ilia Mirkin <imirkin@alum.mit.edu>
-rw-r--r--src/gallium/state_trackers/vdpau/bitmap.c4
-rw-r--r--src/gallium/state_trackers/vdpau/decode.c4
-rw-r--r--src/gallium/state_trackers/vdpau/device.c21
-rw-r--r--src/gallium/state_trackers/vdpau/mixer.c4
-rw-r--r--src/gallium/state_trackers/vdpau/output.c4
-rw-r--r--src/gallium/state_trackers/vdpau/presentation.c4
-rw-r--r--src/gallium/state_trackers/vdpau/surface.c4
-rw-r--r--src/gallium/state_trackers/vdpau/vdpau_private.h12
8 files changed, 46 insertions, 11 deletions
diff --git a/src/gallium/state_trackers/vdpau/bitmap.c b/src/gallium/state_trackers/vdpau/bitmap.c
index a06892132e9..97a428727a5 100644
--- a/src/gallium/state_trackers/vdpau/bitmap.c
+++ b/src/gallium/state_trackers/vdpau/bitmap.c
@@ -67,7 +67,7 @@ vlVdpBitmapSurfaceCreate(VdpDevice device,
if (!vlsurface)
return VDP_STATUS_RESOURCES;
- vlsurface->device = dev;
+ DeviceReference(&vlsurface->device, dev);
memset(&res_tmpl, 0, sizeof(res_tmpl));
res_tmpl.target = PIPE_TEXTURE_2D;
@@ -117,6 +117,7 @@ err_sampler:
pipe_sampler_view_reference(&vlsurface->sampler_view, NULL);
err_unlock:
pipe_mutex_unlock(dev->mutex);
+ DeviceReference(&vlsurface->device, NULL);
FREE(vlsurface);
return ret;
}
@@ -138,6 +139,7 @@ vlVdpBitmapSurfaceDestroy(VdpBitmapSurface surface)
pipe_mutex_unlock(vlsurface->device->mutex);
vlRemoveDataHTAB(surface);
+ DeviceReference(&vlsurface->device, NULL);
FREE(vlsurface);
return VDP_STATUS_OK;
diff --git a/src/gallium/state_trackers/vdpau/decode.c b/src/gallium/state_trackers/vdpau/decode.c
index 1e5f81e22e7..767d3114125 100644
--- a/src/gallium/state_trackers/vdpau/decode.c
+++ b/src/gallium/state_trackers/vdpau/decode.c
@@ -110,7 +110,7 @@ vlVdpDecoderCreate(VdpDevice device,
return VDP_STATUS_RESOURCES;
}
- vldecoder->device = dev;
+ DeviceReference(&vldecoder->device, dev);
templat.entrypoint = PIPE_VIDEO_ENTRYPOINT_BITSTREAM;
templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420;
@@ -141,6 +141,7 @@ error_handle:
error_decoder:
pipe_mutex_unlock(dev->mutex);
+ DeviceReference(&vldecoder->device, NULL);
FREE(vldecoder);
return ret;
}
@@ -163,6 +164,7 @@ vlVdpDecoderDestroy(VdpDecoder decoder)
pipe_mutex_destroy(vldecoder->mutex);
vlRemoveDataHTAB(decoder);
+ DeviceReference(&vldecoder->device, NULL);
FREE(vldecoder);
return VDP_STATUS_OK;
diff --git a/src/gallium/state_trackers/vdpau/device.c b/src/gallium/state_trackers/vdpau/device.c
index 0cdda73f1c0..9c5ec60da4a 100644
--- a/src/gallium/state_trackers/vdpau/device.c
+++ b/src/gallium/state_trackers/vdpau/device.c
@@ -59,6 +59,8 @@ vdp_imp_device_create_x11(Display *display, int screen, VdpDevice *device,
goto no_dev;
}
+ pipe_reference_init(&dev->reference, 1);
+
dev->vscreen = vl_screen_create(display, screen);
if (!dev->vscreen) {
ret = VDP_STATUS_RESOURCES;
@@ -124,7 +126,7 @@ vlVdpPresentationQueueTargetCreateX11(VdpDevice device, Drawable drawable,
if (!pqt)
return VDP_STATUS_RESOURCES;
- pqt->device = dev;
+ DeviceReference(&pqt->device, dev);
pqt->drawable = drawable;
*target = vlAddDataHTAB(pqt);
@@ -153,6 +155,7 @@ vlVdpPresentationQueueTargetDestroy(VdpPresentationQueueTarget presentation_queu
return VDP_STATUS_INVALID_HANDLE;
vlRemoveDataHTAB(presentation_queue_target);
+ DeviceReference(&pqt->device, NULL);
FREE(pqt);
return VDP_STATUS_OK;
@@ -168,16 +171,24 @@ vlVdpDeviceDestroy(VdpDevice device)
if (!dev)
return VDP_STATUS_INVALID_HANDLE;
+ vlRemoveDataHTAB(device);
+ DeviceReference(&dev, NULL);
+
+ return VDP_STATUS_OK;
+}
+
+/**
+ * Free a VdpDevice.
+ */
+void
+vlVdpDeviceFree(vlVdpDevice *dev)
+{
pipe_mutex_destroy(dev->mutex);
vl_compositor_cleanup(&dev->compositor);
dev->context->destroy(dev->context);
vl_screen_destroy(dev->vscreen);
-
- vlRemoveDataHTAB(device);
FREE(dev);
vlDestroyHTAB();
-
- return VDP_STATUS_OK;
}
/**
diff --git a/src/gallium/state_trackers/vdpau/mixer.c b/src/gallium/state_trackers/vdpau/mixer.c
index e6bfb8cbc43..a724aa5b254 100644
--- a/src/gallium/state_trackers/vdpau/mixer.c
+++ b/src/gallium/state_trackers/vdpau/mixer.c
@@ -60,7 +60,7 @@ vlVdpVideoMixerCreate(VdpDevice device,
if (!vmixer)
return VDP_STATUS_RESOURCES;
- vmixer->device = dev;
+ DeviceReference(&vmixer->device, dev);
pipe_mutex_lock(dev->mutex);
@@ -160,6 +160,7 @@ no_params:
no_handle:
vl_compositor_cleanup_state(&vmixer->cstate);
pipe_mutex_unlock(dev->mutex);
+ DeviceReference(&vmixer->device, NULL);
FREE(vmixer);
return ret;
}
@@ -199,6 +200,7 @@ vlVdpVideoMixerDestroy(VdpVideoMixer mixer)
FREE(vmixer->sharpness.filter);
}
pipe_mutex_unlock(vmixer->device->mutex);
+ DeviceReference(&vmixer->device, NULL);
FREE(vmixer);
diff --git a/src/gallium/state_trackers/vdpau/output.c b/src/gallium/state_trackers/vdpau/output.c
index 457f678a5c7..caae50f37a2 100644
--- a/src/gallium/state_trackers/vdpau/output.c
+++ b/src/gallium/state_trackers/vdpau/output.c
@@ -69,7 +69,7 @@ vlVdpOutputSurfaceCreate(VdpDevice device,
if (!vlsurface)
return VDP_STATUS_RESOURCES;
- vlsurface->device = dev;
+ DeviceReference(&vlsurface->device, dev);
memset(&res_tmpl, 0, sizeof(res_tmpl));
@@ -120,6 +120,7 @@ err_resource:
pipe_resource_reference(&res, NULL);
err_unlock:
pipe_mutex_unlock(dev->mutex);
+ DeviceReference(&vlsurface->device, NULL);
FREE(vlsurface);
return VDP_STATUS_ERROR;
}
@@ -149,6 +150,7 @@ vlVdpOutputSurfaceDestroy(VdpOutputSurface surface)
pipe_mutex_unlock(vlsurface->device->mutex);
vlRemoveDataHTAB(surface);
+ DeviceReference(&vlsurface->device, NULL);
FREE(vlsurface);
return VDP_STATUS_OK;
diff --git a/src/gallium/state_trackers/vdpau/presentation.c b/src/gallium/state_trackers/vdpau/presentation.c
index cb6cb3840c4..7f8dbed7ee2 100644
--- a/src/gallium/state_trackers/vdpau/presentation.c
+++ b/src/gallium/state_trackers/vdpau/presentation.c
@@ -62,7 +62,7 @@ vlVdpPresentationQueueCreate(VdpDevice device,
if (!pq)
return VDP_STATUS_RESOURCES;
- pq->device = dev;
+ DeviceReference(&pq->device, dev);
pq->drawable = pqt->drawable;
pipe_mutex_lock(dev->mutex);
@@ -83,6 +83,7 @@ vlVdpPresentationQueueCreate(VdpDevice device,
no_handle:
no_compositor:
+ DeviceReference(&pq->device, NULL);
FREE(pq);
return ret;
}
@@ -104,6 +105,7 @@ vlVdpPresentationQueueDestroy(VdpPresentationQueue presentation_queue)
pipe_mutex_unlock(pq->device->mutex);
vlRemoveDataHTAB(presentation_queue);
+ DeviceReference(&pq->device, NULL);
FREE(pq);
return VDP_STATUS_OK;
diff --git a/src/gallium/state_trackers/vdpau/surface.c b/src/gallium/state_trackers/vdpau/surface.c
index 0d9f2b0c52c..1932cdd1066 100644
--- a/src/gallium/state_trackers/vdpau/surface.c
+++ b/src/gallium/state_trackers/vdpau/surface.c
@@ -74,7 +74,7 @@ vlVdpVideoSurfaceCreate(VdpDevice device, VdpChromaType chroma_type,
goto inv_device;
}
- p_surf->device = dev;
+ DeviceReference(&p_surf->device, dev);
pipe = dev->context;
pipe_mutex_lock(dev->mutex);
@@ -115,6 +115,7 @@ no_handle:
p_surf->video_buffer->destroy(p_surf->video_buffer);
inv_device:
+ DeviceReference(&p_surf->device, NULL);
FREE(p_surf);
no_res:
@@ -140,6 +141,7 @@ vlVdpVideoSurfaceDestroy(VdpVideoSurface surface)
pipe_mutex_unlock(p_surf->device->mutex);
vlRemoveDataHTAB(surface);
+ DeviceReference(&p_surf->device, NULL);
FREE(p_surf);
return VDP_STATUS_OK;
diff --git a/src/gallium/state_trackers/vdpau/vdpau_private.h b/src/gallium/state_trackers/vdpau/vdpau_private.h
index ce6852b586a..65f8e47b1bd 100644
--- a/src/gallium/state_trackers/vdpau/vdpau_private.h
+++ b/src/gallium/state_trackers/vdpau/vdpau_private.h
@@ -344,6 +344,7 @@ CheckSurfaceParams(struct pipe_screen *screen,
typedef struct
{
+ struct pipe_reference reference;
struct vl_screen *vscreen;
struct pipe_context *context;
struct vl_compositor compositor;
@@ -453,6 +454,7 @@ void vlVdpSave4DelayedRendering(vlVdpDevice *dev, VdpOutputSurface surface, stru
/* Internal function pointers */
VdpGetErrorString vlVdpGetErrorString;
VdpDeviceDestroy vlVdpDeviceDestroy;
+void vlVdpDeviceFree(vlVdpDevice *dev);
VdpGetProcAddress vlVdpGetProcAddress;
VdpGetApiVersion vlVdpGetApiVersion;
VdpGetInformationString vlVdpGetInformationString;
@@ -542,4 +544,14 @@ static inline void VDPAU_MSG(unsigned int level, const char *fmt, ...)
}
}
+static inline void
+DeviceReference(vlVdpDevice **ptr, vlVdpDevice *dev)
+{
+ vlVdpDevice *old_dev = *ptr;
+
+ if (pipe_reference(&(*ptr)->reference, &dev->reference))
+ vlVdpDeviceFree(old_dev);
+ *ptr = dev;
+}
+
#endif /* VDPAU_PRIVATE_H */