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 {
|
struct DisjointSet {
|
||||||
int id;
|
int id;
|
||||||
|
bool use;
|
||||||
|
bool row;
|
||||||
int x1;
|
int x1;
|
||||||
int y1;
|
int y1;
|
||||||
int x2;
|
int x2;
|
||||||
@ -377,9 +379,7 @@ static void dsUnion(struct DisjointSet * ds, int a, int b)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
ds[b].id = a;
|
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].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);
|
ds[a].y2 = max(ds[a].y2, ds[b].y2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -390,25 +390,93 @@ static void updateDamageRects(CaptureFrame * frame)
|
|||||||
|
|
||||||
struct DisjointSet ds[w * h];
|
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 y = 0; y < h; ++y)
|
||||||
for (unsigned int x = 0; x < w; ++x)
|
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; // current
|
||||||
ds[y * w + x].x1 = ds[y * w + x].x2 = x;
|
if (ds[c].use)
|
||||||
ds[y * w + x].y1 = ds[y * w + x].y2 = y;
|
continue;
|
||||||
|
|
||||||
if (y > 0 && this->diffMap[(y-1) * w + x])
|
const int l = c - 1; // left
|
||||||
dsUnion(ds, (y-1) * w + x, y * w + x);
|
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])
|
if ((x < w - 1 && y < h - 1 && ds[r].use && ds[d].use) ||
|
||||||
dsUnion(ds, y * w + x, y * w + x - 1);
|
(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;
|
int rectId = 0;
|
||||||
for (unsigned int y = 0; y < h; ++y)
|
for (unsigned int y = 0; y < h; ++y)
|
||||||
for (unsigned int x = 0; x < w; ++x)
|
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)
|
if (rectId >= KVMFR_MAX_DAMAGE_RECTS)
|
||||||
{
|
{
|
||||||
@ -416,10 +484,10 @@ static void updateDamageRects(CaptureFrame * frame)
|
|||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
int x1 = ds[y * w + x].x1 << this->diffShift;
|
int x1 = ds[c].x1 << this->diffShift;
|
||||||
int y1 = ds[y * w + x].y1 << this->diffShift;
|
int y1 = ds[c].y1 << this->diffShift;
|
||||||
int x2 = min((ds[y * w + x].x2 + 1) << this->diffShift, this->width);
|
int x2 = min((ds[c].x2 + 1) << this->diffShift, this->width);
|
||||||
int y2 = min((ds[y * w + x].y2 + 1) << this->diffShift, this->height);
|
int y2 = min((ds[c].y2 + 1) << this->diffShift, this->height);
|
||||||
frame->damageRects[rectId++] = (FrameDamageRect) {
|
frame->damageRects[rectId++] = (FrameDamageRect) {
|
||||||
.x = x1,
|
.x = x1,
|
||||||
.y = y1,
|
.y = y1,
|
||||||
@ -427,8 +495,7 @@ static void updateDamageRects(CaptureFrame * frame)
|
|||||||
.height = y2 - y1,
|
.height = y2 - y1,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
}
|
||||||
rectId = rectsRejectContained(frame->damageRects, rectId);
|
|
||||||
|
|
||||||
done:
|
done:
|
||||||
frame->damageRectsCount = rectId;
|
frame->damageRectsCount = rectId;
|
||||||
|
Loading…
Reference in New Issue
Block a user