Add support for having different GBM formats for different outputs
The gbm-format configuration option can now be specified per-output as well as in the core config section. If it is not specified it will default to the format specified in the core section. The EGL_MESA_configless_context extension is required for this to work. If this extension is available it will create a context without an EGLConfig and then it will potentially use a different EGLConfig for each output. The gl-renderer interface has been changed so that it takes the EGL attributes and visual ID in the create_output function as well as in the create function.
This commit is contained in:
committed by
Kristian Høgsberg
parent
b7f8533e2b
commit
77c1a5b7dc
+45
-20
@@ -147,6 +147,7 @@ struct drm_output {
|
|||||||
drmModeCrtcPtr original_crtc;
|
drmModeCrtcPtr original_crtc;
|
||||||
struct drm_edid edid;
|
struct drm_edid edid;
|
||||||
drmModePropertyPtr dpms_prop;
|
drmModePropertyPtr dpms_prop;
|
||||||
|
uint32_t format;
|
||||||
|
|
||||||
int vblank_pending;
|
int vblank_pending;
|
||||||
int page_flip_pending;
|
int page_flip_pending;
|
||||||
@@ -420,8 +421,6 @@ static uint32_t
|
|||||||
drm_output_check_scanout_format(struct drm_output *output,
|
drm_output_check_scanout_format(struct drm_output *output,
|
||||||
struct weston_surface *es, struct gbm_bo *bo)
|
struct weston_surface *es, struct gbm_bo *bo)
|
||||||
{
|
{
|
||||||
struct drm_compositor *c =
|
|
||||||
(struct drm_compositor *) output->base.compositor;
|
|
||||||
uint32_t format;
|
uint32_t format;
|
||||||
pixman_region32_t r;
|
pixman_region32_t r;
|
||||||
|
|
||||||
@@ -442,7 +441,7 @@ drm_output_check_scanout_format(struct drm_output *output,
|
|||||||
pixman_region32_fini(&r);
|
pixman_region32_fini(&r);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c->format == format)
|
if (output->format == format)
|
||||||
return format;
|
return format;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -507,7 +506,7 @@ drm_output_render_gl(struct drm_output *output, pixman_region32_t *damage)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
output->next = drm_fb_get_from_bo(bo, c, c->format);
|
output->next = drm_fb_get_from_bo(bo, c, output->format);
|
||||||
if (!output->next) {
|
if (!output->next) {
|
||||||
weston_log("failed to get drm_fb for bo\n");
|
weston_log("failed to get drm_fb for bo\n");
|
||||||
gbm_surface_release_buffer(output->surface, bo);
|
gbm_surface_release_buffer(output->surface, bo);
|
||||||
@@ -1528,12 +1527,13 @@ find_crtc_for_connector(struct drm_compositor *ec,
|
|||||||
static int
|
static int
|
||||||
drm_output_init_egl(struct drm_output *output, struct drm_compositor *ec)
|
drm_output_init_egl(struct drm_output *output, struct drm_compositor *ec)
|
||||||
{
|
{
|
||||||
|
EGLint format = output->format;
|
||||||
int i, flags;
|
int i, flags;
|
||||||
|
|
||||||
output->surface = gbm_surface_create(ec->gbm,
|
output->surface = gbm_surface_create(ec->gbm,
|
||||||
output->base.current_mode->width,
|
output->base.current_mode->width,
|
||||||
output->base.current_mode->height,
|
output->base.current_mode->height,
|
||||||
ec->format,
|
format,
|
||||||
GBM_BO_USE_SCANOUT |
|
GBM_BO_USE_SCANOUT |
|
||||||
GBM_BO_USE_RENDERING);
|
GBM_BO_USE_RENDERING);
|
||||||
if (!output->surface) {
|
if (!output->surface) {
|
||||||
@@ -1541,7 +1541,9 @@ drm_output_init_egl(struct drm_output *output, struct drm_compositor *ec)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gl_renderer->output_create(&output->base, output->surface) < 0) {
|
if (gl_renderer->output_create(&output->base, output->surface,
|
||||||
|
gl_renderer->opaque_attribs,
|
||||||
|
&format) < 0) {
|
||||||
weston_log("failed to create gl renderer output state\n");
|
weston_log("failed to create gl renderer output state\n");
|
||||||
gbm_surface_destroy(output->surface);
|
gbm_surface_destroy(output->surface);
|
||||||
return -1;
|
return -1;
|
||||||
@@ -1852,6 +1854,35 @@ setup_output_seat_constraint(struct drm_compositor *ec,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
get_gbm_format_from_section(struct weston_config_section *section,
|
||||||
|
uint32_t default_value,
|
||||||
|
uint32_t *format)
|
||||||
|
{
|
||||||
|
char *s;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
weston_config_section_get_string(section,
|
||||||
|
"gbm-format", &s, NULL);
|
||||||
|
|
||||||
|
if (s == NULL)
|
||||||
|
*format = default_value;
|
||||||
|
else if (strcmp(s, "xrgb8888") == 0)
|
||||||
|
*format = GBM_FORMAT_XRGB8888;
|
||||||
|
else if (strcmp(s, "rgb565") == 0)
|
||||||
|
*format = GBM_FORMAT_RGB565;
|
||||||
|
else if (strcmp(s, "xrgb2101010") == 0)
|
||||||
|
*format = GBM_FORMAT_XRGB2101010;
|
||||||
|
else {
|
||||||
|
weston_log("fatal: unrecognized pixel format: %s\n", s);
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(s);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
create_output_for_connector(struct drm_compositor *ec,
|
create_output_for_connector(struct drm_compositor *ec,
|
||||||
drmModeRes *resources,
|
drmModeRes *resources,
|
||||||
@@ -1919,6 +1950,11 @@ create_output_for_connector(struct drm_compositor *ec,
|
|||||||
transform = parse_transform(s, output->base.name);
|
transform = parse_transform(s, output->base.name);
|
||||||
free(s);
|
free(s);
|
||||||
|
|
||||||
|
if (get_gbm_format_from_section(section,
|
||||||
|
ec->format,
|
||||||
|
&output->format) == -1)
|
||||||
|
output->format = ec->format;
|
||||||
|
|
||||||
weston_config_section_get_string(section, "seat", &s, "");
|
weston_config_section_get_string(section, "seat", &s, "");
|
||||||
setup_output_seat_constraint(ec, &output->base, s);
|
setup_output_seat_constraint(ec, &output->base, s);
|
||||||
free(s);
|
free(s);
|
||||||
@@ -2663,7 +2699,6 @@ drm_compositor_create(struct wl_display *display,
|
|||||||
struct udev_device *drm_device;
|
struct udev_device *drm_device;
|
||||||
struct wl_event_loop *loop;
|
struct wl_event_loop *loop;
|
||||||
const char *path;
|
const char *path;
|
||||||
char *s;
|
|
||||||
uint32_t key;
|
uint32_t key;
|
||||||
|
|
||||||
weston_log("initializing drm backend\n");
|
weston_log("initializing drm backend\n");
|
||||||
@@ -2677,20 +2712,10 @@ drm_compositor_create(struct wl_display *display,
|
|||||||
ec->sprites_are_broken = 1;
|
ec->sprites_are_broken = 1;
|
||||||
|
|
||||||
section = weston_config_get_section(config, "core", NULL, NULL);
|
section = weston_config_get_section(config, "core", NULL, NULL);
|
||||||
weston_config_section_get_string(section,
|
if (get_gbm_format_from_section(section,
|
||||||
"gbm-format", &s, "xrgb8888");
|
GBM_FORMAT_XRGB8888,
|
||||||
if (strcmp(s, "xrgb8888") == 0)
|
&ec->format) == -1)
|
||||||
ec->format = GBM_FORMAT_XRGB8888;
|
|
||||||
else if (strcmp(s, "rgb565") == 0)
|
|
||||||
ec->format = GBM_FORMAT_RGB565;
|
|
||||||
else if (strcmp(s, "xrgb2101010") == 0)
|
|
||||||
ec->format = GBM_FORMAT_XRGB2101010;
|
|
||||||
else {
|
|
||||||
weston_log("fatal: unrecognized pixel format: %s\n", s);
|
|
||||||
free(s);
|
|
||||||
goto err_base;
|
goto err_base;
|
||||||
}
|
|
||||||
free(s);
|
|
||||||
|
|
||||||
ec->use_pixman = param->use_pixman;
|
ec->use_pixman = param->use_pixman;
|
||||||
|
|
||||||
|
|||||||
@@ -628,7 +628,9 @@ fbdev_output_create(struct fbdev_compositor *compositor,
|
|||||||
} else {
|
} else {
|
||||||
setenv("HYBRIS_EGLPLATFORM", "wayland", 1);
|
setenv("HYBRIS_EGLPLATFORM", "wayland", 1);
|
||||||
if (gl_renderer->output_create(&output->base,
|
if (gl_renderer->output_create(&output->base,
|
||||||
(EGLNativeWindowType)NULL) < 0) {
|
(EGLNativeWindowType)NULL,
|
||||||
|
gl_renderer->opaque_attribs,
|
||||||
|
NULL) < 0) {
|
||||||
weston_log("gl_renderer_output_create failed.\n");
|
weston_log("gl_renderer_output_create failed.\n");
|
||||||
goto out_shadow_surface;
|
goto out_shadow_surface;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -593,7 +593,9 @@ wayland_output_init_gl_renderer(struct wayland_output *output)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (gl_renderer->output_create(&output->base,
|
if (gl_renderer->output_create(&output->base,
|
||||||
output->gl.egl_window) < 0)
|
output->gl.egl_window,
|
||||||
|
gl_renderer->alpha_attribs,
|
||||||
|
NULL) < 0)
|
||||||
goto cleanup_window;
|
goto cleanup_window;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -890,7 +890,9 @@ x11_compositor_create_output(struct x11_compositor *c, int x, int y,
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ret = gl_renderer->output_create(&output->base,
|
ret = gl_renderer->output_create(&output->base,
|
||||||
(EGLNativeWindowType) output->window);
|
(EGLNativeWindowType) output->window,
|
||||||
|
gl_renderer->opaque_attribs,
|
||||||
|
NULL);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
+84
-50
@@ -139,6 +139,8 @@ struct gl_renderer {
|
|||||||
|
|
||||||
int has_egl_buffer_age;
|
int has_egl_buffer_age;
|
||||||
|
|
||||||
|
int has_configless_context;
|
||||||
|
|
||||||
struct gl_shader texture_shader_rgba;
|
struct gl_shader texture_shader_rgba;
|
||||||
struct gl_shader texture_shader_rgbx;
|
struct gl_shader texture_shader_rgbx;
|
||||||
struct gl_shader texture_shader_egl_external;
|
struct gl_shader texture_shader_egl_external;
|
||||||
@@ -1658,6 +1660,51 @@ log_egl_config_info(EGLDisplay egldpy, EGLConfig eglconfig)
|
|||||||
weston_log_continue(" unknown\n");
|
weston_log_continue(" unknown\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
egl_choose_config(struct gl_renderer *gr, const EGLint *attribs,
|
||||||
|
const EGLint *visual_id,
|
||||||
|
EGLConfig *config_out)
|
||||||
|
{
|
||||||
|
EGLint count = 0;
|
||||||
|
EGLint matched = 0;
|
||||||
|
EGLConfig *configs;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!eglGetConfigs(gr->egl_display, NULL, 0, &count) || count < 1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
configs = calloc(count, sizeof *configs);
|
||||||
|
if (!configs)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (!eglChooseConfig(gr->egl_display, attribs, configs,
|
||||||
|
count, &matched))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
for (i = 0; i < matched; ++i) {
|
||||||
|
EGLint id;
|
||||||
|
|
||||||
|
if (visual_id) {
|
||||||
|
if (!eglGetConfigAttrib(gr->egl_display,
|
||||||
|
configs[i], EGL_NATIVE_VISUAL_ID,
|
||||||
|
&id))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (id != 0 && id != *visual_id)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
*config_out = configs[i];
|
||||||
|
|
||||||
|
free(configs);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
free(configs);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gl_renderer_output_set_border(struct weston_output *output,
|
gl_renderer_output_set_border(struct weston_output *output,
|
||||||
enum gl_renderer_border_side side,
|
enum gl_renderer_border_side side,
|
||||||
@@ -1689,19 +1736,37 @@ gl_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface);
|
|||||||
|
|
||||||
static int
|
static int
|
||||||
gl_renderer_output_create(struct weston_output *output,
|
gl_renderer_output_create(struct weston_output *output,
|
||||||
EGLNativeWindowType window)
|
EGLNativeWindowType window,
|
||||||
|
const EGLint *attribs,
|
||||||
|
const EGLint *visual_id)
|
||||||
{
|
{
|
||||||
struct weston_compositor *ec = output->compositor;
|
struct weston_compositor *ec = output->compositor;
|
||||||
struct gl_renderer *gr = get_renderer(ec);
|
struct gl_renderer *gr = get_renderer(ec);
|
||||||
struct gl_output_state *go = calloc(1, sizeof *go);
|
struct gl_output_state *go;
|
||||||
|
EGLConfig egl_config;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
if (egl_choose_config(gr, attribs, visual_id, &egl_config) == -1) {
|
||||||
|
weston_log("failed to choose EGL config for output\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (egl_config != gr->egl_config &&
|
||||||
|
!gr->has_configless_context) {
|
||||||
|
weston_log("attempted to use a different EGL config for an "
|
||||||
|
"output but EGL_MESA_configless_context is not "
|
||||||
|
"supported\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
go = calloc(1, sizeof *go);
|
||||||
|
|
||||||
if (!go)
|
if (!go)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
go->egl_surface =
|
go->egl_surface =
|
||||||
eglCreateWindowSurface(gr->egl_display,
|
eglCreateWindowSurface(gr->egl_display,
|
||||||
gr->egl_config,
|
egl_config,
|
||||||
window, NULL);
|
window, NULL);
|
||||||
|
|
||||||
if (go->egl_surface == EGL_NO_SURFACE) {
|
if (go->egl_surface == EGL_NO_SURFACE) {
|
||||||
@@ -1721,6 +1786,8 @@ gl_renderer_output_create(struct weston_output *output,
|
|||||||
|
|
||||||
output->renderer_state = go;
|
output->renderer_state = go;
|
||||||
|
|
||||||
|
log_egl_config_info(gr->egl_display, egl_config);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1774,50 +1841,6 @@ gl_renderer_destroy(struct weston_compositor *ec)
|
|||||||
free(gr);
|
free(gr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
egl_choose_config(struct gl_renderer *gr, const EGLint *attribs,
|
|
||||||
const EGLint *visual_id)
|
|
||||||
{
|
|
||||||
EGLint count = 0;
|
|
||||||
EGLint matched = 0;
|
|
||||||
EGLConfig *configs;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (!eglGetConfigs(gr->egl_display, NULL, 0, &count) || count < 1)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
configs = calloc(count, sizeof *configs);
|
|
||||||
if (!configs)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (!eglChooseConfig(gr->egl_display, attribs, configs,
|
|
||||||
count, &matched))
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
for (i = 0; i < matched; ++i) {
|
|
||||||
EGLint id;
|
|
||||||
|
|
||||||
if (visual_id) {
|
|
||||||
if (!eglGetConfigAttrib(gr->egl_display,
|
|
||||||
configs[i], EGL_NATIVE_VISUAL_ID,
|
|
||||||
&id))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (id != 0 && id != *visual_id)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
gr->egl_config = configs[i];
|
|
||||||
|
|
||||||
free(configs);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
out:
|
|
||||||
free(configs);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
gl_renderer_setup_egl_extensions(struct weston_compositor *ec)
|
gl_renderer_setup_egl_extensions(struct weston_compositor *ec)
|
||||||
{
|
{
|
||||||
@@ -1864,6 +1887,11 @@ gl_renderer_setup_egl_extensions(struct weston_compositor *ec)
|
|||||||
"supported. Performance could be affected.\n");
|
"supported. Performance could be affected.\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef EGL_MESA_configless_context
|
||||||
|
if (strstr(extensions, "EGL_MESA_configless_context"))
|
||||||
|
gr->has_configless_context = 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1917,7 +1945,7 @@ gl_renderer_create(struct weston_compositor *ec, EGLNativeDisplayType display,
|
|||||||
goto err_egl;
|
goto err_egl;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (egl_choose_config(gr, attribs, visual_id) < 0) {
|
if (egl_choose_config(gr, attribs, visual_id, &gr->egl_config) < 0) {
|
||||||
weston_log("failed to choose EGL config\n");
|
weston_log("failed to choose EGL config\n");
|
||||||
goto err_egl;
|
goto err_egl;
|
||||||
}
|
}
|
||||||
@@ -2021,6 +2049,7 @@ gl_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface)
|
|||||||
{
|
{
|
||||||
struct gl_renderer *gr = get_renderer(ec);
|
struct gl_renderer *gr = get_renderer(ec);
|
||||||
const char *extensions;
|
const char *extensions;
|
||||||
|
EGLConfig context_config;
|
||||||
EGLBoolean ret;
|
EGLBoolean ret;
|
||||||
|
|
||||||
static const EGLint context_attribs[] = {
|
static const EGLint context_attribs[] = {
|
||||||
@@ -2034,9 +2063,14 @@ gl_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
log_egl_config_info(gr->egl_display, gr->egl_config);
|
context_config = gr->egl_config;
|
||||||
|
|
||||||
gr->egl_context = eglCreateContext(gr->egl_display, gr->egl_config,
|
#ifdef EGL_MESA_configless_context
|
||||||
|
if (gr->has_configless_context)
|
||||||
|
context_config = EGL_NO_CONFIG_MESA;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
gr->egl_context = eglCreateContext(gr->egl_display, context_config,
|
||||||
EGL_NO_CONTEXT, context_attribs);
|
EGL_NO_CONTEXT, context_attribs);
|
||||||
if (gr->egl_context == NULL) {
|
if (gr->egl_context == NULL) {
|
||||||
weston_log("failed to create context\n");
|
weston_log("failed to create context\n");
|
||||||
|
|||||||
+3
-1
@@ -58,7 +58,9 @@ struct gl_renderer_interface {
|
|||||||
EGLDisplay (*display)(struct weston_compositor *ec);
|
EGLDisplay (*display)(struct weston_compositor *ec);
|
||||||
|
|
||||||
int (*output_create)(struct weston_output *output,
|
int (*output_create)(struct weston_output *output,
|
||||||
EGLNativeWindowType window);
|
EGLNativeWindowType window,
|
||||||
|
const EGLint *attribs,
|
||||||
|
const EGLint *visual_id);
|
||||||
|
|
||||||
void (*output_destroy)(struct weston_output *output);
|
void (*output_destroy)(struct weston_output *output);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user