gl-renderer: Enable async output capture support for OpenGL ES 2

Plug async read back support to OpenGL ES 2 implementations using
GL_NV_pixel_buffer_object, GL_OES_mapbuffer extensions and
GL_EXT_map_buffer_range.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
This commit is contained in:
Loïc Molinari 2023-11-29 12:54:52 +01:00 committed by Derek Foreman
parent b5553cb5dd
commit 4861b19f3d
2 changed files with 36 additions and 6 deletions

View file

@ -188,7 +188,11 @@ struct gl_renderer {
bool has_texture_storage;
bool has_pack_reverse;
bool has_rgb8_rgba8;
bool has_pbo;
GLenum pbo_usage;
PFNGLMAPBUFFERRANGEEXTPROC map_buffer_range;
PFNGLUNMAPBUFFEROESPROC unmap_buffer;
struct wl_list pending_capture_list;

View file

@ -836,15 +836,16 @@ copy_capture(struct gl_capture_task *gl_task)
struct weston_buffer *buffer =
weston_capture_task_get_buffer(gl_task->task);
struct wl_shm_buffer *shm = buffer->shm_buffer;
struct gl_renderer *gr = gl_task->gr;
uint8_t *src, *dst;
int i;
assert(shm);
glBindBuffer(GL_PIXEL_PACK_BUFFER, gl_task->pbo);
src = glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0,
gl_task->stride * gl_task->height,
GL_MAP_READ_BIT);
src = gr->map_buffer_range(GL_PIXEL_PACK_BUFFER, 0,
gl_task->stride * gl_task->height,
GL_MAP_READ_BIT);
dst = wl_shm_buffer_get_data(shm);
wl_shm_buffer_begin_access(shm);
@ -860,7 +861,7 @@ copy_capture(struct gl_capture_task *gl_task)
}
wl_shm_buffer_end_access(shm);
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
gr->unmap_buffer(GL_PIXEL_PACK_BUFFER);
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
}
@ -924,7 +925,7 @@ gl_renderer_do_read_pixels_async(struct gl_renderer *gr,
glBindBuffer(GL_PIXEL_PACK_BUFFER, gl_task->pbo);
glBufferData(GL_PIXEL_PACK_BUFFER, gl_task->stride * gl_task->height,
NULL, GL_STREAM_READ);
NULL, gr->pbo_usage);
glReadPixels(rect->x, rect->y, rect->width, rect->height,
fmt->gl_format, fmt->gl_type, 0);
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
@ -4403,8 +4404,33 @@ gl_renderer_setup(struct weston_compositor *ec)
weston_check_egl_extension(extensions, "GL_OES_rgb8_rgba8"))
gr->has_rgb8_rgba8 = true;
if (gr->gl_version >= gr_gl_version(3, 0))
if (gr->gl_version >= gr_gl_version(3, 0)) {
gr->map_buffer_range = (void *) eglGetProcAddress("glMapBufferRange");
gr->unmap_buffer = (void *) eglGetProcAddress("glUnmapBuffer");
assert(gr->map_buffer_range);
assert(gr->unmap_buffer);
gr->pbo_usage = GL_STREAM_READ;
gr->has_pbo = true;
} else if (gr->gl_version >= gr_gl_version(2, 0) &&
weston_check_egl_extension(extensions, "GL_NV_pixel_buffer_object") &&
weston_check_egl_extension(extensions, "GL_EXT_map_buffer_range") &&
weston_check_egl_extension(extensions, "GL_OES_mapbuffer")) {
gr->map_buffer_range = (void *) eglGetProcAddress("glMapBufferRangeEXT");
gr->unmap_buffer = (void *) eglGetProcAddress("glUnmapBufferOES");
assert(gr->map_buffer_range);
assert(gr->unmap_buffer);
/* Reading isn't exposed to BufferData() on ES 2.0 and
* NV_pixel_buffer_object mentions that "glMapBufferOES does not
* allow reading from the mapped pointer". EXT_map_buffer_range
* (which depends on OES_mapbuffer) adds read access support to
* MapBufferRangeEXT() without extending BufferData() so we
* create a PBO with a write usage hint that ends up being
* mapped with a read access. Even though that sounds incorrect,
* EXT_map_buffer_range provides examples doing so. Mesa
* actually ignores PBOs' usage hint assuming read access. */
gr->pbo_usage = GL_STREAM_DRAW;
gr->has_pbo = true;
}
wl_list_init(&gr->pending_capture_list);