YaGL/VIGS: QOM'ify 97/23297/2
authorStanislav Vorobiov <s.vorobiov@samsung.com>
Mon, 23 Jun 2014 07:47:32 +0000 (11:47 +0400)
committerStanislav Vorobiov <s.vorobiov@samsung.com>
Mon, 23 Jun 2014 09:39:43 +0000 (13:39 +0400)
YaGL and VIGS devices can now be created
entirely from QEMU command line, it's also possible
to tweak all their parameters via QEMU command line
and even have 2 or more separate instances

Change-Id: Ic1ae18f9ac6078f872d28519443e17974abefe82
Signed-off-by: Stanislav Vorobiov <s.vorobiov@samsung.com>
hw/vigs/Makefile.objs
hw/vigs/display.c [new file with mode: 0644]
hw/vigs/display.h [new file with mode: 0644]
hw/vigs/vigs_device.c
hw/vigs/vigs_device.h [deleted file]
hw/vigs/winsys.c [new file with mode: 0644]
hw/vigs/winsys.h
hw/vigs/work_queue.c
hw/vigs/work_queue.h
hw/yagl/yagl_device.c
vl.c

index ab8ef51..92bb3df 100644 (file)
@@ -15,6 +15,8 @@ obj-y += vigs_gl_pool.o
 obj-y += vigs_gl_backend.o
 obj-y += vigs_sw_backend.o
 obj-y += work_queue.o
+obj-y += winsys.o
+obj-y += display.o
 # GL GLX backend
 ifdef CONFIG_LINUX
 obj-y += vigs_gl_backend_glx.o
diff --git a/hw/vigs/display.c b/hw/vigs/display.c
new file mode 100644 (file)
index 0000000..961e7aa
--- /dev/null
@@ -0,0 +1,131 @@
+#include "display.h"
+#include "qom/object_interfaces.h"
+#if defined(CONFIG_LINUX)
+#include <X11/Xlib.h>
+
+static int x_error_handler(Display *dpy, XErrorEvent *e)
+{
+    return 0;
+}
+#endif
+
+static void displayobject_instance_finalize(Object *obj)
+{
+    DisplayObject *dobj = DISPLAYOBJECT(obj);
+
+    dobj->dpy = NULL;
+}
+
+static void displayobject_complete(UserCreatable *obj, Error **errp)
+{
+    DisplayObject *dobj = DISPLAYOBJECT(obj);
+
+#if defined(CONFIG_LINUX)
+    XSetErrorHandler(x_error_handler);
+    XInitThreads();
+
+    dobj->dpy = XOpenDisplay(0);
+
+    if (!dobj->dpy) {
+        error_setg(errp, "Cannot open X display");
+    }
+#else
+    dobj->dpy = NULL;
+#endif
+}
+
+static void displayobject_class_init(ObjectClass *klass, void *class_data)
+{
+    UserCreatableClass *ucc = USER_CREATABLE_CLASS(klass);
+    ucc->complete = displayobject_complete;
+}
+
+static const TypeInfo displayobject_info = {
+    .name = TYPE_DISPLAYOBJECT,
+    .parent = TYPE_OBJECT,
+    .class_init = displayobject_class_init,
+    .instance_size = sizeof(DisplayObject),
+    .instance_finalize = displayobject_instance_finalize,
+    .interfaces = (InterfaceInfo[]) {
+        {TYPE_USER_CREATABLE},
+        {}
+    },
+};
+
+static void displayobject_register_types(void)
+{
+    type_register_static(&displayobject_info);
+}
+
+type_init(displayobject_register_types)
+
+struct query_object_arg
+{
+    DisplayObject *dobj;
+    bool ambiguous;
+};
+
+static int query_object(Object *object, void *opaque)
+{
+    struct query_object_arg *arg = opaque;
+    DisplayObject *dobj;
+
+    dobj = (DisplayObject*)object_dynamic_cast(object, TYPE_DISPLAYOBJECT);
+
+    if (dobj) {
+        if (arg->dobj) {
+            arg->ambiguous = true;
+        }
+        arg->dobj = dobj;
+    }
+
+    return 0;
+}
+
+DisplayObject *displayobject_create(bool *ambiguous)
+{
+    Object *container = container_get(object_get_root(), "/objects");
+    struct query_object_arg arg = { NULL, false };
+
+    object_child_foreach(container, query_object, &arg);
+
+    *ambiguous = arg.ambiguous;
+
+    if (!arg.dobj) {
+        Error *err = NULL;
+
+        arg.dobj = DISPLAYOBJECT(object_new(TYPE_DISPLAYOBJECT));
+
+        user_creatable_complete(&arg.dobj->base, &err);
+
+        if (err) {
+            error_free(err);
+            return NULL;
+        }
+
+        object_property_add_child(container, "dpy0", &arg.dobj->base, &err);
+
+        object_unref(&arg.dobj->base);
+
+        if (err) {
+            error_free(err);
+            return NULL;
+        }
+    }
+
+    return arg.dobj;
+}
+
+DisplayObject *displayobject_find(const char *id)
+{
+    Object *container = container_get(object_get_root(), "/objects");
+    Object *child;
+
+    child = object_property_get_link(container, id, NULL);
+
+    if (!child) {
+        return NULL;
+    }
+
+    return (DisplayObject*)object_dynamic_cast(child, TYPE_DISPLAYOBJECT);
+}
diff --git a/hw/vigs/display.h b/hw/vigs/display.h
new file mode 100644 (file)
index 0000000..710e988
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef _QEMU_DISPLAY_H
+#define _QEMU_DISPLAY_H
+
+#include "qemu-common.h"
+
+#define TYPE_DISPLAYOBJECT "display"
+
+typedef struct {
+    Object base;
+    void *dpy;
+} DisplayObject;
+
+#define DISPLAYOBJECT(obj) \
+   OBJECT_CHECK(DisplayObject, obj, TYPE_DISPLAYOBJECT)
+
+DisplayObject *displayobject_create(bool *ambiguous);
+
+DisplayObject *displayobject_find(const char *id);
+
+#endif
index 442768a..464bd10 100644 (file)
  *
  */
 
