Alexander Graf <agraf@csgraf.de> <agraf@suse.de>
Anthony Liguori <anthony@codemonkey.ws> Anthony Liguori <aliguori@us.ibm.com>
Christian Borntraeger <borntraeger@linux.ibm.com> <borntraeger@de.ibm.com>
+Damien Hedde <damien.hedde@dahe.fr> <damien.hedde@greensocs.com>
Filip Bozuta <filip.bozuta@syrmia.com> <filip.bozuta@rt-rk.com.com>
Frederic Konrad <konrad.frederic@yahoo.fr> <fred.konrad@greensocs.com>
Frederic Konrad <konrad.frederic@yahoo.fr> <konrad@adacore.com>
T: git https://gitlab.com/vsementsov/qemu.git block
Compute Express Link
-M: Ben Widawsky <ben.widawsky@intel.com>
M: Jonathan Cameron <jonathan.cameron@huawei.com>
R: Fan Ni <fan.ni@samsung.com>
S: Supported
Clock framework
M: Luc Michel <luc@lmichel.fr>
-R: Damien Hedde <damien.hedde@greensocs.com>
+R: Damien Hedde <damien.hedde@dahe.fr>
S: Maintained
F: include/hw/clock.h
F: include/hw/qdev-clock.h
void *(*init) (Audiodev *);
void (*fini) (void *);
#ifdef CONFIG_GIO
- void (*set_dbus_server) (AudioState *s, GDBusObjectManagerServer *manager);
+ void (*set_dbus_server) (AudioState *s, GDBusObjectManagerServer *manager, bool p2p);
#endif
struct audio_pcm_ops *pcm_ops;
int can_be_default;
typedef struct DBusAudio {
GDBusObjectManagerServer *server;
+ bool p2p;
GDBusObjectSkeleton *audio;
QemuDBusDisplay1Audio *iface;
GHashTable *out_listeners;
bool out)
{
DBusAudio *da = s->drv_opaque;
- const char *sender = g_dbus_method_invocation_get_sender(invocation);
+ const char *sender =
+ da->p2p ? "p2p" : g_dbus_method_invocation_get_sender(invocation);
g_autoptr(GDBusConnection) listener_conn = NULL;
g_autoptr(GError) err = NULL;
g_autoptr(GSocket) socket = NULL;
}
static void
-dbus_audio_set_server(AudioState *s, GDBusObjectManagerServer *server)
+dbus_audio_set_server(AudioState *s, GDBusObjectManagerServer *server, bool p2p)
{
DBusAudio *da = s->drv_opaque;
g_assert(!da->server);
da->server = g_object_ref(server);
+ da->p2p = p2p;
da->audio = g_dbus_object_skeleton_new(DBUS_DISPLAY1_AUDIO_PATH);
da->iface = qemu_dbus_display1_audio_skeleton_new();
#define rv_fmt_rd_offset "O\t0,o"
#define rv_fmt_rd_rs1_rs2 "O\t0,1,2"
#define rv_fmt_frd_rs1 "O\t3,1"
+#define rv_fmt_frd_frs1 "O\t3,4"
#define rv_fmt_rd_frs1 "O\t0,4"
#define rv_fmt_rd_frs1_frs2 "O\t0,4,5"
#define rv_fmt_frd_frs1_frs2 "O\t3,4,5"
{ "snez", rv_codec_r, rv_fmt_rd_rs2, NULL, 0, 0, 0 },
{ "sltz", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
{ "sgtz", rv_codec_r, rv_fmt_rd_rs2, NULL, 0, 0, 0 },
- { "fmv.s", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
- { "fabs.s", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
- { "fneg.s", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
- { "fmv.d", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
- { "fabs.d", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
- { "fneg.d", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
- { "fmv.q", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
- { "fabs.q", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
- { "fneg.q", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
+ { "fmv.s", rv_codec_r, rv_fmt_frd_frs1, NULL, 0, 0, 0 },
+ { "fabs.s", rv_codec_r, rv_fmt_frd_frs1, NULL, 0, 0, 0 },
+ { "fneg.s", rv_codec_r, rv_fmt_frd_frs1, NULL, 0, 0, 0 },
+ { "fmv.d", rv_codec_r, rv_fmt_frd_frs1, NULL, 0, 0, 0 },
+ { "fabs.d", rv_codec_r, rv_fmt_frd_frs1, NULL, 0, 0, 0 },
+ { "fneg.d", rv_codec_r, rv_fmt_frd_frs1, NULL, 0, 0, 0 },
+ { "fmv.q", rv_codec_r, rv_fmt_frd_frs1, NULL, 0, 0, 0 },
+ { "fabs.q", rv_codec_r, rv_fmt_frd_frs1, NULL, 0, 0, 0 },
+ { "fneg.q", rv_codec_r, rv_fmt_frd_frs1, NULL, 0, 0, 0 },
{ "beqz", rv_codec_sb, rv_fmt_rs1_offset, NULL, 0, 0, 0 },
{ "bnez", rv_codec_sb, rv_fmt_rs1_offset, NULL, 0, 0, 0 },
{ "blez", rv_codec_sb, rv_fmt_rs2_offset, NULL, 0, 0, 0 },
{ "clzw", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
{ "ctzw", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
{ "cpopw", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
- { "slli.uw", rv_codec_i_sh5, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
+ { "slli.uw", rv_codec_i_sh6, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
{ "add.uw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
{ "rolw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
{ "rorw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
switch (((inst >> 12) & 0b111)) {
case 0: op = rv_op_addiw; break;
case 1:
- switch (((inst >> 25) & 0b1111111)) {
+ switch (((inst >> 26) & 0b111111)) {
case 0: op = rv_op_slliw; break;
- case 4: op = rv_op_slli_uw; break;
- case 48:
+ case 2: op = rv_op_slli_uw; break;
+ case 24:
switch ((inst >> 20) & 0b11111) {
case 0b00000: op = rv_op_clzw; break;
case 0b00001: op = rv_op_ctzw; break;
In QEMU, the second kind is named ``atomic_OP_fetch``.
- different atomic read-modify-write operations in Linux imply
- a different set of memory barriers; in QEMU, all of them enforce
- sequential consistency.
-
-- in QEMU, ``qatomic_read()`` and ``qatomic_set()`` do not participate in
- the ordering enforced by read-modify-write operations.
- This is because QEMU uses the C11 memory model. The following example
- is correct in Linux but not in QEMU:
+ a different set of memory barriers. In QEMU, all of them enforce
+ sequential consistency: there is a single order in which the
+ program sees them happen.
+
+- however, according to the C11 memory model that QEMU uses, this order
+ does not propagate to other memory accesses on either side of the
+ read-modify-write operation. As far as those are concerned, the
+ operation consist of just a load-acquire followed by a store-release.
+ Stores that precede the RMW operation, and loads that follow it, can
+ still be reordered and will happen *in the middle* of the read-modify-write
+ operation!
+
+ Therefore, the following example is correct in Linux but not in QEMU:
+----------------------------------+--------------------------------+
| Linux (correct) | QEMU (incorrect) |
return c;
fail:
- cursor_put(c);
+ cursor_unref(c);
return NULL;
}
}
qemu_mutex_lock(&qxl->ssd.lock);
if (qxl->ssd.cursor) {
- cursor_put(qxl->ssd.cursor);
+ cursor_unref(qxl->ssd.cursor);
}
qxl->ssd.cursor = c;
qxl->ssd.mouse_x = cmd->u.set.position.x;
qxl->guest_cursor = 0;
qemu_mutex_unlock(&qxl->track_lock);
if (qxl->ssd.cursor) {
- cursor_put(qxl->ssd.cursor);
+ cursor_unref(qxl->ssd.cursor);
}
qxl->ssd.cursor = cursor_builtin_hidden();
}
default:
fprintf(stderr, "%s: unhandled bpp %d, using fallback cursor\n",
__func__, c->bpp);
- cursor_put(qc);
+ cursor_unref(qc);
qc = cursor_builtin_left_ptr();
}
dpy_cursor_define(s->vga.con, qc);
- cursor_put(qc);
+ cursor_unref(qc);
}
#endif
ps2_put_keycode(s, 0xaa);
}
}
+ } else if ((qcode == Q_KEY_CODE_LANG1 || qcode == Q_KEY_CODE_LANG2)
+ && !key->down) {
+ /* Ignore release for these keys */
} else {
if (qcode < qemu_input_map_qcode_to_atset1_len) {
keycode = qemu_input_map_qcode_to_atset1[qcode];
ps2_put_keycode(s, 0x12);
}
}
+ } else if ((qcode == Q_KEY_CODE_LANG1 || qcode == Q_KEY_CODE_LANG2) &&
+ !key->down) {
+ /* Ignore release for these keys */
} else {
if (qcode < qemu_input_map_qcode_to_atset2_len) {
keycode = qemu_input_map_qcode_to_atset2[qcode];
s->ioredtbl[index] |= ro_bits;
s->irq_eoi[index] = 0;
ioapic_fix_edge_remote_irr(&s->ioredtbl[index]);
+ ioapic_update_kvm_routes(s);
ioapic_service(s);
}
}
ioapic_eoi_broadcast(val);
break;
}
-
- ioapic_update_kvm_routes(s);
}
static const MemoryRegionOps ioapic_io_ops = {
} QEMUCursor;
QEMUCursor *cursor_alloc(int width, int height);
-void cursor_get(QEMUCursor *c);
-void cursor_put(QEMUCursor *c);
+QEMUCursor *cursor_ref(QEMUCursor *c);
+void cursor_unref(QEMUCursor *c);
QEMUCursor *cursor_builtin_hidden(void);
QEMUCursor *cursor_builtin_left_ptr(void);
void cursor_print_ascii_art(QEMUCursor *c, const char *prefix);
QemuConsole *qemu_console_lookup_by_device_name(const char *device_id,
uint32_t head, Error **errp);
QemuConsole *qemu_console_lookup_unused(void);
+QEMUCursor *qemu_console_get_cursor(QemuConsole *con);
bool qemu_console_is_visible(QemuConsole *con);
bool qemu_console_is_graphic(QemuConsole *con);
bool qemu_console_is_fixedsize(QemuConsole *con);
QemuDmaBuf *dmabuf;
} egl_fb;
+#define EGL_FB_INIT { 0, }
+
void egl_fb_destroy(egl_fb *fb);
void egl_fb_setup_default(egl_fb *fb, int width, int height);
void egl_fb_setup_for_tex(egl_fb *fb, int width, int height,
EGLContext qemu_egl_init_ctx(void);
bool qemu_egl_has_dmabuf(void);
+bool egl_init(const char *rendernode, DisplayGLMode mode, Error **errp);
+
#endif /* EGL_HELPERS_H */
object_ref(OBJECT(tioc));
g_source_add_child_source(source, child);
+ g_source_unref(child);
}
static GSource *qio_channel_tls_create_watch(QIOChannel *ioc,
error_message: '-display dbus requires glib>=2.64') \
.require(gdbus_codegen.found(),
error_message: gdbus_codegen_error.format('-display dbus')) \
- .require(opengl.found() and gbm.found(),
- error_message: '-display dbus requires epoxy/egl and gbm') \
+ .require(targetos != 'windows',
+ error_message: '-display dbus is not available on Windows') \
.allowed()
have_virtfs = get_option('virtfs') \
if (p->pending_job) {
uint64_t packet_num = p->packet_num;
- uint32_t flags = p->flags;
+ uint32_t flags;
p->normal_num = 0;
if (use_zero_copy_send) {
}
}
multifd_send_fill_packet(p);
+ flags = p->flags;
p->flags = 0;
p->num_packets++;
p->total_normal_pages += p->normal_num;
}
if (migrate_postcopy_preempt()) {
- /*
- * The preempt channel is established in asynchronous way. Wait
- * for its completion.
- */
- qemu_sem_wait(&mis->postcopy_qemufile_dst_done);
/*
* This thread needs to be created after the temp pages because
* it'll fetch RAM_CHANNEL_POSTCOPY PostcopyTmpPage immediately.
qemu_sem_post(&mis->thread_sync_sem);
+ /*
+ * The preempt channel is established in asynchronous way. Wait
+ * for its completion.
+ */
+ qemu_sem_wait(&mis->postcopy_qemufile_dst_done);
+
/* Sending RAM_SAVE_FLAG_EOS to terminate this thread */
qemu_mutex_lock(&mis->postcopy_prio_thread_mutex);
while (1) {
* initialize the RDMAContext for return path for postcopy after first
* connection request reached.
*/
- if (migrate_postcopy() && !rdma->is_return_path) {
+ if ((migrate_postcopy() || migrate_use_return_path())
+ && !rdma->is_return_path) {
rdma_return_path = qemu_rdma_data_init(rdma->host_port, NULL);
if (rdma_return_path == NULL) {
rdma_ack_cm_event(cm_event);
}
/* Accept the second connection request for return path */
- if (migrate_postcopy() && !rdma->is_return_path) {
+ if ((migrate_postcopy() || migrate_use_return_path())
+ && !rdma->is_return_path) {
qemu_set_fd_handler(rdma->channel->fd, rdma_accept_incoming_migration,
NULL,
(void *)(intptr_t)rdma->return_path);
void rdma_start_incoming_migration(const char *host_port, Error **errp)
{
int ret;
- RDMAContext *rdma, *rdma_return_path = NULL;
+ RDMAContext *rdma;
Error *local_err = NULL;
trace_rdma_start_incoming_migration();
g_free(rdma->host_port);
}
g_free(rdma);
- g_free(rdma_return_path);
}
void rdma_start_outgoing_migration(void *opaque,
}
/* RDMA postcopy need a separate queue pair for return path */
- if (migrate_postcopy()) {
+ if (migrate_postcopy() || migrate_use_return_path()) {
rdma_return_path = qemu_rdma_data_init(host_port, errp);
if (rdma_return_path == NULL) {
#include "qemu/osdep.h"
#include "qapi/qapi-types-migration.h"
#include "migration.h"
+#include CONFIG_DEVICES
#ifdef CONFIG_VFIO
#include "hw/vfio/vfio-common.h"
{
#ifdef CONFIG_VFIO
if (vfio_mig_active()) {
- info->has_vfio = true;
info->vfio = g_malloc0(sizeof(*info->vfio));
info->vfio->transferred = vfio_mig_bytes_transferred();
}
*/
#include "qemu/osdep.h"
#include "qemu/cutils.h"
+#include "qemu/host-utils.h"
#include "xbzrle.h"
/*
__m512i r = _mm512_set1_epi32(0);
while (count512s) {
- if (d + 2 > dlen) {
- return -1;
- }
-
int bytes_to_check = 64;
uint64_t mask = 0xffffffffffffffff;
if (count512s == 1) {
bool is_same = (comp & 0x1);
while (bytes_to_check) {
+ if (d + 2 > dlen) {
+ return -1;
+ }
if (is_same) {
if (nzrun_len) {
d += uleb128_encode_small(dst + d, nzrun_len);
break;
}
never_same = false;
- num = __builtin_ctzll(~comp);
+ num = ctz64(~comp);
num = (num < bytes_to_check) ? num : bytes_to_check;
zrun_len += num;
bytes_to_check -= num;
nzrun_len += 64;
break;
}
- num = __builtin_ctzll(comp);
+ num = ctz64(comp);
num = (num < bytes_to_check) ? num : bytes_to_check;
nzrun_len += num;
bytes_to_check -= num;
# @lang1: since 6.1
# @lang2: since 6.1
#
+# @f13: since 8.0
+# @f14: since 8.0
+# @f15: since 8.0
+# @f16: since 8.0
+# @f17: since 8.0
+# @f18: since 8.0
+# @f19: since 8.0
+# @f20: since 8.0
+# @f21: since 8.0
+# @f22: since 8.0
+# @f23: since 8.0
+# @f24: since 8.0
+#
# 'sysrq' was mistakenly added to hack around the fact that
# the ps2 driver was not generating correct scancodes sequences
# when 'alt+print' was pressed. This flaw is now fixed and the
'volumeup', 'volumedown', 'mediaselect',
'mail', 'calculator', 'computer',
'ac_home', 'ac_back', 'ac_forward', 'ac_refresh', 'ac_bookmarks',
- 'lang1', 'lang2' ] }
+ 'lang1', 'lang2','f13','f14','f15','f16','f17','f18','f19','f20','f21','f22','f23','f24' ] }
##
# @KeyValueKind:
.. parsed-literal::
- |qemu_system_x86| -drive file=a -drive file=b"
+ |qemu_system_x86| -drive file=a -drive file=b
is interpreted like:
-Subproject commit 3208b098f51a9ef96d0dfa71d5ec3a3eaec88f0a
+Subproject commit ea1b7a0733906b8425d948ae94fba63c32b1d425
pid_file_realpath = g_malloc0(PATH_MAX);
if (!realpath(pid_file, pid_file_realpath)) {
- error_report("cannot resolve PID file path: %s: %s",
- pid_file, strerror(errno));
- unlink(pid_file);
- exit(1);
+ if (errno != ENOENT) {
+ warn_report("not removing PID file on exit: cannot resolve PID "
+ "file path: %s: %s", pid_file, strerror(errno));
+ }
+ return;
}
qemu_unlink_pidfile_notifier = (struct UnlinkPidfileNotifier) {
kvm_rate_limit_on_bus_lock();
}
+#ifdef CONFIG_XEN_EMU
/*
* If the callback is asserted as a GSI (or PCI INTx) then check if
* vcpu_info->evtchn_upcall_pending has been cleared, and deassert
if (x86_cpu->env.xen_callback_asserted) {
kvm_xen_maybe_deassert_callback(cpu);
}
+#endif
/* We need to protect the apic state against concurrent accesses from
* different threads in case the userspace irqchip is used. */
'numa-test'
]
-if dbus_display
+if dbus_display and targetos != 'windows'
qtests_i386 += ['dbus-display-test']
endif
uint32_t head;
QemuUIInfo ui_info;
QEMUTimer *ui_timer;
+ QEMUCursor *cursor;
+ int cursor_x, cursor_y, cursor_on;
const GraphicHwOps *hw_ops;
void *hw;
con = active_console;
}
displaychangelistener_display_console(dcl, con, dcl->con ? &error_fatal : NULL);
+ if (con && con->cursor && dcl->ops->dpy_cursor_define) {
+ dcl->ops->dpy_cursor_define(dcl, con->cursor);
+ }
+ if (con && dcl->ops->dpy_mouse_set) {
+ dcl->ops->dpy_mouse_set(dcl, con->cursor_x, con->cursor_y, con->cursor_on);
+ }
text_console_update_cursor(NULL);
}
DisplayState *s = con->ds;
DisplayChangeListener *dcl;
+ con->cursor_x = x;
+ con->cursor_y = y;
+ con->cursor_on = on;
if (!qemu_console_is_visible(con)) {
return;
}
DisplayState *s = con->ds;
DisplayChangeListener *dcl;
+ cursor_unref(con->cursor);
+ con->cursor = cursor_ref(cursor);
if (!qemu_console_is_visible(con)) {
return;
}
return NULL;
}
+QEMUCursor *qemu_console_get_cursor(QemuConsole *con)
+{
+ return con->cursor;
+}
+
bool qemu_console_is_visible(QemuConsole *con)
{
return (con == active_console) || (con->dcls > 0);
return c;
}
-void cursor_get(QEMUCursor *c)
+QEMUCursor *cursor_ref(QEMUCursor *c)
{
c->refcount++;
+ return c;
}
-void cursor_put(QEMUCursor *c)
+void cursor_unref(QEMUCursor *c)
{
if (c == NULL)
return;
g_clear_object(&dpy->clipboard_proxy);
}
-static void
-dbus_on_clipboard_proxy_name_owner_changed(
- DBusDisplay *dpy,
- GObject *object,
- GParamSpec *pspec)
-{
- dbus_clipboard_unregister_proxy(dpy);
-}
-
static gboolean
dbus_clipboard_register(
DBusDisplay *dpy,
{
g_autoptr(GError) err = NULL;
const char *name = NULL;
+ GDBusConnection *connection = g_dbus_method_invocation_get_connection(invocation);
if (dpy->clipboard_proxy) {
g_dbus_method_invocation_return_error(
dpy->clipboard_proxy =
qemu_dbus_display1_clipboard_proxy_new_sync(
- g_dbus_method_invocation_get_connection(invocation),
+ connection,
G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
g_dbus_method_invocation_get_sender(invocation),
"/org/qemu/Display1/Clipboard",
g_object_connect(dpy->clipboard_proxy,
"swapped-signal::notify::g-name-owner",
- dbus_on_clipboard_proxy_name_owner_changed, dpy,
+ dbus_clipboard_unregister_proxy, dpy,
+ NULL);
+ g_object_connect(connection,
+ "swapped-signal::closed",
+ dbus_clipboard_unregister_proxy, dpy,
NULL);
qemu_clipboard_reset_serial();
return DBUS_METHOD_INVOCATION_HANDLED;
}
+static void
+dbus_mouse_update_is_absolute(DBusDisplayConsole *ddc)
+{
+ g_object_set(ddc->iface_mouse,
+ "is-absolute", qemu_input_is_absolute(),
+ NULL);
+}
+
static void
dbus_mouse_mode_change(Notifier *notify, void *data)
{
DBusDisplayConsole *ddc =
container_of(notify, DBusDisplayConsole, mouse_mode_notifier);
- g_object_set(ddc->iface_mouse,
- "is-absolute", qemu_input_is_absolute(),
- NULL);
+ dbus_mouse_update_is_absolute(ddc);
}
int dbus_display_console_get_index(DBusDisplayConsole *ddc)
register_displaychangelistener(&ddc->dcl);
ddc->mouse_mode_notifier.notify = dbus_mouse_mode_change;
qemu_add_mouse_mode_change_notifier(&ddc->mouse_mode_notifier);
+ dbus_mouse_update_is_absolute(ddc);
return ddc;
}
#include "dbus.h"
#include <gio/gunixfdlist.h>
+#ifdef CONFIG_OPENGL
#include "ui/shader.h"
#include "ui/egl-helpers.h"
#include "ui/egl-context.h"
+#endif
#include "trace.h"
struct _DBusDisplayListener {
G_DEFINE_TYPE(DBusDisplayListener, dbus_display_listener, G_TYPE_OBJECT)
+#ifdef CONFIG_GBM
static void dbus_update_gl_cb(GObject *source_object,
GAsyncResult *res,
gpointer user_data)
DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener, dcl);
DisplaySurface *ds;
GVariant *v_data = NULL;
- egl_fb cursor_fb;
+ egl_fb cursor_fb = EGL_FB_INIT;
if (!dmabuf) {
qemu_dbus_display1_listener_call_mouse_set(
ddl->gl_updates = 0;
}
}
+#endif
static void dbus_refresh(DisplayChangeListener *dcl)
{
graphic_hw_update(dcl->con);
}
+#ifdef CONFIG_GBM
static void dbus_gl_gfx_update(DisplayChangeListener *dcl,
int x, int y, int w, int h)
{
ddl->gl_updates++;
}
+#endif
static void dbus_gfx_update(DisplayChangeListener *dcl,
int x, int y, int w, int h)
DBUS_DEFAULT_TIMEOUT, NULL, NULL, NULL);
}
+#ifdef CONFIG_GBM
static void dbus_gl_gfx_switch(DisplayChangeListener *dcl,
struct DisplaySurface *new_surface)
{
width, height, 0, 0, width, height);
}
}
+#endif
static void dbus_gfx_switch(DisplayChangeListener *dcl,
struct DisplaySurface *new_surface)
DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener, dcl);
GVariant *v_data = NULL;
- cursor_get(c);
v_data = g_variant_new_from_data(
G_VARIANT_TYPE("ay"),
c->data,
c->width * c->height * 4,
TRUE,
- (GDestroyNotify)cursor_put,
- c);
+ (GDestroyNotify)cursor_unref,
+ cursor_ref(c));
qemu_dbus_display1_listener_call_cursor_define(
ddl->proxy,
NULL);
}
+#ifdef CONFIG_GBM
const DisplayChangeListenerOps dbus_gl_dcl_ops = {
.dpy_name = "dbus-gl",
.dpy_gfx_update = dbus_gl_gfx_update,
.dpy_gl_release_dmabuf = dbus_release_dmabuf,
.dpy_gl_update = dbus_scanout_update,
};
+#endif
const DisplayChangeListenerOps dbus_dcl_ops = {
.dpy_name = "dbus",
{
DBusDisplayListener *ddl = DBUS_DISPLAY_LISTENER(object);
+ ddl->dcl.ops = &dbus_dcl_ops;
+#ifdef CONFIG_GBM
if (display_opengl) {
ddl->dcl.ops = &dbus_gl_dcl_ops;
- } else {
- ddl->dcl.ops = &dbus_dcl_ops;
}
+#endif
G_OBJECT_CLASS(dbus_display_listener_parent_class)->constructed(object);
}
#include "qom/object_interfaces.h"
#include "sysemu/sysemu.h"
#include "ui/dbus-module.h"
+#ifdef CONFIG_OPENGL
#include "ui/egl-helpers.h"
#include "ui/egl-context.h"
+#endif
#include "audio/audio.h"
#include "audio/audio_int.h"
#include "qapi/error.h"
static DBusDisplay *dbus_display;
+#ifdef CONFIG_OPENGL
static QEMUGLContext dbus_create_context(DisplayGLCtx *dgc,
QEMUGLParams *params)
{
+#ifdef CONFIG_GBM
eglMakeCurrent(qemu_egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
qemu_egl_rn_ctx);
+#endif
return qemu_egl_create_context(dgc, params);
}
dbus_is_compatible_dcl(DisplayGLCtx *dgc,
DisplayChangeListener *dcl)
{
- return dcl->ops == &dbus_gl_dcl_ops || dcl->ops == &dbus_console_dcl_ops;
+ return
+#ifdef CONFIG_GBM
+ dcl->ops == &dbus_gl_dcl_ops ||
+#endif
+ dcl->ops == &dbus_console_dcl_ops;
}
static void
.dpy_gl_ctx_destroy_texture = dbus_destroy_texture,
.dpy_gl_ctx_update_texture = dbus_update_texture,
};
+#endif
static NotifierList dbus_display_notifiers =
NOTIFIER_LIST_INITIALIZER(dbus_display_notifiers);
DBusDisplay *dd = DBUS_DISPLAY(o);
g_autoptr(GDBusObjectSkeleton) vm = NULL;
+#ifdef CONFIG_OPENGL
dd->glctx.ops = &dbus_gl_ops;
if (display_opengl) {
dd->glctx.gls = qemu_gl_init_shader();
}
+#endif
dd->iface = qemu_dbus_display1_vm_skeleton_new();
dd->consoles = g_ptr_array_new_with_free_func(g_object_unref);
g_clear_object(&dd->iface);
g_free(dd->dbus_addr);
g_free(dd->audiodev);
+#ifdef CONFIG_OPENGL
g_clear_pointer(&dd->glctx.gls, qemu_gl_fini_shader);
+#endif
dbus_display = NULL;
}
dd->audiodev);
return;
}
- audio_state->drv->set_dbus_server(audio_state, dd->server);
+ audio_state->drv->set_dbus_server(audio_state, dd->server, dd->p2p);
}
consoles = g_array_new(FALSE, FALSE, sizeof(guint32));
DisplayGLMode mode = opts->has_gl ? opts->gl : DISPLAYGL_MODE_OFF;
if (mode != DISPLAYGL_MODE_OFF) {
- if (egl_rendernode_init(opts->u.dbus.rendernode, mode) < 0) {
- error_report("dbus: render node init failed");
- exit(1);
- }
-
- display_opengl = 1;
+#ifdef CONFIG_OPENGL
+ egl_init(opts->u.dbus.rendernode, mode, &error_fatal);
+#else
+ error_report("dbus: GL rendering is not supported");
+#endif
}
type_register(&dbus_vc_type_info);
#include "qemu/osdep.h"
#include "qemu/error-report.h"
#include "qemu/module.h"
-#include "sysemu/sysemu.h"
+#include "qapi/error.h"
#include "ui/console.h"
#include "ui/egl-helpers.h"
#include "ui/egl-context.h"
static void early_egl_headless_init(DisplayOptions *opts)
{
- display_opengl = 1;
+ DisplayGLMode mode = DISPLAYGL_MODE_ON;
+
+ if (opts->has_gl) {
+ mode = opts->gl;
+ }
+
+ egl_init(opts->u.egl_headless.rendernode, mode, &error_fatal);
}
static void egl_headless_init(DisplayState *ds, DisplayOptions *opts)
{
- DisplayGLMode mode = opts->has_gl ? opts->gl : DISPLAYGL_MODE_ON;
QemuConsole *con;
egl_dpy *edpy;
int idx;
- if (egl_rendernode_init(opts->u.egl_headless.rendernode, mode) < 0) {
- error_report("egl: render node init failed");
- exit(1);
- }
-
for (idx = 0;; idx++) {
DisplayGLCtx *ctx;
#include "qemu/error-report.h"
#include "ui/console.h"
#include "ui/egl-helpers.h"
+#include "sysemu/sysemu.h"
+#include "qapi/error.h"
EGLDisplay *qemu_egl_display;
EGLConfig qemu_egl_config;
/* ------------------------------------------------------------------ */
+#if defined(CONFIG_X11) || defined(CONFIG_GBM)
+static const char *egl_get_error_string(void)
+{
+ EGLint error = eglGetError();
+
+ switch (error) {
+ case EGL_SUCCESS:
+ return "EGL_SUCCESS";
+ case EGL_NOT_INITIALIZED:
+ return "EGL_NOT_INITIALIZED";
+ case EGL_BAD_ACCESS:
+ return "EGL_BAD_ACCESS";
+ case EGL_BAD_ALLOC:
+ return "EGL_BAD_ALLOC";
+ case EGL_BAD_ATTRIBUTE:
+ return "EGL_BAD_ATTRIBUTE";
+ case EGL_BAD_CONTEXT:
+ return "EGL_BAD_CONTEXT";
+ case EGL_BAD_CONFIG:
+ return "EGL_BAD_CONFIG";
+ case EGL_BAD_CURRENT_SURFACE:
+ return "EGL_BAD_CURRENT_SURFACE";
+ case EGL_BAD_DISPLAY:
+ return "EGL_BAD_DISPLAY";
+ case EGL_BAD_SURFACE:
+ return "EGL_BAD_SURFACE";
+ case EGL_BAD_MATCH:
+ return "EGL_BAD_MATCH";
+ case EGL_BAD_PARAMETER:
+ return "EGL_BAD_PARAMETER";
+ case EGL_BAD_NATIVE_PIXMAP:
+ return "EGL_BAD_NATIVE_PIXMAP";
+ case EGL_BAD_NATIVE_WINDOW:
+ return "EGL_BAD_NATIVE_WINDOW";
+ case EGL_CONTEXT_LOST:
+ return "EGL_CONTEXT_LOST";
+ default:
+ return "Unknown EGL error";
+ }
+}
+#endif
+
static void egl_fb_delete_texture(egl_fb *fb)
{
if (!fb->delete_texture) {
qemu_egl_display = qemu_egl_get_display(dpy, platform);
if (qemu_egl_display == EGL_NO_DISPLAY) {
- error_report("egl: eglGetDisplay failed");
+ error_report("egl: eglGetDisplay failed: %s", egl_get_error_string());
return -1;
}
b = eglInitialize(qemu_egl_display, &major, &minor);
if (b == EGL_FALSE) {
- error_report("egl: eglInitialize failed");
+ error_report("egl: eglInitialize failed: %s", egl_get_error_string());
return -1;
}
b = eglBindAPI(gles ? EGL_OPENGL_ES_API : EGL_OPENGL_API);
if (b == EGL_FALSE) {
- error_report("egl: eglBindAPI failed (%s mode)",
- gles ? "gles" : "core");
+ error_report("egl: eglBindAPI failed (%s mode): %s",
+ gles ? "gles" : "core", egl_get_error_string());
return -1;
}
gles ? conf_att_gles : conf_att_core,
&qemu_egl_config, 1, &n);
if (b == EGL_FALSE || n != 1) {
- error_report("egl: eglChooseConfig failed (%s mode)",
- gles ? "gles" : "core");
+ error_report("egl: eglChooseConfig failed (%s mode): %s",
+ gles ? "gles" : "core", egl_get_error_string());
return -1;
}
return ectx;
}
+
+bool egl_init(const char *rendernode, DisplayGLMode mode, Error **errp)
+{
+ ERRP_GUARD();
+
+ if (mode == DISPLAYGL_MODE_OFF) {
+ error_setg(errp, "egl: turning off GL doesn't make sense");
+ return false;
+ }
+
+#ifdef CONFIG_GBM
+ if (egl_rendernode_init(rendernode, mode) < 0) {
+ error_setg(errp, "egl: render node init failed");
+ return false;
+ }
+ display_opengl = 1;
+ return true;
+#else
+ error_setg(errp, "egl: not available on this platform");
+ return false;
+#endif
+}
-Subproject commit d21009b1c9f94b740ea66be8e48a1d8ad8124023
+Subproject commit f5772a62ec52591ff6870b7e8ef32482371f22c6
'--interface-prefix', 'org.qemu.',
'--c-namespace', 'QemuDBus',
'--generate-c-code', '@BASENAME@'])
- dbus_ss.add(when: [gio, pixman, opengl, gbm],
+ dbus_display1_lib = static_library('dbus-display1', dbus_display1, dependencies: gio)
+ dbus_display1_dep = declare_dependency(link_with: dbus_display1_lib, include_directories: include_directories('.'))
+ dbus_ss.add(when: [gio, pixman, dbus_display1_dep],
if_true: [files(
'dbus-chardev.c',
'dbus-clipboard.c',
'dbus-error.c',
'dbus-listener.c',
'dbus.c',
- ), dbus_display1])
+ ), opengl, gbm])
ui_modules += {'dbus' : dbus_ss}
endif
#define SDL2_MAX_IDLE_COUNT (2 * GUI_REFRESH_INTERVAL_DEFAULT \
/ SDL2_REFRESH_INTERVAL_BUSY + 1)
+/* introduced in SDL 2.0.10 */
+#ifndef SDL_HINT_RENDER_BATCHING
+#define SDL_HINT_RENDER_BATCHING "SDL_RENDER_BATCHING"
+#endif
+
static void sdl_update_caption(struct sdl2_console *scon);
static struct sdl2_console *get_scon_from_window(uint32_t window_id)
surface_width(scon->surface),
surface_height(scon->surface),
flags);
+ if (scon->opengl) {
+ const char *driver = "opengl";
+
+ if (scon->opts->gl == DISPLAYGL_MODE_ES) {
+ driver = "opengles2";
+ }
+
+ SDL_SetHint(SDL_HINT_RENDER_DRIVER, driver);
+ SDL_SetHint(SDL_HINT_RENDER_BATCHING, "1");
+ }
scon->real_renderer = SDL_CreateRenderer(scon->real_window, -1, 0);
+
if (scon->opengl) {
- scon->winctx = SDL_GL_GetCurrentContext();
+ scon->winctx = SDL_GL_CreateContext(scon->real_window);
}
sdl_update_caption(scon);
}
return;
}
+ SDL_GL_DeleteContext(scon->winctx);
+ scon->winctx = NULL;
SDL_DestroyRenderer(scon->real_renderer);
scon->real_renderer = NULL;
SDL_DestroyWindow(scon->real_window);
}
#endif
+ if (SDL_GetHintBoolean("QEMU_ENABLE_SDL_LOGGING", SDL_FALSE)) {
+ SDL_LogSetAllPriority(SDL_LOG_PRIORITY_VERBOSE);
+ }
+
if (SDL_Init(SDL_INIT_VIDEO)) {
fprintf(stderr, "Could not initialize SDL(%s) - exiting\n",
SDL_GetError());
-
#version 300 es
in vec2 in_position;
-
#version 300 es
uniform sampler2D image;
-
#version 300 es
in vec2 in_position;
"incompatible with -spice port/tls-port");
exit(1);
}
- if (egl_rendernode_init(qemu_opt_get(opts, "rendernode"),
- DISPLAYGL_MODE_ON) != 0) {
- error_report("Failed to initialize EGL render node for SPICE GL");
- exit(1);
- }
- display_opengl = 1;
+ egl_init(qemu_opt_get(opts, "rendernode"), DISPLAYGL_MODE_ON, &error_fatal);
spice_opengl = 1;
}
#endif
if (ssd->cursor) {
QEMUCursor *c = ssd->cursor;
assert(ssd->dcl.con);
- cursor_get(c);
+ cursor_ref(c);
qemu_mutex_unlock(&ssd->lock);
dpy_cursor_define(ssd->dcl.con, c);
qemu_mutex_lock(&ssd->lock);
- cursor_put(c);
+ cursor_unref(c);
}
if (ssd->mouse_x != -1 && ssd->mouse_y != -1) {
SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl);
qemu_mutex_lock(&ssd->lock);
- cursor_get(c);
- cursor_put(ssd->cursor);
+ cursor_ref(c);
+ cursor_unref(ssd->cursor);
ssd->cursor = c;
ssd->hot_x = c->hot_x;
ssd->hot_y = c->hot_y;
static int vnc_cursor_define(VncState *vs)
{
- QEMUCursor *c = vs->vd->cursor;
+ QEMUCursor *c = qemu_console_get_cursor(vs->vd->dcl.con);
int isize;
- if (!vs->vd->cursor) {
+ if (!c) {
return -1;
}
VncDisplay *vd = container_of(dcl, VncDisplay, dcl);
VncState *vs;
- cursor_put(vd->cursor);
g_free(vd->cursor_mask);
-
- vd->cursor = c;
- cursor_get(vd->cursor);
vd->cursor_msize = cursor_get_mono_bpl(c) * c->height;
vd->cursor_mask = g_malloc0(vd->cursor_msize);
cursor_get_mono_mask(c, 0, vd->cursor_mask);
QKbdState *kbd;
QemuMutex mutex;
- QEMUCursor *cursor;
int cursor_msize;
uint8_t *cursor_mask;