backend-drm: add support for KMS devices with only coverage blend mode

The majority of KMS devices support pre-multiplied encoded framebuffers.
But a few of them don't. This adds support for such devices.

In-shader blending is required for this, and it shouldn't work on
devices that don't support it. For now this works only with the
GL-renderer.

Note: this should never work with test quirks
gl_force_full_redraw_of_shadow_fb and blending_impl ==
WESTON_BLENDING_IMPL_FF.

Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
This commit is contained in:
Leandro Ribeiro 2026-04-15 20:54:54 -03:00
parent b4554fa2d7
commit 595a15db48
13 changed files with 260 additions and 33 deletions

View file

@ -378,6 +378,15 @@ enum weston_repaint_status {
REPAINT_DEFERRED,
};
/** Output's required framebuffer alpha encoding
*
* \ingroup output
*/
enum weston_output_fb_alpha_encoding {
WESTON_OUTPUT_FB_ALPHA_ENCODING_PREMULT = 0,
WESTON_OUTPUT_FB_ALPHA_ENCODING_STRAIGHT,
};
/** Content producer for heads
*
* \rst
@ -582,6 +591,8 @@ struct weston_output {
enum weston_color_format color_format;
enum weston_output_fb_alpha_encoding fb_alpha_encoding;
/**
* Set by the shell to indicate there's some content for this
* output to display.

View file

@ -562,6 +562,18 @@ drm_output_render(struct drm_output_state *state)
scanout_state = drm_output_state_get_plane(state, scanout_plane);
weston_assert_ptr_null(c, scanout_state->fb);
if (output->base.fb_alpha_encoding == WESTON_OUTPUT_FB_ALPHA_ENCODING_PREMULT) {
weston_assert_true(c, drm_plane_supports_blend_mode(scanout_plane,
WDRM_PLANE_BLEND_DEFAULT));
scanout_state->blend_mode = WDRM_PLANE_BLEND_DEFAULT;
} else if (output->base.fb_alpha_encoding == WESTON_OUTPUT_FB_ALPHA_ENCODING_STRAIGHT) {
weston_assert_true(c, drm_plane_supports_blend_mode(scanout_plane,
WDRM_PLANE_BLEND_COVERAGE));
scanout_state->blend_mode = WDRM_PLANE_BLEND_COVERAGE;
} else {
weston_assert_not_reached(c, "unknown fb alpha encoding");
}
pixman_region32_init(&damage);
weston_output_flush_damage_for_primary_plane(&output->base, &damage);
@ -2677,6 +2689,19 @@ drm_output_init_planes(struct drm_output *output)
}
primary_plane_zpos_min = scanout_plane->zpos_min;
/**
* If only coverage blend mode supported by primary plane, renderers
* should produce straight alpha fb's.
*/
if (!drm_plane_supports_blend_mode(scanout_plane, WDRM_PLANE_BLEND_DEFAULT)) {
if (!drm_plane_supports_blend_mode(scanout_plane, WDRM_PLANE_BLEND_COVERAGE)) {
weston_log("Error: primary plane must support either premult "
"or coverage alpha blend mode.\n");
return -1;
}
output->base.fb_alpha_encoding = WESTON_OUTPUT_FB_ALPHA_ENCODING_STRAIGHT;
}
/* Failing to find a cursor plane is not fatal, as we'll fall back
* to software cursor. */
cursor_plane =
@ -2884,6 +2909,27 @@ should_wait_drm_events(struct drm_device *device)
return false;
}
static void
maybe_disable_underlays_for_coverage_alpha(struct drm_output *output,
const struct weston_renderer *renderer)
{
struct weston_compositor *wc = output->base.compositor;
/**
* When straight alpha mode is set, we must feed the primary plane with
* straight alpha fb's. If renderer can't do that, we can still support
* straight alpha outputs by disabling underlays (as the primary plane
* won't get blended with something below it).
*/
if (output->base.fb_alpha_encoding == WESTON_OUTPUT_FB_ALPHA_ENCODING_STRAIGHT &&
!renderer->can_render_fb_encoding_straight_alpha(wc)) {
weston_log("Disabling underlay planes for output '%s': straight alpha "
"is set but renderer can't produce straight alpha fb's.\n",
output->base.name);
output->has_underlay = false;
}
}
static int
drm_output_enable(struct weston_output *base)
{
@ -2922,6 +2968,8 @@ drm_output_enable(struct weston_output *base)
if (ret < 0)
goto err_crtc;
maybe_disable_underlays_for_coverage_alpha(output, b->compositor->renderer);
if (drm_output_init_legacy_gamma_size(output) < 0)
goto err_planes;

View file

@ -103,6 +103,36 @@ drm_output_check_plane_has_view_assigned(struct drm_plane *plane,
return false;
}
static bool
select_plane_blend_mode(struct drm_plane_state *state,
struct drm_fb *fb, char **err_msg)
{
struct drm_plane *plane = state->plane;
if (drm_plane_supports_blend_mode(plane, WDRM_PLANE_BLEND_DEFAULT)) {
state->blend_mode = WDRM_PLANE_BLEND_DEFAULT;
return true;
}
/**
* TODO: for now we don't support coverage alpha from the color
* representation protocol. With that we'd be able to place non-opaque
* straight alpha content in planes that only support coverage blend
* mode.
*/
if (drm_plane_supports_blend_mode(plane, WDRM_PLANE_BLEND_COVERAGE)) {
if (state->alpha != DRM_PLANE_ALPHA_OPAQUE || fb->format->bits.a != 0) {
str_printf(err_msg, "can't offload non-opaque content for outputs in alpha coverage mode");
return false;
}
state->blend_mode = WDRM_PLANE_BLEND_COVERAGE;
return true;
}
str_printf(err_msg, "neither pre-mult or coverage blend modes are supported");
return false;
}
static struct drm_plane_state *
drm_output_try_paint_node_on_plane(struct drm_plane_handle *handle,
struct drm_output_state *output_state,
@ -116,6 +146,7 @@ drm_output_try_paint_node_on_plane(struct drm_plane_handle *handle,
struct drm_backend *b = device->backend;
struct drm_plane *plane = handle->plane;
struct drm_plane_state *state = NULL;
char *err_msg;
assert(!device->disable_client_buffer_scanout);
assert(output == handle->output);
@ -133,6 +164,13 @@ drm_output_try_paint_node_on_plane(struct drm_plane_handle *handle,
drm_plane_state_coords_for_paint_node(state, pnode, zpos);
if (!select_plane_blend_mode(state, fb, &err_msg)) {
drm_debug(b, "\t\t\t[paint node] not placing paint node %s on plane %lu: %s\n",
pnode->internal_name, (unsigned long) plane->plane_id, err_msg);
free(err_msg);
goto out;
}
/* We hold one reference for the lifetime of this function; from
* calling drm_fb_get_from_paint_node() in
* drm_output_prepare_plane_view(), so, we take another reference
@ -238,6 +276,7 @@ drm_output_prepare_cursor_paint_node(struct drm_output_state *output_state,
struct drm_plane *plane;
struct drm_plane_state *plane_state;
const char *p_name;
char *err_msg;
assert(!device->cursors_are_broken);
assert(handle);
@ -283,6 +322,13 @@ drm_output_prepare_cursor_paint_node(struct drm_output_state *output_state,
*/
plane_state->fb = drm_fb_ref(output->gbm_cursor_fb[0]);
if (!select_plane_blend_mode(plane_state, plane_state->fb, &err_msg)) {
drm_debug(b, "\t\t\t\t[%s] not assigning paint node %s to %s plane (%s)\n",
p_name, pnode->internal_name, p_name, err_msg);
free(err_msg);
goto err;
}
/* The cursor API is somewhat special: in cursor_bo_update(), we upload
* a buffer which is always cursor_width x cursor_height, even if the
* surface we want to promote is actually smaller than this. Manually

View file

@ -8376,6 +8376,7 @@ weston_output_init(struct weston_output *output,
output->allow_protection = true;
output->power_state = WESTON_OUTPUT_POWER_NORMAL;
output->repaint_only_on_capture = false;
output->fb_alpha_encoding = WESTON_OUTPUT_FB_ALPHA_ENCODING_PREMULT;
wl_list_init(&output->head_list);

View file

@ -201,6 +201,14 @@ struct weston_renderer {
uint32_t format,
const uint64_t *modifiers, unsigned int count);
/** Checks if renderer is able to produce fb's with straight alpha
* encoding (i.e. not pre-multiplied by alpha).
*
* \param wc The Weston compositor instance.
* \return True if renderer is capable, false otherwise.
*/
bool (*can_render_fb_encoding_straight_alpha)(struct weston_compositor *wc);
enum weston_renderer_type type;
const struct gl_renderer_interface *gl;
const struct vulkan_renderer_interface *vulkan;

View file

@ -57,6 +57,12 @@ noop_renderer_flush_damage(struct weston_paint_node *pnode)
{
}
static bool
noop_renderer_can_render_fb_encoding_straight_alpha(struct weston_compositor *wc)
{
return false;
}
static void
noop_renderer_attach(struct weston_paint_node *pnode)
{
@ -135,6 +141,7 @@ noop_renderer_init(struct weston_compositor *ec)
renderer->base.flush_damage = noop_renderer_flush_damage;
renderer->base.attach = noop_renderer_attach;
renderer->base.destroy = noop_renderer_destroy;
renderer->base.can_render_fb_encoding_straight_alpha = noop_renderer_can_render_fb_encoding_straight_alpha;
renderer->base.type = WESTON_RENDERER_NOOP;
ec->renderer = &renderer->base;

View file

@ -947,6 +947,12 @@ pixman_renderer_destroy_renderbuffer(weston_renderbuffer_t renderbuffer)
free(rb);
}
static bool
pixman_renderer_can_render_fb_encoding_straight_alpha(struct weston_compositor *wc)
{
return false;
}
static bool
pixman_renderer_discard_renderbuffers(struct pixman_output_state *po,
bool destroy)
@ -1080,6 +1086,8 @@ pixman_renderer_init(struct weston_compositor *ec)
renderer->base.create_renderbuffer_dmabuf = NULL;
renderer->base.destroy_renderbuffer =
pixman_renderer_destroy_renderbuffer;
renderer->base.can_render_fb_encoding_straight_alpha =
pixman_renderer_can_render_fb_encoding_straight_alpha;
renderer->base.type = WESTON_RENDERER_PIXMAN;
renderer->base.pixman = &pixman_renderer_interface;
ec->renderer = &renderer->base;

View file

@ -60,6 +60,10 @@
#define SHADER_COLOR_MAPPING_3DLUT 1
#define SHADER_COLOR_MAPPING_MATRIX 2
/* enum gl_shader_fb_alpha_encoding */
#define SHADER_FB_ALPHA_ENCODING_PREMULT 0
#define SHADER_FB_ALPHA_ENCODING_STRAIGHT 1
#if DEF_VARIANT == SHADER_VARIANT_EXTERNAL
#extension GL_OES_EGL_image_external : require
#endif
@ -91,6 +95,7 @@ compile_const int c_color_post_curve = DEF_COLOR_POST_CURVE;
compile_const int c_fb_fetch_curve = DEF_FB_FETCH_CURVE;
compile_const int c_fb_store_curve = DEF_FB_STORE_CURVE;
compile_const int c_color_effect = DEF_COLOR_EFFECT;
compile_const int c_fb_alpha_encoding = DEF_FB_ALPHA_ENCODING;
compile_const bool c_input_is_premult = DEF_INPUT_IS_PREMULT;
compile_const bool c_tint = DEF_TINT;
@ -570,15 +575,29 @@ main()
vec4 src;
vec4 dst;
/* Always alpha pre-multiplied. */
src = fragment_input_color_premult();
/* Framebuffer must have straight alpha. */
/**
* Framebuffer content is pre-multiplied if c_alpha_premult_blending,
* straight alpha otherwise.
*/
dst = gl_LastFragData[0];
dst.rgb = color_curve(c_fb_fetch_curve, fb_fetch_curve_lut,
fb_fetch_curve_par, dst.rgb);
/* glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); */
dst = src + (1.0 - src.a) * dst;
if (c_fb_alpha_encoding == SHADER_FB_ALPHA_ENCODING_PREMULT) {
/* glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); */
dst = src + (1.0 - src.a) * dst;
} else {
/* SHADER_FB_ALPHA_ENCODING_STRAIGHT; same formula here, but
* dst is not alpha pre-mult. */
dst.rgb = src.rgb + (1.0 - src.a) * dst.rgb * dst.a;
dst.a = src.a + (1.0 - src.a) * dst.a;
/* Leave the fb as straight alpha */
if (dst.a > 0.0)
dst.rgb /= dst.a;
}
dst.rgb = color_curve(c_fb_store_curve, fb_store_curve_lut,
fb_store_curve_par, dst.rgb);

View file

@ -252,6 +252,12 @@ enum gl_shader_color_mapping {
SHADER_COLOR_MAPPING_MATRIX,
};
/* Keep the following in sync with fragment.glsl. */
enum gl_shader_fb_alpha_encoding {
SHADER_FB_ALPHA_ENCODING_PREMULT = 0,
SHADER_FB_ALPHA_ENCODING_STRAIGHT,
};
enum gl_shader_attrib_loc {
SHADER_ATTRIB_LOC_POSITION = 0,
SHADER_ATTRIB_LOC_TEXCOORD,
@ -313,6 +319,7 @@ struct gl_shader_requirements
unsigned color_post_curve:3; /* enum gl_shader_color_curve */
bool shader_blending:1;
unsigned fb_alpha_encoding:1; /* enum gl_shader_fb_alpha_encoding */
unsigned fb_fetch_curve:3; /* enum gl_shader_color_curve */
unsigned fb_store_curve:3; /* enum gl_shader_color_curve */
@ -320,7 +327,7 @@ struct gl_shader_requirements
* The total size of all bitfields plus pad_bits_ must fill up exactly
* how many bytes the compiler allocates for them together.
*/
unsigned pad_bits_:7;
unsigned pad_bits_:6;
};
static_assert(sizeof(struct gl_shader_requirements) ==
4 /* total bitfield size in bytes */,
@ -406,6 +413,8 @@ struct gl_shader_config {
union gl_shader_config_color_curve fb_fetch_curve;
union gl_shader_config_color_curve fb_store_curve;
enum gl_shader_fb_alpha_encoding fb_alpha_encoding;
enum weston_color_matrix_coef yuv_coefficients;
enum weston_color_quant_range yuv_range;
};
@ -787,7 +796,8 @@ void
gl_shader_blender_destroy(struct gl_shader_blender *shader_blender);
struct gl_shader_blender *
gl_shader_blender_create(struct gl_renderer *gr, struct weston_output *output);
gl_shader_blender_create(struct gl_renderer *gr, struct weston_output *output,
enum gl_shader_fb_alpha_encoding fb_alpha_encoding);
void
gl_shader_config_set_blender(struct gl_renderer *gr,

View file

@ -4791,6 +4791,26 @@ gl_renderer_create_window_surface(struct gl_renderer *gr,
return egl_surface;
}
static bool
gl_renderer_can_render_fb_encoding_straight_alpha(struct weston_compositor *wc)
{
const struct weston_testsuite_quirks *quirks = &wc->test_data.test_quirks;
struct gl_renderer *gr = get_renderer(wc);
if (!gl_features_has(gr, FEATURE_SHADER_BLENDING))
return false;
/* In-shader blending is required. */
if (quirks->blending_impl == WESTON_BLENDING_IMPL_FF)
return false;
/* This forbids in-shader blending. */
if (quirks->gl_force_full_redraw_of_shadow_fb)
return false;
return true;
}
static int
gl_renderer_output_create(struct weston_output *output,
EGLSurface surface,
@ -4801,8 +4821,11 @@ gl_renderer_output_create(struct weston_output *output,
struct weston_compositor *wc = output->compositor;
struct gl_renderer *gr = get_renderer(wc);
const struct weston_testsuite_quirks *quirks = &wc->test_data.test_quirks;
enum gl_shader_fb_alpha_encoding fb_alpha_encoding;
bool needs_fb_curves;
bool needs_shadow;
bool needs_shader_blending;
bool needs_straight_alpha;
int i;
assert(!get_output_state(output));
@ -4830,25 +4853,33 @@ gl_renderer_output_create(struct weston_output *output,
go->render_sync = EGL_NO_SYNC_KHR;
needs_shadow = quirks->gl_force_full_redraw_of_shadow_fb;
needs_straight_alpha = output->fb_alpha_encoding == WESTON_OUTPUT_FB_ALPHA_ENCODING_STRAIGHT &&
gl_renderer_can_render_fb_encoding_straight_alpha(wc);
needs_shader_blending = quirks->blending_impl == WESTON_BLENDING_IMPL_SHADER ||
needs_straight_alpha;
needs_fb_curves = output->color_outcome->from_blend_to_output &&
!output->from_blend_to_output_by_backend;
if (needs_fb_curves)
weston_assert_true(wc, gl_features_has(gr, FEATURE_COLOR_TRANSFORMS));
if (!needs_shadow && needs_fb_curves) {
if (needs_shader_blending)
weston_assert_false(wc, needs_shadow);
if (!needs_shadow && (needs_fb_curves || needs_shader_blending)) {
switch (quirks->blending_impl) {
case WESTON_BLENDING_IMPL_AUTO:
go->shader_blender = gl_shader_blender_create(gr, output);
break;
case WESTON_BLENDING_IMPL_FF:
weston_assert_false(wc, needs_shader_blending);
go->shader_blender = NULL;
break;
case WESTON_BLENDING_IMPL_AUTO:
case WESTON_BLENDING_IMPL_SHADER:
go->shader_blender = gl_shader_blender_create(gr, output);
if (!go->shader_blender) {
weston_log("Error: quirks were used to force in-shader blending, "
"but it's not supported by the GLES implementation.\n"
fb_alpha_encoding = needs_straight_alpha ? SHADER_FB_ALPHA_ENCODING_STRAIGHT :
SHADER_FB_ALPHA_ENCODING_PREMULT;
go->shader_blender = gl_shader_blender_create(gr, output, fb_alpha_encoding);
if (needs_shader_blending && !go->shader_blender) {
weston_log("Error: in-shader blending required but not supported by "
"the GLES implementation.\n"
"Quitting...\n");
weston_compositor_exit_with_code(wc, RESULT_SKIP);
}
@ -5235,6 +5266,7 @@ gl_renderer_display_create(struct weston_compositor *ec,
gr->base.surface_copy_content = gl_renderer_surface_copy_content;
gr->base.fill_buffer_info = gl_renderer_fill_buffer_info;
gr->base.buffer_init = gl_renderer_buffer_init;
gr->base.can_render_fb_encoding_straight_alpha = gl_renderer_can_render_fb_encoding_straight_alpha;
gr->base.output_set_border = gl_renderer_output_set_border;
gr->base.type = WESTON_RENDERER_GL;

View file

@ -67,6 +67,7 @@ struct gl_renderer_color_effect {
/** for in-shader blending */
struct gl_shader_blender {
enum gl_shader_fb_alpha_encoding fb_alpha_encoding;
struct gl_renderer_color_curve fb_fetch_curve;
struct gl_renderer_color_curve fb_store_curve;
};
@ -588,40 +589,51 @@ gl_shader_blender_destroy(struct gl_shader_blender *shader_blender)
}
struct gl_shader_blender *
gl_shader_blender_create(struct gl_renderer *gr, struct weston_output *output)
gl_shader_blender_create(struct gl_renderer *gr, struct weston_output *output,
enum gl_shader_fb_alpha_encoding fb_alpha_encoding)
{
struct gl_shader_blender *shader_blender;
struct weston_color_curve *fb_fetch;
const struct weston_color_curve *fb_store;
const struct weston_color_transform *xform;
const struct weston_color_curve identity_curve = {
.type = WESTON_COLOR_CURVE_TYPE_IDENTITY,
};
bool ok;
if (!gl_features_has(gr, FEATURE_SHADER_BLENDING))
return NULL;
xform = output->color_outcome->from_blend_to_output;
if (!xform)
return NULL;
fb_store = weston_color_transform_as_single_curve(xform);
if (!fb_store)
return NULL;
fb_fetch = weston_color_curve_create_inverse(fb_store);
if (!fb_fetch)
return NULL;
shader_blender = xzalloc(sizeof *shader_blender);
ok = gl_color_curve_init(gr, &shader_blender->fb_store_curve, fb_store, NULL) &&
gl_color_curve_init(gr, &shader_blender->fb_fetch_curve, fb_fetch, NULL);
free(fb_fetch);
shader_blender->fb_alpha_encoding = fb_alpha_encoding;
if (!ok) {
free(shader_blender);
return NULL;
xform = output->color_outcome->from_blend_to_output;
if (xform) {
fb_store = weston_color_transform_as_single_curve(xform);
if (!fb_store)
goto fail;
fb_fetch = weston_color_curve_create_inverse(fb_store);
if (!fb_fetch)
goto fail;
ok = gl_color_curve_init(gr, &shader_blender->fb_store_curve, fb_store, NULL) &&
gl_color_curve_init(gr, &shader_blender->fb_fetch_curve, fb_fetch, NULL);
free(fb_fetch);
} else {
ok = gl_color_curve_init(gr, &shader_blender->fb_store_curve, &identity_curve, NULL) &&
gl_color_curve_init(gr, &shader_blender->fb_fetch_curve, &identity_curve, NULL);
}
if (!ok)
goto fail;
return shader_blender;
fail:
free(shader_blender);
return NULL;
}
void
@ -637,9 +649,12 @@ gl_shader_config_set_blender(struct gl_renderer *gr,
sconf->req.fb_store_curve = shader_blender->fb_store_curve.type;
sconf->fb_store_curve = shader_blender->fb_store_curve.u;
sconf->fb_alpha_encoding = shader_blender->fb_alpha_encoding;
} else {
sconf->req.shader_blending = false;
sconf->req.fb_fetch_curve = SHADER_COLOR_CURVE_IDENTITY;
sconf->req.fb_store_curve = SHADER_COLOR_CURVE_IDENTITY;
sconf->fb_alpha_encoding = SHADER_FB_ALPHA_ENCODING_PREMULT;
}
}

View file

@ -191,6 +191,18 @@ gl_shader_color_mapping_to_string(enum gl_shader_color_mapping kind)
return gl_shader_enum_map_get(gl_shader_color_mapping_mapping, kind);
}
static const struct gl_shader_enum_map gl_shader_fb_alpha_encoding_mapping[] = {
ENUMVAL(SHADER_FB_ALPHA_ENCODING_PREMULT, "pre-mult"),
ENUMVAL(SHADER_FB_ALPHA_ENCODING_STRAIGHT, "straight"),
};
static const struct gl_shader_enum_map *
gl_shader_fb_alpha_encoding_to_string(enum gl_shader_fb_alpha_encoding kind)
{
return gl_shader_enum_map_get(gl_shader_fb_alpha_encoding_mapping, kind);
}
static void
dump_program_with_line_numbers(int count, const char **sources)
{
@ -256,7 +268,7 @@ create_shader_description_string(const struct gl_shader_requirements *req)
int size;
char *str;
size = asprintf(&str, "%s tc, %s tex, %s effect, CP{ %s, %s, %s }, %cpremult_in %ctint %cshader_blending (%s, %s)",
size = asprintf(&str, "%s tc, %s tex, %s effect, CP{ %s, %s, %s }, %cpremult_in %ctint %cshader_blending fb_alpha_encoding %s (%s, %s)",
gl_shader_texcoord_input_to_string(req->texcoord_input)->desc,
gl_shader_texture_variant_to_string(req->variant)->desc,
gl_shader_color_effect_to_string(req->color_effect)->desc,
@ -266,6 +278,7 @@ create_shader_description_string(const struct gl_shader_requirements *req)
req->input_is_premult ? '+' : '-',
req->tint ? '+' : '-',
req->shader_blending ? '+' : '-',
gl_shader_fb_alpha_encoding_to_string(req->fb_alpha_encoding)->desc,
gl_shader_color_curve_to_string(req->fb_fetch_curve)->desc,
gl_shader_color_curve_to_string(req->fb_store_curve)->desc);
if (size < 0)
@ -305,6 +318,7 @@ create_fragment_shader_config_string(const struct gl_shader_requirements *req)
"#define DEF_COLOR_MAPPING %s\n"
"#define DEF_COLOR_POST_CURVE %s\n"
"#define DEF_SHADER_BLENDING %s\n"
"#define DEF_FB_ALPHA_ENCODING %s\n"
"#define DEF_FB_FETCH_CURVE %s\n"
"#define DEF_FB_STORE_CURVE %s\n"
"#define DEF_COLOR_EFFECT %s\n"
@ -317,6 +331,7 @@ create_fragment_shader_config_string(const struct gl_shader_requirements *req)
gl_shader_color_mapping_to_string(req->color_mapping)->symbol,
gl_shader_color_curve_to_string(req->color_post_curve)->symbol,
req->shader_blending ? "1" : "0",
gl_shader_fb_alpha_encoding_to_string(req->fb_alpha_encoding)->symbol,
gl_shader_color_curve_to_string(req->fb_fetch_curve)->symbol,
gl_shader_color_curve_to_string(req->fb_store_curve)->symbol,
gl_shader_color_effect_to_string(req->color_effect)->symbol,

View file

@ -3196,6 +3196,12 @@ vulkan_renderer_buffer_init(struct weston_compositor *ec,
wl_signal_add(&buffer->destroy_signal, &vb->destroy_listener);
}
static bool
vulkan_renderer_can_render_fb_encoding_straight_alpha(struct weston_compositor *wc)
{
return false;
}
static void
vulkan_renderer_output_destroy_border(struct weston_output *output,
enum weston_renderer_border_side side)
@ -4393,6 +4399,7 @@ vulkan_renderer_display_create(struct weston_compositor *ec,
vr->base.attach = vulkan_renderer_attach;
vr->base.destroy = vulkan_renderer_destroy;
vr->base.buffer_init = vulkan_renderer_buffer_init;
vr->base.can_render_fb_encoding_straight_alpha = vulkan_renderer_can_render_fb_encoding_straight_alpha;
vr->base.output_set_border = vulkan_renderer_output_set_border,
vr->base.type = WESTON_RENDERER_VULKAN;