Update compositor shutdown code

Adds a general wlsc_compositor_shutdown() function that all output
backends call when shutting down.  wlsc_compositor_shutdown() will call
a new 'destroy' method of each output to perform backend-specific
cleanup (e.g., turning off the hardware cursor in the DRM compositor).

Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
diff --git a/compositor/compositor-drm.c b/compositor/compositor-drm.c
index c28c7d2..b5fa28d 100644
--- a/compositor/compositor-drm.c
+++ b/compositor/compositor-drm.c
@@ -59,6 +59,7 @@
 
 	uint32_t crtc_id;
 	uint32_t connector_id;
+	drmModeCrtcPtr original_crtc;
 	GLuint rbo[2];
 	uint32_t fb_id[2];
 	EGLImageKHR image[2];
@@ -255,6 +256,33 @@
 	return ret;
 }
 
+static void
+drm_output_destroy(struct wlsc_output *output_base)
+{
+	struct drm_output *output = (struct drm_output *) output_base;
+	struct drm_compositor *c =
+		(struct drm_compositor *) output_base->compositor;
+	drmModeCrtcPtr origcrtc = output->original_crtc;
+	int i;
+
+	/* Turn off hardware cursor */
+	drm_output_set_cursor(output_base, NULL);
+
+	/* Restore original CRTC state */
+	drmModeSetCrtc(c->drm.fd, origcrtc->crtc_id, origcrtc->buffer_id,
+		origcrtc->x, origcrtc->y, &output->connector_id, 1, &origcrtc->mode);
+	drmModeFreeCrtc(origcrtc);
+
+	/* Destroy output buffers */
+	for (i = 0; i < 2; i++) {
+		drmModeRmFB(c->drm.fd, output->fb_id[i]);
+		c->base.destroy_image(c->base.display, output->image[i]);
+		gbm_bo_destroy(output->bo[i]);
+	}
+
+	free(output);
+}
+
 static int
 on_drm_input(int fd, uint32_t mask, void *data)
 {
@@ -422,6 +450,8 @@
 	output->connector_id = connector->connector_id;
 	ec->connector_allocator |= (1 << output->connector_id);
 
+	output->original_crtc = drmModeGetCrtc(ec->drm.fd, output->crtc_id);
+
 	for (i = 0; i < connector->count_modes; i++)
 		drm_output_add_mode(output, &connector->modes[i]);
 	if (connector->count_modes == 0)
@@ -491,6 +521,7 @@
 	output->base.prepare_scanout_surface =
 		drm_output_prepare_scanout_surface;
 	output->base.set_hardware_cursor = drm_output_set_cursor;
+	output->base.destroy = drm_output_destroy;
 
 	return 0;
 }
@@ -724,6 +755,8 @@
 {
 	struct drm_compositor *d = (struct drm_compositor *) ec;
 
+	wlsc_compositor_shutdown(ec);
+	gbm_device_destroy(d->gbm);
 	tty_destroy(d->tty);
 
 	free(d);
diff --git a/compositor/compositor-openwfd.c b/compositor/compositor-openwfd.c
index 672e723..d4436e3 100644
--- a/compositor/compositor-openwfd.c
+++ b/compositor/compositor-openwfd.c
@@ -187,6 +187,14 @@
 	return -1;
 }
 
