intel-virtual-output: Rebuild pointers after realloc

If reallocs gives us a new memory block, we need to update everything
that pointed into the old blocks.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
Chris Wilson 2013-09-01 16:44:14 +01:00
parent a41acee728
commit 7e6472cfcc
1 changed files with 51 additions and 30 deletions

View File

@ -1378,9 +1378,23 @@ static int add_display(struct context *ctx, Display *dpy)
struct display *display;
if (is_power_of_2(ctx->ndisplay)) {
ctx->display = realloc(ctx->display, 2*ctx->ndisplay*sizeof(struct display));
if (ctx->display == NULL)
struct display *new_display;
new_display = realloc(ctx->display, 2*ctx->ndisplay*sizeof(struct display));
if (new_display == NULL)
return -ENOMEM;
if (new_display != ctx->display) {
int n;
for (n = 0; n < ctx->nclone; n++) {
struct clone *clone = &ctx->clones[n];
clone->src.display = new_display + (clone->src.display - ctx->display);
clone->dst.display = new_display + (clone->dst.display - ctx->display);
}
}
ctx->display = new_display;
}
display = memset(&ctx->display[ctx->ndisplay++], 0, sizeof(struct display));
@ -1540,26 +1554,6 @@ static int context_init(struct context *ctx)
return 0;
}
static void context_build_lists(struct context *ctx)
{
int n, m;
for (n = 1; n < ctx->ndisplay; n++) {
struct display *d = &ctx->display[n];
d->clone = NULL;
for (m = 0; m < ctx->nclone; m++) {
struct clone *c = &ctx->clones[m];
if (c->dst.display != d)
continue;
c->next = d->clone;
d->clone = c;
}
}
}
static int add_fd(struct context *ctx, int fd)
{
if (fd < 0)
@ -1591,12 +1585,39 @@ static void display_init_randr_hpd(struct display *display)
XRRSelectInput(display->dpy, display->root, RROutputChangeNotifyMask);
}
static void rebuild_clones(struct context *ctx)
{
int n, m;
for (n = 1; n < ctx->ndisplay; n++) {
struct display *d = &ctx->display[n];
d->clone = NULL;
for (m = 0; m < ctx->nclone; m++) {
struct clone *c = &ctx->clones[m];
if (c->dst.display != d)
continue;
c->next = d->clone;
d->clone = c;
}
}
}
static struct clone *add_clone(struct context *ctx)
{
if (is_power_of_2(ctx->nclone)) {
ctx->clones = realloc(ctx->clones, 2*ctx->nclone*sizeof(struct clone));
if (ctx->clones == NULL)
struct clone *new_clones;
new_clones = realloc(ctx->clones, 2*ctx->nclone*sizeof(struct clone));
if (new_clones == NULL)
return NULL;
if (new_clones != ctx->clones)
rebuild_clones(ctx);
ctx->clones = new_clones;
}
return memset(&ctx->clones[ctx->nclone++], 0, sizeof(struct clone));
@ -1625,6 +1646,8 @@ static int last_display_add_clones(struct context *ctx)
struct clone *clone = add_clone(ctx);
clone->depth = 24;
clone->next = display->clone;
display->clone = clone;
sprintf(buf, "VIRTUAL%d", ctx->nclone);
ret = clone_output_init(clone, &clone->src, ctx->display, buf, claim_virtual(ctx->display, buf));
@ -1664,19 +1687,17 @@ static int last_display_add_clones(struct context *ctx)
static int last_display_clone(struct context *ctx, int fd)
{
if (fd < 0)
goto err;
return fd;
fd = add_fd(ctx, fd);
if (fd < 0)
goto err;
return fd;
fd = last_display_add_clones(ctx);
if (fd)
goto err;
return fd;
err:
context_build_lists(ctx);
return fd;
return 0;
}
static int first_display_has_singleton(struct context *ctx)