compositor-drm: Fix multi head rendering
This commit is contained in:
committed by
Kristian Høgsberg
parent
13d9db2095
commit
eefc36c760
@@ -59,6 +59,22 @@ struct drm_output {
|
|||||||
uint32_t current;
|
uint32_t current;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
drm_output_prepare_render(struct wlsc_output *output_base)
|
||||||
|
{
|
||||||
|
struct drm_output *output = (struct drm_output *) output_base;
|
||||||
|
|
||||||
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER,
|
||||||
|
GL_COLOR_ATTACHMENT0,
|
||||||
|
GL_RENDERBUFFER,
|
||||||
|
output->rbo[output->current]);
|
||||||
|
|
||||||
|
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
drm_compositor_present(struct wlsc_compositor *ec)
|
drm_compositor_present(struct wlsc_compositor *ec)
|
||||||
{
|
{
|
||||||
@@ -66,14 +82,12 @@ drm_compositor_present(struct wlsc_compositor *ec)
|
|||||||
struct drm_output *output;
|
struct drm_output *output;
|
||||||
|
|
||||||
wl_list_for_each(output, &ec->output_list, base.link) {
|
wl_list_for_each(output, &ec->output_list, base.link) {
|
||||||
output->current ^= 1;
|
if (drm_output_prepare_render(&output->base))
|
||||||
|
continue;
|
||||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER,
|
|
||||||
GL_COLOR_ATTACHMENT0,
|
|
||||||
GL_RENDERBUFFER,
|
|
||||||
output->rbo[output->current]);
|
|
||||||
glFlush();
|
glFlush();
|
||||||
|
|
||||||
|
output->current ^= 1;
|
||||||
|
|
||||||
drmModePageFlip(c->drm.fd, output->crtc_id,
|
drmModePageFlip(c->drm.fd, output->crtc_id,
|
||||||
output->fb_id[output->current ^ 1],
|
output->fb_id[output->current ^ 1],
|
||||||
DRM_MODE_PAGE_FLIP_EVENT, output);
|
DRM_MODE_PAGE_FLIP_EVENT, output);
|
||||||
@@ -88,8 +102,13 @@ page_flip_handler(int fd, unsigned int frame,
|
|||||||
struct wlsc_compositor *compositor = output->compositor;
|
struct wlsc_compositor *compositor = output->compositor;
|
||||||
uint32_t msecs;
|
uint32_t msecs;
|
||||||
|
|
||||||
|
/* run synchronized to first output, ignore other pflip events.
|
||||||
|
* FIXME: support per output/surface frame callbacks */
|
||||||
|
if (output == container_of(compositor->output_list.prev,
|
||||||
|
struct wlsc_output, link)) {
|
||||||
msecs = sec * 1000 + usec / 1000;
|
msecs = sec * 1000 + usec / 1000;
|
||||||
wlsc_compositor_finish_frame(compositor, msecs);
|
wlsc_compositor_finish_frame(compositor, msecs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -175,7 +194,8 @@ static drmModeModeInfo builtin_1024x768 = {
|
|||||||
static int
|
static int
|
||||||
create_output_for_connector(struct drm_compositor *ec,
|
create_output_for_connector(struct drm_compositor *ec,
|
||||||
drmModeRes *resources,
|
drmModeRes *resources,
|
||||||
drmModeConnector *connector)
|
drmModeConnector *connector,
|
||||||
|
int x, int y)
|
||||||
{
|
{
|
||||||
struct drm_output *output;
|
struct drm_output *output;
|
||||||
drmModeEncoder *encoder;
|
drmModeEncoder *encoder;
|
||||||
@@ -215,7 +235,7 @@ create_output_for_connector(struct drm_compositor *ec,
|
|||||||
}
|
}
|
||||||
|
|
||||||
memset(output, 0, sizeof *output);
|
memset(output, 0, sizeof *output);
|
||||||
wlsc_output_init(&output->base, &ec->base, 0, 0,
|
wlsc_output_init(&output->base, &ec->base, x, y,
|
||||||
mode->hdisplay, mode->vdisplay, 0);
|
mode->hdisplay, mode->vdisplay, 0);
|
||||||
|
|
||||||
ec->crtc_allocator |= (1 << i);
|
ec->crtc_allocator |= (1 << i);
|
||||||
@@ -260,6 +280,8 @@ create_output_for_connector(struct drm_compositor *ec,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
output->base.prepare_render = drm_output_prepare_render;
|
||||||
|
|
||||||
wl_list_insert(ec->base.output_list.prev, &output->base.link);
|
wl_list_insert(ec->base.output_list.prev, &output->base.link);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -271,6 +293,7 @@ create_outputs(struct drm_compositor *ec, int option_connector)
|
|||||||
drmModeConnector *connector;
|
drmModeConnector *connector;
|
||||||
drmModeRes *resources;
|
drmModeRes *resources;
|
||||||
int i;
|
int i;
|
||||||
|
int x = 0, y = 0;
|
||||||
|
|
||||||
resources = drmModeGetResources(ec->drm.fd);
|
resources = drmModeGetResources(ec->drm.fd);
|
||||||
if (!resources) {
|
if (!resources) {
|
||||||
@@ -286,9 +309,13 @@ create_outputs(struct drm_compositor *ec, int option_connector)
|
|||||||
if (connector->connection == DRM_MODE_CONNECTED &&
|
if (connector->connection == DRM_MODE_CONNECTED &&
|
||||||
(option_connector == 0 ||
|
(option_connector == 0 ||
|
||||||
connector->connector_id == option_connector))
|
connector->connector_id == option_connector))
|
||||||
if (create_output_for_connector(ec, resources, connector) < 0)
|
if (create_output_for_connector(ec, resources,
|
||||||
|
connector, x, y) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
x += container_of(ec->base.output_list.prev, struct wlsc_output,
|
||||||
|
link)->width;
|
||||||
|
|
||||||
drmModeFreeConnector(connector);
|
drmModeFreeConnector(connector);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -163,19 +163,31 @@ frame_callback(void *data, uint32_t time)
|
|||||||
wlsc_compositor_finish_frame(&c->base, time);
|
wlsc_compositor_finish_frame(&c->base, time);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
wayland_output_prepare_render(struct wlsc_output *output_base)
|
||||||
|
{
|
||||||
|
struct wayland_output *output = (struct wayland_output *) output_base;
|
||||||
|
struct wlsc_compositor *ec = output->base.compositor;
|
||||||
|
|
||||||
|
if (!eglMakeCurrent(ec->display, output->egl_surface,
|
||||||
|
output->egl_surface, ec->context)) {
|
||||||
|
fprintf(stderr, "failed to make current\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
wayland_compositor_present(struct wlsc_compositor *base)
|
wayland_compositor_present(struct wlsc_compositor *base)
|
||||||
{
|
{
|
||||||
struct wayland_compositor *c = (struct wayland_compositor *) base;
|
struct wayland_compositor *c = (struct wayland_compositor *) base;
|
||||||
struct wayland_output *output;
|
struct wayland_output *output;
|
||||||
|
|
||||||
|
|
||||||
wl_list_for_each(output, &base->output_list, base.link) {
|
wl_list_for_each(output, &base->output_list, base.link) {
|
||||||
if (!eglMakeCurrent(c->base.display, output->egl_surface,
|
if (wayland_output_prepare_render(&output->base))
|
||||||
output->egl_surface, c->base.context)) {
|
|
||||||
fprintf(stderr, "failed to make current\n");
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
eglSwapBuffers(c->base.display, output->egl_surface);
|
eglSwapBuffers(c->base.display, output->egl_surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,6 +242,8 @@ wayland_compositor_create_output(struct wayland_compositor *c,
|
|||||||
|
|
||||||
glClearColor(0, 0, 0, 0.5);
|
glClearColor(0, 0, 0, 0.5);
|
||||||
|
|
||||||
|
output->base.prepare_render = wayland_output_prepare_render;
|
||||||
|
|
||||||
wl_list_insert(c->base.output_list.prev, &output->base.link);
|
wl_list_insert(c->base.output_list.prev, &output->base.link);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -156,6 +156,21 @@ x11_compositor_init_egl(struct x11_compositor *c)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
x11_output_prepare_render(struct wlsc_output *output_base)
|
||||||
|
{
|
||||||
|
struct x11_output *output = (struct x11_output *) output_base;
|
||||||
|
struct wlsc_compositor *ec = output->base.compositor;
|
||||||
|
|
||||||
|
if (!eglMakeCurrent(ec->display, output->egl_surface,
|
||||||
|
output->egl_surface, ec->context)) {
|
||||||
|
fprintf(stderr, "failed to make current\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
x11_compositor_present(struct wlsc_compositor *base)
|
x11_compositor_present(struct wlsc_compositor *base)
|
||||||
{
|
{
|
||||||
@@ -165,11 +180,9 @@ x11_compositor_present(struct wlsc_compositor *base)
|
|||||||
uint32_t msec;
|
uint32_t msec;
|
||||||
|
|
||||||
wl_list_for_each(output, &c->base.output_list, base.link) {
|
wl_list_for_each(output, &c->base.output_list, base.link) {
|
||||||
if (!eglMakeCurrent(c->base.display, output->egl_surface,
|
if (x11_output_prepare_render(&output->base))
|
||||||
output->egl_surface, c->base.context)) {
|
|
||||||
fprintf(stderr, "failed to make current\n");
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
eglSwapBuffers(c->base.display, output->egl_surface);
|
eglSwapBuffers(c->base.display, output->egl_surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -324,6 +337,8 @@ x11_compositor_create_output(struct x11_compositor *c, int width, int height)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
output->base.prepare_render = x11_output_prepare_render;
|
||||||
|
|
||||||
wl_list_insert(c->base.output_list.prev, &output->base.link);
|
wl_list_insert(c->base.output_list.prev, &output->base.link);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
+36
-10
@@ -24,6 +24,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <limits.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
@@ -493,6 +494,8 @@ wlsc_output_repaint(struct wlsc_output *output)
|
|||||||
struct wlsc_input_device *eid;
|
struct wlsc_input_device *eid;
|
||||||
pixman_region32_t new_damage, total_damage;
|
pixman_region32_t new_damage, total_damage;
|
||||||
|
|
||||||
|
output->prepare_render(output);
|
||||||
|
|
||||||
glViewport(0, 0, output->width, output->height);
|
glViewport(0, 0, output->width, output->height);
|
||||||
|
|
||||||
glUniformMatrix4fv(ec->proj_uniform, 1, GL_FALSE, output->matrix.d);
|
glUniformMatrix4fv(ec->proj_uniform, 1, GL_FALSE, output->matrix.d);
|
||||||
@@ -849,17 +852,40 @@ notify_motion(struct wl_input_device *device, uint32_t time, int x, int y)
|
|||||||
const struct wl_grab_interface *interface;
|
const struct wl_grab_interface *interface;
|
||||||
struct wlsc_input_device *wd = (struct wlsc_input_device *) device;
|
struct wlsc_input_device *wd = (struct wlsc_input_device *) device;
|
||||||
int32_t sx, sy;
|
int32_t sx, sy;
|
||||||
|
int x_valid = 0, y_valid = 0;
|
||||||
|
int min_x = INT_MAX, min_y = INT_MAX, max_x = INT_MIN, max_y = INT_MIN;
|
||||||
|
|
||||||
/* FIXME: We need some multi head love here. */
|
wl_list_for_each(output, &ec->output_list, link) {
|
||||||
output = container_of(ec->output_list.next, struct wlsc_output, link);
|
if (output->x <= x && x <= output->x + output->width)
|
||||||
if (x < output->x)
|
x_valid = 1;
|
||||||
x = 0;
|
|
||||||
if (y < output->y)
|
if (output->y <= y && y <= output->y + output->height)
|
||||||
y = 0;
|
y_valid = 1;
|
||||||
if (x >= output->x + output->width)
|
|
||||||
x = output->x + output->width - 1;
|
/* FIXME: calculate this only on output addition/deletion */
|
||||||
if (y >= output->y + output->height)
|
if (output->x < min_x)
|
||||||
y = output->y + output->height - 1;
|
min_x = output->x;
|
||||||
|
if (output->y < min_y)
|
||||||
|
min_y = output->y;
|
||||||
|
|
||||||
|
if (output->x + output->width > max_x)
|
||||||
|
max_x = output->x + output->width;
|
||||||
|
if (output->y + output->height > max_y)
|
||||||
|
max_y = output->y + output->height;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!x_valid) {
|
||||||
|
if (x < min_x)
|
||||||
|
x = min_x;
|
||||||
|
else if (x >= max_x)
|
||||||
|
x = max_x;
|
||||||
|
}
|
||||||
|
if (!y_valid) {
|
||||||
|
if (y < min_y)
|
||||||
|
y = min_y;
|
||||||
|
else if (y >= max_y)
|
||||||
|
y = max_y;
|
||||||
|
}
|
||||||
|
|
||||||
device->x = x;
|
device->x = x;
|
||||||
device->y = y;
|
device->y = y;
|
||||||
|
|||||||
@@ -47,6 +47,8 @@ struct wlsc_output {
|
|||||||
struct wlsc_matrix matrix;
|
struct wlsc_matrix matrix;
|
||||||
int32_t x, y, width, height;
|
int32_t x, y, width, height;
|
||||||
pixman_region32_t previous_damage_region;
|
pixman_region32_t previous_damage_region;
|
||||||
|
|
||||||
|
int (*prepare_render)(struct wlsc_output *output);
|
||||||
};
|
};
|
||||||
|
|
||||||
enum wlsc_pointer_type {
|
enum wlsc_pointer_type {
|
||||||
|
|||||||
Reference in New Issue
Block a user