Skip to content

Commit 2103690

Browse files
vivekkreddyelmarco
authored andcommitted
ui/spice: Create a new texture with linear layout when gl=on is specified
Since most encoders/decoders (invoked by Spice) may not work properly with tiled memory associated with a texture, we need to create another texture that has linear memory layout and use that instead. Note that, there does not seem to be a direct way to indicate to the GL implementation that a texture's backing memory needs to be linear. Instead, we have to do it in a roundabout way where we need to first create a tiled texture and import that as a memory object to create a new texture that has a linear memory layout. Cc: Gerd Hoffmann <[email protected]> Cc: Marc-André Lureau <[email protected]> Cc: Dmitry Osipenko <[email protected]> Cc: Frediano Ziglio <[email protected]> Cc: Dongwon Kim <[email protected]> Reviewed-by: Marc-André Lureau <[email protected]> Co-developed-by: Michael Scherle <[email protected]> Signed-off-by: Vivek Kasireddy <[email protected]> Reviewed-by: Dmitry Osipenko <[email protected]> Message-Id: <[email protected]>
1 parent e6f0fe8 commit 2103690

File tree

3 files changed

+89
-0
lines changed

3 files changed

+89
-0
lines changed

include/ui/surface.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ typedef struct DisplaySurface {
2222
GLenum glformat;
2323
GLenum gltype;
2424
GLuint texture;
25+
GLuint mem_obj;
2526
#endif
2627
qemu_pixman_shareable share_handle;
2728
uint32_t share_handle_offset;

ui/console-gl.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,12 @@ void surface_gl_destroy_texture(QemuGLShader *gls,
184184
}
185185
glDeleteTextures(1, &surface->texture);
186186
surface->texture = 0;
187+
#ifdef GL_EXT_memory_object_fd
188+
if (surface->mem_obj) {
189+
glDeleteMemoryObjectsEXT(1, &surface->mem_obj);
190+
surface->mem_obj = 0;
191+
}
192+
#endif
187193
}
188194

189195
void surface_gl_setup_viewport(QemuGLShader *gls,

ui/spice-display.c

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -893,6 +893,81 @@ static void spice_gl_update(DisplayChangeListener *dcl,
893893
ssd->gl_updates++;
894894
}
895895

896+
static bool spice_gl_replace_fd_texture(SimpleSpiceDisplay *ssd,
897+
int *fds, uint64_t *modifier,
898+
int *num_planes)
899+
{
900+
uint32_t offsets[DMABUF_MAX_PLANES], strides[DMABUF_MAX_PLANES];
901+
GLuint texture;
902+
GLuint mem_obj;
903+
int fourcc;
904+
bool ret;
905+
906+
if (!spice_remote_client) {
907+
return true;
908+
}
909+
910+
if (*modifier == DRM_FORMAT_MOD_LINEAR) {
911+
return true;
912+
}
913+
914+
if (*num_planes > 1) {
915+
error_report("spice: cannot replace texture with multiple planes");
916+
return false;
917+
}
918+
919+
/*
920+
* We really want to ensure that the memory layout of the texture
921+
* is linear; otherwise, the encoder's output may show corruption.
922+
*/
923+
if (!surface_gl_create_texture_from_fd(ssd->ds, fds[0], &texture,
924+
&mem_obj)) {
925+
error_report("spice: cannot create new texture from fd");
926+
return false;
927+
}
928+
929+
/*
930+
* A successful return after glImportMemoryFdEXT() means that
931+
* the ownership of fd has been passed to GL. In other words,
932+
* the fd we got above should not be used anymore.
933+
*/
934+
ret = egl_dmabuf_export_texture(texture,
935+
fds,
936+
(EGLint *)offsets,
937+
(EGLint *)strides,
938+
&fourcc,
939+
num_planes,
940+
modifier);
941+
if (!ret) {
942+
glDeleteTextures(1, &texture);
943+
#ifdef GL_EXT_memory_object_fd
944+
glDeleteMemoryObjectsEXT(1, &mem_obj);
945+
#endif
946+
947+
/*
948+
* Since we couldn't export our newly create texture (or create,
949+
* an fd associated with it) we need to backtrack and try to
950+
* recreate the fd associated with the original texture.
951+
*/
952+
ret = egl_dmabuf_export_texture(ssd->ds->texture,
953+
fds,
954+
(EGLint *)offsets,
955+
(EGLint *)strides,
956+
&fourcc,
957+
num_planes,
958+
modifier);
959+
if (!ret) {
960+
surface_gl_destroy_texture(ssd->gls, ssd->ds);
961+
warn_report("spice: no texture available to display");
962+
}
963+
} else {
964+
surface_gl_destroy_texture(ssd->gls, ssd->ds);
965+
ssd->ds->texture = texture;
966+
ssd->ds->mem_obj = mem_obj;
967+
}
968+
return ret;
969+
}
970+
896971
static void spice_server_gl_scanout(QXLInstance *qxl,
897972
const int *fd,
898973
uint32_t width, uint32_t height,
@@ -917,6 +992,7 @@ static void spice_gl_switch(DisplayChangeListener *dcl,
917992
struct DisplaySurface *new_surface)
918993
{
919994
SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl);
995+
bool ret;
920996

921997
if (ssd->ds) {
922998
surface_gl_destroy_texture(ssd->gls, ssd->ds);
@@ -939,6 +1015,12 @@ static void spice_gl_switch(DisplayChangeListener *dcl,
9391015
return;
9401016
}
9411017

1018+
ret = spice_gl_replace_fd_texture(ssd, fd, &modifier, &num_planes);
1019+
if (!ret) {
1020+
surface_gl_destroy_texture(ssd->gls, ssd->ds);
1021+
return;
1022+
}
1023+
9421024
trace_qemu_spice_gl_surface(ssd->qxl.id,
9431025
surface_width(ssd->ds),
9441026
surface_height(ssd->ds),

0 commit comments

Comments
 (0)