Some cleanups and preparations (patches 1-4, also 6). The change which makes wayland actually work in multihead configurations is patch 5.
Gerd Hoffmann (6): drm/qxl: move qxl_primary_apply_cursor to correct place drm/qxl: drop unused offset parameter from qxl_io_create_primary() drm/qxl: track primary bo drm/qxl: use shadow bo directly drm/qxl: cover all crtcs in shadow bo. drm/qxl: use qxl_num_crtc directly
drivers/gpu/drm/qxl/qxl_drv.h | 8 +- drivers/gpu/drm/qxl/qxl_cmd.c | 18 ++-- drivers/gpu/drm/qxl/qxl_display.c | 170 ++++++++++++++++++++++++-------------- drivers/gpu/drm/qxl/qxl_draw.c | 9 +- 4 files changed, 130 insertions(+), 75 deletions(-)
The cursor must be set again after creating the primary surface. Also drop the error message.
Signed-off-by: Gerd Hoffmann kraxel@redhat.com --- drivers/gpu/drm/qxl/qxl_display.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c index ce0b9c40fc..58fb2c4308 100644 --- a/drivers/gpu/drm/qxl/qxl_display.c +++ b/drivers/gpu/drm/qxl/qxl_display.c @@ -533,7 +533,6 @@ static void qxl_primary_atomic_update(struct drm_plane *plane, .x2 = plane->state->fb->width, .y2 = plane->state->fb->height }; - int ret; bool same_shadow = false;
if (old_state->fb) { @@ -554,16 +553,13 @@ static void qxl_primary_atomic_update(struct drm_plane *plane, if (!same_shadow) qxl_io_destroy_primary(qdev); bo_old->is_primary = false; - - ret = qxl_primary_apply_cursor(plane); - if (ret) - DRM_ERROR( - "could not set cursor after creating primary"); }
if (!bo->is_primary) { - if (!same_shadow) + if (!same_shadow) { qxl_io_create_primary(qdev, 0, bo); + qxl_primary_apply_cursor(plane); + } bo->is_primary = true; }
Signed-off-by: Gerd Hoffmann kraxel@redhat.com --- drivers/gpu/drm/qxl/qxl_drv.h | 1 - drivers/gpu/drm/qxl/qxl_cmd.c | 7 +++---- drivers/gpu/drm/qxl/qxl_display.c | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h index 14d3fa8557..6b8d28a23f 100644 --- a/drivers/gpu/drm/qxl/qxl_drv.h +++ b/drivers/gpu/drm/qxl/qxl_drv.h @@ -395,7 +395,6 @@ void qxl_update_screen(struct qxl_device *qxl); /* qxl io operations (qxl_cmd.c) */
void qxl_io_create_primary(struct qxl_device *qdev, - unsigned int offset, struct qxl_bo *bo); void qxl_io_destroy_primary(struct qxl_device *qdev); void qxl_io_memslot_add(struct qxl_device *qdev, uint8_t id); diff --git a/drivers/gpu/drm/qxl/qxl_cmd.c b/drivers/gpu/drm/qxl/qxl_cmd.c index dffc5093ff..f263d83775 100644 --- a/drivers/gpu/drm/qxl/qxl_cmd.c +++ b/drivers/gpu/drm/qxl/qxl_cmd.c @@ -375,8 +375,7 @@ void qxl_io_destroy_primary(struct qxl_device *qdev) qdev->primary_created = false; }
-void qxl_io_create_primary(struct qxl_device *qdev, - unsigned int offset, struct qxl_bo *bo) +void qxl_io_create_primary(struct qxl_device *qdev, struct qxl_bo *bo) { struct qxl_surface_create *create;
@@ -387,9 +386,9 @@ void qxl_io_create_primary(struct qxl_device *qdev, create->height = bo->surf.height; create->stride = bo->surf.stride; if (bo->shadow) { - create->mem = qxl_bo_physical_address(qdev, bo->shadow, offset); + create->mem = qxl_bo_physical_address(qdev, bo->shadow, 0); } else { - create->mem = qxl_bo_physical_address(qdev, bo, offset); + create->mem = qxl_bo_physical_address(qdev, bo, 0); }
DRM_DEBUG_DRIVER("mem = %llx, from %p\n", create->mem, bo->kptr); diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c index 58fb2c4308..d875cae02f 100644 --- a/drivers/gpu/drm/qxl/qxl_display.c +++ b/drivers/gpu/drm/qxl/qxl_display.c @@ -557,7 +557,7 @@ static void qxl_primary_atomic_update(struct drm_plane *plane,
if (!bo->is_primary) { if (!same_shadow) { - qxl_io_create_primary(qdev, 0, bo); + qxl_io_create_primary(qdev, bo); qxl_primary_apply_cursor(plane); } bo->is_primary = true;
Track which bo is used as primary surface. With that in place we don't need the primary_created flag any more, we can just check the primary bo pointer instead.
Also verify we don't already have a primary surface in qxl_io_create_primary().
Signed-off-by: Gerd Hoffmann kraxel@redhat.com --- drivers/gpu/drm/qxl/qxl_drv.h | 2 +- drivers/gpu/drm/qxl/qxl_cmd.c | 7 +++++-- drivers/gpu/drm/qxl/qxl_display.c | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h index 6b8d28a23f..92140e0d71 100644 --- a/drivers/gpu/drm/qxl/qxl_drv.h +++ b/drivers/gpu/drm/qxl/qxl_drv.h @@ -229,7 +229,7 @@ struct qxl_device {
struct qxl_ram_header *ram_header;
- unsigned int primary_created:1; + struct qxl_bo *primary_bo;
struct qxl_memslot *mem_slots; uint8_t n_mem_slots; diff --git a/drivers/gpu/drm/qxl/qxl_cmd.c b/drivers/gpu/drm/qxl/qxl_cmd.c index f263d83775..3c606f0f7a 100644 --- a/drivers/gpu/drm/qxl/qxl_cmd.c +++ b/drivers/gpu/drm/qxl/qxl_cmd.c @@ -372,13 +372,16 @@ void qxl_io_flush_surfaces(struct qxl_device *qdev) void qxl_io_destroy_primary(struct qxl_device *qdev) { wait_for_io_cmd(qdev, 0, QXL_IO_DESTROY_PRIMARY_ASYNC); - qdev->primary_created = false; + qdev->primary_bo = NULL; }
void qxl_io_create_primary(struct qxl_device *qdev, struct qxl_bo *bo) { struct qxl_surface_create *create;
+ if (WARN_ON(qdev->primary_bo)) + return; + DRM_DEBUG_DRIVER("qdev %p, ram_header %p\n", qdev, qdev->ram_header); create = &qdev->ram_header->create_surface; create->format = bo->surf.format; @@ -397,7 +400,7 @@ void qxl_io_create_primary(struct qxl_device *qdev, struct qxl_bo *bo) create->type = QXL_SURF_TYPE_PRIMARY;
wait_for_io_cmd(qdev, 0, QXL_IO_CREATE_PRIMARY_ASYNC); - qdev->primary_created = true; + qdev->primary_bo = bo; }
void qxl_io_memslot_add(struct qxl_device *qdev, uint8_t id) diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c index d875cae02f..69b180735d 100644 --- a/drivers/gpu/drm/qxl/qxl_display.c +++ b/drivers/gpu/drm/qxl/qxl_display.c @@ -302,7 +302,7 @@ static void qxl_crtc_update_monitors_config(struct drm_crtc *crtc, struct qxl_head head; int oldcount, i = qcrtc->index;
- if (!qdev->primary_created) { + if (!qdev->primary_bo) { DRM_DEBUG_KMS("no primary surface, skip (%s)\n", reason); return; }
Pass the shadow bo to qxl_io_create_primary() instead of expecting qxl_io_create_primary to check bo->shadow. Set is_primary flag on the shadow bo. Move the is_primary tracking into qxl_io_create_primary() and qxl_io_destroy_primary() functions.
That simplifies primary surface tracking and the workflow in qxl_primary_atomic_update().
Signed-off-by: Gerd Hoffmann kraxel@redhat.com --- drivers/gpu/drm/qxl/qxl_cmd.c | 8 +++----- drivers/gpu/drm/qxl/qxl_display.c | 29 ++++++++--------------------- 2 files changed, 11 insertions(+), 26 deletions(-)
diff --git a/drivers/gpu/drm/qxl/qxl_cmd.c b/drivers/gpu/drm/qxl/qxl_cmd.c index 3c606f0f7a..3957e70ca0 100644 --- a/drivers/gpu/drm/qxl/qxl_cmd.c +++ b/drivers/gpu/drm/qxl/qxl_cmd.c @@ -372,6 +372,7 @@ void qxl_io_flush_surfaces(struct qxl_device *qdev) void qxl_io_destroy_primary(struct qxl_device *qdev) { wait_for_io_cmd(qdev, 0, QXL_IO_DESTROY_PRIMARY_ASYNC); + qdev->primary_bo->is_primary = false; qdev->primary_bo = NULL; }
@@ -388,11 +389,7 @@ void qxl_io_create_primary(struct qxl_device *qdev, struct qxl_bo *bo) create->width = bo->surf.width; create->height = bo->surf.height; create->stride = bo->surf.stride; - if (bo->shadow) { - create->mem = qxl_bo_physical_address(qdev, bo->shadow, 0); - } else { - create->mem = qxl_bo_physical_address(qdev, bo, 0); - } + create->mem = qxl_bo_physical_address(qdev, bo, 0);
DRM_DEBUG_DRIVER("mem = %llx, from %p\n", create->mem, bo->kptr);
@@ -401,6 +398,7 @@ void qxl_io_create_primary(struct qxl_device *qdev, struct qxl_bo *bo)
wait_for_io_cmd(qdev, 0, QXL_IO_CREATE_PRIMARY_ASYNC); qdev->primary_bo = bo; + qdev->primary_bo->is_primary = true; }
void qxl_io_memslot_add(struct qxl_device *qdev, uint8_t id) diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c index 69b180735d..472df00c02 100644 --- a/drivers/gpu/drm/qxl/qxl_display.c +++ b/drivers/gpu/drm/qxl/qxl_display.c @@ -526,14 +526,13 @@ static void qxl_primary_atomic_update(struct drm_plane *plane, { struct qxl_device *qdev = plane->dev->dev_private; struct qxl_bo *bo = gem_to_qxl_bo(plane->state->fb->obj[0]); - struct qxl_bo *bo_old; + struct qxl_bo *bo_old, *primary; struct drm_clip_rect norect = { .x1 = 0, .y1 = 0, .x2 = plane->state->fb->width, .y2 = plane->state->fb->height }; - bool same_shadow = false;
if (old_state->fb) { bo_old = gem_to_qxl_bo(old_state->fb->obj[0]); @@ -541,26 +540,13 @@ static void qxl_primary_atomic_update(struct drm_plane *plane, bo_old = NULL; }
- if (bo == bo_old) - return; + primary = bo->shadow ? bo->shadow : bo;
- if (bo_old && bo_old->shadow && bo->shadow && - bo_old->shadow == bo->shadow) { - same_shadow = true; - } - - if (bo_old && bo_old->is_primary) { - if (!same_shadow) + if (!primary->is_primary) { + if (qdev->primary_bo) qxl_io_destroy_primary(qdev); - bo_old->is_primary = false; - } - - if (!bo->is_primary) { - if (!same_shadow) { - qxl_io_create_primary(qdev, bo); - qxl_primary_apply_cursor(plane); - } - bo->is_primary = true; + qxl_io_create_primary(qdev, primary); + qxl_primary_apply_cursor(plane); }
qxl_draw_dirty_fb(qdev, plane->state->fb, bo, 0, 0, &norect, 1, 1); @@ -756,6 +742,7 @@ static int qxl_plane_prepare_fb(struct drm_plane *plane, qxl_bo_create(qdev, user_bo->gem_base.size, true, true, QXL_GEM_DOMAIN_VRAM, NULL, &user_bo->shadow); + user_bo->shadow->surf = user_bo->surf; } }
@@ -784,7 +771,7 @@ static void qxl_plane_cleanup_fb(struct drm_plane *plane, user_bo = gem_to_qxl_bo(obj); qxl_bo_unpin(user_bo);
- if (user_bo->shadow && !user_bo->is_primary) { + if (user_bo->shadow && !user_bo->shadow->is_primary) { drm_gem_object_put_unlocked(&user_bo->shadow->gem_base); user_bo->shadow = NULL; }
The qxl device supports only a single active framebuffer ("primary surface" in spice terminology). In multihead configurations are handled by defining rectangles within the primary surface for each head/crtc.
Userspace which uses the qxl ioctl interface (xorg qxl driver) is aware of this limitation and will setup framebuffers and crtcs accordingly.
Userspace which uses dumb framebuffers (xorg modesetting driver, wayland) is not aware of this limitation and tries to use two framebuffers (one for each crtc) instead.
The qxl kms driver already has the dumb bo separated from the primary surface, by using a (shared) shadow bo as primary surface. This is needed to support pageflips without having to re-create the primary surface. The qxl driver will blit from the dumb bo to the shadow bo instead.
So we can extend the shadow logic: Maintain a global shadow bo (aka primary surface), make it big enough that dumb bo's for all crtcs fit in side-by-side. Adjust the pageflip blits to place the heads next to each other in the shadow.
With this patch in place multihead qxl works with wayland.
Signed-off-by: Gerd Hoffmann kraxel@redhat.com --- drivers/gpu/drm/qxl/qxl_drv.h | 5 +- drivers/gpu/drm/qxl/qxl_display.c | 120 +++++++++++++++++++++++++++++--------- drivers/gpu/drm/qxl/qxl_draw.c | 9 ++- 3 files changed, 105 insertions(+), 29 deletions(-)
diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h index 92140e0d71..161be511cd 100644 --- a/drivers/gpu/drm/qxl/qxl_drv.h +++ b/drivers/gpu/drm/qxl/qxl_drv.h @@ -230,6 +230,8 @@ struct qxl_device { struct qxl_ram_header *ram_header;
struct qxl_bo *primary_bo; + struct qxl_bo *dumb_shadow_bo; + struct qxl_head *dumb_heads;
struct qxl_memslot *mem_slots; uint8_t n_mem_slots; @@ -447,7 +449,8 @@ void qxl_draw_dirty_fb(struct qxl_device *qdev, struct qxl_bo *bo, unsigned int flags, unsigned int color, struct drm_clip_rect *clips, - unsigned int num_clips, int inc); + unsigned int num_clips, int inc, + uint32_t dumb_shadow_offset);
void qxl_draw_fill(struct qxl_draw_fill *qxl_draw_fill_rec);
diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c index 472df00c02..a6110ec5ba 100644 --- a/drivers/gpu/drm/qxl/qxl_display.c +++ b/drivers/gpu/drm/qxl/qxl_display.c @@ -323,6 +323,8 @@ static void qxl_crtc_update_monitors_config(struct drm_crtc *crtc, head.y = crtc->y; if (qdev->monitors_config->count < i + 1) qdev->monitors_config->count = i + 1; + if (qdev->primary_bo == qdev->dumb_shadow_bo) + head.x += qdev->dumb_heads[i].x; } else if (i > 0) { head.width = 0; head.height = 0; @@ -424,7 +426,7 @@ static int qxl_framebuffer_surface_dirty(struct drm_framebuffer *fb, }
qxl_draw_dirty_fb(qdev, fb, qobj, flags, color, - clips, num_clips, inc); + clips, num_clips, inc, 0);
drm_modeset_unlock_all(fb->dev);
@@ -533,6 +535,7 @@ static void qxl_primary_atomic_update(struct drm_plane *plane, .x2 = plane->state->fb->width, .y2 = plane->state->fb->height }; + uint32_t dumb_shadow_offset = 0;
if (old_state->fb) { bo_old = gem_to_qxl_bo(old_state->fb->obj[0]); @@ -549,7 +552,12 @@ static void qxl_primary_atomic_update(struct drm_plane *plane, qxl_primary_apply_cursor(plane); }
- qxl_draw_dirty_fb(qdev, plane->state->fb, bo, 0, 0, &norect, 1, 1); + if (bo->is_dumb) + dumb_shadow_offset = + qdev->dumb_heads[plane->state->crtc->index].x; + + qxl_draw_dirty_fb(qdev, plane->state->fb, bo, 0, 0, &norect, 1, 1, + dumb_shadow_offset); }
static void qxl_primary_atomic_disable(struct drm_plane *plane, @@ -705,12 +713,68 @@ static void qxl_cursor_atomic_disable(struct drm_plane *plane, qxl_release_fence_buffer_objects(release); }
+static void qxl_update_dumb_head(struct qxl_device *qdev, + int index, struct qxl_bo *bo) +{ + uint32_t width, height; + + if (index >= qdev->monitors_config->max_allowed) + return; + + if (bo && bo->is_dumb) { + width = bo->surf.width; + height = bo->surf.height; + } else { + width = 0; + height = 0; + } + + if (qdev->dumb_heads[index].width == width && + qdev->dumb_heads[index].height == height) + return; + + DRM_DEBUG("#%d: %dx%d -> %dx%d\n", index, + qdev->dumb_heads[index].width, + qdev->dumb_heads[index].height, + width, height); + qdev->dumb_heads[index].width = width; + qdev->dumb_heads[index].height = height; +} + +static void qxl_calc_dumb_shadow(struct qxl_device *qdev, + struct qxl_surface *surf) +{ + struct qxl_head *head; + int i; + + memset(surf, 0, sizeof(*surf)); + for (i = 0; i < qdev->monitors_config->max_allowed; i++) { + head = qdev->dumb_heads + i; + head->x = surf->width; + surf->width += head->width; + if (surf->height < head->height) + surf->height = head->height; + } + if (surf->width < 64) + surf->width = 64; + if (surf->height < 64) + surf->height = 64; + surf->format = SPICE_SURFACE_FMT_32_xRGB; + surf->stride = surf->width * 4; + + if (!qdev->dumb_shadow_bo || + qdev->dumb_shadow_bo->surf.width != surf->width || + qdev->dumb_shadow_bo->surf.height != surf->height) + DRM_DEBUG("%dx%d\n", surf->width, surf->height); +} + static int qxl_plane_prepare_fb(struct drm_plane *plane, struct drm_plane_state *new_state) { struct qxl_device *qdev = plane->dev->dev_private; struct drm_gem_object *obj; - struct qxl_bo *user_bo, *old_bo = NULL; + struct qxl_bo *user_bo; + struct qxl_surface surf; int ret;
if (!new_state->fb) @@ -720,29 +784,31 @@ static int qxl_plane_prepare_fb(struct drm_plane *plane, user_bo = gem_to_qxl_bo(obj);
if (plane->type == DRM_PLANE_TYPE_PRIMARY && - user_bo->is_dumb && !user_bo->shadow) { - if (plane->state->fb) { - obj = plane->state->fb->obj[0]; - old_bo = gem_to_qxl_bo(obj); - } - if (old_bo && old_bo->shadow && - user_bo->gem_base.size == old_bo->gem_base.size && - plane->state->crtc == new_state->crtc && - plane->state->crtc_w == new_state->crtc_w && - plane->state->crtc_h == new_state->crtc_h && - plane->state->src_x == new_state->src_x && - plane->state->src_y == new_state->src_y && - plane->state->src_w == new_state->src_w && - plane->state->src_h == new_state->src_h && - plane->state->rotation == new_state->rotation && - plane->state->zpos == new_state->zpos) { - drm_gem_object_get(&old_bo->shadow->gem_base); - user_bo->shadow = old_bo->shadow; - } else { - qxl_bo_create(qdev, user_bo->gem_base.size, + user_bo->is_dumb) { + qxl_update_dumb_head(qdev, new_state->crtc->index, + user_bo); + qxl_calc_dumb_shadow(qdev, &surf); + if (!qdev->dumb_shadow_bo || + qdev->dumb_shadow_bo->surf.width != surf.width || + qdev->dumb_shadow_bo->surf.height != surf.height) { + if (qdev->dumb_shadow_bo) { + drm_gem_object_put_unlocked + (&qdev->dumb_shadow_bo->gem_base); + qdev->dumb_shadow_bo = NULL; + } + qxl_bo_create(qdev, surf.width * surf.stride, true, true, QXL_GEM_DOMAIN_VRAM, NULL, - &user_bo->shadow); - user_bo->shadow->surf = user_bo->surf; + &qdev->dumb_shadow_bo); + qdev->dumb_shadow_bo->surf = surf; + } + if (user_bo->shadow != qdev->dumb_shadow_bo) { + if (user_bo->shadow) { + drm_gem_object_put_unlocked + (&user_bo->shadow->gem_base); + user_bo->shadow = NULL; + } + drm_gem_object_get(&qdev->dumb_shadow_bo->gem_base); + user_bo->shadow = qdev->dumb_shadow_bo; } }
@@ -771,7 +837,7 @@ static void qxl_plane_cleanup_fb(struct drm_plane *plane, user_bo = gem_to_qxl_bo(obj); qxl_bo_unpin(user_bo);
- if (user_bo->shadow && !user_bo->shadow->is_primary) { + if (user_bo->shadow) { drm_gem_object_put_unlocked(&user_bo->shadow->gem_base); user_bo->shadow = NULL; } @@ -1105,6 +1171,8 @@ int qxl_create_monitors_object(struct qxl_device *qdev)
memset(qdev->monitors_config, 0, monitors_config_size); qdev->monitors_config->max_allowed = max_allowed; + + qdev->dumb_heads = kcalloc(max_allowed, sizeof(qdev->dumb_heads[0]), GFP_KERNEL); return 0; }
diff --git a/drivers/gpu/drm/qxl/qxl_draw.c b/drivers/gpu/drm/qxl/qxl_draw.c index c408bb83c7..5313ad21c1 100644 --- a/drivers/gpu/drm/qxl/qxl_draw.c +++ b/drivers/gpu/drm/qxl/qxl_draw.c @@ -267,7 +267,8 @@ void qxl_draw_dirty_fb(struct qxl_device *qdev, struct qxl_bo *bo, unsigned int flags, unsigned int color, struct drm_clip_rect *clips, - unsigned int num_clips, int inc) + unsigned int num_clips, int inc, + uint32_t dumb_shadow_offset) { /* * TODO: if flags & DRM_MODE_FB_DIRTY_ANNOTATE_FILL then we should @@ -295,6 +296,9 @@ void qxl_draw_dirty_fb(struct qxl_device *qdev, if (ret) return;
+ clips->x1 += dumb_shadow_offset; + clips->x2 += dumb_shadow_offset; + left = clips->x1; right = clips->x2; top = clips->y1; @@ -342,7 +346,8 @@ void qxl_draw_dirty_fb(struct qxl_device *qdev, goto out_release_backoff;
ret = qxl_image_init(qdev, release, dimage, surface_base, - left, top, width, height, depth, stride); + left - dumb_shadow_offset, + top, width, height, depth, stride); qxl_bo_kunmap(bo); if (ret) goto out_release_backoff;
Skip the pointless and slightly confusing indirection via qdev->monitors_config->max_allowed. Just use qxl_num_crtc instead.
Signed-off-by: Gerd Hoffmann kraxel@redhat.com --- drivers/gpu/drm/qxl/qxl_display.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-)
diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c index a6110ec5ba..731a17ba50 100644 --- a/drivers/gpu/drm/qxl/qxl_display.c +++ b/drivers/gpu/drm/qxl/qxl_display.c @@ -80,10 +80,10 @@ static int qxl_display_copy_rom_client_monitors_config(struct qxl_device *qdev) DRM_DEBUG_KMS("no client monitors configured\n"); return status; } - if (num_monitors > qdev->monitors_config->max_allowed) { + if (num_monitors > qxl_num_crtc) { DRM_DEBUG_KMS("client monitors list will be truncated: %d < %d\n", - qdev->monitors_config->max_allowed, num_monitors); - num_monitors = qdev->monitors_config->max_allowed; + qxl_num_crtc, num_monitors); + num_monitors = qxl_num_crtc; } else { num_monitors = qdev->rom->client_monitors_config.count; } @@ -96,8 +96,7 @@ static int qxl_display_copy_rom_client_monitors_config(struct qxl_device *qdev) return status; } /* we copy max from the client but it isn't used */ - qdev->client_monitors_config->max_allowed = - qdev->monitors_config->max_allowed; + qdev->client_monitors_config->max_allowed = qxl_num_crtc; for (i = 0 ; i < qdev->client_monitors_config->count ; ++i) { struct qxl_urect *c_rect = &qdev->rom->client_monitors_config.heads[i]; @@ -204,7 +203,7 @@ static int qxl_add_monitors_config_modes(struct drm_connector *connector,
if (!qdev->monitors_config) return 0; - if (h >= qdev->monitors_config->max_allowed) + if (h >= qxl_num_crtc) return 0; if (!qdev->client_monitors_config) return 0; @@ -307,8 +306,7 @@ static void qxl_crtc_update_monitors_config(struct drm_crtc *crtc, return; }
- if (!qdev->monitors_config || - qdev->monitors_config->max_allowed <= i) + if (!qdev->monitors_config || qxl_num_crtc <= i) return;
head.id = i; @@ -350,9 +348,10 @@ static void qxl_crtc_update_monitors_config(struct drm_crtc *crtc, if (oldcount != qdev->monitors_config->count) DRM_DEBUG_KMS("active heads %d -> %d (%d total)\n", oldcount, qdev->monitors_config->count, - qdev->monitors_config->max_allowed); + qxl_num_crtc);
qdev->monitors_config->heads[i] = head; + qdev->monitors_config->max_allowed = qxl_num_crtc; qxl_send_monitors_config(qdev); }
@@ -1146,9 +1145,8 @@ int qxl_create_monitors_object(struct qxl_device *qdev) { int ret; struct drm_gem_object *gobj; - int max_allowed = qxl_num_crtc; int monitors_config_size = sizeof(struct qxl_monitors_config) + - max_allowed * sizeof(struct qxl_head); + qxl_num_crtc * sizeof(struct qxl_head);
ret = qxl_gem_object_create(qdev, monitors_config_size, 0, QXL_GEM_DOMAIN_VRAM, @@ -1170,9 +1168,8 @@ int qxl_create_monitors_object(struct qxl_device *qdev) qxl_bo_physical_address(qdev, qdev->monitors_config_bo, 0);
memset(qdev->monitors_config, 0, monitors_config_size); - qdev->monitors_config->max_allowed = max_allowed; - - qdev->dumb_heads = kcalloc(max_allowed, sizeof(qdev->dumb_heads[0]), GFP_KERNEL); + qdev->dumb_heads = kcalloc(qxl_num_crtc, sizeof(qdev->dumb_heads[0]), + GFP_KERNEL); return 0; }
dri-devel@lists.freedesktop.org