+static void
+wfd_output_destroy(struct wlsc_output *output_base)
+{
+	destroy_output(output_base);
+
+	return;
+}
+
 static int
 wfd_output_add_mode(struct wfd_output *output, WFDPortMode mode)
 {
@@ -374,6 +382,7 @@
 	output->base.prepare_scanout_surface =
 		wfd_output_prepare_scanout_surface;
 	output->base.set_hardware_cursor = wfd_output_set_cursor;
+	output->base.destroy = wfd_output_destroy;
 
 	wl_list_insert(ec->base.output_list.prev, &output->base.link);
 
@@ -572,6 +581,8 @@
 {
 	struct wfd_compositor *d = (struct wfd_compositor *) ec;
 
+	wlsc_compositor_shutdown(ec);
+
 	udev_unref(d->udev);
 
 	wfdDestroyDevice(d->dev);
diff --git a/compositor/compositor-wayland.c b/compositor/compositor-wayland.c
index f547c62..df63daf 100644
--- a/compositor/compositor-wayland.c
+++ b/compositor/compositor-wayland.c
@@ -212,6 +212,19 @@
 	return -1;
 }
 
+static void
+wayland_output_destroy(struct wlsc_output *output_base)
+{
+	struct wayland_output *output = (struct wayland_output *) output_base;
+	struct wlsc_compositor *ec = output->base.compositor;
+
+	eglDestroySurface(ec->display, output->egl_surface);
+	wl_egl_window_destroy(output->parent.egl_window);
+	free(output);
+
+	return;
+}
+
 static int
 wayland_compositor_create_output(struct wayland_compositor *c,
 				 int width, int height)
@@ -271,6 +284,7 @@
 	output->base.prepare_scanout_surface =
 		wayland_output_prepare_scanout_surface;
 	output->base.set_hardware_cursor = wayland_output_set_cursor;
+	output->base.destroy = wayland_output_destroy;
 
 	wl_list_insert(c->base.output_list.prev, &output->base.link);
 
@@ -510,6 +524,8 @@
 static void
 wayland_destroy(struct wlsc_compositor *ec)
 {
+	wlsc_compositor_shutdown(ec);
+
 	free(ec);
 }
 
diff --git a/compositor/compositor-x11.c b/compositor/compositor-x11.c
index 0825f1a..f959e78 100644
--- a/compositor/compositor-x11.c
+++ b/compositor/compositor-x11.c
@@ -209,6 +209,11 @@
 	return -1;
 }
 
+static void
+x11_output_destroy(struct wlsc_output *output_base)
+{
+	return;
+}
 
 static void
 x11_output_set_wm_protocols(struct x11_output *output)
@@ -408,6 +413,7 @@
 	output->base.prepare_scanout_surface =
 		x11_output_prepare_scanout_surface;
 	output->base.set_hardware_cursor = x11_output_set_cursor;
+	output->base.destroy = x11_output_destroy;
 
 	wl_list_insert(c->base.output_list.prev, &output->base.link);
 
@@ -679,6 +685,8 @@
 static void
 x11_destroy(struct wlsc_compositor *ec)
 {
+	wlsc_compositor_shutdown(ec);
+
 	free(ec);
 }
 
diff --git a/compositor/compositor.c b/compositor/compositor.c
index b2342b4..bf31220 100644
--- a/compositor/compositor.c
+++ b/compositor/compositor.c
@@ -1956,6 +1956,16 @@
 	return 0;
 }
 
+WL_EXPORT int
+wlsc_compositor_shutdown(struct wlsc_compositor *ec)
+{
+	struct wlsc_output *output;
+
+	/* Destroy all outputs associated with this compositor */
+	wl_list_for_each(output, &ec->output_list, link)
+		output->destroy(output);
+}
+
 static int on_term_signal(int signal_number, void *data)
 {
 	struct wl_display *display = data;
diff --git a/compositor/compositor.h b/compositor/compositor.h
index ea6e9e7..db23c43 100644
--- a/compositor/compositor.h
+++ b/compositor/compositor.h
@@ -87,6 +87,7 @@
 				       struct wlsc_surface *es);
 	int (*set_hardware_cursor)(struct wlsc_output *output,
 				   struct wlsc_input_device *input);
+	void (*destroy)(struct wlsc_output *output);
 };
 
 enum wlsc_pointer_type {
@@ -350,6 +351,8 @@
 
 int
 wlsc_compositor_init(struct wlsc_compositor *ec, struct wl_display *display);
+int
+wlsc_compositor_shutdown(struct wlsc_compositor *ec);
 void
 wlsc_output_move(struct wlsc_output *output, int x, int y);
 void