mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-11-10 08:38:20 +00:00
[host] nvfbc: be more intellegent when unionizing disjointed sets
This commit is contained in:
parent
affc3f51f8
commit
b515fa80d5
@ -356,6 +356,8 @@ done:
|
||||
|
||||
struct DisjointSet {
|
||||
int id;
|
||||
bool use;
|
||||
bool row;
|
||||
int x1;
|
||||
int y1;
|
||||
int x2;
|
||||
@ -377,9 +379,7 @@ static void dsUnion(struct DisjointSet * ds, int a, int b)
|
||||
return;
|
||||
|
||||
ds[b].id = a;
|
||||
ds[a].x1 = min(ds[a].x1, ds[b].x1);
|
||||
ds[a].x2 = max(ds[a].x2, ds[b].x2);
|
||||
ds[a].y1 = min(ds[a].y1, ds[b].y1);
|
||||
ds[a].y2 = max(ds[a].y2, ds[b].y2);
|
||||
}
|
||||
|
||||
@ -390,25 +390,93 @@ static void updateDamageRects(CaptureFrame * frame)
|
||||
|
||||
struct DisjointSet ds[w * h];
|
||||
|
||||
// init the ds usage
|
||||
for(unsigned int i = 0; i < ARRAY_LENGTH(ds); ++i)
|
||||
ds[i].use = (bool)this->diffMap[i];
|
||||
|
||||
// reduce the number of reusuting rectangles by filling in holes and merging
|
||||
// iiregular shapes into contiguous rectangles
|
||||
bool resolve;
|
||||
do
|
||||
{
|
||||
resolve = false;
|
||||
for (unsigned int y = 0; y < h; ++y)
|
||||
for (unsigned int x = 0; x < w; ++x)
|
||||
if (this->diffMap[y * w + x])
|
||||
{
|
||||
ds[y * w + x].id = y * w + x;
|
||||
ds[y * w + x].x1 = ds[y * w + x].x2 = x;
|
||||
ds[y * w + x].y1 = ds[y * w + x].y2 = y;
|
||||
const int c = y * w + x; // current
|
||||
if (ds[c].use)
|
||||
continue;
|
||||
|
||||
if (y > 0 && this->diffMap[(y-1) * w + x])
|
||||
dsUnion(ds, (y-1) * w + x, y * w + x);
|
||||
const int l = c - 1; // left
|
||||
const int r = c + 1; // right
|
||||
const int u = c - w; // up
|
||||
const int d = c + w; // down
|
||||
|
||||
if (x > 0 && this->diffMap[y * w + x - 1])
|
||||
dsUnion(ds, y * w + x, y * w + x - 1);
|
||||
if ((x < w - 1 && y < h - 1 && ds[r].use && ds[d].use) ||
|
||||
(x > 0 && y < h - 1 && ds[l].use && ds[d].use) ||
|
||||
(x < w - 1 && y > 0 && ds[r].use && ds[u].use) ||
|
||||
(x > 0 && y > 0 && ds[l].use && ds[u].use) ||
|
||||
(x > 0 && y > 0 &&
|
||||
x < w - 1 && y < h - 1 && ds[l].use && ds[u].use &&
|
||||
ds[r].use && ds[d].use)
|
||||
)
|
||||
{
|
||||
ds[c].use = true;
|
||||
resolve = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
while(resolve);
|
||||
|
||||
for (unsigned int y = 0; y < h; ++y)
|
||||
for (unsigned int x = 0; x < w; ++x)
|
||||
{
|
||||
const int c = y * w + x; // current
|
||||
const int l = c - 1; // left
|
||||
const int u = c - w; // up
|
||||
|
||||
if (ds[c].use)
|
||||
{
|
||||
ds[c].id = c;
|
||||
ds[c].row = false;
|
||||
ds[c].x1 = ds[c].x2 = x;
|
||||
ds[c].y1 = ds[c].y2 = y;
|
||||
|
||||
if (y > 0 && ds[u].use)
|
||||
{
|
||||
bool ok = true;
|
||||
if (x > 0 && ds[l].id != ds[u].id)
|
||||
{
|
||||
// no need to use dsFind as the search order ensures that the id has
|
||||
// been fully resolved of the block above
|
||||
for(unsigned int j = ds[ds[u].id].x1; j <= ds[ds[u].id].x2; ++j)
|
||||
if (!ds[y * w + j].use)
|
||||
{
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ok)
|
||||
{
|
||||
dsUnion(ds, u, c);
|
||||
ds[c].row = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (x > 0 && ds[l].use && (ds[l].id == l || !ds[l].row))
|
||||
dsUnion(ds, l, c);
|
||||
}
|
||||
}
|
||||
|
||||
int rectId = 0;
|
||||
for (unsigned int y = 0; y < h; ++y)
|
||||
for (unsigned int x = 0; x < w; ++x)
|
||||
if (this->diffMap[y * w + x] && ds[y * w + x].id == y * w + x)
|
||||
{
|
||||
const int c = y * w + x;
|
||||
|
||||
if (ds[c].use && ds[c].id == c)
|
||||
{
|
||||
if (rectId >= KVMFR_MAX_DAMAGE_RECTS)
|
||||
{
|
||||
@ -416,10 +484,10 @@ static void updateDamageRects(CaptureFrame * frame)
|
||||
goto done;
|
||||
}
|
||||
|
||||
int x1 = ds[y * w + x].x1 << this->diffShift;
|
||||
int y1 = ds[y * w + x].y1 << this->diffShift;
|
||||
int x2 = min((ds[y * w + x].x2 + 1) << this->diffShift, this->width);
|
||||
int y2 = min((ds[y * w + x].y2 + 1) << this->diffShift, this->height);
|
||||
int x1 = ds[c].x1 << this->diffShift;
|
||||
int y1 = ds[c].y1 << this->diffShift;
|
||||
int x2 = min((ds[c].x2 + 1) << this->diffShift, this->width);
|
||||
int y2 = min((ds[c].y2 + 1) << this->diffShift, this->height);
|
||||
frame->damageRects[rectId++] = (FrameDamageRect) {
|
||||
.x = x1,
|
||||
.y = y1,
|
||||
@ -427,8 +495,7 @@ static void updateDamageRects(CaptureFrame * frame)
|
||||
.height = y2 - y1,
|
||||
};
|
||||
}
|
||||
|
||||
rectId = rectsRejectContained(frame->damageRects, rectId);
|
||||
}
|
||||
|
||||
done:
|
||||
frame->damageRectsCount = rectId;
|
||||
|
Loading…
Reference in New Issue
Block a user