diff --git a/include/wlr/render/wlr_renderer.h b/include/wlr/render/wlr_renderer.h index a7d0241e..f6e63223 100644 --- a/include/wlr/render/wlr_renderer.h +++ b/include/wlr/render/wlr_renderer.h @@ -221,6 +221,8 @@ struct wlr_render_texture_options { enum wl_output_transform transform; /* Filtering */ enum wlr_scale_filter_mode filter_mode; + /* Blend mode */ + enum wlr_render_blend_mode blend_mode; }; /** diff --git a/render/gles2/pass.c b/render/gles2/pass.c index b1d21616..9003f08c 100644 --- a/render/gles2/pass.c +++ b/render/gles2/pass.c @@ -121,6 +121,17 @@ static void set_tex_matrix(GLint loc, enum wl_output_transform trans, glUniformMatrix3fv(loc, 1, GL_FALSE, tex_matrix); } +static void setup_blending(enum wlr_render_blend_mode mode) { + switch (mode) { + case WLR_RENDER_BLEND_MODE_PREMULTIPLIED: + glEnable(GL_BLEND); + break; + case WLR_RENDER_BLEND_MODE_NONE: + glDisable(GL_BLEND); + break; + } +} + static void render_pass_add_texture(struct wlr_render_pass *wlr_pass, const struct wlr_render_texture_options *options) { struct wlr_gles2_render_pass *pass = get_render_pass(wlr_pass); @@ -159,12 +170,8 @@ static void render_pass_add_texture(struct wlr_render_pass *wlr_pass, src_fbox.height /= options->texture->height; push_gles2_debug(renderer); - - if (!texture->has_alpha && alpha == 1.0) { - glDisable(GL_BLEND); - } else { - glEnable(GL_BLEND); - } + setup_blending(!texture->has_alpha && alpha == 1.0 ? + WLR_RENDER_BLEND_MODE_NONE : options->blend_mode); glUseProgram(shader->program); @@ -202,19 +209,7 @@ static void render_pass_add_rect(struct wlr_render_pass *wlr_pass, const struct wlr_box *box = &options->box; push_gles2_debug(renderer); - - switch (options->blend_mode) { - case WLR_RENDER_BLEND_MODE_PREMULTIPLIED: - if (color->a == 1.0) { - glDisable(GL_BLEND); - } else { - glEnable(GL_BLEND); - } - break; - case WLR_RENDER_BLEND_MODE_NONE: - glDisable(GL_BLEND); - break; - } + setup_blending(color->a == 1.0 ? WLR_RENDER_BLEND_MODE_NONE : options->blend_mode); glUseProgram(renderer->shaders.quad.program); diff --git a/render/pass.c b/render/pass.c index 026e807b..c64772db 100644 --- a/render/pass.c +++ b/render/pass.c @@ -113,10 +113,16 @@ static void legacy_add_texture(struct wlr_render_pass *wlr_pass, pixman_region32_t clip; get_clip_region(pass, options->clip, &clip); + float black[4] = {0}; int rects_len = 0; const pixman_box32_t *rects = pixman_region32_rectangles(&clip, &rects_len); for (int i = 0; i < rects_len; i++) { scissor(pass->renderer, &rects[i]); + + if (options->blend_mode == WLR_RENDER_BLEND_MODE_NONE) { + wlr_renderer_clear(pass->renderer, black); + } + wlr_render_subtexture_with_matrix(pass->renderer, texture, &src_box, matrix, alpha); } diff --git a/render/pixman/pass.c b/render/pixman/pass.c index 0528d540..4b85889b 100644 --- a/render/pixman/pass.c +++ b/render/pixman/pass.c @@ -26,6 +26,16 @@ static bool render_pass_submit(struct wlr_render_pass *wlr_pass) { return true; } +static pixman_op_t get_pixman_blending(enum wlr_render_blend_mode mode) { + switch (mode) { + case WLR_RENDER_BLEND_MODE_PREMULTIPLIED: + return PIXMAN_OP_OVER; + case WLR_RENDER_BLEND_MODE_NONE: + return PIXMAN_OP_SRC; + } + abort(); +} + static void render_pass_add_texture(struct wlr_render_pass *wlr_pass, const struct wlr_render_texture_options *options) { struct wlr_pixman_render_pass *pass = get_render_pass(wlr_pass); @@ -129,8 +139,10 @@ static void render_pass_add_texture(struct wlr_render_pass *wlr_pass, break; } + pixman_op_t op = get_pixman_blending(options->blend_mode); + pixman_image_set_clip_region32(buffer->image, (pixman_region32_t *)options->clip); - pixman_image_composite32(PIXMAN_OP_OVER, texture->image, mask, + pixman_image_composite32(op, texture->image, mask, buffer->image, src_box.x, src_box.y, 0, 0, dest_x, dest_y, width, height); pixman_image_set_clip_region32(buffer->image, NULL); @@ -152,16 +164,8 @@ static void render_pass_add_rect(struct wlr_render_pass *wlr_pass, struct wlr_pixman_buffer *buffer = pass->buffer; struct wlr_box box = options->box; - pixman_op_t op = 0; - switch (options->blend_mode) { - case WLR_RENDER_BLEND_MODE_PREMULTIPLIED: - op = options->color.a == 1 ? PIXMAN_OP_SRC : PIXMAN_OP_OVER; - break; - case WLR_RENDER_BLEND_MODE_NONE: - op = PIXMAN_OP_SRC; - break; - } - assert(op != 0); + pixman_op_t op = get_pixman_blending(options->color.a == 1 ? + WLR_RENDER_BLEND_MODE_NONE : options->blend_mode); struct pixman_color color = { .red = options->color.r * 0xFFFF, diff --git a/render/vulkan/pass.c b/render/vulkan/pass.c index 7ac5cf95..bfb3628f 100644 --- a/render/vulkan/pass.c +++ b/render/vulkan/pass.c @@ -550,6 +550,8 @@ static void render_pass_add_texture(struct wlr_render_pass *wlr_pass, .filter_mode = options->filter_mode, }, .texture_transform = texture->transform, + .blend_mode = !texture->has_alpha && alpha == 1.0 ? + WLR_RENDER_BLEND_MODE_NONE : options->blend_mode, }); if (!pipe) { pass->failed = true;