-#include "vigs_device.h"
 #include "vigs_log.h"
 #include "vigs_server.h"
 #include "vigs_backend.h"
 #include "vigs_regs.h"
 #include "vigs_fenceman.h"
+#include "display.h"
 #include "work_queue.h"
+#include "winsys.h"
 #include "hw/hw.h"
+#include "hw/pci/pci.h"
 #include "ui/console.h"
 #include "qemu/main-loop.h"
 
-#ifdef __linux__
-#include <X11/Xlib.h>
-#endif
-
 #define PCI_VENDOR_ID_VIGS 0x19B2
 #define PCI_DEVICE_ID_VIGS 0x1011
 
 #define VIGS_EXTRA_INVALIDATION (0)
 #endif
 
-#ifdef __linux__
-Display *vigs_display = NULL;
-#else
-void *vigs_display = NULL;
-#endif
-
-struct work_queue *vigs_render_queue = NULL;
-struct winsys_interface *vigs_wsi = NULL;
-
 typedef struct VIGSState
 {
-    VIGSDevice dev;
+    PCIDevice dev;
 
+    char *display;
+    char *render_queue;
+    char *backend;
+    char *wsi;
     MemoryRegion vram_bar;
     uint32_t vram_size;
 
@@ -80,8 +73,6 @@ typedef struct VIGSState
 
     struct vigs_server *server;
 
-    char *backend;
-
     /*
      * Our console.
      */
@@ -94,8 +85,6 @@ typedef struct VIGSState
 
 #define TYPE_VIGS_DEVICE "vigs"
 
-extern const char *vigs_backend;
-
 static void vigs_update_irq(VIGSState *s)
 {
     bool raise = false;
@@ -110,9 +99,9 @@ static void vigs_update_irq(VIGSState *s)
     }
 
     if (raise) {
-        pci_set_irq(&s->dev.pci_dev, 1);
+        pci_set_irq(&s->dev, 1);
     } else {
-        pci_set_irq(&s->dev.pci_dev, 0);
+        pci_set_irq(&s->dev, 0);
     }
 }
 
@@ -299,35 +288,85 @@ static struct vigs_display_ops vigs_dpy_ops =
     .fence_ack = vigs_fence_ack,
 };
 
