Skip to content

Commit f851cd6

Browse files
vivekkreddyelmarco
authored andcommitted
ui/spice: Blit the scanout texture if its memory layout is not linear
In cases where the scanout buffer is provided as a texture (e.g. Virgl) we need to check to see if it has a linear memory layout or not. If it doesn't have a linear layout, then blitting it onto the texture associated with the display surface (which already has a linear layout) seems to ensure that there is no corruption seen regardless of which encoder or decoder is used. 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]> Cc: Michael Scherle <[email protected]> Reviewed-by: Marc-André Lureau <[email protected]> Signed-off-by: Vivek Kasireddy <[email protected]> Message-Id: <[email protected]>
1 parent 2103690 commit f851cd6

File tree

2 files changed

+78
-6
lines changed

2 files changed

+78
-6
lines changed

include/ui/spice-display.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,9 @@ struct SimpleSpiceDisplay {
132132
egl_fb guest_fb;
133133
egl_fb blit_fb;
134134
egl_fb cursor_fb;
135+
bool backing_y_0_top;
136+
bool blit_scanout_texture;
137+
bool new_scanout_texture;
135138
bool have_hot;
136139
#endif
137140
};

ui/spice-display.c

Lines changed: 75 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1086,7 +1086,7 @@ static void qemu_spice_gl_scanout_texture(DisplayChangeListener *dcl,
10861086
{
10871087
SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl);
10881088
EGLint offset[DMABUF_MAX_PLANES], stride[DMABUF_MAX_PLANES], fourcc = 0;
1089-
int fd[DMABUF_MAX_PLANES], num_planes;
1089+
int fd[DMABUF_MAX_PLANES], num_planes, i;
10901090
uint64_t modifier;
10911091

10921092
assert(tex_id);
@@ -1098,11 +1098,26 @@ static void qemu_spice_gl_scanout_texture(DisplayChangeListener *dcl,
10981098

10991099
trace_qemu_spice_gl_scanout_texture(ssd->qxl.id, w, h, fourcc);
11001100

1101-
/* note: spice server will close the fd */
1102-
spice_server_gl_scanout(&ssd->qxl, fd, backing_width, backing_height,
1103-
(uint32_t *)offset, (uint32_t *)stride, num_planes,
1104-
fourcc, modifier, y_0_top);
1105-
qemu_spice_gl_monitor_config(ssd, x, y, w, h);
1101+
if (spice_remote_client && modifier != DRM_FORMAT_MOD_LINEAR) {
1102+
egl_fb_destroy(&ssd->guest_fb);
1103+
egl_fb_setup_for_tex(&ssd->guest_fb,
1104+
backing_width, backing_height,
1105+
tex_id, false);
1106+
ssd->backing_y_0_top = y_0_top;
1107+
ssd->blit_scanout_texture = true;
1108+
ssd->new_scanout_texture = true;
1109+
1110+
for (i = 0; i < num_planes; i++) {
1111+
close(fd[i]);
1112+
}
1113+
} else {
1114+
/* note: spice server will close the fd */
1115+
spice_server_gl_scanout(&ssd->qxl, fd, backing_width, backing_height,
1116+
(uint32_t *)offset, (uint32_t *)stride,
1117+
num_planes, fourcc, modifier, y_0_top);
1118+
qemu_spice_gl_monitor_config(ssd, x, y, w, h);
1119+
}
1120+
11061121
ssd->have_surface = false;
11071122
ssd->have_scanout = true;
11081123
}
@@ -1168,13 +1183,58 @@ static void qemu_spice_gl_release_dmabuf(DisplayChangeListener *dcl,
11681183
egl_dmabuf_release_texture(dmabuf);
11691184
}
11701185

1186+
static bool spice_gl_blit_scanout_texture(SimpleSpiceDisplay *ssd,
1187+
egl_fb *scanout_tex_fb)
1188+
{
1189+
uint32_t offsets[DMABUF_MAX_PLANES], strides[DMABUF_MAX_PLANES];
1190+
int fds[DMABUF_MAX_PLANES], num_planes, fourcc;
1191+
uint64_t modifier;
1192+
bool ret;
1193+
1194+
egl_fb_destroy(scanout_tex_fb);
1195+
egl_fb_setup_for_tex(scanout_tex_fb,
1196+
surface_width(ssd->ds), surface_height(ssd->ds),
1197+
ssd->ds->texture, false);
1198+
egl_fb_blit(scanout_tex_fb, &ssd->guest_fb, false);
1199+
glFlush();
1200+
1201+
if (!ssd->new_scanout_texture) {
1202+
return true;
1203+
}
1204+
1205+
ret = egl_dmabuf_export_texture(ssd->ds->texture,
1206+
fds,
1207+
(EGLint *)offsets,
1208+
(EGLint *)strides,
1209+
&fourcc,
1210+
&num_planes,
1211+
&modifier);
1212+
if (!ret) {
1213+
error_report("spice: failed to get fd for texture");
1214+
return false;
1215+
}
1216+
1217+
spice_server_gl_scanout(&ssd->qxl, fds,
1218+
surface_width(ssd->ds),
1219+
surface_height(ssd->ds),
1220+
(uint32_t *)offsets, (uint32_t *)strides,
1221+
num_planes, fourcc, modifier,
1222+
ssd->backing_y_0_top);
1223+
qemu_spice_gl_monitor_config(ssd, 0, 0,
1224+
surface_width(ssd->ds),
1225+
surface_height(ssd->ds));
1226+
ssd->new_scanout_texture = false;
1227+
return true;
1228+
}
1229+
11711230
static void qemu_spice_gl_update(DisplayChangeListener *dcl,
11721231
uint32_t x, uint32_t y, uint32_t w, uint32_t h)
11731232
{
11741233
SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl);
11751234
EGLint fourcc = 0;
11761235
bool render_cursor = false;
11771236
bool y_0_top = false; /* FIXME */
1237+
bool ret;
11781238
uint32_t width, height, texture;
11791239

11801240
if (!ssd->have_scanout) {
@@ -1269,6 +1329,15 @@ static void qemu_spice_gl_update(DisplayChangeListener *dcl,
12691329
glFlush();
12701330
}
12711331

1332+
if (spice_remote_client && ssd->blit_scanout_texture) {
1333+
egl_fb scanout_tex_fb;
1334+
1335+
ret = spice_gl_blit_scanout_texture(ssd, &scanout_tex_fb);
1336+
if (!ret) {
1337+
return;
1338+
}
1339+
}
1340+
12721341
trace_qemu_spice_gl_update(ssd->qxl.id, w, h, x, y);
12731342
qemu_spice_gl_block(ssd, true);
12741343
glFlush();

0 commit comments

Comments
 (0)