2010-06-11 20:56:24 +04:00
|
|
|
/*
|
Change remaining GPLv2 headers to MIT
The files in question are copyright Benjamin Franzke (who agrees),
Intel Corporation, Red Hat and myself. On behalf of Red Hat,
Richard Fontana says:
"Therefore, to the extent that Red Hat, Inc. has any copyright
interest in the files you cited as of this date (compositor-drm.c,
compositor.c, compositor.h, screenshooter.c in
http://cgit.freedesktop.org/wayland/wayland-demos/tree/compositor),
Red Hat hereby elects to apply the CC0 1.0 Universal Public Domain
Dedication to such copyrighted material. See:
http://creativecommons.org/publicdomain/zero/1.0/legalcode .
Thanks,
Richard E. Fontana
Open Source Licensing and Patent Counsel
Red Hat, Inc."
2011-09-15 23:43:14 +04:00
|
|
|
* Copyright © 2008-2011 Kristian Høgsberg
|
|
|
|
* Copyright © 2011 Intel Corporation
|
2010-06-11 20:56:24 +04:00
|
|
|
*
|
Change remaining GPLv2 headers to MIT
The files in question are copyright Benjamin Franzke (who agrees),
Intel Corporation, Red Hat and myself. On behalf of Red Hat,
Richard Fontana says:
"Therefore, to the extent that Red Hat, Inc. has any copyright
interest in the files you cited as of this date (compositor-drm.c,
compositor.c, compositor.h, screenshooter.c in
http://cgit.freedesktop.org/wayland/wayland-demos/tree/compositor),
Red Hat hereby elects to apply the CC0 1.0 Universal Public Domain
Dedication to such copyrighted material. See:
http://creativecommons.org/publicdomain/zero/1.0/legalcode .
Thanks,
Richard E. Fontana
Open Source Licensing and Patent Counsel
Red Hat, Inc."
2011-09-15 23:43:14 +04:00
|
|
|
* Permission to use, copy, modify, distribute, and sell this software and
|
|
|
|
* its documentation for any purpose is hereby granted without fee, provided
|
|
|
|
* that the above copyright notice appear in all copies and that both that
|
|
|
|
* copyright notice and this permission notice appear in supporting
|
|
|
|
* documentation, and that the name of the copyright holders not be used in
|
|
|
|
* advertising or publicity pertaining to distribution of the software
|
|
|
|
* without specific, written prior permission. The copyright holders make
|
|
|
|
* no representations about the suitability of this software for any
|
|
|
|
* purpose. It is provided "as is" without express or implied warranty.
|
2010-06-11 20:56:24 +04:00
|
|
|
*
|
Change remaining GPLv2 headers to MIT
The files in question are copyright Benjamin Franzke (who agrees),
Intel Corporation, Red Hat and myself. On behalf of Red Hat,
Richard Fontana says:
"Therefore, to the extent that Red Hat, Inc. has any copyright
interest in the files you cited as of this date (compositor-drm.c,
compositor.c, compositor.h, screenshooter.c in
http://cgit.freedesktop.org/wayland/wayland-demos/tree/compositor),
Red Hat hereby elects to apply the CC0 1.0 Universal Public Domain
Dedication to such copyrighted material. See:
http://creativecommons.org/publicdomain/zero/1.0/legalcode .
Thanks,
Richard E. Fontana
Open Source Licensing and Patent Counsel
Red Hat, Inc."
2011-09-15 23:43:14 +04:00
|
|
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
|
|
|
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
|
|
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
|
|
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
|
|
|
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
|
|
|
|
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
|
|
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
2010-06-11 20:56:24 +04:00
|
|
|
*/
|
|
|
|
|
2011-04-12 19:34:32 +04:00
|
|
|
#define _GNU_SOURCE
|
|
|
|
|
2012-02-23 18:45:49 +04:00
|
|
|
#include <errno.h>
|
2010-06-11 20:56:24 +04:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
2011-03-02 13:56:04 +03:00
|
|
|
#include <xf86drm.h>
|
|
|
|
#include <xf86drmMode.h>
|
2012-02-23 18:45:49 +04:00
|
|
|
#include <drm_fourcc.h>
|
2011-03-02 13:56:04 +03:00
|
|
|
|
2011-04-30 11:32:11 +04:00
|
|
|
#include <gbm.h>
|
2012-02-29 21:53:50 +04:00
|
|
|
#include <libbacklight.h>
|
2011-04-30 11:32:11 +04:00
|
|
|
|
2010-06-11 20:56:24 +04:00
|
|
|
#include "compositor.h"
|
2011-12-19 03:14:03 +04:00
|
|
|
#include "evdev.h"
|
2010-06-11 20:56:24 +04:00
|
|
|
|
2010-06-14 19:54:00 +04:00
|
|
|
struct drm_compositor {
|
Rename wayland-compositor to weston
This rename addresses a few problems around the split between core
Wayland and the wayland-demos repository.
1) Initially, we had one big repository with protocol code, sample
compositor and sample clients. We split that repository to make it
possible to implement the protocol without pulling in the sample/demo
code. At this point, the compositor is more than just a "demo" and
wayland-demos doesn't send the right message. The sample compositor
is a useful, self-contained project in it's own right, and we want to
move away from the "demos" label.
2) Another problem is that the wayland-demos compositor is often
called "the wayland compsitor", but it's really just one possible
compositor. Existing X11 compositors are expected to add Wayland
support and then gradually phase out/modularize the X11 support, for
example. Conversely, it's hard to talk about the wayland-demos
compositor specifically as opposed to, eg, the wayland protocol or a
wayland compositor in general.
We are also renaming the repo to weston, and the compositor
subdirectory to src/, to emphasize that the main "output" is the
compositor.
2012-01-03 19:29:47 +04:00
|
|
|
struct weston_compositor base;
|
2010-06-14 19:54:00 +04:00
|
|
|
|
|
|
|
struct udev *udev;
|
|
|
|
struct wl_event_source *drm_source;
|
|
|
|
|
2011-03-15 17:08:41 +03:00
|
|
|
struct udev_monitor *udev_monitor;
|
|
|
|
struct wl_event_source *udev_drm_source;
|
|
|
|
|
2011-03-02 13:14:59 +03:00
|
|
|
struct {
|
|
|
|
int fd;
|
|
|
|
} drm;
|
2011-04-30 11:32:11 +04:00
|
|
|
struct gbm_device *gbm;
|
2012-02-23 18:45:49 +04:00
|
|
|
uint32_t *crtcs;
|
|
|
|
int num_crtcs;
|
2011-02-10 03:01:42 +03:00
|
|
|
uint32_t crtc_allocator;
|
2011-03-15 17:08:41 +03:00
|
|
|
uint32_t connector_allocator;
|
2011-01-14 22:59:13 +03:00
|
|
|
struct tty *tty;
|
2011-12-02 15:07:27 +04:00
|
|
|
|
2012-02-23 18:45:49 +04:00
|
|
|
struct wl_list sprite_list;
|
|
|
|
|
2011-12-02 15:07:27 +04:00
|
|
|
uint32_t prev_state;
|
2010-06-14 19:54:00 +04:00
|
|
|
};
|
|
|
|
|
2011-06-21 19:16:58 +04:00
|
|
|
struct drm_mode {
|
Rename wayland-compositor to weston
This rename addresses a few problems around the split between core
Wayland and the wayland-demos repository.
1) Initially, we had one big repository with protocol code, sample
compositor and sample clients. We split that repository to make it
possible to implement the protocol without pulling in the sample/demo
code. At this point, the compositor is more than just a "demo" and
wayland-demos doesn't send the right message. The sample compositor
is a useful, self-contained project in it's own right, and we want to
move away from the "demos" label.
2) Another problem is that the wayland-demos compositor is often
called "the wayland compsitor", but it's really just one possible
compositor. Existing X11 compositors are expected to add Wayland
support and then gradually phase out/modularize the X11 support, for
example. Conversely, it's hard to talk about the wayland-demos
compositor specifically as opposed to, eg, the wayland protocol or a
wayland compositor in general.
We are also renaming the repo to weston, and the compositor
subdirectory to src/, to emphasize that the main "output" is the
compositor.
2012-01-03 19:29:47 +04:00
|
|
|
struct weston_mode base;
|
2011-06-21 19:16:58 +04:00
|
|
|
drmModeModeInfo mode_info;
|
|
|
|
};
|
|
|
|
|
2010-06-14 19:54:00 +04:00
|
|
|
struct drm_output {
|
Rename wayland-compositor to weston
This rename addresses a few problems around the split between core
Wayland and the wayland-demos repository.
1) Initially, we had one big repository with protocol code, sample
compositor and sample clients. We split that repository to make it
possible to implement the protocol without pulling in the sample/demo
code. At this point, the compositor is more than just a "demo" and
wayland-demos doesn't send the right message. The sample compositor
is a useful, self-contained project in it's own right, and we want to
move away from the "demos" label.
2) Another problem is that the wayland-demos compositor is often
called "the wayland compsitor", but it's really just one possible
compositor. Existing X11 compositors are expected to add Wayland
support and then gradually phase out/modularize the X11 support, for
example. Conversely, it's hard to talk about the wayland-demos
compositor specifically as opposed to, eg, the wayland protocol or a
wayland compositor in general.
We are also renaming the repo to weston, and the compositor
subdirectory to src/, to emphasize that the main "output" is the
compositor.
2012-01-03 19:29:47 +04:00
|
|
|
struct weston_output base;
|
2010-06-14 19:54:00 +04:00
|
|
|
|
|
|
|
uint32_t crtc_id;
|
|
|
|
uint32_t connector_id;
|
2011-08-30 00:52:23 +04:00
|
|
|
drmModeCrtcPtr original_crtc;
|
2010-06-14 19:54:00 +04:00
|
|
|
GLuint rbo[2];
|
|
|
|
uint32_t fb_id[2];
|
|
|
|
EGLImageKHR image[2];
|
2011-04-30 11:32:11 +04:00
|
|
|
struct gbm_bo *bo[2];
|
2010-06-14 19:54:00 +04:00
|
|
|
uint32_t current;
|
2011-04-10 18:49:52 +04:00
|
|
|
|
|
|
|
uint32_t fs_surf_fb_id;
|
|
|
|
uint32_t pending_fs_surf_fb_id;
|
2012-01-26 09:11:01 +04:00
|
|
|
struct wl_buffer *scanout_buffer;
|
|
|
|
struct wl_listener scanout_buffer_destroy_listener;
|
|
|
|
struct wl_buffer *pending_scanout_buffer;
|
|
|
|
struct wl_listener pending_scanout_buffer_destroy_listener;
|
2012-02-29 21:53:50 +04:00
|
|
|
struct backlight *backlight;
|
2010-06-14 19:54:00 +04:00
|
|
|
};
|
|
|
|
|
2012-02-23 18:45:49 +04:00
|
|
|
/*
|
|
|
|
* An output has a primary display plane plus zero or more sprites for
|
|
|
|
* blending display contents.
|
|
|
|
*/
|
|
|
|
struct drm_sprite {
|
|
|
|
struct wl_list link;
|
|
|
|
|
|
|
|
uint32_t fb_id;
|
|
|
|
uint32_t pending_fb_id;
|
|
|
|
struct weston_surface *surface;
|
|
|
|
struct weston_surface *pending_surface;
|
|
|
|
|
|
|
|
struct drm_compositor *compositor;
|
|
|
|
|
|
|
|
struct wl_listener destroy_listener;
|
|
|
|
struct wl_listener pending_destroy_listener;
|
|
|
|
|
|
|
|
uint32_t possible_crtcs;
|
|
|
|
uint32_t plane_id;
|
|
|
|
uint32_t count_formats;
|
|
|
|
|
|
|
|
int32_t src_x, src_y;
|
|
|
|
uint32_t src_w, src_h;
|
|
|
|
uint32_t dest_x, dest_y;
|
|
|
|
uint32_t dest_w, dest_h;
|
|
|
|
|
|
|
|
uint32_t formats[];
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
surface_is_primary(struct weston_compositor *ec, struct weston_surface *es)
|
|
|
|
{
|
|
|
|
struct weston_surface *primary;
|
|
|
|
|
|
|
|
primary = container_of(ec->surface_list.next, struct weston_surface,
|
|
|
|
link);
|
|
|
|
if (es == primary)
|
|
|
|
return -1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
drm_sprite_crtc_supported(struct weston_output *output_base, uint32_t supported)
|
|
|
|
{
|
|
|
|
struct weston_compositor *ec = output_base->compositor;
|
|
|
|
struct drm_compositor *c =(struct drm_compositor *) ec;
|
|
|
|
struct drm_output *output = (struct drm_output *) output_base;
|
|
|
|
int crtc;
|
|
|
|
|
|
|
|
for (crtc = 0; crtc < c->num_crtcs; crtc++) {
|
|
|
|
if (c->crtcs[crtc] != output->crtc_id)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (supported & (1 << crtc))
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-01-26 08:59:42 +04:00
|
|
|
static int
|
|
|
|
drm_output_prepare_scanout_surface(struct drm_output *output)
|
|
|
|
{
|
|
|
|
struct drm_compositor *c =
|
|
|
|
(struct drm_compositor *) output->base.compositor;
|
|
|
|
struct weston_surface *es;
|
|
|
|
EGLint handle, stride;
|
|
|
|
int ret;
|
|
|
|
uint32_t fb_id = 0;
|
|
|
|
struct gbm_bo *bo;
|
|
|
|
|
|
|
|
es = container_of(c->base.surface_list.next,
|
|
|
|
struct weston_surface, link);
|
|
|
|
|
2012-02-17 19:45:16 +04:00
|
|
|
/* Need to verify output->region contained in surface opaque
|
|
|
|
* region. Or maybe just that format doesn't have alpha. */
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (es->geometry.x != output->base.x ||
|
2012-01-25 18:22:05 +04:00
|
|
|
es->geometry.y != output->base.y ||
|
2012-01-25 17:55:43 +04:00
|
|
|
es->geometry.width != output->base.current->width ||
|
|
|
|
es->geometry.height != output->base.current->height ||
|
2012-01-25 16:33:33 +04:00
|
|
|
es->transform.enabled ||
|
2012-01-26 08:59:42 +04:00
|
|
|
es->image == EGL_NO_IMAGE_KHR)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
bo = gbm_bo_create_from_egl_image(c->gbm,
|
|
|
|
c->base.display, es->image,
|
2012-01-25 17:55:43 +04:00
|
|
|
es->geometry.width,
|
|
|
|
es->geometry.height,
|
2012-01-26 08:59:42 +04:00
|
|
|
GBM_BO_USE_SCANOUT);
|
|
|
|
|
|
|
|
handle = gbm_bo_get_handle(bo).s32;
|
|
|
|
stride = gbm_bo_get_pitch(bo);
|
|
|
|
|
|
|
|
gbm_bo_destroy(bo);
|
|
|
|
|
|
|
|
if (handle == 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
ret = drmModeAddFB(c->drm.fd,
|
|
|
|
output->base.current->width,
|
|
|
|
output->base.current->height,
|
|
|
|
24, 32, stride, handle, &fb_id);
|
|
|
|
|
|
|
|
if (ret)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
output->pending_fs_surf_fb_id = fb_id;
|
|
|
|
|
|
|
|
/* assert output->pending_scanout_buffer == NULL */
|
2012-01-26 09:11:01 +04:00
|
|
|
output->pending_scanout_buffer = es->buffer;
|
|
|
|
output->pending_scanout_buffer->busy_count++;
|
2012-01-26 08:59:42 +04:00
|
|
|
|
2012-01-26 09:11:01 +04:00
|
|
|
wl_list_insert(output->pending_scanout_buffer->resource.destroy_listener_list.prev,
|
|
|
|
&output->pending_scanout_buffer_destroy_listener.link);
|
2012-01-26 08:59:42 +04:00
|
|
|
|
|
|
|
pixman_region32_fini(&es->damage);
|
|
|
|
pixman_region32_init(&es->damage);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-01-26 08:47:45 +04:00
|
|
|
static void
|
2012-02-29 07:31:58 +04:00
|
|
|
drm_output_repaint(struct weston_output *output_base,
|
|
|
|
pixman_region32_t *damage)
|
2011-03-11 18:39:20 +03:00
|
|
|
{
|
|
|
|
struct drm_output *output = (struct drm_output *) output_base;
|
2012-01-26 08:47:45 +04:00
|
|
|
struct drm_compositor *compositor =
|
|
|
|
(struct drm_compositor *) output->base.compositor;
|
|
|
|
struct weston_surface *surface;
|
2012-02-23 18:45:49 +04:00
|
|
|
struct drm_sprite *s;
|
2012-01-26 08:47:45 +04:00
|
|
|
uint32_t fb_id = 0;
|
2012-02-23 18:45:49 +04:00
|
|
|
int ret = 0;
|
2011-03-11 18:39:20 +03:00
|
|
|
|
|
|
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER,
|
|
|
|
GL_COLOR_ATTACHMENT0,
|
|
|
|
GL_RENDERBUFFER,
|
|
|
|
output->rbo[output->current]);
|
|
|
|
|
|
|
|
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
2012-01-26 08:47:45 +04:00
|
|
|
return;
|
2012-01-26 08:32:28 +04:00
|
|
|
|
2012-01-26 08:59:42 +04:00
|
|
|
drm_output_prepare_scanout_surface(output);
|
|
|
|
|
2012-01-26 08:47:45 +04:00
|
|
|
wl_list_for_each_reverse(surface, &compositor->base.surface_list, link)
|
2012-02-29 07:31:58 +04:00
|
|
|
weston_surface_draw(surface, &output->base, damage);
|
2010-06-14 19:54:00 +04:00
|
|
|
|
2011-03-14 14:07:26 +03:00
|
|
|
glFlush();
|
|
|
|
|
|
|
|
output->current ^= 1;
|
2010-06-14 19:54:00 +04:00
|
|
|
|
2011-10-21 01:51:45 +04:00
|
|
|
if (output->pending_fs_surf_fb_id != 0) {
|
|
|
|
fb_id = output->pending_fs_surf_fb_id;
|
2011-04-10 18:49:52 +04:00
|
|
|
} else {
|
|
|
|
fb_id = output->fb_id[output->current ^ 1];
|
|
|
|
}
|
|
|
|
|
2012-01-26 08:47:45 +04:00
|
|
|
if (drmModePageFlip(compositor->drm.fd, output->crtc_id,
|
2012-01-18 20:47:41 +04:00
|
|
|
fb_id,
|
|
|
|
DRM_MODE_PAGE_FLIP_EVENT, output) < 0) {
|
|
|
|
fprintf(stderr, "queueing pageflip failed: %m\n");
|
2012-01-26 08:47:45 +04:00
|
|
|
return;
|
2012-01-18 20:47:41 +04:00
|
|
|
}
|
2011-03-11 18:39:20 +03:00
|
|
|
|
2012-02-23 18:45:49 +04:00
|
|
|
/*
|
|
|
|
* Now, update all the sprite surfaces
|
|
|
|
*/
|
|
|
|
wl_list_for_each(s, &compositor->sprite_list, link) {
|
|
|
|
uint32_t flags = 0;
|
|
|
|
drmVBlank vbl = {
|
|
|
|
.request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT,
|
|
|
|
.request.sequence = 1,
|
|
|
|
};
|
|
|
|
|
|
|
|
if (!drm_sprite_crtc_supported(output_base, s->possible_crtcs))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
ret = drmModeSetPlane(compositor->drm.fd, s->plane_id,
|
|
|
|
output->crtc_id, s->pending_fb_id, flags,
|
|
|
|
s->dest_x, s->dest_y,
|
|
|
|
s->dest_w, s->dest_h,
|
|
|
|
s->src_x, s->src_y,
|
|
|
|
s->src_w, s->src_h);
|
|
|
|
if (ret)
|
|
|
|
fprintf(stderr, "setplane failed: %d: %s\n",
|
|
|
|
ret, strerror(errno));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Queue a vblank signal so we know when the surface
|
|
|
|
* becomes active on the display or has been replaced.
|
|
|
|
*/
|
|
|
|
vbl.request.signal = (unsigned long)s;
|
|
|
|
ret = drmWaitVBlank(compositor->drm.fd, &vbl);
|
|
|
|
if (ret) {
|
|
|
|
fprintf(stderr, "vblank event request failed: %d: %s\n",
|
|
|
|
ret, strerror(errno));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-26 08:47:45 +04:00
|
|
|
return;
|
2010-06-11 20:56:24 +04:00
|
|
|
}
|
|
|
|
|
2012-02-23 18:45:49 +04:00
|
|
|
static void
|
|
|
|
vblank_handler(int fd, unsigned int frame, unsigned int sec, unsigned int usec,
|
|
|
|
void *data)
|
|
|
|
{
|
|
|
|
struct drm_sprite *s = (struct drm_sprite *)data;
|
|
|
|
struct drm_compositor *c = s->compositor;
|
|
|
|
|
|
|
|
if (s->surface) {
|
|
|
|
weston_buffer_post_release(s->surface->buffer);
|
|
|
|
wl_list_remove(&s->destroy_listener.link);
|
|
|
|
s->surface = NULL;
|
|
|
|
drmModeRmFB(c->drm.fd, s->fb_id);
|
|
|
|
s->fb_id = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (s->pending_surface) {
|
|
|
|
wl_list_remove(&s->pending_destroy_listener.link);
|
|
|
|
wl_list_insert(s->pending_surface->buffer->resource.destroy_listener_list.prev,
|
|
|
|
&s->destroy_listener.link);
|
|
|
|
s->surface = s->pending_surface;
|
|
|
|
s->pending_surface = NULL;
|
|
|
|
s->fb_id = s->pending_fb_id;
|
|
|
|
s->pending_fb_id = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-11 20:56:24 +04:00
|
|
|
static void
|
|
|
|
page_flip_handler(int fd, unsigned int frame,
|
|
|
|
unsigned int sec, unsigned int usec, void *data)
|
|
|
|
{
|
2011-04-10 18:49:52 +04:00
|
|
|
struct drm_output *output = (struct drm_output *) data;
|
|
|
|
struct drm_compositor *c =
|
|
|
|
(struct drm_compositor *) output->base.compositor;
|
2010-06-11 20:56:24 +04:00
|
|
|
uint32_t msecs;
|
|
|
|
|
2012-01-26 09:11:01 +04:00
|
|
|
if (output->scanout_buffer) {
|
|
|
|
weston_buffer_post_release(output->scanout_buffer);
|
|
|
|
wl_list_remove(&output->scanout_buffer_destroy_listener.link);
|
|
|
|
output->scanout_buffer = NULL;
|
2011-10-21 01:51:45 +04:00
|
|
|
drmModeRmFB(c->drm.fd, output->fs_surf_fb_id);
|
2011-04-10 18:49:52 +04:00
|
|
|
output->fs_surf_fb_id = 0;
|
|
|
|
}
|
|
|
|
|
2012-01-26 09:11:01 +04:00
|
|
|
if (output->pending_scanout_buffer) {
|
|
|
|
output->scanout_buffer = output->pending_scanout_buffer;
|
|
|
|
wl_list_remove(&output->pending_scanout_buffer_destroy_listener.link);
|
|
|
|
wl_list_insert(output->scanout_buffer->resource.destroy_listener_list.prev,
|
|
|
|
&output->scanout_buffer_destroy_listener.link);
|
|
|
|
output->pending_scanout_buffer = NULL;
|
2011-10-21 01:51:45 +04:00
|
|
|
output->fs_surf_fb_id = output->pending_fs_surf_fb_id;
|
|
|
|
output->pending_fs_surf_fb_id = 0;
|
|
|
|
}
|
|
|
|
|
2011-03-14 14:07:26 +03:00
|
|
|
msecs = sec * 1000 + usec / 1000;
|
Rename wayland-compositor to weston
This rename addresses a few problems around the split between core
Wayland and the wayland-demos repository.
1) Initially, we had one big repository with protocol code, sample
compositor and sample clients. We split that repository to make it
possible to implement the protocol without pulling in the sample/demo
code. At this point, the compositor is more than just a "demo" and
wayland-demos doesn't send the right message. The sample compositor
is a useful, self-contained project in it's own right, and we want to
move away from the "demos" label.
2) Another problem is that the wayland-demos compositor is often
called "the wayland compsitor", but it's really just one possible
compositor. Existing X11 compositors are expected to add Wayland
support and then gradually phase out/modularize the X11 support, for
example. Conversely, it's hard to talk about the wayland-demos
compositor specifically as opposed to, eg, the wayland protocol or a
wayland compositor in general.
We are also renaming the repo to weston, and the compositor
subdirectory to src/, to emphasize that the main "output" is the
compositor.
2012-01-03 19:29:47 +04:00
|
|
|
weston_output_finish_frame(&output->base, msecs);
|
2011-04-10 18:49:52 +04:00
|
|
|
}
|
|
|
|
|
2012-02-23 18:45:49 +04:00
|
|
|
static int
|
|
|
|
drm_surface_format_supported(struct drm_sprite *s, uint32_t format)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < s->count_formats; i++)
|
|
|
|
if (s->formats[i] == format)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
drm_surface_transform_supported(struct weston_surface *es)
|
|
|
|
{
|
|
|
|
if (es->transform.enabled)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
drm_surface_overlap_supported(struct weston_output *output_base,
|
|
|
|
pixman_region32_t *overlap)
|
|
|
|
{
|
|
|
|
/* We could potentially use a color key here if the surface left
|
|
|
|
* to display has rectangular regions
|
|
|
|
*/
|
|
|
|
if (pixman_region32_not_empty(overlap))
|
|
|
|
return 0;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
drm_disable_unused_sprites(struct weston_output *output_base)
|
|
|
|
{
|
|
|
|
struct weston_compositor *ec = output_base->compositor;
|
|
|
|
struct drm_compositor *c =(struct drm_compositor *) ec;
|
|
|
|
struct drm_output *output = (struct drm_output *) output_base;
|
|
|
|
struct drm_sprite *s;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
wl_list_for_each(s, &c->sprite_list, link) {
|
|
|
|
if (s->pending_fb_id)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
ret = drmModeSetPlane(c->drm.fd, s->plane_id,
|
|
|
|
output->crtc_id, 0, 0,
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0);
|
|
|
|
if (ret)
|
|
|
|
fprintf(stderr,
|
|
|
|
"failed to disable plane: %d: %s\n",
|
|
|
|
ret, strerror(errno));
|
|
|
|
drmModeRmFB(c->drm.fd, s->fb_id);
|
|
|
|
s->surface = NULL;
|
|
|
|
s->pending_surface = NULL;
|
|
|
|
s->fb_id = 0;
|
|
|
|
s->pending_fb_id = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This function must take care to damage any previously assigned surface
|
|
|
|
* if the sprite ends up binding to a different surface than in the
|
|
|
|
* previous frame.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
drm_output_prepare_overlay_surface(struct weston_output *output_base,
|
|
|
|
struct weston_surface *es,
|
|
|
|
pixman_region32_t *overlap)
|
|
|
|
{
|
|
|
|
struct weston_compositor *ec = output_base->compositor;
|
|
|
|
struct drm_compositor *c =(struct drm_compositor *) ec;
|
|
|
|
struct drm_sprite *s;
|
|
|
|
int found = 0;
|
|
|
|
EGLint handle, stride;
|
|
|
|
struct gbm_bo *bo;
|
|
|
|
uint32_t fb_id = 0;
|
|
|
|
uint32_t handles[4], pitches[4], offsets[4];
|
|
|
|
int ret = 0;
|
|
|
|
pixman_region32_t dest_rect, src_rect;
|
|
|
|
pixman_box32_t *box;
|
|
|
|
uint32_t format;
|
|
|
|
|
|
|
|
if (surface_is_primary(ec, es))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (!es->buffer)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (!drm_surface_transform_supported(es))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (!drm_surface_overlap_supported(output_base, overlap))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
wl_list_for_each(s, &c->sprite_list, link) {
|
|
|
|
if (!drm_sprite_crtc_supported(output_base, s->possible_crtcs))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!s->pending_fb_id) {
|
|
|
|
found = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* No sprites available */
|
|
|
|
if (!found)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
bo = gbm_bo_create_from_egl_image(c->gbm, c->base.display, es->image,
|
|
|
|
es->geometry.width, es->geometry.height,
|
|
|
|
GBM_BO_USE_SCANOUT);
|
|
|
|
format = gbm_bo_get_format(bo);
|
|
|
|
handle = gbm_bo_get_handle(bo).s32;
|
|
|
|
stride = gbm_bo_get_pitch(bo);
|
|
|
|
|
|
|
|
gbm_bo_destroy(bo);
|
|
|
|
|
|
|
|
if (!drm_surface_format_supported(s, format))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (!handle)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
handles[0] = handle;
|
|
|
|
pitches[0] = stride;
|
|
|
|
offsets[0] = 0;
|
|
|
|
|
|
|
|
ret = drmModeAddFB2(c->drm.fd, es->geometry.width, es->geometry.height,
|
|
|
|
format, handles, pitches, offsets,
|
|
|
|
&fb_id, 0);
|
|
|
|
if (ret) {
|
|
|
|
fprintf(stderr, "addfb2 failed: %d\n", ret);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (s->surface && s->surface != es) {
|
|
|
|
struct weston_surface *old_surf = s->surface;
|
|
|
|
pixman_region32_fini(&old_surf->damage);
|
|
|
|
pixman_region32_init_rect(&old_surf->damage,
|
|
|
|
old_surf->geometry.x, old_surf->geometry.y,
|
|
|
|
old_surf->geometry.width, old_surf->geometry.height);
|
|
|
|
}
|
|
|
|
|
|
|
|
s->pending_fb_id = fb_id;
|
|
|
|
s->pending_surface = es;
|
|
|
|
es->buffer->busy_count++;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Calculate the source & dest rects properly based on actual
|
|
|
|
* postion (note the caller has called weston_surface_update_transform()
|
|
|
|
* for us already).
|
|
|
|
*/
|
|
|
|
pixman_region32_init(&dest_rect);
|
|
|
|
pixman_region32_intersect(&dest_rect, &es->transform.boundingbox,
|
|
|
|
&output_base->region);
|
|
|
|
pixman_region32_translate(&dest_rect, -output_base->x, -output_base->y);
|
|
|
|
box = pixman_region32_extents(&dest_rect);
|
|
|
|
s->dest_x = box->x1;
|
|
|
|
s->dest_y = box->y1;
|
|
|
|
s->dest_w = box->x2 - box->x1;
|
|
|
|
s->dest_h = box->y2 - box->y1;
|
|
|
|
pixman_region32_fini(&dest_rect);
|
|
|
|
|
|
|
|
pixman_region32_init(&src_rect);
|
|
|
|
pixman_region32_intersect(&src_rect, &es->transform.boundingbox,
|
|
|
|
&output_base->region);
|
|
|
|
pixman_region32_translate(&src_rect, -es->geometry.x, -es->geometry.y);
|
|
|
|
box = pixman_region32_extents(&src_rect);
|
|
|
|
s->src_x = box->x1;
|
|
|
|
s->src_y = box->y1;
|
|
|
|
s->src_w = box->x2 - box->x1;
|
|
|
|
s->src_h = box->y2 - box->y1;
|
|
|
|
pixman_region32_fini(&src_rect);
|
|
|
|
|
|
|
|
|
|
|
|
wl_list_insert(es->buffer->resource.destroy_listener_list.prev,
|
|
|
|
&s->pending_destroy_listener.link);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-02-24 08:03:14 +04:00
|
|
|
static int
|
|
|
|
drm_output_set_cursor(struct weston_output *output_base,
|
|
|
|
struct weston_input_device *eid);
|
|
|
|
|
|
|
|
static void
|
|
|
|
weston_output_set_cursor(struct weston_output *output,
|
|
|
|
struct weston_input_device *device,
|
|
|
|
pixman_region32_t *overlap)
|
|
|
|
{
|
|
|
|
pixman_region32_t cursor_region;
|
|
|
|
int prior_was_hardware;
|
|
|
|
|
|
|
|
if (device->sprite == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
pixman_region32_init(&cursor_region);
|
|
|
|
pixman_region32_intersect(&cursor_region,
|
|
|
|
&device->sprite->transform.boundingbox,
|
|
|
|
&output->region);
|
|
|
|
|
|
|
|
if (!pixman_region32_not_empty(&cursor_region)) {
|
|
|
|
drm_output_set_cursor(output, NULL);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
prior_was_hardware = device->hw_cursor;
|
|
|
|
if (pixman_region32_not_empty(overlap) ||
|
|
|
|
drm_output_set_cursor(output, device) < 0) {
|
|
|
|
if (prior_was_hardware) {
|
|
|
|
weston_surface_damage(device->sprite);
|
|
|
|
drm_output_set_cursor(output, NULL);
|
|
|
|
}
|
|
|
|
device->hw_cursor = 0;
|
|
|
|
} else {
|
|
|
|
if (!prior_was_hardware)
|
|
|
|
weston_surface_damage_below(device->sprite);
|
|
|
|
pixman_region32_fini(&device->sprite->damage);
|
|
|
|
pixman_region32_init(&device->sprite->damage);
|
|
|
|
device->hw_cursor = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
out:
|
|
|
|
pixman_region32_fini(&cursor_region);
|
|
|
|
}
|
|
|
|
|
2012-02-23 18:45:49 +04:00
|
|
|
static void
|
|
|
|
drm_assign_planes(struct weston_output *output)
|
|
|
|
{
|
|
|
|
struct weston_compositor *ec = output->compositor;
|
|
|
|
struct weston_surface *es;
|
|
|
|
pixman_region32_t overlap, surface_overlap;
|
2012-02-24 08:03:14 +04:00
|
|
|
struct weston_input_device *device;
|
2012-02-23 18:45:49 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Find a surface for each sprite in the output using some heuristics:
|
|
|
|
* 1) size
|
|
|
|
* 2) frequency of update
|
|
|
|
* 3) opacity (though some hw might support alpha blending)
|
|
|
|
* 4) clipping (this can be fixed with color keys)
|
|
|
|
*
|
|
|
|
* The idea is to save on blitting since this should save power.
|
|
|
|
* If we can get a large video surface on the sprite for example,
|
|
|
|
* the main display surface may not need to update at all, and
|
|
|
|
* the client buffer can be used directly for the sprite surface
|
|
|
|
* as we do for flipping full screen surfaces.
|
|
|
|
*/
|
|
|
|
pixman_region32_init(&overlap);
|
|
|
|
wl_list_for_each(es, &ec->surface_list, link) {
|
|
|
|
/*
|
|
|
|
* FIXME: try to assign hw cursors here too, they're just
|
|
|
|
* special overlays
|
|
|
|
*/
|
|
|
|
pixman_region32_init(&surface_overlap);
|
|
|
|
pixman_region32_intersect(&surface_overlap, &overlap,
|
|
|
|
&es->transform.boundingbox);
|
|
|
|
|
2012-02-24 08:03:14 +04:00
|
|
|
device = (struct weston_input_device *) ec->input_device;
|
|
|
|
if (es == device->sprite) {
|
|
|
|
weston_output_set_cursor(output, device,
|
|
|
|
&surface_overlap);
|
|
|
|
|
|
|
|
if (!device->hw_cursor)
|
|
|
|
pixman_region32_union(&overlap, &overlap,
|
|
|
|
&es->transform.boundingbox);
|
|
|
|
} else if (!drm_output_prepare_overlay_surface(output, es,
|
|
|
|
&surface_overlap)) {
|
2012-02-23 18:45:49 +04:00
|
|
|
pixman_region32_fini(&es->damage);
|
|
|
|
pixman_region32_init(&es->damage);
|
|
|
|
} else {
|
|
|
|
pixman_region32_union(&overlap, &overlap,
|
|
|
|
&es->transform.boundingbox);
|
|
|
|
}
|
|
|
|
pixman_region32_fini(&surface_overlap);
|
|
|
|
}
|
|
|
|
pixman_region32_fini(&overlap);
|
|
|
|
|
|
|
|
drm_disable_unused_sprites(output);
|
|
|
|
}
|
|
|
|
|
2011-04-20 13:02:58 +04:00
|
|
|
static int
|
Rename wayland-compositor to weston
This rename addresses a few problems around the split between core
Wayland and the wayland-demos repository.
1) Initially, we had one big repository with protocol code, sample
compositor and sample clients. We split that repository to make it
possible to implement the protocol without pulling in the sample/demo
code. At this point, the compositor is more than just a "demo" and
wayland-demos doesn't send the right message. The sample compositor
is a useful, self-contained project in it's own right, and we want to
move away from the "demos" label.
2) Another problem is that the wayland-demos compositor is often
called "the wayland compsitor", but it's really just one possible
compositor. Existing X11 compositors are expected to add Wayland
support and then gradually phase out/modularize the X11 support, for
example. Conversely, it's hard to talk about the wayland-demos
compositor specifically as opposed to, eg, the wayland protocol or a
wayland compositor in general.
We are also renaming the repo to weston, and the compositor
subdirectory to src/, to emphasize that the main "output" is the
compositor.
2012-01-03 19:29:47 +04:00
|
|
|
drm_output_set_cursor(struct weston_output *output_base,
|
|
|
|
struct weston_input_device *eid)
|
2011-04-20 13:02:58 +04:00
|
|
|
{
|
|
|
|
struct drm_output *output = (struct drm_output *) output_base;
|
|
|
|
struct drm_compositor *c =
|
|
|
|
(struct drm_compositor *) output->base.compositor;
|
|
|
|
EGLint handle, stride;
|
|
|
|
int ret = -1;
|
2011-04-30 11:32:11 +04:00
|
|
|
struct gbm_bo *bo;
|
2011-04-20 13:02:58 +04:00
|
|
|
|
2011-05-06 22:04:21 +04:00
|
|
|
if (eid == NULL) {
|
|
|
|
drmModeSetCursor(c->drm.fd, output->crtc_id, 0, 0, 0);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-04-20 13:02:58 +04:00
|
|
|
if (eid->sprite->image == EGL_NO_IMAGE_KHR)
|
|
|
|
goto out;
|
|
|
|
|
2012-01-25 17:55:43 +04:00
|
|
|
if (eid->sprite->geometry.width > 64 ||
|
|
|
|
eid->sprite->geometry.height > 64)
|
2011-04-20 13:02:58 +04:00
|
|
|
goto out;
|
2011-08-30 13:38:26 +04:00
|
|
|
|
2011-04-30 11:32:11 +04:00
|
|
|
bo = gbm_bo_create_from_egl_image(c->gbm,
|
|
|
|
c->base.display,
|
|
|
|
eid->sprite->image, 64, 64,
|
|
|
|
GBM_BO_USE_CURSOR_64X64);
|
2012-01-19 00:11:07 +04:00
|
|
|
/* Not suitable for hw cursor, fall back */
|
|
|
|
if (bo == NULL)
|
|
|
|
goto out;
|
2011-04-30 11:32:11 +04:00
|
|
|
|
|
|
|
handle = gbm_bo_get_handle(bo).s32;
|
|
|
|
stride = gbm_bo_get_pitch(bo);
|
|
|
|
gbm_bo_destroy(bo);
|
2011-04-20 13:02:58 +04:00
|
|
|
|
2012-01-19 00:11:07 +04:00
|
|
|
/* gbm_bo_create_from_egl_image() didn't always validate the usage
|
|
|
|
* flags, and in that case we might end up with a bad stride. */
|
|
|
|
if (stride != 64 * 4)
|
2011-04-20 13:02:58 +04:00
|
|
|
goto out;
|
|
|
|
|
|
|
|
ret = drmModeSetCursor(c->drm.fd, output->crtc_id, handle, 64, 64);
|
|
|
|
if (ret) {
|
|
|
|
fprintf(stderr, "failed to set cursor: %s\n", strerror(-ret));
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = drmModeMoveCursor(c->drm.fd, output->crtc_id,
|
2012-01-25 18:22:05 +04:00
|
|
|
eid->sprite->geometry.x - output->base.x,
|
|
|
|
eid->sprite->geometry.y - output->base.y);
|
2011-04-20 13:02:58 +04:00
|
|
|
if (ret) {
|
|
|
|
fprintf(stderr, "failed to move cursor: %s\n", strerror(-ret));
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
out:
|
|
|
|
if (ret)
|
|
|
|
drmModeSetCursor(c->drm.fd, output->crtc_id, 0, 0, 0);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-08-30 00:52:23 +04:00
|
|
|
static void
|
Rename wayland-compositor to weston
This rename addresses a few problems around the split between core
Wayland and the wayland-demos repository.
1) Initially, we had one big repository with protocol code, sample
compositor and sample clients. We split that repository to make it
possible to implement the protocol without pulling in the sample/demo
code. At this point, the compositor is more than just a "demo" and
wayland-demos doesn't send the right message. The sample compositor
is a useful, self-contained project in it's own right, and we want to
move away from the "demos" label.
2) Another problem is that the wayland-demos compositor is often
called "the wayland compsitor", but it's really just one possible
compositor. Existing X11 compositors are expected to add Wayland
support and then gradually phase out/modularize the X11 support, for
example. Conversely, it's hard to talk about the wayland-demos
compositor specifically as opposed to, eg, the wayland protocol or a
wayland compositor in general.
We are also renaming the repo to weston, and the compositor
subdirectory to src/, to emphasize that the main "output" is the
compositor.
2012-01-03 19:29:47 +04:00
|
|
|
drm_output_destroy(struct weston_output *output_base)
|
2011-08-30 00:52:23 +04:00
|
|
|
{
|
|
|
|
struct drm_output *output = (struct drm_output *) output_base;
|
|
|
|
struct drm_compositor *c =
|
2011-08-30 13:38:26 +04:00
|
|
|
(struct drm_compositor *) output->base.compositor;
|
2011-08-30 00:52:23 +04:00
|
|
|
drmModeCrtcPtr origcrtc = output->original_crtc;
|
|
|
|
int i;
|
|
|
|
|
2012-02-29 21:53:50 +04:00
|
|
|
if (output->backlight)
|
|
|
|
backlight_destroy(output->backlight);
|
|
|
|
|
2011-08-30 00:52:23 +04:00
|
|
|
/* Turn off hardware cursor */
|
2011-08-30 13:38:26 +04:00
|
|
|
drm_output_set_cursor(&output->base, NULL);
|
2011-08-30 00:52:23 +04:00
|
|
|
|
|
|
|
/* Restore original CRTC state */
|
|
|
|
drmModeSetCrtc(c->drm.fd, origcrtc->crtc_id, origcrtc->buffer_id,
|
2011-08-30 13:38:26 +04:00
|
|
|
origcrtc->x, origcrtc->y,
|
|
|
|
&output->connector_id, 1, &origcrtc->mode);
|
2011-08-30 00:52:23 +04:00
|
|
|
drmModeFreeCrtc(origcrtc);
|
|
|
|
|
2011-08-30 13:44:56 +04:00
|
|
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER,
|
|
|
|
GL_COLOR_ATTACHMENT0,
|
|
|
|
GL_RENDERBUFFER,
|
|
|
|
0);
|
|
|
|
|
|
|
|
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
|
|
|
glDeleteRenderbuffers(2, output->rbo);
|
|
|
|
|
2011-08-30 00:52:23 +04:00
|
|
|
/* 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]);
|
|
|
|
}
|
|
|
|
|
2011-08-30 13:44:56 +04:00
|
|
|
c->crtc_allocator &= ~(1 << output->crtc_id);
|
|
|
|
c->connector_allocator &= ~(1 << output->connector_id);
|
|
|
|
|
Rename wayland-compositor to weston
This rename addresses a few problems around the split between core
Wayland and the wayland-demos repository.
1) Initially, we had one big repository with protocol code, sample
compositor and sample clients. We split that repository to make it
possible to implement the protocol without pulling in the sample/demo
code. At this point, the compositor is more than just a "demo" and
wayland-demos doesn't send the right message. The sample compositor
is a useful, self-contained project in it's own right, and we want to
move away from the "demos" label.
2) Another problem is that the wayland-demos compositor is often
called "the wayland compsitor", but it's really just one possible
compositor. Existing X11 compositors are expected to add Wayland
support and then gradually phase out/modularize the X11 support, for
example. Conversely, it's hard to talk about the wayland-demos
compositor specifically as opposed to, eg, the wayland protocol or a
wayland compositor in general.
We are also renaming the repo to weston, and the compositor
subdirectory to src/, to emphasize that the main "output" is the
compositor.
2012-01-03 19:29:47 +04:00
|
|
|
weston_output_destroy(&output->base);
|
2011-08-30 13:44:56 +04:00
|
|
|
wl_list_remove(&output->base.link);
|
|
|
|
|
2011-08-30 00:52:23 +04:00
|
|
|
free(output);
|
|
|
|
}
|
|
|
|
|
2011-04-22 20:27:57 +04:00
|
|
|
static int
|
2010-06-11 20:56:24 +04:00
|
|
|
on_drm_input(int fd, uint32_t mask, void *data)
|
|
|
|
{
|
|
|
|
drmEventContext evctx;
|
|
|
|
|
|
|
|
memset(&evctx, 0, sizeof evctx);
|
|
|
|
evctx.version = DRM_EVENT_CONTEXT_VERSION;
|
|
|
|
evctx.page_flip_handler = page_flip_handler;
|
2012-02-23 18:45:49 +04:00
|
|
|
evctx.vblank_handler = vblank_handler;
|
2010-06-11 20:56:24 +04:00
|
|
|
drmHandleEvent(fd, &evctx);
|
2011-04-22 20:27:57 +04:00
|
|
|
|
|
|
|
return 1;
|
2010-06-11 20:56:24 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2010-06-14 19:54:00 +04:00
|
|
|
init_egl(struct drm_compositor *ec, struct udev_device *device)
|
2010-06-11 20:56:24 +04:00
|
|
|
{
|
2010-07-29 06:52:28 +04:00
|
|
|
EGLint major, minor;
|
2010-08-09 22:43:33 +04:00
|
|
|
const char *extensions, *filename;
|
|
|
|
int fd;
|
2010-07-29 07:47:54 +04:00
|
|
|
static const EGLint context_attribs[] = {
|
|
|
|
EGL_CONTEXT_CLIENT_VERSION, 2,
|
|
|
|
EGL_NONE
|
|
|
|
};
|
2010-06-11 20:56:24 +04:00
|
|
|
|
2010-08-09 22:43:33 +04:00
|
|
|
filename = udev_device_get_devnode(device);
|
2011-11-05 21:46:01 +04:00
|
|
|
fd = open(filename, O_RDWR | O_CLOEXEC);
|
2010-08-09 22:43:33 +04:00
|
|
|
if (fd < 0) {
|
2010-06-11 20:56:24 +04:00
|
|
|
/* Probably permissions error */
|
|
|
|
fprintf(stderr, "couldn't open %s, skipping\n",
|
|
|
|
udev_device_get_devnode(device));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2011-03-02 13:14:59 +03:00
|
|
|
ec->drm.fd = fd;
|
2011-04-30 11:32:11 +04:00
|
|
|
ec->gbm = gbm_create_device(ec->drm.fd);
|
|
|
|
ec->base.display = eglGetDisplay(ec->gbm);
|
2010-06-14 19:54:00 +04:00
|
|
|
if (ec->base.display == NULL) {
|
2010-06-11 20:56:24 +04:00
|
|
|
fprintf(stderr, "failed to create display\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2010-06-14 19:54:00 +04:00
|
|
|
if (!eglInitialize(ec->base.display, &major, &minor)) {
|
2010-06-11 20:56:24 +04:00
|
|
|
fprintf(stderr, "failed to initialize display\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2010-07-29 06:52:28 +04:00
|
|
|
extensions = eglQueryString(ec->base.display, EGL_EXTENSIONS);
|
2011-11-01 18:37:41 +04:00
|
|
|
if (!strstr(extensions, "EGL_KHR_surfaceless_gles2")) {
|
|
|
|
fprintf(stderr, "EGL_KHR_surfaceless_gles2 not available\n");
|
2010-06-11 20:56:24 +04:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2010-11-23 05:24:39 +03:00
|
|
|
if (!eglBindAPI(EGL_OPENGL_ES_API)) {
|
|
|
|
fprintf(stderr, "failed to bind api EGL_OPENGL_ES_API\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2010-07-29 07:47:54 +04:00
|
|
|
ec->base.context = eglCreateContext(ec->base.display, NULL,
|
|
|
|
EGL_NO_CONTEXT, context_attribs);
|
2010-06-14 19:54:00 +04:00
|
|
|
if (ec->base.context == NULL) {
|
2010-06-11 20:56:24 +04:00
|
|
|
fprintf(stderr, "failed to create context\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2010-06-14 19:54:00 +04:00
|
|
|
if (!eglMakeCurrent(ec->base.display, EGL_NO_SURFACE,
|
|
|
|
EGL_NO_SURFACE, ec->base.context)) {
|
2010-06-11 20:56:24 +04:00
|
|
|
fprintf(stderr, "failed to make context current\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static drmModeModeInfo builtin_1024x768 = {
|
|
|
|
63500, /* clock */
|
|
|
|
1024, 1072, 1176, 1328, 0,
|
|
|
|
768, 771, 775, 798, 0,
|
|
|
|
59920,
|
|
|
|
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC,
|
|
|
|
0,
|
|
|
|
"1024x768"
|
|
|
|
};
|
|
|
|
|
2011-06-21 19:16:58 +04:00
|
|
|
|
|
|
|
static int
|
|
|
|
drm_output_add_mode(struct drm_output *output, drmModeModeInfo *info)
|
|
|
|
{
|
|
|
|
struct drm_mode *mode;
|
|
|
|
|
|
|
|
mode = malloc(sizeof *mode);
|
|
|
|
if (mode == NULL)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
mode->base.flags = 0;
|
|
|
|
mode->base.width = info->hdisplay;
|
|
|
|
mode->base.height = info->vdisplay;
|
|
|
|
mode->base.refresh = info->vrefresh;
|
|
|
|
mode->mode_info = *info;
|
|
|
|
wl_list_insert(output->base.mode_list.prev, &mode->base.link);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
drm_subpixel_to_wayland(int drm_value)
|
|
|
|
{
|
|
|
|
switch (drm_value) {
|
|
|
|
default:
|
|
|
|
case DRM_MODE_SUBPIXEL_UNKNOWN:
|
|
|
|
return WL_OUTPUT_SUBPIXEL_UNKNOWN;
|
|
|
|
case DRM_MODE_SUBPIXEL_NONE:
|
|
|
|
return WL_OUTPUT_SUBPIXEL_NONE;
|
|
|
|
case DRM_MODE_SUBPIXEL_HORIZONTAL_RGB:
|
|
|
|
return WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB;
|
|
|
|
case DRM_MODE_SUBPIXEL_HORIZONTAL_BGR:
|
|
|
|
return WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR;
|
|
|
|
case DRM_MODE_SUBPIXEL_VERTICAL_RGB:
|
|
|
|
return WL_OUTPUT_SUBPIXEL_VERTICAL_RGB;
|
|
|
|
case DRM_MODE_SUBPIXEL_VERTICAL_BGR:
|
|
|
|
return WL_OUTPUT_SUBPIXEL_VERTICAL_BGR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-26 09:11:01 +04:00
|
|
|
static void
|
|
|
|
output_handle_scanout_buffer_destroy(struct wl_listener *listener,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
uint32_t time)
|
|
|
|
{
|
|
|
|
struct drm_output *output =
|
|
|
|
container_of(listener, struct drm_output,
|
|
|
|
scanout_buffer_destroy_listener);
|
|
|
|
|
|
|
|
output->scanout_buffer = NULL;
|
|
|
|
|
|
|
|
if (!output->pending_scanout_buffer)
|
|
|
|
weston_compositor_schedule_repaint(output->base.compositor);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
output_handle_pending_scanout_buffer_destroy(struct wl_listener *listener,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
uint32_t time)
|
|
|
|
{
|
|
|
|
struct drm_output *output =
|
|
|
|
container_of(listener, struct drm_output,
|
|
|
|
pending_scanout_buffer_destroy_listener);
|
|
|
|
|
|
|
|
output->pending_scanout_buffer = NULL;
|
|
|
|
|
|
|
|
weston_compositor_schedule_repaint(output->base.compositor);
|
|
|
|
}
|
|
|
|
|
2012-02-23 18:45:49 +04:00
|
|
|
static void
|
|
|
|
sprite_handle_buffer_destroy(struct wl_listener *listener,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
uint32_t time)
|
|
|
|
{
|
|
|
|
struct drm_sprite *sprite =
|
|
|
|
container_of(listener, struct drm_sprite,
|
|
|
|
destroy_listener);
|
|
|
|
|
|
|
|
sprite->surface = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
sprite_handle_pending_buffer_destroy(struct wl_listener *listener,
|
|
|
|
struct wl_resource *resource,
|
|
|
|
uint32_t time)
|
|
|
|
{
|
|
|
|
struct drm_sprite *sprite =
|
|
|
|
container_of(listener, struct drm_sprite,
|
|
|
|
pending_destroy_listener);
|
|
|
|
|
|
|
|
sprite->pending_surface = NULL;
|
|
|
|
}
|
|
|
|
|
2012-02-29 21:53:50 +04:00
|
|
|
/* returns a value between 1-10 range, where higher is brighter */
|
|
|
|
static uint32_t
|
|
|
|
drm_get_backlight(struct drm_output *output)
|
|
|
|
{
|
|
|
|
long brightness, max_brightness, norm;
|
|
|
|
|
|
|
|
brightness = backlight_get_brightness(output->backlight);
|
|
|
|
max_brightness = backlight_get_max_brightness(output->backlight);
|
|
|
|
|
|
|
|
/* convert it on a scale of 1 to 10 */
|
|
|
|
norm = 1 + ((brightness) * 9)/(max_brightness);
|
|
|
|
|
|
|
|
return (uint32_t) norm;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* values accepted are between 1-10 range */
|
|
|
|
static void
|
|
|
|
drm_set_backlight(struct weston_output *output_base, uint32_t value)
|
|
|
|
{
|
|
|
|
struct drm_output *output = (struct drm_output *) output_base;
|
|
|
|
long max_brightness, new_brightness;
|
|
|
|
|
|
|
|
if (!output->backlight)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (value < 1 || value > 10)
|
|
|
|
return;
|
|
|
|
|
|
|
|
max_brightness = backlight_get_max_brightness(output->backlight);
|
|
|
|
|
|
|
|
/* get denormalized value */
|
|
|
|
new_brightness = ((value - 1) * (max_brightness)) / 9;
|
|
|
|
|
|
|
|
backlight_set_brightness(output->backlight, new_brightness);
|
|
|
|
}
|
|
|
|
|
|
|
|
static drmModePropertyPtr
|
|
|
|
drm_get_prop(int fd, drmModeConnectorPtr connector, const char *name)
|
|
|
|
{
|
|
|
|
drmModePropertyPtr props;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < connector->count_props; i++) {
|
|
|
|
props = drmModeGetProperty(fd, connector->props[i]);
|
|
|
|
if (!props)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!strcmp(props->name, name))
|
|
|
|
return props;
|
|
|
|
|
|
|
|
drmModeFreeProperty(props);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
drm_set_dpms(struct weston_output *output_base, enum dpms_enum level)
|
|
|
|
{
|
|
|
|
struct drm_output *output = (struct drm_output *) output_base;
|
|
|
|
struct weston_compositor *ec = output_base->compositor;
|
|
|
|
struct drm_compositor *c = (struct drm_compositor *) ec;
|
|
|
|
drmModeConnectorPtr connector;
|
|
|
|
drmModePropertyPtr prop;
|
|
|
|
|
|
|
|
connector = drmModeGetConnector(c->drm.fd, output->connector_id);
|
|
|
|
if (!connector)
|
|
|
|
return;
|
|
|
|
|
|
|
|
prop = drm_get_prop(c->drm.fd, connector, "DPMS");
|
|
|
|
if (!prop) {
|
|
|
|
drmModeFreeConnector(connector);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
drmModeConnectorSetProperty(c->drm.fd, connector->connector_id,
|
|
|
|
prop->prop_id, level);
|
|
|
|
drmModeFreeProperty(prop);
|
|
|
|
drmModeFreeConnector(connector);
|
|
|
|
}
|
|
|
|
|
2010-06-11 20:56:24 +04:00
|
|
|
static int
|
2010-06-14 19:54:00 +04:00
|
|
|
create_output_for_connector(struct drm_compositor *ec,
|
2010-06-11 20:56:24 +04:00
|
|
|
drmModeRes *resources,
|
2011-03-11 18:39:20 +03:00
|
|
|
drmModeConnector *connector,
|
2012-02-29 21:53:50 +04:00
|
|
|
int x, int y, struct udev_device *drm_device)
|
2010-06-11 20:56:24 +04:00
|
|
|
{
|
2010-06-14 19:54:00 +04:00
|
|
|
struct drm_output *output;
|
2011-12-08 20:05:45 +04:00
|
|
|
struct drm_mode *drm_mode, *next;
|
2010-06-11 20:56:24 +04:00
|
|
|
drmModeEncoder *encoder;
|
|
|
|
int i, ret;
|
2011-04-30 11:32:11 +04:00
|
|
|
unsigned handle, stride;
|
2010-06-11 20:56:24 +04:00
|
|
|
|
2011-03-02 13:14:59 +03:00
|
|
|
encoder = drmModeGetEncoder(ec->drm.fd, connector->encoders[0]);
|
2010-06-11 20:56:24 +04:00
|
|
|
if (encoder == NULL) {
|
|
|
|
fprintf(stderr, "No encoder for connector.\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < resources->count_crtcs; i++) {
|
2011-02-10 03:01:42 +03:00
|
|
|
if (encoder->possible_crtcs & (1 << i) &&
|
2011-03-15 17:08:41 +03:00
|
|
|
!(ec->crtc_allocator & (1 << resources->crtcs[i])))
|
2010-06-11 20:56:24 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (i == resources->count_crtcs) {
|
|
|
|
fprintf(stderr, "No usable crtc for encoder.\n");
|
2011-12-08 20:05:44 +04:00
|
|
|
drmModeFreeEncoder(encoder);
|
2010-06-11 20:56:24 +04:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2011-06-21 19:16:58 +04:00
|
|
|
output = malloc(sizeof *output);
|
2011-12-08 20:05:44 +04:00
|
|
|
if (output == NULL) {
|
|
|
|
drmModeFreeEncoder(encoder);
|
2011-06-21 19:16:58 +04:00
|
|
|
return -1;
|
2011-12-08 20:05:44 +04:00
|
|
|
}
|
2011-12-08 20:05:46 +04:00
|
|
|
output->fb_id[0] = -1;
|
|
|
|
output->fb_id[1] = -1;
|
2011-06-21 19:16:58 +04:00
|
|
|
|
2010-06-14 19:54:00 +04:00
|
|
|
memset(output, 0, sizeof *output);
|
2011-06-21 19:16:58 +04:00
|
|
|
output->base.subpixel = drm_subpixel_to_wayland(connector->subpixel);
|
|
|
|
output->base.make = "unknown";
|
|
|
|
output->base.model = "unknown";
|
|
|
|
wl_list_init(&output->base.mode_list);
|
2010-06-14 19:54:00 +04:00
|
|
|
|
2010-06-11 20:56:24 +04:00
|
|
|
output->crtc_id = resources->crtcs[i];
|
2011-03-15 17:08:41 +03:00
|
|
|
ec->crtc_allocator |= (1 << output->crtc_id);
|
2010-06-11 20:56:24 +04:00
|
|
|
output->connector_id = connector->connector_id;
|
2011-03-15 17:08:41 +03:00
|
|
|
ec->connector_allocator |= (1 << output->connector_id);
|
2011-06-21 19:16:58 +04:00
|
|
|
|
2011-08-30 00:52:23 +04:00
|
|
|
output->original_crtc = drmModeGetCrtc(ec->drm.fd, output->crtc_id);
|
2011-12-08 20:05:45 +04:00
|
|
|
drmModeFreeEncoder(encoder);
|
|
|
|
|
|
|
|
for (i = 0; i < connector->count_modes; i++) {
|
|
|
|
ret = drm_output_add_mode(output, &connector->modes[i]);
|
|
|
|
if (ret)
|
|
|
|
goto err_free;
|
|
|
|
}
|
2011-08-30 00:52:23 +04:00
|
|
|
|
2011-12-08 20:05:45 +04:00
|
|
|
if (connector->count_modes == 0) {
|
|
|
|
ret = drm_output_add_mode(output, &builtin_1024x768);
|
|
|
|
if (ret)
|
|
|
|
goto err_free;
|
|
|
|
}
|
2011-06-21 19:16:58 +04:00
|
|
|
|
|
|
|
drm_mode = container_of(output->base.mode_list.next,
|
|
|
|
struct drm_mode, base.link);
|
|
|
|
output->base.current = &drm_mode->base;
|
|
|
|
drm_mode->base.flags =
|
|
|
|
WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
|
|
|
|
|
2010-06-11 20:56:24 +04:00
|
|
|
glGenRenderbuffers(2, output->rbo);
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
|
|
glBindRenderbuffer(GL_RENDERBUFFER, output->rbo[i]);
|
|
|
|
|
2011-04-30 11:32:11 +04:00
|
|
|
output->bo[i] =
|
|
|
|
gbm_bo_create(ec->gbm,
|
|
|
|
output->base.current->width,
|
|
|
|
output->base.current->height,
|
|
|
|
GBM_BO_FORMAT_XRGB8888,
|
2011-08-30 13:38:26 +04:00
|
|
|
GBM_BO_USE_SCANOUT |
|
|
|
|
GBM_BO_USE_RENDERING);
|
2011-12-08 20:05:46 +04:00
|
|
|
if (!output->bo[i])
|
|
|
|
goto err_bufs;
|
|
|
|
|
2011-04-30 11:32:11 +04:00
|
|
|
output->image[i] = ec->base.create_image(ec->base.display,
|
|
|
|
NULL,
|
|
|
|
EGL_NATIVE_PIXMAP_KHR,
|
|
|
|
output->bo[i], NULL);
|
2011-12-08 20:05:46 +04:00
|
|
|
if (!output->image[i])
|
|
|
|
goto err_bufs;
|
2011-04-30 11:32:11 +04:00
|
|
|
|
2011-04-25 23:08:20 +04:00
|
|
|
ec->base.image_target_renderbuffer_storage(GL_RENDERBUFFER,
|
|
|
|
output->image[i]);
|
2011-04-30 11:32:11 +04:00
|
|
|
stride = gbm_bo_get_pitch(output->bo[i]);
|
|
|
|
handle = gbm_bo_get_handle(output->bo[i]).u32;
|
2010-06-14 19:54:00 +04:00
|
|
|
|
2011-03-02 13:14:59 +03:00
|
|
|
ret = drmModeAddFB(ec->drm.fd,
|
2011-06-21 19:16:58 +04:00
|
|
|
output->base.current->width,
|
|
|
|
output->base.current->height,
|
2011-10-24 21:13:22 +04:00
|
|
|
24, 32, stride, handle, &output->fb_id[i]);
|
2010-06-11 20:56:24 +04:00
|
|
|
if (ret) {
|
|
|
|
fprintf(stderr, "failed to add fb %d: %m\n", i);
|
2011-12-08 20:05:46 +04:00
|
|
|
goto err_bufs;
|
2010-06-11 20:56:24 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
output->current = 0;
|
|
|
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER,
|
|
|
|
GL_COLOR_ATTACHMENT0,
|
|
|
|
GL_RENDERBUFFER,
|
|
|
|
output->rbo[output->current]);
|
2011-03-02 13:14:59 +03:00
|
|
|
ret = drmModeSetCrtc(ec->drm.fd, output->crtc_id,
|
2010-06-11 20:56:24 +04:00
|
|
|
output->fb_id[output->current ^ 1], 0, 0,
|
2011-06-21 19:16:58 +04:00
|
|
|
&output->connector_id, 1,
|
|
|
|
&drm_mode->mode_info);
|
2010-06-11 20:56:24 +04:00
|
|
|
if (ret) {
|
|
|
|
fprintf(stderr, "failed to set mode: %m\n");
|
2011-12-08 20:05:46 +04:00
|
|
|
goto err_fb;
|
2010-06-11 20:56:24 +04:00
|
|
|
}
|
|
|
|
|
2012-02-29 21:53:50 +04:00
|
|
|
output->backlight = backlight_init(drm_device,
|
|
|
|
connector->connector_type);
|
|
|
|
if (output->backlight) {
|
|
|
|
output->base.set_backlight = drm_set_backlight;
|
|
|
|
output->base.backlight_current = drm_get_backlight(output);
|
|
|
|
}
|
|
|
|
|
Rename wayland-compositor to weston
This rename addresses a few problems around the split between core
Wayland and the wayland-demos repository.
1) Initially, we had one big repository with protocol code, sample
compositor and sample clients. We split that repository to make it
possible to implement the protocol without pulling in the sample/demo
code. At this point, the compositor is more than just a "demo" and
wayland-demos doesn't send the right message. The sample compositor
is a useful, self-contained project in it's own right, and we want to
move away from the "demos" label.
2) Another problem is that the wayland-demos compositor is often
called "the wayland compsitor", but it's really just one possible
compositor. Existing X11 compositors are expected to add Wayland
support and then gradually phase out/modularize the X11 support, for
example. Conversely, it's hard to talk about the wayland-demos
compositor specifically as opposed to, eg, the wayland protocol or a
wayland compositor in general.
We are also renaming the repo to weston, and the compositor
subdirectory to src/, to emphasize that the main "output" is the
compositor.
2012-01-03 19:29:47 +04:00
|
|
|
weston_output_init(&output->base, &ec->base, x, y,
|
2011-10-24 21:26:32 +04:00
|
|
|
connector->mmWidth, connector->mmHeight, 0);
|
|
|
|
|
|
|
|
wl_list_insert(ec->base.output_list.prev, &output->base.link);
|
|
|
|
|
2012-01-26 09:11:01 +04:00
|
|
|
output->scanout_buffer_destroy_listener.func =
|
|
|
|
output_handle_scanout_buffer_destroy;
|
|
|
|
output->pending_scanout_buffer_destroy_listener.func =
|
|
|
|
output_handle_pending_scanout_buffer_destroy;
|
|
|
|
|
2011-10-24 21:26:32 +04:00
|
|
|
output->pending_fs_surf_fb_id = 0;
|
2012-01-26 08:32:28 +04:00
|
|
|
output->base.repaint = drm_output_repaint;
|
2011-08-30 00:52:23 +04:00
|
|
|
output->base.destroy = drm_output_destroy;
|
2012-02-23 18:45:49 +04:00
|
|
|
output->base.assign_planes = drm_assign_planes;
|
2012-02-29 21:53:50 +04:00
|
|
|
output->base.set_dpms = drm_set_dpms;
|
2011-03-11 18:39:20 +03:00
|
|
|
|
2010-06-11 20:56:24 +04:00
|
|
|
return 0;
|
2011-12-08 20:05:45 +04:00
|
|
|
|
2011-12-08 20:05:46 +04:00
|
|
|
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);
|
2011-12-08 20:05:45 +04:00
|
|
|
err_free:
|
|
|
|
wl_list_for_each_safe(drm_mode, next, &output->base.mode_list,
|
|
|
|
base.link) {
|
|
|
|
wl_list_remove(&drm_mode->base.link);
|
|
|
|
free(drm_mode);
|
|
|
|
}
|
|
|
|
|
|
|
|
drmModeFreeCrtc(output->original_crtc);
|
|
|
|
ec->crtc_allocator &= ~(1 << output->crtc_id);
|
|
|
|
ec->connector_allocator &= ~(1 << output->connector_id);
|
|
|
|
|
|
|
|
free(output);
|
|
|
|
return -1;
|
2010-06-11 20:56:24 +04:00
|
|
|
}
|
|
|
|
|
2012-02-23 18:45:49 +04:00
|
|
|
static void
|
|
|
|
create_sprites(struct drm_compositor *ec)
|
|
|
|
{
|
|
|
|
struct drm_sprite *sprite;
|
|
|
|
drmModePlaneRes *plane_res;
|
|
|
|
drmModePlane *plane;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
plane_res = drmModeGetPlaneResources(ec->drm.fd);
|
|
|
|
if (!plane_res) {
|
|
|
|
fprintf(stderr, "failed to get plane resources: %s\n",
|
|
|
|
strerror(errno));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < plane_res->count_planes; i++) {
|
|
|
|
plane = drmModeGetPlane(ec->drm.fd, plane_res->planes[i]);
|
|
|
|
if (!plane)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
sprite = malloc(sizeof(*sprite) + ((sizeof(uint32_t)) *
|
|
|
|
plane->count_formats));
|
|
|
|
if (!sprite) {
|
|
|
|
fprintf(stderr, "%s: out of memory\n",
|
|
|
|
__func__);
|
|
|
|
free(plane);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(sprite, 0, sizeof *sprite);
|
|
|
|
|
|
|
|
sprite->possible_crtcs = plane->possible_crtcs;
|
|
|
|
sprite->plane_id = plane->plane_id;
|
|
|
|
sprite->surface = NULL;
|
|
|
|
sprite->pending_surface = NULL;
|
|
|
|
sprite->fb_id = 0;
|
|
|
|
sprite->pending_fb_id = 0;
|
|
|
|
sprite->destroy_listener.func = sprite_handle_buffer_destroy;
|
|
|
|
sprite->pending_destroy_listener.func =
|
|
|
|
sprite_handle_pending_buffer_destroy;
|
|
|
|
sprite->compositor = ec;
|
|
|
|
sprite->count_formats = plane->count_formats;
|
|
|
|
memcpy(sprite->formats, plane->formats,
|
|
|
|
plane->count_formats);
|
|
|
|
drmModeFreePlane(plane);
|
|
|
|
|
|
|
|
wl_list_insert(&ec->sprite_list, &sprite->link);
|
|
|
|
}
|
|
|
|
|
|
|
|
free(plane_res->planes);
|
|
|
|
free(plane_res);
|
|
|
|
}
|
|
|
|
|
2012-02-24 06:45:32 +04:00
|
|
|
static void
|
|
|
|
destroy_sprites(struct drm_compositor *compositor)
|
|
|
|
{
|
|
|
|
struct drm_sprite *sprite, *next;
|
|
|
|
struct drm_output *output;
|
|
|
|
|
|
|
|
output = container_of(compositor->base.output_list.next,
|
|
|
|
struct drm_output, base.link);
|
|
|
|
|
|
|
|
wl_list_for_each_safe(sprite, next, &compositor->sprite_list, link) {
|
|
|
|
drmModeSetPlane(compositor->drm.fd,
|
|
|
|
sprite->plane_id,
|
|
|
|
output->crtc_id, 0, 0,
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0);
|
|
|
|
drmModeRmFB(compositor->drm.fd, sprite->fb_id);
|
|
|
|
free(sprite);
|
|
|
|
}
|
|
|
|
}
|
2012-02-23 18:45:49 +04:00
|
|
|
|
2010-06-11 20:56:24 +04:00
|
|
|
static int
|
2012-02-29 21:53:50 +04:00
|
|
|
create_outputs(struct drm_compositor *ec, int option_connector,
|
|
|
|
struct udev_device *drm_device)
|
2010-06-11 20:56:24 +04:00
|
|
|
{
|
|
|
|
drmModeConnector *connector;
|
|
|
|
drmModeRes *resources;
|
|
|
|
int i;
|
2011-03-11 18:39:20 +03:00
|
|
|
int x = 0, y = 0;
|
2010-06-11 20:56:24 +04:00
|
|
|
|
2011-03-02 13:14:59 +03:00
|
|
|
resources = drmModeGetResources(ec->drm.fd);
|
2010-06-11 20:56:24 +04:00
|
|
|
if (!resources) {
|
|
|
|
fprintf(stderr, "drmModeGetResources failed\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2012-02-23 18:45:49 +04:00
|
|
|
ec->crtcs = calloc(resources->count_crtcs, sizeof(uint32_t));
|
|
|
|
if (!ec->crtcs)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
ec->num_crtcs = resources->count_crtcs;
|
|
|
|
memcpy(ec->crtcs, resources->crtcs, sizeof(uint32_t) * ec->num_crtcs);
|
|
|
|
|
2010-06-11 20:56:24 +04:00
|
|
|
for (i = 0; i < resources->count_connectors; i++) {
|
2011-08-30 13:38:26 +04:00
|
|
|
connector = drmModeGetConnector(ec->drm.fd,
|
|
|
|
resources->connectors[i]);
|
2010-06-11 20:56:24 +04:00
|
|
|
if (connector == NULL)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (connector->connection == DRM_MODE_CONNECTED &&
|
|
|
|
(option_connector == 0 ||
|
2011-08-02 15:03:54 +04:00
|
|
|
connector->connector_id == option_connector)) {
|
2011-03-11 18:39:20 +03:00
|
|
|
if (create_output_for_connector(ec, resources,
|
2012-02-29 21:53:50 +04:00
|
|
|
connector, x, y,
|
|
|
|
drm_device) < 0) {
|
2011-10-07 10:20:53 +04:00
|
|
|
drmModeFreeConnector(connector);
|
|
|
|
continue;
|
|
|
|
}
|
2010-06-11 20:56:24 +04:00
|
|
|
|
2011-08-02 15:03:54 +04:00
|
|
|
x += container_of(ec->base.output_list.prev,
|
Rename wayland-compositor to weston
This rename addresses a few problems around the split between core
Wayland and the wayland-demos repository.
1) Initially, we had one big repository with protocol code, sample
compositor and sample clients. We split that repository to make it
possible to implement the protocol without pulling in the sample/demo
code. At this point, the compositor is more than just a "demo" and
wayland-demos doesn't send the right message. The sample compositor
is a useful, self-contained project in it's own right, and we want to
move away from the "demos" label.
2) Another problem is that the wayland-demos compositor is often
called "the wayland compsitor", but it's really just one possible
compositor. Existing X11 compositors are expected to add Wayland
support and then gradually phase out/modularize the X11 support, for
example. Conversely, it's hard to talk about the wayland-demos
compositor specifically as opposed to, eg, the wayland protocol or a
wayland compositor in general.
We are also renaming the repo to weston, and the compositor
subdirectory to src/, to emphasize that the main "output" is the
compositor.
2012-01-03 19:29:47 +04:00
|
|
|
struct weston_output,
|
2011-08-02 15:03:54 +04:00
|
|
|
link)->current->width;
|
|
|
|
}
|
2011-03-11 18:39:20 +03:00
|
|
|
|
2010-06-11 20:56:24 +04:00
|
|
|
drmModeFreeConnector(connector);
|
|
|
|
}
|
|
|
|
|
2010-06-14 19:54:00 +04:00
|
|
|
if (wl_list_empty(&ec->base.output_list)) {
|
2010-06-11 20:56:24 +04:00
|
|
|
fprintf(stderr, "No currently active connector found.\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
drmModeFreeResources(resources);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-03-15 17:08:41 +03:00
|
|
|
static void
|
2012-02-29 21:53:50 +04:00
|
|
|
update_outputs(struct drm_compositor *ec, struct udev_device *drm_device)
|
2011-03-15 17:08:41 +03:00
|
|
|
{
|
|
|
|
drmModeConnector *connector;
|
|
|
|
drmModeRes *resources;
|
|
|
|
struct drm_output *output, *next;
|
|
|
|
int x = 0, y = 0;
|
|
|
|
int x_offset = 0, y_offset = 0;
|
|
|
|
uint32_t connected = 0, disconnects = 0;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
resources = drmModeGetResources(ec->drm.fd);
|
|
|
|
if (!resources) {
|
|
|
|
fprintf(stderr, "drmModeGetResources failed\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* collect new connects */
|
|
|
|
for (i = 0; i < resources->count_connectors; i++) {
|
2011-08-30 13:38:26 +04:00
|
|
|
int connector_id = resources->connectors[i];
|
|
|
|
|
|
|
|
connector = drmModeGetConnector(ec->drm.fd, connector_id);
|
2011-12-08 20:05:43 +04:00
|
|
|
if (connector == NULL)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (connector->connection != DRM_MODE_CONNECTED) {
|
|
|
|
drmModeFreeConnector(connector);
|
2011-03-15 17:08:41 +03:00
|
|
|
continue;
|
2011-12-08 20:05:43 +04:00
|
|
|
}
|
2011-03-15 17:08:41 +03:00
|
|
|
|
2011-08-30 13:38:26 +04:00
|
|
|
connected |= (1 << connector_id);
|
|
|
|
|
|
|
|
if (!(ec->connector_allocator & (1 << connector_id))) {
|
Rename wayland-compositor to weston
This rename addresses a few problems around the split between core
Wayland and the wayland-demos repository.
1) Initially, we had one big repository with protocol code, sample
compositor and sample clients. We split that repository to make it
possible to implement the protocol without pulling in the sample/demo
code. At this point, the compositor is more than just a "demo" and
wayland-demos doesn't send the right message. The sample compositor
is a useful, self-contained project in it's own right, and we want to
move away from the "demos" label.
2) Another problem is that the wayland-demos compositor is often
called "the wayland compsitor", but it's really just one possible
compositor. Existing X11 compositors are expected to add Wayland
support and then gradually phase out/modularize the X11 support, for
example. Conversely, it's hard to talk about the wayland-demos
compositor specifically as opposed to, eg, the wayland protocol or a
wayland compositor in general.
We are also renaming the repo to weston, and the compositor
subdirectory to src/, to emphasize that the main "output" is the
compositor.
2012-01-03 19:29:47 +04:00
|
|
|
struct weston_output *last =
|
2011-03-15 17:08:41 +03:00
|
|
|
container_of(ec->base.output_list.prev,
|
Rename wayland-compositor to weston
This rename addresses a few problems around the split between core
Wayland and the wayland-demos repository.
1) Initially, we had one big repository with protocol code, sample
compositor and sample clients. We split that repository to make it
possible to implement the protocol without pulling in the sample/demo
code. At this point, the compositor is more than just a "demo" and
wayland-demos doesn't send the right message. The sample compositor
is a useful, self-contained project in it's own right, and we want to
move away from the "demos" label.
2) Another problem is that the wayland-demos compositor is often
called "the wayland compsitor", but it's really just one possible
compositor. Existing X11 compositors are expected to add Wayland
support and then gradually phase out/modularize the X11 support, for
example. Conversely, it's hard to talk about the wayland-demos
compositor specifically as opposed to, eg, the wayland protocol or a
wayland compositor in general.
We are also renaming the repo to weston, and the compositor
subdirectory to src/, to emphasize that the main "output" is the
compositor.
2012-01-03 19:29:47 +04:00
|
|
|
struct weston_output, link);
|
2011-03-15 17:08:41 +03:00
|
|
|
|
|
|
|
/* XXX: not yet needed, we die with 0 outputs */
|
|
|
|
if (!wl_list_empty(&ec->base.output_list))
|
2011-08-30 13:38:26 +04:00
|
|
|
x = last->x + last->current->width;
|
2011-03-15 17:08:41 +03:00
|
|
|
else
|
|
|
|
x = 0;
|
|
|
|
y = 0;
|
|
|
|
create_output_for_connector(ec, resources,
|
2012-02-29 21:53:50 +04:00
|
|
|
connector, x, y,
|
|
|
|
drm_device);
|
2011-08-30 13:38:26 +04:00
|
|
|
printf("connector %d connected\n", connector_id);
|
|
|
|
|
2011-03-15 17:08:41 +03:00
|
|
|
}
|
|
|
|
drmModeFreeConnector(connector);
|
|
|
|
}
|
|
|
|
drmModeFreeResources(resources);
|
|
|
|
|
|
|
|
disconnects = ec->connector_allocator & ~connected;
|
|
|
|
if (disconnects) {
|
|
|
|
wl_list_for_each_safe(output, next, &ec->base.output_list,
|
|
|
|
base.link) {
|
|
|
|
if (x_offset != 0 || y_offset != 0) {
|
Rename wayland-compositor to weston
This rename addresses a few problems around the split between core
Wayland and the wayland-demos repository.
1) Initially, we had one big repository with protocol code, sample
compositor and sample clients. We split that repository to make it
possible to implement the protocol without pulling in the sample/demo
code. At this point, the compositor is more than just a "demo" and
wayland-demos doesn't send the right message. The sample compositor
is a useful, self-contained project in it's own right, and we want to
move away from the "demos" label.
2) Another problem is that the wayland-demos compositor is often
called "the wayland compsitor", but it's really just one possible
compositor. Existing X11 compositors are expected to add Wayland
support and then gradually phase out/modularize the X11 support, for
example. Conversely, it's hard to talk about the wayland-demos
compositor specifically as opposed to, eg, the wayland protocol or a
wayland compositor in general.
We are also renaming the repo to weston, and the compositor
subdirectory to src/, to emphasize that the main "output" is the
compositor.
2012-01-03 19:29:47 +04:00
|
|
|
weston_output_move(&output->base,
|
2011-03-15 17:08:41 +03:00
|
|
|
output->base.x - x_offset,
|
|
|
|
output->base.y - y_offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (disconnects & (1 << output->connector_id)) {
|
|
|
|
disconnects &= ~(1 << output->connector_id);
|
|
|
|
printf("connector %d disconnected\n",
|
|
|
|
output->connector_id);
|
2011-06-21 19:16:58 +04:00
|
|
|
x_offset += output->base.current->width;
|
2011-08-30 13:44:56 +04:00
|
|
|
drm_output_destroy(&output->base);
|
2011-03-15 17:08:41 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* FIXME: handle zero outputs, without terminating */
|
|
|
|
if (ec->connector_allocator == 0)
|
|
|
|
wl_display_terminate(ec->base.wl_display);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
udev_event_is_hotplug(struct udev_device *device)
|
|
|
|
{
|
|
|
|
struct udev_list_entry *list, *hotplug_entry;
|
2011-08-30 13:38:26 +04:00
|
|
|
|
2011-03-15 17:08:41 +03:00
|
|
|
list = udev_device_get_properties_list_entry(device);
|
|
|
|
|
|
|
|
hotplug_entry = udev_list_entry_get_by_name(list, "HOTPLUG");
|
|
|
|
if (hotplug_entry == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return strcmp(udev_list_entry_get_value(hotplug_entry), "1") == 0;
|
|
|
|
}
|
|
|
|
|
2011-04-22 20:27:57 +04:00
|
|
|
static int
|
2011-03-15 17:08:41 +03:00
|
|
|
udev_drm_event(int fd, uint32_t mask, void *data)
|
|
|
|
{
|
|
|
|
struct drm_compositor *ec = data;
|
|
|
|
struct udev_device *event;
|
|
|
|
|
|
|
|
event = udev_monitor_receive_device(ec->udev_monitor);
|
2011-08-30 13:38:26 +04:00
|
|
|
|
2011-03-15 17:08:41 +03:00
|
|
|
if (udev_event_is_hotplug(event))
|
2012-02-29 21:53:50 +04:00
|
|
|
update_outputs(ec, event);
|
2011-03-15 17:08:41 +03:00
|
|
|
|
|
|
|
udev_device_unref(event);
|
2011-04-22 20:27:57 +04:00
|
|
|
|
|
|
|
return 1;
|
2011-03-15 17:08:41 +03:00
|
|
|
}
|
|
|
|
|
2010-12-02 00:52:15 +03:00
|
|
|
static void
|
Rename wayland-compositor to weston
This rename addresses a few problems around the split between core
Wayland and the wayland-demos repository.
1) Initially, we had one big repository with protocol code, sample
compositor and sample clients. We split that repository to make it
possible to implement the protocol without pulling in the sample/demo
code. At this point, the compositor is more than just a "demo" and
wayland-demos doesn't send the right message. The sample compositor
is a useful, self-contained project in it's own right, and we want to
move away from the "demos" label.
2) Another problem is that the wayland-demos compositor is often
called "the wayland compsitor", but it's really just one possible
compositor. Existing X11 compositors are expected to add Wayland
support and then gradually phase out/modularize the X11 support, for
example. Conversely, it's hard to talk about the wayland-demos
compositor specifically as opposed to, eg, the wayland protocol or a
wayland compositor in general.
We are also renaming the repo to weston, and the compositor
subdirectory to src/, to emphasize that the main "output" is the
compositor.
2012-01-03 19:29:47 +04:00
|
|
|
drm_destroy(struct weston_compositor *ec)
|
2010-12-02 00:52:15 +03:00
|
|
|
{
|
|
|
|
struct drm_compositor *d = (struct drm_compositor *) ec;
|
Rename wayland-compositor to weston
This rename addresses a few problems around the split between core
Wayland and the wayland-demos repository.
1) Initially, we had one big repository with protocol code, sample
compositor and sample clients. We split that repository to make it
possible to implement the protocol without pulling in the sample/demo
code. At this point, the compositor is more than just a "demo" and
wayland-demos doesn't send the right message. The sample compositor
is a useful, self-contained project in it's own right, and we want to
move away from the "demos" label.
2) Another problem is that the wayland-demos compositor is often
called "the wayland compsitor", but it's really just one possible
compositor. Existing X11 compositors are expected to add Wayland
support and then gradually phase out/modularize the X11 support, for
example. Conversely, it's hard to talk about the wayland-demos
compositor specifically as opposed to, eg, the wayland protocol or a
wayland compositor in general.
We are also renaming the repo to weston, and the compositor
subdirectory to src/, to emphasize that the main "output" is the
compositor.
2012-01-03 19:29:47 +04:00
|
|
|
struct weston_input_device *input, *next;
|
2010-12-02 00:52:15 +03:00
|
|
|
|
Rename wayland-compositor to weston
This rename addresses a few problems around the split between core
Wayland and the wayland-demos repository.
1) Initially, we had one big repository with protocol code, sample
compositor and sample clients. We split that repository to make it
possible to implement the protocol without pulling in the sample/demo
code. At this point, the compositor is more than just a "demo" and
wayland-demos doesn't send the right message. The sample compositor
is a useful, self-contained project in it's own right, and we want to
move away from the "demos" label.
2) Another problem is that the wayland-demos compositor is often
called "the wayland compsitor", but it's really just one possible
compositor. Existing X11 compositors are expected to add Wayland
support and then gradually phase out/modularize the X11 support, for
example. Conversely, it's hard to talk about the wayland-demos
compositor specifically as opposed to, eg, the wayland protocol or a
wayland compositor in general.
We are also renaming the repo to weston, and the compositor
subdirectory to src/, to emphasize that the main "output" is the
compositor.
2012-01-03 19:29:47 +04:00
|
|
|
weston_compositor_shutdown(ec);
|
2011-08-30 00:52:23 +04:00
|
|
|
gbm_device_destroy(d->gbm);
|
2012-02-24 06:45:32 +04:00
|
|
|
destroy_sprites(d);
|
2012-01-18 21:38:33 +04:00
|
|
|
drmDropMaster(d->drm.fd);
|
2011-01-14 22:59:13 +03:00
|
|
|
tty_destroy(d->tty);
|
2010-12-02 00:52:15 +03:00
|
|
|
|
2011-12-19 01:52:18 +04:00
|
|
|
wl_list_for_each_safe(input, next, &ec->input_device_list, link)
|
|
|
|
evdev_input_destroy(input);
|
|
|
|
|
2011-01-14 22:59:13 +03:00
|
|
|
free(d);
|
2010-12-02 00:52:15 +03:00
|
|
|
}
|
|
|
|
|
2012-01-18 20:48:46 +04:00
|
|
|
static void
|
|
|
|
drm_compositor_set_modes(struct drm_compositor *compositor)
|
|
|
|
{
|
|
|
|
struct drm_output *output;
|
|
|
|
struct drm_mode *drm_mode;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
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->connector_id, 1,
|
|
|
|
&drm_mode->mode_info);
|
|
|
|
if (ret < 0) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"failed to set mode %dx%d for output at %d,%d: %m",
|
|
|
|
drm_mode->base.width, drm_mode->base.height,
|
|
|
|
output->base.x, output->base.y);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-06 23:15:37 +04:00
|
|
|
static void
|
Rename wayland-compositor to weston
This rename addresses a few problems around the split between core
Wayland and the wayland-demos repository.
1) Initially, we had one big repository with protocol code, sample
compositor and sample clients. We split that repository to make it
possible to implement the protocol without pulling in the sample/demo
code. At this point, the compositor is more than just a "demo" and
wayland-demos doesn't send the right message. The sample compositor
is a useful, self-contained project in it's own right, and we want to
move away from the "demos" label.
2) Another problem is that the wayland-demos compositor is often
called "the wayland compsitor", but it's really just one possible
compositor. Existing X11 compositors are expected to add Wayland
support and then gradually phase out/modularize the X11 support, for
example. Conversely, it's hard to talk about the wayland-demos
compositor specifically as opposed to, eg, the wayland protocol or a
wayland compositor in general.
We are also renaming the repo to weston, and the compositor
subdirectory to src/, to emphasize that the main "output" is the
compositor.
2012-01-03 19:29:47 +04:00
|
|
|
vt_func(struct weston_compositor *compositor, int event)
|
2011-05-06 23:15:37 +04:00
|
|
|
{
|
|
|
|
struct drm_compositor *ec = (struct drm_compositor *) compositor;
|
Rename wayland-compositor to weston
This rename addresses a few problems around the split between core
Wayland and the wayland-demos repository.
1) Initially, we had one big repository with protocol code, sample
compositor and sample clients. We split that repository to make it
possible to implement the protocol without pulling in the sample/demo
code. At this point, the compositor is more than just a "demo" and
wayland-demos doesn't send the right message. The sample compositor
is a useful, self-contained project in it's own right, and we want to
move away from the "demos" label.
2) Another problem is that the wayland-demos compositor is often
called "the wayland compsitor", but it's really just one possible
compositor. Existing X11 compositors are expected to add Wayland
support and then gradually phase out/modularize the X11 support, for
example. Conversely, it's hard to talk about the wayland-demos
compositor specifically as opposed to, eg, the wayland protocol or a
wayland compositor in general.
We are also renaming the repo to weston, and the compositor
subdirectory to src/, to emphasize that the main "output" is the
compositor.
2012-01-03 19:29:47 +04:00
|
|
|
struct weston_output *output;
|
|
|
|
struct weston_input_device *input;
|
2012-02-24 06:45:32 +04:00
|
|
|
struct drm_sprite *sprite;
|
|
|
|
struct drm_output *drm_output;
|
2011-05-06 23:15:37 +04:00
|
|
|
|
|
|
|
switch (event) {
|
|
|
|
case TTY_ENTER_VT:
|
|
|
|
compositor->focus = 1;
|
2012-01-16 19:52:52 +04:00
|
|
|
if (drmSetMaster(ec->drm.fd)) {
|
|
|
|
fprintf(stderr, "failed to set master: %m\n");
|
|
|
|
wl_display_terminate(compositor->wl_display);
|
|
|
|
}
|
2011-12-02 15:07:27 +04:00
|
|
|
compositor->state = ec->prev_state;
|
2012-01-18 20:48:46 +04:00
|
|
|
drm_compositor_set_modes(ec);
|
Rename wayland-compositor to weston
This rename addresses a few problems around the split between core
Wayland and the wayland-demos repository.
1) Initially, we had one big repository with protocol code, sample
compositor and sample clients. We split that repository to make it
possible to implement the protocol without pulling in the sample/demo
code. At this point, the compositor is more than just a "demo" and
wayland-demos doesn't send the right message. The sample compositor
is a useful, self-contained project in it's own right, and we want to
move away from the "demos" label.
2) Another problem is that the wayland-demos compositor is often
called "the wayland compsitor", but it's really just one possible
compositor. Existing X11 compositors are expected to add Wayland
support and then gradually phase out/modularize the X11 support, for
example. Conversely, it's hard to talk about the wayland-demos
compositor specifically as opposed to, eg, the wayland protocol or a
wayland compositor in general.
We are also renaming the repo to weston, and the compositor
subdirectory to src/, to emphasize that the main "output" is the
compositor.
2012-01-03 19:29:47 +04:00
|
|
|
weston_compositor_damage_all(compositor);
|
2011-12-19 02:32:48 +04:00
|
|
|
wl_list_for_each(input, &compositor->input_device_list, link)
|
|
|
|
evdev_add_devices(ec->udev, input);
|
2011-05-06 23:15:37 +04:00
|
|
|
break;
|
|
|
|
case TTY_LEAVE_VT:
|
|
|
|
compositor->focus = 0;
|
2011-12-02 15:07:27 +04:00
|
|
|
ec->prev_state = compositor->state;
|
Rename wayland-compositor to weston
This rename addresses a few problems around the split between core
Wayland and the wayland-demos repository.
1) Initially, we had one big repository with protocol code, sample
compositor and sample clients. We split that repository to make it
possible to implement the protocol without pulling in the sample/demo
code. At this point, the compositor is more than just a "demo" and
wayland-demos doesn't send the right message. The sample compositor
is a useful, self-contained project in it's own right, and we want to
move away from the "demos" label.
2) Another problem is that the wayland-demos compositor is often
called "the wayland compsitor", but it's really just one possible
compositor. Existing X11 compositors are expected to add Wayland
support and then gradually phase out/modularize the X11 support, for
example. Conversely, it's hard to talk about the wayland-demos
compositor specifically as opposed to, eg, the wayland protocol or a
wayland compositor in general.
We are also renaming the repo to weston, and the compositor
subdirectory to src/, to emphasize that the main "output" is the
compositor.
2012-01-03 19:29:47 +04:00
|
|
|
compositor->state = WESTON_COMPOSITOR_SLEEPING;
|
2011-05-06 23:38:28 +04:00
|
|
|
|
2012-01-18 20:50:31 +04:00
|
|
|
/* If we have a repaint scheduled (either from a
|
|
|
|
* pending pageflip or the idle handler), make sure we
|
|
|
|
* cancel that so we don't try to pageflip when we're
|
|
|
|
* vt switched away. The SLEEPING state will prevent
|
|
|
|
* further attemps at repainting. When we switch
|
|
|
|
* back, we schedule a repaint, which will process
|
|
|
|
* pending frame callbacks. */
|
|
|
|
|
|
|
|
wl_list_for_each(output, &ec->base.output_list, link) {
|
|
|
|
output->repaint_needed = 0;
|
|
|
|
drm_output_set_cursor(output, NULL);
|
|
|
|
}
|
|
|
|
|
2012-02-24 06:45:32 +04:00
|
|
|
drm_output = container_of(ec->base.output_list.next,
|
|
|
|
struct drm_output, base.link);
|
|
|
|
|
|
|
|
wl_list_for_each(sprite, &ec->sprite_list, link)
|
|
|
|
drmModeSetPlane(ec->drm.fd,
|
|
|
|
sprite->plane_id,
|
|
|
|
drm_output->crtc_id, 0, 0,
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0);
|
|
|
|
|
2011-12-19 02:32:48 +04:00
|
|
|
wl_list_for_each(input, &compositor->input_device_list, link)
|
|
|
|
evdev_remove_devices(input);
|
2011-05-06 23:38:28 +04:00
|
|
|
|
2012-01-16 19:52:52 +04:00
|
|
|
if (drmDropMaster(ec->drm.fd) < 0)
|
|
|
|
fprintf(stderr, "failed to drop master: %m\n");
|
|
|
|
|
2011-05-06 23:15:37 +04:00
|
|
|
break;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2011-07-16 05:28:38 +04:00
|
|
|
static const char default_seat[] = "seat0";
|
|
|
|
|
Rename wayland-compositor to weston
This rename addresses a few problems around the split between core
Wayland and the wayland-demos repository.
1) Initially, we had one big repository with protocol code, sample
compositor and sample clients. We split that repository to make it
possible to implement the protocol without pulling in the sample/demo
code. At this point, the compositor is more than just a "demo" and
wayland-demos doesn't send the right message. The sample compositor
is a useful, self-contained project in it's own right, and we want to
move away from the "demos" label.
2) Another problem is that the wayland-demos compositor is often
called "the wayland compsitor", but it's really just one possible
compositor. Existing X11 compositors are expected to add Wayland
support and then gradually phase out/modularize the X11 support, for
example. Conversely, it's hard to talk about the wayland-demos
compositor specifically as opposed to, eg, the wayland protocol or a
wayland compositor in general.
We are also renaming the repo to weston, and the compositor
subdirectory to src/, to emphasize that the main "output" is the
compositor.
2012-01-03 19:29:47 +04:00
|
|
|
static struct weston_compositor *
|
2011-07-16 05:28:38 +04:00
|
|
|
drm_compositor_create(struct wl_display *display,
|
2011-09-01 23:58:17 +04:00
|
|
|
int connector, const char *seat, int tty)
|
2010-06-11 20:56:24 +04:00
|
|
|
{
|
2010-06-14 19:54:00 +04:00
|
|
|
struct drm_compositor *ec;
|
2010-06-11 20:56:24 +04:00
|
|
|
struct udev_enumerate *e;
|
2011-08-30 13:38:26 +04:00
|
|
|
struct udev_list_entry *entry;
|
2011-07-16 05:28:38 +04:00
|
|
|
struct udev_device *device, *drm_device;
|
|
|
|
const char *path, *device_seat;
|
2010-06-11 20:56:24 +04:00
|
|
|
struct wl_event_loop *loop;
|
|
|
|
|
2010-06-14 19:54:00 +04:00
|
|
|
ec = malloc(sizeof *ec);
|
|
|
|
if (ec == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
memset(ec, 0, sizeof *ec);
|
2010-06-11 20:56:24 +04:00
|
|
|
ec->udev = udev_new();
|
|
|
|
if (ec->udev == NULL) {
|
|
|
|
fprintf(stderr, "failed to initialize udev context\n");
|
2010-06-14 19:54:00 +04:00
|
|
|
return NULL;
|
2010-06-11 20:56:24 +04:00
|
|
|
}
|
|
|
|
|
2012-01-15 23:29:09 +04:00
|
|
|
ec->base.wl_display = display;
|
|
|
|
ec->tty = tty_create(&ec->base, vt_func, tty);
|
|
|
|
if (!ec->tty) {
|
|
|
|
fprintf(stderr, "failed to initialize tty\n");
|
|
|
|
free(ec);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-06-11 20:56:24 +04:00
|
|
|
e = udev_enumerate_new(ec->udev);
|
2010-06-14 19:54:00 +04:00
|
|
|
udev_enumerate_add_match_subsystem(e, "drm");
|
2011-10-07 10:23:22 +04:00
|
|
|
udev_enumerate_add_match_sysname(e, "card[0-9]*");
|
2011-07-16 05:28:38 +04:00
|
|
|
|
2011-08-30 13:38:26 +04:00
|
|
|
udev_enumerate_scan_devices(e);
|
2011-07-16 05:28:38 +04:00
|
|
|
drm_device = NULL;
|
2011-08-30 13:38:26 +04:00
|
|
|
udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) {
|
2010-06-11 20:56:24 +04:00
|
|
|
path = udev_list_entry_get_name(entry);
|
|
|
|
device = udev_device_new_from_syspath(ec->udev, path);
|
2011-08-30 13:38:26 +04:00
|
|
|
device_seat =
|
2011-07-16 05:28:38 +04:00
|
|
|
udev_device_get_property_value(device, "ID_SEAT");
|
|
|
|
if (!device_seat)
|
|
|
|
device_seat = default_seat;
|
|
|
|
if (strcmp(device_seat, seat) == 0) {
|
|
|
|
drm_device = device;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
udev_device_unref(device);
|
2010-06-11 20:56:24 +04:00
|
|
|
}
|
2011-07-16 05:28:38 +04:00
|
|
|
|
|
|
|
if (drm_device == NULL) {
|
2010-06-14 19:54:00 +04:00
|
|
|
fprintf(stderr, "no drm device found\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
2010-06-11 20:56:24 +04:00
|
|
|
|
2011-07-16 05:28:38 +04:00
|
|
|
if (init_egl(ec, drm_device) < 0) {
|
2010-06-14 19:54:00 +04:00
|
|
|
fprintf(stderr, "failed to initialize egl\n");
|
|
|
|
return NULL;
|
2010-06-11 20:56:24 +04:00
|
|
|
}
|
2011-01-15 00:20:21 +03:00
|
|
|
|
|
|
|
ec->base.destroy = drm_destroy;
|
2011-04-20 13:02:58 +04:00
|
|
|
|
2011-01-15 00:20:21 +03:00
|
|
|
ec->base.focus = 1;
|
|
|
|
|
Rename wayland-compositor to weston
This rename addresses a few problems around the split between core
Wayland and the wayland-demos repository.
1) Initially, we had one big repository with protocol code, sample
compositor and sample clients. We split that repository to make it
possible to implement the protocol without pulling in the sample/demo
code. At this point, the compositor is more than just a "demo" and
wayland-demos doesn't send the right message. The sample compositor
is a useful, self-contained project in it's own right, and we want to
move away from the "demos" label.
2) Another problem is that the wayland-demos compositor is often
called "the wayland compsitor", but it's really just one possible
compositor. Existing X11 compositors are expected to add Wayland
support and then gradually phase out/modularize the X11 support, for
example. Conversely, it's hard to talk about the wayland-demos
compositor specifically as opposed to, eg, the wayland protocol or a
wayland compositor in general.
We are also renaming the repo to weston, and the compositor
subdirectory to src/, to emphasize that the main "output" is the
compositor.
2012-01-03 19:29:47 +04:00
|
|
|
ec->prev_state = WESTON_COMPOSITOR_ACTIVE;
|
2011-12-02 15:07:27 +04:00
|
|
|
|
2011-02-18 18:54:55 +03:00
|
|
|
glGenFramebuffers(1, &ec->base.fbo);
|
|
|
|
glBindFramebuffer(GL_FRAMEBUFFER, ec->base.fbo);
|
|
|
|
|
2011-04-30 00:14:54 +04:00
|
|
|
/* Can't init base class until we have a current egl context */
|
Rename wayland-compositor to weston
This rename addresses a few problems around the split between core
Wayland and the wayland-demos repository.
1) Initially, we had one big repository with protocol code, sample
compositor and sample clients. We split that repository to make it
possible to implement the protocol without pulling in the sample/demo
code. At this point, the compositor is more than just a "demo" and
wayland-demos doesn't send the right message. The sample compositor
is a useful, self-contained project in it's own right, and we want to
move away from the "demos" label.
2) Another problem is that the wayland-demos compositor is often
called "the wayland compsitor", but it's really just one possible
compositor. Existing X11 compositors are expected to add Wayland
support and then gradually phase out/modularize the X11 support, for
example. Conversely, it's hard to talk about the wayland-demos
compositor specifically as opposed to, eg, the wayland protocol or a
wayland compositor in general.
We are also renaming the repo to weston, and the compositor
subdirectory to src/, to emphasize that the main "output" is the
compositor.
2012-01-03 19:29:47 +04:00
|
|
|
if (weston_compositor_init(&ec->base, display) < 0)
|
2011-04-30 00:14:54 +04:00
|
|
|
return NULL;
|
|
|
|
|
2012-02-23 18:45:49 +04:00
|
|
|
wl_list_init(&ec->sprite_list);
|
|
|
|
create_sprites(ec);
|
|
|
|
|
2012-02-29 21:53:50 +04:00
|
|
|
if (create_outputs(ec, connector, drm_device) < 0) {
|
2010-06-14 19:54:00 +04:00
|
|
|
fprintf(stderr, "failed to create output for %s\n", path);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-02-29 21:53:50 +04:00
|
|
|
udev_device_unref(drm_device);
|
2011-10-07 10:27:26 +04:00
|
|
|
udev_enumerate_unref(e);
|
|
|
|
path = NULL;
|
|
|
|
|
2011-12-19 03:14:03 +04:00
|
|
|
evdev_input_create(&ec->base, ec->udev, seat);
|
2010-06-11 20:56:24 +04:00
|
|
|
|
2010-06-14 19:54:00 +04:00
|
|
|
loop = wl_display_get_event_loop(ec->base.wl_display);
|
|
|
|
ec->drm_source =
|
2011-03-02 13:14:59 +03:00
|
|
|
wl_event_loop_add_fd(loop, ec->drm.fd,
|
2010-06-14 19:54:00 +04:00
|
|
|
WL_EVENT_READABLE, on_drm_input, ec);
|
2010-06-11 20:56:24 +04:00
|
|
|
|
2011-03-15 17:08:41 +03:00
|
|
|
ec->udev_monitor = udev_monitor_new_from_netlink(ec->udev, "udev");
|
|
|
|
if (ec->udev_monitor == NULL) {
|
|
|
|
fprintf(stderr, "failed to intialize udev monitor\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
udev_monitor_filter_add_match_subsystem_devtype(ec->udev_monitor,
|
|
|
|
"drm", NULL);
|
|
|
|
ec->udev_drm_source =
|
2011-08-30 13:38:26 +04:00
|
|
|
wl_event_loop_add_fd(loop,
|
|
|
|
udev_monitor_get_fd(ec->udev_monitor),
|
2011-03-15 17:08:41 +03:00
|
|
|
WL_EVENT_READABLE, udev_drm_event, ec);
|
|
|
|
|
|
|
|
if (udev_monitor_enable_receiving(ec->udev_monitor) < 0) {
|
|
|
|
fprintf(stderr, "failed to enable udev-monitor receiving\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-06-14 19:54:00 +04:00
|
|
|
return &ec->base;
|
2010-06-11 20:56:24 +04:00
|
|
|
}
|
2011-05-03 06:09:20 +04:00
|
|
|
|
Rename wayland-compositor to weston
This rename addresses a few problems around the split between core
Wayland and the wayland-demos repository.
1) Initially, we had one big repository with protocol code, sample
compositor and sample clients. We split that repository to make it
possible to implement the protocol without pulling in the sample/demo
code. At this point, the compositor is more than just a "demo" and
wayland-demos doesn't send the right message. The sample compositor
is a useful, self-contained project in it's own right, and we want to
move away from the "demos" label.
2) Another problem is that the wayland-demos compositor is often
called "the wayland compsitor", but it's really just one possible
compositor. Existing X11 compositors are expected to add Wayland
support and then gradually phase out/modularize the X11 support, for
example. Conversely, it's hard to talk about the wayland-demos
compositor specifically as opposed to, eg, the wayland protocol or a
wayland compositor in general.
We are also renaming the repo to weston, and the compositor
subdirectory to src/, to emphasize that the main "output" is the
compositor.
2012-01-03 19:29:47 +04:00
|
|
|
struct weston_compositor *
|
2011-05-06 22:52:41 +04:00
|
|
|
backend_init(struct wl_display *display, char *options);
|
|
|
|
|
Rename wayland-compositor to weston
This rename addresses a few problems around the split between core
Wayland and the wayland-demos repository.
1) Initially, we had one big repository with protocol code, sample
compositor and sample clients. We split that repository to make it
possible to implement the protocol without pulling in the sample/demo
code. At this point, the compositor is more than just a "demo" and
wayland-demos doesn't send the right message. The sample compositor
is a useful, self-contained project in it's own right, and we want to
move away from the "demos" label.
2) Another problem is that the wayland-demos compositor is often
called "the wayland compsitor", but it's really just one possible
compositor. Existing X11 compositors are expected to add Wayland
support and then gradually phase out/modularize the X11 support, for
example. Conversely, it's hard to talk about the wayland-demos
compositor specifically as opposed to, eg, the wayland protocol or a
wayland compositor in general.
We are also renaming the repo to weston, and the compositor
subdirectory to src/, to emphasize that the main "output" is the
compositor.
2012-01-03 19:29:47 +04:00
|
|
|
WL_EXPORT struct weston_compositor *
|
2011-05-03 06:09:20 +04:00
|
|
|
backend_init(struct wl_display *display, char *options)
|
|
|
|
{
|
2011-05-04 23:08:04 +04:00
|
|
|
int connector = 0, i;
|
2011-07-16 05:28:38 +04:00
|
|
|
const char *seat;
|
2011-05-03 06:09:20 +04:00
|
|
|
char *p, *value;
|
2012-01-15 23:27:10 +04:00
|
|
|
int tty = 0;
|
2011-05-03 06:09:20 +04:00
|
|
|
|
2011-09-01 23:58:17 +04:00
|
|
|
static char * const tokens[] = { "connector", "seat", "tty", NULL };
|
2011-08-30 13:38:26 +04:00
|
|
|
|
2011-05-03 06:09:20 +04:00
|
|
|
p = options;
|
2011-07-16 05:28:38 +04:00
|
|
|
seat = default_seat;
|
2011-05-03 06:09:20 +04:00
|
|
|
while (i = getsubopt(&p, tokens, &value), i != -1) {
|
|
|
|
switch (i) {
|
|
|
|
case 0:
|
2011-05-04 23:08:04 +04:00
|
|
|
connector = strtol(value, NULL, 0);
|
2011-05-03 06:09:20 +04:00
|
|
|
break;
|
2011-07-16 05:28:38 +04:00
|
|
|
case 1:
|
|
|
|
seat = value;
|
|
|
|
break;
|
2011-09-01 23:58:17 +04:00
|
|
|
case 2:
|
|
|
|
tty = strtol(value, NULL, 0);
|
|
|
|
break;
|
2011-05-03 06:09:20 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-01 23:58:17 +04:00
|
|
|
return drm_compositor_create(display, connector, seat, tty);
|
2011-05-03 06:09:20 +04:00
|
|
|
}
|