Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • wayland/weston
  • valpackett/weston
  • daniels/weston
  • pq/weston
  • pochu/weston
  • lubosz/weston
  • phomes/weston
  • mvlad/weston
  • etom/weston
  • agners/weston
  • m.tretter/weston
  • pH5/weston
  • rohanjulka19/weston
  • mvaldina/weston
  • drawat/weston
  • emersion/weston
  • linkmauve/weston
  • jadahl/weston
  • tzimmermann/weston
  • cwjo/weston
  • ktullavik/weston
  • orbitcowboy/weston
  • ivyl/weston
  • afrantzis/weston
  • mol/weston
  • vliaskov/weston
  • inzamam.15/weston
  • xexaxo/weston
  • rmader/weston
  • eucan/weston
  • Eugeniy.Paltsev/weston
  • aknautiyal/weston
  • ascent/weston
  • dima/weston
  • ollieparanoid/weston
  • ant8me/weston
  • rdp.effort/weston
  • ewtoombs/weston
  • sjoerd/weston
  • harishkrupo/weston
  • eyelash/weston
  • zubzub/weston
  • mtey/weston
  • strassek/weston
  • bluesirhl/weston
  • makepost/weston
  • bentiss/weston
  • bugaevc/weston
  • derekf/weston
  • Vivek/weston
  • Rigo-V/weston
  • learning/weston
  • mstoeckl/weston
  • ayaka/weston
  • zumbi/weston
  • maxice8/weston
  • romangg/weston
  • JaredHu/weston
  • justdoGIT/weston
  • swick/weston
  • lucaweiss/weston
  • jameshilliard/weston
  • barry.song/weston
  • borneoa/weston
  • bbeckett/weston
  • Kishore409/weston
  • AIDEA775/weston
  • arandomhuman/weston
  • maos20008/weston
  • mvicomoya/weston
  • creiter/weston
  • bbrezillon/weston
  • hedone21/weston
  • shadeslayer/weston
  • ericruei/weston
  • lujin/weston
  • xeechou/weston
  • JeffyCN/weston
  • ajax/weston
  • hwti/weston
  • VKadasani/weston
  • khosokawa/weston
  • nniro/weston
  • RAOF/weston
  • ofourdan/weston
  • eero-t/weston
  • renjiayuan1314/weston
  • leandrohrb/weston
  • heemin.lee/weston
  • archiesix/weston
  • dude/weston
  • mforney/weston
  • marimeireles/weston
  • vitalyp/weston
  • rajendraprasadkj/weston
  • ahe/weston
  • ekurzinger/weston
  • champagneg/weston
  • dbaker/weston
  • liyi42/weston
  • saavedra.pablo/weston
  • afd/weston
  • tomek/weston
  • Cwiiis/weston
  • pmenzel/weston
  • therealkenc/weston
  • Igortorrente/weston
  • azeps/weston
  • msisov/weston
  • whot/weston
  • Fahien/weston
  • doubleagent3276/weston
  • Heartyharts/weston
  • kchibisov/weston
  • christian-rauch/weston
  • krh/weston
  • JimmyOhn/weston
  • luigi.santivetti/weston
  • bnieuwenhuizen/weston
  • pedestrianlove/weston
  • trem/weston
  • Ganjing0224/weston
  • thewayoftherob/weston
  • harpreetbasra1313/weston
  • dmitry.batrak1/weston
  • carbn/weston
  • n3rdopolis/weston
  • denix0/weston
  • NaveenKumar/weston
  • macpijan/weston
  • bigbear1385/weston
  • ShivakumarVH/weston
  • Ts/weston
  • Rpegusus2233/weston
  • hthiery/weston
  • Laplac2/weston
  • bnlrnz/weston
  • anurup_m/weston
  • kennylevinsen/weston
  • fallahmahid.mahdi/weston
  • dwrobel/weston
  • Ambyjkl/weston
  • mroussin/weston
  • wolf._.lael666/weston
  • xndcn/weston
  • nicolesager7/weston
  • tantan/weston
  • zzag/weston
  • uniontechWu/weston
  • marex/weston
  • 9531718244loco/weston
  • dhobsong/weston
  • jcline/weston
  • marler8997/weston
  • dr3020187/weston
  • cardenasvitealejandro/weston
  • kxing/weston_hpd
  • Robyn.marie/weston
  • Bastian-Krause/weston
  • hitong602/weston
  • filip-hejsek/weston
  • yjheo/weston
  • Alvarito050506/weston
  • enocknyaega/weston
  • yuanye100/weston
  • ColinKinloch/weston
  • pritbisw/weston
  • sameer.lattannavar/weston
  • dos/weston
  • jesstindean85/weston
  • ashie/weston
  • JoseExposito/weston
  • bgjdarm/weston
  • fanbaby6/weston
  • pinchyguey45/weston
  • jayjona42/weston
  • hwentland/weston
  • davidre/weston
  • soerenmeier/weston
  • matth/weston
  • fifi899173/weston
  • HarshaMM/weston
  • obbardc/weston
  • Wladmis/weston
  • alex.kanavin/weston
  • qyliss/weston
  • ekapllaj/weston
  • luckyziv/weston
  • qaqsw24/weston
  • g0hl1n/weston
  • yayowd/qimm
  • Vivalavina/weston
  • Shugyousha/weston
  • flakylawww/weston
  • chewi/weston
  • martinetd/weston
  • jlindgren90/weston
  • jianglei121381/weston
  • tpetazzoni/weston
  • shierote/weston
  • LARathbone/weston
  • wengxt/weston
  • vvavrychuk/weston
  • kusma/weston
  • Emantor/weston
  • Ivaniku/tayland
  • 5HT/weston
  • iason.paraskevopoulos/weston
  • jpewhacker/weston
  • ivan.nikolaenko/weston
  • OctopusET/weston
  • paraaz4959/weston
  • vnguyentrong/weston
  • PaulKocialkowski/weston
  • vyivel/weston
  • khangtb/weston
  • isinyaaa/weston
  • meshki022/weston
  • adoan/weston
  • YDinhVan/weston
  • stolk/weston
  • amaksoft/weston
  • flto/weston
  • molinari/weston
  • k77951586/weston
  • t-8ch/weston
  • mominurisiamm887/weston
  • SergioGDR/weston
  • xiangxuy/weston
  • petervdperk/weston
  • zhourunsheng2008/weston
  • vanvugt/weston
  • gilvbp/weston
  • gfxstrand/weston
  • rhelmot/weston
  • yadneshk/weston
  • phnaharris/weston
  • pixellon/weston
  • askebm/weston
  • ChaoGuo/weston
  • lk1025/weston
  • jh-hsd/weston
  • mihlenfeldt/weston
  • wujiansun/weston
  • bmkimg/weston
  • smit-mayani/weston
  • pritamabiswas/weston
  • adarshgm/weston
  • zzyiwei/weston
  • enunes/weston
  • HeYong/weston
  • rawoul/weston
  • andreinonea/weston
  • pleasurefish/weston
  • Foreal/weston
  • kraj/weston
  • rsmith/weston
  • zhouliang/weston
  • Benjamin_Loison/weston
  • daissi/weston
  • sophia/weston
  • wismill/weston
  • rgonzalez/weston
  • diegonieto/weston
  • rgallaispou/weston
  • sardemff7/weston
  • puhui/weston
  • vanfanel/weston
  • jwillikers/weston
  • gtristan/weston
  • ghishadow/weston
  • antonino/weston
  • Zamundaaa/weston
  • bl4ckb0ne/weston
  • david.turner/weston
  • surban/weston
  • chienpv/weston
  • sami/weston
  • chiragkhurana/weston
  • Calandracas/weston
  • lfrb/weston
  • abhinavk/weston
  • joantolo/weston
  • leoli/weston
  • benh/weston
  • igor.torrente/weston
  • jeri.li/weston
  • C0rn3j/weston
  • bbara93/weston
  • heftig/weston
  • longjunyu2/weston
  • davidedmundson/weston
  • zeerd/weston
  • tmaillart1/weston
  • phreer/weston
  • ianr/weston
  • gyeyoung976/weston
  • Trigger.Huang/weston
  • ljia5/weston
  • snow/weston
  • kang-sooyeon/weston
  • marysaka/weston
  • tmaillart/weston
  • Qingwu-Li/weston
  • BBaoVanC/weston
