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.
This commit is contained in:
YaoBing Xiao 2026-03-18 15:08:47 +08:00
parent fb6cfcf809
commit e78131f3d3
5 changed files with 132 additions and 111 deletions

View file

@ -73,18 +73,6 @@ struct wlr_gles2_renderer {
PFNGLGETINTEGER64VEXTPROC glGetInteger64vEXT; PFNGLGETINTEGER64VEXTPROC glGetInteger64vEXT;
} procs; } 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 buffers; // wlr_gles2_buffer.link
struct wl_list textures; // wlr_gles2_texture.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_gles2_render_rect_pass {
struct wlr_render_rect_pass base; 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); 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_gles2_render_texture_pass {
struct wlr_render_texture_pass base; 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); 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_gles2_render_submit_pass *wlr_gles2_render_submit_pass_from_pass(
struct wlr_render_submit_pass *submit_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 #endif

View file

@ -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_render_rect_pass *get_or_create_render_rect_pass(
struct wlr_renderer *renderer); struct wlr_renderer *renderer);
struct wlr_render_rect_pass *wlr_pixman_render_rect_pass_create(void); 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_rect_pass *wlr_vk_render_rect_pass_create(void);
struct wlr_render_texture_pass; 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_render_texture_pass *get_or_create_render_texture_pass(
struct wlr_renderer *renderer); struct wlr_renderer *renderer);
struct wlr_render_texture_pass *wlr_pixman_render_texture_pass_create(void); 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_texture_pass *wlr_vk_render_texture_pass_create(void);
struct wlr_render_submit_pass; struct wlr_render_submit_pass;

View file

@ -9,6 +9,12 @@
#include "render/gles2.h" #include "render/gles2.h"
#include "util/matrix.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 #define MAX_QUADS 86 // 4kb
static const struct wlr_render_pass_impl render_pass_impl; 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_render_pass *pass = get_render_pass(wlr_pass);
struct wlr_gles2_renderer *renderer = pass->buffer->renderer; struct wlr_gles2_renderer *renderer = pass->buffer->renderer;
struct wlr_gles2_texture *texture = gles2_get_texture(options->texture); 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; struct wlr_gles2_tex_shader *shader = NULL;
switch (texture->target) { switch (texture->target) {
case GL_TEXTURE_2D: case GL_TEXTURE_2D:
if (texture->has_alpha) { if (texture->has_alpha) {
shader = &renderer->shaders.tex_rgba; shader = &texture_pass->shaders.tex_rgba;
} else { } else {
shader = &renderer->shaders.tex_rgbx; shader = &texture_pass->shaders.tex_rgbx;
} }
break; break;
case GL_TEXTURE_EXTERNAL_OES: case GL_TEXTURE_EXTERNAL_OES:
// EGL_EXT_image_dma_buf_import_modifiers requires // EGL_EXT_image_dma_buf_import_modifiers requires
// GL_OES_EGL_image_external // GL_OES_EGL_image_external
assert(renderer->exts.OES_egl_image_external); assert(renderer->exts.OES_egl_image_external);
shader = &renderer->shaders.tex_ext; shader = &texture_pass->shaders.tex_ext;
break; break;
default: default:
abort(); abort();
@ -257,6 +264,8 @@ static void render_pass_add_rect(struct wlr_render_pass *wlr_pass,
const struct wlr_render_rect_options *options) { const struct wlr_render_rect_options *options) {
struct wlr_gles2_render_pass *pass = get_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_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; const struct wlr_render_color *color = &options->color;
struct wlr_box box; 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); glClear(GL_COLOR_BUFFER_BIT);
} else { } else {
setup_blending(blend_mode); setup_blending(blend_mode);
glUseProgram(renderer->shaders.quad.program); glUseProgram(rect_pass->shader.program);
set_proj_matrix(renderer->shaders.quad.proj, pass->projection_matrix, &box); set_proj_matrix(rect_pass->shader.proj, pass->projection_matrix, &box);
glUniform4f(renderer->shaders.quad.color, color->r, color->g, color->b, color->a); glUniform4f(rect_pass->shader.color, color->r, color->g, color->b, color->a);
render(&box, options->clip, renderer->shaders.quad.pos_attrib); render(&box, options->clip, rect_pass->shader.pos_attrib);
} }
pop_gles2_debug(renderer); 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) { static void render_rect_pass_destroy(struct wlr_render_rect_pass *pass) {
struct wlr_gles2_render_rect_pass *gles2_pass = struct wlr_gles2_render_rect_pass *gles2_pass =
wlr_gles2_render_rect_pass_from_pass(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); free(gles2_pass);
} }
@ -373,16 +385,43 @@ static const struct wlr_render_rect_pass_impl render_rect_pass_impl = {
.render = render_pass_add_rect, .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)); struct wlr_gles2_render_rect_pass *pass = calloc(1, sizeof(*pass));
if (pass == NULL) { if (pass == NULL) {
wlr_log_errno(WLR_ERROR, "failed to allocate wlr_gles2_render_rect_pass"); wlr_log_errno(WLR_ERROR, "failed to allocate wlr_gles2_render_rect_pass");
return NULL; 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; 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) { 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) { static void render_texture_pass_destroy(struct wlr_render_texture_pass *pass) {
struct wlr_gles2_render_texture_pass *gles2_pass = struct wlr_gles2_render_texture_pass *gles2_pass =
wlr_gles2_render_texture_pass_from_pass(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); free(gles2_pass);
} }
@ -412,17 +456,70 @@ static const struct wlr_render_texture_pass_impl render_texture_pass_impl = {
.render = render_pass_add_texture, .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)); struct wlr_gles2_render_texture_pass *pass = calloc(1, sizeof(*pass));
if (pass == NULL) { if (pass == NULL) {
wlr_log_errno(WLR_ERROR, "failed to allocate wlr_gles2_render_texture_pass"); wlr_log_errno(WLR_ERROR, "failed to allocate wlr_gles2_render_texture_pass");
return NULL; return NULL;
} }
wlr_render_texture_pass_init(&pass->base, &render_texture_pass_impl); 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; 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) { 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; return texture_pass != NULL && texture_pass->impl == &render_texture_pass_impl;
} }

