aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/render/gles2.h2
-rw-r--r--include/wlr/render/interface.h3
-rw-r--r--include/wlr/render/wlr_renderer.h6
-rw-r--r--render/gles2/renderer.c85
-rw-r--r--render/wlr_renderer.c10
5 files changed, 106 insertions, 0 deletions
diff --git a/include/render/gles2.h b/include/render/gles2.h
index d9ddfe6c..24c02e4d 100644
--- a/include/render/gles2.h
+++ b/include/render/gles2.h
@@ -20,6 +20,7 @@ struct wlr_gles2_procs {
PFNGLDEBUGMESSAGECONTROLKHRPROC glDebugMessageControlKHR;
PFNGLPOPDEBUGGROUPKHRPROC glPopDebugGroupKHR;
PFNGLPUSHDEBUGGROUPKHRPROC glPushDebugGroupKHR;
+ PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glEGLImageTargetRenderbufferStorageOES;
};
extern struct wlr_gles2_procs gles2_procs;
@@ -49,6 +50,7 @@ struct wlr_gles2_renderer {
bool read_format_bgra_ext;
bool debug_khr;
bool egl_image_external_oes;
+ bool egl_image_oes;
} exts;
struct {
diff --git a/include/wlr/render/interface.h b/include/wlr/render/interface.h
index 48ef4286..6eb6c22f 100644
--- a/include/wlr/render/interface.h
+++ b/include/wlr/render/interface.h
@@ -64,6 +64,9 @@ struct wlr_renderer_impl {
void (*destroy)(struct wlr_renderer *renderer);
bool (*init_wl_display)(struct wlr_renderer *renderer,
struct wl_display *wl_display);
+ bool (*blit_dmabuf)(struct wlr_renderer *renderer,
+ struct wlr_dmabuf_attributes *dst,
+ struct wlr_dmabuf_attributes *src);
};
void wlr_renderer_init(struct wlr_renderer *renderer,
diff --git a/include/wlr/render/wlr_renderer.h b/include/wlr/render/wlr_renderer.h
index db543bef..e6140f3e 100644
--- a/include/wlr/render/wlr_renderer.h
+++ b/include/wlr/render/wlr_renderer.h
@@ -104,6 +104,12 @@ const struct wlr_drm_format_set *wlr_renderer_get_dmabuf_formats(
bool wlr_renderer_read_pixels(struct wlr_renderer *r, enum wl_shm_format fmt,
uint32_t *flags, uint32_t stride, uint32_t width, uint32_t height,
uint32_t src_x, uint32_t src_y, uint32_t dst_x, uint32_t dst_y, void *data);
+
+/**
+ * Blits the dmabuf in src onto the one in dst.
+ */
+bool wlr_renderer_blit_dmabuf(struct wlr_renderer *r,
+ struct wlr_dmabuf_attributes *dst, struct wlr_dmabuf_attributes *src);
/**
* Checks if a format is supported.
*/
diff --git a/render/gles2/renderer.c b/render/gles2/renderer.c
index 59c970c3..3afade38 100644
--- a/render/gles2/renderer.c
+++ b/render/gles2/renderer.c
@@ -331,6 +331,84 @@ static bool gles2_read_pixels(struct wlr_renderer *wlr_renderer,
return glGetError() == GL_NO_ERROR;
}
+static bool gles2_blit_dmabuf(struct wlr_renderer *wlr_renderer,
+ struct wlr_dmabuf_attributes *dst_attr,
+ struct wlr_dmabuf_attributes *src_attr) {
+ if (!gles2_procs.glEGLImageTargetRenderbufferStorageOES) {
+ return false;
+ }
+
+ struct wlr_egl_context old_context;
+ wlr_egl_save_context(&old_context);
+
+ bool r = false;
+ struct wlr_texture *src_tex =
+ wlr_texture_from_dmabuf(wlr_renderer, src_attr);
+ if (!src_tex) {
+ goto restore_context_out;
+ }
+
+ // This is to take into account y-inversion on both buffers rather than
+ // just the source buffer.
+ bool src_inverted_y =
+ !!(src_attr->flags & WLR_DMABUF_ATTRIBUTES_FLAGS_Y_INVERT);
+ bool dst_inverted_y =
+ !!(dst_attr->flags & WLR_DMABUF_ATTRIBUTES_FLAGS_Y_INVERT);
+ struct wlr_gles2_texture *gles2_src_tex = gles2_get_texture(src_tex);
+ gles2_src_tex->inverted_y = src_inverted_y ^ dst_inverted_y;
+
+ struct wlr_egl *egl = wlr_gles2_renderer_get_egl(wlr_renderer);
+ if (!wlr_egl_make_current(egl, EGL_NO_SURFACE, NULL)) {
+ goto texture_destroy_out;
+ }
+
+ // TODO: The imported buffer should be checked with
+ // eglQueryDmaBufModifiersEXT to see if it may be modified.
+ EGLImageKHR image = wlr_egl_create_image_from_dmabuf(egl, dst_attr);
+ if (image == EGL_NO_IMAGE_KHR) {
+ goto texture_destroy_out;
+ }
+
+ GLuint rbo = 0;
+ glGenRenderbuffers(1, &rbo);
+ glBindRenderbuffer(GL_RENDERBUFFER, rbo);
+ gles2_procs.glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER,
+ image);
+ glBindRenderbuffer(GL_RENDERBUFFER, 0);
+
+ GLuint fbo = 0;
+ glGenFramebuffers(1, &fbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_RENDERBUFFER, rbo);
+
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ if (status != GL_FRAMEBUFFER_COMPLETE) {
+ goto out;
+ }
+
+ // TODO: use ANGLE_framebuffer_blit if available
+ float mat[9];
+ wlr_matrix_projection(mat, 1, 1, WL_OUTPUT_TRANSFORM_NORMAL);
+
+ wlr_renderer_begin(wlr_renderer, dst_attr->width, dst_attr->height);
+ wlr_renderer_clear(wlr_renderer, (float[]){ 0.0, 0.0, 0.0, 0.0 });
+ wlr_render_texture_with_matrix(wlr_renderer, src_tex, mat, 1.0f);
+ wlr_renderer_end(wlr_renderer);
+
+ r = true;
+out:
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ glDeleteFramebuffers(1, &fbo);
+ glDeleteRenderbuffers(1, &rbo);
+ wlr_egl_destroy_image(egl, image);
+texture_destroy_out:
+ wlr_texture_destroy(src_tex);
+restore_context_out:
+ wlr_egl_restore_context(&old_context);
+ return r;
+}
+
static struct wlr_texture *gles2_texture_from_pixels(
struct wlr_renderer *wlr_renderer, enum wl_shm_format wl_fmt,
uint32_t stride, uint32_t width, uint32_t height, const void *data) {
@@ -426,6 +504,7 @@ static const struct wlr_renderer_impl renderer_impl = {
.texture_from_wl_drm = gles2_texture_from_wl_drm,
.texture_from_dmabuf = gles2_texture_from_dmabuf,
.init_wl_display = gles2_init_wl_display,
+ .blit_dmabuf = gles2_blit_dmabuf,
};
void push_gles2_marker(const char *file, const char *func) {
@@ -606,6 +685,12 @@ struct wlr_renderer *wlr_gles2_renderer_create(struct wlr_egl *egl) {
"glEGLImageTargetTexture2DOES");
}
+ if (check_gl_ext(exts_str, "GL_OES_EGL_image")) {
+ renderer->exts.egl_image_oes = true;
+ load_gl_proc(&gles2_procs.glEGLImageTargetRenderbufferStorageOES,
+ "glEGLImageTargetRenderbufferStorageOES");
+ }
+
if (renderer->exts.debug_khr) {
glEnable(GL_DEBUG_OUTPUT_KHR);
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR);
diff --git a/render/wlr_renderer.c b/render/wlr_renderer.c
index 9a126706..89a73fc8 100644
--- a/render/wlr_renderer.c
+++ b/render/wlr_renderer.c
@@ -154,6 +154,16 @@ bool wlr_renderer_read_pixels(struct wlr_renderer *r, enum wl_shm_format fmt,
src_x, src_y, dst_x, dst_y, data);
}
+bool wlr_renderer_blit_dmabuf(struct wlr_renderer *r,
+ struct wlr_dmabuf_attributes *dst,
+ struct wlr_dmabuf_attributes *src) {
+ assert(!r->rendering);
+ if (!r->impl->blit_dmabuf) {
+ return false;
+ }
+ return r->impl->blit_dmabuf(r, dst, src);
+}
+
bool wlr_renderer_format_supported(struct wlr_renderer *r,
enum wl_shm_format fmt) {
return r->impl->format_supported(r, fmt);