-#ifdef __linux__
-static int x_error_handler(Display *dpy, XErrorEvent *e)
+static int vigs_device_init(PCIDevice *dev)
 {
-    return 0;
-}
+    VIGSState *s = DO_UPCAST(VIGSState, dev, dev);
+    DisplayObject *dobj = NULL;
+    WorkQueueObject *wqobj = NULL;
+    WSIObject *wsiobj = NULL;
+    struct vigs_backend *backend = NULL;
 
-static Display *get_display(void)
-{
-    XSetErrorHandler(x_error_handler);
-    XInitThreads();
+    if (s->display) {
+        dobj = displayobject_find(s->display);
+
+        if (!dobj) {
+            error_report("display '%s' not found", s->display);
+            return -1;
+        }
+    } else {
+        bool ambiguous;
 
-    Display *display = XOpenDisplay(0);
+        dobj = displayobject_create(&ambiguous);
 
-    if (!display) {
-        fprintf(stderr, "Cannot open X display\n");
-        exit(1);
+        if (ambiguous) {
+            error_report("ambiguous display, set 'display' property");
+            return -1;
+        }
+
+        if (!dobj) {
+            error_report("unable to create display");
+            return -1;
+        }
     }
 
-    return display;
-}
-#endif
+    if (s->render_queue) {
+        wqobj = workqueueobject_find(s->render_queue);
 
-static int vigs_device_init(PCIDevice *dev)
-{
-    VIGSState *s = DO_UPCAST(VIGSState, dev.pci_dev, dev);
-    struct vigs_backend *backend = NULL;
+        if (!wqobj) {
+            error_report("work queue '%s' not found", s->render_queue);
+            return -1;
+        }
+    } else {
+        bool ambiguous;
+
+        wqobj = workqueueobject_create(&ambiguous);
+
+        if (ambiguous) {
+            error_report("ambiguous work queue, set 'render_queue' property");
+            return -1;
+        }
+
+        if (!dobj) {
+            error_report("unable to create work queue");
+            return -1;
+        }
+    }
+
+    if (!s->backend) {
+        error_report("'backend' property not set");
+        return -1;
+    }
+
+    if (strcmp(s->backend, "gl") && strcmp(s->backend, "sw")) {
+        error_report("backend '%s' not found", s->backend);
+        return -1;
+    }
+
+    if (s->wsi) {
+        Error *err = NULL;
 
-    if (!vigs_render_queue) {
-        vigs_render_queue = work_queue_create("render_queue");
+        wsiobj = WSIOBJECT(object_new(TYPE_WSIOBJECT));
+
+        object_property_add_child(container_get(object_get_root(), "/objects"),
+                                  s->wsi, &wsiobj->base, &err);
+
+        object_unref(&wsiobj->base);
+
+        if (err) {
+            qerror_report_err(err);
+            error_free(err);
+            return -1;
+        }
     }
 
     vigs_log_init();
@@ -358,27 +397,14 @@ static int vigs_device_init(PCIDevice *dev)
                           TYPE_VIGS_DEVICE ".io",
                           VIGS_IO_SIZE);
 
-    pci_register_bar(&s->dev.pci_dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->vram_bar);
-    pci_register_bar(&s->dev.pci_dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->ram_bar);
-    pci_register_bar(&s->dev.pci_dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->io_bar);
+    pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->vram_bar);
+    pci_register_bar(&s->dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->ram_bar);
+    pci_register_bar(&s->dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->io_bar);
 
-    if (!s->backend) {
-        VIGS_LOG_INFO("No backend is specified, defaulting to \"sw\"");
-        // choose "sw" backend as default.
-        backend = vigs_sw_backend_create();
-    } else if (!strcmp(s->backend, "gl")) {
-        VIGS_LOG_INFO("vigs uses \"gl\" backend");
-#ifdef __linux__
-        if (!vigs_display) {
-            vigs_display = get_display();
-        }
-#endif
-        backend = vigs_gl_backend_create(vigs_display);
+    if (!strcmp(s->backend, "gl")) {
+        backend = vigs_gl_backend_create(dobj->dpy);
     } else if (!strcmp(s->backend, "sw")) {
-        VIGS_LOG_INFO("vigs uses \"sw\" backend");
         backend = vigs_sw_backend_create();
-    } else {
-        VIGS_LOG_CRITICAL("Unknown backend=\"%s\" is specified", s->backend);
     }
 
     if (!backend) {
@@ -400,13 +426,18 @@ static int vigs_device_init(PCIDevice *dev)
                                    &vigs_dpy_ops,
                                    s,
                                    backend,
-                                   vigs_render_queue);
+                                   wqobj->wq);
 
     if (!s->server) {
         goto fail;
     }
 
-    vigs_wsi = s->dev.wsi = &s->server->wsi;
+    if (wsiobj) {
+        wsiobj->wsi = &s->server->wsi;
+        if (!strcmp(s->backend, "gl")) {
+            wsiobj->gl_wsi = &s->server->wsi;
+        }
+    }
 
     VIGS_LOG_INFO("VIGS initialized");
 
@@ -439,13 +470,13 @@ fail:
 
 static void vigs_device_reset(DeviceState *d)
 {
-    VIGSState *s = container_of(d, VIGSState, dev.pci_dev.qdev);
+    VIGSState *s = container_of(d, VIGSState, dev.qdev);
 
     vigs_server_reset(s->server);
 
     vigs_fenceman_reset(s->fenceman);
 
-    pci_set_irq(&s->dev.pci_dev, 0);
+    pci_set_irq(&s->dev, 0);
 
     s->reg_con = 0;
     s->reg_int = 0;
@@ -455,7 +486,7 @@ static void vigs_device_reset(DeviceState *d)
 
 static void vigs_device_exit(PCIDevice *dev)
 {
-    VIGSState *s = DO_UPCAST(VIGSState, dev.pci_dev, dev);
+    VIGSState *s = DO_UPCAST(VIGSState, dev, dev);
 
     vigs_server_destroy(s->server);
 
@@ -473,11 +504,14 @@ static void vigs_device_exit(PCIDevice *dev)
 }
 
 static Property vigs_properties[] = {
+    DEFINE_PROP_STRING("display", VIGSState, display),
+    DEFINE_PROP_STRING("render_queue", VIGSState, render_queue),
+    DEFINE_PROP_STRING("backend", VIGSState, backend),
+    DEFINE_PROP_STRING("wsi", VIGSState, wsi),
     DEFINE_PROP_UINT32("vram_size", VIGSState, vram_size,
                        32 * 1024 * 1024),
     DEFINE_PROP_UINT32("ram_size", VIGSState, ram_size,
                        1 * 1024 * 1024),
-    DEFINE_PROP_STRING("backend", VIGSState, backend),
     DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/hw/vigs/vigs_device.h b/hw/vigs/vigs_device.h
deleted file mode 100644 (file)
index c40cb39..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * vigs
- *
- * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Contact:
- * Stanislav Vorobiov <s.vorobiov@samsung.com>
- * Jinhyung Jo <jinhyung.jo@samsung.com>
- * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- *
- * Contributors:
- * - S-Core Co., Ltd
- *
- */
-
-#ifndef _QEMU_VIGS_DEVICE_H
-#define _QEMU_VIGS_DEVICE_H
-
-#include "qemu-common.h"
-#include "hw/pci/pci.h"
-
-struct winsys_interface;
-
-typedef struct VIGSDevice
-{
-    PCIDevice pci_dev;
-
-    struct winsys_interface *wsi;
-} VIGSDevice;
-
-#endif
diff --git a/hw/vigs/winsys.c b/hw/vigs/winsys.c
new file mode 100644 (file)
index 0000000..f486868
--- /dev/null
@@ -0,0 +1,29 @@
+#include "winsys.h"
+#include "qom/object_interfaces.h"
+
+static const TypeInfo wsiobject_info = {
+    .name = TYPE_WSIOBJECT,
+    .parent = TYPE_OBJECT,
+    .instance_size = sizeof(WSIObject)
+};
+
+static void wsiobject_register_types(void)
+{
+    type_register_static(&wsiobject_info);
+}
+
+type_init(wsiobject_register_types)
+
+WSIObject *wsiobject_find(const char *id)
+{
+    Object *container = container_get(object_get_root(), "/objects");
+    Object *child;
+
+    child = object_property_get_link(container, id, NULL);
+
+    if (!child) {
+        return NULL;
+    }
+
+    return (WSIObject*)object_dynamic_cast(child, TYPE_WSIOBJECT);
+}
index 95bdea0..c480e07 100644 (file)
@@ -36,4 +36,17 @@ struct winsys_interface
                       uint32_t /*fence_seq*/);
 };
 
+#define TYPE_WSIOBJECT "wsi"
+
+typedef struct {
+    Object base;
+    struct winsys_interface *wsi;
+    struct winsys_interface *gl_wsi;
+} WSIObject;
+
+#define WSIOBJECT(obj) \
+   OBJECT_CHECK(WSIObject, obj, TYPE_WSIOBJECT)
+
+WSIObject *wsiobject_find(const char *id);
+
 #endif
index 1bc53fa..7eaf778 100644 (file)
@@ -1,4 +1,5 @@
 #include "work_queue.h"
+#include "qom/object_interfaces.h"
 
 static void *work_queue_run(void *arg)
 {
@@ -105,3 +106,115 @@ void work_queue_destroy(struct work_queue *wq)
 
     g_free(wq);
 }
+
+static void workqueueobject_instance_finalize(Object *obj)
+{
+    WorkQueueObject *wqobj = WORKQUEUEOBJECT(obj);
+
+    work_queue_destroy(wqobj->wq);
+
+    wqobj->wq = NULL;
+}
+
+static void workqueueobject_complete(UserCreatable *obj, Error **errp)
+{
+    WorkQueueObject *wqobj = WORKQUEUEOBJECT(obj);
+
+    wqobj->wq = work_queue_create("render_queue");
+}
+
+static void workqueueobject_class_init(ObjectClass *klass, void *class_data)
+{
+    UserCreatableClass *ucc = USER_CREATABLE_CLASS(klass);
+    ucc->complete = workqueueobject_complete;
+}
+
+static const TypeInfo workqueueobject_info = {
+    .name = TYPE_WORKQUEUEOBJECT,
+    .parent = TYPE_OBJECT,
+    .class_init = workqueueobject_class_init,
+    .instance_size = sizeof(WorkQueueObject),
+    .instance_finalize = workqueueobject_instance_finalize,
+    .interfaces = (InterfaceInfo[]) {
+        {TYPE_USER_CREATABLE},
+        {}
+    },
+};
+
+static void workqueueobject_register_types(void)
+{
+    type_register_static(&workqueueobject_info);
+}
+
+type_init(workqueueobject_register_types)
+
+struct query_object_arg
+{
+    WorkQueueObject *wqobj;
+    bool ambiguous;
+};
+
+static int query_object(Object *object, void *opaque)
+{
+    struct query_object_arg *arg = opaque;
+    WorkQueueObject *wqobj;
+
+    wqobj = (WorkQueueObject*)object_dynamic_cast(object, TYPE_WORKQUEUEOBJECT);
+
+    if (wqobj) {
+        if (arg->wqobj) {
+            arg->ambiguous = true;
+        }
+        arg->wqobj = wqobj;
+    }
+
+    return 0;
+}
+
+WorkQueueObject *workqueueobject_create(bool *ambiguous)
+{
+    Object *container = container_get(object_get_root(), "/objects");
+    struct query_object_arg arg = { NULL, false };
+
+    object_child_foreach(container, query_object, &arg);
+
+    *ambiguous = arg.ambiguous;
+
+    if (!arg.wqobj) {
+        Error *err = NULL;
+
+        arg.wqobj = WORKQUEUEOBJECT(object_new(TYPE_WORKQUEUEOBJECT));
+
+        user_creatable_complete(&arg.wqobj->base, &err);
+
+        if (err) {
+            error_free(err);
+            return NULL;
+        }
+
+        object_property_add_child(container, "wq0", &arg.wqobj->base, &err);
+
+        object_unref(&arg.wqobj->base);
+
+        if (err) {
+            error_free(err);
+            return NULL;
+        }
+    }
+
+    return arg.wqobj;
+}
+
+WorkQueueObject *workqueueobject_find(const char *id)
+{
+    Object *container = container_get(object_get_root(), "/objects");
+    Object *child;
+
+    child = object_property_get_link(container, id, NULL);
+
+    if (!child) {
+        return NULL;
+    }
+
+    return (WorkQueueObject*)object_dynamic_cast(child, TYPE_WORKQUEUEOBJECT);
+}
index af27ee2..f0babe4 100644 (file)
@@ -42,4 +42,18 @@ void work_queue_wait(struct work_queue *wq);
 
 void work_queue_destroy(struct work_queue *wq);
 
+#define TYPE_WORKQUEUEOBJECT "work_queue"
+
+typedef struct {
+    Object base;
+    struct work_queue *wq;
+} WorkQueueObject;
+
+#define WORKQUEUEOBJECT(obj) \
+   OBJECT_CHECK(WorkQueueObject, obj, TYPE_WORKQUEUEOBJECT)
+
+WorkQueueObject *workqueueobject_create(bool *ambiguous);
+
+WorkQueueObject *workqueueobject_find(const char *id);
+
 #endif
index 733ed40..b77151f 100644 (file)
 #include "exec/cpu-all.h"
 #include "hw/hw.h"
 #include "hw/pci/pci.h"
+#include "qemu/error-report.h"
 #include <GL/gl.h>
+#include "vigs/display.h"
+#include "vigs/work_queue.h"
 #include "vigs/winsys.h"
 #include "yagl_gles_driver.h"
 
 
 #define YAGL_MAX_USERS (YAGL_MEM_SIZE / YAGL_REGS_SIZE)
 
-#ifdef __linux__
-extern Display *vigs_display;
-#else
-extern void *vigs_display;
-#endif
-
-extern struct work_queue *vigs_render_queue;
-extern struct winsys_interface *vigs_wsi;
-
 struct yagl_user
 {
     bool activated;
@@ -76,6 +70,9 @@ typedef struct YaGLState
 {
     PCIDevice dev;
 
+    char *display;
+    char *render_queue;
+    char *wsi;
     MemoryRegion iomem;
     struct yagl_server_state *ss;
     struct yagl_user users[YAGL_MAX_USERS];
@@ -214,28 +211,6 @@ static void yagl_device_write(void *opaque, hwaddr offset,
     }
 }
 
-#ifdef __linux__
-static int x_error_handler(Display *dpy, XErrorEvent *e)
-{
-    return 0;
-}
-
-static Display *get_display(void)
-{
-    XSetErrorHandler(x_error_handler);
-    XInitThreads();
-
-    Display *display = XOpenDisplay(0);
-
-    if (!display) {
-        fprintf(stderr, "Cannot open X display\n");
-        exit(1);
-    }
-
-    return display;
-}
-#endif
-
 static const MemoryRegionOps yagl_device_ops =
 {
     .read = yagl_device_read,
@@ -246,10 +221,67 @@ static const MemoryRegionOps yagl_device_ops =
 static int yagl_device_init(PCIDevice *dev)
 {
     YaGLState *s = DO_UPCAST(YaGLState, dev, dev);
+    DisplayObject *dobj = NULL;
+    WorkQueueObject *wqobj = NULL;
+    WSIObject *wsiobj = NULL;
     struct yagl_egl_driver *egl_driver = NULL;
     struct yagl_egl_backend *egl_backend = NULL;
     struct yagl_gles_driver *gles_driver = NULL;
 
+    if (s->display) {
+        dobj = displayobject_find(s->display);
+
+        if (!dobj) {
+            error_report("display '%s' not found", s->display);
+            return -1;
+        }
+    } else {
+        bool ambiguous;
+
+        dobj = displayobject_create(&ambiguous);
+
+        if (ambiguous) {
+            error_report("ambiguous display, set 'display' property");
+            return -1;
+        }
+
+        if (!dobj) {
+            error_report("unable to create display");
+            return -1;
+        }
+    }
+
+    if (s->render_queue) {
+        wqobj = workqueueobject_find(s->render_queue);
+
+        if (!wqobj) {
+            error_report("work queue '%s' not found", s->render_queue);
+            return -1;
+        }
+    } else {
+        bool ambiguous;
+
+        wqobj = workqueueobject_create(&ambiguous);
+
+        if (ambiguous) {
+            error_report("ambiguous work queue, set 'render_queue' property");
+            return -1;
+        }
+
+        if (!dobj) {
+            error_report("unable to create work queue");
+            return -1;
+        }
+    }
+
+    if (s->wsi) {
+        wsiobj = wsiobject_find(s->wsi);
+        if (!wsiobj) {
+            error_report("winsys interface '%s' not found", s->wsi);
+            return -1;
+        }
+    }
+
     yagl_log_init();
 
     YAGL_LOG_FUNC_ENTER(yagl_device_init, NULL);
@@ -262,17 +294,7 @@ static int yagl_device_init(PCIDevice *dev)
 
     yagl_handle_gen_init();
 
-    if (!vigs_render_queue) {
-        vigs_render_queue = work_queue_create("render_queue");
-    }
-
-#ifdef __linux__
-    if (!vigs_display) {
-        vigs_display = get_display();
-    }
-#endif
-
-    egl_driver = yagl_egl_driver_create(vigs_display);
+    egl_driver = yagl_egl_driver_create(dobj->dpy);
 
     if (!egl_driver) {
         goto fail;
@@ -285,9 +307,8 @@ static int yagl_device_init(PCIDevice *dev)
         goto fail;
     }
 
-    // FIXME: How can we gurantee that vigs is initialized before ?
-    if (vigs_wsi) {
-        egl_backend = yagl_egl_onscreen_create(vigs_wsi,
+    if (wsiobj && wsiobj->gl_wsi) {
+        egl_backend = yagl_egl_onscreen_create(wsiobj->gl_wsi,
                                                egl_driver,
                                                gles_driver);
         gles_driver = yagl_gles_onscreen_create(gles_driver);
@@ -305,7 +326,8 @@ static int yagl_device_init(PCIDevice *dev)
     egl_driver = NULL;
 
     s->ss = yagl_server_state_create(egl_backend, gles_driver,
-                                     vigs_render_queue, vigs_wsi);
+                                     wqobj->wq,
+                                     (wsiobj ? wsiobj->gl_wsi : NULL));
 
     /*
      * Owned/destroyed by server state.
@@ -376,6 +398,13 @@ static void yagl_device_exit(PCIDevice *dev)
     yagl_log_cleanup();
 }
 
+static Property yagl_properties[] = {
+    DEFINE_PROP_STRING("display", YaGLState, display),
+    DEFINE_PROP_STRING("render_queue", YaGLState, render_queue),
+    DEFINE_PROP_STRING("wsi", YaGLState, wsi),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
 static void yagl_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
@@ -387,6 +416,7 @@ static void yagl_class_init(ObjectClass *klass, void *data)
     k->device_id = PCI_DEVICE_ID_YAGL;
     k->class_id = PCI_CLASS_OTHERS;
     dc->reset = yagl_device_reset;
+    dc->props = yagl_properties;
     dc->desc = "YaGL device";
 }
 
diff --git a/vl.c b/vl.c
index 5c1f583..9458e3a 100644 (file)
--- a/vl.c
+++ b/vl.c
@@ -146,11 +146,11 @@ int qemu_main(int argc, char **argv, char **envp);
 
 #ifdef CONFIG_MARU
 int skin_disabled = 0;
-extern int enable_yagl;
+static int enable_yagl= 0;
 extern int enable_spice;
-const char *yagl_backend = NULL;
-int enable_vigs = 0;
-char *vigs_backend = NULL;
+static const char *yagl_backend = NULL;
+static int enable_vigs = 0;
+static char *vigs_backend = NULL;
 #endif
 
 static const char *data_dir[16];
@@ -4618,7 +4618,10 @@ int main(int argc, char **argv, char **envp)
         PCIDevice *pci_dev = pci_create(pci_bus, -1, "vigs");
         if (vigs_backend) {
             qdev_prop_set_string(&pci_dev->qdev, "backend", vigs_backend);
+        } else {
+            qdev_prop_set_string(&pci_dev->qdev, "backend", "gl");
         }
+        qdev_prop_set_string(&pci_dev->qdev, "wsi", "wsi0");
         qdev_init_nofail(&pci_dev->qdev);
     }
 #endif
@@ -4627,6 +4630,9 @@ int main(int argc, char **argv, char **envp)
     if (enable_yagl) {
         PCIBus *pci_bus = (PCIBus *) object_resolve_path_type("", TYPE_PCI_BUS, NULL);
         PCIDevice *pci_dev = pci_create(pci_bus, -1, "yagl");
+        if (enable_vigs) {
+            qdev_prop_set_string(&pci_dev->qdev, "wsi", "wsi0");
+        }
         qdev_init_nofail(&pci_dev->qdev);
     }
 #endif