Skip to content

Commit b9d45ba

Browse files
committed
gfx/gl3: reuse menu texture across set_texture_frame calls
gl3_set_texture_frame unconditionally destroyed and recreated the GPU texture object on every call via glDeleteTextures + glGenTextures + glTexStorage2D. Menu dimensions rarely change after the first call, so this burned GPU driver overhead and allocator bandwidth every menu frame for no reason. The gl2 driver already handles this correctly (via gl_load_texture_data, which reuses the texture when possible). Cache the last-used (width, height, rgb32) tuple on the driver handle; recreate the texture only when one of those changes, otherwise keep the existing texture and stream new pixel data via glTexSubImage2D. glTexStorage2D is immutable per GL spec so the texture *must* be recreated on dim/format change, but for same-size same-format updates (the overwhelmingly common case) no such recreation is needed. Filter, wrap, and swizzle parameters are still set every call. The menu_linear_filter setting can toggle at runtime, and these calls are negligible compared to the pixel upload. Thread-safety: unchanged. set_texture_frame and the frame read-site both run on the video thread (threaded video) or main thread (non-threaded), sequentially within the same loop iteration. No synchronization required, none added. The existing shared-context bind/unbind wrapping is preserved. gl3_t is calloc'd at init and freed entire on teardown, so the three new cache fields (menu_texture_width, menu_texture_height, menu_texture_rgb32) start at zero on every re-init. On first call menu_texture is 0, which triggers the recreate branch — correct.
1 parent 0f6a3e2 commit b9d45ba

1 file changed

Lines changed: 33 additions & 6 deletions

File tree

gfx/drivers/gl3.c

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,8 @@ typedef struct gl3
168168
unsigned pbo_readback_index;
169169
unsigned hw_render_max_width;
170170
unsigned hw_render_max_height;
171+
unsigned menu_texture_width;
172+
unsigned menu_texture_height;
171173
GLuint scratch_vbos[GL_CORE_NUM_VBOS];
172174
GLuint hw_render_texture;
173175
GLuint hw_render_fbo;
@@ -182,6 +184,7 @@ typedef struct gl3
182184
uint16_t flags;
183185

184186
bool pbo_readback_valid[GL_CORE_NUM_PBOS];
187+
bool menu_texture_rgb32;
185188
} gl3_t;
186189

187190
typedef struct gl3_video_shader_ctx_init
@@ -4722,18 +4725,38 @@ static void gl3_set_texture_frame(void *data,
47224725
? GL_LINEAR : GL_NEAREST;
47234726
unsigned base_size = rgb32 ? sizeof(uint32_t) : sizeof(uint16_t);
47244727
gl3_t *gl = (gl3_t*)data;
4728+
bool recreate;
4729+
47254730
if (!gl)
47264731
return;
47274732

47284733
if (gl->flags & GL3_FLAG_USE_SHARED_CONTEXT)
47294734
gl->ctx_driver->bind_hw_render(gl->ctx_data, false);
47304735

4731-
if (gl->menu_texture)
4732-
glDeleteTextures(1, &gl->menu_texture);
4733-
glGenTextures(1, &gl->menu_texture);
4734-
glBindTexture(GL_TEXTURE_2D, gl->menu_texture);
4735-
glTexStorage2D(GL_TEXTURE_2D, 1, rgb32
4736-
? GL_RGBA8 : GL_RGBA4, width, height);
4736+
/* glTexStorage2D is immutable — the texture object must be
4737+
* recreated whenever dimensions or pixel format change. For
4738+
* same-size same-format updates we keep the existing texture
4739+
* and just stream new pixel data via glTexSubImage2D. */
4740+
recreate = (gl->menu_texture == 0)
4741+
|| (gl->menu_texture_width != width)
4742+
|| (gl->menu_texture_height != height)
4743+
|| (gl->menu_texture_rgb32 != rgb32);
4744+
4745+
if (recreate)
4746+
{
4747+
if (gl->menu_texture != 0)
4748+
glDeleteTextures(1, &gl->menu_texture);
4749+
glGenTextures(1, &gl->menu_texture);
4750+
glBindTexture(GL_TEXTURE_2D, gl->menu_texture);
4751+
glTexStorage2D(GL_TEXTURE_2D, 1, rgb32
4752+
? GL_RGBA8 : GL_RGBA4, width, height);
4753+
4754+
gl->menu_texture_width = width;
4755+
gl->menu_texture_height = height;
4756+
gl->menu_texture_rgb32 = rgb32;
4757+
}
4758+
else
4759+
glBindTexture(GL_TEXTURE_2D, gl->menu_texture);
47374760

47384761
glPixelStorei(GL_UNPACK_ALIGNMENT, base_size);
47394762
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
@@ -4742,6 +4765,10 @@ static void gl3_set_texture_frame(void *data,
47424765
width, height, GL_RGBA, rgb32
47434766
? GL_UNSIGNED_BYTE
47444767
: GL_UNSIGNED_SHORT_4_4_4_4, frame);
4768+
4769+
/* Filter/wrap/swizzle are set every call: the linear-filter menu
4770+
* setting can toggle at runtime, and the cost of these calls is
4771+
* negligible compared to the pixel upload above. */
47454772
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
47464773
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
47474774
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, menu_filter);

0 commit comments

Comments
 (0)