sna: Fix checking the dirty boxes

I forgot how insane the data structure for the list of dirty boxes
attached to the damage is. It is neither a simple list, nor does not store
the count of boxes within each chunk.

Fixes regression from
commit 9026bb9546 [2.21.11]
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Fri Jun 28 15:59:17 2013 +0100

    sna: Inspect the dirty boxes when querying whether damage contains a rectangle

A side effect is that we now make sure that there is an upper bound to
the amount of searching we do for the no-reduce fast path.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=66430
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
Chris Wilson 2013-07-01 22:26:29 +01:00
parent 1c8a33a72e
commit ad0afda3fe
2 changed files with 21 additions and 23 deletions

View File

@ -264,7 +264,7 @@ static inline void list_move_tail(struct list *list, struct list *head)
* @return True if the list contains one or more elements or False otherwise.
*/
static inline bool
list_is_empty(struct list *head)
list_is_empty(const struct list *head)
{
return head->next == head;
}

View File

@ -1341,46 +1341,44 @@ static bool box_overlaps(const BoxRec *a, const BoxRec *b)
bool _sna_damage_contains_box__no_reduce(const struct sna_damage *damage,
const BoxRec *box)
{
struct sna_damage_box *iter;
int ret;
int n, count;
BoxPtr b;
assert(damage && damage->mode != DAMAGE_ALL);
if (!box_contains(&damage->extents, box))
return false;
ret = pixman_region_contains_rectangle(&damage->region, (BoxPtr)box);
n = pixman_region_contains_rectangle(&damage->region, (BoxPtr)box);
if (!damage->dirty)
return ret == PIXMAN_REGION_IN;
return n == PIXMAN_REGION_IN;
if (damage->mode == DAMAGE_ADD) {
if (ret == PIXMAN_REGION_IN)
if (n == PIXMAN_REGION_IN)
return true;
list_for_each_entry(iter, &damage->embedded_box.list, list) {
BoxPtr b;
int n;
count = damage->embedded_box.size;
if (list_is_empty(&damage->embedded_box.list))
count -= damage->remain;
b = (BoxPtr)(iter + 1);
for (n = 0; n < iter->size; n++) {
if (box_contains(&b[n], box))
return true;
}
b = damage->embedded_box.box;
for (n = 0; n < count; n++) {
if (box_contains(&b[n], box))
return true;
}
return false;
} else {
if (ret != PIXMAN_REGION_IN)
if (n != PIXMAN_REGION_IN)
return false;
list_for_each_entry(iter, &damage->embedded_box.list, list) {
BoxPtr b;
int n;
if (!list_is_empty(&damage->embedded_box.list))
return false;
b = (BoxPtr)(iter + 1);
for (n = 0; n < iter->size; n++) {
if (box_overlaps(&b[n], box))
return false;
}
count = damage->embedded_box.size - damage->remain;
b = damage->embedded_box.box;
for (n = 0; n < count; n++) {
if (box_overlaps(&b[n], box))
return false;
}
return true;