From c63d94483b1e52817ca01ca82a867a78ebd39fa6 Mon Sep 17 00:00:00 2001 From: emersion Date: Sat, 24 Mar 2018 18:30:28 -0400 Subject: Redesign wlr_texture - Textures are now immutable (apart from those created from raw pixels), no more invalid textures - Move all wl_drm stuff in wlr_renderer - Most of wlr_texture fields are now private - Remove some duplicated DMA-BUF code in the DRM backend - Add more assertions - Stride is now always given as bytes rather than pixels - Drop wl_shm functions Fun fact: this patch has been written 10,000 meters up in the air. --- render/gles2/renderer.c | 124 ++++++++----- render/gles2/texture.c | 464 +++++++++++++++++++----------------------------- 2 files changed, 259 insertions(+), 329 deletions(-) (limited to 'render/gles2') diff --git a/render/gles2/renderer.c b/render/gles2/renderer.c index 9403c0ed..dcda45e9 100644 --- a/render/gles2/renderer.c +++ b/render/gles2/renderer.c @@ -12,23 +12,27 @@ #include #include #include -#include "render/gles2.h" #include "glapi.h" +#include "render/gles2.h" static const struct wlr_renderer_impl renderer_impl; -static struct wlr_gles2_renderer *gles2_get_renderer( +struct wlr_gles2_renderer *gles2_get_renderer( struct wlr_renderer *wlr_renderer) { assert(wlr_renderer->impl == &renderer_impl); - struct wlr_gles2_renderer *renderer = - (struct wlr_gles2_renderer *)wlr_renderer; + return (struct wlr_gles2_renderer *)wlr_renderer; +} + +struct wlr_gles2_renderer *gles2_get_renderer_in_context( + struct wlr_renderer *wlr_renderer) { + struct wlr_gles2_renderer *renderer = gles2_get_renderer(wlr_renderer); assert(eglGetCurrentContext() == renderer->egl->context); return renderer; } static void gles2_begin(struct wlr_renderer *wlr_renderer, uint32_t width, uint32_t height) { - gles2_get_renderer(wlr_renderer); + gles2_get_renderer_in_context(wlr_renderer); GLES2_DEBUG_PUSH; @@ -45,13 +49,13 @@ static void gles2_begin(struct wlr_renderer *wlr_renderer, uint32_t width, } static void gles2_end(struct wlr_renderer *wlr_renderer) { - gles2_get_renderer(wlr_renderer); + gles2_get_renderer_in_context(wlr_renderer); // no-op } static void gles2_clear(struct wlr_renderer *wlr_renderer, const float color[static 4]) { - gles2_get_renderer(wlr_renderer); + gles2_get_renderer_in_context(wlr_renderer); GLES2_DEBUG_PUSH; glClearColor(color[0], color[1], color[2], color[3]); @@ -61,7 +65,7 @@ static void gles2_clear(struct wlr_renderer *wlr_renderer, static void gles2_scissor(struct wlr_renderer *wlr_renderer, struct wlr_box *box) { - gles2_get_renderer(wlr_renderer); + gles2_get_renderer_in_context(wlr_renderer); GLES2_DEBUG_PUSH; if (box != NULL) { @@ -73,14 +77,6 @@ static void gles2_scissor(struct wlr_renderer *wlr_renderer, GLES2_DEBUG_POP; } -static struct wlr_texture *gles2_renderer_texture_create( - struct wlr_renderer *wlr_renderer) { - assert(wlr_renderer->impl == &renderer_impl); - struct wlr_gles2_renderer *renderer = - (struct wlr_gles2_renderer *)wlr_renderer; - return gles2_texture_create(renderer->egl); -} - static void draw_quad() { GLfloat verts[] = { 1, 0, // top right @@ -107,21 +103,28 @@ static void draw_quad() { glDisableVertexAttribArray(1); } -static bool gles2_render_texture_with_matrix( - struct wlr_renderer *wlr_renderer, struct wlr_texture *wlr_texture, - const float matrix[static 9], float alpha) { - struct wlr_gles2_renderer *renderer = gles2_get_renderer(wlr_renderer); - struct wlr_gles2_texture *texture = gles2_get_texture(wlr_texture); - if (!wlr_texture->valid) { - wlr_log(L_ERROR, "attempt to render invalid texture"); - return false; - } - - GLuint prog = renderer->shaders.tex_rgba; - if (texture->target == GL_TEXTURE_EXTERNAL_OES) { +static bool gles2_render_texture_with_matrix(struct wlr_renderer *wlr_renderer, + struct wlr_texture *wlr_texture, const float matrix[static 9], + float alpha) { + struct wlr_gles2_renderer *renderer = + gles2_get_renderer_in_context(wlr_renderer); + struct wlr_gles2_texture *texture = + gles2_get_texture_in_context(wlr_texture); + + GLuint prog; + GLenum target; + switch (texture->type) { + case WLR_GLES2_TEXTURE_GLTEX: + case WLR_GLES2_TEXTURE_WL_DRM_GL: + prog = texture->has_alpha ? renderer->shaders.tex_rgba : + renderer->shaders.tex_rgbx; + target = GL_TEXTURE_2D; + break; + case WLR_GLES2_TEXTURE_WL_DRM_EXT: + case WLR_GLES2_TEXTURE_DMABUF: prog = renderer->shaders.tex_ext; - } else if (!texture->pixel_format->has_alpha) { - prog = renderer->shaders.tex_rgbx; + target = GL_TEXTURE_EXTERNAL_OES; + break; } // OpenGL ES 2 requires the glUniformMatrix3fv transpose parameter to be set @@ -130,15 +133,23 @@ static bool gles2_render_texture_with_matrix( wlr_matrix_transpose(transposition, matrix); GLES2_DEBUG_PUSH; - glBindTexture(texture->target, texture->tex_id); - glTexParameteri(texture->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(texture->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + GLuint tex_id = texture->type == WLR_GLES2_TEXTURE_GLTEX ? + texture->gl_tex : texture->image_tex; + glActiveTexture(GL_TEXTURE0); + glBindTexture(target, tex_id); + + glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glUseProgram(prog); glUniformMatrix3fv(0, 1, GL_FALSE, transposition); - glUniform1i(1, wlr_texture->inverted_y); + glUniform1i(1, texture->inverted_y); glUniform1f(3, alpha); + draw_quad(); + GLES2_DEBUG_POP; return true; } @@ -146,7 +157,8 @@ static bool gles2_render_texture_with_matrix( static void gles2_render_quad(struct wlr_renderer *wlr_renderer, const float color[static 4], const float matrix[static 9]) { - struct wlr_gles2_renderer *renderer = gles2_get_renderer(wlr_renderer); + struct wlr_gles2_renderer *renderer = + gles2_get_renderer_in_context(wlr_renderer); // OpenGL ES 2 requires the glUniformMatrix3fv transpose parameter to be set // to GL_FALSE @@ -163,7 +175,8 @@ static void gles2_render_quad(struct wlr_renderer *wlr_renderer, static void gles2_render_ellipse(struct wlr_renderer *wlr_renderer, const float color[static 4], const float matrix[static 9]) { - struct wlr_gles2_renderer *renderer = gles2_get_renderer(wlr_renderer); + struct wlr_gles2_renderer *renderer = + gles2_get_renderer_in_context(wlr_renderer); // OpenGL ES 2 requires the glUniformMatrix3fv transpose parameter to be set // to GL_FALSE @@ -183,20 +196,38 @@ static const enum wl_shm_format *gles2_renderer_formats( return gles2_formats(len); } -static bool gles2_buffer_is_drm(struct wlr_renderer *wlr_renderer, - struct wl_resource *buffer) { - struct wlr_gles2_renderer *renderer = gles2_get_renderer(wlr_renderer); +static bool gles2_resource_is_wl_drm_buffer(struct wlr_renderer *wlr_renderer, + struct wl_resource *resource) { + struct wlr_gles2_renderer *renderer = + gles2_get_renderer_in_context(wlr_renderer); + + if (!eglQueryWaylandBufferWL) { + return false; + } + + EGLint fmt; + return eglQueryWaylandBufferWL(renderer->egl->display, resource, + EGL_TEXTURE_FORMAT, &fmt); +} + +static void gles2_wl_drm_buffer_get_size(struct wlr_renderer *wlr_renderer, + struct wl_resource *buffer, int *width, int *height) { + struct wlr_gles2_renderer *renderer = + gles2_get_renderer_in_context(wlr_renderer); + + if (!eglQueryWaylandBufferWL) { + return; + } - EGLint format; - return wlr_egl_query_buffer(renderer->egl, buffer, EGL_TEXTURE_FORMAT, - &format); + eglQueryWaylandBufferWL(renderer->egl->display, buffer, EGL_WIDTH, width); + eglQueryWaylandBufferWL(renderer->egl->display, buffer, EGL_HEIGHT, height); } static bool gles2_read_pixels(struct wlr_renderer *wlr_renderer, enum wl_shm_format wl_fmt, 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) { - gles2_get_renderer(wlr_renderer); + gles2_get_renderer_in_context(wlr_renderer); const struct gles2_pixel_format *fmt = gles2_format_from_wl(wl_fmt); if (fmt == NULL) { @@ -254,14 +285,17 @@ static const struct wlr_renderer_impl renderer_impl = { .end = gles2_end, .clear = gles2_clear, .scissor = gles2_scissor, - .texture_create = gles2_renderer_texture_create, .render_texture_with_matrix = gles2_render_texture_with_matrix, .render_quad = gles2_render_quad, .render_ellipse = gles2_render_ellipse, .formats = gles2_renderer_formats, - .buffer_is_drm = gles2_buffer_is_drm, + .resource_is_wl_drm_buffer = gles2_resource_is_wl_drm_buffer, + .wl_drm_buffer_get_size = gles2_wl_drm_buffer_get_size, .read_pixels = gles2_read_pixels, .format_supported = gles2_format_supported, + .texture_from_pixels = gles2_texture_from_pixels, + .texture_from_wl_drm = gles2_texture_from_wl_drm, + .texture_from_dmabuf = gles2_texture_from_dmabuf, }; void gles2_push_marker(const char *file, const char *func) { diff --git a/render/gles2/texture.c b/render/gles2/texture.c index 46193c78..82effd71 100644 --- a/render/gles2/texture.c +++ b/render/gles2/texture.c @@ -10,366 +10,262 @@ #include #include #include +#include "glapi.h" #include "render/gles2.h" #include "util/signal.h" -static struct gles2_pixel_format external_pixel_format = { - .wl_format = 0, - .depth = 0, - .bpp = 0, - .gl_format = 0, - .gl_type = 0, -}; - -static void gles2_texture_ensure(struct wlr_gles2_texture *texture, - GLenum target) { - if (texture->tex_id) { - return; - } - texture->target = target; - glGenTextures(1, &texture->tex_id); - glBindTexture(target, texture->tex_id); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); -} - static const struct wlr_texture_impl texture_impl; -struct wlr_gles2_texture *gles2_get_texture(struct wlr_texture *wlr_texture) { +static struct wlr_gles2_texture *gles2_get_texture( + struct wlr_texture *wlr_texture) { assert(wlr_texture->impl == &texture_impl); return (struct wlr_gles2_texture *)wlr_texture; } -static bool gles2_texture_upload_pixels(struct wlr_texture *wlr_texture, - enum wl_shm_format format, int stride, int width, int height, - const unsigned char *pixels) { +struct wlr_gles2_texture *gles2_get_texture_in_context( + struct wlr_texture *wlr_texture) { struct wlr_gles2_texture *texture = gles2_get_texture(wlr_texture); - - const struct gles2_pixel_format *fmt = gles2_format_from_wl(format); - if (!fmt || !fmt->gl_format) { - wlr_log(L_ERROR, "No supported pixel format for this texture"); - return false; - } - texture->wlr_texture.width = width; - texture->wlr_texture.height = height; - texture->wlr_texture.format = format; - texture->pixel_format = fmt; - - GLES2_DEBUG_PUSH; - gles2_texture_ensure(texture, GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, texture->tex_id); - glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, stride); - glTexImage2D(GL_TEXTURE_2D, 0, fmt->gl_format, width, height, 0, - fmt->gl_format, fmt->gl_type, pixels); - GLES2_DEBUG_POP; - - texture->wlr_texture.valid = true; - return true; + assert(eglGetCurrentContext() == texture->renderer->egl->context); + return texture; } -static bool gles2_texture_update_pixels(struct wlr_texture *wlr_texture, - enum wl_shm_format format, int stride, int x, int y, - int width, int height, const unsigned char *pixels) { +static void gles2_texture_get_size(struct wlr_texture *wlr_texture, int *width, + int *height) { struct wlr_gles2_texture *texture = gles2_get_texture(wlr_texture); - - // TODO: Test if the unpack subimage extension is supported and adjust the - // upload strategy if not - if (!texture->wlr_texture.valid - || texture->wlr_texture.format != format - /* || unpack not supported */) { - return gles2_texture_upload_pixels(&texture->wlr_texture, format, - stride, width, height, pixels); - } - const struct gles2_pixel_format *fmt = texture->pixel_format; - GLES2_DEBUG_PUSH; - glBindTexture(GL_TEXTURE_2D, texture->tex_id); - glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, stride); - glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, x); - glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, y); - glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, fmt->gl_format, - fmt->gl_type, pixels); - glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, 0); - glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, 0); - GLES2_DEBUG_POP; - return true; + *width = texture->width; + *height = texture->height; } -static bool gles2_texture_upload_shm(struct wlr_texture *wlr_texture, - uint32_t format, struct wl_shm_buffer *buffer) { - struct wlr_gles2_texture *texture = gles2_get_texture(wlr_texture); +static bool gles2_texture_write_pixels(struct wlr_texture *wlr_texture, + enum wl_shm_format wl_fmt, 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, const void *data) { + struct wlr_gles2_texture *texture = + gles2_get_texture_in_context(wlr_texture); + + if (texture->type != WLR_GLES2_TEXTURE_GLTEX) { + wlr_log(L_ERROR, "Cannot write pixels to immutable texture"); + return false; + } - const struct gles2_pixel_format *fmt = gles2_format_from_wl(format); - if (!fmt || !fmt->gl_format) { - wlr_log(L_ERROR, "Unsupported pixel format %"PRIu32" for this texture", - format); + const struct gles2_pixel_format *fmt = gles2_format_from_wl(wl_fmt); + if (fmt == NULL) { + wlr_log(L_ERROR, "Unsupported pixel format %"PRIu32, wl_fmt); return false; } - wl_shm_buffer_begin_access(buffer); - uint8_t *pixels = wl_shm_buffer_get_data(buffer); - int width = wl_shm_buffer_get_width(buffer); - int height = wl_shm_buffer_get_height(buffer); - int pitch = wl_shm_buffer_get_stride(buffer) / (fmt->bpp / 8); - texture->wlr_texture.width = width; - texture->wlr_texture.height = height; - texture->wlr_texture.format = format; - texture->pixel_format = fmt; + // TODO: what if the unpack subimage extension isn't supported? GLES2_DEBUG_PUSH; - gles2_texture_ensure(texture, GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, texture->tex_id); - glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, pitch); - glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, 0); - glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, 0); - glTexImage2D(GL_TEXTURE_2D, 0, fmt->gl_format, width, height, 0, - fmt->gl_format, fmt->gl_type, pixels); - GLES2_DEBUG_POP; - texture->wlr_texture.valid = true; - wl_shm_buffer_end_access(buffer); - return true; -} + glBindTexture(GL_TEXTURE_2D, texture->gl_tex); -static bool gles2_texture_update_shm(struct wlr_texture *wlr_texture, - uint32_t format, int x, int y, int width, int height, - struct wl_shm_buffer *buffer) { - struct wlr_gles2_texture *texture = gles2_get_texture(wlr_texture); + glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, stride / (fmt->bpp / 8)); + glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, src_x); + glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, src_y); - // TODO: Test if the unpack subimage extension is supported and adjust the - // upload strategy if not - assert(texture); - if (!texture->wlr_texture.valid - || texture->wlr_texture.format != format - /* || unpack not supported */) { - return gles2_texture_upload_shm(&texture->wlr_texture, format, buffer); - } - const struct gles2_pixel_format *fmt = texture->pixel_format; - wl_shm_buffer_begin_access(buffer); - uint8_t *pixels = wl_shm_buffer_get_data(buffer); - int pitch = wl_shm_buffer_get_stride(buffer) / (fmt->bpp / 8); + glTexSubImage2D(GL_TEXTURE_2D, 0, dst_x, dst_y, width, height, + fmt->gl_format, fmt->gl_type, data); - GLES2_DEBUG_PUSH; - glBindTexture(GL_TEXTURE_2D, texture->tex_id); - glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, pitch); - glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, x); - glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, y); - glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, - fmt->gl_format, fmt->gl_type, pixels); + glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0); glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, 0); glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, 0); - GLES2_DEBUG_POP; - - wl_shm_buffer_end_access(buffer); + GLES2_DEBUG_POP; return true; } -static bool gles2_texture_upload_drm(struct wlr_texture *wlr_texture, - struct wl_resource *buf) { - struct wlr_gles2_texture *tex = gles2_get_texture(wlr_texture); - if (!glEGLImageTargetTexture2DOES) { - return false; +static void gles2_texture_destroy(struct wlr_texture *wlr_texture) { + if (wlr_texture == NULL) { + return; } - EGLint format; - if (!wlr_egl_query_buffer(tex->egl, buf, EGL_TEXTURE_FORMAT, &format)) { - wlr_log(L_INFO, "upload_drm called with no drm buffer"); - return false; - } + struct wlr_gles2_texture *texture = gles2_get_texture(wlr_texture); - wlr_egl_query_buffer(tex->egl, buf, EGL_WIDTH, - (EGLint*)&tex->wlr_texture.width); - wlr_egl_query_buffer(tex->egl, buf, EGL_HEIGHT, - (EGLint*)&tex->wlr_texture.height); + wlr_egl_make_current(texture->renderer->egl, EGL_NO_SURFACE, NULL); - EGLint inverted_y; - if (wlr_egl_query_buffer(tex->egl, buf, EGL_WAYLAND_Y_INVERTED_WL, - &inverted_y)) { - tex->wlr_texture.inverted_y = !!inverted_y; + GLES2_DEBUG_PUSH; + + if (texture->image_tex) { + glDeleteTextures(1, &texture->image_tex); + } + if (texture->image) { + assert(eglDestroyImageKHR); + eglDestroyImageKHR(texture->renderer->egl->display, texture->image); } - GLenum target; - const struct gles2_pixel_format *pf; - switch (format) { - case EGL_TEXTURE_RGB: - case EGL_TEXTURE_RGBA: - target = GL_TEXTURE_2D; - pf = gles2_format_from_wl(WL_SHM_FORMAT_ARGB8888); - break; - case EGL_TEXTURE_EXTERNAL_WL: - target = GL_TEXTURE_EXTERNAL_OES; - pf = &external_pixel_format; - break; - default: - wlr_log(L_ERROR, "invalid/unsupported egl buffer format"); - return false; + if (texture->type == WLR_GLES2_TEXTURE_GLTEX) { + glDeleteTextures(1, &texture->gl_tex); } - GLES2_DEBUG_PUSH; - gles2_texture_ensure(tex, target); - glBindTexture(GL_TEXTURE_2D, tex->tex_id); GLES2_DEBUG_POP; - EGLint attribs[] = { EGL_WAYLAND_PLANE_WL, 0, EGL_NONE }; + free(texture); +} - if (tex->image) { - wlr_egl_destroy_image(tex->egl, tex->image); +static const struct wlr_texture_impl texture_impl = { + .get_size = gles2_texture_get_size, + .write_pixels = gles2_texture_write_pixels, + .destroy = gles2_texture_destroy, +}; + +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) { + struct wlr_gles2_renderer *renderer = + gles2_get_renderer_in_context(wlr_renderer); + + const struct gles2_pixel_format *fmt = gles2_format_from_wl(wl_fmt); + if (fmt == NULL) { + wlr_log(L_ERROR, "Unsupported pixel format %"PRIu32, wl_fmt); + return NULL; } - tex->image = wlr_egl_create_image(tex->egl, EGL_WAYLAND_BUFFER_WL, - (EGLClientBuffer*) buf, attribs); - if (!tex->image) { - wlr_log(L_ERROR, "failed to create EGL image"); - return false; + struct wlr_gles2_texture *texture = + calloc(1, sizeof(struct wlr_gles2_texture)); + if (texture == NULL) { + wlr_log(L_ERROR, "Allocation failed"); + return NULL; } + wlr_texture_init(&texture->wlr_texture, &texture_impl); + texture->renderer = renderer; + texture->width = width; + texture->height = height; + texture->type = WLR_GLES2_TEXTURE_GLTEX; + texture->has_alpha = fmt->has_alpha; GLES2_DEBUG_PUSH; - glActiveTexture(GL_TEXTURE0); - glBindTexture(target, tex->tex_id); - glEGLImageTargetTexture2DOES(target, tex->image); - GLES2_DEBUG_POP; - tex->wlr_texture.valid = true; - tex->pixel_format = pf; - - return true; -} -static bool gles2_texture_upload_eglimage(struct wlr_texture *wlr_texture, - EGLImageKHR image, uint32_t width, uint32_t height) { - struct wlr_gles2_texture *tex = gles2_get_texture(wlr_texture); + glGenTextures(1, &texture->gl_tex); + glBindTexture(GL_TEXTURE_2D, texture->gl_tex); - tex->image = image; - tex->pixel_format = &external_pixel_format; - tex->wlr_texture.valid = true; - tex->wlr_texture.width = width; - tex->wlr_texture.height = height; + glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, stride / (fmt->bpp / 8)); + glTexImage2D(GL_TEXTURE_2D, 0, fmt->gl_format, width, height, 0, + fmt->gl_format, fmt->gl_type, data); + glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0); - GLES2_DEBUG_PUSH; - gles2_texture_ensure(tex, GL_TEXTURE_2D); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex->tex_id); - glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, tex->image); GLES2_DEBUG_POP; - - return true; + return (struct wlr_texture *)texture; } -static bool gles2_texture_upload_dmabuf(struct wlr_texture *wlr_texture, - struct wl_resource *dmabuf_resource) { - struct wlr_gles2_texture *tex = gles2_get_texture(wlr_texture); - struct wlr_dmabuf_buffer *dmabuf = - wlr_dmabuf_buffer_from_buffer_resource(dmabuf_resource); +struct wlr_texture *gles2_texture_from_wl_drm(struct wlr_renderer *wlr_renderer, + struct wl_resource *data) { + struct wlr_gles2_renderer *renderer = gles2_get_renderer(wlr_renderer); - if (!tex->egl->egl_exts.dmabuf_import) { - wlr_log(L_ERROR, "Want dmabuf but extension not present"); - return false; + if (!eglQueryWaylandBufferWL || !eglCreateImageKHR || + !glEGLImageTargetTexture2DOES) { + return NULL; } - tex->wlr_texture.width = dmabuf->attributes.width; - tex->wlr_texture.height = dmabuf->attributes.height; + EGLint fmt; + if (!eglQueryWaylandBufferWL(renderer->egl->display, data, + EGL_TEXTURE_FORMAT, &fmt)) { + return NULL; + } - if (tex->image) { - wlr_egl_destroy_image(tex->egl, tex->image); + EGLint width, height; + eglQueryWaylandBufferWL(renderer->egl->display, data, EGL_WIDTH, &width); + eglQueryWaylandBufferWL(renderer->egl->display, data, EGL_HEIGHT, &height); + + EGLint inverted_y; + if (!eglQueryWaylandBufferWL(renderer->egl->display, data, + EGL_WAYLAND_Y_INVERTED_WL, &inverted_y)) { + inverted_y = 0; } - if (wlr_dmabuf_buffer_has_inverted_y(dmabuf)) { - wlr_texture->inverted_y = true; + struct wlr_gles2_texture *texture = + calloc(1, sizeof(struct wlr_gles2_texture)); + if (texture == NULL) { + wlr_log(L_ERROR, "Allocation failed"); + return NULL; } + wlr_texture_init(&texture->wlr_texture, &texture_impl); + texture->renderer = renderer; + texture->width = width; + texture->height = height; + texture->wl_drm = data; + texture->inverted_y = !!inverted_y; GLenum target; - const struct gles2_pixel_format *pf; - if (dmabuf->attributes.n_planes > 1) { - target = GL_TEXTURE_EXTERNAL_OES; - pf = &external_pixel_format; - } else { + switch (fmt) { + case EGL_TEXTURE_RGB: + case EGL_TEXTURE_RGBA: target = GL_TEXTURE_2D; - pf = gles2_format_from_wl(WL_SHM_FORMAT_ARGB8888); + texture->type = WLR_GLES2_TEXTURE_WL_DRM_GL; + texture->has_alpha = fmt == EGL_TEXTURE_RGBA; + break; + case EGL_TEXTURE_EXTERNAL_WL: + target = GL_TEXTURE_EXTERNAL_OES; + texture->type = WLR_GLES2_TEXTURE_WL_DRM_EXT; + texture->has_alpha = true; + break; + default: + wlr_log(L_ERROR, "Invalid or unsupported EGL buffer format"); + free(texture); + return NULL; } - GLES2_DEBUG_PUSH; - gles2_texture_ensure(tex, target); - glBindTexture(target, tex->tex_id); - tex->image = wlr_egl_create_image_from_dmabuf(tex->egl, &dmabuf->attributes); - glActiveTexture(GL_TEXTURE0); - glEGLImageTargetTexture2DOES(target, tex->image); - GLES2_DEBUG_POP; - tex->pixel_format = pf; - tex->wlr_texture.valid = true; - return true; -} -static bool gles2_texture_get_dmabuf_size(struct wlr_texture *texture, struct - wl_resource *resource, int *width, int *height) { - if (!wlr_dmabuf_resource_is_buffer(resource)) { - return false; + EGLint attribs[] = { + EGL_WAYLAND_PLANE_WL, 0, + EGL_NONE, + }; + texture->image = eglCreateImageKHR(renderer->egl->display, + renderer->egl->context, EGL_WAYLAND_BUFFER_WL, data, attribs); + if (texture->image == NULL) { + free(texture); + return NULL; } - struct wlr_dmabuf_buffer *dmabuf = - wlr_dmabuf_buffer_from_buffer_resource(resource); - *width = dmabuf->attributes.width; - *height = dmabuf->attributes.height; - return true; -} - -static void gles2_texture_get_buffer_size(struct wlr_texture *texture, - struct wl_resource *resource, int *width, int *height) { - struct wl_shm_buffer *buffer = wl_shm_buffer_get(resource); - if (!buffer) { - struct wlr_gles2_texture *tex = (struct wlr_gles2_texture *)texture; - if (!glEGLImageTargetTexture2DOES) { - return; - } - if (!wlr_egl_query_buffer(tex->egl, resource, EGL_WIDTH, - (EGLint*)width)) { - if (!gles2_texture_get_dmabuf_size(texture, resource, width, - height)) { - wlr_log(L_ERROR, "could not get size of the buffer"); - return; - } - } - wlr_egl_query_buffer(tex->egl, resource, EGL_HEIGHT, (EGLint*)height); + GLES2_DEBUG_PUSH; - return; - } + glGenTextures(1, &texture->image_tex); + glBindTexture(target, texture->image_tex); + glEGLImageTargetTexture2DOES(target, texture->image); - *width = wl_shm_buffer_get_width(buffer); - *height = wl_shm_buffer_get_height(buffer); + GLES2_DEBUG_POP; + return (struct wlr_texture *)texture; } -static void gles2_texture_destroy(struct wlr_texture *wlr_texture) { - struct wlr_gles2_texture *texture = gles2_get_texture(wlr_texture); +struct wlr_texture *gles2_texture_from_dmabuf(struct wlr_renderer *wlr_renderer, + struct wlr_dmabuf_buffer_attribs *attribs) { + struct wlr_gles2_renderer *renderer = gles2_get_renderer(wlr_renderer); - wlr_signal_emit_safe(&texture->wlr_texture.destroy_signal, - &texture->wlr_texture); - if (texture->tex_id) { - GLES2_DEBUG_PUSH; - glDeleteTextures(1, &texture->tex_id); - GLES2_DEBUG_POP; + if (!glEGLImageTargetTexture2DOES) { + return NULL; } - if (texture->image) { - wlr_egl_destroy_image(texture->egl, texture->image); + if (!renderer->egl->egl_exts.dmabuf_import) { + wlr_log(L_ERROR, "Cannot create DMA-BUF texture: EGL extension " + "unavailable"); + return NULL; } - free(texture); -} - -static const struct wlr_texture_impl texture_impl = { - .upload_pixels = gles2_texture_upload_pixels, - .update_pixels = gles2_texture_update_pixels, - .upload_shm = gles2_texture_upload_shm, - .update_shm = gles2_texture_update_shm, - .upload_drm = gles2_texture_upload_drm, - .upload_dmabuf = gles2_texture_upload_dmabuf, - .upload_eglimage = gles2_texture_upload_eglimage, - .get_buffer_size = gles2_texture_get_buffer_size, - .destroy = gles2_texture_destroy, -}; - -struct wlr_texture *gles2_texture_create(struct wlr_egl *egl) { - struct wlr_gles2_texture *texture; - if (!(texture = calloc(1, sizeof(struct wlr_gles2_texture)))) { + struct wlr_gles2_texture *texture = + calloc(1, sizeof(struct wlr_gles2_texture)); + if (texture == NULL) { + wlr_log(L_ERROR, "Allocation failed"); return NULL; } wlr_texture_init(&texture->wlr_texture, &texture_impl); - texture->egl = egl; - return &texture->wlr_texture; + texture->renderer = renderer; + texture->width = attribs->width; + texture->height = attribs->height; + texture->type = WLR_GLES2_TEXTURE_DMABUF; + texture->has_alpha = true; + texture->inverted_y = + (attribs->flags & WLR_DMABUF_BUFFER_ATTRIBS_FLAGS_Y_INVERT) != 0; + + texture->image = wlr_egl_create_image_from_dmabuf(renderer->egl, attribs); + if (texture->image == NULL) { + free(texture); + return NULL; + } + + GLES2_DEBUG_PUSH; + + glGenTextures(1, &texture->image_tex); + glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture->image_tex); + glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, texture->image); + + GLES2_DEBUG_POP; + return (struct wlr_texture *)texture; } -- cgit v1.2.3 From c42fd1018b037f20c5045fb3cbf39ac35ec980c6 Mon Sep 17 00:00:00 2001 From: emersion Date: Tue, 27 Mar 2018 17:02:48 -0400 Subject: render: remove GL calls from wlr_egl --- include/render/gles2.h | 1 + include/wlr/render/egl.h | 3 +-- render/egl.c | 23 +++++++++-------------- render/gles2/renderer.c | 5 +++++ 4 files changed, 16 insertions(+), 16 deletions(-) (limited to 'render/gles2') diff --git a/include/render/gles2.h b/include/render/gles2.h index 43a8d648..33ad9a48 100644 --- a/include/render/gles2.h +++ b/include/render/gles2.h @@ -28,6 +28,7 @@ struct wlr_gles2_renderer { struct wlr_renderer wlr_renderer; struct wlr_egl *egl; + const char *exts_str; struct { GLuint quad; diff --git a/include/wlr/render/egl.h b/include/wlr/render/egl.h index aa429e8e..9f4c0334 100644 --- a/include/wlr/render/egl.h +++ b/include/wlr/render/egl.h @@ -13,8 +13,7 @@ struct wlr_egl { EGLConfig config; EGLContext context; - const char *egl_exts_str; - const char *gl_exts_str; + const char *exts_str; struct { bool buffer_age; diff --git a/render/egl.c b/render/egl.c index e582b6d3..f2966774 100644 --- a/render/egl.c +++ b/render/egl.c @@ -2,7 +2,6 @@ #include #include #include -#include #include #include #include @@ -155,32 +154,28 @@ bool wlr_egl_init(struct wlr_egl *egl, EGLenum platform, void *remote_display, } eglMakeCurrent(egl->display, EGL_NO_SURFACE, EGL_NO_SURFACE, egl->context); - egl->egl_exts_str = eglQueryString(egl->display, EGL_EXTENSIONS); - egl->gl_exts_str = (const char*) glGetString(GL_EXTENSIONS); + egl->exts_str = eglQueryString(egl->display, EGL_EXTENSIONS); wlr_log(L_INFO, "Using EGL %d.%d", (int)major, (int)minor); - wlr_log(L_INFO, "Supported EGL extensions: %s", egl->egl_exts_str); + wlr_log(L_INFO, "Supported EGL extensions: %s", egl->exts_str); wlr_log(L_INFO, "EGL vendor: %s", eglQueryString(egl->display, EGL_VENDOR)); - wlr_log(L_INFO, "Using %s", glGetString(GL_VERSION)); - wlr_log(L_INFO, "GL vendor: %s", glGetString(GL_VENDOR)); - wlr_log(L_INFO, "Supported OpenGL ES extensions: %s", egl->gl_exts_str); - if (!check_egl_ext(egl->egl_exts_str, "EGL_WL_bind_wayland_display") || - !check_egl_ext(egl->egl_exts_str, "EGL_KHR_image_base")) { + if (!check_egl_ext(egl->exts_str, "EGL_WL_bind_wayland_display") || + !check_egl_ext(egl->exts_str, "EGL_KHR_image_base")) { wlr_log(L_ERROR, "Required egl extensions not supported"); goto error; } egl->egl_exts.buffer_age = - check_egl_ext(egl->egl_exts_str, "EGL_EXT_buffer_age"); + check_egl_ext(egl->exts_str, "EGL_EXT_buffer_age"); egl->egl_exts.swap_buffers_with_damage = - check_egl_ext(egl->egl_exts_str, "EGL_EXT_swap_buffers_with_damage") || - check_egl_ext(egl->egl_exts_str, "EGL_KHR_swap_buffers_with_damage"); + check_egl_ext(egl->exts_str, "EGL_EXT_swap_buffers_with_damage") || + check_egl_ext(egl->exts_str, "EGL_KHR_swap_buffers_with_damage"); egl->egl_exts.dmabuf_import = - check_egl_ext(egl->egl_exts_str, "EGL_EXT_image_dma_buf_import"); + check_egl_ext(egl->exts_str, "EGL_EXT_image_dma_buf_import"); egl->egl_exts.dmabuf_import_modifiers = - check_egl_ext(egl->egl_exts_str, "EGL_EXT_image_dma_buf_import_modifiers") + check_egl_ext(egl->exts_str, "EGL_EXT_image_dma_buf_import_modifiers") && eglQueryDmaBufFormatsEXT && eglQueryDmaBufModifiersEXT; print_dmabuf_formats(egl); diff --git a/render/gles2/renderer.c b/render/gles2/renderer.c index 61665a07..36a62aa7 100644 --- a/render/gles2/renderer.c +++ b/render/gles2/renderer.c @@ -377,6 +377,11 @@ struct wlr_renderer *wlr_gles2_renderer_create(struct wlr_backend *backend) { renderer->egl = wlr_backend_get_egl(backend); wlr_egl_make_current(renderer->egl, EGL_NO_SURFACE, NULL); + renderer->exts_str = (const char*) glGetString(GL_EXTENSIONS); + wlr_log(L_INFO, "Using %s", glGetString(GL_VERSION)); + wlr_log(L_INFO, "GL vendor: %s", glGetString(GL_VENDOR)); + wlr_log(L_INFO, "Supported GLES2 extensions: %s", renderer->exts_str); + if (glDebugMessageCallbackKHR && glDebugMessageControlKHR) { glEnable(GL_DEBUG_OUTPUT_KHR); glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR); -- cgit v1.2.3 From c9ed6fed59bb297d1393fdca790ae433bc6f09f9 Mon Sep 17 00:00:00 2001 From: Orestis Floros Date: Fri, 30 Mar 2018 23:43:16 +0300 Subject: Fix build error with -O2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ../render/gles2/renderer.c: In function ‘gles2_render_texture_with_matrix’: ../render/gles2/renderer.c:140:2: error: ‘target’ may be used uninitialized in this function [-Werror=maybe-uninitialized] glBindTexture(target, tex_id); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ../render/gles2/renderer.c:145:2: error: ‘prog’ may be used uninitialized in this function [-Werror=maybe-uninitialized] glUseProgram(prog); --- render/gles2/renderer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'render/gles2') diff --git a/render/gles2/renderer.c b/render/gles2/renderer.c index f96f468b..8f3ce7f7 100644 --- a/render/gles2/renderer.c +++ b/render/gles2/renderer.c @@ -111,8 +111,8 @@ static bool gles2_render_texture_with_matrix(struct wlr_renderer *wlr_renderer, struct wlr_gles2_texture *texture = gles2_get_texture_in_context(wlr_texture); - GLuint prog; - GLenum target; + GLuint prog = 0; + GLenum target = 0; switch (texture->type) { case WLR_GLES2_TEXTURE_GLTEX: case WLR_GLES2_TEXTURE_WL_DRM_GL: -- cgit v1.2.3 From 23d357e371fd49243a6f2989058b25c599888505 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 31 Mar 2018 00:27:30 -0400 Subject: Downgrade gles2 messages to L_DEBUG L_INFO is for stuff that's useful to the user --- render/gles2/renderer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'render/gles2') diff --git a/render/gles2/renderer.c b/render/gles2/renderer.c index 8f3ce7f7..c8094847 100644 --- a/render/gles2/renderer.c +++ b/render/gles2/renderer.c @@ -322,11 +322,11 @@ static log_importance_t gles2_log_importance_to_wlr(GLenum type) { case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_KHR: return L_ERROR; case GL_DEBUG_TYPE_PORTABILITY_KHR: return L_DEBUG; case GL_DEBUG_TYPE_PERFORMANCE_KHR: return L_DEBUG; - case GL_DEBUG_TYPE_OTHER_KHR: return L_INFO; + case GL_DEBUG_TYPE_OTHER_KHR: return L_DEBUG; case GL_DEBUG_TYPE_MARKER_KHR: return L_DEBUG; case GL_DEBUG_TYPE_PUSH_GROUP_KHR: return L_DEBUG; case GL_DEBUG_TYPE_POP_GROUP_KHR: return L_DEBUG; - default: return L_INFO; + default: return L_DEBUG; } } -- cgit v1.2.3 From 33a2eb4b7775d1a3ab2b767739c1f1f054683d22 Mon Sep 17 00:00:00 2001 From: emersion Date: Sat, 31 Mar 2018 18:49:43 -0400 Subject: Untie wlr_backend from wlr_renderer --- backend/drm/renderer.c | 2 +- backend/headless/backend.c | 2 +- backend/wayland/backend.c | 2 +- backend/x11/backend.c | 2 +- examples/output-layout.c | 3 ++- examples/rotation.c | 3 ++- examples/tablet.c | 3 ++- examples/touch.c | 3 ++- include/wlr/render/gles2.h | 3 ++- render/gles2/renderer.c | 5 ++--- 10 files changed, 16 insertions(+), 12 deletions(-) (limited to 'render/gles2') diff --git a/backend/drm/renderer.c b/backend/drm/renderer.c index c1531ce3..f06de1ee 100644 --- a/backend/drm/renderer.c +++ b/backend/drm/renderer.c @@ -31,7 +31,7 @@ bool wlr_drm_renderer_init(struct wlr_drm_backend *drm, goto error_gbm; } - renderer->wlr_rend = wlr_gles2_renderer_create(&drm->backend); + renderer->wlr_rend = wlr_gles2_renderer_create(&renderer->egl); if (!renderer->wlr_rend) { wlr_log(L_ERROR, "Failed to create WLR renderer"); goto error_egl; diff --git a/backend/headless/backend.c b/backend/headless/backend.c index 663bc13b..5bc48240 100644 --- a/backend/headless/backend.c +++ b/backend/headless/backend.c @@ -114,7 +114,7 @@ struct wlr_backend *wlr_headless_backend_create(struct wl_display *display) { return NULL; } - backend->renderer = wlr_gles2_renderer_create(&backend->backend); + backend->renderer = wlr_gles2_renderer_create(&backend->egl); if (backend->renderer == NULL) { wlr_log(L_ERROR, "Failed to create renderer"); } diff --git a/backend/wayland/backend.c b/backend/wayland/backend.c index abb25df5..0135f7c5 100644 --- a/backend/wayland/backend.c +++ b/backend/wayland/backend.c @@ -212,7 +212,7 @@ struct wlr_backend *wlr_wl_backend_create(struct wl_display *display, const char backend->remote_display, NULL, WL_SHM_FORMAT_ARGB8888); wlr_egl_bind_display(&backend->egl, backend->local_display); - backend->renderer = wlr_gles2_renderer_create(&backend->backend); + backend->renderer = wlr_gles2_renderer_create(&backend->egl); if (backend->renderer == NULL) { wlr_log_errno(L_ERROR, "Could not create renderer"); } diff --git a/backend/x11/backend.c b/backend/x11/backend.c index 90658f26..f598aea1 100644 --- a/backend/x11/backend.c +++ b/backend/x11/backend.c @@ -314,7 +314,7 @@ struct wlr_backend *wlr_x11_backend_create(struct wl_display *display, goto error_event; } - x11->renderer = wlr_gles2_renderer_create(&x11->backend); + x11->renderer = wlr_gles2_renderer_create(&x11->egl); if (x11->renderer == NULL) { wlr_log(L_ERROR, "Failed to create renderer"); goto error_egl; diff --git a/examples/output-layout.c b/examples/output-layout.c index c1392a30..53aae7f0 100644 --- a/examples/output-layout.c +++ b/examples/output-layout.c @@ -196,7 +196,8 @@ int main(int argc, char *argv[]) { compositor.keyboard_key_cb = handle_keyboard_key; compositor_init(&compositor); - state.renderer = wlr_gles2_renderer_create(compositor.backend); + struct wlr_egl *egl = wlr_backend_get_egl(compositor.backend); + state.renderer = wlr_gles2_renderer_create(egl); state.cat_texture = wlr_texture_from_pixels(state.renderer, WL_SHM_FORMAT_ABGR8888, cat_tex.width * 4, cat_tex.width, cat_tex.height, cat_tex.pixel_data); diff --git a/examples/rotation.c b/examples/rotation.c index dfafeeca..37873797 100644 --- a/examples/rotation.c +++ b/examples/rotation.c @@ -137,7 +137,8 @@ int main(int argc, char *argv[]) { compositor.keyboard_key_cb = handle_keyboard_key; compositor_init(&compositor); - state.renderer = wlr_gles2_renderer_create(compositor.backend); + struct wlr_egl *egl = wlr_backend_get_egl(compositor.backend); + state.renderer = wlr_gles2_renderer_create(egl); if (!state.renderer) { wlr_log(L_ERROR, "Could not start compositor, OOM"); exit(EXIT_FAILURE); diff --git a/examples/tablet.c b/examples/tablet.c index be428f86..d80b4b2f 100644 --- a/examples/tablet.c +++ b/examples/tablet.c @@ -192,7 +192,8 @@ int main(int argc, char *argv[]) { }; compositor_init(&compositor); - state.renderer = wlr_gles2_renderer_create(compositor.backend); + struct wlr_egl *egl = wlr_backend_get_egl(compositor.backend); + state.renderer = wlr_gles2_renderer_create(egl); if (!state.renderer) { wlr_log(L_ERROR, "Could not start compositor, OOM"); exit(EXIT_FAILURE); diff --git a/examples/touch.c b/examples/touch.c index e9dcf29c..16024fc8 100644 --- a/examples/touch.c +++ b/examples/touch.c @@ -108,7 +108,8 @@ int main(int argc, char *argv[]) { }; compositor_init(&compositor); - state.renderer = wlr_gles2_renderer_create(compositor.backend); + struct wlr_egl *egl = wlr_backend_get_egl(compositor.backend); + state.renderer = wlr_gles2_renderer_create(egl); if (!state.renderer) { wlr_log(L_ERROR, "Could not start compositor, OOM"); exit(EXIT_FAILURE); diff --git a/include/wlr/render/gles2.h b/include/wlr/render/gles2.h index b3b43ab2..a59956bd 100644 --- a/include/wlr/render/gles2.h +++ b/include/wlr/render/gles2.h @@ -5,6 +5,7 @@ #include struct wlr_egl; -struct wlr_renderer *wlr_gles2_renderer_create(struct wlr_backend *backend); + +struct wlr_renderer *wlr_gles2_renderer_create(struct wlr_egl *egl); #endif diff --git a/render/gles2/renderer.c b/render/gles2/renderer.c index c8094847..77af0ab7 100644 --- a/render/gles2/renderer.c +++ b/render/gles2/renderer.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include @@ -400,7 +399,7 @@ extern const GLchar tex_fragment_src_rgba[]; extern const GLchar tex_fragment_src_rgbx[]; extern const GLchar tex_fragment_src_external[]; -struct wlr_renderer *wlr_gles2_renderer_create(struct wlr_backend *backend) { +struct wlr_renderer *wlr_gles2_renderer_create(struct wlr_egl *egl) { struct wlr_gles2_renderer *renderer = calloc(1, sizeof(struct wlr_gles2_renderer)); if (renderer == NULL) { @@ -408,7 +407,7 @@ struct wlr_renderer *wlr_gles2_renderer_create(struct wlr_backend *backend) { } wlr_renderer_init(&renderer->wlr_renderer, &renderer_impl); - renderer->egl = wlr_backend_get_egl(backend); + renderer->egl = egl; wlr_egl_make_current(renderer->egl, EGL_NO_SURFACE, NULL); renderer->exts_str = (const char*) glGetString(GL_EXTENSIONS); -- cgit v1.2.3 From a7bb48b404b4809532e81a5daa981c81279c863a Mon Sep 17 00:00:00 2001 From: emersion Date: Sat, 31 Mar 2018 23:20:00 -0400 Subject: render/egl: add wlr_egl_create_image_from_wl_drm This allows external renderers and potential future GL-based renderers to re-use this function. --- include/wlr/render/egl.h | 20 +++++++++++----- include/wlr/render/wlr_texture.h | 2 +- render/egl.c | 40 ++++++++++++++++++++++++++++---- render/gles2/texture.c | 49 +++++++++++----------------------------- 4 files changed, 64 insertions(+), 47 deletions(-) (limited to 'render/gles2') diff --git a/include/wlr/render/egl.h b/include/wlr/render/egl.h index 20127e38..cca77870 100644 --- a/include/wlr/render/egl.h +++ b/include/wlr/render/egl.h @@ -28,21 +28,22 @@ struct wlr_egl { // TODO: Allocate and return a wlr_egl /** - * Initializes an egl context for the given platform and remote display. + * Initializes an EGL context for the given platform and remote display. * Will attempt to load all possibly required api functions. */ bool wlr_egl_init(struct wlr_egl *egl, EGLenum platform, void *remote_display, EGLint *config_attribs, EGLint visual_id); /** - * Frees all related egl resources, makes the context not-current and + * Frees all related EGL resources, makes the context not-current and * unbinds a bound wayland display. */ void wlr_egl_finish(struct wlr_egl *egl); /** - * Binds the given display to the egl instance. - * This will allow clients to create egl surfaces from wayland ones and render to it. + * Binds the given display to the EGL instance. + * This will allow clients to create EGL surfaces from wayland ones and render + * to it. */ bool wlr_egl_bind_display(struct wlr_egl *egl, struct wl_display *local_display); @@ -53,7 +54,14 @@ bool wlr_egl_bind_display(struct wlr_egl *egl, struct wl_display *local_display) EGLSurface wlr_egl_create_surface(struct wlr_egl *egl, void *window); /** - * Creates an egl image from the given dmabuf attributes. Check usability + * Creates an EGL image from the given wl_drm buffer resource. + */ +EGLImageKHR wlr_egl_create_image_from_wl_drm(struct wlr_egl *egl, + struct wl_resource *data, EGLint *fmt, int *width, int *height, + bool *inverted_y); + +/** + * Creates an EGL image from the given dmabuf attributes. Check usability * of the dmabuf with wlr_egl_check_import_dmabuf once first. */ EGLImageKHR wlr_egl_create_image_from_dmabuf(struct wlr_egl *egl, @@ -78,7 +86,7 @@ int wlr_egl_get_dmabuf_modifiers(struct wlr_egl *egl, int format, uint64_t **modifiers); /** - * Destroys an egl image created with the given wlr_egl. + * Destroys an EGL image created with the given wlr_egl. */ bool wlr_egl_destroy_image(struct wlr_egl *egl, EGLImageKHR image); diff --git a/include/wlr/render/wlr_texture.h b/include/wlr/render/wlr_texture.h index ab361298..239fc51b 100644 --- a/include/wlr/render/wlr_texture.h +++ b/include/wlr/render/wlr_texture.h @@ -23,7 +23,7 @@ struct wlr_texture *wlr_texture_from_pixels(struct wlr_renderer *renderer, const void *data); /** - * Create a new texture from a wayland DRM resource. The returned texture is + * Create a new texture from a wl_drm resource. The returned texture is * immutable. */ struct wlr_texture *wlr_texture_from_wl_drm(struct wlr_renderer *renderer, diff --git a/render/egl.c b/render/egl.c index 3c005b24..a424e8e9 100644 --- a/render/egl.c +++ b/render/egl.c @@ -93,7 +93,8 @@ static void print_dmabuf_formats(struct wlr_egl *egl) { char str_formats[num * 5 + 1]; for (int i = 0; i < num; i++) { - snprintf(&str_formats[i*5], (num - i) * 5 + 1, "%.4s ", (char*)&formats[i]); + snprintf(&str_formats[i*5], (num - i) * 5 + 1, "%.4s ", + (char*)&formats[i]); } wlr_log(L_DEBUG, "Supported dmabuf buffer formats: %s", str_formats); free(formats); @@ -230,8 +231,9 @@ bool wlr_egl_destroy_image(struct wlr_egl *egl, EGLImage image) { } EGLSurface wlr_egl_create_surface(struct wlr_egl *egl, void *window) { - EGLSurface surf = eglCreatePlatformWindowSurfaceEXT(egl->display, egl->config, - window, NULL); + assert(eglCreatePlatformWindowSurfaceEXT); + EGLSurface surf = eglCreatePlatformWindowSurfaceEXT(egl->display, + egl->config, window, NULL); if (surf == EGL_NO_SURFACE) { wlr_log(L_ERROR, "Failed to create EGL surface"); return EGL_NO_SURFACE; @@ -302,7 +304,37 @@ bool wlr_egl_swap_buffers(struct wlr_egl *egl, EGLSurface surface, return true; } -EGLImage wlr_egl_create_image_from_dmabuf(struct wlr_egl *egl, +EGLImageKHR wlr_egl_create_image_from_wl_drm(struct wlr_egl *egl, + struct wl_resource *data, EGLint *fmt, int *width, int *height, + bool *inverted_y) { + if (!eglQueryWaylandBufferWL || !eglCreateImageKHR) { + return NULL; + } + + if (!eglQueryWaylandBufferWL(egl->display, data, EGL_TEXTURE_FORMAT, fmt)) { + return NULL; + } + + eglQueryWaylandBufferWL(egl->display, data, EGL_WIDTH, width); + eglQueryWaylandBufferWL(egl->display, data, EGL_HEIGHT, height); + + EGLint _inverted_y; + if (eglQueryWaylandBufferWL(egl->display, data, EGL_WAYLAND_Y_INVERTED_WL, + &_inverted_y)) { + *inverted_y = !!_inverted_y; + } else { + *inverted_y = false; + } + + const EGLint attribs[] = { + EGL_WAYLAND_PLANE_WL, 0, + EGL_NONE, + }; + return eglCreateImageKHR(egl->display, egl->context, EGL_WAYLAND_BUFFER_WL, + data, attribs); +} + +EGLImageKHR wlr_egl_create_image_from_dmabuf(struct wlr_egl *egl, struct wlr_dmabuf_buffer_attribs *attributes) { bool has_modifier = false; if (attributes->modifier[0] != DRM_FORMAT_MOD_INVALID) { diff --git a/render/gles2/texture.c b/render/gles2/texture.c index 82effd71..e4936d71 100644 --- a/render/gles2/texture.c +++ b/render/gles2/texture.c @@ -90,7 +90,7 @@ static void gles2_texture_destroy(struct wlr_texture *wlr_texture) { } if (texture->image) { assert(eglDestroyImageKHR); - eglDestroyImageKHR(texture->renderer->egl->display, texture->image); + wlr_egl_destroy_image(texture->renderer->egl, texture->image); } if (texture->type == WLR_GLES2_TEXTURE_GLTEX) { @@ -144,34 +144,17 @@ struct wlr_texture *gles2_texture_from_pixels(struct wlr_renderer *wlr_renderer, glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0); GLES2_DEBUG_POP; - return (struct wlr_texture *)texture; + return &texture->wlr_texture; } struct wlr_texture *gles2_texture_from_wl_drm(struct wlr_renderer *wlr_renderer, struct wl_resource *data) { struct wlr_gles2_renderer *renderer = gles2_get_renderer(wlr_renderer); - if (!eglQueryWaylandBufferWL || !eglCreateImageKHR || - !glEGLImageTargetTexture2DOES) { - return NULL; - } - - EGLint fmt; - if (!eglQueryWaylandBufferWL(renderer->egl->display, data, - EGL_TEXTURE_FORMAT, &fmt)) { + if (!glEGLImageTargetTexture2DOES) { return NULL; } - EGLint width, height; - eglQueryWaylandBufferWL(renderer->egl->display, data, EGL_WIDTH, &width); - eglQueryWaylandBufferWL(renderer->egl->display, data, EGL_HEIGHT, &height); - - EGLint inverted_y; - if (!eglQueryWaylandBufferWL(renderer->egl->display, data, - EGL_WAYLAND_Y_INVERTED_WL, &inverted_y)) { - inverted_y = 0; - } - struct wlr_gles2_texture *texture = calloc(1, sizeof(struct wlr_gles2_texture)); if (texture == NULL) { @@ -180,10 +163,15 @@ struct wlr_texture *gles2_texture_from_wl_drm(struct wlr_renderer *wlr_renderer, } wlr_texture_init(&texture->wlr_texture, &texture_impl); texture->renderer = renderer; - texture->width = width; - texture->height = height; texture->wl_drm = data; - texture->inverted_y = !!inverted_y; + + EGLint fmt; + texture->image = wlr_egl_create_image_from_wl_drm(renderer->egl, data, &fmt, + &texture->width, &texture->height, &texture->inverted_y); + if (texture->image == NULL) { + free(texture); + return NULL; + } GLenum target; switch (fmt) { @@ -204,17 +192,6 @@ struct wlr_texture *gles2_texture_from_wl_drm(struct wlr_renderer *wlr_renderer, return NULL; } - EGLint attribs[] = { - EGL_WAYLAND_PLANE_WL, 0, - EGL_NONE, - }; - texture->image = eglCreateImageKHR(renderer->egl->display, - renderer->egl->context, EGL_WAYLAND_BUFFER_WL, data, attribs); - if (texture->image == NULL) { - free(texture); - return NULL; - } - GLES2_DEBUG_PUSH; glGenTextures(1, &texture->image_tex); @@ -222,7 +199,7 @@ struct wlr_texture *gles2_texture_from_wl_drm(struct wlr_renderer *wlr_renderer, glEGLImageTargetTexture2DOES(target, texture->image); GLES2_DEBUG_POP; - return (struct wlr_texture *)texture; + return &texture->wlr_texture; } struct wlr_texture *gles2_texture_from_dmabuf(struct wlr_renderer *wlr_renderer, @@ -267,5 +244,5 @@ struct wlr_texture *gles2_texture_from_dmabuf(struct wlr_renderer *wlr_renderer, glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, texture->image); GLES2_DEBUG_POP; - return (struct wlr_texture *)texture; + return &texture->wlr_texture; } -- cgit v1.2.3 From f3f61bed3e055e7032466723afda33a56f585dc5 Mon Sep 17 00:00:00 2001 From: emersion Date: Sun, 1 Apr 2018 16:07:50 -0400 Subject: Untie wlr_gles2_renderer and wlr_gles2_texture --- include/render/gles2.h | 15 ++------------- include/wlr/render/egl.h | 2 ++ include/wlr/render/gles2.h | 8 ++++++++ render/egl.c | 4 ++++ render/gles2/renderer.c | 33 +++++++++++++++++++++++++++++---- render/gles2/texture.c | 31 +++++++++++++++---------------- 6 files changed, 60 insertions(+), 33 deletions(-) (limited to 'render/gles2') diff --git a/include/render/gles2.h b/include/render/gles2.h index 32cb3221..50252027 100644 --- a/include/render/gles2.h +++ b/include/render/gles2.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -49,7 +50,7 @@ enum wlr_gles2_texture_type { struct wlr_gles2_texture { struct wlr_texture wlr_texture; - struct wlr_gles2_renderer *renderer; + struct wlr_egl *egl; enum wlr_gles2_texture_type type; int width, height; bool has_alpha; @@ -68,20 +69,8 @@ struct wlr_gles2_texture { const struct gles2_pixel_format *gles2_format_from_wl(enum wl_shm_format fmt); const enum wl_shm_format *gles2_formats(size_t *len); -struct wlr_gles2_renderer *gles2_get_renderer( - struct wlr_renderer *wlr_renderer); -struct wlr_gles2_renderer *gles2_get_renderer_in_context( - struct wlr_renderer *wlr_renderer); - struct wlr_gles2_texture *gles2_get_texture_in_context( struct wlr_texture *wlr_texture); -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); -struct wlr_texture *gles2_texture_from_wl_drm(struct wlr_renderer *wlr_renderer, - struct wl_resource *data); -struct wlr_texture *gles2_texture_from_dmabuf(struct wlr_renderer *wlr_renderer, - struct wlr_dmabuf_buffer_attribs *attribs); void gles2_push_marker(const char *file, const char *func); void gles2_pop_marker(void); diff --git a/include/wlr/render/egl.h b/include/wlr/render/egl.h index cca77870..51f63b20 100644 --- a/include/wlr/render/egl.h +++ b/include/wlr/render/egl.h @@ -93,6 +93,8 @@ bool wlr_egl_destroy_image(struct wlr_egl *egl, EGLImageKHR image); bool wlr_egl_make_current(struct wlr_egl *egl, EGLSurface surface, int *buffer_age); +bool wlr_egl_is_current(struct wlr_egl *egl); + bool wlr_egl_swap_buffers(struct wlr_egl *egl, EGLSurface surface, pixman_region32_t *damage); diff --git a/include/wlr/render/gles2.h b/include/wlr/render/gles2.h index a59956bd..65bb36c1 100644 --- a/include/wlr/render/gles2.h +++ b/include/wlr/render/gles2.h @@ -8,4 +8,12 @@ struct wlr_egl; struct wlr_renderer *wlr_gles2_renderer_create(struct wlr_egl *egl); +struct wlr_texture *wlr_gles2_texture_from_pixels(struct wlr_egl *egl, + enum wl_shm_format wl_fmt, uint32_t stride, uint32_t width, uint32_t height, + const void *data); +struct wlr_texture *wlr_gles2_texture_from_wl_drm(struct wlr_egl *egl, + struct wl_resource *data); +struct wlr_texture *wlr_gles2_texture_from_dmabuf(struct wlr_egl *egl, + struct wlr_dmabuf_buffer_attribs *attribs); + #endif diff --git a/render/egl.c b/render/egl.c index a424e8e9..473d1319 100644 --- a/render/egl.c +++ b/render/egl.c @@ -270,6 +270,10 @@ bool wlr_egl_make_current(struct wlr_egl *egl, EGLSurface surface, return true; } +bool wlr_egl_is_current(struct wlr_egl *egl) { + return eglGetCurrentContext() == egl->context; +} + bool wlr_egl_swap_buffers(struct wlr_egl *egl, EGLSurface surface, pixman_region32_t *damage) { EGLBoolean ret; diff --git a/render/gles2/renderer.c b/render/gles2/renderer.c index 77af0ab7..b8bce98d 100644 --- a/render/gles2/renderer.c +++ b/render/gles2/renderer.c @@ -16,16 +16,16 @@ static const struct wlr_renderer_impl renderer_impl; -struct wlr_gles2_renderer *gles2_get_renderer( +static struct wlr_gles2_renderer *gles2_get_renderer( struct wlr_renderer *wlr_renderer) { assert(wlr_renderer->impl == &renderer_impl); return (struct wlr_gles2_renderer *)wlr_renderer; } -struct wlr_gles2_renderer *gles2_get_renderer_in_context( +static struct wlr_gles2_renderer *gles2_get_renderer_in_context( struct wlr_renderer *wlr_renderer) { struct wlr_gles2_renderer *renderer = gles2_get_renderer(wlr_renderer); - assert(eglGetCurrentContext() == renderer->egl->context); + assert(wlr_egl_is_current(renderer->egl)); return renderer; } @@ -252,11 +252,32 @@ static bool gles2_read_pixels(struct wlr_renderer *wlr_renderer, return true; } -static bool gles2_format_supported(struct wlr_renderer *r, +static bool gles2_format_supported(struct wlr_renderer *wlr_renderer, enum wl_shm_format wl_fmt) { return gles2_format_from_wl(wl_fmt) != NULL; } +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) { + struct wlr_gles2_renderer *renderer = gles2_get_renderer(wlr_renderer); + return wlr_gles2_texture_from_pixels(renderer->egl, wl_fmt, stride, width, + height, data); +} + +static struct wlr_texture *gles2_texture_from_wl_drm( + struct wlr_renderer *wlr_renderer, struct wl_resource *data) { + struct wlr_gles2_renderer *renderer = gles2_get_renderer(wlr_renderer); + return wlr_gles2_texture_from_wl_drm(renderer->egl, data); +} + +static struct wlr_texture *gles2_texture_from_dmabuf( + struct wlr_renderer *wlr_renderer, + struct wlr_dmabuf_buffer_attribs *attribs) { + struct wlr_gles2_renderer *renderer = gles2_get_renderer(wlr_renderer); + return wlr_gles2_texture_from_dmabuf(renderer->egl, attribs); +} + static void gles2_destroy(struct wlr_renderer *wlr_renderer) { struct wlr_gles2_renderer *renderer = gles2_get_renderer(wlr_renderer); @@ -400,6 +421,10 @@ extern const GLchar tex_fragment_src_rgbx[]; extern const GLchar tex_fragment_src_external[]; struct wlr_renderer *wlr_gles2_renderer_create(struct wlr_egl *egl) { + if (!load_glapi()) { + return NULL; + } + struct wlr_gles2_renderer *renderer = calloc(1, sizeof(struct wlr_gles2_renderer)); if (renderer == NULL) { diff --git a/render/gles2/texture.c b/render/gles2/texture.c index e4936d71..45169daf 100644 --- a/render/gles2/texture.c +++ b/render/gles2/texture.c @@ -25,7 +25,7 @@ static struct wlr_gles2_texture *gles2_get_texture( struct wlr_gles2_texture *gles2_get_texture_in_context( struct wlr_texture *wlr_texture) { struct wlr_gles2_texture *texture = gles2_get_texture(wlr_texture); - assert(eglGetCurrentContext() == texture->renderer->egl->context); + assert(wlr_egl_is_current(texture->egl)); return texture; } @@ -81,7 +81,7 @@ static void gles2_texture_destroy(struct wlr_texture *wlr_texture) { struct wlr_gles2_texture *texture = gles2_get_texture(wlr_texture); - wlr_egl_make_current(texture->renderer->egl, EGL_NO_SURFACE, NULL); + wlr_egl_make_current(texture->egl, EGL_NO_SURFACE, NULL); GLES2_DEBUG_PUSH; @@ -90,7 +90,7 @@ static void gles2_texture_destroy(struct wlr_texture *wlr_texture) { } if (texture->image) { assert(eglDestroyImageKHR); - wlr_egl_destroy_image(texture->renderer->egl, texture->image); + wlr_egl_destroy_image(texture->egl, texture->image); } if (texture->type == WLR_GLES2_TEXTURE_GLTEX) { @@ -108,11 +108,10 @@ static const struct wlr_texture_impl texture_impl = { .destroy = gles2_texture_destroy, }; -struct wlr_texture *gles2_texture_from_pixels(struct wlr_renderer *wlr_renderer, +struct wlr_texture *wlr_gles2_texture_from_pixels(struct wlr_egl *egl, enum wl_shm_format wl_fmt, uint32_t stride, uint32_t width, uint32_t height, const void *data) { - struct wlr_gles2_renderer *renderer = - gles2_get_renderer_in_context(wlr_renderer); + assert(wlr_egl_is_current(egl)); const struct gles2_pixel_format *fmt = gles2_format_from_wl(wl_fmt); if (fmt == NULL) { @@ -127,7 +126,7 @@ struct wlr_texture *gles2_texture_from_pixels(struct wlr_renderer *wlr_renderer, return NULL; } wlr_texture_init(&texture->wlr_texture, &texture_impl); - texture->renderer = renderer; + texture->egl = egl; texture->width = width; texture->height = height; texture->type = WLR_GLES2_TEXTURE_GLTEX; @@ -147,9 +146,9 @@ struct wlr_texture *gles2_texture_from_pixels(struct wlr_renderer *wlr_renderer, return &texture->wlr_texture; } -struct wlr_texture *gles2_texture_from_wl_drm(struct wlr_renderer *wlr_renderer, +struct wlr_texture *wlr_gles2_texture_from_wl_drm(struct wlr_egl *egl, struct wl_resource *data) { - struct wlr_gles2_renderer *renderer = gles2_get_renderer(wlr_renderer); + assert(wlr_egl_is_current(egl)); if (!glEGLImageTargetTexture2DOES) { return NULL; @@ -162,11 +161,11 @@ struct wlr_texture *gles2_texture_from_wl_drm(struct wlr_renderer *wlr_renderer, return NULL; } wlr_texture_init(&texture->wlr_texture, &texture_impl); - texture->renderer = renderer; + texture->egl = egl; texture->wl_drm = data; EGLint fmt; - texture->image = wlr_egl_create_image_from_wl_drm(renderer->egl, data, &fmt, + texture->image = wlr_egl_create_image_from_wl_drm(egl, data, &fmt, &texture->width, &texture->height, &texture->inverted_y); if (texture->image == NULL) { free(texture); @@ -202,15 +201,15 @@ struct wlr_texture *gles2_texture_from_wl_drm(struct wlr_renderer *wlr_renderer, return &texture->wlr_texture; } -struct wlr_texture *gles2_texture_from_dmabuf(struct wlr_renderer *wlr_renderer, +struct wlr_texture *wlr_gles2_texture_from_dmabuf(struct wlr_egl *egl, struct wlr_dmabuf_buffer_attribs *attribs) { - struct wlr_gles2_renderer *renderer = gles2_get_renderer(wlr_renderer); + assert(wlr_egl_is_current(egl)); if (!glEGLImageTargetTexture2DOES) { return NULL; } - if (!renderer->egl->egl_exts.dmabuf_import) { + if (!egl->egl_exts.dmabuf_import) { wlr_log(L_ERROR, "Cannot create DMA-BUF texture: EGL extension " "unavailable"); return NULL; @@ -223,7 +222,7 @@ struct wlr_texture *gles2_texture_from_dmabuf(struct wlr_renderer *wlr_renderer, return NULL; } wlr_texture_init(&texture->wlr_texture, &texture_impl); - texture->renderer = renderer; + texture->egl = egl; texture->width = attribs->width; texture->height = attribs->height; texture->type = WLR_GLES2_TEXTURE_DMABUF; @@ -231,7 +230,7 @@ struct wlr_texture *gles2_texture_from_dmabuf(struct wlr_renderer *wlr_renderer, texture->inverted_y = (attribs->flags & WLR_DMABUF_BUFFER_ATTRIBS_FLAGS_Y_INVERT) != 0; - texture->image = wlr_egl_create_image_from_dmabuf(renderer->egl, attribs); + texture->image = wlr_egl_create_image_from_dmabuf(egl, attribs); if (texture->image == NULL) { free(texture); return NULL; -- cgit v1.2.3