st/vdpau: add device reference counting
authorChristian König <christian.koenig@amd.com>
Wed, 13 Aug 2014 13:49:18 +0000 (15:49 +0200)
committerChristian König <christian.koenig@amd.com>
Thu, 14 Aug 2014 09:57:07 +0000 (11:57 +0200)
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>
src/gallium/state_trackers/vdpau/bitmap.c
src/gallium/state_trackers/vdpau/decode.c
src/gallium/state_trackers/vdpau/device.c
src/gallium/state_trackers/vdpau/mixer.c
src/gallium/state_trackers/vdpau/output.c
src/gallium/state_trackers/vdpau/presentation.c
src/gallium/state_trackers/vdpau/surface.c
src/gallium/state_trackers/vdpau/vdpau_private.h

index a06892132e908dc2d318790626dc760dd6fd9cbd..97a428727a5c2c67ac333df5a3068b0cf22972c3 100644 (file)
@@ -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;
index 1e5f81e22e7f7cc75c8b34fd551a9127ec3e374a..767d311412552675a4d1c8b99cfb77e60ec8e3b2 100644 (file)
@@ -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;
index 0cdda73f1c074b94963cf4ad03fb28ac7c70bdf4..9c5ec60da4a915d0ac0ef5bfcb226ca0e351d31e 100644 (file)
@@ -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;
 }
 
 /**
index e6bfb8cbc43120803e8772e53fed81f38ea321e0..a724aa5b254ba88e44a3bf1cbd5e4bda1c4d93cc 100644 (file)
@@ -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);
 
index 457f678a5c74a354acaa51820f59ced0cd4b77bc..caae50f37a234f715b1c633d1b10ff319859f153 100644 (file)
@@ -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;
index cb6cb3840c41f9ca65f1b71fd97dae2a69010346..7f8dbed7ee2270feba3eaec08a75417345bbdb08 100644 (file)
@@ -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;
index 0d9f2b0c52ca715a7b2373532522b91ab3c5cae9..1932cdd1066dead42b25df628ffb9c37602755a8 100644 (file)
@@ -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;
index ce6852b586a9bcfee3e1d9d0f017c6f4ee6ed0ad..65f8e47b1bd91aa41c05ced28e87574317137b5d 100644 (file)
@@ -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 */