summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLoïc Molinari <loic.molinari@collabora.com>2023-11-29 12:54:52 +0100
committerDerek Foreman <derek.foreman@collabora.com>2024-03-08 13:12:13 +0000
commit4861b19f3d6b993accaf951e4aabaa3ec08d07cd (patch)
tree4d6c98471ca8a4ea1fa71c72b0a712ad025051f9
parentb5553cb5ddbe1f561fd08702b342a3330359491f (diff)
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>
-rw-r--r--libweston/renderer-gl/gl-renderer-internal.h4
-rw-r--r--libweston/renderer-gl/gl-renderer.c38
2 files changed, 36 insertions, 6 deletions
diff --git a/libweston/renderer-gl/gl-renderer-internal.h b/libweston/renderer-gl/gl-renderer-internal.h
index 926ff028..71d5f4db 100644
--- a/libweston/renderer-gl/gl-renderer-internal.h
+++ b/libweston/renderer-gl/gl-renderer-internal.h
@@ -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;
diff --git a/libweston/renderer-gl/gl-renderer.c b/libweston/renderer-gl/gl-renderer.c
index 38f9fac9..32132163 100644
--- a/libweston/renderer-gl/gl-renderer.c
+++ b/libweston/renderer-gl/gl-renderer.c
@@ -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);