305 results
Show changes
Commits on Source (13)
......@@ -187,11 +187,13 @@ weston_LDFLAGS = -export-dynamic
weston_CPPFLAGS = $(AM_CPPFLAGS) -DIN_WESTON \
-DMODULEDIR='"$(moduledir)"' \
-DXSERVER_PATH='"@XSERVER_PATH@"'
weston_CFLAGS = $(AM_CFLAGS) $(COMPOSITOR_CFLAGS) $(LIBINPUT_BACKEND_CFLAGS)
weston_CFLAGS = $(AM_CFLAGS) $(COMPOSITOR_CFLAGS) $(LIBINPUT_BACKEND_CFLAGS) \
$(PTHREAD_CFLAGS)
weston_LDADD = libshared.la libweston-@LIBWESTON_MAJOR@.la \
$(COMPOSITOR_LIBS) \
$(DL_LIBS) $(LIBINPUT_BACKEND_LIBS) \
$(CLOCK_GETRES_LIBS) \
$(PTHREAD_LIBS) \
-lm
weston_SOURCES = \
......@@ -400,6 +402,23 @@ drm_backend_la_LIBADD += $(LIBVA_LIBS)
drm_backend_la_LDFLAGS += -pthread
drm_backend_la_CFLAGS += $(LIBVA_CFLAGS)
endif
# remoting
if ENABLE_REMOTING
libweston_module_LTLIBRARIES += remoting-plugin.la
remoting_plugin_la_LDFLAGS = -module -avoid-version
remoting_plugin_la_LIBADD = \
$(COMPOSITOR_LIBS) \
$(REMOTING_GST_LIBS)
remoting_plugin_la_CFLAGS = \
$(COMPOSITOR_CFLAGS) \
$(REMOTING_GST_CFLAGS) \
$(AM_CFLAGS)
remoting_plugin_la_SOURCES = \
remoting/remoting-plugin.c \
remoting/remoting-plugin.h
endif
endif
if ENABLE_WAYLAND_COMPOSITOR
......
......@@ -392,8 +392,11 @@ drm_device_init(struct buffer *buf)
#ifdef HAVE_LIBDRM_INTEL
else if (!strcmp(dev->name, "i915")) {
buf->bufmgr = drm_intel_bufmgr_gem_init(buf->drm_fd, 32);
if (!buf->bufmgr)
if (!buf->bufmgr) {
free(dev->name);
free(dev);
return 0;
}
dev->alloc_bo = intel_alloc_bo;
dev->free_bo = intel_free_bo;
dev->export_bo_to_prime = intel_bo_export_to_prime;
......@@ -425,6 +428,7 @@ drm_device_init(struct buffer *buf)
else {
fprintf(stderr, "Error: drm device %s unsupported.\n",
dev->name);
free(dev->name);
free(dev);
return 0;
}
......
......@@ -61,6 +61,7 @@
#include "compositor-wayland.h"
#include "windowed-output-api.h"
#include "weston-debug.h"
#include "../remoting/remoting-plugin.h"
#define WINDOW_TITLE "Weston Compositor"
......@@ -1973,6 +1974,154 @@ drm_heads_changed(struct wl_listener *listener, void *arg)
wet->init_failed = true;
}
static int
drm_backend_remoted_output_configure(struct weston_output *output,
struct weston_config_section *section,
char *modeline,
const struct weston_remoting_api *api)
{
char *gbm_format = NULL;
char *seat = NULL;
char *host = NULL;
int port, ret;
ret = api->set_mode(output, modeline);
if (ret < 0) {
weston_log("Cannot configure an output \"%s\" using "
"weston_remoting_api. Invalid mode\n",
output->name);
return -1;
}
wet_output_set_scale(output, section, 1, 0);
wet_output_set_transform(output, section, WL_OUTPUT_TRANSFORM_NORMAL,
UINT32_MAX);
weston_config_section_get_string(section, "gbm-format", &gbm_format,
NULL);
api->set_gbm_format(output, gbm_format);
free(gbm_format);
weston_config_section_get_string(section, "seat", &seat, "");
api->set_seat(output, seat);
free(seat);
weston_config_section_get_string(section, "host", &host, NULL);
if (!host) {
weston_log("Cannot configure an output \"%s\". Invalid host\n",
output->name);
return -1;
}
api->set_host(output, host);
free(host);
weston_config_section_get_int(section, "port", &port, 0);
if (port <= 0 || 65533 < port) {
weston_log("Cannot configure an output \"%s\". Invalid port\n",
output->name);
return -1;
}
api->set_port(output, port);
return 0;
}
static void
remoted_output_init(struct weston_compositor *c,
struct weston_config_section *section,
const struct weston_remoting_api *api)
{
struct weston_output *output = NULL;
char *output_name, *modeline = NULL;
int ret;
weston_config_section_get_string(section, "name", &output_name,
NULL);
if (!output_name)
return;
weston_config_section_get_string(section, "mode", &modeline, "off");
if (strcmp(modeline, "off") == 0)
goto err;
output = api->create_output(c, output_name);
if (!output) {
weston_log("Cannot create remoted output \"%s\".\n",
output_name);
goto err;
}
ret = drm_backend_remoted_output_configure(output, section, modeline,
api);
if (ret < 0) {
weston_log("Cannot configure remoted output \"%s\".\n",
output_name);
goto err;
}
if (weston_output_enable(output) < 0) {
weston_log("Enabling remoted output \"%s\" failed.\n",
output_name);
goto err;
}
free(modeline);
free(output_name);
weston_log("remoted output '%s' enabled\n", output->name);
return;
err:
free(modeline);
free(output_name);
if (output)
weston_output_destroy(output);
}
static void
load_remoting(struct weston_compositor *c, struct weston_config *wc)
{
const struct weston_remoting_api *api = NULL;
int (*module_init)(struct weston_compositor *ec);
struct weston_config_section *section = NULL;
const char *section_name;
/* read remote-output section in weston.ini */
while (weston_config_next_section(wc, &section, &section_name)) {
if (strcmp(section_name, "remote-output"))
continue;
if (!api) {
char *module_name;
struct weston_config_section *core_section =
weston_config_get_section(wc, "core", NULL,
NULL);
weston_config_section_get_string(core_section,
"remoting",
&module_name,
"remoting-plugin.so");
module_init = weston_load_module(module_name,
"weston_module_init");
free(module_name);
if (!module_init) {
weston_log("Can't load remoting-plugin\n");
return;
}
if (module_init(c) < 0) {
weston_log("Remoting-plugin init failed\n");
return;
}
api = weston_remoting_get_api(c);
if (!api)
return;
}
remoted_output_init(c, section, api);
}
}
static int
load_drm_backend(struct weston_compositor *c,
int *argc, char **argv, struct weston_config *wc)
......@@ -2015,6 +2164,9 @@ load_drm_backend(struct weston_compositor *c,
ret = weston_compositor_load_backend(c, WESTON_BACKEND_DRM,
&config.base);
/* remoting */
load_remoting(c, wc);
free(config.gbm_format);
free(config.seat_id);
......@@ -2531,6 +2683,8 @@ int main(int argc, char *argv[])
struct weston_seat *seat;
struct wet_compositor wet = { 0 };
int require_input;
sigset_t mask;
int32_t wait_for_debugger = 0;
struct wl_protocol_logger *protologger = NULL;
......@@ -2601,6 +2755,14 @@ int main(int argc, char *argv[])
if (!signals[0] || !signals[1] || !signals[2] || !signals[3])
goto out_signals;
/* Xwayland uses SIGUSR1 for communicating with weston. Since some
weston plugins may create additional threads, set up any necessary
signal blocking early so that these threads can inherit the settings
when created. */
sigemptyset(&mask);
sigaddset(&mask, SIGUSR1);
pthread_sigmask(SIG_BLOCK, &mask, NULL);
if (load_configuration(&config, noconfig, config_file) < 0)
goto out_signals;
wet.config = config;
......
......@@ -91,6 +91,9 @@ AC_ARG_VAR([WESTON_SHELL_CLIENT],
PKG_PROG_PKG_CONFIG()
# Check pthread
AX_PTHREAD
# Check for dlsym instead of dlopen because ASAN hijacks the latter
WESTON_SEARCH_LIBS([DL], [dl], [dlsym])
......@@ -223,6 +226,16 @@ if test x$enable_drm_compositor = xyes; then
[AC_MSG_WARN([GBM does not support dmabuf import, will omit that capability])])
fi
AC_ARG_ENABLE(remoting, [ --enable-remoting],,
enable_remoting=no)
AM_CONDITIONAL(ENABLE_REMOTING, test x$enable_remoting = xyes)
if test x$enable_remoting = xyes; then
if test x$enable_drm_compositor != xyes; then
AC_MSG_WARN([The remoting-plugin.so module requires the DRM backend.])
fi
PKG_CHECK_MODULES(REMOTING_GST, [gstreamer-1.0 gstreamer-allocators-1.0 gstreamer-app-1.0 gstreamer-video-1.0])
fi
PKG_CHECK_MODULES(LIBINPUT_BACKEND, [libinput >= 0.8.0])
PKG_CHECK_MODULES(COMPOSITOR, [$COMPOSITOR_MODULES])
......@@ -724,6 +737,7 @@ AC_MSG_RESULT([
systemd notify support ${enable_systemd_notify}
DRM Compositor ${enable_drm_compositor}
Remoting ${enable_remoting}
X11 Compositor ${enable_x11_compositor}
Wayland Compositor ${enable_wayland_compositor}
Headless Compositor ${enable_headless_compositor}
......
#!/bin/bash
# Copyright © 2018 Renesas Electronics Corp.
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice (including the
# next paragraph) shall be included in all copies or substantial
# portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# Authors: IGEL Co., Ltd.
# By using this script, client can receive remoted output via gstreamer.
# Usage:
# remoting-client-receive.bash <PORT NUMBER>
gst-launch-1.0 rtpbin name=rtpbin \
udpsrc caps="application/x-rtp,media=(string)video,clock-rate=(int)90000,encoding-name=JPEG,payload=26" port=$1 ! \
rtpbin.recv_rtp_sink_0 \
rtpbin. ! rtpjpegdepay ! jpegdec ! autovideosink \
udpsrc port=$(($1 + 1)) ! rtpbin.recv_rtcp_sink_0 \
rtpbin.send_rtcp_src_0 ! \
udpsink port=$(($1 + 2)) sync=false async=false
......@@ -586,44 +586,28 @@ update_prop(struct ivi_layout_view *ivi_view)
weston_view_schedule_repaint(ivi_view->view);
}
static bool
ivi_view_is_mapped(struct ivi_layout_view *ivi_view)
{
return (!wl_list_empty(&ivi_view->order_link) &&
ivi_view->on_layer->on_screen &&
ivi_view->on_layer->prop.visibility &&
ivi_view->ivisurf->prop.visibility);
}
static void
commit_changes(struct ivi_layout *layout)
{
struct ivi_layout_screen *iviscrn = NULL;
struct ivi_layout_layer *ivilayer = NULL;
struct ivi_layout_surface *ivisurf = NULL;
struct ivi_layout_view *ivi_view = NULL;
wl_list_for_each(ivi_view, &layout->view_list, link) {
ivisurf = ivi_view->ivisurf;
ivilayer = ivi_view->on_layer;
iviscrn = ivilayer->on_screen;
/*
* If the view is not on the currently rendered scenegraph,
* we do not need to update its properties.
*/
if (wl_list_empty(&ivi_view->order_link) || !iviscrn)
if (!ivi_view_is_mapped(ivi_view))
continue;
/*
* If the view's layer or surface is invisible, we do not need
* to update its properties.
*/
if (!ivilayer->prop.visibility || !ivisurf->prop.visibility) {
/*
* If ivilayer or ivisurf of ivi_view is made invisible
* in this commit_changes call, we have to damage
* the weston_view below this ivi_view. Otherwise content
* of this ivi_view will stay visible.
*/
if ((ivilayer->prop.event_mask | ivisurf->prop.event_mask) &
IVI_NOTIFICATION_VISIBILITY)
weston_view_damage_below(ivi_view->view);
continue;
}
update_prop(ivi_view);
}
}
......@@ -780,10 +764,6 @@ commit_screen_list(struct ivi_layout *layout)
struct ivi_layout_screen *iviscrn = NULL;
struct ivi_layout_layer *ivilayer = NULL;
struct ivi_layout_layer *next = NULL;
struct ivi_layout_view *ivi_view = NULL;
/* Clear view list of layout ivi_layer */
wl_list_init(&layout->layout_layer.view_list.link);
wl_list_for_each(iviscrn, &layout->screen_list, link) {
if (iviscrn->order.dirty) {
......@@ -810,7 +790,28 @@ commit_screen_list(struct ivi_layout *layout)
iviscrn->order.dirty = 0;
}
}
}
static void
build_view_list(struct ivi_layout *layout)
{
struct ivi_layout_screen *iviscrn;
struct ivi_layout_layer *ivilayer;
struct ivi_layout_view *ivi_view;
/* If ivi_view is not part of the scenegrapgh, we have to unmap
* weston_views
*/
wl_list_for_each(ivi_view, &layout->view_list, link) {
if (!ivi_view_is_mapped(ivi_view))
weston_view_unmap(ivi_view->view);
}
/* Clear view list of layout ivi_layer */
wl_list_init(&layout->layout_layer.view_list.link);
wl_list_for_each(iviscrn, &layout->screen_list, link) {
wl_list_for_each(ivilayer, &iviscrn->order.layer_list, order.link) {
if (ivilayer->prop.visibility == false)
continue;
......@@ -1751,6 +1752,7 @@ ivi_layout_commit_changes(void)
commit_surface_list(layout);
commit_layer_list(layout);
commit_screen_list(layout);
build_view_list(layout);
commit_transition(layout);
......
......@@ -74,6 +74,10 @@
#define GBM_BO_USE_CURSOR GBM_BO_USE_CURSOR_64X64
#endif
#ifndef GBM_BO_USE_LINEAR
#define GBM_BO_USE_LINEAR (1 << 4)
#endif
/**
* A small wrapper to print information into the 'drm-backend' debug scope.
*
......@@ -342,6 +346,8 @@ struct drm_backend {
bool aspect_ratio_supported;
bool fb_modifiers;
struct weston_debug_scope *debug;
};
......@@ -369,6 +375,7 @@ struct drm_fb {
uint32_t handles[4];
uint32_t strides[4];
uint32_t offsets[4];
int num_planes;
const struct pixel_format_info *format;
uint64_t modifier;
int width, height;
......@@ -526,6 +533,7 @@ struct drm_output {
struct gbm_surface *gbm_surface;
uint32_t gbm_format;
uint32_t gbm_bo_flags;
/* Plane being displayed directly on the CRTC */
struct drm_plane *scanout_plane;
......@@ -545,6 +553,10 @@ struct drm_output {
struct wl_listener recorder_frame_listener;
struct wl_event_source *pageflip_timer;
bool virtual;
submit_frame_cb virtual_submit_frame;
};
static const char *const aspect_ratio_as_string[] = {
......@@ -857,6 +869,9 @@ drm_output_update_msc(struct drm_output *output, unsigned int seq);
static void
drm_output_destroy(struct weston_output *output_base);
static void
drm_virtual_output_destroy(struct weston_output *output_base);
/**
* Returns true if the plane can be used on the given output for its current
* repaint cycle.
......@@ -866,6 +881,9 @@ drm_plane_is_available(struct drm_plane *plane, struct drm_output *output)
{
assert(plane->state_cur);
if (output->virtual)
return false;
/* The plane still has a request not yet completed by the kernel. */
if (!plane->state_cur->complete)
return false;
......@@ -945,7 +963,7 @@ drm_fb_destroy_gbm(struct gbm_bo *bo, void *data)
}
static int
drm_fb_addfb(struct drm_fb *fb)
drm_fb_addfb(struct drm_backend *b, struct drm_fb *fb)
{
int ret = -EINVAL;
#ifdef HAVE_DRM_ADDFB2_MODIFIERS
......@@ -955,7 +973,7 @@ drm_fb_addfb(struct drm_fb *fb)
/* If we have a modifier set, we must only use the WithModifiers
* entrypoint; we cannot import it through legacy ioctls. */
if (fb->modifier != DRM_FORMAT_MOD_INVALID) {
if (b->fb_modifiers && fb->modifier != DRM_FORMAT_MOD_INVALID) {
/* KMS demands that if a modifier is set, it must be the same
* for all planes. */
#ifdef HAVE_DRM_ADDFB2_MODIFIERS
......@@ -1033,12 +1051,13 @@ drm_fb_create_dumb(struct drm_backend *b, int width, int height,
fb->modifier = DRM_FORMAT_MOD_INVALID;
fb->handles[0] = create_arg.handle;
fb->strides[0] = create_arg.pitch;
fb->num_planes = 1;
fb->size = create_arg.size;
fb->width = width;
fb->height = height;
fb->fd = b->drm.fd;
if (drm_fb_addfb(fb) != 0) {
if (drm_fb_addfb(b, fb) != 0) {
weston_log("failed to create kms fb: %m\n");
goto err_bo;
}
......@@ -1204,13 +1223,14 @@ drm_fb_get_from_dmabuf(struct linux_dmabuf_buffer *dmabuf,
goto err_free;
}
fb->num_planes = dmabuf->attributes.n_planes;
for (i = 0; i < dmabuf->attributes.n_planes; i++) {
fb->handles[i] = gbm_bo_get_handle_for_plane(fb->bo, i).u32;
if (!fb->handles[i])
goto err_free;
}
if (drm_fb_addfb(fb) != 0)
if (drm_fb_addfb(backend, fb) != 0)
goto err_free;
return fb;
......@@ -1251,12 +1271,14 @@ drm_fb_get_from_bo(struct gbm_bo *bo, struct drm_backend *backend,
#ifdef HAVE_GBM_MODIFIERS
fb->modifier = gbm_bo_get_modifier(bo);
for (i = 0; i < gbm_bo_get_plane_count(bo); i++) {
fb->num_planes = gbm_bo_get_plane_count(bo);
for (i = 0; i < fb->num_planes; i++) {
fb->strides[i] = gbm_bo_get_stride_for_plane(bo, i);
fb->handles[i] = gbm_bo_get_handle_for_plane(bo, i).u32;
fb->offsets[i] = gbm_bo_get_offset(bo, i);
}
#else
fb->num_planes = 1;
fb->strides[0] = gbm_bo_get_stride(bo);
fb->handles[0] = gbm_bo_get_handle(bo).u32;
fb->modifier = DRM_FORMAT_MOD_INVALID;
......@@ -1281,7 +1303,7 @@ drm_fb_get_from_bo(struct gbm_bo *bo, struct drm_backend *backend,
goto err_free;
}
if (drm_fb_addfb(fb) != 0) {
if (drm_fb_addfb(backend, fb) != 0) {
if (type == BUFFER_GBM_SURFACE)
weston_log("failed to create kms fb: %m\n");
goto err_free;
......@@ -2662,6 +2684,8 @@ drm_pending_state_apply_atomic(struct drm_pending_state *pending_state,
}
wl_list_for_each(output_state, &pending_state->output_list, link) {
if (output_state->output->virtual)
continue;
if (mode == DRM_STATE_APPLY_SYNC)
assert(output_state->dpms == WESTON_DPMS_OFF);
ret |= drm_output_apply_state_atomic(output_state, req, &flags);
......@@ -2771,6 +2795,12 @@ drm_pending_state_apply(struct drm_pending_state *pending_state)
struct drm_output *output = output_state->output;
int ret;
if (output->virtual) {
drm_output_assign_state(output_state,
DRM_STATE_APPLY_ASYNC);
continue;
}
ret = drm_output_apply_state_legacy(output_state);
if (ret != 0) {
weston_log("Couldn't apply state for output %s\n",
......@@ -2849,6 +2879,8 @@ drm_output_repaint(struct weston_output *output_base,
struct drm_output_state *state = NULL;
struct drm_plane_state *scanout_state;
assert(!output->virtual);
if (output->disable_pending || output->destroy_pending)
goto err;
......@@ -3723,7 +3755,7 @@ drm_assign_planes(struct weston_output *output_base, void *repaint_data)
drm_debug(b, "\t[repaint] preparing state for output %s (%lu)\n",
output_base->name, (unsigned long) output_base->id);
if (!b->sprites_are_broken) {
if (!b->sprites_are_broken && !output->virtual) {
state = drm_output_propose_state(output_base, pending_state,
DRM_OUTPUT_PROPOSE_STATE_PLANES_ONLY);
if (!state) {
......@@ -4032,6 +4064,14 @@ init_kms_caps(struct drm_backend *b)
weston_log("DRM: %s atomic modesetting\n",
b->atomic_modeset ? "supports" : "does not support");
#ifdef HAVE_DRM_ADDFB2_MODIFIERS
ret = drmGetCap(b->drm.fd, DRM_CAP_ADDFB2_MODIFIERS, &cap);
if (ret == 0)
b->fb_modifiers = cap;
else
#endif
b->fb_modifiers = 0;
/*
* KMS support for hardware planes cannot properly synchronize
* without nuclear page flip. Without nuclear/atomic, hw plane
......@@ -4442,6 +4482,63 @@ drm_plane_destroy(struct drm_plane *plane)
free(plane);
}
/**
* Create a drm_plane for virtual output
*
* Call drm_virtual_plane_destroy to clean up the plane.
*
* @param b DRM compositor backend
* @param output Output to create internal plane for
*/
static struct drm_plane *
drm_virtual_plane_create(struct drm_backend *b, struct drm_output *output)
{
struct drm_plane *plane;
/* num of formats is one */
plane = zalloc(sizeof(*plane) + sizeof(plane->formats[0]));
if (!plane) {
weston_log("%s: out of memory\n", __func__);
return NULL;
}
plane->type = WDRM_PLANE_TYPE_PRIMARY;
plane->backend = b;
plane->state_cur = drm_plane_state_alloc(NULL, plane);
plane->state_cur->complete = true;
plane->formats[0].format = output->gbm_format;
plane->count_formats = 1;
if (output->gbm_bo_flags & GBM_BO_USE_LINEAR) {
uint64_t *modifiers = zalloc(sizeof *modifiers);
if (modifiers) {
*modifiers = DRM_FORMAT_MOD_LINEAR;
plane->formats[0].modifiers = modifiers;
plane->formats[0].count_modifiers = 1;
}
}
weston_plane_init(&plane->base, b->compositor, 0, 0);
wl_list_insert(&b->plane_list, &plane->link);
return plane;
}
/**
* Destroy one DRM plane
*
* @param plane Plane to deallocate (will be freed)
*/
static void
drm_virtual_plane_destroy(struct drm_plane *plane)
{
drm_plane_state_free(plane->state_cur, true);
weston_plane_release(&plane->base);
wl_list_remove(&plane->link);
if (plane->formats[0].modifiers)
free(plane->formats[0].modifiers);
free(plane);
}
/**
* Initialise sprites (overlay planes)
*
......@@ -4675,6 +4772,8 @@ drm_output_init_backlight(struct drm_output *output)
*
* If we are called as part of repaint, we simply set the relevant bit in
* state and return.
*
* This function is never called on a virtual output.
*/
static void
drm_set_dpms(struct weston_output *output_base, enum dpms_enum level)
......@@ -4685,6 +4784,8 @@ drm_set_dpms(struct weston_output *output_base, enum dpms_enum level)
struct drm_output_state *state;
int ret;
assert(!output->virtual);
if (output->state_cur->dpms == level)
return;
......@@ -4871,7 +4972,7 @@ drm_output_init_egl(struct drm_output *output, struct drm_backend *b)
output->gbm_surface =
gbm_surface_create(b->gbm, mode->width, mode->height,
output->gbm_format,
GBM_BO_USE_RENDERING | GBM_BO_USE_SCANOUT);
output->gbm_bo_flags);
}
if (!output->gbm_surface) {
......@@ -5585,6 +5686,9 @@ drm_output_set_mode(struct weston_output *base,
struct drm_mode *current;
if (output->virtual)
return -1;
if (drm_output_update_modelist_from_heads(output) < 0)
return -1;
......@@ -5942,6 +6046,8 @@ drm_output_enable(struct weston_output *base)
drmModeRes *resources;
int ret;
assert(!output->virtual);
resources = drmModeGetResources(b->drm.fd);
if (!resources) {
weston_log("drmModeGetResources failed\n");
......@@ -6039,6 +6145,8 @@ drm_output_destroy(struct weston_output *base)
struct drm_output *output = to_drm_output(base);
struct drm_backend *b = to_drm_backend(base->compositor);
assert(!output->virtual);
if (output->page_flip_pending || output->vblank_pending ||
output->atomic_complete_pending) {
output->destroy_pending = 1;
......@@ -6067,6 +6175,8 @@ drm_output_disable(struct weston_output *base)
{
struct drm_output *output = to_drm_output(base);
assert(!output->virtual);
if (output->page_flip_pending || output->vblank_pending ||
output->atomic_complete_pending) {
output->disable_pending = 1;
......@@ -6320,6 +6430,7 @@ drm_output_create(struct weston_compositor *compositor, const char *name)
return NULL;
output->backend = b;
output->gbm_bo_flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING;
weston_output_init(&output->base, compositor, name);
......@@ -6902,12 +7013,269 @@ renderer_switch_binding(struct weston_keyboard *keyboard,
switch_to_gl_renderer(b);
}
static void
drm_virtual_output_start_repaint_loop(struct weston_output *output_base)
{
weston_output_finish_frame(output_base, NULL,
WP_PRESENTATION_FEEDBACK_INVALID);
}
static int
drm_virtual_output_submit_frame(struct drm_output *output,
struct drm_fb *fb)
{
struct drm_backend *b = to_drm_backend(output->base.compositor);
int fd, ret;
assert(fb->num_planes == 1);
ret = drmPrimeHandleToFD(b->drm.fd, fb->handles[0], DRM_CLOEXEC, &fd);
if (ret) {
weston_log("drmPrimeHandleFD failed, errno=%d\n", errno);
return -1;
}
drm_fb_ref(fb);
ret = output->virtual_submit_frame(&output->base, fd, fb->strides[0],
fb);
if (ret < 0) {
drm_fb_unref(fb);
close(fd);
}
return ret;
}
static int
drm_virtual_output_repaint(struct weston_output *output_base,
pixman_region32_t *damage,
void *repaint_data)
{
struct drm_pending_state *pending_state = repaint_data;
struct drm_output_state *state = NULL;
struct drm_output *output = to_drm_output(output_base);
struct drm_plane *scanout_plane = output->scanout_plane;
struct drm_plane_state *scanout_state;
assert(output->virtual);
if (output->disable_pending || output->destroy_pending)
goto err;
/* Drop frame if there isn't free buffers */
if (!gbm_surface_has_free_buffers(output->gbm_surface)) {
weston_log("%s: Drop frame!!\n", __func__);
return -1;
}
assert(!output->state_last);
/* If planes have been disabled in the core, we might not have
* hit assign_planes at all, so might not have valid output state
* here. */
state = drm_pending_state_get_output(pending_state, output);
if (!state)
state = drm_output_state_duplicate(output->state_cur,
pending_state,
DRM_OUTPUT_STATE_CLEAR_PLANES);
drm_output_render(state, damage);
scanout_state = drm_output_state_get_plane(state, scanout_plane);
if (!scanout_state || !scanout_state->fb)
goto err;
if (drm_virtual_output_submit_frame(output, scanout_state->fb) < 0)
goto err;
return 0;
err:
drm_output_state_free(state);
return -1;
}
static void
drm_virtual_output_deinit(struct weston_output *base)
{
struct drm_output *output = to_drm_output(base);
drm_output_fini_egl(output);
drm_virtual_plane_destroy(output->scanout_plane);
}
static void
drm_virtual_output_destroy(struct weston_output *base)
{
struct drm_output *output = to_drm_output(base);
assert(output->virtual);
if (output->base.enabled)
drm_virtual_output_deinit(&output->base);
weston_output_release(&output->base);
drm_output_state_free(output->state_cur);
free(output);
}
static int
drm_virtual_output_enable(struct weston_output *output_base)
{
struct drm_output *output = to_drm_output(output_base);
struct drm_backend *b = to_drm_backend(output_base->compositor);
assert(output->virtual);
if (b->use_pixman) {
weston_log("Not support pixman renderer on Virtual output\n");
goto err;
}
if (!output->virtual_submit_frame) {
weston_log("The virtual_submit_frame hook is not set\n");
goto err;
}
output->scanout_plane = drm_virtual_plane_create(b, output);
if (!output->scanout_plane) {
weston_log("Failed to find primary plane for output %s\n",
output->base.name);
return -1;
}
if (drm_output_init_egl(output, b) < 0) {
weston_log("Failed to init output gl state\n");
goto err;
}
output->base.start_repaint_loop = drm_virtual_output_start_repaint_loop;
output->base.repaint = drm_virtual_output_repaint;
output->base.assign_planes = drm_assign_planes;
output->base.set_dpms = NULL;
output->base.switch_mode = NULL;
output->base.gamma_size = 0;
output->base.set_gamma = NULL;
weston_compositor_stack_plane(b->compositor,
&output->scanout_plane->base,
&b->compositor->primary_plane);
return 0;
err:
return -1;
}
static int
drm_virtual_output_disable(struct weston_output *base)
{
struct drm_output *output = to_drm_output(base);
assert(output->virtual);
if (output->base.enabled)
drm_virtual_output_deinit(&output->base);
return 0;
}
static struct weston_output *
drm_virtual_output_create(struct weston_compositor *c, char *name)
{
struct drm_output *output;
output = zalloc(sizeof *output);
if (!output)
return NULL;
output->virtual = true;
output->gbm_bo_flags = GBM_BO_USE_LINEAR | GBM_BO_USE_RENDERING;
weston_output_init(&output->base, c, name);
output->base.enable = drm_virtual_output_enable;
output->base.destroy = drm_virtual_output_destroy;
output->base.disable = drm_virtual_output_disable;
output->base.attach_head = NULL;
output->state_cur = drm_output_state_alloc(output, NULL);
weston_compositor_add_pending_output(&output->base, c);
return &output->base;
}
static uint32_t
drm_virtual_output_set_gbm_format(struct weston_output *base,
const char *gbm_format)
{
struct drm_output *output = to_drm_output(base);
struct drm_backend *b = to_drm_backend(base->compositor);
if (parse_gbm_format(gbm_format, b->gbm_format, &output->gbm_format) == -1)
output->gbm_format = b->gbm_format;
return output->gbm_format;
}
static void
drm_virtual_output_set_submit_frame_cb(struct weston_output *output_base,
submit_frame_cb cb)
{
struct drm_output *output = to_drm_output(output_base);
output->virtual_submit_frame = cb;
}
static int
drm_virtual_output_get_fence_fd(struct weston_output *output_base)
{
return gl_renderer->create_fence_fd(output_base);
}
static void
drm_virtual_output_buffer_released(struct drm_fb *fb)
{
drm_fb_unref(fb);
}
static void
drm_virtual_output_finish_frame(struct weston_output *output_base,
struct timespec *stamp,
uint32_t presented_flags)
{
struct drm_output *output = to_drm_output(output_base);
struct drm_plane_state *ps;
wl_list_for_each(ps, &output->state_cur->plane_list, link)
ps->complete = true;
drm_output_state_free(output->state_last);
output->state_last = NULL;
weston_output_finish_frame(&output->base, stamp, presented_flags);
/* We can't call this from frame_notify, because the output's
* repaint needed flag is cleared just after that */
if (output->recorder)
weston_output_schedule_repaint(&output->base);
}
static const struct weston_drm_output_api api = {
drm_output_set_mode,
drm_output_set_gbm_format,
drm_output_set_seat,
};
static const struct weston_drm_virtual_output_api virt_api = {
drm_virtual_output_create,
drm_virtual_output_set_gbm_format,
drm_virtual_output_set_submit_frame_cb,
drm_virtual_output_get_fence_fd,
drm_virtual_output_buffer_released,
drm_virtual_output_finish_frame
};
static struct drm_backend *
drm_backend_create(struct weston_compositor *compositor,
struct weston_drm_backend_config *config)
......@@ -7072,6 +7440,14 @@ drm_backend_create(struct weston_compositor *compositor,
goto err_udev_monitor;
}
ret = weston_plugin_api_register(compositor,
WESTON_DRM_VIRTUAL_OUTPUT_API_NAME,
&virt_api, sizeof(virt_api));
if (ret < 0) {
weston_log("Failed to register virtual output API.\n");
goto err_udev_monitor;
}
return b;
err_udev_monitor:
......
......@@ -90,6 +90,79 @@ weston_drm_output_get_api(struct weston_compositor *compositor)
return (const struct weston_drm_output_api *)api;
}
#define WESTON_DRM_VIRTUAL_OUTPUT_API_NAME "weston_drm_virtual_output_api_v1"
struct drm_fb;
typedef int (*submit_frame_cb)(struct weston_output *output, int fd,
int stride, struct drm_fb *buffer);
struct weston_drm_virtual_output_api {
/** Create virtual output.
* This is a low-level function, where the caller is expected to wrap
* the weston_output function pointers as necessary to make the virtual
* output useful. The caller must set up output make, model, serial,
* physical size, the mode list and current mode.
*
* Returns output on success, NULL on failure.
*/
struct weston_output* (*create_output)(struct weston_compositor *c,
char *name);
/** Set pixel format same as drm_output set_gbm_format().
*
* Returns the set format.
*/
uint32_t (*set_gbm_format)(struct weston_output *output,
const char *gbm_format);
/** Set a callback to be called when the DRM-backend has drawn a new
* frame and submits it for display.
* The callback will deliver a buffer to the virtual output's the
* owner and assumes the buffer is now reserved for the owner. The
* callback is called in virtual output repaint function.
* The caller must call buffer_released() and finish_frame().
*
* The callback parameters are output, FD and stride (bytes) of dmabuf,
* and buffer (drm_fb) pointer.
* The callback returns 0 on success, -1 on failure.
*
* The submit_frame_cb callback hook is responsible for closing the fd
* if it returns success. One needs to call the buffer release and
* finish frame functions if and only if this hook returns success.
*/
void (*set_submit_frame_cb)(struct weston_output *output,
submit_frame_cb cb);
/** Get fd for renderer fence.
* The returned fence signals when the renderer job has completed and
* the buffer is fully drawn.
*
* Returns fd on success, -1 on failure.
*/
int (*get_fence_sync_fd)(struct weston_output *output);
/** Notify that the caller has finished using buffer */
void (*buffer_released)(struct drm_fb *fb);
/** Notify finish frame
* This function allows the output repainting mechanism to advance to
* the next frame.
*/
void (*finish_frame)(struct weston_output *output,
struct timespec *stamp,
uint32_t presented_flags);
};
static inline const struct weston_drm_virtual_output_api *
weston_drm_virtual_output_get_api(struct weston_compositor *compositor)
{
const void *api;
api = weston_plugin_api_get(compositor,
WESTON_DRM_VIRTUAL_OUTPUT_API_NAME,
sizeof(struct weston_drm_virtual_output_api));
return (const struct weston_drm_virtual_output_api *)api;
}
/** The backend configuration struct.
*
* weston_drm_backend_config contains the configuration used by a DRM
......
......@@ -106,6 +106,8 @@ struct gl_output_state {
struct weston_matrix output_matrix;
EGLSyncKHR begin_render_sync, end_render_sync;
/* struct timeline_render_point::link */
struct wl_list timeline_render_point_list;
};
......@@ -367,11 +369,11 @@ timeline_render_point_handler(int fd, uint32_t mask, void *data)
}
static EGLSyncKHR
timeline_create_render_sync(struct gl_renderer *gr)
create_render_sync(struct gl_renderer *gr)
{
static const EGLint attribs[] = { EGL_NONE };
if (!weston_timeline_enabled_ || !gr->has_native_fence_sync)
if (!gr->has_native_fence_sync)
return EGL_NO_SYNC_KHR;
return gr->create_sync(gr->egl_display, EGL_SYNC_NATIVE_FENCE_ANDROID,
......@@ -400,12 +402,12 @@ timeline_submit_render_sync(struct gl_renderer *gr,
fd = gr->dup_native_fence_fd(gr->egl_display, sync);
if (fd == EGL_NO_NATIVE_FENCE_FD_ANDROID)
goto out;
return;
trp = zalloc(sizeof *trp);
if (trp == NULL) {
close(fd);
goto out;
return;
}
trp->type = type;
......@@ -417,9 +419,6 @@ timeline_submit_render_sync(struct gl_renderer *gr,
trp);
wl_list_insert(&go->timeline_render_point_list, &trp->link);
out:
gr->destroy_sync(gr->egl_display, sync);
}
static struct egl_image*
......@@ -1254,12 +1253,16 @@ gl_renderer_repaint_output(struct weston_output *output,
pixman_box32_t *rects;
pixman_region32_t buffer_damage, total_damage;
enum gl_border_status border_damage = BORDER_STATUS_CLEAN;
EGLSyncKHR begin_render_sync, end_render_sync;
if (use_output(output) < 0)
return;
begin_render_sync = timeline_create_render_sync(gr);
if (go->begin_render_sync != EGL_NO_SYNC_KHR)
gr->destroy_sync(gr->egl_display, go->begin_render_sync);
if (go->end_render_sync != EGL_NO_SYNC_KHR)
gr->destroy_sync(gr->egl_display, go->end_render_sync);
go->begin_render_sync = create_render_sync(gr);
/* Calculate the viewport */
glViewport(go->borders[GL_RENDERER_BORDER_LEFT].width,
......@@ -1309,7 +1312,7 @@ gl_renderer_repaint_output(struct weston_output *output,
pixman_region32_copy(&output->previous_damage, output_damage);
wl_signal_emit(&output->frame_signal, output);
end_render_sync = timeline_create_render_sync(gr);
go->end_render_sync = create_render_sync(gr);
if (gr->swap_buffers_with_damage) {
pixman_region32_init(&buffer_damage);
......@@ -1360,9 +1363,10 @@ gl_renderer_repaint_output(struct weston_output *output,
/* We have to submit the render sync objects after swap buffers, since
* the objects get assigned a valid sync file fd only after a gl flush.
*/
timeline_submit_render_sync(gr, compositor, output, begin_render_sync,
timeline_submit_render_sync(gr, compositor, output,
go->begin_render_sync,
TIMELINE_RENDER_POINT_TYPE_BEGIN);
timeline_submit_render_sync(gr, compositor, output, end_render_sync,
timeline_submit_render_sync(gr, compositor, output, go->end_render_sync,
TIMELINE_RENDER_POINT_TYPE_END);
}
......@@ -2845,7 +2849,7 @@ log_extensions(const char *name, const char *extensions)
}
static void
log_egl_gl_info(EGLDisplay egldpy)
log_egl_info(EGLDisplay egldpy)
{
const char *str;
......@@ -2860,6 +2864,12 @@ log_egl_gl_info(EGLDisplay egldpy)
str = eglQueryString(egldpy, EGL_EXTENSIONS);
log_extensions("EGL extensions", str ? str : "(null)");
}
static void
log_gl_info(void)
{
const char *str;
str = (char *)glGetString(GL_VERSION);
weston_log("GL version: %s\n", str ? str : "(null)");
......@@ -3059,6 +3069,9 @@ gl_renderer_output_create(struct weston_output *output,
wl_list_init(&go->timeline_render_point_list);
go->begin_render_sync = EGL_NO_SYNC_KHR;
go->end_render_sync = EGL_NO_SYNC_KHR;
output->renderer_state = go;
return 0;
......@@ -3118,6 +3131,11 @@ gl_renderer_output_destroy(struct weston_output *output)
wl_list_for_each_safe(trp, tmp, &go->timeline_render_point_list, link)
timeline_render_point_destroy(trp);
if (go->begin_render_sync != EGL_NO_SYNC_KHR)
gr->destroy_sync(gr->egl_display, go->begin_render_sync);
if (go->end_render_sync != EGL_NO_SYNC_KHR)
gr->destroy_sync(gr->egl_display, go->end_render_sync);
free(go);
}
......@@ -3127,6 +3145,23 @@ gl_renderer_output_surface(struct weston_output *output)
return get_output_state(output)->egl_surface;
}
static int
gl_renderer_create_fence_fd(struct weston_output *output)
{
struct gl_output_state *go = get_output_state(output);
struct gl_renderer *gr = get_renderer(output->compositor);
int fd;
if (go->end_render_sync == EGL_NO_SYNC_KHR)
return -1;
fd = gr->dup_native_fence_fd(gr->egl_display, go->end_render_sync);
if (fd == EGL_NO_NATIVE_FENCE_FD_ANDROID)
return -1;
return fd;
}
static void
gl_renderer_destroy(struct weston_compositor *ec)
{
......@@ -3499,6 +3534,8 @@ gl_renderer_display_create(struct weston_compositor *ec, EGLenum platform,
goto fail_with_error;
}
log_egl_info(gr->egl_display);
if (egl_choose_config(gr, config_attribs, visual_id,
n_ids, &gr->egl_config) < 0) {
weston_log("failed to choose EGL config\n");
......@@ -3735,7 +3772,7 @@ gl_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface)
gr->gl_version = GR_GL_VERSION(2, 0);
}
log_egl_gl_info(gr->egl_display);
log_gl_info();
gr->image_target_texture_2d =
(void *) eglGetProcAddress("glEGLImageTargetTexture2DOES");
......@@ -3807,5 +3844,6 @@ 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,
.create_fence_fd = gl_renderer_create_fence_fd,
.print_egl_error_state = gl_renderer_print_egl_error_state
};
......@@ -113,6 +113,13 @@ struct gl_renderer_interface {
int32_t width, int32_t height,
int32_t tex_width, unsigned char *data);
/* Create fence sync FD to wait for GPU rendering.
*
* Return FD on success, -1 on failure or unsupported
* EGL_ANDROID_native_fence_sync extension.
*/
int (*create_fence_fd)(struct weston_output *output);
void (*print_egl_error_state)(void);
};
This diff is collapsed.
......@@ -45,6 +45,13 @@ including
can run on other VTs. On switching back to Weston's VT, input devices
and DRM master are re-acquired through the parent process
.BR weston-launch .
The DRM backend also supports virtual outputs that are transmitted over
an RTP session as a series of JPEG images (RTP payload type 26) to a remote
client. Virtual outputs are configured in the
.BR remote-output
section of
.BR weston.ini.
.
.\" ***************************************************************
.SH CONFIGURATION
......@@ -138,6 +145,30 @@ Defaults to false. Note that
When a connector is disconnected, there is no EDID information to provide
a list of video modes. Therefore a forced output should also have a
detailed mode line specified.
.SS Section remote-output
.TP
\fBname\fR=\fIname\fR
Specify unique name for the output.
.TP
\fBmode\fR=\fImode\fR
Specify the video mode for the output. The argument
.I mode
is a resolution setting, such as:
.TP
\fBmode\fR=\fIwidthxheight\fR
.TP
\fBmode\fR=\fIwidthxheight@refresh_rate
If refresh_rate is not specified it will default to a 60Hz.
.TP
\fBhost\fR=\fIhost\fR
Specify the host name or IP Address that the remote output will be
transmitted to.
.TP
\fBport\fR=\fIport\fR
Specify the port number to transmit the remote output to. Usable port range
is 1-65533.
.
.\" ***************************************************************
.SH OPTIONS
......
......@@ -189,6 +189,19 @@ useful for debugging a crash on start-up when it would be inconvenient to
launch weston directly from a debugger. Boolean, defaults to
.BR false .
There is also a command line option to do the same.
.TP 7
.BI "remoting="remoting-plugin.so
specifies a plugin for remote output to load (string). This can be used to load
your own implemented remoting plugin or one with Weston as default. Available
remoting plugins in the
.IR "__libweston_modules_dir__"
directroy are:
.PP
.RS 10
.nf
.BR remoting-plugin.so
.fi
.RE
.SH "LIBINPUT SECTION"
The
......
Remoting plugin for Weston
The Remoting plugin creates a streaming image of a virtual output and transmits
it to a remote host. It is currently only supported on the drm-backend. Virtual
outputs are created and configured by adding a remote-output section to
weston.ini. See man weston-drm(7) for configuration details. This plugin is
loaded automatically if any remote-output sections are present.
This plugin sends motion jpeg images to a client via RTP using gstreamer, and
so requires gstreamer-1.0. This plugin starts sending images immediately when
weston is run, and keeps sending them until weston shuts down. The image stream
can be received by any appropriately configured RTP client, but a sample
gstreamer RTP client script can be found at doc/remoting-client-receive.bash.
Script usage:
remoting-client-receive.bash <PORT NUMBER>
How to compile
---------------
Set --enable-remoting=true when configuring weston. The remoting-plugin.so
module is created and installed in the libweston path.
How to configure weston.ini
----------------------------
See man weston-drm(7).
This diff is collapsed.
/*
* Copyright © 2018 Renesas Electronics Corp.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Authors: IGEL Co., Ltd.
*/
#ifndef REMOTING_PLUGIN_H
#define REMOTING_PLUGIN_H
#include "compositor.h"
#include "plugin-registry.h"
#define WESTON_REMOTING_API_NAME "weston_remoting_api_v1"
struct weston_remoting_api {
/** Create remoted outputs
*
* Returns 0 on success, -1 on failure.
*/
struct weston_output *(*create_output)(struct weston_compositor *c,
char *name);
/** Check if output is remoted */
bool (*is_remoted_output)(struct weston_output *output);
/** Set mode */
int (*set_mode)(struct weston_output *output, const char *modeline);
/** Set gbm format */
void (*set_gbm_format)(struct weston_output *output,
const char *gbm_format);
/** Set seat */
void (*set_seat)(struct weston_output *output, const char *seat);
/** Set the destination Host(IP Address) */
void (*set_host)(struct weston_output *output, char *ip);
/** Set the port number */
void (*set_port)(struct weston_output *output, int port);
};
static inline const struct weston_remoting_api *
weston_remoting_get_api(struct weston_compositor *compositor)
{
const void *api;
api = weston_plugin_api_get(compositor, WESTON_REMOTING_API_NAME,
sizeof(struct weston_remoting_api));
return (const struct weston_remoting_api *)api;
}
#endif /* REMOTING_PLUGIN_H */