weston: add egl patches

Closes: #6218 [via git-merge-pr]
This commit is contained in:
Sir_Boops 2017-04-19 13:58:43 -06:00 committed by Michael Aldridge
parent 35c2c81667
commit 1146fc49bb
9 changed files with 1896 additions and 1 deletions

View file

@ -0,0 +1,156 @@
From d178c1add79d48cd639bf5c387067c0e4d5fae09 Mon Sep 17 00:00:00 2001
From: "Miguel A. Vico" <mvicomoya@nvidia.com>
Date: Mon, 2 May 2016 15:56:37 +0200
Subject: [PATCH 1/7] gl-renderer: Add EGLDevice enumeration support
X-NVConfidentiality: public
EGLDevice provides means to enumerate native devices.
In preparation for follow-on changes to support frame presentation
through EGLDevice+EGLOutput, this change adds both
gl_renderer_get_devices() and gl_renderer_get_drm_device_file()
functions which will help to enumerate EGLDevices and match them to DRM
devices.
Signed-off-by: Miguel A Vico Moya <mvicomoya@nvidia.com>
Reviewed-by: Andy Ritger <aritger@nvidia.com>
Reviewed-by: Adam Cheney <acheney@nvidia.com>
Reviewed-by: James Jones <jajones@nvidia.com>
---
libweston/gl-renderer.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++-
libweston/gl-renderer.h | 8 +++++
2 files changed, 96 insertions(+), 1 deletion(-)
diff --git a/libweston/gl-renderer.c b/libweston/gl-renderer.c
index c6091af0..7a840a35 100644
--- libweston/gl-renderer.c
+++ libweston/gl-renderer.c
@@ -3357,6 +3357,90 @@ gl_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface)
return 0;
}
+static int
+gl_renderer_get_devices(EGLint max_devices, EGLDeviceEXT *devices,
+ EGLint *num_devices)
+{
+ const char *extensions;
+ PFNEGLQUERYDEVICESEXTPROC query_devices;
+
+ extensions = (const char *)eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
+ if (!extensions) {
+ weston_log("Retrieving EGL extension string failed.\n");
+ return -1;
+ }
+
+ if (!weston_check_egl_extension(extensions, "EGL_EXT_device_base") &&
+ (!weston_check_egl_extension(extensions, "EGL_EXT_device_query") ||
+ !weston_check_egl_extension(extensions, "EGL_EXT_device_enumeration"))) {
+ weston_log("EGL_EXT_device_base not supported\n");
+ return -1;
+ }
+
+ query_devices = (void *) eglGetProcAddress("eglQueryDevicesEXT");
+ if (!query_devices) {
+ weston_log("Failed to get eglQueryDevicesEXT function\n");
+ return -1;
+ }
+
+ if (query_devices(max_devices, devices, num_devices) != EGL_TRUE) {
+ weston_log("Failed to query EGL Devices\n");
+ gl_renderer_print_egl_error_state();
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+gl_renderer_get_drm_device_file(EGLDeviceEXT device,
+ const char **drm_device_file)
+{
+ const char *exts;
+ PFNEGLQUERYDEVICESTRINGEXTPROC query_device_string;
+
+ exts = (const char *)eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
+ if (!exts) {
+ weston_log("Retrieving EGL extension string failed.\n");
+ return -1;
+ }
+
+ if (!weston_check_egl_extension(exts, "EGL_EXT_device_base") &&
+ (!weston_check_egl_extension(exts, "EGL_EXT_device_query") ||
+ !weston_check_egl_extension(exts, "EGL_EXT_device_enumeration"))) {
+ weston_log("EGL_EXT_device_base not supported.\n");
+ return -1;
+ }
+
+ query_device_string =
+ (void *) eglGetProcAddress("eglQueryDeviceStringEXT");
+ if (!query_device_string) {
+ weston_log("Failed to get eglQueryDeviceStringEXT function\n");
+ return -1;
+ }
+
+ exts = query_device_string(device, EGL_EXTENSIONS);
+ if (!exts) {
+ weston_log("Retrieving EGL extension string failed.\n");
+ return -1;
+ }
+
+ if (!weston_check_egl_extension(exts, "EGL_EXT_device_drm")) {
+ weston_log("EGL_EXT_device_drm not supported.\n");
+ return -1;
+ }
+
+ (*drm_device_file) = query_device_string(device,
+ EGL_DRM_DEVICE_FILE_EXT);
+ if (*drm_device_file == NULL) {
+ weston_log("Failed to query DRM device name.\n");
+ gl_renderer_print_egl_error_state();
+ return -1;
+ }
+
+ return 0;
+}
+
WL_EXPORT struct gl_renderer_interface gl_renderer_interface = {
.opaque_attribs = gl_renderer_opaque_attribs,
.alpha_attribs = gl_renderer_alpha_attribs,
@@ -3367,5 +3451,8 @@ WL_EXPORT struct gl_renderer_interface gl_renderer_interface = {
.output_destroy = gl_renderer_output_destroy,
.output_surface = gl_renderer_output_surface,
.output_set_border = gl_renderer_output_set_border,
- .print_egl_error_state = gl_renderer_print_egl_error_state
+ .print_egl_error_state = gl_renderer_print_egl_error_state,
+
+ .get_devices = gl_renderer_get_devices,
+ .get_drm_device_file = gl_renderer_get_drm_device_file
};
diff --git a/libweston/gl-renderer.h b/libweston/gl-renderer.h
index b47ea07f..9ff4e21e 100644
--- libweston/gl-renderer.h
+++ libweston/gl-renderer.h
@@ -38,6 +38,7 @@
typedef int EGLint;
typedef int EGLenum;
+typedef void *EGLDeviceEXT;
typedef void *EGLDisplay;
typedef void *EGLSurface;
typedef void *EGLConfig;
@@ -114,5 +115,12 @@ struct gl_renderer_interface {
int32_t tex_width, unsigned char *data);
void (*print_egl_error_state)(void);
+
+ int (*get_devices)(EGLint max_devices,
+ EGLDeviceEXT *devices,
+ EGLint *num_devices);
+
+ int (*get_drm_device_file)(EGLDeviceEXT device,
+ const char **drm_device_file);
};
--
2.11.1

View file

@ -0,0 +1,522 @@
From b67b64f6c7565a88558f1398895830394b887ee3 Mon Sep 17 00:00:00 2001
From: "Miguel A. Vico" <mvicomoya@nvidia.com>
Date: Mon, 2 May 2016 16:34:01 +0200
Subject: [PATCH 2/7] gl-renderer: Add support for EGLDevice composited frame
presentation
X-NVConfidentiality: public
EGLDevice provides means to enumerate native devices, and then create
an EGL display connection from them.
Similarly, EGLOutput will provide means to access different
portions of display control hardware associated with an EGLDevice.
For instance, EGLOutputLayer represents a portion of display
control hardware that accepts an image as input and processes it
for presentation on a display device.
EGLStream implements a mechanism to communicate frame producers and
frame consumers. By attaching an EGLOutputLayer consumer to a stream,
a producer will be able to present frames on a display device.
Thus, a compositor could produce frames and feed them to an
EGLOutputLayer through an EGLStream for presentation on a display
device.
This change adds required logic to support presentation approach
described above.
Note that some unpublished EGL extensions were needed:
- EGL_NV_stream_attrib:
https://github.com/aritger/eglstreams-kms-example/blob/master/proposed-extensions/EGL_NV_stream_attrib.txt
- EGL_EXT_stream_acquire_mode:
https://github.com/aritger/eglstreams-kms-example/blob/master/proposed-extensions/EGL_EXT_stream_acquire_mode.txt
- EGL_NV_output_drm_flip_event:
https://github.com/aritger/eglstreams-kms-example/blob/master/proposed-extensions/EGL_NV_output_drm_flip_event.txt
Signed-off-by: Miguel A Vico Moya <mvicomoya@nvidia.com>
Reviewed-by: Andy Ritger <aritger@nvidia.com>
Reviewed-by: Adam Cheney <acheney@nvidia.com>
Reviewed-by: James Jones <jajones@nvidia.com>
---
libweston/gl-renderer.c | 262 +++++++++++++++++++++++++++++++++++++++++++++++-
libweston/gl-renderer.h | 16 +++
shared/weston-egl-ext.h | 40 ++++++++
3 files changed, 315 insertions(+), 3 deletions(-)
diff --git a/libweston/gl-renderer.c b/libweston/gl-renderer.c
index 7a840a35..498a14bd 100644
--- libweston/gl-renderer.c
+++ libweston/gl-renderer.c
@@ -86,6 +86,8 @@ struct gl_output_state {
struct gl_border_image borders[4];
enum gl_border_status border_status;
+ EGLStreamKHR egl_stream;
+
struct weston_matrix output_matrix;
};
@@ -209,6 +211,28 @@ struct gl_renderer {
int has_surfaceless_context;
+ PFNEGLGETOUTPUTLAYERSEXTPROC get_output_layers;
+ PFNEGLQUERYOUTPUTLAYERATTRIBEXTPROC query_output_layer_attrib;
+ int has_egl_output_base;
+ int has_egl_output_drm;
+ int has_egl_output_drm_flip_event;
+
+ PFNEGLCREATESTREAMKHRPROC create_stream;
+ PFNEGLDESTROYSTREAMKHRPROC destroy_stream;
+ int has_egl_stream;
+
+ PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC create_stream_producer_surface;
+ int has_egl_stream_producer_eglsurface;
+
+ PFNEGLSTREAMCONSUMEROUTPUTEXTPROC stream_consumer_output;
+ int has_egl_stream_consumer_egloutput;
+
+#ifdef EGL_NV_stream_attrib
+ PFNEGLSTREAMCONSUMERACQUIREATTRIBNVPROC stream_consumer_acquire_attrib;
+#endif
+ int has_egl_stream_attrib;
+ int has_egl_stream_acquire_mode;
+
int has_dmabuf_import;
struct wl_list dmabuf_images;
@@ -1196,6 +1220,38 @@ gl_renderer_repaint_output(struct weston_output *output,
}
static int
+gl_renderer_output_stream_flip(struct weston_output *output,
+ void *flip_data)
+{
+#if defined(EGL_NV_stream_attrib) && defined(EGL_EXT_stream_acquire_mode)
+ struct gl_output_state *go = get_output_state(output);
+ struct weston_compositor *compositor = output->compositor;
+ struct gl_renderer *gr = get_renderer(compositor);
+
+ EGLAttrib acquire_attribs[3] = { EGL_NONE };
+
+#ifdef EGL_NV_output_drm_flip_event
+ if (gr->has_egl_output_drm_flip_event) {
+ acquire_attribs[0] = EGL_DRM_FLIP_EVENT_DATA_NV;
+ acquire_attribs[1] = (EGLAttrib)flip_data;
+ acquire_attribs[2] = EGL_NONE;
+ }
+#endif
+
+ if (go->egl_stream != EGL_NO_STREAM_KHR)
+ if (gr->stream_consumer_acquire_attrib(
+ gr->egl_display,
+ go->egl_stream,
+ acquire_attribs) != EGL_TRUE)
+ return -1;
+
+ return 0;
+#else
+ return -1;
+#endif
+}
+
+static int
gl_renderer_read_pixels(struct weston_output *output,
pixman_format_code_t format, void *pixels,
uint32_t x, uint32_t y,
@@ -2699,9 +2755,93 @@ gl_renderer_create_window_surface(struct gl_renderer *gr,
return egl_surface;
}
+static EGLSurface
+gl_renderer_create_stream_surface(struct gl_renderer *gr,
+ uint32_t plane_id,
+ uint32_t crtc_id,
+ EGLint width, EGLint height,
+ EGLStreamKHR *egl_stream)
+{
+ EGLint stream_attribs[] = {
+ EGL_STREAM_FIFO_LENGTH_KHR, 1,
+#ifdef EGL_EXT_stream_acquire_mode
+ EGL_CONSUMER_AUTO_ACQUIRE_EXT, EGL_FALSE,
+#endif
+ EGL_NONE
+ };
+ EGLAttrib output_attribs[3];
+ EGLint stream_producer_attribs[] = {
+ EGL_WIDTH, width,
+ EGL_HEIGHT, height,
+ EGL_NONE
+ };
+
+ EGLint num_layers;
+ EGLOutputLayerEXT output_layer;
+ EGLSurface egl_surface = EGL_NO_SURFACE;
+
+ *egl_stream = gr->create_stream(gr->egl_display, stream_attribs);
+
+ if (*egl_stream == EGL_NO_STREAM_KHR) {
+ weston_log("Failed to create EGL stream.\n");
+ goto err_egl_create_surf_base;
+ }
+
+ if (plane_id != ~0u) {
+ output_attribs[0] = EGL_DRM_PLANE_EXT;
+ output_attribs[1] = plane_id;
+ } else {
+ assert(crtc_id != ~0u);
+ output_attribs[0] = EGL_DRM_CRTC_EXT;
+ output_attribs[1] = crtc_id;
+ }
+ output_attribs[2] = EGL_NONE;
+
+ if (gr->get_output_layers(gr->egl_display,
+ output_attribs,
+ &output_layer,
+ 1, &num_layers) != EGL_TRUE) {
+ weston_log("Failed to get output layer.\n");
+ goto err_egl_create_surf_stream;
+ }
+
+ if (num_layers < 1) {
+ weston_log("Unable to find output layers.\n");
+ goto err_egl_create_surf_stream;
+ }
+
+ if (gr->stream_consumer_output(gr->egl_display, *egl_stream,
+ output_layer) != EGL_TRUE) {
+ weston_log("Failed to set EGL stream consumer.\n");
+ goto err_egl_create_surf_stream;
+ }
+
+ egl_surface = gr->create_stream_producer_surface(
+ gr->egl_display,
+ gr->egl_config,
+ *egl_stream,
+ stream_producer_attribs);
+
+ if (egl_surface == EGL_NO_SURFACE) {
+ weston_log("Failed to create EGL producer surface.\n");
+ goto err_egl_create_surf_stream;
+ }
+
+ return egl_surface;
+
+err_egl_create_surf_stream:
+ gr->destroy_stream(gr->egl_display, *egl_stream);
+ *egl_stream = EGL_NO_STREAM_KHR;
+
+err_egl_create_surf_base:
+ gl_renderer_print_egl_error_state();
+ return EGL_NO_SURFACE;
+}
+
static int
gl_renderer_output_create(struct weston_output *output,
- EGLSurface surface)
+ EGLSurface surface,
+ EGLStreamKHR stream)
{
struct gl_output_state *go;
int i;
@@ -2711,6 +2851,7 @@ gl_renderer_output_create(struct weston_output *output,
return -1;
go->egl_surface = surface;
+ go->egl_stream = stream;
for (i = 0; i < BUFFER_DAMAGE_COUNT; i++)
pixman_region32_init(&go->buffer_damage[i]);
@@ -2743,13 +2884,41 @@ gl_renderer_output_window_create(struct weston_output *output,
return -1;
}
- ret = gl_renderer_output_create(output, egl_surface);
+ ret = gl_renderer_output_create(output, egl_surface, EGL_NO_STREAM_KHR);
if (ret < 0)
weston_platform_destroy_egl_surface(gr->egl_display, egl_surface);
return ret;
}
+static int
+gl_renderer_output_stream_create(struct weston_output *output,
+ uint32_t plane_id, uint32_t crtc_id)
+{
+ struct weston_compositor *ec = output->compositor;
+ struct gl_renderer *gr = get_renderer(ec);
+ EGLSurface egl_surface = EGL_NO_SURFACE;
+ EGLStreamKHR egl_stream = EGL_NO_STREAM_KHR;
+ int ret;
+
+ egl_surface =
+ gl_renderer_create_stream_surface(gr,
+ plane_id, crtc_id,
+ output->current_mode->width,
+ output->current_mode->height,
+ &egl_stream);
+ if (egl_surface == EGL_NO_SURFACE)
+ return -1;
+
+ ret = gl_renderer_output_create(output, egl_surface, egl_stream);
+ if (ret < 0) {
+ eglDestroySurface(gr->egl_display, egl_surface);
+ gr->destroy_stream(gr->egl_display, egl_stream);
+ }
+
+ return ret;
+}
+
static void
gl_renderer_output_destroy(struct weston_output *output)
{
@@ -2766,6 +2935,9 @@ gl_renderer_output_destroy(struct weston_output *output)
weston_platform_destroy_egl_surface(gr->egl_display, go->egl_surface);
+ if (go->egl_stream != EGL_NO_STREAM_KHR)
+ gr->destroy_stream(gr->egl_display, go->egl_stream);
+
free(go);
}
@@ -2861,6 +3033,19 @@ gl_renderer_setup_egl_extensions(struct weston_compositor *ec)
(void *) eglGetProcAddress("eglUnbindWaylandDisplayWL");
gr->query_buffer =
(void *) eglGetProcAddress("eglQueryWaylandBufferWL");
+ gr->get_output_layers = (void *) eglGetProcAddress("eglGetOutputLayersEXT");
+ gr->query_output_layer_attrib =
+ (void *) eglGetProcAddress("eglQueryOutputLayerAttribEXT");
+ gr->create_stream = (void *) eglGetProcAddress("eglCreateStreamKHR");
+ gr->destroy_stream = (void *) eglGetProcAddress("eglDestroyStreamKHR");
+ gr->create_stream_producer_surface =
+ (void *) eglGetProcAddress("eglCreateStreamProducerSurfaceKHR");
+ gr->stream_consumer_output =
+ (void *) eglGetProcAddress("eglStreamConsumerOutputEXT");
+#ifdef EGL_NV_stream_attrib
+ gr->stream_consumer_acquire_attrib =
+ (void *) eglGetProcAddress("eglStreamConsumerAcquireAttribNV");
+#endif
extensions =
(const char *) eglQueryString(gr->egl_display, EGL_EXTENSIONS);
@@ -2911,6 +3096,30 @@ gl_renderer_setup_egl_extensions(struct weston_compositor *ec)
if (weston_check_egl_extension(extensions, "GL_EXT_texture_rg"))
gr->has_gl_texture_rg = 1;
+ if (weston_check_egl_extension(extensions, "EGL_EXT_output_base"))
+ gr->has_egl_output_base = 1;
+
+ if (weston_check_egl_extension(extensions, "EGL_EXT_output_drm"))
+ gr->has_egl_output_drm = 1;
+
+ if (weston_check_egl_extension(extensions, "EGL_NV_output_drm_flip_event"))
+ gr->has_egl_output_drm_flip_event = 1;
+
+ if (weston_check_egl_extension(extensions, "EGL_KHR_stream"))
+ gr->has_egl_stream = 1;
+
+ if (weston_check_egl_extension(extensions, "EGL_KHR_stream_producer_eglsurface"))
+ gr->has_egl_stream_producer_eglsurface = 1;
+
+ if (weston_check_egl_extension(extensions, "EGL_EXT_stream_consumer_egloutput"))
+ gr->has_egl_stream_consumer_egloutput = 1;
+
+ if (weston_check_egl_extension(extensions, "EGL_NV_stream_attrib"))
+ gr->has_egl_stream_attrib = 1;
+
+ if (weston_check_egl_extension(extensions, "EGL_EXT_stream_acquire_mode"))
+ gr->has_egl_stream_acquire_mode = 1;
+
renderer_setup_egl_client_extensions(gr);
return 0;
@@ -2936,6 +3145,15 @@ static const EGLint gl_renderer_alpha_attribs[] = {
EGL_NONE
};
+static const EGLint gl_renderer_opaque_stream_attribs[] = {
+ EGL_SURFACE_TYPE, EGL_STREAM_BIT_KHR,
+ EGL_RED_SIZE, 1,
+ EGL_GREEN_SIZE, 1,
+ EGL_BLUE_SIZE, 1,
+ EGL_ALPHA_SIZE, 0,
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL_NONE
+};
/** Checks whether a platform EGL client extension is supported
*
@@ -3009,6 +3227,8 @@ platform_to_extension(EGLenum platform)
return "wayland";
case EGL_PLATFORM_X11_KHR:
return "x11";
+ case EGL_PLATFORM_DEVICE_EXT:
+ return "device";
default:
assert(0 && "bad EGL platform enum");
}
@@ -3145,6 +3365,38 @@ gl_renderer_display_create(struct weston_compositor *ec, EGLenum platform,
if (gl_renderer_setup_egl_extensions(ec) < 0)
goto fail_with_error;
+ if (platform == EGL_PLATFORM_DEVICE_EXT) {
+ if (!gr->has_egl_output_base ||
+ !gr->has_egl_output_drm ||
+ !gr->has_egl_stream ||
+ !gr->has_egl_stream_producer_eglsurface ||
+ !gr->has_egl_stream_consumer_egloutput ||
+ !gr->has_egl_stream_attrib ||
+ !gr->has_egl_stream_acquire_mode) {
+ weston_log("following required extensions not "
+ "supported:\n%s%s%s%s%s%s%s",
+ (gr->has_egl_output_base ? "" :
+ " EGL_EXT_output_base\n"),
+ (gr->has_egl_output_drm ? "" :
+ " EGL_EXT_output_drm\n"),
+ (gr->has_egl_stream ? "" :
+ " EGL_KHR_stream\n"),
+ (gr->has_egl_stream_producer_eglsurface ? "" :
+ " EGL_KHR_stream_producer_eglsurface\n"),
+ (gr->has_egl_stream_consumer_egloutput ? "" :
+ " EGL_EXT_stream_consumer_egloutput\n"),
+ (gr->has_egl_stream_attrib ? "" :
+ " EGL_NV_stream_attrib\n"),
+ (gr->has_egl_stream_acquire_mode ? "" :
+ " EGL_EXT_stream_acquire_mode\n"));
+ goto fail_terminate;
+ }
+
+ if (!gr->has_egl_output_drm_flip_event)
+ weston_log("warning: EGL page flip event notification "
+ "not supported\n");
+ }
+
wl_list_init(&gr->dmabuf_images);
if (gr->has_dmabuf_import)
gr->base.import_dmabuf = gl_renderer_import_dmabuf;
@@ -3444,15 +3696,19 @@ gl_renderer_get_drm_device_file(EGLDeviceEXT device,
WL_EXPORT struct gl_renderer_interface gl_renderer_interface = {
.opaque_attribs = gl_renderer_opaque_attribs,
.alpha_attribs = gl_renderer_alpha_attribs,
+ .opaque_stream_attribs = gl_renderer_opaque_stream_attribs,
.display_create = gl_renderer_display_create,
.display = gl_renderer_display,
.output_window_create = gl_renderer_output_window_create,
+ .output_stream_create = gl_renderer_output_stream_create,
.output_destroy = gl_renderer_output_destroy,
.output_surface = gl_renderer_output_surface,
.output_set_border = gl_renderer_output_set_border,
.print_egl_error_state = gl_renderer_print_egl_error_state,
.get_devices = gl_renderer_get_devices,
- .get_drm_device_file = gl_renderer_get_drm_device_file
+ .get_drm_device_file = gl_renderer_get_drm_device_file,
+
+ .output_stream_flip = gl_renderer_output_stream_flip
};
diff --git a/libweston/gl-renderer.h b/libweston/gl-renderer.h
index 9ff4e21e..39ea3b42 100644
--- libweston/gl-renderer.h
+++ libweston/gl-renderer.h
@@ -60,6 +60,7 @@ enum gl_renderer_border_side {
struct gl_renderer_interface {
const EGLint *opaque_attribs;
const EGLint *alpha_attribs;
+ const EGLint *opaque_stream_attribs;
int (*display_create)(struct weston_compositor *ec,
EGLenum platform,
@@ -78,6 +79,9 @@ struct gl_renderer_interface {
const EGLint *visual_id,
const int n_ids);
+ int (*output_stream_create)(struct weston_output *output,
+ uint32_t plane_id, uint32_t crtc_id);
+
void (*output_destroy)(struct weston_output *output);
EGLSurface (*output_surface)(struct weston_output *output);
@@ -122,5 +126,17 @@ struct gl_renderer_interface {
int (*get_drm_device_file)(EGLDeviceEXT device,
const char **drm_device_file);
+
+ /*
+ * output_stream_flip() makes the EGLOutput consumer attached to the
+ * corresponding <output> stream acquire the new available frame
+ * (repaint_output() has been called previously) and queue a page flip.
+ * Whenever DRM is the underlying API and EGL_NV_output_drm_flip_event
+ * is supported, page flip notification can be requested by passing a
+ * non-NULL <flip_data> pointer. Otherwise, compositors should rely on a
+ * different mechanism in order to re-schedule output repaints.
+ */
+ int (*output_stream_flip)(struct weston_output *output,
+ void *flip_data);
};
diff --git a/shared/weston-egl-ext.h b/shared/weston-egl-ext.h
index f3e6dcea..1c3fec1c 100644
--- shared/weston-egl-ext.h
+++ shared/weston-egl-ext.h
@@ -158,12 +158,52 @@ typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPLATFORMPIXMAPSURFACEEXTPROC) (EGLD
#define EGL_PLATFORM_X11_KHR 0x31D5
#endif
+#ifndef EGL_PLATFORM_DEVICE_EXT
+#define EGL_PLATFORM_DEVICE_EXT 0x313F
+#endif
+
+/*
+ * FIXME: Remove both EGL_EXT_stream_acquire_mode and
+ * EGL_NV_output_drm_flip_event definitions below once both extensions
+ * get published by Khronos and incorportated into Khronos' header files
+ */
+#ifndef EGL_NV_stream_attrib
+#define EGL_NV_stream_attrib 1
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLStreamKHR EGLAPIENTRY eglCreateStreamAttribNV(EGLDisplay dpy, const EGLAttrib *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglSetStreamAttribNV(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLAttrib value);
+EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamAttribNV(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLAttrib *value);
+EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerAcquireAttribNV(EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerReleaseAttribNV(EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list);
+#endif
+typedef EGLStreamKHR (EGLAPIENTRYP PFNEGLCREATESTREAMATTRIBNVPROC) (EGLDisplay dpy, const EGLAttrib *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSETSTREAMATTRIBNVPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLAttrib value);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMATTRIBNVPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLAttrib *value);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERACQUIREATTRIBNVPROC) (EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list);
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERRELEASEATTRIBNVPROC) (EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list);
+#endif /* EGL_NV_stream_attrib */
+
+#ifndef EGL_EXT_stream_acquire_mode
+#define EGL_EXT_stream_acquire_mode 1
+#define EGL_CONSUMER_AUTO_ACQUIRE_EXT 0x332B
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERACQUIREATTRIBEXTPROC) (EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list);
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerAcquireAttribEXT (EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list);
+#endif
+#endif /* EGL_EXT_stream_acquire_mode */
+
+#ifndef EGL_NV_output_drm_flip_event
+#define EGL_NV_output_drm_flip_event 1
+#define EGL_DRM_FLIP_EVENT_DATA_NV 0x333E
+#endif /* EGL_NV_output_drm_flip_event */
+
#else /* ENABLE_EGL */
/* EGL platform definition are keept to allow compositor-xx.c to build */
#define EGL_PLATFORM_GBM_KHR 0x31D7
#define EGL_PLATFORM_WAYLAND_KHR 0x31D8
#define EGL_PLATFORM_X11_KHR 0x31D5
+#define EGL_PLATFORM_DEVICE_EXT 0x313F
#endif /* ENABLE_EGL */
--
2.11.1

View file

@ -0,0 +1,326 @@
From aa3aee0503249a0d667dba1001b292b3907fad18 Mon Sep 17 00:00:00 2001
From: "Miguel A. Vico" <mvicomoya@nvidia.com>
Date: Mon, 2 May 2016 18:22:47 +0200
Subject: [PATCH 3/7] gl-renderer: Add EGL client support for EGLStream frame
presentation
X-NVConfidentiality: public
By attaching a GLTexture consumer to a stream, a producer (wayland EGL
client) could feed frames to a texture, which in turn can be used by a
compositor to prepare the final frame to be presented.
This change adds required logic to support presentation approach
described above.
Note that some unpublished EGL extensions were needed:
- EGL_NV_stream_attrib:
https://github.com/aritger/eglstreams-kms-example/blob/master/proposed-extensions/EGL_NV_stream_attrib.txt
- EGL_WL_wayland_eglstream:
https://github.com/aritger/eglstreams-kms-example/blob/master/proposed-extensions/EGL_WL_wayland_eglstream.txt
Signed-off-by: Miguel A Vico Moya <mvicomoya@nvidia.com>
Reviewed-by: Adam Cheney <acheney@nvidia.com>
Reviewed-by: James Jones <jajones@nvidia.com>
---
libweston/gl-renderer.c | 183 +++++++++++++++++++++++++++++++++++++++++++++++-
shared/weston-egl-ext.h | 5 ++
2 files changed, 187 insertions(+), 1 deletion(-)
diff --git a/libweston/gl-renderer.c b/libweston/gl-renderer.c
index 498a14bd..6bcfe40f 100644
--- libweston/gl-renderer.c
+++ libweston/gl-renderer.c
@@ -168,6 +168,9 @@ struct gl_surface_state {
int hsub[3]; /* horizontal subsampling per plane */
int vsub[3]; /* vertical subsampling per plane */
+ EGLStreamKHR egl_stream;
+ bool new_stream;
+
struct weston_surface *surface;
struct wl_listener surface_destroy_listener;
@@ -219,6 +222,7 @@ struct gl_renderer {
PFNEGLCREATESTREAMKHRPROC create_stream;
PFNEGLDESTROYSTREAMKHRPROC destroy_stream;
+ PFNEGLQUERYSTREAMKHRPROC query_stream;
int has_egl_stream;
PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC create_stream_producer_surface;
@@ -228,11 +232,16 @@ struct gl_renderer {
int has_egl_stream_consumer_egloutput;
#ifdef EGL_NV_stream_attrib
+ PFNEGLCREATESTREAMATTRIBNVPROC create_stream_attrib;
PFNEGLSTREAMCONSUMERACQUIREATTRIBNVPROC stream_consumer_acquire_attrib;
#endif
int has_egl_stream_attrib;
int has_egl_stream_acquire_mode;
+ PFNEGLSTREAMCONSUMERGLTEXTUREEXTERNALKHRPROC stream_consumer_gltexture;
+ int has_egl_stream_consumer_gltexture;
+ int has_egl_wayland_eglstream;
+
int has_dmabuf_import;
struct wl_list dmabuf_images;
@@ -2050,6 +2059,145 @@ gl_renderer_attach_dmabuf(struct weston_surface *surface,
gs->y_inverted = buffer->y_inverted;
}
+/*
+ * gl_renderer_attach_stream_texture
+ *
+ * Try to bind given <buffer> to an EGLStream. If the given buffer was already
+ * bound, it will acquire next frame on the stream.
+ *
+ * Return true if the given <buffer> corresponds to an EGLStream; otherwise,
+ * return false (if might be another kind of buffer).
+ */
+static bool
+gl_renderer_attach_stream_texture(struct weston_surface *es,
+ struct weston_buffer *buffer)
+{
+#ifdef EGL_NV_stream_attrib
+ struct weston_compositor *ec = es->compositor;
+ struct gl_renderer *gr = get_renderer(ec);
+ struct gl_surface_state *gs = get_surface_state(es);
+ EGLStreamKHR stream = EGL_NO_STREAM_KHR;
+ EGLAttrib stream_attribs[] = {
+#ifdef EGL_WL_wayland_eglstream
+ EGL_WAYLAND_EGLSTREAM_WL, (EGLAttrib)buffer->resource,
+#endif
+ EGL_NONE
+ };
+ EGLint stream_state = EGL_STREAM_STATE_EMPTY_KHR;
+
+ /* Check for required extensions. If they arent supported, there's no
+ * way the given buffer corresponds to an EGLStream */
+ if (!gr->has_egl_stream_attrib ||
+ !gr->has_egl_stream_consumer_gltexture ||
+ !gr->has_egl_wayland_eglstream)
+ return false;
+
+ stream = gr->create_stream_attrib(gr->egl_display, stream_attribs);
+ if (stream == EGL_NO_STREAM_KHR) {
+ EGLint err = eglGetError();
+
+ switch (err) {
+ case EGL_BAD_ACCESS:
+ /* EGL_BAD_ACCESS is generated whenever buffer->resource
+ * does not corresponds to a stream */
+ return false;
+
+ case EGL_BAD_STREAM_KHR:
+ /* EGL_BAD_STREAM_KHR is generated whenever
+ * buffer->resource corresponds to a previously created
+ * stream so we must have a valid stream handle already
+ * we can use to acquire next frame */
+ break;
+
+ default:
+ /* An unknown error was generated */
+ assert(0);
+ return false;
+ }
+ } else {
+ /* Clean up current stream resources if needed */
+ if (gs->egl_stream != EGL_NO_STREAM_KHR)
+ gr->destroy_stream(gr->egl_display, gs->egl_stream);
+
+ gs->egl_stream = stream;
+ gs->shader = &gr->texture_shader_egl_external;
+ gs->target = GL_TEXTURE_EXTERNAL_OES;
+
+ glActiveTexture(GL_TEXTURE0);
+ ensure_textures(gs, 2);
+ glBindTexture(gs->target, gs->textures[1]);
+
+ gs->new_stream = (gr->stream_consumer_gltexture(
+ gr->egl_display,
+ gs->egl_stream) == EGL_TRUE);
+
+ if (!gs->new_stream) {
+ weston_log("failed to set stream consumer\n");
+ gl_renderer_print_egl_error_state();
+ gr->destroy_stream(gr->egl_display, gs->egl_stream);
+ gs->egl_stream = EGL_NO_STREAM_KHR;
+ return true; /* buffer->resource is EGLStream */
+ }
+ }
+
+ /* At this point we should have a valid stream handle */
+ assert(gs->egl_stream != EGL_NO_STREAM_KHR);
+
+ /* Check whether there are new frames available */
+ if (gr->query_stream(gr->egl_display,
+ gs->egl_stream,
+ EGL_STREAM_STATE_KHR,
+ &stream_state) != EGL_TRUE) {
+ weston_log("failed to query stream state\n");
+ gl_renderer_print_egl_error_state();
+ return true; /* buffer->resource is EGLStream */
+ }
+
+ /* If no new frame available, re-use last one */
+ if (stream_state != EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR) {
+ /* Fake size of last frame */
+ buffer->width = gs->pitch;
+ buffer->height = gs->height;
+ return true; /* buffer->resource is EGLStream */
+ }
+
+ if (gr->stream_consumer_acquire_attrib(gr->egl_display,
+ gs->egl_stream,
+ NULL) != EGL_TRUE) {
+ weston_log("failed to acquire buffer\n");
+ gl_renderer_print_egl_error_state();
+ return true; /* buffer->resource is EGLStream */
+ }
+
+ /* Swap textures if new stream was created */
+ if (gs->new_stream) {
+ GLuint tmp = gs->textures[0];
+
+ gs->textures[0] = gs->textures[1];
+ gs->textures[1] = tmp;
+ gs->new_stream = false;
+ }
+
+ /* Update buffer and surface data */
+ buffer->legacy_buffer = (void *)buffer->resource;
+ gr->query_buffer(gr->egl_display, buffer->legacy_buffer,
+ EGL_WIDTH, &buffer->width);
+ gr->query_buffer(gr->egl_display, buffer->legacy_buffer,
+ EGL_HEIGHT, &buffer->height);
+ gr->query_buffer(gr->egl_display, buffer->legacy_buffer,
+ EGL_WAYLAND_Y_INVERTED_WL, &buffer->y_inverted);
+
+ gs->pitch = buffer->width;
+ gs->height = buffer->height;
+ gs->buffer_type = BUFFER_TYPE_EGL;
+ gs->y_inverted = buffer->y_inverted;
+
+ return true; /* buffer->resource is EGLStream */
+#else
+ return false;
+#endif
+}
+
static void
gl_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer)
{
@@ -2073,6 +2221,12 @@ gl_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer)
gs->num_textures = 0;
gs->buffer_type = BUFFER_TYPE_NULL;
gs->y_inverted = 1;
+
+ if (gs->egl_stream != EGL_NO_STREAM_KHR) {
+ gr->destroy_stream(gr->egl_display, gs->egl_stream);
+ gs->egl_stream = EGL_NO_STREAM_KHR;
+ }
+
return;
}
@@ -2086,7 +2240,7 @@ gl_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer)
gl_renderer_attach_egl(es, buffer, format);
else if ((dmabuf = linux_dmabuf_buffer_get(buffer->resource)))
gl_renderer_attach_dmabuf(es, buffer, dmabuf);
- else {
+ else if (!gl_renderer_attach_stream_texture(es, buffer)) {
weston_log("unhandled buffer type!\n");
weston_buffer_reference(&gs->buffer_ref, NULL);
gs->buffer_type = BUFFER_TYPE_NULL;
@@ -2274,6 +2428,10 @@ surface_state_destroy(struct gl_surface_state *gs, struct gl_renderer *gr)
weston_buffer_reference(&gs->buffer_ref, NULL);
pixman_region32_fini(&gs->texture_damage);
+
+ if (gs->egl_stream != EGL_NO_STREAM_KHR)
+ gr->destroy_stream(gr->egl_display, gs->egl_stream);
+
free(gs);
}
@@ -2324,6 +2482,8 @@ gl_renderer_create_surface(struct weston_surface *surface)
gs->surface = surface;
+ gs->egl_stream = EGL_NO_STREAM_KHR;
+
pixman_region32_init(&gs->texture_damage);
surface->renderer_state = gs;
@@ -3038,14 +3198,19 @@ gl_renderer_setup_egl_extensions(struct weston_compositor *ec)
(void *) eglGetProcAddress("eglQueryOutputLayerAttribEXT");
gr->create_stream = (void *) eglGetProcAddress("eglCreateStreamKHR");
gr->destroy_stream = (void *) eglGetProcAddress("eglDestroyStreamKHR");
+ gr->query_stream = (void *) eglGetProcAddress("eglQueryStreamKHR");
gr->create_stream_producer_surface =
(void *) eglGetProcAddress("eglCreateStreamProducerSurfaceKHR");
gr->stream_consumer_output =
(void *) eglGetProcAddress("eglStreamConsumerOutputEXT");
#ifdef EGL_NV_stream_attrib
+ gr->create_stream_attrib =
+ (void *) eglGetProcAddress("eglCreateStreamAttribNV");
gr->stream_consumer_acquire_attrib =
(void *) eglGetProcAddress("eglStreamConsumerAcquireAttribNV");
#endif
+ gr->stream_consumer_gltexture =
+ (void *) eglGetProcAddress("eglStreamConsumerGLTextureExternalKHR");
extensions =
(const char *) eglQueryString(gr->egl_display, EGL_EXTENSIONS);
@@ -3120,6 +3285,12 @@ gl_renderer_setup_egl_extensions(struct weston_compositor *ec)
if (weston_check_egl_extension(extensions, "EGL_EXT_stream_acquire_mode"))
gr->has_egl_stream_acquire_mode = 1;
+ if (weston_check_egl_extension(extensions, "EGL_KHR_stream_consumer_gltexture"))
+ gr->has_egl_stream_consumer_gltexture = 1;
+
+ if (weston_check_egl_extension(extensions, "EGL_WL_wayland_eglstream"))
+ gr->has_egl_wayland_eglstream = 1;
+
renderer_setup_egl_client_extensions(gr);
return 0;
@@ -3392,6 +3563,16 @@ gl_renderer_display_create(struct weston_compositor *ec, EGLenum platform,
goto fail_terminate;
}
+ if (!gr->has_egl_stream_consumer_gltexture ||
+ !gr->has_egl_wayland_eglstream)
+ weston_log("warning: following required extensions for "
+ "EGL client frame presentation through "
+ "EGLDevice not supported:\n%s%s",
+ (gr->has_egl_stream_consumer_gltexture ? "" :
+ " EGL_KHR_stream_consumer_gltexture\n"),
+ (gr->has_egl_wayland_eglstream ? "" :
+ " EGL_WL_wayland_eglstream\n"));
+
if (!gr->has_egl_output_drm_flip_event)
weston_log("warning: EGL page flip event notification "
"not supported\n");
diff --git a/shared/weston-egl-ext.h b/shared/weston-egl-ext.h
index 1c3fec1c..11e9ccc1 100644
--- shared/weston-egl-ext.h
+++ shared/weston-egl-ext.h
@@ -197,6 +197,11 @@ EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerAcquireAttribEXT (EGLDisplay dpy,
#define EGL_DRM_FLIP_EVENT_DATA_NV 0x333E
#endif /* EGL_NV_output_drm_flip_event */
+#ifndef EGL_WL_wayland_eglstream
+#define EGL_WL_wayland_eglstream 1
+#define EGL_WAYLAND_EGLSTREAM_WL 0x334B
+#endif /* EGL_WL_wayland_eglstream */
+
#else /* ENABLE_EGL */
/* EGL platform definition are keept to allow compositor-xx.c to build */
--
2.11.1

View file

@ -0,0 +1,86 @@
From d89c874ea121b6855c7bdf2e757fa13d0b04661f Mon Sep 17 00:00:00 2001
From: "Miguel A. Vico" <mvicomoya@nvidia.com>
Date: Tue, 1 Mar 2016 22:19:14 +0100
Subject: [PATCH 4/7] compositor-drm: Gracefully handle vblank and flip invalid
timestamps
X-NVConfidentiality: public
Instant query for vblank timestamp may always fail, resulting in
never scheduling a full repaint in drm_output_start_repaint_loop().
Additionally, timestamp provided in page_flip_handler() may also be
invalid.
This change makes both drm_output_start_repaint_loop() and
page_flip_handler() to schedule a full repaint in any of the
situations above.
Signed-off-by: Miguel A Vico Moya <mvicomoya@nvidia.com>
Reviewed-by: Andy Ritger <aritger@nvidia.com>
---
libweston/compositor-drm.c | 28 +++++++++++++++++++++++++---
1 file changed, 25 insertions(+), 3 deletions(-)
diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c
index 1d38f051..12c1b8b5 100644
--- libweston/compositor-drm.c
+++ libweston/compositor-drm.c
@@ -1,6 +1,7 @@
/*
* Copyright © 2008-2011 Kristian Høgsberg
* Copyright © 2011 Intel Corporation
+ * Copyright © 2016 NVIDIA Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@@ -825,8 +826,16 @@ drm_output_start_repaint_loop(struct weston_output *output_base)
vbl.request.type |= drm_waitvblank_pipe(output);
ret = drmWaitVBlank(backend->drm.fd, &vbl);
- /* Error ret or zero timestamp means failure to get valid timestamp */
- if ((ret == 0) && (vbl.reply.tval_sec > 0 || vbl.reply.tval_usec > 0)) {
+ if (ret) {
+ /* Immediate query failed. It may always fail so we'll never get
+ * a valid timestamp to update msc and call into finish frame.
+ * Hence, jump to finish frame here.
+ */
+ goto finish_frame;
+ }
+
+ /* Zero timestamp means failure to get valid timestamp */
+ if (vbl.reply.tval_sec > 0 || vbl.reply.tval_usec > 0) {
ts.tv_sec = vbl.reply.tval_sec;
ts.tv_nsec = vbl.reply.tval_usec * 1000;
@@ -847,7 +856,7 @@ drm_output_start_repaint_loop(struct weston_output *output_base)
}
}
- /* Immediate query didn't provide valid timestamp.
+ /* Immediate query succeeded, but didn't provide valid timestamp.
* Use pageflip fallback.
*/
fb_id = output->current->fb_id;
@@ -935,6 +944,19 @@ page_flip_handler(int fd, unsigned int frame,
else if (!output->vblank_pending) {
ts.tv_sec = sec;
ts.tv_nsec = usec * 1000;
+
+ /* Zero timestamp means failure to get valid timestamp, so
+ * immediately finish frame
+ *
+ * FIXME: Driver should never return an invalid page flip
+ * timestamp */
+ if (ts.tv_sec == 0 && ts.tv_nsec == 0) {
+ weston_compositor_read_presentation_clock(
+ output->base.compositor,
+ &ts);
+ flags = WP_PRESENTATION_FEEDBACK_INVALID;
+ }
+
weston_output_finish_frame(&output->base, &ts, flags);
/* We can't call this from frame_notify, because the output's
--
2.11.1

View file

@ -0,0 +1,542 @@
From b1db106d3c91c1b35a01573a455c5661a17a06ee Mon Sep 17 00:00:00 2001
From: "Miguel A. Vico" <mvicomoya@nvidia.com>
Date: Thu, 28 Jan 2016 19:37:10 +0100
Subject: [PATCH 5/7] compositor-drm: Add support for EGLDevice+EGLOutput
X-NVConfidentiality: public
As previously stated, EGLDevice and EGLOutput will provide means
to access native device objects and different portions of display
control hardware respectively.
Whenever EGL_EXT_device_drm extension is present, EGLDevice can
be used to enumerate and access DRM KMS devices, and EGLOutputLayer
to enumerate and access DRM KMS crtcs and planes.
By using EGLStreams and attaching an EGLOutputLayer consumer
(representing a DRM KMS crtc or plane) to it, compositor-drm can
produce final composition frames and present them on a DRM device.
This change adds required logic to support presentation through
EGLDevice+EGLOutput+EGLStream. Whether GBM or EGLDevice should be
used can be controlled by --use-egldevice backend argument.
Signed-off-by: Miguel A Vico Moya <mvicomoya@nvidia.com>
Reviewed-by: Andy Ritger <aritger@nvidia.com>
Reviewed-by: Adam Cheney <acheney@nvidia.com>
Reviewed-by: James Jones <jajones@nvidia.com>
---
compositor/main.c | 2 +
libweston/compositor-drm.c | 303 ++++++++++++++++++++++++++++++++-------------
libweston/compositor-drm.h | 4 +
libweston/gl-renderer.h | 1 +
shared/weston-egl-ext.h | 9 ++
5 files changed, 230 insertions(+), 89 deletions(-)
diff --git a/compositor/main.c b/compositor/main.c
index 72c3cd10..ad348d82 100644
--- compositor/main.c
+++ compositor/main.c
@@ -566,6 +566,7 @@ usage(int error_code)
" --seat=SEAT\t\tThe seat that weston should run on\n"
" --tty=TTY\t\tThe tty to use\n"
" --use-pixman\t\tUse the pixman (CPU) renderer\n"
+ " --use-egldevice\tUse EGLDevice and EGLOutput with the GL renderer\n"
" --current-mode\tPrefer current KMS mode over EDID preferred mode\n\n");
#endif
@@ -1227,6 +1228,7 @@ load_drm_backend(struct weston_compositor *c,
{ WESTON_OPTION_INTEGER, "tty", 0, &config.tty },
{ WESTON_OPTION_BOOLEAN, "current-mode", 0, &wet->drm_use_current_mode },
{ WESTON_OPTION_BOOLEAN, "use-pixman", 0, &config.use_pixman },
+ { WESTON_OPTION_BOOLEAN, "use-egldevice", 0, &config.use_egldevice },
};
parse_options(options, ARRAY_LENGTH(options), argc, argv);
diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c
index 12c1b8b5..0236d196 100644
--- libweston/compositor-drm.c
+++ libweston/compositor-drm.c
@@ -94,7 +94,10 @@ struct drm_backend {
int fd;
char *filename;
} drm;
+
+ EGLDeviceEXT egldevice;
struct gbm_device *gbm;
+
struct wl_listener session_listener;
uint32_t gbm_format;
@@ -113,6 +116,7 @@ struct drm_backend {
int cursors_are_broken;
int use_pixman;
+ int use_egldevice;
struct udev_input input;
@@ -595,17 +599,21 @@ drm_output_render_gl(struct drm_output *output, pixman_region32_t *damage)
output->base.compositor->renderer->repaint_output(&output->base,
damage);
- bo = gbm_surface_lock_front_buffer(output->gbm_surface);
- if (!bo) {
- weston_log("failed to lock front buffer: %m\n");
- return;
- }
+ if (b->use_egldevice)
+ output->next = output->dumb[0];
+ else {
+ bo = gbm_surface_lock_front_buffer(output->gbm_surface);
+ if (!bo) {
+ weston_log("failed to lock front buffer: %m\n");
+ return;
+ }
- output->next = drm_fb_get_from_bo(bo, b, output->gbm_format);
- if (!output->next) {
- weston_log("failed to get drm_fb for bo\n");
- gbm_surface_release_buffer(output->gbm_surface, bo);
- return;
+ output->next = drm_fb_get_from_bo(bo, b, output->gbm_format);
+ if (!output->next) {
+ weston_log("failed to get drm_fb for bo\n");
+ gbm_surface_release_buffer(output->gbm_surface, bo);
+ return;
+ }
}
}
@@ -730,9 +738,14 @@ drm_output_repaint(struct weston_output *output_base,
output_base->set_dpms(output_base, WESTON_DPMS_ON);
}
- if (drmModePageFlip(backend->drm.fd, output->crtc_id,
- output->next->fb_id,
- DRM_MODE_PAGE_FLIP_EVENT, output) < 0) {
+ if (backend->use_egldevice)
+ ret = gl_renderer->output_stream_flip(&output->base, output);
+ else
+ ret = drmModePageFlip(backend->drm.fd, output->crtc_id,
+ output->next->fb_id,
+ DRM_MODE_PAGE_FLIP_EVENT, output);
+
+ if (ret < 0) {
weston_log("queueing pageflip failed: %m\n");
goto err_pageflip;
}
@@ -803,7 +816,6 @@ drm_output_start_repaint_loop(struct weston_output *output_base)
struct drm_output *output = to_drm_output(output_base);
struct drm_backend *backend =
to_drm_backend(output_base->compositor);
- uint32_t fb_id;
struct timespec ts, tnow;
struct timespec vbl2now;
int64_t refresh_nsec;
@@ -859,10 +871,14 @@ drm_output_start_repaint_loop(struct weston_output *output_base)
/* Immediate query succeeded, but didn't provide valid timestamp.
* Use pageflip fallback.
*/
- fb_id = output->current->fb_id;
+ if (backend->use_egldevice)
+ ret = gl_renderer->output_stream_flip(&output->base, output);
+ else
+ ret = drmModePageFlip(backend->drm.fd, output->crtc_id,
+ output->current->fb_id,
+ DRM_MODE_PAGE_FLIP_EVENT, output);
- if (drmModePageFlip(backend->drm.fd, output->crtc_id, fb_id,
- DRM_MODE_PAGE_FLIP_EVENT, output) < 0) {
+ if (ret < 0) {
weston_log("queueing pageflip failed: %m\n");
goto finish_frame;
}
@@ -1589,11 +1605,6 @@ create_gbm_device(int fd)
{
struct gbm_device *gbm;
- gl_renderer = weston_load_module("gl-renderer.so",
- "gl_renderer_interface");
- if (!gl_renderer)
- return NULL;
-
/* GBM will load a dri driver, but even though they need symbols from
* libglapi, in some version of Mesa they are not linked to it. Since
* only the gl-renderer module links to it, the call above won't make
@@ -1606,6 +1617,40 @@ create_gbm_device(int fd)
return gbm;
}
+static EGLDeviceEXT
+find_egldevice(const char *filename)
+{
+ EGLDeviceEXT egldevice = EGL_NO_DEVICE_EXT;
+ EGLDeviceEXT *devices;
+ EGLint num_devices;
+ const char *drm_path;
+ int i;
+
+ if (gl_renderer->get_devices(0, NULL, &num_devices) < 0 ||
+ num_devices < 1)
+ return EGL_NO_DEVICE_EXT;
+
+ devices = zalloc(num_devices * sizeof *devices);
+ if (!devices)
+ return EGL_NO_DEVICE_EXT;
+
+ if (gl_renderer->get_devices(num_devices, devices, &num_devices) < 0) {
+ free(devices);
+ return EGL_NO_DEVICE_EXT;
+ }
+
+ for (i = 0; i < num_devices; i++)
+ if (gl_renderer->get_drm_device_file(devices[i],
+ &drm_path) == 0 &&
+ strcmp(filename, drm_path) == 0) {
+ egldevice = devices[i];
+ break;
+ }
+
+ free(devices);
+ return egldevice;
+}
+
/* When initializing EGL, if the preferred buffer format isn't available
* we may be able to substitute an ARGB format for an XRGB one.
*
@@ -1632,38 +1677,62 @@ fallback_format_for(uint32_t format)
static int
drm_backend_create_gl_renderer(struct drm_backend *b)
{
- EGLint format[3] = {
- b->gbm_format,
- fallback_format_for(b->gbm_format),
- 0,
- };
- int n_formats = 2;
+ if (b->use_egldevice) {
+ EGLint device_platform_attribs[] = {
+ EGL_DRM_MASTER_FD_EXT, b->drm.fd,
+ EGL_NONE
+ };
- if (format[1])
- n_formats = 3;
- if (gl_renderer->display_create(b->compositor,
- EGL_PLATFORM_GBM_KHR,
- (void *)b->gbm,
+ return gl_renderer->display_create(
+ b->compositor,
+ EGL_PLATFORM_DEVICE_EXT,
+ (void *)b->egldevice,
+ device_platform_attribs,
+ gl_renderer->opaque_stream_attribs,
NULL,
- gl_renderer->opaque_attribs,
- format,
- n_formats) < 0) {
- return -1;
- }
+ 0);
+ } else {
+ EGLint format[3] = {
+ b->gbm_format,
+ fallback_format_for(b->gbm_format),
+ 0,
+ };
+ int n_formats = 2;
- return 0;
+ if (format[1])
+ n_formats = 3;
+
+ return gl_renderer->display_create(b->compositor,
+ EGL_PLATFORM_GBM_KHR,
+ (void *)b->gbm,
+ NULL,
+ gl_renderer->opaque_attribs,
+ format,
+ n_formats);
+ }
}
static int
init_egl(struct drm_backend *b)
{
- b->gbm = create_gbm_device(b->drm.fd);
-
- if (!b->gbm)
+ gl_renderer = weston_load_module("gl-renderer.so",
+ "gl_renderer_interface");
+ if (!gl_renderer)
return -1;
+ if (b->use_egldevice) {
+ b->egldevice = find_egldevice(b->drm.filename);
+ if (b->egldevice == EGL_NO_DEVICE_EXT)
+ return -1;
+ } else {
+ b->gbm = create_gbm_device(b->drm.fd);
+ if (!b->gbm)
+ return -1;
+ }
+
if (drm_backend_create_gl_renderer(b) < 0) {
- gbm_device_destroy(b->gbm);
+ if (b->gbm)
+ gbm_device_destroy(b->gbm);
return -1;
}
@@ -1894,50 +1963,83 @@ find_crtc_for_connector(struct drm_backend *b,
static int
drm_output_init_egl(struct drm_output *output, struct drm_backend *b)
{
- EGLint format[2] = {
- output->gbm_format,
- fallback_format_for(output->gbm_format),
- };
- int i, flags, n_formats = 1;
-
- output->gbm_surface = gbm_surface_create(b->gbm,
- output->base.current_mode->width,
- output->base.current_mode->height,
- format[0],
- GBM_BO_USE_SCANOUT |
- GBM_BO_USE_RENDERING);
- if (!output->gbm_surface) {
- weston_log("failed to create gbm surface\n");
- return -1;
- }
+ if (b->use_egldevice) {
+ int w = output->base.current_mode->width;
+ int h = output->base.current_mode->height;
- if (format[1])
- n_formats = 2;
- if (gl_renderer->output_window_create(&output->base,
- (EGLNativeWindowType)output->gbm_surface,
- output->gbm_surface,
- gl_renderer->opaque_attribs,
- format,
- n_formats) < 0) {
- weston_log("failed to create gl renderer output state\n");
- gbm_surface_destroy(output->gbm_surface);
- return -1;
- }
+ /* Create a black dumb fb for modesetting */
+ output->dumb[0] = drm_fb_create_dumb(b, w, h,
+ DRM_FORMAT_XRGB8888);
+ if (!output->dumb[0]) {
+ weston_log("failed to create dumb framebuffer\n");
+ return -1;
+ }
+ memset(output->dumb[0]->map, 0, output->dumb[0]->size);
+
+ if (gl_renderer->output_stream_create(&output->base, ~0u,
+ output->crtc_id) < 0) {
+ weston_log("failed to create gl renderer output stream "
+ "state\n");
+ drm_fb_destroy_dumb(output->dumb[0]);
+ output->dumb[0] = NULL;
+ return -1;
+ }
- flags = GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE;
+ /* FIXME: Add hw planes and cursors for EGL device when supported */
+ b->sprites_are_broken = 1;
+ b->cursors_are_broken = 1;
+ } else {
+ EGLint format[2] = {
+ output->gbm_format,
+ fallback_format_for(output->gbm_format),
+ };
+ int i, flags, n_formats = 1;
+
+ output->gbm_surface = gbm_surface_create(
+ b->gbm,
+ output->base.current_mode->width,
+ output->base.current_mode->height,
+ format[0],
+ GBM_BO_USE_SCANOUT |
+ GBM_BO_USE_RENDERING);
+ if (!output->gbm_surface) {
+ weston_log("failed to create gbm surface\n");
+ return -1;
+ }
- for (i = 0; i < 2; i++) {
- if (output->gbm_cursor_bo[i])
- continue;
+ if (format[1])
+ n_formats = 2;
+ if (gl_renderer->output_window_create(
+ &output->base,
+ (EGLNativeWindowType)output->gbm_surface,
+ output->gbm_surface,
+ gl_renderer->opaque_attribs,
+ format,
+ n_formats) < 0) {
+ weston_log("failed to create gl renderer output "
+ "state\n");
+ gbm_surface_destroy(output->gbm_surface);
+ return -1;
+ }
- output->gbm_cursor_bo[i] =
- gbm_bo_create(b->gbm, b->cursor_width, b->cursor_height,
- GBM_FORMAT_ARGB8888, flags);
- }
+ flags = GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE;
- if (output->gbm_cursor_bo[0] == NULL || output->gbm_cursor_bo[1] == NULL) {
- weston_log("cursor buffers unavailable, using gl cursors\n");
- b->cursors_are_broken = 1;
+ for (i = 0; i < 2; i++) {
+ if (output->gbm_cursor_bo[i])
+ continue;
+
+ output->gbm_cursor_bo[i] =
+ gbm_bo_create(b->gbm,
+ b->cursor_width,
+ b->cursor_height,
+ GBM_FORMAT_ARGB8888,
+ flags);
+ }
+
+ if (output->gbm_cursor_bo[0] == NULL || output->gbm_cursor_bo[1] == NULL) {
+ weston_log("cursor buffers unavailable, using gl cursors\n");
+ b->cursors_are_broken = 1;
+ }
}
return 0;
@@ -1947,7 +2049,14 @@ static void
drm_output_fini_egl(struct drm_output *output)
{
gl_renderer->output_destroy(&output->base);
- gbm_surface_destroy(output->gbm_surface);
+
+ if (output->dumb[0]) {
+ drm_fb_destroy_dumb(output->dumb[0]);
+ output->dumb[0] = NULL;
+ }
+
+ if (output->gbm_surface)
+ gbm_surface_destroy(output->gbm_surface);
}
static int
@@ -3107,6 +3216,11 @@ recorder_binding(struct weston_keyboard *keyboard, uint32_t time, uint32_t key,
struct drm_output *output;
int width, height;
+ if (b->use_egldevice) {
+ weston_log("recorder not supported with EGL device\n");
+ return;
+ }
+
output = container_of(b->compositor->output_list.next,
struct drm_output, base.link);
@@ -3162,11 +3276,20 @@ switch_to_gl_renderer(struct drm_backend *b)
weston_log("Switching to GL renderer\n");
- b->gbm = create_gbm_device(b->drm.fd);
- if (!b->gbm) {
- weston_log("Failed to create gbm device. "
- "Aborting renderer switch\n");
- return;
+ if (b->use_egldevice) {
+ b->egldevice = find_egldevice(b->drm.filename);
+ if (b->egldevice == EGL_NO_DEVICE_EXT) {
+ weston_log("Failed to create EGL device. "
+ "Aborting renderer switch\n");
+ return;
+ }
+ } else {
+ b->gbm = create_gbm_device(b->drm.fd);
+ if (!b->gbm) {
+ weston_log("Failed to create gbm device. "
+ "Aborting renderer switch\n");
+ return;
+ }
}
wl_list_for_each(output, &b->compositor->output_list, base.link)
@@ -3175,7 +3298,8 @@ switch_to_gl_renderer(struct drm_backend *b)
b->compositor->renderer->destroy(b->compositor);
if (drm_backend_create_gl_renderer(b) < 0) {
- gbm_device_destroy(b->gbm);
+ if (b->gbm)
+ gbm_device_destroy(b->gbm);
weston_log("Failed to create GL renderer. Quitting.\n");
/* FIXME: we need a function to shutdown cleanly */
assert(0);
@@ -3239,6 +3363,7 @@ drm_backend_create(struct weston_compositor *compositor,
b->sprites_are_broken = 1;
b->compositor = compositor;
b->use_pixman = config->use_pixman;
+ b->use_egldevice = config->use_egldevice;
if (parse_gbm_format(config->gbm_format, GBM_FORMAT_XRGB8888, &b->gbm_format) < 0)
goto err_compositor;
diff --git a/libweston/compositor-drm.h b/libweston/compositor-drm.h
index 2e2995a2..9cd0eef6 100644
--- libweston/compositor-drm.h
+++ libweston/compositor-drm.h
@@ -110,6 +110,10 @@ struct weston_drm_backend_config {
/** Whether to use the pixman renderer instead of the OpenGL ES renderer. */
bool use_pixman;
+ /** Whether to use the GL composition based off EGLDevice & friends instead
+ * of GBM. */
+ bool use_egldevice;
+
/** The seat to be used for input and output.
*
* If NULL the default "seat0" will be used. The backend will
diff --git a/libweston/gl-renderer.h b/libweston/gl-renderer.h
index 39ea3b42..37252492 100644
--- libweston/gl-renderer.h
+++ libweston/gl-renderer.h
@@ -45,6 +45,7 @@ typedef void *EGLConfig;
typedef intptr_t EGLNativeDisplayType;
typedef intptr_t EGLNativeWindowType;
#define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType)0)
+#define EGL_NO_DEVICE_EXT ((EGLDeviceEXT)0)
#endif /* ENABLE_EGL */
diff --git a/shared/weston-egl-ext.h b/shared/weston-egl-ext.h
index 11e9ccc1..de82310f 100644
--- shared/weston-egl-ext.h
+++ shared/weston-egl-ext.h
@@ -162,6 +162,10 @@ typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPLATFORMPIXMAPSURFACEEXTPROC) (EGLD
#define EGL_PLATFORM_DEVICE_EXT 0x313F
#endif
+#ifndef EGL_DRM_MASTER_FD_EXT
+#define EGL_DRM_MASTER_FD_EXT 0x333C
+#endif
+
/*
* FIXME: Remove both EGL_EXT_stream_acquire_mode and
* EGL_NV_output_drm_flip_event definitions below once both extensions
@@ -210,6 +214,11 @@ EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerAcquireAttribEXT (EGLDisplay dpy,
#define EGL_PLATFORM_X11_KHR 0x31D5
#define EGL_PLATFORM_DEVICE_EXT 0x313F
+/* EGL_DRM_MASTER_FD_EXT and EGL_NONE enum values are also kept to allow
+ * compositor-drm.c to build with EGLDevice and EGLStream support */
+#define EGL_DRM_MASTER_FD_EXT 0x333C
+#define EGL_NONE 0x3038
+
#endif /* ENABLE_EGL */
#endif
--
2.11.1

View file

@ -0,0 +1,168 @@
From c876b463f62b18da2446ad097d0bdad63d34363d Mon Sep 17 00:00:00 2001
From: "Miguel A. Vico" <mvicomoya@nvidia.com>
Date: Mon, 27 Feb 2017 15:31:35 -0800
Subject: [PATCH 6/7] simple-egl: Do not set EGL up until XDG setup is complete
X-NVConfidentiality: public
There is nothing that prohibits the underlying EGL_PLATFORM_WAYLAND
implementation to attach a buffer or commit surfaces right after the
Wayland EGLSurface has been created.
Since XDG Shell v6 imposes that no buffer attachments or surface commits
must be done before a configure is complete, Wayland clients shouldn't
start setting EGL up until XDG setup is complete.
Related bug:
https://bugs.freedesktop.org/show_bug.cgi?id=98731
Signed-off-by: Miguel A Vico Moya <mvicomoya@nvidia.com>
---
clients/simple-egl.c | 67 +++++++++++++++++++++++++++-------------------------
1 file changed, 35 insertions(+), 32 deletions(-)
diff --git a/clients/simple-egl.c b/clients/simple-egl.c
index 9b6fa1f2..59311cfc 100644
--- clients/simple-egl.c
+++ clients/simple-egl.c
@@ -221,11 +221,32 @@ init_egl(struct display *display, struct window *window)
if (display->swap_buffers_with_damage)
printf("has EGL_EXT_buffer_age and %s\n", swap_damage_ext_to_entrypoint[i].extension);
+ window->egl_surface =
+ weston_platform_create_egl_surface(display->egl.dpy,
+ display->egl.conf,
+ window->native, NULL);
+
+ ret = eglMakeCurrent(window->display->egl.dpy, window->egl_surface,
+ window->egl_surface, window->display->egl.ctx);
+ assert(ret == EGL_TRUE);
+
+ if (!window->frame_sync)
+ eglSwapInterval(display->egl.dpy, 0);
+
}
static void
-fini_egl(struct display *display)
+fini_egl(struct display *display, struct window *window)
{
+ /* Required, otherwise segfault in egl_dri2.c: dri2_make_current()
+ * on eglReleaseThread(). */
+ eglMakeCurrent(window->display->egl.dpy, EGL_NO_SURFACE, EGL_NO_SURFACE,
+ EGL_NO_CONTEXT);
+
+ weston_platform_destroy_egl_surface(window->display->egl.dpy,
+ window->egl_surface);
+ wl_egl_window_destroy(window->native);
+
eglTerminate(display->egl.dpy);
eglReleaseThread();
}
@@ -360,7 +381,8 @@ handle_ivi_surface_configure(void *data, struct ivi_surface *ivi_surface,
{
struct window *window = data;
- wl_egl_window_resize(window->native, width, height, 0, 0);
+ if (window->native)
+ wl_egl_window_resize(window->native, width, height, 0, 0);
window->geometry.width = width;
window->geometry.height = height;
@@ -413,7 +435,6 @@ static void
create_surface(struct window *window)
{
struct display *display = window->display;
- EGLBoolean ret;
window->surface = wl_compositor_create_surface(display->compositor);
@@ -421,10 +442,6 @@ create_surface(struct window *window)
wl_egl_window_create(window->surface,
window->geometry.width,
window->geometry.height);
- window->egl_surface =
- weston_platform_create_egl_surface(display->egl.dpy,
- display->egl.conf,
- window->native, NULL);
if (display->shell) {
@@ -435,13 +452,6 @@ create_surface(struct window *window)
assert(0);
}
- ret = eglMakeCurrent(window->display->egl.dpy, window->egl_surface,
- window->egl_surface, window->display->egl.ctx);
- assert(ret == EGL_TRUE);
-
- if (!window->frame_sync)
- eglSwapInterval(display->egl.dpy, 0);
-
if (!display->shell)
return;
@@ -452,15 +462,6 @@ create_surface(struct window *window)
static void
destroy_surface(struct window *window)
{
- /* Required, otherwise segfault in egl_dri2.c: dri2_make_current()
- * on eglReleaseThread(). */
- eglMakeCurrent(window->display->egl.dpy, EGL_NO_SURFACE, EGL_NO_SURFACE,
- EGL_NO_CONTEXT);
-
- weston_platform_destroy_egl_surface(window->display->egl.dpy,
- window->egl_surface);
- wl_egl_window_destroy(window->native);
-
if (window->xdg_toplevel)
zxdg_toplevel_v6_destroy(window->xdg_toplevel);
if (window->xdg_surface)
@@ -895,9 +896,7 @@ main(int argc, char **argv)
wl_display_roundtrip(display.display);
- init_egl(&display, &window);
create_surface(&window);
- init_gl(&window);
display.cursor_surface =
wl_compositor_create_surface(display.compositor);
@@ -907,23 +906,27 @@ main(int argc, char **argv)
sigint.sa_flags = SA_RESETHAND;
sigaction(SIGINT, &sigint, NULL);
+ /* We must assure XDG setup is complete before setting EGL up */
+ while (running && window.wait_for_configure) {
+ wl_display_dispatch(display.display);
+ }
+
+ init_egl(&display, &window);
+ init_gl(&window);
+
/* The mainloop here is a little subtle. Redrawing will cause
* EGL to read events so we can just call
* wl_display_dispatch_pending() to handle any events that got
* queued up as a side effect. */
while (running && ret != -1) {
- if (window.wait_for_configure) {
- wl_display_dispatch(display.display);
- } else {
- wl_display_dispatch_pending(display.display);
- redraw(&window, NULL, 0);
- }
+ wl_display_dispatch_pending(display.display);
+ redraw(&window, NULL, 0);
}
fprintf(stderr, "simple-egl exiting\n");
+ fini_egl(&display, &window);
destroy_surface(&window);
- fini_egl(&display);
wl_surface_destroy(display.cursor_surface);
if (display.cursor_theme)
--
2.11.1

View file

@ -0,0 +1,42 @@
From 7f733c58c947c5355dda3d829dd0f4a47c4c819d Mon Sep 17 00:00:00 2001
From: "Miguel A. Vico" <mvicomoya@nvidia.com>
Date: Fri, 11 Nov 2016 20:07:19 +0100
Subject: [PATCH 7/7] Add nvidia-release-notes file
X-NVConfidentiality: public
Signed-off-by: Miguel A Vico Moya <mvicomoya@nvidia.com>
---
nvidia-release-notes | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
create mode 100644 nvidia-release-notes
diff --git a/nvidia-release-notes b/nvidia-release-notes
new file mode 100644
index 00000000..4bd24000
--- /dev/null
+++ nvidia-release-notes
@@ -0,0 +1,21 @@
+NVIDIA EGLStream-based Weston version 2.0
+-----------------------------------------
+
+This branch includes NVIDIA EGLStream patches on top of
+Weston 2.0.
+
+* Known issues:
+
+ - Bad interactions with XDG Shell v6 preventing
+ clients that implement the new interface from
+ starting
+
+ Fixed in 'weston-simple-egl' with commit:
+
+ c876b463f62b18da2446ad097d0bdad63d34363d simple-egl: Do not set EGL up until XDG setup is complete
+
+
+* Contact:
+
+ Miguel A. Vico (mvicomoya AT nvidia.com)
+
--
2.11.1

View file

@ -0,0 +1,53 @@
From 812868a91f8c9c42167bf3bf2c66f6ec1f049c41 Mon Sep 17 00:00:00 2001
From: "Miguel A. Vico" <mvicomoya@nvidia.com>
Date: Tue, 4 Apr 2017 14:39:47 -0700
Subject: [PATCH] compositor-drm: Release current & next fb when deactivating
the session
X-NVConfidentiality: public
With
commit 47224cc9312fef05c1a523ea0da0a1aae66f100d
Author: Daniel Stone <daniels@collabora.com>
Date: Sat Nov 5 08:04:07 2016 +0000
compositor-drm: Delete drm_backend_set_modes
we stopped forcing a modeset when restoring the session. The motivation
was that we would use a stale fb, so better to let the next repaint
handle it.
However, if drm_output::current != NULL, we won't issue a modeset upon
repaint.
This change releases both drm_output::current and drm_output::next when
deactivating the current session. This ensures the very first repaint
after restoring the session will issue a modeset.
Signed-off-by: Miguel A Vico Moya <mvicomoya@nvidia.com>
---
libweston/compositor-drm.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c
index 0236d196..7283d0ff 100644
--- libweston/compositor-drm.c
+++ libweston/compositor-drm.c
@@ -3058,6 +3058,14 @@ session_notify(struct wl_listener *listener, void *data)
wl_list_for_each(output, &compositor->output_list, base.link) {
output->base.repaint_needed = 0;
drmModeSetCursor(b->drm.fd, output->crtc_id, 0, 0, 0);
+ if (output->current != NULL) {
+ drm_output_release_fb(output, output->current);
+ output->current = NULL;
+ }
+ if (output->next != NULL) {
+ drm_output_release_fb(output, output->next);
+ output->next = NULL;
+ }
}
output = container_of(compositor->output_list.next,
--
2.12.1

View file

@ -1,7 +1,7 @@
# Template file for 'weston'.
pkgname=weston
version=2.0.0
revision=1
revision=2
build_style=gnu-configure
# XXX enable rdp compositor if freerdp is updated to >=1.1.
configure_args="--enable-libinput-backend --disable-setuid-install