View file

@ -20,12 +20,6 @@
#include "render/pixel_format.h" #include "render/pixel_format.h"
#include "util/time.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_renderer_impl renderer_impl;
static const struct wlr_render_timer_impl render_timer_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); 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) { if (renderer->exts.KHR_debug) {
glDisable(GL_DEBUG_OUTPUT_KHR); glDisable(GL_DEBUG_OUTPUT_KHR);
renderer->procs.glDebugMessageCallbackKHR(NULL, NULL); renderer->procs.glDebugMessageCallbackKHR(NULL, NULL);
@ -425,7 +412,7 @@ static GLuint compile_shader(struct wlr_gles2_renderer *renderer,
return shader; 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) { const GLchar *vert_src, const GLchar *frag_src) {
push_gles2_debug(renderer); 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); 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); get_gles2_shm_formats(renderer, &renderer->shm_texture_formats);
int drm_fd = wlr_renderer_get_drm_fd(&renderer->wlr_renderer); 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; 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, bool wlr_gles2_renderer_check_ext(struct wlr_renderer *wlr_renderer,

View file

@ -148,7 +148,7 @@ struct wlr_render_rect_pass *get_or_create_render_rect_pass(
#if WLR_HAS_GLES2_RENDERER #if WLR_HAS_GLES2_RENDERER
else if (wlr_renderer_is_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 #endif
@ -200,7 +200,7 @@ struct wlr_render_texture_pass *get_or_create_render_texture_pass(
#if WLR_HAS_GLES2_RENDERER #if WLR_HAS_GLES2_RENDERER
else if (wlr_renderer_is_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 #endif