summaryrefslogtreecommitdiff
path: root/src/sna/kgem.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/sna/kgem.c')
-rw-r--r--src/sna/kgem.c83
1 files changed, 48 insertions, 35 deletions
diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index e90959fa..45a2572d 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -4400,7 +4400,7 @@ struct kgem_bo *kgem_create_2d(struct kgem *kgem,
bucket = cache_bucket(size);
if (flags & CREATE_SCANOUT) {
- struct kgem_bo *last = NULL, *first = NULL;
+ struct kgem_bo *last = NULL;
list_for_each_entry_reverse(bo, &kgem->scanout, list) {
assert(bo->scanout);
@@ -4414,11 +4414,8 @@ struct kgem_bo *kgem_create_2d(struct kgem *kgem,
/* No tiling/pitch without recreating fb */
continue;
- if (bo->delta && !check_scanout_size(kgem, bo, width, height)) {
- if (first == NULL)
- first = bo;
+ if (bo->delta && !check_scanout_size(kgem, bo, width, height))
continue;
- }
if (flags & CREATE_INACTIVE && bo->rq) {
last = bo;
@@ -4448,44 +4445,60 @@ struct kgem_bo *kgem_create_2d(struct kgem *kgem,
return last;
}
- if (first) {
- ScrnInfoPtr scrn =
- container_of(kgem, struct sna, kgem)->scrn;
+ if (container_of(kgem, struct sna, kgem)->scrn->vtSema) {
+ ScrnInfoPtr scrn = container_of(kgem, struct sna, kgem)->scrn;
- if (scrn->vtSema) {
- DBG(("%s: recreate fb %dx%d@%d/%d\n",
- __FUNCTION__, width, height, scrn->depth, scrn->bitsPerPixel));
+ list_for_each_entry_reverse(bo, &kgem->scanout, list) {
+ struct drm_mode_fb_cmd arg;
- if (first->tiling != tiling ||
- (tiling != I915_TILING_NONE && first->pitch != pitch)) {
- if (gem_set_tiling(kgem->fd, first->handle,
- tiling, pitch)) {
- first->tiling = tiling;
- first->pitch = pitch;
- }
- }
+ assert(bo->scanout);
- if (first->tiling == tiling && first->pitch == pitch) {
- struct drm_mode_fb_cmd arg;
+ if (size > num_pages(bo) || num_pages(bo) > 2*size)
+ continue;
- VG_CLEAR(arg);
- arg.width = width;
- arg.height = height;
- arg.pitch = first->pitch;
- arg.bpp = scrn->bitsPerPixel;
- arg.depth = scrn->depth;
- arg.handle = first->handle;
+ if (flags & CREATE_INACTIVE && bo->rq)
+ continue;
- kgem_bo_rmfb(kgem, first);
- if (do_ioctl(kgem->fd, DRM_IOCTL_MODE_ADDFB, &arg)) {
- kgem_bo_free(kgem, first);
+ list_del(&bo->list);
+
+ if (bo->tiling != tiling || bo->pitch != pitch) {
+ if (bo->delta) {
+ kgem_bo_rmfb(kgem, bo);
+ bo->delta = 0;
+ }
+
+ if (gem_set_tiling(kgem->fd, bo->handle,
+ tiling, pitch)) {
+ bo->tiling = tiling;
+ bo->pitch = pitch;
} else {
- DBG(("%s: attached fb=%d to handle=%d\n",
- __FUNCTION__, arg.fb_id, arg.handle));
- first->delta = arg.fb_id;
- return first;
+ kgem_bo_free(kgem, bo);
+ break;
}
}
+
+ VG_CLEAR(arg);
+ arg.width = width;
+ arg.height = height;
+ arg.pitch = bo->pitch;
+ arg.bpp = scrn->bitsPerPixel;
+ arg.depth = scrn->depth;
+ arg.handle = bo->handle;
+
+ if (do_ioctl(kgem->fd, DRM_IOCTL_MODE_ADDFB, &arg)) {
+ kgem_bo_free(kgem, bo);
+ break;
+ }
+
+ bo->delta = arg.fb_id;
+ bo->unique_id = kgem_get_unique_id(kgem);
+
+ DBG((" 2:from scanout: pitch=%d, tiling=%d, handle=%d, id=%d\n",
+ bo->pitch, bo->tiling, bo->handle, bo->unique_id));
+ assert(bo->pitch*kgem_aligned_height(kgem, height, bo->tiling) <= kgem_bo_size(bo));
+ assert_tiling(kgem, bo);
+ bo->refcnt = 1;
+ return bo;
}
}