mirror of
https://gitlab.freedesktop.org/wayland/wayland.git
synced 2025-10-29 05:40:16 -04:00
Update to use new eagle API and drm page flipping
This commit is contained in:
parent
8da19acab7
commit
01f941bfda
1 changed files with 85 additions and 50 deletions
|
|
@ -30,6 +30,7 @@
|
|||
#include <math.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/vt.h>
|
||||
#include <xf86drm.h>
|
||||
#include <xf86drmMode.h>
|
||||
#include <time.h>
|
||||
|
||||
|
|
@ -71,9 +72,11 @@ struct wlsc_output {
|
|||
int32_t x, y, width, height;
|
||||
|
||||
drmModeModeInfo *mode;
|
||||
uint32_t fb_id;
|
||||
uint32_t crtc_id;
|
||||
uint32_t connector_id;
|
||||
|
||||
uint32_t fb_id[2];
|
||||
uint32_t current;
|
||||
};
|
||||
|
||||
struct wlsc_input_device {
|
||||
|
|
@ -126,6 +129,7 @@ struct wlsc_compositor {
|
|||
int repaint_on_timeout;
|
||||
struct timespec previous_swap;
|
||||
uint32_t current_frame;
|
||||
struct wl_event_source *drm_source;
|
||||
|
||||
uint32_t meta_state;
|
||||
struct wl_list animate_list;
|
||||
|
|
@ -582,6 +586,34 @@ wlsc_vector_scalar(struct wlsc_vector *v1, GLdouble s)
|
|||
v1->z *= s;
|
||||
}
|
||||
|
||||
static void
|
||||
page_flip_handler(int fd, unsigned int frame,
|
||||
unsigned int sec, unsigned int usec, void *data)
|
||||
{
|
||||
struct wlsc_output *output = data;
|
||||
struct wlsc_animate *animate, *next;
|
||||
struct wlsc_compositor *compositor = output->compositor;
|
||||
uint32_t msecs;
|
||||
|
||||
msecs = sec * 1000 + usec / 1000;
|
||||
wl_display_post_frame(compositor->wl_display,
|
||||
&compositor->base,
|
||||
compositor->current_frame, msecs);
|
||||
|
||||
wl_event_source_timer_update(compositor->timer_source, 10);
|
||||
compositor->repaint_on_timeout = 1;
|
||||
|
||||
animate = container_of(compositor->animate_list.next, struct wlsc_animate, link);
|
||||
while (&animate->link != &compositor->animate_list) {
|
||||
next = container_of(animate->link.next,
|
||||
struct wlsc_animate, link);
|
||||
animate->animate(animate, compositor, compositor->current_frame, msecs);
|
||||
animate = next;
|
||||
}
|
||||
|
||||
compositor->current_frame++;
|
||||
}
|
||||
|
||||
static void
|
||||
repaint_output(struct wlsc_output *output)
|
||||
{
|
||||
|
|
@ -589,6 +621,7 @@ repaint_output(struct wlsc_output *output)
|
|||
struct wlsc_surface *es;
|
||||
struct wlsc_input_device *eid;
|
||||
double s = 3000;
|
||||
int fd;
|
||||
|
||||
if (!eglMakeCurrent(ec->display, output->surface, output->surface, ec->context)) {
|
||||
fprintf(stderr, "failed to make context current\n");
|
||||
|
|
@ -628,7 +661,10 @@ repaint_output(struct wlsc_output *output)
|
|||
struct wlsc_input_device, link);
|
||||
}
|
||||
|
||||
eglSwapBuffers(ec->display, output->surface);
|
||||
fd = eglGetDisplayFD(ec->display);
|
||||
output->current ^= 1;
|
||||
eglBindColorBuffer(ec->display, output->surface, output->current);
|
||||
drmModePageFlip(fd, output->crtc_id, output->fb_id[output->current ^ 1], output);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -636,9 +672,6 @@ repaint(void *data)
|
|||
{
|
||||
struct wlsc_compositor *ec = data;
|
||||
struct wlsc_output *output;
|
||||
struct wlsc_animate *animate, *next;
|
||||
struct timespec ts;
|
||||
uint32_t msecs;
|
||||
|
||||
if (!ec->repaint_needed) {
|
||||
ec->repaint_on_timeout = 0;
|
||||
|
|
@ -653,24 +686,6 @@ repaint(void *data)
|
|||
}
|
||||
|
||||
ec->repaint_needed = 0;
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
msecs = ts.tv_sec * 1000 + ts.tv_nsec / (1000 * 1000);
|
||||
wl_display_post_frame(ec->wl_display, &ec->base,
|
||||
ec->current_frame, msecs);
|
||||
|
||||
wl_event_source_timer_update(ec->timer_source, 10);
|
||||
ec->repaint_on_timeout = 1;
|
||||
|
||||
animate = container_of(ec->animate_list.next, struct wlsc_animate, link);
|
||||
while (&animate->link != &ec->animate_list) {
|
||||
next = container_of(animate->link.next,
|
||||
struct wlsc_animate, link);
|
||||
animate->animate(animate, ec, ec->current_frame, msecs);
|
||||
animate = next;
|
||||
}
|
||||
|
||||
ec->current_frame++;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -759,16 +774,16 @@ surface_copy(struct wl_client *client,
|
|||
struct wlsc_compositor *ec = es->compositor;
|
||||
EGLSurface src;
|
||||
|
||||
/* FIXME: glCopyPixels should work, but then we'll have to
|
||||
* call eglMakeCurrent to set up the src and dest surfaces
|
||||
* first. This seems cheaper, but maybe there's a better way
|
||||
* to accomplish this. */
|
||||
|
||||
src = eglCreateSurfaceForName(ec->display, ec->config,
|
||||
name, x + width, y + height, stride, NULL);
|
||||
|
||||
eglCopyNativeBuffers(ec->display, es->surface, GL_FRONT_LEFT, dst_x, dst_y,
|
||||
src, GL_FRONT_LEFT, x, y, width, height);
|
||||
eglMakeCurrent(ec->display, es->surface, src, ec->context);
|
||||
glDrawBuffer(GL_FRONT);
|
||||
glReadBuffer(GL_FRONT);
|
||||
glRasterPos2d(0, 0);
|
||||
fprintf(stderr, "copypixels\n");
|
||||
glCopyPixels(x, y, width, height, GL_COLOR);
|
||||
|
||||
eglDestroySurface(ec->display, src);
|
||||
}
|
||||
|
||||
|
|
@ -1307,6 +1322,17 @@ post_output_geometry(struct wl_client *client, struct wl_object *global)
|
|||
output->width, output->height);
|
||||
}
|
||||
|
||||
static void
|
||||
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;
|
||||
drmHandleEvent(fd, &evctx);
|
||||
}
|
||||
|
||||
static int
|
||||
init_egl(struct wlsc_compositor *ec, struct udev_device *device)
|
||||
{
|
||||
|
|
@ -1318,7 +1344,9 @@ init_egl(struct wlsc_compositor *ec, struct udev_device *device)
|
|||
EGL_NONE
|
||||
};
|
||||
|
||||
struct wl_event_loop *loop;
|
||||
EGLint major, minor;
|
||||
int fd;
|
||||
|
||||
ec->display = eglCreateDisplayNative(device);
|
||||
if (ec->display == NULL) {
|
||||
|
|
@ -1339,17 +1367,19 @@ init_egl(struct wlsc_compositor *ec, struct udev_device *device)
|
|||
fprintf(stderr, "failed to create context\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
loop = wl_display_get_event_loop(ec->wl_display);
|
||||
fd = eglGetDisplayFD(ec->display);
|
||||
ec->drm_source =
|
||||
wl_event_loop_add_fd(loop, fd,
|
||||
WL_EVENT_READABLE, on_drm_input, ec);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
create_output(struct wlsc_compositor *ec, struct udev_device *device)
|
||||
{
|
||||
const static EGLint surface_attribs[] = {
|
||||
EGL_RENDER_BUFFER, EGL_BACK_BUFFER,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
drmModeConnector *connector;
|
||||
drmModeRes *resources;
|
||||
drmModeEncoder *encoder;
|
||||
|
|
@ -1414,27 +1444,31 @@ create_output(struct wlsc_compositor *ec, struct udev_device *device)
|
|||
output->width = mode->hdisplay;
|
||||
output->height = mode->vdisplay;
|
||||
|
||||
output->surface = eglCreateSurfaceForName(ec->display,
|
||||
ec->config,
|
||||
0,
|
||||
output->width,
|
||||
output->height,
|
||||
0, surface_attribs);
|
||||
output->surface = eglCreateSurface(ec->display,
|
||||
ec->config,
|
||||
output->width,
|
||||
output->height,
|
||||
2, NULL);
|
||||
if (output->surface == NULL) {
|
||||
fprintf(stderr, "failed to create surface\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
eglGetNativeBuffer(output->surface,
|
||||
GL_FRONT_LEFT, &name, &handle, &stride);
|
||||
ret = drmModeAddFB(fd, output->width, output->height,
|
||||
32, 32, stride, handle, &output->fb_id);
|
||||
if (ret) {
|
||||
fprintf(stderr, "failed to add fb: %m\n");
|
||||
return -1;
|
||||
for (i = 0; i < 2; i++) {
|
||||
eglGetColorBuffer(output->surface,
|
||||
i, &name, &handle, &stride);
|
||||
|
||||
ret = drmModeAddFB(fd, mode->hdisplay, mode->vdisplay,
|
||||
32, 32, stride, handle, &output->fb_id[i]);
|
||||
if (ret) {
|
||||
fprintf(stderr, "failed to add fb %d: %m\n", i);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
ret = drmModeSetCrtc(fd, encoder->crtc_id, output->fb_id, 0, 0,
|
||||
output->current = 0;
|
||||
ret = drmModeSetCrtc(fd, encoder->crtc_id,
|
||||
output->fb_id[output->current ^ 1], 0, 0,
|
||||
&connector->connector_id, 1, mode);
|
||||
if (ret) {
|
||||
fprintf(stderr, "failed to set mode: %m\n");
|
||||
|
|
@ -1493,7 +1527,8 @@ static void on_enter_vt(int signal_number, void *data)
|
|||
fd = eglGetDisplayFD(ec->display);
|
||||
output = container_of(ec->output_list.next, struct wlsc_output, link);
|
||||
while (&output->link != &ec->output_list) {
|
||||
ret = drmModeSetCrtc(fd, output->crtc_id, output->fb_id, 0, 0,
|
||||
ret = drmModeSetCrtc(fd, output->crtc_id,
|
||||
output->fb_id[output->current], 0, 0,
|
||||
&output->connector_id, 1, output->mode);
|
||||
if (ret)
|
||||
fprintf(stderr, "failed to set mode for connector %d: %m\n",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue