summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Franzke <benjaminfranzke@googlemail.com>2011-07-29 16:14:11 +0200
committerBenjamin Franzke <benjaminfranzke@googlemail.com>2011-07-29 16:14:11 +0200
commitd4df86a509efd304c98c3aa8f17932609e80d9f1 (patch)
treeff55debf98f2d14724c51c34186c33bbb43ee24a
parentd0c8ab5402981e577696e006f8efc01c8fa05942 (diff)
add va-attach example
-rw-r--r--va-attach.c281
1 files changed, 281 insertions, 0 deletions
diff --git a/va-attach.c b/va-attach.c
new file mode 100644
index 0000000..93ed884
--- /dev/null
+++ b/va-attach.c
@@ -0,0 +1,281 @@
+/*
+ * Copyright © 2011 Benjamin Franzke
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * compile using:
+ * gcc -o va-attach va-attach.c -I /path/to/libva/test \
+ * `pkg-config --libs --cflags wayland-{client,egl} libva{,-wayland}`
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include <math.h>
+#include <assert.h>
+
+#include <wayland-client.h>
+#include <wayland-egl.h>
+
+#include <va/va.h>
+#include <va/va_wayland.h>
+
+#define CHECK_VASTATUS(va_status,func) \
+if (va_status != VA_STATUS_SUCCESS) { \
+ fprintf(stderr,"%s:%s (%d) failed,exit\n", __func__, func, __LINE__); \
+ exit(1); \
+}
+#include "loadsurface.h"
+
+struct display {
+ struct wl_display *display;
+ struct wl_visual *premultiplied_argb_visual;
+ struct wl_visual *yv12_visual;
+ struct wl_compositor *compositor;
+ struct wl_shell *shell;
+ struct {
+ VADisplay dpy;
+ } va;
+ uint32_t mask;
+};
+
+struct window {
+ struct display *display;
+ struct {
+ int width, height;
+ } geometry;
+ struct {
+#define SURFACE_NUM 16
+ VASurfaceID surface_id[SURFACE_NUM];
+ int width, height;
+ int index;
+ } va;
+
+ struct wl_egl_window *native;
+ struct wl_surface *surface;
+};
+
+static int
+init_va(struct display *display)
+{
+ int major, minor;
+
+ display->va.dpy = vaGetDisplay(display->display);
+ assert(display->va.dpy);
+
+ vaInitialize(display->va.dpy, &major, &minor);
+}
+
+static void
+sync_callback(void *data)
+{
+ int *done = data;
+
+ *done = 1;
+}
+
+static void
+create_surface(struct window *window)
+{
+ struct display *display = window->display;
+ struct wl_visual *visual;
+ int done = 0;
+
+ if (!display->premultiplied_argb_visual) {
+ wl_display_sync_callback(display->display, sync_callback, &done);
+ while (!done)
+ wl_display_iterate(display->display, display->mask);
+ if (!display->premultiplied_argb_visual) {
+ fprintf(stderr, "premultiplied argb visual missing\n");
+ exit(1);
+ }
+ }
+
+ window->surface = wl_compositor_create_surface(display->compositor);
+ visual = display->premultiplied_argb_visual;
+ window->native =
+ wl_egl_window_create(window->surface,
+ window->geometry.width,
+ window->geometry.height,
+ visual);
+
+ wl_shell_set_toplevel(display->shell, window->surface);
+}
+
+
+static VASurfaceID
+get_next_free_surface(struct window *window)
+{
+ struct display *display = window->display;
+ int i;
+
+ i = window->va.index;
+ i++;
+ if (i == SURFACE_NUM)
+ i = 0;
+ window->va.index = i;
+
+ return window->va.surface_id[i];
+}
+
+static void
+redraw_va_surf(struct window *window, uint32_t time)
+{
+ struct display *display = window->display;
+ int width = window->geometry.width;
+ int height = window->geometry.height;
+ VAStatus vaStatus;
+ VASurfaceID surface_id = VA_INVALID_SURFACE;
+
+ while (surface_id == VA_INVALID_SURFACE)
+ surface_id = get_next_free_surface(window);
+
+ vaStatus = vaAttachSurface(display->va.dpy, surface_id, window->native,
+ display->yv12_visual);
+ CHECK_VASTATUS(vaStatus, "vaAttachSurface");
+ usleep(30000);
+}
+
+static void
+redraw(struct wl_surface *surface, void *data, uint32_t time)
+{
+ struct window *window = data;
+
+ redraw_va_surf(window, time);
+
+ wl_display_frame_callback(window->display->display,
+ window->surface,
+ redraw, window);
+}
+
+static void
+compositor_handle_visual(void *data,
+ struct wl_compositor *compositor,
+ uint32_t id, uint32_t token)
+{
+ struct display *d = data;
+
+ switch (token) {
+ case WL_COMPOSITOR_VISUAL_PREMULTIPLIED_ARGB32:
+ d->premultiplied_argb_visual =
+ wl_visual_create(d->display, id, 1);
+ break;
+ case WL_COMPOSITOR_VISUAL_YV12:
+ d->yv12_visual = wl_visual_create(d->display, id, 1);
+ break;
+ }
+}
+
+static const struct wl_compositor_listener compositor_listener = {
+ compositor_handle_visual,
+};
+
+static void
+display_handle_global(struct wl_display *display, uint32_t id,
+ const char *interface, uint32_t version, void *data)
+{
+ struct display *d = data;
+
+ if (strcmp(interface, "wl_compositor") == 0) {
+ d->compositor = wl_compositor_create(display, id, 1);
+ wl_compositor_add_listener(d->compositor,
+ &compositor_listener, d);
+ } else if (strcmp(interface, "wl_shell") == 0) {
+ d->shell = wl_shell_create(display, id, 1);
+ }
+}
+
+static int
+event_mask_update(uint32_t mask, void *data)
+{
+ struct display *d = data;
+
+ d->mask = mask;
+
+ return 0;
+}
+
+static void
+upload_source_YUV_once_for_all(struct window *window)
+{
+ int box_width_loc = 8, row_shift_loc = 0;
+ int i;
+
+ for (i = 0; i < SURFACE_NUM; i++) {
+ upload_surface(window->display->va.dpy,
+ window->va.surface_id[i],
+ box_width_loc, row_shift_loc, 0);
+
+ row_shift_loc++;
+ if (row_shift_loc == (2*box_width_loc))
+ row_shift_loc= 0;
+ }
+}
+
+static int
+create_va_surfaces(struct window *window)
+{
+ struct display *d = window->display;
+ VAStatus status;
+
+ window->va.width = 352;
+ window->va.height = 288;
+ status = vaCreateSurfaces(d->va.dpy,
+ window->va.width, window->va.height,
+ VA_RT_FORMAT_YUV420,
+ SURFACE_NUM, window->va.surface_id);
+ upload_source_YUV_once_for_all(window);
+}
+
+int
+main(int argc, char **argv)
+{
+ struct display display = { 0 };
+ struct window window = { 0 };
+
+ memset(&display, 0, sizeof display);
+ memset(&window, 0, sizeof window);
+
+ window.display = &display;
+ window.geometry.width = 250;
+ window.geometry.height = 250;
+
+ display.display = wl_display_connect(NULL);
+ assert(display.display);
+
+ wl_display_add_global_listener(display.display,
+ display_handle_global, &display);
+
+ wl_display_get_fd(display.display, event_mask_update, &display);
+
+ init_va(&display);
+
+ create_surface(&window);
+ create_va_surfaces(&window);
+
+ redraw(window.surface, &window, 1);
+
+ while (true)
+ wl_display_iterate(display.display, display.mask);
+
+ return 0;
+}