intel-virtual-output: Refactor the image resizing code

And add lots of debug and robustness.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
Chris Wilson 2013-09-02 17:30:15 +01:00
parent 1b07f16ffe
commit 88d43dc2ae
1 changed files with 87 additions and 72 deletions

View File

@ -94,6 +94,7 @@ struct display {
int cursor;
int flush;
int send;
};
struct output {
@ -109,7 +110,7 @@ struct output {
Pixmap pixmap;
GC gc;
int serial;
long serial;
int use_shm;
int use_shm_pixmap;
@ -203,10 +204,6 @@ can_use_shm(Display *dpy,
XSync(dpy, False);
has_shm = success && _x_error_occurred == 0;
codes = XInitExtension(dpy, SHMNAME);
if (codes == NULL)
has_pixmap = 0;
/* As libXext sets the SEND_EVENT bit in the ShmCompletionEvent,
* the Xserver may crash if it does not take care when processing
* the event type. For instance versions of Xorg prior to 1.11.1
@ -218,12 +215,11 @@ can_use_shm(Display *dpy,
*
* Remove the SendEvent bit (0x80) before doing range checks on event type.
*/
if (has_pixmap &&
xlib_vendor_is_xorg(dpy) &&
codes = XInitExtension(dpy, SHMNAME);
if (xlib_vendor_is_xorg(dpy) &&
VendorRelease(dpy) < XORG_VERSION_ENCODE(1,11,0,1))
has_pixmap = 0;
if (has_pixmap) {
codes = 0;
if (codes) {
XShmCompletionEvent e;
e.type = codes->first_event;
@ -237,23 +233,19 @@ can_use_shm(Display *dpy,
e.offset = 0;
XSendEvent(dpy, e.drawable, False, 0, (XEvent *)&e);
XSync(dpy, False);
has_pixmap = _x_error_occurred == 0;
if (_x_error_occurred == 0) {
*shm_opcode = codes->major_opcode;
*shm_event = codes->first_event;
*shm_pixmap = has_pixmap;
}
}
if (success)
XShmDetach(dpy, &shm);
XShmDetach(dpy, &shm);
shmctl(shm.shmid, IPC_RMID, NULL);
shmdt(shm.shmaddr);
if (has_pixmap) {
*shm_opcode = codes->major_opcode;
*shm_event = codes->first_event;
*shm_pixmap = has_pixmap;
}
return has_shm;
}
@ -555,6 +547,7 @@ static void init_image(struct clone *clone)
image->bits_per_pixel = 16;
break;
}
image->obdata = (char *)&clone->shm;
ret = XInitImage(image);
assert(ret);
@ -1015,6 +1008,9 @@ static int clone_output_init(struct clone *clone, struct output *output,
output->use_shm = display->has_shm;
output->use_shm_pixmap = display->has_shm_pixmap;
DBG(("%s-%s use shm? %d (use shm pixmap? %d)\n",
DisplayString(dpy), name, display->has_shm, display->has_shm_pixmap));
depth = output->use_shm ? display->depth : 16;
if (depth < clone->depth)
clone->depth = depth;
@ -1022,26 +1018,11 @@ static int clone_output_init(struct clone *clone, struct output *output,
return 0;
}
static void send_shm(struct output *o, int serial)
static void ximage_set_size(XImage *image, int width, int height)
{
XShmCompletionEvent e;
if (o->display->shm_event == 0) {
XSync(o->dpy, False);
return;
}
e.type = o->display->shm_event;
e.send_event = 1;
e.serial = serial;
e.drawable = o->pixmap;
e.major_code = o->display->shm_opcode;
e.minor_code = X_ShmPutImage;
e.shmseg = 0;
e.offset = 0;
XSendEvent(o->dpy, o->window, False, 0, (XEvent *)&e);
o->serial = serial;
image->width = width;
image->height = height;
image->bytes_per_line = stride_for_depth(width, image->depth);
}
static void get_src(struct clone *c, const XRectangle *clip)
@ -1058,15 +1039,11 @@ static void get_src(struct clone *c, const XRectangle *clip)
if (c->src.use_shm_pixmap) {
XSync(c->src.dpy, False);
} else if (c->src.use_shm) {
c->image.width = clip->width;
c->image.height = clip->height;
c->image.obdata = (char *)&c->shm;
ximage_set_size(&c->image, clip->width, clip->height);
XShmGetImage(c->src.dpy, c->src.pixmap, &c->image,
clip->x, clip->y, AllPlanes);
} else {
c->image.width = c->width;
c->image.height = c->height;
c->image.obdata = 0;
ximage_set_size(&c->image, c->width, c->height);
XGetSubImage(c->src.dpy, c->src.pixmap,
clip->x, clip->y, clip->width, clip->height,
AllPlanes, ZPixmap,
@ -1079,15 +1056,11 @@ static void get_src(struct clone *c, const XRectangle *clip)
0, 0);
XSync(c->src.dpy, False);
} else if (c->src.use_shm) {
c->image.width = clip->width;
c->image.height = clip->height;
c->image.obdata = (char *)&c->shm;
ximage_set_size(&c->image, clip->width, clip->height);
XShmGetImage(c->src.dpy, c->src.window, &c->image,
clip->x, clip->y, AllPlanes);
} else {
c->image.width = c->width;
c->image.height = c->height;
c->image.obdata = 0;
ximage_set_size(&c->image, c->width, c->height);
XGetSubImage(c->src.dpy, c->src.window,
clip->x, clip->y, clip->width, clip->height,
AllPlanes, ZPixmap,
@ -1100,46 +1073,48 @@ static void put_dst(struct clone *c, const XRectangle *clip)
DBG(("%s-%s put_dst(%d,%d)x(%d,%d)\n", DisplayString(c->dst.dpy), c->dst.name,
clip->x, clip->y, clip->width, clip->height));
if (c->dst.use_render) {
int serial;
if (c->dst.use_shm_pixmap) {
DBG(("%s-%s using SHM pixmap composite\n",
DisplayString(c->dst.dpy), c->dst.name));
} else if (c->dst.use_shm) {
c->image.width = clip->width;
c->image.height = clip->height;
c->image.obdata = (char *)&c->shm;
DBG(("%s-%s using SHM image composite\n",
DisplayString(c->dst.dpy), c->dst.name));
ximage_set_size(&c->image, clip->width, clip->height);
XShmPutImage(c->dst.dpy, c->dst.pixmap, c->dst.gc, &c->image,
0, 0,
0, 0,
clip->width, clip->height,
False);
} else {
c->image.width = c->width;
c->image.height = c->height;
c->image.obdata = 0;
DBG(("%s-%s using composite\n",
DisplayString(c->dst.dpy), c->dst.name));
ximage_set_size(&c->image, c->width, c->height);
XPutImage(c->dst.dpy, c->dst.pixmap, c->dst.gc, &c->image,
0, 0,
0, 0,
clip->width, clip->height);
}
serial = NextRequest(c->dst.dpy);
c->dst.serial = NextRequest(c->dst.dpy);
XRenderComposite(c->dst.dpy, PictOpSrc,
c->dst.pix_picture, 0, c->dst.win_picture,
0, 0,
0, 0,
clip->x, clip->y,
clip->width, clip->height);
if (c->dst.use_shm)
send_shm(&c->dst, serial);
c->dst.display->send |= c->dst.use_shm;
} else if (c->dst.pixmap) {
int serial = NextRequest(c->dst.dpy);
DBG(("%s-%s using SHM pixmap\n",
DisplayString(c->dst.dpy), c->dst.name));
c->dst.serial = NextRequest(c->dst.dpy);
XCopyArea(c->dst.dpy, c->dst.pixmap, c->dst.window, c->dst.gc,
0, 0,
clip->width, clip->height,
clip->x, clip->y);
send_shm(&c->dst, serial);
c->dst.display->send = 1;
} else if (c->dst.use_shm) {
c->image.width = clip->width;
c->image.height = clip->height;
c->image.obdata = (char *)&c->shm;
DBG(("%s-%s using SHM image\n",
DisplayString(c->dst.dpy), c->dst.name));
ximage_set_size(&c->image, clip->width, clip->height);
c->dst.serial = NextRequest(c->dst.dpy);
XShmPutImage(c->dst.dpy, c->dst.window, c->dst.gc, &c->image,
0, 0,
@ -1147,9 +1122,9 @@ static void put_dst(struct clone *c, const XRectangle *clip)
clip->width, clip->height,
True);
} else {
c->image.width = c->width;
c->image.height = c->height;
c->image.obdata = 0;
DBG(("%s-%s using image\n",
DisplayString(c->dst.dpy), c->dst.name));
ximage_set_size(&c->image, c->width, c->height);
XPutImage(c->dst.dpy, c->dst.window, c->dst.gc, &c->image,
0, 0,
clip->x, clip->y,
@ -1164,8 +1139,12 @@ static int clone_paint(struct clone *c)
{
XRectangle clip;
DBG(("%s-%s paint clone\n",
DisplayString(c->dst.dpy), c->dst.name));
DBG(("%s-%s paint clone, damaged (%d, %d), (%d, %d) [(%d, %d), (%d, %d)]\n",
DisplayString(c->dst.dpy), c->dst.name,
c->damaged.x1, c->damaged.y1,
c->damaged.x2, c->damaged.y2,
c->src.x, c->src.y,
c->src.x + c->width, c->src.y + c->height));
if (c->damaged.x1 < c->src.x)
c->damaged.x1 = c->src.x;
@ -1181,6 +1160,9 @@ static int clone_paint(struct clone *c)
if (c->damaged.y2 <= c->damaged.y1)
goto done;
DBG(("%s-%s is damaged, last SHM serial: %ld, now %ld\n",
DisplayString(c->dst.dpy), c->dst.name,
(long)c->dst.serial, (long)LastKnownRequestProcessed(c->dst.dpy)));
if (c->dst.serial > LastKnownRequestProcessed(c->dst.dpy))
return EAGAIN;
@ -2137,9 +2119,42 @@ static int first_display_register_as_singleton(struct context *ctx)
} while (1);
}
static void display_flush_send(struct display *display)
{
XShmCompletionEvent e;
if (!display->send)
return;
DBG(("%s flushing send (serial now %ld) (has shm send? %d)\n",
DisplayString(display->dpy),
(long)NextRequest(display->dpy),
display->shm_event));
if (display->shm_event == 0) {
XSync(display->dpy, False);
display->flush = 0;
return;
}
e.type = display->shm_event;
e.send_event = 1;
e.serial = 0;
e.drawable = display->root;
e.major_code = display->shm_opcode;
e.minor_code = X_ShmPutImage;
e.shmseg = 0;
e.offset = 0;
XSendEvent(display->dpy, display->root, False, 0, (XEvent *)&e);
display->send = 0;
display->flush = 1;
}
static void display_flush(struct display *display)
{
display_flush_cursor(display);
display_flush_send(display);
if (!display->flush)
return;