[Mesa-dev] [PATCH] st/vdpau: add device reference counting

Christian König deathsimple at vodafone.de
Wed Aug 13 08:07:03 PDT 2014


From: Christian König <christian.koenig at amd.com>

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 at amd.com>
---
 src/gallium/state_trackers/vdpau/bitmap.c        |  4 +++-
 src/gallium/state_trackers/vdpau/decode.c        |  4 +++-
 src/gallium/state_trackers/vdpau/device.c        | 21 ++++++++++++++++-----
 src/gallium/state_trackers/vdpau/mixer.c         |  4 +++-
 src/gallium/state_trackers/vdpau/output.c        |  4 +++-
 src/gallium/state_trackers/vdpau/presentation.c  |  4 +++-
 src/gallium/state_trackers/vdpau/surface.c       |  4 +++-
 src/gallium/state_trackers/vdpau/vdpau_private.h | 12 ++++++++++++
 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 a068921..97a4287 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 1e5f81e..767d311 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 0cdda73..9c5ec60 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 e6bfb8c..a724aa5 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 457f678..caae50f 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 cb6cb38..7f8dbed 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 0d9f2b0..1932cdd 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 ce6852b..65f8e47 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 */
-- 
1.9.1



More information about the mesa-dev mailing list