[PATCH] compositor-drm: render to a gbm_surface instead of renderbuffers
Ander Conselvan de Oliveira
ander.conselvan.de.oliveira at intel.com
Wed Jan 25 06:28:08 PST 2012
Signed-off-by: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira at intel.com>
---
src/compositor-drm.c | 233 ++++++++++++++++++++++++++-----------------------
1 files changed, 124 insertions(+), 109 deletions(-)
diff --git a/src/compositor-drm.c b/src/compositor-drm.c
index 1f30e7b..05dfcdd 100644
--- a/src/compositor-drm.c
+++ b/src/compositor-drm.c
@@ -68,28 +68,25 @@ struct drm_output {
uint32_t crtc_id;
uint32_t connector_id;
drmModeCrtcPtr original_crtc;
- GLuint rbo[2];
- uint32_t fb_id[2];
- EGLImageKHR image[2];
- struct gbm_bo *bo[2];
- uint32_t current;
-
- uint32_t fs_surf_fb_id;
- uint32_t pending_fs_surf_fb_id;
+ struct gbm_surface *surface;
+ EGLSurface egl_surface;
+ uint32_t current_fb_id;
+ uint32_t next_fb_id;
+ struct gbm_bo *current_bo;
+ struct gbm_bo *next_bo;
};
static int
drm_output_prepare_render(struct weston_output *output_base)
{
struct drm_output *output = (struct drm_output *) output_base;
+ struct weston_compositor *ec = output->base.compositor;
- glFramebufferRenderbuffer(GL_FRAMEBUFFER,
- GL_COLOR_ATTACHMENT0,
- GL_RENDERBUFFER,
- output->rbo[output->current]);
-
- if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
+ if (!eglMakeCurrent(ec->display, output->egl_surface,
+ output->egl_surface, ec->context)) {
+ fprintf(stderr, "failed to make current\n");
return -1;
+ }
return 0;
}
@@ -100,20 +97,37 @@ drm_output_present(struct weston_output *output_base)
struct drm_output *output = (struct drm_output *) output_base;
struct drm_compositor *c =
(struct drm_compositor *) output->base.compositor;
- uint32_t fb_id = 0;
+ EGLint handle, stride;
+ int ret;
+
+ if (output->next_fb_id == 0) {
+ if (drm_output_prepare_render(output_base))
+ return -1;
- glFlush();
+ eglSwapBuffers(c->base.display, output->egl_surface);
+ output->next_bo =
+ gbm_surface_lock_front_buffer(output->surface);
- output->current ^= 1;
+ if (!output->next_bo)
+ return -1;
- if (output->pending_fs_surf_fb_id != 0) {
- fb_id = output->pending_fs_surf_fb_id;
- } else {
- fb_id = output->fb_id[output->current ^ 1];
+ stride = gbm_bo_get_pitch(output->next_bo);
+ handle = gbm_bo_get_handle(output->next_bo).u32;
+
+ ret = drmModeAddFB(c->drm.fd,
+ output->base.current->width,
+ output->base.current->height,
+ 24, 32, stride, handle, &output->next_fb_id);
+ if (ret) {
+ gbm_surface_release_buffer(output->surface,
+ output->next_bo);
+ output->next_bo = NULL;
+ return ret;
+ }
}
if (drmModePageFlip(c->drm.fd, output->crtc_id,
- fb_id,
+ output->next_fb_id,
DRM_MODE_PAGE_FLIP_EVENT, output) < 0) {
fprintf(stderr, "queueing pageflip failed: %m\n");
return -1;
@@ -131,14 +145,21 @@ page_flip_handler(int fd, unsigned int frame,
(struct drm_compositor *) output->base.compositor;
uint32_t msecs;
- if (output->fs_surf_fb_id) {
- drmModeRmFB(c->drm.fd, output->fs_surf_fb_id);
- output->fs_surf_fb_id = 0;
+ drmModeRmFB(c->drm.fd, output->current_fb_id);
+ output->current_fb_id = 0;
+
+ output->current_fb_id = output->next_fb_id;
+ output->next_fb_id = 0;
+
+ if (output->current_bo) {
+ gbm_surface_release_buffer(output->surface,
+ output->current_bo);
+ output->current_bo = NULL;
}
- if (output->pending_fs_surf_fb_id) {
- output->fs_surf_fb_id = output->pending_fs_surf_fb_id;
- output->pending_fs_surf_fb_id = 0;
+ if (output->next_bo) {
+ output->current_bo = output->next_bo;
+ output->next_bo = NULL;
}
msecs = sec * 1000 + usec / 1000;
@@ -185,7 +206,7 @@ drm_output_prepare_scanout_surface(struct weston_output *output_base,
if (ret)
return -1;
- output->pending_fs_surf_fb_id = fb_id;
+ output->next_fb_id = fb_id;
return 0;
}
@@ -270,7 +291,6 @@ drm_output_destroy(struct weston_output *output_base)
struct drm_compositor *c =
(struct drm_compositor *) output->base.compositor;
drmModeCrtcPtr origcrtc = output->original_crtc;
- int i;
/* Turn off hardware cursor */
drm_output_set_cursor(&output->base, NULL);
@@ -281,24 +301,12 @@ drm_output_destroy(struct weston_output *output_base)
&output->connector_id, 1, &origcrtc->mode);
drmModeFreeCrtc(origcrtc);
- glFramebufferRenderbuffer(GL_FRAMEBUFFER,
- GL_COLOR_ATTACHMENT0,
- GL_RENDERBUFFER,
- 0);
-
- glBindRenderbuffer(GL_RENDERBUFFER, 0);
- glDeleteRenderbuffers(2, output->rbo);
-
- /* Destroy output buffers */
- for (i = 0; i < 2; i++) {
- drmModeRmFB(c->drm.fd, output->fb_id[i]);
- c->base.destroy_image(c->base.display, output->image[i]);
- gbm_bo_destroy(output->bo[i]);
- }
-
c->crtc_allocator &= ~(1 << output->crtc_id);
c->connector_allocator &= ~(1 << output->connector_id);
+ eglDestroySurface(c->base.display, output->egl_surface);
+ gbm_surface_destroy(output->surface);
+
weston_output_destroy(&output->base);
wl_list_remove(&output->base.link);
@@ -321,7 +329,7 @@ on_drm_input(int fd, uint32_t mask, void *data)
static int
init_egl(struct drm_compositor *ec, struct udev_device *device)
{
- EGLint major, minor;
+ EGLint major, minor, n;
const char *extensions, *filename;
int fd;
static const EGLint context_attribs[] = {
@@ -329,6 +337,17 @@ init_egl(struct drm_compositor *ec, struct udev_device *device)
EGL_NONE
};
+ static const EGLint config_attribs[] = {
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+ EGL_RED_SIZE, 1,
+ EGL_GREEN_SIZE, 1,
+ EGL_BLUE_SIZE, 1,
+ EGL_ALPHA_SIZE, 0,
+ EGL_DEPTH_SIZE, 1,
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL_NONE
+ };
+
filename = udev_device_get_devnode(device);
fd = open(filename, O_RDWR | O_CLOEXEC);
if (fd < 0) {
@@ -362,7 +381,13 @@ init_egl(struct drm_compositor *ec, struct udev_device *device)
return -1;
}
- ec->base.context = eglCreateContext(ec->base.display, NULL,
+ if (!eglChooseConfig(ec->base.display, config_attribs,
+ &ec->base.config, 1, &n) || n != 1) {
+ fprintf(stderr, "failed to choose config: %d\n", n);
+ return -1;
+ }
+
+ ec->base.context = eglCreateContext(ec->base.display, ec->base.config,
EGL_NO_CONTEXT, context_attribs);
if (ec->base.context == NULL) {
fprintf(stderr, "failed to create context\n");
@@ -462,8 +487,6 @@ create_output_for_connector(struct drm_compositor *ec,
drmModeFreeEncoder(encoder);
return -1;
}
- output->fb_id[0] = -1;
- output->fb_id[1] = -1;
memset(output, 0, sizeof *output);
output->base.subpixel = drm_subpixel_to_wayland(connector->subpixel);
@@ -497,49 +520,52 @@ create_output_for_connector(struct drm_compositor *ec,
drm_mode->base.flags =
WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
- glGenRenderbuffers(2, output->rbo);
- for (i = 0; i < 2; i++) {
- glBindRenderbuffer(GL_RENDERBUFFER, output->rbo[i]);
-
- output->bo[i] =
- gbm_bo_create(ec->gbm,
- output->base.current->width,
- output->base.current->height,
- GBM_BO_FORMAT_XRGB8888,
- GBM_BO_USE_SCANOUT |
- GBM_BO_USE_RENDERING);
- if (!output->bo[i])
- goto err_bufs;
-
- output->image[i] = ec->base.create_image(ec->base.display,
- NULL,
- EGL_NATIVE_PIXMAP_KHR,
- output->bo[i], NULL);
- if (!output->image[i])
- goto err_bufs;
-
- ec->base.image_target_renderbuffer_storage(GL_RENDERBUFFER,
- output->image[i]);
- stride = gbm_bo_get_pitch(output->bo[i]);
- handle = gbm_bo_get_handle(output->bo[i]).u32;
-
- ret = drmModeAddFB(ec->drm.fd,
+ output->surface =
+ gbm_surface_create(ec->gbm,
output->base.current->width,
output->base.current->height,
- 24, 32, stride, handle, &output->fb_id[i]);
- if (ret) {
- fprintf(stderr, "failed to add fb %d: %m\n", i);
- goto err_bufs;
- }
+ GBM_BO_FORMAT_XRGB8888);
+ if (!output->surface) {
+ fprintf(stderr, "failed to create gbm surface\n");
+ return -1;
+ }
+
+ output->egl_surface =
+ eglCreateWindowSurface(ec->base.display, ec->base.config,
+ output->surface, NULL);
+
+ if (output->egl_surface == EGL_NO_SURFACE) {
+ fprintf(stderr, "failed to create egl surface\n");
+ goto err_surface;
+ }
+
+ if (!eglMakeCurrent(ec->base.display, output->egl_surface,
+ output->egl_surface, ec->base.context)) {
+ fprintf(stderr, "failed to make surface current\n");
+ goto err_egl_surface;
+ }
+
+ output->current_bo = gbm_surface_lock_front_buffer(output->surface);
+
+ if (!output->current_bo) {
+ fprintf(stderr, "failed to get surface bo\n");
+ goto err_egl_surface;
+ }
+
+ stride = gbm_bo_get_pitch(output->current_bo);
+ handle = gbm_bo_get_handle(output->current_bo).u32;
+
+ ret = drmModeAddFB(ec->drm.fd,
+ output->base.current->width,
+ output->base.current->height,
+ 24, 32, stride, handle, &output->current_fb_id);
+ if (ret) {
+ fprintf(stderr, "failed to add fb %d: %m\n", i);
+ goto err_bo;
}
- output->current = 0;
- glFramebufferRenderbuffer(GL_FRAMEBUFFER,
- GL_COLOR_ATTACHMENT0,
- GL_RENDERBUFFER,
- output->rbo[output->current]);
ret = drmModeSetCrtc(ec->drm.fd, output->crtc_id,
- output->fb_id[output->current ^ 1], 0, 0,
+ output->current_fb_id, 0, 0,
&output->connector_id, 1,
&drm_mode->mode_info);
if (ret) {
@@ -548,11 +574,12 @@ create_output_for_connector(struct drm_compositor *ec,
}
weston_output_init(&output->base, &ec->base, x, y,
- connector->mmWidth, connector->mmHeight, 0);
+ connector->mmWidth, connector->mmHeight,
+ WL_OUTPUT_FLIPPED);
wl_list_insert(ec->base.output_list.prev, &output->base.link);
- output->pending_fs_surf_fb_id = 0;
+ output->next_fb_id = 0;
output->base.prepare_render = drm_output_prepare_render;
output->base.present = drm_output_present;
output->base.prepare_scanout_surface =
@@ -563,22 +590,13 @@ create_output_for_connector(struct drm_compositor *ec,
return 0;
err_fb:
- glFramebufferRenderbuffer(GL_FRAMEBUFFER,
- GL_COLOR_ATTACHMENT0,
- GL_RENDERBUFFER,
- 0);
-err_bufs:
- for (i = 0; i < 2; i++) {
- if (output->fb_id[i] != -1)
- drmModeRmFB(ec->drm.fd, output->fb_id[i]);
- if (output->image[i])
- ec->base.destroy_image(ec->base.display,
- output->image[i]);
- if (output->bo[i])
- gbm_bo_destroy(output->bo[i]);
- }
- glBindRenderbuffer(GL_RENDERBUFFER, 0);
- glDeleteRenderbuffers(2, output->rbo);
+ drmModeRmFB(ec->drm.fd, output->current_fb_id);
+err_bo:
+ gbm_surface_release_buffer(output->surface, output->current_bo);
+err_egl_surface:
+ eglDestroySurface(ec->base.display, output->egl_surface);
+err_surface:
+ gbm_surface_destroy(output->surface);
err_free:
wl_list_for_each_safe(drm_mode, next, &output->base.mode_list,
base.link) {
@@ -801,7 +819,7 @@ drm_compositor_set_modes(struct drm_compositor *compositor)
wl_list_for_each(output, &compositor->base.output_list, base.link) {
drm_mode = (struct drm_mode *) output->base.current;
ret = drmModeSetCrtc(compositor->drm.fd, output->crtc_id,
- output->fb_id[output->current ^ 1], 0, 0,
+ output->current_fb_id, 0, 0,
&output->connector_id, 1,
&drm_mode->mode_info);
if (ret < 0) {
@@ -932,9 +950,6 @@ drm_compositor_create(struct wl_display *display,
ec->prev_state = WESTON_COMPOSITOR_ACTIVE;
- glGenFramebuffers(1, &ec->base.fbo);
- glBindFramebuffer(GL_FRAMEBUFFER, ec->base.fbo);
-
/* Can't init base class until we have a current egl context */
if (weston_compositor_init(&ec->base, display) < 0)
return NULL;
--
1.7.4.1
More information about the wayland-devel
mailing list