Commit 9ac798ae authored by Philippe Normand's avatar Philippe Normand 🥑 Committed by Thibault Saunier

wpe: Add software rendering support support

Starting from WPEBackend-FDO 1.6.x, software rendering support is available.
This features allows wpesrc to be used on machines without GPU, and/or for
testing purpose. To enable it, set the `LIBGL_ALWAYS_SOFTWARE=true` environment
variable and make sure `video/x-raw, format=BGRA` caps are negotiated by the
wpesrc element.
parent e2cefdd6
Pipeline #107332 passed with stages
in 27 minutes and 51 seconds
This diff is collapsed.
......@@ -31,6 +31,12 @@ typedef struct _GstGLContext GstGLContext;
typedef struct _GstGLDisplay GstGLDisplay;
typedef struct _GstEGLImage GstEGLImage;
#if defined(WPE_FDO_CHECK_VERSION) && WPE_FDO_CHECK_VERSION(1, 5, 0)
#define ENABLE_SHM_BUFFER_SUPPORT 1
#else
#define ENABLE_SHM_BUFFER_SUPPORT 0
#endif
class WPEThreadedView {
public:
WPEThreadedView();
......@@ -44,17 +50,25 @@ public:
void setDrawBackground(gboolean);
GstEGLImage* image();
GstBuffer* buffer();
struct wpe_view_backend* backend() const;
protected:
void handleExportedImage(gpointer);
#if ENABLE_SHM_BUFFER_SUPPORT
void handleExportedBuffer(struct wpe_fdo_shm_exported_buffer*);
#endif
private:
void frameComplete();
void loadUriUnlocked(const gchar*);
void releaseImage(gpointer);
#if ENABLE_SHM_BUFFER_SUPPORT
void releaseSHMBuffer(gpointer);
static void s_releaseSHMBuffer(gpointer);
#endif
static void s_loadEvent(WebKitWebView*, WebKitLoadEvent, gpointer);
......@@ -90,9 +104,17 @@ private:
WebKitWebView* view;
} webkit = { nullptr, nullptr };
// This mutex guards access to either egl or shm resources declared below,
// depending on the runtime behavior.
GMutex images_mutex;
struct {
GMutex mutex;
GstEGLImage* pending { nullptr };
GstEGLImage* committed { nullptr };
} images;
GstEGLImage* pending;
GstEGLImage* committed;
} egl { nullptr, nullptr };
struct {
GstBuffer* pending;
GstBuffer* committed;
} shm { nullptr, nullptr };
};
......@@ -24,7 +24,13 @@
* The wpesrc element is used to produce a video texture representing a web page
* rendered off-screen by WPE.
*
* ## Example launch line
* Starting from WPEBackend-FDO 1.6.x, software rendering support is available. This
* features allows wpesrc to be used on machines without GPU, and/or for testing
* purpose. To enable it, set the `LIBGL_ALWAYS_SOFTWARE=true` environment
* variable and make sure `video/x-raw, format=BGRA` caps are negotiated by the
* wpesrc element.
*
* ## Example launch lines
*
* |[
* gst-launch-1.0 -v wpesrc location="https://gstreamer.freedesktop.org" ! queue ! glimagesink
......@@ -32,6 +38,11 @@
* Shows the GStreamer website homepage
*
* |[
* LIBGL_ALWAYS_SOFTWARE=true gst-launch-1.0 -v wpesrc num-buffers=50 location="https://gstreamer.freedesktop.org" ! videoconvert ! pngenc ! multifilesink location=/tmp/snapshot-%05d.png
* ]|
* Saves the first 50 video frames generated for the GStreamer website as PNG files in /tmp.
*
* |[
* gst-play-1.0 --videosink gtkglsink wpe://https://gstreamer.freedesktop.org
* ]|
* Shows the GStreamer website homepage as played with GstPlayer in a GTK+ window.
......@@ -102,6 +113,7 @@ struct _GstWpeSrc
gboolean draw_background;
GBytes *bytes;
gboolean gl_enabled;
};
static void gst_wpe_src_uri_handler_init (gpointer iface, gpointer data);
......@@ -118,9 +130,41 @@ static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
"width = " GST_VIDEO_SIZE_RANGE ", "
"height = " GST_VIDEO_SIZE_RANGE ", "
"framerate = " GST_VIDEO_FPS_RANGE ", "
"pixel-aspect-ratio = (fraction)1/1," "texture-target = (string)2D")
"pixel-aspect-ratio = (fraction)1/1, texture-target = (string)2D;"
#if ENABLE_SHM_BUFFER_SUPPORT
"video/x-raw, "
"format = (string) BGRA, "
"width = " GST_VIDEO_SIZE_RANGE ", "
"height = " GST_VIDEO_SIZE_RANGE ", "
"framerate = " GST_VIDEO_FPS_RANGE ", "
"pixel-aspect-ratio = (fraction)1/1"
#endif
)
);
static GstFlowReturn
gst_wpe_src_create (GstBaseSrc * bsrc, guint64 offset, guint length, GstBuffer ** buf)
{
GstWpeSrc *src = GST_WPE_SRC (bsrc);
GstFlowReturn ret = GST_FLOW_ERROR;
GstBuffer *locked_buffer;
GST_OBJECT_LOCK (src);
if (src->gl_enabled) {
GST_OBJECT_UNLOCK (src);
return GST_CALL_PARENT_WITH_DEFAULT (GST_BASE_SRC_CLASS, create, (bsrc, offset, length, buf), ret);
}
locked_buffer = src->view->buffer ();
if (locked_buffer != NULL) {
*buf = gst_buffer_ref (locked_buffer);
ret = GST_FLOW_OK;
}
GST_OBJECT_UNLOCK (src);
return ret;
}
static gboolean
gst_wpe_src_fill_memory (GstGLBaseSrc * bsrc, GstGLMemory * memory)
{
......@@ -160,13 +204,28 @@ gst_wpe_src_gl_start (GstGLBaseSrc * base_src)
{
GstWpeSrc *src = GST_WPE_SRC (base_src);
gboolean result = TRUE;
GstCapsFeatures *caps_features;
GstGLContext *context = NULL;
GstGLDisplay *display = NULL;
GST_INFO_OBJECT (src, "Starting up");
GST_OBJECT_LOCK (src);
caps_features = gst_caps_get_features (base_src->out_caps, 0);
if (caps_features != NULL && gst_caps_features_contains (caps_features, GST_CAPS_FEATURE_MEMORY_GL_MEMORY)) {
src->gl_enabled = TRUE;
context = base_src->context;
display = base_src->display;
} else {
src->gl_enabled = FALSE;
}
GST_DEBUG_OBJECT (src, "Will fill GLMemories: %d\n", src->gl_enabled);
src->view = new WPEThreadedView;
result = src->view->initialize (src, base_src->context, base_src->display,
GST_VIDEO_INFO_WIDTH (&base_src->out_info),
GST_VIDEO_INFO_HEIGHT (&base_src->out_info));
result = src->view->initialize (src, context, display,
GST_VIDEO_INFO_WIDTH (&base_src->out_info),
GST_VIDEO_INFO_HEIGHT (&base_src->out_info));
if (src->bytes != NULL) {
src->view->loadData (src->bytes);
......@@ -484,6 +543,7 @@ gst_wpe_src_class_init (GstWpeSrcClass * klass)
gst_element_class_add_static_pad_template (gstelement_class, &src_factory);
base_src_class->fixate = GST_DEBUG_FUNCPTR (gst_wpe_src_fixate);
base_src_class->create = GST_DEBUG_FUNCPTR (gst_wpe_src_create);
gl_base_src_class->supported_gl_api =
static_cast < GstGLAPI >
......
......@@ -10,6 +10,7 @@ wpe_dep = dependency('wpe-webkit-1.0', version : '>= 2.24', required : get_optio
wpe_fdo_dep = dependency('wpebackend-fdo-1.0', required : get_option('wpe'))
egl_dep = dependency('egl', required : get_option('wpe'))
xkbcommon_dep = dependency('xkbcommon', version : '>= 0.8', required : get_option('wpe'))
wl_server_dep = dependency('wayland-server', required : get_option('wpe'))
if not wpe_dep.found() or not wpe_fdo_dep.found() or not egl_dep.found() or not xkbcommon_dep.found()
subdir_done()
......@@ -17,7 +18,7 @@ endif
gstwpe = library('gstwpe',
['WPEThreadedView.cpp', 'gstwpesrc.cpp'],
dependencies : [egl_dep, wpe_dep, wpe_fdo_dep, gstvideo_dep, gstbase_dep, gstgl_dep, xkbcommon_dep],
dependencies : [egl_dep, wpe_dep, wpe_fdo_dep, gstvideo_dep, gstbase_dep, gstgl_dep, xkbcommon_dep, wl_server_dep],
cpp_args : gst_plugins_bad_args + ['-DHAVE_CONFIG_H=1'],
include_directories : [configinc],
install : true,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment