YaGL: Onscreen support added
authorStanislav Vorobiov <s.vorobiov@samsung.com>
Tue, 25 Dec 2012 07:32:56 +0000 (11:32 +0400)
committerStanislav Vorobiov <s.vorobiov@samsung.com>
Mon, 15 Apr 2013 11:24:18 +0000 (15:24 +0400)
53 files changed:
Makefile.target
hw/winsys.h [new file with mode: 0644]
hw/winsys_gl.h [new file with mode: 0644]
hw/yagl_api.h
hw/yagl_apis/egl/yagl_egl_calls.c
hw/yagl_apis/egl/yagl_egl_image.c
hw/yagl_apis/egl/yagl_egl_image.h
hw/yagl_apis/egl/yagl_host_egl_calls.c
hw/yagl_apis/egl/yagl_host_egl_calls.h
hw/yagl_apis/gles/yagl_gles_texture.c
hw/yagl_apis/gles1/yagl_host_gles1_calls.c
hw/yagl_apis/gles2/yagl_host_gles2_calls.c
hw/yagl_backends/egl_offscreen/yagl_egl_offscreen.c
hw/yagl_backends/egl_offscreen/yagl_egl_offscreen_context.c
hw/yagl_backends/egl_offscreen/yagl_egl_offscreen_display.c
hw/yagl_backends/egl_offscreen/yagl_egl_offscreen_image.c
hw/yagl_backends/egl_offscreen/yagl_egl_offscreen_image.h
hw/yagl_backends/egl_offscreen/yagl_egl_offscreen_surface.c
hw/yagl_backends/egl_offscreen/yagl_egl_offscreen_ts.c
hw/yagl_backends/egl_offscreen/yagl_egl_offscreen_ts.h
hw/yagl_backends/egl_onscreen/yagl_egl_onscreen.c [new file with mode: 0644]
hw/yagl_backends/egl_onscreen/yagl_egl_onscreen.h [new file with mode: 0644]
hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_context.c [new file with mode: 0644]
hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_context.h [new file with mode: 0644]
hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_display.c [new file with mode: 0644]
hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_display.h [new file with mode: 0644]
hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_image.c [new file with mode: 0644]
hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_image.h [new file with mode: 0644]
hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_surface.c [new file with mode: 0644]
hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_surface.h [new file with mode: 0644]
hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_ts.c [new file with mode: 0644]
hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_ts.h [new file with mode: 0644]
hw/yagl_device.c
hw/yagl_drivers/egl_glx/yagl_egl_glx.c
hw/yagl_drivers/egl_wgl/yagl_egl_wgl.c
hw/yagl_drivers/gles1_onscreen/yagl_gles1_onscreen.c [new file with mode: 0644]
hw/yagl_drivers/gles1_onscreen/yagl_gles1_onscreen.h [new file with mode: 0644]
hw/yagl_drivers/gles2_onscreen/yagl_gles2_onscreen.c [new file with mode: 0644]
hw/yagl_drivers/gles2_onscreen/yagl_gles2_onscreen.h [new file with mode: 0644]
hw/yagl_drivers/gles_onscreen/yagl_gles_onscreen.c [new file with mode: 0644]
hw/yagl_drivers/gles_onscreen/yagl_gles_onscreen.h [new file with mode: 0644]
hw/yagl_egl_backend.h
hw/yagl_egl_driver.h
hw/yagl_eglb_display.h
hw/yagl_eglb_image.c
hw/yagl_eglb_image.h
hw/yagl_eglb_surface.h
hw/yagl_gles_driver.c
hw/yagl_marshal.h
hw/yagl_server.c
hw/yagl_server.h
hw/yagl_thread.c
hw/yagl_types.h

index 7e6c7e368d9e8de68b92c220c52ab4b6a25ba35d..f1d66c4377cf118dfa3a021d1123d948ec107902 100755 (executable)
@@ -182,11 +182,15 @@ $(call set-vpath, $(SRC_PATH)/hw/yagl_apis/egl: \
                   $(SRC_PATH)/hw/yagl_apis/gles1: \
                   $(SRC_PATH)/hw/yagl_apis/gles2: \
                   $(SRC_PATH)/hw/yagl_backends/egl_offscreen: \
+                  $(SRC_PATH)/hw/yagl_backends/egl_onscreen: \
                   $(SRC_PATH)/hw/yagl_drivers/egl_glx: \
                   $(SRC_PATH)/hw/yagl_drivers/egl_wgl: \
                   $(SRC_PATH)/hw/yagl_drivers/gles_ogl: \
+                  $(SRC_PATH)/hw/yagl_drivers/gles_onscreen: \
                   $(SRC_PATH)/hw/yagl_drivers/gles1_ogl: \
-                  $(SRC_PATH)/hw/yagl_drivers/gles2_ogl)
+                  $(SRC_PATH)/hw/yagl_drivers/gles2_ogl: \
+                  $(SRC_PATH)/hw/yagl_drivers/gles1_onscreen: \
+                  $(SRC_PATH)/hw/yagl_drivers/gles2_onscreen)
 
 obj-y += yagl_device.o
 obj-y += yagl_log.o
@@ -274,6 +278,13 @@ obj-y += yagl_egl_offscreen_display.o
 obj-y += yagl_egl_offscreen_context.o
 obj-y += yagl_egl_offscreen_surface.o
 obj-y += yagl_egl_offscreen_image.o
+# EGL onscreen backend
+obj-y += yagl_egl_onscreen.o
+obj-y += yagl_egl_onscreen_ts.o
+obj-y += yagl_egl_onscreen_display.o
+obj-y += yagl_egl_onscreen_context.o
+obj-y += yagl_egl_onscreen_surface.o
+obj-y += yagl_egl_onscreen_image.o
 # EGL GLX driver
 ifdef CONFIG_YAGL_EGL_GLX
 obj-y += yagl_egl_glx.o
@@ -288,6 +299,12 @@ obj-y += yagl_gles_ogl.o
 obj-y += yagl_gles1_ogl.o
 # GLESv2 OpenGL driver
 obj-y += yagl_gles2_ogl.o
+# GLES onscreen common driver
+obj-y += yagl_gles_onscreen.o
+# GLESv1_CM onscreen driver
+obj-y += yagl_gles1_onscreen.o
+# GLESv2 onscreen driver
+obj-y += yagl_gles2_onscreen.o
 
 endif
 
diff --git a/hw/winsys.h b/hw/winsys.h
new file mode 100644 (file)
index 0000000..f26d27c
--- /dev/null
@@ -0,0 +1,62 @@
+#ifndef _QEMU_WINSYS_H
+#define _QEMU_WINSYS_H
+
+#include "qemu-common.h"
+
+typedef uint32_t winsys_id;
+
+typedef enum
+{
+    winsys_res_type_window = 0,
+    winsys_res_type_pixmap = 1,
+} winsys_res_type;
+
+struct winsys_surface
+{
+    uint32_t width;
+    uint32_t height;
+
+    void (*acquire)(struct winsys_surface */*sfc*/);
+    void (*release)(struct winsys_surface */*sfc*/);
+};
+
+struct winsys_resource;
+
+typedef void (*winsys_resource_cb)(struct winsys_resource */*res*/,
+                                   void */*user_data*/);
+
+struct winsys_resource
+{
+    winsys_id id;
+
+    winsys_res_type type;
+
+    void (*acquire)(struct winsys_resource */*res*/);
+    void (*release)(struct winsys_resource */*res*/);
+
+    void *(*add_callback)(struct winsys_resource */*res*/,
+                          winsys_resource_cb /*cb*/,
+                          void */*user_data*/);
+
+    void (*remove_callback)(struct winsys_resource */*res*/,
+                            void */*cookie*/);
+
+    struct winsys_surface *(*acquire_surface)(struct winsys_resource */*res*/);
+};
+
+struct winsys_info
+{
+};
+
+struct winsys_interface
+{
+    struct winsys_info *ws_info;
+
+    /*
+     * Acquires resource corresponding to winsys id. NULL if no such resource.
+     */
+    struct winsys_resource *(*acquire_resource)(struct winsys_interface */*wsi*/,
+                                                winsys_id /*id*/);
+};
+
+#endif
diff --git a/hw/winsys_gl.h b/hw/winsys_gl.h
new file mode 100644 (file)
index 0000000..03f89ca
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef _QEMU_WINSYS_GL_H
+#define _QEMU_WINSYS_GL_H
+
+#include "winsys.h"
+
+struct winsys_gl_surface
+{
+    struct winsys_surface base;
+
+    GLuint (*get_front_texture)(struct winsys_gl_surface */*sfc*/);
+    GLuint (*get_back_texture)(struct winsys_gl_surface */*sfc*/);
+
+    void (*swap_buffers)(struct winsys_gl_surface */*sfc*/);
+
+    void (*copy_buffers)(uint32_t /*width*/,
+                         uint32_t /*height*/,
+                         struct winsys_gl_surface */*target*/);
+};
+
+struct winsys_gl_info
+{
+    struct winsys_info base;
+
+    /*
+     * OpenGL context that holds all winsys texture objects.
+     */
+    void *context;
+};
+
+#endif
index 0d1e448fa9475a14a24a36ca331db24c8c584fd7..bf6f01d147d7d655483c1b81abcf9669d6f0fbdd 100644 (file)
@@ -14,6 +14,8 @@ struct yagl_api_ps
 
     void (*thread_init)(struct yagl_api_ps */*api_ps*/);
 
+    void (*pre_batch)(struct yagl_api_ps */*api_ps*/);
+
     yagl_api_func (*get_func)(struct yagl_api_ps */*api_ps*/,
                               uint32_t /*func_id*/);
 
