diff --git a/srcpkgs/weston/patches/0001-gl-renderer-Add-EGLDevice-enumeration-support.patch b/srcpkgs/weston/patches/0001-gl-renderer-Add-EGLDevice-enumeration-support.patch new file mode 100644 index 00000000000..0a69e87f51b --- /dev/null +++ b/srcpkgs/weston/patches/0001-gl-renderer-Add-EGLDevice-enumeration-support.patch @@ -0,0 +1,156 @@ +From d178c1add79d48cd639bf5c387067c0e4d5fae09 Mon Sep 17 00:00:00 2001 +From: "Miguel A. Vico" +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 +Reviewed-by: Andy Ritger +Reviewed-by: Adam Cheney +Reviewed-by: James Jones +--- + 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 + diff --git a/srcpkgs/weston/patches/0002-gl-renderer-Add-support-for-EGLDevice-composited-fra.patch b/srcpkgs/weston/patches/0002-gl-renderer-Add-support-for-EGLDevice-composited-fra.patch new file mode 100644 index 00000000000..f34a0323cef --- /dev/null +++ b/srcpkgs/weston/patches/0002-gl-renderer-Add-support-for-EGLDevice-composited-fra.patch @@ -0,0 +1,522 @@ +From b67b64f6c7565a88558f1398895830394b887ee3 Mon Sep 17 00:00:00 2001 +From: "Miguel A. Vico" +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 +Reviewed-by: Andy Ritger +Reviewed-by: Adam Cheney +Reviewed-by: James Jones +--- + 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 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 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 + diff --git a/srcpkgs/weston/patches/0003-gl-renderer-Add-EGL-client-support-for-EGLStream-fra.patch b/srcpkgs/weston/patches/0003-gl-renderer-Add-EGL-client-support-for-EGLStream-fra.patch new file mode 100644 index 00000000000..1dca2ca9237 --- /dev/null +++ b/srcpkgs/weston/patches/0003-gl-renderer-Add-EGL-client-support-for-EGLStream-fra.patch @@ -0,0 +1,326 @@ +From aa3aee0503249a0d667dba1001b292b3907fad18 Mon Sep 17 00:00:00 2001 +From: "Miguel A. Vico" +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 +Reviewed-by: Adam Cheney +Reviewed-by: James Jones +--- + 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 to an EGLStream. If the given buffer was already ++ * bound, it will acquire next frame on the stream. ++ * ++ * Return true if the given 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 + diff --git a/srcpkgs/weston/patches/0004-compositor-drm-Gracefully-handle-vblank-and-flip-inv.patch b/srcpkgs/weston/patches/0004-compositor-drm-Gracefully-handle-vblank-and-flip-inv.patch new file mode 100644 index 00000000000..430bacebd95 --- /dev/null +++ b/srcpkgs/weston/patches/0004-compositor-drm-Gracefully-handle-vblank-and-flip-inv.patch @@ -0,0 +1,86 @@ +From d89c874ea121b6855c7bdf2e757fa13d0b04661f Mon Sep 17 00:00:00 2001 +From: "Miguel A. Vico" +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 +Reviewed-by: Andy Ritger +--- + 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 + diff --git a/srcpkgs/weston/patches/0005-compositor-drm-Add-support-for-EGLDevice-EGLOutput.patch b/srcpkgs/weston/patches/0005-compositor-drm-Add-support-for-EGLDevice-EGLOutput.patch new file mode 100644 index 00000000000..a57c5177430 --- /dev/null +++ b/srcpkgs/weston/patches/0005-compositor-drm-Add-support-for-EGLDevice-EGLOutput.patch @@ -0,0 +1,542 @@ +From b1db106d3c91c1b35a01573a455c5661a17a06ee Mon Sep 17 00:00:00 2001 +From: "Miguel A. Vico" +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 +Reviewed-by: Andy Ritger +Reviewed-by: Adam Cheney +Reviewed-by: James Jones +--- + 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 + diff --git a/srcpkgs/weston/patches/0006-simple-egl-Do-not-set-EGL-up-until-XDG-setup-is-comp.patch b/srcpkgs/weston/patches/0006-simple-egl-Do-not-set-EGL-up-until-XDG-setup-is-comp.patch new file mode 100644 index 00000000000..24611f4f0c3 --- /dev/null +++ b/srcpkgs/weston/patches/0006-simple-egl-Do-not-set-EGL-up-until-XDG-setup-is-comp.patch @@ -0,0 +1,168 @@ +From c876b463f62b18da2446ad097d0bdad63d34363d Mon Sep 17 00:00:00 2001 +From: "Miguel A. Vico" +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 +--- + 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 + diff --git a/srcpkgs/weston/patches/0007-Add-nvidia-release-notes-file.patch b/srcpkgs/weston/patches/0007-Add-nvidia-release-notes-file.patch new file mode 100644 index 00000000000..74db5174209 --- /dev/null +++ b/srcpkgs/weston/patches/0007-Add-nvidia-release-notes-file.patch @@ -0,0 +1,42 @@ +From 7f733c58c947c5355dda3d829dd0f4a47c4c819d Mon Sep 17 00:00:00 2001 +From: "Miguel A. Vico" +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 +--- + 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 + diff --git a/srcpkgs/weston/patches/0008-compositor-drm-Release-current-next-fb-when-deactiva.patch b/srcpkgs/weston/patches/0008-compositor-drm-Release-current-next-fb-when-deactiva.patch new file mode 100644 index 00000000000..c01a6534163 --- /dev/null +++ b/srcpkgs/weston/patches/0008-compositor-drm-Release-current-next-fb-when-deactiva.patch @@ -0,0 +1,53 @@ +From 812868a91f8c9c42167bf3bf2c66f6ec1f049c41 Mon Sep 17 00:00:00 2001 +From: "Miguel A. Vico" +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 + 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 +--- + 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 + diff --git a/srcpkgs/weston/template b/srcpkgs/weston/template index da6191ef4ae..bf1784d679c 100644 --- a/srcpkgs/weston/template +++ b/srcpkgs/weston/template @@ -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