$(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
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
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
--- /dev/null
+#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
--- /dev/null
+#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
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*/);
{
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) {
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) {
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,
&yagl_func_eglCreatePbufferSurfaceOffscreenYAGL,
&yagl_func_eglCreatePixmapSurfaceOffscreenYAGL,
&yagl_func_eglResizeOffscreenSurfaceYAGL,
- &yagl_func_eglUpdateOffscreenImageYAGL
+ &yagl_func_eglUpdateOffscreenImageYAGL,
+ &yagl_func_eglCreateWindowSurfaceOnscreenYAGL,
+ &yagl_func_eglCreatePbufferSurfaceOnscreenYAGL,
+ &yagl_func_eglCreatePixmapSurfaceOnscreenYAGL
};
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;
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
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)
{
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;
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;
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;
}
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;
goto out;
}
- image = yagl_egl_image_create(dpy);
+ image = yagl_egl_image_create(dpy, buffer);
if (!image) {
YAGL_SET_ERR(EGL_BAD_ALLOC);
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;
+}
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_,
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
{
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) {
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);
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;
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)
{
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;
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;
}
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;
#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"
#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 =
#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"
#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)
}
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;
}
}
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;
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);
};
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
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;
#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;
}
#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);
--- /dev/null
+#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;
+}
--- /dev/null
+#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
--- /dev/null
+#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);
+}
--- /dev/null
+#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
--- /dev/null
+#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;
+}
--- /dev/null
+#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
--- /dev/null
+#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;
+}
--- /dev/null
+#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
--- /dev/null
+#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;
+ }
+}
--- /dev/null
+#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
--- /dev/null
+#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);
+}
--- /dev/null
+#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
#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
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];
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();
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);
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)
}
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(),
};
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;
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;
--- /dev/null
+#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;
+}
--- /dev/null
+#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
--- /dev/null
+#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;
+}
--- /dev/null
+#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
--- /dev/null
+#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);
+}
--- /dev/null
+#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
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*/,
};
#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
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*/);
};
#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;
}
struct yagl_eglb_image
{
+ yagl_winsys_id buffer;
+
struct yagl_eglb_display *dpy;
/*
};
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);
/*
* 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*/);
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);
}
#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
#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"
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]) {
#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
{
* 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);
/*
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
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.