Revision 2c62f08d ui/console.c
b/ui/console.c | ||
---|---|---|
121 | 121 |
/* Graphic console state. */ |
122 | 122 |
graphic_hw_update_ptr hw_update; |
123 | 123 |
graphic_hw_invalidate_ptr hw_invalidate; |
124 |
graphic_hw_screen_dump_ptr hw_screen_dump; |
|
125 | 124 |
graphic_hw_text_update_ptr hw_text_update; |
126 | 125 |
void *hw; |
127 | 126 |
int g_width, g_height; |
... | ... | |
188 | 187 |
} |
189 | 188 |
} |
190 | 189 |
|
191 |
void qmp_screendump(const char *filename, Error **errp) |
|
190 |
static void ppm_save(const char *filename, struct DisplaySurface *ds, |
|
191 |
Error **errp) |
|
192 | 192 |
{ |
193 |
QemuConsole *previous_active_console; |
|
194 |
bool cswitch; |
|
195 |
|
|
196 |
previous_active_console = active_console; |
|
197 |
cswitch = previous_active_console && previous_active_console->index != 0; |
|
193 |
int width = pixman_image_get_width(ds->image); |
|
194 |
int height = pixman_image_get_height(ds->image); |
|
195 |
FILE *f; |
|
196 |
int y; |
|
197 |
int ret; |
|
198 |
pixman_image_t *linebuf; |
|
198 | 199 |
|
199 |
/* There is currently no way of specifying which screen we want to dump, |
|
200 |
so always dump the first one. */ |
|
201 |
if (cswitch) { |
|
202 |
console_select(0); |
|
200 |
trace_ppm_save(filename, ds); |
|
201 |
f = fopen(filename, "wb"); |
|
202 |
if (!f) { |
|
203 |
error_setg(errp, "failed to open file '%s': %s", filename, |
|
204 |
strerror(errno)); |
|
205 |
return; |
|
203 | 206 |
} |
204 |
if (consoles[0] && consoles[0]->hw_screen_dump) { |
|
205 |
consoles[0]->hw_screen_dump(consoles[0]->hw, filename, cswitch, errp); |
|
206 |
} else { |
|
207 |
error_setg(errp, "device doesn't support screendump"); |
|
207 |
ret = fprintf(f, "P6\n%d %d\n%d\n", width, height, 255); |
|
208 |
if (ret < 0) { |
|
209 |
linebuf = NULL; |
|
210 |
goto write_err; |
|
211 |
} |
|
212 |
linebuf = qemu_pixman_linebuf_create(PIXMAN_BE_r8g8b8, width); |
|
213 |
for (y = 0; y < height; y++) { |
|
214 |
qemu_pixman_linebuf_fill(linebuf, ds->image, width, 0, y); |
|
215 |
clearerr(f); |
|
216 |
ret = fwrite(pixman_image_get_data(linebuf), 1, |
|
217 |
pixman_image_get_stride(linebuf), f); |
|
218 |
(void)ret; |
|
219 |
if (ferror(f)) { |
|
220 |
goto write_err; |
|
221 |
} |
|
208 | 222 |
} |
209 | 223 |
|
210 |
if (cswitch) { |
|
211 |
console_select(previous_active_console->index); |
|
224 |
out: |
|
225 |
qemu_pixman_image_unref(linebuf); |
|
226 |
fclose(f); |
|
227 |
return; |
|
228 |
|
|
229 |
write_err: |
|
230 |
error_setg(errp, "failed to write to file '%s': %s", filename, |
|
231 |
strerror(errno)); |
|
232 |
unlink(filename); |
|
233 |
goto out; |
|
234 |
} |
|
235 |
|
|
236 |
void qmp_screendump(const char *filename, Error **errp) |
|
237 |
{ |
|
238 |
QemuConsole *con = consoles[0]; |
|
239 |
DisplaySurface *surface; |
|
240 |
|
|
241 |
if (con == NULL) { |
|
242 |
error_setg(errp, "There is no QemuConsole I can screendump from."); |
|
243 |
return; |
|
212 | 244 |
} |
245 |
|
|
246 |
graphic_hw_update(con); |
|
247 |
surface = qemu_console_surface(con); |
|
248 |
ppm_save(filename, surface, errp); |
|
213 | 249 |
} |
214 | 250 |
|
215 | 251 |
void graphic_hw_text_update(QemuConsole *con, console_ch_t *chardata) |
... | ... | |
1411 | 1447 |
|
1412 | 1448 |
QemuConsole *graphic_console_init(graphic_hw_update_ptr update, |
1413 | 1449 |
graphic_hw_invalidate_ptr invalidate, |
1414 |
graphic_hw_screen_dump_ptr screen_dump, |
|
1415 | 1450 |
graphic_hw_text_update_ptr text_update, |
1416 | 1451 |
void *opaque) |
1417 | 1452 |
{ |
... | ... | |
1425 | 1460 |
s = new_console(ds, GRAPHIC_CONSOLE); |
1426 | 1461 |
s->hw_update = update; |
1427 | 1462 |
s->hw_invalidate = invalidate; |
1428 |
s->hw_screen_dump = screen_dump; |
|
1429 | 1463 |
s->hw_text_update = text_update; |
1430 | 1464 |
s->hw = opaque; |
1431 | 1465 |
|
Also available in: Unified diff