diff options
author | Stanislav Vorobiov <s.vorobiov@samsung.com> | 2013-07-29 18:29:07 +0400 |
---|---|---|
committer | Stanislav Vorobiov <s.vorobiov@samsung.com> | 2013-08-01 14:12:21 +0400 |
commit | 7262ded6ba6abcfe57286a438e8610cf4d5072f5 (patch) | |
tree | f56273a273effdfce00053a51e64e6e732dcb263 | |
parent | 5b9dd324588c5f969a9bb8f5fd00632a2c0ae3d8 (diff) | |
download | emulator-yagl-7262ded6ba6abcfe57286a438e8610cf4d5072f5.tar.gz emulator-yagl-7262ded6ba6abcfe57286a438e8610cf4d5072f5.tar.bz2 emulator-yagl-7262ded6ba6abcfe57286a438e8610cf4d5072f5.zip |
YaGL: Separated windowing system related stuff
Change-Id: I26b4dfbccd33e7c8ca89e5ef0bddb6d634220ad6
60 files changed, 1913 insertions, 1123 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 7ccd317..e61ed02 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,6 +40,10 @@ endif () set(YAGL_OUT_DIR ${YAGL_BINARY_DIR}/out) +#define stuff + +add_definitions(-DMESA_EGL_NO_X11_HEADERS) + #set includes/libs set(YAGL_INCLUDE_DIR "${YAGL_SOURCE_DIR}/include") diff --git a/EGL/CMakeLists.txt b/EGL/CMakeLists.txt index eee7514..afc59b7 100644 --- a/EGL/CMakeLists.txt +++ b/EGL/CMakeLists.txt @@ -1,5 +1,4 @@ set(SOURCES - yagl_bimage.c yagl_context.c yagl_display.c yagl_egl_calls.c @@ -17,12 +16,17 @@ set(SOURCES yagl_onscreen_display.c yagl_onscreen_image.c yagl_onscreen_surface.c + yagl_onscreen_buffer.c yagl_ref.c yagl_render.c yagl_resource.c yagl_state.c yagl_surface.c yagl_utils.c + yagl_native_platform.c + yagl_native_display.c + yagl_native_drawable.c + yagl_native_image.c ) set(LIBRARIES @@ -34,21 +38,35 @@ set(LIBRARIES if (PLATFORM_X11) set(SOURCES ${SOURCES} - yagl_dri2.c + x11/yagl_dri2.c + x11/yagl_x11_platform.c + x11/yagl_x11_display.c + x11/yagl_x11_drawable.c + x11/yagl_x11_image.c ) set(LIBRARIES ${LIBRARIES} ${X11_LIBRARIES} ${XEXT_LIBRARIES} ${XFIXES_LIBRARIES} ) + add_definitions(-DYAGL_PLATFORM_X11) endif () if (PLATFORM_GBM) + set(SOURCES ${SOURCES} + gbm/yagl_gbm_platform.c + gbm/yagl_gbm_display.c + gbm/yagl_gbm_drawable.c + ) + add_definitions(-DYAGL_PLATFORM_GBM) endif () if (PLATFORM_WAYLAND) + add_definitions(-DYAGL_PLATFORM_WAYLAND) endif () +include_directories(.) + add_library(EGL SHARED ${SOURCES}) set_target_properties(EGL PROPERTIES VERSION 1.0 SOVERSION 1) diff --git a/EGL/gbm/yagl_gbm_display.c b/EGL/gbm/yagl_gbm_display.c new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/EGL/gbm/yagl_gbm_display.c diff --git a/EGL/gbm/yagl_gbm_display.h b/EGL/gbm/yagl_gbm_display.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/EGL/gbm/yagl_gbm_display.h diff --git a/EGL/gbm/yagl_gbm_drawable.c b/EGL/gbm/yagl_gbm_drawable.c new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/EGL/gbm/yagl_gbm_drawable.c diff --git a/EGL/gbm/yagl_gbm_drawable.h b/EGL/gbm/yagl_gbm_drawable.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/EGL/gbm/yagl_gbm_drawable.h diff --git a/EGL/gbm/yagl_gbm_platform.c b/EGL/gbm/yagl_gbm_platform.c new file mode 100644 index 0000000..7afa63f --- /dev/null +++ b/EGL/gbm/yagl_gbm_platform.c @@ -0,0 +1,20 @@ +#include "yagl_gbm_platform.h" +#include "yagl_native_platform.h" + +static int yagl_gbm_platform_probe(yagl_os_display os_dpy) +{ + return 0; +} + +static struct yagl_native_display + *yagl_gbm_wrap_display(yagl_os_display os_dpy, + int enable_drm) +{ + return NULL; +} + +struct yagl_native_platform yagl_gbm_platform = +{ + .probe = yagl_gbm_platform_probe, + .wrap_display = yagl_gbm_wrap_display +}; diff --git a/EGL/gbm/yagl_gbm_platform.h b/EGL/gbm/yagl_gbm_platform.h new file mode 100644 index 0000000..5c8b585 --- /dev/null +++ b/EGL/gbm/yagl_gbm_platform.h @@ -0,0 +1,10 @@ +#ifndef _YAGL_GBM_PLATFORM_H_ +#define _YAGL_GBM_PLATFORM_H_ + +#include "yagl_export.h" + +struct yagl_native_platform; + +extern struct yagl_native_platform yagl_gbm_platform; + +#endif diff --git a/EGL/yagl_dri2.c b/EGL/x11/yagl_dri2.c index 743b761..ef7e524 100644 --- a/EGL/yagl_dri2.c +++ b/EGL/x11/yagl_dri2.c @@ -1,7 +1,8 @@ #include "yagl_dri2.h" #include "yagl_display.h" -#include "yagl_onscreen_surface.h" +#include "yagl_surface.h" #include "yagl_log.h" +#include "yagl_native_drawable.h" #include <X11/extensions/Xext.h> #include <X11/extensions/extutil.h> #include <X11/extensions/dri2proto.h> @@ -65,7 +66,7 @@ static Bool DRI2WireToEvent(Display *x_dpy, XEvent *event, xEvent *wire) #ifdef DRI2_InvalidateBuffers case DRI2_InvalidateBuffers: awire = (xDRI2InvalidateBuffers*)wire; - dpy = yagl_display_get_x(x_dpy); + dpy = yagl_display_get_os((yagl_os_display)x_dpy); if (!dpy) { YAGL_LOG_ERROR("EGL display not found for X display 0x%X", x_dpy); @@ -75,13 +76,11 @@ static Bool DRI2WireToEvent(Display *x_dpy, XEvent *event, xEvent *wire) sfc = yagl_display_surface_acquire(dpy, (EGLSurface)awire->drawable); if (sfc) { - struct yagl_onscreen_surface *osfc = - (struct yagl_onscreen_surface*)sfc; if (sfc->type == EGL_WINDOW_BIT) { - ++osfc->stamp; + ++sfc->native_drawable->stamp; YAGL_LOG_DEBUG("EGL surface 0x%X invalidated, stamp = %u", awire->drawable, - osfc->stamp); + sfc->native_drawable->stamp); } else { YAGL_LOG_ERROR("EGL surface 0x%X is not a window surface", awire->drawable); diff --git a/EGL/yagl_dri2.h b/EGL/x11/yagl_dri2.h index 4350e42..4350e42 100644 --- a/EGL/yagl_dri2.h +++ b/EGL/x11/yagl_dri2.h diff --git a/EGL/x11/yagl_x11_display.c b/EGL/x11/yagl_x11_display.c new file mode 100644 index 0000000..6c067f3 --- /dev/null +++ b/EGL/x11/yagl_x11_display.c @@ -0,0 +1,235 @@ +#include "yagl_x11_display.h" +#include "yagl_x11_drawable.h" +#include "yagl_x11_image.h" +#include "yagl_log.h" +#include "yagl_malloc.h" +#include "yagl_dri2.h" +#include <X11/Xutil.h> +#include <X11/extensions/XShm.h> +#include <sys/fcntl.h> +#include <stdio.h> +#include <stdlib.h> + +static int yagl_x11_display_dri2_init(Display *x_dpy) +{ + int ret; + int event_base, error_base; + int dri_major, dri_minor; + char *dri_driver = NULL; + char *dri_device = NULL; + int drm_fd = -1; + drm_magic_t magic; + + YAGL_LOG_FUNC_SET(eglGetDisplay); + + if (!yagl_DRI2QueryExtension(x_dpy, &event_base, &error_base)) { + fprintf(stderr, "Critical error! Failed to DRI2QueryExtension on YaGL display, DRI2 not enabled ?\n"); + goto fail; + } + + YAGL_LOG_TRACE("DRI2QueryExtension returned %d %d", + event_base, error_base); + + if (!yagl_DRI2QueryVersion(x_dpy, &dri_major, &dri_minor)) { + fprintf(stderr, "Critical error! Failed to DRI2QueryVersion on YaGL display, DRI2 not enabled ?\n"); + goto fail; + } + + YAGL_LOG_TRACE("DRI2QueryVersion returned %d %d", + dri_major, dri_minor); + + if (!yagl_DRI2Connect(x_dpy, + RootWindow(x_dpy, DefaultScreen(x_dpy)), + &dri_driver, + &dri_device)) { + fprintf(stderr, "Critical error! Failed to DRI2Connect on YaGL display, DRI2 not enabled ?\n"); + goto fail; + } + + YAGL_LOG_TRACE("DRI2Connect returned %s %s", + dri_driver, dri_device); + + drm_fd = open(dri_device, O_RDWR); + + if (drm_fd < 0) { + fprintf(stderr, "Critical error! Failed to open(\"%s\"): %s\n", dri_device, strerror(errno)); + goto fail; + } + + memset(&magic, 0, sizeof(magic)); + + ret = drmGetMagic(drm_fd, &magic); + + if (ret != 0) { + fprintf(stderr, "Critical error! drmGetMagic failed: %s\n", strerror(-ret)); + goto fail; + } + + if (!yagl_DRI2Authenticate(x_dpy, + RootWindow(x_dpy, DefaultScreen(x_dpy)), + magic)) { + fprintf(stderr, "Critical error! Failed to DRI2Authenticate on YaGL display, DRI2 not enabled ?\n"); + goto fail; + } + + goto out; + +fail: + if (drm_fd >= 0) { + close(drm_fd); + drm_fd = -1; + } +out: + if (dri_driver) { + Xfree(dri_driver); + } + if (dri_device) { + Xfree(dri_device); + } + + return drm_fd; +} + +static struct yagl_native_drawable + *yagl_x11_display_wrap_window(struct yagl_native_display *dpy, + yagl_os_window os_window) +{ + return yagl_x11_drawable_create(dpy, os_window, 0, 0); +} + +static struct yagl_native_drawable + *yagl_x11_display_wrap_pixmap(struct yagl_native_display *dpy, + yagl_os_pixmap os_pixmap) +{ + return yagl_x11_drawable_create(dpy, os_pixmap, 0, 1); +} + +static struct yagl_native_drawable + *yagl_x11_display_create_pixmap(struct yagl_native_display *dpy, + uint32_t width, + uint32_t height, + uint32_t depth) +{ + struct yagl_native_drawable *drawable; + Display *x_dpy = YAGL_X11_DPY(dpy->os_dpy); + Pixmap x_pixmap = XCreatePixmap(x_dpy, + RootWindow(x_dpy, DefaultScreen(x_dpy)), + width, height, depth); + + if (!x_pixmap) { + return NULL; + } + + drawable = yagl_x11_drawable_create(dpy, (yagl_os_pixmap)x_pixmap, 1, 1); + + if (!drawable) { + XFreePixmap(x_dpy, x_pixmap); + return NULL; + } + + return drawable; +} + +static struct yagl_native_image + *yagl_x11_display_create_image(struct yagl_native_display *dpy, + uint32_t width, + uint32_t height, + uint32_t depth) +{ + return yagl_x11_image_create(dpy, width, height, depth); +} + +static int yagl_x11_display_get_visual(struct yagl_native_display *dpy, + int *visual_id, + int *visual_type) +{ + Display *x_dpy = YAGL_X11_DPY(dpy->os_dpy); + int screen; + XVisualInfo vi; + + screen = XScreenNumberOfScreen(XDefaultScreenOfDisplay(x_dpy)); + + /* + * 24-bit is the highest supported by soft framebuffer. + */ + if (!XMatchVisualInfo(x_dpy, screen, 24, TrueColor, &vi)) { + return 0; + } + + *visual_id = XVisualIDFromVisual(vi.visual); + *visual_type = TrueColor; + + return 1; +} + +static void yagl_x11_display_destroy(struct yagl_native_display *dpy) +{ + struct yagl_x11_display *x11_dpy = (struct yagl_x11_display*)dpy; + Display *x_dpy = YAGL_X11_DPY(dpy->os_dpy); + + if (x11_dpy->own_dpy) { + XCloseDisplay(x_dpy); + } + + if (dpy->drm_fd >= 0) { + close(dpy->drm_fd); + } + + yagl_native_display_cleanup(dpy); + + yagl_free(x11_dpy); +} + +struct yagl_native_display *yagl_x11_display_create(struct yagl_native_platform *platform, + yagl_os_display os_dpy, + int own_dpy, + int enable_drm) +{ + Display *x_dpy = YAGL_X11_DPY(os_dpy); + struct yagl_x11_display *dpy; + int xmajor; + int xminor; + Bool pixmaps; + int drm_fd = -1; + + YAGL_LOG_FUNC_SET(eglGetDisplay); + + dpy = yagl_malloc0(sizeof(*dpy)); + + dpy->own_dpy = own_dpy; + + dpy->xshm_images_supported = XShmQueryVersion(x_dpy, + &xmajor, + &xminor, + &pixmaps); + dpy->xshm_pixmaps_supported = pixmaps; + + YAGL_LOG_DEBUG("XShm images are%s supported, version %d, %d (pixmaps = %d)", + (dpy->xshm_images_supported ? "" : " NOT"), + xmajor, + xminor, + pixmaps); + + if (enable_drm) { + drm_fd = yagl_x11_display_dri2_init(x_dpy); + + if (drm_fd < 0) { + yagl_free(dpy); + return NULL; + } + } + + yagl_native_display_init(&dpy->base, + platform, + os_dpy, + drm_fd); + + dpy->base.wrap_window = &yagl_x11_display_wrap_window; + dpy->base.wrap_pixmap = &yagl_x11_display_wrap_pixmap; + dpy->base.create_pixmap = &yagl_x11_display_create_pixmap; + dpy->base.create_image = &yagl_x11_display_create_image; + dpy->base.get_visual = &yagl_x11_display_get_visual; + dpy->base.destroy = &yagl_x11_display_destroy; + + return &dpy->base; +} diff --git a/EGL/x11/yagl_x11_display.h b/EGL/x11/yagl_x11_display.h new file mode 100644 index 0000000..7aeb90d --- /dev/null +++ b/EGL/x11/yagl_x11_display.h @@ -0,0 +1,25 @@ +#ifndef _YAGL_X11_DISPLAY_H_ +#define _YAGL_X11_DISPLAY_H_ + +#include "yagl_export.h" +#include "yagl_native_display.h" + +#define YAGL_X11_DPY(os_dpy) ((Display*)(os_dpy)) + +struct yagl_x11_display +{ + struct yagl_native_display base; + + int own_dpy; + + int xshm_images_supported; + + int xshm_pixmaps_supported; +}; + +struct yagl_native_display *yagl_x11_display_create(struct yagl_native_platform *platform, + yagl_os_display os_dpy, + int own_dpy, + int enable_drm); + +#endif diff --git a/EGL/x11/yagl_x11_drawable.c b/EGL/x11/yagl_x11_drawable.c new file mode 100644 index 0000000..b946495 --- /dev/null +++ b/EGL/x11/yagl_x11_drawable.c @@ -0,0 +1,309 @@ +#include "yagl_x11_drawable.h" +#include "yagl_x11_display.h" +#include "yagl_x11_image.h" +#include "yagl_malloc.h" +#include "yagl_dri2.h" +#include "yagl_utils.h" +#include "yagl_log.h" +#include <X11/Xutil.h> +#include <stdio.h> +#include <stdlib.h> + +static uint32_t yagl_x11_drawable_get_buffer(struct yagl_native_drawable *drawable, + yagl_native_attachment attachment) +{ + Display *x_dpy = YAGL_X11_DPY(drawable->dpy->os_dpy); + Drawable x_drawable = YAGL_X11_DRAWABLE(drawable->os_drawable); + unsigned int attachments[1]; + yagl_DRI2Buffer *buffer; + int tmp_width, tmp_height, num_buffers; + uint32_t name; + + YAGL_LOG_FUNC_SET(yagl_x11_drawable_get_buffer); + + if (drawable->dpy->drm_fd < 0) { + fprintf(stderr, "Asking for DRI2 buffer when DRI2 not enabled!\n"); + return 0; + } + + switch (attachment) { + case yagl_native_attachment_front: + attachments[0] = DRI2BufferFrontLeft; + break; + case yagl_native_attachment_back: + attachments[0] = DRI2BufferBackLeft; + break; + default: + YAGL_LOG_ERROR("Bad attachment %u", attachment); + return 0; + } + + buffer = yagl_DRI2GetBuffers(x_dpy, x_drawable, + &tmp_width, &tmp_height, + &attachments[0], + sizeof(attachments)/sizeof(attachments[0]), + &num_buffers); + + if (!buffer) { + return 0; + } + + name = buffer->name; + + Xfree(buffer); + + return name; +} + +static void yagl_x11_drawable_swap_buffers(struct yagl_native_drawable *drawable) +{ + Display *x_dpy = YAGL_X11_DPY(drawable->dpy->os_dpy); + Drawable x_drawable = YAGL_X11_DRAWABLE(drawable->os_drawable); + CARD64 count = 0; + + if (drawable->dpy->drm_fd < 0) { + return; + } + + yagl_DRI2SwapBuffers(x_dpy, + x_drawable, 0, 0, 0, + &count); +} + +static void yagl_x11_drawable_wait(struct yagl_native_drawable *drawable, + uint32_t width, + uint32_t height) +{ + struct yagl_x11_drawable *x11_drawable = (struct yagl_x11_drawable*)drawable; + Display *x_dpy = YAGL_X11_DPY(drawable->dpy->os_dpy); + Drawable x_drawable = YAGL_X11_DRAWABLE(drawable->os_drawable); + XRectangle xrect; + XserverRegion region; + + if (!x11_drawable->is_pixmap || (drawable->dpy->drm_fd < 0)) { + return; + } + + xrect.x = 0; + xrect.y = 0; + xrect.width = width; + xrect.height = height; + + region = XFixesCreateRegion(x_dpy, &xrect, 1); + yagl_DRI2CopyRegion(x_dpy, + x_drawable, + region, + DRI2BufferFakeFrontLeft, + DRI2BufferFrontLeft); + XFixesDestroyRegion(x_dpy, region); +} + +static void yagl_x11_drawable_copy_to_pixmap(struct yagl_native_drawable *drawable, + yagl_os_pixmap os_pixmap, + uint32_t from_x, + uint32_t from_y, + uint32_t to_x, + uint32_t to_y, + uint32_t width, + uint32_t height) +{ + Display *x_dpy = YAGL_X11_DPY(drawable->dpy->os_dpy); + Drawable x_drawable = YAGL_X11_DRAWABLE(drawable->os_drawable); + Pixmap x_pixmap = YAGL_X11_DRAWABLE(os_pixmap); + GC x_gc; + + x_gc = XCreateGC(x_dpy, x_pixmap, 0, NULL); + + if (x_gc) { + XCopyArea(x_dpy, + x_drawable, + x_pixmap, + x_gc, + from_x, from_y, + width, + height, + to_x, to_y); + + XFreeGC(x_dpy, x_gc); + + XSync(x_dpy, 0); + } +} + +static void yagl_x11_drawable_set_swap_interval(struct yagl_native_drawable *drawable, + int interval) +{ + struct yagl_x11_drawable *x11_drawable = (struct yagl_x11_drawable*)drawable; + Display *x_dpy = YAGL_X11_DPY(drawable->dpy->os_dpy); + Drawable x_drawable = YAGL_X11_DRAWABLE(drawable->os_drawable); + + if (x11_drawable->is_pixmap || (drawable->dpy->drm_fd < 0)) { + return; + } + + yagl_DRI2SwapInterval(x_dpy, x_drawable, interval); +} + +static void yagl_x11_drawable_get_geometry(struct yagl_native_drawable *drawable, + uint32_t *width, + uint32_t *height, + uint32_t *depth) +{ + struct yagl_x11_drawable *x11_drawable = (struct yagl_x11_drawable*)drawable; + Display *x_dpy = YAGL_X11_DPY(drawable->dpy->os_dpy); + Drawable x_drawable = YAGL_X11_DRAWABLE(drawable->os_drawable); + union { Window w; int i; unsigned int ui; } tmp_geom; + + if (x11_drawable->is_pixmap) { + pthread_mutex_lock(&x11_drawable->mtx); + + if (!x11_drawable->is_geom_acquired) { + XGetGeometry(x_dpy, + x_drawable, + &tmp_geom.w, + &tmp_geom.i, + &tmp_geom.i, + &x11_drawable->width, + &x11_drawable->height, + &tmp_geom.ui, + &x11_drawable->depth); + + x11_drawable->is_geom_acquired = 1; + } + + pthread_mutex_unlock(&x11_drawable->mtx); + + *width = x11_drawable->width; + *height = x11_drawable->height; + *depth = x11_drawable->depth; + } else { + XGetGeometry(x_dpy, + x_drawable, + &tmp_geom.w, + &tmp_geom.i, + &tmp_geom.i, + width, + height, + &tmp_geom.ui, + depth); + } +} + +static struct yagl_native_image + *yagl_x11_drawable_get_image(struct yagl_native_drawable *drawable, + uint32_t width, + uint32_t height) +{ + Display *x_dpy = YAGL_X11_DPY(drawable->dpy->os_dpy); + Drawable x_drawable = YAGL_X11_DRAWABLE(drawable->os_drawable); + XImage *x_image; + struct yagl_native_image *image; + + YAGL_LOG_FUNC_SET(yagl_x11_drawable_get_image); + + x_image = XGetImage(x_dpy, + x_drawable, + 0, + 0, + width, + height, + AllPlanes, + ZPixmap); + + if (!x_image) { + YAGL_LOG_ERROR("XGetImage failed for drawable %p", + drawable->os_drawable); + return NULL; + } + + image = yagl_x11_image_wrap(drawable->dpy, x_image); + + if (!image) { + YAGL_LOG_ERROR("yagl_x11_image_wrap failed for drawable %p", + drawable->os_drawable); + XDestroyImage(x_image); + return NULL; + } + + return image; +} + +static void yagl_x11_drawable_destroy(struct yagl_native_drawable *drawable) +{ + struct yagl_x11_drawable *x11_drawable = (struct yagl_x11_drawable*)drawable; + Display *x_dpy = YAGL_X11_DPY(drawable->dpy->os_dpy); + Drawable x_drawable = YAGL_X11_DRAWABLE(drawable->os_drawable); + + if (x11_drawable->x_gc) { + XFreeGC(x_dpy, x11_drawable->x_gc); + } + + if (drawable->dpy->drm_fd >= 0) { + yagl_DRI2DestroyDrawable(x_dpy, x_drawable); + } + + pthread_mutex_destroy(&x11_drawable->mtx); + + if (x11_drawable->own_drawable) { + if (x11_drawable->is_pixmap) { + XFreePixmap(x_dpy, x_drawable); + } else { + XDestroyWindow(x_dpy, x_drawable); + } + } + + yagl_native_drawable_cleanup(drawable); + + yagl_free(x11_drawable); +} + +struct yagl_native_drawable *yagl_x11_drawable_create(struct yagl_native_display *dpy, + yagl_os_drawable os_drawable, + int own_drawable, + int is_pixmap) +{ + Display *x_dpy = YAGL_X11_DPY(dpy->os_dpy); + Drawable x_drawable = YAGL_X11_DRAWABLE(os_drawable); + struct yagl_x11_drawable *drawable; + + drawable = yagl_malloc0(sizeof(*drawable)); + + yagl_native_drawable_init(&drawable->base, + dpy, + os_drawable); + + drawable->base.get_buffer = &yagl_x11_drawable_get_buffer; + drawable->base.swap_buffers = &yagl_x11_drawable_swap_buffers; + drawable->base.wait = &yagl_x11_drawable_wait; + drawable->base.copy_to_pixmap = &yagl_x11_drawable_copy_to_pixmap; + drawable->base.set_swap_interval = &yagl_x11_drawable_set_swap_interval; + drawable->base.get_geometry = &yagl_x11_drawable_get_geometry; + drawable->base.get_image = &yagl_x11_drawable_get_image; + drawable->base.destroy = &yagl_x11_drawable_destroy; + + drawable->own_drawable = own_drawable; + drawable->is_pixmap = is_pixmap; + yagl_mutex_init(&drawable->mtx); + + if (dpy->drm_fd >= 0) { + yagl_DRI2CreateDrawable(x_dpy, x_drawable); + } + + return &drawable->base; +} + +GC yagl_x11_drawable_get_gc(struct yagl_x11_drawable *drawable) +{ + pthread_mutex_lock(&drawable->mtx); + + if (!drawable->x_gc) { + Display *x_dpy = YAGL_X11_DPY(drawable->base.dpy->os_dpy); + Drawable x_drawable = YAGL_X11_DRAWABLE(drawable->base.os_drawable); + + drawable->x_gc = XCreateGC(x_dpy, x_drawable, 0, NULL); + } + + pthread_mutex_unlock(&drawable->mtx); + + return drawable->x_gc; +} diff --git a/EGL/x11/yagl_x11_drawable.h b/EGL/x11/yagl_x11_drawable.h new file mode 100644 index 0000000..07862a8 --- /dev/null +++ b/EGL/x11/yagl_x11_drawable.h @@ -0,0 +1,47 @@ +#ifndef _YAGL_X11_DRAWABLE_H_ +#define _YAGL_X11_DRAWABLE_H_ + +#include "yagl_export.h" +#include "yagl_native_drawable.h" +#include <X11/Xlib.h> +#include <pthread.h> + +#define YAGL_X11_DRAWABLE(os_drawable) ((Drawable)(os_drawable)) + +struct yagl_x11_drawable +{ + struct yagl_native_drawable base; + + int own_drawable; + + int is_pixmap; + + pthread_mutex_t mtx; + + /* + * Allocated on first request. + */ + GC x_gc; + + /* + * For pixmaps only, filled on first request. + * @{ + */ + int is_geom_acquired; + uint32_t width; + uint32_t height; + uint32_t depth; + /* + * @} + */ +}; + +struct yagl_native_drawable + *yagl_x11_drawable_create(struct yagl_native_display *dpy, + yagl_os_drawable os_drawable, + int own_drawable, + int is_pixmap); + +GC yagl_x11_drawable_get_gc(struct yagl_x11_drawable *drawable); + +#endif diff --git a/EGL/x11/yagl_x11_image.c b/EGL/x11/yagl_x11_image.c new file mode 100644 index 0000000..c5dfe95 --- /dev/null +++ b/EGL/x11/yagl_x11_image.c @@ -0,0 +1,275 @@ +#include "yagl_x11_image.h" +#include "yagl_x11_display.h" +#include "yagl_x11_drawable.h" +#include "yagl_malloc.h" +#include "yagl_log.h" +#include <X11/Xutil.h> +#include <sys/ipc.h> +#include <sys/shm.h> +#include <sys/time.h> +#include <sys/mman.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +static void yagl_x11_image_draw_internal(struct yagl_x11_image *image, + Drawable target, + GC x_gc) +{ + Display *x_dpy = YAGL_X11_DPY(image->base.dpy->os_dpy); + + if (image->x_shm.shmid != -1) { + XShmPutImage(x_dpy, target, x_gc, image->x_image, + 0, 0, 0, 0, image->base.width, image->base.height, 0); + } else { + XPutImage(x_dpy, target, x_gc, image->x_image, + 0, 0, 0, 0, image->base.width, image->base.height); + } + + XFlush(x_dpy); +} + +static void yagl_x11_image_draw(struct yagl_native_image *image, + struct yagl_native_drawable *drawable) +{ + struct yagl_x11_image *x11_image = (struct yagl_x11_image*)image; + struct yagl_x11_drawable *x11_drawable = (struct yagl_x11_drawable*)drawable; + Drawable x_drawable = YAGL_X11_DRAWABLE(drawable->os_drawable); + GC x_gc = yagl_x11_drawable_get_gc(x11_drawable); + + if (x_gc) { + yagl_x11_image_draw_internal(x11_image, x_drawable, x_gc); + } +} + +static void yagl_x11_image_draw_to_pixmap(struct yagl_native_image *image, + yagl_os_pixmap os_pixmap) +{ + struct yagl_x11_image *x11_image = (struct yagl_x11_image*)image; + Display *x_dpy = YAGL_X11_DPY(image->dpy->os_dpy); + Pixmap x_pixmap = YAGL_X11_DRAWABLE(os_pixmap); + GC x_gc = XCreateGC(x_dpy, x_pixmap, 0, NULL); + + if (x_gc) { + yagl_x11_image_draw_internal(x11_image, x_pixmap, x_gc); + XFreeGC(x_dpy, x_gc); + } +} + +static void yagl_x11_image_destroy(struct yagl_native_image *image) +{ + struct yagl_x11_image *x11_image = (struct yagl_x11_image*)image; + + if (x11_image->is_wrapped) { + XDestroyImage(x11_image->x_image); + x11_image->x_image = NULL; + } else { + Display *x_dpy = YAGL_X11_DPY(image->dpy->os_dpy); + + if (x11_image->x_shm.shmid != -1) { + XShmDetach(x_dpy, &x11_image->x_shm); + + shmdt(x11_image->x_shm.shmaddr); + x11_image->x_shm.shmaddr = (char*)-1; + + shmctl(x11_image->x_shm.shmid, IPC_RMID, 0); + x11_image->x_shm.shmid = -1; + + XDestroyImage(x11_image->x_image); + x11_image->x_image = NULL; + } else { + yagl_free(x11_image->x_image); + x11_image->x_image = NULL; + + yagl_free(image->pixels); + } + } + + yagl_native_image_cleanup(image); + + yagl_free(x11_image); +} + +struct yagl_native_image + *yagl_x11_image_create(struct yagl_native_display *dpy, + uint32_t width, + uint32_t height, + uint32_t depth) +{ + struct yagl_x11_display *x11_dpy = (struct yagl_x11_display*)dpy; + Display *x_dpy = YAGL_X11_DPY(dpy->os_dpy); + struct yagl_x11_image *image; + XPixmapFormatValues *pfs; + int i, num_formats; + Visual visual; + unsigned int image_bytes = 0; + void *pixels = NULL; + uint32_t bpp = 0; + + YAGL_LOG_FUNC_ENTER(yagl_x11_image_create, + "width = %u, height = %u, depth = %u", + width, height, depth); + + image = yagl_malloc0(sizeof(*image)); + + pfs = XListPixmapFormats(x_dpy, &num_formats); + + if (!pfs) { + YAGL_LOG_ERROR("XListPixmapFormats failed"); + + goto fail; + } + + for (i = 0; i < num_formats; ++i) { + if (pfs[i].depth == (int)depth) { + bpp = (pfs[i].bits_per_pixel / 8); + break; + } + } + + XFree(pfs); + pfs = NULL; + + if (i == num_formats) { + YAGL_LOG_ERROR("No suitable pixmap format found for depth %u", depth); + + goto fail; + } + + if (x11_dpy->xshm_images_supported) { + image->x_image = XShmCreateImage(x_dpy, + &visual, + depth, + ZPixmap, + NULL, + &image->x_shm, + width, + height); + if (image->x_image) { + image_bytes = image->x_image->bytes_per_line * image->x_image->height; + + image->x_shm.shmid = shmget(IPC_PRIVATE, + image_bytes, + IPC_CREAT | 0777); + + if (image->x_shm.shmid != -1) { + image->x_shm.shmaddr = shmat(image->x_shm.shmid, 0, 0); + + if (image->x_shm.shmaddr != (char*)-1) { + if (XShmAttach(x_dpy, &image->x_shm)) { + pixels = image->x_image->data = image->x_shm.shmaddr; + + goto allocated; + } else { + YAGL_LOG_ERROR("XShmAttach failed"); + } + + shmdt(image->x_shm.shmaddr); + image->x_shm.shmaddr = (char*)-1; + } else { + YAGL_LOG_ERROR("shmat failed"); + } + + shmctl(image->x_shm.shmid, IPC_RMID, 0); + image->x_shm.shmid = -1; + } else { + YAGL_LOG_ERROR("shmget failed"); + } + + XDestroyImage(image->x_image); + image->x_image = NULL; + } else { + YAGL_LOG_ERROR("XShmCreateImage failed"); + } + } + +allocated: + if (!image->x_image) { + image->x_shm.shmid = -1; + + image_bytes = width * height * bpp; + + pixels = yagl_malloc(image_bytes); + + image->x_image = yagl_malloc0(sizeof(*image->x_image)); + + image->x_image->width = width; + image->x_image->height = height; + image->x_image->xoffset = 0; + image->x_image->format = ZPixmap; + image->x_image->data = pixels; + image->x_image->byte_order = LSBFirst; + image->x_image->bitmap_unit = bpp * 8; + image->x_image->bitmap_pad = 8; + image->x_image->depth = depth; + image->x_image->bytes_per_line = width * bpp; + image->x_image->bits_per_pixel = bpp * 8; + + if (!XInitImage(image->x_image)) { + YAGL_LOG_ERROR("XInitImage failed"); + + yagl_free(image->x_image); + image->x_image = NULL; + + yagl_free(pixels); + pixels = NULL; + + goto fail; + } + } + + XSync(x_dpy, 0); + + yagl_native_image_init(&image->base, + dpy, + width, + height, + depth, + bpp, + pixels); + + image->base.draw = &yagl_x11_image_draw; + image->base.draw_to_pixmap = &yagl_x11_image_draw_to_pixmap; + image->base.destroy = &yagl_x11_image_destroy; + + image->is_wrapped = 0; + + YAGL_LOG_FUNC_EXIT(NULL); + + return &image->base; + +fail: + yagl_free(image); + + YAGL_LOG_FUNC_EXIT(NULL); + + return NULL; +} + +struct yagl_native_image + *yagl_x11_image_wrap(struct yagl_native_display *dpy, + XImage *x_image) +{ + struct yagl_x11_image *image; + + image = yagl_malloc0(sizeof(*image)); + + yagl_native_image_init(&image->base, + dpy, + x_image->width, + x_image->height, + x_image->depth, + (x_image->bits_per_pixel / 8), + x_image->data); + + image->base.draw = &yagl_x11_image_draw; + image->base.draw_to_pixmap = &yagl_x11_image_draw_to_pixmap; + image->base.destroy = &yagl_x11_image_destroy; + + image->x_image = x_image; + image->x_shm.shmid = -1; + image->is_wrapped = 1; + + return &image->base; +} diff --git a/EGL/x11/yagl_x11_image.h b/EGL/x11/yagl_x11_image.h new file mode 100644 index 0000000..f6853a8 --- /dev/null +++ b/EGL/x11/yagl_x11_image.h @@ -0,0 +1,32 @@ +#ifndef _YAGL_X11_IMAGE_H_ +#define _YAGL_X11_IMAGE_H_ + +#include "yagl_export.h" +#include "yagl_native_image.h" +#include <X11/Xlib.h> +#include <X11/extensions/XShm.h> + +struct yagl_x11_image +{ + struct yagl_native_image base; + + XImage *x_image; /* X11 image */ + XShmSegmentInfo x_shm; /* X11 shared memory segment */ + + int is_wrapped; +}; + +struct yagl_native_image + *yagl_x11_image_create(struct yagl_native_display *dpy, + uint32_t width, + uint32_t height, + uint32_t depth); + +/* + * Takes ownership of 'x_image'. + */ +struct yagl_native_image + *yagl_x11_image_wrap(struct yagl_native_display *dpy, + XImage *x_image); + +#endif diff --git a/EGL/x11/yagl_x11_platform.c b/EGL/x11/yagl_x11_platform.c new file mode 100644 index 0000000..6840adf --- /dev/null +++ b/EGL/x11/yagl_x11_platform.c @@ -0,0 +1,55 @@ +#include "yagl_x11_platform.h" +#include "yagl_x11_display.h" +#include "yagl_native_platform.h" +#include "yagl_log.h" +#include "EGL/egl.h" +#include <X11/Xlib.h> + +static int yagl_x11_platform_probe(yagl_os_display os_dpy) +{ + /* + * Can't probe for X11, so assume probe passed. + */ + + return 1; +} + +static struct yagl_native_display + *yagl_x11_wrap_display(yagl_os_display os_dpy, + int enable_drm) +{ + struct yagl_native_display *dpy; + + YAGL_LOG_FUNC_SET(eglGetDisplay); + + if (os_dpy == (yagl_os_display)EGL_DEFAULT_DISPLAY) { + Display *x_dpy = XOpenDisplay(0); + + if (!x_dpy) { + YAGL_LOG_ERROR("unable to open display 0"); + return NULL; + } + + dpy = yagl_x11_display_create(&yagl_x11_platform, + (yagl_os_display)x_dpy, + 1, + enable_drm); + + if (!dpy) { + XCloseDisplay(x_dpy); + } + } else { + dpy = yagl_x11_display_create(&yagl_x11_platform, + os_dpy, + 0, + enable_drm); + } + + return dpy; +} + +struct yagl_native_platform yagl_x11_platform = +{ + .probe = yagl_x11_platform_probe, + .wrap_display = yagl_x11_wrap_display +}; diff --git a/EGL/x11/yagl_x11_platform.h b/EGL/x11/yagl_x11_platform.h new file mode 100644 index 0000000..e167ffd --- /dev/null +++ b/EGL/x11/yagl_x11_platform.h @@ -0,0 +1,10 @@ +#ifndef _YAGL_X11_PLATFORM_H_ +#define _YAGL_X11_PLATFORM_H_ + +#include "yagl_export.h" + +struct yagl_native_platform; + +extern struct yagl_native_platform yagl_x11_platform; + +#endif diff --git a/EGL/yagl_backend.h b/EGL/yagl_backend.h index 6207869..d326ec6 100644 --- a/EGL/yagl_backend.h +++ b/EGL/yagl_backend.h @@ -3,37 +3,48 @@ #include "yagl_export.h" #include "yagl_types.h" -#include <X11/X.h> +#include "yagl_native_types.h" #include "EGL/egl.h" struct yagl_display; struct yagl_surface; struct yagl_image; +struct yagl_native_platform; +struct yagl_native_drawable; struct yagl_backend { - struct yagl_display *(*create_display)(EGLNativeDisplayType /*display_id*/, - Display */*x_dpy*/, + struct yagl_display *(*create_display)(struct yagl_native_platform */*platform*/, + yagl_os_display /*os_dpy*/, yagl_host_handle /*host_dpy*/); + /* + * Takes ownership of 'native_window'. + */ struct yagl_surface *(*create_window_surface)(struct yagl_display */*dpy*/, yagl_host_handle /*host_config*/, - Window /*x_win*/, - const EGLint* /*attrib_list*/); + struct yagl_native_drawable */*native_window*/, + const EGLint */*attrib_list*/); + /* + * Takes ownership of 'native_pixmap'. + */ struct yagl_surface *(*create_pixmap_surface)(struct yagl_display */*dpy*/, yagl_host_handle /*host_config*/, - Pixmap /*x_pixmap*/, - const EGLint* /*attrib_list*/); + struct yagl_native_drawable */*native_pixmap*/, + const EGLint */*attrib_list*/); struct yagl_surface *(*create_pbuffer_surface)(struct yagl_display */*dpy*/, yagl_host_handle /*host_config*/, - const EGLint* /*attrib_list*/); + const EGLint */*attrib_list*/); + /* + * Takes ownership of 'native_pixmap'. + */ struct yagl_image *(*create_image)(struct yagl_display */*dpy*/, yagl_host_handle /*host_context*/, - Pixmap /*x_pixmap*/, - const EGLint* /*attrib_list*/); + struct yagl_native_drawable */*native_pixmap*/, + const EGLint */*attrib_list*/); void (*destroy)(struct yagl_backend */*backend*/); diff --git a/EGL/yagl_bimage.c b/EGL/yagl_bimage.c deleted file mode 100644 index 1265deb..0000000 --- a/EGL/yagl_bimage.c +++ /dev/null @@ -1,208 +0,0 @@ -#include "yagl_bimage.h" -#include "yagl_log.h" -#include "yagl_malloc.h" -#include "yagl_display.h" -#include "yagl_mem.h" -#include <sys/ipc.h> -#include <sys/shm.h> -#include <sys/time.h> -#include <sys/mman.h> -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -struct yagl_bimage *yagl_bimage_create(struct yagl_display *dpy, - uint32_t width, - uint32_t height, - uint32_t depth) -{ - struct yagl_bimage *res = NULL; - XPixmapFormatValues *pfs; - int i, num_formats; - Visual visual; - unsigned int image_bytes = 0; - - YAGL_LOG_FUNC_ENTER(yagl_bimage_create, - "width = %u, height = %u, depth = %u", - width, height, depth); - - res = yagl_malloc0(sizeof(*res)); - - res->width = width; - res->height = height; - res->depth = depth; - res->dpy = dpy; - - pfs = XListPixmapFormats(dpy->x_dpy, &num_formats); - - if (!pfs) { - YAGL_LOG_ERROR("XListPixmapFormats failed"); - - goto fail; - } - - for (i = 0; i < num_formats; ++i) { - if (pfs[i].depth == (int)depth) { - res->bpp = (pfs[i].bits_per_pixel / 8); - break; - } - } - - XFree(pfs); - pfs = NULL; - - if (i == num_formats) { - YAGL_LOG_ERROR("No suitable pixmap format found for depth %u", depth); - - goto fail; - } - - if (dpy->xshm_images_supported) { - res->x_image = XShmCreateImage(dpy->x_dpy, - &visual, - depth, - ZPixmap, - NULL, - &res->x_shm, - width, - height); - if (res->x_image) { - image_bytes = res->x_image->bytes_per_line * res->x_image->height; - - res->x_shm.shmid = shmget(IPC_PRIVATE, image_bytes, IPC_CREAT | 0777); - - if (res->x_shm.shmid != -1) { - res->x_shm.shmaddr = shmat(res->x_shm.shmid, 0, 0); - - if (res->x_shm.shmaddr != (char*)-1) { - if (XShmAttach(dpy->x_dpy, &res->x_shm)) { - res->pixels = res->x_image->data = res->x_shm.shmaddr; - - goto allocated; - } else { - YAGL_LOG_ERROR("XShmAttach failed"); - } - - shmdt(res->x_shm.shmaddr); - res->x_shm.shmaddr = (char*)-1; - } else { - YAGL_LOG_ERROR("shmat failed"); - } - - shmctl(res->x_shm.shmid, IPC_RMID, 0); - res->x_shm.shmid = -1; - } else { - YAGL_LOG_ERROR("shmget failed"); - } - - XDestroyImage(res->x_image); - res->x_image = NULL; - } else { - YAGL_LOG_ERROR("XShmCreateImage failed"); - } - } - -allocated: - if (!dpy->xshm_images_supported || !res->x_image) { - image_bytes = width * height * res->bpp; - - res->pixels = yagl_malloc(image_bytes); - - res->x_image = yagl_malloc0(sizeof(*res->x_image)); - - res->x_image->width = res->width; - res->x_image->height = res->height; - res->x_image->xoffset = 0; - res->x_image->format = ZPixmap; - res->x_image->data = res->pixels; - res->x_image->byte_order = LSBFirst; - res->x_image->bitmap_unit = res->bpp * 8; - res->x_image->bitmap_pad = 8; - res->x_image->depth = res->depth; - res->x_image->bytes_per_line = res->width * res->bpp; - res->x_image->bits_per_pixel = res->bpp * 8; - - if (!XInitImage(res->x_image)) { - YAGL_LOG_ERROR("XInitImage failed"); - - yagl_free(res->x_image); - res->x_image = NULL; - - yagl_free(res->pixels); - res->pixels = NULL; - - goto fail; - } - } - - XSync(dpy->x_dpy, 0); - - if (mlock(res->pixels, res->width * res->height * res->bpp) == -1) - { - fprintf(stderr, "Critical error! Unable to lock YaGL bimage memory: %s!\n", strerror(errno)); - exit(1); - } - - /* - * Probe in immediately. - */ - - yagl_mem_probe_write(res->pixels, res->width * res->height * res->bpp); - - YAGL_LOG_FUNC_EXIT(NULL); - - return res; - -fail: - yagl_free(res); - - YAGL_LOG_FUNC_EXIT(NULL); - - return NULL; -} - -void yagl_bimage_destroy(struct yagl_bimage *bi) -{ - if (munlock(bi->pixels, bi->width * bi->height * bi->bpp) == -1) - { - fprintf(stderr, "Critical error! Unable to unlock YaGL bimage memory: %s!\n", strerror(errno)); - exit(1); - } - - if (bi->x_shm.shmid != -1) { - XShmDetach(bi->dpy->x_dpy, &bi->x_shm); - - shmdt(bi->x_shm.shmaddr); - bi->x_shm.shmaddr = (char*)-1; - - shmctl(bi->x_shm.shmid, IPC_RMID, 0); - bi->x_shm.shmid = -1; - - XDestroyImage(bi->x_image); - bi->x_image = NULL; - - bi->pixels = NULL; - } else { - yagl_free(bi->x_image); - bi->x_image = NULL; - - yagl_free(bi->pixels); - bi->pixels = NULL; - } - - yagl_free(bi); -} - -void yagl_bimage_draw(struct yagl_bimage *bi, Drawable target, GC gc) -{ - if (bi->x_shm.shmid != -1) { - XShmPutImage(bi->dpy->x_dpy, target, gc, bi->x_image, - 0, 0, 0, 0, bi->width, bi->height, 0); - } else { - XPutImage(bi->dpy->x_dpy, target, gc, bi->x_image, - 0, 0, 0, 0, bi->width, bi->height); - } - - XFlush(bi->dpy->x_dpy); -} diff --git a/EGL/yagl_bimage.h b/EGL/yagl_bimage.h deleted file mode 100644 index 98ee5d0..0000000 --- a/EGL/yagl_bimage.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef _YAGL_BIMAGE_H_ -#define _YAGL_BIMAGE_H_ - -#include "yagl_export.h" -#include "yagl_types.h" -#include "EGL/egl.h" -#include <X11/X.h> -#include <X11/Xlib.h> -#include <X11/Xutil.h> -#include <X11/extensions/XShm.h> - -/* - * Backing image for offscreen surfaces. - */ - -struct yagl_display; - -struct yagl_bimage -{ - uint32_t width; - uint32_t height; - uint32_t depth; /* bit-depth. e.g.: 24 */ - - uint32_t bpp; /* bytes-per-pixel. e.g.: 3 */ - void *pixels; /* pixel data */ - - struct yagl_display *dpy; /* The owning display */ - XShmSegmentInfo x_shm; /* X11 shared memory segment */ - XImage* x_image; /* X11 image */ -}; - -struct yagl_bimage *yagl_bimage_create(struct yagl_display *dpy, - uint32_t width, - uint32_t height, - uint32_t depth); - -void yagl_bimage_destroy(struct yagl_bimage *bi); - -void yagl_bimage_draw(struct yagl_bimage *bi, Drawable target, GC gc); - -#endif diff --git a/EGL/yagl_display.c b/EGL/yagl_display.c index 543c13b..f2bcb27 100644 --- a/EGL/yagl_display.c +++ b/EGL/yagl_display.c @@ -5,8 +5,7 @@ #include "yagl_surface.h" #include "yagl_context.h" #include "yagl_image.h" -#include <X11/Xutil.h> -#include <X11/extensions/XShm.h> +#include "yagl_native_display.h" #include <stdio.h> #include <stdlib.h> #include <assert.h> @@ -31,19 +30,13 @@ static void yagl_displays_init(void) } void yagl_display_init(struct yagl_display *dpy, - EGLNativeDisplayType display_id, - Display *x_dpy, + yagl_os_display display_id, + struct yagl_native_display *native_dpy, yagl_host_handle host_dpy) { - int xmajor; - int xminor; - Bool pixmaps; - - YAGL_LOG_FUNC_SET(eglGetDisplay); - yagl_list_init(&dpy->list); dpy->display_id = display_id; - dpy->x_dpy = x_dpy; + dpy->native_dpy = native_dpy; dpy->host_dpy = host_dpy; /* * Need recursive mutex here, @@ -51,35 +44,15 @@ void yagl_display_init(struct yagl_display *dpy, */ yagl_recursive_mutex_init(&dpy->mutex); dpy->prepared = 0; - dpy->xshm_images_supported = XShmQueryVersion(dpy->x_dpy, - &xmajor, - &xminor, - &pixmaps); - dpy->xshm_pixmaps_supported = pixmaps; - - YAGL_LOG_DEBUG("XShm images are%s supported, version %d, %d (pixmaps = %d)", - (dpy->xshm_images_supported ? "" : " NOT"), - xmajor, - xminor, - pixmaps); yagl_list_init(&dpy->surfaces); yagl_list_init(&dpy->contexts); yagl_list_init(&dpy->images); } -void yagl_display_cleanup(struct yagl_display *dpy) -{ - assert(yagl_list_empty(&dpy->images)); - assert(yagl_list_empty(&dpy->contexts)); - assert(yagl_list_empty(&dpy->surfaces)); - pthread_mutex_destroy(&dpy->mutex); - assert(yagl_list_empty(&dpy->list)); -} - -struct yagl_display *yagl_display_get(EGLDisplay native_dpy) +struct yagl_display *yagl_display_get(EGLDisplay handle) { - yagl_host_handle host_dpy = (yagl_host_handle)native_dpy; + yagl_host_handle host_dpy = (yagl_host_handle)handle; struct yagl_display *dpy; yagl_displays_init(); @@ -99,7 +72,7 @@ struct yagl_display *yagl_display_get(EGLDisplay native_dpy) return NULL; } -struct yagl_display *yagl_display_get_x(Display *x_dpy) +struct yagl_display *yagl_display_get_os(yagl_os_display os_dpy) { struct yagl_display *dpy; @@ -108,7 +81,7 @@ struct yagl_display *yagl_display_get_x(Display *x_dpy) pthread_mutex_lock(&g_displays_mutex); yagl_list_for_each(struct yagl_display, dpy, &g_displays, list) { - if (dpy->x_dpy == x_dpy) { + if (dpy->native_dpy->os_dpy == os_dpy) { pthread_mutex_unlock(&g_displays_mutex); return dpy; @@ -120,11 +93,11 @@ struct yagl_display *yagl_display_get_x(Display *x_dpy) return NULL; } -struct yagl_display *yagl_display_add(EGLNativeDisplayType display_id, +struct yagl_display *yagl_display_add(struct yagl_native_platform *platform, + yagl_os_display display_id, yagl_host_handle host_dpy) { struct yagl_display *dpy; - Display *x_dpy; YAGL_LOG_FUNC_SET(eglGetDisplay); @@ -150,29 +123,9 @@ struct yagl_display *yagl_display_add(EGLNativeDisplayType display_id, } } - if (display_id == EGL_DEFAULT_DISPLAY) { - x_dpy = XOpenDisplay(0); - - if (!x_dpy) { - pthread_mutex_unlock(&g_displays_mutex); - - YAGL_LOG_ERROR("unable to open display 0"); - - return NULL; - } - } else { - x_dpy = display_id; - } - - dpy = yagl_get_backend()->create_display(display_id, - x_dpy, - host_dpy); + dpy = yagl_get_backend()->create_display(platform, display_id, host_dpy); if (!dpy) { - if (display_id == EGL_DEFAULT_DISPLAY) { - XCloseDisplay(x_dpy); - } - pthread_mutex_unlock(&g_displays_mutex); return NULL; @@ -266,7 +219,7 @@ void yagl_display_terminate(struct yagl_display *dpy) } int yagl_display_surface_add(struct yagl_display *dpy, - struct yagl_surface *sfc) + struct yagl_surface *sfc) { struct yagl_resource *res = NULL; EGLSurface handle = yagl_surface_get_handle(sfc); diff --git a/EGL/yagl_display.h b/EGL/yagl_display.h index 00855ff..dae320a 100644 --- a/EGL/yagl_display.h +++ b/EGL/yagl_display.h @@ -4,6 +4,7 @@ #include "yagl_export.h" #include "yagl_types.h" #include "yagl_list.h" +#include "yagl_native_types.h" #include "EGL/egl.h" #include "EGL/eglext.h" #include <pthread.h> @@ -11,21 +12,19 @@ struct yagl_surface; struct yagl_context; struct yagl_image; +struct yagl_native_platform; +struct yagl_native_display; struct yagl_display { struct yagl_list list; - EGLNativeDisplayType display_id; + yagl_os_display display_id; - Display *x_dpy; + struct yagl_native_display *native_dpy; yagl_host_handle host_dpy; - int xshm_images_supported; - - int xshm_pixmaps_supported; - pthread_mutex_t mutex; int prepared; @@ -37,18 +36,20 @@ struct yagl_display struct yagl_list images; }; +/* + * Takes ownership of 'native_dpy'. + */ void yagl_display_init(struct yagl_display *dpy, - EGLNativeDisplayType display_id, - Display *x_dpy, + yagl_os_display display_id, + struct yagl_native_display *native_dpy, yagl_host_handle host_dpy); -void yagl_display_cleanup(struct yagl_display *dpy); - -struct yagl_display *yagl_display_get(EGLDisplay native_dpy); +struct yagl_display *yagl_display_get(EGLDisplay handle); -struct yagl_display *yagl_display_get_x(Display *x_dpy); +struct yagl_display *yagl_display_get_os(yagl_os_display os_dpy); -struct yagl_display *yagl_display_add(EGLNativeDisplayType display_id, +struct yagl_display *yagl_display_add(struct yagl_native_platform *platform, + yagl_os_display display_id, yagl_host_handle host_dpy); void yagl_display_prepare(struct yagl_display *dpy); diff --git a/EGL/yagl_egl_calls.c b/EGL/yagl_egl_calls.c index 8c3a417..f9aac39 100644 --- a/EGL/yagl_egl_calls.c +++ b/EGL/yagl_egl_calls.c @@ -10,6 +10,9 @@ #include "yagl_mem_egl.h" #include "yagl_backend.h" #include "yagl_render.h" +#include "yagl_native_platform.h" +#include "yagl_native_display.h" +#include "yagl_native_drawable.h" #include "EGL/eglext.h" #include <stdio.h> #include <string.h> @@ -97,24 +100,33 @@ YAGL_API EGLint eglGetError() YAGL_API EGLDisplay eglGetDisplay(EGLNativeDisplayType display_id) { + struct yagl_native_platform *platform; yagl_host_handle host_dpy; struct yagl_display *dpy; EGLDisplay ret = EGL_NO_DISPLAY; YAGL_LOG_FUNC_ENTER_SPLIT1(eglGetDisplay, EGLNativeDisplayType, display_id); + platform = yagl_guess_platform((yagl_os_display)display_id); + + if (!platform) { + goto out; + } + YAGL_HOST_CALL_ASSERT(yagl_host_eglGetDisplay(&host_dpy, display_id)); if (!host_dpy) { - YAGL_LOG_ERROR("unable to get host display for %p", display_id); + YAGL_LOG_ERROR("unable to get host display for %p", + (yagl_os_display)display_id); goto out; } - dpy = yagl_display_add(display_id, host_dpy); + dpy = yagl_display_add(platform, (yagl_os_display)display_id, host_dpy); if (!dpy) { YAGL_SET_ERR(EGL_BAD_DISPLAY); - YAGL_LOG_ERROR("unable to add display %p, %u", display_id, host_dpy); + YAGL_LOG_ERROR("unable to add display %p, %u", + (yagl_os_display)display_id, host_dpy); goto out; } @@ -231,7 +243,7 @@ YAGL_API EGLBoolean eglGetConfigs( EGLDisplay dpy_, EGLint* num_config ) { EGLBoolean retval = EGL_FALSE; - yagl_host_handle* configs = NULL; + yagl_host_handle *configs = NULL; EGLint i; YAGL_LOG_FUNC_ENTER(eglGetConfigs, @@ -285,7 +297,7 @@ YAGL_API EGLBoolean eglChooseConfig( EGLDisplay dpy, EGLint* num_config ) { EGLBoolean retval = EGL_FALSE; - yagl_host_handle* configs = NULL; + yagl_host_handle *configs = NULL; EGLint i; YAGL_LOG_FUNC_ENTER(eglChooseConfig, "dpy = %u", (yagl_host_handle)dpy); @@ -337,8 +349,7 @@ YAGL_API EGLBoolean eglGetConfigAttrib( EGLDisplay dpy_, { struct yagl_display *dpy = NULL; EGLBoolean ret = EGL_FALSE; - int screen; - XVisualInfo vi; + int visual_id = 0, visual_type = 0; YAGL_LOG_FUNC_ENTER(eglGetConfigAttrib, "dpy = %u, config = %u, attribute = 0x%X", @@ -357,22 +368,18 @@ YAGL_API EGLBoolean eglGetConfigAttrib( EGLDisplay dpy_, break; case EGL_NATIVE_VISUAL_ID: case EGL_NATIVE_VISUAL_TYPE: - screen = XScreenNumberOfScreen(XDefaultScreenOfDisplay(dpy->x_dpy)); - - /* - * 24-bit is the highest supported by soft framebuffer. - */ - if (!XMatchVisualInfo(dpy->x_dpy, screen, 24, TrueColor, &vi)) - { + if (!dpy->native_dpy->get_visual(dpy->native_dpy, + &visual_id, + &visual_type)) { YAGL_SET_ERR(EGL_BAD_CONFIG); - YAGL_LOG_ERROR("XMatchVisualInfo failed"); + YAGL_LOG_ERROR("get_visual failed"); goto fail; } if (attribute == EGL_NATIVE_VISUAL_ID) { - *value = XVisualIDFromVisual(vi.visual); + *value = visual_id; } else { - *value = TrueColor; + *value = visual_type; } ret = EGL_TRUE; @@ -410,6 +417,7 @@ YAGL_API EGLSurface eglCreateWindowSurface( EGLDisplay dpy_, const EGLint* attrib_list) { struct yagl_display *dpy = NULL; + struct yagl_native_drawable *native_win = NULL; struct yagl_surface *surface = NULL; YAGL_LOG_FUNC_ENTER(eglCreateWindowSurface, @@ -421,12 +429,21 @@ YAGL_API EGLSurface eglCreateWindowSurface( EGLDisplay dpy_, goto fail; } + native_win = dpy->native_dpy->wrap_window(dpy->native_dpy, + (yagl_os_window)win); + + if (!native_win) { + goto fail; + } + surface = yagl_get_backend()->create_window_surface(dpy, (yagl_host_handle)config, - win, + native_win, attrib_list); if (!surface) { + native_win->destroy(native_win); + native_win = NULL; goto fail; } @@ -506,6 +523,7 @@ YAGL_API EGLSurface eglCreatePixmapSurface( EGLDisplay dpy_, const EGLint* attrib_list ) { struct yagl_display *dpy = NULL; + struct yagl_native_drawable *native_pixmap = NULL; struct yagl_surface *surface = NULL; YAGL_LOG_FUNC_ENTER(eglCreatePixmapSurface, @@ -517,12 +535,21 @@ YAGL_API EGLSurface eglCreatePixmapSurface( EGLDisplay dpy_, goto fail; } + native_pixmap = dpy->native_dpy->wrap_pixmap(dpy->native_dpy, + (yagl_os_pixmap)pixmap); + + if (!native_pixmap) { + goto fail; + } + surface = yagl_get_backend()->create_pixmap_surface(dpy, (yagl_host_handle)config, - pixmap, + native_pixmap, attrib_list); if (!surface) { + native_pixmap->destroy(native_pixmap); + native_pixmap = NULL; goto fail; } @@ -1328,6 +1355,7 @@ YAGL_API EGLImageKHR eglCreateImageKHR( EGLDisplay dpy_, { EGLImageKHR ret = EGL_NO_IMAGE_KHR; struct yagl_display *dpy = NULL; + struct yagl_native_drawable *native_buffer = NULL; struct yagl_image *image = NULL; YAGL_LOG_FUNC_ENTER(eglCreateImageKHR, @@ -1351,12 +1379,21 @@ YAGL_API EGLImageKHR eglCreateImageKHR( EGLDisplay dpy_, goto out; } + native_buffer = dpy->native_dpy->wrap_pixmap(dpy->native_dpy, + (yagl_os_pixmap)buffer); + + if (!native_buffer) { + goto out; + } + image = yagl_get_backend()->create_image(dpy, (yagl_host_handle)ctx, - (Pixmap)buffer, + native_buffer, attrib_list); if (!image) { + native_buffer->destroy(native_buffer); + native_buffer = NULL; goto out; } diff --git a/EGL/yagl_egl_calls.in b/EGL/yagl_egl_calls.in index 29b02d3..6bd93e9 100644 --- a/EGL/yagl_egl_calls.in +++ b/EGL/yagl_egl_calls.in @@ -1,5 +1,5 @@ EGLint, eglGetError -EGLDisplay^, eglGetDisplay, Display* display_id +EGLDisplay^, eglGetDisplay, void* display_id EGLBoolean, eglInitialize, EGLDisplay^ dpy, EGLint* major, EGLint* minor EGLBoolean, eglTerminate, EGLDisplay^ dpy EGLBoolean, eglGetConfigs, EGLDisplay^ dpy, EGLConfig^* configs, EGLint config_size, EGLint* num_config diff --git a/EGL/yagl_host_egl_calls.c b/EGL/yagl_host_egl_calls.c index 68e6f73..bcb150a 100644 --- a/EGL/yagl_host_egl_calls.c +++ b/EGL/yagl_host_egl_calls.c @@ -31,7 +31,7 @@ int yagl_host_eglGetError(EGLint* retval) /* * eglGetDisplay wrapper. id = 2 */ -int yagl_host_eglGetDisplay(yagl_host_handle* retval, Display* display_id) +int yagl_host_eglGetDisplay(yagl_host_handle* retval, void* display_id) { uint8_t* base = yagl_batch_get_marshal(); yagl_marshal_put_uint32(&base, yagl_api_id_egl); diff --git a/EGL/yagl_host_egl_calls.h b/EGL/yagl_host_egl_calls.h index 9b3baa1..ef0cba5 100644 --- a/EGL/yagl_host_egl_calls.h +++ b/EGL/yagl_host_egl_calls.h @@ -16,7 +16,7 @@ int yagl_host_eglGetError(EGLint* retval); /* * eglGetDisplay wrapper. id = 2 */ -int yagl_host_eglGetDisplay(yagl_host_handle* retval, Display* display_id); +int yagl_host_eglGetDisplay(yagl_host_handle* retval, void* display_id); /* * eglInitialize wrapper. id = 3 diff --git a/EGL/yagl_image.c b/EGL/yagl_image.c index 2927560..becbdca 100644 --- a/EGL/yagl_image.c +++ b/EGL/yagl_image.c @@ -1,4 +1,5 @@ #include "yagl_image.h" +#include "yagl_native_drawable.h" static void yagl_gles_image_update(struct yagl_gles_image *image) { @@ -12,24 +13,26 @@ void yagl_image_init(struct yagl_image *image, yagl_ref_destroy_func destroy_func, yagl_host_handle handle, struct yagl_display *dpy, - Pixmap x_pixmap) + struct yagl_native_drawable *native_pixmap) { yagl_resource_init(&image->res, destroy_func, handle); image->dpy = dpy; - image->x_pixmap = x_pixmap; + image->native_pixmap = native_pixmap; image->gles_image.host_image = handle; image->gles_image.update = &yagl_gles_image_update; } void yagl_image_cleanup(struct yagl_image *image) { + image->native_pixmap->destroy(image->native_pixmap); + image->native_pixmap = NULL; yagl_resource_cleanup(&image->res); } EGLImageKHR yagl_image_get_handle(struct yagl_image *image) { - return (EGLImageKHR)image->x_pixmap; + return (EGLImageKHR)image->native_pixmap->os_drawable; } void yagl_image_acquire(struct yagl_image *image) diff --git a/EGL/yagl_image.h b/EGL/yagl_image.h index d87ec84..cb14c54 100644 --- a/EGL/yagl_image.h +++ b/EGL/yagl_image.h @@ -4,7 +4,6 @@ #include "yagl_export.h" #include "yagl_types.h" #include "yagl_resource.h" -#include <X11/X.h> #include "EGL/egl.h" #include "EGL/eglext.h" #include "GLES2/gl2.h" @@ -12,6 +11,7 @@ #include "yagl_gles_image.h" struct yagl_display; +struct yagl_native_drawable; struct yagl_image { @@ -19,18 +19,21 @@ struct yagl_image struct yagl_display *dpy; - Pixmap x_pixmap; + struct yagl_native_drawable *native_pixmap; struct yagl_gles_image gles_image; void (*update)(struct yagl_image */*image*/); }; +/* + * Takes ownership of 'native_pixmap'. + */ void yagl_image_init(struct yagl_image *image, yagl_ref_destroy_func destroy_func, yagl_host_handle handle, struct yagl_display *dpy, - Pixmap x_pixmap); + struct yagl_native_drawable *native_pixmap); void yagl_image_cleanup(struct yagl_image *image); diff --git a/EGL/yagl_native_display.c b/EGL/yagl_native_display.c new file mode 100644 index 0000000..8323b57 --- /dev/null +++ b/EGL/yagl_native_display.c @@ -0,0 +1,16 @@ +#include "yagl_native_display.h" + +void yagl_native_display_init(struct yagl_native_display *dpy, + struct yagl_native_platform *platform, + yagl_os_display os_dpy, + int drm_fd) +{ + dpy->platform = platform; + dpy->os_dpy = os_dpy; + dpy->drm_fd = drm_fd; +} + +void yagl_native_display_cleanup(struct yagl_native_display *dpy) +{ + dpy->drm_fd = -1; +} diff --git a/EGL/yagl_native_display.h b/EGL/yagl_native_display.h new file mode 100644 index 0000000..4d9be66 --- /dev/null +++ b/EGL/yagl_native_display.h @@ -0,0 +1,49 @@ +#ifndef _YAGL_NATIVE_DISPLAY_H_ +#define _YAGL_NATIVE_DISPLAY_H_ + +#include "yagl_export.h" +#include "yagl_native_types.h" + +struct yagl_native_platform; +struct yagl_native_drawable; +struct yagl_native_image; + +struct yagl_native_display +{ + struct yagl_native_platform *platform; + + yagl_os_display os_dpy; + + int drm_fd; + + struct yagl_native_drawable *(*wrap_window)(struct yagl_native_display */*dpy*/, + yagl_os_window /*os_window*/); + + struct yagl_native_drawable *(*wrap_pixmap)(struct yagl_native_display */*dpy*/, + yagl_os_pixmap /*os_pixmap*/); + + struct yagl_native_drawable *(*create_pixmap)(struct yagl_native_display */*dpy*/, + uint32_t /*width*/, + uint32_t /*height*/, + uint32_t /*depth*/); + + struct yagl_native_image *(*create_image)(struct yagl_native_display */*dpy*/, + uint32_t /*width*/, + uint32_t /*height*/, + uint32_t /*depth*/); + + int (*get_visual)(struct yagl_native_display */*dpy*/, + int */*visual_id*/, + int */*visual_type*/); + + void (*destroy)(struct yagl_native_display */*dpy*/); +}; + +void yagl_native_display_init(struct yagl_native_display *dpy, + struct yagl_native_platform *platform, + yagl_os_display os_dpy, + int drm_fd); + +void yagl_native_display_cleanup(struct yagl_native_display *dpy); + +#endif diff --git a/EGL/yagl_native_drawable.c b/EGL/yagl_native_drawable.c new file mode 100644 index 0000000..b926261 --- /dev/null +++ b/EGL/yagl_native_drawable.c @@ -0,0 +1,14 @@ +#include "yagl_native_drawable.h" + +void yagl_native_drawable_init(struct yagl_native_drawable *drawable, + struct yagl_native_display *dpy, + yagl_os_drawable os_drawable) +{ + drawable->dpy = dpy; + drawable->os_drawable = os_drawable; + drawable->stamp = 0; +} + +void yagl_native_drawable_cleanup(struct yagl_native_drawable *drawable) +{ +} diff --git a/EGL/yagl_native_drawable.h b/EGL/yagl_native_drawable.h new file mode 100644 index 0000000..f8d7dfc --- /dev/null +++ b/EGL/yagl_native_drawable.h @@ -0,0 +1,63 @@ +#ifndef _YAGL_NATIVE_DRAWABLE_H_ +#define _YAGL_NATIVE_DRAWABLE_H_ + +#include "yagl_export.h" +#include "yagl_native_types.h" + +struct yagl_native_image; + +struct yagl_native_drawable +{ + struct yagl_native_display *dpy; + + yagl_os_drawable os_drawable; + + /* + * This gets incremented in drawable invalidate handler. + */ + uint32_t stamp; + + uint32_t (*get_buffer)(struct yagl_native_drawable */*drawable*/, + yagl_native_attachment /*attachment*/); + + void (*swap_buffers)(struct yagl_native_drawable */*drawable*/); + + /* + * 'width' and 'height' are here only because of DRI2. + * DRI2 requires width and height to be passed to DRI2CopyRegion. + */ + void (*wait)(struct yagl_native_drawable */*drawable*/, + uint32_t /*width*/, + uint32_t /*height*/); + + void (*copy_to_pixmap)(struct yagl_native_drawable */*drawable*/, + yagl_os_pixmap /*os_pixmap*/, + uint32_t /*from_x*/, + uint32_t /*from_y*/, + uint32_t /*to_x*/, + uint32_t /*to_y*/, + uint32_t /*width*/, + uint32_t /*height*/); + + void (*set_swap_interval)(struct yagl_native_drawable */*drawable*/, + int /*interval*/); + + void (*get_geometry)(struct yagl_native_drawable */*drawable*/, + uint32_t */*width*/, + uint32_t */*height*/, + uint32_t */*depth*/); + + struct yagl_native_image *(*get_image)(struct yagl_native_drawable */*drawable*/, + uint32_t /*width*/, + uint32_t /*height*/); + + void (*destroy)(struct yagl_native_drawable */*drawable*/); +}; + +void yagl_native_drawable_init(struct yagl_native_drawable *drawable, + struct yagl_native_display *dpy, + yagl_os_drawable os_drawable); + +void yagl_native_drawable_cleanup(struct yagl_native_drawable *drawable); + +#endif diff --git a/EGL/yagl_native_image.c b/EGL/yagl_native_image.c new file mode 100644 index 0000000..d567616 --- /dev/null +++ b/EGL/yagl_native_image.c @@ -0,0 +1,21 @@ +#include "yagl_native_image.h" + +void yagl_native_image_init(struct yagl_native_image *image, + struct yagl_native_display *dpy, + uint32_t width, + uint32_t height, + uint32_t depth, + uint32_t bpp, + void *pixels) +{ + image->dpy = dpy; + image->width = width; + image->height = height; + image->depth = depth; + image->bpp = bpp; + image->pixels = pixels; +} + +void yagl_native_image_cleanup(struct yagl_native_image *image) +{ +} diff --git a/EGL/yagl_native_image.h b/EGL/yagl_native_image.h new file mode 100644 index 0000000..193a77b --- /dev/null +++ b/EGL/yagl_native_image.h @@ -0,0 +1,39 @@ +#ifndef _YAGL_NATIVE_IMAGE_H_ +#define _YAGL_NATIVE_IMAGE_H_ + +#include "yagl_export.h" +#include "yagl_native_types.h" + +struct yagl_native_drawable; + +struct yagl_native_image +{ + struct yagl_native_display *dpy; + + uint32_t width; + uint32_t height; + uint32_t depth; /* bit-depth. e.g.: 24 */ + + uint32_t bpp; /* bytes-per-pixel. e.g.: 3 */ + void *pixels; /* pixel data */ + + void (*draw)(struct yagl_native_image */*image*/, + struct yagl_native_drawable */*drawable*/); + + void (*draw_to_pixmap)(struct yagl_native_image */*image*/, + yagl_os_pixmap /*os_pixmap*/); + + void (*destroy)(struct yagl_native_image */*image*/); +}; + +void yagl_native_image_init(struct yagl_native_image *image, + struct yagl_native_display *dpy, + uint32_t width, + uint32_t height, + uint32_t depth, + uint32_t bpp, + void *pixels); + +void yagl_native_image_cleanup(struct yagl_native_image *image); + +#endif diff --git a/EGL/yagl_native_platform.c b/EGL/yagl_native_platform.c new file mode 100644 index 0000000..3fd8ada --- /dev/null +++ b/EGL/yagl_native_platform.c @@ -0,0 +1,60 @@ +#include "yagl_native_platform.h" +#ifdef YAGL_PLATFORM_X11 +#include "x11/yagl_x11_platform.h" +#endif +#ifdef YAGL_PLATFORM_GBM +#include "gbm/yagl_gbm_platform.h" +#endif +#include "yagl_log.h" +#include <stdlib.h> +#include <string.h> + +static struct +{ + struct yagl_native_platform *platform; + const char *name; +} g_platforms[] = +{ +#ifdef YAGL_PLATFORM_GBM + {&yagl_gbm_platform, "gbm"}, +#endif +#ifdef YAGL_PLATFORM_X11 + {&yagl_x11_platform, "x11"}, +#endif +}; + +struct yagl_native_platform *yagl_guess_platform(yagl_os_display os_dpy) +{ + const char *platform_name = NULL; + uint32_t i; + + YAGL_LOG_FUNC_SET(yagl_guess_platform); + + platform_name = getenv("EGL_PLATFORM"); + + if (!platform_name || !platform_name[0]) { + platform_name = getenv("EGL_DISPLAY"); + } + + if (platform_name && platform_name[0]) { + for (i = 0; i < sizeof(g_platforms)/sizeof(g_platforms[0]); ++i) { + if (strcmp(g_platforms[i].name, platform_name) == 0) { + YAGL_LOG_INFO("EGL platform %s chosen by environment variable", + g_platforms[i].name); + return g_platforms[i].platform; + } + } + } + + for (i = 0; i < sizeof(g_platforms)/sizeof(g_platforms[0]); ++i) { + if (g_platforms[i].platform->probe(os_dpy)) { + YAGL_LOG_INFO("EGL platform %s chosen by probing", + g_platforms[i].name); + return g_platforms[i].platform; + } + } + + YAGL_LOG_ERROR("No EGL platform chosen"); + + return NULL; +} diff --git a/EGL/yagl_native_platform.h b/EGL/yagl_native_platform.h new file mode 100644 index 0000000..b852e22 --- /dev/null +++ b/EGL/yagl_native_platform.h @@ -0,0 +1,23 @@ +#ifndef _YAGL_NATIVE_PLATFORM_H_ +#define _YAGL_NATIVE_PLATFORM_H_ + +#include "yagl_export.h" +#include "yagl_native_types.h" + +struct yagl_native_display; + +struct yagl_native_platform +{ + int (*probe)(yagl_os_display /*os_dpy*/); + + struct yagl_native_display *(*wrap_display)(yagl_os_display /*os_dpy*/, + int /*enable_drm*/); +}; + +/* + * Attempts to guess the platform based on 'os_dpy'. + * Returns NULL if unsuccessful. + */ +struct yagl_native_platform *yagl_guess_platform(yagl_os_display os_dpy); + +#endif diff --git a/EGL/yagl_native_types.h b/EGL/yagl_native_types.h new file mode 100644 index 0000000..54ea0f3 --- /dev/null +++ b/EGL/yagl_native_types.h @@ -0,0 +1,18 @@ +#ifndef _YAGL_NATIVE_TYPES_H_ +#define _YAGL_NATIVE_TYPES_H_ + +#include "yagl_export.h" +#include "yagl_types.h" + +typedef uintptr_t yagl_os_display; +typedef uintptr_t yagl_os_drawable; +typedef uintptr_t yagl_os_window; +typedef uintptr_t yagl_os_pixmap; + +typedef enum +{ + yagl_native_attachment_front, + yagl_native_attachment_back, +} yagl_native_attachment; + +#endif diff --git a/EGL/yagl_offscreen.c b/EGL/yagl_offscreen.c index 012297d..27c196a 100644 --- a/EGL/yagl_offscreen.c +++ b/EGL/yagl_offscreen.c @@ -4,17 +4,25 @@ #include "yagl_display.h" #include "yagl_backend.h" #include "yagl_malloc.h" +#include "yagl_native_platform.h" static struct yagl_display - *yagl_offscreen_create_display(EGLNativeDisplayType display_id, - Display *x_dpy, + *yagl_offscreen_create_display(struct yagl_native_platform *platform, + yagl_os_display os_dpy, yagl_host_handle host_dpy) { struct yagl_display *dpy; + struct yagl_native_display *native_dpy; + + native_dpy = platform->wrap_display(os_dpy, 0); + + if (!native_dpy) { + return NULL; + } dpy = yagl_malloc0(sizeof(*dpy)); - yagl_display_init(dpy, display_id, x_dpy, host_dpy); + yagl_display_init(dpy, os_dpy, native_dpy, host_dpy); return dpy; } @@ -22,11 +30,14 @@ static struct yagl_display static struct yagl_surface *yagl_offscreen_create_window_surface(struct yagl_display *dpy, yagl_host_handle host_config, - Window x_win, + struct yagl_native_drawable *native_window, const EGLint* attrib_list) { struct yagl_offscreen_surface *sfc = - yagl_offscreen_surface_create_window(dpy, host_config, x_win, attrib_list); + yagl_offscreen_surface_create_window(dpy, + host_config, + native_window, + attrib_list); return sfc ? &sfc->base : NULL; } @@ -34,11 +45,14 @@ static struct yagl_surface static struct yagl_surface *yagl_offscreen_create_pixmap_surface(struct yagl_display *dpy, yagl_host_handle host_config, - Pixmap x_pixmap, + struct yagl_native_drawable *native_pixmap, const EGLint* attrib_list) { struct yagl_offscreen_surface *sfc = - yagl_offscreen_surface_create_pixmap(dpy, host_config, x_pixmap, attrib_list); + yagl_offscreen_surface_create_pixmap(dpy, + host_config, + native_pixmap, + attrib_list); return sfc ? &sfc->base : NULL; } @@ -57,11 +71,14 @@ static struct yagl_surface static struct yagl_image *yagl_offscreen_create_image(struct yagl_display *dpy, yagl_host_handle host_context, - Pixmap x_pixmap, + struct yagl_native_drawable *native_pixmap, const EGLint* attrib_list) { struct yagl_offscreen_image *image = - yagl_offscreen_image_create(dpy, host_context, x_pixmap, attrib_list); + yagl_offscreen_image_create(dpy, + host_context, + native_pixmap, + attrib_list); return image ? &image->base : NULL; } diff --git a/EGL/yagl_offscreen_image.c b/EGL/yagl_offscreen_image.c index 8cfd7ec..e0505e3 100644 --- a/EGL/yagl_offscreen_image.c +++ b/EGL/yagl_offscreen_image.c @@ -5,46 +5,43 @@ #include "yagl_state.h" #include "yagl_host_egl_calls.h" #include "yagl_mem_egl.h" +#include "yagl_native_drawable.h" +#include "yagl_native_image.h" #include <string.h> static void yagl_offscreen_image_update(struct yagl_image *image) { struct yagl_offscreen_image *oimage = (struct yagl_offscreen_image*)image; - XImage *x_image = NULL; + struct yagl_native_image *native_image = NULL; YAGL_LOG_FUNC_SET(yagl_offscreen_image_update); - x_image = XGetImage(image->dpy->x_dpy, - image->x_pixmap, - 0, - 0, - oimage->width, - oimage->height, - AllPlanes, - ZPixmap); - - if (!x_image) { - YAGL_LOG_ERROR("XGetImage failed for image %u", image->res.handle); + native_image = image->native_pixmap->get_image(image->native_pixmap, + oimage->width, + oimage->height); + + if (!native_image) { + YAGL_LOG_ERROR("get_image failed for image %u", image->res.handle); return; } while (!yagl_host_eglUpdateOffscreenImageYAGL(image->dpy->host_dpy, image->res.handle, - oimage->width, - oimage->height, - (x_image->bits_per_pixel / 8), - yagl_batch_put(x_image->data, (oimage->width * - oimage->height * - (x_image->bits_per_pixel / 8))))) {} - - XDestroyImage(x_image); + native_image->width, + native_image->height, + native_image->bpp, + yagl_batch_put(native_image->pixels, (native_image->width * + native_image->height * + native_image->bpp)))) {} + + native_image->destroy(native_image); } static void yagl_offscreen_image_destroy(struct yagl_ref *ref) { - struct yagl_offscreen_image *image = (struct yagl_offscreen_image*)ref; + struct yagl_image *image = (struct yagl_image*)ref; - yagl_image_cleanup(&image->base); + yagl_image_cleanup(image); yagl_free(image); } @@ -52,15 +49,12 @@ static void yagl_offscreen_image_destroy(struct yagl_ref *ref) struct yagl_offscreen_image *yagl_offscreen_image_create(struct yagl_display *dpy, yagl_host_handle host_context, - Pixmap x_pixmap, + struct yagl_native_drawable *native_pixmap, const EGLint* attrib_list) { - struct yagl_offscreen_image *image; - unsigned int depth = 0; - union { Window w; int i; unsigned int ui; } tmp_geom; yagl_host_handle host_image = 0; - - image = yagl_malloc0(sizeof(*image)); + struct yagl_offscreen_image *image; + uint32_t depth; do { yagl_mem_probe_read_attrib_list(attrib_list); @@ -68,37 +62,27 @@ struct yagl_offscreen_image dpy->host_dpy, host_context, EGL_NATIVE_PIXMAP_KHR, - x_pixmap, + 0, attrib_list)); if (!host_image) { - goto fail; + return NULL; } - memset(&tmp_geom, 0, sizeof(tmp_geom)); - - XGetGeometry(dpy->x_dpy, - x_pixmap, - &tmp_geom.w, - &tmp_geom.i, - &tmp_geom.i, - &image->width, - &image->height, - &tmp_geom.ui, - &depth); + image = yagl_malloc0(sizeof(*image)); yagl_image_init(&image->base, &yagl_offscreen_image_destroy, host_image, dpy, - x_pixmap); + native_pixmap); image->base.update = &yagl_offscreen_image_update; - return image; + native_pixmap->get_geometry(native_pixmap, + &image->width, + &image->height, + &depth); -fail: - yagl_free(image); - - return NULL; + return image; } diff --git a/EGL/yagl_offscreen_image.h b/EGL/yagl_offscreen_image.h index 6c01193..7dab5d6 100644 --- a/EGL/yagl_offscreen_image.h +++ b/EGL/yagl_offscreen_image.h @@ -16,7 +16,7 @@ struct yagl_offscreen_image struct yagl_offscreen_image *yagl_offscreen_image_create(struct yagl_display *dpy, yagl_host_handle host_context, - Pixmap x_pixmap, + struct yagl_native_drawable *native_pixmap, const EGLint* attrib_list); #endif diff --git a/EGL/yagl_offscreen_surface.c b/EGL/yagl_offscreen_surface.c index 6e90a5e..f1c348a 100644 --- a/EGL/yagl_offscreen_surface.c +++ b/EGL/yagl_offscreen_surface.c @@ -1,25 +1,67 @@ #include "yagl_offscreen_surface.h" #include "yagl_host_egl_calls.h" #include "yagl_egl_state.h" -#include "yagl_bimage.h" #include "yagl_malloc.h" #include "yagl_log.h" #include "yagl_display.h" #include "yagl_mem_egl.h" +#include "yagl_native_display.h" +#include "yagl_native_drawable.h" +#include "yagl_native_image.h" #include <string.h> #include <stdlib.h> #include <assert.h> #include <stdio.h> +#include <sys/mman.h> +#include <errno.h> + +static struct yagl_native_image + *yagl_offscreen_surface_create_bi(struct yagl_native_display *dpy, + uint32_t width, + uint32_t height, + uint32_t depth) +{ + struct yagl_native_image *bi = dpy->create_image(dpy, + width, + height, + depth); + + if (!bi) { + return NULL; + } + + if (mlock(bi->pixels, bi->width * bi->height * bi->bpp) == -1) { + fprintf(stderr, "Critical error! Unable to lock YaGL bi memory: %s!\n", strerror(errno)); + exit(1); + } + + /* + * Probe in immediately. + */ + + yagl_mem_probe_write(bi->pixels, bi->width * bi->height * bi->bpp); + + return bi; +} + +static void yagl_offscreen_surface_destroy_bi(struct yagl_native_image *bi) +{ + if (munlock(bi->pixels, bi->width * bi->height * bi->bpp) == -1) { + fprintf(stderr, "Critical error! Unable to unlock YaGL bi memory: %s!\n", strerror(errno)); + exit(1); + } + + bi->destroy(bi); +} static int yagl_offscreen_surface_resize(struct yagl_offscreen_surface *surface) { int res = 0; EGLBoolean retval = EGL_FALSE; - unsigned int width = 0; - unsigned int height = 0; - unsigned int depth = 0; - union { Window w; int i; unsigned int ui; } tmp_geom; - struct yagl_bimage *bi = NULL; + uint32_t width = 0; + uint32_t height = 0; + uint32_t depth = 0; + struct yagl_native_image *bi = NULL; YAGL_LOG_FUNC_SET(yagl_offscreen_surface_resize); @@ -27,17 +69,10 @@ static int yagl_offscreen_surface_resize(struct yagl_offscreen_surface *surface) return 1; } - memset(&tmp_geom, 0, sizeof(tmp_geom)); - - XGetGeometry(surface->base.dpy->x_dpy, - surface->base.x_drawable.win, - &tmp_geom.w, - &tmp_geom.i, - &tmp_geom.i, - &width, - &height, - &tmp_geom.ui, - &depth); + surface->base.native_drawable->get_geometry(surface->base.native_drawable, + &width, + &height, + &depth); if ((width != surface->bi->width) || (height != surface->bi->height) || @@ -50,17 +85,17 @@ static int yagl_offscreen_surface_resize(struct yagl_offscreen_surface *surface) * First of all, create new backing image. */ - bi = yagl_bimage_create(surface->base.dpy, width, height, depth); + bi = yagl_offscreen_surface_create_bi(surface->base.dpy->native_dpy, + width, height, depth); if (!bi) { - YAGL_LOG_ERROR("yagl_bimage_create failed"); + YAGL_LOG_ERROR("create_bi failed"); yagl_set_error(EGL_BAD_ALLOC); goto out; } /* * Tell the host that it should use new backing image from now on. - * No need to probe in 'bi->pixels', it's already 'mlock'ed. */ YAGL_HOST_CALL_ASSERT(yagl_host_eglResizeOffscreenSurfaceYAGL(&retval, @@ -82,7 +117,7 @@ static int yagl_offscreen_surface_resize(struct yagl_offscreen_surface *surface) * we can safely replace surface's backing image with a new one. */ - yagl_bimage_destroy(surface->bi); + yagl_offscreen_surface_destroy_bi(surface->bi); surface->bi = bi; bi = NULL; } @@ -91,7 +126,7 @@ static int yagl_offscreen_surface_resize(struct yagl_offscreen_surface *surface) out: if (bi) { - yagl_bimage_destroy(bi); + yagl_offscreen_surface_destroy_bi(bi); } return res; @@ -129,37 +164,28 @@ static int yagl_offscreen_surface_swap_buffers(struct yagl_surface *sfc) * Host has updated our image, update the window. */ - yagl_bimage_draw(osfc->bi, sfc->x_drawable.win, osfc->x_gc); + osfc->bi->draw(osfc->bi, sfc->native_drawable); return 1; } static int yagl_offscreen_surface_copy_buffers(struct yagl_surface *sfc, - Pixmap target) + yagl_os_pixmap target) { struct yagl_offscreen_surface *osfc = (struct yagl_offscreen_surface*)sfc; EGLBoolean retval = EGL_FALSE; - GC x_gc; YAGL_LOG_FUNC_SET(eglCopyBuffers); if (sfc->type == EGL_WINDOW_BIT) { - unsigned int width = 0; - unsigned int height = 0; - unsigned int depth = 0; - union { Window w; int i; unsigned int ui; } tmp_geom; - - memset(&tmp_geom, 0, sizeof(tmp_geom)); - - XGetGeometry(sfc->dpy->x_dpy, - sfc->x_drawable.win, - &tmp_geom.w, - &tmp_geom.i, - &tmp_geom.i, - &width, - &height, - &tmp_geom.ui, - &depth); + uint32_t width = 0; + uint32_t height = 0; + uint32_t depth = 0; + + sfc->native_drawable->get_geometry(sfc->native_drawable, + &width, + &height, + &depth); if ((width != osfc->bi->width) || (height != osfc->bi->height) || @@ -186,20 +212,12 @@ static int yagl_offscreen_surface_copy_buffers(struct yagl_surface *sfc, } /* - * Host has updated our image, update the surface. + * Host has updated our image, update the target. */ - x_gc = XCreateGC(sfc->dpy->x_dpy, target, 0, NULL); + osfc->bi->draw_to_pixmap(osfc->bi, target); - if (x_gc) { - yagl_bimage_draw(osfc->bi, target, x_gc); - XFreeGC(sfc->dpy->x_dpy, x_gc); - } else { - YAGL_LOG_ERROR("XCreateGC failed"); - yagl_set_error(EGL_BAD_ALLOC); - } - - return x_gc ? 1 : 0; + return 1; } static void yagl_offscreen_surface_wait_x(struct yagl_surface *sfc) @@ -244,10 +262,8 @@ static void yagl_offscreen_surface_unmap(struct yagl_surface *sfc) case EGL_PBUFFER_BIT: break; case EGL_WINDOW_BIT: - yagl_bimage_draw(osfc->bi, sfc->x_drawable.win, osfc->x_gc); - break; case EGL_PIXMAP_BIT: - yagl_bimage_draw(osfc->bi, sfc->x_drawable.pixmap, osfc->x_gc); + osfc->bi->draw(osfc->bi, sfc->native_drawable); break; default: assert(0); @@ -264,12 +280,7 @@ static void yagl_offscreen_surface_destroy(struct yagl_ref *ref) { struct yagl_offscreen_surface *sfc = (struct yagl_offscreen_surface*)ref; - if (sfc->x_gc) { - XFreeGC(sfc->base.dpy->x_dpy, sfc->x_gc); - sfc->x_gc = 0; - } - - yagl_bimage_destroy(sfc->bi); + yagl_offscreen_surface_destroy_bi(sfc->bi); sfc->bi = NULL; yagl_surface_cleanup(&sfc->base); @@ -280,37 +291,29 @@ static void yagl_offscreen_surface_destroy(struct yagl_ref *ref) struct yagl_offscreen_surface *yagl_offscreen_surface_create_window(struct yagl_display *dpy, yagl_host_handle host_config, - Window x_win, + struct yagl_native_drawable *native_window, const EGLint* attrib_list) { struct yagl_offscreen_surface *sfc; - XWindowAttributes x_wa; + uint32_t width = 0; + uint32_t height = 0; + uint32_t depth = 0; yagl_host_handle host_surface = 0; - struct yagl_bimage *bi = NULL; - GC x_gc = NULL; + struct yagl_native_image *bi = NULL; YAGL_LOG_FUNC_SET(eglCreateWindowSurface); sfc = yagl_malloc0(sizeof(*sfc)); - if (!XGetWindowAttributes(dpy->x_dpy, x_win, &x_wa)) { - YAGL_LOG_ERROR("XGetWindowAttributes failed"); - yagl_set_error(EGL_BAD_NATIVE_WINDOW); - goto fail; - } + native_window->get_geometry(native_window, + &width, + &height, + &depth); - bi = yagl_bimage_create(dpy, x_wa.width, x_wa.height, x_wa.depth); + bi = yagl_offscreen_surface_create_bi(dpy->native_dpy, width, height, depth); if (!bi) { - YAGL_LOG_ERROR("yagl_bimage_create failed"); - yagl_set_error(EGL_BAD_ALLOC); - goto fail; - } - - x_gc = XCreateGC(dpy->x_dpy, x_win, 0, NULL); - - if (!x_gc) { - YAGL_LOG_ERROR("XCreateGC failed"); + YAGL_LOG_ERROR("create_bi failed"); yagl_set_error(EGL_BAD_ALLOC); goto fail; } @@ -334,7 +337,7 @@ struct yagl_offscreen_surface &yagl_offscreen_surface_destroy, host_surface, dpy, - x_win); + native_window); sfc->base.invalidate = &yagl_offscreen_surface_invalidate; sfc->base.finish = &yagl_offscreen_surface_finish; @@ -347,17 +350,15 @@ struct yagl_offscreen_surface sfc->base.set_swap_interval = &yagl_offscreen_surface_set_swap_interval; sfc->bi = bi; - sfc->x_gc = x_gc; return sfc; fail: if (bi) { - yagl_bimage_destroy(bi); - } - if (x_gc) { - XFreeGC(dpy->x_dpy, x_gc); + yagl_offscreen_surface_destroy_bi(bi); + bi = NULL; } + yagl_free(sfc); return NULL; @@ -366,46 +367,29 @@ fail: struct yagl_offscreen_surface *yagl_offscreen_surface_create_pixmap(struct yagl_display *dpy, yagl_host_handle host_config, - Pixmap x_pixmap, + struct yagl_native_drawable *native_pixmap, const EGLint* attrib_list) { struct yagl_offscreen_surface *sfc; - unsigned int width = 0; - unsigned int height = 0; - unsigned int depth = 0; - union { Window w; int i; unsigned int ui; } tmp_geom; + uint32_t width = 0; + uint32_t height = 0; + uint32_t depth = 0; yagl_host_handle host_surface = 0; - struct yagl_bimage *bi = NULL; - GC x_gc = NULL; + struct yagl_native_image *bi = NULL; YAGL_LOG_FUNC_SET(eglCreatePixmapSurface); sfc = yagl_malloc0(sizeof(*sfc)); - memset(&tmp_geom, 0, sizeof(tmp_geom)); + native_pixmap->get_geometry(native_pixmap, + &width, + &height, + &depth); - XGetGeometry(dpy->x_dpy, - x_pixmap, - &tmp_geom.w, - &tmp_geom.i, - &tmp_geom.i, - &width, - &height, - &tmp_geom.ui, - &depth); - - bi = yagl_bimage_create(dpy, width, height, depth); + bi = yagl_offscreen_surface_create_bi(dpy->native_dpy, width, height, depth); if (!bi) { - YAGL_LOG_ERROR("yagl_bimage_create failed"); - yagl_set_error(EGL_BAD_ALLOC); - goto fail; - } - - x_gc = XCreateGC(dpy->x_dpy, x_pixmap, 0, NULL); - - if (!x_gc) { - YAGL_LOG_ERROR("XCreateGC failed"); + YAGL_LOG_ERROR("create_bi failed"); yagl_set_error(EGL_BAD_ALLOC); goto fail; } @@ -429,7 +413,7 @@ struct yagl_offscreen_surface &yagl_offscreen_surface_destroy, host_surface, dpy, - x_pixmap); + native_pixmap); sfc->base.invalidate = &yagl_offscreen_surface_invalidate; sfc->base.finish = &yagl_offscreen_surface_finish; @@ -442,17 +426,15 @@ struct yagl_offscreen_surface sfc->base.set_swap_interval = &yagl_offscreen_surface_set_swap_interval; sfc->bi = bi; - sfc->x_gc = x_gc; return sfc; fail: if (bi) { - yagl_bimage_destroy(bi); - } - if (x_gc) { - XFreeGC(dpy->x_dpy, x_gc); + yagl_offscreen_surface_destroy_bi(bi); + bi = NULL; } + yagl_free(sfc); return NULL; @@ -467,7 +449,7 @@ struct yagl_offscreen_surface uint32_t width = 0; uint32_t height = 0; yagl_host_handle host_surface = 0; - struct yagl_bimage *bi = NULL; + struct yagl_native_image *bi = NULL; int i = 0; YAGL_LOG_FUNC_SET(eglCreatePbufferSurface); @@ -491,10 +473,10 @@ struct yagl_offscreen_surface } } - bi = yagl_bimage_create(dpy, width, height, 24); + bi = yagl_offscreen_surface_create_bi(dpy->native_dpy, width, height, 24); if (!bi) { - YAGL_LOG_ERROR("yagl_bimage_create failed"); + YAGL_LOG_ERROR("create_bi failed"); yagl_set_error(EGL_BAD_ALLOC); goto fail; } @@ -535,8 +517,10 @@ struct yagl_offscreen_surface fail: if (bi) { - yagl_bimage_destroy(bi); + yagl_offscreen_surface_destroy_bi(bi); + bi = NULL; } + yagl_free(sfc); return NULL; diff --git a/EGL/yagl_offscreen_surface.h b/EGL/yagl_offscreen_surface.h index df29e89..035022c 100644 --- a/EGL/yagl_offscreen_surface.h +++ b/EGL/yagl_offscreen_surface.h @@ -5,27 +5,26 @@ #include "yagl_types.h" #include "yagl_surface.h" -struct yagl_bimage; +struct yagl_native_image; +struct yagl_native_drawable; struct yagl_offscreen_surface { struct yagl_surface base; - struct yagl_bimage *bi; - - GC x_gc; + struct yagl_native_image *bi; }; struct yagl_offscreen_surface *yagl_offscreen_surface_create_window(struct yagl_display *dpy, yagl_host_handle host_config, - Window x_win, + struct yagl_native_drawable *native_window, const EGLint* attrib_list); struct yagl_offscreen_surface *yagl_offscreen_surface_create_pixmap(struct yagl_display *dpy, yagl_host_handle host_config, - Pixmap x_pixmap, + struct yagl_native_drawable *native_pixmap, const EGLint* attrib_list); struct yagl_offscreen_surface diff --git a/EGL/yagl_onscreen.c b/EGL/yagl_onscreen.c index 18d67f9..edcd5ef 100644 --- a/EGL/yagl_onscreen.c +++ b/EGL/yagl_onscreen.c @@ -4,46 +4,67 @@ #include "yagl_onscreen_image.h" #include "yagl_backend.h" #include "yagl_malloc.h" +#include "yagl_native_platform.h" +#include "yagl_native_display.h" static struct yagl_display - *yagl_onscreen_create_display(EGLNativeDisplayType display_id, - Display *x_dpy, + *yagl_onscreen_create_display(struct yagl_native_platform *platform, + yagl_os_display os_dpy, yagl_host_handle host_dpy) { - struct yagl_onscreen_display *dpy = - yagl_onscreen_display_create(display_id, x_dpy, host_dpy); + struct yagl_native_display *native_dpy; + struct yagl_onscreen_display *dpy; - return dpy ? &dpy->base : NULL; + native_dpy = platform->wrap_display(os_dpy, 1); + + if (!native_dpy) { + return NULL; + } + + dpy = yagl_onscreen_display_create(os_dpy, native_dpy, host_dpy); + + if (dpy) { + return &dpy->base; + } else { + native_dpy->destroy(native_dpy); + return NULL; + } } static struct yagl_surface *yagl_onscreen_create_window_surface(struct yagl_display *dpy, - yagl_host_handle host_config, - Window x_win, - const EGLint* attrib_list) + yagl_host_handle host_config, + struct yagl_native_drawable *native_window, + const EGLint *attrib_list) { struct yagl_onscreen_surface *sfc = - yagl_onscreen_surface_create_window(dpy, host_config, x_win, attrib_list); + yagl_onscreen_surface_create_window(dpy, + host_config, + native_window, + attrib_list); return sfc ? &sfc->base : NULL; } static struct yagl_surface *yagl_onscreen_create_pixmap_surface(struct yagl_display *dpy, - yagl_host_handle host_config, - Pixmap x_pixmap, - const EGLint* attrib_list) + yagl_host_handle host_config, + struct yagl_native_drawable *native_pixmap, + const EGLint *attrib_list) { struct yagl_onscreen_surface *sfc = - yagl_onscreen_surface_create_pixmap(dpy, host_config, x_pixmap, attrib_list); + yagl_onscreen_surface_create_pixmap(dpy, + host_config, + native_pixmap, + attrib_list); return sfc ? &sfc->base : NULL; } static struct yagl_surface *yagl_onscreen_create_pbuffer_surface(struct yagl_display *dpy, - yagl_host_handle host_config, - const EGLint* attrib_list) + yagl_host_handle host_config, + const EGLint *attrib_list) { struct yagl_onscreen_surface *sfc = yagl_onscreen_surface_create_pbuffer(dpy, host_config, attrib_list); @@ -54,11 +75,14 @@ static struct yagl_surface static struct yagl_image *yagl_onscreen_create_image(struct yagl_display *dpy, yagl_host_handle host_context, - Pixmap x_pixmap, + struct yagl_native_drawable *native_pixmap, const EGLint* attrib_list) { struct yagl_onscreen_image *image = - yagl_onscreen_image_create(dpy, host_context, x_pixmap, attrib_list); + yagl_onscreen_image_create(dpy, + host_context, + native_pixmap, + attrib_list); return image ? &image->base : NULL; } diff --git a/EGL/yagl_onscreen_buffer.c b/EGL/yagl_onscreen_buffer.c new file mode 100644 index 0000000..381a106 --- /dev/null +++ b/EGL/yagl_onscreen_buffer.c @@ -0,0 +1,64 @@ +#include "yagl_onscreen_buffer.h" +#include "yagl_onscreen_display.h" +#include "yagl_native_display.h" +#include "yagl_native_drawable.h" +#include "yagl_log.h" +#include "yagl_malloc.h" +#include "vigs.h" +#include <string.h> + +struct yagl_onscreen_buffer + *yagl_onscreen_buffer_create(struct yagl_onscreen_display *dpy, + struct yagl_native_drawable *native_drawable, + yagl_native_attachment attachment, + uint32_t check_name) +{ + int ret; + uint32_t name; + struct vigs_drm_surface *drm_sfc; + struct yagl_onscreen_buffer *buffer; + + YAGL_LOG_FUNC_ENTER(yagl_onscreen_buffer_create, + "dpy = %p, d = %p, attachment = %u, check_name = %u", + native_drawable->dpy->os_dpy, + native_drawable->os_drawable, + attachment, + check_name); + + name = native_drawable->get_buffer(native_drawable, attachment); + + if (!name) { + YAGL_LOG_FUNC_EXIT(NULL); + return NULL; + } + + if (name == check_name) { + YAGL_LOG_FUNC_EXIT(NULL); + return NULL; + } + + ret = vigs_drm_surface_open(dpy->drm_dev, name, &drm_sfc); + + if (ret != 0) { + YAGL_LOG_ERROR("vigs_drm_surface_open failed for drawable %p: %s", + native_drawable->os_drawable, + strerror(-ret)); + YAGL_LOG_FUNC_EXIT(NULL); + return NULL; + } + + buffer = yagl_malloc0(sizeof(*buffer)); + + buffer->name = name; + buffer->drm_sfc = drm_sfc; + + YAGL_LOG_FUNC_EXIT(NULL); + + return buffer; +} + +void yagl_onscreen_buffer_destroy(struct yagl_onscreen_buffer *buffer) +{ + vigs_drm_gem_unref(&buffer->drm_sfc->gem); + yagl_free(buffer); +} diff --git a/EGL/yagl_onscreen_buffer.h b/EGL/yagl_onscreen_buffer.h new file mode 100644 index 0000000..4873eec --- /dev/null +++ b/EGL/yagl_onscreen_buffer.h @@ -0,0 +1,27 @@ +#ifndef _YAGL_ONSCREEN_BUFFER_H_ +#define _YAGL_ONSCREEN_BUFFER_H_ + +#include "yagl_export.h" +#include "yagl_types.h" +#include "yagl_native_types.h" + +struct vigs_drm_surface; +struct yagl_onscreen_display; +struct yagl_native_drawable; + +struct yagl_onscreen_buffer +{ + uint32_t name; + + struct vigs_drm_surface *drm_sfc; +}; + +struct yagl_onscreen_buffer + *yagl_onscreen_buffer_create(struct yagl_onscreen_display *dpy, + struct yagl_native_drawable *native_drawable, + yagl_native_attachment attachment, + uint32_t check_name); + +void yagl_onscreen_buffer_destroy(struct yagl_onscreen_buffer *buffer); + +#endif diff --git a/EGL/yagl_onscreen_display.c b/EGL/yagl_onscreen_display.c index 80677c4..4179b91 100644 --- a/EGL/yagl_onscreen_display.c +++ b/EGL/yagl_onscreen_display.c @@ -1,182 +1,32 @@ #include "yagl_onscreen_display.h" -#include "yagl_log.h" #include "yagl_malloc.h" -#include <sys/fcntl.h> +#include "yagl_native_display.h" +#include "vigs.h" #include <stdio.h> #include <stdlib.h> +#include <string.h> struct yagl_onscreen_display - *yagl_onscreen_display_create(EGLNativeDisplayType display_id, - Display *x_dpy, + *yagl_onscreen_display_create(yagl_os_display display_id, + struct yagl_native_display *native_dpy, yagl_host_handle host_dpy) { - struct yagl_onscreen_display *tmp_dpy; - struct yagl_onscreen_display *dpy = NULL; int ret; - int event_base, error_base; - int dri_major, dri_minor; - char *dri_driver = NULL; - char *dri_device = NULL; - int drm_fd = -1; - drm_magic_t magic; struct vigs_drm_device *drm_dev = NULL; + struct yagl_onscreen_display *dpy = NULL; - YAGL_LOG_FUNC_SET(eglGetDisplay); - - tmp_dpy = yagl_malloc0(sizeof(*dpy)); - - yagl_display_init(&tmp_dpy->base, display_id, x_dpy, host_dpy); - - if (!yagl_DRI2QueryExtension(x_dpy, &event_base, &error_base)) { - fprintf(stderr, "Critical error! Failed to DRI2QueryExtension on YaGL display, DRI2 not enabled ?\n"); - goto out; - } - - YAGL_LOG_TRACE("DRI2QueryExtension returned %d %d", - event_base, error_base); - - if (!yagl_DRI2QueryVersion(x_dpy, &dri_major, &dri_minor)) { - fprintf(stderr, "Critical error! Failed to DRI2QueryVersion on YaGL display, DRI2 not enabled ?\n"); - goto out; - } - - YAGL_LOG_TRACE("DRI2QueryVersion returned %d %d", - dri_major, dri_minor); - - if (!yagl_DRI2Connect(x_dpy, - RootWindow(x_dpy, DefaultScreen(x_dpy)), - &dri_driver, - &dri_device)) { - fprintf(stderr, "Critical error! Failed to DRI2Connect on YaGL display, DRI2 not enabled ?\n"); - goto out; - } - - YAGL_LOG_TRACE("DRI2Connect returned %s %s", - dri_driver, dri_device); - - drm_fd = open(dri_device, O_RDWR); - - if (drm_fd < 0) { - fprintf(stderr, "Critical error! Failed to open(\"%s\"): %s\n", dri_device, strerror(errno)); - goto fail; - } - - memset(&magic, 0, sizeof(magic)); - - ret = drmGetMagic(drm_fd, &magic); - - if (ret != 0) { - fprintf(stderr, "Critical error! drmGetMagic failed: %s\n", strerror(-ret)); - goto fail; - } - - if (!yagl_DRI2Authenticate(x_dpy, - RootWindow(x_dpy, DefaultScreen(x_dpy)), - magic)) { - fprintf(stderr, "Critical error! Failed to DRI2Authenticate on YaGL display, DRI2 not enabled ?\n"); - goto fail; - } - - ret = vigs_drm_device_create(drm_fd, &drm_dev); + ret = vigs_drm_device_create(native_dpy->drm_fd, &drm_dev); if (ret != 0) { fprintf(stderr, "Critical error! vigs_drm_device_create failed: %s\n", strerror(-ret)); - goto fail; - } - - tmp_dpy->drm_fd = drm_fd; - tmp_dpy->drm_dev = drm_dev; - - dpy = tmp_dpy; - tmp_dpy = NULL; - - goto out; - -fail: - if (drm_dev) { - vigs_drm_device_destroy(drm_dev); - } - if (drm_fd >= 0) { - close(drm_fd); - } -out: - if (dri_driver) { - Xfree(dri_driver); - } - if (dri_device) { - Xfree(dri_device); - } - if (tmp_dpy) { - yagl_display_cleanup(&tmp_dpy->base); - yagl_free(tmp_dpy); - } - - return dpy; -} - -struct yagl_onscreen_buffer - *yagl_onscreen_display_create_buffer(struct yagl_onscreen_display* dpy, - Drawable d, - unsigned int attachment, - uint32_t check_name) -{ - int ret; - unsigned int attachments[1] = - { - attachment - }; - yagl_DRI2Buffer *tmp_buffer; - int tmp_width, tmp_height, num_buffers; - struct vigs_drm_surface *drm_sfc; - struct yagl_onscreen_buffer *buffer; - - YAGL_LOG_FUNC_ENTER(yagl_onscreen_display_create_buffer, - "dpy = %p, d = 0x%X, attachment = %u", - dpy, - d, - attachment); - - tmp_buffer = yagl_DRI2GetBuffers(dpy->base.x_dpy, d, - &tmp_width, &tmp_height, - &attachments[0], - sizeof(attachments)/sizeof(attachments[0]), - &num_buffers); - if (!tmp_buffer) { - YAGL_LOG_ERROR("DRI2GetBuffers failed for drawable 0x%X", d); - YAGL_LOG_FUNC_EXIT(NULL); - return NULL; - } - - if (tmp_buffer->name == check_name) { - Xfree(tmp_buffer); - YAGL_LOG_FUNC_EXIT(NULL); return NULL; } - ret = vigs_drm_surface_open(dpy->drm_dev, tmp_buffer->name, &drm_sfc); + dpy = yagl_malloc0(sizeof(*dpy)); - if (ret != 0) { - YAGL_LOG_ERROR("vigs_drm_surface_open failed for drawable 0x%X: %s", - d, - strerror(-ret)); - Xfree(tmp_buffer); - YAGL_LOG_FUNC_EXIT(NULL); - return NULL; - } + yagl_display_init(&dpy->base, display_id, native_dpy, host_dpy); - buffer = yagl_malloc0(sizeof(*buffer)); + dpy->drm_dev = drm_dev; - buffer->dri2_buffer = tmp_buffer; - buffer->drm_sfc = drm_sfc; - - YAGL_LOG_FUNC_EXIT(NULL); - - return buffer; -} - -void yagl_onscreen_display_destroy_buffer(struct yagl_onscreen_buffer *buffer) -{ - Xfree(buffer->dri2_buffer); - vigs_drm_gem_unref(&buffer->drm_sfc->gem); - yagl_free(buffer); + return dpy; } diff --git a/EGL/yagl_onscreen_display.h b/EGL/yagl_onscreen_display.h index f58046e..1ed4205 100644 --- a/EGL/yagl_onscreen_display.h +++ b/EGL/yagl_onscreen_display.h @@ -4,35 +4,19 @@ #include "yagl_export.h" #include "yagl_types.h" #include "yagl_display.h" -#include "yagl_dri2.h" -#include "vigs.h" + +struct vigs_drm_device; struct yagl_onscreen_display { struct yagl_display base; - int drm_fd; struct vigs_drm_device *drm_dev; }; -struct yagl_onscreen_buffer -{ - yagl_DRI2Buffer *dri2_buffer; - - struct vigs_drm_surface *drm_sfc; -}; - struct yagl_onscreen_display - *yagl_onscreen_display_create(EGLNativeDisplayType display_id, - Display *x_dpy, + *yagl_onscreen_display_create(yagl_os_display display_id, + struct yagl_native_display *native_dpy, yagl_host_handle host_dpy); -struct yagl_onscreen_buffer - *yagl_onscreen_display_create_buffer(struct yagl_onscreen_display* dpy, - Drawable d, - unsigned int attachment, - uint32_t check_name); - -void yagl_onscreen_display_destroy_buffer(struct yagl_onscreen_buffer *buffer); - #endif diff --git a/EGL/yagl_onscreen_image.c b/EGL/yagl_onscreen_image.c index 616390f..43aa1cb 100644 --- a/EGL/yagl_onscreen_image.c +++ b/EGL/yagl_onscreen_image.c @@ -1,10 +1,13 @@ #include "yagl_onscreen_image.h" +#include "yagl_onscreen_buffer.h" +#include "yagl_onscreen_display.h" #include "yagl_display.h" #include "yagl_log.h" #include "yagl_malloc.h" #include "yagl_host_egl_calls.h" #include "yagl_mem_egl.h" #include "yagl_egl_state.h" +#include "vigs.h" static void yagl_onscreen_image_update(struct yagl_image *image) { @@ -14,10 +17,7 @@ static void yagl_onscreen_image_destroy(struct yagl_ref *ref) { struct yagl_onscreen_image *image = (struct yagl_onscreen_image*)ref; - yagl_onscreen_display_destroy_buffer(image->buffer); - - yagl_DRI2DestroyDrawable(image->base.dpy->x_dpy, - image->base.x_pixmap); + yagl_onscreen_buffer_destroy(image->buffer); yagl_image_cleanup(&image->base); @@ -27,7 +27,7 @@ static void yagl_onscreen_image_destroy(struct yagl_ref *ref) struct yagl_onscreen_image *yagl_onscreen_image_create(struct yagl_display *dpy, yagl_host_handle host_context, - Pixmap x_pixmap, + struct yagl_native_drawable *native_pixmap, const EGLint* attrib_list) { struct yagl_onscreen_display *odpy = (struct yagl_onscreen_display*)dpy; @@ -37,12 +37,10 @@ struct yagl_onscreen_image image = yagl_malloc0(sizeof(*image)); - yagl_DRI2CreateDrawable(dpy->x_dpy, x_pixmap); - - new_buffer = yagl_onscreen_display_create_buffer(odpy, - x_pixmap, - DRI2BufferFrontLeft, - 0); + new_buffer = yagl_onscreen_buffer_create(odpy, + native_pixmap, + yagl_native_attachment_front, + 0); if (!new_buffer) { yagl_set_error(EGL_BAD_NATIVE_PIXMAP); @@ -66,7 +64,7 @@ struct yagl_onscreen_image &yagl_onscreen_image_destroy, host_image, dpy, - x_pixmap); + native_pixmap); image->base.update = &yagl_onscreen_image_update; @@ -76,8 +74,7 @@ struct yagl_onscreen_image fail: if (new_buffer) { - yagl_onscreen_display_destroy_buffer(new_buffer); - yagl_DRI2DestroyDrawable(dpy->x_dpy, x_pixmap); + yagl_onscreen_buffer_destroy(new_buffer); } yagl_free(image); diff --git a/EGL/yagl_onscreen_image.h b/EGL/yagl_onscreen_image.h index bcee944..8b597fa 100644 --- a/EGL/yagl_onscreen_image.h +++ b/EGL/yagl_onscreen_image.h @@ -4,8 +4,9 @@ #include "yagl_export.h" #include "yagl_types.h" #include "yagl_image.h" -#include "yagl_dri2.h" -#include "yagl_onscreen_display.h" + +struct yagl_onscreen_buffer; +struct yagl_native_drawable; struct yagl_onscreen_image { @@ -17,7 +18,7 @@ struct yagl_onscreen_image struct yagl_onscreen_image *yagl_onscreen_image_create(struct yagl_display *dpy, yagl_host_handle host_context, - Pixmap x_pixmap, + struct yagl_native_drawable *native_pixmap, const EGLint* attrib_list); #endif diff --git a/EGL/yagl_onscreen_surface.c b/EGL/yagl_onscreen_surface.c index fdc03b8..bf78ac1 100644 --- a/EGL/yagl_onscreen_surface.c +++ b/EGL/yagl_onscreen_surface.c @@ -1,70 +1,19 @@ #include "yagl_onscreen_surface.h" +#include "yagl_onscreen_buffer.h" +#include "yagl_onscreen_display.h" #include "yagl_host_egl_calls.h" #include "yagl_egl_state.h" #include "yagl_log.h" #include "yagl_mem_egl.h" #include "yagl_utils.h" #include "yagl_malloc.h" +#include "yagl_native_display.h" +#include "yagl_native_drawable.h" +#include "vigs.h" #include <assert.h> #include <stdio.h> - -/* - * When this is defined EGL pixmap surface will behave more like pbuffer - * surface, i.e. it'll allocate additional pixmap and all OpenGL rendering - * will go there. eglCopyBuffers will be the only way to get the rendering - * results. - * - * This is a temporary workaround for Tizen, because it currently - * behaves like if pixmap surfaces were pbuffer surfaces. - * - * One of the examples is WebKit, it renders WebGL like this: - * + sfc = eglCreatePixmapSurface(... pixmap_id ...) - * + eglMakeCurrent(... sfc ...); - * + (render step) - * + async: XGetImage(pixmap_id) - * + eglCopyBuffers(... pixmap_id ...) - * - * I.e. it makes asynchronous calls to XGetImage for the pixmap which is - * being rendered to. It doesn't call eglWaitX/glFlush/glFinish, thus, it - * assumes that the image stored in 'pixmap_id' is complete and won't have any - * intermediate rendering results and this is only possible if this pixmap - * surface is a pbuffer surface. A eglCopyBuffers call at the end copies - * the rendering results to the pixmap itself, which is really stupid thing - * to do... unless this is a pbuffer surface... - */ -//#define YAGL_FAKE_PIXMAP_SURFACE - -static void yagl_onscreen_surface_copy_drawable(struct yagl_onscreen_surface *sfc, - int src, int dest) -{ - XRectangle xrect; - XserverRegion region; - - xrect.x = 0; - xrect.y = 0; - xrect.width = sfc->buffer->drm_sfc->width; - xrect.height = sfc->buffer->drm_sfc->height; - - region = XFixesCreateRegion(sfc->base.dpy->x_dpy, &xrect, 1); - switch (sfc->base.type) { - case EGL_PBUFFER_BIT: - yagl_DRI2CopyRegion(sfc->base.dpy->x_dpy, sfc->tmp_pixmap, - region, dest, src); - break; - case EGL_PIXMAP_BIT: - yagl_DRI2CopyRegion(sfc->base.dpy->x_dpy, sfc->base.x_drawable.pixmap, - region, dest, src); - break; - case EGL_WINDOW_BIT: - yagl_DRI2CopyRegion(sfc->base.dpy->x_dpy, sfc->base.x_drawable.win, - region, dest, src); - break; - default: - assert(0); - break; - } - XFixesDestroyRegion(sfc->base.dpy->x_dpy, region); -} +#include <stdlib.h> +#include <string.h> static void yagl_onscreen_surface_invalidate(struct yagl_surface *sfc) { @@ -72,28 +21,28 @@ static void yagl_onscreen_surface_invalidate(struct yagl_surface *sfc) struct yagl_onscreen_display *dpy = (struct yagl_onscreen_display*)sfc->dpy; struct yagl_onscreen_buffer *new_buffer; - if (osfc->last_stamp == osfc->stamp) { + if (osfc->last_stamp == sfc->native_drawable->stamp) { return; } assert(sfc->type == EGL_WINDOW_BIT); - osfc->last_stamp = osfc->stamp; + osfc->last_stamp = sfc->native_drawable->stamp; /* * We only process new buffer if it's different from * the current one. */ - new_buffer = yagl_onscreen_display_create_buffer(dpy, - sfc->x_drawable.win, - DRI2BufferBackLeft, - osfc->buffer->dri2_buffer->name); + new_buffer = yagl_onscreen_buffer_create(dpy, + sfc->native_drawable, + yagl_native_attachment_back, + osfc->buffer->name); if (!new_buffer) { return; } - yagl_onscreen_display_destroy_buffer(osfc->buffer); + yagl_onscreen_buffer_destroy(osfc->buffer); osfc->buffer = new_buffer; YAGL_HOST_CALL_ASSERT(yagl_host_eglInvalidateOnscreenSurfaceYAGL( @@ -118,7 +67,6 @@ static void yagl_onscreen_surface_finish(struct yagl_surface *sfc) static int yagl_onscreen_surface_swap_buffers(struct yagl_surface *sfc) { EGLBoolean retval = EGL_FALSE; - CARD64 count = 0; YAGL_LOG_FUNC_SET(eglSwapBuffers); @@ -133,19 +81,16 @@ static int yagl_onscreen_surface_swap_buffers(struct yagl_surface *sfc) yagl_onscreen_surface_finish(sfc); - yagl_DRI2SwapBuffers(sfc->dpy->x_dpy, - sfc->x_drawable.win, 0, 0, 0, - &count); + sfc->native_drawable->swap_buffers(sfc->native_drawable); return 1; } static int yagl_onscreen_surface_copy_buffers(struct yagl_surface *sfc, - Pixmap target) + yagl_os_pixmap target) { struct yagl_onscreen_surface *osfc = (struct yagl_onscreen_surface*)sfc; EGLBoolean retval = EGL_FALSE; - GC x_gc; YAGL_LOG_FUNC_SET(eglCopyBuffers); @@ -160,62 +105,10 @@ static int yagl_onscreen_surface_copy_buffers(struct yagl_surface *sfc, yagl_onscreen_surface_finish(sfc); - x_gc = XCreateGC(sfc->dpy->x_dpy, target, 0, NULL); - - if (x_gc) { - switch (sfc->type) { - case EGL_PBUFFER_BIT: - XCopyArea(sfc->dpy->x_dpy, - osfc->tmp_pixmap, - target, - x_gc, - 0, 0, - osfc->buffer->drm_sfc->width, - osfc->buffer->drm_sfc->height, - 0, 0); - break; - case EGL_PIXMAP_BIT: -#ifdef YAGL_FAKE_PIXMAP_SURFACE - XCopyArea(sfc->dpy->x_dpy, - osfc->tmp_pixmap, - target, - x_gc, - 0, 0, - osfc->buffer->drm_sfc->width, - osfc->buffer->drm_sfc->height, - 0, 0); -#else - XCopyArea(sfc->dpy->x_dpy, - sfc->x_drawable.pixmap, - target, - x_gc, - 0, 0, - osfc->buffer->drm_sfc->width, - osfc->buffer->drm_sfc->height, - 0, 0); -#endif - break; - case EGL_WINDOW_BIT: - XCopyArea(sfc->dpy->x_dpy, - sfc->x_drawable.win, - target, - x_gc, - 0, 0, - osfc->buffer->drm_sfc->width, - osfc->buffer->drm_sfc->height, - 0, 0); - break; - default: - assert(0); - YAGL_LOG_ERROR("Bad surface type"); - } - } else { - YAGL_LOG_ERROR("XCreateGC failed"); - } - - XFreeGC(sfc->dpy->x_dpy, x_gc); - - XSync(sfc->dpy->x_dpy, 0); + sfc->native_drawable->copy_to_pixmap(sfc->native_drawable, + target, 0, 0, 0, 0, + osfc->buffer->drm_sfc->width, + osfc->buffer->drm_sfc->height); return 1; } @@ -233,11 +126,9 @@ static void yagl_onscreen_surface_wait_x(struct yagl_surface *sfc) */ break; case EGL_PIXMAP_BIT: -#ifndef YAGL_FAKE_PIXMAP_SURFACE - yagl_onscreen_surface_copy_drawable(osfc, - DRI2BufferFrontLeft, - DRI2BufferFakeFrontLeft); -#endif + sfc->native_drawable->wait(sfc->native_drawable, + osfc->buffer->drm_sfc->width, + osfc->buffer->drm_sfc->height); break; default: assert(0); @@ -250,7 +141,6 @@ static void yagl_onscreen_surface_wait_gl(struct yagl_surface *sfc) EGLBoolean retval; /* - * There used to be DRI2CopyRegion call here, but it's not needed. * This call must not be distinguishable from glFinish, so just do * the stuff glFinish does here and not more. */ @@ -311,36 +201,18 @@ static void yagl_onscreen_surface_set_swap_interval(struct yagl_surface *sfc, { assert(sfc->type == EGL_WINDOW_BIT); - yagl_DRI2SwapInterval(sfc->dpy->x_dpy, sfc->x_drawable.win, interval); + sfc->native_drawable->set_swap_interval(sfc->native_drawable, interval); } static void yagl_onscreen_surface_destroy(struct yagl_ref *ref) { struct yagl_onscreen_surface *sfc = (struct yagl_onscreen_surface*)ref; - yagl_onscreen_display_destroy_buffer(sfc->buffer); - switch (sfc->base.type) { - case EGL_PBUFFER_BIT: - yagl_DRI2DestroyDrawable(sfc->base.dpy->x_dpy, - sfc->tmp_pixmap); - break; - case EGL_PIXMAP_BIT: - yagl_DRI2DestroyDrawable(sfc->base.dpy->x_dpy, - sfc->base.x_drawable.pixmap); - break; - case EGL_WINDOW_BIT: - yagl_DRI2DestroyDrawable(sfc->base.dpy->x_dpy, - sfc->base.x_drawable.win); - break; - default: - assert(0); - break; - } + yagl_onscreen_buffer_destroy(sfc->buffer); if (sfc->tmp_pixmap) { - XFreePixmap(sfc->base.dpy->x_dpy, - sfc->tmp_pixmap); - sfc->tmp_pixmap = 0; + sfc->tmp_pixmap->destroy(sfc->tmp_pixmap); + sfc->tmp_pixmap = NULL; } yagl_surface_cleanup(&sfc->base); @@ -351,7 +223,7 @@ static void yagl_onscreen_surface_destroy(struct yagl_ref *ref) struct yagl_onscreen_surface *yagl_onscreen_surface_create_window(struct yagl_display *dpy, yagl_host_handle host_config, - Window x_win, + struct yagl_native_drawable *native_window, const EGLint* attrib_list) { struct yagl_onscreen_display *odpy = (struct yagl_onscreen_display*)dpy; @@ -361,12 +233,10 @@ struct yagl_onscreen_surface sfc = yagl_malloc0(sizeof(*sfc)); - yagl_DRI2CreateDrawable(dpy->x_dpy, x_win); - - new_buffer = yagl_onscreen_display_create_buffer(odpy, - x_win, - DRI2BufferBackLeft, - 0); + new_buffer = yagl_onscreen_buffer_create(odpy, + native_window, + yagl_native_attachment_back, + 0); if (!new_buffer) { yagl_set_error(EGL_BAD_NATIVE_WINDOW); @@ -389,7 +259,7 @@ struct yagl_onscreen_surface &yagl_onscreen_surface_destroy, host_surface, dpy, - x_win); + native_window); sfc->base.invalidate = &yagl_onscreen_surface_invalidate; sfc->base.finish = &yagl_onscreen_surface_finish; @@ -407,119 +277,17 @@ struct yagl_onscreen_surface fail: if (new_buffer) { - yagl_onscreen_display_destroy_buffer(new_buffer); - yagl_DRI2DestroyDrawable(dpy->x_dpy, x_win); + yagl_onscreen_buffer_destroy(new_buffer); } yagl_free(sfc); return NULL; } -#ifdef YAGL_FAKE_PIXMAP_SURFACE -struct yagl_onscreen_surface - *yagl_onscreen_surface_create_pixmap(struct yagl_display *dpy, - yagl_host_handle host_config, - Pixmap x_pixmap, - const EGLint* attrib_list) -{ - struct yagl_onscreen_display *odpy = (struct yagl_onscreen_display*)dpy; - struct yagl_onscreen_surface *sfc; - uint32_t width = 0; - uint32_t height = 0; - unsigned int depth = 0; - union { Window w; int i; unsigned int ui; } tmp_geom; - struct yagl_onscreen_buffer *new_buffer = NULL; - yagl_host_handle host_surface = 0; - - YAGL_LOG_FUNC_SET(eglCreatePixmapSurface); - - memset(&tmp_geom, 0, sizeof(tmp_geom)); - - XGetGeometry(dpy->x_dpy, - x_pixmap, - &tmp_geom.w, - &tmp_geom.i, - &tmp_geom.i, - &width, - &height, - &tmp_geom.ui, - &depth); - - sfc = yagl_malloc0(sizeof(*sfc)); - - sfc->tmp_pixmap = XCreatePixmap(dpy->x_dpy, - RootWindow(dpy->x_dpy, DefaultScreen(dpy->x_dpy)), - width, height, depth); - - if (!sfc->tmp_pixmap) { - YAGL_LOG_ERROR("XCreatePixmap(%u,%u) failed", width, height); - yagl_set_error(EGL_BAD_ALLOC); - goto fail; - } - - yagl_DRI2CreateDrawable(dpy->x_dpy, sfc->tmp_pixmap); - - new_buffer = yagl_onscreen_display_create_buffer(odpy, - sfc->tmp_pixmap, - DRI2BufferFrontLeft, - 0); - - if (!new_buffer) { - yagl_set_error(EGL_BAD_NATIVE_PIXMAP); - goto fail; - } - - do { - yagl_mem_probe_read_attrib_list(attrib_list); - } while (!yagl_host_eglCreatePixmapSurfaceOnscreenYAGL(&host_surface, - dpy->host_dpy, - host_config, - new_buffer->drm_sfc->id, - attrib_list)); - - if (!host_surface) { - goto fail; - } - - yagl_surface_init_pixmap(&sfc->base, - &yagl_onscreen_surface_destroy, - host_surface, - dpy, - x_pixmap); - - sfc->base.invalidate = &yagl_onscreen_surface_invalidate; - sfc->base.finish = &yagl_onscreen_surface_finish; - sfc->base.swap_buffers = &yagl_onscreen_surface_swap_buffers; - sfc->base.copy_buffers = &yagl_onscreen_surface_copy_buffers; - sfc->base.wait_x = &yagl_onscreen_surface_wait_x; - sfc->base.wait_gl = &yagl_onscreen_surface_wait_gl; - sfc->base.map = &yagl_onscreen_surface_map; - sfc->base.unmap = &yagl_onscreen_surface_unmap; - sfc->base.set_swap_interval = &yagl_onscreen_surface_set_swap_interval; - - sfc->buffer = new_buffer; - - return sfc; - -fail: - if (sfc) { - if (sfc->tmp_pixmap) { - if (new_buffer) { - yagl_onscreen_display_destroy_buffer(new_buffer); - yagl_DRI2DestroyDrawable(dpy->x_dpy, sfc->tmp_pixmap); - } - XFreePixmap(dpy->x_dpy, sfc->tmp_pixmap); - } - yagl_free(sfc); - } - - return NULL; -} -#else struct yagl_onscreen_surface *yagl_onscreen_surface_create_pixmap(struct yagl_display *dpy, yagl_host_handle host_config, - Pixmap x_pixmap, + struct yagl_native_drawable *native_pixmap, const EGLint* attrib_list) { struct yagl_onscreen_display *odpy = (struct yagl_onscreen_display*)dpy; @@ -529,12 +297,10 @@ struct yagl_onscreen_surface sfc = yagl_malloc0(sizeof(*sfc)); - yagl_DRI2CreateDrawable(dpy->x_dpy, x_pixmap); - - new_buffer = yagl_onscreen_display_create_buffer(odpy, - x_pixmap, - DRI2BufferFrontLeft, - 0); + new_buffer = yagl_onscreen_buffer_create(odpy, + native_pixmap, + yagl_native_attachment_front, + 0); if (!new_buffer) { yagl_set_error(EGL_BAD_NATIVE_PIXMAP); @@ -557,7 +323,7 @@ struct yagl_onscreen_surface &yagl_onscreen_surface_destroy, host_surface, dpy, - x_pixmap); + native_pixmap); sfc->base.invalidate = &yagl_onscreen_surface_invalidate; sfc->base.finish = &yagl_onscreen_surface_finish; @@ -575,14 +341,12 @@ struct yagl_onscreen_surface fail: if (new_buffer) { - yagl_onscreen_display_destroy_buffer(new_buffer); - yagl_DRI2DestroyDrawable(dpy->x_dpy, x_pixmap); + yagl_onscreen_buffer_destroy(new_buffer); } yagl_free(sfc); return NULL; } -#endif struct yagl_onscreen_surface *yagl_onscreen_surface_create_pbuffer(struct yagl_display *dpy, @@ -618,22 +382,21 @@ struct yagl_onscreen_surface } } - sfc->tmp_pixmap = XCreatePixmap(dpy->x_dpy, - RootWindow(dpy->x_dpy, DefaultScreen(dpy->x_dpy)), - width, height, 24); + sfc->tmp_pixmap = dpy->native_dpy->create_pixmap(dpy->native_dpy, + width, + height, + 24); if (!sfc->tmp_pixmap) { - YAGL_LOG_ERROR("XCreatePixmap(%u,%u) failed", width, height); + YAGL_LOG_ERROR("create_pixmap(%u,%u) failed", width, height); yagl_set_error(EGL_BAD_ALLOC); goto fail; } - yagl_DRI2CreateDrawable(dpy->x_dpy, sfc->tmp_pixmap); - - new_buffer = yagl_onscreen_display_create_buffer(odpy, - sfc->tmp_pixmap, - DRI2BufferFrontLeft, - 0); + new_buffer = yagl_onscreen_buffer_create(odpy, + sfc->tmp_pixmap, + yagl_native_attachment_front, + 0); if (!new_buffer) { yagl_set_error(EGL_BAD_ALLOC); @@ -675,10 +438,10 @@ fail: if (sfc) { if (sfc->tmp_pixmap) { if (new_buffer) { - yagl_onscreen_display_destroy_buffer(new_buffer); - yagl_DRI2DestroyDrawable(dpy->x_dpy, sfc->tmp_pixmap); + yagl_onscreen_buffer_destroy(new_buffer); } - XFreePixmap(dpy->x_dpy, sfc->tmp_pixmap); + sfc->tmp_pixmap->destroy(sfc->tmp_pixmap); + sfc->tmp_pixmap = NULL; } yagl_free(sfc); } diff --git a/EGL/yagl_onscreen_surface.h b/EGL/yagl_onscreen_surface.h index 7d92587..7fc7d03 100644 --- a/EGL/yagl_onscreen_surface.h +++ b/EGL/yagl_onscreen_surface.h @@ -4,8 +4,8 @@ #include "yagl_export.h" #include "yagl_types.h" #include "yagl_surface.h" -#include "yagl_dri2.h" -#include "yagl_onscreen_display.h" + +struct yagl_onscreen_buffer; struct yagl_onscreen_surface { @@ -14,27 +14,20 @@ struct yagl_onscreen_surface /* * Backing pixmap for PBuffer surfaces. NULL otherwise. */ - Pixmap tmp_pixmap; + struct yagl_native_drawable *tmp_pixmap; /* - * For widow surfaces this is DRI2BufferBackLeft. - * For pixmap surfaces this is DRI2BufferFrontLeft. - * For pbuffer surfaces this is DRI2BufferFrontLeft of 'tmp_pixmap'. + * For widow surfaces this is yagl_native_attachment_back. + * For pixmap surfaces this is yagl_native_attachment_front. + * For pbuffer surfaces this is yagl_native_attachment_front of 'tmp_pixmap'. * * TODO: For window surfaces we also need to support - * DRI2BufferFrontLeft. + * yagl_native_attachment_front. */ struct yagl_onscreen_buffer *buffer; /* - * This gets incremented in DRI2 invalidate handler, compare it to - * 'last_timestamp' in order to find out if an invalidate event - * had occurred. - */ - uint32_t stamp; - - /* - * Last value of 'stamp'. + * Last value of 'base.native_drawable->stamp'. */ uint32_t last_stamp; }; @@ -42,18 +35,18 @@ struct yagl_onscreen_surface struct yagl_onscreen_surface *yagl_onscreen_surface_create_window(struct yagl_display *dpy, yagl_host_handle host_config, - Window x_win, - const EGLint* attrib_list); + struct yagl_native_drawable *native_window, + const EGLint *attrib_list); struct yagl_onscreen_surface *yagl_onscreen_surface_create_pixmap(struct yagl_display *dpy, yagl_host_handle host_config, - Pixmap x_pixmap, - const EGLint* attrib_list); + struct yagl_native_drawable *native_pixmap, + const EGLint *attrib_list); struct yagl_onscreen_surface *yagl_onscreen_surface_create_pbuffer(struct yagl_display *dpy, yagl_host_handle host_config, - const EGLint* attrib_list); + const EGLint *attrib_list); #endif diff --git a/EGL/yagl_surface.c b/EGL/yagl_surface.c index b6b311e..bdf1f46 100644 --- a/EGL/yagl_surface.c +++ b/EGL/yagl_surface.c @@ -1,5 +1,6 @@ #include "yagl_surface.h" #include "yagl_utils.h" +#include "yagl_native_drawable.h" #include <assert.h> #include "EGL/eglext.h" @@ -7,13 +8,13 @@ void yagl_surface_init_window(struct yagl_surface *sfc, yagl_ref_destroy_func destroy_func, yagl_host_handle handle, struct yagl_display *dpy, - Window x_win) + struct yagl_native_drawable *native_window) { yagl_resource_init(&sfc->res, destroy_func, handle); sfc->dpy = dpy; sfc->type = EGL_WINDOW_BIT; - sfc->x_drawable.win = x_win; + sfc->native_drawable = native_window; yagl_recursive_mutex_init(&sfc->mtx); } @@ -22,13 +23,13 @@ void yagl_surface_init_pixmap(struct yagl_surface *sfc, yagl_ref_destroy_func destroy_func, yagl_host_handle handle, struct yagl_display *dpy, - Pixmap x_pixmap) + struct yagl_native_drawable *native_pixmap) { yagl_resource_init(&sfc->res, destroy_func, handle); sfc->dpy = dpy; sfc->type = EGL_PIXMAP_BIT; - sfc->x_drawable.pixmap = x_pixmap; + sfc->native_drawable = native_pixmap; yagl_recursive_mutex_init(&sfc->mtx); } @@ -48,6 +49,10 @@ void yagl_surface_init_pbuffer(struct yagl_surface *sfc, void yagl_surface_cleanup(struct yagl_surface *sfc) { + if (sfc->native_drawable) { + sfc->native_drawable->destroy(sfc->native_drawable); + sfc->native_drawable = NULL; + } yagl_resource_cleanup(&sfc->res); pthread_mutex_destroy(&sfc->mtx); } @@ -58,9 +63,8 @@ EGLSurface yagl_surface_get_handle(struct yagl_surface *sfc) case EGL_PBUFFER_BIT: return (EGLSurface)sfc->res.handle; case EGL_PIXMAP_BIT: - return (EGLSurface)sfc->x_drawable.pixmap; case EGL_WINDOW_BIT: - return (EGLSurface)sfc->x_drawable.win; + return (EGLSurface)sfc->native_drawable->os_drawable; default: assert(0); return NULL; diff --git a/EGL/yagl_surface.h b/EGL/yagl_surface.h index b966776..e634ee1 100644 --- a/EGL/yagl_surface.h +++ b/EGL/yagl_surface.h @@ -3,10 +3,12 @@ #include "yagl_export.h" #include "yagl_types.h" +#include "yagl_native_types.h" #include "yagl_resource.h" #include "EGL/egl.h" struct yagl_display; +struct yagl_native_drawable; struct yagl_surface { @@ -16,11 +18,7 @@ struct yagl_surface EGLenum type; - union - { - Window win; - Pixmap pixmap; - } x_drawable; + struct yagl_native_drawable *native_drawable; pthread_mutex_t mtx; @@ -44,7 +42,7 @@ struct yagl_surface int (*swap_buffers)(struct yagl_surface */*sfc*/); - int (*copy_buffers)(struct yagl_surface */*sfc*/, Pixmap /*target*/); + int (*copy_buffers)(struct yagl_surface */*sfc*/, yagl_os_pixmap /*target*/); void (*wait_x)(struct yagl_surface */*sfc*/); @@ -57,17 +55,23 @@ struct yagl_surface void (*set_swap_interval)(struct yagl_surface */*sfc*/, int /*interval*/); }; +/* + * Takes ownership of 'native_window'. + */ void yagl_surface_init_window(struct yagl_surface *sfc, yagl_ref_destroy_func destroy_func, yagl_host_handle handle, struct yagl_display *dpy, - Window x_win); + struct yagl_native_drawable *native_window); +/* + * Takes ownership of 'native_pixmap'. + */ void yagl_surface_init_pixmap(struct yagl_surface *sfc, yagl_ref_destroy_func destroy_func, yagl_host_handle handle, struct yagl_display *dpy, - Pixmap x_pixmap); + struct yagl_native_drawable *native_pixmap); void yagl_surface_init_pbuffer(struct yagl_surface *sfc, yagl_ref_destroy_func destroy_func, diff --git a/GLES_common/yagl_gles_calls.c b/GLES_common/yagl_gles_calls.c index 51a7da8..e6e1f17 100644 --- a/GLES_common/yagl_gles_calls.c +++ b/GLES_common/yagl_gles_calls.c @@ -1,4 +1,3 @@ -#include <X11/Xutil.h> #include <errno.h> #include <stdio.h> #include <stdlib.h> diff --git a/include/yagl_marshal_egl.h b/include/yagl_marshal_egl.h index e625f17..78ea18a 100644 --- a/include/yagl_marshal_egl.h +++ b/include/yagl_marshal_egl.h @@ -14,7 +14,5 @@ #define yagl_marshal_get_EGLint(buff) yagl_marshal_get_int32(buff) #define yagl_marshal_put_EGLClientBuffer(buff, value) yagl_marshal_skip(buff) -#define yagl_marshal_put_EGLNativePixmapType(buff, value) yagl_marshal_skip(buff) -#define yagl_marshal_put_EGLNativeWindowType(buff, value) yagl_marshal_skip(buff) #endif diff --git a/include/yagl_platform.h b/include/yagl_platform.h deleted file mode 100644 index 1c5a6b1..0000000 --- a/include/yagl_platform.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef _YAGL_PLATFORM_H_ -#define _YAGL_PLATFORM_H_ - -#if defined(__i386) || defined(_M_IX86) -#define YAGL_LITTLE_ENDIAN -#elif defined(__x86_64) || defined(_M_X64) || defined(_M_IA64) -#define YAGL_LITTLE_ENDIAN -#elif defined(__arm__) -#define YAGL_LITTLE_ENDIAN -#else -#error Unknown architecture -#endif - -#if defined(__x86_64) || defined(_M_X64) || defined(_M_IA64) || defined(__LP64__) -#define YAGL_64 -#else -#define YAGL_32 -#endif - -#if !defined(YAGL_64) && !defined(YAGL_32) -#error 32 or 64 bit mode must be set -#endif - -#endif diff --git a/include/yagl_types.h b/include/yagl_types.h index 8f0dddf..6573354 100644 --- a/include/yagl_types.h +++ b/include/yagl_types.h @@ -1,10 +1,29 @@ #ifndef _YAGL_TYPES_H_ #define _YAGL_TYPES_H_ -#include "yagl_platform.h" #include <stdint.h> #include <stddef.h> +#if defined(__i386) || defined(_M_IX86) +#define YAGL_LITTLE_ENDIAN +#elif defined(__x86_64) || defined(_M_X64) || defined(_M_IA64) +#define YAGL_LITTLE_ENDIAN +#elif defined(__arm__) +#define YAGL_LITTLE_ENDIAN +#else +#error Unknown architecture +#endif + +#if defined(__x86_64) || defined(_M_X64) || defined(_M_IA64) || defined(__LP64__) +#define YAGL_64 +#else +#define YAGL_32 +#endif + +#if !defined(YAGL_64) && !defined(YAGL_32) +#error 32 or 64 bit mode must be set +#endif + typedef enum { yagl_render_type_offscreen = 1, diff --git a/include/yagl_version.h b/include/yagl_version.h index ae60f16..7c214b2 100644 --- a/include/yagl_version.h +++ b/include/yagl_version.h @@ -6,7 +6,7 @@ /* * Version number. */ -#define YAGL_VERSION 18 +#define YAGL_VERSION 19 /* * Device control codes magic. diff --git a/packaging/emulator-yagl.spec b/packaging/emulator-yagl.spec index 4c1d24b..54e79f5 100644 --- a/packaging/emulator-yagl.spec +++ b/packaging/emulator-yagl.spec @@ -35,6 +35,8 @@ make %install make install +ln -s libGLESv2.so.2.0 %{buildroot}/usr/lib/yagl/libGLESv2.so.1.0 +ln -s libGLESv2.so.1.0 %{buildroot}/usr/lib/yagl/libGLESv2.so.1 mkdir -p %{buildroot}/usr/lib/systemd/system cp packaging/emul-opengl-yagl.service %{buildroot}/usr/lib/systemd/system mkdir -p %{buildroot}/etc/emulator |