summaryrefslogtreecommitdiff
path: root/libweston
diff options
context:
space:
mode:
authorPekka Paalanen <pekka.paalanen@collabora.com>2019-09-20 14:23:12 +0300
committerPekka Paalanen <pq@iki.fi>2019-10-11 12:16:35 +0000
commit5104d7b2afd4980da71370c27b7f79a441759f30 (patch)
treecbe75d129173dcf8ef3a1dd473506ea6e8dfd65f /libweston
parent209187491b7a52b8ae735db69499aff2b03cec75 (diff)
downloadweston-5104d7b2afd4980da71370c27b7f79a441759f30.tar.gz
headless, gl-renderer: support pbuffer outputs
Use the surfaceless platform in the headless backend to initialize the GL-renderer and create pbuffer outputs. This allows headless backend to use GL-renderer, even hardware accelerated. This paves way for exercising GL-renderer in CI and using the Weston test suite to test hardware GL ES implementations. Relates to: https://gitlab.freedesktop.org/wayland/weston/issues/278 Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
Diffstat (limited to 'libweston')
-rw-r--r--libweston/backend-headless/headless.c82
-rw-r--r--libweston/renderer-gl/gl-renderer.c43
-rw-r--r--libweston/renderer-gl/gl-renderer.h27
3 files changed, 151 insertions, 1 deletions
diff --git a/libweston/backend-headless/headless.c b/libweston/backend-headless/headless.c
index e5630b3a..95b390a8 100644
--- a/libweston/backend-headless/headless.c
+++ b/libweston/backend-headless/headless.c
@@ -32,18 +32,22 @@
#include <string.h>
#include <sys/time.h>
#include <stdbool.h>
+#include <drm_fourcc.h>
#include <libweston/libweston.h>
#include <libweston/backend-headless.h>
#include "shared/helpers.h"
#include "linux-explicit-synchronization.h"
#include "pixman-renderer.h"
+#include "renderer-gl/gl-renderer.h"
+#include "linux-dmabuf.h"
#include "presentation-time-server-protocol.h"
#include <libweston/windowed-output-api.h>
enum headless_renderer_type {
HEADLESS_NOOP,
HEADLESS_PIXMAN,
+ HEADLESS_GL,
};
struct headless_backend {
@@ -52,6 +56,8 @@ struct headless_backend {
struct weston_seat fake_seat;
enum headless_renderer_type renderer_type;
+
+ struct gl_renderer_interface *glri;
};
struct headless_head {
@@ -67,6 +73,11 @@ struct headless_output {
pixman_image_t *image;
};
+static const uint32_t headless_formats[] = {
+ DRM_FORMAT_XRGB8888,
+ DRM_FORMAT_ARGB8888,
+};
+
static inline struct headless_head *
to_headless_head(struct weston_head *base)
{
@@ -127,6 +138,15 @@ headless_output_repaint(struct weston_output *output_base,
}
static void
+headless_output_disable_gl(struct headless_output *output)
+{
+ struct weston_compositor *compositor = output->base.compositor;
+ struct headless_backend *b = to_headless_backend(compositor);
+
+ b->glri->output_destroy(&output->base);
+}
+
+static void
headless_output_disable_pixman(struct headless_output *output)
{
pixman_renderer_output_destroy(&output->base);
@@ -146,6 +166,9 @@ headless_output_disable(struct weston_output *base)
wl_event_source_remove(output->finish_frame_timer);
switch (b->renderer_type) {
+ case HEADLESS_GL:
+ headless_output_disable_gl(output);
+ break;
case HEADLESS_PIXMAN:
headless_output_disable_pixman(output);
break;
@@ -168,6 +191,24 @@ headless_output_destroy(struct weston_output *base)
}
static int
+headless_output_enable_gl(struct headless_output *output)
+{
+ struct weston_compositor *compositor = output->base.compositor;
+ struct headless_backend *b = to_headless_backend(compositor);
+
+ if (b->glri->output_pbuffer_create(&output->base,
+ output->base.current_mode->width,
+ output->base.current_mode->height,
+ headless_formats,
+ ARRAY_LENGTH(headless_formats)) < 0) {
+ weston_log("failed to create gl renderer output state\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
headless_output_enable_pixman(struct headless_output *output)
{
output->image_buf = malloc(output->base.current_mode->width *
@@ -209,6 +250,9 @@ headless_output_enable(struct weston_output *base)
wl_event_loop_add_timer(loop, finish_frame_handler, output);
switch (b->renderer_type) {
+ case HEADLESS_GL:
+ ret = headless_output_enable_gl(output);
+ break;
case HEADLESS_PIXMAN:
ret = headless_output_enable_pixman(output);
break;
@@ -339,6 +383,25 @@ headless_destroy(struct weston_compositor *ec)
free(b);
}
+static int
+headless_gl_renderer_init(struct headless_backend *b)
+{
+ b->glri = weston_load_module("gl-renderer.so", "gl_renderer_interface");
+ if (!b->glri)
+ return -1;
+
+ if (b->glri->display_create(b->compositor,
+ EGL_PLATFORM_SURFACELESS_MESA,
+ EGL_DEFAULT_DISPLAY,
+ EGL_PBUFFER_BIT,
+ headless_formats,
+ ARRAY_LENGTH(headless_formats)) < 0) {
+ return -1;
+ }
+
+ return 0;
+}
+
static const struct weston_windowed_output_api api = {
headless_output_set_size,
headless_head_create,
@@ -364,12 +427,22 @@ headless_backend_create(struct weston_compositor *compositor,
b->base.destroy = headless_destroy;
b->base.create_output = headless_output_create;
- if (config->use_pixman)
+ if (config->use_pixman && config->use_gl) {
+ weston_log("Error: cannot use both Pixman *and* GL renderers.\n");
+ goto err_free;
+ }
+
+ if (config->use_gl)
+ b->renderer_type = HEADLESS_GL;
+ else if (config->use_pixman)
b->renderer_type = HEADLESS_PIXMAN;
else
b->renderer_type = HEADLESS_NOOP;
switch (b->renderer_type) {
+ case HEADLESS_GL:
+ ret = headless_gl_renderer_init(b);
+ break;
case HEADLESS_PIXMAN:
ret = pixman_renderer_init(compositor);
break;
@@ -381,6 +454,13 @@ headless_backend_create(struct weston_compositor *compositor,
if (ret < 0)
goto err_input;
+ if (compositor->renderer->import_dmabuf) {
+ if (linux_dmabuf_setup(compositor) < 0) {
+ weston_log("Error: dmabuf protocol setup failed.\n");
+ goto err_input;
+ }
+ }
+
/* Support zwp_linux_explicit_synchronization_unstable_v1 to enable
* testing. */
if (linux_explicit_synchronization_setup(compositor) < 0)
diff --git a/libweston/renderer-gl/gl-renderer.c b/libweston/renderer-gl/gl-renderer.c
index cc77a345..fa472e03 100644
--- a/libweston/renderer-gl/gl-renderer.c
+++ b/libweston/renderer-gl/gl-renderer.c
@@ -3142,6 +3142,48 @@ gl_renderer_output_window_create(struct weston_output *output,
return ret;
}
+static int
+gl_renderer_output_pbuffer_create(struct weston_output *output,
+ int width,
+ int height,
+ const uint32_t *drm_formats,
+ unsigned drm_formats_count)
+{
+ struct gl_renderer *gr = get_renderer(output->compositor);
+ EGLConfig pbuffer_config;
+ EGLSurface egl_surface;
+ int ret;
+ EGLint pbuffer_attribs[] = {
+ EGL_WIDTH, width,
+ EGL_HEIGHT, height,
+ EGL_NONE
+ };
+
+ pbuffer_config = gl_renderer_get_egl_config(gr, EGL_PBUFFER_BIT,
+ drm_formats,
+ drm_formats_count);
+ if (pbuffer_config == EGL_NO_CONFIG_KHR) {
+ weston_log("failed to choose EGL config for PbufferSurface\n");
+ return -1;
+ }
+
+ log_egl_config_info(gr->egl_display, pbuffer_config);
+
+ egl_surface = eglCreatePbufferSurface(gr->egl_display, pbuffer_config,
+ pbuffer_attribs);
+ if (egl_surface == EGL_NO_SURFACE) {
+ weston_log("failed to create egl surface\n");
+ gl_renderer_print_egl_error_state();
+ return -1;
+ }
+
+ ret = gl_renderer_output_create(output, egl_surface);
+ if (ret < 0)
+ eglDestroySurface(gr->egl_display, egl_surface);
+
+ return ret;
+}
+
static void
gl_renderer_output_destroy(struct weston_output *output)
{
@@ -3728,6 +3770,7 @@ gl_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface)
WL_EXPORT struct gl_renderer_interface gl_renderer_interface = {
.display_create = gl_renderer_display_create,
.output_window_create = gl_renderer_output_window_create,
+ .output_pbuffer_create = gl_renderer_output_pbuffer_create,
.output_destroy = gl_renderer_output_destroy,
.output_set_border = gl_renderer_output_set_border,
.create_fence_fd = gl_renderer_create_fence_fd,
diff --git a/libweston/renderer-gl/gl-renderer.h b/libweston/renderer-gl/gl-renderer.h
index 9aac993a..2bca2d00 100644
--- a/libweston/renderer-gl/gl-renderer.h
+++ b/libweston/renderer-gl/gl-renderer.h
@@ -135,6 +135,33 @@ struct gl_renderer_interface {
const uint32_t *drm_formats,
unsigned drm_formats_count);
+ /**
+ * Attach GL-renderer to the output with internal pixel storage
+ *
+ * \param output The output to create a rendering surface for.
+ * \param width Width of the rendering surface in pixels.
+ * \param height Height of the rendering surface in pixels.
+ * \param drm_formats Array of DRM pixel formats that are acceptable.
+ * \param drm_formats_count The drm_formats array length.
+ * \return 0 on success, -1 on failure.
+ *
+ * This function creates the renderer data structures needed to repaint
+ * the output. The repaint results will be kept internal and can only
+ * be accessed through e.g. screen capture.
+ *
+ * The first format in drm_formats that matches any EGLConfig
+ * determines which EGLConfig is chosen. See \c display_create about
+ * how the matching works and the possible limitations.
+ *
+ * This function should be used only if \c display_create was called
+ * with \c EGL_PBUFFER_BIT in \c egl_surface_type.
+ */
+ int (*output_pbuffer_create)(struct weston_output *output,
+ int width,
+ int height,
+ const uint32_t *drm_formats,
+ unsigned drm_formats_count);
+
void (*output_destroy)(struct weston_output *output);
/* Sets the output border.