diff options
author | Pekka Paalanen <pekka.paalanen@collabora.com> | 2019-09-20 14:23:12 +0300 |
---|---|---|
committer | Pekka Paalanen <pq@iki.fi> | 2019-10-11 12:16:35 +0000 |
commit | 5104d7b2afd4980da71370c27b7f79a441759f30 (patch) | |
tree | cbe75d129173dcf8ef3a1dd473506ea6e8dfd65f /libweston | |
parent | 209187491b7a52b8ae735db69499aff2b03cec75 (diff) | |
download | weston-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.c | 82 | ||||
-rw-r--r-- | libweston/renderer-gl/gl-renderer.c | 43 | ||||
-rw-r--r-- | libweston/renderer-gl/gl-renderer.h | 27 |
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. |