summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2011-06-16 23:49:06 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2011-06-17 09:20:33 +0100
commit39f0b0ae17d00402971bb62555d3807bdf39ee93 (patch)
tree931909aa4da4e4f25e8514d44d41e6dabe75c57f
parent37ba33f502af0878f6cb75f890c9fe288d0f7e41 (diff)
sna: Copy the fbcon contents onto the front buffer upon X startup
This patch has been carried by the distributions every since they started doing graphical boot splashes. Time to integrate it and give it some TLC. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--src/sna/sna.h2
-rw-r--r--src/sna/sna_display.c76
-rw-r--r--src/sna/sna_driver.c2
3 files changed, 80 insertions, 0 deletions
diff --git a/src/sna/sna.h b/src/sna/sna.h
index d186f2cc..897fe74e 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -501,6 +501,8 @@ void sna_accel_close(struct sna *sna);
void sna_accel_free(struct sna *sna);
Bool sna_accel_create(struct sna *sna);
+void sna_copy_fbcon(struct sna *sna);
+
void sna_composite(CARD8 op,
PicturePtr src,
PicturePtr mask,
diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index e3f0e98f..bab64ea7 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -466,6 +466,82 @@ sna_crtc_dpms(xf86CrtcPtr crtc, int mode)
sna_crtc_restore(sna_crtc->sna);
}
+static struct kgem_bo *sna_create_bo_for_fbcon(struct sna *sna,
+ drmModeFBPtr fbcon)
+{
+ struct drm_gem_flink flink;
+ struct kgem_bo *bo;
+ int ret;
+
+ /* Create a new reference for the fbcon so that we can track it
+ * using a normal bo and so that when we call gem_close on it we
+ * delete our reference and not fbcon's!
+ */
+ memset(&flink, 0, sizeof(flink));
+ flink.handle = fbcon->handle;
+ ret = drmIoctl(sna->kgem.fd, DRM_IOCTL_GEM_FLINK, &flink);
+ if (ret)
+ return NULL;
+
+ bo = kgem_create_for_name(&sna->kgem, flink.name);
+ if (bo == NULL)
+ return NULL;
+
+ bo->pitch = fbcon->pitch;
+ return bo;
+}
+
+/* Copy the current framebuffer contents into the front-buffer for a seamless
+ * transition from e.g. plymouth.
+ */
+void sna_copy_fbcon(struct sna *sna)
+{
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(sna->scrn);
+ drmModeFBPtr fbcon;
+ struct kgem_bo *fbcon_bo;
+ BoxRec box;
+ int i;
+
+ /* Scan the connectors for a framebuffer and assume that is the fbcon */
+ fbcon = NULL;
+ for (i = 0; fbcon == NULL && i < xf86_config->num_crtc; i++) {
+ struct sna_crtc *crtc = xf86_config->crtc[i]->driver_private;
+ drmModeCrtcPtr mode_crtc;
+
+ mode_crtc = drmModeGetCrtc(sna->kgem.fd,
+ sna->mode.mode_res->crtcs[crtc->num]);
+ if (mode_crtc->buffer_id)
+ fbcon = drmModeGetFB(sna->kgem.fd,
+ mode_crtc->buffer_id);
+ drmModeFreeCrtc(mode_crtc);
+ }
+ if (fbcon == NULL)
+ return;
+
+ if (fbcon->depth != sna->front->drawable.depth)
+ goto cleanup_fbcon;
+
+ box.x1 = box.y1 = 0;
+ box.x2 = fbcon->width;
+ box.y2 = fbcon->height;
+
+ fbcon_bo = sna_create_bo_for_fbcon(sna, fbcon);
+ if (fbcon_bo == NULL)
+ goto cleanup_fbcon;
+
+ sna->render.copy_boxes(sna, GXcopy,
+ sna->front, fbcon_bo, 0, 0,
+ sna->front, sna_pixmap_get_bo(sna->front),
+ (sna->front->drawable.width - fbcon->width)/2,
+ (sna->front->drawable.height - fbcon->height)/2,
+ &box, 1);
+
+ kgem_bo_destroy(&sna->kgem, fbcon_bo);
+
+cleanup_fbcon:
+ drmModeFreeFB(fbcon);
+}
+
static Bool
sna_crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
Rotation rotation, int x, int y)
diff --git a/src/sna/sna_driver.c b/src/sna/sna_driver.c
index 99701771..ee7a8aeb 100644
--- a/src/sna/sna_driver.c
+++ b/src/sna/sna_driver.c
@@ -200,6 +200,8 @@ static Bool sna_create_screen_resources(ScreenPtr screen)
if (!sna_accel_create(sna))
goto cleanup_front;
+ sna_copy_fbcon(sna);
+
if (!sna_enter_vt(screen->myNum, 0))
goto cleanup_front;