From e78131f3d39ad875bea9906ab02db62421762da6 Mon Sep 17 00:00:00 2001 From: YaoBing Xiao Date: Wed, 18 Mar 2026 15:08:47 +0800 Subject: [PATCH] render/gles2: move shaders to render_xxx_pass Stop storing the shader on the renderer and instead create a dedicated shader per wlr_render_xxx_pass. --- include/render/gles2.h | 28 ++++---- include/wlr/render/interface.h | 6 +- render/gles2/pass.c | 121 +++++++++++++++++++++++++++++---- render/gles2/renderer.c | 84 +---------------------- render/pass.c | 4 +- 5 files changed, 132 insertions(+), 111 deletions(-) diff --git a/include/render/gles2.h b/include/render/gles2.h index 38c93b943..efdb6599d 100644 --- a/include/render/gles2.h +++ b/include/render/gles2.h @@ -73,18 +73,6 @@ struct wlr_gles2_renderer { PFNGLGETINTEGER64VEXTPROC glGetInteger64vEXT; } procs; - struct { - struct { - GLuint program; - GLint proj; - GLint color; - GLint pos_attrib; - } quad; - struct wlr_gles2_tex_shader tex_rgba; - struct wlr_gles2_tex_shader tex_rgbx; - struct wlr_gles2_tex_shader tex_ext; - } shaders; - struct wl_list buffers; // wlr_gles2_buffer.link struct wl_list textures; // wlr_gles2_texture.link }; @@ -175,6 +163,13 @@ struct wlr_gles2_render_pass *begin_gles2_buffer_pass(struct wlr_gles2_buffer *b struct wlr_gles2_render_rect_pass { struct wlr_render_rect_pass base; + struct wlr_gles2_renderer *renderer; + struct { + GLuint program; + GLint proj; + GLint color; + GLint pos_attrib; + } shader; }; bool wlr_render_rect_pass_is_gles2(const struct wlr_render_rect_pass *rect_pass); @@ -183,6 +178,12 @@ struct wlr_gles2_render_rect_pass *wlr_gles2_render_rect_pass_from_pass( struct wlr_gles2_render_texture_pass { struct wlr_render_texture_pass base; + struct wlr_gles2_renderer *renderer; + struct { + struct wlr_gles2_tex_shader tex_rgba; + struct wlr_gles2_tex_shader tex_rgbx; + struct wlr_gles2_tex_shader tex_ext; + } shaders; }; bool wlr_render_texture_pass_is_gles2(const struct wlr_render_texture_pass *texture_pass); @@ -197,4 +198,7 @@ bool wlr_render_submit_pass_is_gles2(const struct wlr_render_submit_pass *submit struct wlr_gles2_render_submit_pass *wlr_gles2_render_submit_pass_from_pass( struct wlr_render_submit_pass *submit_pass); +GLuint gles2_link_program(struct wlr_gles2_renderer *renderer, + const GLchar *vert_src, const GLchar *frag_src); + #endif diff --git a/include/wlr/render/interface.h b/include/wlr/render/interface.h index fd3bb1df8..3d61aab40 100644 --- a/include/wlr/render/interface.h +++ b/include/wlr/render/interface.h @@ -110,7 +110,8 @@ void wlr_render_rect_pass_destroy(struct wlr_render_rect_pass *pass); struct wlr_render_rect_pass *get_or_create_render_rect_pass( struct wlr_renderer *renderer); struct wlr_render_rect_pass *wlr_pixman_render_rect_pass_create(void); -struct wlr_render_rect_pass *wlr_gles2_render_rect_pass_create(void); +struct wlr_render_rect_pass *wlr_gles2_render_rect_pass_create( + struct wlr_renderer *wlr_renderer); struct wlr_render_rect_pass *wlr_vk_render_rect_pass_create(void); struct wlr_render_texture_pass; @@ -135,7 +136,8 @@ void wlr_render_texture_pass_destroy(struct wlr_render_texture_pass *pass); struct wlr_render_texture_pass *get_or_create_render_texture_pass( struct wlr_renderer *renderer); struct wlr_render_texture_pass *wlr_pixman_render_texture_pass_create(void); -struct wlr_render_texture_pass *wlr_gles2_render_texture_pass_create(void); +struct wlr_render_texture_pass *wlr_gles2_render_texture_pass_create( + struct wlr_renderer *wlr_renderer); struct wlr_render_texture_pass *wlr_vk_render_texture_pass_create(void); struct wlr_render_submit_pass; diff --git a/render/gles2/pass.c b/render/gles2/pass.c index c5b7e00c7..a33d9a73b 100644 --- a/render/gles2/pass.c +++ b/render/gles2/pass.c @@ -9,6 +9,12 @@ #include "render/gles2.h" #include "util/matrix.h" +#include "common_vert_src.h" +#include "quad_frag_src.h" +#include "tex_rgba_frag_src.h" +#include "tex_rgbx_frag_src.h" +#include "tex_external_frag_src.h" + #define MAX_QUADS 86 // 4kb static const struct wlr_render_pass_impl render_pass_impl; @@ -169,22 +175,23 @@ static void render_pass_add_texture(struct wlr_render_pass *wlr_pass, struct wlr_gles2_render_pass *pass = get_render_pass(wlr_pass); struct wlr_gles2_renderer *renderer = pass->buffer->renderer; struct wlr_gles2_texture *texture = gles2_get_texture(options->texture); - + struct wlr_gles2_render_texture_pass *texture_pass = + wlr_gles2_render_texture_pass_from_pass(renderer->wlr_renderer.texture_pass); struct wlr_gles2_tex_shader *shader = NULL; switch (texture->target) { case GL_TEXTURE_2D: if (texture->has_alpha) { - shader = &renderer->shaders.tex_rgba; + shader = &texture_pass->shaders.tex_rgba; } else { - shader = &renderer->shaders.tex_rgbx; + shader = &texture_pass->shaders.tex_rgbx; } break; case GL_TEXTURE_EXTERNAL_OES: // EGL_EXT_image_dma_buf_import_modifiers requires // GL_OES_EGL_image_external assert(renderer->exts.OES_egl_image_external); - shader = &renderer->shaders.tex_ext; + shader = &texture_pass->shaders.tex_ext; break; default: abort(); @@ -257,6 +264,8 @@ static void render_pass_add_rect(struct wlr_render_pass *wlr_pass, const struct wlr_render_rect_options *options) { struct wlr_gles2_render_pass *pass = get_render_pass(wlr_pass); struct wlr_gles2_renderer *renderer = pass->buffer->renderer; + struct wlr_gles2_render_rect_pass *rect_pass = + wlr_gles2_render_rect_pass_from_pass(renderer->wlr_renderer.rect_pass); const struct wlr_render_color *color = &options->color; struct wlr_box box; @@ -275,10 +284,10 @@ static void render_pass_add_rect(struct wlr_render_pass *wlr_pass, glClear(GL_COLOR_BUFFER_BIT); } else { setup_blending(blend_mode); - glUseProgram(renderer->shaders.quad.program); - set_proj_matrix(renderer->shaders.quad.proj, pass->projection_matrix, &box); - glUniform4f(renderer->shaders.quad.color, color->r, color->g, color->b, color->a); - render(&box, options->clip, renderer->shaders.quad.pos_attrib); + glUseProgram(rect_pass->shader.program); + set_proj_matrix(rect_pass->shader.proj, pass->projection_matrix, &box); + glUniform4f(rect_pass->shader.color, color->r, color->g, color->b, color->a); + render(&box, options->clip, rect_pass->shader.pos_attrib); } pop_gles2_debug(renderer); @@ -365,6 +374,9 @@ struct wlr_gles2_render_pass *begin_gles2_buffer_pass(struct wlr_gles2_buffer *b static void render_rect_pass_destroy(struct wlr_render_rect_pass *pass) { struct wlr_gles2_render_rect_pass *gles2_pass = wlr_gles2_render_rect_pass_from_pass(pass); + push_gles2_debug(gles2_pass->renderer); + glDeleteProgram(gles2_pass->shader.program); + pop_gles2_debug(gles2_pass->renderer); free(gles2_pass); } @@ -373,16 +385,43 @@ static const struct wlr_render_rect_pass_impl render_rect_pass_impl = { .render = render_pass_add_rect, }; -struct wlr_render_rect_pass *wlr_gles2_render_rect_pass_create(void) { +struct wlr_render_rect_pass *wlr_gles2_render_rect_pass_create( + struct wlr_renderer *wlr_renderer) { struct wlr_gles2_render_rect_pass *pass = calloc(1, sizeof(*pass)); if (pass == NULL) { wlr_log_errno(WLR_ERROR, "failed to allocate wlr_gles2_render_rect_pass"); return NULL; } - wlr_render_rect_pass_init(&pass->base, &render_rect_pass_impl); + struct wlr_gles2_renderer *renderer = gles2_get_renderer(wlr_renderer); + if (!wlr_egl_make_current(renderer->egl, NULL)) { + free(pass); + return NULL; + } + wlr_render_rect_pass_init(&pass->base, &render_rect_pass_impl); + push_gles2_debug(renderer); + GLuint prog; + pass->shader.program = prog = + gles2_link_program(renderer, common_vert_src, quad_frag_src); + if (!pass->shader.program) { + goto error; + } + + pass->shader.proj = glGetUniformLocation(pass->shader.program, "proj"); + pass->shader.color = glGetUniformLocation(pass->shader.program, "color"); + pass->shader.pos_attrib = glGetAttribLocation(pass->shader.program, "pos"); + pop_gles2_debug(renderer); + wlr_egl_unset_current(renderer->egl); + pass->renderer = renderer; return &pass->base; + +error: + render_rect_pass_destroy(&pass->base); + pop_gles2_debug(renderer); + wlr_egl_unset_current(renderer->egl); + + return NULL; } bool wlr_render_rect_pass_is_gles2(const struct wlr_render_rect_pass *rect_pass) { @@ -404,6 +443,11 @@ struct wlr_gles2_render_rect_pass *wlr_gles2_render_rect_pass_from_pass( static void render_texture_pass_destroy(struct wlr_render_texture_pass *pass) { struct wlr_gles2_render_texture_pass *gles2_pass = wlr_gles2_render_texture_pass_from_pass(pass); + push_gles2_debug(gles2_pass->renderer); + glDeleteProgram(gles2_pass->shaders.tex_rgba.program); + glDeleteProgram(gles2_pass->shaders.tex_rgbx.program); + glDeleteProgram(gles2_pass->shaders.tex_ext.program); + pop_gles2_debug(gles2_pass->renderer); free(gles2_pass); } @@ -412,17 +456,70 @@ static const struct wlr_render_texture_pass_impl render_texture_pass_impl = { .render = render_pass_add_texture, }; -struct wlr_render_texture_pass *wlr_gles2_render_texture_pass_create(void) { +struct wlr_render_texture_pass *wlr_gles2_render_texture_pass_create( + struct wlr_renderer *wlr_renderer) { struct wlr_gles2_render_texture_pass *pass = calloc(1, sizeof(*pass)); if (pass == NULL) { wlr_log_errno(WLR_ERROR, "failed to allocate wlr_gles2_render_texture_pass"); return NULL; } - wlr_render_texture_pass_init(&pass->base, &render_texture_pass_impl); + struct wlr_gles2_renderer *renderer = gles2_get_renderer(wlr_renderer); + if (!wlr_egl_make_current(renderer->egl, NULL)) { + free(pass); + return NULL; + } + push_gles2_debug(renderer); + GLuint prog; + pass->shaders.tex_rgba.program = prog = + gles2_link_program(renderer, common_vert_src, tex_rgba_frag_src); + if (!pass->shaders.tex_rgba.program) { + goto error; + } + pass->shaders.tex_rgba.proj = glGetUniformLocation(prog, "proj"); + pass->shaders.tex_rgba.tex_proj = glGetUniformLocation(prog, "tex_proj"); + pass->shaders.tex_rgba.tex = glGetUniformLocation(prog, "tex"); + pass->shaders.tex_rgba.alpha = glGetUniformLocation(prog, "alpha"); + pass->shaders.tex_rgba.pos_attrib = glGetAttribLocation(prog, "pos"); + pass->shaders.tex_rgbx.program = prog = + gles2_link_program(renderer, common_vert_src, tex_rgbx_frag_src); + if (!pass->shaders.tex_rgbx.program) { + goto error; + } + pass->shaders.tex_rgbx.proj = glGetUniformLocation(prog, "proj"); + pass->shaders.tex_rgbx.tex_proj = glGetUniformLocation(prog, "tex_proj"); + pass->shaders.tex_rgbx.tex = glGetUniformLocation(prog, "tex"); + pass->shaders.tex_rgbx.alpha = glGetUniformLocation(prog, "alpha"); + pass->shaders.tex_rgbx.pos_attrib = glGetAttribLocation(prog, "pos"); + + if (renderer->exts.OES_egl_image_external) { + pass->shaders.tex_ext.program = prog = + gles2_link_program(renderer, common_vert_src, tex_external_frag_src); + if (!pass->shaders.tex_ext.program) { + goto error; + } + pass->shaders.tex_ext.proj = glGetUniformLocation(prog, "proj"); + pass->shaders.tex_ext.tex_proj = glGetUniformLocation(prog, "tex_proj"); + pass->shaders.tex_ext.tex = glGetUniformLocation(prog, "tex"); + pass->shaders.tex_ext.alpha = glGetUniformLocation(prog, "alpha"); + pass->shaders.tex_ext.pos_attrib = glGetAttribLocation(prog, "pos"); + } + + pop_gles2_debug(renderer); + + wlr_egl_unset_current(renderer->egl); + pass->renderer = renderer; return &pass->base; + +error: + render_texture_pass_destroy(&pass->base); + pop_gles2_debug(renderer); + wlr_egl_unset_current(renderer->egl); + + return NULL; } + bool wlr_render_texture_pass_is_gles2(const struct wlr_render_texture_pass *texture_pass) { return texture_pass != NULL && texture_pass->impl == &render_texture_pass_impl; } diff --git a/render/gles2/renderer.c b/render/gles2/renderer.c index 7f01b8acd..010623354 100644 --- a/render/gles2/renderer.c +++ b/render/gles2/renderer.c @@ -20,12 +20,6 @@ #include "render/pixel_format.h" #include "util/time.h" -#include "common_vert_src.h" -#include "quad_frag_src.h" -#include "tex_rgba_frag_src.h" -#include "tex_rgbx_frag_src.h" -#include "tex_external_frag_src.h" - static const struct wlr_renderer_impl renderer_impl; static const struct wlr_render_timer_impl render_timer_impl; @@ -214,13 +208,6 @@ static void gles2_destroy(struct wlr_renderer *wlr_renderer) { destroy_buffer(buffer); } - push_gles2_debug(renderer); - glDeleteProgram(renderer->shaders.quad.program); - glDeleteProgram(renderer->shaders.tex_rgba.program); - glDeleteProgram(renderer->shaders.tex_rgbx.program); - glDeleteProgram(renderer->shaders.tex_ext.program); - pop_gles2_debug(renderer); - if (renderer->exts.KHR_debug) { glDisable(GL_DEBUG_OUTPUT_KHR); renderer->procs.glDebugMessageCallbackKHR(NULL, NULL); @@ -425,7 +412,7 @@ static GLuint compile_shader(struct wlr_gles2_renderer *renderer, return shader; } -static GLuint link_program(struct wlr_gles2_renderer *renderer, +GLuint gles2_link_program(struct wlr_gles2_renderer *renderer, const GLchar *vert_src, const GLchar *frag_src) { push_gles2_debug(renderer); @@ -630,57 +617,6 @@ struct wlr_renderer *wlr_gles2_renderer_create(struct wlr_egl *egl) { GL_DEBUG_TYPE_PUSH_GROUP_KHR, GL_DONT_CARE, 0, NULL, GL_FALSE); } - push_gles2_debug(renderer); - - GLuint prog; - renderer->shaders.quad.program = prog = - link_program(renderer, common_vert_src, quad_frag_src); - if (!renderer->shaders.quad.program) { - goto error; - } - renderer->shaders.quad.proj = glGetUniformLocation(prog, "proj"); - renderer->shaders.quad.color = glGetUniformLocation(prog, "color"); - renderer->shaders.quad.pos_attrib = glGetAttribLocation(prog, "pos"); - - renderer->shaders.tex_rgba.program = prog = - link_program(renderer, common_vert_src, tex_rgba_frag_src); - if (!renderer->shaders.tex_rgba.program) { - goto error; - } - renderer->shaders.tex_rgba.proj = glGetUniformLocation(prog, "proj"); - renderer->shaders.tex_rgba.tex_proj = glGetUniformLocation(prog, "tex_proj"); - renderer->shaders.tex_rgba.tex = glGetUniformLocation(prog, "tex"); - renderer->shaders.tex_rgba.alpha = glGetUniformLocation(prog, "alpha"); - renderer->shaders.tex_rgba.pos_attrib = glGetAttribLocation(prog, "pos"); - - renderer->shaders.tex_rgbx.program = prog = - link_program(renderer, common_vert_src, tex_rgbx_frag_src); - if (!renderer->shaders.tex_rgbx.program) { - goto error; - } - renderer->shaders.tex_rgbx.proj = glGetUniformLocation(prog, "proj"); - renderer->shaders.tex_rgbx.tex_proj = glGetUniformLocation(prog, "tex_proj"); - renderer->shaders.tex_rgbx.tex = glGetUniformLocation(prog, "tex"); - renderer->shaders.tex_rgbx.alpha = glGetUniformLocation(prog, "alpha"); - renderer->shaders.tex_rgbx.pos_attrib = glGetAttribLocation(prog, "pos"); - - if (renderer->exts.OES_egl_image_external) { - renderer->shaders.tex_ext.program = prog = - link_program(renderer, common_vert_src, tex_external_frag_src); - if (!renderer->shaders.tex_ext.program) { - goto error; - } - renderer->shaders.tex_ext.proj = glGetUniformLocation(prog, "proj"); - renderer->shaders.tex_ext.tex_proj = glGetUniformLocation(prog, "tex_proj"); - renderer->shaders.tex_ext.tex = glGetUniformLocation(prog, "tex"); - renderer->shaders.tex_ext.alpha = glGetUniformLocation(prog, "alpha"); - renderer->shaders.tex_ext.pos_attrib = glGetAttribLocation(prog, "pos"); - } - - pop_gles2_debug(renderer); - - wlr_egl_unset_current(renderer->egl); - get_gles2_shm_formats(renderer, &renderer->shm_texture_formats); int drm_fd = wlr_renderer_get_drm_fd(&renderer->wlr_renderer); @@ -691,24 +627,6 @@ struct wlr_renderer *wlr_gles2_renderer_create(struct wlr_egl *egl) { } return &renderer->wlr_renderer; - -error: - glDeleteProgram(renderer->shaders.quad.program); - glDeleteProgram(renderer->shaders.tex_rgba.program); - glDeleteProgram(renderer->shaders.tex_rgbx.program); - glDeleteProgram(renderer->shaders.tex_ext.program); - - pop_gles2_debug(renderer); - - if (renderer->exts.KHR_debug) { - glDisable(GL_DEBUG_OUTPUT_KHR); - renderer->procs.glDebugMessageCallbackKHR(NULL, NULL); - } - - wlr_egl_unset_current(renderer->egl); - - free(renderer); - return NULL; } bool wlr_gles2_renderer_check_ext(struct wlr_renderer *wlr_renderer, diff --git a/render/pass.c b/render/pass.c index ee2f9dbdc..4aedd9337 100644 --- a/render/pass.c +++ b/render/pass.c @@ -148,7 +148,7 @@ struct wlr_render_rect_pass *get_or_create_render_rect_pass( #if WLR_HAS_GLES2_RENDERER else if (wlr_renderer_is_gles2(renderer)) { - pass = wlr_gles2_render_rect_pass_create(); + pass = wlr_gles2_render_rect_pass_create(renderer); } #endif @@ -200,7 +200,7 @@ struct wlr_render_texture_pass *get_or_create_render_texture_pass( #if WLR_HAS_GLES2_RENDERER else if (wlr_renderer_is_gles2(renderer)) { - pass = wlr_gles2_render_texture_pass_create(); + pass = wlr_gles2_render_texture_pass_create(renderer); } #endif