|
|
|
@ -58,11 +58,6 @@ |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
static int option_current_mode = 0; |
|
|
|
|
static char *output_name; |
|
|
|
|
static char *output_mode; |
|
|
|
|
static char *output_transform; |
|
|
|
|
static char *output_scale; |
|
|
|
|
static struct wl_list configured_output_list; |
|
|
|
|
|
|
|
|
|
enum output_config { |
|
|
|
|
OUTPUT_CONFIG_INVALID = 0, |
|
|
|
@ -73,17 +68,6 @@ enum output_config { |
|
|
|
|
OUTPUT_CONFIG_MODELINE |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
struct drm_configured_output { |
|
|
|
|
char *name; |
|
|
|
|
char *mode; |
|
|
|
|
uint32_t transform; |
|
|
|
|
int32_t scale; |
|
|
|
|
int32_t width, height; |
|
|
|
|
drmModeModeInfo crtc_mode; |
|
|
|
|
enum output_config config; |
|
|
|
|
struct wl_list link; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
struct drm_compositor { |
|
|
|
|
struct weston_compositor base; |
|
|
|
|
|
|
|
|
@ -1265,20 +1249,15 @@ init_pixman(struct drm_compositor *ec) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static struct drm_mode * |
|
|
|
|
drm_output_add_mode(struct drm_output *output, drmModeModeInfo *info, struct drm_configured_output *config) |
|
|
|
|
drm_output_add_mode(struct drm_output *output, drmModeModeInfo *info, int scale) |
|
|
|
|
{ |
|
|
|
|
struct drm_mode *mode; |
|
|
|
|
uint64_t refresh; |
|
|
|
|
int scale; |
|
|
|
|
|
|
|
|
|
mode = malloc(sizeof *mode); |
|
|
|
|
if (mode == NULL) |
|
|
|
|
return NULL; |
|
|
|
|
|
|
|
|
|
scale = 1; |
|
|
|
|
if (config) |
|
|
|
|
scale = config->scale; |
|
|
|
|
|
|
|
|
|
if (info->hdisplay % scale != 0 || |
|
|
|
|
info->vdisplay % scale) { |
|
|
|
|
weston_log("Mode %dx%d not multiple of scale %d\n", info->hdisplay, info->vdisplay, scale); |
|
|
|
@ -1699,6 +1678,76 @@ find_and_parse_output_edid(struct drm_compositor *ec, |
|
|
|
|
drmModeFreePropertyBlob(edid_blob); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int |
|
|
|
|
parse_modeline(const char *s, drmModeModeInfo *mode) |
|
|
|
|
{ |
|
|
|
|
char hsync[16]; |
|
|
|
|
char vsync[16]; |
|
|
|
|
float fclock; |
|
|
|
|
|
|
|
|
|
mode->type = DRM_MODE_TYPE_USERDEF; |
|
|
|
|
mode->hskew = 0; |
|
|
|
|
mode->vscan = 0; |
|
|
|
|
mode->vrefresh = 0; |
|
|
|
|
mode->flags = 0; |
|
|
|
|
|
|
|
|
|
if (sscanf(s, "%f %hd %hd %hd %hd %hd %hd %hd %hd %s %s", |
|
|
|
|
&fclock, |
|
|
|
|
&mode->hdisplay, |
|
|
|
|
&mode->hsync_start, |
|
|
|
|
&mode->hsync_end, |
|
|
|
|
&mode->htotal, |
|
|
|
|
&mode->vdisplay, |
|
|
|
|
&mode->vsync_start, |
|
|
|
|
&mode->vsync_end, |
|
|
|
|
&mode->vtotal, hsync, vsync) != 11) |
|
|
|
|
return -1; |
|
|
|
|
|
|
|
|
|
mode->clock = fclock * 1000; |
|
|
|
|
if (strcmp(hsync, "+hsync") == 0) |
|
|
|
|
mode->flags |= DRM_MODE_FLAG_PHSYNC; |
|
|
|
|
else if (strcmp(hsync, "-hsync") == 0) |
|
|
|
|
mode->flags |= DRM_MODE_FLAG_NHSYNC; |
|
|
|
|
else |
|
|
|
|
return -1; |
|
|
|
|
|
|
|
|
|
if (strcmp(vsync, "+vsync") == 0) |
|
|
|
|
mode->flags |= DRM_MODE_FLAG_PVSYNC; |
|
|
|
|
else if (strcmp(vsync, "-vsync") == 0) |
|
|
|
|
mode->flags |= DRM_MODE_FLAG_NVSYNC; |
|
|
|
|
else |
|
|
|
|
return -1; |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static uint32_t |
|
|
|
|
parse_transform(const char *transform, const char *output_name) |
|
|
|
|
{ |
|
|
|
|
static const struct { const char *name; uint32_t token; } names[] = { |
|
|
|
|
{ "normal", WL_OUTPUT_TRANSFORM_NORMAL }, |
|
|
|
|
{ "90", WL_OUTPUT_TRANSFORM_90 }, |
|
|
|
|
{ "180", WL_OUTPUT_TRANSFORM_180 }, |
|
|
|
|
{ "270", WL_OUTPUT_TRANSFORM_270 }, |
|
|
|
|
{ "flipped", WL_OUTPUT_TRANSFORM_FLIPPED }, |
|
|
|
|
{ "flipped-90", WL_OUTPUT_TRANSFORM_FLIPPED_90 }, |
|
|
|
|
{ "flipped-180", WL_OUTPUT_TRANSFORM_FLIPPED_180 }, |
|
|
|
|
{ "flipped-270", WL_OUTPUT_TRANSFORM_FLIPPED_270 }, |
|
|
|
|
}; |
|
|
|
|
unsigned int i; |
|
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_LENGTH(names); i++) |
|
|
|
|
if (strcmp(names[i].name, transform) == 0) |
|
|
|
|
return names[i].token; |
|
|
|
|
|
|
|
|
|
weston_log("Invalid transform \"%s\" for output %s\n", |
|
|
|
|
transform, output_name); |
|
|
|
|
|
|
|
|
|
return WL_OUTPUT_TRANSFORM_NORMAL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int |
|
|
|
|
create_output_for_connector(struct drm_compositor *ec, |
|
|
|
|
drmModeRes *resources, |
|
|
|
@ -1708,13 +1757,15 @@ create_output_for_connector(struct drm_compositor *ec, |
|
|
|
|
struct drm_output *output; |
|
|
|
|
struct drm_mode *drm_mode, *next, *preferred, *current, *configured; |
|
|
|
|
struct weston_mode *m; |
|
|
|
|
struct drm_configured_output *o = NULL, *temp; |
|
|
|
|
struct weston_config_section *section; |
|
|
|
|
drmModeEncoder *encoder; |
|
|
|
|
drmModeModeInfo crtc_mode; |
|
|
|
|
drmModeModeInfo crtc_mode, modeline; |
|
|
|
|
drmModeCrtc *crtc; |
|
|
|
|
int i; |
|
|
|
|
char name[32]; |
|
|
|
|
int i, width, height, scale; |
|
|
|
|
char name[32], *s; |
|
|
|
|
const char *type_name; |
|
|
|
|
enum output_config config; |
|
|
|
|
uint32_t transform; |
|
|
|
|
|
|
|
|
|
i = find_crtc_for_connector(ec, resources, connector); |
|
|
|
|
if (i < 0) { |
|
|
|
@ -1740,15 +1791,30 @@ create_output_for_connector(struct drm_compositor *ec, |
|
|
|
|
snprintf(name, 32, "%s%d", type_name, connector->connector_type_id); |
|
|
|
|
output->base.name = strdup(name); |
|
|
|
|
|
|
|
|
|
wl_list_for_each(temp, &configured_output_list, link) { |
|
|
|
|
if (strcmp(temp->name, output->base.name) == 0) { |
|
|
|
|
if (temp->mode) |
|
|
|
|
weston_log("%s mode \"%s\" in config\n", |
|
|
|
|
temp->name, temp->mode); |
|
|
|
|
o = temp; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
section = weston_config_get_section(ec->base.config, "output", "name", |
|
|
|
|
output->base.name); |
|
|
|
|
weston_config_section_get_string(section, "mode", &s, "preferred"); |
|
|
|
|
if (strcmp(s, "off") == 0) |
|
|
|
|
config = OUTPUT_CONFIG_OFF; |
|
|
|
|
else if (strcmp(s, "preferred") == 0) |
|
|
|
|
config = OUTPUT_CONFIG_PREFERRED; |
|
|
|
|
else if (strcmp(s, "current") == 0) |
|
|
|
|
config = OUTPUT_CONFIG_CURRENT; |
|
|
|
|
else if (sscanf(s, "%dx%d", &width, &height) == 2) |
|
|
|
|
config = OUTPUT_CONFIG_MODE; |
|
|
|
|
else if (parse_modeline(s, &modeline) == 0) |
|
|
|
|
config = OUTPUT_CONFIG_MODELINE; |
|
|
|
|
else { |
|
|
|
|
weston_log("Invalid mode \"%s\" for output %s\n", |
|
|
|
|
s, output->base.name); |
|
|
|
|
config = OUTPUT_CONFIG_PREFERRED; |
|
|
|
|
} |
|
|
|
|
free(s); |
|
|
|
|
|
|
|
|
|
weston_config_section_get_int(section, "scale", &scale, 1); |
|
|
|
|
weston_config_section_get_string(section, "transform", &s, "normal"); |
|
|
|
|
transform = parse_transform(s, output->base.name); |
|
|
|
|
free(s); |
|
|
|
|
|
|
|
|
|
output->crtc_id = resources->crtcs[i]; |
|
|
|
|
output->pipe = i; |
|
|
|
@ -1773,27 +1839,27 @@ create_output_for_connector(struct drm_compositor *ec, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for (i = 0; i < connector->count_modes; i++) { |
|
|
|
|
drm_mode = drm_output_add_mode(output, &connector->modes[i], o); |
|
|
|
|
drm_mode = drm_output_add_mode(output,
|
|
|
|
|
&connector->modes[i], scale); |
|
|
|
|
if (!drm_mode) |
|
|
|
|
goto err_free; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
preferred = NULL; |
|
|
|
|
current = NULL; |
|
|
|
|
configured = NULL; |
|
|
|
|
|
|
|
|
|
if (o && o->config == OUTPUT_CONFIG_OFF) { |
|
|
|
|
weston_log("Disabling output %s\n", o->name); |
|
|
|
|
|
|
|
|
|
if (config == OUTPUT_CONFIG_OFF) { |
|
|
|
|
weston_log("Disabling output %s\n", output->base.name); |
|
|
|
|
drmModeSetCrtc(ec->drm.fd, output->crtc_id, |
|
|
|
|
0, 0, 0, 0, 0, NULL); |
|
|
|
|
0, 0, 0, 0, 0, NULL); |
|
|
|
|
goto err_free; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
preferred = NULL; |
|
|
|
|
current = NULL; |
|
|
|
|
configured = NULL; |
|
|
|
|
|
|
|
|
|
wl_list_for_each(drm_mode, &output->base.mode_list, base.link) { |
|
|
|
|
if (o && o->config == OUTPUT_CONFIG_MODE && |
|
|
|
|
o->width == drm_mode->base.width * o->scale && |
|
|
|
|
o->height == drm_mode->base.height * o->scale) |
|
|
|
|
if (config == OUTPUT_CONFIG_MODE && |
|
|
|
|
width == drm_mode->base.width * scale && |
|
|
|
|
height == drm_mode->base.height * scale) |
|
|
|
|
configured = drm_mode; |
|
|
|
|
if (!memcmp(&crtc_mode, &drm_mode->mode_info, sizeof crtc_mode)) |
|
|
|
|
current = drm_mode; |
|
|
|
@ -1801,20 +1867,19 @@ create_output_for_connector(struct drm_compositor *ec, |
|
|
|
|
preferred = drm_mode; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (o && o->config == OUTPUT_CONFIG_MODELINE) { |
|
|
|
|
configured = drm_output_add_mode(output, &o->crtc_mode, 0); |
|
|
|
|
if (config == OUTPUT_CONFIG_MODELINE) { |
|
|
|
|
configured = drm_output_add_mode(output, &modeline, scale); |
|
|
|
|
if (!configured) |
|
|
|
|
goto err_free; |
|
|
|
|
current = configured; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (current == NULL && crtc_mode.clock != 0) { |
|
|
|
|
current = drm_output_add_mode(output, &crtc_mode, 0); |
|
|
|
|
current = drm_output_add_mode(output, &crtc_mode, scale); |
|
|
|
|
if (!current) |
|
|
|
|
goto err_free; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (o && o->config == OUTPUT_CONFIG_CURRENT) |
|
|
|
|
if (config == OUTPUT_CONFIG_CURRENT) |
|
|
|
|
configured = current; |
|
|
|
|
|
|
|
|
|
if (option_current_mode && current) |
|
|
|
@ -1835,8 +1900,7 @@ create_output_for_connector(struct drm_compositor *ec, |
|
|
|
|
|
|
|
|
|
weston_output_init(&output->base, &ec->base, x, y, |
|
|
|
|
connector->mmWidth, connector->mmHeight, |
|
|
|
|
o ? o->transform : WL_OUTPUT_TRANSFORM_NORMAL, |
|
|
|
|
o ? o->scale : 1); |
|
|
|
|
transform, scale); |
|
|
|
|
|
|
|
|
|
if (ec->use_pixman) { |
|
|
|
|
if (drm_output_init_pixman(output, ec) < 0) { |
|
|
|
@ -2171,25 +2235,14 @@ drm_restore(struct weston_compositor *ec) |
|
|
|
|
tty_reset(d->tty); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void |
|
|
|
|
drm_free_configured_output(struct drm_configured_output *output) |
|
|
|
|
{ |
|
|
|
|
free(output->name); |
|
|
|
|
free(output->mode); |
|
|
|
|
free(output); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void |
|
|
|
|
drm_destroy(struct weston_compositor *ec) |
|
|
|
|
{ |
|
|
|
|
struct drm_compositor *d = (struct drm_compositor *) ec; |
|
|
|
|
struct udev_seat *seat, *next; |
|
|
|
|
struct drm_configured_output *o, *n; |
|
|
|
|
|
|
|
|
|
wl_list_for_each_safe(seat, next, &ec->seat_list, base.link) |
|
|
|
|
udev_seat_destroy(seat); |
|
|
|
|
wl_list_for_each_safe(o, n, &configured_output_list, link) |
|
|
|
|
drm_free_configured_output(o); |
|
|
|
|
|
|
|
|
|
wl_event_source_remove(d->udev_drm_source); |
|
|
|
|
wl_event_source_remove(d->drm_source); |
|
|
|
@ -2547,158 +2600,6 @@ err_base: |
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int |
|
|
|
|
set_sync_flags(drmModeModeInfo *mode, char *hsync, char *vsync) |
|
|
|
|
{ |
|
|
|
|
mode->flags = 0; |
|
|
|
|
|
|
|
|
|
if (strcmp(hsync, "+hsync") == 0) |
|
|
|
|
mode->flags |= DRM_MODE_FLAG_PHSYNC; |
|
|
|
|
else if (strcmp(hsync, "-hsync") == 0) |
|
|
|
|
mode->flags |= DRM_MODE_FLAG_NHSYNC; |
|
|
|
|
else |
|
|
|
|
return -1; |
|
|
|
|
|
|
|
|
|
if (strcmp(vsync, "+vsync") == 0) |
|
|
|
|
mode->flags |= DRM_MODE_FLAG_PVSYNC; |
|
|
|
|
else if (strcmp(vsync, "-vsync") == 0) |
|
|
|
|
mode->flags |= DRM_MODE_FLAG_NVSYNC; |
|
|
|
|
else |
|
|
|
|
return -1; |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int |
|
|
|
|
check_for_modeline(struct drm_configured_output *output) |
|
|
|
|
{ |
|
|
|
|
drmModeModeInfo mode; |
|
|
|
|
char hsync[16]; |
|
|
|
|
char vsync[16]; |
|
|
|
|
char mode_name[16]; |
|
|
|
|
float fclock; |
|
|
|
|
|
|
|
|
|
mode.type = DRM_MODE_TYPE_USERDEF; |
|
|
|
|
mode.hskew = 0; |
|
|
|
|
mode.vscan = 0; |
|
|
|
|
mode.vrefresh = 0; |
|
|
|
|
|
|
|
|
|
if (sscanf(output_mode, "%f %hd %hd %hd %hd %hd %hd %hd %hd %s %s", |
|
|
|
|
&fclock, &mode.hdisplay, |
|
|
|
|
&mode.hsync_start, |
|
|
|
|
&mode.hsync_end, &mode.htotal, |
|
|
|
|
&mode.vdisplay, |
|
|
|
|
&mode.vsync_start, |
|
|
|
|
&mode.vsync_end, &mode.vtotal, |
|
|
|
|
hsync, vsync) == 11) { |
|
|
|
|
if (set_sync_flags(&mode, hsync, vsync)) |
|
|
|
|
return -1; |
|
|
|
|
|
|
|
|
|
sprintf(mode_name, "%dx%d", mode.hdisplay, mode.vdisplay); |
|
|
|
|
strcpy(mode.name, mode_name); |
|
|
|
|
|
|
|
|
|
mode.clock = fclock * 1000; |
|
|
|
|
} else |
|
|
|
|
return -1; |
|
|
|
|
|
|
|
|
|
output->crtc_mode = mode; |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void |
|
|
|
|
drm_output_set_transform(struct drm_configured_output *output) |
|
|
|
|
{ |
|
|
|
|
if (!output_transform) { |
|
|
|
|
output->transform = WL_OUTPUT_TRANSFORM_NORMAL; |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!strcmp(output_transform, "normal")) |
|
|
|
|
output->transform = WL_OUTPUT_TRANSFORM_NORMAL; |
|
|
|
|
else if (!strcmp(output_transform, "90")) |
|
|
|
|
output->transform = WL_OUTPUT_TRANSFORM_90; |
|
|
|
|
else if (!strcmp(output_transform, "180")) |
|
|
|
|
output->transform = WL_OUTPUT_TRANSFORM_180; |
|
|
|
|
else if (!strcmp(output_transform, "270")) |
|
|
|
|
output->transform = WL_OUTPUT_TRANSFORM_270; |
|
|
|
|
else if (!strcmp(output_transform, "flipped")) |
|
|
|
|
output->transform = WL_OUTPUT_TRANSFORM_FLIPPED; |
|
|
|
|
else if (!strcmp(output_transform, "flipped-90")) |
|
|
|
|
output->transform = WL_OUTPUT_TRANSFORM_FLIPPED_90; |
|
|
|
|
else if (!strcmp(output_transform, "flipped-180")) |
|
|
|
|
output->transform = WL_OUTPUT_TRANSFORM_FLIPPED_180; |
|
|
|
|
else if (!strcmp(output_transform, "flipped-270")) |
|
|
|
|
output->transform = WL_OUTPUT_TRANSFORM_FLIPPED_270; |
|
|
|
|
else { |
|
|
|
|
weston_log("Invalid transform \"%s\" for output %s\n", |
|
|
|
|
output_transform, output_name); |
|
|
|
|
output->transform = WL_OUTPUT_TRANSFORM_NORMAL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
free(output_transform); |
|
|
|
|
output_transform = NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void |
|
|
|
|
output_section_done(void *data) |
|
|
|
|
{ |
|
|
|
|
struct drm_configured_output *output; |
|
|
|
|
|
|
|
|
|
output = malloc(sizeof *output); |
|
|
|
|
|
|
|
|
|
if (!output || !output_name || (output_name[0] == 'X') || |
|
|
|
|
(!output_mode && !output_transform && !output_scale)) { |
|
|
|
|
free(output_name); |
|
|
|
|
free(output_mode); |
|
|
|
|
free(output_transform); |
|
|
|
|
free(output_scale); |
|
|
|
|
free(output); |
|
|
|
|
output_name = NULL; |
|
|
|
|
output_mode = NULL; |
|
|
|
|
output_transform = NULL; |
|
|
|
|
output_scale = NULL; |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
output->config = OUTPUT_CONFIG_INVALID; |
|
|
|
|
output->name = output_name; |
|
|
|
|
output->mode = output_mode; |
|
|
|
|
|
|
|
|
|
if (output_mode) { |
|
|
|
|
if (strcmp(output_mode, "off") == 0) |
|
|
|
|
output->config = OUTPUT_CONFIG_OFF; |
|
|
|
|
else if (strcmp(output_mode, "preferred") == 0) |
|
|
|
|
output->config = OUTPUT_CONFIG_PREFERRED; |
|
|
|
|
else if (strcmp(output_mode, "current") == 0) |
|
|
|
|
output->config = OUTPUT_CONFIG_CURRENT; |
|
|
|
|
else if (sscanf(output_mode, "%dx%d", |
|
|
|
|
&output->width, &output->height) == 2) |
|
|
|
|
output->config = OUTPUT_CONFIG_MODE; |
|
|
|
|
else if (check_for_modeline(output) == 0) |
|
|
|
|
output->config = OUTPUT_CONFIG_MODELINE; |
|
|
|
|
|
|
|
|
|
if (output->config == OUTPUT_CONFIG_INVALID) |
|
|
|
|
weston_log("Invalid mode \"%s\" for output %s\n", |
|
|
|
|
output_mode, output_name); |
|
|
|
|
output_mode = NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
drm_output_set_transform(output); |
|
|
|
|
|
|
|
|
|
if (!output_scale || sscanf(output_scale, "%d", &output->scale) != 1) |
|
|
|
|
output->scale = 1; |
|
|
|
|
|
|
|
|
|
wl_list_insert(&configured_output_list, &output->link); |
|
|
|
|
|
|
|
|
|
if (output_transform) |
|
|
|
|
free(output_transform); |
|
|
|
|
output_transform = NULL; |
|
|
|
|
if (output_scale) |
|
|
|
|
free(output_scale); |
|
|
|
|
output_scale = NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
WL_EXPORT struct weston_compositor * |
|
|
|
|
backend_init(struct wl_display *display, int *argc, char *argv[], |
|
|
|
|
int config_fd) |
|
|
|
@ -2716,23 +2617,6 @@ backend_init(struct wl_display *display, int *argc, char *argv[], |
|
|
|
|
|
|
|
|
|
parse_options(drm_options, ARRAY_LENGTH(drm_options), argc, argv); |
|
|
|
|
|
|
|
|
|
wl_list_init(&configured_output_list); |
|
|
|
|
|
|
|
|
|
const struct config_key drm_config_keys[] = { |
|
|
|
|
{ "name", CONFIG_KEY_STRING, &output_name }, |
|
|
|
|
{ "mode", CONFIG_KEY_STRING, &output_mode }, |
|
|
|
|
{ "transform", CONFIG_KEY_STRING, &output_transform }, |
|
|
|
|
{ "scale", CONFIG_KEY_STRING, &output_scale }, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
const struct config_section config_section[] = { |
|
|
|
|
{ "output", drm_config_keys, |
|
|
|
|
ARRAY_LENGTH(drm_config_keys), output_section_done }, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
parse_config_file(config_fd, config_section, |
|
|
|
|
ARRAY_LENGTH(config_section), NULL); |
|
|
|
|
|
|
|
|
|
return drm_compositor_create(display, connector, seat, tty, use_pixman, |
|
|
|
|
argc, argv, config_fd); |
|
|
|
|
} |
|
|
|
|