mirror of https://gitee.com/openkylin/qemu.git
ui: add egl-headless
ui: some vnc cleanups ui: absolute events for input-linux -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABAgAGBQJZFaFvAAoJEEy22O7T6HE4TqgP/1bwf3/W6Xmg51A93URWK4uq RWGc9nCtIPh+CieqUByHGwDdV88p/6UBuLsXosHG3DM4olRgynAUOjTMBCe9Mq8Q nF2LSPW273Ir/H5bzrDP+3m6roxoMQQbSeXRuA5vQ8u4HpD+Y17T7NOeiwCLFg49 96zSKlucIWHFkGHO4n6fwWR+sIVhsPXwOykFO7EScGav5Ir9SuFJDUx+JeBQ7wot eOKiYEKaJKKnjFHFUYQnyUq+6cZBbuR9B3FRHaCNTxGuWjCXxPO8O1Pz4B2oIZH9 +pcvg+2f12Zw+dm0pMZHO5sH5hkIY7xzRMkFH0ifpscmGNuJT6oJ9xA4x+sJkAiX FrcunzAH939LtcgNloZq07PXhA8O+LqHiTKIPr1ZXomnW3jSmfuNvW1TwADJsL2E 1Pnateibdiz7Xyb4b7hcvgYvjXA3iKbMgfpvu4n7x2P5orHaylmadXFfBjiOJ+u+ z5n1ip3v417javuIAKwYepvHYjvkbcMPtUrkKwja6F+C3jvTH6wc+wMRrKPQxnOJ ZTPrlcEJOqSCYdzxI/fqg8B/HSDr1bcMX+odrCeJWC2O8deAld1aVXaFXz+JW483 zi2vIBh+kHh6VHDtJynv7Sv7mUCY7jWEiBY6AidnMLR6zomKtwrn7wWqxBbCvI5g IVWjoRqul6sTNl3ywMhc =FimK -----END PGP SIGNATURE----- Merge remote-tracking branch 'kraxel/tags/pull-ui-20170512-1' into staging ui: add egl-headless ui: some vnc cleanups ui: absolute events for input-linux # gpg: Signature made Fri 12 May 2017 12:50:07 PM BST # gpg: using RSA key 0x4CB6D8EED3E87138 # gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>" # gpg: aka "Gerd Hoffmann <gerd@kraxel.org>" # gpg: aka "Gerd Hoffmann (private) <kraxel@gmail.com>" # Primary key fingerprint: A032 8CFF B93A 17A7 9901 FE7D 4CB6 D8EE D3E8 7138 * kraxel/tags/pull-ui-20170512-1: vnc: replace hweight_long() with ctpopl() vnc: simple clean up opengl: add egl-headless display egl: explicitly ask for core context egl-helpers: add missing error check egl-helpers: fix display init for x11 egl-helpers: drop support for gles and debug logging virtio-gpu: move virtio_gpu_gl_block ui: input-linux: Add absolute event support ui: Support non-zero minimum values for absolute input axes Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
commit
384d9d554a
|
@ -600,6 +600,22 @@ void virtio_gpu_virgl_reset(VirtIOGPU *g)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void virtio_gpu_gl_block(void *opaque, bool block)
|
||||||
|
{
|
||||||
|
VirtIOGPU *g = opaque;
|
||||||
|
|
||||||
|
if (block) {
|
||||||
|
g->renderer_blocked++;
|
||||||
|
} else {
|
||||||
|
g->renderer_blocked--;
|
||||||
|
}
|
||||||
|
assert(g->renderer_blocked >= 0);
|
||||||
|
|
||||||
|
if (g->renderer_blocked == 0) {
|
||||||
|
virtio_gpu_process_cmdq(g);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int virtio_gpu_virgl_init(VirtIOGPU *g)
|
int virtio_gpu_virgl_init(VirtIOGPU *g)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
|
@ -929,28 +929,14 @@ static int virtio_gpu_ui_info(void *opaque, uint32_t idx, QemuUIInfo *info)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void virtio_gpu_gl_block(void *opaque, bool block)
|
|
||||||
{
|
|
||||||
VirtIOGPU *g = opaque;
|
|
||||||
|
|
||||||
if (block) {
|
|
||||||
g->renderer_blocked++;
|
|
||||||
} else {
|
|
||||||
g->renderer_blocked--;
|
|
||||||
}
|
|
||||||
assert(g->renderer_blocked >= 0);
|
|
||||||
|
|
||||||
if (g->renderer_blocked == 0) {
|
|
||||||
virtio_gpu_process_cmdq(g);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const GraphicHwOps virtio_gpu_ops = {
|
const GraphicHwOps virtio_gpu_ops = {
|
||||||
.invalidate = virtio_gpu_invalidate_display,
|
.invalidate = virtio_gpu_invalidate_display,
|
||||||
.gfx_update = virtio_gpu_update_display,
|
.gfx_update = virtio_gpu_update_display,
|
||||||
.text_update = virtio_gpu_text_update,
|
.text_update = virtio_gpu_text_update,
|
||||||
.ui_info = virtio_gpu_ui_info,
|
.ui_info = virtio_gpu_ui_info,
|
||||||
|
#ifdef CONFIG_VIRGL
|
||||||
.gl_block = virtio_gpu_gl_block,
|
.gl_block = virtio_gpu_gl_block,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static const VMStateDescription vmstate_virtio_gpu_scanout = {
|
static const VMStateDescription vmstate_virtio_gpu_scanout = {
|
||||||
|
|
|
@ -484,12 +484,14 @@ static struct virtio_input_config virtio_tablet_config[] = {
|
||||||
.select = VIRTIO_INPUT_CFG_ABS_INFO,
|
.select = VIRTIO_INPUT_CFG_ABS_INFO,
|
||||||
.subsel = ABS_X,
|
.subsel = ABS_X,
|
||||||
.size = sizeof(virtio_input_absinfo),
|
.size = sizeof(virtio_input_absinfo),
|
||||||
.u.abs.max = const_le32(INPUT_EVENT_ABS_SIZE - 1),
|
.u.abs.min = const_le32(INPUT_EVENT_ABS_MIN),
|
||||||
|
.u.abs.max = const_le32(INPUT_EVENT_ABS_MAX),
|
||||||
},{
|
},{
|
||||||
.select = VIRTIO_INPUT_CFG_ABS_INFO,
|
.select = VIRTIO_INPUT_CFG_ABS_INFO,
|
||||||
.subsel = ABS_Y,
|
.subsel = ABS_Y,
|
||||||
.size = sizeof(virtio_input_absinfo),
|
.size = sizeof(virtio_input_absinfo),
|
||||||
.u.abs.max = const_le32(INPUT_EVENT_ABS_SIZE - 1),
|
.u.abs.min = const_le32(INPUT_EVENT_ABS_MIN),
|
||||||
|
.u.abs.max = const_le32(INPUT_EVENT_ABS_MAX),
|
||||||
},
|
},
|
||||||
{ /* end of list */ },
|
{ /* end of list */ },
|
||||||
};
|
};
|
||||||
|
|
|
@ -169,6 +169,7 @@ void virtio_gpu_virgl_process_cmd(VirtIOGPU *g,
|
||||||
struct virtio_gpu_ctrl_command *cmd);
|
struct virtio_gpu_ctrl_command *cmd);
|
||||||
void virtio_gpu_virgl_fence_poll(VirtIOGPU *g);
|
void virtio_gpu_virgl_fence_poll(VirtIOGPU *g);
|
||||||
void virtio_gpu_virgl_reset(VirtIOGPU *g);
|
void virtio_gpu_virgl_reset(VirtIOGPU *g);
|
||||||
|
void virtio_gpu_gl_block(void *opaque, bool block);
|
||||||
int virtio_gpu_virgl_init(VirtIOGPU *g);
|
int virtio_gpu_virgl_init(VirtIOGPU *g);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -201,16 +201,6 @@ static inline unsigned long find_first_zero_bit(const unsigned long *addr,
|
||||||
return find_next_zero_bit(addr, size, 0);
|
return find_next_zero_bit(addr, size, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned long hweight_long(unsigned long w)
|
|
||||||
{
|
|
||||||
unsigned long count;
|
|
||||||
|
|
||||||
for (count = 0; w; w >>= 1) {
|
|
||||||
count += w & 1;
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* rol8 - rotate an 8-bit value left
|
* rol8 - rotate an 8-bit value left
|
||||||
* @word: value to rotate
|
* @word: value to rotate
|
||||||
|
|
|
@ -527,4 +527,7 @@ static inline void early_gtk_display_init(int opengl)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* egl-headless.c */
|
||||||
|
void egl_headless_init(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -21,7 +21,8 @@ int egl_get_fd_for_texture(uint32_t tex_id, EGLint *stride, EGLint *fourcc);
|
||||||
|
|
||||||
EGLSurface qemu_egl_init_surface_x11(EGLContext ectx, Window win);
|
EGLSurface qemu_egl_init_surface_x11(EGLContext ectx, Window win);
|
||||||
|
|
||||||
int qemu_egl_init_dpy(EGLNativeDisplayType dpy, bool gles, bool debug);
|
int qemu_egl_init_dpy_x11(EGLNativeDisplayType dpy);
|
||||||
|
int qemu_egl_init_dpy_mesa(EGLNativeDisplayType dpy);
|
||||||
EGLContext qemu_egl_init_ctx(void);
|
EGLContext qemu_egl_init_ctx(void);
|
||||||
|
|
||||||
#endif /* EGL_HELPERS_H */
|
#endif /* EGL_HELPERS_H */
|
||||||
|
|
|
@ -8,7 +8,8 @@
|
||||||
#define INPUT_EVENT_MASK_REL (1<<INPUT_EVENT_KIND_REL)
|
#define INPUT_EVENT_MASK_REL (1<<INPUT_EVENT_KIND_REL)
|
||||||
#define INPUT_EVENT_MASK_ABS (1<<INPUT_EVENT_KIND_ABS)
|
#define INPUT_EVENT_MASK_ABS (1<<INPUT_EVENT_KIND_ABS)
|
||||||
|
|
||||||
#define INPUT_EVENT_ABS_SIZE 0x8000
|
#define INPUT_EVENT_ABS_MIN 0x0000
|
||||||
|
#define INPUT_EVENT_ABS_MAX 0x7FFF
|
||||||
|
|
||||||
typedef struct QemuInputHandler QemuInputHandler;
|
typedef struct QemuInputHandler QemuInputHandler;
|
||||||
typedef struct QemuInputHandlerState QemuInputHandlerState;
|
typedef struct QemuInputHandlerState QemuInputHandlerState;
|
||||||
|
@ -54,12 +55,14 @@ void qemu_input_update_buttons(QemuConsole *src, uint32_t *button_map,
|
||||||
uint32_t button_old, uint32_t button_new);
|
uint32_t button_old, uint32_t button_new);
|
||||||
|
|
||||||
bool qemu_input_is_absolute(void);
|
bool qemu_input_is_absolute(void);
|
||||||
int qemu_input_scale_axis(int value, int size_in, int size_out);
|
int qemu_input_scale_axis(int value,
|
||||||
|
int min_in, int max_in,
|
||||||
|
int min_out, int max_out);
|
||||||
InputEvent *qemu_input_event_new_move(InputEventKind kind,
|
InputEvent *qemu_input_event_new_move(InputEventKind kind,
|
||||||
InputAxis axis, int value);
|
InputAxis axis, int value);
|
||||||
void qemu_input_queue_rel(QemuConsole *src, InputAxis axis, int value);
|
void qemu_input_queue_rel(QemuConsole *src, InputAxis axis, int value);
|
||||||
void qemu_input_queue_abs(QemuConsole *src, InputAxis axis,
|
void qemu_input_queue_abs(QemuConsole *src, InputAxis axis, int value,
|
||||||
int value, int size);
|
int min_in, int max_in);
|
||||||
|
|
||||||
void qemu_input_check_mode_change(void);
|
void qemu_input_check_mode_change(void);
|
||||||
void qemu_add_mouse_mode_change_notifier(Notifier *notify);
|
void qemu_add_mouse_mode_change_notifier(Notifier *notify);
|
||||||
|
|
|
@ -33,6 +33,7 @@ common-obj-y += shader.o
|
||||||
common-obj-y += console-gl.o
|
common-obj-y += console-gl.o
|
||||||
common-obj-y += egl-helpers.o
|
common-obj-y += egl-helpers.o
|
||||||
common-obj-y += egl-context.o
|
common-obj-y += egl-context.o
|
||||||
|
common-obj-y += egl-headless.o
|
||||||
ifeq ($(CONFIG_GTK_GL),y)
|
ifeq ($(CONFIG_GTK_GL),y)
|
||||||
common-obj-$(CONFIG_GTK) += gtk-gl-area.o
|
common-obj-$(CONFIG_GTK) += gtk-gl-area.o
|
||||||
else
|
else
|
||||||
|
|
|
@ -749,8 +749,8 @@ - (void) handleEvent:(NSEvent *)event
|
||||||
* clicks in the titlebar.
|
* clicks in the titlebar.
|
||||||
*/
|
*/
|
||||||
if ([self screenContainsPoint:p]) {
|
if ([self screenContainsPoint:p]) {
|
||||||
qemu_input_queue_abs(dcl->con, INPUT_AXIS_X, p.x, screen.width);
|
qemu_input_queue_abs(dcl->con, INPUT_AXIS_X, p.x, 0, screen.width);
|
||||||
qemu_input_queue_abs(dcl->con, INPUT_AXIS_Y, screen.height - p.y, screen.height);
|
qemu_input_queue_abs(dcl->con, INPUT_AXIS_Y, screen.height - p.y, 0, screen.height);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
qemu_input_queue_rel(dcl->con, INPUT_AXIS_X, (int)[event deltaX]);
|
qemu_input_queue_rel(dcl->con, INPUT_AXIS_X, (int)[event deltaX]);
|
||||||
|
|
|
@ -7,9 +7,10 @@ QEMUGLContext qemu_egl_create_context(DisplayChangeListener *dcl,
|
||||||
{
|
{
|
||||||
EGLContext ctx;
|
EGLContext ctx;
|
||||||
EGLint ctx_att[] = {
|
EGLint ctx_att[] = {
|
||||||
EGL_CONTEXT_CLIENT_VERSION, params->major_ver,
|
EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
|
||||||
EGL_CONTEXT_MINOR_VERSION_KHR, params->minor_ver,
|
EGL_CONTEXT_CLIENT_VERSION, params->major_ver,
|
||||||
EGL_NONE
|
EGL_CONTEXT_MINOR_VERSION_KHR, params->minor_ver,
|
||||||
|
EGL_NONE
|
||||||
};
|
};
|
||||||
|
|
||||||
ctx = eglCreateContext(qemu_egl_display, qemu_egl_config,
|
ctx = eglCreateContext(qemu_egl_display, qemu_egl_config,
|
||||||
|
|
|
@ -0,0 +1,158 @@
|
||||||
|
#include "qemu/osdep.h"
|
||||||
|
#include "qemu-common.h"
|
||||||
|
#include "sysemu/sysemu.h"
|
||||||
|
#include "ui/console.h"
|
||||||
|
#include "ui/egl-helpers.h"
|
||||||
|
#include "ui/egl-context.h"
|
||||||
|
|
||||||
|
typedef struct egl_dpy {
|
||||||
|
DisplayChangeListener dcl;
|
||||||
|
DisplaySurface *ds;
|
||||||
|
int width, height;
|
||||||
|
GLuint texture;
|
||||||
|
GLuint framebuffer;
|
||||||
|
GLuint blit_texture;
|
||||||
|
GLuint blit_framebuffer;
|
||||||
|
bool y_0_top;
|
||||||
|
} egl_dpy;
|
||||||
|
|
||||||
|
static void egl_refresh(DisplayChangeListener *dcl)
|
||||||
|
{
|
||||||
|
graphic_hw_update(dcl->con);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void egl_gfx_update(DisplayChangeListener *dcl,
|
||||||
|
int x, int y, int w, int h)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void egl_gfx_switch(DisplayChangeListener *dcl,
|
||||||
|
struct DisplaySurface *new_surface)
|
||||||
|
{
|
||||||
|
egl_dpy *edpy = container_of(dcl, egl_dpy, dcl);
|
||||||
|
|
||||||
|
edpy->ds = new_surface;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void egl_scanout_disable(DisplayChangeListener *dcl)
|
||||||
|
{
|
||||||
|
egl_dpy *edpy = container_of(dcl, egl_dpy, dcl);
|
||||||
|
|
||||||
|
edpy->texture = 0;
|
||||||
|
/* XXX: delete framebuffers here ??? */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void egl_scanout_texture(DisplayChangeListener *dcl,
|
||||||
|
uint32_t backing_id,
|
||||||
|
bool backing_y_0_top,
|
||||||
|
uint32_t backing_width,
|
||||||
|
uint32_t backing_height,
|
||||||
|
uint32_t x, uint32_t y,
|
||||||
|
uint32_t w, uint32_t h)
|
||||||
|
{
|
||||||
|
egl_dpy *edpy = container_of(dcl, egl_dpy, dcl);
|
||||||
|
|
||||||
|
edpy->texture = backing_id;
|
||||||
|
edpy->y_0_top = backing_y_0_top;
|
||||||
|
|
||||||
|
/* source framebuffer */
|
||||||
|
if (!edpy->framebuffer) {
|
||||||
|
glGenFramebuffers(1, &edpy->framebuffer);
|
||||||
|
}
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER_EXT, edpy->framebuffer);
|
||||||
|
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
|
||||||
|
GL_TEXTURE_2D, edpy->texture, 0);
|
||||||
|
|
||||||
|
/* dest framebuffer */
|
||||||
|
if (!edpy->blit_framebuffer) {
|
||||||
|
glGenFramebuffers(1, &edpy->blit_framebuffer);
|
||||||
|
glGenTextures(1, &edpy->blit_texture);
|
||||||
|
edpy->width = 0;
|
||||||
|
edpy->height = 0;
|
||||||
|
}
|
||||||
|
if (edpy->width != backing_width || edpy->height != backing_height) {
|
||||||
|
edpy->width = backing_width;
|
||||||
|
edpy->height = backing_height;
|
||||||
|
glBindTexture(GL_TEXTURE_2D, edpy->blit_texture);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
|
||||||
|
edpy->width, edpy->height,
|
||||||
|
0, GL_BGRA, GL_UNSIGNED_BYTE, 0);
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER_EXT, edpy->blit_framebuffer);
|
||||||
|
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
|
||||||
|
GL_TEXTURE_2D, edpy->blit_texture, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void egl_scanout_flush(DisplayChangeListener *dcl,
|
||||||
|
uint32_t x, uint32_t y,
|
||||||
|
uint32_t w, uint32_t h)
|
||||||
|
{
|
||||||
|
egl_dpy *edpy = container_of(dcl, egl_dpy, dcl);
|
||||||
|
GLuint y1, y2;
|
||||||
|
|
||||||
|
if (!edpy->texture || !edpy->ds) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
assert(surface_width(edpy->ds) == edpy->width);
|
||||||
|
assert(surface_height(edpy->ds) == edpy->height);
|
||||||
|
assert(surface_format(edpy->ds) == PIXMAN_x8r8g8b8);
|
||||||
|
|
||||||
|
/* blit framebuffer, flip if needed */
|
||||||
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, edpy->framebuffer);
|
||||||
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, edpy->blit_framebuffer);
|
||||||
|
glViewport(0, 0, edpy->width, edpy->height);
|
||||||
|
y1 = edpy->y_0_top ? edpy->height : 0;
|
||||||
|
y2 = edpy->y_0_top ? 0 : edpy->height;
|
||||||
|
glBlitFramebuffer(0, y1, edpy->width, y2,
|
||||||
|
0, 0, edpy->width, edpy->height,
|
||||||
|
GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||||
|
|
||||||
|
/* read pixels to surface */
|
||||||
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, edpy->blit_framebuffer);
|
||||||
|
glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
|
||||||
|
glReadPixels(0, 0, edpy->width, edpy->height,
|
||||||
|
GL_BGRA, GL_UNSIGNED_BYTE, surface_data(edpy->ds));
|
||||||
|
|
||||||
|
/* notify about updates */
|
||||||
|
dpy_gfx_update(edpy->dcl.con, x, y, w, h);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const DisplayChangeListenerOps egl_ops = {
|
||||||
|
.dpy_name = "egl-headless",
|
||||||
|
.dpy_refresh = egl_refresh,
|
||||||
|
.dpy_gfx_update = egl_gfx_update,
|
||||||
|
.dpy_gfx_switch = egl_gfx_switch,
|
||||||
|
|
||||||
|
.dpy_gl_ctx_create = qemu_egl_create_context,
|
||||||
|
.dpy_gl_ctx_destroy = qemu_egl_destroy_context,
|
||||||
|
.dpy_gl_ctx_make_current = qemu_egl_make_context_current,
|
||||||
|
.dpy_gl_ctx_get_current = qemu_egl_get_current_context,
|
||||||
|
|
||||||
|
.dpy_gl_scanout_disable = egl_scanout_disable,
|
||||||
|
.dpy_gl_scanout_texture = egl_scanout_texture,
|
||||||
|
.dpy_gl_update = egl_scanout_flush,
|
||||||
|
};
|
||||||
|
|
||||||
|
void egl_headless_init(void)
|
||||||
|
{
|
||||||
|
QemuConsole *con;
|
||||||
|
egl_dpy *edpy;
|
||||||
|
int idx;
|
||||||
|
|
||||||
|
if (egl_rendernode_init(NULL) < 0) {
|
||||||
|
error_report("egl: render node init failed");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (idx = 0;; idx++) {
|
||||||
|
con = qemu_console_lookup_by_index(idx);
|
||||||
|
if (!con || !qemu_console_is_graphic(con)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
edpy = g_new0(egl_dpy, 1);
|
||||||
|
edpy->dcl.con = con;
|
||||||
|
edpy->dcl.ops = &egl_ops;
|
||||||
|
register_displaychangelistener(&edpy->dcl);
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,18 +26,6 @@ EGLConfig qemu_egl_config;
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
static bool egl_gles;
|
|
||||||
static int egl_debug;
|
|
||||||
|
|
||||||
#define egl_dbg(_x ...) \
|
|
||||||
do { \
|
|
||||||
if (egl_debug) { \
|
|
||||||
fprintf(stderr, "egl: " _x); \
|
|
||||||
} \
|
|
||||||
} while (0);
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
#ifdef CONFIG_OPENGL_DMABUF
|
#ifdef CONFIG_OPENGL_DMABUF
|
||||||
|
|
||||||
int qemu_egl_rn_fd;
|
int qemu_egl_rn_fd;
|
||||||
|
@ -92,6 +80,7 @@ static int qemu_egl_rendernode_open(const char *rendernode)
|
||||||
int egl_rendernode_init(const char *rendernode)
|
int egl_rendernode_init(const char *rendernode)
|
||||||
{
|
{
|
||||||
qemu_egl_rn_fd = -1;
|
qemu_egl_rn_fd = -1;
|
||||||
|
int rc;
|
||||||
|
|
||||||
qemu_egl_rn_fd = qemu_egl_rendernode_open(rendernode);
|
qemu_egl_rn_fd = qemu_egl_rendernode_open(rendernode);
|
||||||
if (qemu_egl_rn_fd == -1) {
|
if (qemu_egl_rn_fd == -1) {
|
||||||
|
@ -105,7 +94,11 @@ int egl_rendernode_init(const char *rendernode)
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
qemu_egl_init_dpy((EGLNativeDisplayType)qemu_egl_rn_gbm_dev, false, false);
|
rc = qemu_egl_init_dpy_mesa((EGLNativeDisplayType)qemu_egl_rn_gbm_dev);
|
||||||
|
if (rc != 0) {
|
||||||
|
/* qemu_egl_init_dpy_mesa reports error */
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
if (!epoxy_has_egl_extension(qemu_egl_display,
|
if (!epoxy_has_egl_extension(qemu_egl_display,
|
||||||
"EGL_KHR_surfaceless_context")) {
|
"EGL_KHR_surfaceless_context")) {
|
||||||
|
@ -171,8 +164,6 @@ EGLSurface qemu_egl_init_surface_x11(EGLContext ectx, Window win)
|
||||||
EGLSurface esurface;
|
EGLSurface esurface;
|
||||||
EGLBoolean b;
|
EGLBoolean b;
|
||||||
|
|
||||||
egl_dbg("eglCreateWindowSurface (x11 win id 0x%lx) ...\n",
|
|
||||||
(unsigned long) win);
|
|
||||||
esurface = eglCreateWindowSurface(qemu_egl_display,
|
esurface = eglCreateWindowSurface(qemu_egl_display,
|
||||||
qemu_egl_config,
|
qemu_egl_config,
|
||||||
(EGLNativeWindowType)win, NULL);
|
(EGLNativeWindowType)win, NULL);
|
||||||
|
@ -220,20 +211,19 @@ EGLSurface qemu_egl_init_surface_x11(EGLContext ectx, Window win)
|
||||||
* platform extensions (EGL_KHR_platform_gbm and friends) yet it doesn't seem
|
* platform extensions (EGL_KHR_platform_gbm and friends) yet it doesn't seem
|
||||||
* like mesa will be able to advertise these (even though it can do EGL 1.5).
|
* like mesa will be able to advertise these (even though it can do EGL 1.5).
|
||||||
*/
|
*/
|
||||||
static EGLDisplay qemu_egl_get_display(void *native)
|
static EGLDisplay qemu_egl_get_display(EGLNativeDisplayType native,
|
||||||
|
EGLenum platform)
|
||||||
{
|
{
|
||||||
EGLDisplay dpy = EGL_NO_DISPLAY;
|
EGLDisplay dpy = EGL_NO_DISPLAY;
|
||||||
|
|
||||||
#ifdef EGL_MESA_platform_gbm
|
|
||||||
/* In practise any EGL 1.5 implementation would support the EXT extension */
|
/* In practise any EGL 1.5 implementation would support the EXT extension */
|
||||||
if (epoxy_has_egl_extension(NULL, "EGL_EXT_platform_base")) {
|
if (epoxy_has_egl_extension(NULL, "EGL_EXT_platform_base")) {
|
||||||
PFNEGLGETPLATFORMDISPLAYEXTPROC getPlatformDisplayEXT =
|
PFNEGLGETPLATFORMDISPLAYEXTPROC getPlatformDisplayEXT =
|
||||||
(void *) eglGetProcAddress("eglGetPlatformDisplayEXT");
|
(void *) eglGetProcAddress("eglGetPlatformDisplayEXT");
|
||||||
if (getPlatformDisplayEXT) {
|
if (getPlatformDisplayEXT && platform != 0) {
|
||||||
dpy = getPlatformDisplayEXT(EGL_PLATFORM_GBM_MESA, native, NULL);
|
dpy = getPlatformDisplayEXT(platform, native, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
if (dpy == EGL_NO_DISPLAY) {
|
if (dpy == EGL_NO_DISPLAY) {
|
||||||
/* fallback */
|
/* fallback */
|
||||||
|
@ -242,7 +232,8 @@ static EGLDisplay qemu_egl_get_display(void *native)
|
||||||
return dpy;
|
return dpy;
|
||||||
}
|
}
|
||||||
|
|
||||||
int qemu_egl_init_dpy(EGLNativeDisplayType dpy, bool gles, bool debug)
|
static int qemu_egl_init_dpy(EGLNativeDisplayType dpy,
|
||||||
|
EGLenum platform)
|
||||||
{
|
{
|
||||||
static const EGLint conf_att_gl[] = {
|
static const EGLint conf_att_gl[] = {
|
||||||
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
|
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
|
||||||
|
@ -253,75 +244,66 @@ int qemu_egl_init_dpy(EGLNativeDisplayType dpy, bool gles, bool debug)
|
||||||
EGL_ALPHA_SIZE, 0,
|
EGL_ALPHA_SIZE, 0,
|
||||||
EGL_NONE,
|
EGL_NONE,
|
||||||
};
|
};
|
||||||
static const EGLint conf_att_gles[] = {
|
|
||||||
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
|
|
||||||
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
|
|
||||||
EGL_RED_SIZE, 5,
|
|
||||||
EGL_GREEN_SIZE, 5,
|
|
||||||
EGL_BLUE_SIZE, 5,
|
|
||||||
EGL_ALPHA_SIZE, 0,
|
|
||||||
EGL_NONE,
|
|
||||||
};
|
|
||||||
EGLint major, minor;
|
EGLint major, minor;
|
||||||
EGLBoolean b;
|
EGLBoolean b;
|
||||||
EGLint n;
|
EGLint n;
|
||||||
|
|
||||||
if (debug) {
|
qemu_egl_display = qemu_egl_get_display(dpy, platform);
|
||||||
egl_debug = 1;
|
|
||||||
setenv("EGL_LOG_LEVEL", "debug", true);
|
|
||||||
setenv("LIBGL_DEBUG", "verbose", true);
|
|
||||||
}
|
|
||||||
|
|
||||||
egl_dbg("qemu_egl_get_display (dpy %p) ...\n", dpy);
|
|
||||||
qemu_egl_display = qemu_egl_get_display(dpy);
|
|
||||||
if (qemu_egl_display == EGL_NO_DISPLAY) {
|
if (qemu_egl_display == EGL_NO_DISPLAY) {
|
||||||
error_report("egl: eglGetDisplay failed");
|
error_report("egl: eglGetDisplay failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
egl_dbg("eglInitialize ...\n");
|
|
||||||
b = eglInitialize(qemu_egl_display, &major, &minor);
|
b = eglInitialize(qemu_egl_display, &major, &minor);
|
||||||
if (b == EGL_FALSE) {
|
if (b == EGL_FALSE) {
|
||||||
error_report("egl: eglInitialize failed");
|
error_report("egl: eglInitialize failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
egl_dbg("eglBindAPI ...\n");
|
b = eglBindAPI(EGL_OPENGL_API);
|
||||||
b = eglBindAPI(gles ? EGL_OPENGL_ES_API : EGL_OPENGL_API);
|
|
||||||
if (b == EGL_FALSE) {
|
if (b == EGL_FALSE) {
|
||||||
error_report("egl: eglBindAPI failed");
|
error_report("egl: eglBindAPI failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
egl_dbg("eglChooseConfig ...\n");
|
b = eglChooseConfig(qemu_egl_display, conf_att_gl,
|
||||||
b = eglChooseConfig(qemu_egl_display,
|
|
||||||
gles ? conf_att_gles : conf_att_gl,
|
|
||||||
&qemu_egl_config, 1, &n);
|
&qemu_egl_config, 1, &n);
|
||||||
if (b == EGL_FALSE || n != 1) {
|
if (b == EGL_FALSE || n != 1) {
|
||||||
error_report("egl: eglChooseConfig failed");
|
error_report("egl: eglChooseConfig failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
egl_gles = gles;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int qemu_egl_init_dpy_x11(EGLNativeDisplayType dpy)
|
||||||
|
{
|
||||||
|
#ifdef EGL_KHR_platform_x11
|
||||||
|
return qemu_egl_init_dpy(dpy, EGL_PLATFORM_X11_KHR);
|
||||||
|
#else
|
||||||
|
return qemu_egl_init_dpy(dpy, 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int qemu_egl_init_dpy_mesa(EGLNativeDisplayType dpy)
|
||||||
|
{
|
||||||
|
#ifdef EGL_MESA_platform_gbm
|
||||||
|
return qemu_egl_init_dpy(dpy, EGL_PLATFORM_GBM_MESA);
|
||||||
|
#else
|
||||||
|
return qemu_egl_init_dpy(dpy, 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
EGLContext qemu_egl_init_ctx(void)
|
EGLContext qemu_egl_init_ctx(void)
|
||||||
{
|
{
|
||||||
static const EGLint ctx_att_gl[] = {
|
static const EGLint ctx_att_gl[] = {
|
||||||
|
EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
|
||||||
EGL_NONE
|
EGL_NONE
|
||||||
};
|
};
|
||||||
static const EGLint ctx_att_gles[] = {
|
|
||||||
EGL_CONTEXT_CLIENT_VERSION, 2,
|
|
||||||
EGL_NONE
|
|
||||||
};
|
|
||||||
|
|
||||||
EGLContext ectx;
|
EGLContext ectx;
|
||||||
EGLBoolean b;
|
EGLBoolean b;
|
||||||
|
|
||||||
egl_dbg("eglCreateContext ...\n");
|
|
||||||
ectx = eglCreateContext(qemu_egl_display, qemu_egl_config, EGL_NO_CONTEXT,
|
ectx = eglCreateContext(qemu_egl_display, qemu_egl_config, EGL_NO_CONTEXT,
|
||||||
egl_gles ? ctx_att_gles : ctx_att_gl);
|
ctx_att_gl);
|
||||||
if (ectx == EGL_NO_CONTEXT) {
|
if (ectx == EGL_NO_CONTEXT) {
|
||||||
error_report("egl: eglCreateContext failed");
|
error_report("egl: eglCreateContext failed");
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -246,7 +246,7 @@ void gtk_egl_init(void)
|
||||||
GdkDisplay *gdk_display = gdk_display_get_default();
|
GdkDisplay *gdk_display = gdk_display_get_default();
|
||||||
Display *x11_display = gdk_x11_display_get_xdisplay(gdk_display);
|
Display *x11_display = gdk_x11_display_get_xdisplay(gdk_display);
|
||||||
|
|
||||||
if (qemu_egl_init_dpy(x11_display, false, false) < 0) {
|
if (qemu_egl_init_dpy_x11(x11_display) < 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
4
ui/gtk.c
4
ui/gtk.c
|
@ -912,9 +912,9 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
qemu_input_queue_abs(vc->gfx.dcl.con, INPUT_AXIS_X, x,
|
qemu_input_queue_abs(vc->gfx.dcl.con, INPUT_AXIS_X, x,
|
||||||
surface_width(vc->gfx.ds));
|
0, surface_width(vc->gfx.ds));
|
||||||
qemu_input_queue_abs(vc->gfx.dcl.con, INPUT_AXIS_Y, y,
|
qemu_input_queue_abs(vc->gfx.dcl.con, INPUT_AXIS_Y, y,
|
||||||
surface_height(vc->gfx.ds));
|
0, surface_height(vc->gfx.ds));
|
||||||
qemu_input_event_sync();
|
qemu_input_event_sync();
|
||||||
} else if (s->last_set && s->ptr_owner == vc) {
|
} else if (s->last_set && s->ptr_owner == vc) {
|
||||||
qemu_input_queue_rel(vc->gfx.dcl.con, INPUT_AXIS_X, x - s->last_x);
|
qemu_input_queue_rel(vc->gfx.dcl.con, INPUT_AXIS_X, x - s->last_x);
|
||||||
|
|
|
@ -169,6 +169,10 @@ struct InputLinux {
|
||||||
bool has_abs_x;
|
bool has_abs_x;
|
||||||
int num_keys;
|
int num_keys;
|
||||||
int num_btns;
|
int num_btns;
|
||||||
|
int abs_x_min;
|
||||||
|
int abs_x_max;
|
||||||
|
int abs_y_min;
|
||||||
|
int abs_y_max;
|
||||||
struct input_event event;
|
struct input_event event;
|
||||||
int read_offset;
|
int read_offset;
|
||||||
|
|
||||||
|
@ -314,6 +318,18 @@ static void input_linux_handle_mouse(InputLinux *il, struct input_event *event)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case EV_ABS:
|
||||||
|
switch (event->code) {
|
||||||
|
case ABS_X:
|
||||||
|
qemu_input_queue_abs(NULL, INPUT_AXIS_X, event->value,
|
||||||
|
il->abs_x_min, il->abs_x_max);
|
||||||
|
break;
|
||||||
|
case ABS_Y:
|
||||||
|
qemu_input_queue_abs(NULL, INPUT_AXIS_Y, event->value,
|
||||||
|
il->abs_y_min, il->abs_y_max);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case EV_SYN:
|
case EV_SYN:
|
||||||
qemu_input_event_sync();
|
qemu_input_event_sync();
|
||||||
if (il->wheel != 0) {
|
if (il->wheel != 0) {
|
||||||
|
@ -351,7 +367,7 @@ static void input_linux_event(void *opaque)
|
||||||
if (il->num_keys) {
|
if (il->num_keys) {
|
||||||
input_linux_handle_keyboard(il, &il->event);
|
input_linux_handle_keyboard(il, &il->event);
|
||||||
}
|
}
|
||||||
if (il->has_rel_x && il->num_btns) {
|
if ((il->has_rel_x || il->has_abs_x) && il->num_btns) {
|
||||||
input_linux_handle_mouse(il, &il->event);
|
input_linux_handle_mouse(il, &il->event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -364,6 +380,7 @@ static void input_linux_complete(UserCreatable *uc, Error **errp)
|
||||||
uint8_t keymap[KEY_CNT / 8], keystate[KEY_CNT / 8];
|
uint8_t keymap[KEY_CNT / 8], keystate[KEY_CNT / 8];
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
int rc, ver;
|
int rc, ver;
|
||||||
|
struct input_absinfo absinfo;
|
||||||
|
|
||||||
if (!il->evdev) {
|
if (!il->evdev) {
|
||||||
error_setg(errp, "no input device specified");
|
error_setg(errp, "no input device specified");
|
||||||
|
@ -402,6 +419,12 @@ static void input_linux_complete(UserCreatable *uc, Error **errp)
|
||||||
rc = ioctl(il->fd, EVIOCGBIT(EV_ABS, sizeof(absmap)), &absmap);
|
rc = ioctl(il->fd, EVIOCGBIT(EV_ABS, sizeof(absmap)), &absmap);
|
||||||
if (absmap & (1 << ABS_X)) {
|
if (absmap & (1 << ABS_X)) {
|
||||||
il->has_abs_x = true;
|
il->has_abs_x = true;
|
||||||
|
rc = ioctl(il->fd, EVIOCGABS(ABS_X), &absinfo);
|
||||||
|
il->abs_x_min = absinfo.minimum;
|
||||||
|
il->abs_x_max = absinfo.maximum;
|
||||||
|
rc = ioctl(il->fd, EVIOCGABS(ABS_Y), &absinfo);
|
||||||
|
il->abs_y_min = absinfo.minimum;
|
||||||
|
il->abs_y_max = absinfo.maximum;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
31
ui/input.c
31
ui/input.c
|
@ -166,6 +166,11 @@ void qmp_input_send_event(bool has_device, const char *device,
|
||||||
qemu_input_event_sync();
|
qemu_input_event_sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int qemu_input_transform_invert_abs_value(int value)
|
||||||
|
{
|
||||||
|
return (int64_t)INPUT_EVENT_ABS_MAX - value + INPUT_EVENT_ABS_MIN;
|
||||||
|
}
|
||||||
|
|
||||||
static void qemu_input_transform_abs_rotate(InputEvent *evt)
|
static void qemu_input_transform_abs_rotate(InputEvent *evt)
|
||||||
{
|
{
|
||||||
InputMoveEvent *move = evt->u.abs.data;
|
InputMoveEvent *move = evt->u.abs.data;
|
||||||
|
@ -175,16 +180,16 @@ static void qemu_input_transform_abs_rotate(InputEvent *evt)
|
||||||
move->axis = INPUT_AXIS_Y;
|
move->axis = INPUT_AXIS_Y;
|
||||||
} else if (move->axis == INPUT_AXIS_Y) {
|
} else if (move->axis == INPUT_AXIS_Y) {
|
||||||
move->axis = INPUT_AXIS_X;
|
move->axis = INPUT_AXIS_X;
|
||||||
move->value = INPUT_EVENT_ABS_SIZE - 1 - move->value;
|
move->value = qemu_input_transform_invert_abs_value(move->value);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 180:
|
case 180:
|
||||||
move->value = INPUT_EVENT_ABS_SIZE - 1 - move->value;
|
move->value = qemu_input_transform_invert_abs_value(move->value);
|
||||||
break;
|
break;
|
||||||
case 270:
|
case 270:
|
||||||
if (move->axis == INPUT_AXIS_X) {
|
if (move->axis == INPUT_AXIS_X) {
|
||||||
move->axis = INPUT_AXIS_Y;
|
move->axis = INPUT_AXIS_Y;
|
||||||
move->value = INPUT_EVENT_ABS_SIZE - 1 - move->value;
|
move->value = qemu_input_transform_invert_abs_value(move->value);
|
||||||
} else if (move->axis == INPUT_AXIS_Y) {
|
} else if (move->axis == INPUT_AXIS_Y) {
|
||||||
move->axis = INPUT_AXIS_X;
|
move->axis = INPUT_AXIS_X;
|
||||||
}
|
}
|
||||||
|
@ -467,12 +472,17 @@ bool qemu_input_is_absolute(void)
|
||||||
return (s != NULL) && (s->handler->mask & INPUT_EVENT_MASK_ABS);
|
return (s != NULL) && (s->handler->mask & INPUT_EVENT_MASK_ABS);
|
||||||
}
|
}
|
||||||
|
|
||||||
int qemu_input_scale_axis(int value, int size_in, int size_out)
|
int qemu_input_scale_axis(int value,
|
||||||
|
int min_in, int max_in,
|
||||||
|
int min_out, int max_out)
|
||||||
{
|
{
|
||||||
if (size_in < 2) {
|
int64_t range_in = (int64_t)max_in - min_in;
|
||||||
return size_out / 2;
|
int64_t range_out = (int64_t)max_out - min_out;
|
||||||
|
|
||||||
|
if (range_in < 1) {
|
||||||
|
return min_out + range_out / 2;
|
||||||
}
|
}
|
||||||
return (int64_t)value * (size_out - 1) / (size_in - 1);
|
return ((int64_t)value - min_in) * range_out / range_in + min_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
InputEvent *qemu_input_event_new_move(InputEventKind kind,
|
InputEvent *qemu_input_event_new_move(InputEventKind kind,
|
||||||
|
@ -496,10 +506,13 @@ void qemu_input_queue_rel(QemuConsole *src, InputAxis axis, int value)
|
||||||
qapi_free_InputEvent(evt);
|
qapi_free_InputEvent(evt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void qemu_input_queue_abs(QemuConsole *src, InputAxis axis, int value, int size)
|
void qemu_input_queue_abs(QemuConsole *src, InputAxis axis, int value,
|
||||||
|
int min_in, int max_in)
|
||||||
{
|
{
|
||||||
InputEvent *evt;
|
InputEvent *evt;
|
||||||
int scaled = qemu_input_scale_axis(value, size, INPUT_EVENT_ABS_SIZE);
|
int scaled = qemu_input_scale_axis(value, min_in, max_in,
|
||||||
|
INPUT_EVENT_ABS_MIN,
|
||||||
|
INPUT_EVENT_ABS_MAX);
|
||||||
evt = qemu_input_event_new_move(INPUT_EVENT_KIND_ABS, axis, scaled);
|
evt = qemu_input_event_new_move(INPUT_EVENT_KIND_ABS, axis, scaled);
|
||||||
qemu_input_event_send(src, evt);
|
qemu_input_event_send(src, evt);
|
||||||
qapi_free_InputEvent(evt);
|
qapi_free_InputEvent(evt);
|
||||||
|
|
4
ui/sdl.c
4
ui/sdl.c
|
@ -490,9 +490,9 @@ static void sdl_send_mouse_event(int dx, int dy, int x, int y, int state)
|
||||||
|
|
||||||
if (qemu_input_is_absolute()) {
|
if (qemu_input_is_absolute()) {
|
||||||
qemu_input_queue_abs(dcl->con, INPUT_AXIS_X, x,
|
qemu_input_queue_abs(dcl->con, INPUT_AXIS_X, x,
|
||||||
real_screen->w);
|
0, real_screen->w);
|
||||||
qemu_input_queue_abs(dcl->con, INPUT_AXIS_Y, y,
|
qemu_input_queue_abs(dcl->con, INPUT_AXIS_Y, y,
|
||||||
real_screen->h);
|
0, real_screen->h);
|
||||||
} else {
|
} else {
|
||||||
if (guest_cursor) {
|
if (guest_cursor) {
|
||||||
x -= guest_x;
|
x -= guest_x;
|
||||||
|
|
|
@ -298,8 +298,8 @@ static void sdl_send_mouse_event(struct sdl2_console *scon, int dx, int dy,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
qemu_input_queue_abs(scon->dcl.con, INPUT_AXIS_X, off_x + x, max_w);
|
qemu_input_queue_abs(scon->dcl.con, INPUT_AXIS_X, off_x + x, 0, max_w);
|
||||||
qemu_input_queue_abs(scon->dcl.con, INPUT_AXIS_Y, off_y + y, max_h);
|
qemu_input_queue_abs(scon->dcl.con, INPUT_AXIS_Y, off_y + y, 0, max_h);
|
||||||
} else {
|
} else {
|
||||||
if (guest_cursor) {
|
if (guest_cursor) {
|
||||||
x -= guest_x;
|
x -= guest_x;
|
||||||
|
|
|
@ -172,8 +172,8 @@ static void tablet_position(SpiceTabletInstance* sin, int x, int y,
|
||||||
QemuSpicePointer *pointer = container_of(sin, QemuSpicePointer, tablet);
|
QemuSpicePointer *pointer = container_of(sin, QemuSpicePointer, tablet);
|
||||||
|
|
||||||
spice_update_buttons(pointer, 0, buttons_state);
|
spice_update_buttons(pointer, 0, buttons_state);
|
||||||
qemu_input_queue_abs(NULL, INPUT_AXIS_X, x, pointer->width);
|
qemu_input_queue_abs(NULL, INPUT_AXIS_X, x, 0, pointer->width);
|
||||||
qemu_input_queue_abs(NULL, INPUT_AXIS_Y, y, pointer->height);
|
qemu_input_queue_abs(NULL, INPUT_AXIS_Y, y, 0, pointer->height);
|
||||||
qemu_input_event_sync();
|
qemu_input_event_sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -163,7 +163,6 @@ static void zrle_choose_palette_rle(VncState *vs, int w, int h,
|
||||||
if (packed_bytes < estimated_bytes) {
|
if (packed_bytes < estimated_bytes) {
|
||||||
*use_rle = false;
|
*use_rle = false;
|
||||||
*use_palette = true;
|
*use_palette = true;
|
||||||
estimated_bytes = packed_bytes;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
10
ui/vnc.c
10
ui/vnc.c
|
@ -1556,8 +1556,8 @@ static void pointer_event(VncState *vs, int button_mask, int x, int y)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vs->absolute) {
|
if (vs->absolute) {
|
||||||
qemu_input_queue_abs(con, INPUT_AXIS_X, x, width);
|
qemu_input_queue_abs(con, INPUT_AXIS_X, x, 0, width);
|
||||||
qemu_input_queue_abs(con, INPUT_AXIS_Y, y, height);
|
qemu_input_queue_abs(con, INPUT_AXIS_Y, y, 0, height);
|
||||||
} else if (vnc_has_feature(vs, VNC_FEATURE_POINTER_TYPE_CHANGE)) {
|
} else if (vnc_has_feature(vs, VNC_FEATURE_POINTER_TYPE_CHANGE)) {
|
||||||
qemu_input_queue_rel(con, INPUT_AXIS_X, x - 0x7FFF);
|
qemu_input_queue_rel(con, INPUT_AXIS_X, x - 0x7FFF);
|
||||||
qemu_input_queue_rel(con, INPUT_AXIS_Y, y - 0x7FFF);
|
qemu_input_queue_rel(con, INPUT_AXIS_Y, y - 0x7FFF);
|
||||||
|
@ -2061,15 +2061,15 @@ static void set_pixel_format(VncState *vs, int bits_per_pixel,
|
||||||
}
|
}
|
||||||
|
|
||||||
vs->client_pf.rmax = red_max ? red_max : 0xFF;
|
vs->client_pf.rmax = red_max ? red_max : 0xFF;
|
||||||
vs->client_pf.rbits = hweight_long(red_max);
|
vs->client_pf.rbits = ctpopl(red_max);
|
||||||
vs->client_pf.rshift = red_shift;
|
vs->client_pf.rshift = red_shift;
|
||||||
vs->client_pf.rmask = red_max << red_shift;
|
vs->client_pf.rmask = red_max << red_shift;
|
||||||
vs->client_pf.gmax = green_max ? green_max : 0xFF;
|
vs->client_pf.gmax = green_max ? green_max : 0xFF;
|
||||||
vs->client_pf.gbits = hweight_long(green_max);
|
vs->client_pf.gbits = ctpopl(green_max);
|
||||||
vs->client_pf.gshift = green_shift;
|
vs->client_pf.gshift = green_shift;
|
||||||
vs->client_pf.gmask = green_max << green_shift;
|
vs->client_pf.gmask = green_max << green_shift;
|
||||||
vs->client_pf.bmax = blue_max ? blue_max : 0xFF;
|
vs->client_pf.bmax = blue_max ? blue_max : 0xFF;
|
||||||
vs->client_pf.bbits = hweight_long(blue_max);
|
vs->client_pf.bbits = ctpopl(blue_max);
|
||||||
vs->client_pf.bshift = blue_shift;
|
vs->client_pf.bshift = blue_shift;
|
||||||
vs->client_pf.bmask = blue_max << blue_shift;
|
vs->client_pf.bmask = blue_max << blue_shift;
|
||||||
vs->client_pf.bits_per_pixel = bits_per_pixel;
|
vs->client_pf.bits_per_pixel = bits_per_pixel;
|
||||||
|
|
16
vl.c
16
vl.c
|
@ -2050,6 +2050,7 @@ typedef enum DisplayType {
|
||||||
DT_SDL,
|
DT_SDL,
|
||||||
DT_COCOA,
|
DT_COCOA,
|
||||||
DT_GTK,
|
DT_GTK,
|
||||||
|
DT_EGL,
|
||||||
DT_NONE,
|
DT_NONE,
|
||||||
} DisplayType;
|
} DisplayType;
|
||||||
|
|
||||||
|
@ -2127,6 +2128,15 @@ static DisplayType select_display(const char *p)
|
||||||
error_report("VNC requires a display argument vnc=<display>");
|
error_report("VNC requires a display argument vnc=<display>");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
} else if (strstart(p, "egl-headless", &opts)) {
|
||||||
|
#ifdef CONFIG_OPENGL
|
||||||
|
request_opengl = 1;
|
||||||
|
display_opengl = 1;
|
||||||
|
display = DT_EGL;
|
||||||
|
#else
|
||||||
|
fprintf(stderr, "egl support is disabled\n");
|
||||||
|
exit(1);
|
||||||
|
#endif
|
||||||
} else if (strstart(p, "curses", &opts)) {
|
} else if (strstart(p, "curses", &opts)) {
|
||||||
#ifdef CONFIG_CURSES
|
#ifdef CONFIG_CURSES
|
||||||
display = DT_CURSES;
|
display = DT_CURSES;
|
||||||
|
@ -4658,6 +4668,12 @@ int main(int argc, char **argv, char **envp)
|
||||||
qemu_spice_display_init();
|
qemu_spice_display_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_OPENGL
|
||||||
|
if (display_type == DT_EGL) {
|
||||||
|
egl_headless_init();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (foreach_device_config(DEV_GDB, gdbserver_start) < 0) {
|
if (foreach_device_config(DEV_GDB, gdbserver_start) < 0) {
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue