From 753fffe1ea17517548f58ea52560789157c8ef45 Mon Sep 17 00:00:00 2001 From: osy <50960678+osy@users.noreply.github.com> Date: Wed, 25 Aug 2021 15:46:30 -0700 Subject: [PATCH] spice-display: support GL_TEXTURE_RECTANGLE_ANGLE On macOS with CGL rendering backend, IOSurface only supports rectangle texture targets. On iOS, EAGL, and Metal rendering backends IOSurface only supports 2D texture targets. --- include/ui/egl-helpers.h | 4 ++++ ui/egl-helpers.c | 30 +++++++++++++++++++++--------- ui/spice-display.c | 30 ++++++++++++++++++++++++++---- 3 files changed, 51 insertions(+), 13 deletions(-) diff --git a/include/ui/egl-helpers.h b/include/ui/egl-helpers.h index 117596c1cb67..c6e95b4d5f4a 100644 --- a/include/ui/egl-helpers.h +++ b/include/ui/egl-helpers.h @@ -20,14 +20,18 @@ typedef struct egl_fb { int width; int height; GLuint texture; + GLenum texture_target; GLuint framebuffer; bool delete_texture; } egl_fb; 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_target(egl_fb *fb, int width, int height, + GLuint texture, GLenum target, bool delete); void egl_fb_setup_for_tex(egl_fb *fb, int width, int height, GLuint texture, bool delete); +void egl_fb_setup_new_tex_target(egl_fb *fb, int width, int height, GLenum target); void egl_fb_setup_new_tex(egl_fb *fb, int width, int height); void egl_fb_blit(egl_fb *dst, egl_fb *src, bool flip); void egl_fb_read(DisplaySurface *dst, egl_fb *src); diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c index 0b68f70d6a45..c38667661b5e 100644 --- a/ui/egl-helpers.c +++ b/ui/egl-helpers.c @@ -58,14 +58,15 @@ void egl_fb_setup_default(egl_fb *fb, int width, int height) fb->framebuffer = 0; /* default framebuffer */ } -void egl_fb_setup_for_tex(egl_fb *fb, int width, int height, - GLuint texture, bool delete) +void egl_fb_setup_for_tex_target(egl_fb *fb, int width, int height, + GLuint texture, GLenum target, bool delete) { egl_fb_delete_texture(fb); fb->width = width; fb->height = height; fb->texture = texture; + fb->texture_target = target; fb->delete_texture = delete; if (!fb->framebuffer) { glGenFramebuffers(1, &fb->framebuffer); @@ -73,19 +74,30 @@ void egl_fb_setup_for_tex(egl_fb *fb, int width, int height, glBindFramebuffer(GL_FRAMEBUFFER_EXT, fb->framebuffer); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, - GL_TEXTURE_2D, fb->texture, 0); + fb->texture_target, fb->texture, 0); } -void egl_fb_setup_new_tex(egl_fb *fb, int width, int height) +void egl_fb_setup_for_tex(egl_fb *fb, int width, int height, + GLuint texture, bool delete) +{ + egl_fb_setup_for_tex_target(fb, width, height, texture, GL_TEXTURE_2D, delete); +} + +void egl_fb_setup_new_tex_target(egl_fb *fb, int width, int height, GLenum target) { GLuint texture; glGenTextures(1, &texture); - glBindTexture(GL_TEXTURE_2D, texture); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, + glBindTexture(target, texture); + glTexImage2D(target, 0, GL_RGBA, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, 0); - egl_fb_setup_for_tex(fb, width, height, texture, true); + egl_fb_setup_for_tex_target(fb, width, height, texture, target, true); +} + +void egl_fb_setup_new_tex(egl_fb *fb, int width, int height) +{ + egl_fb_setup_new_tex_target(fb, width, height, GL_TEXTURE_2D); } void egl_fb_blit(egl_fb *dst, egl_fb *src, bool flip) @@ -115,7 +127,7 @@ void egl_texture_blit(QemuGLShader *gls, egl_fb *dst, egl_fb *src, bool flip) glBindFramebuffer(GL_FRAMEBUFFER_EXT, dst->framebuffer); glViewport(0, 0, dst->width, dst->height); glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, src->texture); + glBindTexture(src->texture_target, src->texture); qemu_gl_run_texture_blit(gls, flip); } @@ -131,7 +143,7 @@ void egl_texture_blend(QemuGLShader *gls, egl_fb *dst, egl_fb *src, bool flip, glViewport(x, dst->height - h - y, w, h); } glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, src->texture); + glBindTexture(src->texture_target, src->texture); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); qemu_gl_run_texture_blit(gls, flip); diff --git a/ui/spice-display.c b/ui/spice-display.c index 8f1f3734b01b..0bb210a2c265 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -27,6 +27,10 @@ #ifdef CONFIG_IOSURFACE #include #endif +#ifdef CONFIG_ANGLE +#include +#include +#endif #include "ui/spice-display.h" @@ -825,11 +829,29 @@ static int spice_iosurface_create(SimpleSpiceDisplay *ssd, int width, int height } #if defined(CONFIG_ANGLE) + EGLint target = 0; + GLenum tex_target = 0; + if (eglGetConfigAttrib(qemu_egl_display, + qemu_egl_config, + EGL_BIND_TO_TEXTURE_TARGET_ANGLE, + &target) != EGL_TRUE) { + error_report("spice_iosurface_create: eglGetConfigAttrib failed"); + return 0; + } + if (target == EGL_TEXTURE_2D) { + tex_target = GL_TEXTURE_2D; + } else if (target == EGL_TEXTURE_RECTANGLE_ANGLE) { + tex_target = GL_TEXTURE_RECTANGLE_ANGLE; + } else { + error_report("spice_iosurface_create: unsupported texture target"); + return 0; + } + const EGLint attribs[] = { EGL_WIDTH, width, EGL_HEIGHT, height, EGL_IOSURFACE_PLANE_ANGLE, 0, - EGL_TEXTURE_TARGET, EGL_TEXTURE_2D, + EGL_TEXTURE_TARGET, target, EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT, EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA, EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE, @@ -845,7 +867,7 @@ static int spice_iosurface_create(SimpleSpiceDisplay *ssd, int width, int height goto gl_error; } - egl_fb_setup_new_tex(&ssd->iosurface_fb, width, height); + egl_fb_setup_new_tex_target(&ssd->iosurface_fb, width, height, tex_target); return 1; gl_error: @@ -909,14 +931,14 @@ static int spice_iosurface_create_fd(SimpleSpiceDisplay *ssd, int *fourcc) static void spice_iosurface_blit(SimpleSpiceDisplay *ssd, GLuint src_texture, bool flip) { - egl_fb tmp_fb = { .texture = src_texture }; + egl_fb tmp_fb = { .texture = src_texture, .texture_target = GL_TEXTURE_2D }; if (!ssd->iosurface) { return; } #if defined(CONFIG_ANGLE) eglMakeCurrent(qemu_egl_display, ssd->esurface, ssd->esurface, spice_gl_ctx); - glBindTexture(GL_TEXTURE_2D, ssd->iosurface_fb.texture); + glBindTexture(ssd->iosurface_fb.texture_target, ssd->iosurface_fb.texture); eglBindTexImage(qemu_egl_display, ssd->esurface, EGL_BACK_BUFFER); egl_texture_blit(ssd->gls, &ssd->iosurface_fb, &tmp_fb, flip); #endif