diff options
Diffstat (limited to 'render/gles2/renderer.c')
-rw-r--r-- | render/gles2/renderer.c | 165 |
1 files changed, 114 insertions, 51 deletions
diff --git a/render/gles2/renderer.c b/render/gles2/renderer.c index 61665a07..b8bce98d 100644 --- a/render/gles2/renderer.c +++ b/render/gles2/renderer.c @@ -6,29 +6,32 @@ #include <stdlib.h> #include <wayland-server-protocol.h> #include <wayland-util.h> -#include <wlr/backend.h> #include <wlr/render/egl.h> #include <wlr/render/interface.h> #include <wlr/render/wlr_renderer.h> #include <wlr/types/wlr_matrix.h> #include <wlr/util/log.h> -#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_renderer *wlr_renderer) { assert(wlr_renderer->impl == &renderer_impl); - struct wlr_gles2_renderer *renderer = - (struct wlr_gles2_renderer *)wlr_renderer; - assert(eglGetCurrentContext() == renderer->egl->context); + return (struct wlr_gles2_renderer *)wlr_renderer; +} + +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(wlr_egl_is_current(renderer->egl)); 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 +48,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 +64,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 +76,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 +102,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 = 0; + GLenum target = 0; + 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 +132,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 +156,8 @@ static bool gles2_render_texture_with_matrix( static void gles2_render_quad_with_matrix(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 +174,8 @@ static void gles2_render_quad_with_matrix(struct wlr_renderer *wlr_renderer, static void gles2_render_ellipse_with_matrix(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 +195,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); - EGLint format; - return wlr_egl_query_buffer(renderer->egl, buffer, EGL_TEXTURE_FORMAT, - &format); + 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; + } + + 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) { @@ -222,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); @@ -254,14 +305,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_with_matrix = gles2_render_quad_with_matrix, .render_ellipse_with_matrix = gles2_render_ellipse_with_matrix, .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) { @@ -288,11 +342,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; } } @@ -366,7 +420,11 @@ 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) { + if (!load_glapi()) { + return NULL; + } + struct wlr_gles2_renderer *renderer = calloc(1, sizeof(struct wlr_gles2_renderer)); if (renderer == NULL) { @@ -374,9 +432,14 @@ 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); + 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); |