[dri2] Optimize event parsing to skip obsolete events.
This also fixes the problem where the X server does multiple resizes before the DRI driver gets the events. The obsolete buffer attach events then reference already destroyed buffer objects.
This commit is contained in:
@@ -287,8 +287,8 @@ __driUtilUpdateDrawableInfo(__DRIdrawablePrivate *pdp)
|
|||||||
int
|
int
|
||||||
__driParseEvents(__DRIscreenPrivate *psp, __DRIdrawablePrivate *pdp)
|
__driParseEvents(__DRIscreenPrivate *psp, __DRIdrawablePrivate *pdp)
|
||||||
{
|
{
|
||||||
__DRIDrawableConfigEvent *dc;
|
__DRIDrawableConfigEvent *dc, *last_dc;
|
||||||
__DRIBufferAttachEvent *ba;
|
__DRIBufferAttachEvent *ba, *last_ba;
|
||||||
unsigned int tail, mask, *p, end, total, size, changed;
|
unsigned int tail, mask, *p, end, total, size, changed;
|
||||||
unsigned char *data;
|
unsigned char *data;
|
||||||
size_t rect_size;
|
size_t rect_size;
|
||||||
@@ -309,12 +309,14 @@ __driParseEvents(__DRIscreenPrivate *psp, __DRIdrawablePrivate *pdp)
|
|||||||
|
|
||||||
total = psp->dri2.buffer->head - pdp->dri2.tail;
|
total = psp->dri2.buffer->head - pdp->dri2.tail;
|
||||||
mask = psp->dri2.buffer->size - 1;
|
mask = psp->dri2.buffer->size - 1;
|
||||||
tail = pdp->dri2.tail;
|
|
||||||
end = psp->dri2.buffer->head;
|
end = psp->dri2.buffer->head;
|
||||||
data = psp->dri2.buffer->data;
|
data = psp->dri2.buffer->data;
|
||||||
changed = 0;
|
|
||||||
|
|
||||||
while (tail != end) {
|
changed = 0;
|
||||||
|
last_dc = NULL;
|
||||||
|
last_ba = NULL;
|
||||||
|
|
||||||
|
for (tail = pdp->dri2.tail; tail != end; tail += size) {
|
||||||
p = (unsigned int *) (data + (tail & mask));
|
p = (unsigned int *) (data + (tail & mask));
|
||||||
size = DRI2_EVENT_SIZE(*p);
|
size = DRI2_EVENT_SIZE(*p);
|
||||||
if (size > total || (tail & mask) + size > psp->dri2.buffer->size) {
|
if (size > total || (tail & mask) + size > psp->dri2.buffer->size) {
|
||||||
@@ -326,50 +328,92 @@ __driParseEvents(__DRIscreenPrivate *psp, __DRIdrawablePrivate *pdp)
|
|||||||
switch (DRI2_EVENT_TYPE(*p)) {
|
switch (DRI2_EVENT_TYPE(*p)) {
|
||||||
case DRI2_EVENT_DRAWABLE_CONFIG:
|
case DRI2_EVENT_DRAWABLE_CONFIG:
|
||||||
dc = (__DRIDrawableConfigEvent *) p;
|
dc = (__DRIDrawableConfigEvent *) p;
|
||||||
|
if (dc->drawable == pdp->hHWDrawable)
|
||||||
if (dc->drawable != pdp->hHWDrawable)
|
last_dc = dc;
|
||||||
break;
|
|
||||||
|
|
||||||
if (pdp->w != dc->width || pdp->h != dc->height)
|
|
||||||
changed = 1;
|
|
||||||
|
|
||||||
pdp->x = dc->x;
|
|
||||||
pdp->y = dc->y;
|
|
||||||
pdp->w = dc->width;
|
|
||||||
pdp->h = dc->height;
|
|
||||||
|
|
||||||
pdp->backX = 0;
|
|
||||||
pdp->backY = 0;
|
|
||||||
pdp->numBackClipRects = 1;
|
|
||||||
pdp->pBackClipRects[0].x1 = 0;
|
|
||||||
pdp->pBackClipRects[0].y1 = 0;
|
|
||||||
pdp->pBackClipRects[0].x2 = pdp->w;
|
|
||||||
pdp->pBackClipRects[0].y2 = pdp->h;
|
|
||||||
|
|
||||||
pdp->numClipRects = dc->num_rects;
|
|
||||||
_mesa_free(pdp->pClipRects);
|
|
||||||
rect_size = dc->num_rects * sizeof dc->rects[0];
|
|
||||||
pdp->pClipRects = _mesa_malloc(rect_size);
|
|
||||||
memcpy(pdp->pClipRects, dc->rects, rect_size);
|
|
||||||
|
|
||||||
if (changed)
|
|
||||||
(*psp->DriverAPI.UpdateBuffer)(pdp, p);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DRI2_EVENT_BUFFER_ATTACH:
|
case DRI2_EVENT_BUFFER_ATTACH:
|
||||||
ba = (__DRIBufferAttachEvent *) p;
|
ba = (__DRIBufferAttachEvent *) p;
|
||||||
|
if (ba->drawable == pdp->hHWDrawable &&
|
||||||
if (ba->drawable != pdp->hHWDrawable)
|
ba->buffer.attachment == DRI_DRAWABLE_BUFFER_FRONT_LEFT)
|
||||||
break;
|
last_ba = ba;
|
||||||
|
|
||||||
(*psp->DriverAPI.UpdateBuffer)(pdp, p);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (last_dc) {
|
||||||
|
if (pdp->w != last_dc->width || pdp->h != last_dc->height)
|
||||||
|
changed = 1;
|
||||||
|
|
||||||
tail += size;
|
pdp->x = last_dc->x;
|
||||||
|
pdp->y = last_dc->y;
|
||||||
|
pdp->w = last_dc->width;
|
||||||
|
pdp->h = last_dc->height;
|
||||||
|
|
||||||
|
pdp->backX = 0;
|
||||||
|
pdp->backY = 0;
|
||||||
|
pdp->numBackClipRects = 1;
|
||||||
|
pdp->pBackClipRects[0].x1 = 0;
|
||||||
|
pdp->pBackClipRects[0].y1 = 0;
|
||||||
|
pdp->pBackClipRects[0].x2 = pdp->w;
|
||||||
|
pdp->pBackClipRects[0].y2 = pdp->h;
|
||||||
|
|
||||||
|
pdp->numClipRects = last_dc->num_rects;
|
||||||
|
_mesa_free(pdp->pClipRects);
|
||||||
|
rect_size = last_dc->num_rects * sizeof last_dc->rects[0];
|
||||||
|
pdp->pClipRects = _mesa_malloc(rect_size);
|
||||||
|
memcpy(pdp->pClipRects, last_dc->rects, rect_size);
|
||||||
|
|
||||||
|
if (changed)
|
||||||
|
(*psp->DriverAPI.UpdateBuffer)(pdp, (unsigned int *) last_dc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Front buffer attachments are special, they typically mean that
|
||||||
|
* we're rendering to a redirected window (or a child window of a
|
||||||
|
* redirected window) and that it got resized. Resizing the root
|
||||||
|
* window on randr events is a special case of this. Other causes
|
||||||
|
* may be a window transitioning between redirected and
|
||||||
|
* non-redirected, or a window getting reparented between parents
|
||||||
|
* with different window pixmaps (eg two redirected windows).
|
||||||
|
* These events are special in that the X server allocates the
|
||||||
|
* buffer and that the buffer may be shared by other child
|
||||||
|
* windows. When our window share the window pixmap with its
|
||||||
|
* parent, drawable config events doesn't affect the front buffer.
|
||||||
|
* We only care about the last such event in the buffer; in fact,
|
||||||
|
* older events will refer to invalid buffer objects.*/
|
||||||
|
if (last_ba)
|
||||||
|
(*psp->DriverAPI.UpdateBuffer)(pdp, (unsigned int *) last_ba);
|
||||||
|
|
||||||
|
/* Like for buffer attachments, we only care about the most recent
|
||||||
|
* drawable config. */
|
||||||
|
if (last_dc)
|
||||||
|
(*psp->DriverAPI.UpdateBuffer)(pdp, (unsigned int *) last_dc);
|
||||||
|
|
||||||
|
/* If there was a drawable config event in the buffer and it
|
||||||
|
* changed the size of the window, all buffer auxillary buffer
|
||||||
|
* attachments prior to that are invalid (as opposed to the front
|
||||||
|
* buffer case discussed above). In that case we can start
|
||||||
|
* looking for buffer attachment after the last drawable config
|
||||||
|
* event. If there is no drawable config event in this batch of
|
||||||
|
* events, we have to assume that the last batch might have had
|
||||||
|
* one and process all buffer attach events.*/
|
||||||
|
if (last_dc && changed)
|
||||||
|
tail = (unsigned char *) last_dc - data;
|
||||||
|
else
|
||||||
|
tail = pdp->dri2.tail;
|
||||||
|
|
||||||
|
for ( ; tail != end; tail += size) {
|
||||||
|
ba = (__DRIBufferAttachEvent *) (data + (tail & mask));
|
||||||
|
size = DRI2_EVENT_SIZE(ba->event_header);
|
||||||
|
|
||||||
|
if (DRI2_EVENT_TYPE(ba->event_header) != DRI2_EVENT_BUFFER_ATTACH)
|
||||||
|
continue;
|
||||||
|
if (ba->drawable != pdp->hHWDrawable)
|
||||||
|
continue;
|
||||||
|
if (last_ba == ba)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
(*psp->DriverAPI.UpdateBuffer)(pdp, (unsigned int *) ba);
|
||||||
}
|
}
|
||||||
|
|
||||||
pdp->dri2.tail = tail;
|
pdp->dri2.tail = tail;
|
||||||
|
Reference in New Issue
Block a user