[PATCH 2/2] compositor-drm: don't create and destroy kms fbs on every frame
Ander Conselvan de Oliveira
ander.conselvan.de.oliveira at intel.com
Mon Apr 30 03:31:29 PDT 2012
Use the new gbm_get/set_user_data() to reuse the kms fbs if the gbm
surface's bo's are reused.
---
src/compositor-drm.c | 94 +++++++++++++++++++++++++++++++++++++++----------
1 files changed, 75 insertions(+), 19 deletions(-)
diff --git a/src/compositor-drm.c b/src/compositor-drm.c
index e7433f7..e9b556c 100644
--- a/src/compositor-drm.c
+++ b/src/compositor-drm.c
@@ -199,12 +199,51 @@ drm_output_prepare_scanout_surface(struct drm_output *output)
return 0;
}
+struct bo_user_data {
+ uint32_t fb_id;
+};
+
+static void
+bo_set_fb_id(struct gbm_bo *bo, uint32_t fb_id)
+{
+ struct bo_user_data *user_data= gbm_bo_get_user_data(bo);
+
+ if (!user_data)
+ return;
+
+ user_data->fb_id = fb_id;
+}
+
+static uint32_t
+bo_get_fb_id(struct gbm_bo *bo)
+{
+ struct bo_user_data *user_data= gbm_bo_get_user_data(bo);
+
+ if (user_data)
+ return user_data->fb_id;
+ else
+ return 0;
+}
+
+static void
+bo_free_user_data(struct gbm_bo *bo, void *data)
+{
+ struct gbm_device *gbm = gbm_bo_get_device(bo);
+ struct bo_user_data *user_data = data;
+
+ if (user_data->fb_id)
+ drmModeRmFB(gbm_device_get_fd(gbm), user_data->fb_id);
+
+ free(data);
+}
+
static void
drm_output_render(struct drm_output *output, pixman_region32_t *damage)
{
struct drm_compositor *compositor =
(struct drm_compositor *) output->base.compositor;
struct weston_surface *surface;
+ struct bo_user_data *data;
if (!eglMakeCurrent(compositor->base.display, output->egl_surface,
output->egl_surface, compositor->base.context)) {
@@ -223,6 +262,15 @@ drm_output_render(struct drm_output *output, pixman_region32_t *damage)
fprintf(stderr, "failed to lock front buffer: %m\n");
return;
}
+
+ data = calloc(1, sizeof *data);
+ if (!data) {
+ gbm_surface_release_buffer(output->surface, output->next_bo);
+ output->next_bo = NULL;
+ return;
+ }
+
+ gbm_bo_set_user_data(output->next_bo, data, bo_free_user_data);
}
static void
@@ -241,6 +289,8 @@ drm_output_repaint(struct weston_output *output_base,
if (!output->next_bo)
drm_output_render(output, damage);
+ output->next_fb_id = bo_get_fb_id(output->next_bo);
+
stride = gbm_bo_get_pitch(output->next_bo);
handle = gbm_bo_get_handle(output->next_bo).u32;
@@ -252,15 +302,20 @@ drm_output_repaint(struct weston_output *output_base,
output->next_bo = NULL;
}
- ret = drmModeAddFB(compositor->drm.fd,
- output->base.current->width,
- output->base.current->height,
- 24, 32, stride, handle, &output->next_fb_id);
- if (ret) {
- fprintf(stderr, "failed to create kms fb: %m\n");
- gbm_surface_release_buffer(output->surface, output->next_bo);
- output->next_bo = NULL;
- return;
+ if (!output->next_fb_id) {
+ ret = drmModeAddFB(compositor->drm.fd,
+ output->base.current->width,
+ output->base.current->height,
+ 24, 32, stride, handle, &output->next_fb_id);
+ if (ret) {
+ fprintf(stderr, "failed to create kms fb: %m\n");
+ gbm_surface_release_buffer(output->surface, output->next_bo);
+ output->next_bo = NULL;
+ return;
+ }
+
+ if (output->next_bo)
+ bo_set_fb_id(output->next_bo, output->next_fb_id);
}
mode = container_of(output->base.current, struct drm_mode, base);
@@ -355,22 +410,23 @@ page_flip_handler(int fd, unsigned int frame,
(struct drm_compositor *) output->base.compositor;
uint32_t msecs;
- if (output->current_fb_id)
- drmModeRmFB(c->drm.fd, output->current_fb_id);
- output->current_fb_id = output->next_fb_id;
- output->next_fb_id = 0;
-
- if (output->scanout_buffer) {
- weston_buffer_post_release(output->scanout_buffer);
- wl_list_remove(&output->scanout_buffer_destroy_listener.link);
- output->scanout_buffer = NULL;
- } else if (output->current_bo) {
+ if (output->current_bo) {
gbm_surface_release_buffer(output->surface,
output->current_bo);
+ } else {
+ if (output->scanout_buffer) {
+ weston_buffer_post_release(output->scanout_buffer);
+ wl_list_remove(&output->scanout_buffer_destroy_listener.link);
+ output->scanout_buffer = NULL;
+ }
+ if (output->current_fb_id)
+ drmModeRmFB(c->drm.fd, output->current_fb_id);
}
output->current_bo = output->next_bo;
output->next_bo = NULL;
+ output->current_fb_id = output->next_fb_id;
+ output->next_fb_id = 0;
if (output->pending_scanout_buffer) {
output->scanout_buffer = output->pending_scanout_buffer;
--
1.7.4.1
More information about the wayland-devel
mailing list