Merge tag 'sdmmc-20240716' of https://github.com/philmd/qemu into staging
SD/MMC patches queue
Addition of eMMC support is a long-term collaborative virtual work by:
- Cédric Le Goater
- Edgar E. Iglesias
- Francisco Iglesias
- Joel Stanley
- Luc Michel
- Philippe Mathieu-Daudé
- Sai Pavan Boddu
- Vincent Palatin
# -----BEGIN PGP SIGNATURE-----
#
# iQIzBAABCAAdFiEE+qvnXhKRciHc/Wuy4+MsLN6twN4FAmaWvlEACgkQ4+MsLN6t
# wN7p7hAAj6JV3fIg1iKBR49asQVzU3/nYRIlWnp6QsLRGX+qwjMnuMzlvpinTtq4
# SJZobw1OJp/2LNaEGqAqNHqBpwAPibUnkei0pd1Y+v6Cyywo7X5Y1hRvQf46Ezqm
# u2FxsAfWc4cQs+sFrbNq/v7X2+R6VmChkA+EVc4cB0gwMOjvtg8RQObdhKr7Y6UX
# b9KvRDSNMH75ht39RD/smtcn/kprkkTQYo/ciBbVWdnBMiKuhN0qLXbKnZu9lMs4
# Ru29ypT+98pL1E/4YbgNcLGYXHjKrSIpD3+DEvmWe09LdG2+YMASv7do3iKfAYN5
# KdQ9BNZxYrpmeDAiyL521pODsgvU/wDDdbK0xUztPqcHhpYkvcfYWdzO8wr28Ib0
# wOEA0+xzveeD+1ZKjilbZ6tKzsRrKgv1O8j1T8rXab2/3mjrW2R5G/5y4bpM8E4h
# KuqGwC2YjWsJi3CwRL5Cvu5YBsiyYF7mk0zTKK2qwO87B7Pa0PJ3Y9x0xIWm4blp
# RoZ1SaCChH3M1hKK3jDjrIutXrZG8CzHpe17QjTQeUxo+/wX3VfDYbXasTe1orFu
# +JkUBU+xZ6m1+dWAa22H5KbeY8wd99p6w+ChnVmS15WqVK8i2e4gfTsKGh7Idt3t
# Vf4CaCD/2vRtKo4AN+YNDUg1DWV89zXRbnkR5oWUWG3Fda5Qo3k=
# =m52p
# -----END PGP SIGNATURE-----
# gpg: Signature made Wed 17 Jul 2024 04:39:13 AM AEST
# gpg: using RSA key FAABE75E12917221DCFD6BB2E3E32C2CDEADC0DE
# gpg: Good signature from "Philippe Mathieu-Daudé (F4BUG) <f4bug@amsat.org>" [full]
* tag 'sdmmc-20240716' of https://github.com/philmd/qemu:
hw/sd/sdcard: Support boot area in emmc image
hw/sd/sdcard: Add mmc SWITCH function support (CMD6)
hw/sd/sdcard: Add eMMC 'boot-partition-size' property
hw/sd/sdcard: Add emmc_cmd_SEND_EXT_CSD handler (CMD8)
hw/sd/sdcard: Implement eMMC sleep state (CMD5)
hw/sd/sdcard: Add emmc_cmd_PROGRAM_CID handler (CMD26)
hw/sd/sdcard: Fix SET_BLOCK_COUNT command argument on eMMC (CMD23)
hw/sd/sdcard: Add emmc_cmd_SET_RELATIVE_ADDR handler (CMD3)
hw/sd/sdcard: Register unimplemented command handlers
hw/sd/sdcard: Register generic command handlers
hw/sd/sdcard: Basis for eMMC support
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
index 245fd63..9010dad 100644
--- a/accel/tcg/cpu-exec.c
+++ b/accel/tcg/cpu-exec.c
@@ -857,8 +857,7 @@
else {
const TCGCPUOps *tcg_ops = cpu->cc->tcg_ops;
- if (tcg_ops->cpu_exec_interrupt &&
- tcg_ops->cpu_exec_interrupt(cpu, interrupt_request)) {
+ if (tcg_ops->cpu_exec_interrupt(cpu, interrupt_request)) {
if (!tcg_ops->need_replay_interrupt ||
tcg_ops->need_replay_interrupt(interrupt_request)) {
replay_interrupt();
@@ -1080,6 +1079,7 @@
/* Check mandatory TCGCPUOps handlers */
#ifndef CONFIG_USER_ONLY
assert(cpu->cc->tcg_ops->cpu_exec_halt);
+ assert(cpu->cc->tcg_ops->cpu_exec_interrupt);
#endif /* !CONFIG_USER_ONLY */
cpu->cc->tcg_ops->initialize();
tcg_target_initialized = true;
diff --git a/hw/core/loader.c b/hw/core/loader.c
index a3bea1e..31593a1 100644
--- a/hw/core/loader.c
+++ b/hw/core/loader.c
@@ -845,19 +845,6 @@
return ret;
}
-/* Load a gzip-compressed kernel. */
-ssize_t load_image_gzipped(const char *filename, hwaddr addr, uint64_t max_sz)
-{
- ssize_t bytes;
- uint8_t *data;
-
- bytes = load_image_gzipped_buffer(filename, max_sz, &data);
- if (bytes != -1) {
- rom_add_blob_fixed(filename, data, bytes, addr);
- g_free(data);
- }
- return bytes;
-}
/* The PE/COFF MS-DOS stub magic number */
#define EFI_PE_MSDOS_MAGIC "MZ"
@@ -1076,8 +1063,8 @@
{
MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine());
Rom *rom;
- ssize_t rc;
- int fd = -1;
+ gsize size;
+ g_autoptr(GError) gerr = NULL;
char devpath[100];
if (as && mr) {
@@ -1095,10 +1082,10 @@
rom->path = g_strdup(file);
}
- fd = open(rom->path, O_RDONLY | O_BINARY);
- if (fd == -1) {
- fprintf(stderr, "Could not open option rom '%s': %s\n",
- rom->path, strerror(errno));
+ if (!g_file_get_contents(rom->path, (gchar **) &rom->data,
+ &size, &gerr)) {
+ fprintf(stderr, "rom: file %-20s: error %s\n",
+ rom->name, gerr->message);
goto err;
}
@@ -1107,23 +1094,8 @@
rom->fw_file = g_strdup(file);
}
rom->addr = addr;
- rom->romsize = lseek(fd, 0, SEEK_END);
- if (rom->romsize == -1) {
- fprintf(stderr, "rom: file %-20s: get size error: %s\n",
- rom->name, strerror(errno));
- goto err;
- }
-
+ rom->romsize = size;
rom->datasize = rom->romsize;
- rom->data = g_malloc0(rom->datasize);
- lseek(fd, 0, SEEK_SET);
- rc = read(fd, rom->data, rom->datasize);
- if (rc != rom->datasize) {
- fprintf(stderr, "rom: file %-20s: read error: rc=%zd (expected %zd)\n",
- rom->name, rc, rom->datasize);
- goto err;
- }
- close(fd);
rom_insert(rom);
if (rom->fw_file && fw_cfg) {
const char *basename;
@@ -1160,9 +1132,6 @@
return 0;
err:
- if (fd != -1)
- close(fd);
-
rom_free(rom);
return -1;
}
diff --git a/hw/display/ati.c b/hw/display/ati.c
index 8d2501b..b1f94f5 100644
--- a/hw/display/ati.c
+++ b/hw/display/ati.c
@@ -742,7 +742,7 @@
if (!s->cursor_guest_mode &&
(s->regs.crtc_gen_cntl & CRTC2_CUR_EN) && !(t & BIT(31))) {
dpy_mouse_set(s->vga.con, s->regs.cur_hv_pos >> 16,
- s->regs.cur_hv_pos & 0xffff, 1);
+ s->regs.cur_hv_pos & 0xffff, true);
}
break;
}
diff --git a/hw/display/qxl-render.c b/hw/display/qxl-render.c
index 8daae72..335d01e 100644
--- a/hw/display/qxl-render.c
+++ b/hw/display/qxl-render.c
@@ -307,10 +307,6 @@
return 1;
}
- if (!dpy_cursor_define_supported(qxl->vga.con)) {
- return 0;
- }
-
if (qxl->debug > 1 && cmd->type != QXL_CURSOR_MOVE) {
fprintf(stderr, "%s", __func__);
qxl_log_cmd_cursor(qxl, cmd, ext->group_id);
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index d60b1b2..3281842 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -109,8 +109,7 @@
s->cursor.pos.x = cursor->pos.x;
s->cursor.pos.y = cursor->pos.y;
}
- dpy_mouse_set(s->con, cursor->pos.x, cursor->pos.y,
- cursor->resource_id ? 1 : 0);
+ dpy_mouse_set(s->con, cursor->pos.x, cursor->pos.y, cursor->resource_id);
}
struct virtio_gpu_simple_resource *
diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c
index 1c0f9d9..3db3ff9 100644
--- a/hw/display/vmware_vga.c
+++ b/hw/display/vmware_vga.c
@@ -904,10 +904,8 @@
caps |= SVGA_CAP_RECT_FILL;
#endif
#ifdef HW_MOUSE_ACCEL
- if (dpy_cursor_define_supported(s->vga.con)) {
- caps |= SVGA_CAP_CURSOR | SVGA_CAP_CURSOR_BYPASS_2 |
- SVGA_CAP_CURSOR_BYPASS;
- }
+ caps |= SVGA_CAP_CURSOR | SVGA_CAP_CURSOR_BYPASS_2 |
+ SVGA_CAP_CURSOR_BYPASS;
#endif
ret = caps;
break;
@@ -1167,7 +1165,7 @@
s->enable = 0;
s->config = 0;
s->svgaid = SVGA_ID;
- s->cursor.on = 0;
+ s->cursor.on = false;
s->redraw_fifo_last = 0;
s->syncing = 0;
diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c
index 8582ac0..505b44c 100644
--- a/hw/isa/vt82c686.c
+++ b/hw/isa/vt82c686.c
@@ -719,7 +719,7 @@
ISABus *isa_bus;
int i;
- qdev_init_gpio_out(dev, &s->cpu_intr, 1);
+ qdev_init_gpio_out_named(dev, &s->cpu_intr, "intr", 1);
qdev_init_gpio_in_named(dev, via_isa_pirq, "pirq", PCI_NUM_PINS);
isa_irq = qemu_allocate_irqs(via_isa_request_i8259_irq, s, 1);
isa_bus = isa_bus_new(dev, pci_address_space(d), pci_address_space_io(d),
diff --git a/hw/mips/fuloong2e.c b/hw/mips/fuloong2e.c
index a45aac3..6e4303b 100644
--- a/hw/mips/fuloong2e.c
+++ b/hw/mips/fuloong2e.c
@@ -299,7 +299,7 @@
object_resolve_path_component(OBJECT(pci_dev),
"rtc"),
"date");
- qdev_connect_gpio_out(DEVICE(pci_dev), 0, env->irq[5]);
+ qdev_connect_gpio_out_named(DEVICE(pci_dev), "intr", 0, env->irq[5]);
dev = DEVICE(object_resolve_path_component(OBJECT(pci_dev), "ide"));
pci_ide_create_devs(PCI_DEVICE(dev));
diff --git a/hw/ppc/amigaone.c b/hw/ppc/amigaone.c
index ddfa094..900f93c 100644
--- a/hw/ppc/amigaone.c
+++ b/hw/ppc/amigaone.c
@@ -153,8 +153,9 @@
object_property_add_alias(OBJECT(machine), "rtc-time",
object_resolve_path_component(via, "rtc"),
"date");
- qdev_connect_gpio_out(DEVICE(via), 0,
- qdev_get_gpio_in(DEVICE(cpu), PPC6xx_INPUT_INT));
+ qdev_connect_gpio_out_named(DEVICE(via), "intr", 0,
+ qdev_get_gpio_in(DEVICE(cpu),
+ PPC6xx_INPUT_INT));
for (i = 0; i < PCI_NUM_PINS; i++) {
qdev_connect_gpio_out(dev, i, qdev_get_gpio_in_named(DEVICE(via),
"pirq", i));
diff --git a/hw/ppc/pegasos2.c b/hw/ppc/pegasos2.c
index c1bd8df..9b0a6b7 100644
--- a/hw/ppc/pegasos2.c
+++ b/hw/ppc/pegasos2.c
@@ -195,8 +195,8 @@
object_property_add_alias(OBJECT(machine), "rtc-time",
object_resolve_path_component(via, "rtc"),
"date");
- qdev_connect_gpio_out(DEVICE(via), 0,
- qdev_get_gpio_in_named(pm->mv, "gpp", 31));
+ qdev_connect_gpio_out_named(DEVICE(via), "intr", 0,
+ qdev_get_gpio_in_named(pm->mv, "gpp", 31));
dev = PCI_DEVICE(object_resolve_path_component(via, "ide"));
pci_ide_create_devs(dev);
diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
index 5d9b526..8504dd3 100644
--- a/hw/scsi/esp.c
+++ b/hw/scsi/esp.c
@@ -594,7 +594,7 @@
if (!s->current_req) {
return;
}
- if (s->async_len == 0 && esp_get_tc(s) && s->ti_size) {
+ if (s->async_len == 0 && esp_get_tc(s)) {
/* Defer until data is available. */
return;
}
@@ -647,7 +647,7 @@
if (!s->current_req) {
return;
}
- if (s->async_len == 0 && esp_get_tc(s) && s->ti_size) {
+ if (s->async_len == 0 && esp_get_tc(s)) {
/* Defer until data is available. */
return;
}
diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
index a2c8536..e6acfcb 100644
--- a/include/hw/core/cpu.h
+++ b/include/hw/core/cpu.h
@@ -985,6 +985,14 @@
void cpu_exit(CPUState *cpu);
/**
+ * cpu_pause:
+ * @cpu: The CPU to pause.
+ *
+ * Pauses CPU, i.e. puts CPU into stopped state.
+ */
+void cpu_pause(CPUState *cpu);
+
+/**
* cpu_resume:
* @cpu: The CPU to resume.
*
diff --git a/include/hw/loader.h b/include/hw/loader.h
index 9844c5e..7f6d06b 100644
--- a/include/hw/loader.h
+++ b/include/hw/loader.h
@@ -77,15 +77,13 @@
ssize_t load_image_mr(const char *filename, MemoryRegion *mr);
/* This is the limit on the maximum uncompressed image size that
- * load_image_gzipped_buffer() and load_image_gzipped() will read. It prevents
+ * load_image_gzipped_buffer() will read. It prevents
* g_malloc() in those functions from allocating a huge amount of memory.
*/
#define LOAD_IMAGE_MAX_GUNZIP_BYTES (256 << 20)
ssize_t load_image_gzipped_buffer(const char *filename, uint64_t max_sz,
uint8_t **buffer);
-ssize_t load_image_gzipped(const char *filename, hwaddr addr, uint64_t max_sz);
-
/**
* unpack_efi_zboot_image:
* @buffer: pointer to a variable holding the address of a buffer containing the
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index 5336728..77bfcbd 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -624,8 +624,9 @@
* @name: Name of the input GPIO array
* @n: Number of the GPIO line in that array (which must be in range)
*
- * Returns the qemu_irq corresponding to a named input GPIO line
- * (which the device has set up with qdev_init_gpio_in_named()).
+ * Returns the qemu_irq corresponding to a single input GPIO line
+ * in a named array of input GPIO lines on a device (which the device
+ * has set up with qdev_init_gpio_in_named()).
* The @name string must correspond to an input GPIO array which exists on
* the device, and the index @n of the GPIO line must be valid (i.e.
* be at least 0 and less than the total number of input GPIOs in that
@@ -673,15 +674,15 @@
* GPIO lines
* @dev: Device whose GPIO to connect
* @name: Name of the output GPIO array
- * @n: Number of the anonymous output GPIO line (which must be in range)
+ * @n: Number of the output GPIO line within that array (which must be in range)
* @input_pin: qemu_irq to connect the output line to
*
- * This function connects an anonymous output GPIO line on a device
- * up to an arbitrary qemu_irq, so that when the device asserts that
- * output GPIO line, the qemu_irq's callback is invoked.
+ * This function connects a single GPIO output in a named array of output
+ * GPIO lines on a device up to an arbitrary qemu_irq, so that when the
+ * device asserts that output GPIO line, the qemu_irq's callback is invoked.
* The @name string must correspond to an output GPIO array which exists on
* the device, and the index @n of the GPIO line must be valid (i.e.
- * be at least 0 and less than the total number of input GPIOs in that
+ * be at least 0 and less than the total number of output GPIOs in that
* array); this function will assert() if passed an invalid name or index.
*
* Outbound GPIO lines can be connected to any qemu_irq, but the common
@@ -796,7 +797,7 @@
* @dev: Device to create output GPIOs for
* @pins: Pointer to qemu_irq or qemu_irq array for the GPIO lines
* @name: Name to give this array of GPIO lines
- * @n: Number of GPIO lines to create
+ * @n: Number of GPIO lines to create in this array
*
* Like qdev_init_gpio_out(), but creates an array of GPIO output lines
* with a name. Code using the device can then connect these GPIO lines
diff --git a/include/ui/console.h b/include/ui/console.h
index a208a68..fa986ab 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -233,7 +233,7 @@
/* optional */
void (*dpy_mouse_set)(DisplayChangeListener *dcl,
- int x, int y, int on);
+ int x, int y, bool on);
/* optional */
void (*dpy_cursor_define)(DisplayChangeListener *dcl,
QEMUCursor *cursor);
@@ -322,9 +322,8 @@
void dpy_text_cursor(QemuConsole *con, int x, int y);
void dpy_text_update(QemuConsole *con, int x, int y, int w, int h);
void dpy_text_resize(QemuConsole *con, int w, int h);
-void dpy_mouse_set(QemuConsole *con, int x, int y, int on);
+void dpy_mouse_set(QemuConsole *con, int x, int y, bool on);
void dpy_cursor_define(QemuConsole *con, QEMUCursor *cursor);
-bool dpy_cursor_define_supported(QemuConsole *con);
bool dpy_gfx_check_format(QemuConsole *con,
pixman_format_code_t format);
diff --git a/meson.build b/meson.build
index 6a93da4..a1e5127 100644
--- a/meson.build
+++ b/meson.build
@@ -1070,7 +1070,8 @@
endif
endif
-cocoa = dependency('appleframeworks', modules: ['Cocoa', 'CoreVideo'],
+cocoa = dependency('appleframeworks',
+ modules: ['Cocoa', 'CoreVideo', 'QuartzCore'],
required: get_option('cocoa'))
vmnet = dependency('appleframeworks', modules: 'vmnet', required: get_option('vmnet'))
diff --git a/system/cpus.c b/system/cpus.c
index d3640c9..5e3a988 100644
--- a/system/cpus.c
+++ b/system/cpus.c
@@ -568,6 +568,22 @@
qemu_cond_signal(&qemu_cpu_cond);
}
+void cpu_pause(CPUState *cpu)
+{
+ if (qemu_cpu_is_self(cpu)) {
+ qemu_cpu_stop(cpu, true);
+ } else {
+ cpu->stop = true;
+ qemu_cpu_kick(cpu);
+ }
+}
+
+void cpu_resume(CPUState *cpu)
+{
+ cpu->stop = false;
+ cpu->stopped = false;
+ qemu_cpu_kick(cpu);
+}
static bool all_vcpus_paused(void)
{
@@ -588,12 +604,7 @@
qemu_clock_enable(QEMU_CLOCK_VIRTUAL, false);
CPU_FOREACH(cpu) {
- if (qemu_cpu_is_self(cpu)) {
- qemu_cpu_stop(cpu, true);
- } else {
- cpu->stop = true;
- qemu_cpu_kick(cpu);
- }
+ cpu_pause(cpu);
}
/* We need to drop the replay_lock so any vCPU threads woken up
@@ -613,13 +624,6 @@
bql_lock();
}
-void cpu_resume(CPUState *cpu)
-{
- cpu->stop = false;
- cpu->stopped = false;
- qemu_cpu_kick(cpu);
-}
-
void resume_all_vcpus(void)
{
CPUState *cpu;
diff --git a/system/physmem.c b/system/physmem.c
index 2154432..9a3b3a7 100644
--- a/system/physmem.c
+++ b/system/physmem.c
@@ -1845,11 +1845,14 @@
}
if (new_block->flags & RAM_GUEST_MEMFD) {
+ int ret;
+
assert(kvm_enabled());
assert(new_block->guest_memfd < 0);
- if (ram_block_discard_require(true) < 0) {
- error_setg_errno(errp, errno,
+ ret = ram_block_discard_require(true);
+ if (ret < 0) {
+ error_setg_errno(errp, -ret,
"cannot set up private guest memory: discard currently blocked");
error_append_hint(errp, "Are you using assigned devices?\n");
goto out_free;
diff --git a/system/vl.c b/system/vl.c
index bdd2f6e..9e8f16f 100644
--- a/system/vl.c
+++ b/system/vl.c
@@ -1000,9 +1000,16 @@
const VGAInterfaceInfo *ti = &vga_interfaces[t];
assert(t < VGA_TYPE_MAX);
- return !ti->class_names[0] ||
- module_object_class_by_name(ti->class_names[0]) ||
- module_object_class_by_name(ti->class_names[1]);
+
+ if (!ti->class_names[0] || module_object_class_by_name(ti->class_names[0])) {
+ return true;
+ }
+
+ if (ti->class_names[1] && module_object_class_by_name(ti->class_names[1])) {
+ return true;
+ }
+
+ return false;
}
static const char *
diff --git a/target/tricore/cpu.c b/target/tricore/cpu.c
index 4d9c036..1a26171 100644
--- a/target/tricore/cpu.c
+++ b/target/tricore/cpu.c
@@ -155,6 +155,11 @@
set_feature(&cpu->env, TRICORE_FEATURE_162);
}
+static bool tricore_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
+{
+ /* Interrupts are not implemented */
+ return false;
+}
#include "hw/core/sysemu-cpu-ops.h"
@@ -169,6 +174,7 @@
.synchronize_from_tb = tricore_cpu_synchronize_from_tb,
.restore_state_to_opc = tricore_restore_state_to_opc,
.tlb_fill = tricore_cpu_tlb_fill,
+ .cpu_exec_interrupt = tricore_cpu_exec_interrupt,
.cpu_exec_halt = tricore_cpu_has_work,
};
diff --git a/ui/cocoa.m b/ui/cocoa.m
index 2935247..4c2dd33 100644
--- a/ui/cocoa.m
+++ b/ui/cocoa.m
@@ -25,6 +25,7 @@
#include "qemu/osdep.h"
#import <Cocoa/Cocoa.h>
+#import <QuartzCore/QuartzCore.h>
#include <crt_externs.h>
#include "qemu/help-texts.h"
@@ -79,12 +80,16 @@
DisplaySurface *surface);
static void cocoa_refresh(DisplayChangeListener *dcl);
+static void cocoa_mouse_set(DisplayChangeListener *dcl, int x, int y, bool on);
+static void cocoa_cursor_define(DisplayChangeListener *dcl, QEMUCursor *cursor);
static const DisplayChangeListenerOps dcl_ops = {
.dpy_name = "cocoa",
.dpy_gfx_update = cocoa_update,
.dpy_gfx_switch = cocoa_switch,
.dpy_refresh = cocoa_refresh,
+ .dpy_mouse_set = cocoa_mouse_set,
+ .dpy_cursor_define = cocoa_cursor_define,
};
static DisplayChangeListener dcl = {
.ops = &dcl_ops,
@@ -307,6 +312,12 @@
BOOL isMouseGrabbed;
BOOL isAbsoluteEnabled;
CFMachPortRef eventsTap;
+ CGColorSpaceRef colorspace;
+ CALayer *cursorLayer;
+ QEMUCursor *cursor;
+ int mouseX;
+ int mouseY;
+ bool mouseOn;
}
- (void) switchSurface:(pixman_image_t *)image;
- (void) grabMouse;
@@ -359,9 +370,16 @@
[trackingArea release];
screen.width = frameRect.size.width;
screen.height = frameRect.size.height;
+ colorspace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_VERSION_14_0
[self setClipsToBounds:YES];
#endif
+ [self setWantsLayer:YES];
+ cursorLayer = [[CALayer alloc] init];
+ [cursorLayer setAnchorPoint:CGPointMake(0, 1)];
+ [cursorLayer setAutoresizingMask:kCALayerMaxXMargin |
+ kCALayerMinYMargin];
+ [[self layer] addSublayer:cursorLayer];
}
return self;
@@ -379,6 +397,9 @@
CFRelease(eventsTap);
}
+ CGColorSpaceRelease(colorspace);
+ [cursorLayer release];
+ cursor_unref(cursor);
[super dealloc];
}
@@ -423,6 +444,72 @@
[NSCursor unhide];
}
+- (void)setMouseX:(int)x y:(int)y on:(bool)on
+{
+ CGPoint position;
+
+ mouseX = x;
+ mouseY = y;
+ mouseOn = on;
+
+ position.x = mouseX;
+ position.y = screen.height - mouseY;
+
+ [CATransaction begin];
+ [CATransaction setDisableActions:YES];
+ [cursorLayer setPosition:position];
+ [cursorLayer setHidden:!mouseOn];
+ [CATransaction commit];
+}
+
+- (void)setCursor:(QEMUCursor *)given_cursor
+{
+ CGDataProviderRef provider;
+ CGImageRef image;
+ CGRect bounds = CGRectZero;
+
+ cursor_unref(cursor);
+ cursor = given_cursor;
+
+ if (!cursor) {
+ return;
+ }
+
+ cursor_ref(cursor);
+
+ bounds.size.width = cursor->width;
+ bounds.size.height = cursor->height;
+
+ provider = CGDataProviderCreateWithData(
+ NULL,
+ cursor->data,
+ cursor->width * cursor->height * 4,
+ NULL
+ );
+
+ image = CGImageCreate(
+ cursor->width, //width
+ cursor->height, //height
+ 8, //bitsPerComponent
+ 32, //bitsPerPixel
+ cursor->width * 4, //bytesPerRow
+ colorspace, //colorspace
+ kCGBitmapByteOrder32Little | kCGImageAlphaFirst, //bitmapInfo
+ provider, //provider
+ NULL, //decode
+ 0, //interpolate
+ kCGRenderingIntentDefault //intent
+ );
+
+ CGDataProviderRelease(provider);
+ [CATransaction begin];
+ [CATransaction setDisableActions:YES];
+ [cursorLayer setBounds:bounds];
+ [cursorLayer setContents:(id)image];
+ [CATransaction commit];
+ CGImageRelease(image);
+}
+
- (void) drawRect:(NSRect) rect
{
COCOA_DEBUG("QemuCocoaView: drawRect\n");
@@ -456,7 +543,7 @@
DIV_ROUND_UP(bitsPerPixel, 8) * 2, //bitsPerComponent
bitsPerPixel, //bitsPerPixel
stride, //bytesPerRow
- CGColorSpaceCreateWithName(kCGColorSpaceSRGB), //colorspace
+ colorspace, //colorspace
kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst, //bitmapInfo
dataProviderRef, //provider
NULL, //decode
@@ -2012,6 +2099,21 @@
[pool release];
}
+static void cocoa_mouse_set(DisplayChangeListener *dcl, int x, int y, bool on)
+{
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [cocoaView setMouseX:x y:y on:on];
+ });
+}
+
+static void cocoa_cursor_define(DisplayChangeListener *dcl, QEMUCursor *cursor)
+{
+ dispatch_async(dispatch_get_main_queue(), ^{
+ BQL_LOCK_GUARD();
+ [cocoaView setCursor:qemu_console_get_cursor(dcl->con)];
+ });
+}
+
static void cocoa_display_init(DisplayState *ds, DisplayOptions *opts)
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
diff --git a/ui/console.c b/ui/console.c
index e67c5da..e8f0083 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -49,7 +49,8 @@
uint32_t head;
QEMUCursor *cursor;
- int cursor_x, cursor_y, cursor_on;
+ int cursor_x, cursor_y;
+ bool cursor_on;
} QemuGraphicConsole;
typedef QemuConsoleClass QemuGraphicConsoleClass;
@@ -957,7 +958,7 @@
}
}
-void dpy_mouse_set(QemuConsole *c, int x, int y, int on)
+void dpy_mouse_set(QemuConsole *c, int x, int y, bool on)
{
QemuGraphicConsole *con = QEMU_GRAPHIC_CONSOLE(c);
DisplayState *s = c->ds;
@@ -1000,19 +1001,6 @@
}
}
-bool dpy_cursor_define_supported(QemuConsole *con)
-{
- DisplayState *s = con->ds;
- DisplayChangeListener *dcl;
-
- QLIST_FOREACH(dcl, &s->listeners, next) {
- if (dcl->ops->dpy_cursor_define) {
- return true;
- }
- }
- return false;
-}
-
QEMUGLContext dpy_gl_ctx_create(QemuConsole *con,
struct QEMUGLParams *qparams)
{
diff --git a/ui/dbus-listener.c b/ui/dbus-listener.c
index 5490088..a54123a 100644
--- a/ui/dbus-listener.c
+++ b/ui/dbus-listener.c
@@ -726,7 +726,7 @@
}
static void dbus_mouse_set(DisplayChangeListener *dcl,
- int x, int y, int on)
+ int x, int y, bool on)
{
DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener, dcl);
diff --git a/ui/gtk.c b/ui/gtk.c
index 93b13b7..bc29f7a 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -446,7 +446,7 @@
}
static void gd_mouse_set(DisplayChangeListener *dcl,
- int x, int y, int visible)
+ int x, int y, bool visible)
{
VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
GdkDisplay *dpy;
diff --git a/ui/sdl2.c b/ui/sdl2.c
index 0a0eb5a..98ed974 100644
--- a/ui/sdl2.c
+++ b/ui/sdl2.c
@@ -49,7 +49,7 @@
static SDL_Cursor *sdl_cursor_normal;
static SDL_Cursor *sdl_cursor_hidden;
static int absolute_enabled;
-static int guest_cursor;
+static bool guest_cursor;
static int guest_x, guest_y;
static SDL_Cursor *guest_sprite;
static Notifier mouse_mode_notifier;
@@ -729,7 +729,7 @@
}
static void sdl_mouse_warp(DisplayChangeListener *dcl,
- int x, int y, int on)
+ int x, int y, bool on)
{
struct sdl2_console *scon = container_of(dcl, struct sdl2_console, dcl);
diff --git a/ui/spice-display.c b/ui/spice-display.c
index 8a8472d..c794ae0 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
@@ -254,7 +254,7 @@
static SimpleSpiceCursor*
qemu_spice_create_cursor_update(SimpleSpiceDisplay *ssd,
QEMUCursor *c,
- int on)
+ bool on)
{
size_t size = c ? c->width * c->height * 4 : 0;
SimpleSpiceCursor *update;
@@ -448,7 +448,8 @@
qemu_mutex_lock(&ssd->lock);
if (ssd->cursor) {
g_free(ssd->ptr_define);
- ssd->ptr_define = qemu_spice_create_cursor_update(ssd, ssd->cursor, 0);
+ ssd->ptr_define =
+ qemu_spice_create_cursor_update(ssd, ssd->cursor, false);
}
qemu_mutex_unlock(&ssd->lock);
}
@@ -476,7 +477,7 @@
ssd->mouse_x = -1;
ssd->mouse_y = -1;
qemu_mutex_unlock(&ssd->lock);
- dpy_mouse_set(ssd->dcl.con, x, y, 1);
+ dpy_mouse_set(ssd->dcl.con, x, y, true);
} else {
qemu_mutex_unlock(&ssd->lock);
}
@@ -747,7 +748,7 @@
}
static void display_mouse_set(DisplayChangeListener *dcl,
- int x, int y, int on)
+ int x, int y, bool on)
{
SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl);
@@ -774,7 +775,7 @@
g_free(ssd->ptr_move);
ssd->ptr_move = NULL;
g_free(ssd->ptr_define);
- ssd->ptr_define = qemu_spice_create_cursor_update(ssd, c, 0);
+ ssd->ptr_define = qemu_spice_create_cursor_update(ssd, c, false);
qemu_mutex_unlock(&ssd->lock);
qemu_spice_wakeup(ssd);
}
diff --git a/ui/vnc.c b/ui/vnc.c
index dd530f0..dae5d51 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -981,7 +981,7 @@
}
static void vnc_mouse_set(DisplayChangeListener *dcl,
- int x, int y, int visible)
+ int x, int y, bool visible)
{
/* can we ask the client(s) to move the pointer ??? */
}