diff options
author | Miguel A. Vico | 2019-03-26 17:54:58 -0700 |
---|---|---|
committer | Miguel A. Vico | 2019-03-27 22:04:18 -0700 |
commit | 6270174bd71c83185112d299fbc842293b7ffb2c (patch) | |
tree | ca801657abff728d5f55c31b55db438fb686053b /0004-gl-renderer-Add-EGL-client-support-for-EGLStream-fra.patch | |
parent | 1ec939fa1774fe9bfa98f601f90a1b0669b267ba (diff) | |
download | aur-6270174bd71c83185112d299fbc842293b7ffb2c.tar.gz |
Update to weston 6.0.0
Diffstat (limited to '0004-gl-renderer-Add-EGL-client-support-for-EGLStream-fra.patch')
-rw-r--r-- | 0004-gl-renderer-Add-EGL-client-support-for-EGLStream-fra.patch | 326 |
1 files changed, 326 insertions, 0 deletions
diff --git a/0004-gl-renderer-Add-EGL-client-support-for-EGLStream-fra.patch b/0004-gl-renderer-Add-EGL-client-support-for-EGLStream-fra.patch new file mode 100644 index 000000000000..2f2a7a9c5377 --- /dev/null +++ b/0004-gl-renderer-Add-EGL-client-support-for-EGLStream-fra.patch @@ -0,0 +1,326 @@ +From 1c422fb24eadccabd3ed07de15923acc982aa6a1 Mon Sep 17 00:00:00 2001 +From: "Miguel A. Vico" <mvicomoya@nvidia.com> +Date: Thu, 29 Mar 2018 00:15:49 -0700 +Subject: [PATCH 4/8] 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 f3fb2c65..5e594535 100644 +--- a/libweston/gl-renderer.c ++++ b/libweston/gl-renderer.c +@@ -189,6 +189,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; + + /* Whether this surface was used in the current output repaint. +@@ -248,6 +251,7 @@ struct gl_renderer { + + PFNEGLCREATESTREAMKHRPROC create_stream; + PFNEGLDESTROYSTREAMKHRPROC destroy_stream; ++ PFNEGLQUERYSTREAMKHRPROC query_stream; + int has_egl_stream; + + PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC create_stream_producer_surface; +@@ -257,11 +261,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; + +@@ -2528,6 +2537,145 @@ gl_renderer_attach_dmabuf(struct weston_surface *surface, + surface->is_opaque = dmabuf_is_opaque(dmabuf); + } + ++/* ++ * 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) + { +@@ -2554,6 +2702,12 @@ gl_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer) + gs->buffer_type = BUFFER_TYPE_NULL; + gs->y_inverted = 1; + es->is_opaque = false; ++ ++ 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; + } + +@@ -2567,7 +2721,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"); + if (gr->has_bind_display) { + weston_log("eglQueryWaylandBufferWL failed\n"); +@@ -2764,6 +2918,10 @@ surface_state_destroy(struct gl_surface_state *gs, struct gl_renderer *gr) + weston_buffer_reference(&gs->buffer_ref, NULL); + weston_buffer_release_reference(&gs->buffer_release_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); + } + +@@ -2814,6 +2972,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; + +@@ -3570,14 +3730,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); +@@ -3676,6 +3841,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; +@@ -3953,6 +4124,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 f39990ed..96982e2d 100644 +--- a/shared/weston-egl-ext.h ++++ b/shared/weston-egl-ext.h +@@ -243,6 +243,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.21.0 + |