index 050464aa66bb0609db59d799c8f7abfdd1c51e07..46e4fa63edd8580a1a441f00347a9f6ddd6950a4 100644 (file)
@@ -487,8 +487,8 @@ static bool yagl_func_eglCopyBuffers(uint8_t **out_buff,
 {
     yagl_host_handle dpy = yagl_marshal_get_host_handle(out_buff);
     yagl_host_handle surface = yagl_marshal_get_host_handle(out_buff);
-    EGLNativePixmapType target = yagl_marshal_get_EGLNativePixmapType(out_buff);
-    YAGL_LOG_FUNC_ENTER_SPLIT3(eglCopyBuffers, yagl_host_handle, yagl_host_handle, EGLNativePixmapType, dpy, surface, target);
+    yagl_winsys_id target = yagl_marshal_get_yagl_winsys_id(out_buff);
+    YAGL_LOG_FUNC_ENTER_SPLIT3(eglCopyBuffers, yagl_host_handle, yagl_host_handle, yagl_winsys_id, dpy, surface, target);
     EGLBoolean retval;
     bool res = yagl_host_eglCopyBuffers(&retval, dpy, surface, target);
     if (!res) {
@@ -509,9 +509,9 @@ static bool yagl_func_eglCreateImageKHR(uint8_t **out_buff,
     yagl_host_handle dpy = yagl_marshal_get_host_handle(out_buff);
     yagl_host_handle ctx = yagl_marshal_get_host_handle(out_buff);
     EGLenum target = yagl_marshal_get_EGLenum(out_buff);
-    yagl_host_handle buffer = yagl_marshal_get_host_handle(out_buff);
+    yagl_winsys_id buffer = yagl_marshal_get_yagl_winsys_id(out_buff);
     target_ulong attrib_list = yagl_marshal_get_ptr(out_buff);
-    YAGL_LOG_FUNC_ENTER_SPLIT5(eglCreateImageKHR, yagl_host_handle, yagl_host_handle, EGLenum, yagl_host_handle, target_ulong, dpy, ctx, target, buffer, attrib_list);
+    YAGL_LOG_FUNC_ENTER_SPLIT5(eglCreateImageKHR, yagl_host_handle, yagl_host_handle, EGLenum, yagl_winsys_id, target_ulong, dpy, ctx, target, buffer, attrib_list);
     yagl_host_handle retval;
     bool res = yagl_host_eglCreateImageKHR(&retval, dpy, ctx, target, buffer, attrib_list);
     if (!res) {
@@ -660,7 +660,72 @@ static bool yagl_func_eglUpdateOffscreenImageYAGL(uint8_t **out_buff,
     return res;
 }
 
-const uint32_t yagl_egl_api_num_funcs = 31;
+/*
+ * eglCreateWindowSurfaceOnscreenYAGL dispatcher. id = 32
+ */
+static bool yagl_func_eglCreateWindowSurfaceOnscreenYAGL(uint8_t **out_buff,
+    uint8_t *in_buff)
+{
+    yagl_host_handle dpy = yagl_marshal_get_host_handle(out_buff);
+    yagl_host_handle config = yagl_marshal_get_host_handle(out_buff);
+    yagl_winsys_id win = yagl_marshal_get_yagl_winsys_id(out_buff);
+    target_ulong attrib_list = yagl_marshal_get_ptr(out_buff);
+    YAGL_LOG_FUNC_ENTER_SPLIT4(eglCreateWindowSurfaceOnscreenYAGL, yagl_host_handle, yagl_host_handle, yagl_winsys_id, target_ulong, dpy, config, win, attrib_list);
+    yagl_host_handle retval;
+    bool res = yagl_host_eglCreateWindowSurfaceOnscreenYAGL(&retval, dpy, config, win, attrib_list);
+    if (!res) {
+        YAGL_LOG_FUNC_EXIT(NULL);
+        return false;
+    }
+    YAGL_LOG_FUNC_EXIT_SPLIT(yagl_host_handle, retval);
+    yagl_marshal_put_host_handle(&in_buff, retval);
+    return true;
+}
+
+/*
+ * eglCreatePbufferSurfaceOnscreenYAGL dispatcher. id = 33
+ */
+static bool yagl_func_eglCreatePbufferSurfaceOnscreenYAGL(uint8_t **out_buff,
+    uint8_t *in_buff)
+{
+    yagl_host_handle dpy = yagl_marshal_get_host_handle(out_buff);
+    yagl_host_handle config = yagl_marshal_get_host_handle(out_buff);
+    target_ulong attrib_list = yagl_marshal_get_ptr(out_buff);
+    YAGL_LOG_FUNC_ENTER_SPLIT3(eglCreatePbufferSurfaceOnscreenYAGL, yagl_host_handle, yagl_host_handle, target_ulong, dpy, config, attrib_list);
+    yagl_host_handle retval;
+    bool res = yagl_host_eglCreatePbufferSurfaceOnscreenYAGL(&retval, dpy, config, attrib_list);
+    if (!res) {
+        YAGL_LOG_FUNC_EXIT(NULL);
+        return false;
+    }
+    YAGL_LOG_FUNC_EXIT_SPLIT(yagl_host_handle, retval);
+    yagl_marshal_put_host_handle(&in_buff, retval);
+    return true;
+}
+
+/*
+ * eglCreatePixmapSurfaceOnscreenYAGL dispatcher. id = 34
+ */
+static bool yagl_func_eglCreatePixmapSurfaceOnscreenYAGL(uint8_t **out_buff,
+    uint8_t *in_buff)
+{
+    yagl_host_handle dpy = yagl_marshal_get_host_handle(out_buff);
+    yagl_host_handle config = yagl_marshal_get_host_handle(out_buff);
+    yagl_winsys_id pixmap = yagl_marshal_get_yagl_winsys_id(out_buff);
+    target_ulong attrib_list = yagl_marshal_get_ptr(out_buff);
+    YAGL_LOG_FUNC_ENTER_SPLIT4(eglCreatePixmapSurfaceOnscreenYAGL, yagl_host_handle, yagl_host_handle, yagl_winsys_id, target_ulong, dpy, config, pixmap, attrib_list);
+    yagl_host_handle retval;
+    bool res = yagl_host_eglCreatePixmapSurfaceOnscreenYAGL(&retval, dpy, config, pixmap, attrib_list);
+    if (!res) {
+        YAGL_LOG_FUNC_EXIT(NULL);
+        return false;
+    }
+    YAGL_LOG_FUNC_EXIT_SPLIT(yagl_host_handle, retval);
+    yagl_marshal_put_host_handle(&in_buff, retval);
+    return true;
+}
+
+const uint32_t yagl_egl_api_num_funcs = 34;
 
 yagl_api_func yagl_egl_api_funcs[] = {
     &yagl_func_eglGetError,
@@ -693,5 +758,8 @@ yagl_api_func yagl_egl_api_funcs[] = {
     &yagl_func_eglCreatePbufferSurfaceOffscreenYAGL,
     &yagl_func_eglCreatePixmapSurfaceOffscreenYAGL,
     &yagl_func_eglResizeOffscreenSurfaceYAGL,
-    &yagl_func_eglUpdateOffscreenImageYAGL
+    &yagl_func_eglUpdateOffscreenImageYAGL,
+    &yagl_func_eglCreateWindowSurfaceOnscreenYAGL,
+    &yagl_func_eglCreatePbufferSurfaceOnscreenYAGL,
+    &yagl_func_eglCreatePixmapSurfaceOnscreenYAGL
 };
index 73c615e9ba5254ebc79cd49c3b1a183e42ba3194..f64e80b6d68ee9f1bdc8775bcf03d76f04e18dd0 100644 (file)
@@ -14,12 +14,13 @@ static void yagl_egl_image_destroy(struct yagl_ref *ref)
     g_free(image);
 }
 
-struct yagl_egl_image *yagl_egl_image_create(struct yagl_egl_display *dpy)
+struct yagl_egl_image *yagl_egl_image_create(struct yagl_egl_display *dpy,
+                                             yagl_winsys_id buffer)
 {
     struct yagl_eglb_image *backend_image;
     struct yagl_egl_image *image;
 
-    backend_image = dpy->backend_dpy->create_image(dpy->backend_dpy);
+    backend_image = dpy->backend_dpy->create_image(dpy->backend_dpy, buffer);
 
     if (!backend_image) {
         return NULL;
index f010cabaf9a0bfc71e9ab10170ec680c5d0b1590..06c17cd4a9bb7c2bf716e12d5db6160111aa36f3 100644 (file)
@@ -16,7 +16,8 @@ struct yagl_egl_image
     struct yagl_eglb_image *backend_image;
 };
 
-struct yagl_egl_image *yagl_egl_image_create(struct yagl_egl_display *dpy);
+struct yagl_egl_image *yagl_egl_image_create(struct yagl_egl_display *dpy,
+                                             yagl_winsys_id buffer);
 
 /*
  * Helper functions that simply acquire/release yagl_egl_image::res
index 1701ffad94306839060945e718f7b17d189d21ea..b28751817d2d35308615a970397c81b838207c23 100644 (file)
@@ -236,6 +236,13 @@ static bool yagl_egl_release_current_context(struct yagl_egl_display *dpy)
     return true;
 }
 
+static void yagl_host_egl_pre_batch(struct yagl_api_ps *api_ps)
+{
+    struct yagl_egl_api_ps *egl_api_ps = (struct yagl_egl_api_ps*)api_ps;
+
+    egl_api_ps->backend->pre_batch(egl_api_ps->backend);
+}
+
 static yagl_api_func yagl_host_egl_get_func(struct yagl_api_ps *api_ps,
                                             uint32_t func_id)
 {
@@ -335,6 +342,7 @@ struct yagl_api_ps *yagl_host_egl_process_init(struct yagl_api *api)
     yagl_api_ps_init(&egl_api_ps->base, api);
 
     egl_api_ps->base.thread_init = &yagl_host_egl_thread_init;
+    egl_api_ps->base.pre_batch = &yagl_host_egl_pre_batch;
     egl_api_ps->base.get_func = &yagl_host_egl_get_func;
     egl_api_ps->base.thread_fini = &yagl_host_egl_thread_fini;
     egl_api_ps->base.fini = &yagl_host_egl_process_fini;
@@ -1570,7 +1578,7 @@ out:
 bool yagl_host_eglCopyBuffers(EGLBoolean* retval,
     yagl_host_handle dpy_,
     yagl_host_handle surface_,
-    EGLNativePixmapType target)
+    yagl_winsys_id target)
 {
     struct yagl_egl_display *dpy = NULL;
     struct yagl_egl_surface *surface = NULL;
@@ -1607,9 +1615,9 @@ bool yagl_host_eglCopyBuffers(EGLBoolean* retval,
         goto out;
     }
 
-    if (!surface->backend_sfc->copy_buffers(surface->backend_sfc)) {
+    if (!surface->backend_sfc->copy_buffers(surface->backend_sfc, target)) {
         yagl_egl_surface_unlock(surface);
-        YAGL_SET_ERR(EGL_BAD_ALLOC);
+        YAGL_SET_ERR(EGL_BAD_NATIVE_PIXMAP);
         goto out;
     }
 
@@ -1627,7 +1635,7 @@ bool yagl_host_eglCreateImageKHR(yagl_host_handle* retval,
     yagl_host_handle dpy_,
     yagl_host_handle ctx,
     EGLenum target,
-    yagl_host_handle buffer_,
+    yagl_winsys_id buffer,
     target_ulong /* const EGLint* */ attrib_list_)
 {
     bool res = true;
@@ -1677,7 +1685,7 @@ bool yagl_host_eglCreateImageKHR(yagl_host_handle* retval,
         goto out;
     }
 
-    image = yagl_egl_image_create(dpy);
+    image = yagl_egl_image_create(dpy, buffer);
 
     if (!image) {
         YAGL_SET_ERR(EGL_BAD_ALLOC);
@@ -2201,3 +2209,315 @@ out:
 
     return res;
 }
+
+bool yagl_host_eglCreateWindowSurfaceOnscreenYAGL(yagl_host_handle* retval,
+    yagl_host_handle dpy_,
+    yagl_host_handle config_,
+    yagl_winsys_id win,
+    target_ulong /* const EGLint* */ attrib_list_)
+{
+    bool res = true;
+    EGLint *attrib_list = NULL;
+    struct yagl_eglb_surface *backend_sfc = NULL;
+    struct yagl_egl_window_attribs attribs;
+    int i = 0;
+    struct yagl_egl_display *dpy = NULL;
+    struct yagl_egl_config *config = NULL;
+    struct yagl_egl_surface *surface = NULL;
+
+    YAGL_LOG_FUNC_SET(eglCreateWindowSurfaceOnscreenYAGL);
+
+    *retval = 0;
+
+    if (attrib_list_) {
+        attrib_list = yagl_mem_get_attrib_list(attrib_list_);
+
+        if (!attrib_list) {
+            res = false;
+            goto out;
+        }
+    }
+
+    yagl_egl_window_attribs_init(&attribs);
+
+    if (!yagl_egl_is_attrib_list_empty(attrib_list)) {
+        while (attrib_list[i] != EGL_NONE) {
+            switch (attrib_list[i]) {
+            case EGL_RENDER_BUFFER:
+                break;
+            default:
+                YAGL_SET_ERR(EGL_BAD_ATTRIBUTE);
+                goto out;
+            }
+
+            i += 2;
+        }
+    }
+
+    if (!yagl_validate_display(dpy_, &dpy)) {
+        goto out;
+    }
+
+    if (!yagl_validate_config(dpy, config_, &config)) {
+        goto out;
+    }
+
+    if (!dpy->backend_dpy->create_onscreen_window_surface) {
+        YAGL_LOG_CRITICAL("Onscreen window surfaces not supported");
+        YAGL_SET_ERR(EGL_BAD_NATIVE_WINDOW);
+        goto out;
+    }
+
+    backend_sfc = dpy->backend_dpy->create_onscreen_window_surface(dpy->backend_dpy,
+                                                                   &config->native,
+                                                                   &attribs,
+                                                                   win);
+
+    if (!backend_sfc) {
+        YAGL_LOG_ERROR("Unable to create window surface for 0x%X", win);
+        YAGL_SET_ERR(EGL_BAD_NATIVE_WINDOW);
+        goto out;
+    }
+
+    surface = yagl_egl_surface_create(dpy, config, backend_sfc);
+
+    if (!surface) {
+        YAGL_SET_ERR(EGL_BAD_ALLOC);
+        goto out;
+    }
+
+    /*
+     * Owned by 'surface' now.
+     */
+    backend_sfc = NULL;
+
+    yagl_egl_display_add_surface(dpy, surface);
+    yagl_egl_surface_release(surface);
+
+    *retval = surface->res.handle;
+
+out:
+    yagl_egl_config_release(config);
+    if (backend_sfc) {
+        backend_sfc->destroy(backend_sfc);
+    }
+    g_free(attrib_list);
+
+    return res;
+}
+
+bool yagl_host_eglCreatePbufferSurfaceOnscreenYAGL(yagl_host_handle* retval,
+    yagl_host_handle dpy_,
+    yagl_host_handle config_,
+    target_ulong /* const EGLint* */ attrib_list_)
+{
+    bool res = true;
+    EGLint *attrib_list = NULL;
+    struct yagl_eglb_surface *backend_sfc = NULL;
+    struct yagl_egl_pbuffer_attribs attribs;
+    uint32_t width = 0;
+    uint32_t height = 0;
+    struct yagl_egl_display *dpy = NULL;
+    struct yagl_egl_config *config = NULL;
+    struct yagl_egl_surface *surface = NULL;
+    int i = 0;
+
+    YAGL_LOG_FUNC_SET(eglCreatePbufferSurfaceOnscreenYAGL);
+
+    *retval = 0;
+
+    if (attrib_list_) {
+        attrib_list = yagl_mem_get_attrib_list(attrib_list_);
+
+        if (!attrib_list) {
+            res = false;
+            goto out;
+        }
+    }
+
+    yagl_egl_pbuffer_attribs_init(&attribs);
+
+    if (!yagl_egl_is_attrib_list_empty(attrib_list)) {
+        while (attrib_list[i] != EGL_NONE) {
+            switch (attrib_list[i]) {
+            case EGL_LARGEST_PBUFFER:
+                attribs.largest = (attrib_list[i + 1] ? EGL_TRUE : EGL_FALSE);
+                break;
+            case EGL_MIPMAP_TEXTURE:
+                attribs.tex_mipmap = (attrib_list[i + 1] ? EGL_TRUE : EGL_FALSE);
+                break;
+            case EGL_TEXTURE_FORMAT:
+                switch (attrib_list[i + 1]) {
+                case EGL_NO_TEXTURE:
+                case EGL_TEXTURE_RGB:
+                case EGL_TEXTURE_RGBA:
+                    attribs.tex_format = attrib_list[i + 1];
+                    break;
+                default:
+                    YAGL_SET_ERR(EGL_BAD_ATTRIBUTE);
+                    goto out;
+                }
+                break;
+            case EGL_TEXTURE_TARGET:
+                switch (attrib_list[i + 1]) {
+                case EGL_NO_TEXTURE:
+                case EGL_TEXTURE_2D:
+                    attribs.tex_target = attrib_list[i + 1];
+                    break;
+                default:
+                    YAGL_SET_ERR(EGL_BAD_ATTRIBUTE);
+                    goto out;
+                }
+                break;
+            case EGL_HEIGHT:
+                height = attrib_list[i + 1];
+                break;
+            case EGL_WIDTH:
+                width = attrib_list[i + 1];
+                break;
+            default:
+                YAGL_SET_ERR(EGL_BAD_ATTRIBUTE);
+                goto out;
+            }
+
+            i += 2;
+        }
+    }
+
+    if (!yagl_validate_display(dpy_, &dpy)) {
+        goto out;
+    }
+
+    if (!yagl_validate_config(dpy, config_, &config)) {
+        goto out;
+    }
+
+    if (!dpy->backend_dpy->create_onscreen_pbuffer_surface) {
+        YAGL_LOG_CRITICAL("Onscreen pbuffer surfaces not supported");
+        YAGL_SET_ERR(EGL_BAD_ALLOC);
+        goto out;
+    }
+
+    backend_sfc = dpy->backend_dpy->create_onscreen_pbuffer_surface(dpy->backend_dpy,
+                                                                    &config->native,
+                                                                    &attribs,
+                                                                    width,
+                                                                    height);
+
+    if (!backend_sfc) {
+        YAGL_SET_ERR(EGL_BAD_ALLOC);
+        goto out;
+    }
+
+    surface = yagl_egl_surface_create(dpy, config, backend_sfc);
+
+    if (!surface) {
+        YAGL_SET_ERR(EGL_BAD_ALLOC);
+        goto out;
+    }
+
+    /*
+     * Owned by 'surface' now.
+     */
+    backend_sfc = NULL;
+
+    yagl_egl_display_add_surface(dpy, surface);
+    yagl_egl_surface_release(surface);
+
+    *retval = surface->res.handle;
+
+out:
+    yagl_egl_config_release(config);
+    if (backend_sfc) {
+        backend_sfc->destroy(backend_sfc);
+    }
+    g_free(attrib_list);
+
+    return res;
+}
+
+bool yagl_host_eglCreatePixmapSurfaceOnscreenYAGL(yagl_host_handle* retval,
+    yagl_host_handle dpy_,
+    yagl_host_handle config_,
+    yagl_winsys_id pixmap,
+    target_ulong /* const EGLint* */ attrib_list_)
+{
+    bool res = true;
+    EGLint *attrib_list = NULL;
+    struct yagl_eglb_surface *backend_sfc = NULL;
+    struct yagl_egl_pixmap_attribs attribs;
+    struct yagl_egl_display *dpy = NULL;
+    struct yagl_egl_config *config = NULL;
+    struct yagl_egl_surface *surface = NULL;
+
+    YAGL_LOG_FUNC_SET(eglCreatePixmapSurfaceOnscreenYAGL);
+
+    *retval = 0;
+
+    if (attrib_list_) {
+        attrib_list = yagl_mem_get_attrib_list(attrib_list_);
+
+        if (!attrib_list) {
+            res = false;
+            goto out;
+        }
+    }
+
+    yagl_egl_pixmap_attribs_init(&attribs);
+
+    if (!yagl_egl_is_attrib_list_empty(attrib_list)) {
+        YAGL_SET_ERR(EGL_BAD_ATTRIBUTE);
+        goto out;
+    }
+
+    if (!yagl_validate_display(dpy_, &dpy)) {
+        goto out;
+    }
+
+    if (!yagl_validate_config(dpy, config_, &config)) {
+        goto out;
+    }
+
+    if (!dpy->backend_dpy->create_onscreen_pixmap_surface) {
+        YAGL_LOG_CRITICAL("Onscreen pixmap surfaces not supported");
+        YAGL_SET_ERR(EGL_BAD_NATIVE_PIXMAP);
+        goto out;
+    }
+
+    backend_sfc = dpy->backend_dpy->create_onscreen_pixmap_surface(dpy->backend_dpy,
+                                                                   &config->native,
+                                                                   &attribs,
+                                                                   pixmap);
+
+    if (!backend_sfc) {
+        YAGL_LOG_ERROR("Unable to create pixmap surface for 0x%X", pixmap);
+        YAGL_SET_ERR(EGL_BAD_NATIVE_PIXMAP);
+        goto out;
+    }
+
+    surface = yagl_egl_surface_create(dpy, config, backend_sfc);
+
+    if (!surface) {
+        YAGL_SET_ERR(EGL_BAD_NATIVE_PIXMAP);
+        goto out;
+    }
+
+    /*
+     * Owned by 'surface' now.
+     */
+    backend_sfc = NULL;
+
+    yagl_egl_display_add_surface(dpy, surface);
+    yagl_egl_surface_release(surface);
+
+    *retval = surface->res.handle;
+
+out:
+    yagl_egl_config_release(config);
+    if (backend_sfc) {
+        backend_sfc->destroy(backend_sfc);
+    }
+    g_free(attrib_list);
+
+    return res;
+}
index eafbfd6c2db520c3cbfb4b6a115c18f0bb55d373..86966cf32f6dece233dd7174a152d596bca9a57a 100644 (file)
@@ -89,12 +89,12 @@ bool yagl_host_eglSwapBuffers(EGLBoolean* retval,
 bool yagl_host_eglCopyBuffers(EGLBoolean* retval,
     yagl_host_handle dpy_,
     yagl_host_handle surface_,
-    EGLNativePixmapType target);
+    yagl_winsys_id target);
 bool yagl_host_eglCreateImageKHR(yagl_host_handle* retval,
     yagl_host_handle dpy_,
     yagl_host_handle ctx,
     EGLenum target,
-    yagl_host_handle buffer_,
+    yagl_winsys_id buffer,
     target_ulong /* const EGLint* */ attrib_list_);
 bool yagl_host_eglDestroyImageKHR(EGLBoolean* retval,
     yagl_host_handle dpy_,
@@ -136,5 +136,19 @@ bool yagl_host_eglUpdateOffscreenImageYAGL(yagl_host_handle dpy_,
     uint32_t height,
     uint32_t bpp,
     target_ulong /* const void* */ pixels);
+bool yagl_host_eglCreateWindowSurfaceOnscreenYAGL(yagl_host_handle* retval,
+    yagl_host_handle dpy_,
+    yagl_host_handle config_,
+    yagl_winsys_id win,
+    target_ulong /* const EGLint* */ attrib_list_);
+bool yagl_host_eglCreatePbufferSurfaceOnscreenYAGL(yagl_host_handle* retval,
+    yagl_host_handle dpy_,
+    yagl_host_handle config_,
+    target_ulong /* const EGLint* */ attrib_list_);
+bool yagl_host_eglCreatePixmapSurfaceOnscreenYAGL(yagl_host_handle* retval,
+    yagl_host_handle dpy_,
+    yagl_host_handle config_,
+    yagl_winsys_id pixmap,
+    target_ulong /* const EGLint* */ attrib_list_);
 
 #endif
index e1db7e8566982f0fc112a2e19ca579d2f1a19354..2ba39a6e735b9e62ab9741330e3d1088a89de446 100644 (file)
@@ -7,10 +7,6 @@ static void yagl_gles_texture_destroy(struct yagl_ref *ref)
 {
     struct yagl_gles_texture *texture = (struct yagl_gles_texture*)ref;
 
-    /*
-     * TODO: Add to reap list once we'll move it
-     * to gles driver.
-     */
     yagl_gles_image_release(texture->image);
 
     if (!texture->image) {
index 3a9678efa9a1f87fc45ea6a30f7ab3bcc53318cf..2156ac8783d61d21373d2009b52250a503065d25 100644 (file)
@@ -100,6 +100,10 @@ static void yagl_host_gles1_thread_init(struct yagl_api_ps *api_ps)
     YAGL_LOG_FUNC_EXIT(NULL);
 }
 
+static void yagl_host_gles1_pre_batch(struct yagl_api_ps *api_ps)
+{
+}
+
 static void yagl_host_gles1_thread_fini(struct yagl_api_ps *api_ps)
 {
     YAGL_LOG_FUNC_ENTER(yagl_host_gles1_thread_fini, NULL);
@@ -177,6 +181,7 @@ struct yagl_api_ps *yagl_host_gles1_process_init(struct yagl_api *api)
     yagl_api_ps_init(&gles1_api_ps->base, api);
 
     gles1_api_ps->base.thread_init = &yagl_host_gles1_thread_init;
+    gles1_api_ps->base.pre_batch = &yagl_host_gles1_pre_batch;
     gles1_api_ps->base.get_func = &yagl_host_gles1_get_func;
     gles1_api_ps->base.thread_fini = &yagl_host_gles1_thread_fini;
     gles1_api_ps->base.fini = &yagl_host_gles1_process_fini;
index ff5454a5f797d9f19b809f375ec19897a6ba60e1..886df6ce1080ea876eeaa0a2c280356d9689a87d 100644 (file)
@@ -109,6 +109,10 @@ static struct yagl_client_image
     return image ? &image->base : NULL;
 }
 
+static void yagl_host_gles2_pre_batch(struct yagl_api_ps *api_ps)
+{
+}
+
 static yagl_api_func yagl_host_gles2_get_func(struct yagl_api_ps *api_ps,
                                               uint32_t func_id)
 {
@@ -194,6 +198,7 @@ struct yagl_api_ps *yagl_host_gles2_process_init(struct yagl_api *api)
     yagl_api_ps_init(&gles2_api_ps->base, api);
 
     gles2_api_ps->base.thread_init = &yagl_host_gles2_thread_init;
+    gles2_api_ps->base.pre_batch = &yagl_host_gles2_pre_batch;
     gles2_api_ps->base.get_func = &yagl_host_gles2_get_func;
     gles2_api_ps->base.thread_fini = &yagl_host_gles2_thread_fini;
     gles2_api_ps->base.fini = &yagl_host_gles2_process_fini;
index 7da6cfcc16e83c19dad5b3642cd236036cc86e25..02a15f1f16cdafc15d44354be3d265c2acd4402a 100644 (file)
@@ -11,15 +11,17 @@ YAGL_DEFINE_TLS(struct yagl_egl_offscreen_ts*, egl_offscreen_ts);
 
 static void yagl_egl_offscreen_thread_init(struct yagl_egl_backend *backend)
 {
-    struct yagl_egl_offscreen *egl_offscreen = (struct yagl_egl_offscreen*)backend;
-
     YAGL_LOG_FUNC_ENTER(yagl_egl_offscreen_thread_init, NULL);
 
-    egl_offscreen_ts = yagl_egl_offscreen_ts_create(egl_offscreen->driver);
+    egl_offscreen_ts = yagl_egl_offscreen_ts_create();
 
     YAGL_LOG_FUNC_EXIT(NULL);
 }
 
+static void yagl_egl_offscreen_pre_batch(struct yagl_egl_backend *backend)
+{
+}
+
 static struct yagl_eglb_display *yagl_egl_offscreen_create_display(struct yagl_egl_backend *backend)
 {
     struct yagl_egl_offscreen *egl_offscreen = (struct yagl_egl_offscreen*)backend;
@@ -222,6 +224,7 @@ struct yagl_egl_backend *yagl_egl_offscreen_create(struct yagl_egl_driver *drive
     }
 
     egl_offscreen->base.thread_init = &yagl_egl_offscreen_thread_init;
+    egl_offscreen->base.pre_batch = &yagl_egl_offscreen_pre_batch;
     egl_offscreen->base.create_display = &yagl_egl_offscreen_create_display;
     egl_offscreen->base.make_current = &yagl_egl_offscreen_make_current;
     egl_offscreen->base.release_current = &yagl_egl_offscreen_release_current;
index 23663f63a2c01cb4de7ac732e7273dea05ac677e..d7c43d54dfc30866fc34e1f4ccd7d65a837ec09d 100644 (file)
@@ -1,6 +1,5 @@
 #include "yagl_egl_offscreen_context.h"
 #include "yagl_egl_offscreen_display.h"
-#include "yagl_egl_offscreen_ts.h"
 #include "yagl_egl_offscreen.h"
 #include "yagl_egl_native_config.h"
 #include "yagl_client_context.h"
@@ -9,8 +8,6 @@
 #include "yagl_process.h"
 #include "yagl_thread.h"
 
-YAGL_DECLARE_TLS(struct yagl_egl_offscreen_ts*, egl_offscreen_ts);
-
 static void yagl_egl_offscreen_context_destroy(struct yagl_eglb_context *ctx)
 {
     struct yagl_egl_offscreen_context *egl_offscreen_ctx =
index 1bea0f5dec4a4f89218fc6cc882045f7e9452479..4ae7dd202a08a1195b1eee16ac1edc3c36e46d4a 100644 (file)
@@ -2,7 +2,6 @@
 #include "yagl_egl_offscreen_context.h"
 #include "yagl_egl_offscreen_surface.h"
 #include "yagl_egl_offscreen_image.h"
-#include "yagl_egl_offscreen_ts.h"
 #include "yagl_egl_offscreen.h"
 #include "yagl_egl_native_config.h"
 #include "yagl_log.h"
@@ -10,8 +9,6 @@
 #include "yagl_process.h"
 #include "yagl_thread.h"
 
-YAGL_DECLARE_TLS(struct yagl_egl_offscreen_ts*, egl_offscreen_ts);
-
 static struct yagl_egl_native_config
     *yagl_egl_offscreen_display_config_enum(struct yagl_eglb_display *dpy,
                                             int *num_configs)
@@ -98,12 +95,13 @@ static struct yagl_eglb_surface
 }
 
 static struct yagl_eglb_image
-    *yagl_egl_offscreen_display_create_image(struct yagl_eglb_display *dpy)
+    *yagl_egl_offscreen_display_create_image(struct yagl_eglb_display *dpy,
+                                             yagl_winsys_id buffer)
 {
     struct yagl_egl_offscreen_display *egl_offscreen_dpy =
         (struct yagl_egl_offscreen_display*)dpy;
     struct yagl_egl_offscreen_image *image =
-        yagl_egl_offscreen_image_create(egl_offscreen_dpy);
+        yagl_egl_offscreen_image_create(egl_offscreen_dpy, buffer);
 
     return image ? &image->base : NULL;
 }
index 303b8282b3423afb0a90b5bbe05be7a9db201f2f..bb911a4dee0af052294ad6a62b2c318948ecc7be 100644 (file)
@@ -61,7 +61,8 @@ static void yagl_egl_offscreen_image_destroy(struct yagl_eglb_image *image)
 }
 
 struct yagl_egl_offscreen_image
-    *yagl_egl_offscreen_image_create(struct yagl_egl_offscreen_display *dpy)
+    *yagl_egl_offscreen_image_create(struct yagl_egl_offscreen_display *dpy,
+                                     yagl_winsys_id buffer)
 {
     struct yagl_egl_offscreen_image *image;
 
@@ -70,7 +71,7 @@ struct yagl_egl_offscreen_image
 
     image = g_malloc0(sizeof(*image));
 
-    yagl_eglb_image_init(&image->base, &dpy->base);
+    yagl_eglb_image_init(&image->base, buffer, &dpy->base);
 
     qemu_mutex_init(&image->update_mtx);
 
index 899089c3e14e3c81d0b3f5ecf1bcb8af04131dc6..c032a0e0db3ac91effbe7d195a0c2e142dfecff1 100644 (file)
@@ -17,6 +17,7 @@ struct yagl_egl_offscreen_image
 };
 
 struct yagl_egl_offscreen_image
-    *yagl_egl_offscreen_image_create(struct yagl_egl_offscreen_display *dpy);
+    *yagl_egl_offscreen_image_create(struct yagl_egl_offscreen_display *dpy,
+                                     yagl_winsys_id buffer);
 
 #endif
index cd44c0bea5429a35be5b3bf75bd3698d06bc480b..3860d444fa92418e778246e37d088fbe28fae732 100644 (file)
@@ -121,7 +121,8 @@ static bool yagl_egl_offscreen_surface_swap_buffers(struct yagl_eglb_surface *sf
     return true;
 }
 
-static bool yagl_egl_offscreen_surface_copy_buffers(struct yagl_eglb_surface *sfc)
+static bool yagl_egl_offscreen_surface_copy_buffers(struct yagl_eglb_surface *sfc,
+                                                    yagl_winsys_id target)
 {
     struct yagl_egl_offscreen_surface *osfc =
         (struct yagl_egl_offscreen_surface*)sfc;
index b6c227d83c27980a1163bb563cb06476ca92ad18..ac699f875d4cd6f9cad8d81924e06b116ec88bd4 100644 (file)
@@ -1,12 +1,10 @@
 #include "yagl_egl_offscreen_ts.h"
 
-struct yagl_egl_offscreen_ts *yagl_egl_offscreen_ts_create(struct yagl_egl_driver *driver)
+struct yagl_egl_offscreen_ts *yagl_egl_offscreen_ts_create(void)
 {
     struct yagl_egl_offscreen_ts *egl_offscreen_ts =
         g_malloc0(sizeof(struct yagl_egl_offscreen_ts));
 
-    egl_offscreen_ts->driver = driver;
-
     return egl_offscreen_ts;
 }
 
index 1db8866a95d41b56730a3848028956787c9bbead..615009caebe7ccf1151324d3824c3ead85801213 100644 (file)
@@ -3,19 +3,16 @@
 
 #include "yagl_types.h"
 
-struct yagl_egl_driver;
 struct yagl_egl_offscreen_display;
 struct yagl_egl_offscreen_context;
 
 struct yagl_egl_offscreen_ts
 {
-    struct yagl_egl_driver *driver;
-
     struct yagl_egl_offscreen_display *dpy;
     struct yagl_egl_offscreen_context *ctx;
 };
 
-struct yagl_egl_offscreen_ts *yagl_egl_offscreen_ts_create(struct yagl_egl_driver *driver);
+struct yagl_egl_offscreen_ts *yagl_egl_offscreen_ts_create(void);
 
 void yagl_egl_offscreen_ts_destroy(struct yagl_egl_offscreen_ts *egl_offscreen_ts);
 
diff --git a/hw/yagl_backends/egl_onscreen/yagl_egl_onscreen.c b/hw/yagl_backends/egl_onscreen/yagl_egl_onscreen.c
new file mode 100644 (file)
index 0000000..097171d
--- /dev/null
@@ -0,0 +1,354 @@
+#include "yagl_egl_onscreen.h"
+#include <GL/gl.h>
+#include "yagl_egl_onscreen_ts.h"
+#include "yagl_egl_onscreen_display.h"
+#include "yagl_egl_onscreen_context.h"
+#include "yagl_egl_onscreen_surface.h"
+#include "yagl_tls.h"
+#include "yagl_log.h"
+#include "yagl_process.h"
+#include "yagl_thread.h"
+#include "yagl_gles_driver.h"
+#include "winsys_gl.h"
+
+YAGL_DEFINE_TLS(struct yagl_egl_onscreen_ts*, egl_onscreen_ts);
+
+static void yagl_egl_onscreen_setup_framebuffer_zero(struct yagl_egl_onscreen *egl_onscreen)
+{
+    GLuint cur_fb = 0;
+
+    assert(egl_onscreen_ts->dpy);
+
+    yagl_egl_onscreen_surface_setup(egl_onscreen_ts->sfc_draw);
+    yagl_egl_onscreen_context_setup(egl_onscreen_ts->ctx);
+
+    egl_onscreen->gles_driver->GetIntegerv(GL_FRAMEBUFFER_BINDING,
+                                           (GLint*)&cur_fb);
+
+    egl_onscreen->gles_driver->BindFramebuffer(GL_FRAMEBUFFER,
+                                               egl_onscreen_ts->ctx->fb);
+
+    yagl_egl_onscreen_surface_attach_to_framebuffer(egl_onscreen_ts->sfc_draw);
+
+    egl_onscreen->gles_driver->BindFramebuffer(GL_FRAMEBUFFER,
+                                               cur_fb);
+}
+
+static void yagl_egl_onscreen_thread_init(struct yagl_egl_backend *backend)
+{
+    struct yagl_egl_onscreen *egl_onscreen = (struct yagl_egl_onscreen*)backend;
+
+    YAGL_LOG_FUNC_ENTER(yagl_egl_onscreen_thread_init, NULL);
+
+    egl_onscreen_ts = yagl_egl_onscreen_ts_create(egl_onscreen->gles_driver);
+
+    YAGL_LOG_FUNC_EXIT(NULL);
+}
+
+static void yagl_egl_onscreen_pre_batch(struct yagl_egl_backend *backend)
+{
+    struct yagl_egl_onscreen *egl_onscreen = (struct yagl_egl_onscreen*)backend;
+
+    if (!egl_onscreen_ts->dpy) {
+        return;
+    }
+
+    if (egl_onscreen_ts->sfc_draw->needs_update) {
+        yagl_egl_onscreen_setup_framebuffer_zero(egl_onscreen);
+    }
+}
+
+static struct yagl_eglb_display *yagl_egl_onscreen_create_display(struct yagl_egl_backend *backend)
+{
+    struct yagl_egl_onscreen *egl_onscreen = (struct yagl_egl_onscreen*)backend;
+    struct yagl_egl_onscreen_display *dpy =
+        yagl_egl_onscreen_display_create(egl_onscreen);
+
+    return dpy ? &dpy->base : NULL;
+}
+
+static bool yagl_egl_onscreen_make_current(struct yagl_egl_backend *backend,
+                                           struct yagl_eglb_display *dpy,
+                                           struct yagl_eglb_context *ctx,
+                                           struct yagl_eglb_surface *draw,
+                                           struct yagl_eglb_surface *read)
+{
+    struct yagl_egl_onscreen *egl_onscreen = (struct yagl_egl_onscreen*)backend;
+    struct yagl_egl_onscreen_display *egl_onscreen_dpy = (struct yagl_egl_onscreen_display*)dpy;
+    struct yagl_egl_onscreen_context *egl_onscreen_ctx = (struct yagl_egl_onscreen_context*)ctx;
+    struct yagl_egl_onscreen_surface *egl_onscreen_draw = (struct yagl_egl_onscreen_surface*)draw;
+    struct yagl_egl_onscreen_surface *egl_onscreen_read = (struct yagl_egl_onscreen_surface*)read;
+    bool res;
+
+    YAGL_LOG_FUNC_ENTER(yagl_egl_onscreen_make_current, NULL);
+
+    res = egl_onscreen->egl_driver->make_current(egl_onscreen->egl_driver,
+                                                 egl_onscreen_dpy->native_dpy,
+                                                 egl_onscreen_draw->dummy_native_sfc,
+                                                 egl_onscreen_read->dummy_native_sfc,
+                                                 egl_onscreen_ctx->native_ctx);
+
+    if (res) {
+        GLuint cur_fb = 0;
+
+        egl_onscreen_ts->dpy = egl_onscreen_dpy;
+        egl_onscreen_ts->ctx = egl_onscreen_ctx;
+        egl_onscreen_ts->sfc_draw = egl_onscreen_draw;
+        egl_onscreen_ts->sfc_read = egl_onscreen_read;
+
+        yagl_egl_onscreen_setup_framebuffer_zero(egl_onscreen);
+
+        egl_onscreen->gles_driver->GetIntegerv(GL_FRAMEBUFFER_BINDING,
+                                               (GLint*)&cur_fb);
+
+        if (cur_fb == 0) {
+            /*
+             * No framebuffer, then bind our framebuffer zero.
+             */
+
+            egl_onscreen->gles_driver->BindFramebuffer(GL_FRAMEBUFFER,
+                                                       egl_onscreen_ctx->fb);
+
+            /*
+             * Setup default viewport and scissor.
+             */
+            egl_onscreen->gles_driver->Viewport(0,
+                0,
+                yagl_egl_onscreen_surface_width(egl_onscreen_draw),
+                yagl_egl_onscreen_surface_height(egl_onscreen_draw));
+            egl_onscreen->gles_driver->Scissor(0,
+                0,
+                yagl_egl_onscreen_surface_width(egl_onscreen_draw),
+                yagl_egl_onscreen_surface_height(egl_onscreen_draw));
+        }
+    }
+
+    YAGL_LOG_FUNC_EXIT("%d", res);
+
+    return res;
+}
+
+static bool yagl_egl_onscreen_release_current(struct yagl_egl_backend *backend, bool force)
+{
+    struct yagl_egl_onscreen *egl_onscreen = (struct yagl_egl_onscreen*)backend;
+    bool res;
+
+    YAGL_LOG_FUNC_ENTER(yagl_egl_onscreen_release_current, NULL);
+
+    assert(egl_onscreen_ts->dpy);
+
+    if (!egl_onscreen_ts->dpy) {
+        return false;
+    }
+
+    res = egl_onscreen->egl_driver->make_current(egl_onscreen->egl_driver,
+                                                 egl_onscreen_ts->dpy->native_dpy,
+                                                 EGL_NO_SURFACE,
+                                                 EGL_NO_SURFACE,
+                                                 EGL_NO_CONTEXT);
+
+    if (res || force) {
+        egl_onscreen_ts->dpy = NULL;
+        egl_onscreen_ts->ctx = NULL;
+        egl_onscreen_ts->sfc_draw = NULL;
+        egl_onscreen_ts->sfc_read = NULL;
+    }
+
+    YAGL_LOG_FUNC_EXIT("%d", res);
+
+    return res || force;
+}
+
+static void yagl_egl_onscreen_wait_native(struct yagl_egl_backend *backend)
+{
+    struct yagl_egl_onscreen *egl_onscreen = (struct yagl_egl_onscreen*)backend;
+
+    YAGL_LOG_FUNC_ENTER(yagl_egl_onscreen_wait_native, NULL);
+
+    egl_onscreen->egl_driver->wait_native(egl_onscreen->egl_driver);
+
+    YAGL_LOG_FUNC_EXIT(NULL);
+}
+
+static void yagl_egl_onscreen_thread_fini(struct yagl_egl_backend *backend)
+{
+    YAGL_LOG_FUNC_ENTER(yagl_egl_onscreen_thread_fini, NULL);
+
+    yagl_egl_onscreen_ts_destroy(egl_onscreen_ts);
+    egl_onscreen_ts = NULL;
+
+    YAGL_LOG_FUNC_EXIT(NULL);
+}
+
+static void yagl_egl_onscreen_ensure_current(struct yagl_egl_backend *backend)
+{
+    struct yagl_egl_onscreen *egl_onscreen = (struct yagl_egl_onscreen*)backend;
+
+    if (egl_onscreen_ts && egl_onscreen_ts->dpy) {
+        return;
+    }
+
+    egl_onscreen->egl_driver->make_current(egl_onscreen->egl_driver,
+                                           egl_onscreen->ensure_dpy,
+                                           egl_onscreen->ensure_sfc,
+                                           egl_onscreen->ensure_sfc,
+                                           egl_onscreen->ensure_ctx);
+}
+
+static void yagl_egl_onscreen_unensure_current(struct yagl_egl_backend *backend)
+{
+    struct yagl_egl_onscreen *egl_onscreen = (struct yagl_egl_onscreen*)backend;
+
+    if (egl_onscreen_ts && egl_onscreen_ts->dpy) {
+        return;
+    }
+
+    egl_onscreen->egl_driver->make_current(egl_onscreen->egl_driver,
+                                           egl_onscreen->ensure_dpy,
+                                           EGL_NO_SURFACE,
+                                           EGL_NO_SURFACE,
+                                           EGL_NO_CONTEXT);
+}
+
+static void yagl_egl_onscreen_destroy(struct yagl_egl_backend *backend)
+{
+    struct yagl_egl_onscreen *egl_onscreen = (struct yagl_egl_onscreen*)backend;
+
+    YAGL_LOG_FUNC_ENTER(yagl_egl_onscreen_destroy, NULL);
+
+    egl_onscreen->egl_driver->context_destroy(egl_onscreen->egl_driver,
+                                              egl_onscreen->ensure_dpy,
+                                              egl_onscreen->global_ctx);
+    egl_onscreen->egl_driver->context_destroy(egl_onscreen->egl_driver,
+                                              egl_onscreen->ensure_dpy,
+                                              egl_onscreen->ensure_ctx);
+    egl_onscreen->egl_driver->pbuffer_surface_destroy(egl_onscreen->egl_driver,
+                                                      egl_onscreen->ensure_dpy,
+                                                      egl_onscreen->ensure_sfc);
+    egl_onscreen->egl_driver->config_cleanup(egl_onscreen->egl_driver,
+                                             egl_onscreen->ensure_dpy,
+                                             &egl_onscreen->ensure_config);
+    egl_onscreen->egl_driver->display_close(egl_onscreen->egl_driver,
+                                            egl_onscreen->ensure_dpy);
+
+    egl_onscreen->egl_driver->destroy(egl_onscreen->egl_driver);
+    egl_onscreen->egl_driver = NULL;
+
+    yagl_egl_backend_cleanup(&egl_onscreen->base);
+
+    g_free(egl_onscreen);
+
+    YAGL_LOG_FUNC_EXIT(NULL);
+}
+
+struct yagl_egl_backend *yagl_egl_onscreen_create(struct winsys_interface *wsi,
+                                                  struct yagl_egl_driver *egl_driver,
+                                                  struct yagl_gles_driver *gles_driver)
+{
+    struct yagl_egl_onscreen *egl_onscreen = g_malloc0(sizeof(struct yagl_egl_onscreen));
+    EGLNativeDisplayType dpy = NULL;
+    struct yagl_egl_native_config *configs = NULL;
+    int i, num_configs = 0;
+    struct yagl_egl_pbuffer_attribs attribs;
+    EGLSurface sfc = EGL_NO_SURFACE;
+    EGLContext ctx = EGL_NO_CONTEXT;
+    EGLContext global_ctx = EGL_NO_CONTEXT;
+    struct winsys_gl_info *ws_info = (struct winsys_gl_info*)wsi->ws_info;
+
+    YAGL_LOG_FUNC_ENTER(yagl_egl_onscreen_create, NULL);
+
+    yagl_egl_pbuffer_attribs_init(&attribs);
+
+    yagl_egl_backend_init(&egl_onscreen->base, yagl_render_type_onscreen);
+
+    dpy = egl_driver->display_open(egl_driver);
+
+    if (!dpy) {
+        goto fail;
+    }
+
+    configs = egl_driver->config_enum(egl_driver, dpy, &num_configs);
+
+    if (!configs || (num_configs <= 0)) {
+        goto fail;
+    }
+
+    sfc = egl_driver->pbuffer_surface_create(egl_driver, dpy, &configs[0],
+                                             1, 1, &attribs);
+
+    if (sfc == EGL_NO_SURFACE) {
+        goto fail;
+    }
+
+    ctx = egl_driver->context_create(egl_driver, dpy, &configs[0],
+                                     yagl_client_api_gles2,
+                                     (EGLContext)ws_info->context);
+
+    if (ctx == EGL_NO_CONTEXT) {
+        goto fail;
+    }
+
+    global_ctx = egl_driver->context_create(egl_driver, dpy, &configs[0],
+                                            yagl_client_api_gles2, ctx);
+
+    if (global_ctx == EGL_NO_CONTEXT) {
+        goto fail;
+    }
+
+    egl_onscreen->base.thread_init = &yagl_egl_onscreen_thread_init;
+    egl_onscreen->base.pre_batch = &yagl_egl_onscreen_pre_batch;
+    egl_onscreen->base.create_display = &yagl_egl_onscreen_create_display;
+    egl_onscreen->base.make_current = &yagl_egl_onscreen_make_current;
+    egl_onscreen->base.release_current = &yagl_egl_onscreen_release_current;
+    egl_onscreen->base.wait_native = &yagl_egl_onscreen_wait_native;
+    egl_onscreen->base.thread_fini = &yagl_egl_onscreen_thread_fini;
+    egl_onscreen->base.ensure_current = &yagl_egl_onscreen_ensure_current;
+    egl_onscreen->base.unensure_current = &yagl_egl_onscreen_unensure_current;
+    egl_onscreen->base.destroy = &yagl_egl_onscreen_destroy;
+
+    egl_onscreen->wsi = wsi;
+    egl_onscreen->egl_driver = egl_driver;
+    egl_onscreen->gles_driver = gles_driver;
+    egl_onscreen->ensure_dpy = dpy;
+    egl_onscreen->ensure_config = configs[0];
+    egl_onscreen->ensure_ctx = ctx;
+    egl_onscreen->ensure_sfc = sfc;
+    egl_onscreen->global_ctx = global_ctx;
+
+    for (i = 1; i < num_configs; ++i) {
+        egl_driver->config_cleanup(egl_driver, dpy, &configs[i]);
+    }
+    g_free(configs);
+
+    YAGL_LOG_FUNC_EXIT(NULL);
+
+    return &egl_onscreen->base;
+
+fail:
+    if (ctx != EGL_NO_CONTEXT) {
+        egl_driver->context_destroy(egl_driver, dpy, ctx);
+    }
+
+    if (sfc != EGL_NO_SURFACE) {
+        egl_driver->pbuffer_surface_destroy(egl_driver, dpy, sfc);
+    }
+
+    if (configs) {
+        for (i = 0; i < num_configs; ++i) {
+            egl_driver->config_cleanup(egl_driver, dpy, &configs[i]);
+        }
+        g_free(configs);
+    }
+
+    if (dpy) {
+        egl_driver->display_close(egl_driver, dpy);
+    }
+
+    yagl_egl_backend_cleanup(&egl_onscreen->base);
+
+    g_free(egl_onscreen);
+
+    YAGL_LOG_FUNC_EXIT(NULL);
+
+    return NULL;
+}
diff --git a/hw/yagl_backends/egl_onscreen/yagl_egl_onscreen.h b/hw/yagl_backends/egl_onscreen/yagl_egl_onscreen.h
new file mode 100644 (file)
index 0000000..d10bbb5
--- /dev/null
@@ -0,0 +1,47 @@
+#ifndef _QEMU_YAGL_EGL_ONSCREEN_H
+#define _QEMU_YAGL_EGL_ONSCREEN_H
+
+#include "yagl_egl_backend.h"
+#include "yagl_egl_driver.h"
+#include "yagl_egl_native_config.h"
+
+struct winsys_interface;
+struct yagl_gles_driver;
+
+struct yagl_egl_onscreen
+{
+    struct yagl_egl_backend base;
+
+    struct winsys_interface *wsi;
+
+    struct yagl_egl_driver *egl_driver;
+
+    struct yagl_gles_driver *gles_driver;
+
+    /*
+     * Display, config, context and surface which'll be used
+     * when we need to ensure that at least some context
+     * is current.
+     */
+    EGLNativeDisplayType ensure_dpy;
+    struct yagl_egl_native_config ensure_config;
+    EGLContext ensure_ctx;
+    EGLSurface ensure_sfc;
+
+    /*
+     * Global context, all created contexts share with it. This
+     * context is never current to any thread (And never make it
+     * current because on windows it's impossible to share with
+     * a context that's current).
+     */
+    EGLContext global_ctx;
+};
+
+/*
+ * Takes ownership of 'egl_driver'.
+ */
+struct yagl_egl_backend *yagl_egl_onscreen_create(struct winsys_interface *wsi,
+                                                  struct yagl_egl_driver *egl_driver,
+                                                  struct yagl_gles_driver *gles_driver);
+
+#endif
diff --git a/hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_context.c b/hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_context.c
new file mode 100644 (file)
index 0000000..67b1197
--- /dev/null
@@ -0,0 +1,92 @@
+#include <GL/gl.h>
+#include "yagl_egl_onscreen_context.h"
+#include "yagl_egl_onscreen_display.h"
+#include "yagl_egl_onscreen.h"
+#include "yagl_egl_native_config.h"
+#include "yagl_client_context.h"
+#include "yagl_gles_driver.h"
+#include "yagl_log.h"
+#include "yagl_tls.h"
+#include "yagl_process.h"
+#include "yagl_thread.h"
+
+static void yagl_egl_onscreen_context_destroy(struct yagl_eglb_context *ctx)
+{
+    struct yagl_egl_onscreen_context *egl_onscreen_ctx =
+        (struct yagl_egl_onscreen_context*)ctx;
+    struct yagl_egl_onscreen_display *dpy =
+        (struct yagl_egl_onscreen_display*)ctx->dpy;
+    struct yagl_egl_onscreen *egl_onscreen =
+        (struct yagl_egl_onscreen*)ctx->dpy->backend;
+
+    YAGL_LOG_FUNC_ENTER(yagl_egl_onscreen_context_destroy, NULL);
+
+    if (egl_onscreen_ctx->fb) {
+        yagl_ensure_ctx();
+        egl_onscreen->gles_driver->DeleteFramebuffers(1, &egl_onscreen_ctx->fb);
+        yagl_unensure_ctx();
+    }
+
+    egl_onscreen->egl_driver->context_destroy(egl_onscreen->egl_driver,
+                                              dpy->native_dpy,
+                                              egl_onscreen_ctx->native_ctx);
+
+    yagl_eglb_context_cleanup(ctx);
+
+    g_free(egl_onscreen_ctx);
+
+    YAGL_LOG_FUNC_EXIT(NULL);
+}
+
+struct yagl_egl_onscreen_context
+    *yagl_egl_onscreen_context_create(struct yagl_egl_onscreen_display *dpy,
+                                      const struct yagl_egl_native_config *cfg,
+                                      struct yagl_client_context *client_ctx,
+                                      struct yagl_egl_onscreen_context *share_context)
+{
+    struct yagl_egl_onscreen *egl_onscreen =
+        (struct yagl_egl_onscreen*)dpy->base.backend;
+    struct yagl_egl_onscreen_context *ctx;
+    EGLContext native_ctx;
+
+    YAGL_LOG_FUNC_ENTER(yagl_egl_onscreen_context_create,
+                        "dpy = %p, cfg = %d",
+                        dpy,
+                        cfg->config_id);
+
+    native_ctx = egl_onscreen->egl_driver->context_create(
+        egl_onscreen->egl_driver,
+        dpy->native_dpy,
+        cfg,
+        client_ctx->client_api,
+        (share_context ? share_context->native_ctx : egl_onscreen->global_ctx));
+
+    if (!native_ctx) {
+        YAGL_LOG_FUNC_EXIT(NULL);
+        return NULL;
+    }
+
+    ctx = g_malloc0(sizeof(*ctx));
+
+    yagl_eglb_context_init(&ctx->base, &dpy->base, client_ctx);
+
+    ctx->base.destroy = &yagl_egl_onscreen_context_destroy;
+
+    ctx->native_ctx = native_ctx;
+
+    YAGL_LOG_FUNC_EXIT(NULL);
+
+    return ctx;
+}
+
+void yagl_egl_onscreen_context_setup(struct yagl_egl_onscreen_context *ctx)
+{
+    struct yagl_egl_onscreen *egl_onscreen =
+        (struct yagl_egl_onscreen*)ctx->base.dpy->backend;
+
+    if (ctx->fb) {
+        return;
+    }
+
+    egl_onscreen->gles_driver->GenFramebuffers(1, &ctx->fb);
+}
diff --git a/hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_context.h b/hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_context.h
new file mode 100644 (file)
index 0000000..13c4b59
--- /dev/null
@@ -0,0 +1,34 @@
+#ifndef _QEMU_YAGL_EGL_ONSCREEN_CONTEXT_H
+#define _QEMU_YAGL_EGL_ONSCREEN_CONTEXT_H
+
+#include "yagl_eglb_context.h"
+#include <EGL/egl.h>
+
+struct yagl_egl_onscreen_display;
+struct yagl_egl_onscreen_surface;
+struct yagl_egl_native_config;
+
+struct yagl_egl_onscreen_context
+{
+    struct yagl_eglb_context base;
+
+    EGLContext native_ctx;
+
+    /*
+     * Framebuffer that is used to render to window/pixmap/pbuffer texture.
+     * Allocated when this context is made current for the first time.
+     *
+     * Onscreen GLES API redirects framebuffer zero to this framebuffer.
+     */
+    GLuint fb;
+};
+
+struct yagl_egl_onscreen_context
+    *yagl_egl_onscreen_context_create(struct yagl_egl_onscreen_display *dpy,
+                                      const struct yagl_egl_native_config *cfg,
+                                      struct yagl_client_context *client_ctx,
+                                      struct yagl_egl_onscreen_context *share_context);
+
+void yagl_egl_onscreen_context_setup(struct yagl_egl_onscreen_context *ctx);
+
+#endif
diff --git a/hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_display.c b/hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_display.c
new file mode 100644 (file)
index 0000000..398dccf
--- /dev/null
@@ -0,0 +1,191 @@
+#include "yagl_egl_onscreen_display.h"
+#include <GL/gl.h>
+#include "yagl_egl_onscreen_context.h"
+#include "yagl_egl_onscreen_surface.h"
+#include "yagl_egl_onscreen_image.h"
+#include "yagl_egl_onscreen.h"
+#include "yagl_egl_native_config.h"
+#include "yagl_log.h"
+#include "yagl_tls.h"
+#include "yagl_process.h"
+#include "yagl_thread.h"
+
+static struct yagl_egl_native_config
+    *yagl_egl_onscreen_display_config_enum(struct yagl_eglb_display *dpy,
+                                            int *num_configs)
+{
+    struct yagl_egl_onscreen_display *egl_onscreen_dpy =
+        (struct yagl_egl_onscreen_display*)dpy;
+    struct yagl_egl_onscreen *egl_onscreen =
+        (struct yagl_egl_onscreen*)dpy->backend;
+    struct yagl_egl_native_config *native_configs;
+
+    YAGL_LOG_FUNC_ENTER(yagl_egl_onscreen_display_config_enum,
+                        "dpy = %p", dpy);
+
+    native_configs =
+        egl_onscreen->egl_driver->config_enum(egl_onscreen->egl_driver,
+                                              egl_onscreen_dpy->native_dpy,
+                                              num_configs);
+
+    YAGL_LOG_FUNC_EXIT(NULL);
+
+    return native_configs;
+}
+
+static void yagl_egl_onscreen_display_config_cleanup(struct yagl_eglb_display *dpy,
+    const struct yagl_egl_native_config *cfg)
+{
+    struct yagl_egl_onscreen_display *egl_onscreen_dpy =
+        (struct yagl_egl_onscreen_display*)dpy;
+    struct yagl_egl_onscreen *egl_onscreen =
+        (struct yagl_egl_onscreen*)dpy->backend;
+
+    YAGL_LOG_FUNC_ENTER(yagl_egl_onscreen_display_config_cleanup,
+                        "dpy = %p, cfg = %d",
+                        dpy,
+                        cfg->config_id);
+
+    egl_onscreen->egl_driver->config_cleanup(egl_onscreen->egl_driver,
+                                             egl_onscreen_dpy->native_dpy,
+                                             cfg);
+
+    YAGL_LOG_FUNC_EXIT(NULL);
+}
+
+static struct yagl_eglb_context
+    *yagl_egl_onscreen_display_create_context(struct yagl_eglb_display *dpy,
+                                              const struct yagl_egl_native_config *cfg,
+                                              struct yagl_client_context *client_ctx,
+                                              struct yagl_eglb_context *share_context)
+{
+    struct yagl_egl_onscreen_display *egl_onscreen_dpy =
+        (struct yagl_egl_onscreen_display*)dpy;
+    struct yagl_egl_onscreen_context *ctx =
+        yagl_egl_onscreen_context_create(egl_onscreen_dpy,
+                                         cfg,
+                                         client_ctx,
+                                         (struct yagl_egl_onscreen_context*)share_context);
+
+    return ctx ? &ctx->base : NULL;
+}
+
+static struct yagl_eglb_surface
+    *yagl_egl_onscreen_display_create_window_surface(struct yagl_eglb_display *dpy,
+                                                     const struct yagl_egl_native_config *cfg,
+                                                     const struct yagl_egl_window_attribs *attribs,
+                                                     yagl_winsys_id id)
+{
+    struct yagl_egl_onscreen_display *egl_onscreen_dpy =
+        (struct yagl_egl_onscreen_display*)dpy;
+    struct yagl_egl_onscreen_surface *sfc =
+        yagl_egl_onscreen_surface_create_window(egl_onscreen_dpy,
+                                                cfg,
+                                                attribs,
+                                                id);
+
+    return sfc ? &sfc->base : NULL;
+}
+
+static struct yagl_eglb_surface
+    *yagl_egl_onscreen_display_create_pixmap_surface(struct yagl_eglb_display *dpy,
+                                                     const struct yagl_egl_native_config *cfg,
+                                                     const struct yagl_egl_pixmap_attribs *attribs,
+                                                     yagl_winsys_id id)
+{
+    struct yagl_egl_onscreen_display *egl_onscreen_dpy =
+        (struct yagl_egl_onscreen_display*)dpy;
+    struct yagl_egl_onscreen_surface *sfc =
+        yagl_egl_onscreen_surface_create_pixmap(egl_onscreen_dpy,
+                                                cfg,
+                                                attribs,
+                                                id);
+
+    return sfc ? &sfc->base : NULL;
+}
+
+static struct yagl_eglb_surface
+    *yagl_egl_onscreen_display_create_pbuffer_surface(struct yagl_eglb_display *dpy,
+                                                      const struct yagl_egl_native_config *cfg,
+                                                      const struct yagl_egl_pbuffer_attribs *attribs,
+                                                      uint32_t width,
+                                                      uint32_t height)
+{
+    struct yagl_egl_onscreen_display *egl_onscreen_dpy =
+        (struct yagl_egl_onscreen_display*)dpy;
+    struct yagl_egl_onscreen_surface *sfc =
+        yagl_egl_onscreen_surface_create_pbuffer(egl_onscreen_dpy,
+                                                 cfg,
+                                                 attribs,
+                                                 width,
+                                                 height);
+
+    return sfc ? &sfc->base : NULL;
+}
+
+static struct yagl_eglb_image
+    *yagl_egl_onscreen_display_create_image(struct yagl_eglb_display *dpy,
+                                            yagl_winsys_id buffer)
+{
+    struct yagl_egl_onscreen_display *egl_onscreen_dpy =
+        (struct yagl_egl_onscreen_display*)dpy;
+    struct yagl_egl_onscreen_image *image =
+        yagl_egl_onscreen_image_create(egl_onscreen_dpy, buffer);
+
+    return image ? &image->base : NULL;
+}
+
+static void yagl_egl_onscreen_display_destroy(struct yagl_eglb_display *dpy)
+{
+    struct yagl_egl_onscreen_display *egl_onscreen_dpy =
+        (struct yagl_egl_onscreen_display*)dpy;
+    struct yagl_egl_onscreen *egl_onscreen =
+        (struct yagl_egl_onscreen*)dpy->backend;
+
+    YAGL_LOG_FUNC_ENTER(yagl_egl_onscreen_display_destroy,
+                        "dpy = %p", dpy);
+
+    egl_onscreen->egl_driver->display_close(egl_onscreen->egl_driver,
+                                            egl_onscreen_dpy->native_dpy);
+
+    yagl_eglb_display_cleanup(dpy);
+
+    g_free(egl_onscreen_dpy);
+
+    YAGL_LOG_FUNC_EXIT(NULL);
+}
+
+struct yagl_egl_onscreen_display
+    *yagl_egl_onscreen_display_create(struct yagl_egl_onscreen *egl_onscreen)
+{
+    struct yagl_egl_onscreen_display *dpy;
+    EGLNativeDisplayType native_dpy;
+
+    YAGL_LOG_FUNC_ENTER(yagl_egl_onscreen_display_create, NULL);
+
+    native_dpy = egl_onscreen->egl_driver->display_open(egl_onscreen->egl_driver);
+
+    if (!native_dpy) {
+        YAGL_LOG_FUNC_EXIT(NULL);
+        return NULL;
+    }
+
+    dpy = g_malloc0(sizeof(*dpy));
+
+    yagl_eglb_display_init(&dpy->base, &egl_onscreen->base);
+
+    dpy->base.config_enum = &yagl_egl_onscreen_display_config_enum;
+    dpy->base.config_cleanup = &yagl_egl_onscreen_display_config_cleanup;
+    dpy->base.create_context = &yagl_egl_onscreen_display_create_context;
+    dpy->base.create_onscreen_window_surface = &yagl_egl_onscreen_display_create_window_surface;
+    dpy->base.create_onscreen_pixmap_surface = &yagl_egl_onscreen_display_create_pixmap_surface;
+    dpy->base.create_onscreen_pbuffer_surface = &yagl_egl_onscreen_display_create_pbuffer_surface;
+    dpy->base.create_image = &yagl_egl_onscreen_display_create_image;
+    dpy->base.destroy = &yagl_egl_onscreen_display_destroy;
+
+    dpy->native_dpy = native_dpy;
+
+    YAGL_LOG_FUNC_EXIT("%p", dpy);
+
+    return dpy;
+}
diff --git a/hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_display.h b/hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_display.h
new file mode 100644 (file)
index 0000000..e62e837
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef _QEMU_YAGL_EGL_ONSCREEN_DISPLAY_H
+#define _QEMU_YAGL_EGL_ONSCREEN_DISPLAY_H
+
+#include "yagl_eglb_display.h"
+
+struct yagl_egl_onscreen;
+
+struct yagl_egl_onscreen_display
+{
+    struct yagl_eglb_display base;
+
+    EGLNativeDisplayType native_dpy;
+};
+
+struct yagl_egl_onscreen_display
+    *yagl_egl_onscreen_display_create(struct yagl_egl_onscreen *egl_onscreen);
+
+#endif
diff --git a/hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_image.c b/hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_image.c
new file mode 100644 (file)
index 0000000..bf53cbc
--- /dev/null
@@ -0,0 +1,120 @@
+#include "yagl_egl_onscreen_image.h"
+#include "yagl_egl_onscreen_display.h"
+#include "yagl_egl_onscreen.h"
+#include "yagl_log.h"
+#include "yagl_process.h"
+#include "yagl_thread.h"
+#include "yagl_ref.h"
+#include "yagl_client_interface.h"
+#include <GL/gl.h>
+#include "winsys_gl.h"
+
+struct yagl_egl_onscreen_image_data
+{
+    struct yagl_ref ref;
+
+    struct winsys_gl_surface *ws_sfc;
+};
+
+static void yagl_egl_onscreen_image_data_destroy(struct yagl_ref *ref)
+{
+    struct yagl_egl_onscreen_image_data *image_data =
+        (struct yagl_egl_onscreen_image_data*)ref;
+
+    image_data->ws_sfc->base.release(&image_data->ws_sfc->base);
+
+    yagl_ref_cleanup(ref);
+
+    g_free(image_data);
+}
+
+static void yagl_egl_onscreen_image_destroy(struct yagl_eglb_image *image)
+{
+    struct yagl_egl_onscreen_image *oimage =
+        (struct yagl_egl_onscreen_image*)image;
+
+    YAGL_LOG_FUNC_ENTER(yagl_egl_onscreen_image_destroy, NULL);
+
+    yagl_eglb_image_cleanup(image);
+
+    g_free(oimage);
+
+    YAGL_LOG_FUNC_EXIT(NULL);
+}
+
+struct yagl_egl_onscreen_image
+    *yagl_egl_onscreen_image_create(struct yagl_egl_onscreen_display *dpy,
+                                    yagl_winsys_id buffer)
+{
+    struct yagl_egl_onscreen *egl_onscreen =
+        (struct yagl_egl_onscreen*)dpy->base.backend;
+    struct winsys_resource *ws_res = NULL;
+    struct winsys_gl_surface *ws_sfc = NULL;
+    struct yagl_client_interface *client_iface = NULL;
+    struct yagl_egl_onscreen_image_data *image_data = NULL;
+    struct yagl_client_image *glegl_image = NULL;
+    struct yagl_egl_onscreen_image *image = NULL;
+
+    YAGL_LOG_FUNC_ENTER(yagl_egl_onscreen_image_create,
+                        "dpy = %p, buffer = 0x%X", dpy, buffer);
+
+    client_iface = cur_ts->ps->client_ifaces[yagl_client_api_gles2];
+
+    if (!client_iface) {
+        YAGL_LOG_ERROR("No GLESv2 API, can't create image");
+        goto out;
+    }
+
+    ws_res = egl_onscreen->wsi->acquire_resource(egl_onscreen->wsi, buffer);
+
+    if (!ws_res) {
+        goto out;
+    }
+
+    if (ws_res->type != winsys_res_type_pixmap) {
+        goto out;
+    }
+
+    ws_sfc = (struct winsys_gl_surface*)ws_res->acquire_surface(ws_res);
+
+    if (!ws_sfc) {
+        goto out;
+    }
+
+    image_data = g_malloc0(sizeof(*image_data));
+
+    yagl_ref_init(&image_data->ref, &yagl_egl_onscreen_image_data_destroy);
+
+    glegl_image = client_iface->create_image(client_iface,
+                                             ws_sfc->get_front_texture(ws_sfc),
+                                             &image_data->ref);
+
+    if (!glegl_image) {
+        yagl_ref_cleanup(&image_data->ref);
+        g_free(image_data);
+        goto out;
+    }
+
+    ws_sfc->base.acquire(&ws_sfc->base);
+    image_data->ws_sfc = ws_sfc;
+
+    image = g_malloc0(sizeof(*image));
+
+    yagl_eglb_image_init(&image->base, buffer, &dpy->base);
+
+    image->base.glegl_image = glegl_image;
+    image->base.destroy = &yagl_egl_onscreen_image_destroy;
+
+out:
+    if (ws_sfc) {
+        ws_sfc->base.release(&ws_sfc->base);
+    }
+
+    if (ws_res) {
+        ws_res->release(ws_res);
+    }
+
+    YAGL_LOG_FUNC_EXIT(NULL);
+
+    return image;
+}
diff --git a/hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_image.h b/hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_image.h
new file mode 100644 (file)
index 0000000..e40ef49
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef _QEMU_YAGL_EGL_onscreen_IMAGE_H
+#define _QEMU_YAGL_EGL_onscreen_IMAGE_H
+
+#include "yagl_eglb_image.h"
+
+struct yagl_egl_onscreen_display;
+
+struct yagl_egl_onscreen_image
+{
+    struct yagl_eglb_image base;
+};
+
+struct yagl_egl_onscreen_image
+    *yagl_egl_onscreen_image_create(struct yagl_egl_onscreen_display *dpy,
+                                    yagl_winsys_id buffer);
+
+#endif
diff --git a/hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_surface.c b/hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_surface.c
new file mode 100644 (file)
index 0000000..b2897dc
--- /dev/null
@@ -0,0 +1,544 @@
+#include <GL/gl.h>
+#include "yagl_egl_onscreen_surface.h"
+#include "yagl_egl_onscreen_display.h"
+#include "yagl_egl_onscreen.h"
+#include "yagl_log.h"
+#include "yagl_process.h"
+#include "yagl_thread.h"
+#include "yagl_gles_driver.h"
+#include "winsys_gl.h"
+
+static void yagl_egl_onscreen_surface_invalidate(struct yagl_eglb_surface *sfc)
+{
+    sfc->invalid = true;
+}
+
+static bool yagl_egl_onscreen_surface_query(struct yagl_eglb_surface *sfc,
+                                             EGLint attribute,
+                                             EGLint *value)
+{
+    struct yagl_egl_onscreen_surface *osfc =
+        (struct yagl_egl_onscreen_surface*)sfc;
+
+    switch (attribute) {
+    case EGL_HEIGHT:
+        *value = yagl_egl_onscreen_surface_height(osfc);
+        break;
+    case EGL_WIDTH:
+        *value = yagl_egl_onscreen_surface_width(osfc);
+        break;
+    default:
+        return false;
+    }
+
+    return true;
+}
+
+static bool yagl_egl_onscreen_surface_swap_buffers(struct yagl_eglb_surface *sfc)
+{
+    struct yagl_egl_onscreen_surface *osfc =
+        (struct yagl_egl_onscreen_surface*)sfc;
+
+    osfc->ws_sfc->swap_buffers(osfc->ws_sfc);
+
+    return true;
+}
+
+static bool yagl_egl_onscreen_surface_copy_buffers(struct yagl_eglb_surface *sfc,
+                                                   yagl_winsys_id target)
+{
+    struct yagl_egl_onscreen_surface *osfc =
+        (struct yagl_egl_onscreen_surface*)sfc;
+    struct yagl_egl_onscreen *egl_onscreen =
+        (struct yagl_egl_onscreen*)sfc->dpy->backend;
+    struct winsys_resource *ws_res = NULL;
+    struct winsys_gl_surface *ws_sfc = NULL;
+    bool res = false;
+
+    ws_res = egl_onscreen->wsi->acquire_resource(egl_onscreen->wsi, target);
+
+    if (!ws_res) {
+        goto out;
+    }
+
+    if (ws_res->type != winsys_res_type_pixmap) {
+        goto out;
+    }
+
+    ws_sfc = (struct winsys_gl_surface*)ws_res->acquire_surface(ws_res);
+
+    if (!ws_sfc) {
+        goto out;
+    }
+
+    ws_sfc->copy_buffers(yagl_egl_onscreen_surface_width(osfc),
+                         yagl_egl_onscreen_surface_height(osfc),
+                         ws_sfc);
+
+    res = true;
+
+out:
+    if (ws_sfc) {
+        ws_sfc->base.release(&ws_sfc->base);
+    }
+
+    if (ws_res) {
+        ws_res->release(ws_res);
+    }
+
+    return res;
+}
+
+static void yagl_egl_onscreen_surface_update(struct winsys_resource *res,
+                                             void *user_data)
+{
+    struct yagl_egl_onscreen_surface *sfc = user_data;
+
+    YAGL_LOG_FUNC_ENTER(yagl_egl_onscreen_surface_update,
+                        "id = 0x%X",
+                        res->id);
+
+    sfc->needs_update = true;
+
+    YAGL_LOG_FUNC_EXIT(NULL);
+}
+
+static void yagl_egl_onscreen_surface_destroy(struct yagl_eglb_surface *sfc)
+{
+    struct yagl_egl_onscreen_surface *osfc =
+        (struct yagl_egl_onscreen_surface*)sfc;
+    struct yagl_egl_onscreen *egl_onscreen =
+        (struct yagl_egl_onscreen*)sfc->dpy->backend;
+
+    YAGL_LOG_FUNC_ENTER(yagl_egl_onscreen_surface_destroy, NULL);
+
+    if (osfc->cookie) {
+        osfc->ws_res->remove_callback(osfc->ws_res, osfc->cookie);
+        osfc->cookie = NULL;
+    }
+
+    egl_onscreen->egl_driver->pbuffer_surface_destroy(
+        egl_onscreen->egl_driver,
+        ((struct yagl_egl_onscreen_display*)sfc->dpy)->native_dpy,
+        osfc->dummy_native_sfc);
+    osfc->dummy_native_sfc = EGL_NO_SURFACE;
+
+    if (osfc->ws_sfc) {
+        osfc->ws_sfc->base.release(&osfc->ws_sfc->base);
+        osfc->ws_sfc = NULL;
+    }
+
+    if (osfc->ws_res) {
+        osfc->ws_res->release(osfc->ws_res);
+        osfc->ws_res = NULL;
+    }
+
+    if (osfc->pbuffer_tex || osfc->rb) {
+        yagl_ensure_ctx();
+        egl_onscreen->gles_driver->DeleteTextures(1, &osfc->pbuffer_tex);
+        egl_onscreen->gles_driver->DeleteRenderbuffers(1, &osfc->rb);
+        yagl_unensure_ctx();
+    }
+
+    yagl_eglb_surface_cleanup(sfc);
+
+    g_free(osfc);
+
+    YAGL_LOG_FUNC_EXIT(NULL);
+}
+
+struct yagl_egl_onscreen_surface
+    *yagl_egl_onscreen_surface_create_window(struct yagl_egl_onscreen_display *dpy,
+                                             const struct yagl_egl_native_config *cfg,
+                                             const struct yagl_egl_window_attribs *attribs,
+                                             yagl_winsys_id id)
+{
+    struct yagl_egl_onscreen *egl_onscreen =
+        (struct yagl_egl_onscreen*)dpy->base.backend;
+    struct winsys_resource *ws_res = NULL;
+    struct winsys_gl_surface *ws_sfc = NULL;
+    struct yagl_egl_onscreen_surface *sfc = NULL;
+    EGLSurface dummy_native_sfc = EGL_NO_SURFACE;
+    struct yagl_egl_pbuffer_attribs pbuffer_attribs;
+
+    YAGL_LOG_FUNC_ENTER(yagl_egl_onscreen_surface_create_window,
+                        "dpy = %p, cfg = %d, id = 0x%X",
+                        dpy,
+                        cfg->config_id,
+                        id);
+
+    ws_res = egl_onscreen->wsi->acquire_resource(egl_onscreen->wsi, id);
+
+    if (!ws_res) {
+        goto fail;
+    }
+
+    if (ws_res->type != winsys_res_type_window) {
+        goto fail;
+    }
+
+    ws_sfc = (struct winsys_gl_surface*)ws_res->acquire_surface(ws_res);
+
+    if (!ws_sfc) {
+        goto fail;
+    }
+
+    yagl_egl_pbuffer_attribs_init(&pbuffer_attribs);
+
+    dummy_native_sfc = egl_onscreen->egl_driver->pbuffer_surface_create(egl_onscreen->egl_driver,
+                                                                        dpy->native_dpy,
+                                                                        cfg,
+                                                                        1,
+                                                                        1,
+                                                                        &pbuffer_attribs);
+
+    if (!dummy_native_sfc) {
+        goto fail;
+    }
+
+    sfc = g_malloc0(sizeof(*sfc));
+
+    yagl_eglb_surface_init(&sfc->base, &dpy->base, EGL_WINDOW_BIT, attribs);
+
+    sfc->dummy_native_sfc = dummy_native_sfc;
+    sfc->ws_res = ws_res;
+    sfc->ws_sfc = ws_sfc;
+
+    sfc->base.invalidate = &yagl_egl_onscreen_surface_invalidate;
+    sfc->base.query = &yagl_egl_onscreen_surface_query;
+    sfc->base.swap_buffers = &yagl_egl_onscreen_surface_swap_buffers;
+    sfc->base.copy_buffers = &yagl_egl_onscreen_surface_copy_buffers;
+    sfc->base.destroy = &yagl_egl_onscreen_surface_destroy;
+
+    sfc->cookie = ws_res->add_callback(ws_res,
+                                       &yagl_egl_onscreen_surface_update,
+                                       sfc);
+
+    YAGL_LOG_FUNC_EXIT(NULL);
+
+    return sfc;
+
+fail:
+    if (ws_sfc) {
+        ws_sfc->base.release(&ws_sfc->base);
+    }
+
+    if (ws_res) {
+        ws_res->release(ws_res);
+    }
+
+    YAGL_LOG_FUNC_EXIT(NULL);
+
+    return NULL;
+}
+
+struct yagl_egl_onscreen_surface
+    *yagl_egl_onscreen_surface_create_pixmap(struct yagl_egl_onscreen_display *dpy,
+                                             const struct yagl_egl_native_config *cfg,
+                                             const struct yagl_egl_pixmap_attribs *attribs,
+                                             yagl_winsys_id id)
+{
+    struct yagl_egl_onscreen *egl_onscreen =
+        (struct yagl_egl_onscreen*)dpy->base.backend;
+    struct winsys_resource *ws_res = NULL;
+    struct winsys_gl_surface *ws_sfc = NULL;
+    struct yagl_egl_onscreen_surface *sfc = NULL;
+    EGLSurface dummy_native_sfc = EGL_NO_SURFACE;
+    struct yagl_egl_pbuffer_attribs pbuffer_attribs;
+
+    YAGL_LOG_FUNC_ENTER(yagl_egl_onscreen_surface_create_pixmap,
+                        "dpy = %p, cfg = %d, id = 0x%X",
+                        dpy,
+                        cfg->config_id,
+                        id);
+
+    ws_res = egl_onscreen->wsi->acquire_resource(egl_onscreen->wsi, id);
+
+    if (!ws_res) {
+        goto fail;
+    }
+
+    if (ws_res->type != winsys_res_type_pixmap) {
+        goto fail;
+    }
+
+    ws_sfc = (struct winsys_gl_surface*)ws_res->acquire_surface(ws_res);
+
+    if (!ws_sfc) {
+        goto fail;
+    }
+
+    yagl_egl_pbuffer_attribs_init(&pbuffer_attribs);
+
+    dummy_native_sfc = egl_onscreen->egl_driver->pbuffer_surface_create(egl_onscreen->egl_driver,
+                                                                        dpy->native_dpy,
+                                                                        cfg,
+                                                                        1,
+                                                                        1,
+                                                                        &pbuffer_attribs);
+
+    if (!dummy_native_sfc) {
+        goto fail;
+    }
+
+    sfc = g_malloc0(sizeof(*sfc));
+
+    yagl_eglb_surface_init(&sfc->base, &dpy->base, EGL_PIXMAP_BIT, attribs);
+
+    sfc->dummy_native_sfc = dummy_native_sfc;
+    sfc->ws_res = ws_res;
+    sfc->ws_sfc = ws_sfc;
+
+    sfc->base.invalidate = &yagl_egl_onscreen_surface_invalidate;
+    sfc->base.query = &yagl_egl_onscreen_surface_query;
+    sfc->base.swap_buffers = &yagl_egl_onscreen_surface_swap_buffers;
+    sfc->base.copy_buffers = &yagl_egl_onscreen_surface_copy_buffers;
+    sfc->base.destroy = &yagl_egl_onscreen_surface_destroy;
+
+    YAGL_LOG_FUNC_EXIT(NULL);
+
+    return sfc;
+
+fail:
+    if (ws_sfc) {
+        ws_sfc->base.release(&ws_sfc->base);
+    }
+
+    if (ws_res) {
+        ws_res->release(ws_res);
+    }
+
+    YAGL_LOG_FUNC_EXIT(NULL);
+
+    return NULL;
+}
+
+struct yagl_egl_onscreen_surface
+    *yagl_egl_onscreen_surface_create_pbuffer(struct yagl_egl_onscreen_display *dpy,
+                                             const struct yagl_egl_native_config *cfg,
+                                             const struct yagl_egl_pbuffer_attribs *attribs,
+                                             uint32_t width,
+                                             uint32_t height)
+{
+    struct yagl_egl_onscreen *egl_onscreen =
+        (struct yagl_egl_onscreen*)dpy->base.backend;
+    struct yagl_egl_onscreen_surface *sfc = NULL;
+    EGLSurface dummy_native_sfc = EGL_NO_SURFACE;
+    struct yagl_egl_pbuffer_attribs pbuffer_attribs;
+
+    YAGL_LOG_FUNC_ENTER(yagl_egl_onscreen_surface_create_pbuffer,
+                        "dpy = %p, cfg = %d, width = %u, height = %u",
+                        dpy,
+                        cfg->config_id,
+                        width,
+                        height);
+
+    yagl_egl_pbuffer_attribs_init(&pbuffer_attribs);
+
+    dummy_native_sfc = egl_onscreen->egl_driver->pbuffer_surface_create(egl_onscreen->egl_driver,
+                                                                        dpy->native_dpy,
+                                                                        cfg,
+                                                                        1,
+                                                                        1,
+                                                                        &pbuffer_attribs);
+
+    if (!dummy_native_sfc) {
+        goto fail;
+    }
+
+    sfc = g_malloc0(sizeof(*sfc));
+
+    yagl_eglb_surface_init(&sfc->base, &dpy->base, EGL_PBUFFER_BIT, attribs);
+
+    sfc->dummy_native_sfc = dummy_native_sfc;
+    sfc->pbuffer_width = width;
+    sfc->pbuffer_height = height;
+
+    sfc->base.invalidate = &yagl_egl_onscreen_surface_invalidate;
+    sfc->base.query = &yagl_egl_onscreen_surface_query;
+    sfc->base.swap_buffers = &yagl_egl_onscreen_surface_swap_buffers;
+    sfc->base.copy_buffers = &yagl_egl_onscreen_surface_copy_buffers;
+    sfc->base.destroy = &yagl_egl_onscreen_surface_destroy;
+
+    YAGL_LOG_FUNC_EXIT(NULL);
+
+    return sfc;
+
+fail:
+    YAGL_LOG_FUNC_EXIT(NULL);
+
+    return NULL;
+}
+
+void yagl_egl_onscreen_surface_setup(struct yagl_egl_onscreen_surface *sfc)
+{
+    struct yagl_egl_onscreen *egl_onscreen =
+        (struct yagl_egl_onscreen*)sfc->base.dpy->backend;
+    GLuint cur_rb = 0;
+    GLuint cur_tex = 0;
+
+    YAGL_LOG_FUNC_SET(yagl_egl_onscreen_surface_setup);
+
+    if (sfc->needs_update) {
+        struct winsys_gl_surface *ws_sfc = NULL;
+
+        ws_sfc = (struct winsys_gl_surface*)sfc->ws_res->acquire_surface(sfc->ws_res);
+
+        if (ws_sfc) {
+            if (ws_sfc != sfc->ws_sfc) {
+                YAGL_LOG_DEBUG("winsys resource was changed for 0x%X", sfc->ws_res->id);
+
+                if (sfc->rb) {
+                    egl_onscreen->gles_driver->DeleteRenderbuffers(1, &sfc->rb);
+                    sfc->rb = 0;
+                }
+
+                sfc->ws_sfc->base.release(&sfc->ws_sfc->base);
+                ws_sfc->base.acquire(&ws_sfc->base);
+                sfc->ws_sfc = ws_sfc;
+            }
+
+            ws_sfc->base.release(&ws_sfc->base);
+        } else {
+            YAGL_LOG_WARN("winsys resource was destroyed for 0x%X", sfc->ws_res->id);
+        }
+
+        sfc->needs_update = false;
+    }
+
+    switch (sfc->base.type) {
+    case EGL_PBUFFER_BIT:
+        if (!sfc->rb) {
+            egl_onscreen->gles_driver->GenRenderbuffers(1, &sfc->rb);
+
+            egl_onscreen->gles_driver->GetIntegerv(GL_RENDERBUFFER_BINDING,
+                                                   (GLint*)&cur_rb);
+
+            egl_onscreen->gles_driver->BindRenderbuffer(GL_RENDERBUFFER, sfc->rb);
+
+            egl_onscreen->gles_driver->RenderbufferStorage(GL_RENDERBUFFER,
+                                                           GL_DEPTH24_STENCIL8,
+                                                           sfc->pbuffer_width,
+                                                           sfc->pbuffer_height);
+
+            egl_onscreen->gles_driver->BindRenderbuffer(GL_RENDERBUFFER, cur_rb);
+        }
+        if (!sfc->pbuffer_tex) {
+            egl_onscreen->gles_driver->GenTextures(1, &sfc->pbuffer_tex);
+
+            egl_onscreen->gles_driver->GetIntegerv(GL_TEXTURE_BINDING_2D,
+                                                   (GLint*)&cur_tex);
+
+            egl_onscreen->gles_driver->BindTexture(GL_TEXTURE_2D, sfc->pbuffer_tex);
+
+            egl_onscreen->gles_driver->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+            egl_onscreen->gles_driver->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+            egl_onscreen->gles_driver->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+            egl_onscreen->gles_driver->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+            /*
+             * TODO: Use pbuffer attribs to setup texture format
+             * correctly.
+             */
+
+            egl_onscreen->gles_driver->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8,
+                                                  sfc->pbuffer_width,
+                                                  sfc->pbuffer_height, 0,
+                                                  GL_BGRA, GL_UNSIGNED_INT,
+                                                  NULL);
+
+            egl_onscreen->gles_driver->BindTexture(GL_TEXTURE_2D, cur_tex);
+        }
+        break;
+    case EGL_PIXMAP_BIT:
+    case EGL_WINDOW_BIT:
+        if (!sfc->rb) {
+            egl_onscreen->gles_driver->GenRenderbuffers(1, &sfc->rb);
+
+            egl_onscreen->gles_driver->GetIntegerv(GL_RENDERBUFFER_BINDING,
+                                                   (GLint*)&cur_rb);
+
+            egl_onscreen->gles_driver->BindRenderbuffer(GL_RENDERBUFFER, sfc->rb);
+
+            egl_onscreen->gles_driver->RenderbufferStorage(GL_RENDERBUFFER,
+                                                           GL_DEPTH24_STENCIL8,
+                                                           sfc->ws_sfc->base.width,
+                                                           sfc->ws_sfc->base.height);
+
+            egl_onscreen->gles_driver->BindRenderbuffer(GL_RENDERBUFFER, cur_rb);
+        }
+        break;
+    default:
+        assert(false);
+        break;
+    }
+}
+
+void yagl_egl_onscreen_surface_attach_to_framebuffer(struct yagl_egl_onscreen_surface *sfc)
+{
+    struct yagl_egl_onscreen *egl_onscreen =
+        (struct yagl_egl_onscreen*)sfc->base.dpy->backend;
+
+    switch (sfc->base.type) {
+    case EGL_PBUFFER_BIT:
+        egl_onscreen->gles_driver->FramebufferTexture2D(GL_FRAMEBUFFER,
+                                                        GL_COLOR_ATTACHMENT0,
+                                                        GL_TEXTURE_2D,
+                                                        sfc->pbuffer_tex,
+                                                        0);
+        break;
+    case EGL_PIXMAP_BIT:
+        egl_onscreen->gles_driver->FramebufferTexture2D(GL_FRAMEBUFFER,
+                                                        GL_COLOR_ATTACHMENT0,
+                                                        GL_TEXTURE_2D,
+                                                        sfc->ws_sfc->get_front_texture(sfc->ws_sfc),
+                                                        0);
+        break;
+    case EGL_WINDOW_BIT:
+        egl_onscreen->gles_driver->FramebufferTexture2D(GL_FRAMEBUFFER,
+                                                        GL_COLOR_ATTACHMENT0,
+                                                        GL_TEXTURE_2D,
+                                                        sfc->ws_sfc->get_back_texture(sfc->ws_sfc),
+                                                        0);
+        break;
+    default:
+        assert(false);
+        break;
+    }
+    egl_onscreen->gles_driver->FramebufferRenderbuffer(GL_FRAMEBUFFER,
+                                                       GL_DEPTH_ATTACHMENT,
+                                                       GL_RENDERBUFFER,
+                                                       sfc->rb);
+    egl_onscreen->gles_driver->FramebufferRenderbuffer(GL_FRAMEBUFFER,
+                                                       GL_STENCIL_ATTACHMENT,
+                                                       GL_RENDERBUFFER,
+                                                       sfc->rb);
+}
+
+uint32_t yagl_egl_onscreen_surface_width(struct yagl_egl_onscreen_surface *sfc)
+{
+    switch (sfc->base.type) {
+    case EGL_PBUFFER_BIT:
+        return sfc->pbuffer_width;
+    case EGL_PIXMAP_BIT:
+    case EGL_WINDOW_BIT:
+        return sfc->ws_sfc->base.width;
+    default:
+        assert(false);
+        return 0;
+    }
+}
+
+uint32_t yagl_egl_onscreen_surface_height(struct yagl_egl_onscreen_surface *sfc)
+{
+    switch (sfc->base.type) {
+    case EGL_PBUFFER_BIT:
+        return sfc->pbuffer_height;
+    case EGL_PIXMAP_BIT:
+    case EGL_WINDOW_BIT:
+        return sfc->ws_sfc->base.height;
+    default:
+        assert(false);
+        return 0;
+    }
+}
diff --git a/hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_surface.h b/hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_surface.h
new file mode 100644 (file)
index 0000000..e1be1e1
--- /dev/null
@@ -0,0 +1,86 @@
+#ifndef _QEMU_YAGL_EGL_ONSCREEN_SURFACE_H
+#define _QEMU_YAGL_EGL_ONSCREEN_SURFACE_H
+
+#include "yagl_eglb_surface.h"
+#include "yagl_egl_surface_attribs.h"
+
+struct yagl_egl_onscreen_display;
+struct yagl_egl_native_config;
+
+struct winsys_resource;
+struct winsys_gl_surface;
+
+struct yagl_egl_onscreen_surface
+{
+    struct yagl_eglb_surface base;
+
+    /*
+     * 1x1 native pbuffer surface, used just to be able to make
+     * this surface current.
+     */
+    EGLSurface dummy_native_sfc;
+
+    /*
+     * winsys resource in case if this is a window or pixmap surface.
+     */
+    struct winsys_resource *ws_res;
+
+    /*
+     * winsys surface in case if this is a window or pixmap surface.
+     */
+    struct winsys_gl_surface *ws_sfc;
+
+    /*
+     * Callback cookie from ws_res::add_callback.
+     */
+    void *cookie;
+
+    /*
+     * pbuffer texture in case if this is a pbuffer surface. Allocated
+     * when this surface is made current for the first time.
+     */
+    GLuint pbuffer_tex;
+    uint32_t pbuffer_width;
+    uint32_t pbuffer_height;
+
+    /*
+     * Depth and stencil renderbuffer for 'ws_sfc'/'pbuffer_tex'. Allocated
+     * when this surface is made current for the first time.
+     */
+    GLuint rb;
+
+    /*
+     * This surface has been changed on target and
+     * needs update on host.
+     */
+    bool needs_update;
+};
+
+struct yagl_egl_onscreen_surface
+    *yagl_egl_onscreen_surface_create_window(struct yagl_egl_onscreen_display *dpy,
+                                             const struct yagl_egl_native_config *cfg,
+                                             const struct yagl_egl_window_attribs *attribs,
+                                             yagl_winsys_id id);
+
+struct yagl_egl_onscreen_surface
+    *yagl_egl_onscreen_surface_create_pixmap(struct yagl_egl_onscreen_display *dpy,
+                                             const struct yagl_egl_native_config *cfg,
+                                             const struct yagl_egl_pixmap_attribs *attribs,
+                                             yagl_winsys_id id);
+
+struct yagl_egl_onscreen_surface
+    *yagl_egl_onscreen_surface_create_pbuffer(struct yagl_egl_onscreen_display *dpy,
+                                             const struct yagl_egl_native_config *cfg,
+                                             const struct yagl_egl_pbuffer_attribs *attribs,
+                                             uint32_t width,
+                                             uint32_t height);
+
+void yagl_egl_onscreen_surface_setup(struct yagl_egl_onscreen_surface *sfc);
+
+void yagl_egl_onscreen_surface_attach_to_framebuffer(struct yagl_egl_onscreen_surface *sfc);
+
+uint32_t yagl_egl_onscreen_surface_width(struct yagl_egl_onscreen_surface *sfc);
+
+uint32_t yagl_egl_onscreen_surface_height(struct yagl_egl_onscreen_surface *sfc);
+
+#endif
diff --git a/hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_ts.c b/hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_ts.c
new file mode 100644 (file)
index 0000000..fee9225
--- /dev/null
@@ -0,0 +1,21 @@
+#include "yagl_egl_onscreen_ts.h"
+#include <GL/gl.h>
+#include "yagl_egl_onscreen.h"
+#include "yagl_egl_onscreen_context.h"
+#include "yagl_egl_onscreen_surface.h"
+#include "yagl_gles_driver.h"
+
+struct yagl_egl_onscreen_ts *yagl_egl_onscreen_ts_create(struct yagl_gles_driver *gles_driver)
+{
+    struct yagl_egl_onscreen_ts *egl_onscreen_ts =
+        g_malloc0(sizeof(struct yagl_egl_onscreen_ts));
+
+    egl_onscreen_ts->gles_driver = gles_driver;
+
+    return egl_onscreen_ts;
+}
+
+void yagl_egl_onscreen_ts_destroy(struct yagl_egl_onscreen_ts *egl_onscreen_ts)
+{
+    g_free(egl_onscreen_ts);
+}
diff --git a/hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_ts.h b/hw/yagl_backends/egl_onscreen/yagl_egl_onscreen_ts.h
new file mode 100644 (file)
index 0000000..2c26747
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef _QEMU_YAGL_EGL_ONSCREEN_TS_H
+#define _QEMU_YAGL_EGL_ONSCREEN_TS_H
+
+#include "yagl_types.h"
+
+struct yagl_gles_driver;
+struct yagl_egl_onscreen_display;
+struct yagl_egl_onscreen_context;
+struct yagl_egl_onscreen_surface;
+
+struct yagl_egl_onscreen_ts
+{
+    struct yagl_gles_driver *gles_driver;
+
+    struct yagl_egl_onscreen_display *dpy;
+    struct yagl_egl_onscreen_context *ctx;
+    struct yagl_egl_onscreen_surface *sfc_draw;
+    struct yagl_egl_onscreen_surface *sfc_read;
+};
+
+struct yagl_egl_onscreen_ts *yagl_egl_onscreen_ts_create(struct yagl_gles_driver *gles_driver);
+
+void yagl_egl_onscreen_ts_destroy(struct yagl_egl_onscreen_ts *egl_onscreen_ts);
+
+#endif
index b33e23a1d9de8aeda51b40962aad6b4c3a51448a..61713d7d1069bd869858c1cdffd145b4fc2879f7 100644 (file)
@@ -5,9 +5,20 @@
 #include "yagl_stats.h"
 #include "yagl_process.h"
 #include "yagl_thread.h"
+#include "yagl_egl_driver.h"
+#include "yagl_drivers/gles1_ogl/yagl_gles1_ogl.h"
+#include "yagl_drivers/gles2_ogl/yagl_gles2_ogl.h"
+#include "yagl_drivers/gles1_onscreen/yagl_gles1_onscreen.h"
+#include "yagl_drivers/gles2_onscreen/yagl_gles2_onscreen.h"
+#include "yagl_backends/egl_offscreen/yagl_egl_offscreen.h"
+#include "yagl_backends/egl_onscreen/yagl_egl_onscreen.h"
 #include "cpu-all.h"
 #include "hw.h"
 #include "pci.h"
+#include <GL/gl.h>
+#include "winsys.h"
+#include "yagl_gles1_driver.h"
+#include "yagl_gles2_driver.h"
 
 #define PCI_VENDOR_ID_YAGL 0x19B1
 #define PCI_DEVICE_ID_YAGL 0x1010
@@ -30,12 +41,10 @@ struct yagl_user
 typedef struct YaGLState
 {
     PCIDevice dev;
-#if defined(CONFIG_YAGL_EGL_GLX)
+#if defined(__linux__)
     Display *x_display;
-#elif defined(CONFIG_YAGL_EGL_WGL)
-#else
-#error Unknown EGL driver
 #endif
+    struct winsys_interface *wsi;
     MemoryRegion iomem;
     struct yagl_server_state *ss;
     struct yagl_user users[YAGL_MAX_USERS];
@@ -211,6 +220,10 @@ static const MemoryRegionOps yagl_device_ops =
 static int yagl_device_init(PCIDevice *dev)
 {
     YaGLState *s = DO_UPCAST(YaGLState, dev, dev);
+    struct yagl_egl_driver *egl_driver = NULL;
+    struct yagl_egl_backend *egl_backend = NULL;
+    struct yagl_gles1_driver *gles1_driver = NULL;
+    struct yagl_gles2_driver *gles2_driver = NULL;
 
     yagl_log_init();
 
@@ -226,28 +239,58 @@ static int yagl_device_init(PCIDevice *dev)
 
     yagl_stats_init();
 
-#if defined(CONFIG_YAGL_EGL_GLX)
-    if (s->x_display) {
-        s->ss = yagl_server_state_create(s->x_display);
-    } else {
-        YAGL_LOG_CRITICAL("x_display is NULL");
-        s->ss = NULL;
-    }
-#elif defined(CONFIG_YAGL_EGL_WGL)
-    s->ss = yagl_server_state_create();
+#if defined(__linux__)
+    egl_driver = yagl_egl_driver_create(s->x_display);
 #else
-#error Unknown EGL driver
+    egl_driver = yagl_egl_driver_create();
 #endif
-    if (!s->ss) {
-        yagl_stats_cleanup();
 
-        yagl_handle_gen_cleanup();
+    if (!egl_driver) {
+        goto fail;
+    }
+
+    gles1_driver = yagl_gles1_ogl_create(egl_driver->dyn_lib);
+
+    if (!gles1_driver) {
+        goto fail;
+    }
+
+    gles2_driver = yagl_gles2_ogl_create(egl_driver->dyn_lib);
+
+    if (!gles2_driver) {
+        goto fail;
+    }
+
+    if (s->wsi) {
+        egl_backend = yagl_egl_onscreen_create(s->wsi,
+                                               egl_driver,
+                                               &gles2_driver->base);
+        gles1_driver = yagl_gles1_onscreen_create(gles1_driver);
+        gles2_driver = yagl_gles2_onscreen_create(gles2_driver);
+    } else {
+        egl_backend = yagl_egl_offscreen_create(egl_driver);
+    }
 
-        YAGL_LOG_FUNC_EXIT(NULL);
+    if (!egl_backend) {
+        goto fail;
+    }
 
-        yagl_log_cleanup();
+    /*
+     * Now owned by EGL backend.
+     */
+    egl_driver = NULL;
 
-        return -1;
+    s->ss = yagl_server_state_create(egl_backend, gles1_driver, gles2_driver);
+
+    /*
+     * Owned/destroyed by server state.
+     */
+    egl_backend = NULL;
+    gles1_driver = NULL;
+    gles2_driver = NULL;
+
+    if (!s->ss) {
+        goto fail;
     }
 
     s->in_buff = g_malloc(YAGL_MARSHAL_MAX_RESPONSE);
@@ -257,6 +300,33 @@ static int yagl_device_init(PCIDevice *dev)
     YAGL_LOG_FUNC_EXIT(NULL);
 
     return 0;
+
+fail:
+    if (egl_backend) {
+        egl_backend->destroy(egl_backend);
+    }
+
+    if (gles1_driver) {
+        gles1_driver->destroy(gles1_driver);
+    }
+
+    if (gles2_driver) {
+        gles2_driver->destroy(gles2_driver);
+    }
+
+    if (egl_driver) {
+        egl_driver->destroy(egl_driver);
+    }
+
+    yagl_stats_cleanup();
+
+    yagl_handle_gen_cleanup();
+
+    YAGL_LOG_FUNC_EXIT(NULL);
+
+    yagl_log_cleanup();
+
+    return -1;
 }
 
 static void yagl_device_reset(DeviceState *d)
@@ -300,16 +370,18 @@ static void yagl_device_exit(PCIDevice *dev)
 }
 
 static Property yagl_properties[] = {
-#if defined(CONFIG_YAGL_EGL_GLX)
+#if defined(__linux__)
     {
         .name   = "x_display",
         .info   = &qdev_prop_ptr,
         .offset = offsetof(YaGLState, x_display),
     },
-#elif defined(CONFIG_YAGL_EGL_WGL)
-#else
-#error Unknown EGL driver
 #endif
+    {
+        .name   = "winsys_gl_interface",
+        .info   = &qdev_prop_ptr,
+        .offset = offsetof(YaGLState, wsi),
+    },
     DEFINE_PROP_END_OF_LIST(),
 };
 
index dd6e592b043e5384966cba0339e0fbf15b05e194..f06cd9d22b0710ce5045630894b8ac58820246b6 100644 (file)
@@ -465,7 +465,7 @@ static void yagl_egl_glx_destroy(struct yagl_egl_driver *driver)
     YAGL_LOG_FUNC_EXIT(NULL);
 }
 
-struct yagl_egl_driver *yagl_egl_glx_driver_create(Display *x_display)
+struct yagl_egl_driver *yagl_egl_driver_create(Display *x_display)
 {
     struct yagl_egl_driver *egl_driver;
     struct yagl_egl_glx *egl_glx;
index 37963ad1f571c6a15d68bc470d47200752c4a6e0..6e68e36303a317403723c6c66b99cb09d5a496a0 100644 (file)
@@ -903,7 +903,7 @@ out:
     return ext_initialized;
 }
 
-struct yagl_egl_driver *yagl_egl_wgl_driver_create(void)
+struct yagl_egl_driver *yagl_egl_driver_create(void)
 {
     YaglEglWglDriver *egl_wgl;
     struct yagl_egl_driver *egl_driver;
diff --git a/hw/yagl_drivers/gles1_onscreen/yagl_gles1_onscreen.c b/hw/yagl_drivers/gles1_onscreen/yagl_gles1_onscreen.c
new file mode 100644 (file)
index 0000000..f3dbf90
--- /dev/null
@@ -0,0 +1,56 @@
+#include <GL/gl.h>
+#include "yagl_gles1_onscreen.h"
+#include "yagl_drivers/gles_onscreen/yagl_gles_onscreen.h"
+#include "yagl_gles1_driver.h"
+#include "yagl_log.h"
+#include "yagl_process.h"
+#include "yagl_thread.h"
+
+struct yagl_gles1_onscreen
+{
+    struct yagl_gles1_driver base;
+
+    struct yagl_gles1_driver *orig_driver;
+};
+
+static void yagl_gles1_onscreen_destroy(struct yagl_gles1_driver *driver)
+{
+    struct yagl_gles1_onscreen *gles1_onscreen = (struct yagl_gles1_onscreen*)driver;
+
+    YAGL_LOG_FUNC_ENTER(yagl_gles1_onscreen_destroy, NULL);
+
+    gles1_onscreen->orig_driver->destroy(gles1_onscreen->orig_driver);
+    gles1_onscreen->orig_driver = NULL;
+
+    yagl_gles1_driver_cleanup(driver);
+    yagl_gles_onscreen_cleanup(&driver->base);
+    g_free(gles1_onscreen);
+
+    YAGL_LOG_FUNC_EXIT(NULL);
+}
+
+struct yagl_gles1_driver
+    *yagl_gles1_onscreen_create(struct yagl_gles1_driver *orig_driver)
+{
+    struct yagl_gles1_onscreen *gles1_onscreen = NULL;
+
+    YAGL_LOG_FUNC_ENTER(yagl_gles1_onscreen_create, NULL);
+
+    gles1_onscreen = g_malloc0(sizeof(*gles1_onscreen));
+
+    /*
+     * Just copy over everything, then init our fields.
+     */
+    memcpy(&gles1_onscreen->base, orig_driver, sizeof(*orig_driver));
+    gles1_onscreen->orig_driver = orig_driver;
+
+    yagl_gles_onscreen_init(&gles1_onscreen->base.base);
+
+    yagl_gles1_driver_init(&gles1_onscreen->base);
+
+    gles1_onscreen->base.destroy = &yagl_gles1_onscreen_destroy;
+
+    YAGL_LOG_FUNC_EXIT(NULL);
+
+    return &gles1_onscreen->base;
+}
diff --git a/hw/yagl_drivers/gles1_onscreen/yagl_gles1_onscreen.h b/hw/yagl_drivers/gles1_onscreen/yagl_gles1_onscreen.h
new file mode 100644 (file)
index 0000000..d255b23
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef _QEMU_YAGL_GLES1_ONSCREEN_H
+#define _QEMU_YAGL_GLES1_ONSCREEN_H
+
+#include "yagl_types.h"
+
+struct yagl_gles1_driver;
+
+/*
+ * Takes ownership of 'orig_driver'.
+ */
+struct yagl_gles1_driver
+    *yagl_gles1_onscreen_create(struct yagl_gles1_driver *orig_driver);
+
+#endif
diff --git a/hw/yagl_drivers/gles2_onscreen/yagl_gles2_onscreen.c b/hw/yagl_drivers/gles2_onscreen/yagl_gles2_onscreen.c
new file mode 100644 (file)
index 0000000..c60644a
--- /dev/null
@@ -0,0 +1,56 @@
+#include <GL/gl.h>
+#include "yagl_gles2_onscreen.h"
+#include "yagl_drivers/gles_onscreen/yagl_gles_onscreen.h"
+#include "yagl_gles2_driver.h"
+#include "yagl_log.h"
+#include "yagl_process.h"
+#include "yagl_thread.h"
+
+struct yagl_gles2_onscreen
+{
+    struct yagl_gles2_driver base;
+
+    struct yagl_gles2_driver *orig_driver;
+};
+
+static void yagl_gles2_onscreen_destroy(struct yagl_gles2_driver *driver)
+{
+    struct yagl_gles2_onscreen *gles2_onscreen = (struct yagl_gles2_onscreen*)driver;
+
+    YAGL_LOG_FUNC_ENTER(yagl_gles2_onscreen_destroy, NULL);
+
+    gles2_onscreen->orig_driver->destroy(gles2_onscreen->orig_driver);
+    gles2_onscreen->orig_driver = NULL;
+
+    yagl_gles2_driver_cleanup(driver);
+    yagl_gles_onscreen_cleanup(&driver->base);
+    g_free(gles2_onscreen);
+
+    YAGL_LOG_FUNC_EXIT(NULL);
+}
+
+struct yagl_gles2_driver
+    *yagl_gles2_onscreen_create(struct yagl_gles2_driver *orig_driver)
+{
+    struct yagl_gles2_onscreen *gles2_onscreen = NULL;
+
+    YAGL_LOG_FUNC_ENTER(yagl_gles2_onscreen_create, NULL);
+
+    gles2_onscreen = g_malloc0(sizeof(*gles2_onscreen));
+
+    /*
+     * Just copy over everything, then init our fields.
+     */
+    memcpy(&gles2_onscreen->base, orig_driver, sizeof(*orig_driver));
+    gles2_onscreen->orig_driver = orig_driver;
+
+    yagl_gles_onscreen_init(&gles2_onscreen->base.base);
+
+    yagl_gles2_driver_init(&gles2_onscreen->base);
+
+    gles2_onscreen->base.destroy = &yagl_gles2_onscreen_destroy;
+
+    YAGL_LOG_FUNC_EXIT(NULL);
+
+    return &gles2_onscreen->base;
+}
diff --git a/hw/yagl_drivers/gles2_onscreen/yagl_gles2_onscreen.h b/hw/yagl_drivers/gles2_onscreen/yagl_gles2_onscreen.h
new file mode 100644 (file)
index 0000000..168d7d9
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef _QEMU_YAGL_GLES2_ONSCREEN_H
+#define _QEMU_YAGL_GLES2_ONSCREEN_H
+
+#include "yagl_types.h"
+
+struct yagl_gles2_driver;
+
+/*
+ * Takes ownership of 'orig_driver'.
+ */
+struct yagl_gles2_driver
+    *yagl_gles2_onscreen_create(struct yagl_gles2_driver *orig_driver);
+
+#endif
diff --git a/hw/yagl_drivers/gles_onscreen/yagl_gles_onscreen.c b/hw/yagl_drivers/gles_onscreen/yagl_gles_onscreen.c
new file mode 100644 (file)
index 0000000..24c251c
--- /dev/null
@@ -0,0 +1,212 @@
+#include <GL/gl.h>
+#include "yagl_gles_onscreen.h"
+#include "yagl_gles_driver.h"
+#include "yagl_log.h"
+#include "yagl_tls.h"
+#include "yagl_process.h"
+#include "yagl_thread.h"
+#include "yagl_backends/egl_onscreen/yagl_egl_onscreen_ts.h"
+#include "yagl_backends/egl_onscreen/yagl_egl_onscreen_context.h"
+
+YAGL_DECLARE_TLS(struct yagl_egl_onscreen_ts*, egl_onscreen_ts);
+
+static void YAGL_GLES_APIENTRY yagl_gles_onscreen_GetBooleanv(GLenum pname, GLboolean* params)
+{
+    GLuint cur_fb = 0;
+
+    if (!egl_onscreen_ts || !egl_onscreen_ts->dpy) {
+        return;
+    }
+
+    if ((pname == GL_FRAMEBUFFER_BINDING) && params) {
+        egl_onscreen_ts->gles_driver->GetIntegerv(pname, (GLint*)&cur_fb);
+        params[0] = (cur_fb == egl_onscreen_ts->ctx->fb) ? 0 : cur_fb;
+    } else {
+        egl_onscreen_ts->gles_driver->GetBooleanv(pname, params);
+    }
+}
+
+static void YAGL_GLES_APIENTRY yagl_gles_onscreen_GetFloatv(GLenum pname, GLfloat* params)
+{
+    GLuint cur_fb = 0;
+
+    if (!egl_onscreen_ts || !egl_onscreen_ts->dpy) {
+        return;
+    }
+
+    if ((pname == GL_FRAMEBUFFER_BINDING) && params) {
+        egl_onscreen_ts->gles_driver->GetIntegerv(pname, (GLint*)&cur_fb);
+        params[0] = (cur_fb == egl_onscreen_ts->ctx->fb) ? 0 : cur_fb;
+    } else {
+        egl_onscreen_ts->gles_driver->GetFloatv(pname, params);
+    }
+}
+
+static void YAGL_GLES_APIENTRY yagl_gles_onscreen_GetIntegerv(GLenum pname, GLint* params)
+{
+    GLuint cur_fb = 0;
+
+    if (!egl_onscreen_ts || !egl_onscreen_ts->dpy) {
+        return;
+    }
+
+    if ((pname == GL_FRAMEBUFFER_BINDING) && params) {
+        egl_onscreen_ts->gles_driver->GetIntegerv(pname, (GLint*)&cur_fb);
+        params[0] = (cur_fb == egl_onscreen_ts->ctx->fb) ? 0 : cur_fb;
+    } else {
+        egl_onscreen_ts->gles_driver->GetIntegerv(pname, params);
+    }
+}
+
+static void YAGL_GLES_APIENTRY yagl_gles_onscreen_DeleteFramebuffers(GLsizei n,
+    const GLuint* framebuffers)
+{
+    GLsizei i;
+
+    if (!egl_onscreen_ts || !egl_onscreen_ts->dpy) {
+        return;
+    }
+
+    for (i = 0; i < n; ++i) {
+        if (framebuffers[i] != egl_onscreen_ts->ctx->fb) {
+            egl_onscreen_ts->gles_driver->DeleteBuffers(1, &framebuffers[i]);
+        }
+    }
+}
+
+static void YAGL_GLES_APIENTRY yagl_gles_onscreen_BindFramebuffer(GLenum target,
+    GLuint framebuffer)
+{
+    if (!egl_onscreen_ts || !egl_onscreen_ts->dpy) {
+        return;
+    }
+
+    if (framebuffer == egl_onscreen_ts->ctx->fb) {
+        /*
+         * TODO: Generate GL_INVALID_OPERATION error.
+         */
+
+        return;
+    }
+
+    if (framebuffer == 0) {
+        framebuffer = egl_onscreen_ts->ctx->fb;
+    }
+
+    egl_onscreen_ts->gles_driver->BindFramebuffer(target, framebuffer);
+}
+
+static void YAGL_GLES_APIENTRY yagl_gles_onscreen_FramebufferTexture2D(GLenum target,
+    GLenum attachment, GLenum textarget, GLuint texture, GLint level)
+{
+    GLuint cur_fb = 0;
+
+    if (!egl_onscreen_ts || !egl_onscreen_ts->dpy) {
+        return;
+    }
+
+    egl_onscreen_ts->gles_driver->GetIntegerv(GL_FRAMEBUFFER_BINDING,
+                                              (GLint*)&cur_fb);
+
+    if (cur_fb != egl_onscreen_ts->ctx->fb) {
+        egl_onscreen_ts->gles_driver->FramebufferTexture2D(target,
+                                                           attachment,
+                                                           textarget,
+                                                           texture,
+                                                           level);
+    } else {
+        /*
+         * TODO: Generate GL_INVALID_OPERATION error.
+         */
+    }
+}
+
+static void YAGL_GLES_APIENTRY yagl_gles_onscreen_FramebufferRenderbuffer(GLenum target,
+    GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
+{
+    GLuint cur_fb = 0;
+
+    if (!egl_onscreen_ts || !egl_onscreen_ts->dpy) {
+        return;
+    }
+
+    egl_onscreen_ts->gles_driver->GetIntegerv(GL_FRAMEBUFFER_BINDING,
+                                              (GLint*)&cur_fb);
+
+    if (cur_fb != egl_onscreen_ts->ctx->fb) {
+        egl_onscreen_ts->gles_driver->FramebufferRenderbuffer(target,
+                                                              attachment,
+                                                              renderbuffertarget,
+                                                              renderbuffer);
+    } else {
+        /*
+         * TODO: Generate GL_INVALID_OPERATION error.
+         */
+    }
+}
+
+static GLenum YAGL_GLES_APIENTRY yagl_gles_onscreen_CheckFramebufferStatus(GLenum target)
+{
+    GLuint cur_fb = 0;
+
+    if (!egl_onscreen_ts || !egl_onscreen_ts->dpy) {
+        return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+    }
+
+    egl_onscreen_ts->gles_driver->GetIntegerv(GL_FRAMEBUFFER_BINDING,
+                                              (GLint*)&cur_fb);
+
+    if (cur_fb != egl_onscreen_ts->ctx->fb) {
+        return egl_onscreen_ts->gles_driver->CheckFramebufferStatus(target);
+    } else {
+        return GL_FRAMEBUFFER_COMPLETE;
+    }
+}
+
+static void YAGL_GLES_APIENTRY yagl_gles_onscreen_GetFramebufferAttachmentParameteriv(GLenum target,
+    GLenum attachment, GLenum pname, GLint* params)
+{
+    GLuint cur_fb = 0;
+
+    if (!egl_onscreen_ts || !egl_onscreen_ts->dpy) {
+        return;
+    }
+
+    egl_onscreen_ts->gles_driver->GetIntegerv(GL_FRAMEBUFFER_BINDING,
+                                              (GLint*)&cur_fb);
+
+    if (cur_fb != egl_onscreen_ts->ctx->fb) {
+        egl_onscreen_ts->gles_driver->GetFramebufferAttachmentParameteriv(target,
+                                                                          attachment,
+                                                                          pname,
+                                                                          params);
+    } else {
+        /*
+         * TODO: Generate GL_INVALID_OPERATION error.
+         */
+    }
+}
+
+void yagl_gles_onscreen_init(struct yagl_gles_driver *driver)
+{
+    YAGL_LOG_FUNC_ENTER(yagl_gles_onscreen_init, NULL);
+
+    yagl_gles_driver_init(driver);
+
+    driver->GetBooleanv = &yagl_gles_onscreen_GetBooleanv;
+    driver->GetFloatv = &yagl_gles_onscreen_GetFloatv;
+    driver->GetIntegerv = &yagl_gles_onscreen_GetIntegerv;
+    driver->DeleteFramebuffers = &yagl_gles_onscreen_DeleteFramebuffers;
+    driver->BindFramebuffer = &yagl_gles_onscreen_BindFramebuffer;
+    driver->FramebufferTexture2D = &yagl_gles_onscreen_FramebufferTexture2D;
+    driver->FramebufferRenderbuffer = &yagl_gles_onscreen_FramebufferRenderbuffer;
+    driver->CheckFramebufferStatus = &yagl_gles_onscreen_CheckFramebufferStatus;
+    driver->GetFramebufferAttachmentParameteriv = &yagl_gles_onscreen_GetFramebufferAttachmentParameteriv;
+
+    YAGL_LOG_FUNC_EXIT(NULL);
+}
+
+void yagl_gles_onscreen_cleanup(struct yagl_gles_driver *driver)
+{
+    yagl_gles_driver_cleanup(driver);
+}
diff --git a/hw/yagl_drivers/gles_onscreen/yagl_gles_onscreen.h b/hw/yagl_drivers/gles_onscreen/yagl_gles_onscreen.h
new file mode 100644 (file)
index 0000000..9b22195
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef _QEMU_YAGL_GLES_ONSCREEN_H
+#define _QEMU_YAGL_GLES_ONSCREEN_H
+
+#include "yagl_types.h"
+
+struct yagl_gles_driver;
+
+void yagl_gles_onscreen_init(struct yagl_gles_driver *driver);
+void yagl_gles_onscreen_cleanup(struct yagl_gles_driver *driver);
+
+#endif
index 8c320fe3aeecdd5fb641e0f16f924155b52a3d6b..93db2d0bcbd5a813bec5b020033149401540d9b5 100644 (file)
@@ -18,6 +18,8 @@ struct yagl_egl_backend
 
     void (*thread_init)(struct yagl_egl_backend */*backend*/);
 
+    void (*pre_batch)(struct yagl_egl_backend */*backend*/);
+
     struct yagl_eglb_display *(*create_display)(struct yagl_egl_backend */*backend*/);
 
     bool (*make_current)(struct yagl_egl_backend */*backend*/,
index d0801275c93d1d71d4507960bf1ff5c20db0ab4e..71f0a27056d2f5902d97aaae77dcb9bc305a32c1 100644 (file)
@@ -80,9 +80,9 @@ struct yagl_egl_driver
 };
 
 #if defined(CONFIG_YAGL_EGL_GLX)
-struct yagl_egl_driver *yagl_egl_glx_driver_create(Display *x_display);
+struct yagl_egl_driver *yagl_egl_driver_create(Display *x_display);
 #elif defined(CONFIG_YAGL_EGL_WGL)
-struct yagl_egl_driver *yagl_egl_wgl_driver_create(void);
+struct yagl_egl_driver *yagl_egl_driver_create(void);
 #else
 #error Unknown EGL driver
 #endif
index 701fcead66882426a8b00cbe4a6cba3faf0718e2..7f9346dac56d2dae337dd2d0676a2af70b31816d 100644 (file)
@@ -44,18 +44,21 @@ struct yagl_eglb_display
     struct yagl_eglb_surface *(*create_onscreen_window_surface)(struct yagl_eglb_display */*dpy*/,
                                                                 const struct yagl_egl_native_config */*cfg*/,
                                                                 const struct yagl_egl_window_attribs */*attribs*/,
-                                                                uint32_t /*id*/);
+                                                                yagl_winsys_id /*id*/);
 
     struct yagl_eglb_surface *(*create_onscreen_pixmap_surface)(struct yagl_eglb_display */*dpy*/,
                                                                 const struct yagl_egl_native_config */*cfg*/,
                                                                 const struct yagl_egl_pixmap_attribs */*attribs*/,
-                                                                uint32_t /*id*/);
+                                                                yagl_winsys_id /*id*/);
 
     struct yagl_eglb_surface *(*create_onscreen_pbuffer_surface)(struct yagl_eglb_display */*dpy*/,
                                                                  const struct yagl_egl_native_config */*cfg*/,
-                                                                 const struct yagl_egl_pbuffer_attribs */*attribs*/);
+                                                                 const struct yagl_egl_pbuffer_attribs */*attribs*/,
+                                                                 uint32_t /*width*/,
+                                                                 uint32_t /*height*/);
 
-    struct yagl_eglb_image *(*create_image)(struct yagl_eglb_display */*dpy*/);
+    struct yagl_eglb_image *(*create_image)(struct yagl_eglb_display */*dpy*/,
+                                            yagl_winsys_id /*buffer*/);
 
     void (*destroy)(struct yagl_eglb_display */*dpy*/);
 };
index 0dd366b9c5dc06732998517da08238398fe4149a..e28c423d23aeafebee041b2e0fe18b19f2f89581 100644 (file)
@@ -2,8 +2,10 @@
 #include "yagl_client_image.h"
 
 void yagl_eglb_image_init(struct yagl_eglb_image *image,
+                          yagl_winsys_id buffer,
                           struct yagl_eglb_display *dpy)
 {
+    image->buffer = buffer;
     image->dpy = dpy;
 }
 
index 289c2edf5bb2f432807a8847acbeb8caec1ec861..0b87b1d0705eb9efb699b7b991d33a7705ff0c75 100644 (file)
@@ -8,6 +8,8 @@ struct yagl_client_image;
 
 struct yagl_eglb_image
 {
+    yagl_winsys_id buffer;
+
     struct yagl_eglb_display *dpy;
 
     /*
@@ -28,6 +30,7 @@ struct yagl_eglb_image
 };
 
 void yagl_eglb_image_init(struct yagl_eglb_image *image,
+                          yagl_winsys_id buffer,
                           struct yagl_eglb_display *dpy);
 void yagl_eglb_image_cleanup(struct yagl_eglb_image *image);
 
index eeb9146bc1c85cd98a93e90462242671efaaf7d9..c61fb75b99dfc82813c6d7ce7aaf6e112b69435d 100644 (file)
@@ -64,7 +64,8 @@ struct yagl_eglb_surface
     /*
      * Only called for valid surfaces.
      */
-    bool (*copy_buffers)(struct yagl_eglb_surface */*sfc*/);
+    bool (*copy_buffers)(struct yagl_eglb_surface */*sfc*/,
+                         yagl_winsys_id /*target*/);
 
     void (*destroy)(struct yagl_eglb_surface */*sfc*/);
 
index 3f0532395cba1b547f5b92ce84267e99b525b3e7..aa99bbe376a6514a2f2a94a9db0dd65eecd69faf 100644 (file)
@@ -14,10 +14,12 @@ void yagl_gles_driver_cleanup(struct yagl_gles_driver *driver)
 
 void yagl_ensure_ctx(void)
 {
+    assert(cur_ts);
     cur_ts->ps->egl_iface->ensure_ctx(cur_ts->ps->egl_iface);
 }
 
 void yagl_unensure_ctx(void)
 {
+    assert(cur_ts);
     cur_ts->ps->egl_iface->unensure_ctx(cur_ts->ps->egl_iface);
 }
index c9717a530ed08ed7be7d6f6c0e4ac74b4ab98140..e12c62266404882de5eea56cbb5c741af87aaeb0 100644 (file)
@@ -119,5 +119,6 @@ static __inline void yagl_marshal_put_call_result(uint8_t** buff, yagl_call_resu
 #define yagl_marshal_get_api_id(buff) yagl_marshal_get_uint32(buff)
 #define yagl_marshal_get_func_id(buff) yagl_marshal_get_uint32(buff)
 #define yagl_marshal_put_render_type(buff, value) yagl_marshal_put_uint32(buff, value)
+#define yagl_marshal_get_yagl_winsys_id(buff) yagl_marshal_get_uint32(buff)
 
 #endif
index 6bc9d9127327e45ecb522f10193d100dc084a177..42c532d12775d5719efafe7afc142d19b8afe46f 100644 (file)
@@ -5,14 +5,11 @@
 #include "yagl_marshal.h"
 #include "yagl_version.h"
 #include "yagl_log.h"
-#include "yagl_egl_driver.h"
+#include "yagl_egl_backend.h"
 #include "yagl_egl_interface.h"
 #include "yagl_apis/egl/yagl_egl_api.h"
 #include "yagl_apis/gles1/yagl_gles1_api.h"
-#include "yagl_drivers/gles1_ogl/yagl_gles1_ogl.h"
 #include "yagl_apis/gles2/yagl_gles2_api.h"
-#include "yagl_drivers/gles2_ogl/yagl_gles2_ogl.h"
-#include "yagl_backends/egl_offscreen/yagl_egl_offscreen.h"
 #include <GL/gl.h>
 #include "yagl_gles1_driver.h"
 #include "yagl_gles2_driver.h"
@@ -33,71 +30,36 @@ static struct yagl_thread_state
     return NULL;
 }
 
-#if defined(CONFIG_YAGL_EGL_GLX)
-    struct yagl_server_state *yagl_server_state_create(Display *x_display)
-#elif defined(CONFIG_YAGL_EGL_WGL)
-    struct yagl_server_state *yagl_server_state_create(void)
-#else
-#error Unknown EGL driver
-#endif
+struct yagl_server_state
+    *yagl_server_state_create(struct yagl_egl_backend *egl_backend,
+                              struct yagl_gles1_driver *gles1_driver,
+                              struct yagl_gles2_driver *gles2_driver)
 {
     int i;
     struct yagl_server_state *ss =
         g_malloc0(sizeof(struct yagl_server_state));
-    struct yagl_egl_driver *egl_driver;
-    struct yagl_egl_backend *egl_backend;
-    struct yagl_gles1_driver *gles1_driver;
-    struct yagl_gles2_driver *gles2_driver;
 
     QLIST_INIT(&ss->processes);
 
-#if defined(CONFIG_YAGL_EGL_GLX)
-    egl_driver = yagl_egl_glx_driver_create(x_display);
-#elif defined(CONFIG_YAGL_EGL_WGL)
-    egl_driver = yagl_egl_wgl_driver_create();
-#else
-#error Unknown EGL driver
-#endif
-
-    if (!egl_driver) {
-        goto fail;
-    }
-
-    egl_backend = yagl_egl_offscreen_create(egl_driver);
-
-    if (!egl_backend) {
-        egl_driver->destroy(egl_driver);
-        goto fail;
-    }
-
     ss->apis[yagl_api_id_egl - 1] = yagl_egl_api_create(egl_backend);
 
     if (!ss->apis[yagl_api_id_egl - 1]) {
         egl_backend->destroy(egl_backend);
+        gles1_driver->destroy(gles1_driver);
+        gles2_driver->destroy(gles2_driver);
 
         goto fail;
     }
 
-    gles1_driver = yagl_gles1_ogl_create(egl_driver->dyn_lib);
-
-    if (!gles1_driver) {
-        goto fail;
-    }
-
     ss->apis[yagl_api_id_gles1 - 1] = yagl_gles1_api_create(gles1_driver);
 
     if (!ss->apis[yagl_api_id_gles1 - 1]) {
         gles1_driver->destroy(gles1_driver);
+        gles2_driver->destroy(gles2_driver);
 
         goto fail;
     }
 
-    gles2_driver = yagl_gles2_ogl_create(egl_driver->dyn_lib);
-
-    if (!gles2_driver) {
-        goto fail;
-    }
-
     ss->apis[yagl_api_id_gles2 - 1] = yagl_gles2_api_create(gles2_driver);
 
     if (!ss->apis[yagl_api_id_gles2 - 1]) {
index 0deac7756f76b567c298afe8601acf56cafb927d..23106a01b914a2e864ca54e74aba65716fa8210d 100644 (file)
@@ -3,10 +3,12 @@
 
 #include "yagl_types.h"
 #include "qemu-queue.h"
-#include <EGL/egl.h>
 
 struct yagl_api;
 struct yagl_process_state;
+struct yagl_egl_backend;
+struct yagl_gles1_driver;
+struct yagl_gles2_driver;
 
 struct yagl_server_state
 {
@@ -20,13 +22,15 @@ struct yagl_server_state
  * server state which is a part of YaGL device.
  * @{
  */
-#if defined(CONFIG_YAGL_EGL_GLX)
-    struct yagl_server_state *yagl_server_state_create(Display *x_display);
-#elif defined(CONFIG_YAGL_EGL_WGL)
-    struct yagl_server_state *yagl_server_state_create(void);
-#else
-#error Unknown EGL driver
-#endif
+
+/*
+ * 'egl_backend' and 'gles2_driver' will be owned by returned server state
+ * or destroyed in case of error.
+ */
+struct yagl_server_state
+    *yagl_server_state_create(struct yagl_egl_backend *egl_backend,
+                              struct yagl_gles1_driver *gles1_driver,
+                              struct yagl_gles2_driver *gles2_driver);
 
 void yagl_server_state_destroy(struct yagl_server_state *ss);
 /*
index 8e6a9ac6ddb1676f30fbaafffcc7ff69aa3eed75..7e50ef4dbccdfcad2fc6a4059b4fcf99b887cdb5 100644 (file)
@@ -76,6 +76,12 @@ static void *yagl_thread_func(void* arg)
 
         YAGL_LOG_TRACE("batch started");
 
+        for (i = 0; i < YAGL_NUM_APIS; ++i) {
+            if (ts->ps->api_states[i]) {
+                ts->ps->api_states[i]->pre_batch(ts->ps->api_states[i]);
+            }
+        }
+
         /*
          * current_buff is:
          *  (yagl_api_id) api_id
index edd5b1f1d2689db90d7782c196a993ca987d272a..87f7daccef67403a7a0b0a036665406544d5226a 100644 (file)
@@ -8,6 +8,7 @@ typedef uint32_t yagl_tid;
 typedef uint32_t yagl_func_id;
 typedef uint32_t yagl_host_handle;
 typedef uint32_t yagl_object_name;
+typedef uint32_t yagl_winsys_id;
 
 /*
  * YaGL supported render types.