compositor-drm: Add support for using the pixman renderer
If --use-pixman is passed as command line option to weston, the drm backend will use the pixman renderer instead of the gl one.
This commit is contained in:
parent
1d41ad4054
commit
5fb44141bf
|
@ -42,6 +42,7 @@
|
|||
|
||||
#include "compositor.h"
|
||||
#include "gl-renderer.h"
|
||||
#include "pixman-renderer.h"
|
||||
#include "evdev.h"
|
||||
#include "launcher-util.h"
|
||||
|
||||
|
@ -104,6 +105,8 @@ struct drm_compositor {
|
|||
|
||||
int cursors_are_broken;
|
||||
|
||||
int use_pixman;
|
||||
|
||||
uint32_t prev_state;
|
||||
};
|
||||
|
||||
|
@ -148,6 +151,11 @@ struct drm_output {
|
|||
int current_cursor;
|
||||
struct drm_fb *current, *next;
|
||||
struct backlight *backlight;
|
||||
|
||||
struct drm_fb *dumb[2];
|
||||
pixman_image_t *image[2];
|
||||
int current_image;
|
||||
pixman_region32_t previous_damage;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -381,7 +389,8 @@ drm_output_release_fb(struct drm_output *output, struct drm_fb *fb)
|
|||
if (!fb)
|
||||
return;
|
||||
|
||||
if (fb->map) {
|
||||
if (fb->map &&
|
||||
(fb != output->dumb[0] && fb != output->dumb[1])) {
|
||||
drm_fb_destroy_dumb(fb);
|
||||
} else if (fb->bo) {
|
||||
if (fb->is_client_buffer)
|
||||
|
@ -437,7 +446,7 @@ drm_output_prepare_scanout_surface(struct weston_output *_output,
|
|||
|
||||
if (es->geometry.x != output->base.x ||
|
||||
es->geometry.y != output->base.y ||
|
||||
buffer == NULL ||
|
||||
buffer == NULL || c->gbm == NULL ||
|
||||
buffer->width != output->base.current->width ||
|
||||
buffer->height != output->base.current->height ||
|
||||
output->base.transform != es->buffer_transform ||
|
||||
|
@ -469,7 +478,7 @@ drm_output_prepare_scanout_surface(struct weston_output *_output,
|
|||
}
|
||||
|
||||
static void
|
||||
drm_output_render(struct drm_output *output, pixman_region32_t *damage)
|
||||
drm_output_render_gl(struct drm_output *output, pixman_region32_t *damage)
|
||||
{
|
||||
struct drm_compositor *c =
|
||||
(struct drm_compositor *) output->base.compositor;
|
||||
|
@ -477,9 +486,6 @@ drm_output_render(struct drm_output *output, pixman_region32_t *damage)
|
|||
|
||||
c->base.renderer->repaint_output(&output->base, damage);
|
||||
|
||||
pixman_region32_subtract(&c->base.primary_plane.damage,
|
||||
&c->base.primary_plane.damage, damage);
|
||||
|
||||
bo = gbm_surface_lock_front_buffer(output->surface);
|
||||
if (!bo) {
|
||||
weston_log("failed to lock front buffer: %m\n");
|
||||
|
@ -494,6 +500,47 @@ drm_output_render(struct drm_output *output, pixman_region32_t *damage)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
drm_output_render_pixman(struct drm_output *output, pixman_region32_t *damage)
|
||||
{
|
||||
struct weston_compositor *ec = output->base.compositor;
|
||||
pixman_region32_t total_damage, previous_damage;
|
||||
|
||||
pixman_region32_init(&total_damage);
|
||||
pixman_region32_init(&previous_damage);
|
||||
|
||||
pixman_region32_copy(&previous_damage, damage);
|
||||
|
||||
pixman_region32_union(&total_damage, damage, &output->previous_damage);
|
||||
pixman_region32_copy(&output->previous_damage, &previous_damage);
|
||||
|
||||
output->current_image ^= 1;
|
||||
|
||||
output->next = output->dumb[output->current_image];
|
||||
pixman_renderer_output_set_buffer(&output->base,
|
||||
output->image[output->current_image]);
|
||||
|
||||
ec->renderer->repaint_output(&output->base, &total_damage);
|
||||
|
||||
pixman_region32_fini(&total_damage);
|
||||
pixman_region32_fini(&previous_damage);
|
||||
}
|
||||
|
||||
static void
|
||||
drm_output_render(struct drm_output *output, pixman_region32_t *damage)
|
||||
{
|
||||
struct drm_compositor *c =
|
||||
(struct drm_compositor *) output->base.compositor;
|
||||
|
||||
if (c->use_pixman)
|
||||
drm_output_render_pixman(output, damage);
|
||||
else
|
||||
drm_output_render_gl(output, damage);
|
||||
|
||||
pixman_region32_subtract(&c->base.primary_plane.damage,
|
||||
&c->base.primary_plane.damage, damage);
|
||||
}
|
||||
|
||||
static void
|
||||
drm_output_repaint(struct weston_output *output_base,
|
||||
pixman_region32_t *damage)
|
||||
|
@ -693,6 +740,9 @@ drm_output_prepare_overlay_surface(struct weston_output *output_base,
|
|||
uint32_t format;
|
||||
wl_fixed_t sx1, sy1, sx2, sy2;
|
||||
|
||||
if (c->gbm == NULL)
|
||||
return NULL;
|
||||
|
||||
if (es->buffer_transform != output_base->transform)
|
||||
return NULL;
|
||||
|
||||
|
@ -819,6 +869,8 @@ drm_output_prepare_cursor_surface(struct weston_output *output_base,
|
|||
(struct drm_compositor *) output_base->compositor;
|
||||
struct drm_output *output = (struct drm_output *) output_base;
|
||||
|
||||
if (c->gbm == NULL)
|
||||
return NULL;
|
||||
if (output->base.transform != WL_OUTPUT_TRANSFORM_NORMAL)
|
||||
return NULL;
|
||||
if (output->cursor_surface)
|
||||
|
@ -968,6 +1020,9 @@ drm_assign_planes(struct weston_output *output)
|
|||
pixman_region32_fini(&overlap);
|
||||
}
|
||||
|
||||
static void
|
||||
drm_output_fini_pixman(struct drm_output *output);
|
||||
|
||||
static void
|
||||
drm_output_destroy(struct weston_output *output_base)
|
||||
{
|
||||
|
@ -991,9 +1046,12 @@ drm_output_destroy(struct weston_output *output_base)
|
|||
c->crtc_allocator &= ~(1 << output->crtc_id);
|
||||
c->connector_allocator &= ~(1 << output->connector_id);
|
||||
|
||||
gl_renderer_output_destroy(output_base);
|
||||
|
||||
gbm_surface_destroy(output->surface);
|
||||
if (c->use_pixman) {
|
||||
drm_output_fini_pixman(output);
|
||||
} else {
|
||||
gl_renderer_output_destroy(output_base);
|
||||
gbm_surface_destroy(output->surface);
|
||||
}
|
||||
|
||||
weston_plane_release(&output->fb_plane);
|
||||
weston_plane_release(&output->cursor_plane);
|
||||
|
@ -1032,6 +1090,8 @@ choose_mode (struct drm_output *output, struct weston_mode *target_mode)
|
|||
|
||||
static int
|
||||
drm_output_init_egl(struct drm_output *output, struct drm_compositor *ec);
|
||||
static int
|
||||
drm_output_init_pixman(struct drm_output *output, struct drm_compositor *c);
|
||||
|
||||
static int
|
||||
drm_output_switch_mode(struct weston_output *output_base, struct weston_mode *mode)
|
||||
|
@ -1073,12 +1133,22 @@ drm_output_switch_mode(struct weston_output *output_base, struct weston_mode *mo
|
|||
drm_output_release_fb(output, output->next);
|
||||
output->current = output->next = NULL;
|
||||
|
||||
gl_renderer_output_destroy(&output->base);
|
||||
gbm_surface_destroy(output->surface);
|
||||
if (ec->use_pixman) {
|
||||
drm_output_fini_pixman(output);
|
||||
if (drm_output_init_pixman(output, ec) < 0) {
|
||||
weston_log("failed to init output pixman state with "
|
||||
"new mode\n");
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
gl_renderer_output_destroy(&output->base);
|
||||
gbm_surface_destroy(output->surface);
|
||||
|
||||
if (drm_output_init_egl(output, ec) < 0) {
|
||||
weston_log("failed to init output egl state with new mode");
|
||||
return -1;
|
||||
if (drm_output_init_egl(output, ec) < 0) {
|
||||
weston_log("failed to init output egl state with "
|
||||
"new mode");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -1143,6 +1213,12 @@ init_egl(struct drm_compositor *ec)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
init_pixman(struct drm_compositor *ec)
|
||||
{
|
||||
return pixman_renderer_init(&ec->base);
|
||||
}
|
||||
|
||||
static struct drm_mode *
|
||||
drm_output_add_mode(struct drm_output *output, drmModeModeInfo *info)
|
||||
{
|
||||
|
@ -1367,6 +1443,66 @@ drm_output_init_egl(struct drm_output *output, struct drm_compositor *ec)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
drm_output_init_pixman(struct drm_output *output, struct drm_compositor *c)
|
||||
{
|
||||
int w = output->base.current->width;
|
||||
int h = output->base.current->height;
|
||||
unsigned int i;
|
||||
|
||||
/* FIXME error checking */
|
||||
|
||||
for (i = 0; i < ARRAY_LENGTH(output->dumb); i++) {
|
||||
output->dumb[i] = drm_fb_create_dumb(c, w, h);
|
||||
if (!output->dumb[i])
|
||||
goto err;
|
||||
|
||||
output->image[i] =
|
||||
pixman_image_create_bits(PIXMAN_x8r8g8b8, w, h,
|
||||
output->dumb[i]->map,
|
||||
output->dumb[i]->stride);
|
||||
if (!output->image[i])
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (pixman_renderer_output_create(&output->base) < 0)
|
||||
goto err;
|
||||
|
||||
pixman_region32_init_rect(&output->previous_damage,
|
||||
output->base.x, output->base.y, w, h);
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
for (i = 0; i < ARRAY_LENGTH(output->dumb); i++) {
|
||||
if (output->dumb[i])
|
||||
drm_fb_destroy_dumb(output->dumb[i]);
|
||||
if (output->image[i])
|
||||
pixman_image_unref(output->image[i]);
|
||||
|
||||
output->dumb[i] = NULL;
|
||||
output->image[i] = NULL;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
drm_output_fini_pixman(struct drm_output *output)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
pixman_renderer_output_destroy(&output->base);
|
||||
pixman_region32_fini(&output->previous_damage);
|
||||
|
||||
for (i = 0; i < ARRAY_LENGTH(output->dumb); i++) {
|
||||
drm_fb_destroy_dumb(output->dumb[i]);
|
||||
pixman_image_unref(output->image[i]);
|
||||
output->dumb[i] = NULL;
|
||||
output->image[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
create_output_for_connector(struct drm_compositor *ec,
|
||||
drmModeRes *resources,
|
||||
|
@ -1504,7 +1640,12 @@ create_output_for_connector(struct drm_compositor *ec,
|
|||
connector->mmWidth, connector->mmHeight,
|
||||
o ? o->transform : WL_OUTPUT_TRANSFORM_NORMAL);
|
||||
|
||||
if (drm_output_init_egl(output, ec) < 0) {
|
||||
if (ec->use_pixman) {
|
||||
if (drm_output_init_pixman(output, ec) < 0) {
|
||||
weston_log("Failed to init output pixman state\n");
|
||||
goto err_output;
|
||||
}
|
||||
} else if (drm_output_init_egl(output, ec) < 0) {
|
||||
weston_log("Failed to init output gl state\n");
|
||||
goto err_output;
|
||||
}
|
||||
|
@ -2098,7 +2239,10 @@ drm_destroy(struct weston_compositor *ec)
|
|||
ec->renderer->destroy(ec);
|
||||
|
||||
destroy_sprites(d);
|
||||
gbm_device_destroy(d->gbm);
|
||||
|
||||
if (d->gbm)
|
||||
gbm_device_destroy(d->gbm);
|
||||
|
||||
if (weston_launcher_drm_set_master(&d->base, d->drm.fd, 0) < 0)
|
||||
weston_log("failed to drop master: %m\n");
|
||||
tty_destroy(d->tty);
|
||||
|
@ -2278,7 +2422,7 @@ planes_binding(struct wl_seat *seat, uint32_t time, uint32_t key, void *data)
|
|||
|
||||
static struct weston_compositor *
|
||||
drm_compositor_create(struct wl_display *display,
|
||||
int connector, const char *seat, int tty,
|
||||
int connector, const char *seat, int tty, int pixman,
|
||||
int argc, char *argv[], const char *config_file)
|
||||
{
|
||||
struct drm_compositor *ec;
|
||||
|
@ -2299,6 +2443,8 @@ drm_compositor_create(struct wl_display *display,
|
|||
* functionality for now. */
|
||||
ec->sprites_are_broken = 1;
|
||||
|
||||
ec->use_pixman = pixman;
|
||||
|
||||
if (weston_compositor_init(&ec->base, display, argc, argv,
|
||||
config_file) < 0) {
|
||||
weston_log("weston_compositor_init failed\n");
|
||||
|
@ -2330,9 +2476,16 @@ drm_compositor_create(struct wl_display *display,
|
|||
goto err_udev_dev;
|
||||
}
|
||||
|
||||
if (init_egl(ec) < 0) {
|
||||
weston_log("failed to initialize egl\n");
|
||||
goto err_udev_dev;
|
||||
if (ec->use_pixman) {
|
||||
if (init_pixman(ec) < 0) {
|
||||
weston_log("failed to initialize pixman renderer\n");
|
||||
goto err_udev_dev;
|
||||
}
|
||||
} else {
|
||||
if (init_egl(ec) < 0) {
|
||||
weston_log("failed to initialize egl\n");
|
||||
goto err_udev_dev;
|
||||
}
|
||||
}
|
||||
|
||||
ec->base.destroy = drm_destroy;
|
||||
|
@ -2564,7 +2717,7 @@ WL_EXPORT struct weston_compositor *
|
|||
backend_init(struct wl_display *display, int argc, char *argv[],
|
||||
const char *config_file)
|
||||
{
|
||||
int connector = 0, tty = 0;
|
||||
int connector = 0, tty = 0, use_pixman = 0;
|
||||
const char *seat = default_seat;
|
||||
|
||||
const struct weston_option drm_options[] = {
|
||||
|
@ -2572,6 +2725,7 @@ backend_init(struct wl_display *display, int argc, char *argv[],
|
|||
{ WESTON_OPTION_STRING, "seat", 0, &seat },
|
||||
{ WESTON_OPTION_INTEGER, "tty", 0, &tty },
|
||||
{ WESTON_OPTION_BOOLEAN, "current-mode", 0, &option_current_mode },
|
||||
{ WESTON_OPTION_BOOLEAN, "use-pixman", 0, &use_pixman },
|
||||
};
|
||||
|
||||
parse_options(drm_options, ARRAY_LENGTH(drm_options), argc, argv);
|
||||
|
@ -2592,6 +2746,6 @@ backend_init(struct wl_display *display, int argc, char *argv[],
|
|||
parse_config_file(config_file, config_section,
|
||||
ARRAY_LENGTH(config_section), NULL);
|
||||
|
||||
return drm_compositor_create(display, connector, seat, tty, argc, argv,
|
||||
config_file);
|
||||
return drm_compositor_create(display, connector, seat, tty, use_pixman,
|
||||
argc, argv, config_file);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue