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;
} 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

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_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;

View file

@ -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;
}

View file

@ -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,

View file

@ -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