Skip to content

Commit

Permalink
Re-implement X11 EGL platform based on wayland code.
Browse files Browse the repository at this point in the history
It renders to gralloc-allocated buffers and then uses XShmPutImage/XPutImage to copy result to X server.
  • Loading branch information
NotKit committed Oct 18, 2017
1 parent ed62407 commit f5b21fb
Show file tree
Hide file tree
Showing 7 changed files with 1,165 additions and 2 deletions.
1 change: 1 addition & 0 deletions hybris/configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ AC_CONFIG_FILES([
egl/platforms/null/Makefile
egl/platforms/fbdev/Makefile
egl/platforms/wayland/Makefile
egl/platforms/x11/Makefile
egl/platforms/hwcomposer/Makefile
egl/platforms/hwcomposer/hwcomposer-egl.pc
glesv1/glesv1_cm.pc
Expand Down
2 changes: 1 addition & 1 deletion hybris/egl/platforms/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ if WANT_WAYLAND
SUBDIRS += wayland
endif


SUBDIRS += x11
2 changes: 1 addition & 1 deletion hybris/egl/platforms/common/eglplatformcommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ extern "C" void hybris_dump_buffer_to_file(ANativeWindowBuffer *buf)
char b[1024];
int bytes_pp = 0;

if (buf->format == HAL_PIXEL_FORMAT_RGBA_8888)
if (buf->format == HAL_PIXEL_FORMAT_RGBA_8888 || buf->format == HAL_PIXEL_FORMAT_BGRA_8888)
bytes_pp = 4;
else if (buf->format == HAL_PIXEL_FORMAT_RGB_565)
bytes_pp = 2;
Expand Down
43 changes: 43 additions & 0 deletions hybris/egl/platforms/x11/Makefile.am
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
pkglib_LTLIBRARIES = eglplatform_x11.la

eglplatform_x11_la_SOURCES = eglplatform_x11.cpp x11_window.cpp
eglplatform_x11_la_CXXFLAGS = \
-I$(top_srcdir)/common \
-I$(top_srcdir)/include \
-I$(top_srcdir)/egl \
-I$(top_srcdir)/egl/platforms/common \
$(ANDROID_HEADERS_CFLAGS) \
$(WAYLAND_CLIENT_CFLAGS)

if WANT_DEBUG
eglplatform_x11_la_CXXFLAGS += -I$(top_srcdir)/common
endif

if WANT_TRACE
eglplatform_x11_la_CXXFLAGS += -DDEBUG
endif

if WANT_DEBUG
eglplatform_x11_la_CXXFLAGS += -ggdb -O0
endif

if !WANT_WL_SERVERSIDE_BUFFERS
eglplatform_x11_la_CXXFLAGS += -DHYBRIS_NO_SERVER_SIDE_BUFFERS
endif



eglplatform_x11_la_LDFLAGS = \
-avoid-version -module -shared -export-dynamic \
$(top_builddir)/egl/platforms/common/libhybris-eglplatformcommon.la \
$(top_builddir)/hardware/libhardware.la \
-lX11 -lXext

if HAS_ANDROID_4_2_0
eglplatform_x11_la_LDFLAGS += $(top_builddir)/libsync/libsync.la
endif

if HAS_ANDROID_5_0_0
eglplatform_x11_la_LDFLAGS += $(top_builddir)/libsync/libsync.la
endif

235 changes: 235 additions & 0 deletions hybris/egl/platforms/x11/eglplatform_x11.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
/****************************************************************************************
**
** Copyright (C) 2013 Jolla Ltd.
** Contact: Carsten Munk <carsten.munk@jollamobile.com>
** All rights reserved.
**
** This file is part of X11 enablement for libhybris
**
** You may use this file under the terms of the GNU Lesser General
** Public License version 2.1 as published by the Free Software Foundation
** and appearing in the file license.lgpl included in the packaging
** of this file.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation
** and appearing in the file license.lgpl included in the packaging
** of this file.
**
** This library is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
** Lesser General Public License for more details.
**
****************************************************************************************/

#include <android-config.h>
#include <ws.h>
#include <malloc.h>
#include <assert.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <assert.h>
#include <stdlib.h>
extern "C" {
#include <eglplatformcommon.h>
};
#include <eglhybris.h>

#include <EGL/eglext.h>

extern "C" {
#include <wayland-client.h>
#include <wayland-egl.h>
}

#include "x11_window.h"
#include "logging.h"

#include <X11/Xlib.h>
#include <X11/Xutil.h>

static gralloc_module_t *gralloc = 0;
static alloc_device_t *alloc = 0;


static const char * (*_eglQueryString)(EGLDisplay dpy, EGLint name) = NULL;
static __eglMustCastToProperFunctionPointerType (*_eglGetProcAddress)(const char *procname) = NULL;
static EGLSyncKHR (*_eglCreateSyncKHR)(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list) = NULL;
static EGLBoolean (*_eglDestroySyncKHR)(EGLDisplay dpy, EGLSyncKHR sync) = NULL;
static EGLint (*_eglClientWaitSyncKHR)(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout) = NULL;

struct X11Display {
_EGLDisplay base;
Display *xl_display;
};

extern "C" void x11ws_init_module(struct ws_egl_interface *egl_iface)
{
int err;
hw_get_module(GRALLOC_HARDWARE_MODULE_ID, (const hw_module_t **) &gralloc);
err = gralloc_open((const hw_module_t *) gralloc, &alloc);
TRACE("++ %lu x11: got gralloc %p err:%s", pthread_self(), gralloc, strerror(-err));
eglplatformcommon_init(egl_iface, gralloc, alloc);
}

static void _init_egl_funcs(EGLDisplay display)
{
if (_eglQueryString != NULL)
return;

_eglQueryString = (const char * (*)(void*, int))
hybris_android_egl_dlsym("eglQueryString");
assert(_eglQueryString);
_eglGetProcAddress = (__eglMustCastToProperFunctionPointerType (*)(const char *))
hybris_android_egl_dlsym("eglGetProcAddress");
assert(_eglGetProcAddress);

const char *extensions = (*_eglQueryString)(display, EGL_EXTENSIONS);

if (strstr(extensions, "EGL_KHR_fence_sync")) {
_eglCreateSyncKHR = (PFNEGLCREATESYNCKHRPROC)
(*_eglGetProcAddress)("eglCreateSyncKHR");
assert(_eglCreateSyncKHR);
_eglDestroySyncKHR = (PFNEGLDESTROYSYNCKHRPROC)
(*_eglGetProcAddress)("eglDestroySyncKHR");
assert(_eglDestroySyncKHR);
_eglClientWaitSyncKHR = (PFNEGLCLIENTWAITSYNCKHRPROC)
(*_eglGetProcAddress)("eglClientWaitSyncKHR");
assert(_eglClientWaitSyncKHR);
}
}

extern "C" _EGLDisplay *x11ws_GetDisplay(EGLNativeDisplayType display)
{
X11Display *xdpy = new X11Display;
xdpy->xl_display = (Display *)display;

return &xdpy->base;
}

extern "C" void x11ws_Terminate(_EGLDisplay *dpy)
{
X11Display *xdpy = (X11Display *)dpy;
int ret = 0;
delete xdpy;
}

extern "C" EGLNativeWindowType x11ws_CreateWindow(EGLNativeWindowType win, _EGLDisplay *display)
{
Window xlib_window = (Window) win;
X11Display *xdpy = (X11Display *)display;

if (win == 0 || xdpy->xl_display == 0) {
HYBRIS_ERROR("Running with EGL_PLATFORM=x11 without X server is not possible");
HYBRIS_ERROR("If you want to run a standlone EGL client do it like this:");
HYBRIS_ERROR(" $ export EGL_PLATFORM=null");
HYBRIS_ERROR(" $ test_glevs2");
abort();
}

X11NativeWindow *window = new X11NativeWindow(xdpy->xl_display, xlib_window, alloc, gralloc);
window->common.incRef(&window->common);
return (EGLNativeWindowType) static_cast<struct ANativeWindow *>(window);
}

extern "C" void x11ws_DestroyWindow(EGLNativeWindowType win)
{
X11NativeWindow *window = static_cast<X11NativeWindow *>((struct ANativeWindow *)win);
window->common.decRef(&window->common);
}

extern "C" __eglMustCastToProperFunctionPointerType x11ws_eglGetProcAddress(const char *procname)
{
return eglplatformcommon_eglGetProcAddress(procname);
}

extern "C" void x11ws_passthroughImageKHR(EGLContext *ctx, EGLenum *target, EGLClientBuffer *buffer, const EGLint **attrib_list)
{
eglplatformcommon_passthroughImageKHR(ctx, target, buffer, attrib_list);
}

extern "C" const char *x11ws_eglQueryString(EGLDisplay dpy, EGLint name, const char *(*real_eglQueryString)(EGLDisplay dpy, EGLint name))
{
const char *ret = eglplatformcommon_eglQueryString(dpy, name, real_eglQueryString);
if (ret && name == EGL_EXTENSIONS)
{
static char eglextensionsbuf[1024];
snprintf(eglextensionsbuf, 1022, "%s %s", ret,
"EGL_EXT_swap_buffers_with_damage EGL_WL_create_x11_buffer_from_image"
);
ret = eglextensionsbuf;
}
return ret;
}

extern "C" void x11ws_prepareSwap(EGLDisplay dpy, EGLNativeWindowType win, EGLint *damage_rects, EGLint damage_n_rects)
{
X11NativeWindow *window = static_cast<X11NativeWindow *>((struct ANativeWindow *)win);
window->prepareSwap(damage_rects, damage_n_rects);
}

extern "C" void x11ws_finishSwap(EGLDisplay dpy, EGLNativeWindowType win)
{
_init_egl_funcs(dpy);
X11NativeWindow *window = static_cast<X11NativeWindow *>((struct ANativeWindow *)win);
if (_eglCreateSyncKHR) {
EGLSyncKHR sync = (*_eglCreateSyncKHR)(dpy, EGL_SYNC_FENCE_KHR, NULL);
(*_eglClientWaitSyncKHR)(dpy, sync, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, EGL_FOREVER_KHR);
(*_eglDestroySyncKHR)(dpy, sync);
}
window->finishSwap();
}

extern "C" void x11ws_setSwapInterval(EGLDisplay dpy, EGLNativeWindowType win, EGLint interval)
{
X11NativeWindow *window = static_cast<X11NativeWindow *>((struct ANativeWindow *)win);
window->setSwapInterval(interval);
}

extern "C" EGLBoolean x11ws_eglGetConfigAttrib(struct _EGLDisplay *display, EGLConfig config, EGLint attribute, EGLint *value)
{
TRACE("attribute:%i", attribute);
if (attribute == EGL_NATIVE_VISUAL_ID)
{
X11Display *xdpy = (X11Display *)display;
XVisualInfo visinfo_template;
XVisualInfo *visinfo = NULL;
int visinfos_count = 0;

visinfo_template.depth = 32;
visinfo = XGetVisualInfo (xdpy->xl_display,
VisualDepthMask,
&visinfo_template,
&visinfos_count);

if (visinfos_count)
{
TRACE("visinfo.visualid:%i", attribute);
*value = visinfo->visualid;
return EGL_TRUE;
}

}
return EGL_FALSE;
}

struct ws_module ws_module_info = {
x11ws_init_module,
x11ws_GetDisplay,
x11ws_Terminate,
x11ws_CreateWindow,
x11ws_DestroyWindow,
x11ws_eglGetProcAddress,
x11ws_passthroughImageKHR,
x11ws_eglQueryString,
x11ws_prepareSwap,
x11ws_finishSwap,
x11ws_setSwapInterval,
x11ws_eglGetConfigAttrib
};
Loading

0 comments on commit f5b21fb

Please sign in to comment.