From 28713ecdf1ae07ace4eb5171fca7e626c86b455a Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 11 May 2007 16:11:04 +0000 Subject: sys/ximage/gstximagesrc.c (gst_ximage_src_open_display, gst_ximage_src_ximage_get): Original commit message from CVS: Patch by: Eric Anholt * sys/ximage/gstximagesrc.c (gst_ximage_src_open_display, gst_ximage_src_ximage_get): Use union of all damage between frames to make it faster. Fixes bug #342463. Also fix crasher when cursor is at bottom right of window. --- sys/ximage/gstximagesrc.c | 152 ++++++++++++++++++++++------------------------ 1 file changed, 73 insertions(+), 79 deletions(-) (limited to 'sys/ximage') diff --git a/sys/ximage/gstximagesrc.c b/sys/ximage/gstximagesrc.c index fd814c4a..115a48b0 100644 --- a/sys/ximage/gstximagesrc.c +++ b/sys/ximage/gstximagesrc.c @@ -164,8 +164,7 @@ gst_ximage_src_open_display (GstXImageSrc * s, const gchar * name) if (XDamageQueryExtension (s->xcontext->disp, &s->damage_event_base, &error_base)) { s->damage = - XDamageCreate (s->xcontext->disp, s->xwindow, - XDamageReportRawRectangles); + XDamageCreate (s->xcontext->disp, s->xwindow, XDamageReportNonEmpty); if (s->damage != None) { s->damage_region = XFixesCreateRegion (s->xcontext->disp, NULL, 0); if (s->damage_region != None) { @@ -399,7 +398,8 @@ gst_ximage_src_ximage_get (GstXImageSrc * ximagesrc) g_return_val_if_fail (GST_IS_XIMAGE_SRC (ximagesrc), NULL); #ifdef HAVE_XDAMAGE - if (ximagesrc->have_xdamage && ximagesrc->use_damage) { + if (ximagesrc->have_xdamage && ximagesrc->use_damage && + ximagesrc->last_ximage != NULL) { XEvent ev; /* have_frame is TRUE when either the entire screen has been @@ -410,92 +410,84 @@ gst_ximage_src_ximage_get (GstXImageSrc * ximagesrc) do { XNextEvent (ximagesrc->xcontext->disp, &ev); - if (ev.type == ximagesrc->damage_event_base + XDamageNotify) { - XDamageNotifyEvent *dev = (XDamageNotifyEvent *) & ev; -#ifdef HAVE_XSHM - if (ximagesrc->xcontext->use_xshm && - dev->area.width == ximagesrc->xcontext->width && - dev->area.height == ximagesrc->xcontext->height) { - GST_DEBUG_OBJECT (ximagesrc, "Entire screen was damaged"); - XShmGetImage (ximagesrc->xcontext->disp, ximagesrc->xwindow, - ximage->ximage, ximagesrc->startx, ximagesrc->starty, AllPlanes); - /* No need to collect more events */ - while (XPending (ximagesrc->xcontext->disp)) { - XNextEvent (ximagesrc->xcontext->disp, &ev); + if (ev.type == ximagesrc->damage_event_base + XDamageNotify) { + XserverRegion parts; + XRectangle *rects; + int nrects; + + parts = XFixesCreateRegion (ximagesrc->xcontext->disp, 0, 0); + XDamageSubtract (ximagesrc->xcontext->disp, ximagesrc->damage, None, + parts); + /* Now copy out all of the damaged rectangles. */ + rects = XFixesFetchRegion (ximagesrc->xcontext->disp, parts, &nrects); + if (rects != NULL) { + int i; + + if (!have_frame) { + GST_LOG_OBJECT (ximagesrc, + "Copying from last frame ximage->size: %d", + GST_BUFFER_SIZE (GST_BUFFER (ximage))); + memcpy (GST_BUFFER_DATA (GST_BUFFER (ximage)), + GST_BUFFER_DATA (GST_BUFFER (ximagesrc->last_ximage)), + GST_BUFFER_SIZE (GST_BUFFER (ximage))); + have_frame = TRUE; } - have_frame = TRUE; - break; - } else -#endif - { - /* if we only want a small area, clip this damage region to - * area we want */ - if (ximagesrc->endx > ximagesrc->startx && - ximagesrc->endy > ximagesrc->starty) { - /* see if damage area intersects */ - if (dev->area.x + dev->area.width < ximagesrc->startx || - dev->area.x > ximagesrc->endx) { - /* trivial reject */ - } else if (dev->area.y + dev->area.height < ximagesrc->starty || - dev->area.y > ximagesrc->endy) { - /* trivial reject */ - } else { - /* find intersect region */ - int startx, starty, width, height; - - startx = (dev->area.x < ximagesrc->startx) ? ximagesrc->startx : - dev->area.x; - starty = (dev->area.y < ximagesrc->starty) ? ximagesrc->starty : - dev->area.y; - width = (dev->area.x + dev->area.width < ximagesrc->endx) ? - dev->area.x + dev->area.width - startx : - ximagesrc->endx - startx; - height = (dev->area.y + dev->area.height < ximagesrc->endy) ? - dev->area.y + dev->area.height - starty : ximagesrc->endy - - starty; - if (!have_frame) { + for (i = 0; i < nrects; i++) { + GST_LOG_OBJECT (ximagesrc, + "Damaged sub-region @ %d,%d size %dx%d reported", + rects[i].x, rects[i].y, rects[i].width, rects[i].height); + + /* if we only want a small area, clip this damage region to + * area we want */ + if (ximagesrc->endx > ximagesrc->startx && + ximagesrc->endy > ximagesrc->starty) { + /* see if damage area intersects */ + if (rects[i].x + rects[i].width < ximagesrc->startx || + rects[i].x > ximagesrc->endx) { + /* trivial reject */ + } else if (rects[i].y + rects[i].height < ximagesrc->starty || + rects[i].y > ximagesrc->endy) { + /* trivial reject */ + } else { + /* find intersect region */ + int startx, starty, width, height; + + startx = (rects[i].x < ximagesrc->startx) ? ximagesrc->startx : + rects[i].x; + starty = (rects[i].y < ximagesrc->starty) ? ximagesrc->starty : + rects[i].y; + width = (rects[i].x + rects[i].width < ximagesrc->endx) ? + rects[i].x + rects[i].width - startx : + ximagesrc->endx - startx; + height = (rects[i].y + rects[i].height < ximagesrc->endy) ? + rects[i].y + rects[i].height - starty : ximagesrc->endy - + starty; + GST_LOG_OBJECT (ximagesrc, - "Copying from last frame ximage->size: %d", - GST_BUFFER_SIZE (GST_BUFFER (ximage))); - memcpy (GST_BUFFER_DATA (GST_BUFFER (ximage)), - GST_BUFFER_DATA (GST_BUFFER (ximagesrc->last_ximage)), - GST_BUFFER_SIZE (GST_BUFFER (ximage))); - have_frame = TRUE; + "Retrieving damaged sub-region @ %d,%d size %dx%d as intersect region", + startx, starty, width, height); + XGetSubImage (ximagesrc->xcontext->disp, ximagesrc->xwindow, + startx, starty, width, height, AllPlanes, ZPixmap, + ximage->ximage, startx - ximagesrc->startx, + starty - ximagesrc->starty); } + } else { GST_LOG_OBJECT (ximagesrc, - "Retrieving damaged sub-region @ %d,%d size %dx%d as intersect region", - startx, starty, width, height); + "Retrieving damaged sub-region @ %d,%d size %dx%d", + rects[i].x, rects[i].y, rects[i].width, rects[i].height); + XGetSubImage (ximagesrc->xcontext->disp, ximagesrc->xwindow, - startx, starty, width, height, AllPlanes, ZPixmap, - ximage->ximage, startx - ximagesrc->startx, - starty - ximagesrc->starty); - } - } else { - if (!have_frame) { - GST_LOG_OBJECT (ximagesrc, - "Copying from last frame ximage->size: %d", - GST_BUFFER_SIZE (GST_BUFFER (ximage))); - memcpy (GST_BUFFER_DATA (GST_BUFFER (ximage)), - GST_BUFFER_DATA (GST_BUFFER (ximagesrc->last_ximage)), - GST_BUFFER_SIZE (GST_BUFFER (ximage))); - have_frame = TRUE; + rects[i].x, rects[i].y, + rects[i].width, rects[i].height, + AllPlanes, ZPixmap, ximage->ximage, rects[i].x, rects[i].y); } - - GST_LOG_OBJECT (ximagesrc, - "Retrieving damaged sub-region @ %d,%d size %dx%d", - dev->area.x, dev->area.y, dev->area.width, dev->area.height); - - XGetSubImage (ximagesrc->xcontext->disp, ximagesrc->xwindow, - dev->area.x, dev->area.y, - dev->area.width, dev->area.height, - AllPlanes, ZPixmap, ximage->ximage, dev->area.x, dev->area.y); } + free (rects); } } } while (XPending (ximagesrc->xcontext->disp)); - XDamageSubtract (ximagesrc->xcontext->disp, ximagesrc->damage, None, None); if (!have_frame) { GST_LOG_OBJECT (ximagesrc, "Copying from last frame ximage->size: %d", @@ -644,9 +636,11 @@ gst_ximage_src_ximage_get (GstXImageSrc * ximagesrc) ximagesrc->cursor_image->pixels[i] = GUINT_TO_LE (ximagesrc->cursor_image->pixels[i]); /* copy those pixels across */ - for (j = starty; j < starty + iheight && j < starty + ximagesrc->height; + for (j = starty; + j < starty + iheight && j < ximagesrc->starty + ximagesrc->height; j++) { - for (i = startx; i < startx + iwidth && i < startx + ximagesrc->width; + for (i = startx; + i < startx + iwidth && i < ximagesrc->startx + ximagesrc->width; i++) { guint8 *src, *dest; -- cgit